ntdll/kernel32: #5

Eric Pouech eric.pouech at wanadoo.fr
Thu Mar 13 14:33:15 CST 2003


ChangeLog:
- implementation of LdrLoadDll out of loader/module.c
- in impacted functions, ensure that we only use ntdll functions
- for internal loading, start using NTDLL style for error reporting
- making use of new LdrLoadDll

A+
-- 
Eric Pouech
-------------- next part --------------
diff -u -x '*~' -x '.#*' dlls/ntdll4/loader.c dlls/ntdll/loader.c
--- dlls/ntdll4/loader.c	2003-03-07 13:24:21.000000000 +0100
+++ dlls/ntdll/loader.c	2003-03-09 16:01:11.000000000 +0100
@@ -44,6 +44,48 @@
 }
 
 
+/*************************************************************************
+ *		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 long_len = strlen( filename );
+    DWORD short_len = GetShortPathNameA( filename, NULL, 0 );
+
+    if ((wm = RtlAllocateHeap( ntdll_get_process_heap(), HEAP_ZERO_MEMORY,
+                               sizeof(*wm) + long_len + short_len + 1 )))
+    {
+        wm->module = hModule;
+        wm->tlsindex = -1;
+
+        wm->filename = wm->data;
+        memcpy( wm->filename, filename, long_len + 1 );
+        if ((wm->modname = strrchr( wm->filename, '\\' ))) wm->modname++;
+        else wm->modname = wm->filename;
+
+        wm->short_filename = wm->filename + long_len + 1;
+        GetShortPathNameA( wm->filename, wm->short_filename, short_len + 1 );
+        if ((wm->short_modname = strrchr( wm->short_filename, '\\' ))) wm->short_modname++;
+        else wm->short_modname = wm->short_filename;
+
+        wm->next = MODULE_modref_list;
+        if (wm->next) wm->next->prev = wm;
+        MODULE_modref_list = wm;
+
+        if (!(RtlImageNtHeader(hModule)->FileHeader.Characteristics & IMAGE_FILE_DLL))
+        {
+            if (!exe_modref) exe_modref = wm;
+            else FIXME( "Trying to load second .EXE file: %s\n", filename );
+        }
+    }
+    return wm;
+}
+
 /******************************************************************
  *		LdrDisableThreadCalloutsForDll (NTDLL.@)
  *
@@ -182,6 +224,247 @@
 }
 
 
+/***********************************************************************
+ *      allocate_lib_dir
+ *
+ * helper for MODULE_LoadLibraryExA.  Allocate space to hold the directory
+ * portion of the provided name and put the name in it.
+ *
+ */
+static LPCSTR allocate_lib_dir(LPCSTR libname)
+{
+    LPCSTR p, pmax;
+    LPSTR result;
+    int length;
+
+    pmax = libname;
+    if ((p = strrchr( pmax, '\\' ))) pmax = p + 1;
+    if ((p = strrchr( pmax, '/' ))) pmax = p + 1; /* Naughty.  MSDN says don't */
+    if (pmax == libname && pmax[0] && pmax[1] == ':') pmax += 2;
+
+    length = pmax - libname;
+
+    result = RtlAllocateHeap (ntdll_get_process_heap(), 0, length+1);
+
+    if (result)
+    {
+        strncpy (result, libname, length);
+        result [length] = '\0';
+    }
+
+    return result;
+}
+
+/***********************************************************************
+ *	MODULE_LoadLibraryExA	(internal)
+ *
+ * Load a PE style module according to the load order.
+ *
+ * libdir is used to support LOAD_WITH_ALTERED_SEARCH_PATH during the recursion
+ *        on this function.  When first called from LoadLibraryExA it will be
+ *        NULL but thereafter it may point to a buffer containing the path
+ *        portion of the library name.  Note that the recursion all occurs
+ *        within a Critical section (see LoadLibraryExA) so the use of a
+ *        static is acceptable.
+ *        (We have to use a static variable at some point anyway, to pass the
+ *        information from BUILTIN32_dlopen through dlopen and the builtin's
+ *        init function into load_library).
+ * allocated_libdir is TRUE in the stack frame that allocated libdir
+ */
+NTSTATUS MODULE_LoadLibraryExA( LPCSTR libname, DWORD flags, WINE_MODREF** pwm)
+{
+    int i;
+    enum loadorder_type loadorder[LOADORDER_NTYPES];
+    LPSTR filename;
+    const char *filetype = "";
+    DWORD found;
+    BOOL allocated_libdir = FALSE;
+    static LPCSTR libdir = NULL; /* See above */
+    NTSTATUS nts = STATUS_SUCCESS;
+
+    *pwm = NULL;
+    if ( !libname ) return STATUS_DLL_NOT_FOUND; /* FIXME ? */
+
+    filename = RtlAllocateHeap ( ntdll_get_process_heap(), 0, MAX_PATH + 1 );
+    if ( !filename ) return STATUS_NO_MEMORY;
+    *filename = 0; /* Just in case we don't set it before goto error */
+
+    RtlEnterCriticalSection( &loader_section );
+
+    if ((flags & LOAD_WITH_ALTERED_SEARCH_PATH) && FILE_contains_path(libname))
+    {
+        if (!(libdir = allocate_lib_dir(libname)))
+        {
+            nts = STATUS_NO_MEMORY;
+            goto error;
+        }
+        allocated_libdir = TRUE;
+    }
+
+    if (!libdir || allocated_libdir)
+        found = SearchPathA(NULL, libname, ".dll", MAX_PATH, filename, NULL);
+    else
+        found = DIR_SearchAlternatePath(libdir, libname, ".dll", MAX_PATH, filename, NULL);
+
+    /* build the modules filename */
+    if (!found)
+    {
+        if (!MODULE_GetBuiltinPath( libname, ".dll", filename, MAX_PATH ))
+        {
+            nts = STATUS_INTERNAL_ERROR;
+            goto error;
+        }
+    }
+
+    /* Check for already loaded module */
+    if (!(*pwm = MODULE_FindModule(filename)) && !FILE_contains_path(libname))
+    {
+        LPSTR	fn = RtlAllocateHeap ( ntdll_get_process_heap(), 0, MAX_PATH + 1 );
+        if (fn)
+        {
+            /* since the default loading mechanism uses a more detailed algorithm
+             * than SearchPath (like using PATH, which can even be modified between
+             * two attempts of loading the same DLL), the look-up above (with
+             * SearchPath) can have put the file in system directory, whereas it
+             * has already been loaded but with a different path. So do a specific
+             * look-up with filename (without any path)
+             */
+            strcpy ( fn, libname );
+            /* if the filename doesn't have an extension append .DLL */
+            if (!strrchr( fn, '.')) strcat( fn, ".dll" );
+            if ((*pwm = MODULE_FindModule( fn )) != NULL)
+                strcpy( filename, fn );
+            RtlFreeHeap( ntdll_get_process_heap(), 0, fn );
+        }
+    }
+    if (*pwm)
+    {
+        (*pwm)->refCount++;
+        
+        if (((*pwm)->flags & WINE_MODREF_DONT_RESOLVE_REFS) &&
+            !(flags & DONT_RESOLVE_DLL_REFERENCES))
+        {
+            (*pwm)->flags &= ~WINE_MODREF_DONT_RESOLVE_REFS;
+            PE_fixup_imports( *pwm );
+        }
+        TRACE("Already loaded module '%s' at %p, count=%d\n", filename, (*pwm)->module, (*pwm)->refCount);
+        if (allocated_libdir)
+        {
+            RtlFreeHeap( ntdll_get_process_heap(), 0, (LPSTR)libdir );
+            libdir = NULL;
+        }
+        RtlLeaveCriticalSection( &loader_section );
+        RtlFreeHeap( ntdll_get_process_heap(), 0, filename );
+        return STATUS_SUCCESS;
+    }
+
+    MODULE_GetLoadOrder( loadorder, filename, TRUE);
+
+    for (i = 0; i < LOADORDER_NTYPES; i++)
+    {
+        if (loadorder[i] == LOADORDER_INVALID) break;
+
+        switch (loadorder[i])
+        {
+        case LOADORDER_DLL:
+            TRACE("Trying native dll '%s'\n", filename);
+            nts = PE_LoadLibraryExA(filename, flags, pwm);
+            filetype = "native";
+            break;
+            
+        case LOADORDER_BI:
+            TRACE("Trying built-in '%s'\n", filename);
+            nts = BUILTIN32_LoadLibraryExA(filename, flags, pwm);
+            filetype = "builtin";
+            break;
+            
+        default:
+            nts = STATUS_INTERNAL_ERROR;
+            break;
+        }
+
+        if (nts == STATUS_SUCCESS)
+        {
+            /* Initialize DLL just loaded */
+            TRACE("Loaded module '%s' at %p\n", filename, (*pwm)->module);
+            if (!TRACE_ON(module))
+                TRACE_(loaddll)("Loaded module '%s' : %s\n", filename, filetype);
+            /* Set the refCount here so that an attach failure will */
+            /* decrement the dependencies through the MODULE_FreeLibrary call. */
+            (*pwm)->refCount = 1;
+            
+            if (allocated_libdir)
+            {
+                RtlFreeHeap( ntdll_get_process_heap(), 0, (LPSTR)libdir );
+                libdir = NULL;
+            }
+            RtlLeaveCriticalSection( &loader_section );
+            RtlFreeHeap( ntdll_get_process_heap(), 0, filename );
+            return nts;
+        }
+
+        if (nts != STATUS_NO_SUCH_FILE)
+        {
+            WARN("Loading of %s DLL %s failed (status %ld).\n",
+                 filetype, filename, nts);
+            break;
+        }
+    }
+
+ error:
+    if (allocated_libdir)
+    {
+        RtlFreeHeap( ntdll_get_process_heap(), 0, (LPSTR)libdir );
+        libdir = NULL;
+    }
+    RtlLeaveCriticalSection( &loader_section );
+    WARN("Failed to load module '%s'; status=%ld\n", filename, nts);
+    RtlFreeHeap( ntdll_get_process_heap(), 0, filename );
+    return nts;
+}
+
+/******************************************************************
+ *		LdrLoadDll (NTDLL.@)
+ *
+ *
+ */
+NTSTATUS WINAPI LdrLoadDll(LPCWSTR path_name, DWORD flags, PUNICODE_STRING libname, HMODULE* hModule)
+{
+    WINE_MODREF *wm;
+    NTSTATUS    nts = STATUS_SUCCESS;
+    STRING      str;
+
+    RtlUnicodeStringToAnsiString(&str, libname, TRUE);
+
+    RtlEnterCriticalSection( &loader_section );
+
+    switch (nts = MODULE_LoadLibraryExA( str.Buffer, flags, &wm ))
+    {
+    case STATUS_SUCCESS:
+        if ( !MODULE_DllProcessAttach( wm, NULL ) )
+        {
+            WARN_(module)("Attach failed for module '%s'.\n", str.Buffer);
+            LdrUnloadDll(wm->module);
+            nts = STATUS_DLL_INIT_FAILED;
+            wm = NULL;
+        }
+        break;
+    case STATUS_NO_SUCH_FILE:
+        nts = STATUS_DLL_NOT_FOUND;
+        break;
+    default: /* keep error code as it is (memory...) */
+        break;
+    }
+
+    *hModule = (wm) ? wm->module : NULL;
+    
+    RtlLeaveCriticalSection( &loader_section );
+
+    RtlFreeAnsiString(&str);
+
+    return nts;
+}
+
 /******************************************************************
  *		LdrShutdownProcess (NTDLL.@)
  *
diff -u -x '*~' -x '.#*' dlls/ntdll4/ntdll_misc.h dlls/ntdll/ntdll_misc.h
--- dlls/ntdll4/ntdll_misc.h	2003-03-07 10:31:34.000000000 +0100
+++ dlls/ntdll/ntdll_misc.h	2003-03-07 12:18:59.000000000 +0100
@@ -21,6 +21,7 @@
 
 #include "winnt.h"
 #include "winternl.h"
+#include "module.h"
 #include "thread.h"
 
 /* debug helper */
