- Fixed resource functions to work directly from the HMODULE instead of
  requiring a modref.
- Attempted to get LOAD_LIBRARY_AS_DATAFILE right (based on patches by
  Eric Pouech and Dusan Lacko).
- Simplified modref structure and handling.

diff --git a/loader/module.c b/loader/module.c
index 264b7f0..2f37291 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -20,7 +20,6 @@
 #include "module.h"
 #include "snoop.h"
 #include "neexe.h"
-#include "pe_image.h"
 #include "dosexe.h"
 #include "process.h"
 #include "syslevel.h"
@@ -41,8 +40,9 @@
 /*************************************************************************
  *		MODULE32_LookupHMODULE
  * looks for the referenced HMODULE in the current process
+ * NOTE: Assumes that the process critical section is held!
  */
-WINE_MODREF *MODULE32_LookupHMODULE( HMODULE hmod )
+static WINE_MODREF *MODULE32_LookupHMODULE( HMODULE hmod )
 {
     WINE_MODREF	*wm;
 
@@ -51,15 +51,50 @@
 
     if (!HIWORD(hmod)) {
     	ERR("tried to lookup 0x%04x in win32 module handler!\n",hmod);
+        SetLastError( ERROR_INVALID_HANDLE );
 	return NULL;
     }
     for ( wm = PROCESS_Current()->modref_list; wm; wm=wm->next )
 	if (wm->module == hmod)
 	    return wm;
+    SetLastError( ERROR_INVALID_HANDLE );
     return NULL;
 }
 
 /*************************************************************************
+ *		MODULE_AllocModRef
+ *
+ * Allocate a WINE_MODREF structure and add it to the process list
+ * NOTE: Assumes that the process critical section is held!
+ */
+WINE_MODREF *MODULE_AllocModRef( HMODULE hModule, LPCSTR filename )
+{
+    WINE_MODREF *wm;
+    DWORD len;
+
+    if ((wm = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wm) )))
+    {
+        wm->module = hModule;
+        wm->tlsindex = -1;
+
+        wm->filename = HEAP_strdupA( GetProcessHeap(), 0, filename );
+        if ((wm->modname = strrchr( wm->filename, '\\' ))) wm->modname++;
+        else wm->modname = wm->filename;
+
+        len = GetShortPathNameA( wm->filename, NULL, 0 );
+        wm->short_filename = (char *)HeapAlloc( GetProcessHeap(), 0, len+1 );
+        GetShortPathNameA( wm->filename, wm->short_filename, len+1 );
+        if ((wm->short_modname = strrchr( wm->short_filename, '\\' ))) wm->short_modname++;
+        else wm->short_modname = wm->short_filename;
+
+        wm->next = PROCESS_Current()->modref_list;
+        if (wm->next) wm->next->prev = wm;
+        PROCESS_Current()->modref_list = wm;
+    }
+    return wm;
+}
+
+/*************************************************************************
  *		MODULE_InitDLL
  */
 static BOOL MODULE_InitDLL( WINE_MODREF *wm, DWORD type, LPVOID lpReserved )
@@ -70,32 +105,14 @@
                                  "THREAD_ATTACH", "THREAD_DETACH" };
     assert( wm );
 
-
     /* Skip calls for modules loaded with special load flags */
 
-    if (    ( wm->flags & WINE_MODREF_DONT_RESOLVE_REFS )
-         || ( wm->flags & WINE_MODREF_LOAD_AS_DATAFILE ) )
-        return TRUE;
-
+    if (wm->flags & WINE_MODREF_DONT_RESOLVE_REFS) return TRUE;
 
     TRACE("(%s,%s,%p) - CALL\n", wm->modname, typeName[type], lpReserved );
 
     /* Call the initialization routine */
-    switch ( wm->type )
-    {
-    case MODULE32_PE:
-        retv = PE_InitDLL( wm, type, lpReserved );
-        break;
-
-    case MODULE32_ELF:
-        /* no need to do that, dlopen() already does */
-        break;
-
-    default:
-        ERR("wine_modref type %d not handled.\n", wm->type );
-        retv = FALSE;
-        break;
-    }
+    retv = PE_InitDLL( wm->module, type, lpReserved );
 
     /* The state of the module list may have changed due to the call
        to PE_InitDLL. We cannot assume that this module has not been
@@ -626,13 +643,13 @@
     ptr = strrchr( filename, '.' );
     if ( ptr && !strchr( ptr, '\\' ) && !strchr( ptr, '/' ) )
     {
-        if ( !lstrcmpiA( ptr, ".COM" ) )
+        if ( !strcasecmp( ptr, ".COM" ) )
         {
             *lpBinaryType = SCS_DOS_BINARY;
             return TRUE;
         }
 
-        if ( !lstrcmpiA( ptr, ".PIF" ) )
+        if ( !strcasecmp( ptr, ".PIF" ) )
         {
             *lpBinaryType = SCS_PIF_BINARY;
             return TRUE;
@@ -1152,15 +1169,17 @@
 DWORD WINAPI GetModuleFileNameA( 
 	HMODULE hModule,	/* [in] module handle (32bit) */
 	LPSTR lpFileName,	/* [out] filenamebuffer */
