Release 970914

Thu Sep 11 18:24:56 1997  Philippe De Muyter  <phdm@info.ucl.ac.be>

	* [objects/dc.c]
	In DC_SetupGCForPatBlt, replace R2_NOT by GXxor with (black xor white).

Tue Sep  9 23:04:02 1997  U. Bonnes <bon@elektron.ikp.physik.th-darmstadt.de>

	* [memory/virtual.c] 
	Do not write debugging info unconditionally to stderr.

	* [files/profile.c]
	Call PROFILE_GetSection in PROFILE_GetString for key_name "" too.

	* [misc/crtdll.c]
	Many new functions.

	* [include/windows.h] [windows/winpos.c]
	ClientToScreen16 doesn't have a return value.

Sun Sep  7 10:06:39 1997  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [misc/main.c] [AUTHORS]
	Update the list of contributors. Please let me know if I forgot
	someone.

	* [if1632/*.spec] [if1632/builtin.c] [tools/build.c]
	Ordinal base for Win32 DLLs is now computed automatically from the
	lowest ordinal found.

	* [include/wintypes.h]
	WINAPI is now defined as attribute((stdcall)). This will require
	gcc to compile.

	* [if1632/thunk.c]
	Removed Win32 thunks (no longer needed with stdcall).

	* [if1632/crtdll.spec] [misc/crtdll.c]
	Make sure we only reference cdecl functions in the spec file.

	* [objects/dc.c]
	Use CapNotLast drawing style for 1-pixel wide lines.

	* [tools/build.c]
	Added 'double' argument type.
	Added 'varargs' function type for Win32.
	Made CallTo16_xxx functions stdcall.

Fri Sep  5 14:50:49 1997  Alex Korobka <alex@trantor.pharm.sunysb.edu>

	* [tools/build.c] [windows/win.c] [windows/event.c] [windows/message.c]
	More fixes to get message exchange closer to the original.

	* [misc/spy.c]
	Message logs now contain window names.

	* [loader/resource.c] [loader/ne_resource.c] [loader/task.c]
	  [objects/cursoricon.c] [windows/user.c]
	Added some obscure features to fix memory leaks.

Fri Sep  5 00:46:28 1997  Jan Willamowius <jan@janhh.shnet.org>

	* [if1632/kernel32.spec] [win32/newfns.c]
	Added stub for UTRegister() and UTUnRegister().

Thu Sep  4 12:03:12 1997  Frans van Dorsselaer <dorssel@rulhmpc49.LeidenUniv.nl>
	* [controls/edit.c]
	Allow ASCII codes > 127 in WM_CHAR.

Mon Sep  1 17:23:24 1997  Dimitrie O. Paun  <dimi@mail.cs.toronto.edu>

	* [controls/widgets.c]
	In InitCommonControls, remember the name of the class
	because lpszClassName was made to point to a local array
	Added the ProgressBar to the list of implemented controls.
	Call InitCommonControls from WIDGETS_Init to register all
	implemented Common Controls.
	
	* [include/commctrl.h]
	Added misc decl for the Progress Bar.

	* [controls/progress.c] [include/progress.h]
	First attempt at implementiong the Progress Bar class.

	* [objects/brush.h]
	Implementation for GetSysColorBrush[16|32]

	* [controls/status.c]
	Use DrawEdge to draw the borders and fill the background

	* [controls/uitools.c]
	Added DrawDiagEdge32 and DrawRectEdge32

	* [graphics/painting.c]
	Implement DrawEdge[16|32]
	Started DrawFrameControl32

Mon Sep  1 10:07:09 1997  Lawson Whitney <lawson_whitney@juno.com>

	* [misc/comm.c] [include/windows.h]
	SetCommEventMask returns a SEGPTR.

Sun Aug 31 23:28:32 1997  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [loader/pe_image.c][loader/module.c][include/pe_image.h]
	  [include/module.h]
	Cleaned up the whole Win32 library mess (a bit).

	* [debugger/stabs.c]
	If 'wine' has no absolute path and isn't found, check $PATH too.

	* [misc/ole2nls.c]
	Some fixes.

	* [misc/ver.c]
	Added support for PE style version resources.

	* [memory/string.c]
	Check for NULL pointers to _lstr* functions, just as Windows95 does.

	* [multimedia/time.c]
	Made list of timers a simple linked list.

	* [loader/resource.c]
	Netscape 3 seems to pass NEGATIVE resource Ids (in an
	unsigned int, yes). Don't know why, fixed it anyway.

	* [objects/bitmap.c]
	LoadImageW added.

	* [include/win.h][windows/win.c]
	Change wIDmenu from UINT16 to UINT32 and changed the
	SetWindow(Long|Word) accordingly.

Thu Aug 28 19:30:08 1997  Morten Welinder  <terra@diku.dk>

	* [include/windows.h]
	Add a few more colors defined for Win95.
	Add a few more brush styles.

	* [windows/syscolor.c]
 	Add error checks for SYSCOLOR_SetColor, SYSCOLOR_Init,
	GetSysColor16, GetSysColor32.  Add support for above colors.

Sun Aug 24 16:22:57 1997  Andrew Taylor <andrew@riscan.com>

	* [multimedia/mmsystem.c]
	Changed mmioDescend to use mmio functions for file I/O, neccessary
	for memory files.
diff --git a/loader/module.c b/loader/module.c
index a41ce37..c40d240 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -18,6 +18,7 @@
 #include "hook.h"
 #include "module.h"
 #include "neexe.h"
+#include "resource.h"
 #include "selectors.h"
 #include "stackframe.h"
 #include "task.h"
@@ -26,7 +27,7 @@
 #include "debug.h"
 #include "callback.h"
 
-extern HINSTANCE16 PE_LoadModule( int fd, OFSTRUCT *ofs, LOADPARAMS* params );
+extern HINSTANCE16 PE_LoadModule( HFILE32 hf, OFSTRUCT *ofs, LOADPARAMS* params );
 
 static HMODULE16 hFirstModule = 0;
 static HMODULE16 hCachedModule = 0;  /* Module cached by MODULE_OpenFile */
@@ -35,19 +36,70 @@
 /***********************************************************************
  *           MODULE_GetPtr
  */
-NE_MODULE *MODULE_GetPtr( HMODULE16 hModule )
+NE_MODULE *MODULE_GetPtr( HMODULE32 hModule )
 {
-    NE_MODULE *pModule = (NE_MODULE *)GlobalLock16( hModule );
-    if (!pModule || (pModule->magic != IMAGE_OS2_SIGNATURE) ||
-        (pModule->self != hModule)) return NULL;
-    return pModule;
+    HMODULE16 hnd =MODULE_HANDLEtoHMODULE16(hModule);
+
+    if (!hnd)
+    	return NULL;
+    return (NE_MODULE*)GlobalLock16(hnd);
 }
 
+/***********************************************************************
+ *           MODULE_HANDLEtoHMODULE16
+ */
+HMODULE16
+MODULE_HANDLEtoHMODULE16(HANDLE32 handle) {
+    NE_MODULE	*pModule;
+
+    if (HIWORD(handle)) {
+	/* this is a HMODULE32 aka pe->mappeddll */
+
+        /* walk the list looking for the correct startaddress */
+    	pModule = (NE_MODULE *)GlobalLock16( hFirstModule );
+	while (pModule) { 
+		if (	((pModule->flags&(NE_FFLAGS_BUILTIN|NE_FFLAGS_WIN32))==NE_FFLAGS_WIN32) &&
+			pModule->pe_module &&
+			((HMODULE32)pModule->pe_module->mappeddll == handle)
+		)
+			return pModule->self;
+		pModule=(NE_MODULE*)GlobalLock16(pModule->next);
+	}
+	return 0;
+    }
+    return GetExePtr(handle);
+}
+
+/***********************************************************************
+ *           MODULE_HANDLEtoHMODULE32
+ * return HMODULE32, if possible, HMODULE16 otherwise
+ */
+HMODULE32
+MODULE_HANDLEtoHMODULE32(HANDLE32 handle) {
+    NE_MODULE *pModule;
+
+    if (HIWORD(handle))
+    	return (HMODULE32)handle;
+    else {
+    	handle = GetExePtr(handle);
+	if (!handle)
+	    return 0;
+    	pModule = (NE_MODULE *)GlobalLock16( handle );
+	if (!pModule)
+	    return 0;
+	
+	if (	((pModule->flags&(NE_FFLAGS_BUILTIN|NE_FFLAGS_WIN32))==NE_FFLAGS_WIN32) &&
+		pModule->pe_module
+	)
+		return (HMODULE32)pModule->pe_module->mappeddll;
+	return handle;
+    }
+}
 
 /***********************************************************************
  *           MODULE_DumpModule
  */
-void MODULE_DumpModule( HMODULE16 hModule )
+void MODULE_DumpModule( HMODULE32 hModule )
 {
     int i, ordinal;
     SEGTABLEENTRY *pSeg;
@@ -210,7 +262,7 @@
 /***********************************************************************
  *           MODULE_OpenFile
  */
-int MODULE_OpenFile( HMODULE16 hModule )
+int MODULE_OpenFile( HMODULE32 hModule )
 {
     NE_MODULE *pModule;
     DOS_FULL_NAME full_name;
@@ -218,7 +270,7 @@
 
     static int cachedfd = -1;
 
-    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
+    hModule = MODULE_HANDLEtoHMODULE16(hModule);
     dprintf_module( stddeb, "MODULE_OpenFile(%04x) cache: mod=%04x fd=%d\n",
                     hModule, hCachedModule, cachedfd );
     if (!(pModule = MODULE_GetPtr( hModule ))) return -1;
@@ -275,7 +327,7 @@
 /***********************************************************************
  *           MODULE_CreateSegments
  */
-static BOOL32 MODULE_CreateSegments( HMODULE16 hModule )
+static BOOL32 MODULE_CreateSegments( HMODULE32 hModule )
 {
     SEGTABLEENTRY *pSegment;
     NE_MODULE *pModule;
@@ -306,7 +358,7 @@
 /***********************************************************************
  *           MODULE_GetInstance
  */
-HINSTANCE16 MODULE_GetInstance( HMODULE16 hModule )
+HINSTANCE16 MODULE_GetInstance( HMODULE32 hModule )
 {
     SEGTABLEENTRY *pSegment;
     NE_MODULE *pModule;
@@ -359,12 +411,13 @@
  *
  * Create a dummy NE module for Win32 or Winelib.
  */
-HMODULE16 MODULE_CreateDummyModule( const OFSTRUCT *ofs )
+HMODULE32 MODULE_CreateDummyModule( const OFSTRUCT *ofs )
 {
-    HMODULE16 hModule;
+    HMODULE32 hModule;
     NE_MODULE *pModule;
     SEGTABLEENTRY *pSegment;
-    char *pStr,*basename,*s;
+    char *pStr,*s;
+    const char* basename;
 
     INT32 of_size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName)
                     + strlen(ofs->szPathName) + 1;
@@ -379,7 +432,7 @@
                  8;
 
     hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
-    if (!hModule) return (HMODULE16)11;  /* invalid exe */
+    if (!hModule) return (HMODULE32)11;  /* invalid exe */
 
     FarSetOwner( hModule, hModule );
     pModule = (NE_MODULE *)GlobalLock16( hModule );
@@ -432,7 +485,7 @@
     *pStr = strlen(basename);
     if (*pStr>8) *pStr=8;
     strncpy( pStr+1, basename, 8 );
-    free(basename);
+    free((void*)basename);
     pStr += 9;
 
     /* All tables zero terminated */
@@ -447,12 +500,12 @@
 /***********************************************************************
  *           MODULE_LoadExeHeader
  */
-static HMODULE16 MODULE_LoadExeHeader( HFILE32 hFile, OFSTRUCT *ofs )
+static HMODULE32 MODULE_LoadExeHeader( HFILE32 hFile, OFSTRUCT *ofs )
 {
     IMAGE_DOS_HEADER mz_header;
     IMAGE_OS2_HEADER ne_header;
     int size;
-    HMODULE16 hModule;
+    HMODULE32 hModule;
     NE_MODULE *pModule;
     BYTE *pData;
     char *buffer, *fastload = NULL;
@@ -469,18 +522,18 @@
     _llseek32( hFile, 0, SEEK_SET );
     if ((_lread32(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
         (mz_header.e_magic != IMAGE_DOS_SIGNATURE))
-        return (HMODULE16)11;  /* invalid exe */
+        return (HMODULE32)11;  /* invalid exe */
 
     _llseek32( hFile, mz_header.e_lfanew, SEEK_SET );
     if (_lread32( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
-        return (HMODULE16)11;  /* invalid exe */
+        return (HMODULE32)11;  /* invalid exe */
 
-    if (ne_header.ne_magic == IMAGE_NT_SIGNATURE) return (HMODULE16)21;  /* win32 exe */
-    if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE) return (HMODULE16)11;  /* invalid exe */
+    if (ne_header.ne_magic == IMAGE_NT_SIGNATURE) return (HMODULE32)21;  /* win32 exe */
+    if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE) return (HMODULE32)11;  /* invalid exe */
 
     if (ne_header.ne_magic == IMAGE_OS2_SIGNATURE_LX) {
       fprintf(stderr, "Sorry, this is an OS/2 linear executable (LX) file !\n");
-      return (HMODULE16)11;
+      return (HMODULE32)11;
     }
     /* We now have a valid NE header */
 
@@ -501,7 +554,7 @@
            ne_header.entry_tab_length;
 
     hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
-    if (!hModule) return (HMODULE16)11;  /* invalid exe */
+    if (!hModule) return (HMODULE32)11;  /* invalid exe */
     FarSetOwner( hModule, hModule );
     pModule = (NE_MODULE *)GlobalLock16( hModule );
     memcpy( pModule, &ne_header, sizeof(ne_header) );
@@ -560,7 +613,7 @@
             HeapFree( SystemHeap, 0, buffer );
             if (fastload) HeapFree( SystemHeap, 0, fastload );
             GlobalFree16( hModule );
-            return (HMODULE16)11;  /* invalid exe */
+            return (HMODULE32)11;  /* invalid exe */
         }
         pSeg = (struct ne_segment_table_entry_s *)buffer;
         for (i = ne_header.n_segment_tab; i > 0; i--, pSeg++)
@@ -574,7 +627,7 @@
     {
         if (fastload) HeapFree( SystemHeap, 0, fastload );
         GlobalFree16( hModule );
-        return (HMODULE16)11;  /* invalid exe */
+        return (HMODULE32)11;  /* invalid exe */
     }
 
     /* Get the resource table */
@@ -584,8 +637,9 @@
         pModule->res_table = (int)pData - (int)pModule;
         if (!READ(mz_header.e_lfanew + ne_header.resource_tab_offset,
                   ne_header.rname_tab_offset - ne_header.resource_tab_offset,
-                  pData )) return (HMODULE16)11;  /* invalid exe */
+                  pData )) return (HMODULE32)11;  /* invalid exe */
         pData += ne_header.rname_tab_offset - ne_header.resource_tab_offset;
+	NE_InitResourceHandler( hModule );
     }
     else pModule->res_table = 0;  /* No resource table */
 
@@ -598,7 +652,7 @@
     {
         if (fastload) HeapFree( SystemHeap, 0, fastload );
         GlobalFree16( hModule );
-        return (HMODULE16)11;  /* invalid exe */
+        return (HMODULE32)11;  /* invalid exe */
     }
     pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
 
@@ -613,7 +667,7 @@
         {
             if (fastload) HeapFree( SystemHeap, 0, fastload );
             GlobalFree16( hModule );
-            return (HMODULE16)11;  /* invalid exe */
+            return (HMODULE32)11;  /* invalid exe */
         }
         pData += ne_header.n_mod_ref_tab * sizeof(WORD);
     }
@@ -628,7 +682,7 @@
     {
         if (fastload) HeapFree( SystemHeap, 0, fastload );
         GlobalFree16( hModule );
-        return (HMODULE16)11;  /* invalid exe */
+        return (HMODULE32)11;  /* invalid exe */
     }
     pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
 
@@ -641,7 +695,7 @@
     {
         if (fastload) HeapFree( SystemHeap, 0, fastload );
         GlobalFree16( hModule );
-        return (HMODULE16)11;  /* invalid exe */
+        return (HMODULE32)11;  /* invalid exe */
     }
     pData += ne_header.entry_tab_length;
 
@@ -659,7 +713,7 @@
         if (!pModule->nrname_handle)
         {
             GlobalFree16( hModule );
-            return (HMODULE16)11;  /* invalid exe */
+            return (HMODULE32)11;  /* invalid exe */
         }
         buffer = GlobalLock16( pModule->nrname_handle );
         _llseek32( hFile, ne_header.nrname_tab_offset, SEEK_SET );
@@ -668,7 +722,7 @@
         {
             GlobalFree16( pModule->nrname_handle );
             GlobalFree16( hModule );
-            return (HMODULE16)11;  /* invalid exe */
+            return (HMODULE32)11;  /* invalid exe */
         }
     }
     else pModule->nrname_handle = 0;
@@ -678,13 +732,13 @@
     if (pModule->modref_count)
     {
         pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
-                                    (pModule->modref_count+1)*sizeof(HMODULE16),
+                                    (pModule->modref_count+1)*sizeof(HMODULE32),
                                     hModule, FALSE, FALSE, FALSE );
         if (!pModule->dlls_to_init)
         {
             if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
             GlobalFree16( hModule );
-            return (HMODULE16)11;  /* invalid exe */
+            return (HMODULE32)11;  /* invalid exe */
         }
     }
     else pModule->dlls_to_init = 0;
@@ -699,7 +753,7 @@
  *
  * Lookup the ordinal for a given name.
  */
-WORD MODULE_GetOrdinal( HMODULE16 hModule, const char *name )
+WORD MODULE_GetOrdinal( HMODULE32 hModule, const char *name )
 {
     unsigned char buffer[256], *cpnt;
     BYTE len;
@@ -763,7 +817,7 @@
  *
  * Return the entry point for a given ordinal.
  */
-FARPROC16 MODULE_GetEntryPoint( HMODULE16 hModule, WORD ordinal )
+FARPROC16 MODULE_GetEntryPoint( HMODULE32 hModule, WORD ordinal )
 {
     NE_MODULE *pModule;
     WORD curOrdinal = 1;
@@ -823,7 +877,7 @@
  * Change the value of an entry point. Use with caution!
  * It can only change the offset value, not the selector.
  */
-BOOL16 MODULE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset )
+BOOL16 MODULE_SetEntryPoint( HMODULE32 hModule, WORD ordinal, WORD offset )
 {
     NE_MODULE *pModule;
     WORD curOrdinal = 1;
@@ -872,7 +926,7 @@
 {
     WORD ordinal;
     FARPROC16 ret;
-    static HMODULE16 hModule = 0;
+    static HMODULE32 hModule = 0;
 
     if (!hModule) hModule = GetModuleHandle16( "WPROCS" );
     ordinal = MODULE_GetOrdinal( hModule, name );
@@ -886,7 +940,7 @@
 /***********************************************************************
  *           MODULE_GetModuleName
  */
-LPSTR MODULE_GetModuleName( HMODULE16 hModule )
+LPSTR MODULE_GetModuleName( HMODULE32 hModule )
 {
     NE_MODULE *pModule;
     BYTE *p, len;
@@ -916,9 +970,9 @@
  *
  * Find a module from a path name.
  */
-HMODULE16 MODULE_FindModule( LPCSTR path )
+HMODULE32 MODULE_FindModule( LPCSTR path )
 {
-    HMODULE16 hModule = hFirstModule;
+    HMODULE32 hModule = hFirstModule;
     LPCSTR filename, dotptr, modulepath, modulename;
     BYTE len, *name_table;
 
@@ -973,7 +1027,7 @@
  *
  * Remove a module from memory.
  */
-static void MODULE_FreeModule( HMODULE16 hModule )
+BOOL16 MODULE_FreeModule( HMODULE32 hModule, TDB* pTaskContext )
 {
     HMODULE16 *hPrevModule;
     NE_MODULE *pModule;
@@ -981,17 +1035,28 @@
     HMODULE16 *pModRef;
     int i;
 
-    if (!(pModule = MODULE_GetPtr( hModule ))) return;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
+    hModule = pModule->self;
+
+    if (((INT16)(--pModule->count)) > 0 ) return TRUE;
+    else pModule->count = 0;
+
     if (pModule->flags & NE_FFLAGS_BUILTIN)
-        return;  /* Can't free built-in module */
+        return FALSE;  /* Can't free built-in module */
 
-    if (pModule->flags & NE_FFLAGS_LIBMODULE) MODULE_CallWEP( hModule );
+    if (pModule->flags & NE_FFLAGS_LIBMODULE) 
+    {
+	MODULE_CallWEP( hModule );
 
-    /* Free the objects owned by the module */
+	/* Free the objects owned by the DLL module */
 
-    HOOK_FreeModuleHooks( hModule );
-    CLASS_FreeModuleClasses( hModule );
-
+	if( pTaskContext && pTaskContext->userhandler )
+	{
+            pTaskContext->userhandler( hModule, USIG_DLL_UNLOAD, 0,
+                                       pTaskContext->hInstance,
+                                       pTaskContext->hQueue );
+	}
+    }
     /* Clear magic number just in case */
 
     pModule->magic = pModule->self = 0;
@@ -1030,6 +1095,8 @@
       /* Remove module from cache */
 
     if (hCachedModule == hModule) hCachedModule = 0;
+
+    return TRUE;
 }
 
 
@@ -1038,7 +1105,7 @@
  *
  * Implementation of LoadModule()
  */
-HINSTANCE16 MODULE_Load( LPCSTR name, LPVOID paramBlock, BOOL32 first )
+HINSTANCE16 MODULE_Load( LPCSTR name, LPVOID paramBlock, UINT16 uFlags)
 {
     HMODULE16 hModule;
     HINSTANCE16 hInstance, hPrevInstance;
@@ -1080,10 +1147,9 @@
         hModule = MODULE_LoadExeHeader( hFile, &ofs );
         if (hModule < 32)
         {
-            /* Note: PE_LoadModule closes the file */
             if (hModule == 21)
                 hModule = PE_LoadModule( hFile, &ofs, paramBlock );
-            else _lclose32( hFile );
+	    else _lclose32( hFile );
 
             if (hModule < 32)
                 fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
@@ -1092,6 +1158,7 @@
         }
         _lclose32( hFile );
         pModule = MODULE_GetPtr( hModule );
+	pModule->flags |= uFlags; /* stamp implicitly loaded modules */
 
           /* Allocate the segments for this module */
 
@@ -1117,7 +1184,7 @@
                 /* its handle in the list of DLLs to initialize.   */
                 HMODULE16 hDLL;
 
-                if ((hDLL = MODULE_Load( buffer, (LPVOID)-1, FALSE )) == 2)
+                if ((hDLL = MODULE_Load( buffer, (LPVOID)-1, NE_FFLAGS_IMPLICIT )) == 2)
                 {
                     /* file not found */
                     char *p;
@@ -1127,15 +1194,17 @@
                     if (!(p = strrchr( buffer, '\\' ))) p = buffer;
                     memcpy( p + 1, pstr + 1, *pstr );
                     strcpy( p + 1 + *pstr, ".dll" );
-                    hDLL = MODULE_Load( buffer, (LPVOID)-1, FALSE );
+                    hDLL = MODULE_Load( buffer, (LPVOID)-1, NE_FFLAGS_IMPLICIT );
                 }
                 if (hDLL < 32)
                 {
+		    /* FIXME: cleanup what was done */
+
                     fprintf( stderr, "Could not load '%s' required by '%s', error = %d\n",
                              buffer, name, hDLL );
                     return 2;  /* file not found */
                 }
-                *pModRef = GetExePtr( hDLL );
+                *pModRef = MODULE_HANDLEtoHMODULE16( hDLL );
                 *pDLLs++ = *pModRef;
             }
             else  /* Increment the reference count of the DLL */
@@ -1158,11 +1227,12 @@
 		HMODULE16 hselfload = GetModuleHandle16("WPROCS");
                 DWORD oldstack;
 		WORD saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
-		fprintf (stderr, "Warning:  %*.*s is a self-loading module\n"
-                                "Support for self-loading modules is very experimental\n",
-                *((BYTE*)pModule + pModule->name_table),
-                *((BYTE*)pModule + pModule->name_table),
-                (char *)pModule + pModule->name_table + 1);
+
+		dprintf_module(stddeb, "MODULE_Load: %*.*s is a self-loading module!\n",
+					*((BYTE*)pModule + pModule->name_table),
+					*((BYTE*)pModule + pModule->name_table),
+					 (char *)pModule + pModule->name_table + 1);
+
 		NE_LoadSegment( hModule, 1 );
 		selfloadheader = (SELFLOADHEADER *)
 			PTR_SEG_OFF_TO_LIN(pSegTable->selector, 0);
@@ -1210,7 +1280,8 @@
 		  frame32->ecx = 0;
 		  frame32->ebx = 0;
 		  frame32->ebp = 0;
-		  frame32->retaddr = 0;
+		  frame32->restore_addr = 0;
+		  frame32->retaddr      = 0;
 		  frame32->codeselector = WINE_CODE_SELECTOR;
 		  /* pTask->esp = (DWORD)frame32; */
 		}
@@ -1242,10 +1313,14 @@
 
         pModule->count = 1;
 
-        if (first && (pModule->flags & NE_FFLAGS_LIBMODULE))
-            NE_InitializeDLLs( hModule );
+	  /* Call initialization rountines for all loaded DLLs. Note that
+	   * when we load implicitly linked DLLs this will be done by the InitTask().
+	   */
+
+        if ((pModule->flags & (NE_FFLAGS_LIBMODULE | NE_FFLAGS_IMPLICIT)) ==
+			       NE_FFLAGS_LIBMODULE ) NE_InitializeDLLs( hModule );
     }
-    else
+    else /* module is already loaded, just create a new data segment if it's a task */
     {
         pModule = MODULE_GetPtr( hModule );
         hPrevInstance = MODULE_GetInstance( hModule );
@@ -1254,6 +1329,7 @@
             NE_LoadSegment( hModule, pModule->dgroup );
         pModule->count++;
     }
+
 #else
     lstrcpyn32A( ofs.szPathName, name, sizeof(ofs.szPathName) );
     if ((hModule = MODULE_CreateDummyModule( &ofs )) < 32) return hModule;
@@ -1269,6 +1345,8 @@
 	HTASK16 hTask;
         WORD	showcmd;
 
+	pModule->flags |= NE_FFLAGS_GUI;
+
 	/* PowerPoint passes NULL as showCmd */
 	if (params->showCmd)
 		showcmd = *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1);
@@ -1292,7 +1370,7 @@
  */
 HINSTANCE16 LoadModule16( LPCSTR name, LPVOID paramBlock )
 {
-    return MODULE_Load( name, paramBlock, TRUE );
+    return MODULE_Load( name, paramBlock, 0 );
 }
 
 
@@ -1303,13 +1381,11 @@
 {
     NE_MODULE *pModule;
 
-    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
     if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
-
     dprintf_module( stddeb, "FreeModule16: %s count %d\n", 
 		    MODULE_GetModuleName(hModule), pModule->count );
-    if (--pModule->count == 0) MODULE_FreeModule( hModule );
-    return TRUE;
+
+    return MODULE_FreeModule( hModule, GlobalLock16(GetCurrentTask()) );
 }
 
 
@@ -1318,7 +1394,7 @@
  */
 HMODULE16 WINAPI WIN16_GetModuleHandle( SEGPTR name )
 {
-    if (HIWORD(name) == 0) return GetExePtr( (HINSTANCE16)name );
+    if (HIWORD(name) == 0) return MODULE_HANDLEtoHMODULE16( (HINSTANCE16)name );
     return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
 }
 
@@ -1327,6 +1403,33 @@
     return MODULE_FindModule( name );
 }
 
+/***********************************************************************
+ *              GetModuleHandle         (KERNEL32.237)
+ */
+HMODULE32 WINAPI GetModuleHandle32A(LPCSTR module)
+{
+    HMODULE32	hModule;
+
+    dprintf_win32(stddeb, "GetModuleHandleA: %s\n", module ? module : "NULL");
+/* Freecell uses the result of GetModuleHandleA(0) as the hInstance in
+all calls to e.g. CreateWindowEx. */
+    if (module == NULL) {
+	TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
+	hModule = pTask->hInstance;
+    } else
+	hModule = MODULE_FindModule(module);
+    return MODULE_HANDLEtoHMODULE32(hModule);
+}
+
+HMODULE32 WINAPI GetModuleHandle32W(LPCWSTR module)
+{
+    HMODULE32 hModule;
+    LPSTR modulea = HEAP_strdupWtoA( GetProcessHeap(), 0, module );
+    hModule = GetModuleHandle32A( modulea );
+    HeapFree( GetProcessHeap(), 0, modulea );
+    return hModule;
+}
+
 
 /**********************************************************************
  *	    GetModuleUsage    (KERNEL.48)
@@ -1335,7 +1438,6 @@
 {
     NE_MODULE *pModule;
 
-    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
     dprintf_module( stddeb, "GetModuleUsage(%04x): returning %d\n",
                     hModule, pModule->count );
@@ -1352,7 +1454,6 @@
     NE_MODULE *pModule;
 
     if (!hModule) hModule = GetCurrentTask();
-    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
     lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), nSize );
     dprintf_module( stddeb, "GetModuleFileName16: %s\n", lpFileName );
@@ -1373,7 +1474,6 @@
         TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
         hModule = pTask->hInstance;
     }
-    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
     lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), size );
     dprintf_module( stddeb, "GetModuleFileName32A: %s\n", lpFileName );
@@ -1410,17 +1510,73 @@
 
 /***********************************************************************
  *           LoadLibraryEx32W   (KERNEL.513)
+ * FIXME
  */
-HINSTANCE16 WINAPI LoadLibraryEx32W16( LPCSTR libname, HANDLE16 hf,
+HMODULE32 WINAPI LoadLibraryEx32W16( LPCSTR libname, HANDLE16 hf,
                                        DWORD flags )
 {
     fprintf(stderr,"LoadLibraryEx32W(%s,%d,%08lx)\n",libname,hf,flags);
-    if (!flags && !hf)
-    	return LoadLibrary32A(libname);
-    return 0;
+    return LoadLibraryEx32A(libname,hf,flags);
 }
 
 /***********************************************************************
+ *           LoadLibraryEx32A   (KERNEL32)
+ */
+HMODULE32 WINAPI LoadLibraryEx32A(LPCSTR libname,HFILE32 hfile,DWORD flags)
+{
+    HMODULE32 hmod;
+    
+    hmod = PE_LoadLibraryEx32A(libname,hfile,flags);
+    if (hmod <= 32) {
+	char buffer[256];
+
+	strcpy( buffer, libname );
+	strcat( buffer, ".dll" );
+	hmod = PE_LoadLibraryEx32A(buffer,hfile,flags);
+    }
+    /* initialize all DLLs, which haven't been initialized yet. */
+    PE_InitializeDLLs( GetCurrentProcessId(), DLL_PROCESS_ATTACH, NULL);
+    return hmod;
+}
+
+/***********************************************************************
+ *           LoadLibraryA         (KERNEL32)
+ */
+HMODULE32 WINAPI LoadLibrary32A(LPCSTR libname) {
+	return LoadLibraryEx32A(libname,0,0);
+}
+
+/***********************************************************************
+ *           LoadLibraryW         (KERNEL32)
+ */
+HMODULE32 WINAPI LoadLibrary32W(LPCWSTR libnameW)
+{
+    return LoadLibraryEx32W(libnameW,0,0);
+}
+
+/***********************************************************************
+ *           LoadLibraryExW       (KERNEL32)
+ */
+HMODULE32 WINAPI LoadLibraryEx32W(LPCWSTR libnameW,HFILE32 hfile,DWORD flags)
+{
+    LPSTR libnameA = HEAP_strdupWtoA( GetProcessHeap(), 0, libnameW );
+    HMODULE32 ret = LoadLibraryEx32A( libnameA , hfile, flags );
+
+    HeapFree( GetProcessHeap(), 0, libnameA );
+    return ret;
+}
+
+/***********************************************************************
+ *           FreeLibrary
+ */
+BOOL32 WINAPI FreeLibrary32(HINSTANCE32 hLibModule)
+{
+	fprintf(stderr,"FreeLibrary: empty stub\n");
+	return TRUE;
+}
+
+
+/***********************************************************************
  *           LoadLibrary   (KERNEL.95)
  */
 HINSTANCE16 WINAPI LoadLibrary16( LPCSTR libname )
@@ -1434,17 +1590,13 @@
     }
     dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
 
-    /* This does not increment the module reference count, and will
-     * therefore cause crashes on FreeLibrary calls.
-    if ((handle = MODULE_FindModule( libname )) != 0) return handle;
-     */
-    handle = MODULE_Load( libname, (LPVOID)-1, TRUE );
+    handle = MODULE_Load( libname, (LPVOID)-1, 0 );
     if (handle == (HINSTANCE16)2)  /* file not found */
     {
         char buffer[256];
         lstrcpyn32A( buffer, libname, 252 );
         strcat( buffer, ".dll" );
-        handle = MODULE_Load( buffer, (LPVOID)-1, TRUE );
+        handle = MODULE_Load( buffer, (LPVOID)-1, 0 );
     }
     return handle;
 }
@@ -1486,7 +1638,7 @@
         return 2;  /* File not found */
     if (!(cmdShowHandle = GlobalAlloc16( 0, 2 * sizeof(WORD) )))
         return 8;  /* Out of memory */
-    if (!(cmdLineHandle = GlobalAlloc16( 0, 256 )))
+    if (!(cmdLineHandle = GlobalAlloc16( 0, 1024 )))
     {
         GlobalFree16( cmdShowHandle );
         return 8;  /* Out of memory */
@@ -1531,7 +1683,7 @@
 	}
 
 	if (*p)
-	    lstrcpyn32A( cmdline + 1, p + 1, 127 );
+	    lstrcpyn32A( cmdline + 1, p + 1, 1023 );
 	else
 	    cmdline[1] = '\0';
 
@@ -1645,7 +1797,7 @@
  *           WIN32_GetProcAddress16   (KERNEL32.36)
  * Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func)
  */
-FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE16 hModule, LPSTR name )
+FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE32 hModule, LPSTR name )
 {
     WORD	ordinal;
     FARPROC16	ret;
@@ -1654,7 +1806,7 @@
     	fprintf(stderr,"WIN32_GetProcAddress16: hModule may not be 0!\n");
 	return (FARPROC16)0;
     }
-    hModule = GetExePtr(hModule);
+    hModule = MODULE_HANDLEtoHMODULE16(hModule);
     if (HIWORD(name)) {
         ordinal = MODULE_GetOrdinal( hModule, name );
         dprintf_module( stddeb, "WIN32_GetProcAddress16: %04x '%s'\n",
@@ -1679,7 +1831,7 @@
     FARPROC16 ret;
 
     if (!hModule) hModule = GetCurrentTask();
-    hModule = GetExePtr( hModule );
+    hModule = MODULE_HANDLEtoHMODULE16( hModule );
 
     if (HIWORD(name) != 0)
     {
@@ -1714,13 +1866,16 @@
 	dprintf_win32(stddeb,"GetProcAddress32(%08lx,%s)\n",(DWORD)hModule,function);
     else
 	dprintf_win32(stddeb,"GetProcAddress32(%08lx,%p)\n",(DWORD)hModule,function);
-    hModule = GetExePtr( hModule );
     if (!(pModule = MODULE_GetPtr( hModule )))
         return (FARPROC32)0;
-    if (!(pModule->flags & NE_FFLAGS_WIN32) || !pModule->pe_module)
-        return (FARPROC32)0;
     if (pModule->flags & NE_FFLAGS_BUILTIN)
         return BUILTIN_GetProcAddress32( pModule, function );
+    if (!pModule->pe_module) {
+    	fprintf(stderr,"Oops, Module 0x%08lx has got no pe_module?\n",
+		(DWORD)MODULE_HANDLEtoHMODULE32(hModule)
+	);
+	return (FARPROC32)0;
+    }
     return PE_FindExportedFunction( pModule->pe_module, function );
 #else
     return NULL;
@@ -1732,14 +1887,20 @@
  */
 LPIMAGE_NT_HEADERS WINAPI RtlImageNtHeader(HMODULE32 hModule)
 {
+    /* basically:
+     * return  hModule+(((IMAGE_DOS_HEADER*)hModule)->e_lfanew); 
+     * but we could get HMODULE16 or the like (think builtin modules)
+     */
+
 #ifndef WINELIB
     NE_MODULE *pModule;
 
-    hModule = GetExePtr( hModule );
     if (!(pModule = MODULE_GetPtr( hModule )))
         return (LPIMAGE_NT_HEADERS)0;
     if (!(pModule->flags & NE_FFLAGS_WIN32) || !pModule->pe_module)
         return (LPIMAGE_NT_HEADERS)0;
+    if (pModule->flags & NE_FFLAGS_BUILTIN)
+        return (LPIMAGE_NT_HEADERS)0;
     return pModule->pe_module->pe_header;
 #else
     return NULL;
@@ -1763,7 +1924,7 @@
 BOOL16 WINAPI IsSharedSelector( HANDLE16 selector )
 {
     /* Check whether the selector belongs to a DLL */
-    NE_MODULE *pModule = MODULE_GetPtr( GetExePtr( selector ));
+    NE_MODULE *pModule = MODULE_GetPtr( selector );
     if (!pModule) return FALSE;
     return (pModule->flags & NE_FFLAGS_LIBMODULE) != 0;
 }
@@ -1815,7 +1976,7 @@
  */
 BOOL16 WINAPI ModuleFindHandle( MODULEENTRY *lpme, HMODULE16 hModule )
 {
-    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
+    hModule = MODULE_HANDLEtoHMODULE16( hModule );
     lpme->wNext = hModule;
     return ModuleNext( lpme );
 }
diff --git a/loader/ne_image.c b/loader/ne_image.c
index dd0ff09..e1631e9 100644
--- a/loader/ne_image.c
+++ b/loader/ne_image.c
@@ -17,6 +17,7 @@
 #include <errno.h>
 #include "neexe.h"
 #include "windows.h"
+#include "task.h"
 #include "arch.h"
 #include "selectors.h"
 #include "callback.h"
@@ -455,7 +456,7 @@
  *
  * Call the DLL initialization code
  */
-static BOOL32 NE_InitDLL( HMODULE16 hModule )
+static BOOL32 NE_InitDLL( TDB* pTask, HMODULE16 hModule )
 {
     NE_MODULE *pModule;
     SEGTABLEENTRY *pSegTable;
@@ -473,6 +474,17 @@
 
     if (!(pModule->flags & NE_FFLAGS_LIBMODULE) ||
         (pModule->flags & NE_FFLAGS_WIN32)) return TRUE; /*not a library*/
+
+    /* Call USER signal handler. This is necessary to install a
+     * proper loader for HICON and HCURSOR resources that this DLL 
+     * may contain. InitApp() does this for task modules. */
+
+    if (pTask && pTask->userhandler)
+    {
+        pTask->userhandler( hModule, USIG_DLL_LOAD, 0, pTask->hInstance,
+                            pTask->hQueue );
+    }
+
     if (!pModule->cs) return TRUE;  /* no initialization code */
 
     memset( &context, 0, sizeof(context) );
@@ -516,10 +528,12 @@
 /***********************************************************************
  *           NE_InitializeDLLs
  *
- * Initialize the loaded DLLs.
+ * Recursively initialize all DLLs (according to the order in which 
+ * they where loaded).
  */
 void NE_InitializeDLLs( HMODULE16 hModule )
 {
+    TDB* pTask = (TDB*)GlobalLock16(GetCurrentTask());
     NE_MODULE *pModule;
     HMODULE16 *pDLL;
 
@@ -529,6 +543,7 @@
 /*        PE_InitializeDLLs(hModule); */
         return;
     }
+
     if (pModule->dlls_to_init)
     {
 	HGLOBAL16 to_init = pModule->dlls_to_init;
@@ -539,7 +554,7 @@
         }
         GlobalFree16( to_init );
     }
-    NE_InitDLL( hModule );
+    NE_InitDLL( pTask, hModule );
 }
 
 
diff --git a/loader/ne_resource.c b/loader/ne_resource.c
index cf885e8..7121b18 100644
--- a/loader/ne_resource.c
+++ b/loader/ne_resource.c
@@ -3,6 +3,7 @@
  *
  * Copyright 1993 Robert J. Amstadt
  * Copyright 1995 Alexandre Julliard
+ *	     1997 Alex Korobka
  */
 
 #include <stdio.h>
@@ -22,6 +23,8 @@
 #include "stddebug.h"
 #include "debug.h"
 
+#define  NEXT_TYPEINFO(pTypeInfo) ((NE_TYPEINFO *)((char*)((pTypeInfo) + 1) + \
+                                   (pTypeInfo)->count * sizeof(NE_NAMEINFO)))
 
 /***********************************************************************
  *           NE_FindNameTableId
@@ -29,29 +32,26 @@
  * Find the type and resource id from their names.
  * Return value is MAKELONG( typeId, resId ), or 0 if not found.
  */
-static DWORD NE_FindNameTableId( HMODULE16 hModule, SEGPTR typeId, SEGPTR resId )
+static DWORD NE_FindNameTableId( NE_MODULE *pModule, SEGPTR typeId, SEGPTR resId )
 {
-    NE_MODULE *pModule;
-    NE_TYPEINFO *pTypeInfo;
+    NE_TYPEINFO *pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
     NE_NAMEINFO *pNameInfo;
     HGLOBAL16 handle;
     WORD *p;
     DWORD ret = 0;
     int count;
 
-    if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
-    pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
     for (; pTypeInfo->type_id != 0;
-             pTypeInfo = (NE_TYPEINFO *)((char*)(pTypeInfo+1) +
-                                       pTypeInfo->count * sizeof(NE_NAMEINFO)))
+	   pTypeInfo = (NE_TYPEINFO *)((char*)(pTypeInfo+1) +
+					pTypeInfo->count * sizeof(NE_NAMEINFO)))
     {
-        if (pTypeInfo->type_id != 0x800f) continue;
-        pNameInfo = (NE_NAMEINFO *)(pTypeInfo + 1);
-        for (count = pTypeInfo->count; count > 0; count--, pNameInfo++)
-        {
+	if (pTypeInfo->type_id != 0x800f) continue;
+	pNameInfo = (NE_NAMEINFO *)(pTypeInfo + 1);
+	for (count = pTypeInfo->count; count > 0; count--, pNameInfo++)
+	{
             dprintf_resource( stddeb, "NameTable entry: type=%04x id=%04x\n",
                               pTypeInfo->type_id, pNameInfo->id );
-            handle = LoadResource16( hModule, 
+            handle = LoadResource16( pModule->self, 
 				   (HRSRC16)((int)pNameInfo - (int)pModule) );
             for(p = (WORD*)LockResource16(handle); p && *p; p = (WORD *)((char*)p+*p))
             {
@@ -89,11 +89,56 @@
             }
             FreeResource16( handle );
             if (ret) return ret;
-        }
+	}
     }
     return 0;
 }
 
+/***********************************************************************
+ *           NE_FindTypeSection
+ *
+ * Find header struct for a particular resource type.
+ */
+static NE_TYPEINFO* NE_FindTypeSection( NE_MODULE *pModule, 
+					NE_TYPEINFO *pTypeInfo, SEGPTR typeId )
+{
+    /* start from pTypeInfo */
+
+    if (HIWORD(typeId) != 0)  /* Named type */
+    {
+	char *str = (char *)PTR_SEG_TO_LIN( typeId );
+	BYTE len = strlen( str );
+	while (pTypeInfo->type_id)
+	{
+	    if (!(pTypeInfo->type_id & 0x8000))
+	    {
+		BYTE *p = (BYTE*)pModule + pModule->res_table + pTypeInfo->type_id;
+		if ((*p == len) && !lstrncmpi32A( p+1, str, len ))
+		{
+		    dprintf_resource( stddeb, "  Found type '%s'\n", str );
+		    return pTypeInfo;
+		}
+	    }
+	    dprintf_resource( stddeb, "  Skipping type %04x\n", pTypeInfo->type_id );
+	    pTypeInfo = NEXT_TYPEINFO(pTypeInfo);
+	}
+    }
+    else  /* Numeric type id */
+    {
+	WORD id = LOWORD(typeId) | 0x8000;
+	while (pTypeInfo->type_id)
+	{
+            if (pTypeInfo->type_id == id)
+	    {
+		dprintf_resource( stddeb, "  Found type %04x\n", id );
+		return pTypeInfo;
+	    }
+	    dprintf_resource( stddeb, "  Skipping type %04x\n", pTypeInfo->type_id );
+	    pTypeInfo = NEXT_TYPEINFO(pTypeInfo);
+	}
+    }
+    return NULL;
+}
 
 /***********************************************************************
  *           NE_FindResourceFromType
@@ -131,6 +176,83 @@
 
 
 /***********************************************************************
+ *           NE_DefResourceHandler
+ *
+ * This is the default LoadProc() function. 
+ */
+HGLOBAL16 WINAPI NE_DefResourceHandler( HGLOBAL16 hMemObj, HMODULE16 hModule,
+                                        HRSRC16 hRsrc )
+{
+    int  fd;
+    NE_MODULE* pModule = MODULE_GetPtr( hModule );
+    if ( pModule && (fd = MODULE_OpenFile( hModule )) >= 0)
+    {
+	HGLOBAL16 handle;
+	WORD sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
+	NE_NAMEINFO* pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
+
+        dprintf_resource( stddeb, "NEResourceHandler: loading, pos=%d, len=%d\n",
+                         (int)pNameInfo->offset << sizeShift,
+                         (int)pNameInfo->length << sizeShift );
+	if( hMemObj )
+	    handle = GlobalReAlloc16( hMemObj, pNameInfo->length << sizeShift, 0 );
+	else
+	    handle = NE_AllocResource( hModule, hRsrc, 0 );
+
+	if( handle )
+	{
+            lseek( fd, (int)pNameInfo->offset << sizeShift, SEEK_SET );
+            read( fd, GlobalLock16( handle ), (int)pNameInfo->length << sizeShift );
+	}
+	return handle;
+    }
+    return (HGLOBAL16)0;
+}
+
+/***********************************************************************
+ *           NE_InitResourceHandler
+ *
+ * Fill in 'resloader' fields in the resource table.
+ */
+BOOL32 NE_InitResourceHandler( HMODULE16 hModule )
+{
+    NE_MODULE *pModule = MODULE_GetPtr( hModule );
+    NE_TYPEINFO *pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
+
+    dprintf_resource(stddeb,"InitResourceHandler[%04x]\n", hModule );
+
+    while(pTypeInfo->type_id)
+    {
+	pTypeInfo->resloader = (DWORD)&NE_DefResourceHandler;
+	pTypeInfo = NEXT_TYPEINFO(pTypeInfo);
+    }
+    return TRUE;
+}
+
+/***********************************************************************
+ *           NE_SetResourceHandler
+ */
+FARPROC32 NE_SetResourceHandler( HMODULE16 hModule, SEGPTR typeId, 
+				 FARPROC32 resourceHandler )
+{
+    NE_MODULE *pModule = MODULE_GetPtr( hModule );
+    NE_TYPEINFO *pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
+    FARPROC32  prevHandler = NULL;
+
+    do
+    {
+	pTypeInfo = NE_FindTypeSection( pModule, pTypeInfo, typeId );
+        if( pTypeInfo )
+        {
+	    prevHandler = (FARPROC32)pTypeInfo->resloader;
+	    pTypeInfo->resloader = (DWORD)resourceHandler;
+	    pTypeInfo = NEXT_TYPEINFO(pTypeInfo);
+        }
+    } while( pTypeInfo );
+    return prevHandler;
+}
+
+/***********************************************************************
  *           NE_FindResource
  */
 HRSRC16 NE_FindResource( HMODULE16 hModule, SEGPTR typeId, SEGPTR resId )
@@ -142,10 +264,12 @@
     if (!pModule || !pModule->res_table) return 0;
     pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
 
-    if (HIWORD(typeId) || HIWORD(resId))
+    if ((pModule->expected_version < 0x030a) && (HIWORD(typeId) || HIWORD(resId)))
     {
-        /* Search the names in the nametable */
-        DWORD id = NE_FindNameTableId( hModule, typeId, resId );
+        /* Search the names in the nametable (which is not present 
+         * since Windows 3.1).  */
+
+        DWORD id = NE_FindNameTableId( pModule, typeId, resId );
         if (id)  /* found */
         {
             typeId = LOWORD(id);
@@ -153,60 +277,27 @@
         }
     }
 
-    if (HIWORD(typeId) != 0)  /* Named type */
+    do
     {
-        char *str = (char *)PTR_SEG_TO_LIN( typeId );
-        BYTE len = strlen( str );
-        while (pTypeInfo->type_id)
-        {
-            if (!(pTypeInfo->type_id & 0x8000))
-            {
-                BYTE *p = (BYTE*)pModule+pModule->res_table+pTypeInfo->type_id;
-                if ((*p == len) && !lstrncmpi32A( p+1, str, len ))
-                {
-                    dprintf_resource( stddeb, "  Found type '%s'\n", str );
-                    hRsrc = NE_FindResourceFromType(pModule, pTypeInfo, resId);
-                    if (hRsrc)
-                    {
-                        dprintf_resource( stddeb, "    Found id %08lx\n", resId );
-                        return hRsrc;
-                    }
-                    dprintf_resource( stddeb, "    Not found, going on\n" );
-                }
-            }
-            dprintf_resource( stddeb, "  Skipping type %04x\n",
-                              pTypeInfo->type_id );
-            pTypeInfo = (NE_TYPEINFO *)((char*)(pTypeInfo+1) +
-                                       pTypeInfo->count * sizeof(NE_NAMEINFO));
-        }
-    }
-    else  /* Numeric type id */
-    {
-        WORD id = LOWORD(typeId) | 0x8000;
-        while (pTypeInfo->type_id)
-        {
-            if (pTypeInfo->type_id == id)
-            {
-                dprintf_resource( stddeb, "  Found type %04x\n", id );
-                hRsrc = NE_FindResourceFromType( pModule, pTypeInfo, resId );
-                if (hRsrc)
-                {
-                    dprintf_resource( stddeb, "    Found id %08lx\n", resId );
-                    return hRsrc;
-                }
-                dprintf_resource( stddeb, "    Not found, going on\n" );
-            }
-            dprintf_resource( stddeb, "  Skipping type %04x\n",
-                              pTypeInfo->type_id );
-            pTypeInfo = (NE_TYPEINFO *)((char*)(pTypeInfo+1) +
-                                       pTypeInfo->count * sizeof(NE_NAMEINFO));
-        }
-    }
+	pTypeInfo = NE_FindTypeSection( pModule, pTypeInfo, typeId );
+        if( pTypeInfo )
+	{
+	    hRsrc = NE_FindResourceFromType(pModule, pTypeInfo, resId);
+	    if( hRsrc )
+	    {
+		dprintf_resource( stddeb, "    Found id %08lx\n", resId );
+		return hRsrc;
+	    }
+	    dprintf_resource( stddeb, "    Not found, going on\n" );
+	    pTypeInfo = NEXT_TYPEINFO(pTypeInfo);
+	}
+    } while( pTypeInfo );
+
+    dprintf_resource( stddeb, "failed!\n");
     return 0;
 }
 
 
