Author: tkreuzer
Date: Mon Oct 1 23:06:32 2012
New Revision: 57454
URL:
http://svn.reactos.org/svn/reactos?rev=57454&view=rev
Log:
[NTOSKRNL]
Implement Kdbg CLI callbacks. These callbacks can be registered from external modules and
allow to process kdbg commands.
[WIN32K]
Implement kdbg callbacks for gdi: "gdi!dumpht <type>" dumps the handle
table, "gdi!handle <x>" dumps information about a handle.
CORE-6650 #resolve
Added:
trunk/reactos/include/reactos/kdros.h (with props)
Modified:
trunk/reactos/ntoskrnl/include/internal/kd.h
trunk/reactos/ntoskrnl/kd/kdmain.c
trunk/reactos/ntoskrnl/kdbg/kdb_cli.c
trunk/reactos/win32ss/gdi/ntgdi/gdidbg.c
trunk/reactos/win32ss/gdi/ntgdi/gdidebug.h
trunk/reactos/win32ss/gdi/ntgdi/gdiobj.c
trunk/reactos/win32ss/gdi/ntgdi/gdiobj.h
trunk/reactos/win32ss/user/ntuser/main.c
Added: trunk/reactos/include/reactos/kdros.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/kdros.h?re…
==============================================================================
--- trunk/reactos/include/reactos/kdros.h (added)
+++ trunk/reactos/include/reactos/kdros.h [iso-8859-1] Mon Oct 1 23:06:32 2012
@@ -1,0 +1,65 @@
+
+
+
+#pragma once
+
+#if 0
+
+VOID
+FORCEINLINE
+KdRosDumpAllThreads(VOID)
+{
+ KdSystemDebugControl(' soR', (PVOID)DumpAllThreads, 0, 0, 0, 0, 0);
+}
+
+VOID
+FORCEINLINE
+KdRosDumpUserThreads(VOID)
+{
+ KdSystemDebugControl(' soR', (PVOID)DumpUserThreads, 0, 0, 0, 0, 0);
+}
+
+VOID
+FORCEINLINE
+KdRosDumpArmPfnDatabase(VOID)
+{
+ KdSystemDebugControl(' soR', (PVOID)KdSpare3, 0, 0, 0, 0, 0);
+}
+#endif
+
+VOID
+FORCEINLINE
+KdRosSetDebugCallback(
+ ULONG Id,
+ PVOID Callback)
+{
+ KdSystemDebugControl('CsoR', Callback, Id, 0, 0, 0, 0);
+}
+
+VOID
+FORCEINLINE
+KdRosDumpStackFrames(
+ ULONG Count,
+ PULONG_PTR Backtrace)
+{
+ KdSystemDebugControl('DsoR', Backtrace, Count, 0, 0, 0, 0);
+}
+
+#if KDBG
+VOID
+FORCEINLINE
+KdRosRegisterCliCallback(
+ PVOID Callback)
+{
+ KdSystemDebugControl('RbdK', Callback, FALSE, 0, 0, 0, 0);
+}
+
+VOID
+FORCEINLINE
+KdRosDeregisterCliCallback(
+ PVOID Callback)
+{
+ KdSystemDebugControl('RbdK', Callback, TRUE, 0, 0, 0, 0);
+}
+#endif
+
Propchange: trunk/reactos/include/reactos/kdros.h
------------------------------------------------------------------------------
svn:eol-style = native
Modified: trunk/reactos/ntoskrnl/include/internal/kd.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/kd.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/kd.h [iso-8859-1] Mon Oct 1 23:06:32 2012
@@ -67,6 +67,21 @@
#ifdef __NTOSKRNL__
#if defined(KDBG) || DBG
+
+#if KDBG
+typedef
+BOOLEAN
+(NTAPI *PKDBG_CLI_ROUTINE)(
+ IN PCHAR Command,
+ IN ULONG Argc,
+ IN PCH Argv[]);
+
+BOOLEAN
+NTAPI
+KdbRegisterCliCallback(
+ PVOID Callback,
+ BOOLEAN Deregister);
+#endif
VOID
KdbSymProcessSymbols(
Modified: trunk/reactos/ntoskrnl/kd/kdmain.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/kd/kdmain.c?rev=5…
==============================================================================
--- trunk/reactos/ntoskrnl/kd/kdmain.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/kd/kdmain.c [iso-8859-1] Mon Oct 1 23:06:32 2012
@@ -97,7 +97,15 @@
KeRosDumpStackFrames((PULONG)Buffer1, Buffer1Length);
break;
}
-#endif
+
+#if KDBG
+ /* Register KDBG CLI callback */
+ case 'RbdK':
+ {
+ Result = KdbRegisterCliCallback(Buffer1, Buffer1Length);
+ }
+#endif /* KDBG */
+#endif /* DBG */
default:
HalDisplayString ("Invalid debug service call!\n");
break;
Modified: trunk/reactos/ntoskrnl/kdbg/kdb_cli.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/kdbg/kdb_cli.c?re…
==============================================================================
--- trunk/reactos/ntoskrnl/kdbg/kdb_cli.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/kdbg/kdb_cli.c [iso-8859-1] Mon Oct 1 23:06:32 2012
@@ -96,6 +96,7 @@
/* GLOBALS *******************************************************************/
+static PKDBG_CLI_ROUTINE KdbCliCallbacks[10];
static BOOLEAN KdbUseIntelSyntax = FALSE; /* Set to TRUE for intel syntax */
static BOOLEAN KdbBreakOnModuleLoad = FALSE; /* Set to TRUE to break into KDB when a
module is loaded */
@@ -3266,6 +3267,82 @@
}
}
+
+BOOLEAN
+NTAPI
+KdbRegisterCliCallback(
+ PVOID Callback,
+ BOOLEAN Deregister)
+{
+ ULONG i;
+
+ /* Loop all entries */
+ for (i = 0; i < _countof(KdbCliCallbacks); i++)
+ {
+ /* Check if deregistering was requested */
+ if (Deregister)
+ {
+ /* Check if this entry is the one that was registered */
+ if (KdbCliCallbacks[i] == Callback)
+ {
+ /* Delete it and report success */
+ KdbCliCallbacks[i] = NULL;
+ return TRUE;
+ }
+ }
+ else
+ {
+ /* Check if this entry is free */
+ if (KdbCliCallbacks[i] == NULL)
+ {
+ /* Set it and and report success */
+ KdbCliCallbacks[i] = Callback;
+ return TRUE;
+ }
+ }
+ }
+
+ /* Unsuccessful */
+ return FALSE;
+}
+
+/*! \brief Invokes registered CLI callbacks until one of them handled the
+ * Command.
+ *
+ * \param Command - Command line to parse and execute if possible.
+ * \param Argc - Number of arguments in Argv
+ * \param Argv - Array of strings, each of them containing one argument.
+ *
+ * \return TRUE, if the command was handled, FALSE if it was not handled.
+ */
+static
+BOOLEAN
+KdbpInvokeCliCallbacks(
+ IN PCHAR Command,
+ IN ULONG Argc,
+ IN PCH Argv[])
+{
+ ULONG i;
+
+ /* Loop all entries */
+ for (i = 0; i < _countof(KdbCliCallbacks); i++)
+ {
+ /* Check if this entry is registered */
+ if (KdbCliCallbacks[i])
+ {
+ /* Invoke the callback and check if it handled the command */
+ if (KdbCliCallbacks[i](Command, Argc, Argv))
+ {
+ return TRUE;
+ }
+ }
+ }
+
+ /* None of the callbacks handled the command */
+ return FALSE;
+}
+
+
/*!\brief Parses command line and executes command if found
*
* \param Command Command line to parse and execute if possible.
@@ -3280,6 +3357,7 @@
ULONG i;
PCHAR p;
ULONG Argc;
+ // FIXME: for what do we need a 1024 characters command line and 256 tokens?
static PCH Argv[256];
static CHAR OrigCommand[1024];
@@ -3318,6 +3396,12 @@
{
return KdbDebuggerCommands[i].Fn(Argc, Argv);
}
+ }
+
+ /* Now invoke the registered callbacks */
+ if (KdbpInvokeCliCallbacks(Command, Argc, Argv))
+ {
+ return TRUE;
}
KdbpPrint("Command '%s' is unknown.\n", OrigCommand);
Modified: trunk/reactos/win32ss/gdi/ntgdi/gdidbg.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/ntgdi/gdidbg.c…
==============================================================================
--- trunk/reactos/win32ss/gdi/ntgdi/gdidbg.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/gdi/ntgdi/gdidbg.c [iso-8859-1] Mon Oct 1 23:06:32 2012
@@ -118,7 +118,7 @@
VOID
NTAPI
-DbgDumpGdiHandleTable(void)
+DbgDumpGdiHandleTableWithBT(void)
{
static int leak_reported = 0;
int i, j, idx, nTraces = 0;
@@ -729,6 +729,36 @@
return ret;
}
-#endif
+
+#if KDBG
+
+BOOLEAN
+NTAPI
+DbgGdiKdbgCliCallback(
+ IN PCHAR pszCommand,
+ IN ULONG argc,
+ IN PCH argv[])
+{
+
+ if (stricmp(argv[0], "gdi!dumpht") == 0)
+ {
+ DbgDumpGdiHandleTable(argc - 1, argv + 1);
+ }
+ else if (stricmp(argv[0], "gdi!handle") == 0)
+ {
+ DbgDumpHandleInfo(argv[1]);
+ }
+ else
+ {
+ /* Not handled */
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+#endif // KDBG
+
+#endif // DBG
/* EOF */
Modified: trunk/reactos/win32ss/gdi/ntgdi/gdidebug.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/ntgdi/gdidebug…
==============================================================================
--- trunk/reactos/win32ss/gdi/ntgdi/gdidebug.h [iso-8859-1] (original)
+++ trunk/reactos/win32ss/gdi/ntgdi/gdidebug.h [iso-8859-1] Mon Oct 1 23:06:32 2012
@@ -28,6 +28,15 @@
} data;
} LOGENTRY, *PLOGENTRY;
+#if KDBG
+BOOLEAN
+NTAPI
+DbgGdiKdbgCliCallback(
+ IN PCHAR Command,
+ IN ULONG Argc,
+ IN PCH Argv[]);
+#endif
+
#if DBG_ENABLE_EVENT_LOGGING
VOID NTAPI DbgDumpEventList(PSLIST_HEADER pslh);
VOID NTAPI DbgLogEvent(PSLIST_HEADER pslh, LOG_EVENT_TYPE nEventType, LPARAM lParam);
@@ -44,7 +53,7 @@
#endif
-VOID NTAPI DbgDumpGdiHandleTable(VOID);
+VOID NTAPI DbgDumpGdiHandleTableWithBT(VOID);
ULONG NTAPI DbgCaptureStackBackTace(PVOID* pFrames, ULONG nFramesToCapture);
BOOL NTAPI DbgGdiHTIntegrityCheck(VOID);
VOID NTAPI DbgDumpLockedGdiHandles(VOID);
Modified: trunk/reactos/win32ss/gdi/ntgdi/gdiobj.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/ntgdi/gdiobj.c…
==============================================================================
--- trunk/reactos/win32ss/gdi/ntgdi/gdiobj.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/gdi/ntgdi/gdiobj.c [iso-8859-1] Mon Oct 1 23:06:32 2012
@@ -1341,4 +1341,170 @@
return TRUE;
}
+#if DBG && KDBG
+static const char * gpszObjectTypes[] =
+{
+ "FREE", "DC", "UNUSED1", "UNUSED2",
"RGN", "SURF", "CLIENTOBJ", "PATH",
+ "PAL", "ICMLCS", "LFONT", "RFONT",
"PFE", "PFT", "ICMCXF", "SPRITE",
+ "BRUSH", "UMPD", "UNUSED4", "SPACE",
"UNUSED5", "META", "EFSTATE",
+ "BMFD", "VTFD", "TTFD", "RC",
"TEMP", "DRVOBJ", "DCIOBJ", "SPOOL",
+ "RESERVED", "ALL"
+};
+
+extern PEPROCESS gpepCSRSS;;
+
+VOID
+NTAPI
+DbgDumpGdiHandleTable(ULONG argc, char *argv[])
+{
+ ULONG i;
+ UCHAR Objt, jReqestedType;
+ PENTRY pentry;
+ POBJ pobj;
+ KAPC_STATE ApcState;
+
+ /* No CSRSS, no handle table */
+ if (!gpepCSRSS) return;
+ KeStackAttachProcess(&gpepCSRSS->Pcb, &ApcState);
+
+ if (argc == 0)
+ {
+ USHORT Counts[GDIObjType_MAX_TYPE + 2] = {0};
+
+ /* Loop all possibly used entries in the handle table */
+ for (i = RESERVE_ENTRIES_COUNT; i < gulFirstUnused; i++)
+ {
+ if (MmIsAddressValid(&gpentHmgr[i]))
+ {
+ Objt = gpentHmgr[i].Objt & 0x1F;
+ Counts[Objt]++;
+ }
+ }
+
+ DbgPrint("Type Count\n");
+ DbgPrint("-------------------\n");
+ for (i = 0; i <= GDIObjType_MAX_TYPE; i++)
+ {
+ DbgPrint("%02x %-9s %d\n",
+ i, gpszObjectTypes[i], Counts[i]);
+ }
+ DbgPrint("\n");
+ }
+ else
+ {
+ /* Loop all object types */
+ for (i = 0; i <= GDIObjType_MAX_TYPE + 1; i++)
+ {
+ /* Check if this object type was requested */
+ if (stricmp(argv[0], gpszObjectTypes[i]) == 0)
+ {
+ jReqestedType = i;
+ break;
+ }
+ }
+
+ /* Check if we didn't find it yet */
+ if (i > GDIObjType_MAX_TYPE)
+ {
+ /* Try if it's a number */
+ i = atoi(argv[0]);
+
+ /* Check for "0" */
+ if ((i > GDIObjType_MAX_TYPE) ||
+ ((i == 0) && (stricmp(argv[0], "0") == 0)))
+ {
+ DbgPrint("Unknown object type: %s\n", argv[0]);
+ goto leave;
+ }
+
+ jReqestedType = i;
+ }
+
+ /* Print header */
+ DbgPrint("Index Handle Type ThreadId cLocks ulRefCount\n");
+ DbgPrint("----------------------------------------------------\n");
+
+ /* Loop all possibly used entries in the handle table */
+ for (i = RESERVE_ENTRIES_COUNT; i < gulFirstUnused; i++)
+ {
+ /* Get the entry and the object */
+ pentry = &gpentHmgr[i];
+
+ if (!MmIsAddressValid(pentry)) continue;
+
+ pobj = pentry->einfo.pobj;
+ Objt = pentry->Objt & 0x1F;
+
+ if ((jReqestedType == GDIObjType_MAX_TYPE + 1) ||
+ (Objt == jReqestedType))
+ {
+ DbgPrint("%04lx %p %-9s 0x%06lx %-7ld ",
+ i, pobj->hHmgr, gpszObjectTypes[Objt],
+ pobj->dwThreadId, pobj->cExclusiveLock);
+ if (MmIsAddressValid(&gpaulRefCount[i]))
+ DbgPrint("0x%06lx\n", gpaulRefCount[i]);
+ else
+ DbgPrint("????????\n");
+ }
+ }
+ }
+
+leave:
+ KeUnstackDetachProcess(&ApcState);
+}
+
+VOID
+NTAPI
+DbgDumpHandleInfo(char *argv)
+{
+ ULONG_PTR ulObject;
+ BASEOBJECT *pobj;
+ ENTRY *pentry;
+ USHORT usIndex;
+ char *endptr;
+ KAPC_STATE ApcState;
+
+ /* Skip optional '0x' prefix */
+ if ((argv[0] == '0') && ((argv[1] == 'x') || (argv[1] ==
'X')))
+ argv += 2;
+
+ /* Make a number from the string (hex) */
+ ulObject = strtol(argv, &endptr, 16);
+ if (*endptr != '\0')
+ return;
+
+ /* No CSRSS, no handle table */
+ if (!gpepCSRSS) return;
+ KeStackAttachProcess(&gpepCSRSS->Pcb, &ApcState);
+
+ usIndex = ulObject & 0xFFFF;
+ pentry = &gpentHmgr[usIndex];
+
+ if (MmIsAddressValid(pentry))
+ {
+ pobj = pentry->einfo.pobj;
+
+ DbgPrint("GDI handle=%p, type=%s, index=0x%lx, pentry=%p.\n",
+ ulObject, gpszObjectTypes[(ulObject >> 16) & 0x1f],
+ usIndex, pentry);
+ DbgPrint(" ENTRY = {.pobj = %p, ObjectOwner = 0x%lx, FullUnique =
0x%04x,\n"
+ " Objt=0x%02x, Flags = 0x%02x, pUser = 0x%p}\n",
+ pentry->einfo.pobj, pentry->ObjectOwner.ulObj,
pentry->FullUnique,
+ pentry->Objt, pentry->Flags, pentry->pUser);
+ DbgPrint(" BASEOBJECT = {hHmgr = %p, dwThreadId = 0x%lx,\n"
+ " cExclusiveLock = %ld, BaseFlags = 0x%lx}\n",
+ pobj->hHmgr, pobj->dwThreadId,
+ pobj->cExclusiveLock, pobj->BaseFlags);
+ if (MmIsAddressValid(&gpaulRefCount[usIndex]))
+ DbgPrint(" gpaulRefCount[idx] = %ld\n", gpaulRefCount[usIndex]);
+ }
+ else
+ {
+ DbgPrint("Coudn't access ENTRY. Probably paged out.\n");
+ }
+
+ KeUnstackDetachProcess(&ApcState);
+}
+#endif // DBG && KDBG
+
/* EOF */
Modified: trunk/reactos/win32ss/gdi/ntgdi/gdiobj.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/ntgdi/gdiobj.h…
==============================================================================
--- trunk/reactos/win32ss/gdi/ntgdi/gdiobj.h [iso-8859-1] (original)
+++ trunk/reactos/win32ss/gdi/ntgdi/gdiobj.h [iso-8859-1] Mon Oct 1 23:06:32 2012
@@ -180,3 +180,15 @@
PGDIOBJ NTAPI GDIOBJ_ShareLockObj(HGDIOBJ hObj, DWORD ObjectType);
PVOID NTAPI GDI_MapHandleTable(PEPROCESS Process);
+#if DBG && KDBG
+VOID
+NTAPI
+DbgDumpGdiHandleTable(
+ ULONG argc,
+ char *argv[]);
+
+VOID
+NTAPI
+DbgDumpHandleInfo(
+ char *argv);
+#endif
Modified: trunk/reactos/win32ss/user/ntuser/main.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/main.c…
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/main.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/main.c [iso-8859-1] Mon Oct 1 23:06:32 2012
@@ -11,6 +11,7 @@
#define NDEBUG
#include <debug.h>
+#include <kdros.h>
HANDLE hModuleWin;
@@ -87,6 +88,9 @@
#if DBG
DbgInitDebugChannels();
+#if KDBG
+ KdRosRegisterCliCallback(DbgGdiKdbgCliCallback);
+#endif
#endif
TRACE_CH(UserProcess,"Allocated ppi 0x%p for PID:0x%lx\n", ppiCurrent,
HandleToUlong(Process->UniqueProcessId));
@@ -408,7 +412,7 @@
TRACE_CH(UserThread,"Attached Thread ptiTo is getting switched!\n");
UserAttachThreadInput(ptiFrom, ptiCurrent, FALSE);
}
-
+
// ptiFrom
if (ptiCurrent->pqAttach && ptiCurrent->MessageQueue)
{