blob: a91e3235fcbe260d42c3dd8c8ee7dfd05ab9056e [file] [log] [blame]
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001/*
2 * Wine debugger utility routines
Alexandre Julliard808cb041995-08-17 17:11:36 +00003 *
4 * Copyright 1993 Eric Youngdale
5 * Copyright 1995 Alexandre Julliard
Alexandre Julliardf0b23541993-09-29 12:21:49 +00006 */
7
Marcus Meissnerb0d52b01999-02-28 19:59:00 +00008#include "config.h"
Alexandre Julliardecc37121994-11-22 16:31:29 +00009#include <stdlib.h>
Eric Pouechd33bcb62000-03-15 19:57:20 +000010#include <string.h>
Eric Pouech527eea92000-03-08 16:44:54 +000011#include "winbase.h"
12#include "wingdi.h"
13#include "winuser.h"
14#include "toolhelp.h"
Alexandre Julliarda6795412000-04-16 19:46:35 +000015#include "tlhelp32.h"
Alexandre Julliardded30381995-07-06 17:18:27 +000016#include "debugger.h"
Alexandre Julliardc6c09441997-01-12 18:32:19 +000017#include "expr.h"
Alexandre Julliardf0b23541993-09-29 12:21:49 +000018
Alexandre Julliard808cb041995-08-17 17:11:36 +000019/***********************************************************************
Eric Pouechb1518651999-02-20 16:39:51 +000020 * DEBUG_PrintBasic
Alexandre Julliard808cb041995-08-17 17:11:36 +000021 *
22 * Implementation of the 'print' command.
23 */
Eric Pouechd33bcb62000-03-15 19:57:20 +000024void DEBUG_PrintBasic( const DBG_VALUE* value, int count, char format )
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000025{
Alexandre Julliard01d63461997-01-20 19:43:45 +000026 char * default_format;
Eric Pouechd33bcb62000-03-15 19:57:20 +000027 long long int res;
Alexandre Julliardc6c09441997-01-12 18:32:19 +000028
Eric Pouechd33bcb62000-03-15 19:57:20 +000029 assert(value->cookie == DV_TARGET || value->cookie == DV_HOST);
30 if( value->type == NULL )
Alexandre Julliard808cb041995-08-17 17:11:36 +000031 {
Eric Poueche5efa0c2000-04-13 19:31:58 +000032 DEBUG_Printf(DBG_CHN_MESG, "Unable to evaluate expression\n");
Alexandre Julliardc6c09441997-01-12 18:32:19 +000033 return;
Alexandre Julliard808cb041995-08-17 17:11:36 +000034 }
Alexandre Julliardc6c09441997-01-12 18:32:19 +000035
36 default_format = NULL;
Eric Pouechd33bcb62000-03-15 19:57:20 +000037 res = DEBUG_GetExprValue(value, &default_format);
Alexandre Julliard2787be81995-05-22 18:23:01 +000038
Alexandre Julliardc6c09441997-01-12 18:32:19 +000039 switch(format)
Alexandre Julliard808cb041995-08-17 17:11:36 +000040 {
41 case 'x':
Eric Pouechd33bcb62000-03-15 19:57:20 +000042 if (value->addr.seg)
Alexandre Julliard01d63461997-01-20 19:43:45 +000043 {
Eric Poueche5efa0c2000-04-13 19:31:58 +000044 DEBUG_nchar += DEBUG_Printf( DBG_CHN_MESG, "0x%04lx", (long unsigned int) res );
Alexandre Julliard01d63461997-01-20 19:43:45 +000045 }
46 else
47 {
Eric Poueche5efa0c2000-04-13 19:31:58 +000048 DEBUG_nchar += DEBUG_Printf( DBG_CHN_MESG, "0x%08lx", (long unsigned int) res );
Alexandre Julliard01d63461997-01-20 19:43:45 +000049 }
Alexandre Julliardc6c09441997-01-12 18:32:19 +000050 break;
51
Alexandre Julliard808cb041995-08-17 17:11:36 +000052 case 'd':
Eric Poueche5efa0c2000-04-13 19:31:58 +000053 DEBUG_nchar += DEBUG_Printf( DBG_CHN_MESG, "%ld\n", (long int) res );
Alexandre Julliardc6c09441997-01-12 18:32:19 +000054 break;
55
Alexandre Julliard808cb041995-08-17 17:11:36 +000056 case 'c':
Eric Poueche5efa0c2000-04-13 19:31:58 +000057 DEBUG_nchar += DEBUG_Printf( DBG_CHN_MESG, "%d = '%c'",
58 (char)(res & 0xff), (char)(res & 0xff) );
Alexandre Julliardc6c09441997-01-12 18:32:19 +000059 break;
60
Alexandre Julliard808cb041995-08-17 17:11:36 +000061 case 'i':
62 case 's':
63 case 'w':
64 case 'b':
Eric Poueche5efa0c2000-04-13 19:31:58 +000065 DEBUG_Printf( DBG_CHN_MESG, "Format specifier '%c' is meaningless in 'print' command\n", format );
Alexandre Julliardc6c09441997-01-12 18:32:19 +000066 case 0:
67 if( default_format != NULL )
68 {
Eric Pouechd33bcb62000-03-15 19:57:20 +000069 if (strstr(default_format, "%S") == NULL)
70 {
Eric Poueche5efa0c2000-04-13 19:31:58 +000071 DEBUG_nchar += DEBUG_Printf( DBG_CHN_MESG, default_format, res );
Eric Pouechd33bcb62000-03-15 19:57:20 +000072 }
73 else
74 {
75 char* ptr;
76 int state = 0;
77
78 /* FIXME: simplistic implementation for default_format being
79 * foo%Sbar => will print foo, then string then bar
80 */
81 for (ptr = default_format; *ptr; ptr++)
82 {
Eric Pouechd33bcb62000-03-15 19:57:20 +000083 if (*ptr == '%') state++;
84 else if (state == 1)
85 {
86 if (*ptr == 'S')
87 {
88 char ch;
89 char* str = (char*)(long)res;
90
91 for (; DEBUG_READ_MEM(str, &ch, 1) && ch; str++) {
Eric Pouech04c16b82000-04-30 12:21:15 +000092 DEBUG_Output(DBG_CHN_MESG, &ch, 1);
Eric Pouechd33bcb62000-03-15 19:57:20 +000093 DEBUG_nchar++;
94 }
95 }
96 else
97 {
98 /* shouldn't happen */
Eric Pouech04c16b82000-04-30 12:21:15 +000099 DEBUG_Printf(DBG_CHN_MESG, "%%%c", *ptr);
Eric Pouechd33bcb62000-03-15 19:57:20 +0000100 DEBUG_nchar += 2;
101 }
102 state = 0;
103 }
104 else
105 {
Eric Pouech04c16b82000-04-30 12:21:15 +0000106 DEBUG_Output(DBG_CHN_MESG, ptr, 1);
Eric Pouechd33bcb62000-03-15 19:57:20 +0000107 DEBUG_nchar++;
108 }
109 }
110 }
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000111 }
112 break;
Alexandre Julliard808cb041995-08-17 17:11:36 +0000113 }
114}
115
116
117/***********************************************************************
118 * DEBUG_PrintAddress
119 *
120 * Print an 16- or 32-bit address, with the nearest symbol if any.
121 */
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000122struct symbol_info
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000123DEBUG_PrintAddress( const DBG_ADDR *addr, int addrlen, int flag )
Alexandre Julliard808cb041995-08-17 17:11:36 +0000124{
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000125 struct symbol_info rtn;
126
127 const char *name = DEBUG_FindNearestSymbol( addr, flag, &rtn.sym, 0,
128 &rtn.list );
Alexandre Julliard808cb041995-08-17 17:11:36 +0000129
Eric Poueche5efa0c2000-04-13 19:31:58 +0000130 if (addr->seg) DEBUG_Printf( DBG_CHN_MESG, "0x%04lx:", addr->seg&0xFFFF );
131 if (addrlen == 16) DEBUG_Printf( DBG_CHN_MESG, "0x%04lx", addr->off );
132 else DEBUG_Printf( DBG_CHN_MESG, "0x%08lx", addr->off );
133 if (name) DEBUG_Printf( DBG_CHN_MESG, " (%s)", name );
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000134 return rtn;
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000135}
136/***********************************************************************
137 * DEBUG_PrintAddressAndArgs
138 *
139 * Print an 16- or 32-bit address, with the nearest symbol if any.
140 * Similar to DEBUG_PrintAddress, but we print the arguments to
141 * each function (if known). This is useful in a backtrace.
142 */
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000143struct symbol_info
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000144DEBUG_PrintAddressAndArgs( const DBG_ADDR *addr, int addrlen,
145 unsigned int ebp, int flag )
146{
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000147 struct symbol_info rtn;
148
149 const char *name = DEBUG_FindNearestSymbol( addr, flag, &rtn.sym, ebp,
150 &rtn.list );
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000151
Eric Poueche5efa0c2000-04-13 19:31:58 +0000152 if (addr->seg) DEBUG_Printf( DBG_CHN_MESG, "0x%04lx:", addr->seg );
153 if (addrlen == 16) DEBUG_Printf( DBG_CHN_MESG, "0x%04lx", addr->off );
154 else DEBUG_Printf( DBG_CHN_MESG, "0x%08lx", addr->off );
155 if (name) DEBUG_Printf( DBG_CHN_MESG, " (%s)", name );
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000156
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000157 return rtn;
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000158}
159
160
Alexandre Julliard808cb041995-08-17 17:11:36 +0000161/***********************************************************************
162 * DEBUG_Help
163 *
164 * Implementation of the 'help' command.
165 */
166void DEBUG_Help(void)
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000167{
Alexandre Julliard808cb041995-08-17 17:11:36 +0000168 int i = 0;
Alexandre Julliardd90840e1996-06-11 16:02:08 +0000169 static const char * const helptext[] =
Alexandre Julliard808cb041995-08-17 17:11:36 +0000170{
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000171"The commands accepted by the Wine debugger are a reasonable",
Alexandre Julliard21979011997-03-05 08:22:35 +0000172"subset of the commands that gdb accepts.",
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000173"The commands currently are:",
Alexandre Julliard410ae4f1999-06-18 18:23:11 +0000174" help quit",
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000175" break [*<addr>] delete break bpnum",
176" disable bpnum enable bpnum",
Alexandre Julliard410ae4f1999-06-18 18:23:11 +0000177" condition <bpnum> [<expr>] pass",
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000178" bt cont [N]",
179" step [N] next [N]",
180" stepi [N] nexti [N]",
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000181" x <addr> print <expr>",
182" set <reg> = <expr> set *<addr> = <expr>",
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000183" up down",
Alexandre Julliard21979011997-03-05 08:22:35 +0000184" list <lines> disassemble [<addr>][,<addr>]",
185" frame <n> finish",
186" show dir dir <path>",
187" display <expr> undisplay <disnum>",
Marcus Meissner40c11eb1999-01-24 09:37:33 +0000188" delete display <disnum> debugmsg <class>[-+]<type>\n",
Guy Albertelli0e65b381999-06-12 10:49:36 +0000189" mode [16,32] walk [wnd,class,queue,module,",
Eric Pouechd33bcb62000-03-15 19:57:20 +0000190" whatis process,modref <pid>]",
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000191" info (see 'help info' for options)\n",
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000192
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000193"The 'x' command accepts repeat counts and formats (including 'i') in the",
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000194"same way that gdb does.\n",
195
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000196" The following are examples of legal expressions:",
197" $eax $eax+0x3 0x1000 ($eip + 256) *$eax *($esp + 3)",
198" Also, a nm format symbol table can be read from a file using the",
199" symbolfile command. Symbols can also be defined individually with",
200" the define command.",
201"",
Alexandre Julliard808cb041995-08-17 17:11:36 +0000202NULL
203};
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000204
Eric Poueche5efa0c2000-04-13 19:31:58 +0000205 while(helptext[i]) DEBUG_Printf(DBG_CHN_MESG,"%s\n", helptext[i++]);
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000206}
Alexandre Julliard902da691995-11-05 14:39:02 +0000207
208
Alexandre Julliard902da691995-11-05 14:39:02 +0000209/***********************************************************************
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000210 * DEBUG_HelpInfo
Alexandre Julliard902da691995-11-05 14:39:02 +0000211 *
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000212 * Implementation of the 'help info' command.
Alexandre Julliard902da691995-11-05 14:39:02 +0000213 */
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000214void DEBUG_HelpInfo(void)
Alexandre Julliard902da691995-11-05 14:39:02 +0000215{
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000216 int i = 0;
217 static const char * const infotext[] =
218{
219"The info commands allow you to get assorted bits of interesting stuff",
220"to be displayed. The options are:",
221" info break Dumps information about breakpoints",
222" info display Shows auto-display expressions in use",
223" info locals Displays values of all local vars for current frame",
Alexandre Julliard889f7421997-04-15 17:19:52 +0000224" info maps Dumps all virtual memory mappings",
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000225" info module <handle> Displays internal module state",
226" info queue <handle> Displays internal queue state",
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000227" info reg Displays values in all registers at top of stack",
228" info segments Dumps information about all known segments",
229" info share Dumps information about shared libraries",
230" info stack Dumps information about top of stack",
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000231" info wnd <handle> Displays internal window state",
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000232"",
233NULL
234};
Alexandre Julliard902da691995-11-05 14:39:02 +0000235
Eric Poueche5efa0c2000-04-13 19:31:58 +0000236 while(infotext[i]) DEBUG_Printf(DBG_CHN_MESG,"%s\n", infotext[i++]);
Alexandre Julliard902da691995-11-05 14:39:02 +0000237}
Eric Pouech527eea92000-03-08 16:44:54 +0000238
239/* FIXME: merge InfoClass and InfoClass2 */
240void DEBUG_InfoClass(const char* name)
241{
242 WNDCLASSEXA wca;
243
Eric Poueche5efa0c2000-04-13 19:31:58 +0000244 if (!GetClassInfoEx(0, name, &wca)) {
245 DEBUG_Printf(DBG_CHN_MESG, "Cannot find class '%s'\n", name);
Eric Pouech527eea92000-03-08 16:44:54 +0000246 return;
247 }
248
Eric Poueche5efa0c2000-04-13 19:31:58 +0000249 DEBUG_Printf(DBG_CHN_MESG, "Class '%s':\n", name);
250 DEBUG_Printf(DBG_CHN_MESG,
251 "style=%08x wndProc=%08lx\n"
252 "inst=%04x icon=%04x cursor=%04x bkgnd=%04x\n"
253 "clsExtra=%d winExtra=%d\n",
254 wca.style, (DWORD)wca.lpfnWndProc, wca.hInstance,
255 wca.hIcon, wca.hCursor, wca.hbrBackground,
256 wca.cbClsExtra, wca.cbWndExtra);
Eric Pouech527eea92000-03-08 16:44:54 +0000257
258 /* FIXME:
259 * + print #windows (or even list of windows...)
260 * + print extra bytes => this requires a window handle on this very class...
261 */
262}
263
264static void DEBUG_InfoClass2(HWND hWnd, const char* name)
265{
266 WNDCLASSEXA wca;
267
Eric Poueche5efa0c2000-04-13 19:31:58 +0000268 if (!GetClassInfoEx(GetWindowLong(hWnd, GWL_HINSTANCE), name, &wca)) {
269 DEBUG_Printf(DBG_CHN_MESG, "Cannot find class '%s'\n", name);
Eric Pouech527eea92000-03-08 16:44:54 +0000270 return;
271 }
272
Eric Poueche5efa0c2000-04-13 19:31:58 +0000273 DEBUG_Printf(DBG_CHN_MESG, "Class '%s':\n", name);
274 DEBUG_Printf(DBG_CHN_MESG,
275 "style=%08x wndProc=%08lx\n"
276 "inst=%04x icon=%04x cursor=%04x bkgnd=%04x\n"
277 "clsExtra=%d winExtra=%d\n",
278 wca.style, (DWORD)wca.lpfnWndProc, wca.hInstance,
279 wca.hIcon, wca.hCursor, wca.hbrBackground,
280 wca.cbClsExtra, wca.cbWndExtra);
Eric Pouech527eea92000-03-08 16:44:54 +0000281
282 if (wca.cbClsExtra) {
283 int i;
284 WORD w;
285
Eric Poueche5efa0c2000-04-13 19:31:58 +0000286 DEBUG_Printf(DBG_CHN_MESG, "Extra bytes:" );
Eric Pouech527eea92000-03-08 16:44:54 +0000287 for (i = 0; i < wca.cbClsExtra / 2; i++) {
288 w = GetClassWord(hWnd, i * 2);
289 /* FIXME: depends on i386 endian-ity */
Eric Poueche5efa0c2000-04-13 19:31:58 +0000290 DEBUG_Printf(DBG_CHN_MESG, " %02x", HIBYTE(w));
291 DEBUG_Printf(DBG_CHN_MESG, " %02x", LOBYTE(w));
Eric Pouech527eea92000-03-08 16:44:54 +0000292 }
Eric Poueche5efa0c2000-04-13 19:31:58 +0000293 DEBUG_Printf(DBG_CHN_MESG, "\n" );
Eric Pouech527eea92000-03-08 16:44:54 +0000294 }
Eric Poueche5efa0c2000-04-13 19:31:58 +0000295 DEBUG_Printf(DBG_CHN_MESG, "\n" );
Eric Pouech527eea92000-03-08 16:44:54 +0000296}
297
298struct class_walker {
299 ATOM* table;
300 int used;
301 int alloc;
302};
303
304static void DEBUG_WalkClassesHelper(HWND hWnd, struct class_walker* cw)
305{
306 char clsName[128];
307 int i;
308 ATOM atom;
309 HWND child;
310
Eric Poueche5efa0c2000-04-13 19:31:58 +0000311 if (!GetClassName(hWnd, clsName, sizeof(clsName)))
Eric Pouech527eea92000-03-08 16:44:54 +0000312 return;
Eric Poueche5efa0c2000-04-13 19:31:58 +0000313 if ((atom = FindAtom(clsName)) == 0)
Eric Pouech527eea92000-03-08 16:44:54 +0000314 return;
315
316 for (i = 0; i < cw->used; i++) {
317 if (cw->table[i] == atom)
318 break;
319 }
320 if (i == cw->used) {
321 if (cw->used >= cw->alloc) {
322 cw->alloc += 16;
323 cw->table = DBG_realloc(cw->table, cw->alloc * sizeof(ATOM));
324 }
325 cw->table[cw->used++] = atom;
326 DEBUG_InfoClass2(hWnd, clsName);
327 }
328 do {
329 if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
330 DEBUG_WalkClassesHelper(child, cw);
331 } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
332}
333
334void DEBUG_WalkClasses(void)
335{
336 struct class_walker cw;
337
338 cw.table = NULL;
339 cw.used = cw.alloc = 0;
340 DEBUG_WalkClassesHelper(GetDesktopWindow(), &cw);
341 DBG_free(cw.table);
342}
343
Eric Pouech527eea92000-03-08 16:44:54 +0000344void DEBUG_DumpQueue(DWORD q)
345{
Eric Poueche5efa0c2000-04-13 19:31:58 +0000346 DEBUG_Printf(DBG_CHN_MESG, "No longer doing info queue '0x%08lx'\n", q);
Eric Pouech527eea92000-03-08 16:44:54 +0000347}
348
349void DEBUG_WalkQueues(void)
350{
Eric Poueche5efa0c2000-04-13 19:31:58 +0000351 DEBUG_Printf(DBG_CHN_MESG, "No longer walking queues list\n");
Eric Pouech527eea92000-03-08 16:44:54 +0000352}
353
354void DEBUG_InfoWindow(HWND hWnd)
355{
356 char clsName[128];
357 char wndName[128];
358 RECT clientRect;
359 RECT windowRect;
360 int i;
361 WORD w;
362
Eric Poueche5efa0c2000-04-13 19:31:58 +0000363 if (!GetClassName(hWnd, clsName, sizeof(clsName)))
Eric Pouech527eea92000-03-08 16:44:54 +0000364 strcpy(clsName, "-- Unknown --");
Eric Poueche5efa0c2000-04-13 19:31:58 +0000365 if (!GetWindowText(hWnd, wndName, sizeof(wndName)))
Eric Pouech527eea92000-03-08 16:44:54 +0000366 strcpy(wndName, "-- Empty --");
367 if (!GetClientRect(hWnd, &clientRect))
368 SetRectEmpty(&clientRect);
369 if (!GetWindowRect(hWnd, &windowRect))
370 SetRectEmpty(&windowRect);
371
372 /* FIXME missing fields: hmemTaskQ, hrgnUpdate, dce, flags, pProp, scroll */
Eric Poueche5efa0c2000-04-13 19:31:58 +0000373 DEBUG_Printf(DBG_CHN_MESG,
374 "next=0x%04x child=0x%04x parent=0x%04x owner=0x%04x class='%s'\n"
375 "inst=%08lx active=%04x idmenu=%08lx\n"
376 "style=%08lx exstyle=%08lx wndproc=%08lx text='%s'\n"
377 "client=%d,%d-%d,%d window=%d,%d-%d,%d sysmenu=%04x\n",
378 GetWindow(hWnd, GW_HWNDNEXT),
379 GetWindow(hWnd, GW_CHILD),
380 GetParent(hWnd),
381 GetWindow(hWnd, GW_OWNER),
382 clsName,
383 GetWindowLong(hWnd, GWL_HINSTANCE),
384 GetLastActivePopup(hWnd),
385 GetWindowLong(hWnd, GWL_ID),
386 GetWindowLong(hWnd, GWL_STYLE),
387 GetWindowLong(hWnd, GWL_EXSTYLE),
388 GetWindowLong(hWnd, GWL_WNDPROC),
389 wndName,
390 clientRect.left, clientRect.top, clientRect.right, clientRect.bottom,
391 windowRect.left, windowRect.top, windowRect.right, windowRect.bottom,
392 GetSystemMenu(hWnd, FALSE));
Eric Pouech527eea92000-03-08 16:44:54 +0000393
Eric Poueche5efa0c2000-04-13 19:31:58 +0000394 if (GetClassLong(hWnd, GCL_CBWNDEXTRA)) {
395 DEBUG_Printf(DBG_CHN_MESG, "Extra bytes:" );
396 for (i = 0; i < GetClassLong(hWnd, GCL_CBWNDEXTRA) / 2; i++) {
Eric Pouech527eea92000-03-08 16:44:54 +0000397 w = GetWindowWord(hWnd, i * 2);
398 /* FIXME: depends on i386 endian-ity */
Eric Poueche5efa0c2000-04-13 19:31:58 +0000399 DEBUG_Printf(DBG_CHN_MESG, " %02x", HIBYTE(w));
400 DEBUG_Printf(DBG_CHN_MESG, " %02x", LOBYTE(w));
Eric Pouech527eea92000-03-08 16:44:54 +0000401 }
Eric Poueche5efa0c2000-04-13 19:31:58 +0000402 DEBUG_Printf(DBG_CHN_MESG, "\n");
Eric Pouech527eea92000-03-08 16:44:54 +0000403 }
Eric Poueche5efa0c2000-04-13 19:31:58 +0000404 DEBUG_Printf(DBG_CHN_MESG, "\n");
Eric Pouech527eea92000-03-08 16:44:54 +0000405}
406
407void DEBUG_WalkWindows(HWND hWnd, int indent)
408{
409 char clsName[128];
410 char wndName[128];
411 HWND child;
412
413 if (!IsWindow(hWnd))
414 hWnd = GetDesktopWindow();
415
416 if (!indent) /* first time around */
Eric Poueche5efa0c2000-04-13 19:31:58 +0000417 DEBUG_Printf(DBG_CHN_MESG,
418 "%-16.16s %-17.17s %-8.8s %s\n",
419 "hwnd", "Class Name", " Style", " WndProc Text");
Eric Pouech527eea92000-03-08 16:44:54 +0000420
421 do {
Eric Poueche5efa0c2000-04-13 19:31:58 +0000422 if (!GetClassName(hWnd, clsName, sizeof(clsName)))
Eric Pouech527eea92000-03-08 16:44:54 +0000423 strcpy(clsName, "-- Unknown --");
Eric Poueche5efa0c2000-04-13 19:31:58 +0000424 if (!GetWindowText(hWnd, wndName, sizeof(wndName)))
Eric Pouech527eea92000-03-08 16:44:54 +0000425 strcpy(wndName, "-- Empty --");
426
427 /* FIXME: missing hmemTaskQ */
Eric Poueche5efa0c2000-04-13 19:31:58 +0000428 DEBUG_Printf(DBG_CHN_MESG, "%*s%04x%*s", indent, "", hWnd, 13-indent,"");
429 DEBUG_Printf(DBG_CHN_MESG, "%-17.17s %08lx %08lx %.14s\n",
430 clsName, GetWindowLong(hWnd, GWL_STYLE),
431 GetWindowLong(hWnd, GWL_WNDPROC), wndName);
Eric Pouech527eea92000-03-08 16:44:54 +0000432
433 if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
434 DEBUG_WalkWindows(child, indent + 1 );
435 } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
436}
437
438void DEBUG_WalkProcess(void)
439{
Alexandre Julliarda6795412000-04-16 19:46:35 +0000440 HANDLE snap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
441 if (snap != INVALID_HANDLE_VALUE)
442 {
443 PROCESSENTRY32 entry;
444 DWORD current = DEBUG_CurrProcess ? DEBUG_CurrProcess->pid : 0;
Eric Pouechf1822352000-05-11 21:43:43 +0000445 BOOL ok;
446
447 entry.dwSize = sizeof(entry);
448 ok = Process32First( snap, &entry );
Alexandre Julliarda6795412000-04-16 19:46:35 +0000449
450 DEBUG_Printf(DBG_CHN_MESG, "%-8.8s %-8.8s %-8.8s %s\n",
451 "pid", "threads", "parent", "exe" );
452 while (ok)
453 {
454 if (entry.th32ProcessID != GetCurrentProcessId())
Eric Pouechf1822352000-05-11 21:43:43 +0000455 DEBUG_Printf(DBG_CHN_MESG, "%08lx %8ld %08lx '%s'%s\n",
Alexandre Julliarda6795412000-04-16 19:46:35 +0000456 entry.th32ProcessID, entry.cntThreads,
457 entry.th32ParentProcessID, entry.szExeFile,
458 (entry.th32ProcessID == current) ? " <==" : "" );
459 ok = Process32Next( snap, &entry );
460 }
461 CloseHandle( snap );
462 }
463}
464
465void DEBUG_WalkThreads(void)
466{
467 HANDLE snap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
468 if (snap != INVALID_HANDLE_VALUE)
469 {
470 THREADENTRY32 entry;
471 DWORD current = DEBUG_CurrThread ? DEBUG_CurrThread->tid : 0;
Eric Pouechf1822352000-05-11 21:43:43 +0000472 BOOL ok;
473
474 entry.dwSize = sizeof(entry);
475 ok = Thread32First( snap, &entry );
Alexandre Julliarda6795412000-04-16 19:46:35 +0000476
477 DEBUG_Printf(DBG_CHN_MESG, "%-8.8s %-8.8s %s\n",
478 "tid", "process", "prio" );
479 while (ok)
480 {
481 if (entry.th32OwnerProcessID != GetCurrentProcessId())
482 DEBUG_Printf(DBG_CHN_MESG, "%08lx %08lx %4ld%s\n",
483 entry.th32ThreadID, entry.th32OwnerProcessID,
484 entry.tbBasePri, (entry.th32ThreadID == current) ? " <==" : "" );
485 ok = Thread32Next( snap, &entry );
486 }
487 CloseHandle( snap );
488 }
Eric Pouech527eea92000-03-08 16:44:54 +0000489}
490
491void DEBUG_WalkModref(DWORD p)
492{
Eric Poueche5efa0c2000-04-13 19:31:58 +0000493 DEBUG_Printf(DBG_CHN_MESG, "No longer walking module references list\n");
Eric Pouech527eea92000-03-08 16:44:54 +0000494}
495
496void DEBUG_InfoSegments(DWORD start, int length)
497{
498 char flags[3];
499 DWORD i;
500 LDT_ENTRY le;
501
502 if (length == -1) length = (8192 - start);
503
504 for (i = start; i < start + length; i++)
505 {
506 if (!GetThreadSelectorEntry(DEBUG_CurrThread->handle, (i << 3)|7, &le))
507 continue;
508
509 if (le.HighWord.Bits.Type & 0x08)
510 {
511 flags[0] = (le.HighWord.Bits.Type & 0x2) ? 'r' : '-';
512 flags[1] = '-';
513 flags[2] = 'x';
514 }
515 else
516 {
517 flags[0] = 'r';
518 flags[1] = (le.HighWord.Bits.Type & 0x2) ? 'w' : '-';
519 flags[2] = '-';
520 }
Eric Poueche5efa0c2000-04-13 19:31:58 +0000521 DEBUG_Printf(DBG_CHN_MESG,
522 "%04lx: sel=%04lx base=%08x limit=%08x %d-bit %c%c%c\n",
523 i, (i<<3)|7,
524 (le.HighWord.Bits.BaseHi << 24) +
525 (le.HighWord.Bits.BaseMid << 16) + le.BaseLow,
526 ((le.HighWord.Bits.LimitHi << 8) + le.LimitLow) <<
527 (le.HighWord.Bits.Granularity ? 12 : 0),
528 le.HighWord.Bits.Default_Big ? 32 : 16,
529 flags[0], flags[1], flags[2] );
Eric Pouech527eea92000-03-08 16:44:54 +0000530 }
531}
532
533void DEBUG_InfoVirtual(void)
534{
Eric Poueche5efa0c2000-04-13 19:31:58 +0000535 DEBUG_Printf(DBG_CHN_MESG, "No longer providing virtual mapping information\n");
Eric Pouech527eea92000-03-08 16:44:54 +0000536}