-
 /***********************************************************************
  *           NE_AllocResource
  */
@@ -273,33 +364,67 @@
  */
 HGLOBAL16 NE_LoadResource( HMODULE16 hModule,  HRSRC16 hRsrc )
 {
-    NE_NAMEINFO *pNameInfo=NULL;
-    WORD sizeShift;
-    int fd;
-
+    NE_TYPEINFO *pTypeInfo;
+    NE_NAMEINFO *pNameInfo = NULL;
     NE_MODULE *pModule = MODULE_GetPtr( hModule );
-    if (!pModule || !pModule->res_table) return 0;
+    int d;
+
+    if (!hRsrc || !pModule || !pModule->res_table) return 0;
+
+    /* First, verify hRsrc (just an offset from pModule to the needed pNameInfo) */
+
+    d = pModule->res_table + 2;
+    pTypeInfo = (NE_TYPEINFO *)((char *)pModule + d);
 #ifndef WINELIB
-    pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
-#endif
-    if (pNameInfo->handle)
+    while( hRsrc > d )
     {
-        pNameInfo->usage++;
-        dprintf_resource( stddeb, "  Already loaded, new count=%d\n",
-                          pNameInfo->usage );
-        return pNameInfo->handle;
+	if (pTypeInfo->type_id == 0)
+		break; /* terminal entry */
+	d += sizeof(NE_TYPEINFO) + pTypeInfo->count * sizeof(NE_NAMEINFO);
+	if (hRsrc < d)
+	{
+	    if( ((d - hRsrc)%sizeof(NE_NAMEINFO)) == 0 )
+	    {
+		pNameInfo = (NE_NAMEINFO *)(((char *)pModule) + hRsrc);
+		break;
+	    }
+	    else 
+		break; /* NE_NAMEINFO boundary mismatch */
+	}
+	pTypeInfo = (NE_TYPEINFO *)(((char *)pModule) + d);
     }
-    sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
-    dprintf_resource( stddeb, "  Loading, pos=%d, len=%d\n",
-                      (int)pNameInfo->offset << sizeShift,
-                      (int)pNameInfo->length << sizeShift );
-    if ((fd = MODULE_OpenFile( hModule )) == -1) return 0;
-    pNameInfo->handle = NE_AllocResource( hModule, hRsrc, 0 );
-    pNameInfo->usage = 1;
-    lseek( fd, (int)pNameInfo->offset << sizeShift, SEEK_SET );
-    read( fd, GlobalLock16( pNameInfo->handle ),
-          (int)pNameInfo->length << sizeShift );
-    return pNameInfo->handle;
+#endif
+    if (pNameInfo)
+    {
+	RESOURCEHANDLER16 __r16loader;
+	if (pNameInfo->handle
+	    && !(GlobalFlags16(pNameInfo->handle) & GMEM_DISCARDED))
+	{
+	    pNameInfo->usage++;
+	    dprintf_resource( stddeb, "  Already loaded, new count=%d\n",
+			      pNameInfo->usage );
+	}
+	else
+	{
+	    if (pTypeInfo->resloader)
+	  	__r16loader = (RESOURCEHANDLER16)pTypeInfo->resloader;
+	    else /* this is really bad */
+	    {
+		fprintf( stderr, "[%04x]: Missing resource handler!!!...\n", hModule);
+		__r16loader = NE_DefResourceHandler;
+	    }
+
+	    /* Finally call resource loader */
+
+	    if ((pNameInfo->handle = __r16loader(pNameInfo->handle, hModule, hRsrc)))
+	    {
+		pNameInfo->usage++;
+		pNameInfo->flags |= NE_SEGFLAGS_LOADED;
+	    }
+	}
+	return pNameInfo->handle;
+    }
+    return 0;
 }
 
 
