Changed LdrLoadDll to only search for the dll in the specified path,
using ntdll functions. Moved LOAD_WITH_ALTERED_SEARCH_PATH functionality to LoadLibraryEx where it belongs.
This commit is contained in:
parent
33fee69bf4
commit
4137aecaa5
|
@ -125,6 +125,7 @@ extern BOOL build_command_line( char **argv );
|
|||
extern void RELAY_InitDebugLists(void);
|
||||
extern void SHELL_LoadRegistry(void);
|
||||
extern void VERSION_Init( const char *appname );
|
||||
extern void MODULE_InitLoadPath(void);
|
||||
|
||||
/***********************************************************************
|
||||
* get_basename
|
||||
|
@ -561,6 +562,9 @@ void __wine_process_init( int argc, char *argv[] )
|
|||
TRACE( "starting process name=%s file=%p argv[0]=%s\n",
|
||||
debugstr_a(main_exe_name), main_exe_file, debugstr_a(argv[0]) );
|
||||
|
||||
MODULE_InitLoadPath();
|
||||
VERSION_Init( main_exe_name );
|
||||
|
||||
if (!main_exe_file) /* no file handle -> Winelib app */
|
||||
{
|
||||
TRACE( "starting Winelib app %s\n", debugstr_a(main_exe_name) );
|
||||
|
@ -569,7 +573,6 @@ void __wine_process_init( int argc, char *argv[] )
|
|||
MESSAGE( "%s: cannot open builtin library for '%s': %s\n", argv0, main_exe_name, error );
|
||||
ExitProcess(1);
|
||||
}
|
||||
VERSION_Init( main_exe_name );
|
||||
|
||||
switch( MODULE_GetBinaryType( main_exe_file ))
|
||||
{
|
||||
|
|
|
@ -1109,44 +1109,13 @@ static void load_builtin_callback( void *module, const char *filename )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* 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 WCHAR *allocate_lib_dir(LPCWSTR libname)
|
||||
{
|
||||
LPCWSTR p, pmax;
|
||||
LPWSTR result;
|
||||
int length;
|
||||
|
||||
pmax = libname;
|
||||
if ((p = strrchrW( pmax, '\\' ))) pmax = p + 1;
|
||||
if ((p = strrchrW( pmax, '/' ))) pmax = p + 1; /* Naughty. MSDN says don't */
|
||||
if (pmax == libname && pmax[0] && pmax[1] == ':') pmax += 2;
|
||||
|
||||
length = pmax - libname;
|
||||
|
||||
result = RtlAllocateHeap (GetProcessHeap(), 0, (length+1) * sizeof(WCHAR) );
|
||||
|
||||
if (result)
|
||||
{
|
||||
memcpy( result, libname, length * sizeof(WCHAR) );
|
||||
result [length] = '\0';
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* load_native_dll (internal)
|
||||
*/
|
||||
static NTSTATUS load_native_dll( LPCWSTR name, DWORD flags, WINE_MODREF** pwm )
|
||||
static NTSTATUS load_native_dll( LPCWSTR name, HANDLE file, DWORD flags, WINE_MODREF** pwm )
|
||||
{
|
||||
void *module;
|
||||
HANDLE file, mapping;
|
||||
HANDLE mapping;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
LARGE_INTEGER size;
|
||||
IMAGE_NT_HEADERS *nt;
|
||||
|
@ -1155,14 +1124,6 @@ static NTSTATUS load_native_dll( LPCWSTR name, DWORD flags, WINE_MODREF** pwm )
|
|||
NTSTATUS status;
|
||||
UINT drive_type;
|
||||
|
||||
file = CreateFileW( name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
|
||||
if (file == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
/* keep it that way until we transform CreateFile into NtCreateFile */
|
||||
return (GetLastError() == ERROR_FILE_NOT_FOUND) ?
|
||||
STATUS_DLL_NOT_FOUND : STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
TRACE( "loading %s\n", debugstr_w(name) );
|
||||
|
||||
attr.Length = sizeof(attr);
|
||||
|
@ -1175,21 +1136,17 @@ static NTSTATUS load_native_dll( LPCWSTR name, DWORD flags, WINE_MODREF** pwm )
|
|||
|
||||
status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
|
||||
&attr, &size, 0, SEC_IMAGE, file );
|
||||
if (status != STATUS_SUCCESS) goto done;
|
||||
if (status != STATUS_SUCCESS) return status;
|
||||
|
||||
module = NULL;
|
||||
status = NtMapViewOfSection( mapping, GetCurrentProcess(),
|
||||
&module, 0, 0, &size, &len, ViewShare, 0, PAGE_READONLY );
|
||||
NtClose( mapping );
|
||||
if (status != STATUS_SUCCESS) goto done;
|
||||
if (status != STATUS_SUCCESS) return status;
|
||||
|
||||
/* create the MODREF */
|
||||
|
||||
if (!(wm = alloc_module( module, name )))
|
||||
{
|
||||
status = STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
if (!(wm = alloc_module( module, name ))) return STATUS_NO_MEMORY;
|
||||
|
||||
/* fixup imports */
|
||||
|
||||
|
@ -1208,7 +1165,7 @@ static NTSTATUS load_native_dll( LPCWSTR name, DWORD flags, WINE_MODREF** pwm )
|
|||
* around with no problems, so we don't care.
|
||||
* As these might reference our wm, we don't free it.
|
||||
*/
|
||||
goto done;
|
||||
return status;
|
||||
}
|
||||
}
|
||||
else wm->ldr.Flags |= LDR_DONT_RESOLVE_REFS;
|
||||
|
@ -1236,67 +1193,7 @@ static NTSTATUS load_native_dll( LPCWSTR name, DWORD flags, WINE_MODREF** pwm )
|
|||
if (TRACE_ON(snoop)) SNOOP_SetupDLL( module );
|
||||
|
||||
*pwm = wm;
|
||||
status = STATUS_SUCCESS;
|
||||
done:
|
||||
NtClose( file );
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* get_builtin_path
|
||||
*
|
||||
* Get the path of a builtin module when the native file does not exist.
|
||||
*/
|
||||
static BOOL get_builtin_path( const WCHAR *libname, WCHAR *filename, UINT size )
|
||||
{
|
||||
WCHAR *p;
|
||||
BOOL ret = FALSE;
|
||||
UINT len = GetSystemDirectoryW( filename, size );
|
||||
|
||||
if (contains_path( libname ))
|
||||
{
|
||||
WCHAR *tmp;
|
||||
|
||||
/* if the library name contains a path and can not be found,
|
||||
* return an error.
|
||||
* exception: if the path is the system directory, proceed,
|
||||
* so that modules which are not PE modules can be loaded.
|
||||
* If the library name does not contain a path and can not
|
||||
* be found, assume the system directory is meant */
|
||||
|
||||
if (strlenW(libname) >= size) return FALSE; /* too long */
|
||||
if (strchrW( libname, '/' )) /* need to convert slashes */
|
||||
{
|
||||
if (!(tmp = RtlAllocateHeap( GetProcessHeap(), 0,
|
||||
(strlenW(libname)+1) * sizeof(WCHAR) ))) return FALSE;
|
||||
strcpyW( tmp, libname );
|
||||
for (p = tmp; *p; p++) if (*p == '/') *p = '\\';
|
||||
}
|
||||
else tmp = (WCHAR *)libname;
|
||||
|
||||
if (!strncmpiW( filename, tmp, len ) && tmp[len] == '\\')
|
||||
{
|
||||
strcpyW( filename, tmp );
|
||||
ret = TRUE;
|
||||
}
|
||||
if (tmp != libname) RtlFreeHeap( GetProcessHeap(), 0, tmp );
|
||||
if (!ret) return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strlenW(libname) >= size - len - 1) return FALSE;
|
||||
filename[len] = '\\';
|
||||
strcpyW( filename+len+1, libname );
|
||||
}
|
||||
|
||||
/* if the filename doesn't have an extension, append ".dll" */
|
||||
if (!(p = strrchrW( filename, '.')) || strchrW( p, '/' ) || strchrW( p, '\\'))
|
||||
{
|
||||
if (strlenW(filename) + 3 >= size) return FALSE;
|
||||
strcatW( filename, dllW );
|
||||
}
|
||||
return TRUE;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1365,103 +1262,53 @@ static NTSTATUS load_builtin_dll( LPCWSTR path, DWORD flags, WINE_MODREF** pwm )
|
|||
* load_dll (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
|
||||
*
|
||||
* The loader_section must be locked while calling this function.
|
||||
*/
|
||||
static NTSTATUS load_dll( LPCWSTR libname, DWORD flags, WINE_MODREF** pwm )
|
||||
{
|
||||
int i;
|
||||
enum loadorder_type loadorder[LOADORDER_NTYPES];
|
||||
WCHAR *filename;
|
||||
WCHAR *filename, *file_part;
|
||||
const char *filetype = "";
|
||||
DWORD found;
|
||||
WINE_MODREF *main_exe;
|
||||
BOOL allocated_libdir = FALSE;
|
||||
static WCHAR *libdir = NULL; /* See above */
|
||||
HANDLE handle = INVALID_HANDLE_VALUE;
|
||||
NTSTATUS nts = STATUS_DLL_NOT_FOUND;
|
||||
const WCHAR *load_path;
|
||||
|
||||
*pwm = NULL;
|
||||
filename = RtlAllocateHeap ( GetProcessHeap(), 0, (MAX_PATH + 1) * sizeof(WCHAR) );
|
||||
filename = RtlAllocateHeap ( GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR) );
|
||||
if ( !filename ) return STATUS_NO_MEMORY;
|
||||
*filename = 0; /* Just in case we don't set it before goto error */
|
||||
|
||||
if ((flags & LOAD_WITH_ALTERED_SEARCH_PATH) && contains_path(libname))
|
||||
if (!(load_path = current_load_path))
|
||||
load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
|
||||
|
||||
TRACE( "looking for %s in %s\n", debugstr_w(libname), debugstr_w(load_path) );
|
||||
|
||||
if (RtlDosSearchPath_U( load_path, libname, dllW, MAX_PATH * sizeof(WCHAR), filename, &file_part ))
|
||||
{
|
||||
if (!(libdir = allocate_lib_dir(libname)))
|
||||
if ((*pwm = find_module( filename )) != NULL) goto found;
|
||||
|
||||
/* check for already loaded module in a different path */
|
||||
if (!contains_path( libname ))
|
||||
{
|
||||
nts = STATUS_NO_MEMORY;
|
||||
goto error;
|
||||
if ((*pwm = find_module( file_part )) != NULL) goto found;
|
||||
}
|
||||
allocated_libdir = TRUE;
|
||||
handle = CreateFileW( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
|
||||
}
|
||||
|
||||
if (!libdir || allocated_libdir)
|
||||
found = SearchPathW(NULL, libname, dllW, MAX_PATH, filename, NULL);
|
||||
else
|
||||
found = DIR_SearchAlternatePath(libdir, libname, dllW, MAX_PATH, filename);
|
||||
|
||||
/* build the modules filename */
|
||||
if (!found)
|
||||
else /* we didn't find the file */
|
||||
{
|
||||
if (!get_builtin_path( libname, filename, MAX_PATH ))
|
||||
if (contains_path( libname ))
|
||||
{
|
||||
nts = STATUS_INTERNAL_ERROR;
|
||||
goto error;
|
||||
RtlGetFullPathName_U( libname, MAX_PATH * sizeof(WCHAR), filename, &file_part );
|
||||
if ((*pwm = find_module( filename )) != NULL) goto found;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for already loaded module */
|
||||
if (!(*pwm = find_module(filename)) && !contains_path(libname))
|
||||
{
|
||||
LPWSTR fn = RtlAllocateHeap ( GetProcessHeap(), 0, (MAX_PATH + 1) * sizeof(WCHAR) );
|
||||
if (fn)
|
||||
else
|
||||
{
|
||||
/* 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)
|
||||
*/
|
||||
strcpyW ( fn, libname );
|
||||
/* if the filename doesn't have an extension append .DLL */
|
||||
if (!strrchrW( fn, '.')) strcatW( fn, dllW );
|
||||
if ((*pwm = find_module( fn )) != NULL)
|
||||
strcpyW( filename, fn );
|
||||
RtlFreeHeap( GetProcessHeap(), 0, fn );
|
||||
if ((*pwm = find_module( libname )) != NULL) goto found;
|
||||
strcpyW( filename, libname );
|
||||
file_part = filename;
|
||||
}
|
||||
}
|
||||
|
||||
if (*pwm)
|
||||
{
|
||||
if ((*pwm)->ldr.LoadCount != -1) (*pwm)->ldr.LoadCount++;
|
||||
|
||||
if (((*pwm)->ldr.Flags & LDR_DONT_RESOLVE_REFS) &&
|
||||
!(flags & DONT_RESOLVE_DLL_REFERENCES))
|
||||
{
|
||||
(*pwm)->ldr.Flags &= ~LDR_DONT_RESOLVE_REFS;
|
||||
fixup_imports( *pwm );
|
||||
}
|
||||
if (allocated_libdir)
|
||||
{
|
||||
RtlFreeHeap( GetProcessHeap(), 0, libdir );
|
||||
libdir = NULL;
|
||||
}
|
||||
TRACE("Already loaded module %s at %p, count=%d\n",
|
||||
debugstr_w(filename), (*pwm)->ldr.BaseAddress, (*pwm)->ldr.LoadCount);
|
||||
RtlFreeHeap( GetProcessHeap(), 0, filename );
|
||||
return STATUS_SUCCESS;
|
||||
if (!strchrW( file_part, '.' )) strcatW( file_part, dllW );
|
||||
}
|
||||
|
||||
main_exe = get_modref( NtCurrentTeb()->Peb->ImageBaseAddress );
|
||||
|
@ -1475,7 +1322,8 @@ static NTSTATUS load_dll( LPCWSTR libname, DWORD flags, WINE_MODREF** pwm )
|
|||
{
|
||||
case LOADORDER_DLL:
|
||||
TRACE("Trying native dll %s\n", debugstr_w(filename));
|
||||
nts = load_native_dll(filename, flags, pwm);
|
||||
if (handle != INVALID_HANDLE_VALUE)
|
||||
nts = load_native_dll(filename, handle, flags, pwm);
|
||||
filetype = "native";
|
||||
break;
|
||||
case LOADORDER_BI:
|
||||
|
@ -1498,33 +1346,32 @@ static NTSTATUS load_dll( LPCWSTR libname, DWORD flags, WINE_MODREF** pwm )
|
|||
/* Set the ldr.LoadCount here so that an attach failure will */
|
||||
/* decrement the dependencies through the MODULE_FreeLibrary call. */
|
||||
(*pwm)->ldr.LoadCount = 1;
|
||||
|
||||
if (allocated_libdir)
|
||||
{
|
||||
RtlFreeHeap( GetProcessHeap(), 0, libdir );
|
||||
libdir = NULL;
|
||||
}
|
||||
if (handle != INVALID_HANDLE_VALUE) NtClose( handle );
|
||||
RtlFreeHeap( GetProcessHeap(), 0, filename );
|
||||
return nts;
|
||||
}
|
||||
|
||||
if (nts != STATUS_DLL_NOT_FOUND)
|
||||
{
|
||||
WARN("Loading of %s DLL %s failed (status %lx).\n",
|
||||
filetype, debugstr_w(filename), nts);
|
||||
break;
|
||||
}
|
||||
if (nts != STATUS_DLL_NOT_FOUND) break;
|
||||
}
|
||||
|
||||
error:
|
||||
if (allocated_libdir)
|
||||
{
|
||||
RtlFreeHeap( GetProcessHeap(), 0, libdir );
|
||||
libdir = NULL;
|
||||
}
|
||||
WARN("Failed to load module %s; status=%lx\n", debugstr_w(filename), nts);
|
||||
WARN("Failed to load module %s; status=%lx\n", debugstr_w(libname), nts);
|
||||
if (handle != INVALID_HANDLE_VALUE) NtClose( handle );
|
||||
RtlFreeHeap( GetProcessHeap(), 0, filename );
|
||||
return nts;
|
||||
|
||||
found:
|
||||
if ((*pwm)->ldr.LoadCount != -1) (*pwm)->ldr.LoadCount++;
|
||||
|
||||
if (((*pwm)->ldr.Flags & LDR_DONT_RESOLVE_REFS) &&
|
||||
!(flags & DONT_RESOLVE_DLL_REFERENCES))
|
||||
{
|
||||
(*pwm)->ldr.Flags &= ~LDR_DONT_RESOLVE_REFS;
|
||||
fixup_imports( *pwm );
|
||||
}
|
||||
TRACE("Found loaded module %s for %s at %p, count=%d\n",
|
||||
debugstr_w((*pwm)->ldr.FullDllName.Buffer), debugstr_w(libname),
|
||||
(*pwm)->ldr.BaseAddress, (*pwm)->ldr.LoadCount);
|
||||
RtlFreeHeap( GetProcessHeap(), 0, filename );
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
|
|
|
@ -987,99 +987,3 @@ DWORD WINAPI SearchPathA( LPCSTR path, LPCSTR name, LPCSTR ext,
|
|||
RtlFreeUnicodeString(&extW);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* search_alternate_path
|
||||
*
|
||||
*
|
||||
* FIXME: should return long path names.?
|
||||
*/
|
||||
static BOOL search_alternate_path(LPCWSTR dll_path, LPCWSTR name, LPCWSTR ext,
|
||||
DOS_FULL_NAME *full_name)
|
||||
{
|
||||
LPCWSTR p;
|
||||
LPWSTR tmp = NULL;
|
||||
BOOL ret = TRUE;
|
||||
|
||||
/* First check the supplied parameters */
|
||||
|
||||
p = strrchrW( name, '.' );
|
||||
if (p && !strchrW( p, '/' ) && !strchrW( p, '\\' ))
|
||||
ext = NULL; /* Ignore the specified extension */
|
||||
|
||||
/* Allocate a buffer for the file name and extension */
|
||||
|
||||
if (ext)
|
||||
{
|
||||
DWORD len = strlenW(name) + strlenW(ext);
|
||||
if (!(tmp = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) )))
|
||||
{
|
||||
SetLastError( ERROR_OUTOFMEMORY );
|
||||
return 0;
|
||||
}
|
||||
strcpyW( tmp, name );
|
||||
strcatW( tmp, ext );
|
||||
name = tmp;
|
||||
}
|
||||
|
||||
if (DIR_TryEnvironmentPath (name, full_name, dll_path))
|
||||
;
|
||||
else if (DOSFS_GetFullName (name, TRUE, full_name)) /* current dir */
|
||||
;
|
||||
else if (DIR_TryPath (&DIR_System, name, full_name)) /* System dir */
|
||||
;
|
||||
else if (DIR_TryPath (&DIR_Windows, name, full_name)) /* Windows dir */
|
||||
;
|
||||
else
|
||||
ret = DIR_TryEnvironmentPath( name, full_name, NULL );
|
||||
|
||||
if (tmp) HeapFree( GetProcessHeap(), 0, tmp );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DIR_SearchAlternatePath
|
||||
*
|
||||
* Searches for a specified file in the search path.
|
||||
*
|
||||
* PARAMS
|
||||
* dll_path [I] Path to search
|
||||
* name [I] Filename to search for.
|
||||
* ext [I] File extension to append to file name. The first
|
||||
* character must be a period. This parameter is
|
||||
* specified only if the filename given does not
|
||||
* contain an extension.
|
||||
* buflen [I] size of buffer, in characters
|
||||
* buffer [O] buffer for found filename
|
||||
*
|
||||
* RETURNS
|
||||
* Success: length of string copied into buffer, not including
|
||||
* terminating null character. If the filename found is
|
||||
* longer than the length of the buffer, the length of the
|
||||
* filename is returned.
|
||||
* Failure: Zero
|
||||
*
|
||||
* NOTES
|
||||
* If the file is not found, calls SetLastError(ERROR_FILE_NOT_FOUND)
|
||||
*
|
||||
* FIXME: convert to unicode
|
||||
*/
|
||||
DWORD DIR_SearchAlternatePath( LPCWSTR dll_path, LPCWSTR name, LPCWSTR ext,
|
||||
DWORD buflen, LPWSTR buffer )
|
||||
{
|
||||
DOS_FULL_NAME full_name;
|
||||
DWORD ret = 0;
|
||||
|
||||
if (search_alternate_path( dll_path, name, ext, &full_name))
|
||||
{
|
||||
lstrcpynW( buffer, full_name.short_name, buflen );
|
||||
ret = strlenW(buffer);
|
||||
}
|
||||
else
|
||||
SetLastError(ERROR_FILE_NOT_FOUND);
|
||||
|
||||
TRACE("Returning %ld\n", ret );
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -91,8 +91,6 @@ extern LONG WINAPI WIN16_hread(HFILE16,SEGPTR,LONG);
|
|||
extern int DIR_Init(void);
|
||||
extern UINT DIR_GetWindowsUnixDir( LPSTR path, UINT count );
|
||||
extern UINT DIR_GetSystemUnixDir( LPSTR path, UINT count );
|
||||
extern DWORD DIR_SearchAlternatePath( LPCWSTR dll_path, LPCWSTR name, LPCWSTR ext,
|
||||
DWORD buflen, LPWSTR buffer);
|
||||
extern DWORD DIR_SearchPath( LPCWSTR path, LPCWSTR name, LPCWSTR ext,
|
||||
DOS_FULL_NAME *full_name, BOOL win32 );
|
||||
|
||||
|
|
198
loader/module.c
198
loader/module.c
|
@ -515,6 +515,125 @@ DWORD WINAPI GetModuleFileNameW( HMODULE hModule, LPWSTR lpFileName, DWORD size
|
|||
return strlenW(lpFileName);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* get_dll_system_path
|
||||
*/
|
||||
static const WCHAR *get_dll_system_path(void)
|
||||
{
|
||||
static WCHAR *path;
|
||||
|
||||
if (!path)
|
||||
{
|
||||
WCHAR *p, *exe_name;
|
||||
int len = 3;
|
||||
|
||||
exe_name = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer;
|
||||
if (!(p = strrchrW( exe_name, '\\' ))) p = exe_name;
|
||||
/* include trailing backslash only on drive root */
|
||||
if (p == exe_name + 2 && exe_name[1] == ':') p++;
|
||||
len += p - exe_name;
|
||||
len += GetSystemDirectoryW( NULL, 0 );
|
||||
len += GetWindowsDirectoryW( NULL, 0 );
|
||||
path = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
|
||||
memcpy( path, exe_name, (p - exe_name) * sizeof(WCHAR) );
|
||||
p = path + (p - exe_name);
|
||||
*p++ = ';';
|
||||
*p++ = '.';
|
||||
*p++ = ';';
|
||||
GetSystemDirectoryW( p, path + len - p);
|
||||
p += strlenW(p);
|
||||
*p++ = ';';
|
||||
GetWindowsDirectoryW( p, path + len - p);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* get_dll_load_path
|
||||
*
|
||||
* Compute the load path to use for a given dll.
|
||||
* Returned pointer must be freed by caller.
|
||||
*/
|
||||
static WCHAR *get_dll_load_path( LPCWSTR module )
|
||||
{
|
||||
static const WCHAR pathW[] = {'P','A','T','H',0};
|
||||
|
||||
const WCHAR *system_path = get_dll_system_path();
|
||||
const WCHAR *mod_end = NULL;
|
||||
UNICODE_STRING name, value;
|
||||
WCHAR *p, *ret;
|
||||
int len = 0, path_len = 0;
|
||||
|
||||
/* adjust length for module name */
|
||||
|
||||
if (module)
|
||||
{
|
||||
mod_end = module;
|
||||
if ((p = strrchrW( mod_end, '\\' ))) mod_end = p;
|
||||
if ((p = strrchrW( mod_end, '/' ))) mod_end = p;
|
||||
if (mod_end == module + 2 && module[1] == ':') mod_end++;
|
||||
if (mod_end == module && module[0] && module[1] == ':') mod_end += 2;
|
||||
len += (mod_end - module);
|
||||
system_path = strchrW( system_path, ';' );
|
||||
}
|
||||
len += strlenW( system_path ) + 2;
|
||||
|
||||
/* get the PATH variable */
|
||||
|
||||
RtlInitUnicodeString( &name, pathW );
|
||||
value.Length = 0;
|
||||
value.MaximumLength = 0;
|
||||
value.Buffer = NULL;
|
||||
if (RtlQueryEnvironmentVariable_U( NULL, &name, &value ) == STATUS_BUFFER_TOO_SMALL)
|
||||
path_len = value.Length;
|
||||
|
||||
if (!(ret = HeapAlloc( GetProcessHeap(), 0, path_len + len * sizeof(WCHAR) ))) return NULL;
|
||||
p = ret;
|
||||
if (module)
|
||||
{
|
||||
memcpy( ret, module, (mod_end - module) * sizeof(WCHAR) );
|
||||
p += (mod_end - module);
|
||||
}
|
||||
strcpyW( p, system_path );
|
||||
p += strlenW(p);
|
||||
*p++ = ';';
|
||||
value.Buffer = p;
|
||||
value.MaximumLength = path_len;
|
||||
|
||||
while (RtlQueryEnvironmentVariable_U( NULL, &name, &value ) == STATUS_BUFFER_TOO_SMALL)
|
||||
{
|
||||
WCHAR *new_ptr;
|
||||
|
||||
/* grow the buffer and retry */
|
||||
path_len = value.Length;
|
||||
if (!(new_ptr = HeapReAlloc( GetProcessHeap(), 0, ret, path_len + len * sizeof(WCHAR) )))
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, ret );
|
||||
return NULL;
|
||||
}
|
||||
value.Buffer = new_ptr + (value.Buffer - ret);
|
||||
value.MaximumLength = path_len;
|
||||
ret = new_ptr;
|
||||
}
|
||||
value.Buffer[value.Length / sizeof(WCHAR)] = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* MODULE_InitLoadPath
|
||||
*
|
||||
* Create the initial dll load path.
|
||||
*/
|
||||
void MODULE_InitLoadPath(void)
|
||||
{
|
||||
WCHAR *path = get_dll_load_path( NULL );
|
||||
RtlInitUnicodeString( &NtCurrentTeb()->Peb->ProcessParameters->DllPath, path );
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* load_library_as_datafile
|
||||
*/
|
||||
|
@ -555,6 +674,40 @@ static BOOL load_library_as_datafile( LPCWSTR name, HMODULE* hmod)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* load_library
|
||||
*
|
||||
* Helper for LoadLibraryExA/W.
|
||||
*/
|
||||
static HMODULE load_library( const UNICODE_STRING *libname, DWORD flags )
|
||||
{
|
||||
NTSTATUS nts;
|
||||
HMODULE hModule;
|
||||
WCHAR *load_path;
|
||||
|
||||
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->Buffer, &hModule )) return hModule;
|
||||
flags |= DONT_RESOLVE_DLL_REFERENCES; /* Just in case */
|
||||
/* Fallback to normal behaviour */
|
||||
}
|
||||
|
||||
load_path = get_dll_load_path( flags & LOAD_WITH_ALTERED_SEARCH_PATH ? libname->Buffer : NULL );
|
||||
nts = LdrLoadDll( load_path, flags, libname, &hModule );
|
||||
HeapFree( GetProcessHeap(), 0, load_path );
|
||||
if (nts != STATUS_SUCCESS)
|
||||
{
|
||||
hModule = 0;
|
||||
SetLastError( RtlNtStatusToDosError( nts ) );
|
||||
}
|
||||
return hModule;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* LoadLibraryExA (KERNEL32.@)
|
||||
*
|
||||
|
@ -578,7 +731,6 @@ static BOOL load_library_as_datafile( LPCWSTR name, HMODULE* hmod)
|
|||
HMODULE WINAPI LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags)
|
||||
{
|
||||
UNICODE_STRING wstr;
|
||||
NTSTATUS nts;
|
||||
HMODULE hModule;
|
||||
|
||||
if (!libname)
|
||||
|
@ -587,29 +739,8 @@ HMODULE WINAPI LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags)
|
|||
return 0;
|
||||
}
|
||||
RtlCreateUnicodeStringFromAsciiz( &wstr, libname );
|
||||
|
||||
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( wstr.Buffer, &hModule))
|
||||
{
|
||||
RtlFreeUnicodeString( &wstr );
|
||||
return hModule;
|
||||
}
|
||||
flags |= DONT_RESOLVE_DLL_REFERENCES; /* Just in case */
|
||||
/* Fallback to normal behaviour */
|
||||
}
|
||||
|
||||
nts = LdrLoadDll(NULL, flags, &wstr, &hModule);
|
||||
if (nts != STATUS_SUCCESS)
|
||||
{
|
||||
hModule = 0;
|
||||
SetLastError( RtlNtStatusToDosError( nts ) );
|
||||
}
|
||||
hModule = load_library( &wstr, flags );
|
||||
RtlFreeUnicodeString( &wstr );
|
||||
|
||||
return hModule;
|
||||
}
|
||||
|
||||
|
@ -621,33 +752,14 @@ HMODULE WINAPI LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags)
|
|||
HMODULE WINAPI LoadLibraryExW(LPCWSTR libnameW, HANDLE hfile, DWORD flags)
|
||||
{
|
||||
UNICODE_STRING wstr;
|
||||
NTSTATUS nts;
|
||||
HMODULE hModule;
|
||||
|
||||
if (!libnameW)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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, &hModule)) return hModule;
|
||||
flags |= DONT_RESOLVE_DLL_REFERENCES; /* Just in case */
|
||||
/* Fallback to normal behaviour */
|
||||
}
|
||||
|
||||
RtlInitUnicodeString( &wstr, libnameW );
|
||||
nts = LdrLoadDll(NULL, flags, &wstr, &hModule);
|
||||
if (nts != STATUS_SUCCESS)
|
||||
{
|
||||
hModule = 0;
|
||||
SetLastError( RtlNtStatusToDosError( nts ) );
|
||||
}
|
||||
return hModule;
|
||||
return load_library( &wstr, flags );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
Loading…
Reference in New Issue