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.

328 lines
6.4 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. dbgnewp.cxx
  6. Abstract:
  7. Debug new private file
  8. Author:
  9. Steve Kiraly (SteveKi) 23-June-1998
  10. Revision History:
  11. --*/
  12. #include "precomp.hxx"
  13. #pragma hdrstop
  14. #include "dbgtag.hxx"
  15. #include "dbgnewp.hxx"
  16. TDebugNewAllocator::
  17. TDebugNewAllocator(
  18. VOID
  19. ) : m_bValid( FALSE ),
  20. m_hDataHeap( NULL ),
  21. m_pTag( NULL )
  22. {
  23. }
  24. TDebugNewAllocator::
  25. ~TDebugNewAllocator(
  26. VOID
  27. )
  28. {
  29. Destroy();
  30. }
  31. BOOL
  32. TDebugNewAllocator::
  33. bValid(
  34. VOID
  35. ) const
  36. {
  37. return m_bValid;
  38. }
  39. VOID
  40. TDebugNewAllocator::
  41. Initialize(
  42. IN UINT uSizeHint
  43. )
  44. {
  45. m_pTag = INTERNAL_NEW TDebugNewTag();
  46. m_hDataHeap = HeapCreate( 0, kDataHeapSize, 0 );
  47. if (m_hDataHeap && m_pTag->bInit() )
  48. {
  49. m_bValid = TRUE;
  50. }
  51. }
  52. VOID
  53. TDebugNewAllocator::
  54. Destroy(
  55. VOID
  56. )
  57. {
  58. if (m_hDataHeap)
  59. {
  60. HeapDestroy( m_hDataHeap );
  61. }
  62. INTERNAL_DELETE m_pTag;
  63. }
  64. //
  65. // Allocate a new memory block, tracking the allocation for
  66. // leak detection.
  67. //
  68. PVOID
  69. TDebugNewAllocator::
  70. Allocate(
  71. IN SIZE_T Size,
  72. IN PVOID pVoid,
  73. IN LPCTSTR pszFile,
  74. IN UINT uLine
  75. )
  76. {
  77. //
  78. // Allocate the memory block.
  79. //
  80. Header *pHeader = reinterpret_cast<Header *>( HeapAlloc( m_hDataHeap,
  81. 0,
  82. sizeof( Header ) + Size + sizeof( Tail ) ) );
  83. //
  84. // If the block was allocated successfully.
  85. //
  86. if (pHeader)
  87. {
  88. //
  89. // Track this memory allocation.
  90. //
  91. if( m_pTag->Tag( &pHeader->pTag, pHeader, Size, pszFile, uLine ) )
  92. {
  93. //
  94. // Set the header data and tail pattern. The tag back pointer is
  95. // is set for efficent release, the data area is filled with a known pattern
  96. // and tail is filled with a known pattern for overwrite detection.
  97. //
  98. FillHeaderDataTailPattern( pHeader, Size );
  99. //
  100. // Adjust returned pointer to client data area.
  101. //
  102. pHeader++;
  103. }
  104. else
  105. {
  106. //
  107. // Tag entry was not available, something horrible happened.
  108. // If this happens then clean up the allocation and
  109. // return failure for this allocation.
  110. //
  111. HeapFree( m_hDataHeap, 0, pHeader );
  112. pHeader = NULL;
  113. }
  114. }
  115. return pHeader;
  116. }
  117. //
  118. // Release the memory block, checking for duplicate frees and
  119. // tail overwrites.
  120. //
  121. VOID
  122. TDebugNewAllocator::
  123. Release(
  124. IN PVOID pVoid
  125. )
  126. {
  127. //
  128. // Convert the client data area pointer to header pointer.
  129. //
  130. Header *pHeader = reinterpret_cast<Header *>( pVoid ) - 1;
  131. //
  132. // Validate the header and tail signatures.
  133. //
  134. ValidationErrorCode ValidationError = ValidateHeaderDataTailPattern( pVoid, pHeader );
  135. switch (ValidationError)
  136. {
  137. case kValidationErrorSuccess:
  138. //
  139. // Release allocation from tag list.
  140. //
  141. m_pTag->Release( pHeader->pTag );
  142. //
  143. // Release this block back to the heap.
  144. //
  145. HeapFree( m_hDataHeap, 0, pHeader );
  146. break;
  147. case kValidationErrorNullPointer:
  148. //
  149. // It is ok to attempt to free the null pointer.
  150. //
  151. break;
  152. //
  153. // We leak memory allocations that fail header, tail or tag validation.
  154. //
  155. case kValidationErrorInvalidHeader:
  156. ErrorText( _T("Buffer failed header validation\n") );
  157. break;
  158. case kValidationErrorInvalidTail:
  159. ErrorText( _T("Buffer failed tail validation\n") );
  160. break;
  161. case kValidationErrorUnknown:
  162. default:
  163. ErrorText( _T("Buffer failed validation\n") );
  164. break;
  165. }
  166. }
  167. VOID
  168. TDebugNewAllocator::
  169. Report(
  170. IN UINT uDevice,
  171. IN LPCTSTR pszConfiguration
  172. ) const
  173. {
  174. m_pTag->DisplayInuseTagEntries( uDevice, pszConfiguration );
  175. }
  176. /********************************************************************
  177. Private member functions.
  178. ********************************************************************/
  179. VOID
  180. TDebugNewAllocator::
  181. FillHeaderDataTailPattern(
  182. IN Header *pHeader,
  183. IN SIZE_T Size
  184. )
  185. {
  186. //
  187. // Fill the header pattern.
  188. //
  189. memset( &pHeader->pSignature, kHeaderPattern, sizeof( PVOID ) );
  190. //
  191. // Fill the Data pattern.
  192. //
  193. memset( ++pHeader, kDataAllocPattern, Size );
  194. //
  195. // Calculate the tail pointer.
  196. //
  197. Tail *pTail = reinterpret_cast<Tail *>( reinterpret_cast<PBYTE>( pHeader ) + Size );
  198. //
  199. // Write the tail pattern.
  200. //
  201. memset( &pTail->pSignature, kTailPattern, sizeof( PVOID ) );
  202. }
  203. TDebugNewAllocator::ValidationErrorCode
  204. TDebugNewAllocator::
  205. ValidateHeaderDataTailPattern(
  206. IN PVOID pVoid,
  207. IN Header *pHeader
  208. )
  209. {
  210. if (!pVoid)
  211. {
  212. return kValidationErrorNullPointer;
  213. }
  214. //
  215. // Validate the header pointer.
  216. //
  217. if (!pHeader)
  218. {
  219. return kValidationErrorInvalidHeaderPtr;
  220. }
  221. //
  222. // Validate the header structure.
  223. //
  224. if (IsBadReadPtr( pHeader, sizeof( Header )))
  225. {
  226. return kValidationErrorInvalidHeader;
  227. }
  228. //
  229. // Validate the header signature.
  230. //
  231. PVOID pTemp;
  232. memset( &pTemp, kHeaderPattern, sizeof( PVOID ) );
  233. if (pHeader->pSignature != pTemp)
  234. {
  235. return kValidationErrorInvalidHeaderSignature;
  236. }
  237. //
  238. // Validate the tag entry.
  239. //
  240. switch (m_pTag->ValidateEntry( pHeader->pTag ))
  241. {
  242. case TDebugNewTag::kValidationErrorInvalidPointer:
  243. break;
  244. case TDebugNewTag::kValidationErrorInvalidHeader:
  245. break;
  246. case TDebugNewTag::kValidationErrorTagNotLinked:
  247. break;
  248. case TDebugNewTag::kValidationErrorUnknown:
  249. default:
  250. break;
  251. }
  252. //
  253. // Get the tail pointer.
  254. //
  255. Tail *pTail = reinterpret_cast<Tail *>( reinterpret_cast<PBYTE>(pHeader+1)+m_pTag->GetSize( pHeader->pTag ) );
  256. //
  257. // Validate the tail structure.
  258. //
  259. if (IsBadReadPtr( pTail, sizeof( Tail )))
  260. {
  261. return kValidationErrorInvalidTailPointer;
  262. }
  263. //
  264. // Validate the tail signature.
  265. //
  266. memset( &pTemp, kTailPattern, sizeof( PVOID ) );
  267. if( pTail->pSignature != pTemp )
  268. {
  269. return kValidationErrorInvalidTailSignature;
  270. }
  271. return kValidationErrorSuccess;
  272. }