@@ -324,7 +449,7 @@
     WORD count;
 
     NE_MODULE *pModule = MODULE_GetPtr( hModule );
-    if (!pModule || !pModule->res_table) return handle;
+    if (!handle || !pModule || !pModule->res_table) return handle;
     pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
     while (pTypeInfo->type_id)
     {
@@ -345,7 +470,10 @@
         }
         pTypeInfo = (NE_TYPEINFO *)pNameInfo;
     }
-    fprintf( stderr, "NE_FreeResource: %04x %04x not found!\n", hModule, handle );
+
+    dprintf_resource(stddeb, "NE_FreeResource[%04x]: no intrinsic resource for %04x\n", 
+			      hModule, handle );
+    GlobalFree16( handle ); /* it could have been DirectResAlloc()'ed */
     return handle;
 }
 #endif /* WINELIB */
diff --git a/loader/pe_image.c b/loader/pe_image.c
index 223348b..415094f 100644
--- a/loader/pe_image.c
+++ b/loader/pe_image.c
@@ -17,11 +17,14 @@
 #include <string.h>
 #include <unistd.h>
 #include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
 #include "windows.h"
 #include "winbase.h"
 #include "callback.h"
 #include "neexe.h"
 #include "peexe.h"
+#include "process.h"
 #include "pe_image.h"
 #include "module.h"
 #include "global.h"
@@ -33,8 +36,7 @@
 #include "debugger.h"
 #include "xmalloc.h"
 
-static void PE_InitDLL(HMODULE16 hModule, DWORD type, LPVOID lpReserved);
-
+static void PE_InitDLL(PE_MODREF* modref, DWORD type, LPVOID lpReserved);
 
 /* convert PE image VirtualAddress to Real Address */
 #define RVA(x) ((unsigned int)load_addr+(unsigned int)(x))
