Release 980517

Sun May 17 16:23:56 1998  Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>

	* [file/profile.c]
	Fix the return value of PROFILE_GetSection

	* [misc/crtdll.c]
	Do _getdrive, fix _chdrive.

	* [misc/commdlg.c]
	First cut at ChooseColor[WA].

	* [misc/network.c]
	Do something sensible for WNetGetDirectoryType16.

Sun May 17 10:21:35 1998  Andreas Mohr <100.30936@germany.net>

	* [controls/menu.c]
	Fixed disabled sub menus with MF_BYPOSITION that were not disabled.

	* [misc/crtdll.c] [relay32/crtdll.spec] [include/winerror.h]
	Implemented fscanf, fsetpos, _access, _fpreset (thanks to Uwe Bonnes),
	and _ltoa. 

	* [loader/task.c]
	MakeProcInstance: must use CURRENT_DS if hInst == NULL.

	* [misc/shell.c]
	SHELL_GetResourceTable, InternalExtractIcon: fixed broken .ICO handling

	* [windows/winpos.c]
	DeferWindowPos: removed "same parent" requirement.
	Which doc states that this is required ?

Sat May 16 20:08:11 1998  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [loader/module.c] [loader/ne/module.c]
	More NE module cleanups.

	* [loader/task.c]
	Fixed SwitchStackBack().

Fri May 15 10:04:27 1998  Marcus Meissner <marcus@jet.franken.de>

	* [configure.in][inlcude/acconfig.h]
	Fixed broken OSS check, added check for working sigaltstack,
	fixed broken statfs checks on some linux systems.

	* [files/directory.c][loader/pe_image.c][relay32/builtin.c]
	  [loader/module.c]
	Added handling of win32 module pathnames.

	* [relay32/wnaspi32.spec]
	New file.

	* [misc/lzexpand.c]
	LZCopy auto-decompresses LZ compressed files, even if they are not
	specially flagged. Fixes some InstallShield problems.

	* [misc/registry.c]
	Some fixes for RegQueryInfoKey (reference program monkey.exe
	from Win32 SDK works now better). Probably still has faults.

Fri May 15 08:58:58 1998  Martin Boehme <boehme@informatik.mu-luebeck.de>

	* [graphics/mapping.c] [include/dc.h] [include/gdi.h] [objects/dc.c]
	Reworked the way world transformations and mapping modes are handled
	so that both of these transformations can be computed in a single
	step.

	* [graphics/painting.c] [graphics/path.c] [include/path.h]
	More GDI path support.

	* [graphics/x11drv/graphics.c]
	Fixed the return value of GRAPH_DrawArc for the zero height /
	zero width case to reflect Windows' behaviour.

	* [include/windows.h] [relay32/gdi32.spec] [objects/dc.c]
	Implemented ModifyWorldTransform and CombineTransform.

Tue May 14 18:03:46 1998  Eric Kohl <ekohl@abo.rhein-zeitung.de>

	* [controls/commctrl.c][relay32/comctl32.spec]
	  [controls/*.c][include/*.h]
	Implemented InitCommonControlsEx (dll version 4.72 compatible).
	InitCommonControls calls ImageCommonControlsEx.
	Registering code of the common controls had to be changed
	(see XXXX_Register functions).

	* [controls/status.c][include/commctrl.h][include/status.h]
	Implemented most new features and fixed the look and feel.

	* [contols/commctrl.c][include/commctrl.h][relay32/comctl32.spec]
	Implemented MenuHelp (incomplete).

	* [controls/status.c][controls/progress.c]
	Changed allocation strategy for control specific memory.

	* [controls/header.c][include/header.h][include/commctrl.h]
	First implementation of header control.

	* [windows/defwnd.c][windows/syscolors.c]
	Fixed default control colors for Win95 look.

	* [windows/nonclient.c]
	Fixed off by one error for Win95 look. Top border of child windows
	should be visible.

	* [misc/imagelist.h]
	Improved documentation and fixed some bugs.

Thu May 14 15:42:21 1998  Robert Wilhelm  <robert@physiol.med.tu-muenchen.de>

	* [relay32/crtdll.spec]
	Added hypot,j0,j1,jn and ceil.

Wed May 13 19:10:10 1998  Pascal Cuoq <pcuoq@ens-lyon.fr>

	* [controls/listbox.c]
	Item height is now exactly font height.
	Wine listboxes now behave like Windows' when they are 
	created without WS_VSCROLL but the program subsequently 
	calls ShowScrollBar or SetScrollInfo.

Wed May 13 18:33:01 1998  Ulrich Weigand <weigand@informatik.uni-erlangen.de>

	* [relay32/relay386.c]
	Restore ES also in the non-debug case.

	* [windows/event.c]
	Bugfix: Blocking TSXNextEvent could deadlock Wine.

	* [win32/process.c] [windows/message.c]
	Silly stubs for MsgWaitForMultipleObjects / PostThreadMessage
	that make some programs run better.

	* [windows/winproc.c]
	WINPROC_MapMsg32Ato16/16To32A: added WM_NOTIFY.  

        * [win32/kernel32.c]
	Added 16->32 thunking and improved 32->16 thunking functions.

	* [tools/build.c]
	Added new variant of CallFrom16 stub for use with Win95 thunks.

	* [if1632/kernel.spec] [if1632/builtin.c] [win32/kernel32.c]
	Added a few undocumented KERNEL functions.

	* [loader/ne/module.c] [loader/ne/segment.c]
	Call DllEntryPoint for 16-bit DLLs with subsystem >= 4.0.

	* [win32/kernel32.spec] [win32/wow32.spec] [win32/ordinals.c]
	Use names from the Oct 94 beta release for undoc. functions.

Wed May 13 14:18:26 1998  Matthew Becker <mbecker@glasscity.net>

	* [misc/registry.c]
	Code cleanup.

	* [misc/cpu.c]
	Commented out the registry puts temporarily.

	* [programs/regtest/*]
	New registry testing program.

Tue May 12 22:54:03 1998  Michael Mess <michael@kawo2.rwth-aachen.de>

	* [multimedia/audio.c]
	ioctl's do not commute in /dev/dsp initialization.

Tue May 12 20:11:42 1998  Karl Garrison <karlos@eznet.net>

	* [win32/console.c]
	Implemented SetConsoleTextAttribute, FillConsoleOutputCharacter.
	Improved cursor positioning.
	This allows for text colors in an xterm, rxvt, or console.

Tue May 12 17:57:52 1998  Petter Reinholdtsen <pere@td.org.uit.no>

	* [Makefile.in]
	Create prefix/{bin|lib} directories if missing during install.

Sun May 10 19:37:51 1998  Jan Willamowius <jan@janhh.shnet.org>

	* [multimedia/mmio.c]
	Have mmioSetBuffer return success (0), so Corel Draw 4
	keeps working. (IO is still unbuffered)

Wed May  6 16:57:55 1998  James Juran <jrj120@psu.edu>

        * [Makefile.in] [Make.rules.in]
	Changed "make clean" to remove `textedit` backup files (*%)

	* [controls/menu.c][graphics/x11drv/xfont.c][include/libres.h]
	  [loader/main.c][loader/ne/module.c][scheduler/synchro.c]
	  [win32/time.c][windows/winpos.c][include/windows.h]
	Fixed miscellaneous compilation warnings.

	* [misc/main.c][miscemu/main.c][include/main.h]
	Moved prototypes to new include file main.h, various cleanups.

Tue May  5 21:05:06 1998  Morten Welinder  <terra@diku.dk>

	* [misc/winsock.c]
	Don't refer to __FreeBSD__ when HAVE_STRERROR is meant.

	* [misc/debugstr.c]
	For debug_dumpstrSend, send strings to stderr.

Tue May  5 21:47:40 1998  Huw D M Davies <h.davies1@physics.oxford.ac.uk>

	* [objects/region.c]
	Fix for REGION_RegionOp() if newReg is one of the source regions.

Tue May  5 18:27:32 1998  Jim Peterson <jspeter@roanoke.infi.net>

	* [misc/main.c]
	Add '-h/-help' option and print WINE_RELEASE_INFO with usage message.

	* [misc/spy.c]
	Realign trace messages.

Tue May  5 15:46:47 1998  Donnie V. Savage <dsavage@cisco.com>

	* [graphics/ddraw.c]
	Fixed compile warnings

	* [misc/winsock.c]
	Warnings should not be errors.

Tue May  5 13:40:42 1998  Jim Peterson <jspeter@roanoke.infi.net>

	* [*/*]
	Remove many warnings through explicit casts, added #include's,
	and corrected printf formats.

Tue May  5 05:18:12 1998  Insomnia (Stea Greene) <insomnia@core.binghamton.edu>

	* [graphics/ddraw.c]
	Kept unchanged portion of old palette when changing only a few
	palette entries.  Really should only deallocate the changed cells.
	This make StarCraft work almost perfectly (sound overflows still
	cause static).

Mon May  4 15:04:57 1998  Alexander V. Lukyanov <lav@long.yar.ru>

	* [misc/lstr.c]
	FormatMessage: terminate string on %0, undo linefeed strip.
diff --git a/loader/libres.c b/loader/libres.c
index 5dafc8f..eb9598b 100644
--- a/loader/libres.c
+++ b/loader/libres.c
@@ -76,7 +76,7 @@
     for(Res=ResBlock->Resources; *Res; Res++)
       if(name)
       {
-	if((*Res)->type==typeid && !lstrcmpi32W((*Res)->name,name))
+	if((*Res)->type==typeid && !lstrcmpi32W((LPCWSTR)(*Res)->name,name))
 	  return (HRSRC32)*Res;
       }
       else
diff --git a/loader/main.c b/loader/main.c
index 5ab11da..5b1eaec 100644
--- a/loader/main.c
+++ b/loader/main.c
@@ -14,6 +14,7 @@
 #include "bitmap.h"
 #include "comm.h"
 #include "win.h"
+#include "main.h"
 #include "menu.h"
 #include "atom.h"
 #include "dialog.h"
diff --git a/loader/module.c b/loader/module.c
index 63568ee..17f1bb0 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -25,18 +25,11 @@
 #include "selectors.h"
 #include "stackframe.h"
 #include "task.h"
-#include "toolhelp.h"
 #include "debug.h"
 #include "callback.h"
 
 extern BOOL32 THREAD_InitDone;
 
