improved exception handling
merged all module handling code in new module.c file
reenabled 'walk module' and 'info module' commands
added ability to drive break on thread startup

diff --git a/debugger/Makefile.in b/debugger/Makefile.in
index a5524d7..54328b4 100644
--- a/debugger/Makefile.in
+++ b/debugger/Makefile.in
@@ -15,7 +15,8 @@
 	hash.c \
 	info.c \
 	memory.c \
-	msc.c	\
+	module.c \
+	msc.c \
 	registers.c \
 	source.c \
 	stabs.c	\
diff --git a/debugger/break.c b/debugger/break.c
index 2199505..f38cb2f 100644
--- a/debugger/break.c
+++ b/debugger/break.c
@@ -208,7 +208,6 @@
 	    }
 	    
 	    *lpdr = DEBUG_ToLinear(&breakpoints[i].addr);
-	    fprintf(stderr, "Setting DR%d %08lx\n", (lpdr - &DEBUG_context.Dr0) / 4, *lpdr);
 	    bits = (breakpoints[i].u.w.rw) ? DR7_RW_WRITE : DR7_RW_READ;
 	    switch (breakpoints[i].u.w.len + 1)
 	    {
@@ -226,7 +225,6 @@
 	 break;
       }
    }
-   fprintf(stderr, "Setting DR7 %08lx\n", DEBUG_context.Dr7);
 }
 
 /***********************************************************************
diff --git a/debugger/dbg.y b/debugger/dbg.y
index f4c3899..1ed882b 100644
--- a/debugger/dbg.y
+++ b/debugger/dbg.y
@@ -398,8 +398,9 @@
     else fprintf(stderr,"Invalid mode (use 16 or 32)\n");
 }
 
-static WINE_EXCEPTION_FILTER(wine_dbg)
+static WINE_EXCEPTION_FILTER(wine_dbg_cmd)
 {
+	fprintf(stderr, "\nwine_dbg_cmd: ");
    switch (GetExceptionCode()) {
    case DEBUG_STATUS_INTERNAL_ERROR:
       fprintf(stderr, "WineDbg internal error\n");
@@ -537,7 +538,7 @@
 	       if ((ret_ok = DEBUG_ValidateRegisters()))
 		  ret_ok = DEBUG_READ_MEM_VERBOSE((void*)DEBUG_ToLinear( &addr ), &ch, 1 );
 	    } 
-	    __EXCEPT(wine_dbg)
+	    __EXCEPT(wine_dbg_cmd)
 	    {
 	       ret_ok = 0;
 	    }
diff --git a/debugger/debugger.h b/debugger/debugger.h
index 104bfde..d95ce57 100644
--- a/debugger/debugger.h
+++ b/debugger/debugger.h
@@ -11,6 +11,7 @@
 #include <assert.h>
 #include "windef.h"
 #include "winbase.h"
+#include "wine/exception.h"
 
 #ifdef __i386__
 #define STEP_FLAG 0x00000100 /* single step flag */
@@ -135,8 +136,8 @@
     struct expr * condition;
 } BREAKPOINT;
 
-typedef struct tagWINE_DBG_THREAD {
-    struct tagWINE_DBG_PROCESS*	process;
+typedef struct tagDBG_THREAD {
+    struct tagDBG_PROCESS*	process;
     HANDLE			handle;
     DWORD			tid;
     LPVOID			start;
@@ -146,21 +147,30 @@
     enum exec_mode 		dbg_exec_mode;
     int 			dbg_exec_count;
     BREAKPOINT			stepOverBP;
-    struct tagWINE_DBG_THREAD* 	next;
-    struct tagWINE_DBG_THREAD* 	prev;
-} WINE_DBG_THREAD;
+    struct tagDBG_THREAD* 	next;
+    struct tagDBG_THREAD* 	prev;
+} DBG_THREAD;
 
-typedef struct tagWINE_DBG_PROCESS {
+typedef struct tagDBG_PROCESS {
     HANDLE			handle;
     DWORD			pid;
-    WINE_DBG_THREAD*		threads;
-    struct tagWINE_DBG_PROCESS*	next;
-    struct tagWINE_DBG_PROCESS*	prev;
-} WINE_DBG_PROCESS;
+    DBG_THREAD*			threads;
+    int				num_threads;
+    struct tagDBG_MODULE*	modules;
+    /*
+     * This is an index we use to keep track of the debug information
+     * when we have multiple sources.  We use the same database to also
+     * allow us to do an 'info shared' type of deal, and we use the index
+     * to eliminate duplicates.
+     */
+    int				next_index;
+    struct tagDBG_PROCESS*	next;
+    struct tagDBG_PROCESS*	prev;
+} DBG_PROCESS;
 
-extern	WINE_DBG_PROCESS* DEBUG_CurrProcess;
-extern	WINE_DBG_THREAD*  DEBUG_CurrThread;
-extern  CONTEXT		  DEBUG_context;
+extern	DBG_PROCESS*	DEBUG_CurrProcess;
+extern	DBG_THREAD*	DEBUG_CurrThread;
+extern  CONTEXT		DEBUG_context;
 
 #define DEBUG_READ_MEM(addr, buf, len) \
       (ReadProcessMemory(DEBUG_CurrProcess->handle, (addr), (buf), (len), NULL))
@@ -174,6 +184,28 @@
 #define DEBUG_WRITE_MEM_VERBOSE(addr, buf, len) \
       (DEBUG_WRITE_MEM((addr), (buf), (len)) || (DEBUG_InvalLinAddr( addr ),0))
 
+typedef struct tagDBG_MODULE {
+   struct tagDBG_MODULE*	next;
+   void*			load_addr;
+   char*			module_name;
+   char				status;
+   char				type;
+   short int			dbg_index;
+   HMODULE                      handle;
+   void*			extra_info;
+} DBG_MODULE;
+
+/* status field */
+#define DM_STATUS_NEW		0
+#define DM_STATUS_LOADED	1
+#define DM_STATUS_ERROR		2
+
+/* type field */
+#define DM_TYPE_UNKNOWN		0
+#define DM_TYPE_ELF		1
+#define DM_TYPE_NE		2
+#define DM_TYPE_PE		3
+
 #ifdef __i386__
 #ifdef REG_SP  /* Some Sun includes define this */
 #undef REG_SP
@@ -249,7 +281,6 @@
 					     unsigned int ebp,
 					     struct list_id * source);
 extern void DEBUG_ReadSymbolTable( const char * filename );
-extern int  DEBUG_LoadEntryPoints( const char * prefix );
 extern void DEBUG_AddLineNumber( struct name_hash * func, int line_num, 
 				 unsigned long offset );
 extern struct wine_locals *
@@ -270,7 +301,7 @@
 
 extern int DEBUG_SetLocalSymbolType(struct wine_locals * sym, 
 				    struct datatype * type);
-BOOL DEBUG_Normalize(struct name_hash * nh );
+extern BOOL DEBUG_Normalize(struct name_hash * nh );
 
   /* debugger/info.c */
 extern void DEBUG_PrintBasic( const DBG_VALUE* value, int count, char format );
@@ -309,6 +340,24 @@
 extern int  DEBUG_IsSelectorSystem( WORD sel );
 #endif
 
+  /* debugger/module.c */
+extern int  DEBUG_LoadEntryPoints( const char * prefix );
+extern void DEBUG_LoadModule32( const char* name, DWORD base );
+extern DBG_MODULE* DEBUG_AddModule(const char* name, int type, 
+				   void* mod_addr, HMODULE hmod);
+extern DBG_MODULE* DEBUG_FindModuleByName(const char* name, int type);
+extern DBG_MODULE* DEBUG_FindModuleByHandle(HANDLE handle, int type);
+extern DBG_MODULE* DEBUG_RegisterPEModule(HMODULE, u_long load_addr, const char* name);
+extern DBG_MODULE* DEBUG_RegisterELFModule(u_long load_addr, const char* name);
+extern int DEBUG_ProcessDeferredDebug(void);
+extern void DEBUG_InfoShare(void);
+
+  /* debugger/msc.c */
+extern int DEBUG_RegisterMSCDebugInfo(DBG_MODULE* module, void* nth, unsigned long nth_ofs);
+extern int DEBUG_RegisterStabsDebugInfo(DBG_MODULE* module, void* nth, unsigned long nth_ofs);
+extern void DEBUG_InitCVDataTypes(void);
+extern int DEBUG_ProcessMSCDebugInfo(DBG_MODULE* module);
+
   /* debugger/registers.c */
 extern void DEBUG_SetRegister( enum debug_regs reg, int val );
 extern int DEBUG_GetRegister( enum debug_regs reg );
@@ -330,13 +379,6 @@
 extern int DEBUG_ParseStabs(char * addr, unsigned int load_offset, unsigned int staboff, 
 			    int stablen, unsigned int strtaboff, int strtablen);
 
-  /* debugger/msc.c */
-extern int DEBUG_RegisterDebugInfo( HMODULE, const char *);
-extern int DEBUG_ProcessDeferredDebug(void);
-extern int DEBUG_RegisterELFDebugInfo(int load_addr, u_long size, const char * name);
-extern void DEBUG_InfoShare(void);
-extern void DEBUG_InitCVDataTypes(void);
-
   /* debugger/types.c */
 extern int DEBUG_nchar;
 extern void DEBUG_InitTypes(void);
diff --git a/debugger/hash.c b/debugger/hash.c
index cd6cd19..1eaf5ce 100644
--- a/debugger/hash.c
+++ b/debugger/hash.c
@@ -11,11 +11,7 @@
 #include <string.h>
 #include <limits.h>
 #include <sys/types.h>
-#include "neexe.h"
-#include "module.h"
-#include "process.h"
 #include "debugger.h"
-#include "toolhelp.h"
 
 #define NR_NAME_HASH 16384
 #ifndef PATH_MAX
@@ -771,259 +767,6 @@
 }
 
 
