mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
851 lines
24 KiB
851 lines
24 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
pool.c
|
|
|
|
Abstract:
|
|
|
|
WinDbg Extension Api
|
|
|
|
Author:
|
|
|
|
Lou Perazzoli (Loup) 5-Nov-1993
|
|
|
|
Environment:
|
|
|
|
User Mode.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#include <limits.h>
|
|
|
|
typedef struct _POOL_BLOCK_HEAD {
|
|
POOL_HEADER Header;
|
|
LIST_ENTRY List;
|
|
} POOL_BLOCK_HEAD, *PPOOL_BLOCK_HEADER;
|
|
|
|
typedef struct _POOL_HACKER {
|
|
POOL_HEADER Header;
|
|
ULONG Contents[8];
|
|
} POOL_HACKER;
|
|
|
|
|
|
#define TAG 0
|
|
#define NONPAGED_ALLOC 1
|
|
#define NONPAGED_FREE 2
|
|
#define PAGED_ALLOC 3
|
|
#define PAGED_FREE 4
|
|
#define NONPAGED_USED 5
|
|
#define PAGED_USED 6
|
|
|
|
ULONG SortBy;
|
|
ULONG Paren;
|
|
|
|
int UserSpecifiedLineLimit = INT_MAX;
|
|
BOOLEAN LimitMaxLines = TRUE;
|
|
|
|
typedef struct _FILTER {
|
|
ULONG Tag;
|
|
BOOLEAN Exclude;
|
|
} FILTER, *PFILTER;
|
|
|
|
#define MAX_FILTER 64
|
|
FILTER Filter[MAX_FILTER];
|
|
ULONG FilterCount = 0;
|
|
|
|
typedef struct _STRING_HACK {
|
|
ULONG String1;
|
|
ULONG Pad;
|
|
} STRING_HACK, *PSTRING_HACK;
|
|
|
|
|
|
BOOLEAN
|
|
CheckSingleFilter (
|
|
PCHAR Tag,
|
|
PCHAR Filter
|
|
);
|
|
|
|
int _CRTAPI1
|
|
ulcomp(const void *e1,const void *e2);
|
|
|
|
int _CRTAPI1
|
|
ulcomp(const void *e1,const void *e2)
|
|
{
|
|
ULONG u1;
|
|
|
|
switch (SortBy) {
|
|
case TAG:
|
|
|
|
u1 = ((PUCHAR)e1)[0] - ((PUCHAR)e2)[0];
|
|
if (u1 != 0) {
|
|
return u1;
|
|
}
|
|
u1 = ((PUCHAR)e1)[1] - ((PUCHAR)e2)[1];
|
|
if (u1 != 0) {
|
|
return u1;
|
|
}
|
|
u1 = ((PUCHAR)e1)[2] - ((PUCHAR)e2)[2];
|
|
if (u1 != 0) {
|
|
return u1;
|
|
}
|
|
u1 = ((PUCHAR)e1)[3] - ((PUCHAR)e2)[3];
|
|
return u1;
|
|
break;
|
|
|
|
case NONPAGED_ALLOC:
|
|
u1 = ((PPOOL_TRACKER_TABLE)e2)->NonPagedAllocs -
|
|
((PPOOL_TRACKER_TABLE)e1)->NonPagedAllocs;
|
|
return (u1);
|
|
break;
|
|
|
|
case NONPAGED_FREE:
|
|
u1 = ((PPOOL_TRACKER_TABLE)e2)->NonPagedFrees -
|
|
((PPOOL_TRACKER_TABLE)e1)->NonPagedFrees;
|
|
return (u1);
|
|
break;
|
|
|
|
case NONPAGED_USED:
|
|
u1 = ((PPOOL_TRACKER_TABLE)e2)->NonPagedBytes -
|
|
((PPOOL_TRACKER_TABLE)e1)->NonPagedBytes;
|
|
return (u1);
|
|
break;
|
|
|
|
case PAGED_USED:
|
|
u1 = ((PPOOL_TRACKER_TABLE)e2)->PagedBytes -
|
|
((PPOOL_TRACKER_TABLE)e1)->PagedBytes;
|
|
return (u1);
|
|
break;
|
|
|
|
default:
|
|
return(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
DECLARE_API( frag )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump pool fragmentation
|
|
|
|
Arguments:
|
|
|
|
args - Flags
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG Flags;
|
|
ULONG result;
|
|
ULONG i;
|
|
ULONG count;
|
|
PUCHAR Pool;
|
|
ULONG PoolLoc1;
|
|
ULONG TotalFrag;
|
|
ULONG TotalCount;
|
|
ULONG Frag;
|
|
ULONG PoolStart;
|
|
POOL_DESCRIPTOR PoolDesc;
|
|
PPOOL_DESCRIPTOR PoolLoc;
|
|
POOL_BLOCK_HEAD PoolBlock;
|
|
|
|
dprintf("\n NonPaged Pool Fragmentation\n\n");
|
|
Flags = 0;
|
|
PoolStart = 0;
|
|
|
|
sscanf(args,"%lx %lx", &Flags,&PoolStart);
|
|
|
|
if (PoolStart != 0) {
|
|
PoolStart += POOL_OVERHEAD;
|
|
|
|
Pool = (PUCHAR)PoolStart;
|
|
do {
|
|
|
|
Pool = Pool - POOL_OVERHEAD;
|
|
if ( !ReadMemory( (DWORD)Pool,
|
|
&PoolBlock,
|
|
sizeof(PoolBlock),
|
|
&result) ) {
|
|
dprintf("%08lx: Unable to get contents of pool block\n", Pool );
|
|
return;
|
|
}
|
|
|
|
count += 1;
|
|
|
|
dprintf(" %lx size: %4lx previous size: %4lx %c%c%c%c links: %8lx %8lx\n",
|
|
(ULONG)Pool,
|
|
(ULONG)PoolBlock.Header.BlockSize << POOL_BLOCK_SHIFT,
|
|
(ULONG)PoolBlock.Header.PreviousSize << POOL_BLOCK_SHIFT,
|
|
(ULONG)PoolBlock.Header.PoolTag,
|
|
(ULONG)PoolBlock.Header.PoolTag >> 8,
|
|
(ULONG)PoolBlock.Header.PoolTag >> 16,
|
|
(ULONG)(PoolBlock.Header.PoolTag&~PROTECTED_POOL) >> 24,
|
|
(ULONG)PoolBlock.List.Flink,
|
|
(ULONG)PoolBlock.List.Blink);
|
|
|
|
if (Flags != 3) {
|
|
Pool = (PUCHAR)PoolBlock.List.Flink;
|
|
} else {
|
|
Pool = (PUCHAR)PoolBlock.List.Blink;
|
|
}
|
|
if ( CheckControlC() ) {
|
|
return;
|
|
}
|
|
} while ( ((ULONG)Pool & 0xfffffff0) != (PoolStart & 0xfffffff0 ));
|
|
|
|
return;
|
|
}
|
|
|
|
PoolLoc1 = GetExpression( "NonPagedPoolDescriptor" );
|
|
if ( !PoolLoc1 ) {
|
|
dprintf("unable to get nonpaged pool head\n");
|
|
return;
|
|
|
|
} else {
|
|
PoolLoc = (PPOOL_DESCRIPTOR)PoolLoc1;
|
|
if ( !ReadMemory( (DWORD)PoolLoc,
|
|
&PoolDesc,
|
|
sizeof(POOL_DESCRIPTOR),
|
|
&result) ) {
|
|
dprintf("%08lx: Unable to get pool descriptor\n", PoolLoc1 );
|
|
return;
|
|
}
|
|
}
|
|
|
|
TotalFrag = 0;
|
|
TotalCount = 0;
|
|
|
|
for (i=0; i < POOL_LIST_HEADS ;i++ ) {
|
|
|
|
Frag = 0;
|
|
count = 0;
|
|
Pool = (PUCHAR)PoolDesc.ListHeads[i].Flink;
|
|
|
|
while ( Pool != (PUCHAR)(&PoolLoc->ListHeads[i])) {
|
|
|
|
Pool = Pool - POOL_OVERHEAD;
|
|
if ( !ReadMemory( (DWORD)Pool,
|
|
&PoolBlock,
|
|
sizeof(PoolBlock),
|
|
&result) ) {
|
|
dprintf("%08lx: Unable to get contents of pool block\n", Pool );
|
|
return;
|
|
}
|
|
|
|
Frag += (ULONG)PoolBlock.Header.BlockSize << POOL_BLOCK_SHIFT;
|
|
count += 1;
|
|
|
|
if (Flags & 2) {
|
|
dprintf(" %lx size: %4lx previous size: %4lx %c%c%c%c\n",
|
|
(ULONG)Pool,
|
|
(ULONG)PoolBlock.Header.BlockSize << POOL_BLOCK_SHIFT,
|
|
(ULONG)PoolBlock.Header.PreviousSize << POOL_BLOCK_SHIFT,
|
|
(ULONG)PoolBlock.Header.PoolTag,
|
|
(ULONG)PoolBlock.Header.PoolTag >> 8,
|
|
(ULONG)PoolBlock.Header.PoolTag >> 16,
|
|
(ULONG)(PoolBlock.Header.PoolTag&~PROTECTED_POOL) >> 24);
|
|
}
|
|
Pool = (PUCHAR)PoolBlock.List.Flink;
|
|
if ( CheckControlC() ) {
|
|
return;
|
|
}
|
|
}
|
|
if (Flags & 1) {
|
|
dprintf("index: %2ld number of fragments: %5ld bytes: %6ld\n",
|
|
i,count,Frag);
|
|
}
|
|
TotalFrag += Frag;
|
|
TotalCount += count;
|
|
}
|
|
|
|
dprintf("\n Number of fragments: %7ld consuming %7ld bytes\n",
|
|
TotalCount,TotalFrag);
|
|
dprintf( " NonPagedPool Usage: %7ld bytes\n",(PoolDesc.TotalPages + PoolDesc.TotalBigPages)*PAGE_SIZE);
|
|
return;
|
|
}
|
|
|
|
|
|
PRTL_BITMAP
|
|
GetBitmap(
|
|
ULONG pBitmap
|
|
)
|
|
{
|
|
ULONG Result;
|
|
RTL_BITMAP Bitmap;
|
|
PRTL_BITMAP p;
|
|
|
|
if ( !ReadMemory( (DWORD)pBitmap,
|
|
&Bitmap,
|
|
sizeof(Bitmap),
|
|
&Result) ) {
|
|
dprintf("%08lx: Unable to get contents of bitmap\n", pBitmap );
|
|
return NULL;
|
|
}
|
|
|
|
p = HeapAlloc( GetProcessHeap(), 0, sizeof( *p ) + (Bitmap.SizeOfBitMap / 8) );
|
|
if (p) {
|
|
p->SizeOfBitMap = Bitmap.SizeOfBitMap;
|
|
p->Buffer = (PULONG)(p + 1);
|
|
if ( !ReadMemory( (DWORD)Bitmap.Buffer,
|
|
p->Buffer,
|
|
Bitmap.SizeOfBitMap / 8,
|
|
&Result) ) {
|
|
dprintf("%08lx: Unable to get contents of bitmap buffer\n", Bitmap.Buffer );
|
|
HeapFree( GetProcessHeap(), 0, p );
|
|
p = NULL;
|
|
}
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
|
|
VOID
|
|
DumpPool( VOID )
|
|
{
|
|
PCHAR p, pStart;
|
|
ULONG Size;
|
|
ULONG BusyFlag;
|
|
ULONG CurrentPage, NumberOfPages;
|
|
PRTL_BITMAP StartMap = GetBitmap( GetUlongValue( "MmPagedPoolAllocationMap" ) );
|
|
PRTL_BITMAP EndMap = GetBitmap( GetUlongValue( "MmEndOfPagedPoolBitmap" ) );
|
|
PVOID PagedPoolStart = (PVOID)GetUlongValue( "MmPagedPoolStart" );
|
|
PVOID PagedPoolEnd = (PVOID)GetUlongValue( "MmPagedPoolEnd" );
|
|
PVOID NonPagedPoolStart = (PVOID)GetUlongValue( "MmNonPagedPoolStart" );
|
|
PVOID NonPagedPoolEnd = (PVOID)GetUlongValue( "MmNonPagedPoolEnd" );
|
|
|
|
if (StartMap && EndMap) {
|
|
p = PagedPoolStart;
|
|
CurrentPage = 0;
|
|
dprintf( "Paged Pool: %x .. %x\n", PagedPoolStart, PagedPoolEnd );
|
|
while (p < (PCHAR)PagedPoolEnd) {
|
|
if ( CheckControlC() ) {
|
|
return;
|
|
}
|
|
pStart = p;
|
|
BusyFlag = RtlCheckBit( StartMap, CurrentPage );
|
|
while ( ~(BusyFlag ^ RtlCheckBit( StartMap, CurrentPage )) ) {
|
|
p += PAGE_SIZE;
|
|
if (RtlCheckBit( EndMap, CurrentPage )) {
|
|
CurrentPage++;
|
|
break;
|
|
}
|
|
|
|
CurrentPage++;
|
|
if (p > (PCHAR)PagedPoolEnd) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
Size = p - pStart;
|
|
dprintf( "%08x: %x - %s\n", pStart, Size, BusyFlag ? "busy" : "free" );
|
|
}
|
|
}
|
|
|
|
HeapFree( GetProcessHeap(), 0, StartMap );
|
|
HeapFree( GetProcessHeap(), 0, EndMap );
|
|
}
|
|
|
|
|
|
DECLARE_API( pool )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump kernel mode heap
|
|
|
|
Arguments:
|
|
|
|
args - Page Flags
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PPOOL_TRACKER_TABLE PoolTrackTable;
|
|
POOL_TRACKER_TABLE Tags;
|
|
ULONG result;
|
|
ULONG PoolTag;
|
|
ULONG Flags;
|
|
ULONG Result;
|
|
PVOID PoolPageToDump;
|
|
PVOID StartPage;
|
|
PUCHAR Pool;
|
|
POOL_HACKER PoolBlock;
|
|
ULONG Previous;
|
|
UCHAR c;
|
|
|
|
PoolTrackTable = (PPOOL_TRACKER_TABLE)GetUlongValue ("PoolTrackTable");
|
|
|
|
PoolPageToDump = (PVOID)0xFFFFFFFF;
|
|
Flags = 0;
|
|
sscanf(args,"%lx %lx",&PoolPageToDump,&Flags);
|
|
if (PoolPageToDump == (PVOID)0xFFFFFFFF) {
|
|
DumpPool();
|
|
return;
|
|
}
|
|
|
|
Pool = (PUCHAR)PAGE_ALIGN (PoolPageToDump);
|
|
StartPage = (PVOID)Pool;
|
|
Previous = 0;
|
|
|
|
while ((PVOID)PAGE_ALIGN(Pool) == StartPage) {
|
|
if ( CheckControlC() ) {
|
|
return;
|
|
}
|
|
|
|
if ( !ReadMemory( (DWORD)Pool,
|
|
&PoolBlock,
|
|
sizeof(POOL_HACKER),
|
|
&Result) ) {
|
|
dprintf("%08lx: Unable to get contents of pool block\n", Pool );
|
|
return;
|
|
}
|
|
|
|
if ((ULONG)PoolPageToDump >= (ULONG)Pool &&
|
|
(ULONG)PoolPageToDump < ((ULONG)Pool + ((ULONG)PoolBlock.Header.BlockSize << POOL_BLOCK_SHIFT))
|
|
) {
|
|
c = '*';
|
|
} else {
|
|
c = ' ';
|
|
}
|
|
dprintf("%c%lx size: %4lx previous size: %4lx ",
|
|
c,
|
|
(ULONG)Pool,
|
|
(ULONG)PoolBlock.Header.BlockSize << POOL_BLOCK_SHIFT,
|
|
(ULONG)PoolBlock.Header.PreviousSize << POOL_BLOCK_SHIFT);
|
|
|
|
if (PoolBlock.Header.PoolType == 0) {
|
|
dprintf(" (Free)");
|
|
dprintf(" %c%c%c%c%c\n",
|
|
c,
|
|
(ULONG)PoolBlock.Header.PoolTag,
|
|
(ULONG)PoolBlock.Header.PoolTag >> 8,
|
|
(ULONG)PoolBlock.Header.PoolTag >> 16,
|
|
(ULONG)(PoolBlock.Header.PoolTag&~PROTECTED_POOL) >> 24);
|
|
} else {
|
|
dprintf(" (Allocated)");
|
|
if ((PoolBlock.Header.PoolType & POOL_QUOTA_MASK) == 0) {
|
|
if (PoolBlock.Header.AllocatorBackTraceIndex != 0 &&
|
|
PoolBlock.Header.AllocatorBackTraceIndex & POOL_BACKTRACEINDEX_PRESENT
|
|
) {
|
|
if ( !ReadMemory( (DWORD)&PoolTrackTable[ PoolBlock.Header.PoolTagHash&~(PROTECTED_POOL >> 16) ],
|
|
&Tags,
|
|
sizeof(Tags),
|
|
&result) ) {
|
|
PoolTag = 0;
|
|
} else {
|
|
PoolTag = Tags.Key;
|
|
}
|
|
|
|
if (PoolBlock.Header.PoolTagHash & (PROTECTED_POOL >> 16)) {
|
|
PoolTag |= PROTECTED_POOL;
|
|
}
|
|
|
|
} else {
|
|
PoolTag = PoolBlock.Header.PoolTag;
|
|
}
|
|
|
|
dprintf(" %c%c%c%c%c%s\n",
|
|
c,
|
|
PoolTag,
|
|
PoolTag >> 8,
|
|
PoolTag >> 16,
|
|
(PoolTag&~PROTECTED_POOL) >> 24,
|
|
(PoolTag&PROTECTED_POOL) ? " (Protected)" : ""
|
|
);
|
|
|
|
} else {
|
|
if (PoolBlock.Header.ProcessBilled != NULL) {
|
|
dprintf(" Process: %08x\n", PoolBlock.Header.ProcessBilled );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (Flags & 1) {
|
|
dprintf(" %08lx %08lx %08lx %08lx %08lx\n",
|
|
Pool+sizeof(POOL_HEADER),
|
|
PoolBlock.Contents[0],
|
|
PoolBlock.Contents[1],
|
|
PoolBlock.Contents[2],
|
|
PoolBlock.Contents[3]);
|
|
|
|
dprintf(" %08lx %08lx %08lx %08lx %08lx\n",
|
|
Pool+sizeof(POOL_HEADER)+16,
|
|
PoolBlock.Contents[4],
|
|
PoolBlock.Contents[5],
|
|
PoolBlock.Contents[6],
|
|
PoolBlock.Contents[7]);
|
|
dprintf("\n");
|
|
}
|
|
|
|
if ((PoolBlock.Header.BlockSize << POOL_BLOCK_SHIFT) > POOL_PAGE_SIZE) {
|
|
dprintf("Bad allocation size @%lx, too large\n", Pool);
|
|
return;
|
|
}
|
|
|
|
if (PoolBlock.Header.BlockSize == 0) {
|
|
dprintf("Bad allocation size @%lx, zero is invalid\n", Pool);
|
|
return;
|
|
}
|
|
|
|
if (PoolBlock.Header.PreviousSize != Previous) {
|
|
dprintf("Bad previous allocation size @%lx, last size was %lx\n",
|
|
Pool, Previous);
|
|
|
|
return;
|
|
}
|
|
|
|
Previous = PoolBlock.Header.BlockSize;
|
|
Pool += (Previous << POOL_BLOCK_SHIFT);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
DECLARE_API( poolused )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump usage by pool tag
|
|
|
|
Arguments:
|
|
|
|
args -
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
POOL_TRACKER_TABLE Tags[MAX_TRACKER_TABLE];
|
|
ULONG PoolTrackTable;
|
|
ULONG Flags;
|
|
ULONG i;
|
|
ULONG result;
|
|
int num;
|
|
|
|
Flags = 0;
|
|
sscanf(args,"%lx", &Flags);
|
|
|
|
|
|
PoolTrackTable = GetUlongValue ("PoolTrackTable");
|
|
|
|
if ( !PoolTrackTable ) {
|
|
dprintf("unable to get tag table.\n");
|
|
return;
|
|
}
|
|
|
|
if (Flags & 2) {
|
|
SortBy = NONPAGED_USED;
|
|
dprintf(" Sorting by NonPaged Pool Consumed\n");
|
|
} else if (Flags & 4) {
|
|
SortBy = PAGED_USED;
|
|
dprintf(" Sorting by Paged Pool Consumed\n");
|
|
} else {
|
|
SortBy = TAG;
|
|
dprintf(" Sorting by Tag\n");
|
|
}
|
|
|
|
dprintf("\n Pool Used:\n");
|
|
if (!(Flags & 1)) {
|
|
dprintf(" NonPaged Paged\n");
|
|
dprintf(" Tag Allocs Used Allocs Used\n");
|
|
|
|
} else {
|
|
dprintf(" NonPaged Paged\n");
|
|
dprintf(" Tag Allocs Frees Diff Used Allocs Frees Diff Used\n");
|
|
}
|
|
|
|
for (i = 0; i < MAX_TRACKER_TABLE; i++) {
|
|
if ( CheckControlC() ) {
|
|
return;
|
|
}
|
|
|
|
if ( !ReadMemory( (DWORD)PoolTrackTable,
|
|
&Tags[i],
|
|
sizeof(POOL_TRACKER_TABLE),
|
|
&result) ) {
|
|
dprintf("%08lx: Unable to get tag descriptor\n",PoolTrackTable);
|
|
return;
|
|
}
|
|
PoolTrackTable += sizeof(POOL_TRACKER_TABLE);
|
|
}
|
|
|
|
num = MAX_TRACKER_TABLE;
|
|
|
|
qsort((void *)&Tags[0],
|
|
(size_t)num,
|
|
(size_t)sizeof(POOL_TRACKER_TABLE),
|
|
ulcomp);
|
|
|
|
for (i = 0; i < MAX_TRACKER_TABLE; i++) {
|
|
|
|
if (Tags[i].Key != 0) {
|
|
if (!(Flags & 1)) {
|
|
if ((Tags[i].NonPagedBytes != 0) || (Tags[i].PagedBytes != 0)) {
|
|
dprintf(" %c%c%c%c %8ld %8ld %8ld %8ld\n",
|
|
Tags[i].Key,
|
|
Tags[i].Key >> 8,
|
|
Tags[i].Key >> 16,
|
|
Tags[i].Key >> 24,
|
|
Tags[i].NonPagedAllocs - Tags[i].NonPagedFrees,
|
|
Tags[i].NonPagedBytes,
|
|
Tags[i].PagedAllocs - Tags[i].PagedFrees,
|
|
Tags[i].PagedBytes);
|
|
}
|
|
|
|
} else {
|
|
dprintf(" %c%c%c%c %8ld %8ld %8ld %8ld %8ld %8ld %8ld %8ld\n",
|
|
Tags[i].Key,
|
|
Tags[i].Key >> 8,
|
|
Tags[i].Key >> 16,
|
|
Tags[i].Key >> 24,
|
|
Tags[i].NonPagedAllocs,
|
|
Tags[i].NonPagedFrees,
|
|
Tags[i].NonPagedAllocs - Tags[i].NonPagedFrees,
|
|
Tags[i].NonPagedBytes,
|
|
Tags[i].PagedAllocs,
|
|
Tags[i].PagedFrees,
|
|
Tags[i].PagedAllocs - Tags[i].PagedFrees,
|
|
Tags[i].PagedBytes);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
DECLARE_API( poolfind )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
finds a tag in nonpaged pool
|
|
|
|
Arguments:
|
|
|
|
args -
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
PPOOL_TRACKER_TABLE PoolTrackTable;
|
|
POOL_TRACKER_TABLE Tags;
|
|
ULONG result;
|
|
ULONG PoolTag;
|
|
ULONG Flags;
|
|
ULONG Result;
|
|
PVOID PoolPage;
|
|
PVOID StartPage;
|
|
PUCHAR Pool;
|
|
POOL_HACKER PoolBlock;
|
|
ULONG Previous;
|
|
PCHAR PoolStart;
|
|
PCHAR PoolEnd;
|
|
ULONG TagName;
|
|
CHAR TagNameX[4] = {' ',' ',' ',' '};
|
|
|
|
|
|
Flags = 0;
|
|
sscanf(args,"%c%c%c%c %lx", &TagNameX[0],
|
|
&TagNameX[1], &TagNameX[2], &TagNameX[3], &Flags);
|
|
|
|
TagName = TagNameX[0] | (TagNameX[1] << 8) | (TagNameX[2] << 16) | (TagNameX[3] << 24);
|
|
|
|
if (Flags == 0) {
|
|
PoolStart = (PCHAR)GetUlongValue ("MmNonPagedPoolStart");
|
|
PoolEnd = (PCHAR)
|
|
PoolStart + GetUlongValue ("MmMaximumNonPagedPoolInBytes");
|
|
} else {
|
|
PoolStart = (PCHAR)GetUlongValue ("MmPagedPoolStart");
|
|
PoolEnd = (PCHAR)
|
|
PoolStart + GetUlongValue ("MmSizeOfPagedPoolInBytes");
|
|
}
|
|
|
|
dprintf("\nSearching %s pool (%lx : %lx) for Tag: %c%c%c%c\n\n",
|
|
(Flags == 0) ? "NonPaged" : "Paged",
|
|
PoolStart, PoolEnd,
|
|
TagName,
|
|
TagName >> 8,
|
|
TagName >> 16,
|
|
TagName >> 24);
|
|
|
|
PoolTrackTable = (PPOOL_TRACKER_TABLE)GetUlongValue ("PoolTrackTable");
|
|
|
|
PoolPage = (PVOID)PoolStart;
|
|
|
|
while (PoolPage < (PVOID)PoolEnd) {
|
|
|
|
Pool = (PUCHAR)PAGE_ALIGN (PoolPage);
|
|
StartPage = (PVOID)Pool;
|
|
Previous = 0;
|
|
|
|
while ((PVOID)PAGE_ALIGN(Pool) == StartPage) {
|
|
if ( !ReadMemory( (DWORD)Pool,
|
|
&PoolBlock,
|
|
sizeof(POOL_HACKER),
|
|
&Result) ) {
|
|
break;
|
|
}
|
|
|
|
if ((PoolBlock.Header.BlockSize << POOL_BLOCK_SHIFT) > POOL_PAGE_SIZE) {
|
|
//dprintf("Bad allocation size @%lx, too large\n", Pool);
|
|
break;
|
|
}
|
|
|
|
if (PoolBlock.Header.BlockSize == 0) {
|
|
//dprintf("Bad allocation size @%lx, zero is invalid\n", Pool);
|
|
break;
|
|
}
|
|
|
|
if (PoolBlock.Header.PreviousSize != Previous) {
|
|
//dprintf("Bad previous allocation size @%lx, last size was %lx\n",Pool, Previous);
|
|
break;
|
|
}
|
|
|
|
PoolTag = PoolBlock.Header.PoolTag;
|
|
if ((PoolBlock.Header.PoolType & POOL_QUOTA_MASK) == 0) {
|
|
if (PoolBlock.Header.AllocatorBackTraceIndex != 0 &&
|
|
PoolBlock.Header.AllocatorBackTraceIndex & POOL_BACKTRACEINDEX_PRESENT
|
|
) {
|
|
|
|
if ( !ReadMemory( (DWORD)&PoolTrackTable[ PoolBlock.Header.PoolTagHash&~(PROTECTED_POOL >> 16) ],
|
|
&Tags,
|
|
sizeof(Tags),
|
|
&result) ) {
|
|
PoolTag = 0;
|
|
} else {
|
|
PoolTag = Tags.Key;
|
|
}
|
|
|
|
if (PoolBlock.Header.PoolTagHash & (PROTECTED_POOL >> 16)) {
|
|
PoolTag |= PROTECTED_POOL;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (CheckSingleFilter ((PCHAR)&PoolTag, (PCHAR)&TagName)) {
|
|
|
|
dprintf("%lx size: %4lx previous size: %4lx ",
|
|
(ULONG)Pool,
|
|
(ULONG)PoolBlock.Header.BlockSize << POOL_BLOCK_SHIFT,
|
|
(ULONG)PoolBlock.Header.PreviousSize << POOL_BLOCK_SHIFT);
|
|
|
|
if (PoolBlock.Header.PoolType == 0) {
|
|
dprintf(" (Free)");
|
|
dprintf(" %c%c%c%c\n",
|
|
(ULONG)PoolBlock.Header.PoolTag,
|
|
(ULONG)PoolBlock.Header.PoolTag >> 8,
|
|
(ULONG)PoolBlock.Header.PoolTag >> 16,
|
|
(ULONG)(PoolBlock.Header.PoolTag&~PROTECTED_POOL) >> 24);
|
|
} else {
|
|
dprintf(" (Allocated)");
|
|
if ((PoolBlock.Header.PoolType & POOL_QUOTA_MASK) == 0) {
|
|
if (PoolBlock.Header.AllocatorBackTraceIndex != 0 &&
|
|
PoolBlock.Header.AllocatorBackTraceIndex & POOL_BACKTRACEINDEX_PRESENT
|
|
) {
|
|
if ( !ReadMemory( (DWORD)&PoolTrackTable[ PoolBlock.Header.PoolTagHash&~(PROTECTED_POOL >> 16) ],
|
|
&Tags,
|
|
sizeof(Tags),
|
|
&result) ) {
|
|
PoolTag = 0;
|
|
} else {
|
|
PoolTag = Tags.Key;
|
|
}
|
|
|
|
if (PoolBlock.Header.PoolTagHash & (PROTECTED_POOL >> 16)) {
|
|
PoolTag |= PROTECTED_POOL;
|
|
}
|
|
|
|
} else {
|
|
PoolTag = PoolBlock.Header.PoolTag;
|
|
}
|
|
|
|
dprintf(" %c%c%c%c%s\n",
|
|
PoolTag,
|
|
PoolTag >> 8,
|
|
PoolTag >> 16,
|
|
(PoolTag&~PROTECTED_POOL) >> 24,
|
|
(PoolTag&PROTECTED_POOL) ? " (Protected)" : ""
|
|
);
|
|
|
|
} else {
|
|
if (PoolBlock.Header.ProcessBilled != NULL) {
|
|
dprintf(" Process: %08x\n", PoolBlock.Header.ProcessBilled );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Previous = PoolBlock.Header.BlockSize;
|
|
Pool += (Previous << POOL_BLOCK_SHIFT);
|
|
if ( CheckControlC() ) {
|
|
dprintf("\n...terminating - searched pool to %lx\n",
|
|
PoolPage);
|
|
return;
|
|
}
|
|
}
|
|
PoolPage = (PVOID)((PCHAR)PoolPage + PAGE_SIZE);
|
|
if ( CheckControlC() ) {
|
|
dprintf("\n...terminating - searched pool to %lx\n",
|
|
PoolPage);
|
|
return;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
BOOLEAN
|
|
CheckSingleFilter (
|
|
PCHAR Tag,
|
|
PCHAR Filter
|
|
)
|
|
{
|
|
ULONG i;
|
|
CHAR tc;
|
|
CHAR fc;
|
|
|
|
for ( i = 0; i < 4; i++ ) {
|
|
tc = *Tag++;
|
|
fc = *Filter++;
|
|
if ( fc == '*' ) return TRUE;
|
|
if ( fc == '?' ) continue;
|
|
if ( tc != fc ) return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|