windows-nt/Source/XPSP1/NT/printscan/print/spooler/dbglib/dbgnewp.cxx

329 lines
6.4 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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<Header *>( 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<Header *>( 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<Tail *>( reinterpret_cast<PBYTE>( 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<Tail *>( reinterpret_cast<PBYTE>(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;
}