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