-        DWORD size		/* [in] size of filenamebuffer */
-) {                   
-    WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
+        DWORD size )		/* [in] size of filenamebuffer */
+{
+    WINE_MODREF *wm;
 
-    if (!wm) /* can happen on start up or the like */
-    	return 0;
+    EnterCriticalSection( &PROCESS_Current()->crit_section );
 
-    lstrcpynA( lpFileName, wm->filename, size );
-       
+    lpFileName[0] = 0;
+    if ((wm = MODULE32_LookupHMODULE( hModule )))
+        lstrcpynA( lpFileName, wm->filename, size );
+
+    LeaveCriticalSection( &PROCESS_Current()->crit_section );
     TRACE("%s\n", lpFileName );
     return strlen(lpFileName);
 }                   
@@ -1193,6 +1212,25 @@
 		return 0;
 	}
 
+        if (flags & LOAD_LIBRARY_AS_DATAFILE)
+        {
+            char filename[256];
+            HFILE hFile;
+            HMODULE hmod = 0;
+
+            if (!SearchPathA( NULL, libname, ".dll", sizeof(filename), filename, NULL ))
+                return 0;
+            /* FIXME: maybe we should use the hfile parameter instead */
+            hFile = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ,
+                                 NULL, OPEN_EXISTING, 0, -1 );
+            if (hFile != INVALID_HANDLE_VALUE)
+            {
+                hmod = PE_LoadImage( hFile, filename, flags );
+                CloseHandle( hFile );
+            }
+            return hmod;
+        }
+
 	EnterCriticalSection(&PROCESS_Current()->crit_section);
 
 	wm = MODULE_LoadLibraryExA( libname, hfile, flags );
@@ -1237,6 +1275,14 @@
 	{
 		if(!(pwm->flags & WINE_MODREF_MARKER))
 			pwm->refCount++;
+
+                if ((pwm->flags & WINE_MODREF_DONT_RESOLVE_REFS) &&
+		    !(flags & DONT_RESOLVE_DLL_REFERENCES))
+                {
+                    extern DWORD fixup_imports(WINE_MODREF *wm); /*FIXME*/
+                    pwm->flags &= ~WINE_MODREF_DONT_RESOLVE_REFS;
+                    fixup_imports( pwm );
+		}
 		TRACE("Already loaded module '%s' at 0x%08x, count=%d, \n", libname, pwm->module, pwm->refCount);
 		LeaveCriticalSection(&PROCESS_Current()->crit_section);
 		return pwm;
@@ -1371,23 +1417,12 @@
 		if(wm == PROCESS_Current()->modref_list)
 			PROCESS_Current()->modref_list = wm->next;
 
-		/* 
-		 * The unloaders are also responsible for freeing the modref itself
-		 * because the loaders were responsible for allocating it.
-		 */
-		switch(wm->type)
-		{
-                case MODULE32_PE:       if ( !(wm->flags & WINE_MODREF_INTERNAL) )
-                                               PE_UnloadLibrary(wm);
-                                        else
-                                               BUILTIN32_UnloadLibrary(wm);
-					break;
-		case MODULE32_ELF:	ELF_UnloadLibrary(wm);		break;
-		case MODULE32_ELFDLL:	ELFDLL_UnloadLibrary(wm);	break;
-
-		default:
-			ERR("Invalid or unhandled MODREF type %d encountered (wm=%p)\n", wm->type, wm);
-		}
+                TRACE(" unloading %s\n", wm->filename);
+                /* VirtualFree( (LPVOID)wm->module, 0, MEM_RELEASE ); */  /* FIXME */
+                /* if (wm->dlhandle) dlclose( wm->dlhandle ); */  /* FIXME */
+                HeapFree( GetProcessHeap(), 0, wm->filename );
+                HeapFree( GetProcessHeap(), 0, wm->short_filename );
+                HeapFree( GetProcessHeap(), 0, wm );
 	}
 }
 
@@ -1592,32 +1627,22 @@
 	LPCSTR function,	/* [in] function to be looked up */
 	BOOL snoop )
 {
-    WINE_MODREF	*wm = MODULE32_LookupHMODULE( hModule );
-    FARPROC	retproc;
+    WINE_MODREF	*wm;
+    FARPROC	retproc = 0;
 
     if (HIWORD(function))
 	TRACE_(win32)("(%08lx,%s)\n",(DWORD)hModule,function);
     else
 	TRACE_(win32)("(%08lx,%p)\n",(DWORD)hModule,function);
-    if (!wm) {
-    	SetLastError(ERROR_INVALID_HANDLE);
-        return (FARPROC)0;
-    }
-    switch (wm->type)
+
+    EnterCriticalSection( &PROCESS_Current()->crit_section );
+    if ((wm = MODULE32_LookupHMODULE( hModule )))
     {
-    case MODULE32_PE:
-     	retproc = PE_FindExportedFunction( wm, function, snoop );
-	if (!retproc) SetLastError(ERROR_PROC_NOT_FOUND);
-	return retproc;
-    case MODULE32_ELF:
-    	retproc = ELF_FindExportedFunction( wm, function);
-	if (!retproc) SetLastError(ERROR_PROC_NOT_FOUND);
-	return retproc;
-    default:
-    	ERR("wine_modref type %d not handled.\n",wm->type);
-    	SetLastError(ERROR_INVALID_HANDLE);
-    	return (FARPROC)0;
+        retproc = wm->find_export( wm, function, snoop );
+        if (!retproc) SetLastError(ERROR_PROC_NOT_FOUND);
     }
+    LeaveCriticalSection( &PROCESS_Current()->crit_section );
+    return retproc;
 }