Release 960309
[wine] / debugger / info.c
1 /*
2  * Wine debugger utility routines
3  *
4  * Copyright 1993 Eric Youngdale
5  * Copyright 1995 Alexandre Julliard
6  */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include "global.h"
11 #include "user.h"
12 #include "class.h"
13 #include "win.h"
14 #include "message.h"
15 #include "spy.h"
16 #include "debugger.h"
17
18 int             iWndIndent = 0;
19
20 extern  char    lpstrSpyMessageIndent[]; /* from misc/spy.c */
21
22 /***********************************************************************
23  *          DEBUG_InitWalk
24  */
25 void DEBUG_InitWalk(void)
26 {
27   fprintf(stderr,"%-24.24s %-6.6s %-17.17s %-8.8s %s\n",
28                  "HWND / WNDPTR","hQueue","Class Name", "Style", "WndProc");
29   lpstrSpyMessageIndent[0]='\0';
30 }
31
32 /***********************************************************************
33  *           DEBUG_WndWalk
34  *
35  */
36 void DEBUG_WndWalk(HWND hStart)
37 {
38   WND*          wndPtr;
39   CLASS*        classPtr;
40   char          className[0x10];
41   int           i;
42
43   if( !hStart )
44        hStart = GetDesktopHwnd();
45
46   wndPtr = WIN_FindWndPtr(hStart);
47
48   if( !wndPtr )
49     { fprintf(stderr, "Invalid window handle: %04x\n", hStart);
50       return; }
51
52   i = strlen(lpstrSpyMessageIndent);
53  
54   /* 0x10 bytes are always reserved at the end of lpstrSpyMessageIndent */
55   sprintf(lpstrSpyMessageIndent + i,"%04x %08x",hStart, (unsigned) wndPtr);
56
57   classPtr = CLASS_FindClassPtr(wndPtr->hClass);
58   if(classPtr)
59      GlobalGetAtomName(classPtr->atomName ,className, 0x10);
60   else
61      strcpy(className,"<BAD>");
62
63   fprintf(stderr,"%-24.24s %-6.4x %-17.17s %08x %04x:%04x\n",
64                  lpstrSpyMessageIndent,
65                  wndPtr->hmemTaskQ, 
66                  className,
67                  (unsigned) wndPtr->dwStyle,
68                  HIWORD(wndPtr->lpfnWndProc),
69                  LOWORD(wndPtr->lpfnWndProc));
70
71   lpstrSpyMessageIndent[i] = '\0';
72
73   if( wndPtr->hwndChild )  
74     {
75       /* walk children */
76
77       hStart = wndPtr->hwndChild;
78       wndPtr = WIN_FindWndPtr(hStart);
79
80       iWndIndent ++;
81       if( iWndIndent < SPY_MAX_INDENTLEVEL - 0x10 )
82         { 
83           lpstrSpyMessageIndent[iWndIndent - 1] = ' ';
84           lpstrSpyMessageIndent[iWndIndent] = '\0';
85         }
86  
87       while( wndPtr )
88           { 
89              DEBUG_WndWalk(hStart);
90              hStart = wndPtr->hwndNext; 
91              wndPtr = WIN_FindWndPtr(hStart);
92           }
93
94       if( hStart )
95           fprintf(stderr, "%s%s"NPFMT"\n", lpstrSpyMessageIndent,
96                                           "<BAD>", hStart);
97
98       if( iWndIndent )
99         {
100           iWndIndent--;
101           if( iWndIndent < SPY_MAX_INDENTLEVEL - 0x10 )
102               lpstrSpyMessageIndent[iWndIndent] = '\0';
103         }
104
105     }
106 }
107
108 /***********************************************************************
109  *           DEBUG_WndDump
110  *
111  */ 
112 void DEBUG_WndDump(HWND hWnd)
113 {
114   WND*          wnd;
115   char*         lpWndText = NULL;
116
117   wnd = WIN_FindWndPtr(hWnd);
118
119   if( !wnd )
120     { fprintf(stderr, "Invalid window handle: %04x\n", hWnd);
121       return; }
122  
123   if( wnd->hText ) 
124       lpWndText = (LPSTR) USER_HEAP_LIN_ADDR( wnd->hText );
125
126   fprintf( stderr, "next: %12.4x\n"
127                    "child:  %10.4x\n"
128                    "parent: %10.4x\n"
129                    "owner:  %10.4x\n"
130                    "hClass: %10.4x\n"
131                    "hInst:  %10.4x\n"
132                    "clientRect: %i,%i - %i,%i\n"
133                    "windowRect: %i,%i - %i,%i\n"
134                    "hRgnUpdate: %6.4x\n"
135                    "hLastPopup: %6.4x\n"
136                    "Style:  %10.8x\n"
137                    "StyleEx: %9.8x\n"
138                    "hDCE:   %10.4x\n"
139                    "hVscroll: %8.4x\n"
140                    "hHscroll: %8.4x\n"
141                    "menuID: %10.4x\n"
142                    "hText:  %10.4x (\"%s\")\n"
143                    "flags:  %10.4x\n",
144                    wnd->hwndNext, wnd->hwndChild,wnd->hwndParent,
145                    wnd->hwndOwner,wnd->hClass,wnd->hInstance,
146                    wnd->rectClient.left, wnd->rectClient.top, 
147                    wnd->rectClient.right, wnd->rectClient.bottom,
148                    wnd->rectWindow.left, wnd->rectWindow.top,
149                    wnd->rectWindow.right, wnd->rectWindow.bottom,
150                    wnd->hrgnUpdate, wnd->hwndLastActive,
151                    (unsigned) wnd->dwStyle, (unsigned) wnd->dwExStyle,
152                    wnd->hdce, wnd->hVScroll, wnd->hHScroll,
153                    wnd->wIDmenu, wnd->hText, (lpWndText)?lpWndText:"NULL",
154                    wnd->flags);
155 }
156
157 /***********************************************************************
158  *           DEBUG_QueueDump
159  *
160  */
161 void DEBUG_QueueDump(HQUEUE hQ)
162 {
163  MESSAGEQUEUE*  pq; 
164
165  if( !hQ || IsBadReadPtr((SEGPTR)MAKELONG( 0, GlobalHandleToSel(hQ)),
166                                                 sizeof(MESSAGEQUEUE)) )
167    {
168      fprintf(stderr, "Invalid queue handle: "NPFMT"\n", hQ);
169      return;
170    }
171
172  pq = (MESSAGEQUEUE*) GlobalLock( hQ );
173
174  fprintf(stderr,"next: %12.4x  Intertask SendMessage:\n"
175                 "hTask: %11.4x  ----------------------\n"
176                 "msgSize: %9.4x  hWnd: %10.4x\n"
177                 "msgCount: %8.4x  msg: %11.4x\n"
178                 "msgNext: %9.4x  wParam: %8.4x\n"
179                 "msgFree: %9.4x  lParam: %8.8x\n"
180                 "qSize: %11.4x  lRet: %10.8x\n"
181                 "wWinVer: %9.4x  ISMH: %10.4x\n"
182                 "paints: %10.4x  hSendTask: %5.4x\n"
183                 "timers: %10.4x  hPrevSend: %5.4x\n"
184                 "wakeBits: %8.4x\n"
185                 "wakeMask: %8.4x\n"
186                 "hCurHook: %8.4x\n",
187                 pq->next, pq->hTask, pq->msgSize, pq->hWnd, 
188                 pq->msgCount, pq->msg, pq->nextMessage, pq->wParam,
189                 pq->nextFreeMessage, (unsigned)pq->lParam, pq->queueSize,
190                 (unsigned)pq->SendMessageReturn, pq->wWinVersion, pq->InSendMessageHandle,
191                 pq->wPaintCount, pq->hSendingTask, pq->wTimerCount,
192                 pq->hPrevSendingTask, pq->status, pq->wakeMask, pq->hCurHook);
193 }
194
195 /***********************************************************************
196  *           DEBUG_Print
197  *
198  * Implementation of the 'print' command.
199  */
200 void DEBUG_Print( const DBG_ADDR *addr, int count, char format )
201 {
202     if (count != 1)
203     {
204         fprintf( stderr, "Count other than 1 is meaningless in 'print' command\n" );
205         return;
206     }
207
208     if (addr->seg && (addr->seg != 0xffffffff))
209     {
210         switch(format)
211         {
212         case 'x':
213             fprintf( stderr, "0x%04lx:", addr->seg );
214             break;
215
216         case 'd':
217             fprintf( stderr, "%ld:", addr->seg );
218             break;
219
220         case 'c':
221             break;  /* No segment to print */
222
223         case 'i':
224         case 's':
225         case 'w':
226         case 'b':
227             break;  /* Meaningless format */
228         }
229     }
230
231     switch(format)
232     {
233     case 'x':
234         if (addr->seg) fprintf( stderr, "0x%04lx\n", addr->off );
235         else fprintf( stderr, "0x%08lx\n", addr->off );
236         break;
237
238     case 'd':
239         fprintf( stderr, "%ld\n", addr->off );
240         break;
241
242     case 'c':
243         fprintf( stderr, "%d = '%c'\n",
244                  (char)(addr->off & 0xff), (char)(addr->off & 0xff) );
245         break;
246
247     case 'i':
248     case 's':
249     case 'w':
250     case 'b':
251         fprintf( stderr, "Format specifier '%c' is meaningless in 'print' command\n", format );
252         break;
253     }
254 }
255
256
257 /***********************************************************************
258  *           DEBUG_PrintAddress
259  *
260  * Print an 16- or 32-bit address, with the nearest symbol if any.
261  */
262 void DEBUG_PrintAddress( const DBG_ADDR *addr, int addrlen )
263 {
264     const char *name = DEBUG_FindNearestSymbol( addr );
265
266     if (addr->seg) fprintf( stderr, "0x%04lx:", addr->seg );
267     if (addrlen == 16) fprintf( stderr, "0x%04lx", addr->off );
268     else fprintf( stderr, "0x%08lx", addr->off );
269     if (name) fprintf( stderr, " (%s)", name );
270 }
271
272
273 /***********************************************************************
274  *           DEBUG_Help
275  *
276  * Implementation of the 'help' command.
277  */
278 void DEBUG_Help(void)
279 {
280     int i = 0;
281     static const char * helptext[] =
282 {
283 "The commands accepted by the Wine debugger are a small subset",
284 "of the commands that gdb would accept.  The commands currently",
285 "are:\n",
286 "  break [*<addr>]                      delete break bpnum",
287 "  disable bpnum                        enable bpnum",
288 "  help                                 quit",
289 "  x <addr>                             cont",
290 "  step                                 next",
291 "  mode [16,32]                         print <expr>",
292 "  set <reg> = <expr>                   set *<addr> = <expr>",
293 "  walk [wnd] <expr>                     dump [wnd, queue] <expr>",
294 "  info [reg,stack,break,segments]      bt",
295 "  symbolfile <filename>                define <identifier> <addr>",
296 "  list <addr> ",
297 "",
298 "The 'x' command accepts repeat counts and formats (including 'i') in the",
299 "same way that gdb does.",
300 "",
301 " The following are examples of legal expressions:",
302 " $eax     $eax+0x3   0x1000   ($eip + 256)  *$eax   *($esp + 3)",
303 " Also, a nm format symbol table can be read from a file using the",
304 " symbolfile command.  Symbols can also be defined individually with",
305 " the define command.",
306 "",
307 NULL
308 };
309
310     while(helptext[i]) fprintf(stderr,"%s\n", helptext[i++]);
311 }
312
313
314
315 /***********************************************************************
316  *           DEBUG_List
317  *
318  * Implementation of the 'list' command.
319  */
320 void DEBUG_List( DBG_ADDR *addr, int count )
321 {
322     static DBG_ADDR lasttime = { 0xffffffff, 0 };
323
324     if (addr == NULL) addr = &lasttime;
325     DBG_FIX_ADDR_SEG( addr, CS_reg(DEBUG_context) );
326     while (count-- > 0)
327     {
328         DEBUG_PrintAddress( addr, dbg_mode );
329         fprintf( stderr, ":  " );
330         if (!DBG_CHECK_READ_PTR( addr, 1 )) return;
331         DEBUG_Disasm( addr );
332         fprintf (stderr, "\n");
333     }
334     lasttime = *addr;
335 }