Removed references to GetSystemDirectoryW.

Optimized module lookup a bit.
Keep track of the modref pointer across builtin dll loads to avoid
having to look it up by name afterwards.
This commit is contained in:
Alexandre Julliard 2003-10-07 22:56:34 +00:00
parent 7e0ddbc60f
commit 146afcc98c
3 changed files with 156 additions and 93 deletions

View File

@ -73,10 +73,23 @@ typedef struct _wine_modref
struct _wine_modref **deps; struct _wine_modref **deps;
} WINE_MODREF; } WINE_MODREF;
/* info about the current builtin dll load */
/* used to keep track of things across the register_dll constructor call */
struct builtin_load_info
{
const WCHAR *load_path;
NTSTATUS status;
WINE_MODREF *wm;
};
static struct builtin_load_info *builtin_load_info;
static UINT tls_module_count; /* number of modules with TLS directory */ static UINT tls_module_count; /* number of modules with TLS directory */
static UINT tls_total_size; /* total size of TLS storage */ static UINT tls_total_size; /* total size of TLS storage */
static const IMAGE_TLS_DIRECTORY **tls_dirs; /* array of TLS directories */ static const IMAGE_TLS_DIRECTORY **tls_dirs; /* array of TLS directories */
static UNICODE_STRING system_dir; /* system directory */
static CRITICAL_SECTION loader_section; static CRITICAL_SECTION loader_section;
static CRITICAL_SECTION_DEBUG critsect_debug = static CRITICAL_SECTION_DEBUG critsect_debug =
{ {
@ -88,10 +101,8 @@ static CRITICAL_SECTION loader_section = { &critsect_debug, -1, 0, 0, 0, 0 };
static WINE_MODREF *cached_modref; static WINE_MODREF *cached_modref;
static WINE_MODREF *current_modref; static WINE_MODREF *current_modref;
static NTSTATUS last_builtin_status; /* use to gather all errors in callback */
static const WCHAR *current_load_path;
static NTSTATUS load_dll( LPCWSTR libname, DWORD flags, WINE_MODREF** pwm ); static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_MODREF** pwm );
static FARPROC find_named_export( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports, static FARPROC find_named_export( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports,
DWORD exp_size, const char *name, int hint ); DWORD exp_size, const char *name, int hint );
@ -139,47 +150,56 @@ static WINE_MODREF *get_modref( HMODULE hmod )
/********************************************************************** /**********************************************************************
* find_module * find_basename_module
*
* Find a (loaded) win32 module depending on path
* path: [in] pathname of module/library to be found
* *
* Find a module from its base name.
* The loader_section must be locked while calling this function * The loader_section must be locked while calling this function
* RETURNS
* the module handle if found
* 0 if not
*/ */
static WINE_MODREF *find_module( LPCWSTR path ) static WINE_MODREF *find_basename_module( LPCWSTR name )
{ {
WINE_MODREF *wm;
PLIST_ENTRY mark, entry; PLIST_ENTRY mark, entry;
PLDR_MODULE mod;
WCHAR dllname[260], *p;
/* Append .DLL to name if no extension present */ if (cached_modref && !strcmpiW( name, cached_modref->ldr.BaseDllName.Buffer ))
strcpyW( dllname, path ); return cached_modref;
if (!(p = strrchrW( dllname, '.')) || strchrW( p, '/' ) || strchrW( p, '\\'))
strcatW( dllname, dllW );
if ((wm = cached_modref) != NULL)
{
if ( !strcmpiW( dllname, wm->ldr.BaseDllName.Buffer ) ) return wm;
if ( !strcmpiW( dllname, wm->ldr.FullDllName.Buffer ) ) return wm;
}
mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList; mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
for (entry = mark->Flink; entry != mark; entry = entry->Flink) for (entry = mark->Flink; entry != mark; entry = entry->Flink)
{ {
mod = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList); LDR_MODULE *mod = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList);
wm = CONTAINING_RECORD(mod, WINE_MODREF, ldr); if (!strcmpiW( name, mod->BaseDllName.Buffer ))
{
if ( !strcmpiW( dllname, wm->ldr.BaseDllName.Buffer ) ) break; cached_modref = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
if ( !strcmpiW( dllname, wm->ldr.FullDllName.Buffer ) ) break; return cached_modref;
}
} }
if (entry == mark) wm = NULL; return NULL;
}
cached_modref = wm;
return wm; /**********************************************************************
* find_fullname_module
*
* Find a module from its full path name.
* The loader_section must be locked while calling this function
*/
static WINE_MODREF *find_fullname_module( LPCWSTR name )
{
PLIST_ENTRY mark, entry;
if (cached_modref && !strcmpiW( name, cached_modref->ldr.FullDllName.Buffer ))
return cached_modref;
mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
for (entry = mark->Flink; entry != mark; entry = entry->Flink)
{
LDR_MODULE *mod = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList);
if (!strcmpiW( name, mod->FullDllName.Buffer ))
{
cached_modref = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
return cached_modref;
}
}
return NULL;
} }
@ -194,16 +214,16 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward )
IMAGE_EXPORT_DIRECTORY *exports; IMAGE_EXPORT_DIRECTORY *exports;
DWORD exp_size; DWORD exp_size;
WINE_MODREF *wm; WINE_MODREF *wm;
WCHAR mod_name[256]; WCHAR mod_name[32];
char *end = strchr(forward, '.'); char *end = strchr(forward, '.');
FARPROC proc = NULL; FARPROC proc = NULL;
if (!end) return NULL; if (!end) return NULL;
if (end - forward >= sizeof(mod_name)/sizeof(WCHAR)) return NULL; if ((end - forward) * sizeof(WCHAR) >= sizeof(mod_name) - sizeof(dllW)) return NULL;
ascii_to_unicode( mod_name, forward, end - forward ); ascii_to_unicode( mod_name, forward, end - forward );
mod_name[end - forward] = 0; memcpy( mod_name + (end - forward), dllW, sizeof(dllW) );
if (!(wm = find_module( mod_name ))) if (!(wm = find_basename_module( mod_name )))
{ {
ERR("module not found for forward '%s' used by %s\n", ERR("module not found for forward '%s' used by %s\n",
forward, debugstr_w(get_modref(module)->ldr.FullDllName.Buffer) ); forward, debugstr_w(get_modref(module)->ldr.FullDllName.Buffer) );
@ -305,7 +325,7 @@ static FARPROC find_named_export( HMODULE module, IMAGE_EXPORT_DIRECTORY *export
* Import the dll specified by the given import descriptor. * Import the dll specified by the given import descriptor.
* The loader_section must be locked while calling this function. * The loader_section must be locked while calling this function.
*/ */
static WINE_MODREF *import_dll( HMODULE module, IMAGE_IMPORT_DESCRIPTOR *descr ) static WINE_MODREF *import_dll( HMODULE module, IMAGE_IMPORT_DESCRIPTOR *descr, LPCWSTR load_path )
{ {
NTSTATUS status; NTSTATUS status;
WINE_MODREF *wmImp; WINE_MODREF *wmImp;
@ -320,14 +340,14 @@ static WINE_MODREF *import_dll( HMODULE module, IMAGE_IMPORT_DESCRIPTOR *descr )
if (len * sizeof(WCHAR) <= sizeof(buffer)) if (len * sizeof(WCHAR) <= sizeof(buffer))
{ {
ascii_to_unicode( buffer, name, len ); ascii_to_unicode( buffer, name, len );
status = load_dll( buffer, 0, &wmImp ); status = load_dll( load_path, buffer, 0, &wmImp );
} }
else /* need to allocate a larger buffer */ else /* need to allocate a larger buffer */
{ {
WCHAR *ptr = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) ); WCHAR *ptr = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) );
if (!ptr) return NULL; if (!ptr) return NULL;
ascii_to_unicode( ptr, name, len ); ascii_to_unicode( ptr, name, len );
status = load_dll( ptr, 0, &wmImp ); status = load_dll( load_path, ptr, 0, &wmImp );
RtlFreeHeap( GetProcessHeap(), 0, ptr ); RtlFreeHeap( GetProcessHeap(), 0, ptr );
} }
@ -396,7 +416,7 @@ static WINE_MODREF *import_dll( HMODULE module, IMAGE_IMPORT_DESCRIPTOR *descr )
* Fixup all imports of a given module. * Fixup all imports of a given module.
* The loader_section must be locked while calling this function. * The loader_section must be locked while calling this function.
*/ */
static NTSTATUS fixup_imports( WINE_MODREF *wm ) static NTSTATUS fixup_imports( WINE_MODREF *wm, LPCWSTR load_path )
{ {
int i, nb_imports; int i, nb_imports;
IMAGE_IMPORT_DESCRIPTOR *imports; IMAGE_IMPORT_DESCRIPTOR *imports;
@ -429,7 +449,7 @@ static NTSTATUS fixup_imports( WINE_MODREF *wm )
current_modref = wm; current_modref = wm;
for (i = 0; i < nb_imports; i++) for (i = 0; i < nb_imports; i++)
{ {
if (!(wm->deps[i] = import_dll( wm->ldr.BaseAddress, &imports[i] ))) break; if (!(wm->deps[i] = import_dll( wm->ldr.BaseAddress, &imports[i], load_path ))) break;
} }
current_modref = prev; current_modref = prev;
if (i < nb_imports) return STATUS_DLL_NOT_FOUND; if (i < nb_imports) return STATUS_DLL_NOT_FOUND;
@ -1012,7 +1032,6 @@ static void load_builtin_callback( void *module, const char *filename )
IMAGE_NT_HEADERS *nt; IMAGE_NT_HEADERS *nt;
WINE_MODREF *wm; WINE_MODREF *wm;
WCHAR *fullname, *p; WCHAR *fullname, *p;
DWORD len;
if (!module) if (!module)
{ {
@ -1022,7 +1041,7 @@ static void load_builtin_callback( void *module, const char *filename )
if (!(nt = RtlImageNtHeader( module ))) if (!(nt = RtlImageNtHeader( module )))
{ {
ERR( "bad module for %s\n", filename ? filename : "main exe" ); ERR( "bad module for %s\n", filename ? filename : "main exe" );
last_builtin_status = STATUS_INVALID_IMAGE_FORMAT; builtin_load_info->status = STATUS_INVALID_IMAGE_FORMAT;
return; return;
} }
if (!(nt->FileHeader.Characteristics & IMAGE_FILE_DLL)) if (!(nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
@ -1035,16 +1054,16 @@ static void load_builtin_callback( void *module, const char *filename )
/* create the MODREF */ /* create the MODREF */
len = GetSystemDirectoryW( NULL, 0 );
if (!(fullname = RtlAllocateHeap( GetProcessHeap(), 0, if (!(fullname = RtlAllocateHeap( GetProcessHeap(), 0,
(len + strlen(filename) + 1) * sizeof(WCHAR) ))) system_dir.MaximumLength + (strlen(filename) + 1) * sizeof(WCHAR) )))
{ {
ERR( "can't load %s\n", filename ); ERR( "can't load %s\n", filename );
last_builtin_status = STATUS_NO_MEMORY; builtin_load_info->status = STATUS_NO_MEMORY;
return; return;
} }
p = fullname + GetSystemDirectoryW( fullname, len ); memcpy( fullname, system_dir.Buffer, system_dir.Length );
*p++ = '\\'; p = fullname + system_dir.Length / sizeof(WCHAR);
if (p > fullname && p[-1] != '\\') *p++ = '\\';
ascii_to_unicode( p, filename, strlen(filename) + 1 ); ascii_to_unicode( p, filename, strlen(filename) + 1 );
wm = alloc_module( module, fullname ); wm = alloc_module( module, fullname );
@ -1052,22 +1071,23 @@ static void load_builtin_callback( void *module, const char *filename )
if (!wm) if (!wm)
{ {
ERR( "can't load %s\n", filename ); ERR( "can't load %s\n", filename );
last_builtin_status = STATUS_NO_MEMORY; builtin_load_info->status = STATUS_NO_MEMORY;
return; return;
} }
wm->ldr.Flags |= LDR_WINE_INTERNAL; wm->ldr.Flags |= LDR_WINE_INTERNAL;
/* fixup imports */ /* fixup imports */
if (fixup_imports( wm ) != STATUS_SUCCESS) if (fixup_imports( wm, builtin_load_info->load_path ) != STATUS_SUCCESS)
{ {
/* the module has only be inserted in the load & memory order lists */ /* the module has only be inserted in the load & memory order lists */
RemoveEntryList(&wm->ldr.InLoadOrderModuleList); RemoveEntryList(&wm->ldr.InLoadOrderModuleList);
RemoveEntryList(&wm->ldr.InMemoryOrderModuleList); RemoveEntryList(&wm->ldr.InMemoryOrderModuleList);
/* FIXME: free the modref */ /* FIXME: free the modref */
last_builtin_status = STATUS_DLL_NOT_FOUND; builtin_load_info->status = STATUS_DLL_NOT_FOUND;
return; return;
} }
builtin_load_info->wm = wm;
TRACE( "loaded %s %p %p\n", filename, wm, module ); TRACE( "loaded %s %p %p\n", filename, wm, module );
/* send the DLL load event */ /* send the DLL load event */
@ -1093,7 +1113,8 @@ static void load_builtin_callback( void *module, const char *filename )
/****************************************************************************** /******************************************************************************
* load_native_dll (internal) * load_native_dll (internal)
*/ */
static NTSTATUS load_native_dll( LPCWSTR name, HANDLE file, DWORD flags, WINE_MODREF** pwm ) static NTSTATUS load_native_dll( LPCWSTR load_path, LPCWSTR name, HANDLE file,
DWORD flags, WINE_MODREF** pwm )
{ {
void *module; void *module;
HANDLE mapping; HANDLE mapping;
@ -1133,7 +1154,7 @@ static NTSTATUS load_native_dll( LPCWSTR name, HANDLE file, DWORD flags, WINE_MO
if (!(flags & DONT_RESOLVE_DLL_REFERENCES)) if (!(flags & DONT_RESOLVE_DLL_REFERENCES))
{ {
if ((status = fixup_imports(wm)) != STATUS_SUCCESS) if ((status = fixup_imports( wm, load_path )) != STATUS_SUCCESS)
{ {
/* the module has only be inserted in the load & memory order lists */ /* the module has only be inserted in the load & memory order lists */
RemoveEntryList(&wm->ldr.InLoadOrderModuleList); RemoveEntryList(&wm->ldr.InLoadOrderModuleList);
@ -1181,14 +1202,14 @@ static NTSTATUS load_native_dll( LPCWSTR name, HANDLE file, DWORD flags, WINE_MO
/*********************************************************************** /***********************************************************************
* load_builtin_dll * load_builtin_dll
*/ */
static NTSTATUS load_builtin_dll( LPCWSTR path, DWORD flags, WINE_MODREF** pwm ) static NTSTATUS load_builtin_dll( LPCWSTR load_path, LPCWSTR path, DWORD flags, WINE_MODREF** pwm )
{ {
char error[256], dllname[MAX_PATH]; char error[256], dllname[MAX_PATH];
int file_exists; int file_exists;
const WCHAR *name, *p; const WCHAR *name, *p;
DWORD len, i; DWORD len, i;
void *handle; void *handle;
WINE_MODREF *wm; struct builtin_load_info info, *prev_info;
/* Fix the name in case we have a full path and extension */ /* Fix the name in case we have a full path and extension */
name = path; name = path;
@ -1205,13 +1226,20 @@ static NTSTATUS load_builtin_dll( LPCWSTR path, DWORD flags, WINE_MODREF** pwm )
if (dllname[i] >= 'A' && dllname[i] <= 'Z') dllname[i] += 'a' - 'A'; if (dllname[i] >= 'A' && dllname[i] <= 'Z') dllname[i] += 'a' - 'A';
} }
last_builtin_status = STATUS_SUCCESS; /* load_library will modify info.status. Note also that load_library can be
/* load_library will modify last_builtin_status. Note also that load_library can be
* called several times, if the .so file we're loading has dependencies. * called several times, if the .so file we're loading has dependencies.
* last_builtin_status will gather all the errors we may get while loading all these * info.status will gather all the errors we may get while loading all these
* libraries * libraries
*/ */
if (!(handle = wine_dll_load( dllname, error, sizeof(error), &file_exists ))) info.load_path = load_path;
info.status = STATUS_SUCCESS;
info.wm = NULL;
prev_info = builtin_load_info;
builtin_load_info = &info;
handle = wine_dll_load( dllname, error, sizeof(error), &file_exists );
builtin_load_info = prev_info;
if (!handle)
{ {
if (!file_exists) if (!file_exists)
{ {
@ -1223,18 +1251,25 @@ static NTSTATUS load_builtin_dll( LPCWSTR path, DWORD flags, WINE_MODREF** pwm )
ERR("failed to load .so lib for builtin %s: %s\n", debugstr_w(name), error ); ERR("failed to load .so lib for builtin %s: %s\n", debugstr_w(name), error );
return STATUS_PROCEDURE_NOT_FOUND; return STATUS_PROCEDURE_NOT_FOUND;
} }
if (last_builtin_status != STATUS_SUCCESS) return last_builtin_status; if (info.status != STATUS_SUCCESS) return info.status;
if (!(wm = find_module( path ))) wm = find_module( name ); if (!info.wm)
if (!wm)
{ {
ERR( "loaded .so but dll %s still not found - 16-bit dll or version conflict.\n", /* The constructor wasn't called, this means the .so is already
debugstr_w(name) ); * loaded under a different name. We can't support multiple names
* for the same module, so return an error. */
return STATUS_INVALID_IMAGE_FORMAT;
}
info.wm->ldr.SectionHandle = handle;
if (strcmpiW( info.wm->ldr.BaseDllName.Buffer, name ))
{
ERR( "loaded .so for %s but got %s instead - probably 16-bit dll\n",
debugstr_w(name), debugstr_w(info.wm->ldr.BaseDllName.Buffer) );
/* wine_dll_unload( handle );*/ /* wine_dll_unload( handle );*/
return STATUS_INVALID_IMAGE_FORMAT; return STATUS_INVALID_IMAGE_FORMAT;
} }
wm->ldr.SectionHandle = handle; *pwm = info.wm;
*pwm = wm;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -1275,12 +1310,12 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname,
*size = len + sizeof(WCHAR); *size = len + sizeof(WCHAR);
return STATUS_BUFFER_TOO_SMALL; return STATUS_BUFFER_TOO_SMALL;
} }
if ((*pwm = find_module( filename )) != NULL) return STATUS_SUCCESS; if ((*pwm = find_fullname_module( filename )) != NULL) return STATUS_SUCCESS;
/* check for already loaded module in a different path */ /* check for already loaded module in a different path */
if (!contains_path( libname )) if (!contains_path( libname ))
{ {
if ((*pwm = find_module( file_part )) != NULL) return STATUS_SUCCESS; if ((*pwm = find_basename_module( file_part )) != NULL) return STATUS_SUCCESS;
} }
*handle = CreateFileW( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); *handle = CreateFileW( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -1301,7 +1336,7 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname,
if (len >= *size) goto overflow; if (len >= *size) goto overflow;
strcatW( filename, dllW ); strcatW( filename, dllW );
} }
*pwm = find_module( filename ); *pwm = find_basename_module( filename );
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
} }
@ -1316,7 +1351,7 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname,
if (len >= *size) goto overflow; if (len >= *size) goto overflow;
strcatW( file_part, dllW ); strcatW( file_part, dllW );
} }
if ((*pwm = find_module( filename )) != NULL) return STATUS_SUCCESS; if ((*pwm = find_fullname_module( filename )) != NULL) return STATUS_SUCCESS;
*handle = CreateFileW( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); *handle = CreateFileW( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -1332,7 +1367,7 @@ overflow:
* Load a PE style module according to the load order. * Load a PE style module according to the load order.
* The loader_section must be locked while calling this function. * The loader_section must be locked while calling this function.
*/ */
static NTSTATUS load_dll( LPCWSTR libname, DWORD flags, WINE_MODREF** pwm ) static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_MODREF** pwm )
{ {
int i; int i;
enum loadorder_type loadorder[LOADORDER_NTYPES]; enum loadorder_type loadorder[LOADORDER_NTYPES];
@ -1343,10 +1378,6 @@ static NTSTATUS load_dll( LPCWSTR libname, DWORD flags, WINE_MODREF** pwm )
WINE_MODREF *main_exe; WINE_MODREF *main_exe;
HANDLE handle = INVALID_HANDLE_VALUE; HANDLE handle = INVALID_HANDLE_VALUE;
NTSTATUS nts; NTSTATUS nts;
const WCHAR *load_path;
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) ); TRACE( "looking for %s in %s\n", debugstr_w(libname), debugstr_w(load_path) );
@ -1370,7 +1401,7 @@ static NTSTATUS load_dll( LPCWSTR libname, DWORD flags, WINE_MODREF** pwm )
!(flags & DONT_RESOLVE_DLL_REFERENCES)) !(flags & DONT_RESOLVE_DLL_REFERENCES))
{ {
(*pwm)->ldr.Flags &= ~LDR_DONT_RESOLVE_REFS; (*pwm)->ldr.Flags &= ~LDR_DONT_RESOLVE_REFS;
fixup_imports( *pwm ); fixup_imports( *pwm, load_path );
} }
TRACE("Found loaded module %s for %s at %p, count=%d\n", TRACE("Found loaded module %s for %s at %p, count=%d\n",
debugstr_w((*pwm)->ldr.FullDllName.Buffer), debugstr_w(libname), debugstr_w((*pwm)->ldr.FullDllName.Buffer), debugstr_w(libname),
@ -1391,12 +1422,12 @@ static NTSTATUS load_dll( LPCWSTR libname, DWORD flags, WINE_MODREF** pwm )
case LOADORDER_DLL: case LOADORDER_DLL:
TRACE("Trying native dll %s\n", debugstr_w(filename)); TRACE("Trying native dll %s\n", debugstr_w(filename));
if (handle == INVALID_HANDLE_VALUE) continue; /* it cannot possibly be loaded */ if (handle == INVALID_HANDLE_VALUE) continue; /* it cannot possibly be loaded */
nts = load_native_dll(filename, handle, flags, pwm); nts = load_native_dll( load_path, filename, handle, flags, pwm );
filetype = "native"; filetype = "native";
break; break;
case LOADORDER_BI: case LOADORDER_BI:
TRACE("Trying built-in %s\n", debugstr_w(filename)); TRACE("Trying built-in %s\n", debugstr_w(filename));
nts = load_builtin_dll(filename, flags, pwm); nts = load_builtin_dll( load_path, filename, flags, pwm );
filetype = "builtin"; filetype = "builtin";
break; break;
default: default:
@ -1435,14 +1466,11 @@ NTSTATUS WINAPI LdrLoadDll(LPCWSTR path_name, DWORD flags,
{ {
WINE_MODREF *wm; WINE_MODREF *wm;
NTSTATUS nts; NTSTATUS nts;
const WCHAR *prev_load_path;
RtlEnterCriticalSection( &loader_section ); RtlEnterCriticalSection( &loader_section );
prev_load_path = current_load_path; if (!path_name) path_name = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
current_load_path = path_name; nts = load_dll( path_name, libname->Buffer, flags, &wm );
nts = load_dll( libname->Buffer, flags, &wm );
current_load_path = prev_load_path;
if (nts == STATUS_SUCCESS && !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS)) if (nts == STATUS_SUCCESS && !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS))
{ {
@ -1720,6 +1748,7 @@ void WINAPI LdrInitializeThunk( HANDLE main_file, ULONG unknown2, ULONG unknown3
{ {
NTSTATUS status; NTSTATUS status;
WINE_MODREF *wm; WINE_MODREF *wm;
LPCWSTR load_path;
LPTHREAD_START_ROUTINE entry; LPTHREAD_START_ROUTINE entry;
PEB *peb = NtCurrentTeb()->Peb; PEB *peb = NtCurrentTeb()->Peb;
UNICODE_STRING *main_exe_name = &peb->ProcessParameters->ImagePathName; UNICODE_STRING *main_exe_name = &peb->ProcessParameters->ImagePathName;
@ -1763,7 +1792,8 @@ void WINAPI LdrInitializeThunk( HANDLE main_file, ULONG unknown2, ULONG unknown3
RtlEnterCriticalSection( &loader_section ); RtlEnterCriticalSection( &loader_section );
if ((status = fixup_imports( wm )) != STATUS_SUCCESS) goto error; load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
if ((status = fixup_imports( wm, load_path )) != STATUS_SUCCESS) goto error;
if ((status = alloc_process_tls()) != STATUS_SUCCESS) goto error; if ((status = alloc_process_tls()) != STATUS_SUCCESS) goto error;
if ((status = alloc_thread_tls()) != STATUS_SUCCESS) goto error; if ((status = alloc_thread_tls()) != STATUS_SUCCESS) goto error;
if ((status = process_attach( wm, (LPVOID)1 )) != STATUS_SUCCESS) goto error; if ((status = process_attach( wm, (LPVOID)1 )) != STATUS_SUCCESS) goto error;
@ -1857,12 +1887,20 @@ PVOID WINAPI RtlImageRvaToVa( const IMAGE_NT_HEADERS *nt, HMODULE module,
*/ */
HMODULE BUILTIN32_LoadExeModule( HMODULE main ) HMODULE BUILTIN32_LoadExeModule( HMODULE main )
{ {
struct builtin_load_info info, *prev_info;
if (!MODULE_GetSystemDirectory( &system_dir ))
MESSAGE( "Couldn't get system dir in process init\n");
NtCurrentTeb()->Peb->ImageBaseAddress = main; NtCurrentTeb()->Peb->ImageBaseAddress = main;
last_builtin_status = STATUS_SUCCESS; info.status = STATUS_SUCCESS;
info.load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
prev_info = builtin_load_info;
builtin_load_info = &info;
wine_dll_set_callback( load_builtin_callback ); wine_dll_set_callback( load_builtin_callback );
builtin_load_info = prev_info;
if (!NtCurrentTeb()->Peb->ImageBaseAddress) if (!NtCurrentTeb()->Peb->ImageBaseAddress)
MESSAGE( "No built-in EXE module loaded! Did you create a .spec file?\n" ); MESSAGE( "No built-in EXE module loaded! Did you create a .spec file?\n" );
if (last_builtin_status != STATUS_SUCCESS) if (info.status != STATUS_SUCCESS)
MESSAGE( "Error while processing initial modules\n"); MESSAGE( "Error while processing initial modules\n");
return NtCurrentTeb()->Peb->ImageBaseAddress; return NtCurrentTeb()->Peb->ImageBaseAddress;
} }

View File

@ -476,6 +476,30 @@ static BOOL get_registry_value( HKEY hkey, const WCHAR *module, enum loadorder_t
} }
/***************************************************************************
* MODULE_GetSystemDirectory
*
* Retrieve the system directory. The string must be freed by the caller.
*/
BOOL MODULE_GetSystemDirectory( UNICODE_STRING *sysdir )
{
static const WCHAR winsysdirW[] = {'w','i','n','s','y','s','d','i','r',0};
UNICODE_STRING name;
RtlInitUnicodeString( &name, winsysdirW );
sysdir->MaximumLength = 0;
if (RtlQueryEnvironmentVariable_U( NULL, &name, sysdir ) != STATUS_BUFFER_TOO_SMALL)
return FALSE;
sysdir->MaximumLength = sysdir->Length + sizeof(WCHAR);
if (!(sysdir->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, sysdir->MaximumLength )))
return FALSE;
if (RtlQueryEnvironmentVariable_U( NULL, &name, sysdir ) == STATUS_SUCCESS)
return TRUE;
RtlFreeUnicodeString( sysdir );
return FALSE;
}
/*************************************************************************** /***************************************************************************
* MODULE_GetLoadOrderW (internal) * MODULE_GetLoadOrderW (internal)
* *
@ -510,17 +534,17 @@ void MODULE_GetLoadOrderW( enum loadorder_type loadorder[], const WCHAR *app_nam
*/ */
if (win32) if (win32)
{ {
WCHAR sysdir[MAX_PATH+1]; UNICODE_STRING path_str, sysdir;
UNICODE_STRING path_str, sysdir_str;
if (!GetSystemDirectoryW( sysdir, MAX_PATH )) return;
if (!MODULE_GetSystemDirectory( &sysdir )) return;
RtlInitUnicodeString( &path_str, path ); RtlInitUnicodeString( &path_str, path );
RtlInitUnicodeString( &sysdir_str, sysdir ); if (RtlPrefixUnicodeString( &sysdir, &path_str, TRUE ))
if (RtlPrefixUnicodeString( &sysdir_str, &path_str, TRUE ))
{ {
path += sysdir_str.Length / sizeof(WCHAR); const WCHAR *p = path + sysdir.Length / sizeof(WCHAR);
while (*path == '\\' || *path == '/') path++; while (*p == '\\' || *p == '/') p++;
if (!strchrW( p, '\\' ) && !strchrW( p, '/' )) path = p;
} }
RtlFreeUnicodeString( &sysdir );
} }
if (!(len = strlenW(path))) return; if (!(len = strlenW(path))) return;

View File

@ -40,6 +40,7 @@ extern NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handl
const LARGE_INTEGER *timeout ); const LARGE_INTEGER *timeout );
/* module handling */ /* module handling */
extern BOOL MODULE_GetSystemDirectory( UNICODE_STRING *sysdir );
extern void RELAY_InitDebugLists(void); extern void RELAY_InitDebugLists(void);
extern FARPROC RELAY_GetProcAddress( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports, extern FARPROC RELAY_GetProcAddress( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports,
DWORD exp_size, FARPROC proc, const WCHAR *user ); DWORD exp_size, FARPROC proc, const WCHAR *user );