mirror of
https://github.com/reactos/reactos.git
synced 2024-06-24 06:51:47 +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
|
@ -1282,3 +1282,230 @@ ExEnumHandleTable(IN PHANDLE_TABLE HandleTable,
|
||||||
KeLeaveCriticalRegion();
|
KeLeaveCriticalRegion();
|
||||||
return Result;
|
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 ExpKdbgExtFileCache(ULONG Argc, PCHAR Argv[]);
|
||||||
BOOLEAN ExpKdbgExtDefWrites(ULONG Argc, PCHAR Argv[]);
|
BOOLEAN ExpKdbgExtDefWrites(ULONG Argc, PCHAR Argv[]);
|
||||||
BOOLEAN ExpKdbgExtIrpFind(ULONG Argc, PCHAR Argv[]);
|
BOOLEAN ExpKdbgExtIrpFind(ULONG Argc, PCHAR Argv[]);
|
||||||
|
BOOLEAN ExpKdbgExtHandle(ULONG Argc, PCHAR Argv[]);
|
||||||
|
|
||||||
#ifdef __ROS_DWARF__
|
#ifdef __ROS_DWARF__
|
||||||
static BOOLEAN KdbpCmdPrintStruct(ULONG Argc, PCHAR Argv[]);
|
static BOOLEAN KdbpCmdPrintStruct(ULONG Argc, PCHAR Argv[]);
|
||||||
|
@ -194,6 +195,7 @@ static const struct
|
||||||
{ "!filecache", "!filecache", "Display cache usage.", ExpKdbgExtFileCache },
|
{ "!filecache", "!filecache", "Display cache usage.", ExpKdbgExtFileCache },
|
||||||
{ "!defwrites", "!defwrites", "Display cache write values.", ExpKdbgExtDefWrites },
|
{ "!defwrites", "!defwrites", "Display cache write values.", ExpKdbgExtDefWrites },
|
||||||
{ "!irpfind", "!irpfind [Pool [startaddress [criteria data]]]", "Lists IRPs potentially matching criteria", ExpKdbgExtIrpFind },
|
{ "!irpfind", "!irpfind [Pool [startaddress [criteria data]]]", "Lists IRPs potentially matching criteria", ExpKdbgExtIrpFind },
|
||||||
|
{ "!handle", "!handle [Handle]", "Displays info about handles", ExpKdbgExtHandle },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
Loading…
Reference in a new issue