-/***********************************************************************
- *           DEBUG_LoadEntryPoints16
- *
- * Load the entry points of a Win16 module into the hash table.
- */
-static void DEBUG_LoadEntryPoints16( HMODULE16 hModule, NE_MODULE *pModule,
-                                     const char *name )
-{
-    DBG_VALUE	value;
-    char 	buffer[256];
-    FARPROC16	address;
-    unsigned char *cpnt = (unsigned char *)pModule + pModule->name_table;
-
-    value.type = NULL;
-    value.cookie = DV_TARGET;
-    value.addr.seg = 0;
-    value.addr.off = 0;
-
-    /* First search the resident names */
-
-    while (*cpnt)
-    {
-        cpnt += *cpnt + 1 + sizeof(WORD);
-        sprintf( buffer, "%s.%.*s", name, *cpnt, cpnt + 1 );
-        if ((address = NE_GetEntryPoint(hModule, *(WORD *)(cpnt + *cpnt + 1))))
-        {
-            value.addr.seg = HIWORD(address);
-            value.addr.off = LOWORD(address);
-            DEBUG_AddSymbol( buffer, &value, NULL, SYM_WIN32 | SYM_FUNC );
-        }
-    }
-
-    /* Now search the non-resident names table */
-
-    if (!pModule->nrname_handle) return;  /* No non-resident table */
-    cpnt = (char *)GlobalLock16( pModule->nrname_handle );
-    while (*cpnt)
-    {
-        cpnt += *cpnt + 1 + sizeof(WORD);
-        sprintf( buffer, "%s.%.*s", name, *cpnt, cpnt + 1 );
-        if ((address = NE_GetEntryPoint(hModule, *(WORD *)(cpnt + *cpnt + 1))))
-        {
-            value.addr.seg = HIWORD(address);
-            value.addr.off = LOWORD(address);
-            DEBUG_AddSymbol( buffer, &value, NULL, SYM_WIN32 | SYM_FUNC );
-        }
-    }
-}
-
-
-/***********************************************************************
- *           DEBUG_LoadEntryPoints32
- *
- * Load the entry points of a Win32 module into the hash table.
- */
-static void DEBUG_LoadEntryPoints32( HMODULE hModule, const char *name )
-{
-#define RVA(x) (hModule+(DWORD)(x))
-
-    DBG_VALUE	value;
-    char buffer[256];
-    int i, j;
-    IMAGE_SECTION_HEADER *pe_seg;
-    IMAGE_EXPORT_DIRECTORY *exports;
-    IMAGE_DATA_DIRECTORY *dir;
-    WORD *ordinals;
-    void **functions;
-    const char **names;
- 
-    value.type = NULL;
-    value.cookie = DV_TARGET;
-    value.addr.seg = 0;
-    value.addr.off = 0;
-
-    /* Add start of DLL */
-
-    value.addr.off = hModule;
-    DEBUG_AddSymbol( name, &value, NULL, SYM_WIN32 | SYM_FUNC );
-
-    /* Add entry point */
-
-    sprintf( buffer, "%s.EntryPoint", name );
-    value.addr.off = (DWORD)RVA_PTR( hModule, OptionalHeader.AddressOfEntryPoint );
-    DEBUG_AddSymbol( buffer, &value, NULL, SYM_WIN32 | SYM_FUNC );
-
-    /* Add start of sections */
-
-    pe_seg = PE_SECTIONS(hModule);
-    for (i = 0; i < PE_HEADER(hModule)->FileHeader.NumberOfSections; i++)
-    {
-        sprintf( buffer, "%s.%s", name, pe_seg->Name );
-        value.addr.off = RVA(pe_seg->VirtualAddress );
-        DEBUG_AddSymbol( buffer, &value, NULL, SYM_WIN32 | SYM_FUNC );
-        pe_seg++;
-    }
-
-    /* Add exported functions */
-
-    dir = &PE_HEADER(hModule)->OptionalHeader.
-                                   DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
-    if (dir->Size)
-    {
-      exports   = (IMAGE_EXPORT_DIRECTORY *)RVA( dir->VirtualAddress );
-      ordinals  = (WORD *)RVA( exports->AddressOfNameOrdinals );
-      names     = (const char **)RVA( exports->AddressOfNames );
-      functions = (void **)RVA( exports->AddressOfFunctions );
-
-      for (i = 0; i < exports->NumberOfNames; i++)
-      {
-          if (!names[i]) continue;
-          sprintf( buffer, "%s.%s", name, (char *)RVA(names[i]) );
-          value.addr.off = RVA( functions[ordinals[i]] );
-        DEBUG_AddSymbol( buffer, &value, NULL, SYM_WIN32 | SYM_FUNC );
-      }
-
-      for (i = 0; i < exports->NumberOfFunctions; i++)
-      {
-          if (!functions[i]) continue;
-          /* Check if we already added it with a name */
-          for (j = 0; j < exports->NumberOfNames; j++)
-            if ((ordinals[j] == i) && names[j]) break;
-          if (j < exports->NumberOfNames) continue;
-          sprintf( buffer, "%s.%ld", name, i + exports->Base );
-          value.addr.off = (DWORD)RVA( functions[i] );
-          DEBUG_AddSymbol( buffer, &value, NULL, SYM_WIN32 | SYM_FUNC );
-      }
-    }
-    DEBUG_RegisterDebugInfo(hModule, name);
-#undef RVA
-}
-
-typedef struct tag_lmr{
-   char*		module_name;
-   BOOL			is16;
-   struct tag_lmr*	next;
-} DBG_LoadedModuleRef;
-
-typedef struct {
-   int			rowcount;
-   int			first;
-   const char* 		pfx;
-} DBG_LEPData;
-
-static	BOOL	DEBUG_LEPHelper(const char* mod_name, BOOL is16, DBG_LEPData* lep)
-{
-static	DBG_LoadedModuleRef* 	lmr = NULL;
-    DBG_LoadedModuleRef*	p;
-    DBG_LoadedModuleRef**	pp1;
-    DBG_LoadedModuleRef*	p2;
-    int				len = strlen(mod_name);
-    int				cmp;
-
-    for (p = lmr; p; p = p->next) {
-        cmp = strcasecmp(p->module_name, mod_name);
-	if (cmp == 0 && p->is16 == is16)
-	   return FALSE;
-	if (cmp >= 0)
-	   break;
-    }
-
-    if (!lep->first) {
-        if (lep->pfx) fprintf( stderr, lep->pfx );
-	fprintf( stderr, "   " );
-	lep->first++;
-	lep->rowcount = 3;
-    }
-
-    if ((lep->rowcount + len) > 76)
-    {
-        fprintf( stderr, "\n   ");
-	lep->rowcount = 3;
-    }
-    fprintf( stderr, " %s", mod_name );
-    lep->rowcount += len + 1;
-
-    p = DBG_alloc(sizeof(*lmr));
-    p->module_name = DBG_strdup(mod_name);
-    p->is16 = is16;
-    
-    p2 = NULL;
-    for (pp1 = &lmr; *pp1; pp1 = &(*pp1)->next) {
-        if (strcasecmp((*pp1)->module_name, mod_name) > 0)
-	    break;
-       p2 = *pp1;
-    }
-    if (p2 == NULL) 
-    {
-        p->next = lmr;
-	lmr = p;
-    } 
-    else if (*pp1 == NULL) 
-    {
-        p->next = NULL;
-	*pp1 = p;
-    } 
-    else 
-    {
-       p->next = *pp1;
-       p2->next = p;
-    }
-
-    return TRUE;
-}
-
-/***********************************************************************
- *           DEBUG_LoadEntryPoints
- *
- * Load the entry points of all the modules into the hash table.
- */
-int DEBUG_LoadEntryPoints(const char* pfx)
-{
-    MODULEENTRY	entry;
-    NE_MODULE*	pModule;
-    BOOL 	ok;
-    WINE_MODREF*wm;
-    DBG_LEPData	lep;
-    PDB*	current = PROCESS_Current();
-
-    lep.first = 0;
-    lep.pfx = pfx;
-
-    /* FIXME: we assume that a module is never removed from memory */
-    
-    for (ok = ModuleFirst16(&entry); ok; ok = ModuleNext16(&entry))
-    {
-        if (!(pModule = NE_GetPtr( entry.hModule ))) continue;
-        if (!(pModule->flags & NE_FFLAGS_WIN32) &&  /* NE module */
-	    DEBUG_LEPHelper( entry.szModule, TRUE, &lep ))
-	    DEBUG_LoadEntryPoints16( entry.hModule, pModule, entry.szModule );
-    }
-
-    for (wm = current->modref_list; wm; wm=wm->next)
-    {
-        if ((wm->flags & WINE_MODREF_INTERNAL))
-        {
-            if (DEBUG_LEPHelper( wm->modname, FALSE, &lep ))
-               DEBUG_LoadEntryPoints32( wm->module, wm->modname );
-        }
-    }
-    if (lep.first) fprintf( stderr, " $");
-    for (wm = current->modref_list; wm; wm=wm->next)
-    {
-        if (!(wm->flags & WINE_MODREF_INTERNAL))
-        {
-            if (DEBUG_LEPHelper( wm->modname, FALSE, &lep ))
-               DEBUG_LoadEntryPoints32( wm->module, wm->modname );
-        }
-    }
-    if (lep.first) fprintf( stderr, "\n" );
-    return lep.first;
-}
-
-
 void
 DEBUG_AddLineNumber( struct name_hash * func, int line_num, 
 		     unsigned long offset )
diff --git a/debugger/info.c b/debugger/info.c
index 7f1f64f..19ca90c 100644
--- a/debugger/info.c
+++ b/debugger/info.c
@@ -344,16 +344,6 @@
    DBG_free(cw.table);
 }
 