-extern HMODULE16 hFirstModule;  /* FIXME */
-static HMODULE16 hCachedModule = 0;  /* Module cached by MODULE_OpenFile */
-
-static HMODULE32 MODULE_LoadModule(LPCSTR name,BOOL32 force) { return 0; }
-HMODULE32 (*fnBUILTIN_LoadModule)(LPCSTR name,BOOL32 force) = MODULE_LoadModule;
-
 
 /*************************************************************************
  *		MODULE32_LookupHMODULE
@@ -58,116 +51,6 @@
     return NULL;
 }
 
-/***********************************************************************
- *           MODULE_GetPtr16
- */
-NE_MODULE *MODULE_GetPtr16( HMODULE16 hModule )
-{
-    return (NE_MODULE*)GlobalLock16( GetExePtr(hModule) );
-}
-
-
-/***********************************************************************
- *           MODULE_GetPtr32
- */
-NE_MODULE *MODULE_GetPtr32( HMODULE32 hModule )
-{
-    return (NE_MODULE*)GlobalLock16( MODULE_HANDLEtoHMODULE16(hModule) );
-}
-
-/***********************************************************************
- *           MODULE_HANDLEtoHMODULE16
- */
-HMODULE16
-MODULE_HANDLEtoHMODULE16(HANDLE32 handle) {
-    NE_MODULE	*pModule;
-
-    if (HIWORD(handle))
-    {
-        WARN(module,"looking up 0x%08x in win16 function!\n",handle);
-	/* this is a HMODULE32 */
-
-        /* walk the list looking for the correct startaddress */
-    	pModule = (NE_MODULE *)GlobalLock16( hFirstModule );
-	while (pModule)
-        {
-            if (pModule->module32 == handle) return pModule->self;
-            pModule = (NE_MODULE*)GlobalLock16(pModule->next);
-	}
-	return 0;
-    }
-    return GetExePtr(handle);
-}
-
-/***********************************************************************
- *           MODULE_OpenFile
- */
-int MODULE_OpenFile( HMODULE32 hModule )
-{
-    NE_MODULE *pModule;
-    DOS_FULL_NAME full_name;
-    char *name;
-
-    static int cachedfd = -1;
-
-    hModule = MODULE_HANDLEtoHMODULE16(hModule);
-    TRACE(module, "(%04x) cache: mod=%04x fd=%d\n",
-                    hModule, hCachedModule, cachedfd );
-    if (!(pModule = MODULE_GetPtr32( hModule ))) return -1;
-    if (hCachedModule == hModule) return cachedfd;
-    close( cachedfd );
-    hCachedModule = hModule;
-    name = NE_MODULE_NAME( pModule );
-    if (!DOSFS_GetFullName( name, TRUE, &full_name ) ||
-        (cachedfd = open( full_name.long_name, O_RDONLY )) == -1)
-        WARN( module, "Can't open file '%s' for module %04x\n",
-                 name, hModule );
-    TRACE(module, "opened '%s' -> %d\n",
-                    name, cachedfd );
-    return cachedfd;
-}
-
-
-/***********************************************************************
- *           MODULE_CreateInstance
- *
- * If lib_only is TRUE, handle the module like a library even if it is a .EXE
- */
-HINSTANCE16 MODULE_CreateInstance( HMODULE16 hModule, HINSTANCE16 *prev,
-                                   BOOL32 lib_only )
-{
-    SEGTABLEENTRY *pSegment;
-    NE_MODULE *pModule;
-    int minsize;
-    HINSTANCE16 hNewInstance;
-
-    if (!(pModule = MODULE_GetPtr16( hModule ))) return 0;
-    if (pModule->dgroup == 0)
-    {
-        if (prev) *prev = hModule;
-        return hModule;
-    }
-
-    pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
-    if (prev) *prev = pSegment->selector;
-
-      /* if it's a library, create a new instance only the first time */
-    if (pSegment->selector)
-    {
-        if (pModule->flags & NE_FFLAGS_LIBMODULE) return pSegment->selector;
-        if (lib_only) return pSegment->selector;
-    }
-
-    minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
-    if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
-    minsize += pModule->heap_size;
-    hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
-                                 minsize, hModule, FALSE, FALSE, FALSE );
-    if (!hNewInstance) return 0;
-    pSegment->selector = hNewInstance;
-    return hNewInstance;
-}
-
 
 /***********************************************************************
  *           MODULE_CreateDummyModule
@@ -312,63 +195,6 @@
 }
 
 
-/***********************************************************************
- *           MODULE_GetModuleName
- */
-LPSTR MODULE_GetModuleName( HMODULE32 hModule )
-{
-    NE_MODULE *pModule;
-    BYTE *p, len;
-    static char buffer[10];
-
-    if (!(pModule = MODULE_GetPtr32( hModule ))) return NULL;
-    p = (BYTE *)pModule + pModule->name_table;
-    len = MIN( *p, 8 );
-    memcpy( buffer, p + 1, len );
-    buffer[len] = '\0';
-    return buffer;
-}
-
-
-/**********************************************************************
- *	    MODULE_FindModule
- *
- * Find a module from a path name.
- * RETURNS
- *	the win16 module handle if found
- * 	0 if not
- */
-HMODULE32 MODULE_FindModule16(
-	LPCSTR path	/* [in] path of the module to be found */
-) {
-    HMODULE32 hModule = hFirstModule;
-    LPCSTR	filename, dotptr, modulepath, modulename;
-    BYTE	len, *name_table;
-
-    if (!(filename = strrchr( path, '\\' ))) filename = path;
-    else filename++;
-    if ((dotptr = strrchr( filename, '.' )) != NULL)
-        len = (BYTE)(dotptr - filename);
-    else len = strlen( filename );
-
-    while(hModule)
-    {
-        NE_MODULE *pModule = MODULE_GetPtr16( hModule );
-        if (!pModule) break;
-        modulepath = NE_MODULE_NAME(pModule);
-        if (!(modulename = strrchr( modulepath, '\\' )))
-            modulename = modulepath;
-        else modulename++;
-        if (!lstrcmpi32A( modulename, filename )) return hModule;
-
-        name_table = (BYTE *)pModule + pModule->name_table;
-        if ((*name_table == len) && !lstrncmpi32A(filename, name_table+1, len))
-            return hModule;
-        hModule = pModule->next;
-    }
-    return 0;
-}
-
 /**********************************************************************
  *	    MODULE_FindModule32
  *
@@ -427,105 +253,6 @@
 
 
 /**********************************************************************
- *	    MODULE_CallWEP
- *
- * Call a DLL's WEP, allowing it to shut down.
- * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
- */
-static BOOL16 MODULE_CallWEP( HMODULE16 hModule )
-{
-    FARPROC16 WEP = (FARPROC16)0;
-    WORD ordinal = NE_GetOrdinal( hModule, "WEP" );
-
-    if (ordinal) WEP = NE_GetEntryPoint( hModule, ordinal );
-    if (!WEP)
-    {
-	WARN(module, "module %04x doesn't have a WEP\n", hModule );
-	return FALSE;
-    }
-    return Callbacks->CallWindowsExitProc( WEP, WEP_FREE_DLL );
-}
-
-
-/**********************************************************************
- *	    MODULE_FreeModule
- *
- * Remove a module from memory.
- */
-BOOL16 MODULE_FreeModule( HMODULE32 hModule, TDB* pTaskContext )
-{
-    HMODULE16 *hPrevModule;
-    NE_MODULE *pModule;
-    SEGTABLEENTRY *pSegment;
-    HMODULE16 *pModRef;
-    int i;
-
-    if (!(pModule = MODULE_GetPtr32( hModule ))) return FALSE;
-    hModule = pModule->self;
-
-    if (((INT16)(--pModule->count)) > 0 ) return TRUE;
-    else pModule->count = 0;
-
-    if (pModule->flags & NE_FFLAGS_BUILTIN)
-        return FALSE;  /* Can't free built-in module */
-
-    if (pModule->flags & NE_FFLAGS_LIBMODULE) 
-    {
-	MODULE_CallWEP( hModule );
-
-	/* Free the objects owned by the DLL module */
-
-	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;
-
-      /* Remove it from the linked list */
-
-    hPrevModule = &hFirstModule;
-    while (*hPrevModule && (*hPrevModule != hModule))
-    {
-        hPrevModule = &(MODULE_GetPtr16( *hPrevModule ))->next;
-    }
-    if (*hPrevModule) *hPrevModule = pModule->next;
-
-      /* Free all the segments */
-
-    pSegment = NE_SEG_TABLE( pModule );
-    for (i = 1; i <= pModule->seg_count; i++, pSegment++)
-    {
-        GlobalFree16( pSegment->selector );
-    }
-
-      /* Free the referenced modules */
-
-    pModRef = (HMODULE16*)NE_MODULE_TABLE( pModule );
-    for (i = 0; i < pModule->modref_count; i++, pModRef++)
-    {
-        FreeModule16( *pModRef );
-    }
-
-      /* Free the module storage */
-
-    if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
-    if (pModule->dlls_to_init) GlobalFree16( pModule->dlls_to_init );
-    GlobalFree16( hModule );
-
-      /* Remove module from cache */
-
-    if (hCachedModule == hModule) hCachedModule = 0;
-
-    return TRUE;
-}
-
-
-/**********************************************************************
  *	    MODULE_Load
  *
  * Implementation of LoadModule().
@@ -534,74 +261,34 @@
  * without a preceding length byte).
  * If cmd_line is NULL, the module is loaded as a library even if it is a .exe
  */
-HINSTANCE16 MODULE_Load( LPCSTR name, UINT16 uFlags,
+HINSTANCE16 MODULE_Load( LPCSTR name, BOOL32 implicit,
                          LPCSTR cmd_line, LPCSTR env, UINT32 show_cmd )
 {
-    HMODULE32 hModule;
+    HMODULE16 hModule;
     HINSTANCE16 hInstance, hPrevInstance;
     NE_MODULE *pModule;
-    OFSTRUCT ofs;
-    HFILE32 hFile;
 
     if (__winelib)
     {
+        OFSTRUCT ofs;
         lstrcpyn32A( ofs.szPathName, name, sizeof(ofs.szPathName) );
         if ((hModule = MODULE_CreateDummyModule( &ofs )) < 32) return hModule;
         pModule = (NE_MODULE *)GlobalLock16( hModule );
-        hInstance = MODULE_CreateInstance( hModule, &hPrevInstance,
-                                           (cmd_line == NULL) );
+        hInstance = NE_CreateInstance( pModule, &hPrevInstance,
+                                       (cmd_line == NULL) );
     }
     else
     {
-        hModule = MODULE_FindModule16( name );
-
-        if (!hModule)  /* We have to load the module */
-        {
-            /* Try to load the built-in first if not disabled */
-            if ((hModule = fnBUILTIN_LoadModule( name, FALSE )))
-                return MODULE_HANDLEtoHMODULE16( hModule );
-            
-            if ((hFile = OpenFile32( name, &ofs, OF_READ )) == HFILE_ERROR32)
-            {
-                /* Now try the built-in even if disabled */
-                if ((hModule = fnBUILTIN_LoadModule( name, TRUE )))
-                {
-                    WARN(module, "Could not load Windows DLL '%s', using built-in module.\n", name );
-                    return MODULE_HANDLEtoHMODULE16( hModule );
-                }
-                return 2;  /* File not found */
-            }
-
-            /* Create the module structure */
-
-            hModule = NE_LoadModule( hFile, &ofs, uFlags, cmd_line,
-                                     env, show_cmd );
-            if (hModule < 32)
-            {
-                if ((hModule == 21) && cmd_line)
-                    hModule = PE_LoadModule( hFile, &ofs, cmd_line,
-                                             env, show_cmd );
-            }
-
-            if (hModule < 32)
-                fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
-                         name, hModule );
-            _lclose32( hFile );
-            return hModule;
-        }
-        else /* module is already loaded, just create a new data segment if it's a task */
-        {
-            pModule = MODULE_GetPtr32( hModule );
-            hInstance = MODULE_CreateInstance( hModule, &hPrevInstance,
-                                               (cmd_line == NULL) );
-            if (hInstance != hPrevInstance)  /* not a library */
-                NE_LoadSegment( pModule, pModule->dgroup );
-            pModule->count++;
-        }
-    } /* !winelib */
+        hInstance = NE_LoadModule( name, &hPrevInstance, implicit,
+                                 (cmd_line == NULL) );
+        if ((hInstance == 21) && cmd_line)
+            return PE_LoadModule( name, cmd_line, env, show_cmd );
+    }
 
     /* Create a task for this instance */
 
+    if (hInstance < 32) return hInstance;
+    pModule = NE_GetPtr( hInstance );
     if (cmd_line && !(pModule->flags & NE_FFLAGS_LIBMODULE))
     {
         PDB32 *pdb;
@@ -622,9 +309,8 @@
  */
 HINSTANCE16 LoadModule16( LPCSTR name, LPVOID paramBlock )
 {
-    LOADPARAMS *params = (LOADPARAMS *)paramBlock;
-    LPSTR cmd_line = (LPSTR)PTR_SEG_TO_LIN( params->cmdLine );
-    LPSTR new_cmd_line;
+    LOADPARAMS *params;
+    LPSTR cmd_line, new_cmd_line;
     UINT16 show_cmd = 0;
     LPCVOID env = NULL;
     HINSTANCE16 hInstance;
@@ -649,7 +335,7 @@
     strcat( new_cmd_line, cmd_line );
 
     if (params->hEnvironment) env = GlobalLock16( params->hEnvironment );
-    hInstance = MODULE_Load( name, 0, new_cmd_line, env, show_cmd );
+    hInstance = MODULE_Load( name, FALSE, new_cmd_line, env, show_cmd );
     if (params->hEnvironment) GlobalUnlock16( params->hEnvironment );
     HeapFree( GetProcessHeap(), 0, new_cmd_line );
     return hInstance;
@@ -682,41 +368,12 @@
   CloseHandle32(pi.hThread); 
 
 #else
-  return MODULE_Load( name, 0, params->lpCmdLine, params->lpEnvAddress, 
+  return MODULE_Load( name, FALSE, params->lpCmdLine, params->lpEnvAddress, 
                         *((UINT16 *)params->lpCmdShow + 1) );
 #endif
 }
 
 
-/**********************************************************************
- *	    FreeModule16    (KERNEL.46)
- */
-BOOL16 WINAPI FreeModule16( HMODULE16 hModule )
-{
-    NE_MODULE *pModule;
-
-    if (!(pModule = MODULE_GetPtr16( hModule ))) return FALSE;
-    TRACE(module, "%s count %d\n", 
-		    MODULE_GetModuleName(hModule), pModule->count );
-
-    return MODULE_FreeModule( hModule, GlobalLock16(GetCurrentTask()) );
-}
-
-
-/**********************************************************************
- *	    GetModuleHandle16    (KERNEL.47)
- */
-HMODULE16 WINAPI WIN16_GetModuleHandle( SEGPTR name )
-{
-    if (HIWORD(name) == 0) return GetExePtr( (HINSTANCE16)name );
-    return MODULE_FindModule16( PTR_SEG_TO_LIN(name) );
-}
-
-HMODULE16 WINAPI GetModuleHandle16( LPCSTR name )
-{
-    return MODULE_FindModule16( name );
-}
-
 /***********************************************************************
  *              GetModuleHandle         (KERNEL32.237)
  */
@@ -740,52 +397,23 @@
 }
 
 
-/**********************************************************************
- *	    GetModuleUsage    (KERNEL.48)
- */
-INT16 WINAPI GetModuleUsage( HINSTANCE16 hModule )
-{
-    NE_MODULE *pModule;
-
-    if (!(pModule = MODULE_GetPtr16( hModule ))) return 0;
-    TRACE(module, "(%04x): returning %d\n",
-                    hModule, pModule->count );
-    return pModule->count;
-}
-
-
-/**********************************************************************
- *	    GetModuleFileName16    (KERNEL.49)
- */
-INT16 WINAPI GetModuleFileName16( HINSTANCE16 hModule, LPSTR lpFileName,
-                                  INT16 nSize )
-{
-    NE_MODULE *pModule;
-
-    if (!hModule) hModule = GetCurrentTask();
-    if (!(pModule = MODULE_GetPtr16( hModule ))) return 0;
-    lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), nSize );
-    TRACE(module, "%s\n", lpFileName );
-    return strlen(lpFileName);
-}
-
-
 /***********************************************************************
  *              GetModuleFileName32A      (KERNEL32.235)
- * FIXME FIXME
  */
