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.
846 lines
23 KiB
846 lines
23 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
irp.c
|
|
|
|
Abstract:
|
|
|
|
WinDbg Extension Api
|
|
|
|
Author:
|
|
|
|
Ramon J San Andres (ramonsa) 5-Nov-1993
|
|
|
|
Environment:
|
|
|
|
User Mode.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
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
|
|
|
|
|
|
VOID
|
|
DumpIrp(
|
|
PVOID IrpToDump,
|
|
BOOLEAN FullOutput
|
|
);
|
|
|
|
BOOLEAN
|
|
CheckSingleFilter (
|
|
PCHAR Tag,
|
|
PCHAR Filter
|
|
);
|
|
|
|
#if 0
|
|
|
|
VOID
|
|
DumpIrpZone(
|
|
IN ULONG Address,
|
|
IN BOOLEAN FullOutput
|
|
);
|
|
|
|
VOID
|
|
DumpIrpRegion(
|
|
IN ULONG Address,
|
|
IN BOOLEAN FullOutput
|
|
);
|
|
|
|
#endif
|
|
|
|
DECLARE_API( irp )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps the specified Irp
|
|
|
|
Arguments:
|
|
|
|
args - Address
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG irpToDump;
|
|
char buf[128];
|
|
|
|
buf[0] = '\0';
|
|
|
|
if (!*args) {
|
|
irpToDump = EXPRLastDump;
|
|
} else {
|
|
sscanf(args, "%lx %s", &irpToDump, buf);
|
|
}
|
|
|
|
|
|
DumpIrp((PUCHAR)irpToDump, (BOOLEAN) (buf[0] != '\0'));
|
|
}
|
|
|
|
|
|
DECLARE_API( irpzone )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps both the small irp zone and the large irp zone. Only irps that
|
|
are currently allocated are dumped. "args" controls the type of dump.
|
|
If "args" is present then the Irp is sent to the DumpIrp routine to be
|
|
disected. Otherwise, only the irp, its thread and the driver holding the
|
|
irp (i.e. the driver of the last stack) is printed.
|
|
|
|
Arguments:
|
|
|
|
args - a string pointer. If anything is in the string it indicates full
|
|
information (i.e. call DumpIrp).
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG listAddress;
|
|
BOOLEAN fullOutput = FALSE;
|
|
|
|
dprintf("irpzone is no longer supported. Use irpfind to search " \
|
|
"nonpaged pool for active Irps\n");
|
|
|
|
#if 0
|
|
|
|
if (args) {
|
|
if (*args) {
|
|
fullOutput = TRUE;
|
|
}
|
|
}
|
|
|
|
listAddress = GetExpression( "IopSmallIrpList" );
|
|
if ( listAddress ) {
|
|
dprintf("Small Irp region\n");
|
|
DumpIrpRegion(listAddress, fullOutput);
|
|
} else {
|
|
dprintf("Cannot find Small Irp list\n");
|
|
}
|
|
dprintf("\n");
|
|
|
|
listAddress = GetExpression( "IopLargeIrpList" );
|
|
if ( listAddress ) {
|
|
dprintf("Large Irp region\n");
|
|
DumpIrpRegion(listAddress, fullOutput);
|
|
} else {
|
|
dprintf("Cannot find Large Irp list\n");
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DumpIrp(
|
|
PVOID IrpToDump,
|
|
BOOLEAN FullOutput
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine dumps an Irp. It does not check to see that the address
|
|
supplied actually locates an Irp. This is done to allow for dumping
|
|
Irps post mortem, or after they have been freed or completed.
|
|
|
|
Arguments:
|
|
|
|
IrpToDump - the address of the irp.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
IO_STACK_LOCATION irpStack;
|
|
PCHAR buffer;
|
|
ULONG irpStackAddress;
|
|
ULONG result;
|
|
IRP irp;
|
|
CCHAR irpStackIndex;
|
|
|
|
if ( !ReadMemory( (DWORD) IrpToDump,
|
|
&irp,
|
|
sizeof(irp),
|
|
&result) ) {
|
|
dprintf("%08lx: Could not read Irp\n", IrpToDump);
|
|
return;
|
|
}
|
|
|
|
if (irp.Type != IO_TYPE_IRP) {
|
|
dprintf("IRP signature does not match, probably not an IRP\n");
|
|
return;
|
|
}
|
|
|
|
dprintf("Irp is active with %d stacks %d is current\n",
|
|
irp.StackCount,
|
|
irp.CurrentLocation);
|
|
|
|
if ((irp.MdlAddress != NULL) && (irp.Type == IO_TYPE_IRP)) {
|
|
dprintf(" Mdl = %08lx ", irp.MdlAddress);
|
|
} else {
|
|
dprintf(" No Mdl ");
|
|
}
|
|
|
|
if (irp.AssociatedIrp.MasterIrp != NULL) {
|
|
dprintf("%s = %08lx ",
|
|
(irp.Flags & IRP_ASSOCIATED_IRP) ? "Associated Irp" :
|
|
(irp.Flags & IRP_DEALLOCATE_BUFFER) ? "System buffer" :
|
|
"Irp count",
|
|
irp.AssociatedIrp.MasterIrp);
|
|
}
|
|
|
|
dprintf("Thread %08lx: ", irp.Tail.Overlay.Thread);
|
|
|
|
if (irp.StackCount > 15) {
|
|
dprintf("Too many Irp stacks to be believed (>15)!!\n");
|
|
return;
|
|
} else {
|
|
if (irp.CurrentLocation > irp.StackCount) {
|
|
dprintf("Irp is completed. ");
|
|
} else {
|
|
dprintf("Irp stack trace. ");
|
|
}
|
|
}
|
|
|
|
if (irp.PendingReturned) {
|
|
dprintf("Pending has been returned\n");
|
|
} else {
|
|
dprintf("\n");
|
|
}
|
|
|
|
if (FullOutput)
|
|
{
|
|
dprintf("Flags = %08lx\n", irp.Flags);
|
|
dprintf("ThreadListEntry.Flink = %08lx\n", irp.ThreadListEntry.Flink);
|
|
dprintf("ThreadListEntry.Blink = %08lx\n", irp.ThreadListEntry.Blink);
|
|
dprintf("IoStatus.Status = %08lx\n", irp.IoStatus.Status);
|
|
dprintf("IoStatus.Information = %08lx\n", irp.IoStatus.Information);
|
|
dprintf("RequestorMode = %08lx\n", irp.RequestorMode);
|
|
dprintf("Cancel = %02lx\n", irp.Cancel);
|
|
dprintf("CancelIrql = %lx\n", irp.CancelIrql);
|
|
dprintf("ApcEnvironment = %02lx\n", irp.ApcEnvironment);
|
|
dprintf("UserIosb = %08lx\n", irp.UserIosb);
|
|
dprintf("UserEvent = %08lx\n", irp.UserEvent);
|
|
dprintf("Overlay.AsynchronousParameters.UserApcRoutine = %08lx\n", irp.Overlay.AsynchronousParameters.UserApcRoutine);
|
|
dprintf("Overlay.AsynchronousParameters.UserApcContext = %08lx\n", irp.Overlay.AsynchronousParameters.UserApcContext);
|
|
dprintf(
|
|
"Overlay.AllocationSize = %08lx - %08lx\n",
|
|
irp.Overlay.AllocationSize.HighPart,
|
|
irp.Overlay.AllocationSize.LowPart);
|
|
dprintf("CancelRoutine = %08lx\n", irp.CancelRoutine);
|
|
dprintf("UserBuffer = %08lx\n", irp.UserBuffer);
|
|
dprintf("&Tail.Overlay.DeviceQueueEntry = %08lx\n", &irp.Tail.Overlay.DeviceQueueEntry);
|
|
dprintf("Tail.Overlay.Thread = %08lx\n", irp.Tail.Overlay.Thread);
|
|
dprintf("Tail.Overlay.AuxiliaryBuffer = %08lx\n", irp.Tail.Overlay.AuxiliaryBuffer);
|
|
dprintf("Tail.Overlay.ListEntry.Flink = %08lx\n", irp.Tail.Overlay.ListEntry.Flink);
|
|
dprintf("Tail.Overlay.ListEntry.Blink = %08lx\n", irp.Tail.Overlay.ListEntry.Blink);
|
|
dprintf("Tail.Overlay.CurrentStackLocation = %08lx\n", irp.Tail.Overlay.CurrentStackLocation);
|
|
dprintf("Tail.Overlay.OriginalFileObject = %08lx\n", irp.Tail.Overlay.OriginalFileObject);
|
|
dprintf("Tail.Apc = %08lx\n", irp.Tail.Apc);
|
|
dprintf("Tail.CompletionKey = %08lx\n", irp.Tail.CompletionKey);
|
|
}
|
|
|
|
irpStackAddress = (ULONG)IrpToDump + sizeof(irp);
|
|
|
|
buffer = LocalAlloc(LPTR, 256);
|
|
if (buffer == NULL) {
|
|
dprintf("Can't allocate 256 bytes\n");
|
|
return;
|
|
}
|
|
|
|
dprintf(" cmd flg cl Device File Completion-Context\n");
|
|
for (irpStackIndex = 1; irpStackIndex <= irp.StackCount; irpStackIndex++) {
|
|
|
|
if ( !ReadMemory( (DWORD) irpStackAddress,
|
|
&irpStack,
|
|
sizeof(irpStack),
|
|
&result) ) {
|
|
dprintf("%08lx: Could not read IrpStack\n", irpStackAddress);
|
|
goto exit;
|
|
}
|
|
|
|
dprintf("%c%3x %2x %2x %08lx %08lx %08lx-%08lx %s %s %s %s\n",
|
|
irpStackIndex == irp.CurrentLocation ? '>' : ' ',
|
|
irpStack.MajorFunction,
|
|
irpStack.Flags,
|
|
irpStack.Control,
|
|
irpStack.DeviceObject,
|
|
irpStack.FileObject,
|
|
irpStack.CompletionRoutine,
|
|
irpStack.Context,
|
|
(irpStack.Control & SL_INVOKE_ON_SUCCESS) ? "Success" : "",
|
|
(irpStack.Control & SL_INVOKE_ON_ERROR) ? "Error" : "",
|
|
(irpStack.Control & SL_INVOKE_ON_CANCEL) ? "Cancel" : "",
|
|
(irpStack.Control & SL_PENDING_RETURNED) ? "pending" : "");
|
|
|
|
if (irpStack.DeviceObject != NULL) {
|
|
dprintf("\t ");
|
|
DumpDevice(irpStack.DeviceObject, FALSE);
|
|
}
|
|
|
|
if (irpStack.CompletionRoutine != NULL) {
|
|
|
|
GetSymbol((LPVOID)irpStack.CompletionRoutine, buffer, &result);
|
|
dprintf("\t%s\n", buffer);
|
|
} else {
|
|
dprintf("\n");
|
|
}
|
|
|
|
dprintf("\t\t\tArgs: %08lx %08lx %08lx %08lx\n",
|
|
irpStack.Parameters.Others.Argument1,
|
|
irpStack.Parameters.Others.Argument2,
|
|
irpStack.Parameters.Others.Argument3,
|
|
irpStack.Parameters.Others.Argument4);
|
|
irpStackAddress += sizeof(irpStack);
|
|
if (CheckControlC()) {
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
exit:
|
|
LocalFree(buffer);
|
|
}
|
|
|
|
#if 0
|
|
|
|
VOID
|
|
DumpIrpZone(
|
|
IN ULONG Address,
|
|
IN BOOLEAN FullOutput
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps an Irp zone. This routine is used by bandDumpIrpZone and does
|
|
not know which zone is being dumped. The information concerning the
|
|
Irp Zone comes from the zone header supplied. No checks are made to
|
|
insure that the zone header is in fact a zone header, that is up to
|
|
the caller.
|
|
|
|
Arguments:
|
|
|
|
Address - the address for the zone header.
|
|
FullOutput - If TRUE then call DumpIrp to print the Irp.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PIRP irp;
|
|
ULONG i;
|
|
ULONG offset;
|
|
PVOID zoneAddress;
|
|
ULONG irpAddress;
|
|
ULONG result;
|
|
ULONG totalcount = 0;
|
|
ULONG activecount = 0;
|
|
ZONE_HEADER zoneHeader;
|
|
PZONE_SEGMENT_HEADER irpZone;
|
|
PIO_STACK_LOCATION irpSp;
|
|
|
|
if ( !ReadMemory( (DWORD)Address,
|
|
&zoneHeader,
|
|
sizeof(zoneHeader),
|
|
&result) ) {
|
|
dprintf("%08lx: Could not read Irp list\n", Address);
|
|
return;
|
|
}
|
|
|
|
zoneAddress = (PVOID)zoneHeader.SegmentList.Next;
|
|
|
|
irpZone = LocalAlloc(LPTR, zoneHeader.TotalSegmentSize);
|
|
if (irpZone == NULL) {
|
|
dprintf("Could not allocate %d bytes for zone\n",
|
|
zoneHeader.TotalSegmentSize);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Do the zone read in small chunks so the rest of the debugger
|
|
// doesn't get upset.
|
|
//
|
|
|
|
offset = 0;
|
|
|
|
while (offset < zoneHeader.TotalSegmentSize) {
|
|
|
|
i = zoneHeader.TotalSegmentSize - offset;
|
|
|
|
if (i > 1024) {
|
|
i = 1024;
|
|
}
|
|
|
|
if ( !ReadMemory( (DWORD)((PCH)zoneAddress + offset),
|
|
(PVOID)((PCH)irpZone + offset),
|
|
i,
|
|
&result) ) {
|
|
dprintf("%08lx: Could not read zone for size %d\n",
|
|
zoneAddress,
|
|
zoneHeader.TotalSegmentSize);
|
|
LocalFree(irpZone);
|
|
return;
|
|
}
|
|
|
|
if (CheckControlC()) {
|
|
break;
|
|
}
|
|
|
|
offset += i;
|
|
}
|
|
|
|
irp = (PIRP)((PCH)irpZone + sizeof(ZONE_SEGMENT_HEADER));
|
|
irpAddress = (ULONG)((PCH)zoneAddress + sizeof(ZONE_SEGMENT_HEADER));
|
|
|
|
for (i = sizeof(ZONE_SEGMENT_HEADER);
|
|
i <= zoneHeader.TotalSegmentSize;
|
|
i += zoneHeader.BlockSize, irpAddress += zoneHeader.BlockSize) {
|
|
|
|
totalcount++;
|
|
if (irp->Type == IO_TYPE_IRP) {
|
|
activecount++;
|
|
if (FullOutput) {
|
|
DumpIrp((PUCHAR)irpAddress, FALSE);
|
|
dprintf("\n");
|
|
} else {
|
|
irpSp = (PIO_STACK_LOCATION)
|
|
(((PCH) irp + sizeof(IRP)) +
|
|
((irp->CurrentLocation - 1) * sizeof(IO_STACK_LOCATION)));
|
|
dprintf("%08lx Thread %08lx ",
|
|
irpAddress,
|
|
irp->Tail.Overlay.Thread);
|
|
|
|
if (irp->CurrentLocation > irp->StackCount) {
|
|
dprintf("Irp is complete");
|
|
} else {
|
|
dprintf("current stack belongs to ");
|
|
DumpDevice(irpSp->DeviceObject, FALSE);
|
|
}
|
|
dprintf("\n");
|
|
}
|
|
}
|
|
|
|
if (CheckControlC()) {
|
|
break;
|
|
}
|
|
|
|
irp = (PIRP)((PCH)irp + zoneHeader.BlockSize);
|
|
}
|
|
|
|
LocalFree(irpZone);
|
|
if (totalcount != 0) {
|
|
dprintf("%lx active, %lx total\n", activecount, totalcount);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
DumpIrpRegion(
|
|
IN ULONG Address,
|
|
IN BOOLEAN FullOutput
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps an Irp region. This routine is used by bandDumpIrpZone and does
|
|
not know which region is being dumped. The information concerning the
|
|
Irp Zone comes from the region header supplied. No checks are made to
|
|
insure that the region header is in fact a region header, that is up to
|
|
the caller.
|
|
|
|
Arguments:
|
|
|
|
Address - the address for the region header.
|
|
FullOutput - If TRUE then call DumpIrp to print the Irp.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
PIRP irp;
|
|
ULONG i;
|
|
ULONG offset;
|
|
PVOID regionAddress;
|
|
ULONG irpAddress;
|
|
ULONG result;
|
|
ULONG totalcount = 0;
|
|
ULONG activecount = 0;
|
|
REGION_HEADER regionHeader;
|
|
PIO_STACK_LOCATION irpSp;
|
|
PREGION_SEGMENT_HEADER irpRegion;
|
|
|
|
if ( !ReadMemory( (DWORD)Address,
|
|
®ionHeader,
|
|
sizeof(regionHeader),
|
|
&result) ) {
|
|
dprintf("%08lx: Could not read Irp region\n", Address);
|
|
return;
|
|
}
|
|
|
|
regionAddress = (PVOID)regionHeader.FirstSegment;
|
|
|
|
irpRegion = LocalAlloc(LPTR, regionHeader.TotalSize);
|
|
if (irpRegion == NULL) {
|
|
dprintf("Could not allocate %d bytes for region\n",
|
|
regionHeader.TotalSize);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Do the zone read in small chunks so the rest of the debugger
|
|
// doesn't get upset.
|
|
//
|
|
|
|
offset = 0;
|
|
|
|
while (offset < regionHeader.TotalSize) {
|
|
|
|
i = regionHeader.TotalSize - offset;
|
|
|
|
if (i > 1024) {
|
|
i = 1024;
|
|
}
|
|
|
|
if ( !ReadMemory( (DWORD)((PCH)regionAddress + offset),
|
|
(PVOID)((PCH)irpRegion + offset),
|
|
i,
|
|
&result) ) {
|
|
dprintf("%08lx: Could not read region for size %d\n",
|
|
regionAddress,
|
|
regionHeader.TotalSize);
|
|
LocalFree(irpRegion);
|
|
return;
|
|
}
|
|
|
|
if (CheckControlC()) {
|
|
break;
|
|
}
|
|
|
|
offset += i;
|
|
}
|
|
|
|
irp = (PIRP)((PCH)irpRegion + sizeof(REGION_SEGMENT_HEADER));
|
|
irpAddress = (ULONG)((PCH)regionAddress + sizeof(REGION_SEGMENT_HEADER));
|
|
|
|
for (i = sizeof(REGION_SEGMENT_HEADER);
|
|
i <= regionHeader.TotalSize;
|
|
i += regionHeader.BlockSize, irpAddress += regionHeader.BlockSize) {
|
|
|
|
totalcount++;
|
|
if (irp->Type == IO_TYPE_IRP) {
|
|
activecount++;
|
|
if (FullOutput) {
|
|
DumpIrp((PUCHAR)irpAddress, FALSE);
|
|
dprintf("\n");
|
|
} else {
|
|
irpSp = (PIO_STACK_LOCATION)
|
|
(((PCH) irp + sizeof(IRP)) +
|
|
((irp->CurrentLocation - 1) * sizeof(IO_STACK_LOCATION)));
|
|
dprintf("%08lx Thread %08lx ",
|
|
irpAddress,
|
|
irp->Tail.Overlay.Thread);
|
|
|
|
if (irp->CurrentLocation > irp->StackCount) {
|
|
dprintf("Irp is complete (CurrentLocation %d > StackCount %d)",
|
|
irp->CurrentLocation,
|
|
irp->StackCount);
|
|
} else {
|
|
dprintf("current stack belongs to ");
|
|
DumpDevice(irpSp->DeviceObject, FALSE);
|
|
}
|
|
dprintf("\n");
|
|
}
|
|
}
|
|
|
|
if (CheckControlC()) {
|
|
break;
|
|
}
|
|
|
|
irp = (PIRP)((PCH)irp + regionHeader.BlockSize);
|
|
}
|
|
|
|
LocalFree(irpRegion);
|
|
if (totalcount != 0) {
|
|
dprintf("%lx active, %lx total for region\n", activecount, totalcount);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
DECLARE_API(irpfind)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
finds Irps in non-paged pool
|
|
|
|
Arguments:
|
|
|
|
args -
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
#define IRPBUFSIZE (sizeof(IRP) + (5 * sizeof(IO_STACK_LOCATION)))
|
|
|
|
{
|
|
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] = {' ',' ',' ',' '};
|
|
PIO_STACK_LOCATION irpSp;
|
|
PIRP Irp;
|
|
ULONG irpAddress;
|
|
UCHAR turn;
|
|
UCHAR turnTable[] = {'|', '/', '-', '\\'};
|
|
BOOLEAN fullOutput = FALSE;
|
|
ULONG activeCount = 0;
|
|
|
|
if (args) {
|
|
if (*args) {
|
|
fullOutput = TRUE;
|
|
}
|
|
}
|
|
|
|
Flags = 0;
|
|
TagName = ' prI';
|
|
|
|
Irp = malloc(IRPBUFSIZE);
|
|
|
|
if(Irp == NULL) {
|
|
dprintf("Unable to allocate irp sized buffer\n");
|
|
return;
|
|
}
|
|
|
|
PoolStart = (PCHAR)GetUlongValue ("MmNonPagedPoolStart");
|
|
PoolEnd = (PCHAR) PoolStart + GetUlongValue ("MmMaximumNonPagedPoolInBytes");
|
|
|
|
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;
|
|
}
|
|
|
|
#ifdef SHOW_PROGRESS
|
|
dprintf("\b");
|
|
#endif
|
|
|
|
if (((PoolBlock.Header.BlockSize << POOL_BLOCK_SHIFT) > POOL_PAGE_SIZE) ||
|
|
(PoolBlock.Header.BlockSize == 0) ||
|
|
(PoolBlock.Header.PreviousSize != 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 ((PoolBlock.Header.PoolType != 0) &&
|
|
(CheckSingleFilter ((PCHAR)&PoolTag, (PCHAR)&TagName))) {
|
|
|
|
irpAddress = (ULONG) Pool + (ULONG) sizeof(POOL_HEADER);
|
|
|
|
if(ReadMemory(irpAddress,
|
|
Irp,
|
|
sizeof(DWORD),
|
|
&result)) {
|
|
|
|
if(Irp->Type == IO_TYPE_IRP) {
|
|
|
|
activeCount++;
|
|
|
|
if (fullOutput) {
|
|
dprintf("%08lx: ", irpAddress);
|
|
DumpIrp((PUCHAR)irpAddress, FALSE);
|
|
dprintf("\n");
|
|
} else {
|
|
if(ReadMemory(irpAddress,
|
|
Irp,
|
|
PoolBlock.Header.BlockSize <<
|
|
POOL_BLOCK_SHIFT,
|
|
&result)) {
|
|
|
|
irpSp = (PIO_STACK_LOCATION)
|
|
(((PCHAR) Irp + sizeof(IRP)) +
|
|
(Irp->CurrentLocation - 1) *
|
|
sizeof(IO_STACK_LOCATION));
|
|
|
|
dprintf("%08lx Thread %08lx ", irpAddress,
|
|
Irp->Tail.Overlay.Thread);
|
|
|
|
if(Irp->CurrentLocation > Irp->StackCount) {
|
|
dprintf("Irp is complete (CurrentLocation "
|
|
"%d > StackCount %d)",
|
|
Irp->CurrentLocation,
|
|
Irp->StackCount);
|
|
} else {
|
|
dprintf("current stack belongs to ");
|
|
DumpDevice(irpSp->DeviceObject, FALSE);
|
|
}
|
|
dprintf("\n");
|
|
}
|
|
}
|
|
} else {
|
|
// dprintf("%08lx (size %04lx) uninitialized or overwritten IRP\n",
|
|
// irpAddress,
|
|
// PoolBlock.Header.BlockSize << POOL_BLOCK_SHIFT);
|
|
}
|
|
} else {
|
|
dprintf("Possible IRP @ %lx - unable to read addr\n", irpAddress );
|
|
}
|
|
} else {
|
|
#ifdef SHOW_PROGRESS
|
|
dprintf("%c", turnTable[turn]);
|
|
turn = (turn + 1) % 4;
|
|
#endif
|
|
}
|
|
|
|
Previous = PoolBlock.Header.BlockSize;
|
|
Pool += (Previous << POOL_BLOCK_SHIFT);
|
|
if ( CheckControlC() ) {
|
|
dprintf("\n...terminating - searched pool to %lx\n",
|
|
PoolPage);
|
|
dprintf("%d active irps\n", activeCount);
|
|
return;
|
|
}
|
|
}
|
|
|
|
PoolPage = (PVOID)((PCHAR)PoolPage + PAGE_SIZE);
|
|
|
|
if ( CheckControlC() ) {
|
|
dprintf("\n...terminating - searched pool to %lx\n",
|
|
PoolPage);
|
|
dprintf("%d active irps\n", activeCount);
|
|
return;
|
|
}
|
|
}
|
|
|
|
dprintf("%d active irps\n", activeCount);
|
|
return;
|
|
}
|
|
|
|
#if 0
|
|
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;
|
|
}
|
|
#endif
|