@@ -29,11 +30,12 @@
 
 /* module handling */
 extern FARPROC MODULE_GetProcAddress( HMODULE hModule, LPCSTR function, int hint, BOOL snoop );
+extern WINE_MODREF *MODULE_AllocModRef( HMODULE hModule, LPCSTR filename );
+extern NTSTATUS MODULE_LoadLibraryExA( LPCSTR libname, DWORD flags, WINE_MODREF** );
 
 static inline HANDLE ntdll_get_process_heap(void)
 {
     HANDLE *pdb = (HANDLE *)NtCurrentTeb()->process;
     return pdb[0x18 / sizeof(HANDLE)];  /* get dword at offset 0x18 in pdb */
 }
-
 #endif
diff -u -x '*~' -x '.#*' dlls/ntdll4/ntdll.spec dlls/ntdll/ntdll.spec
--- dlls/ntdll4/ntdll.spec	2003-03-07 10:49:41.000000000 +0100
+++ dlls/ntdll/ntdll.spec	2003-03-07 11:11:19.000000000 +0100
@@ -42,7 +42,7 @@
 @ stdcall LdrGetDllHandle(long long ptr ptr) LdrGetDllHandle
 @ stdcall LdrGetProcedureAddress(ptr ptr long ptr) LdrGetProcedureAddress
 @ stub LdrInitializeThunk
