Started implementation of the functions GetDefaultCommConfigA/W.
[wine.git] / debugger / info.c
blobe9ac863d24bbce3f5b8606f49d788f0e68a96138
1 /*
2 * Wine debugger utility routines
4 * Copyright 1993 Eric Youngdale
5 * Copyright 1995 Alexandre Julliard
6 */
8 #include "config.h"
9 #include <stdlib.h>
10 #include <string.h>
11 #include "winbase.h"
12 #include "wingdi.h"
13 #include "winuser.h"
14 #include "toolhelp.h"
15 #include "tlhelp32.h"
16 #include "debugger.h"
17 #include "expr.h"
19 /***********************************************************************
20 * DEBUG_PrintBasic
22 * Implementation of the 'print' command.
24 void DEBUG_PrintBasic( const DBG_VALUE* value, int count, char format )
26 char * default_format;
27 long long int res;
29 assert(value->cookie == DV_TARGET || value->cookie == DV_HOST);
30 if( value->type == NULL )
32 DEBUG_Printf(DBG_CHN_MESG, "Unable to evaluate expression\n");
33 return;
36 default_format = NULL;
37 res = DEBUG_GetExprValue(value, &default_format);
39 switch(format)
41 case 'x':
42 if (value->addr.seg)
44 DEBUG_nchar += DEBUG_Printf( DBG_CHN_MESG, "0x%04lx", (long unsigned int) res );
46 else
48 DEBUG_nchar += DEBUG_Printf( DBG_CHN_MESG, "0x%08lx", (long unsigned int) res );
50 break;
52 case 'd':
53 DEBUG_nchar += DEBUG_Printf( DBG_CHN_MESG, "%ld\n", (long int) res );
54 break;
56 case 'c':
57 DEBUG_nchar += DEBUG_Printf( DBG_CHN_MESG, "%d = '%c'",
58 (char)(res & 0xff), (char)(res & 0xff) );
59 break;
61 case 'i':
62 case 's':
63 case 'w':
64 case 'b':
65 DEBUG_Printf( DBG_CHN_MESG, "Format specifier '%c' is meaningless in 'print' command\n", format );
66 case 0:
67 if( default_format != NULL )
69 if (strstr(default_format, "%S") == NULL)
71 DEBUG_nchar += DEBUG_Printf( DBG_CHN_MESG, default_format, res );
73 else
75 char* ptr;
76 int state = 0;
78 /* FIXME: simplistic implementation for default_format being
79 * foo%Sbar => will print foo, then string then bar
81 for (ptr = default_format; *ptr; ptr++)
83 DEBUG_Printf(DBG_CHN_MESG, "[%c]", *ptr);
85 if (*ptr == '%') state++;
86 else if (state == 1)
88 if (*ptr == 'S')
90 char ch;
91 char* str = (char*)(long)res;
93 for (; DEBUG_READ_MEM(str, &ch, 1) && ch; str++) {
94 DEBUG_Output(DBG_CHN_MESG, &ch, 1);
95 DEBUG_nchar++;
98 else
100 /* shouldn't happen */
101 DEBUG_Printf(DBG_CHN_MESG, "%%%c", *ptr);
102 DEBUG_nchar += 2;
104 state = 0;
106 else
108 DEBUG_Output(DBG_CHN_MESG, ptr, 1);
109 DEBUG_nchar++;
114 break;
119 /***********************************************************************
120 * DEBUG_PrintAddress
122 * Print an 16- or 32-bit address, with the nearest symbol if any.
124 struct symbol_info
125 DEBUG_PrintAddress( const DBG_ADDR *addr, int addrlen, int flag )
127 struct symbol_info rtn;
129 const char *name = DEBUG_FindNearestSymbol( addr, flag, &rtn.sym, 0,
130 &rtn.list );
132 if (addr->seg) DEBUG_Printf( DBG_CHN_MESG, "0x%04lx:", addr->seg&0xFFFF );
133 if (addrlen == 16) DEBUG_Printf( DBG_CHN_MESG, "0x%04lx", addr->off );
134 else DEBUG_Printf( DBG_CHN_MESG, "0x%08lx", addr->off );
135 if (name) DEBUG_Printf( DBG_CHN_MESG, " (%s)", name );
136 return rtn;
138 /***********************************************************************
139 * DEBUG_PrintAddressAndArgs
141 * Print an 16- or 32-bit address, with the nearest symbol if any.
142 * Similar to DEBUG_PrintAddress, but we print the arguments to
143 * each function (if known). This is useful in a backtrace.
145 struct symbol_info
146 DEBUG_PrintAddressAndArgs( const DBG_ADDR *addr, int addrlen,
147 unsigned int ebp, int flag )
149 struct symbol_info rtn;
151 const char *name = DEBUG_FindNearestSymbol( addr, flag, &rtn.sym, ebp,
152 &rtn.list );
154 if (addr->seg) DEBUG_Printf( DBG_CHN_MESG, "0x%04lx:", addr->seg );
155 if (addrlen == 16) DEBUG_Printf( DBG_CHN_MESG, "0x%04lx", addr->off );
156 else DEBUG_Printf( DBG_CHN_MESG, "0x%08lx", addr->off );
157 if (name) DEBUG_Printf( DBG_CHN_MESG, " (%s)", name );
159 return rtn;
163 /***********************************************************************
164 * DEBUG_Help
166 * Implementation of the 'help' command.
168 void DEBUG_Help(void)
170 int i = 0;
171 static const char * const helptext[] =
173 "The commands accepted by the Wine debugger are a reasonable",
174 "subset of the commands that gdb accepts.",
175 "The commands currently are:",
176 " help quit",
177 " break [*<addr>] delete break bpnum",
178 " disable bpnum enable bpnum",
179 " condition <bpnum> [<expr>] pass",
180 " bt cont [N]",
181 " step [N] next [N]",
182 " stepi [N] nexti [N]",
183 " x <addr> print <expr>",
184 " set <reg> = <expr> set *<addr> = <expr>",
185 " up down",
186 " list <lines> disassemble [<addr>][,<addr>]",
187 " frame <n> finish",
188 " show dir dir <path>",
189 " display <expr> undisplay <disnum>",
190 " delete display <disnum> debugmsg <class>[-+]<type>\n",
191 " mode [16,32] walk [wnd,class,queue,module,",
192 " whatis process,modref <pid>]",
193 " info (see 'help info' for options)\n",
195 "The 'x' command accepts repeat counts and formats (including 'i') in the",
196 "same way that gdb does.\n",
198 " The following are examples of legal expressions:",
199 " $eax $eax+0x3 0x1000 ($eip + 256) *$eax *($esp + 3)",
200 " Also, a nm format symbol table can be read from a file using the",
201 " symbolfile command. Symbols can also be defined individually with",
202 " the define command.",
204 NULL
207 while(helptext[i]) DEBUG_Printf(DBG_CHN_MESG,"%s\n", helptext[i++]);
211 /***********************************************************************
212 * DEBUG_HelpInfo
214 * Implementation of the 'help info' command.
216 void DEBUG_HelpInfo(void)
218 int i = 0;
219 static const char * const infotext[] =
221 "The info commands allow you to get assorted bits of interesting stuff",
222 "to be displayed. The options are:",
223 " info break Dumps information about breakpoints",
224 " info display Shows auto-display expressions in use",
225 " info locals Displays values of all local vars for current frame",
226 " info maps Dumps all virtual memory mappings",
227 " info module <handle> Displays internal module state",
228 " info queue <handle> Displays internal queue state",
229 " info reg Displays values in all registers at top of stack",
230 " info segments Dumps information about all known segments",
231 " info share Dumps information about shared libraries",
232 " info stack Dumps information about top of stack",
233 " info wnd <handle> Displays internal window state",
235 NULL
238 while(infotext[i]) DEBUG_Printf(DBG_CHN_MESG,"%s\n", infotext[i++]);
241 /* FIXME: merge InfoClass and InfoClass2 */
242 void DEBUG_InfoClass(const char* name)
244 WNDCLASSEXA wca;
246 if (!GetClassInfoEx(0, name, &wca)) {
247 DEBUG_Printf(DBG_CHN_MESG, "Cannot find class '%s'\n", name);
248 return;
251 DEBUG_Printf(DBG_CHN_MESG, "Class '%s':\n", name);
252 DEBUG_Printf(DBG_CHN_MESG,
253 "style=%08x wndProc=%08lx\n"
254 "inst=%04x icon=%04x cursor=%04x bkgnd=%04x\n"
255 "clsExtra=%d winExtra=%d\n",
256 wca.style, (DWORD)wca.lpfnWndProc, wca.hInstance,
257 wca.hIcon, wca.hCursor, wca.hbrBackground,
258 wca.cbClsExtra, wca.cbWndExtra);
260 /* FIXME:
261 * + print #windows (or even list of windows...)
262 * + print extra bytes => this requires a window handle on this very class...
266 static void DEBUG_InfoClass2(HWND hWnd, const char* name)
268 WNDCLASSEXA wca;
270 if (!GetClassInfoEx(GetWindowLong(hWnd, GWL_HINSTANCE), name, &wca)) {
271 DEBUG_Printf(DBG_CHN_MESG, "Cannot find class '%s'\n", name);
272 return;
275 DEBUG_Printf(DBG_CHN_MESG, "Class '%s':\n", name);
276 DEBUG_Printf(DBG_CHN_MESG,
277 "style=%08x wndProc=%08lx\n"
278 "inst=%04x icon=%04x cursor=%04x bkgnd=%04x\n"
279 "clsExtra=%d winExtra=%d\n",
280 wca.style, (DWORD)wca.lpfnWndProc, wca.hInstance,
281 wca.hIcon, wca.hCursor, wca.hbrBackground,
282 wca.cbClsExtra, wca.cbWndExtra);
284 if (wca.cbClsExtra) {
285 int i;
286 WORD w;
288 DEBUG_Printf(DBG_CHN_MESG, "Extra bytes:" );
289 for (i = 0; i < wca.cbClsExtra / 2; i++) {
290 w = GetClassWord(hWnd, i * 2);
291 /* FIXME: depends on i386 endian-ity */
292 DEBUG_Printf(DBG_CHN_MESG, " %02x", HIBYTE(w));
293 DEBUG_Printf(DBG_CHN_MESG, " %02x", LOBYTE(w));
295 DEBUG_Printf(DBG_CHN_MESG, "\n" );
297 DEBUG_Printf(DBG_CHN_MESG, "\n" );
300 struct class_walker {
301 ATOM* table;
302 int used;
303 int alloc;
306 static void DEBUG_WalkClassesHelper(HWND hWnd, struct class_walker* cw)
308 char clsName[128];
309 int i;
310 ATOM atom;
311 HWND child;
313 if (!GetClassName(hWnd, clsName, sizeof(clsName)))
314 return;
315 if ((atom = FindAtom(clsName)) == 0)
316 return;
318 for (i = 0; i < cw->used; i++) {
319 if (cw->table[i] == atom)
320 break;
322 if (i == cw->used) {
323 if (cw->used >= cw->alloc) {
324 cw->alloc += 16;
325 cw->table = DBG_realloc(cw->table, cw->alloc * sizeof(ATOM));
327 cw->table[cw->used++] = atom;
328 DEBUG_InfoClass2(hWnd, clsName);
330 do {
331 if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
332 DEBUG_WalkClassesHelper(child, cw);
333 } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
336 void DEBUG_WalkClasses(void)
338 struct class_walker cw;
340 cw.table = NULL;
341 cw.used = cw.alloc = 0;
342 DEBUG_WalkClassesHelper(GetDesktopWindow(), &cw);
343 DBG_free(cw.table);
346 void DEBUG_DumpQueue(DWORD q)
348 DEBUG_Printf(DBG_CHN_MESG, "No longer doing info queue '0x%08lx'\n", q);
351 void DEBUG_WalkQueues(void)
353 DEBUG_Printf(DBG_CHN_MESG, "No longer walking queues list\n");
356 void DEBUG_InfoWindow(HWND hWnd)
358 char clsName[128];
359 char wndName[128];
360 RECT clientRect;
361 RECT windowRect;
362 int i;
363 WORD w;
365 if (!GetClassName(hWnd, clsName, sizeof(clsName)))
366 strcpy(clsName, "-- Unknown --");
367 if (!GetWindowText(hWnd, wndName, sizeof(wndName)))
368 strcpy(wndName, "-- Empty --");
369 if (!GetClientRect(hWnd, &clientRect))
370 SetRectEmpty(&clientRect);
371 if (!GetWindowRect(hWnd, &windowRect))
372 SetRectEmpty(&windowRect);
374 /* FIXME missing fields: hmemTaskQ, hrgnUpdate, dce, flags, pProp, scroll */
375 DEBUG_Printf(DBG_CHN_MESG,
376 "next=0x%04x child=0x%04x parent=0x%04x owner=0x%04x class='%s'\n"
377 "inst=%08lx active=%04x idmenu=%08lx\n"
378 "style=%08lx exstyle=%08lx wndproc=%08lx text='%s'\n"
379 "client=%d,%d-%d,%d window=%d,%d-%d,%d sysmenu=%04x\n",
380 GetWindow(hWnd, GW_HWNDNEXT),
381 GetWindow(hWnd, GW_CHILD),
382 GetParent(hWnd),
383 GetWindow(hWnd, GW_OWNER),
384 clsName,
385 GetWindowLong(hWnd, GWL_HINSTANCE),
386 GetLastActivePopup(hWnd),
387 GetWindowLong(hWnd, GWL_ID),
388 GetWindowLong(hWnd, GWL_STYLE),
389 GetWindowLong(hWnd, GWL_EXSTYLE),
390 GetWindowLong(hWnd, GWL_WNDPROC),
391 wndName,
392 clientRect.left, clientRect.top, clientRect.right, clientRect.bottom,
393 windowRect.left, windowRect.top, windowRect.right, windowRect.bottom,
394 GetSystemMenu(hWnd, FALSE));
396 if (GetClassLong(hWnd, GCL_CBWNDEXTRA)) {
397 DEBUG_Printf(DBG_CHN_MESG, "Extra bytes:" );
398 for (i = 0; i < GetClassLong(hWnd, GCL_CBWNDEXTRA) / 2; i++) {
399 w = GetWindowWord(hWnd, i * 2);
400 /* FIXME: depends on i386 endian-ity */
401 DEBUG_Printf(DBG_CHN_MESG, " %02x", HIBYTE(w));
402 DEBUG_Printf(DBG_CHN_MESG, " %02x", LOBYTE(w));
404 DEBUG_Printf(DBG_CHN_MESG, "\n");
406 DEBUG_Printf(DBG_CHN_MESG, "\n");
409 void DEBUG_WalkWindows(HWND hWnd, int indent)
411 char clsName[128];
412 char wndName[128];
413 HWND child;
415 if (!IsWindow(hWnd))
416 hWnd = GetDesktopWindow();
418 if (!indent) /* first time around */
419 DEBUG_Printf(DBG_CHN_MESG,
420 "%-16.16s %-17.17s %-8.8s %s\n",
421 "hwnd", "Class Name", " Style", " WndProc Text");
423 do {
424 if (!GetClassName(hWnd, clsName, sizeof(clsName)))
425 strcpy(clsName, "-- Unknown --");
426 if (!GetWindowText(hWnd, wndName, sizeof(wndName)))
427 strcpy(wndName, "-- Empty --");
429 /* FIXME: missing hmemTaskQ */
430 DEBUG_Printf(DBG_CHN_MESG, "%*s%04x%*s", indent, "", hWnd, 13-indent,"");
431 DEBUG_Printf(DBG_CHN_MESG, "%-17.17s %08lx %08lx %.14s\n",
432 clsName, GetWindowLong(hWnd, GWL_STYLE),
433 GetWindowLong(hWnd, GWL_WNDPROC), wndName);
435 if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
436 DEBUG_WalkWindows(child, indent + 1 );
437 } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
440 void DEBUG_WalkProcess(void)
442 HANDLE snap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
443 if (snap != INVALID_HANDLE_VALUE)
445 PROCESSENTRY32 entry;
446 DWORD current = DEBUG_CurrProcess ? DEBUG_CurrProcess->pid : 0;
447 BOOL ok;
449 entry.dwSize = sizeof(entry);
450 ok = Process32First( snap, &entry );
452 DEBUG_Printf(DBG_CHN_MESG, "%-8.8s %-8.8s %-8.8s %s\n",
453 "pid", "threads", "parent", "exe" );
454 while (ok)
456 if (entry.th32ProcessID != GetCurrentProcessId())
457 DEBUG_Printf(DBG_CHN_MESG, "%08lx %8ld %08lx '%s'%s\n",
458 entry.th32ProcessID, entry.cntThreads,
459 entry.th32ParentProcessID, entry.szExeFile,
460 (entry.th32ProcessID == current) ? " <==" : "" );
461 ok = Process32Next( snap, &entry );
463 CloseHandle( snap );
467 void DEBUG_WalkThreads(void)
469 HANDLE snap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
470 if (snap != INVALID_HANDLE_VALUE)
472 THREADENTRY32 entry;
473 DWORD current = DEBUG_CurrThread ? DEBUG_CurrThread->tid : 0;
474 BOOL ok;
476 entry.dwSize = sizeof(entry);
477 ok = Thread32First( snap, &entry );
479 DEBUG_Printf(DBG_CHN_MESG, "%-8.8s %-8.8s %s\n",
480 "tid", "process", "prio" );
481 while (ok)
483 if (entry.th32OwnerProcessID != GetCurrentProcessId())
484 DEBUG_Printf(DBG_CHN_MESG, "%08lx %08lx %4ld%s\n",
485 entry.th32ThreadID, entry.th32OwnerProcessID,
486 entry.tbBasePri, (entry.th32ThreadID == current) ? " <==" : "" );
487 ok = Thread32Next( snap, &entry );
489 CloseHandle( snap );
493 void DEBUG_WalkModref(DWORD p)
495 DEBUG_Printf(DBG_CHN_MESG, "No longer walking module references list\n");
498 void DEBUG_InfoSegments(DWORD start, int length)
500 char flags[3];
501 DWORD i;
502 LDT_ENTRY le;
504 if (length == -1) length = (8192 - start);
506 for (i = start; i < start + length; i++)
508 if (!GetThreadSelectorEntry(DEBUG_CurrThread->handle, (i << 3)|7, &le))
509 continue;
511 if (le.HighWord.Bits.Type & 0x08)
513 flags[0] = (le.HighWord.Bits.Type & 0x2) ? 'r' : '-';
514 flags[1] = '-';
515 flags[2] = 'x';
517 else
519 flags[0] = 'r';
520 flags[1] = (le.HighWord.Bits.Type & 0x2) ? 'w' : '-';
521 flags[2] = '-';
523 DEBUG_Printf(DBG_CHN_MESG,
524 "%04lx: sel=%04lx base=%08x limit=%08x %d-bit %c%c%c\n",
525 i, (i<<3)|7,
526 (le.HighWord.Bits.BaseHi << 24) +
527 (le.HighWord.Bits.BaseMid << 16) + le.BaseLow,
528 ((le.HighWord.Bits.LimitHi << 8) + le.LimitLow) <<
529 (le.HighWord.Bits.Granularity ? 12 : 0),
530 le.HighWord.Bits.Default_Big ? 32 : 16,
531 flags[0], flags[1], flags[2] );
535 void DEBUG_InfoVirtual(void)
537 DEBUG_Printf(DBG_CHN_MESG, "No longer providing virtual mapping information\n");