270 lines
6.5 KiB
C
270 lines
6.5 KiB
C
/*++
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
rxcemm.c
|
||
|
||
Abstract:
|
||
|
||
This module contains the NT implementation of memory management for RxCe.
|
||
|
||
Notes:
|
||
|
||
|
||
--*/
|
||
|
||
#include "precomp.h"
|
||
#pragma hdrstop
|
||
#include "rxtdip.h"
|
||
|
||
//
|
||
// The debug trace level
|
||
//
|
||
|
||
#define Dbg (DEBUG_TRACE_RXCEPOOL)
|
||
|
||
#define RXCE_ZONE_ALLOCATION 0x80
|
||
|
||
//
|
||
// Pool debugging data structures.
|
||
//
|
||
LIST_ENTRY s_RxMdlList;
|
||
|
||
// MDL debugging structures.
|
||
|
||
typedef struct _WRAPPED_RX_MDL {
|
||
LIST_ENTRY Next;
|
||
PUCHAR File;
|
||
int Line;
|
||
PMDL pMdl;
|
||
} WRAPPED_RX_MDL, *PWRAPPED_RX_MDL;
|
||
|
||
//
|
||
// Pool header data structure. Ensure it is 8 byte aligned, no
|
||
// matter what members are added to the pool header
|
||
//
|
||
typedef struct _RX_POOL_HEADER {
|
||
union {
|
||
struct _RXH {
|
||
BYTE Signature[ 16 ];
|
||
ULONG Size;
|
||
ULONG Type;
|
||
PSZ AFileName;
|
||
ULONG ALineNumber;
|
||
PSZ FFileName;
|
||
ULONG FLineNumber;
|
||
};
|
||
UCHAR _pad[ (sizeof( struct _RXH ) + 7) & (~7) ];
|
||
};
|
||
} RX_POOL_HEADER, *PRX_POOL_HEADER;
|
||
|
||
//
|
||
// Number of trailer bytes after a pool allocation with a known signature
|
||
//
|
||
#define TRAIL_BYTES 16
|
||
|
||
#ifdef RX_POOL_WRAPPER
|
||
|
||
PVOID
|
||
_RxAllocatePoolWithTag(
|
||
ULONG Type,
|
||
ULONG Size,
|
||
ULONG Tag,
|
||
PSZ FileName,
|
||
ULONG LineNumber
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine allocates the desired pool and sets up the debugging header and trailer
|
||
to catch most instances of memory trashing
|
||
|
||
Arguments:
|
||
|
||
Type - type of pool to be allocated
|
||
|
||
Size - size of the allocation
|
||
|
||
Return Value:
|
||
|
||
a valid pointer if successful, otherwise FALSE.
|
||
|
||
--*/
|
||
{
|
||
#if 0
|
||
PCHAR pBuffer;
|
||
PRX_POOL_HEADER pPoolHeader;
|
||
|
||
ASSERT( Size != 0 );
|
||
ASSERT(
|
||
Type == PagedPool ||
|
||
Type == (PagedPool | POOL_COLD_ALLOCATION) ||
|
||
Type == NonPagedPool);
|
||
|
||
ASSERT( (sizeof(RX_POOL_HEADER)&7) == 0 );
|
||
|
||
pPoolHeader = ExAllocatePoolWithTagPriority(
|
||
Type,
|
||
sizeof( *pPoolHeader ) + Size + TRAIL_BYTES,
|
||
Tag,
|
||
LowPoolPriority);
|
||
|
||
if ( pPoolHeader == NULL ) {
|
||
RxLog(("RA:NULL %d %d %s\n", Type, LineNumber, &FileName[24]));
|
||
return( NULL );
|
||
}
|
||
|
||
//
|
||
// Fill the head so we can verify valid free's
|
||
//
|
||
RtlFillMemory( pPoolHeader->Signature, sizeof( pPoolHeader->Signature ), 'H' );
|
||
pPoolHeader->Size = Size;
|
||
pPoolHeader->Type = Type;
|
||
pPoolHeader->AFileName = FileName;
|
||
pPoolHeader->ALineNumber = LineNumber;
|
||
pPoolHeader->FFileName = NULL;
|
||
pPoolHeader->FLineNumber = 0;
|
||
|
||
pBuffer = (PCHAR)(pPoolHeader + 1);
|
||
|
||
//
|
||
// Fill the memory to catch uninitialized structures, etc
|
||
//
|
||
RtlFillMemory( pBuffer, Size, '*' );
|
||
|
||
//
|
||
// Fill the tail to catch overruns
|
||
//
|
||
RtlFillMemory( pBuffer + Size, TRAIL_BYTES, 'T' );
|
||
|
||
//
|
||
// Make sure we're starting out valid
|
||
//
|
||
RxCheckMemoryBlock( pBuffer );
|
||
|
||
return( pBuffer );
|
||
#endif
|
||
|
||
return ExAllocatePoolWithTagPriority(
|
||
Type,Size,Tag,LowPoolPriority);
|
||
}
|
||
|
||
VOID
|
||
_RxFreePool( PVOID pBuffer, PSZ FileName, ULONG LineNumber )
|
||
{
|
||
#if 0
|
||
if( _RxCheckMemoryBlock( pBuffer, FileName, LineNumber ) ) {
|
||
|
||
PRX_POOL_HEADER pPoolHeader = ((PRX_POOL_HEADER)pBuffer) - 1;
|
||
|
||
//
|
||
// Zap the block, to catch cases where we are using freed blocks
|
||
//
|
||
RtlFillMemory( pPoolHeader->Signature,
|
||
sizeof( pPoolHeader->Signature ),
|
||
'F' );
|
||
|
||
pPoolHeader->FFileName = FileName;
|
||
pPoolHeader->FLineNumber = LineNumber;
|
||
RtlFillMemory( pPoolHeader+1,
|
||
pPoolHeader->Size + TRAIL_BYTES,
|
||
'F' );
|
||
|
||
ExFreePool( pPoolHeader );
|
||
}
|
||
#endif
|
||
|
||
ExFreePool(pBuffer);
|
||
}
|
||
|
||
BOOLEAN
|
||
_RxCheckMemoryBlock(
|
||
PVOID pBuffer,
|
||
PSZ FileName,
|
||
ULONG LineNumber
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine frees up the pool allocated through RxAllocate
|
||
|
||
Arguments:
|
||
|
||
pv - the block to be freed
|
||
|
||
--*/
|
||
{
|
||
PRX_POOL_HEADER pPoolHeader = ((PRX_POOL_HEADER)pBuffer) - 1;
|
||
PCHAR pTail;
|
||
ULONG i;
|
||
|
||
if( pBuffer == NULL ) {
|
||
DbgPrint( "RxCheckMemoryBlock( NULL ) at %s %d\n",
|
||
FileName, LineNumber );
|
||
DbgBreakPoint();
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Make sure we have a valid block
|
||
//
|
||
for( i=0; i < sizeof( pPoolHeader->Signature ); i++ ) {
|
||
if( pPoolHeader->Signature[i] != 'H' ) {
|
||
if( pPoolHeader->Signature[i] == 'F' && i == 0 ) {
|
||
DbgPrint( "RxFreePool: Likely double free on block at %X\n", pPoolHeader );
|
||
}
|
||
|
||
DbgPrint( "RxCheckMemoryBlock: Invalid header signature for block %X\n", pPoolHeader );
|
||
DbgPrint( " Called from %s %d\n", FileName, LineNumber );
|
||
DbgPrint( " Originally Freed at %s %d\n",pPoolHeader->FFileName,pPoolHeader->FLineNumber);
|
||
DbgPrint( " Size is x%X, user part at %X\n", pPoolHeader->Size, pPoolHeader + 1 );
|
||
DbgBreakPoint();
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
if( pPoolHeader->Type != PagedPool &&
|
||
pPoolHeader->Type != (PagedPool | POOL_COLD_ALLOCATION) &&
|
||
pPoolHeader->Type != NonPagedPool) {
|
||
DbgPrint( "RxCheckMemoryBlock:\n" );
|
||
DbgPrint( " Invalid PoolHeader->Type for block %X\n", pPoolHeader );
|
||
DbgPrint( " Called from %s %d\n", FileName, LineNumber );
|
||
DbgBreakPoint();
|
||
return FALSE;
|
||
}
|
||
|
||
if( pPoolHeader->Size == 0 ) {
|
||
DbgPrint( "RxCheckMemoryBlock:\n" );
|
||
DbgPrint( " Size is 0 for block %X\n", pPoolHeader );
|
||
DbgPrint( " Called from %s %d\n", FileName, LineNumber );
|
||
DbgBreakPoint();
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Look to see if the buffer has been overrun
|
||
//
|
||
pTail = (PCHAR)pBuffer + pPoolHeader->Size;
|
||
for( i=0; i < TRAIL_BYTES; i++ ) {
|
||
if( *pTail++ != 'T' ) {
|
||
DbgPrint( "RxCheckMemoryBlock: Overrun memory block at %X\n", pPoolHeader );
|
||
DbgPrint( " RxCheckMemoryBlock called from %s line %d\n", FileName, LineNumber );
|
||
DbgPrint( " Allocated at %s line %d\n", pPoolHeader->AFileName, pPoolHeader->ALineNumber );
|
||
DbgPrint( " Size is x%X, user part at %X\n", pPoolHeader->Size, pPoolHeader + 1 );
|
||
DbgPrint( " Overrun begins at %X\n", pTail-1 );
|
||
DbgBreakPoint();
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
#endif
|
||
|
||
|