-@ stub LdrLoadDll
+@ stdcall LdrLoadDll(wstr long ptr ptr) LdrLoadDll
 @ stub LdrProcessRelocationBlock
 @ stub LdrQueryImageFileExecutionOptions
 @ stub LdrQueryProcessModuleInformation
diff -u -x '*~' -x '.#*' include4/module.h include/module.h
--- include4/module.h	2003-03-07 06:58:46.000000000 +0100
+++ include/module.h	2003-03-07 12:38:05.000000000 +0100
@@ -25,6 +25,7 @@
 #include "winbase.h"
 #include "wine/windef16.h"
 #include "wine/winbase16.h"
+#include "winternl.h"
 
   /* In-memory module structure. See 'Windows Internals' p. 219 */
 typedef struct _NE_MODULE
@@ -193,11 +194,9 @@
 };
 
 /* module.c */
-extern WINE_MODREF *MODULE_AllocModRef( HMODULE hModule, LPCSTR filename );
 extern BOOL MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved );
 extern void MODULE_DllProcessDetach( BOOL bForceDetach, LPVOID lpReserved );
 extern void MODULE_DllThreadAttach( LPVOID lpReserved );
-extern WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HANDLE hfile, DWORD flags );
 extern WINE_MODREF *MODULE_FindModule( LPCSTR path );
 extern HMODULE16 MODULE_CreateDummyModule( LPCSTR filename, HMODULE module32 );
 extern enum binary_type MODULE_GetBinaryType( HANDLE hfile );
@@ -254,7 +253,7 @@
 extern HGLOBAL PE_LoadResource(HMODULE,HRSRC);
 
 /* loader/pe_image.c */
-extern WINE_MODREF *PE_LoadLibraryExA(LPCSTR, DWORD);
+extern NTSTATUS PE_LoadLibraryExA(LPCSTR, DWORD, WINE_MODREF**);
 extern HMODULE PE_LoadImage( HANDLE hFile, LPCSTR filename, DWORD flags );
 extern WINE_MODREF *PE_CreateModule( HMODULE hModule, LPCSTR filename,
                                      DWORD flags, HANDLE hFile, BOOL builtin );
