https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2991f6e76e8b7587cca19…
commit 2991f6e76e8b7587cca1993a332879ee37cf415c
Author: Pierre Schweitzer <pierre(a)reactos.org>
AuthorDate: Sat Feb 9 13:45:19 2019 +0100
Commit: Pierre Schweitzer <pierre(a)reactos.org>
CommitDate: Sat Feb 9 13:46:35 2019 +0100
[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
---
ntoskrnl/ex/handle.c | 227 ++++++++++++++++++++++++++++++++++++++++++++++++
ntoskrnl/kdbg/kdb_cli.c | 2 +
2 files changed, 229 insertions(+)
diff --git a/ntoskrnl/ex/handle.c b/ntoskrnl/ex/handle.c
index a0ea5fb448c..a5901d856d6 100644
--- a/ntoskrnl/ex/handle.c
+++ b/ntoskrnl/ex/handle.c
@@ -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
diff --git a/ntoskrnl/kdbg/kdb_cli.c b/ntoskrnl/kdbg/kdb_cli.c
index ed40fe3661c..5ef7f616af0 100644
--- a/ntoskrnl/kdbg/kdb_cli.c
+++ b/ntoskrnl/kdbg/kdb_cli.c
@@ -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 *****************************************************************/