mirror of
https://github.com/reactos/reactos.git
synced 2024-11-18 21:13:52 +00:00
[NTOSKRNL] Add a first implementation of !handle command in KDBG
It allows dumping all the handles (filtered by PID/Process) and it displays basic information about file and key handles
This commit is contained in:
parent
5bfe6a5376
commit
2991f6e76e
2 changed files with 229 additions and 0 deletions
|
@ -1282,3 +1282,230 @@ ExEnumHandleTable(IN PHANDLE_TABLE HandleTable,
|
|||
KeLeaveCriticalRegion();
|
||||
return Result;
|
||||
}
|
||||
|
||||
#if DBG && defined(KDBG)
|
||||
BOOLEAN ExpKdbgExtHandle(ULONG Argc, PCHAR Argv[])
|
||||
{
|
||||
USHORT i;
|
||||
char *endptr;
|
||||
HANDLE ProcessId;
|
||||
EXHANDLE ExHandle;
|
||||
PLIST_ENTRY Entry;
|
||||
PEPROCESS Process;
|
||||
WCHAR KeyPath[MAX_PATH];
|
||||
PFILE_OBJECT FileObject;
|
||||
PHANDLE_TABLE HandleTable;
|
||||
POBJECT_HEADER ObjectHeader;
|
||||
PHANDLE_TABLE_ENTRY TableEntry;
|
||||
ULONG NeededLength, NameLength;
|
||||
PCM_KEY_CONTROL_BLOCK Kcb, CurrentKcb;
|
||||
POBJECT_HEADER_NAME_INFO ObjectNameInfo;
|
||||
|
||||
if (Argc > 1)
|
||||
{
|
||||
/* Get EPROCESS address or PID */
|
||||
i = 0;
|
||||
while (Argv[1][i])
|
||||
{
|
||||
if (!isdigit(Argv[1][i]))
|
||||
{
|
||||
i = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
if (!KdbpGetHexNumber(Argv[1], (PVOID)&Process))
|
||||
{
|
||||
KdbpPrint("Invalid parameter: %s\n", Argv[1]);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* In the end, we always want a PID */
|
||||
ProcessId = PsGetProcessId(Process);
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessId = (HANDLE)strtoul(Argv[1], &endptr, 10);
|
||||
if (*endptr != '\0')
|
||||
{
|
||||
KdbpPrint("Invalid parameter: %s\n", Argv[1]);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessId = PsGetCurrentProcessId();
|
||||
}
|
||||
|
||||
for (Entry = HandleTableListHead.Flink;
|
||||
Entry != &HandleTableListHead;
|
||||
Entry = Entry->Flink)
|
||||
{
|
||||
/* Only return matching PID
|
||||
* 0 matches everything
|
||||
*/
|
||||
HandleTable = CONTAINING_RECORD(Entry, HANDLE_TABLE, HandleTableList);
|
||||
if (ProcessId != 0 && HandleTable->UniqueProcessId != ProcessId)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
KdbpPrint("\n");
|
||||
|
||||
KdbpPrint("Handle table at %p with %d entries in use\n", HandleTable, HandleTable->HandleCount);
|
||||
|
||||
ExHandle.Value = 0;
|
||||
while ((TableEntry = ExpLookupHandleTableEntry(HandleTable, ExHandle)))
|
||||
{
|
||||
if ((TableEntry->Object) &&
|
||||
(TableEntry->NextFreeTableEntry != -2))
|
||||
{
|
||||
ObjectHeader = ObpGetHandleObject(TableEntry);
|
||||
|
||||
KdbpPrint("%p: Object: %p GrantedAccess: %x Entry: %p\n", ExHandle.Value, &ObjectHeader->Body, TableEntry->GrantedAccess, TableEntry);
|
||||
KdbpPrint("Object: %p Type: (%x) ", &ObjectHeader->Body, ObjectHeader->Type);
|
||||
if (ObjectHeader->Type == IoFileObjectType)
|
||||
{
|
||||
KdbpPrint("File");
|
||||
}
|
||||
else if (ObjectHeader->Type == ExEventObjectType)
|
||||
{
|
||||
KdbpPrint("Event");
|
||||
}
|
||||
else if (ObjectHeader->Type == ExEventPairObjectType)
|
||||
{
|
||||
KdbpPrint("EventPair");
|
||||
}
|
||||
else if (ObjectHeader->Type == ExMutantObjectType)
|
||||
{
|
||||
KdbpPrint("Mutant");
|
||||
}
|
||||
else if (ObjectHeader->Type == ExSemaphoreObjectType)
|
||||
{
|
||||
KdbpPrint("Semaphore");
|
||||
}
|
||||
else if (ObjectHeader->Type == ExTimerType)
|
||||
{
|
||||
KdbpPrint("Timer");
|
||||
}
|
||||
else if (ObjectHeader->Type == ExWindowStationObjectType)
|
||||
{
|
||||
KdbpPrint("WindowStation");
|
||||
}
|
||||
else if (ObjectHeader->Type == ExDesktopObjectType)
|
||||
{
|
||||
KdbpPrint("Desktop");
|
||||
}
|
||||
else if (ObjectHeader->Type == ObpDirectoryObjectType)
|
||||
{
|
||||
KdbpPrint("Directory");
|
||||
}
|
||||
else if (ObjectHeader->Type == CmpKeyObjectType)
|
||||
{
|
||||
KdbpPrint("Key");
|
||||
}
|
||||
else if (ObjectHeader->Type == MmSectionObjectType)
|
||||
{
|
||||
KdbpPrint("Section");
|
||||
}
|
||||
else if (ObjectHeader->Type == PsThreadType)
|
||||
{
|
||||
KdbpPrint("Thread");
|
||||
}
|
||||
else if (ObjectHeader->Type == LpcPortObjectType)
|
||||
{
|
||||
KdbpPrint("ALPC Port");
|
||||
}
|
||||
KdbpPrint("\n");
|
||||
KdbpPrint("\tObjectHeader: %p\n", ObjectHeader);
|
||||
KdbpPrint("\t\tHandleCount: %u PointerCount: %u\n", ObjectHeader->HandleCount, ObjectHeader->PointerCount);
|
||||
|
||||
/* Specific objects debug prints */
|
||||
|
||||
/* For file, display path */
|
||||
if (ObjectHeader->Type == IoFileObjectType)
|
||||
{
|
||||
FileObject = (PFILE_OBJECT)&ObjectHeader->Body;
|
||||
|
||||
KdbpPrint("\t\t\tName: %wZ\n", &FileObject->FileName);
|
||||
}
|
||||
|
||||
/* For directory, and win32k objects, display object name */
|
||||
else if (ObjectHeader->Type == ObpDirectoryObjectType ||
|
||||
ObjectHeader->Type == ExWindowStationObjectType ||
|
||||
ObjectHeader->Type == ExDesktopObjectType)
|
||||
{
|
||||
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
|
||||
if (ObjectNameInfo != NULL && ObjectNameInfo->Name.Buffer != NULL)
|
||||
{
|
||||
KdbpPrint("\t\t\tName: %wZ\n", &ObjectNameInfo->Name);
|
||||
}
|
||||
}
|
||||
|
||||
/* For registry keys, display full path */
|
||||
else if (ObjectHeader->Type == CmpKeyObjectType)
|
||||
{
|
||||
Kcb = ((PCM_KEY_BODY)&ObjectHeader->Body)->KeyControlBlock;
|
||||
if (!Kcb->Delete)
|
||||
{
|
||||
CurrentKcb = Kcb;
|
||||
|
||||
/* See: CmpQueryNameInformation() */
|
||||
|
||||
while (CurrentKcb != NULL)
|
||||
{
|
||||
if (CurrentKcb->NameBlock->Compressed)
|
||||
NeededLength += CmpCompressedNameSize(CurrentKcb->NameBlock->Name, CurrentKcb->NameBlock->NameLength);
|
||||
else
|
||||
NeededLength += CurrentKcb->NameBlock->NameLength;
|
||||
|
||||
NeededLength += sizeof(OBJ_NAME_PATH_SEPARATOR);
|
||||
|
||||
CurrentKcb = CurrentKcb->ParentKcb;
|
||||
}
|
||||
|
||||
if (NeededLength < MAX_PATH * sizeof(WCHAR))
|
||||
{
|
||||
CurrentKcb = Kcb;
|
||||
|
||||
while (CurrentKcb != NULL)
|
||||
{
|
||||
if (CurrentKcb->NameBlock->Compressed)
|
||||
{
|
||||
NameLength = CmpCompressedNameSize(CurrentKcb->NameBlock->Name, CurrentKcb->NameBlock->NameLength);
|
||||
CmpCopyCompressedName(&KeyPath[(NeededLength - NameLength)/sizeof(WCHAR)],
|
||||
NameLength,
|
||||
CurrentKcb->NameBlock->Name,
|
||||
CurrentKcb->NameBlock->NameLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
NameLength = CurrentKcb->NameBlock->NameLength;
|
||||
RtlCopyMemory(&KeyPath[(NeededLength - NameLength)/sizeof(WCHAR)],
|
||||
CurrentKcb->NameBlock->Name,
|
||||
NameLength);
|
||||
}
|
||||
|
||||
NeededLength -= NameLength;
|
||||
NeededLength -= sizeof(OBJ_NAME_PATH_SEPARATOR);
|
||||
KeyPath[NeededLength/sizeof(WCHAR)] = OBJ_NAME_PATH_SEPARATOR;
|
||||
|
||||
CurrentKcb = CurrentKcb->ParentKcb;
|
||||
}
|
||||
}
|
||||
|
||||
KdbpPrint("\t\t\tName: %S\n", KeyPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ExHandle.Value += INDEX_TO_HANDLE_VALUE(1);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -97,6 +97,7 @@ BOOLEAN ExpKdbgExtPoolFind(ULONG Argc, PCHAR Argv[]);
|
|||
BOOLEAN ExpKdbgExtFileCache(ULONG Argc, PCHAR Argv[]);
|
||||
BOOLEAN ExpKdbgExtDefWrites(ULONG Argc, PCHAR Argv[]);
|
||||
BOOLEAN ExpKdbgExtIrpFind(ULONG Argc, PCHAR Argv[]);
|
||||
BOOLEAN ExpKdbgExtHandle(ULONG Argc, PCHAR Argv[]);
|
||||
|
||||
#ifdef __ROS_DWARF__
|
||||
static BOOLEAN KdbpCmdPrintStruct(ULONG Argc, PCHAR Argv[]);
|
||||
|
@ -194,6 +195,7 @@ static const struct
|
|||
{ "!filecache", "!filecache", "Display cache usage.", ExpKdbgExtFileCache },
|
||||
{ "!defwrites", "!defwrites", "Display cache write values.", ExpKdbgExtDefWrites },
|
||||
{ "!irpfind", "!irpfind [Pool [startaddress [criteria data]]]", "Lists IRPs potentially matching criteria", ExpKdbgExtIrpFind },
|
||||
{ "!handle", "!handle [Handle]", "Displays info about handles", ExpKdbgExtHandle },
|
||||
};
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
|
Loading…
Reference in a new issue