@@ -268,7 +267,7 @@
 extern void MODULE_AddLoadOrderOption( const char *option );
 
 /* relay32/builtin.c */
-extern WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR name, DWORD flags);
+extern NTSTATUS BUILTIN32_LoadLibraryExA(LPCSTR name, DWORD flags, WINE_MODREF**);
 extern HMODULE BUILTIN32_LoadExeModule( HMODULE main );
 extern void *BUILTIN32_dlopen( const char *name );
 extern int BUILTIN32_dlclose( void *handle );
diff -u -x '*~' -x '.#*' include4/winternl.h include/winternl.h
--- include4/winternl.h	2003-03-04 07:47:52.000000000 +0100
+++ include/winternl.h	2003-03-07 06:01:03.000000000 +0100
@@ -1187,7 +1187,7 @@
 NTSTATUS WINAPI LdrFindEntryForAddress(void*, PLDR_MODULE*);
 NTSTATUS WINAPI LdrGetDllHandle(ULONG, ULONG, PUNICODE_STRING, HMODULE*);
 NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE, PANSI_STRING, ULONG, void**);
-NTSTATUS WINAPI LdrLoadDll(LPCSTR, DWORD, PUNICODE_STRING, HMODULE*);
+NTSTATUS WINAPI LdrLoadDll(LPCWSTR, DWORD, PUNICODE_STRING, HMODULE*);
 NTSTATUS WINAPI LdrShutdownThread(void);
 NTSTATUS WINAPI LdrShutdownProcess(void);
 NTSTATUS WINAPI LdrUnloadDll(HMODULE);
diff -u -x '*~' -x '.#*' loader4/module.c loader/module.c
--- loader4/module.c	2003-03-07 13:26:09.000000000 +0100
+++ loader/module.c	2003-03-09 14:50:22.000000000 +0100
@@ -96,48 +96,6 @@
 }
 
 /*************************************************************************
- *		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 long_len = strlen( filename );
-    DWORD short_len = GetShortPathNameA( filename, NULL, 0 );
-
-    if ((wm = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
-                         sizeof(*wm) + long_len + short_len + 1 )))
-    {
-        wm->module = hModule;
-        wm->tlsindex = -1;
-
-        wm->filename = wm->data;
-        memcpy( wm->filename, filename, long_len + 1 );
-        if ((wm->modname = strrchr( wm->filename, '\\' ))) wm->modname++;
-        else wm->modname = wm->filename;
-
-        wm->short_filename = wm->filename + long_len + 1;
-        GetShortPathNameA( wm->filename, wm->short_filename, short_len + 1 );
-        if ((wm->short_modname = strrchr( wm->short_filename, '\\' ))) wm->short_modname++;
-        else wm->short_modname = wm->short_filename;
-
-        wm->next = MODULE_modref_list;
-        if (wm->next) wm->next->prev = wm;
-        MODULE_modref_list = wm;
-
-        if (!(RtlImageNtHeader(hModule)->FileHeader.Characteristics & IMAGE_FILE_DLL))
-        {
-            if (!exe_modref) exe_modref = wm;
-            else FIXME( "Trying to load second .EXE file: %s\n", filename );
-        }
-    }
-    return wm;
-}
-
-/*************************************************************************
  *		MODULE_InitDLL
  */
 BOOL MODULE_InitDLL( WINE_MODREF *wm, DWORD type, LPVOID lpReserved )
@@ -1024,277 +982,146 @@
     return strlenW(lpFileName);
 }
 
-
-/***********************************************************************
- *           LoadLibraryExA   (KERNEL32.@)
- */
-HMODULE WINAPI LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags)
-{
-	WINE_MODREF *wm;
-
-	if(!libname)
-	{
-		SetLastError(ERROR_INVALID_PARAMETER);
-		return 0;
-	}
-
-        if (flags & LOAD_LIBRARY_AS_DATAFILE)
-        {
-            char filename[256];
-            HMODULE hmod = 0;
-
-            /* This method allows searching for the 'native' libraries only */
-            if (SearchPathA( NULL, libname, ".dll", sizeof(filename), filename, NULL ))
-            {
-                /* FIXME: maybe we should use the hfile parameter instead */
-                HANDLE hFile = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ,
-                                            NULL, OPEN_EXISTING, 0, 0 );
-                if (hFile != INVALID_HANDLE_VALUE)
-                {
-                    HANDLE mapping;
-                    switch (MODULE_GetBinaryType( hFile ))
-                    {
-                    case BINARY_PE_EXE:
-                    case BINARY_PE_DLL:
-                        mapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
-                        if (mapping)
-                        {
-                            hmod = (HMODULE)MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
-                            CloseHandle( mapping );
-                        }
-                        break;
-                    default:
-                        break;
-                    }
-                    CloseHandle( hFile );
-                }
-                if (hmod) return (HMODULE)((ULONG_PTR)hmod + 1);
-            }
-            flags |= DONT_RESOLVE_DLL_REFERENCES; /* Just in case */
-            /* Fallback to normal behaviour */
-        }
-
-        RtlEnterCriticalSection( &loader_section );
-
-	wm = MODULE_LoadLibraryExA( libname, hfile, flags );
-	if ( wm )
-	{
-		if ( !MODULE_DllProcessAttach( wm, NULL ) )
-		{
-			WARN_(module)("Attach failed for module '%s'.\n", libname);
-			LdrUnloadDll(wm->module);
-			SetLastError(ERROR_DLL_INIT_FAILED);
-			wm = NULL;
-		}
-	}
-
-        RtlLeaveCriticalSection( &loader_section );
-	return wm ? wm->module : 0;
-}
-
-/***********************************************************************
- *      allocate_lib_dir
+/******************************************************************
+ *		load_library_as_datafile
  *
- * helper for MODULE_LoadLibraryExA.  Allocate space to hold the directory
- * portion of the provided name and put the name in it.
  *
  */
