ReactOS 0.4.16-dev-319-g6cf4263
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
15extern PENTRY gpentHmgr;
18
19
20static 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
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
46static
47BOOL
48KdbGetHexNumber(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
62static
63VOID
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
78static
79VOID
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",
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 */
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
175leave:
177}
178
179static
180VOID
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
229static
230VOID
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
271cleanup:
273}
274
275static
276VOID
278{
279}
280
281#if DBG_ENABLE_EVENT_LOGGING
282static
283VOID
284KdbCommand_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
323NTAPI
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 {
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
static COUNTS Counts
Definition: ObType.c:60
unsigned char BOOLEAN
static int argc
Definition: ServiceArgs.c:12
UINT32 strtoul(const char *String, char **Terminator, UINT32 Base)
Definition: utclib.c:696
#define leave
Definition: btrfs_drv.h:138
#define _stricmp
Definition: cat.c:22
HGDIOBJ hHmgr(VOID)
Definition: baseobj.hpp:95
PEPROCESS gpepCSRSS
Definition: csr.c:15
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static void cleanup(void)
Definition: main.c:1335
#define PAGE_SIZE
Definition: env_spec_w32.h:49
unsigned int BOOL
Definition: ntddk_ex.h:94
static VOID KdbCommand_Gdi_entry(char *argv)
Definition: gdikdbgext.c:231
static const char * gpszObjectTypes[]
Definition: gdikdbgext.c:20
static VOID KdbCommand_Gdi_handle(char *argv)
Definition: gdikdbgext.c:181
BOOLEAN KdbIsMemoryValid(PVOID pvBase, ULONG cjSize)
Definition: gdikdbgext.c:31
static VOID KdbCommand_Gdi_baseobject(char *argv)
Definition: gdikdbgext.c:277
static BOOL KdbGetHexNumber(char *pszNum, ULONG_PTR *pulValue)
Definition: gdikdbgext.c:48
static VOID KdbCommand_Gdi_dumpht(ULONG argc, char *argv[])
Definition: gdikdbgext.c:80
PENTRY gpentHmgr
Definition: gdiobj.c:149
PULONG gpaulRefCount
Definition: gdiobj.c:150
ULONG gulFirstUnused
Definition: gdiobj.c:152
BOOLEAN NTAPI DbgGdiKdbgCliCallback(IN PCHAR pszCommand, IN ULONG argc, IN PCH argv[])
Definition: gdikdbgext.c:324
static VOID KdbCommand_Gdi_help(VOID)
Definition: gdikdbgext.c:64
struct _BASEOBJECT * POBJ
static const unsigned RESERVE_ENTRIES_COUNT
Definition: gdiobj.h:11
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
#define DbgPrint
Definition: hal.h:12
BOOLEAN NTAPI MmIsAddressValid(IN PVOID VirtualAddress)
Definition: mmsup.c:174
#define argv
Definition: mplay32.c:18
CHAR * PCH
Definition: ntbasedef.h:399
@ GDIObjType_MAX_TYPE
Definition: ntgdityp.h:151
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1765
unsigned short USHORT
Definition: pedump.c:61
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:704
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:756
Definition: DelNode.c:62
HGDIOBJ hHmgr
Definition: gdiobj.h:40
USHORT BaseFlags
Definition: gdiobj.h:46
USHORT cExclusiveLock
Definition: gdiobj.h:45
DWORD dwThreadId
Definition: gdiobj.h:43
Definition: ntgdihdl.h:218
union _ENTRY::_OBJECTOWNER ObjectOwner
UCHAR Objt
Definition: ntgdihdl.h:236
PVOID pUser
Definition: ntgdihdl.h:238
UCHAR Flags
Definition: ntgdihdl.h:237
union _ENTRY::_EINFO einfo
USHORT FullUnique
Definition: ntgdihdl.h:235
KPROCESS Pcb
Definition: pstypes.h:1263
uint32_t * PULONG
Definition: typedefs.h:59
#define NTAPI
Definition: typedefs.h:36
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
char * PCHAR
Definition: typedefs.h:51
#define ALIGN_DOWN_POINTER_BY(ptr, align)
Definition: umtypes.h:82
struct _BASEOBJECT * pobj
Definition: ntgdihdl.h:221
HGDIOBJ hFree
Definition: ntgdihdl.h:222
ULONG ulObj
Definition: ntgdihdl.h:232
#define DBG_ENABLE_EVENT_LOGGING
Definition: win32kp.h:16
_In_ ULONG cjSize
Definition: winddi.h:3634
KAPC_STATE
Definition: ketypes.h:1409
#define InterlockedPushEntrySList(SListHead, SListEntry)
Definition: rtlfuncs.h:3406
#define InterlockedFlushSList(SListHead)
Definition: rtlfuncs.h:3412
#define PSLIST_ENTRY
Definition: rtltypes.h:134
unsigned char UCHAR
Definition: xmlstorage.h:181