@@ -91,25 +93,40 @@
  */
 FARPROC32 PE_FindExportedFunction(struct pe_data *pe, LPCSTR funcName)
 {
-	IMAGE_EXPORT_DIRECTORY * exports = pe->pe_export;
-	unsigned load_addr = pe->load_addr;
-	u_short * ordinal;
-	u_long * function;
-	u_char ** name, *ename;
-	int i;
+	IMAGE_EXPORT_DIRECTORY 		*exports;
+	unsigned			load_addr;
+	u_short				* ordinal;
+	u_long				* function;
+	u_char				** name, *ename;
+	int				i;
+	PDB32				*process=(PDB32*)GetCurrentProcessId();
+	PE_MODREF			*pem;
+
+	pem = process->modref_list;
+	while (pem && (pem->pe_module != pe))
+		pem=pem->next;
+	if (!pem) {
+		fprintf(stderr,"No MODREF found for PE_MODULE %p in process %p\n",pe,process);
+		return NULL;
+	}
+	load_addr	= pem->load_addr;
+	exports		= pem->pe_export;
 
 	if (HIWORD(funcName))
 		dprintf_win32(stddeb,"PE_FindExportedFunction(%s)\n",funcName);
 	else
 		dprintf_win32(stddeb,"PE_FindExportedFunction(%d)\n",(int)funcName);
-	if (!exports)
+	if (!exports) {
+		fprintf(stderr,"Module %p/MODREF %p doesn't have a exports table.\n",pe,pem);
 		return NULL;
-	ordinal=(u_short*) RVA(exports->AddressOfNameOrdinals);
-	function=(u_long*) RVA(exports->AddressOfFunctions);
-	name=(u_char **) RVA(exports->AddressOfNames);
+	}
+	ordinal	= (u_short*)  RVA(exports->AddressOfNameOrdinals);
+	function= (u_long*)   RVA(exports->AddressOfFunctions);
+	name	= (u_char **) RVA(exports->AddressOfNames);
+
 	if (HIWORD(funcName)) {
 		for(i=0; i<exports->NumberOfNames; i++) {
-			ename=(char*) RVA(*name);
+			ename=(char*)RVA(*name);
 			if(!strcmp(ename,funcName))
 				return (FARPROC32) RVA(function[*ordinal]);
 			ordinal++;
@@ -127,18 +144,17 @@
 }
 
 void 
-fixup_imports (struct pe_data *pe, HMODULE16 hModule)
+fixup_imports (PDB32 *process,PE_MODREF *pem)
 {
-    IMAGE_IMPORT_DESCRIPTOR *pe_imp;
-    int	fixup_failed = 0;
-    unsigned int load_addr = pe->load_addr;
-    int i;
-    NE_MODULE *ne_mod;
-    HMODULE16 *mod_ptr;
-    char *modname;
+    PE_MODULE			*pe = pem->pe_module;
+    IMAGE_IMPORT_DESCRIPTOR	*pe_imp;
+    int	fixup_failed		= 0;
+    unsigned int load_addr	= pem->load_addr;
+    int				i;
+    char			*modname;
     
-    if (pe->pe_export)
-    	modname = (char*) RVA(pe->pe_export->Name);
+    if (pem->pe_export)
+    	modname = (char*) RVA(pem->pe_export->Name);
     else
         modname = "<unknown>";
 
@@ -146,40 +162,77 @@
     dprintf_win32 (stddeb, "\nDumping imports list\n");
 
     /* first, count the number of imported non-internal modules */
-    pe_imp = pe->pe_import;
+    pe_imp = pem->pe_import;
+    if (!pe_imp) 
+    	fprintf(stderr,"no import directory????\n");
 
     /* FIXME: should terminate on 0 Characteristics */
     for (i = 0; pe_imp->Name; pe_imp++)
 	i++;
 
-    /* Now, allocate memory for dlls_to_init */
-    ne_mod = GlobalLock16 (hModule);
-    ne_mod->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT, (i+1)*sizeof(HMODULE16),
-                                        hModule, FALSE, FALSE, FALSE);
-    mod_ptr = GlobalLock16 (ne_mod->dlls_to_init);
-    /* load the modules and put their handles into the list */
+    /* load the imported modules. They are automatically 
+     * added to the modref list of the process.
+     */
  
-     /* FIXME: should terminate on 0 Characteristics */
-     for (i = 0, pe_imp = pe->pe_import; pe_imp->Name; pe_imp++) {
+    /* FIXME: should terminate on 0 Characteristics */
+    for (i = 0, pe_imp = pem->pe_import; pe_imp->Name; pe_imp++) {
+    	HMODULE32	res;
+	PE_MODREF	*xpem,**ypem;
+
+
  	char *name = (char *) RVA(pe_imp->Name);
-	mod_ptr[i] = MODULE_Load( name, (LPVOID)-1, FALSE );
-	if (mod_ptr[i] <= (HMODULE16) 32) {
+
+	/* don't use MODULE_Load, Win32 creates new task differently */
+	res = PE_LoadLibraryEx32A( name, 0, 0 );
+	if (res <= (HMODULE32) 32) {
 	    char *p, buffer[256];
 
 	    /* Try with prepending the path of the current module */
-	    GetModuleFileName16 (hModule, buffer, sizeof (buffer));
+	    GetModuleFileName32A (pe->mappeddll, buffer, sizeof (buffer));
 	    if (!(p = strrchr (buffer, '\\')))
 		p = buffer;
 	    strcpy (p + 1, name);
-	    mod_ptr[i] = MODULE_Load( buffer, (LPVOID)-1, FALSE );
+	    res = PE_LoadLibraryEx32A( buffer, 0, 0 );
 	}
-	if (mod_ptr[i] <= (HMODULE16) 32) {
+	if (res <= (HMODULE32) 32) {
 	    fprintf (stderr, "Module %s not found\n", name);
 	    exit (0);
 	}
+	res = MODULE_HANDLEtoHMODULE32(res);
+	xpem = pem->next;
+	while (xpem) {
+		if (xpem->pe_module->mappeddll == res)
+			break;
+		xpem = xpem->next;
+	}
+	if (xpem) {
+		/* it has been loaded *BEFORE* us, so we have to init
+		 * it before us. we just swap the two modules which should
+		 * work.
+		 */
+		/* unlink xpem from chain */
+		ypem = &(process->modref_list);
+		while (*ypem) {
+			if ((*ypem)==xpem)
+				break;
+			ypem = &((*ypem)->next);
+		}
+		*ypem		= xpem->next;
+
+		/* link it directly before pem */
+		ypem		= &(process->modref_list);
+		while (*ypem) {
+			if ((*ypem)==pem)
+				break;
+			ypem = &((*ypem)->next);
+		}
+		*ypem		= xpem;
+		xpem->next	= pem;
+		
+	}
 	i++;
     }
-    pe_imp = pe->pe_import;
+    pe_imp = pem->pe_import;
     while (pe_imp->Name) {
 	char			*Module;
 	IMAGE_IMPORT_BY_NAME	*pe_name;
@@ -269,9 +322,9 @@
     if (fixup_failed) exit(1);
 }
 
-static void calc_vma_size(struct pe_data *pe)
+static int calc_vma_size(struct pe_data *pe)
 {
-  int i;
+  int i,vma_size = 0;
 
   dprintf_win32(stddeb, "Dump of segment table\n");
   dprintf_win32(stddeb, "   Name    VSz  Vaddr     SzRaw   Fileadr  *Reloc *Lineum #Reloc #Linum Char\n");
@@ -288,19 +341,21 @@
 	     pe->pe_seg[i].NumberOfRelocations,
 	     pe->pe_seg[i].NumberOfLinenumbers,
 	     pe->pe_seg[i].Characteristics);
-	  pe->vma_size = MAX(pe->vma_size,
+	  vma_size = MAX(vma_size,
 	  		pe->pe_seg[i].VirtualAddress + 
 			pe->pe_seg[i].SizeOfRawData);
     }
+    return vma_size;
 }
 
-static void do_relocations(struct pe_data *pe)
+static void do_relocations(PE_MODREF *pem)
 {
-	int delta = pe->load_addr - pe->base_addr;
-	unsigned int load_addr = pe->load_addr;
-	IMAGE_BASE_RELOCATION	*r = pe->pe_reloc;
-	int hdelta = (delta >> 16) & 0xFFFF;
-	int ldelta = delta & 0xFFFF;
+	int delta = pem->load_addr - pem->pe_module->pe_header->OptionalHeader.ImageBase;
+
+	unsigned int			load_addr= pem->load_addr;
+	IMAGE_BASE_RELOCATION		*r = pem->pe_reloc;
+	int				hdelta = (delta >> 16) & 0xFFFF;
+	int				ldelta = delta & 0xFFFF;
 
 	/* int reloc_size = */
 
@@ -360,27 +415,47 @@
 
 /**********************************************************************
  *			PE_LoadImage
- * Load one PE format executable into memory
+ * Load one PE format DLL/EXE into memory
+ * 
+ * Unluckily we can't just mmap the sections where we want them, for 
+ * (at least) Linux does only support offset with are multiples of the
+ * underlying filesystemblocksize, but PE DLLs usually have alignments of 512
+ * byte. This fails for instance when you try to map from CDROM (bsize 2048).
+ *
+ * BUT we have to map the whole image anyway, for Win32 programs sometimes
+ * want to access them. (HMODULE32 point to the start of it)
  */
-static void PE_LoadImage( struct pe_data **ret_pe, int fd, HMODULE16 hModule, WORD offset, OFSTRUCT *ofs )
+static PE_MODULE *PE_LoadImage( int fd )
 {
 	struct pe_data		*pe;
-	int			i, result;
-	int			load_addr;
-	IMAGE_DATA_DIRECTORY	dir;
-	char			buffer[200];
 	DBG_ADDR		daddr;
-	char			*modname;
+	struct stat		stbuf;
 
 	daddr.seg=0;
 	daddr.type = NULL;
+	if (-1==fstat(fd,&stbuf)) {
+		perror("PE_LoadImage:fstat");
+		return NULL;
+	}
 	pe = xmalloc(sizeof(struct pe_data));
 	memset(pe,0,sizeof(struct pe_data));
-	pe->pe_header = xmalloc(sizeof(IMAGE_NT_HEADERS));
 
-	/* read PE header */
-	lseek( fd, offset, SEEK_SET);
-	read( fd, pe->pe_header, sizeof(IMAGE_NT_HEADERS));
+	/* map the PE image somewhere */
+	pe->mappeddll = (HMODULE32)mmap(NULL,stbuf.st_size,PROT_READ,MAP_SHARED,fd,0);
+	if (!pe->mappeddll || pe->mappeddll==-1) {
+		perror("PE_LoadImage:mmap");
+		free(pe);
+		return NULL;
+	}
+	/* link PE header */
+	pe->pe_header = (IMAGE_NT_HEADERS*)(pe->mappeddll+(((IMAGE_DOS_HEADER*)pe->mappeddll)->e_lfanew));
+	if (pe->pe_header->Signature!=IMAGE_NT_SIGNATURE) {
+		fprintf(stderr,"image doesn't have PE signature, but 0x%08lx\n",
+			pe->pe_header->Signature
+		);
+		free(pe);
+		return NULL;
+	}
 
 	if (pe->pe_header->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) {
 		fprintf(stderr,"trying to load PE image for unsupported architecture (");
@@ -403,48 +478,66 @@
 			fprintf(stderr,"Unknown-%04x",pe->pe_header->FileHeader.Machine);break;
 		}
 		fprintf(stderr,")\n");
-		return;
+		return NULL;
 	}
-/* FIXME: this is a *horrible* hack to make COMDLG32.DLL load OK. The
- * problem needs to be fixed properly at some stage 
+	pe->pe_seg = (IMAGE_SECTION_HEADER*)(((LPBYTE)(pe->pe_header+1))-
+		 (16 - pe->pe_header->OptionalHeader.NumberOfRvaAndSizes) * sizeof(IMAGE_DATA_DIRECTORY));
+
+/* FIXME: the (16-...) is a *horrible* hack to make COMDLG32.DLL load OK. The
+ * problem needs to be fixed properly at some stage.
  */
-	if (pe->pe_header->OptionalHeader.NumberOfRvaAndSizes != 16) {
-		printf("Short PE Header!!!\n");
-		lseek( fd, -(16 - pe->pe_header->OptionalHeader.NumberOfRvaAndSizes) * sizeof(IMAGE_DATA_DIRECTORY), SEEK_CUR);
+ 	return pe;
+}
+
+/**********************************************************************
+ * This maps a loaded PE dll into the address space of the specified process.
+ */
+void
+PE_MapImage(PE_MODULE *pe,PDB32 *process, OFSTRUCT *ofs, DWORD flags) {
+	PE_MODREF		*pem;
+	int			i, result;
+	int			load_addr;
+	IMAGE_DATA_DIRECTORY	dir;
+	char			buffer[200];
+	DBG_ADDR		daddr;
+	char			*modname;
+	int			vma_size;
+	
+	pem		= (PE_MODREF*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*pem));
+	/* NOTE: fixup_imports takes care of the correct order */
+	pem->next	= process->modref_list;
+	process->modref_list = pem;
+
+	pem->pe_module	= pe;
+	if (!(pe->pe_header->FileHeader.Characteristics & IMAGE_FILE_DLL)) {
+		if (process->exe_modref)
+			fprintf(stderr,"overwriting old exe_modref... arrgh\n");
+		process->exe_modref = pem;
 	}
 
-	/* read sections */
-	pe->pe_seg = xmalloc(sizeof(IMAGE_SECTION_HEADER) * 
-				   pe->pe_header->FileHeader.NumberOfSections);
-	read( fd, pe->pe_seg, sizeof(IMAGE_SECTION_HEADER) * 
-			pe->pe_header->FileHeader.NumberOfSections);
-
-	load_addr = pe->pe_header->OptionalHeader.ImageBase;
-	pe->base_addr=load_addr;
-	pe->vma_size=0;
+	load_addr 	= pe->pe_header->OptionalHeader.ImageBase;
 	dprintf_win32(stddeb, "Load addr is %x\n",load_addr);
-	calc_vma_size(pe);
-	load_addr = (int) VirtualAlloc( (void*)pe->base_addr, pe->vma_size, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
-        pe->load_addr = load_addr;
+	vma_size = calc_vma_size(pe);
+	load_addr 	= (int) VirtualAlloc( (void*)load_addr, vma_size, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
+        pem->load_addr	= load_addr;
 
-	dprintf_win32(stddeb, "Load addr is really %x, range %x\n",
-		pe->load_addr, pe->vma_size);
+	dprintf_win32(stddeb, "Load addr is really %lx, range %x\n",
+		pem->load_addr, vma_size);
 	
 
 	for(i=0; i < pe->pe_header->FileHeader.NumberOfSections; i++)
 	{
-		/* load only non-BSS segments */
-		if(!(pe->pe_seg[i].Characteristics & 
-			IMAGE_SCN_CNT_UNINITIALIZED_DATA))
-                {
-                    if(lseek(fd,pe->pe_seg[i].PointerToRawData,SEEK_SET) == -1
-                       || read(fd,(char*)RVA(pe->pe_seg[i].VirtualAddress),
-                               pe->pe_seg[i].SizeOfRawData) != pe->pe_seg[i].SizeOfRawData)
-                    {
-			fprintf(stderr,"Failed to load section %x\n", i);
-			exit(0);
-                    }
-                }
+		/* memcpy only non-BSS segments */
+		/* FIXME: this should be done by mmap(..MAP_PRIVATE|MAP_FIXED..)
+		 * but it is not possible for (at least) Linux needs an offset
+		 * aligned to a block on the filesystem.
+		 */
+		if(!(pe->pe_seg[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA))
+		    memcpy((char*)RVA(pe->pe_seg[i].VirtualAddress),
+		    	(char*)(pe->mappeddll+pe->pe_seg[i].PointerToRawData),
+			pe->pe_seg[i].SizeOfRawData
+		    );
+
 		result = RVA (pe->pe_seg[i].VirtualAddress);
 #if 1
 		/* not needed, memory is zero */
@@ -456,16 +549,16 @@
 #endif
 
 		if(strcmp(pe->pe_seg[i].Name, ".idata") == 0)
-			pe->pe_import = (LPIMAGE_IMPORT_DESCRIPTOR) result;
+			pem->pe_import = (LPIMAGE_IMPORT_DESCRIPTOR) result;
 
 		if(strcmp(pe->pe_seg[i].Name, ".edata") == 0)
-			pe->pe_export = (LPIMAGE_EXPORT_DIRECTORY) result;
+			pem->pe_export = (LPIMAGE_EXPORT_DIRECTORY) result;
 
 		if(strcmp(pe->pe_seg[i].Name, ".rsrc") == 0)
-			pe->pe_resource = (LPIMAGE_RESOURCE_DIRECTORY) result;
+			pem->pe_resource = (LPIMAGE_RESOURCE_DIRECTORY) result;
 
 		if(strcmp(pe->pe_seg[i].Name, ".reloc") == 0)
-			pe->pe_reloc = (LPIMAGE_BASE_RELOCATION) result;
+			pem->pe_reloc = (LPIMAGE_BASE_RELOCATION) result;
 	}
 
 	/* There is word that the actual loader does not care about the
@@ -473,26 +566,26 @@
 	dir=pe->pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
 	if(dir.Size)
 	{
-		if(pe->pe_export && (int)pe->pe_export!=RVA(dir.VirtualAddress))
+		if(pem->pe_export && (int)pem->pe_export!=RVA(dir.VirtualAddress))
 			fprintf(stderr,"wrong export directory??\n");
 		/* always trust the directory */
-		pe->pe_export = (LPIMAGE_EXPORT_DIRECTORY) RVA(dir.VirtualAddress);
+		pem->pe_export = (LPIMAGE_EXPORT_DIRECTORY) RVA(dir.VirtualAddress);
 	}
 
 	dir=pe->pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
 	if(dir.Size)
 	{
-		if(pe->pe_import && (int)pe->pe_import!=RVA(dir.VirtualAddress))
+		if(pem->pe_import && (int)pem->pe_import!=RVA(dir.VirtualAddress))
 			fprintf(stderr,"wrong import directory??\n");
-		pe->pe_import = (LPIMAGE_IMPORT_DESCRIPTOR) RVA(dir.VirtualAddress);
+		pem->pe_import = (LPIMAGE_IMPORT_DESCRIPTOR) RVA(dir.VirtualAddress);
 	}
 
 	dir=pe->pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
 	if(dir.Size)
 	{
-		if(pe->pe_resource && (int)pe->pe_resource!=RVA(dir.VirtualAddress))
+		if(pem->pe_resource && (int)pem->pe_resource!=RVA(dir.VirtualAddress))
 			fprintf(stderr,"wrong resource directory??\n");
-		pe->pe_resource = (LPIMAGE_RESOURCE_DIRECTORY) RVA(dir.VirtualAddress);
+		pem->pe_resource = (LPIMAGE_RESOURCE_DIRECTORY) RVA(dir.VirtualAddress);
 	}
 
 	if(pe->pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size)
@@ -506,15 +599,15 @@
 	dir=pe->pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
 	if(dir.Size)
 	{
-		if(pe->pe_reloc && (int)pe->pe_reloc!= RVA(dir.VirtualAddress))
+		if(pem->pe_reloc && (int)pem->pe_reloc!= RVA(dir.VirtualAddress))
 			fprintf(stderr,"wrong relocation list??\n");
-		pe->pe_reloc = (void *) RVA(dir.VirtualAddress);
+		pem->pe_reloc = (void *) RVA(dir.VirtualAddress);
 	}
 
 	if(pe->pe_header->OptionalHeader.DataDirectory
 		[IMAGE_DIRECTORY_ENTRY_DEBUG].Size)
 	  {
-	    DEBUG_RegisterDebugInfo(fd, pe, load_addr, 
+	    DEBUG_RegisterDebugInfo(pe, load_addr, 
 			pe->pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress,
 			pe->pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size);
 	  }
@@ -549,18 +642,12 @@
 	if(pe->pe_header->OptionalHeader.DataDirectory[15].Size)
 		dprintf_win32(stdnimp,"Unknown directory 15 ignored\n");
 
-	if(pe->pe_reloc) do_relocations(pe);
-
-	/* Do exports before imports because fixup_imports
-	 * may load a module that references this module.
-	 */
-
-	if(pe->pe_export) dump_exports(pe->pe_export,load_addr);
-	*ret_pe = pe;	/* make export list available for GetProcAddress */
-	if(pe->pe_import) fixup_imports(pe, hModule);
+	if(pem->pe_reloc)	do_relocations(pem);
+	if(pem->pe_export)	dump_exports(pem->pe_export,load_addr);
+	if(pem->pe_import)	fixup_imports(process,pem);
   		
-	if (pe->pe_export)
-		modname = (char*)RVA(pe->pe_export->Name);
+	if (pem->pe_export)
+		modname = (char*)RVA(pem->pe_export->Name);
 	else {
 		char *s;
 		modname = s = ofs->szPathName;
@@ -587,31 +674,70 @@
 
 HINSTANCE16 MODULE_CreateInstance(HMODULE16 hModule,LOADPARAMS *params);
 
+/******************************************************************************
+ * The PE Library Loader frontend. 
+ * FIXME: handle the flags.
+ */
+HMODULE32 PE_LoadLibraryEx32A (LPCSTR name, HFILE32 hFile, DWORD flags) {
+	OFSTRUCT	ofs;
+	HMODULE32	hModule;
+	NE_MODULE	*pModule;
+
+	if ((hModule = MODULE_FindModule( name )))
+		return hModule;
+
+	/* try to load builtin, enabled modules first */
+	if ((hModule = BUILTIN_LoadModule( name, FALSE )))
+		return hModule;
+
+	/* try to open the specified file */
+	if (HFILE_ERROR32==(hFile=OpenFile32(name,&ofs,OF_READ))) {
+		/* Now try the built-in even if disabled */
+		if ((hModule = BUILTIN_LoadModule( name, TRUE ))) {
+			fprintf( stderr, "Warning: could not load Windows DLL '%s', using built-in module.\n", name );
+			return hModule;
+		}
+		return 1;
+	}
+	if ((hModule = MODULE_CreateDummyModule( &ofs )) < 32) {
+		_lclose32(hFile);
+		return hModule;
+	}
+
+	pModule		= (NE_MODULE *)GlobalLock16( hModule );
+	pModule->flags	= NE_FFLAGS_WIN32;
+
+	/* FIXME: check if pe image loaded already ... */
+	pModule->pe_module = PE_LoadImage( FILE_GetUnixHandle(hFile) );
+	_lclose32(hFile);
+	if (!pModule->pe_module)
+		return 21;
+	/* recurse */
+	PE_MapImage(pModule->pe_module,(PDB32*)GetCurrentProcessId(),&ofs,flags);
+	return pModule->pe_module->mappeddll;
+}
+
+/*****************************************************************************
+ * Load the PE main .EXE. All other loading is done by PE_LoadLibraryEx32A
+ * FIXME: this function should use PE_LoadLibraryEx32A, but currently can't
+ * due to the TASK_CreateTask stuff.
+ */
 HINSTANCE16 PE_LoadModule( HFILE32 hFile, OFSTRUCT *ofs, LOADPARAMS* params )
 {
     HMODULE16 hModule;
     HINSTANCE16 hInstance;
     NE_MODULE *pModule;
-    IMAGE_DOS_HEADER mz_header;
-    int fd;
 
     if ((hModule = MODULE_CreateDummyModule( ofs )) < 32) return hModule;
     pModule = (NE_MODULE *)GlobalLock16( hModule );
     pModule->flags = NE_FFLAGS_WIN32;
 
-    /* FIXME: Hack because PE_LoadModule is recursive */
-    fd = dup( FILE_GetUnixHandle(hFile) );
-    _lclose32( hFile );
-    lseek( fd, 0, SEEK_SET );
-    read( fd, &mz_header, sizeof(mz_header) );
-
-    PE_LoadImage( &pModule->pe_module, fd, hModule, mz_header.e_lfanew, ofs );
+    pModule->pe_module = PE_LoadImage( FILE_GetUnixHandle(hFile) );
+    _lclose32(hFile);
     if (!pModule->pe_module)
     	return 21;
-    close( fd );
 
     hInstance = MODULE_CreateInstance( hModule, params );
-
     if (!(pModule->pe_module->pe_header->FileHeader.Characteristics & IMAGE_FILE_DLL))
     {
         TASK_CreateTask( hModule, hInstance, 0,
@@ -619,10 +745,11 @@
                          (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
                          *((WORD*)PTR_SEG_TO_LIN(params->showCmd) + 1) );
     }
+    PE_MapImage(pModule->pe_module,(PDB32*)GetCurrentProcessId(),ofs,0);
     return hInstance;
 }
 
-int PE_UnloadImage( HMODULE16 hModule )
+int PE_UnloadImage( HMODULE32 hModule )
 {
 	printf("PEunloadImage() called!\n");
 	/* free resources, image, unmap */
@@ -634,19 +761,13 @@
  * DLL_PROCESS_ATTACH. Only new created threads do DLL_THREAD_ATTACH
  * (SDK)
  */
-static void PE_InitDLL(HMODULE16 hModule, DWORD type,LPVOID lpReserved)
+static void PE_InitDLL(PE_MODREF *pem, DWORD type,LPVOID lpReserved)
 {
-    NE_MODULE *pModule;
-    PE_MODULE *pe;
-    unsigned int load_addr;
+    PE_MODULE		*pe = pem->pe_module;
+    unsigned int	load_addr = pem->load_addr;
 
-    hModule = GetExePtr(hModule);
-    if (!(pModule = MODULE_GetPtr(hModule))) return;
-    if (!(pModule->flags & NE_FFLAGS_WIN32) || !(pe = pModule->pe_module))
-        return;
-
-    load_addr = pe->load_addr;
-
+    if (type==DLL_PROCESS_ATTACH)
+	pem->flags |= PE_MODREF_PROCESS_ATTACHED;
 #ifndef WINELIB
     if (Options.debug) {
             DBG_ADDR addr = { NULL, 0, RVA(pe->pe_header->OptionalHeader.AddressOfEntryPoint) };
@@ -666,58 +787,81 @@
     if (	(pe->pe_header->FileHeader.Characteristics & IMAGE_FILE_DLL) &&
 		(pe->pe_header->OptionalHeader.AddressOfEntryPoint)
     ) {
-	printf("InitPEDLL() called!\n");
-	CallDLLEntryProc32( 
-	    (FARPROC32)RVA(pe->pe_header->OptionalHeader.AddressOfEntryPoint),
-	    hModule,
-	    type,
-	    (DWORD)lpReserved
-	);
+        FARPROC32 entry = (FARPROC32)RVA(pe->pe_header->OptionalHeader.AddressOfEntryPoint);
+        dprintf_relay( stddeb, "CallTo32(entryproc=%p,module=%d,type=%ld,res=%p)\n",
+                       entry, pe->mappeddll, type, lpReserved );
+        entry( pe->mappeddll, type, lpReserved );
     }
 }
 
-void PE_InitializeDLLs(HMODULE16 hModule,DWORD type,LPVOID lpReserved)
-{
-	NE_MODULE *pModule;
-	HMODULE16 *pDLL;
-	pModule = MODULE_GetPtr( GetExePtr(hModule) );
-	if (pModule->dlls_to_init)
-	{
-		HGLOBAL16 to_init = pModule->dlls_to_init;
-		pModule->dlls_to_init = 0;
-	
-		for (pDLL = (HMODULE16 *)GlobalLock16( to_init ); *pDLL; pDLL++)
-		{
-                    PE_InitializeDLLs( *pDLL, type, lpReserved);
+/* Call the DLLentry function of all dlls used by that process.
+ * (NOTE: this may recursively call this function (if a library calls
+ * LoadLibrary) ... but it won't matter)
+ */
+void PE_InitializeDLLs(PDB32 *process,DWORD type,LPVOID lpReserved) {
+	PE_MODREF	*pem;
+
+	pem = process->modref_list;
+	while (pem) {
+		if (pem->flags & PE_MODREF_NO_DLL_CALLS) {
+			pem = pem->next;
+			continue;
 		}
-		GlobalFree16( to_init );
+		if (type==DLL_PROCESS_ATTACH) {
+			if (pem->flags & PE_MODREF_PROCESS_ATTACHED) {
+				pem = pem->next;
+				continue;
+			}
+		}
+		PE_InitDLL( pem, type, lpReserved );
+		pem = pem->next;
 	}
-	PE_InitDLL( hModule, type, lpReserved );
 }
 
-void PE_InitTls( PE_MODULE *module )
+void PE_InitTls(PDB32 *pdb)
 {
-   /* FIXME: tls callbacks ??? */
-   DWORD  index;
-   DWORD  datasize;
-   DWORD  size;
-   LPVOID mem;
-   LPIMAGE_TLS_DIRECTORY pdir;
+	/* FIXME: tls callbacks ??? */
+	PE_MODREF		*pem;
+	IMAGE_NT_HEADERS	*peh;
+	DWORD			size,datasize,index;
+	LPVOID			mem;
+	LPIMAGE_TLS_DIRECTORY	pdir;
 
-    if (!module->pe_header->OptionalHeader.DataDirectory[IMAGE_FILE_THREAD_LOCAL_STORAGE].VirtualAddress)
-        return;
+	pem = pdb->modref_list;
+	while (pem) {
+		peh = pem->pe_module->pe_header;
+		if (!peh->OptionalHeader.DataDirectory[IMAGE_FILE_THREAD_LOCAL_STORAGE].VirtualAddress) {
+			pem = pem->next;
+			continue;
+		}
+		pdir = (LPVOID)(pem->load_addr + peh->OptionalHeader.
+			DataDirectory[IMAGE_FILE_THREAD_LOCAL_STORAGE].VirtualAddress);
+		index	= TlsAlloc();
+		datasize= pdir->EndAddressOfRawData-pdir->StartAddressOfRawData;
+		size	= datasize + pdir->SizeOfZeroFill;
+		mem=VirtualAlloc(0,size,MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE);
+		memcpy(mem,(LPVOID) pdir->StartAddressOfRawData, datasize);
+		TlsSetValue(index,mem);
+		*(pdir->AddressOfIndex)=index;   
+		pem=pem->next;
+	}
+}
 
-    pdir = (LPVOID)(module->load_addr + module->pe_header->OptionalHeader.
-               DataDirectory[IMAGE_FILE_THREAD_LOCAL_STORAGE].VirtualAddress);
-    index = TlsAlloc();
-    datasize = pdir->EndAddressOfRawData-pdir->StartAddressOfRawData;
-    size     = datasize + pdir->SizeOfZeroFill;
-        
-    mem = VirtualAlloc(0,size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
-    
-    memcpy(mem,(LPVOID) pdir->StartAddressOfRawData, datasize);
-    TlsSetValue(index,mem);
-    *(pdir->AddressOfIndex)=index;   
+/****************************************************************************
+ *		DisableThreadLibraryCalls (KERNEL32.74)
+ * Don't call DllEntryPoint for DLL_THREAD_{ATTACH,DETACH} if set.
+ */
+BOOL32 WINAPI DisableThreadLibraryCalls(HMODULE32 hModule)
+{
+	PDB32	*process = (PDB32*)GetCurrentProcessId();
+	PE_MODREF	*pem = process->modref_list;
+
+	while (pem) {
+		if (pem->pe_module->mappeddll == hModule)
+			pem->flags|=PE_MODREF_NO_DLL_CALLS;
+		pem = pem->next;
+	}
+	return TRUE;
 }
 
 #endif /* WINELIB */
diff --git a/loader/pe_resource.c b/loader/pe_resource.c
index 2d2bbaf..9b8ae7e 100644
--- a/loader/pe_resource.c
+++ b/loader/pe_resource.c
@@ -18,6 +18,8 @@
 #include "pe_image.h"
 #include "module.h"
 #include "heap.h"
+#include "task.h"
+#include "process.h"
 #include "libres.h"
 #include "stackframe.h"
 #include "neexe.h"
@@ -25,20 +27,24 @@
 #include "debug.h"
 
 /**********************************************************************
- *  HMODULE32toPE_MODULE 
+ *  HMODULE32toPE_MODREF 
  *
- * small helper function to get a PE_MODULE from a passed HMODULE32
+ * small helper function to get a PE_MODREF from a passed HMODULE32
  */
-static PE_MODULE*
-HMODULE32toPE_MODULE(HMODULE32 hmod) {
+static PE_MODREF*
+HMODULE32toPE_MODREF(HMODULE32 hmod) {
 	NE_MODULE	*pModule;
+	PDB32		*pdb = (PDB32*)GetCurrentProcessId();
+	PE_MODREF	*pem;
 
 	if (!hmod) hmod = GetTaskDS(); /* FIXME: correct? */
-	hmod = GetExePtr( hmod );  /* In case we were passed an hInstance */
-
+	hmod = MODULE_HANDLEtoHMODULE32( hmod );
+	if (!hmod) return NULL;
 	if (!(pModule = MODULE_GetPtr( hmod ))) return 0;
-	if (!(pModule->flags & NE_FFLAGS_WIN32)) return 0;
-	return pModule->pe_module;
+	pem = pdb->modref_list;
+	while (pem && pem->pe_module->mappeddll != hmod)
+		pem=pem->next;
+	return pem;
 }
 
 /**********************************************************************
@@ -106,12 +112,12 @@
     LPIMAGE_RESOURCE_DIRECTORY resdirptr;
     DWORD root;
     HANDLE32 result;
-    PE_MODULE	*pe = HMODULE32toPE_MODULE(hModule);
+    PE_MODREF	*pem = HMODULE32toPE_MODREF(hModule);
 
-    if (!pe || !pe->pe_resource)
+    if (!pem || !pem->pe_resource)
     	return 0;
 
-    resdirptr = pe->pe_resource;
+    resdirptr = pem->pe_resource;
     root = (DWORD) resdirptr;
     if ((resdirptr = GetResDirEntryW(resdirptr, type, root)) == NULL)
 	return 0;
@@ -130,13 +136,13 @@
  */
 HANDLE32 PE_LoadResource32( HINSTANCE32 hModule, HANDLE32 hRsrc )
 {
-    PE_MODULE	*pe = HMODULE32toPE_MODULE(hModule);
+    PE_MODREF	*pem = HMODULE32toPE_MODREF(hModule);
 
-    if (!pe || !pe->pe_resource)
+    if (!pem || !pem->pe_resource)
     	return 0;
     if (!hRsrc)
    	 return 0;
-    return (HANDLE32) (pe->load_addr+((LPIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->OffsetToData);
+    return (HANDLE32) (pem->load_addr+((LPIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->OffsetToData);
 }
 
 
@@ -169,21 +175,21 @@
 
 DWORD PE_SizeofResource32( HINSTANCE32 hModule, HANDLE32 hRsrc )
 {
-    PE_MODULE	*pe = HMODULE32toPE_MODULE(hModule);
+    PE_MODREF	*pem = HMODULE32toPE_MODREF(hModule);
     DWORD	max,data;
     IMAGE_DATA_DIRECTORY	dir;
 
-    if (!pe || !pe->pe_resource)
+    if (!pem || !pem->pe_resource)
     	return 0;
     if (!hRsrc) return 0;
 
     max=(DWORD)-1;
-    dir=pe->pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
+    dir=pem->pe_module->pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
     if(dir.Size)
-    	max=(DWORD)pe->pe_resource+dir.Size;
+    	max=(DWORD)pem->pe_resource+dir.Size;
 
-    data=((DWORD)pe->load_addr+((LPIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->OffsetToData);
-    walk_resdir(pe->load_addr,(DWORD)pe->pe_resource,0,data,0,&max);
+    data=((DWORD)pem->load_addr+((LPIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->OffsetToData);
+    walk_resdir(pem->load_addr,(DWORD)pem->pe_resource,0,data,0,&max);
     return max-data;
 }
 
@@ -192,24 +198,24 @@
  */
 BOOL32
 PE_EnumResourceTypes32A(HMODULE32 hmod,ENUMRESTYPEPROC32A lpfun,LONG lparam) {
-    PE_MODULE	*pe = HMODULE32toPE_MODULE(hmod);
+    PE_MODREF	*pem = HMODULE32toPE_MODREF(hmod);
     int		i;
     LPIMAGE_RESOURCE_DIRECTORY		resdir;
     LPIMAGE_RESOURCE_DIRECTORY_ENTRY	et;
     BOOL32	ret;
     HANDLE32	heap = GetProcessHeap();	
 
-    if (!pe || !pe->pe_resource)
+    if (!pem || !pem->pe_resource)
     	return FALSE;
 
-    resdir = (LPIMAGE_RESOURCE_DIRECTORY)pe->pe_resource;
+    resdir = (LPIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
     et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
     ret = FALSE;
     for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
     	LPSTR	name;
 
 	if (HIWORD(et[i].u1.Name))
-		name = HEAP_strdupWtoA(heap,0,(LPWSTR)((LPBYTE)pe->pe_resource+et[i].u1.Name));
+		name = HEAP_strdupWtoA(heap,0,(LPWSTR)((LPBYTE)pem->pe_resource+et[i].u1.Name));
 	else
 		name = (LPSTR)et[i].u1.Name;
 	ret = lpfun(hmod,name,lparam);
@@ -226,22 +232,22 @@
  */
 BOOL32
 PE_EnumResourceTypes32W(HMODULE32 hmod,ENUMRESTYPEPROC32W lpfun,LONG lparam) {
-    PE_MODULE	*pe = HMODULE32toPE_MODULE(hmod);
+    PE_MODREF	*pem = HMODULE32toPE_MODREF(hmod);
     int		i;
     LPIMAGE_RESOURCE_DIRECTORY		resdir;
     LPIMAGE_RESOURCE_DIRECTORY_ENTRY	et;
     BOOL32	ret;
 
-    if (!pe || !pe->pe_resource)
+    if (!pem || !pem->pe_resource)
     	return FALSE;
 
-    resdir = (LPIMAGE_RESOURCE_DIRECTORY)pe->pe_resource;
+    resdir = (LPIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
     et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
     ret = FALSE;
     for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
 	LPWSTR	type;
     	if (HIWORD(et[i].u1.Name))
-		type = (LPWSTR)((LPBYTE)pe->pe_resource+et[i].u1.Name);
+		type = (LPWSTR)((LPBYTE)pem->pe_resource+et[i].u1.Name);
 	else
 		type = (LPWSTR)et[i].u1.Name;
 
@@ -259,7 +265,7 @@
 PE_EnumResourceNames32A(
 	HMODULE32 hmod,LPCSTR type,ENUMRESNAMEPROC32A lpfun,LONG lparam
 ) {
-    PE_MODULE	*pe = HMODULE32toPE_MODULE(hmod);
+    PE_MODREF	*pem = HMODULE32toPE_MODREF(hmod);
     int		i;
     LPIMAGE_RESOURCE_DIRECTORY		resdir;
     LPIMAGE_RESOURCE_DIRECTORY_ENTRY	et;
@@ -267,14 +273,14 @@
     HANDLE32	heap = GetProcessHeap();	
     LPWSTR	typeW;
 
-    if (!pe || !pe->pe_resource)
+    if (!pem || !pem->pe_resource)
     	return FALSE;
-    resdir = (LPIMAGE_RESOURCE_DIRECTORY)pe->pe_resource;
+    resdir = (LPIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
     if (HIWORD(type))
 	typeW = HEAP_strdupAtoW(heap,0,type);
     else
 	typeW = (LPWSTR)type;
-    resdir = GetResDirEntryW(resdir,typeW,(DWORD)pe->pe_resource);
+    resdir = GetResDirEntryW(resdir,typeW,(DWORD)pem->pe_resource);
     if (HIWORD(typeW))
     	HeapFree(heap,0,typeW);
     if (!resdir)
@@ -285,7 +291,7 @@
     	LPSTR	name;
 
 	if (HIWORD(et[i].u1.Name))
-	    name = HEAP_strdupWtoA(heap,0,(LPWSTR)((LPBYTE)pe->pe_resource+et[i].u1.Name));
+	    name = HEAP_strdupWtoA(heap,0,(LPWSTR)((LPBYTE)pem->pe_resource+et[i].u1.Name));
 	else
 	    name = (LPSTR)et[i].u1.Name;
 	ret = lpfun(hmod,type,name,lparam);
@@ -303,17 +309,17 @@
 PE_EnumResourceNames32W(
 	HMODULE32 hmod,LPCWSTR type,ENUMRESNAMEPROC32W lpfun,LONG lparam
 ) {
-    PE_MODULE	*pe = HMODULE32toPE_MODULE(hmod);
+    PE_MODREF	*pem = HMODULE32toPE_MODREF(hmod);
     int		i;
     LPIMAGE_RESOURCE_DIRECTORY		resdir;
     LPIMAGE_RESOURCE_DIRECTORY_ENTRY	et;
     BOOL32	ret;
 
-    if (!pe || !pe->pe_resource)
+    if (!pem || !pem->pe_resource)
     	return FALSE;
 
-    resdir = (LPIMAGE_RESOURCE_DIRECTORY)pe->pe_resource;
-    resdir = GetResDirEntryW(resdir,type,(DWORD)pe->pe_resource);
+    resdir = (LPIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
+    resdir = GetResDirEntryW(resdir,type,(DWORD)pem->pe_resource);
     if (!resdir)
     	return FALSE;
     et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
@@ -321,7 +327,7 @@
     for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
 	LPWSTR	name;
     	if (HIWORD(et[i].u1.Name))
-		name = (LPWSTR)((LPBYTE)pe->pe_resource+et[i].u1.Name);
+		name = (LPWSTR)((LPBYTE)pem->pe_resource+et[i].u1.Name);
 	else
 		name = (LPWSTR)et[i].u1.Name;
 	ret = lpfun(hmod,type,name,lparam);
@@ -339,7 +345,7 @@
 	HMODULE32 hmod,LPCSTR name,LPCSTR type,ENUMRESLANGPROC32A lpfun,
 	LONG lparam
 ) {
-    PE_MODULE	*pe = HMODULE32toPE_MODULE(hmod);
+    PE_MODREF	*pem = HMODULE32toPE_MODREF(hmod);
     int		i;
     LPIMAGE_RESOURCE_DIRECTORY		resdir;
     LPIMAGE_RESOURCE_DIRECTORY_ENTRY	et;
@@ -347,15 +353,15 @@
     HANDLE32	heap = GetProcessHeap();	
     LPWSTR	nameW,typeW;
 
-    if (!pe || !pe->pe_resource)
+    if (!pem || !pem->pe_resource)
     	return FALSE;
 
-    resdir = (LPIMAGE_RESOURCE_DIRECTORY)pe->pe_resource;
+    resdir = (LPIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
     if (HIWORD(name))
 	nameW = HEAP_strdupAtoW(heap,0,name);
     else
     	nameW = (LPWSTR)name;
-    resdir = GetResDirEntryW(resdir,nameW,(DWORD)pe->pe_resource);
+    resdir = GetResDirEntryW(resdir,nameW,(DWORD)pem->pe_resource);
     if (HIWORD(nameW))
     	HeapFree(heap,0,nameW);
     if (!resdir)
@@ -364,7 +370,7 @@
 	typeW = HEAP_strdupAtoW(heap,0,type);
     else
 	typeW = (LPWSTR)type;
-    resdir = GetResDirEntryW(resdir,typeW,(DWORD)pe->pe_resource);
+    resdir = GetResDirEntryW(resdir,typeW,(DWORD)pem->pe_resource);
     if (HIWORD(typeW))
     	HeapFree(heap,0,typeW);
     if (!resdir)
@@ -372,7 +378,7 @@
     et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
     ret = FALSE;
     for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
-    	/* languages are just ids... I hope */
+    	/* languages are just ids... I hopem */
 	ret = lpfun(hmod,name,type,et[i].u1.Id,lparam);
 	if (!ret)
 		break;
@@ -388,20 +394,20 @@
 	HMODULE32 hmod,LPCWSTR name,LPCWSTR type,ENUMRESLANGPROC32W lpfun,
 	LONG lparam
 ) {
-    PE_MODULE	*pe = HMODULE32toPE_MODULE(hmod);
+    PE_MODREF	*pem = HMODULE32toPE_MODREF(hmod);
     int		i;
     LPIMAGE_RESOURCE_DIRECTORY		resdir;
     LPIMAGE_RESOURCE_DIRECTORY_ENTRY	et;
     BOOL32	ret;
 
-    if (!pe || !pe->pe_resource)
+    if (!pem || !pem->pe_resource)
     	return FALSE;
 
-    resdir = (LPIMAGE_RESOURCE_DIRECTORY)pe->pe_resource;
-    resdir = GetResDirEntryW(resdir,name,(DWORD)pe->pe_resource);
+    resdir = (LPIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
+    resdir = GetResDirEntryW(resdir,name,(DWORD)pem->pe_resource);
     if (!resdir)
     	return FALSE;
-    resdir = GetResDirEntryW(resdir,type,(DWORD)pe->pe_resource);
+    resdir = GetResDirEntryW(resdir,type,(DWORD)pem->pe_resource);
     if (!resdir)
     	return FALSE;
     et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
diff --git a/loader/resource.c b/loader/resource.c
index 31c6453..2654396 100644
--- a/loader/resource.c
+++ b/loader/resource.c
@@ -18,6 +18,7 @@
 #include "global.h"
 #include "heap.h"
 #include "neexe.h"
+#include "task.h"
 #include "accel.h"
 #include "module.h"
 #include "resource.h"
@@ -33,6 +34,11 @@
 
 extern WORD WINE_LanguageId;
 
+/* error message when 16-bit resource function is called for Win32 module */
+static const char* NEWin32FailureString = "fails with Win32 module\n";
+/* error message when 32-bit resource function is called for Win16 module */
+static const char* PEWin16FailureString = "fails with Win16 module\n";
+
 /**********************************************************************
  *	    FindResource16    (KERNEL.60)
  */
@@ -40,9 +46,10 @@
 {
     NE_MODULE *pModule;
 
-    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
+    hModule = MODULE_HANDLEtoHMODULE16( hModule ); 
     dprintf_resource(stddeb, "FindResource16: module=%04x type=", hModule );
     PrintId( type );
+
     if (HIWORD(name))  /* Check for '#xxx' name */
     {
 	char *ptr = PTR_SEG_TO_LIN( name );
@@ -50,20 +57,23 @@
 	    if (!(name = (SEGPTR)atoi( ptr + 1 ))) return 0;
 	}
     }
+
     dprintf_resource( stddeb, " name=" );
     PrintId( name );
     dprintf_resource( stddeb, "\n" );
-    if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
-#ifndef WINELIB
-    if (pModule->flags & NE_FFLAGS_WIN32)
+
+    if ((pModule = MODULE_GetPtr( hModule )))
     {
-        fprintf(stderr,"Don't know how to FindResource16() for Win32 module\n");
-        return 0;
-    }
-    return NE_FindResource( hModule, type, name );
+#ifndef WINELIB
+	if (pModule->flags & NE_FFLAGS_WIN32)
+	    fprintf(stderr,"FindResource16: %s", NEWin32FailureString);
+	else
+	    return NE_FindResource( hModule, type, name );
 #else
-    return LIBRES_FindResource16( hModule, name, type );
+	return LIBRES_FindResource16( hModule, name, type );
 #endif
+    }
+    return 0;
 }
 
 
@@ -109,7 +119,7 @@
     NE_MODULE *pModule;
 
     if (!hModule) hModule = GetTaskDS();
-    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
+    hModule = MODULE_HANDLEtoHMODULE32( hModule );
     dprintf_resource(stddeb, "FindResource32W: module=%08x type=", hModule );
     if (HIWORD(type))
     	dprintf_resource(stddeb,"%p",type);
@@ -145,21 +155,22 @@
 {
     NE_MODULE *pModule;
 
-    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
+    hModule = MODULE_HANDLEtoHMODULE16( hModule );
     dprintf_resource(stddeb, "LoadResource16: module=%04x res=%04x\n",
                      hModule, hRsrc );
     if (!hRsrc) return 0;
-    if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
-#ifndef WINELIB
-    if (pModule->flags & NE_FFLAGS_WIN32)
+    if ((pModule = MODULE_GetPtr( hModule )))
     {
-        fprintf(stderr,"Don't know how to LoadResource16() for Win32 module\n");
-        return 0;
-    }
-    return NE_LoadResource( hModule, hRsrc );
+#ifndef WINELIB
+	if (pModule->flags & NE_FFLAGS_WIN32)
+	    fprintf(stderr,"LoadResource16: %s", NEWin32FailureString);
+	else
+	    return NE_LoadResource( hModule, hRsrc );
 #else
-    return LIBRES_LoadResource( hModule, hRsrc );
+	return LIBRES_LoadResource( hModule, hRsrc );
 #endif
+    }
+    return 0;
 }
 
 /**********************************************************************
@@ -171,7 +182,7 @@
     NE_MODULE *pModule;
 
     if (!hModule) hModule = GetTaskDS(); /* FIXME: see FindResource32W */
-    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
+    hModule = MODULE_HANDLEtoHMODULE32( hModule );
     dprintf_resource(stddeb, "LoadResource32: module=%04x res=%04x\n",
                      hModule, hRsrc );
     if (!hRsrc) return 0;
@@ -179,7 +190,7 @@
     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
     if (!(pModule->flags & NE_FFLAGS_WIN32))
     {
-    	fprintf(stderr,"LoadResource32: tried to load a non win32 resource.\n");
+    	fprintf(stderr,"LoadResource32: %s", PEWin16FailureString );
    	return 0;  /* FIXME? */
     }
     return PE_LoadResource32(hModule,hRsrc);
@@ -201,11 +212,11 @@
 
     dprintf_resource(stddeb, "LockResource: handle=%04x\n", handle );
     if (!handle) return (SEGPTR)0;
-    hModule = GetExePtr( handle );
+    hModule = MODULE_HANDLEtoHMODULE16( handle );
     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
     if (pModule->flags & NE_FFLAGS_WIN32)
     {
-        fprintf(stderr,"Don't know how to LockResource() for Win32 module\n");
+        fprintf(stderr,"LockResource16: %s", NEWin32FailureString);
         return 0;
     }
     return NE_LockResource( hModule, handle );
@@ -223,11 +234,11 @@
 
     dprintf_resource(stddeb, "LockResource: handle=%04x\n", handle );
     if (!handle) return NULL;
-    hModule = GetExePtr( handle );
+    hModule = MODULE_HANDLEtoHMODULE16( handle );
     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
     if (pModule->flags & NE_FFLAGS_WIN32)
     {
-        fprintf(stderr,"Don't know how to LockResource16() for Win32 module\n");
+        fprintf(stderr,"LockResource16: %s", NEWin32FailureString);
         return 0;
     }
     return (LPSTR)PTR_SEG_TO_LIN( NE_LockResource( hModule, handle ) );
@@ -257,11 +268,11 @@
 
     dprintf_resource(stddeb, "FreeResource16: handle=%04x\n", handle );
     if (!handle) return FALSE;
-    hModule = GetExePtr( handle );
+    hModule = MODULE_HANDLEtoHMODULE16( handle );
     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
     if (pModule->flags & NE_FFLAGS_WIN32)
     {
-        fprintf(stderr,"Don't know how to FreeResource16() for Win32 module\n");
+        fprintf(stderr,"FreeResource16: %s", NEWin32FailureString);
         return 0;
     }
     return NE_FreeResource( hModule, handle );
@@ -287,7 +298,7 @@
 {
     NE_MODULE *pModule;
 
-    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
+    hModule = MODULE_HANDLEtoHMODULE16( hModule );
     dprintf_resource(stddeb, "AccessResource16: module=%04x res=%04x\n",
                      hModule, hRsrc );
     if (!hRsrc) return 0;
@@ -295,7 +306,7 @@
 #ifndef WINELIB
     if (pModule->flags & NE_FFLAGS_WIN32)
     {
-        fprintf(stderr,"Don't know how to AccessResource16() for Win32 module\n");
+        fprintf(stderr,"AccessResource16: %s", NEWin32FailureString);
         return 0;
     }
     return NE_AccessResource( hModule, hRsrc );
@@ -310,7 +321,7 @@
  */
 INT32 WINAPI AccessResource32( HINSTANCE32 hModule, HRSRC32 hRsrc )
 {
-    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
+    hModule = MODULE_HANDLEtoHMODULE32( hModule );
     dprintf_resource(stddeb, "AccessResource: module=%04x res=%04x\n",
                      hModule, hRsrc );
     if (!hRsrc) return 0;
@@ -326,14 +337,14 @@
 {
     NE_MODULE *pModule;
 
-    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
+    hModule = MODULE_HANDLEtoHMODULE16( hModule );
     dprintf_resource(stddeb, "SizeofResource16: module=%04x res=%04x\n",
                      hModule, hRsrc );
     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
 #ifndef WINELIB
     if (pModule->flags & NE_FFLAGS_WIN32)
     {
-        fprintf(stderr,"Don't know how to SizeOfResource16() for Win32 module\n");
+        fprintf(stderr,"SizeOfResource16: %s", NEWin32FailureString);
         return 0;
     }
     return NE_SizeofResource( hModule, hRsrc );
@@ -348,7 +359,7 @@
  */
 DWORD WINAPI SizeofResource32( HINSTANCE32 hModule, HRSRC32 hRsrc )
 {
-    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
+    hModule = MODULE_HANDLEtoHMODULE32( hModule );
     dprintf_resource(stddeb, "SizeofResource32: module=%04x res=%04x\n",
                      hModule, hRsrc );
 #ifndef WINELIB
@@ -367,7 +378,7 @@
 {
     NE_MODULE *pModule;
 
-    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
+    hModule = MODULE_HANDLEtoHMODULE16( hModule );
     dprintf_resource(stddeb, "AllocResource: module=%04x res=%04x size=%ld\n",
                      hModule, hRsrc, size );
     if (!hRsrc) return 0;
@@ -375,7 +386,7 @@
 #ifndef WINELIB
     if (pModule->flags & NE_FFLAGS_WIN32)
     {
-        fprintf(stderr,"Don't know how to AllocResource() for Win32 module\n");
+        fprintf(stderr,"AllocResource16: %s", NEWin32FailureString);
         return 0;
     }
     return NE_AllocResource( hModule, hRsrc, size );
@@ -394,7 +405,7 @@
 {
     dprintf_resource(stddeb,"DirectResAlloc(%04x,%04x,%04x)\n",
                      hInstance, wType, wSize );
-    hInstance = GetExePtr(hInstance);
+    hInstance = MODULE_HANDLEtoHMODULE16(hInstance);
     if(!hInstance)return 0;
     if(wType != 0x10)	/* 0x10 is the only observed value, passed from
                            CreateCursorIndirect. */
@@ -405,6 +416,9 @@
 
 /**********************************************************************
  *			LoadAccelerators16	[USER.177]
+ *
+ * FIXME: this code leaks memory because HACCEL must be a result of LoadResource()
+ *        (see TWIN for hints).
  */
 HACCEL16 WINAPI LoadAccelerators16(HINSTANCE16 instance, SEGPTR lpTableName)
 {
@@ -578,6 +592,8 @@
     int string_num;
     int i;
 
+    if (HIWORD(resource_id)==0xFFFF) /* netscape 3 passes this */
+	resource_id = (UINT32)(-((INT32)resource_id));
     dprintf_resource(stddeb, "LoadString: instance = %04x, id = %04x, buffer = %08x, "
 	   "length = %d\n", instance, (int)resource_id, (int) buffer, buflen);
 
@@ -747,15 +763,24 @@
 /**********************************************************************
  *	SetResourceHandler	(KERNEL.43)
  */
-FARPROC16 WINAPI SetResourceHandler( HINSTANCE16 instance, SEGPTR s,
-                                     FARPROC16 farproc )
+FARPROC16 WINAPI SetResourceHandler( HMODULE16 hModule, SEGPTR s,
+                                     FARPROC16 resourceHandler )
 {
-    if (HIWORD(s))
-	fprintf(stderr,"SetResourceHandler(%04x,%s,%p), empty STUB!\n",
-		instance,(char*)PTR_SEG_TO_LIN(s),farproc);
-    else
-	fprintf(stderr,"SetResourceHandler(%04x,0x%04x,%p), empty STUB!\n",
-		instance,LOWORD(s),farproc);
+    NE_MODULE *pModule;
+
+    hModule = GetExePtr( hModule );
+
+    dprintf_resource(stddeb, "SetResourceHandler: module=%04x type=", hModule );
+    PrintId( s );
+    dprintf_resource( stddeb, "\n" );
+
+    if ((pModule = MODULE_GetPtr( hModule )))
+    {
+	if (pModule->flags & NE_FFLAGS_WIN32)
+	    fprintf(stderr,"SetResourceHandler: %s", NEWin32FailureString);
+	else if (pModule->res_table)
+	    return NE_SetResourceHandler( hModule, s, resourceHandler );
+    }
     return NULL;
 }
 
diff --git a/loader/task.c b/loader/task.c
index 467548c..3266976 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -9,7 +9,7 @@
 #include <string.h>
 
 #include "windows.h"
-#include "task.h"
+#include "user.h"
 #include "callback.h"
 #include "file.h"
 #include "global.h"
@@ -40,9 +40,9 @@
   /* Min. number of thunks allocated when creating a new segment */
 #define MIN_THUNKS  32
 
-extern INT32 WINSOCK_DeleteTaskWSI( TDB* pTask, struct _WSINFO* pwsi );
-extern void  USER_AppExit( HTASK16, HINSTANCE16, HQUEUE16 );
-extern void  PE_InitTls( PE_MODULE *module );
+extern INT32 WINSOCK_DeleteTaskWSI( TDB* pTask, struct _WSINFO* );
+extern BOOL32 MODULE_FreeModule( HMODULE16 hModule, TDB* ptaskContext );
+extern void PE_InitTls( PDB32 *pdb32 );
 
   /* Saved 16-bit stack for current process (Win16 only) */
 DWORD IF1632_Saved16_ss_sp = 0;
@@ -370,12 +370,16 @@
 
         extern void InitTask( CONTEXT *context );
 
+        FARPROC32 entry = (FARPROC32)(pCurrentProcess->exe_modref->load_addr + 
+                 pCurrentProcess->exe_modref->pe_module->pe_header->OptionalHeader.AddressOfEntryPoint);
+
         InitTask( NULL );
         InitApp( pTask->hModule );
         __asm__ __volatile__("movw %w0,%%fs"::"r" (pCurrentThread->teb_sel));
-        PE_InitializeDLLs( pTask->hModule, DLL_PROCESS_ATTACH, (LPVOID)-1 );
-        exit_code = CallTaskStart32((FARPROC32)(pModule->pe_module->load_addr + 
-                pModule->pe_module->pe_header->OptionalHeader.AddressOfEntryPoint) );
+
+        PE_InitializeDLLs( pCurrentProcess, DLL_PROCESS_ATTACH, (LPVOID)-1 );
+        dprintf_relay( stddeb, "CallTo32(entryproc=%p)\n", entry );
+        exit_code = entry();
         TASK_KillCurrentTask( exit_code );
     }
     else
@@ -437,6 +441,7 @@
     STACK32FRAME *frame32;
 #ifndef WINELIB32
     extern DWORD CALLTO16_RetAddr_word;
+    extern void CALLTO16_Restore();
 #endif
     
     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
@@ -546,18 +551,21 @@
 
     /* Create the Win32 part of the task */
 
-    pdb32 = PROCESS_Create( pTask );
+    pCurrentProcess = pdb32 = PROCESS_Create( pTask, cmdLine );
     pdb32->task = hTask;
     if (pModule->flags & NE_FFLAGS_WIN32)
     {
+    /*
         LPTHREAD_START_ROUTINE start =
-            (LPTHREAD_START_ROUTINE)(pModule->pe_module->load_addr +
-            pModule->pe_module->pe_header->OptionalHeader.AddressOfEntryPoint);
-        pTask->thdb = THREAD_Create( pdb32, 0, start );
+            (LPTHREAD_START_ROUTINE)(
+	    	pCurrentProcess->exe_modref->load_addr +
+		pCurrentProcess->exe_modref->pe_module->pe_header->OptionalHeader.AddressOfEntryPoint);
+     */
+        pTask->thdb = THREAD_Create( pdb32, 0, 0 );
 #ifndef WINELIB
         /* FIXME: should not be done here */
         pCurrentThread = pTask->thdb;
-        PE_InitTls( pModule->pe_module );
+        PE_InitTls( pdb32 );
 #endif
     }
     else
@@ -575,6 +583,7 @@
     frame32->ebx = 0;
     frame32->ebp = 0;
 #ifndef WINELIB
+    frame32->restore_addr = (DWORD)CALLTO16_Restore;
     frame32->retaddr = (DWORD)TASK_CallToStart;
     frame32->codeselector = WINE_CODE_SELECTOR;
 #endif
@@ -613,10 +622,12 @@
     {
         if (pModule->flags & NE_FFLAGS_WIN32)
         {
-            DBG_ADDR addr = { NULL, 0, pModule->pe_module->load_addr + 
-                              pModule->pe_module->pe_header->OptionalHeader.AddressOfEntryPoint };
+	/*
+            DBG_ADDR addr = { NULL, 0, pCurrentProcess->exe_modref->load_addr + 
+                              pCurrentProcess->exe_modref->pe_module->pe_header->OptionalHeader.AddressOfEntryPoint };
             fprintf( stderr, "Win32 task '%s': ", name );
             DEBUG_AddBreakpoint( &addr );
+	 */
         }
         else
         {
@@ -656,7 +667,7 @@
 
     /* Free the task module */
 
-    FreeModule16( pTask->hModule );
+    MODULE_FreeModule( pTask->hModule, pTask );
 
     /* Free the selector aliases */
 
@@ -691,17 +702,16 @@
 
     dprintf_task(stddeb, "Killing task %04x\n", hCurrentTask );
 
-    /* Clean up sockets */
+    /* Delete active sockets */
 
-    if( pTask->pwsi ) 
-    {
-	dprintf_task(stddeb, "\tremoving socket table\n");
+    if( pTask->pwsi )
 	WINSOCK_DeleteTaskWSI( pTask, pTask->pwsi );
-    }
 
     /* Perform USER cleanup */
 
-    USER_AppExit( hCurrentTask, pTask->hInstance, pTask->hQueue );
+    if (pTask->userhandler)
+        pTask->userhandler( hCurrentTask, USIG_TERMINATION, 0,
+                            pTask->hInstance, pTask->hQueue );
 
     if (hTaskToKill && (hTaskToKill != hCurrentTask))
     {
@@ -867,6 +877,8 @@
 
 /***********************************************************************
  *           InitTask  (KERNEL.91)
+ *
+ * Called by the application startup code.
  */
 void WINAPI InitTask( CONTEXT *context )
 {
@@ -880,7 +892,13 @@
     if (!(pTask = (TDB *)GlobalLock16( hCurrentTask ))) return;
     if (!(pModule = MODULE_GetPtr( pTask->hModule ))) return;
 
+    /* This is a hack to install task USER signal handler before 
+     * implicitly loaded DLLs are initialized (see windows/user.c) */
+
+    pTask->userhandler = (USERSIGNALPROC)&USER_SignalProc;
+
 #ifndef WINELIB
+    /* Initialize implicitly loaded DLLs */
     NE_InitializeDLLs( pTask->hModule );
 #endif
 
@@ -1374,6 +1392,8 @@
 
 /***********************************************************************
  *           SetTaskSignalProc   (KERNEL.38)
+ *
+ * Real 16-bit interface is provided by the THUNK_SetTaskSignalProc.
  */
 FARPROC16 WINAPI SetTaskSignalProc( HTASK16 hTask, FARPROC16 proc )
 {
@@ -1382,8 +1402,8 @@
 
     if (!hTask) hTask = hCurrentTask;
     if (!(pTask = (TDB *)GlobalLock16( hTask ))) return NULL;
-    oldProc = pTask->userhandler;
-    pTask->userhandler = proc;
+    oldProc = (FARPROC16)pTask->userhandler;
+    pTask->userhandler = (USERSIGNALPROC)proc;
     return oldProc;
 }
 
@@ -1464,7 +1484,6 @@
     return 0;
 }
 
-
 /***********************************************************************
  *           TaskFirst   (TOOLHELP.63)
  */