-static LPCSTR allocate_lib_dir(LPCSTR libname)
+static BOOL load_library_as_datafile(const void* name, BOOL unicode, HMODULE* hmod)
 {
-    LPCSTR p, pmax;
-    LPSTR result;
-    int length;
+    HANDLE hFile = INVALID_HANDLE_VALUE;
+    HANDLE mapping;
+    
+    *hmod = 0;
 
-    pmax = libname;
-    if ((p = strrchr( pmax, '\\' ))) pmax = p + 1;
-    if ((p = strrchr( pmax, '/' ))) pmax = p + 1; /* Naughty.  MSDN says don't */
-    if (pmax == libname && pmax[0] && pmax[1] == ':') pmax += 2;
+    if (unicode)
+    {
+        WCHAR filenameW[MAX_PATH];
+static  WCHAR dotDLL[] = {'.','d','l','l',0};
 
-    length = pmax - libname;
+        if (SearchPathW( NULL, (LPCWSTR)name, dotDLL, sizeof(filenameW) / sizeof(filenameW[0]), filenameW, NULL ))
+        {
+            hFile = CreateFileW( filenameW, GENERIC_READ, FILE_SHARE_READ,
+                                 NULL, OPEN_EXISTING, 0, 0 );
+        }
+    }
+    else
+    {
+        char filenameA[MAX_PATH];
 
-    result = HeapAlloc (GetProcessHeap(), 0, length+1);
+        if (SearchPathA( NULL, (const char*)name, ".dll", sizeof(filenameA), filenameA, NULL ))
+        {
+            hFile = CreateFileA( filenameA, GENERIC_READ, FILE_SHARE_READ,
+                                 NULL, OPEN_EXISTING, 0, 0 );
+        }
+    }
 
-    if (result)
+    if (hFile == INVALID_HANDLE_VALUE) return FALSE;
+    switch (MODULE_GetBinaryType( hFile ))
     {
-        strncpy (result, libname, length);
-        result [length] = '\0';
+    case BINARY_PE_EXE:
+    case BINARY_PE_DLL:
+        mapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
+        if (mapping)
+        {
+            *hmod = (HMODULE)MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
+            CloseHandle( mapping );
+        }
+        break;
+    default:
+        break;
     }
+    CloseHandle( hFile );
 
-    return result;
+    return *hmod != 0;
 }
 
-/***********************************************************************
- *	MODULE_LoadLibraryExA	(internal)
- *
- * Load a PE style module according to the load order.
+/******************************************************************
+ *		LoadLibraryExA          (KERNEL32.@)
  *
  * The HFILE parameter is not used and marked reserved in the SDK. I can
  * only guess that it should force a file to be mapped, but I rather
  * ignore the parameter because it would be extremely difficult to
  * integrate this with different types of module representations.
  *
- * libdir is used to support LOAD_WITH_ALTERED_SEARCH_PATH during the recursion
- *        on this function.  When first called from LoadLibraryExA it will be
- *        NULL but thereafter it may point to a buffer containing the path
- *        portion of the library name.  Note that the recursion all occurs
- *        within a Critical section (see LoadLibraryExA) so the use of a
- *        static is acceptable.
- *        (We have to use a static variable at some point anyway, to pass the
- *        information from BUILTIN32_dlopen through dlopen and the builtin's
- *        init function into load_library).
- * allocated_libdir is TRUE in the stack frame that allocated libdir
- */
-WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HANDLE hfile, DWORD flags )
-{
-	DWORD err = GetLastError();
-	WINE_MODREF *pwm;
-	int i;
-	enum loadorder_type loadorder[LOADORDER_NTYPES];
-	LPSTR filename;
-        const char *filetype = "";
-        DWORD found;
-        BOOL allocated_libdir = FALSE;
-        static LPCSTR libdir = NULL; /* See above */
-
-	if ( !libname ) return NULL;
-
-	filename = HeapAlloc ( GetProcessHeap(), 0, MAX_PATH + 1 );
-	if ( !filename ) return NULL;
-        *filename = 0; /* Just in case we don't set it before goto error */
-
-        RtlEnterCriticalSection( &loader_section );
+ */
+HMODULE WINAPI LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags)
+{
+    UNICODE_STRING      wstr;
+    NTSTATUS            nts;
+    HMODULE             hModule;
 
-        if ((flags & LOAD_WITH_ALTERED_SEARCH_PATH) && FILE_contains_path(libname))
-        {
-            if (!(libdir = allocate_lib_dir(libname))) goto error;
-            allocated_libdir = TRUE;
-        }
+    if (!libname)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return 0;
+    }
 
