Convert HMIXER, HMIXEROBJ to a void*.
[wine] / debugger / winedbg.c
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2
3 /* Wine internal debugger
4  * Interface to Windows debugger API
5  * Copyright 2000 Eric Pouech
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include <stdlib.h>
23 #include <stdarg.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include "debugger.h"
27
28 #include "ntddk.h"
29 #include "thread.h"
30 #include "wincon.h"
31 #include "winreg.h"
32 #include "wingdi.h"
33 #include "winuser.h"
34 #include "msvcrt/excpt.h"
35 #include "wine/library.h"
36
37 DBG_PROCESS*    DEBUG_CurrProcess = NULL;
38 DBG_THREAD*     DEBUG_CurrThread = NULL;
39 DWORD           DEBUG_CurrTid;
40 DWORD           DEBUG_CurrPid;
41 CONTEXT         DEBUG_context;
42 BOOL            DEBUG_InteractiveP = FALSE;
43 int             curr_frame = 0;
44 static char*    DEBUG_LastCmdLine = NULL;
45
46 static DBG_PROCESS* DEBUG_ProcessList = NULL;
47 static enum {none_mode = 0, winedbg_mode, automatic_mode, gdb_mode} local_mode;
48
49 DBG_INTVAR DEBUG_IntVars[DBG_IV_LAST];
50
51 void    DEBUG_OutputA(int chn, const char* buffer, int len)
52 {
53     if (DBG_IVAR(ConChannelMask) & chn)
54         WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buffer, len, NULL, NULL);
55     if (DBG_IVAR(StdChannelMask) & chn)
56         fwrite(buffer, len, 1, stderr);
57 }
58
59 void    DEBUG_OutputW(int chn, const WCHAR* buffer, int len)
60 {
61     /* FIXME: this won't work is std output isn't attached to a console */
62     if (DBG_IVAR(ConChannelMask) & chn)
63         WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), buffer, len, NULL, NULL);
64     /* simplistic Unicode to ANSI conversion */
65     if (DBG_IVAR(StdChannelMask) & chn)
66         while (len--) fputc((char)*buffer++, stderr);
67 }
68
69 int     DEBUG_Printf(int chn, const char* format, ...)
70 {
71 static    char  buf[4*1024];
72     va_list     valist;
73     int         len;
74
75     va_start(valist, format);
76     len = vsnprintf(buf, sizeof(buf), format, valist);
77     va_end(valist);
78
79     if (len <= -1 || len >= sizeof(buf)) {
80         len = sizeof(buf) - 1;
81         buf[len] = 0;
82         buf[len - 1] = buf[len - 2] = buf[len - 3] = '.';
83     }
84     DEBUG_OutputA(chn, buf, len);
85     return len;
86 }
87
88 static  BOOL DEBUG_IntVarsRW(int read)
89 {
90     HKEY        hkey;
91     DWORD       type = REG_DWORD;
92     DWORD       val;
93     DWORD       count = sizeof(val);
94     int         i;
95     DBG_INTVAR* div = DEBUG_IntVars;
96
97     if (read) {
98 /* initializes internal vars table */
99 #define  INTERNAL_VAR(_var,_val,_ref,_typ)                      \
100         div->val = _val; div->name = #_var; div->pval = _ref;   \
101         div->type = DEBUG_GetBasicType(_typ); div++;
102 #include "intvar.h"
103 #undef   INTERNAL_VAR
104     }
105
106     if (RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine\\WineDbg", &hkey)) {
107         /* since the IVars are not yet setup, DEBUG_Printf doesn't work,
108          * so don't use it */
109         fprintf(stderr, "Cannot create WineDbg key in registry\n");
110         return FALSE;
111     }
112
113     for (i = 0; i < DBG_IV_LAST; i++) {
114         if (read) {
115             if (!DEBUG_IntVars[i].pval) {
116                 if (!RegQueryValueEx(hkey, DEBUG_IntVars[i].name, 0,
117                                      &type, (LPSTR)&val, &count))
118                     DEBUG_IntVars[i].val = val;
119                 DEBUG_IntVars[i].pval = &DEBUG_IntVars[i].val;
120             } else {
121                 *DEBUG_IntVars[i].pval = 0;
122             }
123         } else {
124             /* FIXME: type should be infered from basic type -if any- of intvar */
125             if (DEBUG_IntVars[i].pval == &DEBUG_IntVars[i].val)
126                 RegSetValueEx(hkey, DEBUG_IntVars[i].name, 0,
127                               type, (LPCVOID)DEBUG_IntVars[i].pval, count);
128         }
129     }
130     RegCloseKey(hkey);
131     return TRUE;
132 }
133
134 DBG_INTVAR*     DEBUG_GetIntVar(const char* name)
135 {
136     int         i;
137
138     for (i = 0; i < DBG_IV_LAST; i++) {
139         if (!strcmp(DEBUG_IntVars[i].name, name))
140             return &DEBUG_IntVars[i];
141     }
142     return NULL;
143 }
144
145 DBG_PROCESS*    DEBUG_GetProcess(DWORD pid)
146 {
147     DBG_PROCESS*        p;
148
149     for (p = DEBUG_ProcessList; p; p = p->next)
150         if (p->pid == pid) break;
151     return p;
152 }
153
154 DBG_PROCESS*    DEBUG_AddProcess(DWORD pid, HANDLE h, const char* imageName)
155 {
156     DBG_PROCESS*        p;
157
158     if ((p = DEBUG_GetProcess(pid)))
159     {
160         if (p->handle != 0)
161         {
162             DEBUG_Printf(DBG_CHN_ERR, "Process (%lu) is already defined\n", pid);
163         }
164         else
165         {
166             p->handle = h;
167             p->imageName = imageName ? DBG_strdup(imageName) : NULL;
168         }
169         return p;
170     }
171
172     if (!(p = DBG_alloc(sizeof(DBG_PROCESS)))) return NULL;
173     p->handle = h;
174     p->pid = pid;
175     p->imageName = imageName ? DBG_strdup(imageName) : NULL;
176     p->threads = NULL;
177     p->num_threads = 0;
178     p->continue_on_first_exception = FALSE;
179     p->modules = NULL;
180     p->num_modules = 0;
181     p->next_index = 0;
182     p->dbg_hdr_addr = 0;
183     p->delayed_bp = NULL;
184     p->num_delayed_bp = 0;
185
186     p->next = DEBUG_ProcessList;
187     p->prev = NULL;
188     if (DEBUG_ProcessList) DEBUG_ProcessList->prev = p;
189     DEBUG_ProcessList = p;
190     return p;
191 }
192
193 void DEBUG_DelProcess(DBG_PROCESS* p)
194 {
195     int i;
196
197     while (p->threads) DEBUG_DelThread(p->threads);
198
199     for (i = 0; i < p->num_delayed_bp; i++)
200         if (p->delayed_bp[i].is_symbol)
201             DBG_free(p->delayed_bp[i].u.symbol.name);
202
203     DBG_free(p->delayed_bp);
204     if (p->prev) p->prev->next = p->next;
205     if (p->next) p->next->prev = p->prev;
206     if (p == DEBUG_ProcessList) DEBUG_ProcessList = p->next;
207     if (p == DEBUG_CurrProcess) DEBUG_CurrProcess = NULL;
208     DBG_free((char*)p->imageName);
209     DBG_free(p);
210 }
211
212 static  void                    DEBUG_InitCurrProcess(void)
213 {
214 }
215
216 BOOL DEBUG_ProcessGetString(char* buffer, int size, HANDLE hp, LPSTR addr)
217 {
218     DWORD sz;
219     *(WCHAR*)buffer = 0;
220     return (addr && ReadProcessMemory(hp, addr, buffer, size, &sz));
221 }
222
223 BOOL DEBUG_ProcessGetStringIndirect(char* buffer, int size, HANDLE hp, LPVOID addr)
224 {
225     LPVOID      ad;
226     DWORD       sz;
227
228     if (   addr
229         && ReadProcessMemory(hp, addr, &ad, sizeof(ad), &sz)
230         && sz == sizeof(ad)
231         && ad
232         && ReadProcessMemory(hp, ad, buffer, size, &sz))
233         return TRUE;
234     *(WCHAR*)buffer = 0;
235     return FALSE;
236 }
237
238 DBG_THREAD*     DEBUG_GetThread(DBG_PROCESS* p, DWORD tid)
239 {
240     DBG_THREAD* t;
241
242     if (!p) return NULL;
243     for (t = p->threads; t; t = t->next)
244         if (t->tid == tid) break;
245     return t;
246 }
247
248 DBG_THREAD*     DEBUG_AddThread(DBG_PROCESS* p, DWORD tid,
249                                 HANDLE h, LPVOID start, LPVOID teb)
250 {
251     DBG_THREAD* t = DBG_alloc(sizeof(DBG_THREAD));
252     if (!t)
253         return NULL;
254
255     t->handle = h;
256     t->tid = tid;
257     t->start = start;
258     t->teb = teb;
259     t->process = p;
260     t->wait_for_first_exception = 0;
261     t->exec_mode = EXEC_CONT;
262     t->exec_count = 0;
263
264     sprintf(t->name, "%08lx", tid);
265
266     p->num_threads++;
267     t->next = p->threads;
268     t->prev = NULL;
269     if (p->threads) p->threads->prev = t;
270     p->threads = t;
271
272     return t;
273 }
274
275 static  void                    DEBUG_InitCurrThread(void)
276 {
277     if (DEBUG_CurrThread->start) {
278         if (DEBUG_CurrThread->process->num_threads == 1 ||
279             DBG_IVAR(BreakAllThreadsStartup)) {
280             DBG_VALUE   value;
281
282             DEBUG_SetBreakpoints(FALSE);
283             value.type = NULL;
284             value.cookie = DV_TARGET;
285             value.addr.seg = 0;
286             value.addr.off = (DWORD)DEBUG_CurrThread->start;
287             DEBUG_AddBreakpointFromValue(&value);
288             DEBUG_SetBreakpoints(TRUE);
289         }
290     } else {
291         DEBUG_CurrThread->wait_for_first_exception = 1;
292     }
293 }
294
295 void                    DEBUG_DelThread(DBG_THREAD* t)
296 {
297     if (t->prev) t->prev->next = t->next;
298     if (t->next) t->next->prev = t->prev;
299     if (t == t->process->threads) t->process->threads = t->next;
300     t->process->num_threads--;
301     if (t == DEBUG_CurrThread) DEBUG_CurrThread = NULL;
302     DBG_free(t);
303 }
304
305 BOOL                            DEBUG_Attach(DWORD pid, BOOL cofe)
306 {
307     if (!(DEBUG_CurrProcess = DEBUG_AddProcess(pid, 0, NULL))) return FALSE;
308
309     if (!DebugActiveProcess(pid)) {
310         DEBUG_Printf(DBG_CHN_MESG, "Can't attach process %lx: error %ld\n", pid, GetLastError());
311         DEBUG_DelProcess(DEBUG_CurrProcess);
312         DEBUG_CurrProcess = NULL;
313         return FALSE;
314     }
315     DEBUG_CurrProcess->continue_on_first_exception = cofe;
316     return TRUE;
317 }
318
319 BOOL                            DEBUG_Detach(void)
320 {
321     /* remove all set breakpoints in debuggee code */
322     DEBUG_SetBreakpoints(FALSE);
323     /* needed for single stepping (ugly).
324      * should this be handled inside the server ??? */
325 #ifdef __i386__
326     DEBUG_context.EFlags &= ~STEP_FLAG;
327 #endif
328     SetThreadContext(DEBUG_CurrThread->handle, &DEBUG_context);
329     DebugActiveProcessStop(DEBUG_CurrProcess->pid);
330     DEBUG_DelProcess(DEBUG_CurrProcess);
331     DEBUG_CurrProcess = NULL;
332     /* FIXME: should zero out the symbol table too */
333     return TRUE;
334 }
335
336 static  BOOL    DEBUG_ExceptionProlog(BOOL is_debug, BOOL force, DWORD code)
337 {
338     DBG_ADDR    addr;
339     int         newmode;
340
341     DEBUG_GetCurrentAddress(&addr);
342     DEBUG_SuspendExecution();
343
344     if (!is_debug)
345     {
346         if (!addr.seg)
347             DEBUG_Printf(DBG_CHN_MESG, " in 32-bit code (0x%08lx)", addr.off);
348         else
349             switch(DEBUG_GetSelectorType(addr.seg))
350             {
351             case MODE_32:
352                 DEBUG_Printf(DBG_CHN_MESG, " in 32-bit code (%04lx:%08lx)", addr.seg, addr.off);
353                 break;
354             case MODE_16:
355                 DEBUG_Printf(DBG_CHN_MESG, " in 16-bit code (%04lx:%04lx)", addr.seg, addr.off);
356                 break;
357             case MODE_VM86:
358                 DEBUG_Printf(DBG_CHN_MESG, " in vm86 code (%04lx:%04lx)", addr.seg, addr.off);
359                 break;
360             case MODE_INVALID:
361                 DEBUG_Printf(DBG_CHN_MESG, " bad CS (%lx)", addr.seg);
362                 break;
363         }
364         DEBUG_Printf(DBG_CHN_MESG, ".\n");
365     }
366
367     DEBUG_LoadEntryPoints("Loading new modules symbols:\n");
368
369     if (!force && is_debug &&
370         DEBUG_ShouldContinue(&addr, code,
371                              &DEBUG_CurrThread->exec_count))
372         return FALSE;
373
374     if ((newmode = DEBUG_GetSelectorType(addr.seg)) == MODE_INVALID) newmode = MODE_32;
375     if (newmode != DEBUG_CurrThread->dbg_mode)
376     {
377         static const char * const names[] = { "???", "16-bit", "32-bit", "vm86" };
378         DEBUG_Printf(DBG_CHN_MESG,"In %s mode.\n", names[newmode] );
379         DEBUG_CurrThread->dbg_mode = newmode;
380     }
381
382     DEBUG_DoDisplay();
383
384     if (is_debug || force) {
385         /*
386          * Do a quiet backtrace so that we have an idea of what the situation
387          * is WRT the source files.
388          */
389         DEBUG_BackTrace(DEBUG_CurrTid, FALSE);
390     } else {
391         /* This is a real crash, dump some info */
392         DEBUG_InfoRegisters(&DEBUG_context);
393         DEBUG_InfoStack();
394 #ifdef __i386__
395         if (DEBUG_CurrThread->dbg_mode == MODE_16) {
396             DEBUG_InfoSegments(DEBUG_context.SegDs >> 3, 1);
397             if (DEBUG_context.SegEs != DEBUG_context.SegDs)
398                 DEBUG_InfoSegments(DEBUG_context.SegEs >> 3, 1);
399         }
400         DEBUG_InfoSegments(DEBUG_context.SegFs >> 3, 1);
401 #endif
402         DEBUG_BackTrace(DEBUG_CurrTid, TRUE);
403     }
404
405     if (!is_debug ||
406         (DEBUG_CurrThread->exec_mode == EXEC_STEPI_OVER) ||
407         (DEBUG_CurrThread->exec_mode == EXEC_STEPI_INSTR)) {
408
409         struct list_id list;
410
411         /* Show where we crashed */
412         curr_frame = 0;
413         DEBUG_DisassembleInstruction(&addr);
414
415         /* resets list internal arguments so we can look at source code when needed */
416         DEBUG_FindNearestSymbol(&addr, TRUE, NULL, 0, &list);
417         if (list.sourcefile) DEBUG_List(&list, NULL, 0);
418     }
419     return TRUE;
420 }
421
422 static  void    DEBUG_ExceptionEpilog(void)
423 {
424     DEBUG_RestartExecution(DEBUG_CurrThread->exec_count);
425     /*
426      * This will have gotten absorbed into the breakpoint info
427      * if it was used.  Otherwise it would have been ignored.
428      * In any case, we don't mess with it any more.
429      */
430     if (DEBUG_CurrThread->exec_mode == EXEC_CONT)
431         DEBUG_CurrThread->exec_count = 0;
432 }
433
434 static  BOOL DEBUG_HandleException(EXCEPTION_RECORD *rec, BOOL first_chance, BOOL force)
435 {
436     BOOL             is_debug = FALSE;
437     THREADNAME_INFO *pThreadName;
438     DBG_THREAD      *pThread;
439
440     assert(DEBUG_CurrThread);
441
442     switch (rec->ExceptionCode)
443     {
444     case EXCEPTION_BREAKPOINT:
445     case EXCEPTION_SINGLE_STEP:
446         is_debug = TRUE;
447         break;
448     case EXCEPTION_NAME_THREAD:
449         pThreadName = (THREADNAME_INFO*)(rec->ExceptionInformation);
450         if (pThreadName->dwThreadID == -1)
451             pThread = DEBUG_CurrThread;
452         else
453             pThread = DEBUG_GetThread(DEBUG_CurrProcess, pThreadName->dwThreadID);
454
455         if (ReadProcessMemory(DEBUG_CurrThread->process->handle, pThreadName->szName,
456                               pThread->name, 9, NULL))
457             DEBUG_Printf (DBG_CHN_MESG,
458                           "Thread ID=0x%lx renamed using MS VC6 extension (name==\"%s\")\n",
459                           pThread->tid, pThread->name);
460         return FALSE;
461     }
462
463     if (first_chance && !is_debug && !force && !DBG_IVAR(BreakOnFirstChance))
464     {
465         /* pass exception to program except for debug exceptions */
466         return FALSE;
467     }
468
469     if (!is_debug)
470     {
471         /* print some infos */
472         DEBUG_Printf(DBG_CHN_MESG, "%s: ",
473                       first_chance ? "First chance exception" : "Unhandled exception");
474         switch (rec->ExceptionCode)
475         {
476         case EXCEPTION_INT_DIVIDE_BY_ZERO:
477             DEBUG_Printf(DBG_CHN_MESG, "divide by zero");
478             break;
479         case EXCEPTION_INT_OVERFLOW:
480             DEBUG_Printf(DBG_CHN_MESG, "overflow");
481             break;
482         case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
483             DEBUG_Printf(DBG_CHN_MESG, "array bounds ");
484             break;
485         case EXCEPTION_ILLEGAL_INSTRUCTION:
486             DEBUG_Printf(DBG_CHN_MESG, "illegal instruction");
487             break;
488         case EXCEPTION_STACK_OVERFLOW:
489             DEBUG_Printf(DBG_CHN_MESG, "stack overflow");
490             break;
491         case EXCEPTION_PRIV_INSTRUCTION:
492             DEBUG_Printf(DBG_CHN_MESG, "privileged instruction");
493             break;
494         case EXCEPTION_ACCESS_VIOLATION:
495             if (rec->NumberParameters == 2)
496                 DEBUG_Printf(DBG_CHN_MESG, "page fault on %s access to 0x%08lx",
497                               rec->ExceptionInformation[0] ? "write" : "read",
498                               rec->ExceptionInformation[1]);
499             else
500                 DEBUG_Printf(DBG_CHN_MESG, "page fault");
501             break;
502         case EXCEPTION_DATATYPE_MISALIGNMENT:
503             DEBUG_Printf(DBG_CHN_MESG, "Alignment");
504             break;
505         case DBG_CONTROL_C:
506             DEBUG_Printf(DBG_CHN_MESG, "^C");
507             break;
508         case CONTROL_C_EXIT:
509             DEBUG_Printf(DBG_CHN_MESG, "^C");
510             break;
511         case EXCEPTION_CRITICAL_SECTION_WAIT:
512             {
513                 DBG_ADDR        addr;
514
515                 addr.seg = 0;
516                 addr.off = rec->ExceptionInformation[0];
517
518                 DEBUG_Printf(DBG_CHN_MESG, "wait failed on critical section ");
519                 DEBUG_PrintAddress(&addr, DEBUG_CurrThread->dbg_mode, FALSE);
520             }
521             if (!DBG_IVAR(BreakOnCritSectTimeOut))
522             {
523                 DEBUG_Printf(DBG_CHN_MESG, "\n");
524                 return FALSE;
525             }
526             break;
527         case EXCEPTION_WINE_STUB:
528             {
529                 char dll[32], name[64];
530                 DEBUG_ProcessGetString( dll, sizeof(dll), DEBUG_CurrThread->process->handle,
531                                         (char *)rec->ExceptionInformation[0] );
532                 DEBUG_ProcessGetString( name, sizeof(name), DEBUG_CurrThread->process->handle,
533                                         (char *)rec->ExceptionInformation[1] );
534                 DEBUG_Printf(DBG_CHN_MESG, "unimplemented function %s.%s called", dll, name );
535             }
536             break;
537         case EXCEPTION_VM86_INTx:
538             DEBUG_Printf(DBG_CHN_MESG, "interrupt %02lx in vm86 mode",
539                          rec->ExceptionInformation[0]);
540             break;
541         case EXCEPTION_VM86_STI:
542             DEBUG_Printf(DBG_CHN_MESG, "sti in vm86 mode");
543             break;
544         case EXCEPTION_VM86_PICRETURN:
545             DEBUG_Printf(DBG_CHN_MESG, "PIC return in vm86 mode");
546             break;
547         default:
548             DEBUG_Printf(DBG_CHN_MESG, "%08lx", rec->ExceptionCode);
549             break;
550         }
551     }
552
553     if (local_mode == automatic_mode)
554     {
555         DEBUG_ExceptionProlog(is_debug, FALSE, rec->ExceptionCode);
556         DEBUG_ExceptionEpilog();
557         return TRUE;  /* terminate execution */
558     }
559
560     if (DEBUG_ExceptionProlog(is_debug, force, rec->ExceptionCode))
561     {
562         DEBUG_InteractiveP = TRUE;
563         return TRUE;
564     }
565     DEBUG_ExceptionEpilog();
566
567     return FALSE;
568 }
569
570 static  BOOL    DEBUG_HandleDebugEvent(DEBUG_EVENT* de)
571 {
572     char                buffer[256];
573     BOOL                ret = FALSE;
574
575     DEBUG_CurrPid = de->dwProcessId;
576     DEBUG_CurrTid = de->dwThreadId;
577
578     if ((DEBUG_CurrProcess = DEBUG_GetProcess(de->dwProcessId)) != NULL)
579         DEBUG_CurrThread = DEBUG_GetThread(DEBUG_CurrProcess, de->dwThreadId);
580     else
581         DEBUG_CurrThread = NULL;
582
583     switch (de->dwDebugEventCode)
584     {
585     case EXCEPTION_DEBUG_EVENT:
586         if (!DEBUG_CurrThread)
587         {
588             DEBUG_Printf(DBG_CHN_ERR, "%08lx:%08lx: not a registered process or thread (perhaps a 16 bit one ?)\n",
589                          de->dwProcessId, de->dwThreadId);
590             break;
591         }
592
593         DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: exception code=%08lx\n",
594                      de->dwProcessId, de->dwThreadId,
595                      de->u.Exception.ExceptionRecord.ExceptionCode);
596
597         if (DEBUG_CurrProcess->continue_on_first_exception)
598         {
599             DEBUG_CurrProcess->continue_on_first_exception = FALSE;
600             if (!DBG_IVAR(BreakOnAttach)) break;
601         }
602
603         DEBUG_context.ContextFlags =  CONTEXT_CONTROL
604                                     | CONTEXT_INTEGER
605 #ifdef CONTEXT_SEGMENTS
606                                     | CONTEXT_SEGMENTS
607 #endif
608 #ifdef CONTEXT_DEBUG_REGISTERS
609                                     | CONTEXT_DEBUG_REGISTERS
610 #endif
611                                     ;
612
613         if (!GetThreadContext(DEBUG_CurrThread->handle, &DEBUG_context))
614         {
615             DEBUG_Printf(DBG_CHN_WARN, "Can't get thread's context\n");
616             break;
617         }
618
619         ret = DEBUG_HandleException(&de->u.Exception.ExceptionRecord,
620                                     de->u.Exception.dwFirstChance,
621                                     DEBUG_CurrThread->wait_for_first_exception);
622         if (DEBUG_CurrThread)
623         {
624             DEBUG_CurrThread->wait_for_first_exception = 0;
625             SetThreadContext(DEBUG_CurrThread->handle, &DEBUG_context);
626         }
627         break;
628
629     case CREATE_THREAD_DEBUG_EVENT:
630         DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: create thread D @%08lx\n", de->dwProcessId, de->dwThreadId,
631                      (unsigned long)(LPVOID)de->u.CreateThread.lpStartAddress);
632
633         if (DEBUG_CurrProcess == NULL)
634         {
635             DEBUG_Printf(DBG_CHN_ERR, "Unknown process\n");
636             break;
637         }
638         if (DEBUG_GetThread(DEBUG_CurrProcess, de->dwThreadId) != NULL)
639         {
640             DEBUG_Printf(DBG_CHN_TRACE, "Thread already listed, skipping\n");
641             break;
642         }
643
644         DEBUG_CurrThread = DEBUG_AddThread(DEBUG_CurrProcess,
645                                            de->dwThreadId,
646                                            de->u.CreateThread.hThread,
647                                            de->u.CreateThread.lpStartAddress,
648                                            de->u.CreateThread.lpThreadLocalBase);
649         if (!DEBUG_CurrThread)
650         {
651             DEBUG_Printf(DBG_CHN_ERR, "Couldn't create thread\n");
652             break;
653         }
654         DEBUG_InitCurrThread();
655         break;
656
657     case CREATE_PROCESS_DEBUG_EVENT:
658         DEBUG_ProcessGetStringIndirect(buffer, sizeof(buffer),
659                                        de->u.CreateProcessInfo.hProcess,
660                                        de->u.CreateProcessInfo.lpImageName);
661
662         /* FIXME unicode ? de->u.CreateProcessInfo.fUnicode */
663         DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: create process '%s'/%p @%08lx (%ld<%ld>)\n",
664                      de->dwProcessId, de->dwThreadId,
665                      buffer, de->u.CreateProcessInfo.lpImageName,
666                      (unsigned long)(LPVOID)de->u.CreateProcessInfo.lpStartAddress,
667                      de->u.CreateProcessInfo.dwDebugInfoFileOffset,
668                      de->u.CreateProcessInfo.nDebugInfoSize);
669
670         DEBUG_CurrProcess = DEBUG_AddProcess(de->dwProcessId,
671                                              de->u.CreateProcessInfo.hProcess,
672                                              buffer[0] ? buffer : "<Debugged Process>");
673         if (DEBUG_CurrProcess == NULL)
674         {
675             DEBUG_Printf(DBG_CHN_ERR, "Couldn't create process\n");
676             break;
677         }
678
679         DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: create thread I @%08lx\n",
680                      de->dwProcessId, de->dwThreadId,
681                      (unsigned long)(LPVOID)de->u.CreateProcessInfo.lpStartAddress);
682
683         DEBUG_CurrThread = DEBUG_AddThread(DEBUG_CurrProcess,
684                                            de->dwThreadId,
685                                            de->u.CreateProcessInfo.hThread,
686                                            de->u.CreateProcessInfo.lpStartAddress,
687                                            de->u.CreateProcessInfo.lpThreadLocalBase);
688         if (!DEBUG_CurrThread)
689         {
690             DEBUG_Printf(DBG_CHN_ERR, "Couldn't create thread\n");
691             break;
692         }
693
694         DEBUG_InitCurrProcess();
695         DEBUG_InitCurrThread();
696
697         /* module is either PE, NE or ELF module (for WineLib), but all
698          * are loaded with wine, so load its symbols, then the main module
699          */
700         do
701         {
702             char*   ptr = getenv("WINELOADER");
703
704             if (!ptr || DEBUG_ReadExecutableDbgInfo( ptr ) == DIL_ERROR)
705                 DEBUG_ReadExecutableDbgInfo( "wine" );
706         } while (0);
707
708         DEBUG_LoadModule32(DEBUG_CurrProcess->imageName, de->u.CreateProcessInfo.hFile,
709                            (DWORD)de->u.CreateProcessInfo.lpBaseOfImage);
710
711         break;
712
713     case EXIT_THREAD_DEBUG_EVENT:
714         DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: exit thread (%ld)\n",
715                      de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
716
717         if (DEBUG_CurrThread == NULL)
718         {
719             DEBUG_Printf(DBG_CHN_ERR, "Unknown thread\n");
720             break;
721         }
722         /* FIXME: remove break point set on thread startup */
723         DEBUG_DelThread(DEBUG_CurrThread);
724         break;
725
726     case EXIT_PROCESS_DEBUG_EVENT:
727         DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: exit process (%ld)\n",
728                      de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
729
730         if (DEBUG_CurrProcess == NULL)
731         {
732             DEBUG_Printf(DBG_CHN_ERR, "Unknown process\n");
733             break;
734         }
735         /* just in case */
736         DEBUG_SetBreakpoints(FALSE);
737         /* kill last thread */
738         DEBUG_DelThread(DEBUG_CurrProcess->threads);
739         DEBUG_DelProcess(DEBUG_CurrProcess);
740
741         DEBUG_Printf(DBG_CHN_MESG, "Process of pid=%08lx has terminated\n", DEBUG_CurrPid);
742         break;
743
744     case LOAD_DLL_DEBUG_EVENT:
745         if (DEBUG_CurrThread == NULL)
746         {
747             DEBUG_Printf(DBG_CHN_ERR, "Unknown thread\n");
748             break;
749         }
750         DEBUG_ProcessGetStringIndirect(buffer, sizeof(buffer),
751                                        DEBUG_CurrThread->process->handle,
752                                        de->u.LoadDll.lpImageName);
753
754         /* FIXME unicode: de->u.LoadDll.fUnicode */
755         DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: loads DLL %s @%08lx (%ld<%ld>)\n",
756                      de->dwProcessId, de->dwThreadId,
757                      buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll,
758                      de->u.LoadDll.dwDebugInfoFileOffset,
759                      de->u.LoadDll.nDebugInfoSize);
760         _strupr(buffer);
761         DEBUG_LoadModule32(buffer, de->u.LoadDll.hFile, (DWORD)de->u.LoadDll.lpBaseOfDll);
762         DEBUG_CheckDelayedBP();
763         if (DBG_IVAR(BreakOnDllLoad))
764         {
765             DEBUG_Printf(DBG_CHN_MESG, "Stopping on DLL %s loading at %08lx\n",
766                          buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll);
767             ret = TRUE;
768         }
769         break;
770
771     case UNLOAD_DLL_DEBUG_EVENT:
772         DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: unload DLL @%08lx\n", de->dwProcessId, de->dwThreadId,
773                      (unsigned long)de->u.UnloadDll.lpBaseOfDll);
774         break;
775
776     case OUTPUT_DEBUG_STRING_EVENT:
777         if (DEBUG_CurrThread == NULL)
778         {
779             DEBUG_Printf(DBG_CHN_ERR, "Unknown thread\n");
780             break;
781         }
782
783         DEBUG_ProcessGetString(buffer, sizeof(buffer),
784                                DEBUG_CurrThread->process->handle,
785                                de->u.DebugString.lpDebugStringData);
786
787         /* FIXME unicode de->u.DebugString.fUnicode ? */
788         DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: output debug string (%s)\n",
789                      de->dwProcessId, de->dwThreadId, buffer);
790         break;
791
792     case RIP_EVENT:
793         DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: rip error=%ld type=%ld\n",
794                      de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
795                      de->u.RipInfo.dwType);
796         break;
797
798     default:
799         DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: unknown event (%ld)\n",
800                      de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
801     }
802
803     return ret;
804 }
805
806 static void                     DEBUG_ResumeDebuggee(DWORD cont)
807 {
808     DEBUG_ExceptionEpilog();
809 #if 1
810     DEBUG_Printf(DBG_CHN_TRACE,
811                  "Exiting debugger      PC=%lx EFL=%08lx mode=%d count=%d\n",
812 #ifdef __i386__
813                  DEBUG_context.Eip, DEBUG_context.EFlags,
814 #else
815                  0L, 0L,
816 #endif
817                  DEBUG_CurrThread->exec_mode, DEBUG_CurrThread->exec_count);
818 #endif
819     DEBUG_InteractiveP = FALSE;
820     if (DEBUG_CurrThread)
821     {
822         if (!SetThreadContext(DEBUG_CurrThread->handle, &DEBUG_context))
823             DEBUG_Printf(DBG_CHN_MESG, "Cannot set ctx on %lu\n", DEBUG_CurrTid);
824         DEBUG_CurrThread->wait_for_first_exception = 0;
825     }
826     if (!ContinueDebugEvent(DEBUG_CurrPid, DEBUG_CurrTid, cont))
827         DEBUG_Printf(DBG_CHN_MESG, "Cannot continue on %lu (%lu)\n",
828                      DEBUG_CurrTid, cont);
829 }
830
831 void                            DEBUG_WaitNextException(DWORD cont, int count, int mode)
832 {
833     DEBUG_EVENT         de;
834
835     if (cont == DBG_CONTINUE)
836     {
837         DEBUG_CurrThread->exec_count = count;
838         DEBUG_CurrThread->exec_mode = mode;
839     }
840     DEBUG_ResumeDebuggee(cont);
841
842     while (DEBUG_CurrProcess && WaitForDebugEvent(&de, INFINITE))
843     {
844         if (DEBUG_HandleDebugEvent(&de)) break;
845         ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
846     }
847     if (!DEBUG_CurrProcess) return;
848     DEBUG_InteractiveP = TRUE;
849 #if 1
850     DEBUG_Printf(DBG_CHN_TRACE,
851                  "Entering debugger     PC=%lx EFL=%08lx mode=%d count=%d\n",
852 #ifdef __i386__
853                  DEBUG_context.Eip, DEBUG_context.EFlags,
854 #else
855                  0L, 0L,
856 #endif
857                  DEBUG_CurrThread->exec_mode, DEBUG_CurrThread->exec_count);
858 #endif
859 }
860
861 static  DWORD   DEBUG_MainLoop(void)
862 {
863     DEBUG_EVENT         de;
864
865     DEBUG_Printf(DBG_CHN_MESG, "WineDbg starting on pid %lx\n", DEBUG_CurrPid);
866
867     /* wait for first exception */
868     while (WaitForDebugEvent(&de, INFINITE))
869     {
870         if (DEBUG_HandleDebugEvent(&de)) break;
871         ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
872     }
873     if (local_mode == automatic_mode)
874     {
875         /* print some extra information */
876         DEBUG_Printf(DBG_CHN_MESG, "Modules:\n");
877         DEBUG_WalkModules();
878         DEBUG_Printf(DBG_CHN_MESG, "Threads:\n");
879         DEBUG_WalkThreads();
880     }
881     else
882     {
883         DEBUG_InteractiveP = TRUE;
884         DEBUG_Parser(NULL);
885     }
886     DEBUG_Printf(DBG_CHN_MESG, "WineDbg terminated on pid %lx\n", DEBUG_CurrPid);
887
888     return 0;
889 }
890
891 static  BOOL    DEBUG_Start(LPSTR cmdLine)
892 {
893     PROCESS_INFORMATION info;
894     STARTUPINFOA        startup;
895
896     memset(&startup, 0, sizeof(startup));
897     startup.cb = sizeof(startup);
898     startup.dwFlags = STARTF_USESHOWWINDOW;
899     startup.wShowWindow = SW_SHOWNORMAL;
900
901     /* FIXME: shouldn't need the CREATE_NEW_CONSOLE, but as usual CUI:s need it
902      * while GUI:s don't
903      */
904     if (!CreateProcess(NULL, cmdLine, NULL, NULL,
905                        FALSE, DEBUG_PROCESS|DEBUG_ONLY_THIS_PROCESS|CREATE_NEW_CONSOLE,
906                        NULL, NULL, &startup, &info))
907     {
908         DEBUG_Printf(DBG_CHN_MESG, "Couldn't start process '%s'\n", cmdLine);
909         return FALSE;
910     }
911     DEBUG_CurrPid = info.dwProcessId;
912     if (!(DEBUG_CurrProcess = DEBUG_AddProcess(DEBUG_CurrPid, 0, NULL))) return FALSE;
913
914     return TRUE;
915 }
916
917 void    DEBUG_Run(const char* args)
918 {
919     DBG_MODULE* wmod = DEBUG_GetProcessMainModule(DEBUG_CurrProcess);
920     const char* pgm = (wmod) ? wmod->module_name : "none";
921
922     if (args) {
923         DEBUG_Printf(DBG_CHN_MESG, "Run (%s) with '%s'\n", pgm, args);
924     } else {
925         if (!DEBUG_LastCmdLine) {
926             DEBUG_Printf(DBG_CHN_MESG, "Cannot find previously used command line.\n");
927             return;
928         }
929         DEBUG_Start(DEBUG_LastCmdLine);
930     }
931 }
932
933 static BOOL WINAPI DEBUG_CtrlCHandler(DWORD dwCtrlType)
934 {
935     if (dwCtrlType == CTRL_C_EVENT)
936     {
937         DEBUG_Printf(DBG_CHN_MESG, "Ctrl-C: stopping debuggee\n");
938         /* FIXME: since we likely have a single process, signal the first process
939          * in list
940          */
941         return DEBUG_ProcessList && DebugBreakProcess(DEBUG_ProcessList->handle);
942     }
943     return FALSE;
944 }
945
946 static void DEBUG_InitConsole(void)
947 {
948     COORD       c;
949     SMALL_RECT  sr;
950     DWORD       mode;
951
952     /* keep it as a cuiexe for now, so that Wine won't touch the Unix stdin,
953      * stdout and stderr streams
954      */
955     if (DBG_IVAR(UseXTerm))
956     {
957         FreeConsole();
958         AllocConsole();
959     }
960
961     /* this would be nicer for output */
962     c.X = 132;
963     c.Y = 500;
964     SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), c);
965
966     /* sets the console's window width accordingly */
967     sr.Left   = 0;
968     sr.Top    = 0;
969     sr.Right  = c.X - 1;
970     sr.Bottom = 50;
971     SetConsoleWindowInfo(GetStdHandle(STD_OUTPUT_HANDLE), TRUE, &sr);
972
973     /* put the line editing mode with the nice emacs features (FIXME: could be triggered by a IVAR) */
974     if (GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &mode))
975         SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode | WINE_ENABLE_LINE_INPUT_EMACS);
976
977     /* set our control-C handler */
978     SetConsoleCtrlHandler(DEBUG_CtrlCHandler, TRUE);
979 }
980
981 static int DEBUG_Usage(void)
982 {
983     DEBUG_Printf(DBG_CHN_MESG, "Usage: winedbg [--debugmsg dbgoptions] [--auto] [--gdb] cmdline\n" );
984     return 1;
985 }
986
987 int main(int argc, char** argv)
988 {
989     DWORD       retv = 0;
990     unsigned    gdb_flags = 0;
991
992     /* Initialize the type handling stuff. */
993     DEBUG_InitTypes();
994     DEBUG_InitCVDataTypes();
995
996     /* Initialize internal vars (types must have been initialized before) */
997     if (!DEBUG_IntVarsRW(TRUE)) return -1;
998
999     /* parse options */
1000     while (argc > 1 && argv[1][0] == '-')
1001     {
1002         if (!strcmp( argv[1], "--auto" ))
1003         {
1004             if (local_mode != none_mode) return DEBUG_Usage();
1005             local_mode = automatic_mode;
1006             /* force some internal variables */
1007             DBG_IVAR(UseXTerm) = 0;
1008             DBG_IVAR(BreakOnDllLoad) = 0;
1009             DBG_IVAR(ConChannelMask) = 0;
1010             DBG_IVAR(StdChannelMask) = DBG_CHN_MESG;
1011             argc--; argv++;
1012             continue;
1013         }
1014         if (!strcmp( argv[1], "--gdb" ))
1015         {
1016             if (local_mode != none_mode) return DEBUG_Usage();
1017             local_mode = gdb_mode;
1018             argc--; argv++;
1019             continue;
1020         }
1021         if (strcmp( argv[1], "--no-start") == 0 && local_mode == gdb_mode)
1022         {
1023             gdb_flags |= 1;
1024             argc--; argv++; /* as we don't use argv[0] */
1025             continue;
1026         }
1027         if (strcmp(argv[1], "--with-xterm") == 0 && local_mode == gdb_mode)
1028         {
1029             gdb_flags |= 2;
1030             argc--; argv++; /* as we don't use argv[0] */
1031             continue;
1032         }
1033         if (!strcmp( argv[1], "--debugmsg" ) && argv[2])
1034         {
1035             wine_dbg_parse_options( argv[2] );
1036             argc -= 2;
1037             argv += 2;
1038             continue;
1039         }
1040         return DEBUG_Usage();
1041     }
1042
1043     if (local_mode == none_mode) local_mode = winedbg_mode;
1044
1045     /* try the from <myself> pid */
1046     if (DEBUG_CurrPid == 0 && argc == 2)
1047     {
1048         char*   ptr;
1049
1050         DEBUG_CurrPid = strtol(argv[1], &ptr, 10);
1051         if (DEBUG_CurrPid == 0 || ptr == NULL ||
1052             !DEBUG_Attach(DEBUG_CurrPid, local_mode != gdb_mode))
1053             DEBUG_CurrPid = 0;
1054     }
1055
1056     /* try the from <myself> pid evt (Win32 JIT debugger) */
1057     if (DEBUG_CurrPid == 0 && argc == 3)
1058     {
1059         HANDLE  hEvent;
1060         DWORD   pid;
1061         char*   ptr;
1062
1063         if ((pid = strtol(argv[1], &ptr, 10)) != 0 && ptr != NULL &&
1064             (hEvent = (HANDLE)strtol(argv[2], &ptr, 10)) != 0 && ptr != NULL)
1065         {
1066             if (!DEBUG_Attach(pid, TRUE))
1067             {
1068                 /* don't care about result */
1069                 SetEvent(hEvent);
1070                 goto leave;
1071             }
1072             if (!SetEvent(hEvent))
1073             {
1074                 DEBUG_Printf(DBG_CHN_ERR, "Invalid event handle: %p\n", hEvent);
1075                 goto leave;
1076             }
1077             CloseHandle(hEvent);
1078             DEBUG_CurrPid = pid;
1079         }
1080     }
1081
1082     if (DEBUG_CurrPid == 0 && argc > 1)
1083     {
1084         int     i, len;
1085         LPSTR   cmdLine;
1086
1087         if (!(cmdLine = DBG_alloc(len = 1))) goto oom_leave;
1088         cmdLine[0] = '\0';
1089
1090         for (i = 1; i < argc; i++)
1091         {
1092             len += strlen(argv[i]) + 1;
1093             if (!(cmdLine = DBG_realloc(cmdLine, len))) goto oom_leave;
1094             strcat(cmdLine, argv[i]);
1095             cmdLine[len - 2] = ' ';
1096             cmdLine[len - 1] = '\0';
1097         }
1098
1099         if (!DEBUG_Start(cmdLine))
1100         {
1101             DEBUG_Printf(DBG_CHN_MESG, "Couldn't start process '%s'\n", cmdLine);
1102             goto leave;
1103         }
1104         DBG_free(DEBUG_LastCmdLine);
1105         DEBUG_LastCmdLine = cmdLine;
1106     }
1107     /* don't save local vars in gdb mode */
1108     if (local_mode == gdb_mode && DEBUG_CurrPid)
1109         return DEBUG_GdbRemote(gdb_flags);
1110
1111     DEBUG_InitConsole();
1112
1113     retv = DEBUG_MainLoop();
1114     /* don't save modified variables in auto mode */
1115     if (local_mode != automatic_mode) DEBUG_IntVarsRW(FALSE);
1116
1117  leave:
1118     return retv;
1119
1120  oom_leave:
1121     DEBUG_Printf(DBG_CHN_MESG, "Out of memory\n");
1122     goto leave;
1123 }