Cosmetics.
[wine] / debugger / winedbg.c
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2
3 /* Wine internal debugger
4  * Interface to Windows debugger API
5  * Eric Pouech (c) 2000
6  */
7
8 #include <stdlib.h>
9 #include <stdarg.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include "debugger.h"
13
14 #include "ntddk.h"
15 #include "thread.h"
16 #include "wincon.h"
17 #include "wingdi.h"
18 #include "winuser.h"
19
20 #include "winreg.h"
21
22 #ifdef DBG_need_heap
23 HANDLE dbg_heap = 0;
24 #endif
25
26 DBG_PROCESS*    DEBUG_CurrProcess = NULL;
27 DBG_THREAD*     DEBUG_CurrThread = NULL;
28 DWORD           DEBUG_CurrTid;
29 DWORD           DEBUG_CurrPid;
30 CONTEXT         DEBUG_context;
31 BOOL            DEBUG_interactiveP = FALSE;
32 int             curr_frame = 0;
33 static char*    DEBUG_LastCmdLine = NULL;
34
35 static DBG_PROCESS* DEBUG_ProcessList = NULL;
36 DBG_INTVAR DEBUG_IntVars[DBG_IV_LAST];
37
38 void    DEBUG_Output(int chn, const char* buffer, int len)
39 {
40     if (DBG_IVAR(ConChannelMask) & chn)
41         WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buffer, len, NULL, NULL);
42     if (DBG_IVAR(StdChannelMask) & chn)
43         fwrite(buffer, len, 1, stderr);
44 }
45
46 int     DEBUG_Printf(int chn, const char* format, ...)
47 {
48 static    char  buf[4*1024];
49     va_list     valist;
50     int         len;
51
52     va_start(valist, format);
53     len = vsnprintf(buf, sizeof(buf), format, valist);
54     va_end(valist);
55
56     if (len <= -1) {
57         len = sizeof(buf) - 1;
58         buf[len] = 0;
59         buf[len - 1] = buf[len - 2] = buf[len - 3] = '.';
60     }
61     DEBUG_Output(chn, buf, len);
62     return len;
63 }
64
65 static  BOOL DEBUG_IntVarsRW(int read)
66 {
67     HKEY        hkey;
68     DWORD       type = REG_DWORD;
69     DWORD       val;
70     DWORD       count = sizeof(val);
71     int         i;
72     DBG_INTVAR* div = DEBUG_IntVars;
73
74     if (read) {
75 /* initializes internal vars table */
76 #define  INTERNAL_VAR(_var,_val,_ref,_typ)                      \
77         div->val = _val; div->name = #_var; div->pval = _ref;   \
78         div->type = _typ; div++;
79 #include "intvar.h"
80 #undef   INTERNAL_VAR
81     }
82
83     if (RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine\\WineDbg", &hkey)) {
84         /* since the IVars are not yet setup, DEBUG_Printf doesn't work,
85          * so don't use it */
86         fprintf(stderr, "Cannot create WineDbg key in registry\n");
87         return FALSE;
88     }
89
90     for (i = 0; i < DBG_IV_LAST; i++) {
91         if (read) {
92             if (!DEBUG_IntVars[i].pval) {
93                 if (!RegQueryValueEx(hkey, DEBUG_IntVars[i].name, 0, 
94                                      &type, (LPSTR)&val, &count))
95                     DEBUG_IntVars[i].val = val;
96                 DEBUG_IntVars[i].pval = &DEBUG_IntVars[i].val;
97             } else {
98                 *DEBUG_IntVars[i].pval = 0;
99             }
100         } else {
101             /* FIXME: type should be infered from basic type -if any- of intvar */
102             if (DEBUG_IntVars[i].pval == &DEBUG_IntVars[i].val)
103                 RegSetValueEx(hkey, DEBUG_IntVars[i].name, 0, 
104                               type, (LPCVOID)DEBUG_IntVars[i].pval, count);
105         }
106     }
107     RegCloseKey(hkey);
108     return TRUE;
109 }
110
111 DBG_INTVAR*     DEBUG_GetIntVar(const char* name)
112 {
113     int         i;
114
115     for (i = 0; i < DBG_IV_LAST; i++) {
116         if (!strcmp(DEBUG_IntVars[i].name, name))
117             return &DEBUG_IntVars[i];
118     }
119     return NULL;
120 }
121                        
122 static WINE_EXCEPTION_FILTER(wine_dbg)
123 {
124     DEBUG_Printf(DBG_CHN_MESG, "\nwine_dbg: Exception (%lx) inside debugger, continuing...\n", GetExceptionCode());
125     DEBUG_ExternalDebugger();
126     return EXCEPTION_EXECUTE_HANDLER;
127 }
128
129 DBG_PROCESS*    DEBUG_GetProcess(DWORD pid)
130 {
131     DBG_PROCESS*        p;
132     
133     for (p = DEBUG_ProcessList; p; p = p->next)
134         if (p->pid == pid) break;
135     return p;
136 }
137
138 static  DBG_PROCESS*    DEBUG_AddProcess(DWORD pid, HANDLE h, const char* imageName)
139 {
140     DBG_PROCESS*        p = DBG_alloc(sizeof(DBG_PROCESS));
141     if (!p)
142         return NULL;
143     p->handle = h;
144     p->pid = pid;
145     p->imageName = imageName ? DBG_strdup(imageName) : NULL;
146     p->threads = NULL;
147     p->num_threads = 0;
148     p->continue_on_first_exception = FALSE;
149     p->modules = NULL;
150     p->num_modules = 0;
151     p->next_index = 0;
152     p->dbg_hdr_addr = 0;
153     p->delayed_bp = NULL;
154     p->num_delayed_bp = 0;
155
156     p->next = DEBUG_ProcessList;
157     p->prev = NULL;
158     if (DEBUG_ProcessList) DEBUG_ProcessList->prev = p;
159     DEBUG_ProcessList = p;
160     return p;
161 }
162
163 static  void                    DEBUG_DelThread(DBG_THREAD* p);
164
165 static  void                    DEBUG_DelProcess(DBG_PROCESS* p)
166 {
167     int i;
168
169     if (p->threads != NULL) {
170         DEBUG_Printf(DBG_CHN_ERR, "Shouldn't happen\n");
171         while (p->threads) DEBUG_DelThread(p->threads);
172     }
173     for (i = 0; i < p->num_delayed_bp; i++) {
174         DBG_free(p->delayed_bp[i].name);
175     }
176     DBG_free(p->delayed_bp);
177     if (p->prev) p->prev->next = p->next;
178     if (p->next) p->next->prev = p->prev;
179     if (p == DEBUG_ProcessList) DEBUG_ProcessList = p->next;
180     if (p == DEBUG_CurrProcess) DEBUG_CurrProcess = NULL;
181     DBG_free((char*)p->imageName);
182     DBG_free(p);
183 }
184
185 static  void                    DEBUG_InitCurrProcess(void)
186 {
187 }
188
189 static BOOL DEBUG_ProcessGetString(char* buffer, int size, HANDLE hp, LPSTR addr)
190 {
191     DWORD sz;
192     *(WCHAR*)buffer = 0;
193     return (addr && ReadProcessMemory(hp, addr, buffer, size, &sz));
194 }
195
196 static BOOL DEBUG_ProcessGetStringIndirect(char* buffer, int size, HANDLE hp, LPVOID addr)
197 {
198     LPVOID      ad;
199     DWORD       sz;
200     
201     if (   addr 
202         && ReadProcessMemory(hp, addr, &ad, sizeof(ad), &sz) 
203         && sz == sizeof(ad) 
204         && ad 
205         && ReadProcessMemory(hp, ad, buffer, size, &sz))
206         return TRUE;
207     *(WCHAR*)buffer = 0;
208     return FALSE;
209 }
210
211 DBG_THREAD*     DEBUG_GetThread(DBG_PROCESS* p, DWORD tid)
212 {
213     DBG_THREAD* t;
214     
215     for (t = p->threads; t; t = t->next)
216         if (t->tid == tid) break;
217     return t;
218 }
219
220 static  DBG_THREAD*     DEBUG_AddThread(DBG_PROCESS* p, DWORD tid, 
221                                         HANDLE h, LPVOID start, LPVOID teb)
222 {
223     DBG_THREAD* t = DBG_alloc(sizeof(DBG_THREAD));
224     if (!t)
225         return NULL;
226     
227     t->handle = h;
228     t->tid = tid;
229     t->start = start;
230     t->teb = teb;
231     t->process = p;
232     t->wait_for_first_exception = 0;
233     t->dbg_exec_mode = EXEC_CONT;
234     t->dbg_exec_count = 0;
235     sprintf(t->name, "%08lx", tid);
236
237     p->num_threads++;
238     t->next = p->threads;
239     t->prev = NULL;
240     if (p->threads) p->threads->prev = t;
241     p->threads = t;
242
243     return t;
244 }
245
246 static  void                    DEBUG_InitCurrThread(void)
247 {
248     if (DEBUG_CurrThread->start) {
249         if (DEBUG_CurrThread->process->num_threads == 1 || 
250             DBG_IVAR(BreakAllThreadsStartup)) {
251             DBG_VALUE   value;
252             
253             DEBUG_SetBreakpoints(FALSE);
254             value.type = NULL;
255             value.cookie = DV_TARGET;
256             value.addr.seg = 0;
257             value.addr.off = (DWORD)DEBUG_CurrThread->start;
258             DEBUG_AddBreakpoint(&value, NULL);
259             DEBUG_SetBreakpoints(TRUE);
260         }
261     } else {
262         DEBUG_CurrThread->wait_for_first_exception = 1;
263     }
264 }
265
266 static  void                    DEBUG_DelThread(DBG_THREAD* t)
267 {
268     if (t->prev) t->prev->next = t->next;
269     if (t->next) t->next->prev = t->prev;
270     if (t == t->process->threads) t->process->threads = t->next;
271     t->process->num_threads--;
272     if (t == DEBUG_CurrThread) DEBUG_CurrThread = NULL;
273     DBG_free(t);
274 }
275
276 BOOL                            DEBUG_Attach(DWORD pid, BOOL cofe)
277 {
278     if (!(DEBUG_CurrProcess = DEBUG_AddProcess(pid, 0, NULL))) return FALSE;
279
280     if (!DebugActiveProcess(pid)) {
281         DEBUG_Printf(DBG_CHN_MESG, "Can't attach process %lx: error %ld\n", pid, GetLastError());
282         DEBUG_DelProcess(DEBUG_CurrProcess);
283         DEBUG_CurrProcess = NULL;
284         return FALSE;
285     }
286     DEBUG_CurrProcess->continue_on_first_exception = cofe;
287     return TRUE;
288 }
289
290 static  BOOL    DEBUG_ExceptionProlog(BOOL is_debug, BOOL force, DWORD code)
291 {
292     DBG_ADDR    addr;
293     int         newmode;
294
295     DEBUG_GetCurrentAddress(&addr);
296     DEBUG_SuspendExecution();
297
298     if (!is_debug) {
299         if (!addr.seg)
300             DEBUG_Printf(DBG_CHN_MESG, " in 32-bit code (0x%08lx)", addr.off);
301         else
302             switch(DEBUG_GetSelectorType(addr.seg))
303             {
304             case MODE_32:
305                 DEBUG_Printf(DBG_CHN_MESG, " in 32-bit code (%04lx:%08lx)", addr.seg, addr.off);
306                 break;
307             case MODE_16:
308                 DEBUG_Printf(DBG_CHN_MESG, " in 16-bit code (%04lx:%04lx)", addr.seg, addr.off);
309                 break;
310             case MODE_VM86:
311                 DEBUG_Printf(DBG_CHN_MESG, " in vm86 code (%04lx:%04lx)", addr.seg, addr.off);
312                 break;
313             case MODE_INVALID:
314                 DEBUG_Printf(DBG_CHN_MESG, " bad CS (%lx)", addr.seg);
315                 break;
316         }
317         DEBUG_Printf(DBG_CHN_MESG, ".\n");
318     }
319  
320     DEBUG_LoadEntryPoints("Loading new modules symbols:\n");
321
322     if (!force && is_debug && 
323         DEBUG_ShouldContinue(&addr,
324                              code, 
325                              DEBUG_CurrThread->dbg_exec_mode, 
326                              &DEBUG_CurrThread->dbg_exec_count))
327         return FALSE;
328
329     if ((newmode = DEBUG_GetSelectorType(addr.seg)) == MODE_INVALID) newmode = MODE_32;
330     if (newmode != DEBUG_CurrThread->dbg_mode)
331     {
332         static const char * const names[] = { "???", "16-bit", "32-bit", "vm86" };
333         DEBUG_Printf(DBG_CHN_MESG,"In %s mode.\n", names[newmode] );
334         DEBUG_CurrThread->dbg_mode = newmode;
335     }
336
337     DEBUG_DoDisplay();
338
339     if (is_debug || force) {
340         /*
341          * Do a quiet backtrace so that we have an idea of what the situation
342          * is WRT the source files.
343          */
344         DEBUG_BackTrace(DEBUG_CurrTid, FALSE);
345     } else {
346         /* This is a real crash, dump some info */
347         DEBUG_InfoRegisters();
348         DEBUG_InfoStack();
349 #ifdef __i386__
350         if (DEBUG_CurrThread->dbg_mode == MODE_16) {
351             DEBUG_InfoSegments(DEBUG_context.SegDs >> 3, 1);
352             if (DEBUG_context.SegEs != DEBUG_context.SegDs)
353                 DEBUG_InfoSegments(DEBUG_context.SegEs >> 3, 1);
354         }
355         DEBUG_InfoSegments(DEBUG_context.SegFs >> 3, 1);
356 #endif
357         DEBUG_BackTrace(DEBUG_CurrTid, TRUE);
358     }
359
360     if (!is_debug ||
361         (DEBUG_CurrThread->dbg_exec_mode == EXEC_STEPI_OVER) ||
362         (DEBUG_CurrThread->dbg_exec_mode == EXEC_STEPI_INSTR)) {
363
364         struct list_id list;
365
366         /* Show where we crashed */
367         curr_frame = 0;
368         DEBUG_DisassembleInstruction(&addr);
369
370         /* resets list internal arguments so we can look at source code when needed */
371         DEBUG_FindNearestSymbol(&addr, TRUE, NULL, 0, &list); 
372         if (list.sourcefile) DEBUG_List(&list, NULL, 0);
373     }
374     return TRUE;
375 }
376
377 static  DWORD   DEBUG_ExceptionEpilog(void)
378 {
379     DEBUG_CurrThread->dbg_exec_mode = DEBUG_RestartExecution(DEBUG_CurrThread->dbg_exec_mode, 
380                                                              DEBUG_CurrThread->dbg_exec_count);
381     /*
382      * This will have gotten absorbed into the breakpoint info
383      * if it was used.  Otherwise it would have been ignored.
384      * In any case, we don't mess with it any more.
385      */
386     if (DEBUG_CurrThread->dbg_exec_mode == EXEC_CONT || DEBUG_CurrThread->dbg_exec_mode == EXEC_PASS)
387         DEBUG_CurrThread->dbg_exec_count = 0;
388     
389     return (DEBUG_CurrThread->dbg_exec_mode == EXEC_PASS) ? DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE;
390 }
391
392 static  BOOL    DEBUG_HandleException(EXCEPTION_RECORD *rec, BOOL first_chance, BOOL force, LPDWORD cont)
393 {
394     BOOL             is_debug = FALSE;
395     BOOL             ret = TRUE;
396     THREADNAME_INFO *pThreadName;
397     DBG_THREAD      *pThread;
398
399
400     *cont = DBG_CONTINUE;
401
402     switch (rec->ExceptionCode)
403     {
404     case EXCEPTION_BREAKPOINT:
405     case EXCEPTION_SINGLE_STEP:
406         is_debug = TRUE;
407         break;
408     case EXCEPTION_NAME_THREAD:
409         pThreadName = (THREADNAME_INFO*)(rec->ExceptionInformation);
410         if (pThreadName->dwThreadID == -1)
411             pThread = DEBUG_CurrThread;
412         else
413             pThread = DEBUG_GetThread(DEBUG_CurrProcess, pThreadName->dwThreadID);
414
415         if (ReadProcessMemory(DEBUG_CurrThread->process->handle, pThreadName->szName,
416                               pThread->name, 9, NULL))
417             DEBUG_Printf (DBG_CHN_MESG,
418                           "Thread ID=0x%lx renamed using MS VC6 extension (name==\"%s\")\n",
419                           pThread->tid, pThread->name);
420         return TRUE;
421     }
422
423     if (first_chance && !is_debug && !force && !DBG_IVAR(BreakOnFirstChance))
424     {
425         /* pass exception to program except for debug exceptions */
426         *cont = is_debug ? DBG_CONTINUE : DBG_EXCEPTION_NOT_HANDLED;
427         return TRUE;
428     }
429
430     if (!is_debug)
431     {
432         /* print some infos */
433         DEBUG_Printf(DBG_CHN_MESG, "%s: ",
434                       first_chance ? "First chance exception" : "Unhandled exception");
435         switch (rec->ExceptionCode)
436         {
437         case EXCEPTION_INT_DIVIDE_BY_ZERO:
438             DEBUG_Printf(DBG_CHN_MESG, "divide by zero");
439             break;
440         case EXCEPTION_INT_OVERFLOW:
441             DEBUG_Printf(DBG_CHN_MESG, "overflow");
442             break;
443         case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
444             DEBUG_Printf(DBG_CHN_MESG, "array bounds ");
445             break;
446         case EXCEPTION_ILLEGAL_INSTRUCTION:
447             DEBUG_Printf(DBG_CHN_MESG, "illegal instruction");
448             break;
449         case EXCEPTION_STACK_OVERFLOW:
450             DEBUG_Printf(DBG_CHN_MESG, "stack overflow");
451             break;
452         case EXCEPTION_PRIV_INSTRUCTION:
453             DEBUG_Printf(DBG_CHN_MESG, "privileged instruction");
454             break;
455         case EXCEPTION_ACCESS_VIOLATION:
456             if (rec->NumberParameters == 2)
457                 DEBUG_Printf(DBG_CHN_MESG, "page fault on %s access to 0x%08lx", 
458                               rec->ExceptionInformation[0] ? "write" : "read",
459                               rec->ExceptionInformation[1]);
460             else
461                 DEBUG_Printf(DBG_CHN_MESG, "page fault");
462             break;
463         case EXCEPTION_DATATYPE_MISALIGNMENT:
464             DEBUG_Printf(DBG_CHN_MESG, "Alignment");
465             break;
466         case CONTROL_C_EXIT:
467             DEBUG_Printf(DBG_CHN_MESG, "^C");
468             break;
469         case EXCEPTION_CRITICAL_SECTION_WAIT:
470             {
471                 DBG_ADDR        addr;
472
473                 addr.seg = 0;
474                 addr.off = rec->ExceptionInformation[0];
475
476                 DEBUG_Printf(DBG_CHN_MESG, "wait failed on critical section ");
477                 DEBUG_PrintAddress(&addr, DEBUG_CurrThread->dbg_mode, FALSE);
478             }
479             if (!DBG_IVAR(BreakOnCritSectTimeOut))
480             {
481                 DEBUG_Printf(DBG_CHN_MESG, "\n");
482                 return TRUE;
483             }
484             break;
485         case EXCEPTION_WINE_STUB:
486             {
487                 char dll[32], name[64];
488                 DEBUG_ProcessGetString( dll, sizeof(dll), DEBUG_CurrThread->process->handle,
489                                         (char *)rec->ExceptionInformation[0] );
490                 DEBUG_ProcessGetString( name, sizeof(name), DEBUG_CurrThread->process->handle,
491                                         (char *)rec->ExceptionInformation[1] );
492                 DEBUG_Printf(DBG_CHN_MESG, "unimplemented function %s.%s called", dll, name );
493             }
494             break;
495         case EXCEPTION_VM86_INTx:
496             DEBUG_Printf(DBG_CHN_MESG, "interrupt %02lx in vm86 mode",
497                          rec->ExceptionInformation[0]);
498             break;
499         case EXCEPTION_VM86_STI:
500             DEBUG_Printf(DBG_CHN_MESG, "sti in vm86 mode");
501             break;
502         case EXCEPTION_VM86_PICRETURN:
503             DEBUG_Printf(DBG_CHN_MESG, "PIC return in vm86 mode");
504             break;
505         default:
506             DEBUG_Printf(DBG_CHN_MESG, "%08lx", rec->ExceptionCode);
507             break;
508         }
509     }
510
511 #if 0
512     DEBUG_Printf(DBG_CHN_TRACE, 
513                  "Entering debugger     PC=%lx EFL=%08lx mode=%d count=%d\n",
514 #ifdef __i386__
515                  DEBUG_context.Eip, DEBUG_context.EFlags, 
516 #else
517                  0L, 0L,
518 #endif
519                  DEBUG_CurrThread->dbg_exec_mode, DEBUG_CurrThread->dbg_exec_count);
520 #endif
521
522     if (DEBUG_ExceptionProlog(is_debug, force, rec->ExceptionCode)) {
523         DEBUG_interactiveP = TRUE;
524         while ((ret = DEBUG_Parser())) {
525             if (DEBUG_ValidateRegisters()) {
526                 if (DEBUG_CurrThread->dbg_exec_mode != EXEC_PASS || first_chance)
527                     break;
528                 DEBUG_Printf(DBG_CHN_MESG, "Cannot pass on last chance exception. You must use cont\n");
529             }
530         }
531         DEBUG_interactiveP = FALSE;
532     }
533     *cont = DEBUG_ExceptionEpilog();
534
535 #if 0
536     DEBUG_Printf(DBG_CHN_TRACE, 
537                  "Exiting debugger      PC=%lx EFL=%08lx mode=%d count=%d\n",
538 #ifdef __i386__
539                  DEBUG_context.Eip, DEBUG_context.EFlags, 
540 #else
541                  0L, 0L,
542 #endif
543                  DEBUG_CurrThread->dbg_exec_mode, DEBUG_CurrThread->dbg_exec_count);
544 #endif
545
546     return ret;
547 }
548
549 static  BOOL    DEBUG_HandleDebugEvent(DEBUG_EVENT* de, LPDWORD cont)
550 {
551     char                buffer[256];
552     BOOL                ret;
553
554     DEBUG_CurrPid = de->dwProcessId;
555     DEBUG_CurrTid = de->dwThreadId;
556
557     __TRY {
558         ret = TRUE;
559         *cont = 0L;
560         
561         if ((DEBUG_CurrProcess = DEBUG_GetProcess(de->dwProcessId)) != NULL)
562             DEBUG_CurrThread = DEBUG_GetThread(DEBUG_CurrProcess, de->dwThreadId);
563         else 
564             DEBUG_CurrThread = NULL;
565         
566         switch (de->dwDebugEventCode) {
567         case EXCEPTION_DEBUG_EVENT:
568             if (!DEBUG_CurrThread) {
569                 DEBUG_Printf(DBG_CHN_ERR, "%08lx:%08lx: not a registered process or thread (perhaps a 16 bit one ?)\n",
570                              de->dwProcessId, de->dwThreadId);
571                 break;
572             }
573             
574             DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: exception code=%08lx\n", 
575                          de->dwProcessId, de->dwThreadId, 
576                          de->u.Exception.ExceptionRecord.ExceptionCode);
577
578             if (DEBUG_CurrProcess->continue_on_first_exception) {
579                 DEBUG_CurrProcess->continue_on_first_exception = FALSE;
580                 if (!DBG_IVAR(BreakOnAttach)) {
581                     *cont = DBG_CONTINUE;
582                     break;
583                 }
584             }
585
586             DEBUG_context.ContextFlags =  CONTEXT_CONTROL
587                                         | CONTEXT_INTEGER
588 #ifdef CONTEXT_SEGMENTS
589                                         | CONTEXT_SEGMENTS
590 #endif
591 #ifdef CONTEXT_DEBUG_REGISTERS
592                                         | CONTEXT_DEBUG_REGISTERS
593 #endif
594                                         ;
595
596             if (!GetThreadContext(DEBUG_CurrThread->handle, &DEBUG_context)) {
597                 DEBUG_Printf(DBG_CHN_WARN, "Can't get thread's context\n");
598                 break;
599             }
600             
601             ret = DEBUG_HandleException(&de->u.Exception.ExceptionRecord, 
602                                         de->u.Exception.dwFirstChance, 
603                                         DEBUG_CurrThread->wait_for_first_exception,
604                                         cont);
605             if (DEBUG_CurrThread) {
606                 DEBUG_CurrThread->wait_for_first_exception = 0;
607                 SetThreadContext(DEBUG_CurrThread->handle, &DEBUG_context);
608             }
609             break;
610             
611         case CREATE_THREAD_DEBUG_EVENT:
612             DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: create thread D @%08lx\n", de->dwProcessId, de->dwThreadId, 
613                          (unsigned long)(LPVOID)de->u.CreateThread.lpStartAddress);
614             
615             if (DEBUG_CurrProcess == NULL) {
616                 DEBUG_Printf(DBG_CHN_ERR, "Unknown process\n");
617                 break;
618             }
619             if (DEBUG_GetThread(DEBUG_CurrProcess, de->dwThreadId) != NULL) {
620                 DEBUG_Printf(DBG_CHN_TRACE, "Thread already listed, skipping\n");
621                 break;
622             }
623             
624             DEBUG_CurrThread = DEBUG_AddThread(DEBUG_CurrProcess, 
625                                                de->dwThreadId, 
626                                                de->u.CreateThread.hThread, 
627                                                de->u.CreateThread.lpStartAddress, 
628                                                de->u.CreateThread.lpThreadLocalBase);
629             if (!DEBUG_CurrThread) {
630                 DEBUG_Printf(DBG_CHN_ERR, "Couldn't create thread\n");
631                 break;
632             }
633             DEBUG_InitCurrThread();
634             break;
635             
636         case CREATE_PROCESS_DEBUG_EVENT:
637             DEBUG_ProcessGetStringIndirect(buffer, sizeof(buffer), 
638                                            de->u.CreateProcessInfo.hProcess, 
639                                            de->u.CreateProcessInfo.lpImageName);
640
641             /* FIXME unicode ? de->u.CreateProcessInfo.fUnicode */
642             DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: create process '%s'/%p @%08lx (%ld<%ld>)\n", 
643                          de->dwProcessId, de->dwThreadId, 
644                          buffer, de->u.CreateProcessInfo.lpImageName,
645                          (unsigned long)(LPVOID)de->u.CreateProcessInfo.lpStartAddress,
646                          de->u.CreateProcessInfo.dwDebugInfoFileOffset,
647                          de->u.CreateProcessInfo.nDebugInfoSize);
648             
649             if ((DEBUG_CurrProcess = DEBUG_GetProcess(de->dwProcessId)) != NULL) {
650                 if (DEBUG_CurrProcess->handle) {
651                     DEBUG_Printf(DBG_CHN_ERR, "Skipping already defined process\n");
652                     break;
653                 }
654                 DEBUG_CurrProcess->handle = de->u.CreateProcessInfo.hProcess;
655                 if (DEBUG_CurrProcess->imageName == NULL)
656                     DEBUG_CurrProcess->imageName = DBG_strdup(buffer[0] ? buffer : "<Debugged Process>");
657
658             } else {
659                 DEBUG_CurrProcess = DEBUG_AddProcess(de->dwProcessId,
660                                                      de->u.CreateProcessInfo.hProcess,
661                                                      buffer[0] ? buffer : "<Debugged Process>");
662                 if (DEBUG_CurrProcess == NULL) {
663                     DEBUG_Printf(DBG_CHN_ERR, "Unknown process\n");
664                     break;
665                 }
666             }
667             
668             DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: create thread I @%08lx\n", 
669                          de->dwProcessId, de->dwThreadId, 
670                          (unsigned long)(LPVOID)de->u.CreateProcessInfo.lpStartAddress);
671             
672             DEBUG_CurrThread = DEBUG_AddThread(DEBUG_CurrProcess,       
673                                                de->dwThreadId, 
674                                                de->u.CreateProcessInfo.hThread, 
675                                                de->u.CreateProcessInfo.lpStartAddress, 
676                                                de->u.CreateProcessInfo.lpThreadLocalBase);
677             if (!DEBUG_CurrThread) {
678                 DEBUG_Printf(DBG_CHN_ERR, "Couldn't create thread\n");
679                 break;
680             }
681             
682             DEBUG_InitCurrProcess();
683             DEBUG_InitCurrThread();
684
685             DEBUG_LoadModule32(DEBUG_CurrProcess->imageName, de->u.CreateProcessInfo.hFile, 
686                                (DWORD)de->u.CreateProcessInfo.lpBaseOfImage);
687
688             if (buffer[0])  /* we got a process name */
689             {
690                 DWORD type;
691                 if (!GetBinaryTypeA( buffer, &type ))
692                 {
693                     /* not a Windows binary, assume it's a Unix executable then */
694                     char unixname[MAX_PATH];
695                     /* HACK!! should fix DEBUG_ReadExecutableDbgInfo to accept DOS filenames */
696                     if (wine_get_unix_file_name( buffer, unixname, sizeof(unixname) ))
697                     {
698                         DEBUG_ReadExecutableDbgInfo( unixname );
699                         break;
700                     }
701                 }
702             }
703             /* if it is a Windows binary, or an invalid or missing file name,
704              * we use wine itself as the main executable */
705             DEBUG_ReadExecutableDbgInfo( "wine" );
706             break;
707             
708         case EXIT_THREAD_DEBUG_EVENT:
709             DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: exit thread (%ld)\n", 
710                          de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
711             
712             if (DEBUG_CurrThread == NULL) {
713                 DEBUG_Printf(DBG_CHN_ERR, "Unknown thread\n");
714                 break;
715             }
716             /* FIXME: remove break point set on thread startup */
717             DEBUG_DelThread(DEBUG_CurrThread);
718             break;
719             
720         case EXIT_PROCESS_DEBUG_EVENT:
721             DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: exit process (%ld)\n", 
722                          de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
723             
724             if (DEBUG_CurrProcess == NULL) {
725                 DEBUG_Printf(DBG_CHN_ERR, "Unknown process\n");
726                 break;
727             }
728             /* just in case */
729             DEBUG_SetBreakpoints(FALSE);
730             /* kill last thread */
731             DEBUG_DelThread(DEBUG_CurrProcess->threads);
732             DEBUG_DelProcess(DEBUG_CurrProcess);
733
734             DEBUG_Printf(DBG_CHN_MESG, "Process of pid=%08lx has terminated\n", DEBUG_CurrPid);
735             break;
736             
737         case LOAD_DLL_DEBUG_EVENT:
738             if (DEBUG_CurrThread == NULL) {
739                 DEBUG_Printf(DBG_CHN_ERR, "Unknown thread\n");
740                 break;
741             }
742             DEBUG_ProcessGetStringIndirect(buffer, sizeof(buffer), 
743                                            DEBUG_CurrThread->process->handle, 
744                                            de->u.LoadDll.lpImageName);
745             
746             /* FIXME unicode: de->u.LoadDll.fUnicode */
747             DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: loads DLL %s @%08lx (%ld<%ld>)\n", 
748                          de->dwProcessId, de->dwThreadId, 
749                          buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll,
750                          de->u.LoadDll.dwDebugInfoFileOffset,
751                          de->u.LoadDll.nDebugInfoSize);
752             _strupr(buffer);
753             DEBUG_LoadModule32(buffer, de->u.LoadDll.hFile, (DWORD)de->u.LoadDll.lpBaseOfDll);
754             DEBUG_CheckDelayedBP();
755             if (DBG_IVAR(BreakOnDllLoad)) {
756                 DEBUG_Printf(DBG_CHN_MESG, "Stopping on DLL %s loading at %08lx\n", 
757                              buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll);
758                 ret = DEBUG_Parser();
759             }
760             break;
761             
762         case UNLOAD_DLL_DEBUG_EVENT:
763             DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: unload DLL @%08lx\n", de->dwProcessId, de->dwThreadId, 
764                          (unsigned long)de->u.UnloadDll.lpBaseOfDll);
765             break;
766             
767         case OUTPUT_DEBUG_STRING_EVENT:
768             if (DEBUG_CurrThread == NULL) {
769                 DEBUG_Printf(DBG_CHN_ERR, "Unknown thread\n");
770                 break;
771             }
772             
773             DEBUG_ProcessGetString(buffer, sizeof(buffer), 
774                                    DEBUG_CurrThread->process->handle, 
775                                    de->u.DebugString.lpDebugStringData);
776             
777             /* fixme unicode de->u.DebugString.fUnicode ? */
778             DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: output debug string (%s)\n", 
779                          de->dwProcessId, de->dwThreadId, buffer);
780             break;
781             
782         case RIP_EVENT:
783             DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: rip error=%ld type=%ld\n", 
784                          de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError, 
785                          de->u.RipInfo.dwType);
786             break;
787             
788         default:
789             DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: unknown event (%ld)\n", 
790                          de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
791         }
792         
793     } __EXCEPT(wine_dbg) {
794         *cont = 0;
795         ret = TRUE;
796     }
797     __ENDTRY;
798     return ret;
799 }
800
801 static  DWORD   DEBUG_MainLoop(void)
802 {
803     DEBUG_EVENT         de;
804     DWORD               cont;
805     BOOL                ret;
806
807     DEBUG_Printf(DBG_CHN_MESG, " on pid %lx\n", DEBUG_CurrPid);
808     
809     for (ret = TRUE; ret; ) {
810         /* wait until we get at least one loaded process */
811         while (!DEBUG_ProcessList && (ret = DEBUG_Parser()));
812         if (!ret) break;
813
814         while (ret && DEBUG_ProcessList && WaitForDebugEvent(&de, INFINITE)) {
815             ret = DEBUG_HandleDebugEvent(&de, &cont);
816             ContinueDebugEvent(de.dwProcessId, de.dwThreadId, cont);
817         }
818     };
819     
820     DEBUG_Printf(DBG_CHN_MESG, "WineDbg terminated on pid %lx\n", DEBUG_CurrPid);
821
822     return 0;
823 }
824
825 static  BOOL    DEBUG_Start(LPSTR cmdLine)
826 {
827     PROCESS_INFORMATION info;
828     STARTUPINFOA        startup;
829
830     memset(&startup, 0, sizeof(startup));
831     startup.cb = sizeof(startup);
832     startup.dwFlags = STARTF_USESHOWWINDOW;
833     startup.wShowWindow = SW_SHOWNORMAL;
834     
835     if (!CreateProcess(NULL, cmdLine, NULL, NULL, 
836                        FALSE, DEBUG_PROCESS, NULL, NULL, &startup, &info)) {
837         DEBUG_Printf(DBG_CHN_MESG, "Couldn't start process '%s'\n", cmdLine);
838         return FALSE;
839     }
840     DEBUG_CurrPid = info.dwProcessId;
841     if (!(DEBUG_CurrProcess = DEBUG_AddProcess(DEBUG_CurrPid, 0, NULL))) return FALSE;
842
843     return TRUE;
844 }
845
846 void    DEBUG_Run(const char* args)
847 {
848     DBG_MODULE* wmod = DEBUG_GetProcessMainModule(DEBUG_CurrProcess);
849     const char* pgm = (wmod) ? wmod->module_name : "none";
850
851     if (args) {
852         DEBUG_Printf(DBG_CHN_MESG, "Run (%s) with '%s'\n", pgm, args);
853     } else {
854         if (!DEBUG_LastCmdLine) {
855             DEBUG_Printf(DBG_CHN_MESG, "Cannot find previously used command line.\n");
856             return;
857         }
858         DEBUG_Start(DEBUG_LastCmdLine);
859     }
860 }
861
862 int DEBUG_main(int argc, char** argv)
863 {
864     DWORD       retv = 0;
865
866 #ifdef DBG_need_heap
867     /* Initialize the debugger heap. */
868     dbg_heap = HeapCreate(HEAP_NO_SERIALIZE, 0x1000, 0x8000000); /* 128MB */
869 #endif
870     
871     /* Initialize the type handling stuff. */
872     DEBUG_InitTypes();
873     DEBUG_InitCVDataTypes();    
874
875     /* Initialize internal vars (types must have been initialized before) */
876     if (!DEBUG_IntVarsRW(TRUE)) return -1;
877
878     /* keep it as a guiexe for now, so that Wine won't touch the Unix stdin, 
879      * stdout and stderr streams
880      */
881     if (DBG_IVAR(UseXTerm)) {
882         COORD           pos;
883         
884         /* This is a hack: it forces creation of an xterm, not done by default */
885         pos.X = 0; pos.Y = 1;
886         SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
887     }
888
889     DEBUG_Printf(DBG_CHN_MESG, "WineDbg starting... ");
890         
891     if (argc == 3) {
892         HANDLE  hEvent;
893         DWORD   pid;
894
895         if ((pid = atoi(argv[1])) != 0 && (hEvent = (HANDLE)atoi(argv[2])) != 0) {
896             if (!DEBUG_Attach(pid, TRUE)) {
897                 /* don't care about result */
898                 SetEvent(hEvent);
899                 goto leave;
900             }
901             if (!SetEvent(hEvent)) {
902                 DEBUG_Printf(DBG_CHN_ERR, "Invalid event handle: %p\n", hEvent);
903                 goto leave;
904             }
905             CloseHandle(hEvent);
906             DEBUG_CurrPid = pid;
907         }
908     }
909         
910     if (DEBUG_CurrPid == 0 && argc > 1) {
911         int     i, len;
912         LPSTR   cmdLine;
913                 
914         if (!(cmdLine = DBG_alloc(len = 1))) goto oom_leave;
915         cmdLine[0] = '\0';
916
917         for (i = 1; i < argc; i++) {
918             len += strlen(argv[i]) + 1;
919             if (!(cmdLine = DBG_realloc(cmdLine, len))) goto oom_leave;
920             strcat(cmdLine, argv[i]);
921             cmdLine[len - 2] = ' ';
922             cmdLine[len - 1] = '\0';
923         }
924
925         if (!DEBUG_Start(cmdLine)) {
926             DEBUG_Printf(DBG_CHN_MESG, "Couldn't start process '%s'\n", cmdLine);
927             goto leave;
928         }
929         DBG_free(DEBUG_LastCmdLine);
930         DEBUG_LastCmdLine = cmdLine;
931     }
932
933     retv = DEBUG_MainLoop();
934
935     /* saves modified variables */
936     DEBUG_IntVarsRW(FALSE);
937
938  leave:
939     return retv;
940
941  oom_leave:
942     DEBUG_Printf(DBG_CHN_MESG, "Out of memory\n");
943     goto leave;
944 }