-        if (!libdir || allocated_libdir)
-            found = SearchPathA(NULL, libname, ".dll", MAX_PATH, filename, NULL);
-        else
-            found = DIR_SearchAlternatePath(libdir, libname, ".dll", MAX_PATH, filename, NULL);
-
-	/* build the modules filename */
-        if (!found)
-	{
-            if (!MODULE_GetBuiltinPath( libname, ".dll", filename, MAX_PATH )) goto error;
-	}
+    if (flags & LOAD_LIBRARY_AS_DATAFILE)
+    {
+        /* The method in load_library_as_datafile allows searching for the 
+         * 'native' libraries only 
+         */
+        if (load_library_as_datafile(libname, FALSE, &hModule))
+            return (HMODULE)((ULONG_PTR)hModule + 1);
+        flags |= DONT_RESOLVE_DLL_REFERENCES; /* Just in case */
+        /* Fallback to normal behaviour */
+    }
 
-	/* Check for already loaded module */
-	if (!(pwm = MODULE_FindModule(filename)) && !FILE_contains_path(libname))
-        {
-	    LPSTR	fn = HeapAlloc ( GetProcessHeap(), 0, MAX_PATH + 1 );
-	    if (fn)
-	    {
-	    	/* since the default loading mechanism uses a more detailed algorithm
-		 * than SearchPath (like using PATH, which can even be modified between
-		 * two attempts of loading the same DLL), the look-up above (with
-		 * SearchPath) can have put the file in system directory, whereas it
-		 * has already been loaded but with a different path. So do a specific
-		 * look-up with filename (without any path)
-	     	 */
-	    	strcpy ( fn, libname );
-	    	/* if the filename doesn't have an extension append .DLL */
-	    	if (!strrchr( fn, '.')) strcat( fn, ".dll" );
-	    	if ((pwm = MODULE_FindModule( fn )) != NULL)
-		   strcpy( filename, fn );
-		HeapFree( GetProcessHeap(), 0, fn );
-	    }
-	}
-	if (pwm)
-	{
-		pwm->refCount++;
+    RtlCreateUnicodeStringFromAsciiz( &wstr, libname );
+    nts = LdrLoadDll(NULL, flags, &wstr, &hModule);
+    if (nts != STATUS_SUCCESS)
+    {
+        hModule = 0;
+        SetLastError( RtlNtStatusToDosError( nts ) );
+    }
+    RtlFreeUnicodeString( &wstr );
 
-                if ((pwm->flags & WINE_MODREF_DONT_RESOLVE_REFS) &&
-		    !(flags & DONT_RESOLVE_DLL_REFERENCES))
-                {
-                    pwm->flags &= ~WINE_MODREF_DONT_RESOLVE_REFS;
-                    PE_fixup_imports( pwm );
-		}
-		TRACE("Already loaded module '%s' at %p, count=%d\n", filename, pwm->module, pwm->refCount);
-                if (allocated_libdir)
-                {
-                    HeapFree ( GetProcessHeap(), 0, (LPSTR)libdir );
-                    libdir = NULL;
-                }
-                RtlLeaveCriticalSection( &loader_section );
-		HeapFree ( GetProcessHeap(), 0, filename );
-		return pwm;
-	}
+    return hModule;
+}
 
-        MODULE_GetLoadOrder( loadorder, filename, TRUE);
+/***********************************************************************
+ *           LoadLibraryExW       (KERNEL32.@)
+ */
+HMODULE WINAPI LoadLibraryExW(LPCWSTR libnameW, HANDLE hfile, DWORD flags)
+{
+    UNICODE_STRING      wstr;
+    NTSTATUS            nts;
+    HMODULE             hModule;
 
-	for(i = 0; i < LOADORDER_NTYPES; i++)
-	{
-                if (loadorder[i] == LOADORDER_INVALID) break;
-                SetLastError( ERROR_FILE_NOT_FOUND );
-
-		switch(loadorder[i])
-		{
-		case LOADORDER_DLL:
-			TRACE("Trying native dll '%s'\n", filename);
-			pwm = PE_LoadLibraryExA(filename, flags);
-                        filetype = "native";
-			break;
-
-		case LOADORDER_BI:
-			TRACE("Trying built-in '%s'\n", filename);
-			pwm = BUILTIN32_LoadLibraryExA(filename, flags);
-                        filetype = "builtin";
-			break;
-
-                default:
-			pwm = NULL;
-			break;
-		}
-
-		if(pwm)
-		{
-			/* Initialize DLL just loaded */
-			TRACE("Loaded module '%s' at %p\n", filename, pwm->module);
-                        if (!TRACE_ON(module))
-                            TRACE_(loaddll)("Loaded module '%s' : %s\n", filename, filetype);
-			/* Set the refCount here so that an attach failure will */
-			/* decrement the dependencies through the MODULE_FreeLibrary call. */
-			pwm->refCount = 1;
-
-                        if (allocated_libdir)
-                        {
-                            HeapFree ( GetProcessHeap(), 0, (LPSTR)libdir );
-                            libdir = NULL;
-                        }
-                        RtlLeaveCriticalSection( &loader_section );
-                        SetLastError( err );  /* restore last error */
-			HeapFree ( GetProcessHeap(), 0, filename );
-			return pwm;
-		}
+    if (!libnameW)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return 0;
+    }
 
-		if(GetLastError() != ERROR_FILE_NOT_FOUND)
-                {
-                    WARN("Loading of %s DLL %s failed (error %ld).\n",
-                         filetype, filename, GetLastError());
-                    break;
-                }
-	}
+    if (flags & LOAD_LIBRARY_AS_DATAFILE)
+    {
+        /* The method in load_library_as_datafile allows searching for the 
+         * 'native' libraries only 
+         */
+        if (load_library_as_datafile(libnameW, TRUE, &hModule))
+            return (HMODULE)((ULONG_PTR)hModule + 1);
+        flags |= DONT_RESOLVE_DLL_REFERENCES; /* Just in case */
+        /* Fallback to normal behaviour */
+    }
 