-void DEBUG_DumpModule(DWORD mod)
-{
-   fprintf(stderr, "No longer doing info module '0x%08lx'\n", mod);
-}
-
-void DEBUG_WalkModules(void)
-{
-   fprintf(stderr, "No longer walking modules list\n");
-}
-
 void DEBUG_DumpQueue(DWORD q)
 {
    fprintf(stderr, "No longer doing info queue '0x%08lx'\n", q);
diff --git a/debugger/module.c b/debugger/module.c
new file mode 100644
index 0000000..f73dfb2
--- /dev/null
+++ b/debugger/module.c
@@ -0,0 +1,519 @@
+/* -*- tab-width: 8; c-basic-offset: 4 -*- */
+/*
+ * File module.c - module handling for the wine debugger
+ *
+ * Copyright (C) 1993, Eric Youngdale.
+ * 		 2000, Eric Pouech
+ */
+#include "config.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "neexe.h"
+#include "peexe.h"
+#include "module.h"
+#include "debugger.h"
+#include "toolhelp.h"
+
+/***********************************************************************
+ * Creates and links a new module to the current process 
+ *
+ */
+DBG_MODULE*	DEBUG_AddModule(const char* name, int type, 
+				void* mod_addr, HMODULE hmodule)
+{
+    DBG_MODULE*	wmod;
+
+    if (!(wmod = (DBG_MODULE*)DBG_alloc(sizeof(*wmod))))
+	return NULL;
+
+    memset(wmod, 0, sizeof(*wmod));
+
+    wmod->next = DEBUG_CurrProcess->modules;
+    wmod->status = DM_STATUS_NEW;
+    wmod->type = type;
+    wmod->load_addr = mod_addr;
+    wmod->handle = hmodule;
+    wmod->dbg_index = DEBUG_CurrProcess->next_index;
+    wmod->module_name = DBG_strdup(name);
+    DEBUG_CurrProcess->modules = wmod;
+
+    return wmod;
+}
+
+/***********************************************************************
+ *	DEBUG_FindModuleByName
+ *
+ */
+DBG_MODULE*	DEBUG_FindModuleByName(const char* name, int type)
+{
+    DBG_MODULE*	wmod;
+    
+    for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
+	if ((type == DM_TYPE_UNKNOWN || type == wmod->type) &&
+	    !strcasecmp(name, wmod->module_name)) break;
+    }
+    return wmod;
+}
+
+/***********************************************************************
+ *	DEBUG_FindModuleByAddr
+ *
+ * either the addr where module is loaded, or any address inside the 
+ * module
+ */
+DBG_MODULE*	DEBUG_FindModuleByAddr(void* addr, int type)
+{
+    DBG_MODULE*	wmod;
+    DBG_MODULE*	res = NULL;
+    
+    for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
+	if ((type == DM_TYPE_UNKNOWN || type == wmod->type) &&
+	    (u_long)addr >= (u_long)wmod->load_addr &&
+	    (!res || res->load_addr < wmod->load_addr))
+	    res = wmod;
+    }
+    return res;
+}
+
+/***********************************************************************
+ *		DEBUG_FindModuleByHandle
+ */
+DBG_MODULE*	DEBUG_FindModuleByHandle(HANDLE handle, int type)
+{
+    DBG_MODULE*	wmod;
+    
+    for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
+	if ((type == DM_TYPE_UNKNOWN || type == wmod->type) && handle == wmod->handle) break;
+    }
+    return wmod;
+}
+
+/***********************************************************************
+ *			DEBUG_RegisterELFModule
+ *
+ * ELF modules are also entered into the list - this is so that we
+ * can make 'info shared' types of displays possible.
+ */
+DBG_MODULE* DEBUG_RegisterELFModule(u_long load_addr, const char* name)
+{
+    DBG_MODULE*	wmod = DEBUG_AddModule(name, DM_TYPE_ELF, (void*)load_addr, 0);
+
+    if (!wmod) return NULL;
+
+    wmod->status = DM_STATUS_LOADED;
+    DEBUG_CurrProcess->next_index++;
+
+    return wmod;
+}
+
+/***********************************************************************
+ *			DEBUG_RegisterPEModule
+ *
+ */
+DBG_MODULE* DEBUG_RegisterPEModule(HMODULE hModule, u_long load_addr, const char *module_name)
+{
+    DBG_MODULE*	wmod = DEBUG_AddModule(module_name, DM_TYPE_PE, (void*)load_addr, hModule);
+
+    if (!wmod) return NULL;
+
+    DEBUG_CurrProcess->next_index++;
+
+    return wmod;
+}
+
+/***********************************************************************
+ *			DEBUG_RegisterNEModule
+ *
+ */
+DBG_MODULE* DEBUG_RegisterNEModule(HMODULE hModule, void* load_addr, const char *module_name)
+{
+    DBG_MODULE*	wmod = DEBUG_AddModule(module_name, DM_TYPE_NE, load_addr, hModule);
+
+    if (!wmod) return NULL;
+
+    wmod->status = DM_STATUS_LOADED;
+    DEBUG_CurrProcess->next_index++;
+    return wmod;
+}
+
+/***********************************************************************
+ *           DEBUG_GetEP16
+ *
+ * Helper function fo DEBUG_LoadModuleEPs16:
+ *	finds the address of a given entry point from a given module
+ */
+static BOOL DEBUG_GetEP16(char* moduleAddr, const NE_MODULE* module, 
+			  WORD ordinal, DBG_ADDR* addr)
+{
+    void*		idx;
+    ET_ENTRY		entry;
+    ET_BUNDLE		bundle;
+    SEGTABLEENTRY	ste;
+
+    bundle.next = module->entry_table;
+    do {
+	if (!bundle.next)
+	    return FALSE;
+	idx = moduleAddr + bundle.next;
+	if (!DEBUG_READ_MEM_VERBOSE(idx, &bundle, sizeof(bundle)))
+	    return FALSE;
+    } while ((ordinal < bundle.first + 1) || (ordinal > bundle.last));
+    
+    if (!DEBUG_READ_MEM_VERBOSE((char*)idx + sizeof(ET_BUNDLE) + 
+				(ordinal - bundle.first - 1) * sizeof(ET_ENTRY), 
+				&entry, sizeof(ET_ENTRY)))
+	return FALSE;
+    
+    addr->seg = entry.segnum;
+    addr->off = entry.offs;
+    
+    if (addr->seg == 0xfe) addr->seg = 0xffff;  /* constant entry */
+    else {
+	if (!DEBUG_READ_MEM_VERBOSE(moduleAddr + module->seg_table + 
+				    sizeof(ste) * (addr->seg - 1),
+				    &ste, sizeof(ste)))
+	    return FALSE;
+	addr->seg = GlobalHandleToSel16(ste.hSeg);
+    }
+    return TRUE;
+}
+
+/***********************************************************************
+ *           DEBUG_LoadModule16
+ *
+ * Load the entry points of a Win16 module into the hash table.
+ */
+static void DEBUG_LoadModule16(HMODULE hModule, NE_MODULE* module, char* moduleAddr, const char* name)
+{
+    DBG_VALUE	value;
+    BYTE	buf[1 + 256 + 2];
+    char 	epname[512];
+    char*	cpnt;
+    DBG_MODULE*	wmod;
+
+    wmod = DEBUG_RegisterNEModule(hModule, moduleAddr, name);
+
+    value.type = NULL;
+    value.cookie = DV_TARGET;
+    value.addr.seg = 0;
+    value.addr.off = 0;
+    
+    cpnt = moduleAddr + module->name_table;
+    
+    /* First search the resident names */
+    
+    /* skip module name */
+    if (!DEBUG_READ_MEM_VERBOSE(cpnt, buf, sizeof(buf)) || !buf[0])
+	return;
+    cpnt += 1 + buf[0] + sizeof(WORD);
+    
+    while (DEBUG_READ_MEM_VERBOSE(cpnt, buf, sizeof(buf)) && buf[0]) {
+	sprintf(epname, "%s.%.*s", name, buf[0], &buf[1]);
+	if (DEBUG_GetEP16(moduleAddr, module, *(WORD*)&buf[1 + buf[0]], &value.addr)) {
+	    DEBUG_AddSymbol(epname, &value, NULL, SYM_WIN32 | SYM_FUNC);
+	}
+	cpnt += buf[0] + 1 + sizeof(WORD);
+    }
+    
+    /* Now search the non-resident names table */
+    if (!module->nrname_handle) return;  /* No non-resident table */
+    cpnt = (char *)GlobalLock16(module->nrname_handle);
+    while (DEBUG_READ_MEM_VERBOSE(cpnt, buf, sizeof(buf)) && buf[0]) {
+	sprintf(epname, "%s.%.*s", name, buf[0], &buf[1]);
+	if (DEBUG_GetEP16(moduleAddr, module, *(WORD*)&buf[1 + buf[0]], &value.addr)) {
+	    DEBUG_AddSymbol(epname, &value, NULL, SYM_WIN32 | SYM_FUNC);
+	}
+	cpnt += buf[0] + 1 + sizeof(WORD);
+    }
+    GlobalUnlock16(module->nrname_handle);
+}
+
+/***********************************************************************
+ *			DEBUG_LoadModule32
+ */
+void	DEBUG_LoadModule32(const char* name, DWORD base)
+{
+    DBG_VALUE			value;
+    char			buffer[256];
+    char			bufstr[256];
+    int 			i;
+    IMAGE_NT_HEADERS		pe_header;
+    DWORD			pe_header_ofs;
+    IMAGE_SECTION_HEADER 	pe_seg;
+    DWORD			pe_seg_ofs;
+    IMAGE_DATA_DIRECTORY 	dir;
+    DWORD			dir_ofs;
+    DBG_MODULE*			wmod;
+
+    /* FIXME: we make the assumption that hModule == base */
+    wmod = DEBUG_RegisterPEModule((HMODULE)base, base, name);
+
+    fprintf(stderr, "Registring 32bit DLL '%s' at %08lx\n", name, base);
+    
+    value.type = NULL;
+    value.cookie = DV_TARGET;
+    value.addr.seg = 0;
+    value.addr.off = 0;
+    
+    /* grab PE Header */
+    if (!DEBUG_READ_MEM_VERBOSE((void*)(base + OFFSET_OF(IMAGE_DOS_HEADER, e_lfanew)), 
+				&pe_header_ofs, sizeof(pe_header_ofs)) ||
+	!DEBUG_READ_MEM_VERBOSE((void*)(base + pe_header_ofs), 
+				&pe_header, sizeof(pe_header)))
+	return;
+    
+    if (wmod) {
+	DEBUG_RegisterMSCDebugInfo(wmod, &pe_header, pe_header_ofs);	
+	DEBUG_RegisterStabsDebugInfo(wmod, &pe_header, pe_header_ofs);
+    }
+
+    /* Add start of DLL */
+    value.addr.off = base;
+    DEBUG_AddSymbol(name, &value, NULL, SYM_WIN32 | SYM_FUNC);
+    
+    /* Add entry point */
+    sprintf(buffer, "%s.EntryPoint", name);
+    value.addr.off = base + pe_header.OptionalHeader.AddressOfEntryPoint;
+    DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
+
+    /* Add start of sections */
+    pe_seg_ofs = pe_header_ofs + OFFSET_OF(IMAGE_NT_HEADERS, OptionalHeader) +
+	pe_header.FileHeader.SizeOfOptionalHeader;
+    
+    for (i = 0; i < pe_header.FileHeader.NumberOfSections; i++, pe_seg_ofs += sizeof(pe_seg)) {
+	if (!DEBUG_READ_MEM_VERBOSE((void*)(base + pe_seg_ofs), &pe_seg, sizeof(pe_seg)) ||
+	    !DEBUG_READ_MEM_VERBOSE((void*)pe_seg.Name, bufstr, sizeof(bufstr)))
+	    continue;
+	bufstr[sizeof(bufstr) - 1] = 0;
+	sprintf(buffer, "%s.%s", name, bufstr);
+	value.addr.off = base + pe_seg.VirtualAddress;
+	DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
+    }
+    
+    /* Add exported functions */
+    dir_ofs = pe_header_ofs + 
+	OFFSET_OF(IMAGE_NT_HEADERS, 
+		  OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]);
+    if (DEBUG_READ_MEM_VERBOSE((void*)(base + dir_ofs), &dir, sizeof(dir)) && dir.Size) {
+	IMAGE_EXPORT_DIRECTORY 	exports;
+	WORD*			ordinals = NULL;
+	void**			functions = NULL;
+	DWORD*			names = NULL;
+	int			j;
+	
+	if (DEBUG_READ_MEM_VERBOSE((void*)(base + dir.VirtualAddress), 
+				   &exports, sizeof(exports)) &&
+	    
+	    ((functions = DBG_alloc(sizeof(functions[0]) * exports.NumberOfFunctions))) &&
+	    DEBUG_READ_MEM_VERBOSE((void*)(base + (DWORD)exports.AddressOfFunctions),
+				   functions, sizeof(functions[0]) * exports.NumberOfFunctions) &&
+	    
+	    ((ordinals = DBG_alloc(sizeof(ordinals[0]) * exports.NumberOfNames))) &&
+	    DEBUG_READ_MEM_VERBOSE((void*)(base + (DWORD)exports.AddressOfNameOrdinals),
+				   ordinals, sizeof(ordinals[0]) * exports.NumberOfNames) &&
+	    
+	    ((names = DBG_alloc(sizeof(names[0]) * exports.NumberOfNames))) &&
+	    DEBUG_READ_MEM_VERBOSE((void*)(base + (DWORD)exports.AddressOfNames),
+				   names, sizeof(names[0]) * exports.NumberOfNames)) {
+	    
+	    for (i = 0; i < exports.NumberOfNames; i++) {
+		if (!names[i] ||
+		    !DEBUG_READ_MEM_VERBOSE((void*)(base + names[i]), bufstr, sizeof(bufstr)))
+		    continue;
+		bufstr[sizeof(bufstr) - 1] = 0;
+		sprintf(buffer, "%s.%s", name, bufstr);
+		value.addr.off = base + (DWORD)functions[ordinals[i]];
+		DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
+	    }
+	    
+	    for (i = 0; i < exports.NumberOfFunctions; i++) {
+		if (!functions[i]) continue;
+		/* Check if we already added it with a name */
+		for (j = 0; j < exports.NumberOfNames; j++)
+		    if ((ordinals[j] == i) && names[j]) break;
+		if (j < exports.NumberOfNames) continue;
+		sprintf(buffer, "%s.%ld", name, i + exports.Base);
+		value.addr.off = base + (DWORD)functions[i];
+		DEBUG_AddSymbol(buffer, &value, NULL, SYM_WIN32 | SYM_FUNC);
+	    }
+	}
+	DBG_free(functions);
+	DBG_free(ordinals);
+	DBG_free(names);
+    }
+}
+
+/***********************************************************************
+ *           	DEBUG_LoadEntryPoints
+ *
+ * Load the entry points of all the modules into the hash table.
+ */
+int DEBUG_LoadEntryPoints(const char* pfx)
+{
+    MODULEENTRY	entry;
+    NE_MODULE	module;
+    void*	moduleAddr;
+    int		first = 0;
+    int		rowcount = 0;
+    int		len;
+
+    /* FIXME: we assume that a module is never removed from memory */
+    if (ModuleFirst16(&entry)) do {
+	if (DEBUG_FindModuleByName(entry.szModule, DM_TYPE_UNKNOWN) ||
+	    !(moduleAddr = NE_GetPtr(entry.hModule)) ||
+	    !DEBUG_READ_MEM_VERBOSE(moduleAddr, &module, sizeof(module)) ||
+	    (module.flags & NE_FFLAGS_WIN32) /* NE module */)
+	    continue;
+	if (!first) {
+	    if (pfx) fprintf(stderr, pfx);
+	    fprintf(stderr, "   ");
+	    rowcount = 3 + (pfx ? strlen(pfx) : 0);
+	    first = 1;
+	}
+	
+	len = strlen(entry.szModule);
+	if ((rowcount + len) > 76) {
+	    fprintf(stderr, "\n   ");
+	    rowcount = 3;
+	}
+	fprintf(stderr, " %s", entry.szModule);
+	rowcount += len + 1;
+	
+	DEBUG_LoadModule16(entry.hModule, &module, moduleAddr, entry.szModule);
+    } while (ModuleNext16(&entry));
+    
+    if (first) fprintf(stderr, "\n"); 
+    return first;
+}
+
+/***********************************************************************
+ *		DEBUG_ProcessDeferredDebug
+ *
+ */
+int DEBUG_ProcessDeferredDebug(void)
+{
+    DBG_MODULE*	wmod;
+    int		sts;
+    int		last_proc = -1;
+    int		need_print = 0;
+    int		rowcount = 0;
+    int		len;
+
+    for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
+	if (wmod->status != DM_STATUS_NEW) continue;
+	
+	if (last_proc != wmod->dbg_index) {
+	    if (!need_print) {
+		fprintf(stderr, "DeferredDebug for:");
+		rowcount = 18;
+		need_print = 1;
+	    }
+	    if (rowcount + (len = strlen(wmod->module_name)) > 76) {
+		rowcount = 0;
+		fprintf(stderr, "\n");
+	    } else {
+		fprintf(stderr, " ");
+		rowcount++;
+	    }
+	    rowcount += len;
+	    fprintf(stderr, wmod->module_name);
+	    last_proc = wmod->dbg_index;
+	}
+	
+	sts = (wmod->extra_info) ? DEBUG_ProcessMSCDebugInfo(wmod) : TRUE;
+	wmod->status = (sts) ? DM_STATUS_LOADED : DM_STATUS_ERROR;
+    }
+    if (need_print) fprintf(stderr, "\n");
+    return TRUE;
+}
+
+/***********************************************************************
+ *           DEBUG_InfoShare
+ *
+ * Display shared libarary information.
+ */
+void DEBUG_InfoShare(void)
+{
+    DBG_MODULE*	wmod;
+    const char*	xtype;
+
+    fprintf(stderr, "Address\t\tModule\tName\n");
+
+    for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
+	switch (wmod->type) {
+	case DM_TYPE_NE:	xtype = "NE"; break;
+	case DM_TYPE_PE:	xtype = "PE"; break;
+	case DM_TYPE_ELF:	xtype = "ELF"; break;
+	default:		xtype = "???"; break;
+	}
+	fprintf(stderr, "0x%8.8x\t(%s)\t%s\n", (unsigned int)wmod->load_addr,
+		xtype, wmod->module_name);
+    }
+}
+
+static const char*	DEBUG_GetModuleType(int type)
+{
+    switch (type) {
+    case DM_TYPE_NE:	return "NE";
+    case DM_TYPE_PE:	return "PE";
+    case DM_TYPE_ELF:	return "ELF";
+    default:		return "???";;
+    }
+}
+
+static const char*	DEBUG_GetModuleStatus(int status)
+{
+    switch (status) {
+    case DM_STATUS_NEW:		return "deferred"; 
+    case DM_STATUS_LOADED:	return "ok"; 
+    case DM_STATUS_ERROR:	return "error"; 
+    default:			return "???"; 
+    }
+}
+
+/***********************************************************************
+ *           DEBUG_
+ * Display information about a given module (DLL or EXE)
+ */
+void DEBUG_DumpModule(DWORD mod)
+{
+    DBG_MODULE*	wmod;
+
+    if (!(wmod = DEBUG_FindModuleByHandle(mod, DM_TYPE_UNKNOWN)) &&
+	!(wmod = DEBUG_FindModuleByAddr((void*)mod, DM_TYPE_UNKNOWN))) {
+	fprintf(stderr, "'0x%08lx' is not a valid module handle or address\n", mod);
+	return;
+    }
+
+    fprintf(stderr, "Module '%s' (handle=0x%08x) at 0x%8.8x (%s/%s)\n",
+	    wmod->module_name, wmod->handle, (unsigned int)wmod->load_addr,
+	    DEBUG_GetModuleType(wmod->type), DEBUG_GetModuleStatus(wmod->status));
+}
+
+/***********************************************************************
+ *           DEBUG_WalkModules
+ *
+ * Display information about all modules (DLLs and EXEs)
+ */
+void DEBUG_WalkModules(void)
+{
+    DBG_MODULE*	wmod;
+    const char*	xtype;
+
+    fprintf(stderr, "Address\t\tModule\tName\n");
+
+    for (wmod = DEBUG_CurrProcess->modules; wmod; wmod = wmod->next) {
+	switch (wmod->type) {
+	case DM_TYPE_NE:	xtype = "NE"; break;
+	case DM_TYPE_PE:	xtype = "PE"; break;
+	case DM_TYPE_ELF:	continue;
+	default:		xtype = "???"; break;
+	}
+	
+	fprintf(stderr, "0x%8.8x\t(%s)\t%s\n", 
+		(unsigned int)wmod->load_addr, DEBUG_GetModuleType(wmod->type), 
+		wmod->module_name);
+    }
+}
+
diff --git a/debugger/msc.c b/debugger/msc.c
index 8842f34..24bc680 100644
--- a/debugger/msc.c
+++ b/debugger/msc.c
@@ -36,9 +36,19 @@
 #include "peexe.h"
 #include "file.h"
 
