Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

351 lines
7.3 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corp., 1991-1996 **/
  4. /**********************************************************************/
  5. /*
  6. buffer.cxx
  7. Implementation of the BUFFER class.
  8. FILE HISTORY:
  9. MuraliK 3-July-1996 Rewrote the buffer class
  10. */
  11. #include "precomp.hxx"
  12. #include <buffer.hxx>
  13. #include "dbgutil.h"
  14. #include <auxctrs.h>
  15. #include <irtlmisc.h>
  16. LONG g_SBAuxCounters[NUM_AUX_COUNTERS];
  17. BUFFER::~BUFFER(void)
  18. {
  19. if ( IsDynAlloced())
  20. {
  21. /* INTRINSA suppress = all */
  22. ::IisFree( m_pb );
  23. }
  24. }
  25. /*******************************************************************
  26. NAME: BUFFER::GetNewStorage
  27. SYNOPSIS: Given an object with no allocated storage,
  28. allocate the initial memory.
  29. ENTRY: cbRequested - amount of storage requested in bytes
  30. EXIT: Either storage alloc'd, or error reported
  31. Sets m_cb, m_pb and m_fIsDynAlloced
  32. RETURNS: TRUE if successful, FALSE for GetLastError()
  33. NOTES:
  34. Private member function.
  35. ********************************************************************/
  36. BOOL
  37. BUFFER::GetNewStorage( UINT cbRequested )
  38. {
  39. AcIncrement( CacBufferAllocs);
  40. if ( cbRequested <= m_cb) {
  41. return TRUE;
  42. }
  43. DBG_ASSERT( !IsDynAlloced()); // otherwise I should free up the block :(
  44. m_pb = (BYTE*) ::IisMalloc( cbRequested );
  45. if ( !m_pb ) {
  46. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  47. } else {
  48. m_pb[0] = '\0'; // just store null
  49. m_cb = cbRequested;
  50. m_fIsDynAlloced = 1;
  51. }
  52. return (m_pb != NULL);
  53. } // BUFFER::GetNewStorage()
  54. /*******************************************************************
  55. NAME: BUFFER::ReallocStorage
  56. SYNOPSIS: Do a "hard" reallocation to the new size
  57. ENTRY: cbNewRequested - new size, in bytes
  58. EXIT: Storage realloc'd. m_pb, m_cb, m_fIsDynAlloced changed
  59. RETURNS: TRUE if successful, FALSE for GetLastError()
  60. ********************************************************************/
  61. BOOL
  62. BUFFER::ReallocStorage( UINT cbNewRequested )
  63. {
  64. if ( cbNewRequested <= m_cb) {
  65. return (TRUE);
  66. }
  67. BYTE* pb = (BYTE*) ((IsDynAlloced())
  68. ? (::IisReAlloc(m_pb, cbNewRequested))
  69. : (::IisMalloc(cbNewRequested))
  70. );
  71. AcIncrement( CacBufferReallocs);
  72. if (pb == NULL)
  73. {
  74. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  75. return FALSE;
  76. }
  77. if ( !IsDynAlloced()) {
  78. // First time this block is allocated. Copy over old contents.
  79. CopyMemory( pb, m_pb, m_cb);
  80. m_fIsDynAlloced = 1;
  81. }
  82. m_pb = pb;
  83. m_cb = cbNewRequested;
  84. DBG_ASSERT( m_pb != NULL );
  85. return TRUE;
  86. } // BUFFER::ReallocStorage()
  87. /*******************************************************************
  88. NAME: BUFFER::VerifyState
  89. SYNOPSIS: Verifies the state of the object.
  90. Asserts out if the state is invalid, i.e. if an
  91. internal error took place.
  92. NOTES: This function does nothing in the retail version.
  93. ********************************************************************/
  94. VOID BUFFER::VerifyState() const
  95. {
  96. //
  97. // 1. If Dynamically Allocated ==>
  98. // m_pb points to something other than m_rgb &
  99. // m_cb > INLINED_BUFFER_LEN
  100. // 2. If not Dynamicall Allocated ==>
  101. // (a) it can be using user-supplied buffer & any sized
  102. // (b) it can be using inlined buffer & m_cb == INLINED_BUFFER_LEN
  103. //
  104. DBG_ASSERT(( IsDynAlloced() && (m_pb != m_rgb) &&
  105. (m_cb > INLINED_BUFFER_LEN)) ||
  106. ( !IsDynAlloced() &&
  107. ( m_pb != m_rgb || m_cb == INLINED_BUFFER_LEN)
  108. )
  109. );
  110. } // BUFFER::VerifyState()
  111. /*******************************************************************
  112. NAME: BUFFER::FreeMemory
  113. SYNOPSIS: Frees the heap memory associated with this buffer object
  114. ********************************************************************/
  115. VOID
  116. BUFFER::FreeMemory(
  117. VOID
  118. )
  119. {
  120. if ( IsDynAlloced()) {
  121. ::IisFree( m_pb );
  122. m_pb = m_rgb;
  123. m_cb = INLINED_BUFFER_LEN;
  124. m_fIsDynAlloced = 0;
  125. }
  126. m_rgb[0] = '\0'; // reset the contents
  127. }
  128. BOOL
  129. BUFFER_CHAIN::AppendBuffer(
  130. BUFFER_CHAIN_ITEM * pBCI
  131. )
  132. /*++
  133. Routine Description:
  134. Adds a new buffer chain item to the end of the buffer chain
  135. Arguments:
  136. pBCI - Chain item to append
  137. Return Value:
  138. TRUE if successful, FALSE on error
  139. --*/
  140. {
  141. DBG_ASSERT( pBCI );
  142. DBG_ASSERT( pBCI->_ListEntry.Flink == NULL );
  143. InsertTailList( &_ListHead,
  144. &pBCI->_ListEntry );
  145. return TRUE;
  146. }
  147. DWORD
  148. BUFFER_CHAIN::DeleteChain(
  149. VOID
  150. )
  151. /*++
  152. Routine Description:
  153. Deletes all of the buffers in this chain
  154. Return Value:
  155. Total number of allocated bytes freed by this call
  156. --*/
  157. {
  158. BUFFER_CHAIN_ITEM * pBCI;
  159. DWORD cbFreed = 0;
  160. while ( !IsListEmpty( &_ListHead ))
  161. {
  162. pBCI = CONTAINING_RECORD( _ListHead.Flink,
  163. BUFFER_CHAIN_ITEM,
  164. _ListEntry );
  165. DBG_ASSERT( pBCI->_ListEntry.Flink != NULL );
  166. RemoveEntryList( &pBCI->_ListEntry );
  167. cbFreed += pBCI->QuerySize();
  168. delete pBCI;
  169. }
  170. return cbFreed;
  171. }
  172. BUFFER_CHAIN_ITEM *
  173. BUFFER_CHAIN::NextBuffer(
  174. BUFFER_CHAIN_ITEM * pBCI
  175. )
  176. /*++
  177. Routine Description:
  178. Returns the next buffer in the chain. Start the enumeration by
  179. passing pBCI as NULL. Continue it by passing the return value
  180. Arguments:
  181. pBCI - Previous item in enumeration
  182. Return Value:
  183. Pointer to next item in chain, NULL when done
  184. --*/
  185. {
  186. if ( pBCI != NULL )
  187. {
  188. if ( pBCI->_ListEntry.Flink != &_ListHead )
  189. {
  190. return CONTAINING_RECORD( pBCI->_ListEntry.Flink,
  191. BUFFER_CHAIN_ITEM,
  192. _ListEntry );
  193. }
  194. else
  195. {
  196. return NULL;
  197. }
  198. }
  199. if ( !IsListEmpty( &_ListHead ))
  200. {
  201. return CONTAINING_RECORD( _ListHead.Flink,
  202. BUFFER_CHAIN_ITEM,
  203. _ListEntry );
  204. }
  205. return NULL;
  206. }
  207. DWORD
  208. BUFFER_CHAIN::CalcTotalSize(
  209. BOOL fUsed
  210. ) const
  211. /*++
  212. Routine Description:
  213. Returns the total amount of memory allocated by this buffer chain
  214. excluding the size of the structures themselves
  215. Arguments:
  216. fUsed - If FALSE, returns total allocated by chain, if TRUE returns
  217. total used by chain
  218. Return Value:
  219. Total bytes allocated or total bytes used
  220. --*/
  221. {
  222. LIST_ENTRY * pEntry;
  223. BUFFER_CHAIN_ITEM * pBCI;
  224. DWORD cbRet = 0;
  225. for ( pEntry = _ListHead.Flink;
  226. pEntry != &_ListHead;
  227. pEntry = pEntry->Flink )
  228. {
  229. pBCI = CONTAINING_RECORD( pEntry, BUFFER_CHAIN_ITEM, _ListEntry );
  230. if ( fUsed == FALSE )
  231. cbRet += pBCI->QuerySize();
  232. else
  233. cbRet += pBCI->QueryUsed();
  234. }
  235. return cbRet;
  236. }
  237. /***************************** End Of File ******************************/