-DWORD WINAPI GetModuleFileName32A( HMODULE32 hModule, LPSTR lpFileName,
-                                   DWORD size )
-{                   
-    NE_MODULE *pModule;
-           
-    if (!hModule)
-    {
-        TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
-        hModule = pTask->hInstance;
-    }
-    if (!(pModule = MODULE_GetPtr32( hModule ))) return 0;
-    lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), size );
+DWORD WINAPI GetModuleFileName32A( 
+	HMODULE32 hModule,	/* [in] module handle (32bit) */
+	LPSTR lpFileName,	/* [out] filenamebuffer */
+        DWORD size		/* [in] size of filenamebuffer */
+) {                   
+    WINE_MODREF *wm = MODULE32_LookupHMODULE(PROCESS_Current(),hModule);
+
+    if (!wm) /* can happen on start up or the like */
+    	return 0;
+
+    /* FIXME: we should probably get a real long name, but wm->longname
+     * is currently a UNIX filename!
+     */
+    lstrcpyn32A( lpFileName, wm->shortname, size );
     TRACE(module, "%s\n", lpFileName );
     return strlen(lpFileName);
 }                   
@@ -805,19 +433,6 @@
 }
 
 
-/**********************************************************************
- *	    GetModuleName    (KERNEL.27)
- */
-BOOL16 WINAPI GetModuleName( HINSTANCE16 hinst, LPSTR buf, INT16 nSize )
-{
-    LPSTR name = MODULE_GetModuleName(hinst);
-
-    if (!name) return FALSE;
-    lstrcpyn32A( buf, name, nSize );
-    return TRUE;
-}
-
-
 /***********************************************************************
  *           LoadLibraryEx32W   (KERNEL.513)
  * FIXME
@@ -882,29 +497,8 @@
  */
 BOOL32 WINAPI FreeLibrary32(HINSTANCE32 hLibModule)
 {
-    TRACE(module,"hLibModule=%08x\n", hLibModule);
-    return MODULE_FreeModule(hLibModule,GlobalLock16(GetCurrentTask()) );
-}
-
-
-/***********************************************************************
- *           LoadLibrary   (KERNEL.95)
- */
-HINSTANCE16 WINAPI LoadLibrary16( LPCSTR libname )
-{
-    HINSTANCE16 handle;
-
-    TRACE(module, "(%08x) %s\n", (int)libname, libname);
-
-    handle = MODULE_Load( libname, 0, NULL, NULL, 0 );
-    if (handle == (HINSTANCE16)2)  /* file not found */
-    {
-        char buffer[256];
-        lstrcpyn32A( buffer, libname, 252 );
-        strcat( buffer, ".dll" );
-        handle = MODULE_Load( buffer, 0, NULL, NULL, 0 );
-    }
-    return handle;
+    WARN(module,"(%08x): stub\n", hLibModule);
+    return TRUE;  /* FIXME */
 }
 
 
@@ -919,15 +513,6 @@
 }
 
 
-/***********************************************************************
- *           FreeLibrary16   (KERNEL.96)
- */
-void WINAPI FreeLibrary16( HINSTANCE16 handle )
-{
-    TRACE(module,"%04x\n", handle );
-    FreeModule16( handle );
-}
-
 
 /***********************************************************************
  *           PrivateFreeLibrary       (KERNEL32)
@@ -1001,7 +586,7 @@
 	{
 	    /* Winelib: Use LoadModule() only for the program itself */
 	    if (__winelib) use_load_module = 0;
-            handle = MODULE_Load( filename, 0, lpCmdLine, NULL, nCmdShow );
+            handle = MODULE_Load( filename, FALSE, lpCmdLine, NULL, nCmdShow );
 	    if (handle == 2)  /* file not found */
 	    {
 		/* Check that the original file name did not have a suffix */
@@ -1011,7 +596,7 @@
 		{
 		    p = filename + strlen(filename);
 		    strcpy( p, ".exe" );
-                    handle = MODULE_Load( filename, 0, lpCmdLine,
+                    handle = MODULE_Load( filename, FALSE, lpCmdLine,
                                           NULL, nCmdShow );
                     *p = '\0';  /* Remove extension */
 		}
@@ -1094,7 +679,7 @@
  *           WIN32_GetProcAddress16   (KERNEL32.36)
  * Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func)
  */
-FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE32 hModule, LPSTR name )
+FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE32 hModule, LPCSTR name )
 {
     WORD	ordinal;
     FARPROC16	ret;
@@ -1103,7 +688,12 @@
     	WARN(module,"hModule may not be 0!\n");
 	return (FARPROC16)0;
     }