- error:
-        if (allocated_libdir)
-        {
-            HeapFree ( GetProcessHeap(), 0, (LPSTR)libdir );
-            libdir = NULL;
-        }
-        RtlLeaveCriticalSection( &loader_section );
-	WARN("Failed to load module '%s'; error=%ld\n", filename, GetLastError());
-	HeapFree ( GetProcessHeap(), 0, filename );
-	return NULL;
+    RtlInitUnicodeString( &wstr, libnameW );
+    nts = LdrLoadDll(NULL, flags, &wstr, &hModule);
+    if (nts != STATUS_SUCCESS)
+    {
+        hModule = 0;
+        SetLastError( RtlNtStatusToDosError( nts ) );
+    }
+    return hModule;
 }
 
 /***********************************************************************
  *           LoadLibraryA         (KERNEL32.@)
  */
-HMODULE WINAPI LoadLibraryA(LPCSTR libname) {
-	return LoadLibraryExA(libname,0,0);
+HMODULE WINAPI LoadLibraryA(LPCSTR libname)
+{
+    return LoadLibraryExA(libname, 0, 0);
 }
 
 /***********************************************************************
@@ -1302,7 +1129,7 @@
  */
 HMODULE WINAPI LoadLibraryW(LPCWSTR libnameW)
 {
-    return LoadLibraryExW(libnameW,0,0);
+    return LoadLibraryExW(libnameW, 0, 0);
 }
 
 /***********************************************************************
@@ -1321,18 +1148,6 @@
 }
 
 /***********************************************************************
- *           LoadLibraryExW       (KERNEL32.@)
- */
-HMODULE WINAPI LoadLibraryExW(LPCWSTR libnameW,HANDLE hfile,DWORD flags)
-{
-    LPSTR libnameA = HEAP_strdupWtoA( GetProcessHeap(), 0, libnameW );
-    HMODULE ret = LoadLibraryExA( libnameA , hfile, flags );
-
-    HeapFree( GetProcessHeap(), 0, libnameA );
-    return ret;
-}
-
-/***********************************************************************
  *           FreeLibrary   (KERNEL32.@)
  *           FreeLibrary32 (KERNEL.486)
  */
@@ -1341,6 +1156,12 @@
     BOOL                retv = FALSE;
     NTSTATUS            nts;
 
+    if (!hLibModule)
+    {
+        SetLastError( ERROR_INVALID_HANDLE );
+        return FALSE;
+    }
+
     if ((ULONG_PTR)hLibModule & 1)
     {
         /* this is a LOAD_LIBRARY_AS_DATAFILE module */
@@ -1348,13 +1169,6 @@
         UnmapViewOfFile( ptr );
         return TRUE;
     }
-    
-    if (!hLibModule)
-    {
-        SetLastError( ERROR_INVALID_HANDLE );
-        RtlLeaveCriticalSection( &loader_section );
-        return FALSE;
-    }
 
     if ((nts = LdrUnloadDll( hLibModule )) == STATUS_SUCCESS) retv = TRUE;
     else SetLastError( RtlNtStatusToDosError( nts ) );
@@ -1381,8 +1195,6 @@
     return LoadLibrary16(libname);
 }
 
-
-
 /***********************************************************************
  *           PrivateFreeLibrary       (KERNEL32.@)
  *
diff -u -x '*~' -x '.#*' loader4/pe_image.c loader/pe_image.c
--- loader4/pe_image.c	2003-03-07 05:14:23.000000000 +0100
+++ loader/pe_image.c	2003-03-07 13:08:53.000000000 +0100
@@ -257,7 +257,7 @@
 
     /* Allocate module dependency list */
     wm->nDeps = i;
