/*++ 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; }