-    hModule = MODULE_HANDLEtoHMODULE16(hModule);
+    if (HIWORD(hModule))
+    {
+    	WARN( module, "hModule is Win32 handle (%08x)\n", hModule );
+	return (FARPROC16)0;
+    }
+    hModule = GetExePtr( hModule );
     if (HIWORD(name)) {
         ordinal = NE_GetOrdinal( hModule, name );
         TRACE(module, "%04x '%s'\n",
@@ -1201,78 +791,3 @@
     if (!wm || (wm->type != MODULE32_PE)) return (LPIMAGE_NT_HEADERS)0;
     return PE_HEADER(wm->module);
 }
-
-
-/**********************************************************************
- *	    GetExpWinVer    (KERNEL.167)
- */
-WORD WINAPI GetExpWinVer( HMODULE16 hModule )
-{
-    NE_MODULE *pModule = MODULE_GetPtr16( hModule );
-    return pModule ? pModule->expected_version : 0;
-}
-
-
-/**********************************************************************
- *	    IsSharedSelector    (KERNEL.345)
- */
-BOOL16 WINAPI IsSharedSelector( HANDLE16 selector )
-{
-    /* Check whether the selector belongs to a DLL */
-    NE_MODULE *pModule = MODULE_GetPtr16( selector );
-    if (!pModule) return FALSE;
-    return (pModule->flags & NE_FFLAGS_LIBMODULE) != 0;
-}
-
-
-/**********************************************************************
- *	    ModuleFirst    (TOOLHELP.59)
- */
-BOOL16 WINAPI ModuleFirst( MODULEENTRY *lpme )
-{
-    lpme->wNext = hFirstModule;
-    return ModuleNext( lpme );
-}
-
-
-/**********************************************************************
- *	    ModuleNext    (TOOLHELP.60)
- */
-BOOL16 WINAPI ModuleNext( MODULEENTRY *lpme )
-{
-    NE_MODULE *pModule;
-    char *name;
-
-    if (!lpme->wNext) return FALSE;
-    if (!(pModule = MODULE_GetPtr16( lpme->wNext ))) return FALSE;
-    name = (char *)pModule + pModule->name_table;
-    memcpy( lpme->szModule, name + 1, *name );
-    lpme->szModule[(BYTE)*name] = '\0';
-    lpme->hModule = lpme->wNext;
-    lpme->wcUsage = pModule->count;
-    strncpy( lpme->szExePath, NE_MODULE_NAME(pModule), MAX_PATH );
-    lpme->szExePath[MAX_PATH] = '\0';
-    lpme->wNext = pModule->next;
-    return TRUE;
-}
-
-
-/**********************************************************************
- *	    ModuleFindName    (TOOLHELP.61)
- */
-BOOL16 WINAPI ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
-{
-    lpme->wNext = GetModuleHandle16( name );
-    return ModuleNext( lpme );
-}
-
-
-/**********************************************************************
- *	    ModuleFindHandle    (TOOLHELP.62)
- */
-BOOL16 WINAPI ModuleFindHandle( MODULEENTRY *lpme, HMODULE16 hModule )
-{
-    hModule = GetExePtr( hModule );
-    lpme->wNext = hModule;
-    return ModuleNext( lpme );
-}
diff --git a/loader/ne/module.c b/loader/ne/module.c
index 5cd97f8..0a2fe70 100644
--- a/loader/ne/module.c
+++ b/loader/ne/module.c
@@ -5,15 +5,36 @@
  */
 
 #include <assert.h>
+#include <fcntl.h>
 #include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
 #include "module.h"
+#include "file.h"
 #include "ldt.h"
+#include "callback.h"
 #include "heap.h"
+#include "task.h"
 #include "global.h"
 #include "process.h"
+#include "toolhelp.h"
 #include "debug.h"
 
-HMODULE16 hFirstModule = 0;
+static HMODULE16 hFirstModule = 0;
+static NE_MODULE *pCachedModule = 0;  /* Module cached by NE_OpenFile */
+
+static HMODULE16 NE_LoadBuiltin(LPCSTR name,BOOL32 force) { return 0; }
+HMODULE16 (*fnBUILTIN_LoadModule)(LPCSTR name,BOOL32 force) = NE_LoadBuiltin;
+
+
+/***********************************************************************
+ *           NE_GetPtr
+ */
+NE_MODULE *NE_GetPtr( HMODULE16 hModule )
+{
+    return (NE_MODULE *)GlobalLock16( GetExePtr(hModule) );
+}
+
 
 /***********************************************************************
  *           NE_DumpModule
@@ -26,7 +47,7 @@
     WORD *pword;
     NE_MODULE *pModule;
 
-    if (!(pModule = MODULE_GetPtr16( hModule )))
+    if (!(pModule = NE_GetPtr( hModule )))
     {
         fprintf( stderr, "**** %04x is not a module handle\n", hModule );
         return;
@@ -99,8 +120,9 @@
         pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
         for (i = 0; i < pModule->modref_count; i++, pword++)
         {
-	    DUMP( "%d: %04x -> '%s'\n", i, *pword,
-		    MODULE_GetModuleName(*pword));
+            char name[10];
+            GetModuleName( *pword, name, sizeof(name) );
+	    DUMP( "%d: %04x -> '%s'\n", i, *pword, name );
         }
     }
     else DUMP( "None\n" );
@@ -170,7 +192,7 @@
     fprintf( stderr, "Module Flags Name\n" );
     while (hModule)
     {
-        NE_MODULE *pModule = MODULE_GetPtr16( hModule );
+        NE_MODULE *pModule = NE_GetPtr( hModule );
         if (!pModule)
         {
             fprintf( stderr, "**** Bad module %04x in list\n", hModule );
@@ -205,7 +227,7 @@
     BYTE len;
     NE_MODULE *pModule;
 
-    if (!(pModule = MODULE_GetPtr16( hModule ))) return 0;
+    if (!(pModule = NE_GetPtr( hModule ))) return 0;
     assert( !(pModule->flags & NE_FFLAGS_WIN32) );
 
     TRACE( module, "(%04x,'%s')\n", hModule, name );
@@ -270,7 +292,7 @@
     BYTE *p;
     WORD sel, offset;
 
-    if (!(pModule = MODULE_GetPtr16( hModule ))) return 0;
+    if (!(pModule = NE_GetPtr( hModule ))) return 0;
     assert( !(pModule->flags & NE_FFLAGS_WIN32) );
 
     p = (BYTE *)pModule + pModule->entry_table;
@@ -321,7 +343,7 @@
     WORD curOrdinal = 1;
     BYTE *p;
 
-    if (!(pModule = MODULE_GetPtr16( hModule ))) return FALSE;
+    if (!(pModule = NE_GetPtr( hModule ))) return FALSE;
     assert( !(pModule->flags & NE_FFLAGS_WIN32) );
 
     p = (BYTE *)pModule + pModule->entry_table;
@@ -356,9 +378,35 @@
 
 
 /***********************************************************************
+ *           NE_OpenFile
+ */
+int NE_OpenFile( NE_MODULE *pModule )
+{
+    DOS_FULL_NAME full_name;
+    char *name;
+
+    static int cachedfd = -1;
+
+    TRACE( module, "(%p) cache: mod=%p fd=%d\n",
+           pModule, pCachedModule, cachedfd );
+    if (pCachedModule == pModule) return cachedfd;
+    close( cachedfd );
+    pCachedModule = pModule;
+    name = NE_MODULE_NAME( pModule );
+    if (!DOSFS_GetFullName( name, TRUE, &full_name ) ||
+        (cachedfd = open( full_name.long_name, O_RDONLY )) == -1)
+        WARN( module, "Can't open file '%s' for module %04x\n",
+              name, pModule->self );
+    TRACE(module, "opened '%s' -> %d\n",
+                    name, cachedfd );
+    return cachedfd;
+}
+
+
+/***********************************************************************
  *           NE_LoadExeHeader
  */
-static HMODULE16 NE_LoadExeHeader( HFILE32 hFile, OFSTRUCT *ofs )
+static HMODULE16 NE_LoadExeHeader( HFILE16 hFile, OFSTRUCT *ofs )
 {
     IMAGE_DOS_HEADER mz_header;
     IMAGE_OS2_HEADER ne_header;
@@ -374,23 +422,23 @@
        ((fastload && ((offset) >= fastload_offset) && \
          ((offset)+(size) <= fastload_offset+fastload_length)) ? \
         (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
-        (_llseek32( hFile, (offset), SEEK_SET), \
-         _lread32( hFile, (buffer), (size) ) == (size)))
+        (_llseek16( hFile, (offset), SEEK_SET), \
+         _hread16( hFile, (buffer), (size) ) == (size)))
 
-    _llseek32( hFile, 0, SEEK_SET );
-    if ((_lread32(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
+    _llseek16( hFile, 0, SEEK_SET );
+    if ((_hread16(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
         (mz_header.e_magic != IMAGE_DOS_SIGNATURE))
         return (HMODULE16)11;  /* invalid exe */
 
-    _llseek32( hFile, mz_header.e_lfanew, SEEK_SET );
-    if (_lread32( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
+    _llseek16( hFile, mz_header.e_lfanew, SEEK_SET );
+    if (_hread16( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
         return (HMODULE16)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_OS2_SIGNATURE_LX) {
-      fprintf(stderr, "Sorry, this is an OS/2 linear executable (LX) file !\n");
+      MSG("Sorry, this is an OS/2 linear executable (LX) file !\n");
       return (HMODULE16)12;
     }
 
@@ -425,7 +473,7 @@
 
     /* Clear internal Wine flags in case they are set in the EXE file */
 
-    pModule->flags &= ~(NE_FFLAGS_BUILTIN|NE_FFLAGS_WIN32|NE_FFLAGS_IMPLICIT);
+    pModule->flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32);
 
     /* Read the fast-load area */
 
@@ -437,11 +485,11 @@
                         fastload_offset, fastload_length );
         if ((fastload = HeapAlloc( SystemHeap, 0, fastload_length )) != NULL)
         {
-            _llseek32( hFile, fastload_offset, SEEK_SET);
-            if (_lread32(hFile, fastload, fastload_length) != fastload_length)
+            _llseek16( hFile, fastload_offset, SEEK_SET);
+            if (_hread16(hFile, fastload, fastload_length) != fastload_length)
             {
                 HeapFree( SystemHeap, 0, fastload );
-                fprintf(stderr, "Error reading fast-load area !\n");
+                WARN( module, "Error reading fast-load area!\n");
                 fastload = NULL;
             }
         }
@@ -575,8 +623,8 @@
             return (HMODULE16)11;  /* invalid exe */
         }
         buffer = GlobalLock16( pModule->nrname_handle );
-        _llseek32( hFile, ne_header.nrname_tab_offset, SEEK_SET );
-        if (_lread32( hFile, buffer, ne_header.nrname_tab_length )
+        _llseek16( hFile, ne_header.nrname_tab_offset, SEEK_SET );
+        if (_hread16( hFile, buffer, ne_header.nrname_tab_length )
               != ne_header.nrname_tab_length)
         {
             GlobalFree16( pModule->nrname_handle );
@@ -620,19 +668,18 @@
 
     for (i = 0; i < pModule->modref_count; i++, pModRef++)
     {
-        char buffer[256];
+        char buffer[260];
         BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
         memcpy( buffer, pstr + 1, *pstr );
         strcpy( buffer + *pstr, ".dll" );
         TRACE(module, "Loading '%s'\n", buffer );
-        if (!(*pModRef = MODULE_FindModule16( buffer )))
+        if (!(*pModRef = GetModuleHandle16( buffer )))
         {
             /* If the DLL is not loaded yet, load it and store */
             /* its handle in the list of DLLs to initialize.   */
             HMODULE16 hDLL;
 
-            if ((hDLL = MODULE_Load( buffer, NE_FFLAGS_IMPLICIT,
-                                     NULL, NULL, 0 )) == 2)
+            if ((hDLL = NE_LoadModule( buffer, NULL, TRUE, TRUE )) == 2)
             {
                 /* file not found */
                 char *p;
@@ -642,13 +689,13 @@
                 if (!(p = strrchr( buffer, '\\' ))) p = buffer;
                 memcpy( p + 1, pstr + 1, *pstr );
                 strcpy( p + 1 + *pstr, ".dll" );
-                hDLL = MODULE_Load( buffer, NE_FFLAGS_IMPLICIT, NULL, NULL, 0);
+                hDLL = NE_LoadModule( buffer, NULL, TRUE, TRUE );
             }
             if (hDLL < 32)
             {
                 /* FIXME: cleanup what was done */
 
-                fprintf( stderr, "Could not load '%s' required by '%.*s', error = %d\n",
+               WARN( module, "Could not load '%s' required by '%.*s', error=%d\n",
                          buffer, *((BYTE*)pModule + pModule->name_table),
                          (char *)pModule + pModule->name_table + 1, hDLL );
                 return FALSE;
@@ -658,7 +705,7 @@
         }
         else  /* Increment the reference count of the DLL */
         {
-            NE_MODULE *pOldDLL = MODULE_GetPtr16( *pModRef );
+            NE_MODULE *pOldDLL = NE_GetPtr( *pModRef );
             if (pOldDLL) pOldDLL->count++;
         }
     }
@@ -675,24 +722,60 @@
  * without a preceding length byte).
  * If cmd_line is NULL, the module is loaded as a library even if it is a .exe
  */
-HINSTANCE16 NE_LoadModule( HFILE32 hFile, OFSTRUCT *ofs, UINT16 flags,
-                           LPCSTR cmd_line, LPCSTR env, UINT32 show_cmd )
+HINSTANCE16 NE_LoadModule( LPCSTR name, HINSTANCE16 *hPrevInstance,
+                           BOOL32 implicit, BOOL32 lib_only )
 {
     HMODULE16 hModule;
     HINSTANCE16 hInstance;
     NE_MODULE *pModule;
+    HFILE16 hFile;
+    OFSTRUCT ofs;
+
+    /* Check if the module is already loaded */
+
+    if ((hModule = GetModuleHandle16( name )) != 0)
+    {
+        HINSTANCE16 prev;
+        pModule = NE_GetPtr( hModule );
+        hInstance = NE_CreateInstance( pModule, &prev, lib_only );
+        if (hInstance != prev)  /* not a library */
+            NE_LoadSegment( pModule, pModule->dgroup );
+        pModule->count++;
+        if (hPrevInstance) *hPrevInstance = prev;
+        return hInstance;
+    }
+    if (hPrevInstance) *hPrevInstance = 0;
+
+    /* Try to load the built-in first if not disabled */
+
+    if ((hModule = fnBUILTIN_LoadModule( name, FALSE ))) return hModule;
+
+    if ((hFile = OpenFile16( name, &ofs, OF_READ )) == HFILE_ERROR16)
+    {
+        /* Now try the built-in even if disabled */
+        if ((hModule = fnBUILTIN_LoadModule( name, TRUE )))
+        {
+            WARN(module, "Could not load Windows DLL '%s', using built-in module.\n", name );
+            return hModule;
+        }
+        return 2;  /* File not found */
+    }
 
     /* Create the module structure */
 
-    if ((hModule = NE_LoadExeHeader( hFile, ofs )) < 32) return hModule;
-
-    pModule = MODULE_GetPtr16( hModule );
-    pModule->flags |= flags; /* stamp implicitly loaded modules */
+    hModule = NE_LoadExeHeader( hFile, &ofs );
+    _lclose16( hFile );
+    if (hModule < 32) return hModule;
+    pModule = NE_GetPtr( hModule );
 
     /* Allocate the segments for this module */
 
-    NE_CreateSegments( hModule );
-    hInstance = MODULE_CreateInstance( hModule, NULL, (cmd_line == NULL) );
+    if (!NE_CreateSegments( pModule ) ||
+        !(hInstance = NE_CreateInstance( pModule, NULL, lib_only )))
+    {
+        GlobalFreeAll( hModule );
+        return 8;  /* Insufficient memory */
+    }
 
     /* Load the referenced DLLs */
 
@@ -716,21 +799,307 @@
      * when we load implicitly linked DLLs this will be done by InitTask().
      */
 
-    if ((pModule->flags & (NE_FFLAGS_LIBMODULE | NE_FFLAGS_IMPLICIT)) ==
-                                                           NE_FFLAGS_LIBMODULE)
+    if (!implicit && (pModule->flags & NE_FFLAGS_LIBMODULE))
         NE_InitializeDLLs( hModule );
 
-    /* Create a task for this instance */
+    return hInstance;
+}
 
-    if (cmd_line && !(pModule->flags & NE_FFLAGS_LIBMODULE))
+
+/***********************************************************************
+ *           LoadLibrary   (KERNEL.95)
+ */
+HINSTANCE16 WINAPI LoadLibrary16( LPCSTR libname )
+{
+    HINSTANCE16 handle;
+    LPCSTR p;
+    char *new_name;
+
+    TRACE(module, "(%08x) %s\n", (int)libname, libname);
+
+    /* Check for an extension */
+
+    if ((p = strrchr( libname, '.')) && !strchr( p, '/' ) && !strchr( p, '\\'))
     {
-        PDB32 *pdb;
-
-	pModule->flags |= NE_FFLAGS_GUI;
-
-        pdb = PROCESS_Create( pModule, cmd_line, env, hInstance, 0, show_cmd );
-        if (pdb && (GetNumTasks() > 1)) Yield16();
+        /* An extension is present -> use the name as is */
+        return NE_LoadModule( libname, NULL, FALSE, TRUE );
     }
 
-    return hInstance;
+    /* Now append .dll before loading */
+
+    if (!(new_name = HeapAlloc( GetProcessHeap(), 0, strlen(libname) + 4 )))
+        return 0;
+    strcpy( new_name, libname );
+    strcat( new_name, ".dll" );
+    handle = NE_LoadModule( new_name, NULL, FALSE, TRUE );
+    HeapFree( GetProcessHeap(), 0, new_name );
+    return handle;
+}
+
+
+/**********************************************************************
+ *	    MODULE_CallWEP
+ *
+ * Call a DLL's WEP, allowing it to shut down.
+ * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
+ */
+static BOOL16 MODULE_CallWEP( HMODULE16 hModule )
+{
+    FARPROC16 WEP = (FARPROC16)0;
+    WORD ordinal = NE_GetOrdinal( hModule, "WEP" );
+
+    if (ordinal) WEP = NE_GetEntryPoint( hModule, ordinal );
+    if (!WEP)
+    {
+	WARN(module, "module %04x doesn't have a WEP\n", hModule );
+	return FALSE;
+    }
+    return Callbacks->CallWindowsExitProc( WEP, WEP_FREE_DLL );
+}
+
+
+/**********************************************************************
+ *	    NE_FreeModule
+ *
+ * Implementation of FreeModule16().
+ */
+static BOOL16 NE_FreeModule( HMODULE16 hModule, BOOL32 call_wep )
+{
+    HMODULE16 *hPrevModule;
+    NE_MODULE *pModule;
+    HMODULE16 *pModRef;
+    int i;
+
+    if (!(pModule = NE_GetPtr( hModule ))) return FALSE;
+    hModule = pModule->self;
+
+    TRACE( module, "%04x count %d\n", hModule, pModule->count );
+
+    if (((INT16)(--pModule->count)) > 0 ) return TRUE;
+    else pModule->count = 0;
+
+    if (pModule->flags & NE_FFLAGS_BUILTIN)
+        return FALSE;  /* Can't free built-in module */
+
+    if (call_wep)
+    {
+        if (pModule->flags & NE_FFLAGS_LIBMODULE)
+        {
+            TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
+            MODULE_CallWEP( hModule );
+
+            /* Free the objects owned by the DLL module */
+
+            if (pTask && pTask->userhandler)
+                pTask->userhandler( hModule, USIG_DLL_UNLOAD, 0,
+                                    pTask->hInstance, pTask->hQueue );
+        }
+        else
+            call_wep = FALSE;  /* We are freeing a task -> no more WEPs */
+    }
+    
+
+    /* Clear magic number just in case */
+
+    pModule->magic = pModule->self = 0;
+
+      /* Remove it from the linked list */
+
+    hPrevModule = &hFirstModule;
+    while (*hPrevModule && (*hPrevModule != hModule))
+    {
+        hPrevModule = &(NE_GetPtr( *hPrevModule ))->next;
+    }
+    if (*hPrevModule) *hPrevModule = pModule->next;
+
+    /* Free the referenced modules */
+
+    pModRef = (HMODULE16*)NE_MODULE_TABLE( pModule );
+    for (i = 0; i < pModule->modref_count; i++, pModRef++)
+    {
+        NE_FreeModule( *pModRef, call_wep );
+    }
+
+    /* Free the module storage */
+
+    GlobalFreeAll( hModule );
+
+    /* Remove module from cache */
+
+    if (pCachedModule == pModule) pCachedModule = NULL;
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *	    FreeModule16    (KERNEL.46)
+ */
+BOOL16 WINAPI FreeModule16( HMODULE16 hModule )
+{
+    return NE_FreeModule( hModule, TRUE );
+}
+
+
+/***********************************************************************
+ *           FreeLibrary16   (KERNEL.96)
+ */
+void WINAPI FreeLibrary16( HINSTANCE16 handle )
+{
+    TRACE(module,"%04x\n", handle );
+    FreeModule16( handle );
+}
+
+
+/**********************************************************************
+ *	    GetModuleName    (KERNEL.27)
+ */
+BOOL16 WINAPI GetModuleName( HINSTANCE16 hinst, LPSTR buf, INT16 count )
+{
+    NE_MODULE *pModule;
+    BYTE *p;
+
+    if (!(pModule = NE_GetPtr( hinst ))) return FALSE;
+    p = (BYTE *)pModule + pModule->name_table;
+    if (count > *p) count = *p + 1;
+    if (count > 0)
+    {
+        memcpy( buf, p + 1, count - 1 );
+        buf[count-1] = '\0';
+    }
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *	    GetModuleUsage    (KERNEL.48)
+ */
+INT16 WINAPI GetModuleUsage( HINSTANCE16 hModule )
+{
+    NE_MODULE *pModule = NE_GetPtr( hModule );
+    return pModule ? pModule->count : 0;
+}
+
+
+/**********************************************************************
+ *	    GetExpWinVer    (KERNEL.167)
+ */
+WORD WINAPI GetExpWinVer( HMODULE16 hModule )
+{
+    NE_MODULE *pModule = NE_GetPtr( hModule );
+    return pModule ? pModule->expected_version : 0;
+}
+
+
+/**********************************************************************
+ *	    GetModuleFileName16    (KERNEL.49)
+ */
+INT16 WINAPI GetModuleFileName16( HINSTANCE16 hModule, LPSTR lpFileName,
+                                  INT16 nSize )
+{
+    NE_MODULE *pModule;
+
+    if (!hModule) hModule = GetCurrentTask();
+    if (!(pModule = NE_GetPtr( hModule ))) return 0;
+    lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), nSize );
+    TRACE(module, "%s\n", lpFileName );
+    return strlen(lpFileName);
+}
+
+
+/**********************************************************************
+ *	    GetModuleHandle16    (KERNEL.47)
+ *
+ * Find a module from a path name.
+ *
+ * RETURNS
+ *	the win16 module handle if found
+ * 	0 if not
+ */
+HMODULE16 WINAPI WIN16_GetModuleHandle( SEGPTR name )
+{
+    if (HIWORD(name) == 0) return GetExePtr( (HINSTANCE16)name );
+    return GetModuleHandle16( PTR_SEG_TO_LIN(name) );
+}
+
+HMODULE16 WINAPI GetModuleHandle16( LPCSTR name )
+{
+    HMODULE16 hModule = hFirstModule;
+    LPCSTR filename, dotptr, modulepath, modulename;
+    BYTE len, *name_table;
+
+    if (!(filename = strrchr( name, '\\' ))) filename = name;
+    else filename++;
+    if ((dotptr = strrchr( filename, '.' )) != NULL)
+        len = (BYTE)(dotptr - filename);
+    else len = strlen( filename );
+
+    while (hModule)
+    {
+        NE_MODULE *pModule = NE_GetPtr( hModule );
+        if (!pModule) break;
+        modulepath = NE_MODULE_NAME(pModule);
+        if (!(modulename = strrchr( modulepath, '\\' )))
+            modulename = modulepath;
+        else modulename++;
+        if (!lstrcmpi32A( modulename, filename )) return hModule;
+
+        name_table = (BYTE *)pModule + pModule->name_table;
+        if ((*name_table == len) && !lstrncmpi32A(filename, name_table+1, len))
+            return hModule;
+        hModule = pModule->next;
+    }
+    return 0;
+}
+
+
+/**********************************************************************
+ *	    ModuleFirst    (TOOLHELP.59)
+ */
+BOOL16 WINAPI ModuleFirst( MODULEENTRY *lpme )
+{
+    lpme->wNext = hFirstModule;
+    return ModuleNext( lpme );
+}
+
+
+/**********************************************************************
+ *	    ModuleNext    (TOOLHELP.60)
+ */
+BOOL16 WINAPI ModuleNext( MODULEENTRY *lpme )
+{
+    NE_MODULE *pModule;
+    char *name;
+
+    if (!lpme->wNext) return FALSE;
+    if (!(pModule = NE_GetPtr( lpme->wNext ))) return FALSE;
+    name = (char *)pModule + pModule->name_table;
+    memcpy( lpme->szModule, name + 1, *name );
+    lpme->szModule[(BYTE)*name] = '\0';
+    lpme->hModule = lpme->wNext;
+    lpme->wcUsage = pModule->count;
+    strncpy( lpme->szExePath, NE_MODULE_NAME(pModule), MAX_PATH );
+    lpme->szExePath[MAX_PATH] = '\0';
+    lpme->wNext = pModule->next;
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *	    ModuleFindName    (TOOLHELP.61)
+ */
+BOOL16 WINAPI ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
+{
+    lpme->wNext = GetModuleHandle16( name );
+    return ModuleNext( lpme );
+}
+
+
+/**********************************************************************
+ *	    ModuleFindHandle    (TOOLHELP.62)
+ */
+BOOL16 WINAPI ModuleFindHandle( MODULEENTRY *lpme, HMODULE16 hModule )
+{
+    hModule = GetExePtr( hModule );
+    lpme->wNext = hModule;
+    return ModuleNext( lpme );
 }
diff --git a/loader/ne/resource.c b/loader/ne/resource.c
index 832be3b..807871d 100644
--- a/loader/ne/resource.c
+++ b/loader/ne/resource.c
@@ -183,8 +183,8 @@
                                         HRSRC16 hRsrc )
 {
     int  fd;
-    NE_MODULE* pModule = MODULE_GetPtr16( hModule );
-    if ( pModule && (fd = MODULE_OpenFile( hModule )) >= 0)
+    NE_MODULE* pModule = NE_GetPtr( hModule );
+    if (pModule && (fd = NE_OpenFile( pModule )) >= 0)
     {
 	HGLOBAL16 handle;
 	WORD sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
@@ -215,7 +215,7 @@
  */
 BOOL32 NE_InitResourceHandler( HMODULE16 hModule )
 {
-    NE_MODULE *pModule = MODULE_GetPtr16( hModule );
+    NE_MODULE *pModule = NE_GetPtr( hModule );
     NE_TYPEINFO *pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
 
     TRACE(resource,"InitResourceHandler[%04x]\n", hModule );
@@ -236,7 +236,7 @@
                                      FARPROC16 resourceHandler )
 {
     FARPROC16 prevHandler = NULL;
-    NE_MODULE *pModule = MODULE_GetPtr16( hModule );
+    NE_MODULE *pModule = NE_GetPtr( hModule );
     NE_TYPEINFO *pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
 
     if (!pModule || !pModule->res_table) return NULL;
@@ -264,7 +264,7 @@
     NE_TYPEINFO *pTypeInfo;
     HRSRC16 hRsrc;
 
-    NE_MODULE *pModule = MODULE_GetPtr16( hModule );
+    NE_MODULE *pModule = NE_GetPtr( hModule );
     if (!pModule || !pModule->res_table) return 0;
 
     assert( !__winelib );  /* Can't use Win16 resource functions in Winelib */
@@ -333,7 +333,7 @@
     NE_NAMEINFO *pNameInfo=NULL;
     WORD sizeShift;
 
-    NE_MODULE *pModule = MODULE_GetPtr16( hModule );
+    NE_MODULE *pModule = NE_GetPtr( hModule );
     if (!pModule || !pModule->res_table || !hRsrc) return 0;
 
     TRACE( resource, "module=%04x res=%04x size=%ld\n", hModule, hRsrc, size );
@@ -361,7 +361,7 @@
     if (!(hInstance = GetExePtr( hInstance ))) return 0;
     if(wType != 0x10)	/* 0x10 is the only observed value, passed from
                            CreateCursorIndirect. */
-        fprintf(stderr, "DirectResAlloc: wType = %x\n", wType);
+        TRACE(resource, "(wType=%x)\n", wType);
     return GLOBAL_Alloc(GMEM_MOVEABLE, wSize, hInstance, FALSE, FALSE, FALSE);
 }
 
@@ -373,7 +373,7 @@
 {
     HFILE32 fd;
 
-    NE_MODULE *pModule = MODULE_GetPtr16( hModule );
+    NE_MODULE *pModule = NE_GetPtr( hModule );
     if (!pModule || !pModule->res_table || !hRsrc) return -1;
 
     TRACE(resource, "module=%04x res=%04x\n", hModule, hRsrc );
@@ -398,7 +398,7 @@
     NE_NAMEINFO *pNameInfo=NULL;
     WORD sizeShift;
 
-    NE_MODULE *pModule = MODULE_GetPtr16( hModule );
+    NE_MODULE *pModule = NE_GetPtr( hModule );
     if (!pModule || !pModule->res_table) return 0;
 
     TRACE(resource, "module=%04x res=%04x\n", hModule, hRsrc );
@@ -418,7 +418,7 @@
 {
     NE_TYPEINFO *pTypeInfo;
     NE_NAMEINFO *pNameInfo = NULL;
-    NE_MODULE *pModule = MODULE_GetPtr16( hModule );
+    NE_MODULE *pModule = NE_GetPtr( hModule );
     int d;
 
     TRACE( resource, "module=%04x res=%04x\n", hModule, hRsrc );
@@ -464,7 +464,7 @@
 	  	loader = (RESOURCEHANDLER16)pTypeInfo->resloader;
 	    else /* this is really bad */
 	    {
-		fprintf( stderr, "[%04x]: Missing resource handler!!!...\n", hModule);
+		ERR(resource, "[%04x]: Missing resource handler!\n", hModule);
 		loader = NE_DefResourceHandler;
 	    }
 
@@ -513,8 +513,7 @@
     NE_TYPEINFO *pTypeInfo;
     NE_NAMEINFO *pNameInfo;
     WORD count;
-    HMODULE16 hModule  = GetExePtr( handle );
-    NE_MODULE *pModule = MODULE_GetPtr16( hModule );
+    NE_MODULE *pModule = NE_GetPtr( GetExePtr(handle) );
 
     if (!handle || !pModule || !pModule->res_table) return handle;
 
@@ -545,7 +544,7 @@
     }
 
     TRACE(resource, "[%04x]: no intrinsic resource for %04x, assuming DirectResAlloc()!\n", 
-		 hModule, handle );
+          pModule->self, handle );
     GlobalFree16( handle ); 
     return handle;
 }
diff --git a/loader/ne/segment.c b/loader/ne/segment.c
index 99f78ce..a6478a5 100644
--- a/loader/ne/segment.c
+++ b/loader/ne/segment.c
@@ -72,7 +72,7 @@
 
     if (!pSeg->filepos) return TRUE;  /* No file image, just return */
 	
-    fd = MODULE_OpenFile( pModule->self );
+    fd = NE_OpenFile( pModule );
     TRACE(module, "Loading segment %d, selector=%04x, flags=%04x\n",
                     segnum, pSeg->selector, pSeg->flags );
     lseek( fd, pSeg->filepos << pModule->alignment, SEEK_SET );
@@ -118,8 +118,8 @@
  		   pSeg->minsize ? pSeg->minsize : 0x10000);
  	    FreeSelector(newselector);
  	    pSeg->selector = oldselector;
- 	    fprintf(stderr, "A new selector was allocated for the dgroup segment\n"
- 		    "Old selector is %d, new one is %d", oldselector, newselector);
+ 	    TRACE(module, "New selector allocated for dgroup segment:Old=%d,New=%d\n", 
+                oldselector, newselector);
  	  } else {
  	    FreeSelector(pSeg->selector);
  	    pSeg->selector = newselector;
@@ -201,22 +201,22 @@
             address = NE_GetEntryPoint( module, ordinal );
             if (!address)
             {
-                NE_MODULE *pTarget = MODULE_GetPtr16( module );
+                NE_MODULE *pTarget = NE_GetPtr( module );
                 if (!pTarget)
-                    fprintf( stderr, "Module not found: %04x, reference %d of module %*.*s\n",
+                    WARN(module, "Module not found: %04x, reference %d of module %*.*s\n",
                              module, rep->target1, 
                              *((BYTE *)pModule + pModule->name_table),
                              *((BYTE *)pModule + pModule->name_table),
                              (char *)pModule + pModule->name_table + 1 );
                 else
-                    fprintf( stderr, "Warning: no handler for %.*s.%d, setting to 0:0\n",
+                    WARN(module, "No handler for %.*s.%d, setting to 0:0\n",
                             *((BYTE *)pTarget + pTarget->name_table),
                             (char *)pTarget + pTarget->name_table + 1,
                             ordinal );
             }
             if (TRACE_ON(fixup))
             {
-                NE_MODULE *pTarget = MODULE_GetPtr16( module );
+                NE_MODULE *pTarget = NE_GetPtr( module );
                 TRACE( fixup, "%d: %.*s.%d=%04x:%04x %s\n", i + 1, 
                        *((BYTE *)pTarget + pTarget->name_table),
                        (char *)pTarget + pTarget->name_table + 1,
@@ -236,14 +236,14 @@
 
             if (ERR_ON(fixup) && !address)
             {
-                NE_MODULE *pTarget = MODULE_GetPtr16( module );
+                NE_MODULE *pTarget = NE_GetPtr( module );
                 ERR(fixup, "Warning: no handler for %.*s.%s, setting to 0:0\n",
                     *((BYTE *)pTarget + pTarget->name_table),
                     (char *)pTarget + pTarget->name_table + 1, func_name );
             }
             if (TRACE_ON(fixup))
             {
-	        NE_MODULE *pTarget = MODULE_GetPtr16( module );
+	        NE_MODULE *pTarget = NE_GetPtr( module );
                 TRACE( fixup, "%d: %.*s.%s=%04x:%04x %s\n", i + 1, 
                        *((BYTE *)pTarget + pTarget->name_table),
                        (char *)pTarget + pTarget->name_table + 1,
@@ -288,8 +288,12 @@
         /* Apparently, high bit of address_type is sometimes set; */
         /* we ignore it for now */
 	if (rep->address_type > NE_RADDR_OFFSET32)
+        {
+            char module[10];
+            GetModuleName( pModule->self, module, sizeof(module) );
             ERR( fixup, "WARNING: module %s: unknown reloc addr type = 0x%02x. Please report.\n",
-                 MODULE_GetModuleName(pModule->self), rep->address_type );
+                 module, rep->address_type );
+        }
 
         if (additive)
         {
@@ -405,7 +409,7 @@
         stack16Top->ip = 0;
         stack16Top->cs = 0;
 
-        hf = FILE_DupUnixHandle( MODULE_OpenFile( pModule->self ) );
+        hf = FILE_DupUnixHandle( NE_OpenFile( pModule ) );
         Callbacks->CallBootAppProc(selfloadheader->BootApp, pModule->self, hf);
         _lclose32(hf);
         /* some BootApp procs overwrite the selector of dgroup */
@@ -490,7 +494,7 @@
 			if (pModule->flags & NE_FFLAGS_MULTIPLEDATA)
                         {
 			    /* can this happen? */
-			    fprintf( stderr, "FixupPrologs got confused\n" );
+			    ERR(fixup, "FixupPrologs got confused\n" );
 			}
                         else if (pModule->flags & NE_FFLAGS_SINGLEDATA)
                         {
@@ -523,9 +527,8 @@
  *
  * Call the DLL initialization code
  */
-static BOOL32 NE_InitDLL( TDB* pTask, HMODULE16 hModule )
+static BOOL32 NE_InitDLL( TDB* pTask, NE_MODULE *pModule )
 {
-    NE_MODULE *pModule;
     SEGTABLEENTRY *pSegTable;
     CONTEXT context;
 
@@ -536,7 +539,6 @@
      * es:si  command line (always 0)
      */
 
-    if (!(pModule = MODULE_GetPtr16( hModule ))) return FALSE;
     pSegTable = NE_SEG_TABLE( pModule );
 
     if (!(pModule->flags & NE_FFLAGS_LIBMODULE) ||
@@ -548,7 +550,7 @@
 
     if (pTask && pTask->userhandler)
     {
-        pTask->userhandler( hModule, USIG_DLL_LOAD, 0, pTask->hInstance,
+        pTask->userhandler( pModule->self, USIG_DLL_LOAD, 0, pTask->hInstance,
                             pTask->hQueue );
     }
 
@@ -561,7 +563,7 @@
         if (pModule->flags & NE_FFLAGS_MULTIPLEDATA || pModule->dgroup)
         {
             /* Not SINGLEDATA */
-            fprintf(stderr, "Library is not marked SINGLEDATA\n");
+            ERR(dll, "Library is not marked SINGLEDATA\n");
             exit(1);
         }
         else  /* DATA NONE DLL */
@@ -589,7 +591,7 @@
     EIP_reg(&context) = pModule->ip;
     EBP_reg(&context) = OFFSETOF(THREAD_Current()->cur_stack)
                           + (WORD)&((STACK16FRAME*)0)->bp;
-    EDI_reg(&context) = DS_reg(&context) ? DS_reg(&context) : hModule;
+    EDI_reg(&context) = DS_reg(&context) ? DS_reg(&context) : pModule->self;
 
 
     pModule->cs = 0;  /* Don't initialize it twice */
@@ -600,6 +602,44 @@
     return TRUE;
 }
 
+/***********************************************************************
+ *           NE_CallDllEntryPoint
+ *
+ * Call the DllEntryPoint of DLLs with subsystem >= 4.0 
+ */
+
+static void NE_CallDllEntryPoint( NE_MODULE *pModule, DWORD dwReason )
+{
+    FARPROC16 entryPoint;
+    WORD ordinal;
+    CONTEXT context;
+    THDB *thdb = THREAD_Current();
+    LPBYTE stack = (LPBYTE)THREAD_STACK16(thdb);
+
+    if (pModule->expected_version < 0x0400) return;
+    if (!(ordinal = NE_GetOrdinal( pModule->self, "DllEntryPoint" ))) return;
+    if (!(entryPoint = NE_GetEntryPoint( pModule->self, ordinal ))) return;
+
+    memset( &context, 0, sizeof(context) );
+
+    CS_reg(&context) = HIWORD(entryPoint);
+    IP_reg(&context) = LOWORD(entryPoint);
+    EBP_reg(&context) =  OFFSETOF( thdb->cur_stack )
+                         + (WORD)&((STACK16FRAME*)0)->bp;
+
+    *(DWORD *)(stack -  4) = dwReason;      /* dwReason */
+    *(WORD *) (stack -  6) = pModule->self; /* hInst */
+    *(WORD *) (stack -  8) = 0;             /* wDS */
+    *(WORD *) (stack - 10) = 0;             /* wHeapSize */
+    *(DWORD *)(stack - 14) = 0;             /* dwReserved1 */
+    *(WORD *) (stack - 16) = 0;             /* wReserved2 */
+
+    TRACE(dll, "Calling DllEntryPoint, cs:ip=%04lx:%04x\n",
+          CS_reg(&context), IP_reg(&context));
+
+    Callbacks->CallRegisterShortProc( &context, 16 );
+}
+
 
 /***********************************************************************
  *           NE_InitializeDLLs
@@ -613,8 +653,8 @@
     NE_MODULE *pModule;
     HMODULE16 *pDLL;
 
-    if (!(pModule = MODULE_GetPtr16( hModule ))) return;
-    if (pModule->flags & NE_FFLAGS_WIN32) return;
+    if (!(pModule = NE_GetPtr( hModule ))) return;
+    assert( !(pModule->flags & NE_FFLAGS_WIN32) );
 
     if (pModule->dlls_to_init)
     {
@@ -626,7 +666,47 @@
         }
         GlobalFree16( to_init );
     }
-    NE_InitDLL( pTask, hModule );
+    NE_InitDLL( pTask, pModule );
+    NE_CallDllEntryPoint( pModule, DLL_PROCESS_ATTACH );
+}
+
+
+/***********************************************************************
+ *           NE_CreateInstance
+ *
+ * If lib_only is TRUE, handle the module like a library even if it is a .EXE
+ */
+HINSTANCE16 NE_CreateInstance( NE_MODULE *pModule, HINSTANCE16 *prev,
+                               BOOL32 lib_only )
+{
+    SEGTABLEENTRY *pSegment;
+    int minsize;
+    HINSTANCE16 hNewInstance;
+
+    if (pModule->dgroup == 0)
+    {
+        if (prev) *prev = pModule->self;
+        return pModule->self;
+    }
+
+    pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
+    if (prev) *prev = pSegment->selector;
+
+      /* if it's a library, create a new instance only the first time */
+    if (pSegment->selector)
+    {
+        if (pModule->flags & NE_FFLAGS_LIBMODULE) return pSegment->selector;
+        if (lib_only) return pSegment->selector;
+    }
+
+    minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
+    if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
+    minsize += pModule->heap_size;
+    hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED, minsize,
+                                 pModule->self, FALSE, FALSE, FALSE );
+    if (!hNewInstance) return 0;
+    pSegment->selector = hNewInstance;
+    return hNewInstance;
 }
 
 
@@ -639,7 +719,7 @@
 /* It does nothing */
 void WINAPI PatchCodeHandle(HANDLE16 hSel)
 {
-	fprintf(stderr,"PatchCodeHandle(%04x),stub!\n",hSel);
+    FIXME(module,"(%04x): stub.\n",hSel);
 }
 
 
@@ -682,13 +762,11 @@
 /***********************************************************************
  *           NE_CreateSegments
  */
-BOOL32 NE_CreateSegments( HMODULE16 hModule )
+BOOL32 NE_CreateSegments( NE_MODULE *pModule )
 {
     SEGTABLEENTRY *pSegment;
-    NE_MODULE *pModule;
     int i, minsize;
 
-    if (!(pModule = MODULE_GetPtr16( hModule ))) return FALSE;
     assert( !(pModule->flags & NE_FFLAGS_WIN32) );
 
     pSegment = NE_SEG_TABLE( pModule );
@@ -696,10 +774,10 @@
     {
         minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
         if (i == pModule->ss) minsize += pModule->stack_size;
-	/* The DGROUP is allocated by MODULE_CreateInstance */
+	/* The DGROUP is allocated by NE_CreateInstance */
         if (i == pModule->dgroup) continue;
         pSegment->selector = GLOBAL_Alloc( NE_Ne2MemFlags(pSegment->flags),
-                                      minsize, hModule,
+                                      minsize, pModule->self,
                                       !(pSegment->flags & NE_SEGFLAGS_DATA),
                                       FALSE,
                             FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
@@ -710,3 +788,15 @@
                             (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
     return TRUE;
 }
+
+
+/**********************************************************************
+ *	    IsSharedSelector    (KERNEL.345)
+ */
+BOOL16 WINAPI IsSharedSelector( HANDLE16 selector )
+{
+    /* Check whether the selector belongs to a DLL */
+    NE_MODULE *pModule = NE_GetPtr( selector );
+    if (!pModule) return FALSE;
+    return (pModule->flags & NE_FFLAGS_LIBMODULE) != 0;
+}
diff --git a/loader/pe_image.c b/loader/pe_image.c
index 12c962e..3d2dfbd 100644
--- a/loader/pe_image.c
+++ b/loader/pe_image.c
@@ -241,18 +241,14 @@
 	/* don't use MODULE_Load, Win32 creates new task differently */
 	res = PE_LoadLibraryEx32A( name, process, 0, 0 );
 	if (res <= (HMODULE32) 32) {
-	    char buffer[1024];
-
-	    /* Try with prepending the path of the current module */
-	    if (GetModuleFileName32A( wm->module, buffer, sizeof (buffer))) {
-	        char *p;
-
-		if (!(p = strrchr (buffer, '\\')))
-		    p = buffer;
-		strcpy (p + 1, name);
-		res = PE_LoadLibraryEx32A( buffer, process, 0, 0 );
-	    } else
-	    	ERR(win32,"cannot find the module just loaded!\n");
+	    char *p,buffer[2000];
+	    
+	    /* GetModuleFileName would use the wrong process, so don't use it */
+	    strcpy(buffer,wm->shortname);
+	    if (!(p = strrchr (buffer, '\\')))
+		p = buffer;
+	    strcpy (p + 1, name);
+	    res = PE_LoadLibraryEx32A( buffer, process, 0, 0 );
 	}
 	if (res <= (HMODULE32) 32) {
 	    WARN (module, "Module %s not found\n", name);
@@ -533,36 +529,32 @@
 /**********************************************************************
  * This maps a loaded PE dll into the address space of the specified process.
  */
-static BOOL32 PE_MapImage( HMODULE32 *phModule, PDB32 *process,
-                           OFSTRUCT *ofs, DWORD flags )
+static BOOL32 PE_MapImage( PDB32 *process,WINE_MODREF *wm, OFSTRUCT *ofs, DWORD flags )
 {
-	WINE_MODREF		*wm;
 	PE_MODREF		*pem;
 	int			i, result;
 	DWORD			load_addr;
 	IMAGE_DATA_DIRECTORY	dir;
 	char			*modname;
 	int			vma_size;
-	HMODULE32		hModule = *phModule;
+	HMODULE32		hModule = wm->module;
 
         IMAGE_SECTION_HEADER *pe_seg;
         IMAGE_DOS_HEADER *dos_header = (IMAGE_DOS_HEADER *)hModule;
         IMAGE_NT_HEADERS *nt_header = PE_HEADER(hModule);
 	
-
-	wm = (WINE_MODREF*)HeapAlloc(process->heap,HEAP_ZERO_MEMORY,
-                                    sizeof(*wm));
-	wm->type= MODULE32_PE;
 	pem 	= &(wm->binfmt.pe);
 
-	/* NOTE: fixup_imports takes care of the correct order */
-	wm->next	= process->modref_list;
-	process->modref_list = wm;
+	result = GetLongPathName32A(ofs->szPathName,NULL,0);
+	wm->longname = (char*)HeapAlloc(process->heap,0,result+1);
+	GetLongPathName32A(ofs->szPathName,wm->longname,result+1);
+
+	wm->shortname = HEAP_strdupA(process->heap,0,ofs->szPathName);
 
 	if (!(nt_header->FileHeader.Characteristics & IMAGE_FILE_DLL))
         {
 		if (process->exe_modref)
-			WARN(win32,"overwriting old exe_modref... arrgh\n");
+			FIXME(win32,"overwriting old exe_modref... arrgh\n");
 		process->exe_modref = wm;
 	}
 
@@ -577,10 +569,10 @@
 						 MEM_RESERVE | MEM_COMMIT,
 						 PAGE_EXECUTE_READWRITE );
 	}
-	/* *phModule is the module32 entry in the NE_MODULE. We need to
-	 * change it here, since it can get referenced by fixup_imports()
+	/* NOTE: this changes a value in the process modref chain, which can
+	 * be accessed independently from this function
 	 */
-	wm->module = *phModule = (HMODULE32)load_addr;
+	wm->module = (HMODULE32)load_addr;
 
 	TRACE(win32, "Load addr is really %lx, range %x\n",
                       load_addr, vma_size);
@@ -713,8 +705,6 @@
 		modname = s = ofs->szPathName;
 		while ((s=strchr(modname,'\\')))
 			modname = s+1;
-		if ((s=strchr(modname,'.')))
-			*s='\0';
 		wm->modname = HEAP_strdupA(process->heap,0,modname);
 	}
 	if(pem->pe_import)	{
@@ -760,13 +750,9 @@
 	WINE_MODREF	*wm;
 
 	if ((hModule = MODULE_FindModule32( process, name ))) {
-		
-		pModule = MODULE_GetPtr32(hModule);
 		for (wm= process->modref_list;wm;wm=wm->next)
-			if (wm->module == hModule) {
-				pModule->count++;
+			if (wm->module == hModule)
 				return hModule;
-			}
 		/* Since MODULE_FindModule32 uses the modref chain too, the
 		 * module MUST have been found above. If not, something has gone
 		 * terribly wrong.
@@ -781,31 +767,55 @@
 	if (HFILE_ERROR32==(hFile=OpenFile32(name,&ofs,OF_READ))) {
 		/* Now try the built-in even if disabled */
 		if ((hModule = BUILTIN32_LoadModule( name, TRUE, process ))) {
-			fprintf( stderr, "Warning: could not load external DLL '%s', using built-in module.\n", name );
-			return hModule;
+		    WARN( module, "Could not load external DLL '%s', using built-in module.\n", name );
+		    return hModule;
 		}
 		return 1;
 	}
+	/* will go away ... */
 	if ((hModule = MODULE_CreateDummyModule( &ofs )) < 32) {
 		_lclose32(hFile);
 		return hModule;
 	}
-	pModule		= (NE_MODULE *)GlobalLock16( hModule );
-	pModule->flags	= NE_FFLAGS_WIN32;
-	pModule->module32 = PE_LoadImage( hFile );
+	pModule         = (NE_MODULE *)GlobalLock16( hModule );
+	pModule->flags  = NE_FFLAGS_WIN32;
+	/* .. */
+
+	wm=(WINE_MODREF*)HeapAlloc(process->heap,HEAP_ZERO_MEMORY,sizeof(*wm));
+	wm->type = MODULE32_PE;
+	/* NOTE: fixup_imports takes care of the correct order */
+	wm->next = process->modref_list;
+	process->modref_list = wm;
+
+	wm->module = pModule->module32 = PE_LoadImage( hFile );
+
 	CloseHandle( hFile );
-        if (pModule->module32 < 32) 
+        if (wm->module < 32) 
         {
-            FreeLibrary32( hModule);
+	    process->modref_list = wm->next;
+	    HeapFree(process->heap,0,wm);
+	    ERR(win32,"can't load %s\n",ofs.szPathName);
             return 21; /* FIXME: probably 0 */
         }
 
 	/* (possible) recursion */
-	if (!PE_MapImage( &(pModule->module32), process, &ofs,flags)) {
-		/* FIXME: should free this module and its referenced ones */
-		return 0;
+	if (!PE_MapImage(process,wm,&ofs,flags)) {
+	    /* ERROR cleanup ... */
+	    WINE_MODREF	**xwm;
+
+	    ERR(win32,"couldn't load %s\n",ofs.szPathName);
+	    /* unlink from process modref chain */
+	    for (    xwm=&(process->modref_list);
+		     *xwm && (*xwm!=wm);
+		     xwm=&((*xwm)->next)
+	    ) /* EMPTY */;
+	    if (*xwm)
+	    	*xwm=(*xwm)->next;
+	    	
+	    return 0;
 	}
-	return pModule->module32;
+        pModule->module32 = wm->module;
+	return wm->module;
 }
 
 /*****************************************************************************
@@ -813,23 +823,30 @@
  * FIXME: this function should use PE_LoadLibraryEx32A, but currently can't
  * due to the PROCESS_Create stuff.
  */
-HINSTANCE16 PE_LoadModule( HFILE32 hFile, OFSTRUCT *ofs, LPCSTR cmd_line,
+HINSTANCE16 PE_LoadModule( LPCSTR name, LPCSTR cmd_line,
                            LPCSTR env, UINT16 show_cmd )
 {
     HMODULE16 hModule16;
     HMODULE32 hModule32;
     HINSTANCE16 hInstance;
     NE_MODULE *pModule;
+    HFILE32 hFile;
+    OFSTRUCT ofs;
     THDB *thdb = THREAD_Current();
-    
-    if ((hModule16 = MODULE_CreateDummyModule( ofs )) < 32) return hModule16;
+    PDB32 *process;
+    WINE_MODREF	*wm;
+
+    if ((hFile = OpenFile32( name, &ofs, OF_READ )) == HFILE_ERROR32)
+        return 2;  /* File not found */
+
+    if ((hModule16 = MODULE_CreateDummyModule( &ofs )) < 32) return hModule16;
     pModule = (NE_MODULE *)GlobalLock16( hModule16 );
     pModule->flags = NE_FFLAGS_WIN32;
 
     pModule->module32 = hModule32 = PE_LoadImage( hFile );
     if (hModule32 < 32) return 21;
 
-    hInstance = MODULE_CreateInstance( hModule16, NULL, (cmd_line == NULL) );
+    hInstance = NE_CreateInstance( pModule, NULL, (cmd_line == NULL) );
     if (cmd_line &&
         !(PE_HEADER(hModule32)->FileHeader.Characteristics & IMAGE_FILE_DLL))
     {
@@ -838,11 +855,21 @@
         TDB *pTask = (TDB *)GlobalLock16( pdb->task );
         thdb = pTask->thdb;
     }
-    if (!PE_MapImage( &(pModule->module32), thdb->process, ofs, 0 ))
+
+    process = thdb->process;
+
+    wm=(WINE_MODREF*)HeapAlloc(process->heap,HEAP_ZERO_MEMORY,sizeof(*wm));
+    wm->type = MODULE32_PE;
+    /* NOTE: fixup_imports takes care of the correct order */
+    wm->next = process->modref_list;
+    wm->module = hModule32;
+    process->modref_list = wm;
+    if (!PE_MapImage( process, wm, &ofs, 0 ))
     {
      	/* FIXME: should destroy the task created and free referenced stuff */
         return 0;
     }
+    pModule->module32 = wm->module;
     /* FIXME: Yuck. Is there no other good place to do that? */
     PE_InitTls( thdb );
     return hInstance;
diff --git a/loader/resource.c b/loader/resource.c
index 32f2a6d..c4bec2f 100644
--- a/loader/resource.c
+++ b/loader/resource.c
@@ -187,7 +187,7 @@
 	    break;
 	}
     if (__winelib)
-        fprintf(stderr,"SizeofResource32: not implemented for WINELIB\n");
+        FIXME(module,"Not implemented for WINELIB\n");
     return 0;
 }
 
diff --git a/loader/signal.c b/loader/signal.c
index 05cf70a..2e3dec6 100644
--- a/loader/signal.c
+++ b/loader/signal.c
@@ -158,7 +158,7 @@
 {
     extern void SYNC_SetupSignals(void);
 
-#ifdef HAVE_SIGALTSTACK
+#ifdef HAVE_WORKING_SIGALTSTACK
     struct sigaltstack ss;
     ss.ss_sp    = SIGNAL_Stack;
     ss.ss_size  = sizeof(SIGNAL_Stack);
diff --git a/loader/task.c b/loader/task.c
index 99c7611..2d25eac 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -37,7 +37,6 @@
 #define MIN_THUNKS  32
 
 extern INT32 WINSOCK_DeleteTaskWSI( TDB* pTask, struct _WSINFO* );
-extern BOOL32 MODULE_FreeModule( HMODULE16 hModule, TDB* ptaskContext );
 
   /* Pointer to function to switch to a larger stack */
 int (*IF1632_CallLargeStack)( int (*func)(), void *arg ) = NULL;
@@ -208,7 +207,7 @@
 {
     int exit_code = 1;
     TDB *pTask = (TDB *)GlobalLock16( hCurrentTask );
-    NE_MODULE *pModule = MODULE_GetPtr16( pTask->hModule );
+    NE_MODULE *pModule = NE_GetPtr( pTask->hModule );
     SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
 
     SET_CUR_THREAD( pTask->thdb );
@@ -276,9 +275,10 @@
 {
     HTASK16 hTask;
     TDB *pTask;
-    LPSTR name, cmd_line;
+    LPSTR cmd_line;
     WORD sp;
     char *stack32Top;
+    char name[10];
     STACK16FRAME *frame16;
     STACK32FRAME *frame32;
     PDB32 *pdb32 = thdb->process;
@@ -319,7 +319,7 @@
 
       /* Copy the module name */
 
-    name = MODULE_GetModuleName( pModule->self );
+    GetModuleName( pModule->self, name, sizeof(name) );
     strncpy( pTask->module_name, name, sizeof(pTask->module_name) );
 
       /* Allocate a selector for the PDB */
@@ -432,7 +432,7 @@
 
     /* Free the task module */
 
-    MODULE_FreeModule( pTask->hModule, pTask );
+    FreeModule16( pTask->hModule );
 
     /* Free the selector aliases */
 
@@ -660,7 +660,7 @@
 
     if (context) EAX_reg(context) = 0;
     if (!(pTask = (TDB *)GlobalLock16( hCurrentTask ))) return;
-    if (!(pModule = MODULE_GetPtr16( pTask->hModule ))) return;
+    if (!(pModule = NE_GetPtr( pTask->hModule ))) return;
 
     /* This is a hack to install task USER signal handler before 
      * implicitly loaded DLLs are initialized (see windows/user.c) */
@@ -855,7 +855,7 @@
     BYTE *thunk,*lfunc;
     SEGPTR thunkaddr;
 
-    if (!hInstance) return 0;
+    if (!hInstance) hInstance = CURRENT_DS;
     thunkaddr = TASK_AllocThunk( hCurrentTask );
     if (!thunkaddr) return (FARPROC16)0;
     thunk = PTR_SEG_TO_LIN( thunkaddr );
@@ -995,12 +995,8 @@
 
 /***********************************************************************
  *           SwitchStackBack   (KERNEL.109)
- *
- * Note: the function is declared as 'register' in the spec file in order
- * to make sure all registers are preserved, but we don't use them in any
- * way, so we don't need a CONTEXT* argument.
  */
-void WINAPI SwitchStackBack(void)
+void WINAPI SwitchStackBack( CONTEXT *context )
 {
     TDB *pTask;
     STACK16FRAME *oldFrame, *newFrame;
@@ -1022,6 +1018,8 @@
     /* Switch back to the old stack */
 
     pTask->thdb->cur_stack = pData->old_ss_sp;
+    SS_reg(context)  = SELECTOROF(pData->old_ss_sp);
+    ESP_reg(context) = OFFSETOF(pData->old_ss_sp);
     pData->old_ss_sp = 0;
 
     /* Build a stack frame for the return */