ReactOS  0.4.13-dev-257-gfabbd7c
gdikdbgext.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS win32 kernel mode subsystem
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: win32ss/gdi/ntgdi/gdikdbgext.c
5  * PURPOSE: KDBG extension for GDI
6  * PROGRAMMERS: Timo Kreuzer
7  */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #include <win32k.h>
12 //#define NDEBUG
13 //#include <debug.h>
14 
15 extern PENTRY gpentHmgr;
16 extern PULONG gpaulRefCount;
17 extern ULONG gulFirstUnused;
18 
19 
20 static const char * gpszObjectTypes[] =
21 {
22  "FREE", "DC", "UNUSED1", "UNUSED2", "RGN", "SURF", "CLIENTOBJ", "PATH",
23  "PAL", "ICMLCS", "LFONT", "RFONT", "PFE", "PFT", "ICMCXF", "SPRITE",
24  "BRUSH", "UMPD", "UNUSED4", "SPACE", "UNUSED5", "META", "EFSTATE",
25  "BMFD", "VTFD", "TTFD", "RC", "TEMP", "DRVOBJ", "DCIOBJ", "SPOOL",
26  "RESERVED", "ALL"
27 };
28 
29 
30 BOOLEAN
32 {
33  PUCHAR pjAddress;
34 
35  pjAddress = ALIGN_DOWN_POINTER_BY(pvBase, PAGE_SIZE);
36 
37  while (pjAddress < (PUCHAR)pvBase + cjSize)
38  {
39  if (!MmIsAddressValid(pjAddress)) return FALSE;
40  pjAddress += PAGE_SIZE;
41  }
42 
43  return TRUE;
44 }
45 
46 static
47 BOOL
48 KdbGetHexNumber(char *pszNum, ULONG_PTR *pulValue)
49 {
50  char *endptr;
51 
52  /* Skip optional '0x' prefix */
53  if ((pszNum[0] == '0') && ((pszNum[1] == 'x') || (pszNum[1] == 'X')))
54  pszNum += 2;
55 
56  /* Make a number from the string (hex) */
57  *pulValue = strtoul(pszNum, &endptr, 16);
58 
59  return (*endptr == '\0');
60 }
61 
62 static
63 VOID
65 {
66  DbgPrint("GDI KDBG extension.\nAvailable commands:\n"
67  "- help - Displays this screen.\n"
68  "- dumpht [<type>] - Dumps all handles of <type> or lists all types\n"
69  "- handle <handle> - Displays information about a handle\n"
70  "- entry <entry> - Displays an ENTRY, <entry> can be a pointer or index\n"
71  "- baseobject <object> - Displays a BASEOBJECT\n"
73  "- eventlist <object> - Displays the eventlist for an object\n"
74 #endif
75  );
76 }
77 
78 static
79 VOID
81 {
82  ULONG i;
83  UCHAR Objt, jReqestedType;
84  PENTRY pentry;
85  POBJ pobj;
87  ULONG_PTR ulArg;
88 
89  /* No CSRSS, no handle table */
90  if (!gpepCSRSS) return;
92 
93  if (argc == 0)
94  {
96 
97  /* Loop all possibly used entries in the handle table */
99  {
100  if (KdbIsMemoryValid(&gpentHmgr[i], sizeof(ENTRY)))
101  {
102  Objt = gpentHmgr[i].Objt & 0x1F;
103  Counts[Objt]++;
104  }
105  }
106 
107  DbgPrint("Type Count\n");
108  DbgPrint("-------------------\n");
109  for (i = 0; i <= GDIObjType_MAX_TYPE; i++)
110  {
111  DbgPrint("%02x %-9s %d\n",
112  i, gpszObjectTypes[i], Counts[i]);
113  }
114  DbgPrint("\n");
115  }
116  else
117  {
118  /* Loop all object types */
119  for (i = 0; i <= GDIObjType_MAX_TYPE + 1; i++)
120  {
121  /* Check if this object type was requested */
122  if (stricmp(argv[0], gpszObjectTypes[i]) == 0) break;
123  }
124 
125  /* Check if we didn't find it yet */
126  if (i > GDIObjType_MAX_TYPE + 1)
127  {
128  /* Try if it's a number */
129  if (!KdbGetHexNumber(argv[0], &ulArg))
130  {
131  DbgPrint("Invalid parameter: %s\n", argv[0]);
132  return;
133  }
134 
135  /* Check if it's inside the allowed range */
136  if (i > GDIObjType_MAX_TYPE)
137  {
138  DbgPrint("Unknown object type: %s\n", argv[0]);
139  goto leave;
140  }
141  }
142 
143  jReqestedType = i;
144 
145  /* Print header */
146  DbgPrint("Index Handle Type pObject ThreadId cLocks ulRefCount\n");
147  DbgPrint("---------------------------------------------------------------\n");
148 
149  /* Loop all possibly used entries in the handle table */
151  {
152  /* Get the entry and the object */
153  pentry = &gpentHmgr[i];
154 
155  if (!MmIsAddressValid(pentry)) continue;
156 
157  pobj = pentry->einfo.pobj;
158  Objt = pentry->Objt & 0x1F;
159 
160  /* Check if ALL objects are requested, or the object type matches */
161  if ((jReqestedType == GDIObjType_MAX_TYPE + 1) ||
162  (Objt == jReqestedType))
163  {
164  DbgPrint("%04lx %p %-9s 0x%p 0x%06lx %-6ld ",
165  i, pobj->hHmgr, gpszObjectTypes[Objt], pobj,
166  pobj->dwThreadId, pobj->cExclusiveLock);
168  DbgPrint("0x%08lx\n", gpaulRefCount[i]);
169  else
170  DbgPrint("??????????\n");
171  }
172  }
173  }
174 
175 leave:
177 }
178 
179 static
180 VOID
182 {
183  ULONG_PTR ulObject;
184  BASEOBJECT *pobj;
185  ENTRY *pentry;
186  USHORT usIndex;
188 
189  /* Convert the parameter into a number */
190  if (!KdbGetHexNumber(argv, &ulObject))
191  {
192  DbgPrint("Invalid parameter: %s\n", argv);
193  return;
194  }
195 
196  /* No CSRSS, no handle table */
197  if (!gpepCSRSS) return;
199 
200  usIndex = ulObject & 0xFFFF;
201  pentry = &gpentHmgr[usIndex];
202 
203  if (MmIsAddressValid(pentry))
204  {
205  pobj = pentry->einfo.pobj;
206 
207  DbgPrint("GDI handle=%p, type=%s, index=0x%lx, pentry=%p.\n",
208  ulObject, gpszObjectTypes[(ulObject >> 16) & 0x1f],
209  usIndex, pentry);
210  DbgPrint(" ENTRY = {.pobj = %p, ObjectOwner = 0x%lx, FullUnique = 0x%04x,\n"
211  " Objt=0x%02x, Flags = 0x%02x, pUser = 0x%p}\n",
212  pentry->einfo.pobj, pentry->ObjectOwner.ulObj, pentry->FullUnique,
213  pentry->Objt, pentry->Flags, pentry->pUser);
214  DbgPrint(" BASEOBJECT = {hHmgr = %p, dwThreadId = 0x%lx,\n"
215  " cExclusiveLock = %ld, BaseFlags = 0x%lx}\n",
216  pobj->hHmgr, pobj->dwThreadId,
217  pobj->cExclusiveLock, pobj->BaseFlags);
218  if (MmIsAddressValid(&gpaulRefCount[usIndex]))
219  DbgPrint(" gpaulRefCount[idx] = %ld\n", gpaulRefCount[usIndex]);
220  }
221  else
222  {
223  DbgPrint("Coudn't access ENTRY. Probably paged out.\n");
224  }
225 
227 }
228 
229 static
230 VOID
232 {
233  ULONG_PTR ulValue;
234  PENTRY pentry;
236 
237  /* Convert the parameter into a number */
238  if (!KdbGetHexNumber(argv, &ulValue))
239  {
240  DbgPrint("Invalid parameter: %s\n", argv);
241  return;
242  }
243 
244  /* No CSRSS, no handle table */
245  if (!gpepCSRSS) return;
247 
248  /* If the parameter is smaller than 0x10000, it's an index */
249  pentry = (ulValue <= 0xFFFF) ? &gpentHmgr[ulValue] : (PENTRY)ulValue;
250 
251  /* Check if the address is readable */
252  if (!MmIsAddressValid(pentry))
253  {
254  DbgPrint("Cannot access entry at %p\n", pentry);
255  goto cleanup;
256  }
257 
258  /* print the entry */
259  DbgPrint("Dumping ENTRY #%ld, @%p:\n", (pentry - gpentHmgr), pentry);
260  if (pentry->Objt != 0)
261  DbgPrint(" pobj = 0x%p\n", pentry->einfo.pobj);
262  else
263  DbgPrint(" hFree = 0x%p\n", pentry->einfo.hFree);
264  DbgPrint(" ObjectOwner = 0x%p\n", pentry->ObjectOwner.ulObj);
265  DbgPrint(" FullUnique = 0x%x\n", pentry->FullUnique);
266  DbgPrint(" Objt = 0x%x (%s)\n", pentry->Objt,
267  pentry->Objt <= 0x1E ? gpszObjectTypes[pentry->Objt] : "invalid");
268  DbgPrint(" Flags = 0x%x\n", pentry->Flags);
269  DbgPrint(" pUser = 0x%p\n", pentry->pUser);
270 
271 cleanup:
273 }
274 
275 static
276 VOID
278 {
279 }
280 
281 #if DBG_ENABLE_EVENT_LOGGING
282 static
283 VOID
284 KdbCommand_Gdi_eventlist(char *argv)
285 {
286  ULONG_PTR ulValue;
287  POBJ pobj;
288  PSLIST_ENTRY psle, psleFirst;
289  PLOGENTRY pLogEntry;
290 
291  /* Convert the parameter into a number */
292  if (!KdbGetHexNumber(argv, &ulValue))
293  {
294  DbgPrint("Invalid parameter: %s\n", argv);
295  return;
296  }
297 
298  pobj = (POBJ)ulValue;
299 
300  /* Check if the address is readable */
301  if (!KdbIsMemoryValid(pobj, sizeof(BASEOBJECT)))
302  {
303  DbgPrint("Cannot access BASEOBJECT at %p\n", pobj);
304  return;
305  }
306 
307  /* The kernel doesn't export RtlFirstEntrySList :( */
308  psleFirst = InterlockedFlushSList(&pobj->slhLog);
309 
310  /* Loop all events, but don't remove them */
311  for (psle = psleFirst; psle != NULL; psle = psle->Next)
312  {
313  pLogEntry = CONTAINING_RECORD(psle, LOGENTRY, sleLink);
314  DbgPrintEvent(pLogEntry);
315  }
316 
317  /* Put the log back in place */
318  InterlockedPushEntrySList(&pobj->slhLog, psleFirst);
319 }
320 #endif
321 
322 BOOLEAN
323 NTAPI
325  IN PCHAR pszCommand,
326  IN ULONG argc,
327  IN PCH argv[])
328 {
329 
330  if (stricmp(argv[0], "!gdi.help") == 0)
331  {
333  }
334  else if (stricmp(argv[0], "!gdi.dumpht") == 0)
335  {
336  KdbCommand_Gdi_dumpht(argc - 1, argv + 1);
337  }
338  else if (stricmp(argv[0], "!gdi.handle") == 0)
339  {
341  }
342  else if (stricmp(argv[0], "!gdi.entry") == 0)
343  {
345  }
346  else if (stricmp(argv[0], "!gdi.baseobject") == 0)
347  {
349  }
350 #if DBG_ENABLE_EVENT_LOGGING
351  else if (stricmp(argv[0], "!gdi.eventlist") == 0)
352  {
353  KdbCommand_Gdi_eventlist(argv[1]);
354  }
355 #endif
356  else
357  {
358  /* Not handled */
359  return FALSE;
360  }
361 
362  return TRUE;
363 }
364 
365 
366 
367 
368 
signed char * PCHAR
Definition: retypes.h:7
static BOOL KdbGetHexNumber(char *pszNum, ULONG_PTR *pulValue)
Definition: gdikdbgext.c:48
static int argc
Definition: ServiceArgs.c:12
#define IN
Definition: typedefs.h:38
UINT32 strtoul(const char *String, char **Terminator, UINT32 Base)
Definition: utclib.c:696
#define TRUE
Definition: types.h:120
KAPC_STATE
Definition: ketypes.h:1273
PVOID pUser
Definition: ntgdihdl.h:247
#define DbgPrint
Definition: loader.c:25
UCHAR Objt
Definition: ntgdihdl.h:245
unsigned char * PUCHAR
Definition: retypes.h:3
PEPROCESS gpepCSRSS
Definition: csr.c:15
struct _BASEOBJECT * pobj
Definition: ntgdihdl.h:230
DWORD dwThreadId
Definition: gdiobj.h:43
UCHAR Flags
Definition: ntgdihdl.h:246
USHORT cExclusiveLock
Definition: gdiobj.h:45
HGDIOBJ hHmgr
Definition: gdiobj.h:40
#define argv
Definition: mplay32.c:18
PENTRY gpentHmgr
Definition: gdiobj.c:147
USHORT BaseFlags
Definition: gdiobj.h:46
union _ENTRY::_EINFO einfo
uint32_t ULONG_PTR
Definition: typedefs.h:63
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:701
unsigned int BOOL
Definition: ntddk_ex.h:94
CHAR * PCH
Definition: ntbasedef.h:398
HGDIOBJ hHmgr(VOID)
Definition: baseobj.hpp:95
static VOID KdbCommand_Gdi_entry(char *argv)
Definition: gdikdbgext.c:231
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define DBG_ENABLE_EVENT_LOGGING
Definition: win32kp.h:16
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_Check_return_ _CRTIMP int __cdecl stricmp(_In_z_ const char *_Str1, _In_z_ const char *_Str2)
BOOLEAN NTAPI DbgGdiKdbgCliCallback(IN PCHAR pszCommand, IN ULONG argc, IN PCH argv[])
Definition: gdikdbgext.c:324
static COUNTS Counts
Definition: ObType.c:60
#define InterlockedFlushSList(SListHead)
Definition: rtlfuncs.h:3397
#define PSLIST_ENTRY
Definition: rtltypes.h:130
ULONG ulObj
Definition: ntgdihdl.h:241
BOOLEAN NTAPI MmIsAddressValid(IN PVOID VirtualAddress)
Definition: mmsup.c:174
unsigned char UCHAR
Definition: xmlstorage.h:181
#define PAGE_SIZE
Definition: env_spec_w32.h:49
KPROCESS Pcb
Definition: pstypes.h:1193
NTKERNELAPI PSLIST_ENTRY FASTCALL InterlockedPushEntrySList(IN PSLIST_HEADER ListHead, IN PSLIST_ENTRY ListEntry)
Definition: interlocked.c:82
HGDIOBJ hFree
Definition: ntgdihdl.h:231
static VOID KdbCommand_Gdi_handle(char *argv)
Definition: gdikdbgext.c:181
static const unsigned RESERVE_ENTRIES_COUNT
Definition: gdiobj.h:11
static VOID KdbCommand_Gdi_dumpht(ULONG argc, char *argv[])
Definition: gdikdbgext.c:80
static VOID KdbCommand_Gdi_help(VOID)
Definition: gdikdbgext.c:64
PULONG gpaulRefCount
Definition: gdiobj.c:148
unsigned short USHORT
Definition: pedump.c:61
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:753
USHORT FullUnique
Definition: ntgdihdl.h:244
ULONG gulFirstUnused
Definition: gdiobj.c:150
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1484
unsigned int * PULONG
Definition: retypes.h:1
static const char * gpszObjectTypes[]
Definition: gdikdbgext.c:20
struct _BASEOBJECT * POBJ
unsigned int ULONG
Definition: retypes.h:1
_In_ ULONG cjSize
Definition: winddi.h:3634
char * cleanup(char *str)
Definition: wpickclick.c:99
static VOID KdbCommand_Gdi_baseobject(char *argv)
Definition: gdikdbgext.c:277
union _ENTRY::_OBJECTOWNER ObjectOwner
Definition: ntgdihdl.h:226
#define ALIGN_DOWN_POINTER_BY(ptr, align)
Definition: umtypes.h:82
BOOLEAN KdbIsMemoryValid(PVOID pvBase, ULONG cjSize)
Definition: gdikdbgext.c:31