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.
363 lines
8.5 KiB
363 lines
8.5 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
handle.c
|
|
|
|
Abstract:
|
|
|
|
WinDbg Extension Api
|
|
|
|
Author:
|
|
|
|
Ramon J San Andres (ramonsa) 5-Nov-1993
|
|
|
|
Environment:
|
|
|
|
User Mode.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
BOOL
|
|
DumpHandles (
|
|
IN PEPROCESS ProcessContents,
|
|
IN PEPROCESS RealProcessBase,
|
|
IN HANDLE HandleToDump,
|
|
IN POBJECT_TYPE pObjectType,
|
|
IN ULONG Flags
|
|
);
|
|
|
|
BOOLEAN
|
|
DumpHandle(
|
|
IN PHANDLE_TABLE HandleTable,
|
|
IN POBJECT_TABLE_ENTRY p,
|
|
IN HANDLE Handle,
|
|
IN POBJECT_TYPE pObjectType,
|
|
IN ULONG Flags
|
|
);
|
|
|
|
DECLARE_API( handle )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump the active handles
|
|
|
|
Arguments:
|
|
|
|
args - [flags [process [TypeName]]]
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG ProcessToDump;
|
|
HANDLE HandleToDump;
|
|
ULONG Flags;
|
|
ULONG Result;
|
|
ULONG nArgs;
|
|
LIST_ENTRY List;
|
|
PLIST_ENTRY Next;
|
|
ULONG ProcessHead;
|
|
PEPROCESS Process;
|
|
EPROCESS ProcessContents;
|
|
char TypeName[ MAX_PATH ];
|
|
POBJECT_TYPE pObjectType;
|
|
|
|
HandleToDump = (HANDLE)0xFFFFFFFF;
|
|
Flags = 0xFFFFFFFF;
|
|
ProcessToDump = 0xFFFFFFFF;
|
|
|
|
dprintf("processor number %d\n", dwProcessor);
|
|
|
|
nArgs = sscanf(args,"%lx %lx %lx %s",&HandleToDump,&Flags,&ProcessToDump, TypeName);
|
|
if (ProcessToDump == 0xFFFFFFFF) {
|
|
ProcessToDump = (ULONG)GetCurrentProcessAddress( dwProcessor, hCurrentThread, NULL );
|
|
if (ProcessToDump == 0) {
|
|
dprintf("Unable to get current process pointer.\n");
|
|
return;
|
|
}
|
|
}
|
|
|
|
pObjectType = NULL;
|
|
if (nArgs > 3 && FetchObjectManagerVariables()) {
|
|
pObjectType = FindObjectType( TypeName );
|
|
}
|
|
|
|
if (HandleToDump == (HANDLE)0xFFFFFFFF) {
|
|
HandleToDump = 0;
|
|
}
|
|
|
|
if (ProcessToDump == 0) {
|
|
dprintf("**** NT ACTIVE PROCESS HANDLE DUMP ****\n");
|
|
if (Flags == 0xFFFFFFFF) {
|
|
Flags = 1;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If a process id is specified, then search the active process list
|
|
// for the specified process id.
|
|
//
|
|
|
|
if (ProcessToDump < MM_USER_PROBE_ADDRESS) {
|
|
ProcessHead = GetExpression( "PsActiveProcessHead" );
|
|
if ( !ProcessHead ||
|
|
!ReadMemory( (DWORD)ProcessHead,
|
|
&List,
|
|
sizeof(LIST_ENTRY),
|
|
&Result) ) {
|
|
|
|
dprintf("%08lx: Unable to get value of PsActiveProcessHead\n", ProcessHead );
|
|
return;
|
|
}
|
|
|
|
if (ProcessToDump != 0) {
|
|
dprintf("Searching for Process with Cid == %lx\n", ProcessToDump);
|
|
}
|
|
|
|
Next = List.Flink;
|
|
if (Next == NULL) {
|
|
dprintf("PsActiveProcessHead is NULL!\n");
|
|
return;
|
|
}
|
|
|
|
} else {
|
|
Next = NULL;
|
|
ProcessHead = 1;
|
|
}
|
|
|
|
while((ULONG)Next != ProcessHead) {
|
|
if (Next != NULL) {
|
|
Process = CONTAINING_RECORD(Next,EPROCESS,ActiveProcessLinks);
|
|
|
|
} else {
|
|
Process = (PEPROCESS)ProcessToDump;
|
|
}
|
|
|
|
if ( !ReadMemory( (DWORD)Process,
|
|
&ProcessContents,
|
|
sizeof(EPROCESS),
|
|
&Result) ) {
|
|
|
|
dprintf("%08lx: Unable to read _EPROCESS\n", Process );
|
|
return;
|
|
}
|
|
|
|
if (ProcessToDump == 0 ||
|
|
ProcessToDump < MM_USER_PROBE_ADDRESS && ProcessToDump == (ULONG)ProcessContents.UniqueProcessId ||
|
|
ProcessToDump > MM_USER_PROBE_ADDRESS && ProcessToDump == (ULONG)Process
|
|
) {
|
|
if (DumpProcess (&ProcessContents, Process, 0)) {
|
|
if (!DumpHandles (&ProcessContents, Process, HandleToDump, pObjectType, Flags)) {
|
|
break;
|
|
}
|
|
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (Next == NULL) {
|
|
break;
|
|
}
|
|
Next = ProcessContents.ActiveProcessLinks.Flink;
|
|
|
|
if ( CheckControlC() ) {
|
|
return;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
DumpHandles (
|
|
IN PEPROCESS ProcessContents,
|
|
IN PEPROCESS RealProcessBase,
|
|
IN HANDLE HandleToDump,
|
|
IN POBJECT_TYPE pObjectType,
|
|
IN ULONG Flags
|
|
)
|
|
|
|
{
|
|
|
|
ULONG CountTableEntries;
|
|
ULONG HandleNumber;
|
|
ULONG NumberOfHandles;
|
|
ULONG Result;
|
|
ULONG cb;
|
|
ULONG i;
|
|
HANDLE_TABLE HandleTable;
|
|
PHANDLE_ENTRY TableEntries, p;
|
|
PCHAR Address;
|
|
|
|
if (!ReadMemory((DWORD)ProcessContents->ObjectTable,
|
|
&HandleTable,
|
|
sizeof(HANDLE_TABLE),
|
|
&Result)) {
|
|
|
|
dprintf("%08lx: Unable to read handle table\n",
|
|
ProcessContents->ObjectTable);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
HandleNumber = (ULONG)HandleToDump >> 2;
|
|
CountTableEntries = HandleTable.TableBound - HandleTable.TableEntries;
|
|
if (HandleNumber == 0) {
|
|
NumberOfHandles = CountTableEntries - 1;
|
|
HandleTable.TableEntries = &HandleTable.TableEntries[1];
|
|
|
|
} else {
|
|
if (HandleNumber >= CountTableEntries) {
|
|
dprintf("Invalid handle (%d)\n", HandleNumber);
|
|
return FALSE;
|
|
}
|
|
|
|
NumberOfHandles = 1;
|
|
HandleTable.TableEntries = &HandleTable.TableEntries[HandleNumber];
|
|
}
|
|
|
|
cb = NumberOfHandles * sizeof(HANDLE_ENTRY);
|
|
TableEntries = LocalAlloc(LPTR, cb);
|
|
if (TableEntries == NULL) {
|
|
dprintf("Unable to allocate memory for reading handle table (%u bytes)\n",
|
|
cb);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
Address = (PCHAR)HandleTable.TableEntries;
|
|
p = TableEntries;
|
|
|
|
while (cb > 0) {
|
|
if (!ReadMemory((DWORD)Address, p, cb, &i)) {
|
|
dprintf("Unable to read handle table entries (%lx, %lx) - (%u, %u)\n",
|
|
ProcessContents->ObjectTable,
|
|
Address,
|
|
i,
|
|
Result);
|
|
|
|
LocalFree(TableEntries);
|
|
return FALSE;
|
|
}
|
|
|
|
cb -= i;
|
|
Address += i;
|
|
p = (PHANDLE_ENTRY)((PCHAR)p + i);
|
|
}
|
|
|
|
dprintf("Handle Table at %x with %d. %s at %x - %s\n",
|
|
ProcessContents->ObjectTable,
|
|
NumberOfHandles,
|
|
(NumberOfHandles == 1) ? "Entry" : "Entries",
|
|
HandleTable.TableEntries,
|
|
(HandleTable.LifoOrder == FALSE) ? "FIFO Order" : "LIFO Order");
|
|
|
|
p = TableEntries;
|
|
if (HandleNumber != 0) {
|
|
DumpHandle(&HandleTable,
|
|
(POBJECT_TABLE_ENTRY)p,
|
|
(HANDLE)(HandleNumber << 2),
|
|
pObjectType,
|
|
Flags);
|
|
|
|
} else {
|
|
for (i = 1; i < CountTableEntries; i++) {
|
|
DumpHandle(&HandleTable,
|
|
(POBJECT_TABLE_ENTRY)p,
|
|
(HANDLE)(i << 2),
|
|
pObjectType,
|
|
Flags);
|
|
|
|
p += 1;
|
|
if (CheckControlC()) {
|
|
goto exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
exit:
|
|
LocalFree(TableEntries);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN
|
|
DumpHandle(
|
|
IN PHANDLE_TABLE HandleTable,
|
|
IN POBJECT_TABLE_ENTRY p,
|
|
IN HANDLE Handle,
|
|
IN POBJECT_TYPE pObjectType,
|
|
IN ULONG Flags
|
|
)
|
|
|
|
{
|
|
|
|
ULONG Result;
|
|
ULONG HandleAttributes;
|
|
OBJECT_HEADER ObjectHeader;
|
|
PVOID ObjectBody;
|
|
|
|
if (ExIsEntryFree(HandleTable->TableEntries, HandleTable->TableBound, (PHANDLE_ENTRY)p)) {
|
|
if (pObjectType == NULL && Flags & 4) {
|
|
dprintf("%04lx: free handle\n", Handle);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
HandleAttributes = p->NonPagedObjectHeader & 0x6;
|
|
p->NonPagedObjectHeader ^= HandleAttributes;
|
|
|
|
if (!ReadMemory((DWORD)p->NonPagedObjectHeader,
|
|
&ObjectHeader,
|
|
sizeof(ObjectHeader),
|
|
&Result)) {
|
|
|
|
dprintf("%08lx: Unable to read nonpaged object header\n", p->NonPagedObjectHeader);
|
|
return FALSE;
|
|
}
|
|
|
|
if (pObjectType != NULL && ObjectHeader.Type != pObjectType) {
|
|
return TRUE;
|
|
}
|
|
|
|
ObjectBody = &((POBJECT_HEADER)p->NonPagedObjectHeader)->Body;
|
|
dprintf("%04lx: Object: %08lx GrantedAccess: %08lx",
|
|
Handle,
|
|
ObjectBody,
|
|
p->GrantedAccess);
|
|
|
|
if (HandleAttributes & 2) {
|
|
dprintf(" (Inherit)");
|
|
}
|
|
|
|
if (HandleAttributes & 4) {
|
|
dprintf(" (Audit)");
|
|
}
|
|
|
|
dprintf("\n");
|
|
if (Flags & 2) {
|
|
DumpObject( " ",ObjectBody, &ObjectHeader,Flags );
|
|
}
|
|
|
|
EXPRLastDump = (ULONG)ObjectBody;
|
|
dprintf("\n");
|
|
return TRUE;
|
|
}
|