-    wm->deps  = HeapAlloc( GetProcessHeap(), 0, i*sizeof(WINE_MODREF *) );
+    wm->deps  = RtlAllocateHeap( ntdll_get_process_heap(), 0, i*sizeof(WINE_MODREF *) );
 
     /* load the imported modules. They are automatically
      * added to the modref list of the process.
@@ -268,19 +268,24 @@
 	IMAGE_IMPORT_BY_NAME	*pe_name;
 	PIMAGE_THUNK_DATA	import_list,thunk_list;
  	char			*name = get_rva(wm->module, pe_imp->Name);
+        NTSTATUS                nts;
 
 	if (characteristics_detection && !pe_imp->u.Characteristics)
 		break;
 
-	wmImp = MODULE_LoadLibraryExA( name, 0, 0 );
-	if (!wmImp) {
-            if(GetLastError() == ERROR_FILE_NOT_FOUND)
-                ERR_(module)("Module (file) %s (which is needed by %s) not found\n", name, wm->filename);
-            else
-                ERR_(module)("Loading module (file) %s (which is needed by %s) failed (error %ld).\n",
-                        name, wm->filename, GetLastError());
+	nts = MODULE_LoadLibraryExA( name, 0, &wmImp );
+        switch (nts)
+        {
+        case STATUS_SUCCESS:
+            break;
+        case STATUS_NO_SUCH_FILE:
+            ERR_(module)("Module (file) %s (which is needed by %s) not found\n", name, wm->filename);
+            return 1;
+        default:
+            ERR_(module)("Loading module (file) %s (which is needed by %s) failed (error %ld).\n",
+                         name, wm->filename, GetLastError());
 	    return 1;
-	}
+        }
         wm->deps[i++] = wmImp;
 
 	/* FIXME: forwarder entries ... */
@@ -575,35 +580,38 @@
  * The PE Library Loader frontend.
  * FIXME: handle the flags.
  */
-WINE_MODREF *PE_LoadLibraryExA (LPCSTR name, DWORD flags)
+NTSTATUS PE_LoadLibraryExA (LPCSTR name, DWORD flags, WINE_MODREF** pwm)
 {
 	HMODULE		hModule32;
-	WINE_MODREF	*wm;
 	HANDLE		hFile;
 
 	hFile = CreateFileA( name, GENERIC_READ, FILE_SHARE_READ,
                              NULL, OPEN_EXISTING, 0, 0 );
-	if ( hFile == INVALID_HANDLE_VALUE ) return NULL;
+	if ( hFile == INVALID_HANDLE_VALUE ) 
+        {
+            /* keep it that way until we transform CreateFile into NtCreateFile */
+            return (GetLastError() == ERROR_FILE_NOT_FOUND) ? 
+                STATUS_NO_SUCH_FILE : STATUS_INTERNAL_ERROR;
+        }
 
 	/* Load PE module */
 	hModule32 = PE_LoadImage( hFile, name, flags );
 	if (!hModule32)
 	{
                 CloseHandle( hFile );
-		return NULL;
+		return STATUS_INTERNAL_ERROR;
 	}
 
 	/* Create 32-bit MODREF */
-	if ( !(wm = PE_CreateModule( hModule32, name, flags, hFile, FALSE )) )
+	if ( !(*pwm = PE_CreateModule( hModule32, name, flags, hFile, FALSE )) )
 	{
 		ERR( "can't load %s\n", name );
                 CloseHandle( hFile );
-		SetLastError( ERROR_OUTOFMEMORY );
-		return NULL;
+		return STATUS_NO_MEMORY; /* FIXME */
 	}
 
         CloseHandle( hFile );
-	return wm;
+	return STATUS_SUCCESS;
 }
 
 
diff -u -x '*~' -x '.#*' relay324/builtin32.c relay32/builtin32.c
--- relay324/builtin32.c	2003-03-13 21:07:56.000000000 +0100
+++ relay32/builtin32.c	2003-03-07 12:40:51.000000000 +0100
@@ -147,9 +147,8 @@
  * Partly copied from the original PE_ version.
  *
  */
-WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags)
+NTSTATUS BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags, WINE_MODREF** pwm)
 {
-    WINE_MODREF   *wm;
     char dllname[20], *p;
     LPCSTR name;
     void *handle;
@@ -159,29 +158,24 @@
     if ((p = strrchr( name, '\\' ))) name = p + 1;
     if ((p = strrchr( name, '/' ))) name = p + 1;
 
-    if (strlen(name) >= sizeof(dllname)-4) goto error;
+    if (strlen(name) >= sizeof(dllname)-4) return STATUS_NO_SUCH_FILE;
 
     strcpy( dllname, name );
     p = strrchr( dllname, '.' );
     if (!p) strcat( dllname, ".dll" );
     for (p = dllname; *p; p++) *p = FILE_tolower(*p);
 
-    if (!(handle = BUILTIN32_dlopen( dllname ))) goto error;
+    if (!(handle = BUILTIN32_dlopen( dllname ))) return STATUS_NO_SUCH_FILE;
 
-    if (!(wm = MODULE_FindModule( path ))) wm = MODULE_FindModule( dllname );
-    if (!wm)
+    if (!((*pwm) = MODULE_FindModule( path ))) *pwm = MODULE_FindModule( dllname );
+    if (!*pwm)
     {
         ERR( "loaded .so but dll %s still not found - 16-bit dll or version conflict.\n", dllname );
         /* wine_dll_unload( handle );*/
-        SetLastError( ERROR_BAD_EXE_FORMAT );
-        return NULL;
+        return STATUS_INVALID_IMAGE_FORMAT;
     }
-    wm->dlhandle = handle;
-    return wm;
-
- error:
-    SetLastError( ERROR_FILE_NOT_FOUND );
-    return NULL;
+    (*pwm)->dlhandle = handle;
+    return STATUS_SUCCESS;
 }
 
 /***********************************************************************


More information about the wine-patches mailing list