+typedef struct {
+   IMAGE_DEBUG_DIRECTORY	dbgdir;
+   u_long			sect_ofs;
+   int				nsect;
+   char*			dbg_info;
+   int				dbg_size;
+} MSC_DBG_INFO;
+
+#define	MSC_INFO(module)	((MSC_DBG_INFO*)((module)->extra_info))
+
 /*
-    *dbg_filename must be at least MAX_PATHNAME_LEN bytes in size
-*/
+ * dbg_filename must be at least MAX_PATHNAME_LEN bytes in size
+ */
 static void LocateDebugInfoFile(char *filename, char *dbg_filename)
 {
     char	  *str1 = DBG_alloc(MAX_PATHNAME_LEN*10);
@@ -75,13 +85,6 @@
     DBG_free(str2);
     return;
 }
-/*
- * This is an index we use to keep track of the debug information
- * when we have multiple sources.  We use the same database to also
- * allow us to do an 'info shared' type of deal, and we use the index
- * to eliminate duplicates.
- */
-static int DEBUG_next_index = 0;
 
 union any_size
 {
@@ -690,30 +693,6 @@
 
 
 /*
- ********************************************************************
- */
-struct deferred_debug_info
-{
-	struct deferred_debug_info	* next;
-	char				* load_addr;
-	char				* module_name;
-	char				* dbg_info;
-	int				  dbg_size;
-        HMODULE                         module;
-	PIMAGE_DEBUG_DIRECTORY           dbgdir;
-        PIMAGE_SECTION_HEADER	          sectp;
-	int				  nsect;
-	short int			  dbg_index;			
-	char				  status;
-};
-
-#define DF_STATUS_NEW		0
-#define DF_STATUS_LOADED	1
-#define DF_STATUS_ERROR		2
-
-struct deferred_debug_info * dbglist = NULL;
-
-/*
  * A simple macro that tells us whether a given COFF symbol is a
  * function or not.
  */
@@ -1295,36 +1274,37 @@
  * We don't fully process it here for performance reasons.
  */
 int
-DEBUG_RegisterDebugInfo( HMODULE hModule, const char *module_name)
+DEBUG_RegisterMSCDebugInfo(DBG_MODULE* module, void* _nth, unsigned long nth_ofs)
 {
   int			  has_codeview = FALSE;
   int			  rtn = FALSE;
-  int			  orig_size;
-  PIMAGE_DEBUG_DIRECTORY dbgptr;
-  u_long v_addr, size;
-  PIMAGE_NT_HEADERS	  nth  = PE_HEADER(hModule);
+  IMAGE_DEBUG_DIRECTORY   dbg;
+  u_long                  v_addr, size, orig_size;
+  PIMAGE_NT_HEADERS	  nth = (PIMAGE_NT_HEADERS)_nth;
 
-  size = nth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
-  if (size) {
+  orig_size = nth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
+  if (orig_size) {
     v_addr = nth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
-    dbgptr = (PIMAGE_DEBUG_DIRECTORY) (hModule + v_addr);
-    orig_size = size;
-    for(; size >= sizeof(*dbgptr); size -= sizeof(*dbgptr), dbgptr++ )
+    for(size = orig_size; size >= sizeof(dbg); size -= sizeof(dbg))
     {
-      switch(dbgptr->Type)
+      if (!DEBUG_READ_MEM_VERBOSE((void*)(module->load_addr + v_addr), &dbg, sizeof(dbg))) continue;
+
+      switch(dbg.Type)
 	{
 	case IMAGE_DEBUG_TYPE_CODEVIEW:
 	case IMAGE_DEBUG_TYPE_MISC:
 	  has_codeview = TRUE;
 	  break;
 	}
+      v_addr += sizeof(dbg);
     }
 
-    size = orig_size;
-    dbgptr = (PIMAGE_DEBUG_DIRECTORY) (hModule + v_addr);
-    for(; size >= sizeof(*dbgptr); size -= sizeof(*dbgptr), dbgptr++ )
+    v_addr = nth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+    for(size = orig_size; size >= sizeof(dbg); size -= sizeof(dbg))
     {
-      switch(dbgptr->Type)
+      if (!DEBUG_READ_MEM_VERBOSE((void*)(module->load_addr + v_addr), &dbg, sizeof(dbg))) continue;
+
+      switch(dbg.Type)
 	{
 	case IMAGE_DEBUG_TYPE_COFF:
 	  /*
@@ -1352,22 +1332,14 @@
 	   * it just points to itself, and we can ignore this.
 	   */
 
-
-
-
-
-
-          if(   (dbgptr->Type != IMAGE_DEBUG_TYPE_MISC) ||
-                (PE_HEADER(hModule)->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED) != 0 )
+          if(   (dbg.Type != IMAGE_DEBUG_TYPE_MISC) ||
+                (nth->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED) != 0 )
             {
-                char                 fn[PATH_MAX];
-                int                  fd = -1;
-                DOS_FULL_NAME        full_name;
-                struct deferred_debug_info*      deefer = (struct deferred_debug_info *) DBG_alloc(sizeof(*deefer));
- 
-                deefer->module    = hModule;
-                deefer->load_addr = (char *)hModule;
- 
+                char            fn[PATH_MAX];
+                int             fd = -1;
+                DOS_FULL_NAME   full_name;
+		char*		dbg_info;
+
                 /*
                  * Read the important bits.  What we do after this depends
                  * upon the type, but this is always enough so we are able
@@ -1377,60 +1349,72 @@
                  * the DataDirectory array's content. One its entry contains the *beloved*
                  * debug information. (Note the DataDirectory is mapped, not its content)
                  */
- 
-                 if (GetModuleFileNameA(hModule, fn, sizeof(fn)) > 0 &&
+		/* FIXME: the module->handle value is not usable in the debugger's process */
+		if (GetModuleFileNameA(module->handle, fn, sizeof(fn)) > 0 &&
                     DOSFS_GetFullName(fn, TRUE, &full_name) &&
                     (fd = open(full_name.long_name, O_RDONLY)) > 0)
-                {
-                    deefer->dbg_info = mmap(NULL, dbgptr->SizeOfData,
-                                            PROT_READ, MAP_PRIVATE, fd, dbgptr->PointerToRawData);
+		{
+                    dbg_info = mmap(NULL, dbg.SizeOfData,
+				    PROT_READ, MAP_PRIVATE, fd, dbg.PointerToRawData);
                     close(fd);
-                    if( deefer->dbg_info == (char *) 0xffffffff )
-                    {
-                        DBG_free(deefer);
-                        break;
-                    }
+                    if( dbg_info == (char *) 0xffffffff ) break;
                 }
                 else
                 {
-                    DBG_free(deefer);
-                    fprintf(stderr, " (not mapped: fn=%s, lfn=%s, fd=%d)", fn, full_name.long_name, fd);
+                    fprintf(stderr, " (not mapped: fn='%s', lfn='%s', fd=%d)\n", fn, full_name.long_name, fd);
                     break;
                 }
-                deefer->dbg_size = dbgptr->SizeOfData;
-                deefer->dbgdir = dbgptr;
-                deefer->next = dbglist;
-                deefer->status = DF_STATUS_NEW;
-                deefer->dbg_index = DEBUG_next_index;
-                deefer->module_name = DBG_strdup(module_name);
+		if (!(module->extra_info = DBG_alloc(sizeof(MSC_DBG_INFO))))
+		    break;
 
-                deefer->sectp = PE_SECTIONS(hModule);
-                deefer->nsect = PE_HEADER(hModule)->FileHeader.NumberOfSections;
-
-                dbglist = deefer;
+		MSC_INFO(module)->dbg_info = dbg_info;
+		MSC_INFO(module)->dbg_size = dbg.SizeOfData;
+                MSC_INFO(module)->dbgdir = dbg;
+                MSC_INFO(module)->sect_ofs = nth_ofs + OFFSET_OF(IMAGE_NT_HEADERS, OptionalHeader) +
+		   nth->FileHeader.SizeOfOptionalHeader;
+                MSC_INFO(module)->nsect = nth->FileHeader.NumberOfSections;
             }
 	  break;
 #if 0
 	default:
 #endif
 	}
+      v_addr += sizeof(dbg);
     }
-    DEBUG_next_index++;
+    DEBUG_CurrProcess->next_index++;
   }
-  /* look for .stabs/.stabstr sections */
-  {
-    PIMAGE_SECTION_HEADER      pe_seg = PE_SECTIONS(hModule);
-    int i,stabsize=0,stabstrsize=0;
-    unsigned int stabs=0,stabstr=0;
-    
-    for (i=0;i<nth->FileHeader.NumberOfSections;i++) {
-      if (!strcasecmp(pe_seg[i].Name,".stab")) {
-	stabs = pe_seg[i].VirtualAddress;
-	stabsize = pe_seg[i].SizeOfRawData;
-      }
-      if (!strncasecmp(pe_seg[i].Name,".stabstr",8)) {
-	stabstr = pe_seg[i].VirtualAddress;
-	stabstrsize = pe_seg[i].SizeOfRawData;
+
+  return rtn;
+}
+
+/* look for stabs information in PE header (it's how mingw compiler provides its
+ * debugging information
+ */
+int DEBUG_RegisterStabsDebugInfo(DBG_MODULE* module, void* _nth, unsigned long nth_ofs)
+{
+    IMAGE_SECTION_HEADER	pe_seg;
+    unsigned long		pe_seg_ofs;
+    int 		      	i, stabsize = 0, stabstrsize = 0;
+    unsigned int 		stabs = 0, stabstr = 0;
+    char			bufstr[256];
+    PIMAGE_NT_HEADERS		nth  = (PIMAGE_NT_HEADERS)_nth;
+
+    pe_seg_ofs = nth_ofs + OFFSET_OF(IMAGE_NT_HEADERS, OptionalHeader) +
+	nth->FileHeader.SizeOfOptionalHeader;
+
+    for (i = 0; i < nth->FileHeader.NumberOfSections; i++, pe_seg_ofs += sizeof(pe_seg)) {
+      if (!DEBUG_READ_MEM_VERBOSE((void*)(module->load_addr + pe_seg_ofs), 
+				  &pe_seg, sizeof(pe_seg)) ||
+	  !DEBUG_READ_MEM_VERBOSE((void*)pe_seg.Name, bufstr, sizeof(bufstr)))
+	  {fprintf(stderr, "err3\n");continue;}
+      bufstr[sizeof(bufstr) - 1] = 0;
+
+      if (!strcasecmp(bufstr, ".stab")) {
+	stabs = pe_seg.VirtualAddress;
+	stabsize = pe_seg.SizeOfRawData;
+      } else if (!strncasecmp(bufstr, ".stabstr", 8)) {
+	stabstr = pe_seg.VirtualAddress;
+	stabstrsize = pe_seg.SizeOfRawData;
       }
     }
     if (stabstrsize && stabsize) {
@@ -1438,56 +1422,21 @@
       /* Won't work currently, since MINGW32 uses some special typedefs
        * which we do not handle yet. Support for them is a bit difficult.
        */
-      DEBUG_ParseStabs(hModule,0,stabs,stabsize,stabstr,stabstrsize);
+       /* FIXME: load_addr is in a different address space... */
+      DEBUG_ParseStabs(module->load_addr, 0, stabs, stabsize, stabstr, stabstrsize);
 #endif
       fprintf(stderr,"(stabs not loaded)");
     }
-  }
-  return (rtn);
+    return TRUE;
 }
 
 /*
- * ELF modules are also entered into the list - this is so that we
- * can make 'info shared' types of displays possible.
- */
-int
-DEBUG_RegisterELFDebugInfo(int load_addr, u_long size, const char * name)
-{
-  struct deferred_debug_info * deefer;
-
-  deefer = (struct deferred_debug_info *) DBG_alloc(sizeof(*deefer));
-  deefer->module = 0;
-  
-  /*
-   * Read the important bits.  What we do after this depends
-   * upon the type, but this is always enough so we are able
-   * to proceed if we know what we need to do next.
-   */
-  deefer->dbg_size = size;
-  deefer->dbg_info = (char *) NULL;
-  
-  deefer->load_addr = (char *) load_addr;
-  deefer->dbgdir = NULL;
-  deefer->next = dbglist;
-  deefer->status = DF_STATUS_LOADED;
-  deefer->dbg_index = DEBUG_next_index;
-  deefer->module_name = DBG_strdup(name);
-  dbglist = deefer;
-
-  DEBUG_next_index++;
-
-  return (TRUE);
-}
-
-
-
-/*
  * Process COFF debugging information embedded in a Win32 application.
  *
  */
 static
 int
-DEBUG_ProcessCoff(struct deferred_debug_info * deefer)
+DEBUG_ProcessCoff(DBG_MODULE* module)
 {
   struct CoffAuxSection * aux;
   struct CoffDebug   * coff;
@@ -1512,7 +1461,7 @@
   int		       rtn = FALSE;
   char		     * this_file = NULL;
 
-  coff = (struct CoffDebug *) deefer->dbg_info;
+  coff = (struct CoffDebug *) MSC_INFO(module)->dbg_info;
 
   coff_symbol = (struct CoffSymbol *) ((unsigned int) coff + coff->SymbolOffset);
   coff_linetab = (struct CoffLinenum *) ((unsigned int) coff + coff->LinenumberOffset);
@@ -1679,7 +1628,7 @@
 	    }
 
 	  new_value.addr.seg = 0;
-	  new_value.addr.off = (int) (deefer->load_addr + coff_sym->Value);
+	  new_value.addr.off = (int) (module->load_addr + coff_sym->Value);
 
 	  if( curr_file->neps + 1 >= curr_file->neps_alloc )
 	    {
@@ -1719,7 +1668,7 @@
 	    }
 
 	  new_value.addr.seg = 0;
-	  new_value.addr.off = (int) (deefer->load_addr + coff_sym->Value);
+	  new_value.addr.off = (int) (module->load_addr + coff_sym->Value);
 
 #if 0
 	  fprintf(stderr, "%d: %x %s\n", i, new_value.addr.off, nampnt);
@@ -1778,7 +1727,7 @@
 	    }
 
 	  new_value.addr.seg = 0;
-	  new_value.addr.off = (int) (deefer->load_addr + coff_sym->Value);
+	  new_value.addr.off = (int) (module->load_addr + coff_sym->Value);
 
 #if 0
 	  fprintf(stderr, "%d: %x %s\n", i, new_value.addr.off, nampnt);
@@ -1860,7 +1809,7 @@
 		{
 		  if (i+1 >= coff_files[j].neps) break;
 		  DEBUG_GetSymbolAddr(coff_files[j].entries[i+1], &new_value.addr);
-		  if( (((unsigned int)deefer->load_addr +
+		  if( (((unsigned int)module->load_addr +
 		        linepnt->VirtualAddr) >= new_value.addr.off) )
 		  {
 		      i++;
@@ -1875,7 +1824,7 @@
 	      DEBUG_GetSymbolAddr(coff_files[j].entries[i], &new_value.addr);
 	      DEBUG_AddLineNumber(coff_files[j].entries[i], 
 				  linepnt->Linenum,
-				  (unsigned int) deefer->load_addr 
+				  (unsigned int) module->load_addr 
 				  + linepnt->VirtualAddr 
 				  - new_value.addr.off);
 	    }
@@ -2006,9 +1955,9 @@
 }
 
 static int
-DEBUG_SnarfCodeView(      struct deferred_debug_info * deefer,
-			  char			     * cv_data,
-			  int			       size,
+DEBUG_SnarfCodeView(      DBG_MODULE	      	      * module,
+			  char			      * cv_data,
+			  int			        size,
 			  struct codeview_linetab_hdr * linetab)
 {
   struct name_hash	* curr_func = NULL;
@@ -2025,8 +1974,12 @@
   struct name_hash	* thunk_sym = NULL;
 
   ptr.c = cv_data;
-  nsect = deefer->nsect;
-  sectp = deefer->sectp;
+  nsect = MSC_INFO(module)->nsect;
+  sectp = DBG_alloc(sizeof(*sectp) * nsect);
+  if (!sectp || 
+      !DEBUG_READ_MEM_VERBOSE(module->load_addr + MSC_INFO(module)->sect_ofs, 
+			      sectp, sizeof(*sectp) * nsect))
+     return FALSE;
 
   /*
    * Loop over the different types of records and whenever we
@@ -2075,7 +2028,7 @@
 	  memcpy(symname, sym->data.name, sym->data.namelen);
 	  new_value.addr.seg = 0;
 	  new_value.type = DEBUG_GetCVType(sym->data.symtype);
-	  new_value.addr.off = (unsigned int) deefer->load_addr + 
+	  new_value.addr.off = (unsigned int) module->load_addr + 
 	     sectp[sym->data.seg - 1].VirtualAddress + 
 	     sym->data.offset;
 	  new_value.cookie = DV_TARGET;
@@ -2105,7 +2058,7 @@
 	  memcpy(symname, sym->data32.name, sym->data32.namelen);
 	  new_value.addr.seg = 0;
 	  new_value.type = DEBUG_GetCVType(sym->data32.symtype);
-	  new_value.addr.off = (unsigned int) deefer->load_addr + 
+	  new_value.addr.off = (unsigned int) module->load_addr + 
 	     sectp[sym->data32.seg - 1].VirtualAddress + 
 	     sym->data32.offset;
 	  new_value.cookie = DV_TARGET;
@@ -2120,7 +2073,7 @@
 	  memcpy(symname, sym->thunk.name, sym->thunk.namelen);
 	  new_value.addr.seg = 0;
 	  new_value.type = NULL;
-	  new_value.addr.off = (unsigned int) deefer->load_addr + 
+	  new_value.addr.off = (unsigned int) module->load_addr + 
 	     sectp[sym->thunk.segment - 1].VirtualAddress + 
 	     sym->thunk.offset;
 	  new_value.cookie = DV_TARGET;
@@ -2136,7 +2089,7 @@
 	  memcpy(symname, sym->proc.name, sym->proc.namelen);
 	  new_value.addr.seg = 0;
 	  new_value.type = DEBUG_GetCVType(sym->proc.proctype);
-	  new_value.addr.off = (unsigned int) deefer->load_addr + 
+	  new_value.addr.off = (unsigned int) module->load_addr + 
 	     sectp[sym->proc.segment - 1].VirtualAddress + 
 	     sym->proc.offset;
 	  new_value.cookie = DV_TARGET;
@@ -2147,10 +2100,10 @@
 	   */
 	  for(i=0; linetab && linetab[i].linetab != NULL; i++)
 	    {
-	      if(     ((unsigned int) deefer->load_addr 
+	      if(     ((unsigned int) module->load_addr 
 		       + sectp[linetab[i].segno - 1].VirtualAddress 
 		       + linetab[i].start <= new_value.addr.off)
-		  &&  ((unsigned int) deefer->load_addr 
+		  &&  ((unsigned int) module->load_addr 
 		       + sectp[linetab[i].segno - 1].VirtualAddress 
 		       + linetab[i].end > new_value.addr.off) )
 		{
@@ -2202,7 +2155,7 @@
 	  memcpy(symname, sym->proc32.name, sym->proc32.namelen);
 	  new_value.addr.seg = 0;
 	  new_value.type = DEBUG_GetCVType(sym->proc32.proctype);
-	  new_value.addr.off = (unsigned int) deefer->load_addr + 
+	  new_value.addr.off = (unsigned int) module->load_addr + 
 	    sectp[sym->proc32.segment - 1].VirtualAddress + 
 	    sym->proc32.offset;
 	  new_value.cookie = DV_TARGET;
@@ -2213,10 +2166,10 @@
 	   */
 	  for(i=0; linetab && linetab[i].linetab != NULL; i++)
 	    {
-	      if(     ((unsigned int) deefer->load_addr 
+	      if(     ((unsigned int) module->load_addr 
 		       + sectp[linetab[i].segno - 1].VirtualAddress 
 		       + linetab[i].start <= new_value.addr.off)
-		  &&  ((unsigned int) deefer->load_addr 
+		  &&  ((unsigned int) module->load_addr 
 		       + sectp[linetab[i].segno - 1].VirtualAddress 
 		       + linetab[i].end > new_value.addr.off) )
 		{
@@ -2316,6 +2269,7 @@
       DBG_free(linetab);
     }
 
+  DBG_free(sectp);
   return TRUE;
 }
 
@@ -2593,7 +2547,7 @@
     }
 }
 
-int DEBUG_ProcessPDBFile( struct deferred_debug_info *deefer, char *full_filename )
+static int DEBUG_ProcessPDBFile( DBG_MODULE* module, char *full_filename )
 {
     char filename[MAX_PATHNAME_LEN];
     struct stat	statbuf;
@@ -2690,7 +2644,7 @@
      */
 
     if (      root->TimeDateStamp 
-         != ((struct CodeViewDebug *)deefer->dbg_info)->cv_timestamp ) 
+         != ((struct CodeViewDebug *)MSC_INFO(module)->dbg_info)->cv_timestamp ) 
     {
         fprintf(stderr, "-Wrong time stamp of .PDB file %s\n", filename);
         goto leave;
@@ -2719,7 +2673,7 @@
     modimage = pdb_read_file( image, toc, symbols.gsym_file );
     if ( modimage )
     {
-        DEBUG_SnarfCodeView( deefer, modimage, 
+        DEBUG_SnarfCodeView( module, modimage, 
                              toc->file[symbols.gsym_file].size, NULL );
         pdb_free( modimage );
     }
@@ -2762,7 +2716,7 @@
                 linetab = DEBUG_SnarfLinetab( modimage + symbol_size, lineno_size );
 
             if ( symbol_size )
-                DEBUG_SnarfCodeView( deefer, modimage + sizeof(DWORD),
+                DEBUG_SnarfCodeView( module, modimage + sizeof(DWORD),
                                      symbol_size - sizeof(DWORD), linetab );
 
             pdb_free( modimage );
@@ -2794,16 +2748,16 @@
 /*
  * Process DBG file which contains debug information.
  */
-/* static */
+static
 int
-DEBUG_ProcessDBGFile(struct deferred_debug_info * deefer, char * filename)
+DEBUG_ProcessDBGFile(DBG_MODULE* module, char * filename)
 {
   char			      * addr = (char *) 0xffffffff;
   char			      * codeview;
   struct CV4_DirHead	      * codeview_dir;
   struct CV4_DirEnt	      * codeview_dent;
   PIMAGE_DEBUG_DIRECTORY	dbghdr;
-  struct deferred_debug_info    deefer2;
+  DBG_MODULE			module2;
   int				fd = -1;
   int				i;
   int				j;
@@ -2847,7 +2801,7 @@
 
   pdbg = (PIMAGE_SEPARATE_DEBUG_HEADER) addr;
 
-  if( pdbg->TimeDateStamp != deefer->dbgdir->TimeDateStamp )
+  if( pdbg->TimeDateStamp != MSC_INFO(module)->dbgdir.TimeDateStamp )
     {
       fprintf(stderr, "Warning - %s has incorrect internal timestamp\n",
 	      dbg_file);
@@ -2877,12 +2831,12 @@
 		   * Dummy up a deferred debug header to handle the
 		   * COFF stuff embedded within the DBG file.
 		   */
-		  memset((char *) &deefer2, 0, sizeof(deefer2));
-		  deefer2.dbg_info = (addr + dbghdr->PointerToRawData);
-		  deefer2.dbg_size = dbghdr->SizeOfData;
-		  deefer2.load_addr = deefer->load_addr;
+		  memset((char *) &module2, 0, sizeof(module2));
+		  MSC_INFO(&module2)->dbg_info = (addr + dbghdr->PointerToRawData);
+		  MSC_INFO(&module2)->dbg_size = dbghdr->SizeOfData;
+		  module2.load_addr = module->load_addr;
 
-		  DEBUG_ProcessCoff(&deefer2);
+		  DEBUG_ProcessCoff(&module2);
 		  break;
 		case IMAGE_DEBUG_TYPE_CODEVIEW:
 		  /*
@@ -2950,7 +2904,7 @@
 			  /*
 			   * Now process the CV stuff.
 			   */
-			  DEBUG_SnarfCodeView(deefer, 
+			  DEBUG_SnarfCodeView(module, 
 					      codeview + codeview_dent->offset + sizeof(DWORD),
 					      codeview_dent->size - sizeof(DWORD),
 					      linetab);
@@ -2978,126 +2932,83 @@
 }
 
 int
-DEBUG_ProcessDeferredDebug(void)
+DEBUG_ProcessMSCDebugInfo(DBG_MODULE* module)
 {
-  struct deferred_debug_info * deefer;
   struct CodeViewDebug	     * cvd;
   struct MiscDebug	     * misc;
   char			     * filename;
-  int			       last_proc = -1;
-  int                          need_print =0;
   int			       sts;
-
-  for(deefer = dbglist; deefer; deefer = deefer->next)
-    {
-      if( deefer->status != DF_STATUS_NEW )
-	{
-	  continue;
-	}
-
-      if( last_proc != deefer->dbg_index )
-	{
-	  if (!need_print)
-	    {
-	      fprintf(stderr, "DeferredDebug for:");
-	      need_print=1;
-	    }
-	  fprintf(stderr, " %s",deefer->module_name);
-	  last_proc = deefer->dbg_index;
-	}
-
-      switch(deefer->dbgdir->Type)
-	{
-	case IMAGE_DEBUG_TYPE_COFF:
-	  /*
-	   * Standard COFF debug information that VC++ adds when you
-	   * use /debugtype:both with the linker.
-	   */
+  
+  switch (MSC_INFO(module)->dbgdir.Type)
+     {
+     case IMAGE_DEBUG_TYPE_COFF:
+	/*
+	 * Standard COFF debug information that VC++ adds when you
+	 * use /debugtype:both with the linker.
+	 */
 #if 0
-	  fprintf(stderr, "Processing COFF symbols...\n");
+	fprintf(stderr, "Processing COFF symbols...\n");
 #endif
-	  sts = DEBUG_ProcessCoff(deefer);
-	  break;
-	case IMAGE_DEBUG_TYPE_CODEVIEW:
-	  /*
-	   * This is a pointer to a PDB file of some sort.
-	   */
-	  cvd = (struct CodeViewDebug *) deefer->dbg_info;
-
-	  if( strcmp(cvd->cv_nbtype, "NB10") != 0 )
-	    {
+	sts = DEBUG_ProcessCoff(module);
+	break;
+     case IMAGE_DEBUG_TYPE_CODEVIEW:
+	/*
+	 * This is a pointer to a PDB file of some sort.
+	 */
+	cvd = (struct CodeViewDebug *) MSC_INFO(module)->dbg_info;
+	
+	if( strcmp(cvd->cv_nbtype, "NB10") != 0 )
+	   {
 	      /*
 	       * Whatever this is, we don't know how to deal with
 	       * it yet.
 	       */
 	      sts = FALSE;
 	      break;
-	    }
-	  sts = DEBUG_ProcessPDBFile(deefer, cvd->cv_name);
+	   }
+	sts = DEBUG_ProcessPDBFile(module, cvd->cv_name);
 #if 0
-	  fprintf(stderr, "Processing PDB file %s\n", cvd->cv_name);
+	fprintf(stderr, "Processing PDB file %s\n", cvd->cv_name);
 #endif
-	  break;
-	case IMAGE_DEBUG_TYPE_MISC:
-	  /*
-	   * A pointer to a .DBG file of some sort.  These files
-	   * can contain either CV4 or COFF information.  Open
-	   * the file, and try to do the right thing with it.
-	   */
-	  misc = (struct MiscDebug *) deefer->dbg_info;
-
-	  filename = strrchr((char *) &misc->Data, '.');
-
-	  /*
-	   * Ignore the file if it doesn't have a .DBG extension.
-	   */
-	  if(    (filename == NULL)
-	      || (    (strcmp(filename, ".dbg") != 0)
-	           && (strcmp(filename, ".DBG") != 0)) )
-	    {
-	       sts = FALSE;
-	       break;
-	    }
-
-	  filename = (char *) &misc->Data;
-
-	  /*
-	   * Do the dirty deed...
-	   */
-	  sts = DEBUG_ProcessDBGFile(deefer, filename);
-      
-	  break;
-	default:
-	  /*
-	   * We should never get here...
-	   */
-	   sts = FALSE;
-	  break;
-	}
-      deefer->status = (sts) ? DF_STATUS_LOADED : DF_STATUS_ERROR;
-
-    }
-  if(need_print)
-     fprintf(stderr, "\n");
-  return TRUE;
-
+	break;
+     case IMAGE_DEBUG_TYPE_MISC:
+	/*
+	 * A pointer to a .DBG file of some sort.  These files
+	 * can contain either CV4 or COFF information.  Open
+	 * the file, and try to do the right thing with it.
+	 */
+	misc = (struct MiscDebug *) MSC_INFO(module)->dbg_info;
+	
+	filename = strrchr((char *) &misc->Data, '.');
+	
+	/*
+	 * Ignore the file if it doesn't have a .DBG extension.
+	 */
+	if(    (filename == NULL)
+	       || (    (strcmp(filename, ".dbg") != 0)
+		       && (strcmp(filename, ".DBG") != 0)) )
+	   {
+	      sts = FALSE;
+	      break;
+	   }
+	
+	filename = (char *) &misc->Data;
+	
+	/*
+	 * Do the dirty deed...
+	 */
+	sts = DEBUG_ProcessDBGFile(module, filename);
+	
+	break;
+     default:
+	/*
+	 * We should never get here...
+	 */
+	sts = FALSE;
+	break;
+     }
+  return sts;
 }
 
-/***********************************************************************
- *           DEBUG_InfoShare
- *
- * Display shared libarary information.
- */
-void DEBUG_InfoShare(void)
-{
-  struct deferred_debug_info * deefer;
 
-  fprintf(stderr,"Address\t\tModule\tName\n");
-
-  for(deefer = dbglist; deefer; deefer = deefer->next)
-  {
-      fprintf(stderr,"0x%8.8x\t(%s)\t%s\n", (unsigned int) deefer->load_addr,
-              deefer->module ? "Win32" : "ELF", deefer->module_name);
-  }
-}
 
diff --git a/debugger/stabs.c b/debugger/stabs.c
index b240a01..f7b8dd6 100644
--- a/debugger/stabs.c
+++ b/debugger/stabs.c
@@ -1237,9 +1237,9 @@
   ehptr = (Elf32_Ehdr *) addr;
 
   if( load_offset == 0 )
-      DEBUG_RegisterELFDebugInfo(ehptr->e_entry, statbuf.st_size, filename);
+      DEBUG_RegisterELFModule(ehptr->e_entry, filename);
   else
-      DEBUG_RegisterELFDebugInfo(load_offset, statbuf.st_size, filename);
+      DEBUG_RegisterELFModule(load_offset, filename);
 
   spnt = (Elf32_Shdr *) (addr + ehptr->e_shoff);
   nsect = ehptr->e_shnum;
diff --git a/debugger/winedbg.c b/debugger/winedbg.c
index f98a80c..be37c11 100644
--- a/debugger/winedbg.c
+++ b/debugger/winedbg.c
@@ -9,7 +9,12 @@
 #include <stdio.h>
 #include <sys/stat.h>
 #include "debugger.h"
-#include "winbase.h"
+
+#include "thread.h"
+#include "process.h"
+#include "wingdi.h"
+#include "winuser.h"
+
 #include "winreg.h"
 #include "debugtools.h"
 #include "options.h"
@@ -20,29 +25,56 @@
 
 DEFAULT_DEBUG_CHANNEL(winedbg);
     
-WINE_DBG_PROCESS* DEBUG_CurrProcess = NULL;
-WINE_DBG_THREAD*  DEBUG_CurrThread = NULL;
-CONTEXT		  DEBUG_context;
+DBG_PROCESS*	DEBUG_CurrProcess = NULL;
+DBG_THREAD*	DEBUG_CurrThread = NULL;
+CONTEXT		DEBUG_context;
 
-static WINE_DBG_PROCESS* proc = NULL;
+static DBG_PROCESS* proc = NULL;
+static BOOL bBreakAllThreads = FALSE;
 
-static	WINE_DBG_PROCESS*	DEBUG_GetProcess(DWORD pid)
+static	BOOL DEBUG_Init(void)
 {
-    WINE_DBG_PROCESS*	p;
+    HKEY	hkey;
+    DWORD 	type;
+    DWORD	val;
+    DWORD 	count = sizeof(val);
+
+    if (!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\WineDbg", &hkey)) {
+	if (!RegQueryValueExA(hkey, "BreakAllThreadsStartup", 0, &type, (LPSTR)&val, &count)) {
+	    bBreakAllThreads = val;
+	}
+	RegCloseKey(hkey);
+    }
+    return TRUE;
+}
+		       
+static WINE_EXCEPTION_FILTER(wine_dbg)
+{
+    DEBUG_ExternalDebugger();
+    fprintf(stderr, "\nwine_dbg: Exception %lx\n", GetExceptionCode());
+    return EXCEPTION_EXECUTE_HANDLER;
+}
+
+static	DBG_PROCESS*	DEBUG_GetProcess(DWORD pid)
+{
+    DBG_PROCESS*	p;
     
     for (p = proc; p; p = p->next)
 	if (p->pid == pid) break;
     return p;
 }
 
-static	WINE_DBG_PROCESS*	DEBUG_AddProcess(DWORD pid, HANDLE h)
+static	DBG_PROCESS*	DEBUG_AddProcess(DWORD pid, HANDLE h)
 {
-    WINE_DBG_PROCESS*	p = DBG_alloc(sizeof(WINE_DBG_PROCESS));
+    DBG_PROCESS*	p = DBG_alloc(sizeof(DBG_PROCESS));
     if (!p)
 	return NULL;
     p->handle = h;
     p->pid = pid;
     p->threads = NULL;
+    p->num_threads = 0;
+    p->modules = NULL;
+    p->next_index = 0;
 
     p->next = proc;
     p->prev = NULL;
@@ -51,9 +83,9 @@
     return p;
 }
 
-static	void			DEBUG_DelThread(WINE_DBG_THREAD* p);
+static	void			DEBUG_DelThread(DBG_THREAD* p);
 
-static	void			DEBUG_DelProcess(WINE_DBG_PROCESS* p)
+static	void			DEBUG_DelProcess(DBG_PROCESS* p)
 {
     if (p->threads != NULL) {
 	ERR("Shouldn't happen\n");
@@ -138,19 +170,19 @@
     return FALSE;
 }
 
-static	WINE_DBG_THREAD*	DEBUG_GetThread(WINE_DBG_PROCESS* p, DWORD tid)
+static	DBG_THREAD*	DEBUG_GetThread(DBG_PROCESS* p, DWORD tid)
 {
-    WINE_DBG_THREAD*	t;
+    DBG_THREAD*	t;
     
     for (t = p->threads; t; t = t->next)
 	if (t->tid == tid) break;
     return t;
 }
 
-static	WINE_DBG_THREAD*	DEBUG_AddThread(WINE_DBG_PROCESS* p, DWORD tid, 
-						HANDLE h, LPVOID start, LPVOID teb)
+static	DBG_THREAD*	DEBUG_AddThread(DBG_PROCESS* p, DWORD tid, 
+					HANDLE h, LPVOID start, LPVOID teb)
 {
-    WINE_DBG_THREAD*	t = DBG_alloc(sizeof(WINE_DBG_THREAD));
+    DBG_THREAD*	t = DBG_alloc(sizeof(DBG_THREAD));
     if (!t)
 	return NULL;
     
@@ -162,7 +194,8 @@
     t->wait_for_first_exception = 0;
     t->dbg_exec_mode = EXEC_CONT;
     t->dbg_exec_count = 0;
-    
+
+    p->num_threads++;
     t->next = p->threads;
     t->prev = NULL;
     if (p->threads) p->threads->prev = t;
@@ -176,25 +209,28 @@
     if (!Options.debug) return;
 
     if (DEBUG_CurrThread->start) {
-	DBG_VALUE	value;
-	
-	DEBUG_SetBreakpoints(FALSE);
-	value.type = NULL;
-	value.cookie = DV_TARGET;
-	value.addr.seg = 0;
-	value.addr.off = (DWORD)DEBUG_CurrThread->start;
-	DEBUG_AddBreakpoint(&value);
-	DEBUG_SetBreakpoints(TRUE);
+	if (DEBUG_CurrThread->process->num_threads == 1 || bBreakAllThreads) {
+	    DBG_VALUE	value;
+	    
+	    DEBUG_SetBreakpoints(FALSE);
+	    value.type = NULL;
+	    value.cookie = DV_TARGET;
+	    value.addr.seg = 0;
+	    value.addr.off = (DWORD)DEBUG_CurrThread->start;
+	    DEBUG_AddBreakpoint(&value);
+	    DEBUG_SetBreakpoints(TRUE);
+	}
     } else {
 	DEBUG_CurrThread->wait_for_first_exception = 1;
     }
 }
 
-static	void			DEBUG_DelThread(WINE_DBG_THREAD* t)
+static	void			DEBUG_DelThread(DBG_THREAD* t)
 {
     if (t->prev) t->prev->next = t->next;
     if (t->next) t->next->prev = t->prev;
     if (t == t->process->threads) t->process->threads = t->next;
+    t->process->num_threads--;
     DBG_free(t);
 }
 
@@ -281,42 +317,41 @@
     return ret;
 }
 
-static	DWORD	CALLBACK	DEBUG_MainLoop(DWORD pid)
+static	DWORD	DEBUG_HandleDebugEvent(DEBUG_EVENT* de)
 {
-    DEBUG_EVENT		de;
     char		buffer[256];
     DWORD		cont;
-
-    while (WaitForDebugEvent(&de, INFINITE)) {
+    
+    __TRY {
 	cont = 0L;
-
-	if ((DEBUG_CurrProcess = DEBUG_GetProcess(de.dwProcessId)) != NULL)
-	    DEBUG_CurrThread = DEBUG_GetThread(DEBUG_CurrProcess, de.dwThreadId);
+	
+	if ((DEBUG_CurrProcess = DEBUG_GetProcess(de->dwProcessId)) != NULL)
+	    DEBUG_CurrThread = DEBUG_GetThread(DEBUG_CurrProcess, de->dwThreadId);
 	else 
 	    DEBUG_CurrThread = NULL;
-
-	switch (de.dwDebugEventCode) {
+	
+	switch (de->dwDebugEventCode) {
 	case EXCEPTION_DEBUG_EVENT:
 	    if (!DEBUG_CurrThread) break;
-
+	    
 	    TRACE("%08lx:%08lx: exception code=%08lx %d\n", 
-		  de.dwProcessId, de.dwThreadId, 
-		  de.u.Exception.ExceptionRecord.ExceptionCode,
+		  de->dwProcessId, de->dwThreadId, 
+		  de->u.Exception.ExceptionRecord.ExceptionCode,
 		  DEBUG_CurrThread->wait_for_first_exception);
-
+	    
 	    DEBUG_context.ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_SEGMENTS|CONTEXT_DEBUG_REGISTERS;
 	    if (!GetThreadContext(DEBUG_CurrThread->handle, &DEBUG_context)) {
 		WARN("Can't get thread's context\n");
 		break;
 	    }
-
-	    TRACE("%p:%p\n", de.u.Exception.ExceptionRecord.ExceptionAddress, 
+	    
+	    TRACE("%p:%p\n", de->u.Exception.ExceptionRecord.ExceptionAddress, 
 		  (void*)DEBUG_context.Eip);
-
-	    cont = DEBUG_HandleException(&de.u.Exception.ExceptionRecord, 
-					 de.u.Exception.dwFirstChance, 
+	    
+	    cont = DEBUG_HandleException(&de->u.Exception.ExceptionRecord, 
+					 de->u.Exception.dwFirstChance, 
 					 DEBUG_CurrThread->wait_for_first_exception);
-
+	    
 	    if (DEBUG_CurrThread->wait_for_first_exception) {
 		DEBUG_CurrThread->wait_for_first_exception = 0;
 #ifdef __i386__
@@ -327,23 +362,23 @@
 	    break;
 	    
 	case CREATE_THREAD_DEBUG_EVENT:
-	    TRACE("%08lx:%08lx: create thread D @%p\n", de.dwProcessId, de.dwThreadId, 
-		  de.u.CreateThread.lpStartAddress);
+	    TRACE("%08lx:%08lx: create thread D @%p\n", de->dwProcessId, de->dwThreadId, 
+		  de->u.CreateThread.lpStartAddress);
 	    
 	    if (DEBUG_CurrProcess == NULL) {
 		ERR("Unknown process\n");
 		break;
 	    }
-	    if (DEBUG_GetThread(DEBUG_CurrProcess, de.dwThreadId) != NULL) {
+	    if (DEBUG_GetThread(DEBUG_CurrProcess, de->dwThreadId) != NULL) {
 		TRACE("Thread already listed, skipping\n");
 		break;
 	    }
-
+	    
 	    DEBUG_CurrThread = DEBUG_AddThread(DEBUG_CurrProcess, 
-					       de.dwThreadId, 
-					       de.u.CreateThread.hThread, 
-					       de.u.CreateThread.lpStartAddress, 
-					       de.u.CreateThread.lpThreadLocalBase);
+					       de->dwThreadId, 
+					       de->u.CreateThread.hThread, 
+					       de->u.CreateThread.lpStartAddress, 
+					       de->u.CreateThread.lpThreadLocalBase);
 	    if (!DEBUG_CurrThread) {
 		ERR("Couldn't create thread\n");
 		break;
@@ -353,34 +388,34 @@
 	    
 	case CREATE_PROCESS_DEBUG_EVENT:
 	    DEBUG_ProcessGetStringIndirect(buffer, sizeof(buffer), 
-                                           de.u.CreateProcessInfo.hProcess, 
-                                           de.u.LoadDll.lpImageName);
+                                           de->u.CreateProcessInfo.hProcess, 
+                                           de->u.LoadDll.lpImageName);
 	    
-	    /* FIXME unicode ? de.u.CreateProcessInfo.fUnicode */
+	    /* FIXME unicode ? de->u.CreateProcessInfo.fUnicode */
 	    TRACE("%08lx:%08lx: create process %s @%p\n", 
-		  de.dwProcessId, de.dwThreadId, 
+		  de->dwProcessId, de->dwThreadId, 
 		  buffer,
-		  de.u.CreateProcessInfo.lpStartAddress);
+		  de->u.CreateProcessInfo.lpStartAddress);
 	    
-	    if (DEBUG_GetProcess(de.dwProcessId) != NULL) {
+	    if (DEBUG_GetProcess(de->dwProcessId) != NULL) {
 		TRACE("Skipping already defined process\n");
 		break;
 	    }
-	    DEBUG_CurrProcess = DEBUG_AddProcess(de.dwProcessId,
-						 de.u.CreateProcessInfo.hProcess);
+	    DEBUG_CurrProcess = DEBUG_AddProcess(de->dwProcessId,
+						 de->u.CreateProcessInfo.hProcess);
 	    if (DEBUG_CurrProcess == NULL) {
 		ERR("Unknown process\n");
 		break;
 	    }
 	    
-	    TRACE("%08lx:%08lx: create thread I @%p\n", de.dwProcessId, de.dwThreadId, 
-		  de.u.CreateProcessInfo.lpStartAddress);
+	    TRACE("%08lx:%08lx: create thread I @%p\n", de->dwProcessId, de->dwThreadId, 
+		  de->u.CreateProcessInfo.lpStartAddress);
 	    
 	    DEBUG_CurrThread = DEBUG_AddThread(DEBUG_CurrProcess, 	
-					       de.dwThreadId, 
-					       de.u.CreateProcessInfo.hThread, 
-					       de.u.CreateProcessInfo.lpStartAddress, 
-					       de.u.CreateProcessInfo.lpThreadLocalBase);
+					       de->dwThreadId, 
+					       de->u.CreateProcessInfo.hThread, 
+					       de->u.CreateProcessInfo.lpStartAddress, 
+					       de->u.CreateProcessInfo.lpThreadLocalBase);
 	    if (!DEBUG_CurrThread) {
 		ERR("Couldn't create thread\n");
 		break;
@@ -390,15 +425,15 @@
 	    DEBUG_InitCurrThread();
 #ifdef _WE_SUPPORT_THE_STAB_TYPES_USED_BY_MINGW_TOO
 	    /* so far, process name is not set */
-	    DEBUG_RegisterDebugInfo((DWORD)de.u.CreateProcessInfo.lpBaseOfImage, 
+	    DEBUG_RegisterDebugInfo((DWORD)de->u.CreateProcessInfo.lpBaseOfImage, 
 				    "wine-exec");
 #endif
 	    break;
 	    
 	case EXIT_THREAD_DEBUG_EVENT:
 	    TRACE("%08lx:%08lx: exit thread (%ld)\n", 
-		  de.dwProcessId, de.dwThreadId, de.u.ExitThread.dwExitCode);
-
+		  de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
+	    
 	    if (DEBUG_CurrThread == NULL) {
 		ERR("Unknown thread\n");
 		break;
@@ -409,8 +444,8 @@
 	    
 	case EXIT_PROCESS_DEBUG_EVENT:
 	    TRACE("%08lx:%08lx: exit process (%ld)\n", 
-		  de.dwProcessId, de.dwThreadId, de.u.ExitProcess.dwExitCode);
-
+		  de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
+	    
 	    if (DEBUG_CurrProcess == NULL) {
 		ERR("Unknown process\n");
 		break;
@@ -428,16 +463,18 @@
 	    }
 	    DEBUG_ProcessGetStringIndirect(buffer, sizeof(buffer), 
                                            DEBUG_CurrThread->process->handle, 
-                                           de.u.LoadDll.lpImageName);
+                                           de->u.LoadDll.lpImageName);
 	    
-	    /* FIXME unicode: de.u.LoadDll.fUnicode */
-	    TRACE("%08lx:%08lx: loads DLL %s @%p\n", de.dwProcessId, de.dwThreadId, 
-		  buffer, de.u.LoadDll.lpBaseOfDll);
+	    /* FIXME unicode: de->u.LoadDll.fUnicode */
+	    TRACE("%08lx:%08lx: loads DLL %s @%p\n", de->dwProcessId, de->dwThreadId, 
+		  buffer, de->u.LoadDll.lpBaseOfDll);
+	    CharUpperA(buffer);
+	    DEBUG_LoadModule32( buffer, (DWORD)de->u.LoadDll.lpBaseOfDll);
 	    break;
 	    
 	case UNLOAD_DLL_DEBUG_EVENT:
-	    TRACE("%08lx:%08lx: unload DLL @%p\n", de.dwProcessId, de.dwThreadId, 
-		  de.u.UnloadDll.lpBaseOfDll);
+	    TRACE("%08lx:%08lx: unload DLL @%p\n", de->dwProcessId, de->dwThreadId, 
+		  de->u.UnloadDll.lpBaseOfDll);
 	    break;
 	    
 	case OUTPUT_DEBUG_STRING_EVENT:
@@ -445,27 +482,45 @@
 		ERR("Unknown thread\n");
 		break;
 	    }
-
+	    
 	    DEBUG_ProcessGetString(buffer, sizeof(buffer), 
 				   DEBUG_CurrThread->process->handle, 
-				   de.u.DebugString.lpDebugStringData);
+				   de->u.DebugString.lpDebugStringData);
 	    
-	    /* fixme unicode de.u.DebugString.fUnicode ? */
+	    /* fixme unicode de->u.DebugString.fUnicode ? */
 	    TRACE("%08lx:%08lx: output debug string (%s)\n", 
-		  de.dwProcessId, de.dwThreadId, 
+		  de->dwProcessId, de->dwThreadId, 
 		  buffer);
 	    break;
 	    
 	case RIP_EVENT:
 	    TRACE("%08lx:%08lx: rip error=%ld type=%ld\n", 
-		  de.dwProcessId, de.dwThreadId, de.u.RipInfo.dwError, 
-		  de.u.RipInfo.dwType);
+		  de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError, 
+		  de->u.RipInfo.dwType);
 	    break;
 	    
 	default:
 	    TRACE("%08lx:%08lx: unknown event (%ld)\n", 
-		  de.dwProcessId, de.dwThreadId, de.dwDebugEventCode);
+		  de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
 	}
+	
+    } __EXCEPT(wine_dbg) {
+	cont = 0;
+    }
+    __ENDTRY;
+
+    return cont;
+}
+
+static	DWORD	CALLBACK	DEBUG_MainLoop(DWORD pid)
+{
+    DEBUG_EVENT		de;
+    DWORD		cont;
+
+    DEBUG_Init();
+
+    while (WaitForDebugEvent(&de, INFINITE)) {
+	cont = DEBUG_HandleDebugEvent(&de);
 	ContinueDebugEvent(de.dwProcessId, de.dwThreadId, cont);
     }
     
@@ -474,11 +529,6 @@
     return 0L;
 }
 
-#include "thread.h"
-#include "process.h"
-#include "wingdi.h"
-#include "winuser.h"
-
 static	DWORD	CALLBACK	DEBUG_StarterFromPID(LPVOID pid)
 {
     TRACE("WineDbg started on pid %ld\n", (DWORD)pid);