/*++ Copyright (c) 1998-1999 Microsoft Corporation All rights reserved. Module Name: dbgnewp.cxx Abstract: Debug new private file Author: Steve Kiraly (SteveKi) 23-June-1998 Revision History: --*/ #include "precomp.hxx" #pragma hdrstop #include "dbgtag.hxx" #include "dbgnewp.hxx" TDebugNewAllocator:: TDebugNewAllocator( VOID ) : m_bValid( FALSE ), m_hDataHeap( NULL ), m_pTag( NULL ) { } TDebugNewAllocator:: ~TDebugNewAllocator( VOID ) { Destroy(); } BOOL TDebugNewAllocator:: bValid( VOID ) const { return m_bValid; } VOID TDebugNewAllocator:: Initialize( IN UINT uSizeHint ) { m_pTag = INTERNAL_NEW TDebugNewTag(); m_hDataHeap = HeapCreate( 0, kDataHeapSize, 0 ); if (m_hDataHeap && m_pTag->bInit() ) { m_bValid = TRUE; } } VOID TDebugNewAllocator:: Destroy( VOID ) { if (m_hDataHeap) { HeapDestroy( m_hDataHeap ); } INTERNAL_DELETE m_pTag; } // // Allocate a new memory block, tracking the allocation for // leak detection. // PVOID TDebugNewAllocator:: Allocate( IN SIZE_T Size, IN PVOID pVoid, IN LPCTSTR pszFile, IN UINT uLine ) { // // Allocate the memory block. // Header *pHeader = reinterpret_cast
( HeapAlloc( m_hDataHeap, 0, sizeof( Header ) + Size + sizeof( Tail ) ) ); // // If the block was allocated successfully. // if (pHeader) { // // Track this memory allocation. // if( m_pTag->Tag( &pHeader->pTag, pHeader, Size, pszFile, uLine ) ) { // // Set the header data and tail pattern. The tag back pointer is // is set for efficent release, the data area is filled with a known pattern // and tail is filled with a known pattern for overwrite detection. // FillHeaderDataTailPattern( pHeader, Size ); // // Adjust returned pointer to client data area. // pHeader++; } else { // // Tag entry was not available, something horrible happened. // If this happens then clean up the allocation and // return failure for this allocation. // HeapFree( m_hDataHeap, 0, pHeader ); pHeader = NULL; } } return pHeader; } // // Release the memory block, checking for duplicate frees and // tail overwrites. // VOID TDebugNewAllocator:: Release( IN PVOID pVoid ) { // // Convert the client data area pointer to header pointer. // Header *pHeader = reinterpret_cast
( pVoid ) - 1; // // Validate the header and tail signatures. // ValidationErrorCode ValidationError = ValidateHeaderDataTailPattern( pVoid, pHeader ); switch (ValidationError) { case kValidationErrorSuccess: // // Release allocation from tag list. // m_pTag->Release( pHeader->pTag ); // // Release this block back to the heap. // HeapFree( m_hDataHeap, 0, pHeader ); break; case kValidationErrorNullPointer: // // It is ok to attempt to free the null pointer. // break; // // We leak memory allocations that fail header, tail or tag validation. // case kValidationErrorInvalidHeader: ErrorText( _T("Buffer failed header validation\n") ); break; case kValidationErrorInvalidTail: ErrorText( _T("Buffer failed tail validation\n") ); break; case kValidationErrorUnknown: default: ErrorText( _T("Buffer failed validation\n") ); break; } } VOID TDebugNewAllocator:: Report( IN UINT uDevice, IN LPCTSTR pszConfiguration ) const { m_pTag->DisplayInuseTagEntries( uDevice, pszConfiguration ); } /******************************************************************** Private member functions. ********************************************************************/ VOID TDebugNewAllocator:: FillHeaderDataTailPattern( IN Header *pHeader, IN SIZE_T Size ) { // // Fill the header pattern. // memset( &pHeader->pSignature, kHeaderPattern, sizeof( PVOID ) ); // // Fill the Data pattern. // memset( ++pHeader, kDataAllocPattern, Size ); // // Calculate the tail pointer. // Tail *pTail = reinterpret_cast( reinterpret_cast( pHeader ) + Size ); // // Write the tail pattern. // memset( &pTail->pSignature, kTailPattern, sizeof( PVOID ) ); } TDebugNewAllocator::ValidationErrorCode TDebugNewAllocator:: ValidateHeaderDataTailPattern( IN PVOID pVoid, IN Header *pHeader ) { if (!pVoid) { return kValidationErrorNullPointer; } // // Validate the header pointer. // if (!pHeader) { return kValidationErrorInvalidHeaderPtr; } // // Validate the header structure. // if (IsBadReadPtr( pHeader, sizeof( Header ))) { return kValidationErrorInvalidHeader; } // // Validate the header signature. // PVOID pTemp; memset( &pTemp, kHeaderPattern, sizeof( PVOID ) ); if (pHeader->pSignature != pTemp) { return kValidationErrorInvalidHeaderSignature; } // // Validate the tag entry. // switch (m_pTag->ValidateEntry( pHeader->pTag )) { case TDebugNewTag::kValidationErrorInvalidPointer: break; case TDebugNewTag::kValidationErrorInvalidHeader: break; case TDebugNewTag::kValidationErrorTagNotLinked: break; case TDebugNewTag::kValidationErrorUnknown: default: break; } // // Get the tail pointer. // Tail *pTail = reinterpret_cast( reinterpret_cast(pHeader+1)+m_pTag->GetSize( pHeader->pTag ) ); // // Validate the tail structure. // if (IsBadReadPtr( pTail, sizeof( Tail ))) { return kValidationErrorInvalidTailPointer; } // // Validate the tail signature. // memset( &pTemp, kTailPattern, sizeof( PVOID ) ); if( pTail->pSignature != pTemp ) { return kValidationErrorInvalidTailSignature; } return kValidationErrorSuccess; }