LoadLibraryEx handles LOAD_WITH_ALTERED_SEARCH_PATH
Medland, Bill
Bill.Medland at accpac.com
Tue Aug 14 14:53:14 CDT 2001
<<diff14.txt>>
-------------- next part --------------
Bill Medland (medbi01 at accpac.com)
Add handling of the LOAD_WITH_ALTERED_SEARCH_PATH to LoadLibraryEx
This implementation will not yet handle Windows DLLs loaded by a builtin DLL.
Index: wine/dlls/kernel/wowthunk.c
===================================================================
RCS file: /home/wine/wine/dlls/kernel/wowthunk.c,v
retrieving revision 1.16
diff -u -r1.16 wowthunk.c
--- wine/dlls/kernel/wowthunk.c 2001/07/25 00:43:30 1.16
+++ wine/dlls/kernel/wowthunk.c 2001/08/14 18:48:55
@@ -309,7 +309,7 @@
/* if the file can not be found, call LoadLibraryExA anyway, since it might be
a buildin module. This case is handled in MODULE_LoadLibraryExA */
- if ( ! DIR_SearchPath ( NULL, lpszLibFile, ".DLL", &full_name, FALSE ) ) {
+ if ( ! DIR_SearchPath ( NULL, lpszLibFile, ".DLL", &full_name, 0 ) ) {
strcpy ( full_name.short_name, lpszLibFile );
}
Index: wine/files/directory.c
===================================================================
RCS file: /home/wine/wine/files/directory.c,v
retrieving revision 1.40
diff -u -r1.40 directory.c
--- wine/files/directory.c 2001/07/02 19:59:48 1.40
+++ wine/files/directory.c 2001/08/14 18:48:55
@@ -565,17 +565,25 @@
/***********************************************************************
* DIR_SearchPath
*
- * Implementation of SearchPathA. 'win32' specifies whether the search
- * order is Win16 (module path last) or Win32 (module path first).
+ * Implementation of SearchPathA and similar functions.
+ * flags controls how the search is done.
+ * bit 0. specifies whether the search order is Win16 (module path last) or
+ * Win32 (module path first). (Win32 when set, Win16 when reset)
+ * bit 1. specifies whether the module path is the path of the application
+ * (as used in e.g. SearchPath) or the location of a DLL being
+ * loaded with LoadLibraryEx (..LOAD_WITH_ALTERED_SEARCH_PATH).
+ * When reset the application is used. When set the DLL location
+ * (passed in via the path) is used.
*
* FIXME: should return long path names.
*/
DWORD DIR_SearchPath( LPCSTR path, LPCSTR name, LPCSTR ext,
- DOS_FULL_NAME *full_name, BOOL win32 )
+ DOS_FULL_NAME *full_name, int flags )
{
LPCSTR p;
LPSTR tmp = NULL;
BOOL ret = TRUE;
+ BOOL win32 = flags & 0x01;
/* First check the supplied parameters */
@@ -615,12 +623,14 @@
if (path)
{
ret = DIR_TryEnvironmentPath( name, full_name, path );
- goto done;
+ if (!(flags & 0x02) || ret)
+ goto done;
}
/* Try the path of the current executable (for Win32 search order) */
- if (win32 && DIR_TryModulePath( name, full_name, win32 )) goto done;
+ if (win32 && !(flags & 0x02) &&
+ DIR_TryModulePath( name, full_name, win32 )) goto done;
/* Try the current directory */
@@ -649,6 +659,46 @@
return ret;
}
+/***********************************************************************
+ * SearchEitherPathA
+ *
+ * SearchPathA extended to allow searching by the alternate search path.
+ *
+ * Arguments are as for SearchPath except for the following:
+ *
+ * flags controls the order in which the directories are searched.
+ * If flags is 1 then the directories are searched as for SearchPath
+ * If flags is 3 then the directories are searched as for LoadLibraryEx
+ * with the LOAD_WITH_ALTERED_SEARCH_PATH, with the name of the DLL's
+ * directory being passed in through the path argument.
+ * For all other values the behaviour is undefined.
+ */
+
+DWORD WINAPI SearchEitherPathA( LPCSTR path, LPCSTR name, LPCSTR ext,
+ DWORD buflen, LPSTR buffer,
+ LPSTR *lastpart, int flags )
+{
+ LPSTR p, res;
+ DOS_FULL_NAME full_name;
+
+ if (!DIR_SearchPath( path, name, ext, &full_name, flags ))
+ {
+ SetLastError(ERROR_FILE_NOT_FOUND);
+ return 0;
+ }
+ lstrcpynA( buffer, full_name.short_name, buflen );
+ res = full_name.long_name +
+ strlen(DRIVE_GetRoot( full_name.short_name[0] - 'A' ));
+ while (*res == '/') res++;
+ if (buflen)
+ {
+ if (buflen > 3) lstrcpynA( buffer + 3, res, buflen - 3 );
+ for (p = buffer; *p; p++) if (*p == '/') *p = '\\';
+ if (lastpart) *lastpart = strrchr( buffer, '\\' ) + 1;
+ }
+ TRACE("Returning %d\n", strlen(res) + 3 );
+ return strlen(res) + 3;
+}
/***********************************************************************
* SearchPathA [KERNEL32.@]
@@ -679,31 +729,11 @@
* (tested on NT 4.0)
*/
DWORD WINAPI SearchPathA( LPCSTR path, LPCSTR name, LPCSTR ext, DWORD buflen,
- LPSTR buffer, LPSTR *lastpart )
+ LPSTR buffer, LPSTR *lastpart )
{
- LPSTR p, res;
- DOS_FULL_NAME full_name;
-
- if (!DIR_SearchPath( path, name, ext, &full_name, TRUE ))
- {
- SetLastError(ERROR_FILE_NOT_FOUND);
- return 0;
- }
- lstrcpynA( buffer, full_name.short_name, buflen );
- res = full_name.long_name +
- strlen(DRIVE_GetRoot( full_name.short_name[0] - 'A' ));
- while (*res == '/') res++;
- if (buflen)
- {
- if (buflen > 3) lstrcpynA( buffer + 3, res, buflen - 3 );
- for (p = buffer; *p; p++) if (*p == '/') *p = '\\';
- if (lastpart) *lastpart = strrchr( buffer, '\\' ) + 1;
- }
- TRACE("Returning %d\n", strlen(res) + 3 );
- return strlen(res) + 3;
+ return SearchEitherPathA (path, name, ext, buflen, buffer, lastpart, 0x01);
}
-
/***********************************************************************
* SearchPathW (KERNEL32.@)
*/
@@ -717,7 +747,7 @@
LPSTR pathA = HEAP_strdupWtoA( GetProcessHeap(), 0, path );
LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
LPSTR extA = HEAP_strdupWtoA( GetProcessHeap(), 0, ext );
- DWORD ret = DIR_SearchPath( pathA, nameA, extA, &full_name, TRUE );
+ DWORD ret = DIR_SearchPath( pathA, nameA, extA, &full_name, 0x01 );
HeapFree( GetProcessHeap(), 0, extA );
HeapFree( GetProcessHeap(), 0, nameA );
HeapFree( GetProcessHeap(), 0, pathA );
Index: wine/files/file.c
===================================================================
RCS file: /home/wine/wine/files/file.c,v
retrieving revision 1.106
diff -u -r1.106 file.c
--- wine/files/file.c 2001/07/23 18:09:41 1.106
+++ wine/files/file.c 2001/08/14 18:48:55
@@ -923,7 +923,7 @@
/* Now look for the file */
- if (!DIR_SearchPath( NULL, name, NULL, &full_name, win32 )) goto not_found;
+ if (!DIR_SearchPath( NULL, name, NULL, &full_name, win32 ? 1 : 0 )) goto not_found;
found:
TRACE("found %s = %s\n",
Index: wine/include/file.h
===================================================================
RCS file: /home/wine/wine/include/file.h,v
retrieving revision 1.28
diff -u -r1.28 file.h
--- wine/include/file.h 2001/07/12 22:29:42 1.28
+++ wine/include/file.h 2001/08/14 18:48:55
@@ -80,6 +80,9 @@
extern int DIR_Init(void);
extern UINT DIR_GetWindowsUnixDir( LPSTR path, UINT count );
extern UINT DIR_GetSystemUnixDir( LPSTR path, UINT count );
+DWORD WINAPI SearchEitherPathA( LPCSTR path, LPCSTR name, LPCSTR ext,
+ DWORD buflen, LPSTR buffer,
+ LPSTR *lastpart, int flags );
extern DWORD DIR_SearchPath( LPCSTR path, LPCSTR name, LPCSTR ext,
DOS_FULL_NAME *full_name, BOOL win32 );
Index: wine/include/module.h
===================================================================
RCS file: /home/wine/wine/include/module.h,v
retrieving revision 1.59
diff -u -r1.59 module.h
--- wine/include/module.h 2001/07/24 21:45:24 1.59
+++ wine/include/module.h 2001/08/14 18:48:55
@@ -179,7 +179,7 @@
extern void MODULE_DllProcessDetach( BOOL bForceDetach, LPVOID lpReserved );
extern void MODULE_DllThreadAttach( LPVOID lpReserved );
extern void MODULE_DllThreadDetach( LPVOID lpReserved );
-extern WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags );
+extern WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags, LPCSTR libdir );
extern BOOL MODULE_FreeLibrary( WINE_MODREF *wm );
extern WINE_MODREF *MODULE_FindModule( LPCSTR path );
extern HMODULE16 MODULE_CreateDummyModule( LPCSTR filename, HMODULE module32 );
@@ -228,12 +228,14 @@
extern HGLOBAL PE_LoadResource(HMODULE,HRSRC);
/* loader/pe_image.c */
-extern WINE_MODREF *PE_LoadLibraryExA(LPCSTR, DWORD);
+extern WINE_MODREF *PE_LoadLibraryExA(LPCSTR, DWORD, LPCSTR);
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 );
+ DWORD flags, HANDLE hFile, BOOL builtin,
+ LPCSTR libdir);
extern void PE_InitTls(void);
extern BOOL PE_InitDLL( HMODULE module, DWORD type, LPVOID lpReserved );
+extern DWORD PE_fixup_imports(WINE_MODREF *wm, LPCSTR libdir);
/* loader/loadorder.c */
extern void MODULE_InitLoadOrder(void);
@@ -241,7 +243,7 @@
extern void MODULE_AddLoadOrderOption( const char *option );
/* loader/elf.c */
-extern WINE_MODREF *ELF_LoadLibraryExA( LPCSTR libname, DWORD flags);
+extern WINE_MODREF *ELF_LoadLibraryExA( LPCSTR libname, DWORD flags, LPCSTR libdir);
/* relay32/builtin.c */
extern WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR name, DWORD flags);
Index: wine/loader/elf.c
===================================================================
RCS file: /home/wine/wine/loader/elf.c,v
retrieving revision 1.33
diff -u -r1.33 elf.c
--- wine/loader/elf.c 2001/07/24 21:45:24 1.33
+++ wine/loader/elf.c 2001/08/14 18:48:55
@@ -99,7 +99,12 @@
return hmod;
}
-WINE_MODREF *ELF_LoadLibraryExA( LPCSTR libname, DWORD flags)
+/*****************************************************************
+ * ELF_LoadLibraryExA
+ *
+ * libdir is carried around the recursion loop for MODULE_LoadLibraryExA
+ */
+WINE_MODREF *ELF_LoadLibraryExA( LPCSTR libname, DWORD flags, LPCSTR libdir)
{
WINE_MODREF *wm;
HMODULE hmod;
@@ -161,7 +166,7 @@
SNOOP_RegisterDLL(hmod,libname,0,STUBSIZE/sizeof(ELF_STDCALL_STUB));
- wm = PE_CreateModule( hmod, libname, 0, 0, FALSE );
+ wm = PE_CreateModule( hmod, libname, 0, 0, FALSE, libdir );
wm->find_export = ELF_FindExportedFunction;
wm->dlhandle = dlhandle;
return wm;
Index: wine/loader/module.c
===================================================================
RCS file: /home/wine/wine/loader/module.c,v
retrieving revision 1.137
diff -u -r1.137 module.c
--- wine/loader/module.c 2001/07/26 20:12:55 1.137
+++ wine/loader/module.c 2001/08/14 18:48:56
@@ -1299,7 +1299,7 @@
RtlAcquirePebLock();
- wm = MODULE_LoadLibraryExA( libname, hfile, flags );
+ wm = MODULE_LoadLibraryExA( libname, hfile, flags, NULL );
if ( wm )
{
if ( !MODULE_DllProcessAttach( wm, NULL ) )
@@ -1316,6 +1316,43 @@
}
/***********************************************************************
+ * AllocateLibdir
+ *
+ * helper for MODULE_LoadLibraryExA. Allocate space to hold the directory
+ * portion of the provided name and put the name in it.
+ *
+ */
+static LPCSTR AllocateLibdir (LPCSTR libname)
+{
+ LPCSTR p1, p2, p3, pmax;
+ LPSTR result;
+ int length;
+
+ p1 = strrchr (libname, '\\');
+ p2 = strrchr (libname, '/'); /* Naughty. MSDN says don't */
+ p3 = strrchr (libname, ':'); /* assert null or libname+1 */
+ /* assert (p1 || p2 || p3) */
+
+ /* assert null is less than all pointers */
+ pmax = p1;
+ if (p2 > pmax) pmax = p2;
+ if (p3 > pmax) pmax = p3;
+ /* assert pmax */
+
+ length = (pmax - libname)+1;
+
+ result = HeapAlloc (GetProcessHeap(), 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.
@@ -1325,8 +1362,12 @@
* ignore the parameter because it would be extremely difficult to
* integrate this with different types of module represenations.
*
+ * libdir is used to support LOAD_WITH_ALTERED_SEARCH_PATH during the recursion
+ * on this function. When called from LoadLibraryExA it will be NULL
+ * but thereafter it may point to a buffer containing the path portion
+ * of the library name.
*/
-WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags )
+WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags, LPCSTR libdir )
{
DWORD err = GetLastError();
WINE_MODREF *pwm;
@@ -1334,14 +1375,24 @@
enum loadorder_type loadorder[LOADORDER_NTYPES];
LPSTR filename, p;
const char *filetype = "";
+ BOOL allocated_libdir = FALSE;
if ( !libname ) return NULL;
filename = HeapAlloc ( GetProcessHeap(), 0, MAX_PATH + 1 );
if ( !filename ) return NULL;
+ if ((flags & LOAD_WITH_ALTERED_SEARCH_PATH) &&
+ ( strchr ( libname, '\\' ) || strchr ( libname, ':') ||
+ strchr ( libname, '/' ) ))
+ {
+ if (!(libdir = AllocateLibdir (libname))) goto error;
+ allocated_libdir = TRUE;
+ }
+
/* build the modules filename */
- if (!SearchPathA( NULL, libname, ".dll", MAX_PATH, filename, NULL ))
+ if (!SearchEitherPathA( libdir, libname, ".dll", MAX_PATH, filename,
+ NULL, libdir ? 0x03 : 0x01 ))
{
if ( ! GetSystemDirectoryA ( filename, MAX_PATH ) )
goto error;
@@ -1404,13 +1455,14 @@
if ((pwm->flags & WINE_MODREF_DONT_RESOLVE_REFS) &&
!(flags & DONT_RESOLVE_DLL_REFERENCES))
{
- extern DWORD fixup_imports(WINE_MODREF *wm); /*FIXME*/
pwm->flags &= ~WINE_MODREF_DONT_RESOLVE_REFS;
- fixup_imports( pwm );
+ PE_fixup_imports( pwm, libdir );
}
TRACE("Already loaded module '%s' at 0x%08x, count=%d, \n", filename, pwm->module, pwm->refCount);
RtlReleasePebLock();
HeapFree ( GetProcessHeap(), 0, filename );
+ if (allocated_libdir)
+ HeapFree ( GetProcessHeap(), 0, (LPSTR)libdir );
return pwm;
}
@@ -1425,13 +1477,13 @@
{
case LOADORDER_DLL:
TRACE("Trying native dll '%s'\n", filename);
- pwm = PE_LoadLibraryExA(filename, flags);
+ pwm = PE_LoadLibraryExA(filename, flags, libdir);
filetype = "native";
break;
case LOADORDER_SO:
TRACE("Trying so-library '%s'\n", filename);
- pwm = ELF_LoadLibraryExA(filename, flags);
+ pwm = ELF_LoadLibraryExA(filename, flags, libdir);
filetype = "so";
break;
@@ -1459,6 +1511,8 @@
RtlReleasePebLock();
SetLastError( err ); /* restore last error */
HeapFree ( GetProcessHeap(), 0, filename );
+ if (allocated_libdir)
+ HeapFree ( GetProcessHeap(), 0, (LPSTR)libdir );
return pwm;
}
@@ -1470,6 +1524,8 @@
error:
WARN("Failed to load module '%s'; error=0x%08lx, \n", filename, GetLastError());
HeapFree ( GetProcessHeap(), 0, filename );
+ if (allocated_libdir)
+ HeapFree ( GetProcessHeap(), 0, (LPSTR)libdir );
return NULL;
}
Index: wine/loader/pe_image.c
===================================================================
RCS file: /home/wine/wine/loader/pe_image.c,v
retrieving revision 1.97
diff -u -r1.97 pe_image.c
--- wine/loader/pe_image.c 2001/08/09 21:16:55 1.97
+++ wine/loader/pe_image.c 2001/08/14 18:48:56
@@ -17,7 +17,7 @@
* - If you want to enhance, speed up or clean up something in here, think
* twice WHY it is implemented in that strange way. There is usually a reason.
* Though sometimes it might just be lazyness ;)
- * - In PE_MapImage, right before fixup_imports() all external and internal
+ * - In PE_MapImage, right before PE_fixup_imports() all external and internal
* state MUST be correct since this function can be called with the SAME image
* AGAIN. (Thats recursion for you.) That means MODREF.module and
* NE_MODULE.module32.
@@ -242,7 +242,12 @@
}
}
-DWORD fixup_imports( WINE_MODREF *wm )
+/****************************************************************
+ * PE_fixup_imports
+ *
+ * libdir is carried around the recursion loop for MODULE_LoadLibraryExA
+ */
+DWORD PE_fixup_imports( WINE_MODREF *wm, LPCSTR libdir )
{
IMAGE_IMPORT_DESCRIPTOR *pe_imp;
unsigned int load_addr = wm->module;
@@ -286,7 +291,7 @@
if (characteristics_detection && !pe_imp->u.Characteristics)
break;
- wmImp = MODULE_LoadLibraryExA( name, 0, 0 );
+ wmImp = MODULE_LoadLibraryExA( name, 0, 0, libdir );
if (!wmImp) {
ERR_(module)("Module (file) %s needed by %s not found\n", name, wm->filename);
return 1;
@@ -525,9 +530,11 @@
* process that is to own the module to be created.
*
* Note: Assumes that the process critical section is held
+ *
+ * libdir is carried around the recursion loop for MODULE_LoadLibraryExA
*/
WINE_MODREF *PE_CreateModule( HMODULE hModule, LPCSTR filename, DWORD flags,
- HANDLE hFile, BOOL builtin )
+ HANDLE hFile, BOOL builtin, LPCSTR libdir )
{
DWORD load_addr = (DWORD)hModule; /* for RVA */
IMAGE_NT_HEADERS *nt = PE_HEADER(hModule);
@@ -633,7 +640,8 @@
/* Fixup Imports */
- if (!(wm->flags & WINE_MODREF_DONT_RESOLVE_REFS) && fixup_imports( wm ))
+ if (!(wm->flags & WINE_MODREF_DONT_RESOLVE_REFS) &&
+ PE_fixup_imports( wm, libdir ))
{
/* remove entry from modref chain */
@@ -681,8 +689,9 @@
/******************************************************************************
* The PE Library Loader frontend.
* FIXME: handle the flags.
+ * libdir is carried around the recursion loop for MODULE_LoadLibraryExA
*/
-WINE_MODREF *PE_LoadLibraryExA (LPCSTR name, DWORD flags)
+WINE_MODREF *PE_LoadLibraryExA (LPCSTR name, DWORD flags, LPCSTR libdir)
{
HMODULE hModule32;
WINE_MODREF *wm;
@@ -701,7 +710,7 @@
}
/* Create 32-bit MODREF */
- if ( !(wm = PE_CreateModule( hModule32, name, flags, hFile, FALSE )) )
+ if ( !(wm = PE_CreateModule( hModule32, name, flags, hFile, FALSE, libdir )) )
{
ERR( "can't load %s\n", name );
CloseHandle( hFile );
Index: wine/relay32/builtin32.c
===================================================================
RCS file: /home/wine/wine/relay32/builtin32.c,v
retrieving revision 1.81
diff -u -r1.81 builtin32.c
--- wine/relay32/builtin32.c 2001/07/25 00:43:36 1.81
+++ wine/relay32/builtin32.c 2001/08/14 18:48:56
@@ -87,7 +87,7 @@
MESSAGE( "Warning: loading builtin %s, but native version already present. Expect trouble.\n", filename );
/* Create 32-bit MODREF */
- if (!(wm = PE_CreateModule( module, filename, 0, 0, TRUE )))
+ if (!(wm = PE_CreateModule( module, filename, 0, 0, TRUE, NULL )))
{
ERR( "can't load %s\n", filename );
SetLastError( ERROR_OUTOFMEMORY );
Index: wine/scheduler/process.c
===================================================================
RCS file: /home/wine/wine/scheduler/process.c,v
retrieving revision 1.160
diff -u -r1.160 process.c
--- wine/scheduler/process.c 2001/08/06 17:48:17 1.160
+++ wine/scheduler/process.c 2001/08/14 18:48:56
@@ -353,7 +353,7 @@
if (!SIGNAL_Init()) goto error;
/* create the main modref and load dependencies */
- if (!(wm = PE_CreateModule( current_process.module, main_exe_name, 0, 0, FALSE )))
+ if (!(wm = PE_CreateModule( current_process.module, main_exe_name, 0, 0, FALSE, NULL )))
goto error;
wm->refCount++;
More information about the wine-patches
mailing list