|
|
/*++
Copyright (c) 1995-2001 Microsoft Corporation
Module Name:
heapdbg.c
Abstract:
Domain Name System (DNS) Library
Heap debugging routines.
Author:
Jim Gilroy (jamesg) January 31, 1995
Revision History:
--*/
#include "local.h"
#include "heapdbg.h"
//
// locking
//
#define LOCK_HEAP(p) EnterCriticalSection( &p->ListCs )
#define UNLOCK_HEAP(p) LeaveCriticalSection( &p->ListCs )
//
// Heap
//
// Debug heap routines allow heap to be specified by caller of
// each routine, or by having heap global.
// If global, the heap handle may be supplied to initialization
// routine OR created internally.
//
#define HEAP_DBG_DEFAULT_CREATE_FLAGS \
( HEAP_GROWABLE | \ HEAP_GENERATE_EXCEPTIONS | \ HEAP_TAIL_CHECKING_ENABLED | \ HEAP_FREE_CHECKING_ENABLED | \ HEAP_CREATE_ALIGN_16 | \ HEAP_CLASS_1 )
//
// Dnslib using this heap
//
PHEAP_BLOB g_pDnslibHeapBlob;
HEAP_BLOB g_DnslibHeapBlob;
//
// Heap Header / Trailer Flags
//
#define HEAP_CODE 0xdddddddd
#define HEAP_CODE_ACTIVE 0xaaaaaaaa
#define HEAP_CODE_FREE 0xeeeeeeee
//
// Heap Trailer from Header
//
#define HEAP_TRAILER(_head_) \
( (PHEAP_TRAILER) ( \ (PCHAR)(_head_) \ + (_head_)->AllocSize \ - sizeof(HEAP_TRAILER) ) )
//
// Private protos
//
VOID DbgHeapValidateHeader( IN PHEAP_HEADER h );
//
// Private utilities
//
INT DbgHeapFindAllocSize( IN INT iRequestSize ) /*++
Routine Description:
Determines actual size of debug alloc.
Adds in sizes of DWORD aligned header and trailer.
Arguments:
iRequestSize - requested allocation size
Return Value:
None
--*/ { register INT imodSize;
//
// find DWORD multiple size of original alloc,
// this is required so debug trailer will be DWORD aligned
//
imodSize = iRequestSize % sizeof(DWORD); if ( imodSize ) { imodSize = sizeof(DWORD) - imodSize; }
imodSize += iRequestSize + sizeof(HEAP_HEADER) + sizeof(HEAP_TRAILER);
ASSERT( ! (imodSize % sizeof(DWORD)) );
return( imodSize ); }
PVOID DbgHeapSetHeaderAlloc( IN OUT PHEAP_BLOB pHeap, IN OUT PHEAP_HEADER h, IN INT iSize, IN LPSTR pszFile, IN DWORD dwLine ) /*++
Routine Description:
Sets/Resets heap globals and heap header info.
Arguments:
h - ptr to new memory block
iSize - size allocated
Return Value:
None
--*/ { PHEAP_TRAILER t; INT allocSize;
ASSERT( iSize > 0 );
//
// determine actual alloc
//
allocSize = DbgHeapFindAllocSize( iSize );
//
// update heap info globals
//
pHeap->AllocMem += allocSize; pHeap->CurrentMem += allocSize; pHeap->AllocCount++; pHeap->CurrentCount++;
//
// fill in header
//
h->HeapCodeBegin = HEAP_CODE; h->AllocCount = pHeap->AllocCount; h->AllocSize = allocSize; h->RequestSize = iSize;
h->LineNo = dwLine; h->FileName = pszFile;
#if 0
allocSize = strlen(pszFile) - HEAP_HEADER_FILE_SIZE; if ( allocSize > 0 ) { pszFile = &pszFile[ allocSize ]; } strncpy( h->FileName, pszFile, HEAP_HEADER_FILE_SIZE ); #endif
h->AllocTime = GetCurrentTime(); h->CurrentMem = pHeap->CurrentMem; h->CurrentCount = pHeap->CurrentCount; h->HeapCodeEnd = HEAP_CODE_ACTIVE;
//
// fill in trailer
//
t = HEAP_TRAILER( h ); t->HeapCodeBegin = h->HeapCodeBegin; t->AllocCount = h->AllocCount; t->AllocSize = h->AllocSize; t->HeapCodeEnd = h->HeapCodeEnd;
//
// attach to alloc list
//
LOCK_HEAP(pHeap); InsertTailList( &pHeap->ListHead, &h->ListEntry ); UNLOCK_HEAP(pHeap);
//
// return ptr to user memory
// - first byte past header
//
return( h+1 ); }
PHEAP_HEADER DbgHeapSetHeaderFree( IN OUT PHEAP_BLOB pHeap, IN OUT PVOID pMem ) /*++
Routine Description:
Resets heap globals and heap header info for free.
Arguments:
pMem - ptr to user memory to free
Return Value:
Ptr to block to be freed.
--*/ { register PHEAP_HEADER h;
//
// validate memory block -- get ptr to header
//
h = Dns_DbgHeapValidateMemory( pMem, TRUE );
//
// get blob if not passed in
//
if ( !pHeap ) { pHeap = h->pHeap; }
//
// remove from current allocs list
//
LOCK_HEAP(pHeap);
RemoveEntryList( &h->ListEntry );
UNLOCK_HEAP(pHeap);
//
// update heap info globals
//
pHeap->CurrentMem -= h->AllocSize; pHeap->FreeMem += h->AllocSize; pHeap->FreeCount++; pHeap->CurrentCount--;
//
// reset header
//
h->HeapCodeEnd = HEAP_CODE_FREE; HEAP_TRAILER(h)->HeapCodeBegin = HEAP_CODE_FREE;
//
// return ptr to block to be freed
//
return( h ); }
//
// Heap Init\Cleanup
//
DNS_STATUS Dns_HeapInitialize( OUT PHEAP_BLOB pHeap, IN HANDLE hHeap, IN DWORD dwCreateFlags, IN BOOL fUseHeaders, IN BOOL fResetDnslib, IN BOOL fFullHeapChecks, IN DWORD dwException, IN DWORD dwDefaultFlags, IN PSTR pszDefaultFileName, IN DWORD dwDefaultFileLine ) /*++
Routine Description:
Initialize heap debugging.
MUST call this routine before using DbgHeapMessage routines.
Arguments:
pHeap -- heap blob to setup
hHeap -- heap to use
dwCreateFlags -- flags to RtlCreateHeap() if creating
fUseHeaders -- use headers and trailers for full debug
fResetDnslib -- reset dnslib heap to use these routines
fFullHeapChecks -- flag, TRUE for full heap checks
dwException -- exception to raise if out of heap
dwDefaultFlags -- heap flags for simple alloc\free
pszDefaultFileName -- file name for simple alloc\free
dwDefaultFileLine -- file line# for simple alloc\free
Return Value:
None.
--*/ { DNSDBG( TRACE, ( "Dns_DbgHeapInit( %p )\n", pHeap ));
//
// zero heap blob
//
RtlZeroMemory( pHeap, sizeof(*pHeap) );
// alloc list
// - alloc list head
// - critical section to protect list operations
InitializeListHead( &pHeap->ListHead ); if ( fUseHeaders ) { DNS_STATUS status = RtlInitializeCriticalSection( &pHeap->ListCs ); if ( status != NO_ERROR ) { return status; } }
//
// heap
// can either
// - always get heap in each call
// - use heap caller supplies here
// - create a heap here
//
// to use simple dnslib compatible calls we must have
// a known heap, so must get one created here
// DCR: not sure this is TRUE, process heap may work
// g_hDnsHeap left NULL
//
if ( hHeap ) { pHeap->hHeap = hHeap; } else { pHeap->hHeap = RtlCreateHeap( dwCreateFlags ? dwCreateFlags : HEAP_DBG_DEFAULT_CREATE_FLAGS, NULL, // no base specified
0, // default reserve size
0, // default commit size
NULL, // no lock
NULL // no parameters
); if ( !pHeap->hHeap ) { return DNS_ERROR_NO_MEMORY; } pHeap->fCreated = TRUE; } pHeap->Tag = HEAP_CODE_ACTIVE;
// set globals
// - full heap checks before all heap operations?
// - raise exception on alloc failure?
pHeap->fHeaders = fUseHeaders; pHeap->fCheckAll = fFullHeapChecks; pHeap->FailureException = dwException;
// set globals for simple allocator
pHeap->DefaultFlags = dwDefaultFlags; pHeap->pszDefaultFile = pszDefaultFileName; pHeap->DefaultLine = dwDefaultFileLine;
// reset dnslib heap routines to use debug heap
if ( fResetDnslib ) { if ( fUseHeaders ) { Dns_LibHeapReset( Dns_DbgHeapAlloc, Dns_DbgHeapRealloc, Dns_DbgHeapFree ); } else { Dns_LibHeapReset( Dns_HeapAlloc, Dns_HeapRealloc, Dns_HeapFree ); }
g_pDnslibHeapBlob = pHeap; }
return NO_ERROR; }
VOID Dns_HeapCleanup( IN OUT PHEAP_BLOB pHeap ) /*++
Routine Description:
Cleanup.
Arguments:
None.
Return Value:
None.
--*/ { DNSDBG( TRACE, ( "Dns_HeapCleanup( %p )\n", pHeap ));
// if not initialized -- do nothing
if ( !pHeap ) { return; } if ( pHeap->Tag != HEAP_CODE_ACTIVE ) { DNS_ASSERT( pHeap->Tag == HEAP_CODE_ACTIVE ); return; } DNS_ASSERT( pHeap->hHeap );
// if created heap, destroy it
if ( pHeap->fCreated ) { RtlDestroyHeap( pHeap->hHeap ); }
// cleanup critical section
if ( pHeap->fHeaders ) { RtlDeleteCriticalSection( &pHeap->ListCs ); }
// tag as invalid
pHeap->Tag = HEAP_CODE_FREE; }
//
// Heap Validation
//
VOID DbgHeapValidateHeader( IN PHEAP_HEADER h ) /*++
Routine Description:
Validates heap header.
Arguments:
h - ptr to header of block
Return Value:
None.
--*/ { register PHEAP_TRAILER t;
//
// extract trailer
//
t = HEAP_TRAILER( h );
//
// verify header
//
if ( h->HeapCodeBegin != HEAP_CODE || h->HeapCodeEnd != HEAP_CODE_ACTIVE ) { DNSDBG( HEAPDBG, ( "Invalid memory block at %p -- invalid header.\n", h ));
if ( h->HeapCodeEnd == HEAP_CODE_FREE ) { DNSDBG( HEAPDBG, ( "ERROR: Previous freed memory.\n" )); } goto Invalid; }
//
// match header, trailer alloc number
//
if ( h->HeapCodeBegin != t->HeapCodeBegin || h->AllocCount != t->AllocCount || h->AllocSize != t->AllocSize || h->HeapCodeEnd != t->HeapCodeEnd ) { DNSDBG( HEAPDBG, ( "Invalid memory block at %p -- header / trailer mismatch.\n", h )); goto Invalid; } return;
Invalid:
DNSDBG( ANY, ( "Validation failure, in heap blob %p\n", h->pHeap ));
Dns_DbgHeapHeaderPrint( h, t ); ASSERT( FALSE ); Dns_DbgHeapGlobalInfoPrint( h->pHeap ); Dns_DbgHeapDumpAllocList( h->pHeap ); ASSERT( FALSE ); return; }
PHEAP_HEADER Dns_DbgHeapValidateMemory( IN PVOID pMem, IN BOOL fAtHeader ) /*++
Routine Description:
Validates users heap pointer, and returns actual.
Note: This memory MUST have been allocated by THESE MEMORY routines.
Arguments:
pMem - ptr to memory to validate
fAtHeader - TRUE if pMem is known to be immediately after a head header, otherwise this function will search backwards through memory starting at pMem looking for a valid heap header
Return Value:
Pointer to actual heap pointer.
--*/ { register PHEAP_HEADER pheader;
//
// Get pointer to heap header.
//
pheader = (PHEAP_HEADER) pMem - 1; if ( !fAtHeader ) { int iterations = 32 * 1024;
//
// Back up from pMem a DWORD at a time looking for HEAP_CODE.
// If we don't find one, eventually we will generate an exception,
// which will be interesting. This could be handled, but for now
// this loop will just walk to past the start of valid memory.
//
while ( 1 ) { //
// Break if we've found the heap header.
//
if ( pheader->HeapCodeBegin == HEAP_CODE && ( pheader->HeapCodeEnd == HEAP_CODE_ACTIVE || pheader->HeapCodeEnd == HEAP_CODE_FREE ) ) { break; }
//
// Sanity check: too many iterations?
//
if ( ( --iterations ) == 0 ) { ASSERT( iterations > 0 ); return NULL; }
//
// Back up another DWORD.
//
pheader = ( PHEAP_HEADER ) ( ( PBYTE ) pheader - 4 ); } }
//
// Verify header and trailer.
//
DbgHeapValidateHeader( pheader );
return pheader; }
VOID Dns_DbgHeapValidateAllocList( IN OUT PHEAP_BLOB pHeap ) /*++
Routine Description:
Dumps header information for all nodes in alloc list.
Arguments:
None
Return Value:
None
--*/ { PLIST_ENTRY pentry;
DNSDBG( TRACE, ( "Dns_DbgHeapValidateAllocList( %p )\n", pHeap ));
if ( !pHeap->fHeaders ) { DNS_ASSERT( pHeap->fHeaders ); return; }
//
// loop through all outstanding alloc's, validating each one
//
LOCK_HEAP(pHeap);
pentry = pHeap->ListHead.Flink;
while( pentry != &pHeap->ListHead ) { DbgHeapValidateHeader( HEAP_HEADER_FROM_LIST_ENTRY(pentry) );
pentry = pentry->Flink; } UNLOCK_HEAP(pHeap); }
//
// Heap Printing
//
VOID Dns_DbgHeapGlobalInfoPrint( IN PHEAP_BLOB pHeap ) /*++
Routine Description:
Prints global heap info.
Arguments:
None
Return Value:
None
--*/ { DNS_PRINT(( "Debug Heap Information:\n" "\tHeap Blob = %p\n" "\tHandle = %p\n" "\tDebug headers = %d\n" "\tDnslib redirect = %d\n" "\tFull checks = %d\n" "\tFlags = %08x\n" "\tStats ---------------\n" "\tMemory Allocated = %d\n" "\tMemory Freed = %d\n" "\tMemory Current = %d\n" "\tAlloc Count = %d\n" "\tFree Count = %d\n" "\tCurrent Count = %d\n",
pHeap, pHeap->hHeap, pHeap->fHeaders, pHeap->fDnsLib, pHeap->fCheckAll, pHeap->DefaultFlags,
pHeap->AllocMem, pHeap->FreeMem, pHeap->CurrentMem, pHeap->AllocCount, pHeap->FreeCount, pHeap->CurrentCount )); }
VOID Dns_DbgHeapHeaderPrint( IN PHEAP_HEADER h, IN PHEAP_TRAILER t ) /*++
Routine Description:
Prints heap header and trailer.
Arguments:
None
Return Value:
None
--*/ { if ( h ) { DNSDBG( HEAPDBG, ( "Heap Header at %p:\n" "\tHeapCodeBegin = %08lx\n" "\tAllocCount = %d\n" "\tAllocSize = %d\n" "\tRequestSize = %d\n" "\tHeapBlob = %p\n" "\tFileName = %s\n" "\tLineNo = %d\n" "\tAllocTime = %d\n" "\tCurrentMem = %d\n" "\tCurrentCount = %d\n" "\tHeapCodeEnd = %08lx\n", h, h->HeapCodeBegin, h->AllocCount, h->AllocSize, h->RequestSize, h->pHeap, h->FileName, h->LineNo, h->AllocTime / 1000, h->CurrentMem, h->CurrentCount, h->HeapCodeEnd )); }
if ( t ) { DNSDBG( HEAPDBG, ( "Heap Trailer at %p:\n" "\tHeapCodeBegin = %08lx\n" "\tAllocCount = %d\n" "\tAllocSize = %d\n" "\tHeapCodeEnd = %08lx\n", t, t->HeapCodeBegin, t->AllocCount, t->AllocSize, t->HeapCodeEnd )); } }
VOID Dns_DbgHeapDumpAllocList( IN PHEAP_BLOB pHeap ) /*++
Routine Description:
Dumps header information for all nodes in alloc list.
Arguments:
None
Return Value:
None
--*/ { PLIST_ENTRY pentry; PHEAP_HEADER phead;
if ( !pHeap->fHeaders ) { DNSDBG( HEAPDBG, ( "Non-debug heap -- no alloc list!\n" )); return; }
//
// loop through all outstanding alloc's, dumping output
//
LOCK_HEAP(pHeap); DNSDBG( HEAPDBG, ( "Dumping Alloc List:\n" ));
pentry = pHeap->ListHead.Flink;
while( pentry != &pHeap->ListHead ) { phead = HEAP_HEADER_FROM_LIST_ENTRY( pentry );
Dns_DbgHeapHeaderPrint( phead, HEAP_TRAILER( phead ) ); pentry = pentry->Flink; }
DNSDBG( HEAPDBG, ( "End Dump of Alloc List.\n" )); UNLOCK_HEAP(pHeap); }
//
// Full debug heap routines
//
PVOID Dns_DbgHeapAllocEx( IN OUT PHEAP_BLOB pHeap, IN DWORD dwFlags, IN INT iSize, IN LPSTR pszFile, IN DWORD dwLine ) /*++
Routine Description:
Allocates memory.
Arguments:
iSize - number of bytes to allocate
Return Value:
Pointer to memory allocated. NULL if allocation fails.
--*/ { register PHEAP_HEADER h; INT allocSize;
DNSDBG( HEAP2, ( "Dns_DbgHeapAlloc( %p, %d )\n", pHeap, iSize ));
//
// full heap check?
//
IF_DNSDBG( HEAP_CHECK ) { Dns_DbgHeapValidateAllocList( pHeap ); }
if ( iSize <= 0 ) { DNSDBG( ANY, ( "Invalid alloc size = %d\n", iSize )); DNS_ASSERT( FALSE ); return( NULL ); }
//
// allocate memory
//
// first add heap header to size
//
allocSize = DbgHeapFindAllocSize( iSize );
h = (PHEAP_HEADER) RtlAllocateHeap( pHeap->hHeap, dwFlags ? dwFlags : pHeap->DefaultFlags, allocSize ); if ( ! h ) { Dns_DbgHeapGlobalInfoPrint( pHeap ); return NULL; }
//
// setup header / globals for new alloc
//
// return ptr to first byte after header
//
return DbgHeapSetHeaderAlloc( pHeap, h, iSize, pszFile, dwLine ); }
PVOID Dns_DbgHeapReallocEx( IN OUT PHEAP_BLOB pHeap, IN DWORD dwFlags, IN OUT PVOID pMem, IN INT iSize, IN LPSTR pszFile, IN DWORD dwLine ) /*++
Routine Description:
Reallocates memory
Arguments:
pMem - ptr to existing memory to reallocated iSize - number of bytes to reallocate
Return Value:
Pointer to memory allocated. NULL if allocation fails.
--*/ { register PHEAP_HEADER h; register PHEAP_HEADER pnew; INT previousSize; INT allocSize;
//
// full heap check?
//
IF_DNSDBG( HEAP_CHECK ) { Dns_DbgHeapValidateAllocList( pHeap ); }
if ( iSize <= 0 ) { DNSDBG( HEAPDBG, ( "Invalid realloc size = %d\n", iSize )); return( NULL ); }
//
// validate memory
//
// extract pointer to actual alloc'd block
// mark as free, and reset globals appropriately
//
h = DbgHeapSetHeaderFree( pHeap, pMem );
//
// reallocate memory
//
// first add heap header to size
//
allocSize = DbgHeapFindAllocSize( iSize );
pnew = (PHEAP_HEADER) RtlReAllocateHeap( pHeap->hHeap, dwFlags ? dwFlags : pHeap->DefaultFlags, h, allocSize ); if ( ! pnew ) { Dns_DbgHeapGlobalInfoPrint( pHeap ); return( NULL ); }
//
// setup header / globals for realloc
//
// return ptr to first byte after header
//
return DbgHeapSetHeaderAlloc( pHeap, pnew, iSize, pszFile, dwLine ); }
VOID Dns_DbgHeapFreeEx( IN OUT PHEAP_BLOB pHeap, IN DWORD dwFlags, IN OUT PVOID pMem ) /*++
Routine Description:
Frees memory
Note: This memory MUST have been allocated by DbgHeap routines.
Arguments:
pMem - ptr to memory to be freed
Return Value:
None.
--*/ { register PHEAP_HEADER h;
DNSDBG( HEAP2, ( "Dns_DbgHeapFreeEx( %p, %p )\n", pHeap, pMem ));
//
// validate header
//
// reset heap header / globals for free
//
h = DbgHeapSetHeaderFree( pHeap, pMem );
//
// get blob
//
if ( !pHeap ) { pHeap = h->pHeap; }
//
// full heap check?
//
IF_DNSDBG( HEAP_CHECK ) { Dns_DbgHeapValidateAllocList( pHeap ); }
RtlFreeHeap( pHeap->hHeap, dwFlags ? dwFlags : pHeap->DefaultFlags, h ); }
//
// Dnslib memory compatible versions
//
// Heap routines with simple function signature that matches
// the dnslib routines and allows DnsLib memory routines to
// be redirected to these routines through Dns_LibHeapReset().
//
// Note: to use these functions, must have specified at particular
// heap to use.
//
PVOID Dns_DbgHeapAlloc( IN INT iSize ) { return Dns_DbgHeapAllocEx( g_pDnslibHeapBlob, 0, iSize, NULL, 0 ); }
PVOID Dns_DbgHeapRealloc( IN OUT PVOID pMem, IN INT iSize ) { return Dns_DbgHeapReallocEx( g_pDnslibHeapBlob, 0, pMem, iSize, NULL, 0 ); }
VOID Dns_DbgHeapFree( IN OUT PVOID pMem ) { Dns_DbgHeapFreeEx( g_pDnslibHeapBlob, 0, pMem ); }
//
// Non debug header versions
//
// These allow you to use a private heap with some of the features
// of the debug heap
// - same initialization
// - specifying individual heap
// - redirection of dnslib (without building your own routines)
// - alloc and free counts
// but without the overhead of the headers.
//
PVOID Dns_HeapAllocEx( IN OUT PHEAP_BLOB pHeap, IN DWORD dwFlags, IN INT iSize ) /*++
Routine Description:
Allocates memory.
Arguments:
pHeap - heap to use
dwFlags - flags
iSize - number of bytes to allocate
Return Value:
Pointer to memory allocated. NULL if allocation fails.
--*/ { PVOID p;
DNSDBG( HEAP2, ( "Dns_HeapAlloc( %p, %d )\n", pHeap, iSize ));
//
// allocate memory
//
p = (PHEAP_HEADER) RtlAllocateHeap( pHeap->hHeap, dwFlags ? dwFlags : pHeap->DefaultFlags, iSize ); if ( p ) { pHeap->AllocCount++; pHeap->CurrentCount++; } return p; }
PVOID Dns_HeapReallocEx( IN OUT PHEAP_BLOB pHeap, IN DWORD dwFlags, IN OUT PVOID pMem, IN INT iSize ) /*++
Routine Description:
Reallocates memory
Arguments:
pMem - ptr to existing memory to reallocated iSize - number of bytes to reallocate
Return Value:
Pointer to memory allocated. NULL if allocation fails.
--*/ { PVOID p; INT previousSize; INT allocSize;
//
// reallocate memory
//
// first add heap header to size
//
p = RtlReAllocateHeap( pHeap->hHeap, dwFlags ? dwFlags : pHeap->DefaultFlags, pMem, iSize ); if ( p ) { pHeap->AllocCount++; pHeap->FreeCount++; } return p; }
VOID Dns_HeapFreeEx( IN OUT PHEAP_BLOB pHeap, IN DWORD dwFlags, IN OUT PVOID pMem ) /*++
Routine Description:
Frees memory
Note: This memory MUST have been allocated by DbgHeap routines.
Arguments:
pMem - ptr to memory to be freed
Return Value:
None.
--*/ { DNSDBG( HEAP2, ( "Dns_HeapFreeEx( %p, %p )\n", pHeap, pMem ));
RtlFreeHeap( pHeap->hHeap, dwFlags ? dwFlags : pHeap->DefaultFlags, pMem );
pHeap->FreeCount++; pHeap->CurrentCount--; }
//
// Dnslib memory compatible versions
//
// Heap routines with simple function signature that matches
// the dnslib routines and allows DnsLib memory routines to
// be redirected to these routines through Dns_LibHeapReset().
//
// Note: to use these functions, must have specified at particular
// heap to use.
//
PVOID Dns_HeapAlloc( IN INT iSize ) { return Dns_HeapAllocEx( g_pDnslibHeapBlob, 0, iSize ); }
PVOID Dns_HeapRealloc( IN OUT PVOID pMem, IN INT iSize ) { return Dns_HeapReallocEx( g_pDnslibHeapBlob, 0, pMem, iSize ); }
VOID Dns_HeapFree( IN OUT PVOID pMem ) { Dns_HeapFreeEx( g_pDnslibHeapBlob, 0, pMem ); }
//
// End heapdbg.c
//
|