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
|
|||
|
|
|||
|
|