ntdll: Prevent loading Wine system dependencies in place of identically named application DLLs.
That is, load Wine system dependencies only when they are imported from Wine builtins or other system dependencies, and do not match a Wine system dependency by its base name when looking for already-loaded modules. The reasoning is that it is possible for an application to ship, and expect to use, a newer version of a MinGW-compiled library, or one with custom patches, or possibly an unrelated library with the same name. We don't want to offer Wine's system dependencies in place of the application's, or vice versa. Signed-off-by: Zebediah Figura <zfigura@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
7e926a9aa9
commit
bfbccf1a03
|
@ -135,6 +135,7 @@ typedef struct _wine_modref
|
||||||
LDR_DATA_TABLE_ENTRY ldr;
|
LDR_DATA_TABLE_ENTRY ldr;
|
||||||
struct file_id id;
|
struct file_id id;
|
||||||
ULONG CheckSum;
|
ULONG CheckSum;
|
||||||
|
BOOL system;
|
||||||
} WINE_MODREF;
|
} WINE_MODREF;
|
||||||
|
|
||||||
static UINT tls_module_count; /* number of modules with TLS directory */
|
static UINT tls_module_count; /* number of modules with TLS directory */
|
||||||
|
@ -185,7 +186,7 @@ static WINE_MODREF *last_failed_modref;
|
||||||
|
|
||||||
static LDR_DDAG_NODE *node_ntdll, *node_kernel32;
|
static LDR_DDAG_NODE *node_ntdll, *node_kernel32;
|
||||||
|
|
||||||
static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, DWORD flags, WINE_MODREF** pwm );
|
static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, DWORD flags, WINE_MODREF** pwm, BOOL system );
|
||||||
static NTSTATUS process_attach( LDR_DDAG_NODE *node, LPVOID lpReserved );
|
static NTSTATUS process_attach( LDR_DDAG_NODE *node, LPVOID lpReserved );
|
||||||
static FARPROC find_ordinal_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports,
|
static FARPROC find_ordinal_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports,
|
||||||
DWORD exp_size, DWORD ordinal, LPCWSTR load_path );
|
DWORD exp_size, DWORD ordinal, LPCWSTR load_path );
|
||||||
|
@ -517,8 +518,8 @@ static WINE_MODREF *find_basename_module( LPCWSTR name )
|
||||||
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)
|
||||||
{
|
{
|
||||||
LDR_DATA_TABLE_ENTRY *mod = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
|
WINE_MODREF *mod = CONTAINING_RECORD(entry, WINE_MODREF, ldr.InLoadOrderLinks);
|
||||||
if (RtlEqualUnicodeString( &name_str, &mod->BaseDllName, TRUE ))
|
if (RtlEqualUnicodeString( &name_str, &mod->ldr.BaseDllName, TRUE ) && !mod->system)
|
||||||
{
|
{
|
||||||
cached_modref = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
|
cached_modref = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
|
||||||
return cached_modref;
|
return cached_modref;
|
||||||
|
@ -760,8 +761,9 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward, LPCWS
|
||||||
|
|
||||||
if (!(wm = find_basename_module( mod_name )))
|
if (!(wm = find_basename_module( mod_name )))
|
||||||
{
|
{
|
||||||
|
WINE_MODREF *imp = get_modref( module );
|
||||||
TRACE( "delay loading %s for '%s'\n", debugstr_w(mod_name), forward );
|
TRACE( "delay loading %s for '%s'\n", debugstr_w(mod_name), forward );
|
||||||
if (load_dll( load_path, mod_name, 0, &wm ) == STATUS_SUCCESS &&
|
if (load_dll( load_path, mod_name, 0, &wm, imp->system ) == STATUS_SUCCESS &&
|
||||||
!(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS))
|
!(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS))
|
||||||
{
|
{
|
||||||
if (!imports_fixup_done && current_modref)
|
if (!imports_fixup_done && current_modref)
|
||||||
|
@ -778,7 +780,7 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward, LPCWS
|
||||||
if (!wm)
|
if (!wm)
|
||||||
{
|
{
|
||||||
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(imp->ldr.FullDllName.Buffer) );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -926,6 +928,7 @@ void * WINAPI RtlFindExportedRoutineByName( HMODULE module, const char *name )
|
||||||
*/
|
*/
|
||||||
static BOOL import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *descr, LPCWSTR load_path, WINE_MODREF **pwm )
|
static BOOL import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *descr, LPCWSTR load_path, WINE_MODREF **pwm )
|
||||||
{
|
{
|
||||||
|
BOOL system = current_modref->system || (current_modref->ldr.Flags & LDR_WINE_INTERNAL);
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
WINE_MODREF *wmImp;
|
WINE_MODREF *wmImp;
|
||||||
HMODULE imp_mod;
|
HMODULE imp_mod;
|
||||||
|
@ -954,7 +957,7 @@ static BOOL import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *descr, LP
|
||||||
}
|
}
|
||||||
|
|
||||||
status = build_import_name( buffer, name, len );
|
status = build_import_name( buffer, name, len );
|
||||||
if (!status) status = load_dll( load_path, buffer, 0, &wmImp );
|
if (!status) status = load_dll( load_path, buffer, 0, &wmImp, system );
|
||||||
|
|
||||||
if (status)
|
if (status)
|
||||||
{
|
{
|
||||||
|
@ -1224,7 +1227,7 @@ static NTSTATUS fixup_imports_ilonly( WINE_MODREF *wm, LPCWSTR load_path, void *
|
||||||
prev = current_modref;
|
prev = current_modref;
|
||||||
current_modref = wm;
|
current_modref = wm;
|
||||||
assert( !wm->ldr.DdagNode->Dependencies.Tail );
|
assert( !wm->ldr.DdagNode->Dependencies.Tail );
|
||||||
if (!(status = load_dll( load_path, L"mscoree.dll", 0, &imp ))
|
if (!(status = load_dll( load_path, L"mscoree.dll", 0, &imp, FALSE ))
|
||||||
&& !add_module_dependency_after( wm->ldr.DdagNode, imp->ldr.DdagNode, NULL ))
|
&& !add_module_dependency_after( wm->ldr.DdagNode, imp->ldr.DdagNode, NULL ))
|
||||||
status = STATUS_NO_MEMORY;
|
status = STATUS_NO_MEMORY;
|
||||||
current_modref = prev;
|
current_modref = prev;
|
||||||
|
@ -1996,7 +1999,7 @@ static NTSTATUS perform_relocations( void *module, IMAGE_NT_HEADERS *nt, SIZE_T
|
||||||
*/
|
*/
|
||||||
static NTSTATUS build_module( LPCWSTR load_path, const UNICODE_STRING *nt_name, void **module,
|
static NTSTATUS build_module( LPCWSTR load_path, const UNICODE_STRING *nt_name, void **module,
|
||||||
const SECTION_IMAGE_INFORMATION *image_info, const struct file_id *id,
|
const SECTION_IMAGE_INFORMATION *image_info, const struct file_id *id,
|
||||||
DWORD flags, WINE_MODREF **pwm )
|
DWORD flags, BOOL system, WINE_MODREF **pwm )
|
||||||
{
|
{
|
||||||
static const char builtin_signature[] = "Wine builtin DLL";
|
static const char builtin_signature[] = "Wine builtin DLL";
|
||||||
char *signature = (char *)((IMAGE_DOS_HEADER *)*module + 1);
|
char *signature = (char *)((IMAGE_DOS_HEADER *)*module + 1);
|
||||||
|
@ -2021,6 +2024,7 @@ static NTSTATUS build_module( LPCWSTR load_path, const UNICODE_STRING *nt_name,
|
||||||
if (id) wm->id = *id;
|
if (id) wm->id = *id;
|
||||||
if (image_info->LoaderFlags) wm->ldr.Flags |= LDR_COR_IMAGE;
|
if (image_info->LoaderFlags) wm->ldr.Flags |= LDR_COR_IMAGE;
|
||||||
if (image_info->u.s.ComPlusILOnly) wm->ldr.Flags |= LDR_COR_ILONLY;
|
if (image_info->u.s.ComPlusILOnly) wm->ldr.Flags |= LDR_COR_ILONLY;
|
||||||
|
wm->system = system;
|
||||||
|
|
||||||
set_security_cookie( *module, map_size );
|
set_security_cookie( *module, map_size );
|
||||||
|
|
||||||
|
@ -2475,7 +2479,7 @@ static WINE_MODREF *find_existing_module( HMODULE module )
|
||||||
*/
|
*/
|
||||||
static NTSTATUS load_native_dll( LPCWSTR load_path, const UNICODE_STRING *nt_name, HANDLE mapping,
|
static NTSTATUS load_native_dll( LPCWSTR load_path, const UNICODE_STRING *nt_name, HANDLE mapping,
|
||||||
const SECTION_IMAGE_INFORMATION *image_info, const struct file_id *id,
|
const SECTION_IMAGE_INFORMATION *image_info, const struct file_id *id,
|
||||||
DWORD flags, WINE_MODREF** pwm )
|
DWORD flags, BOOL system, WINE_MODREF** pwm )
|
||||||
{
|
{
|
||||||
void *module = NULL;
|
void *module = NULL;
|
||||||
SIZE_T len = 0;
|
SIZE_T len = 0;
|
||||||
|
@ -2497,7 +2501,7 @@ static NTSTATUS load_native_dll( LPCWSTR load_path, const UNICODE_STRING *nt_nam
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
if (!convert_to_pe64( module, image_info )) status = STATUS_INVALID_IMAGE_FORMAT;
|
if (!convert_to_pe64( module, image_info )) status = STATUS_INVALID_IMAGE_FORMAT;
|
||||||
#endif
|
#endif
|
||||||
if (!status) status = build_module( load_path, nt_name, &module, image_info, id, flags, pwm );
|
if (!status) status = build_module( load_path, nt_name, &module, image_info, id, flags, system, pwm );
|
||||||
if (status && module) NtUnmapViewOfSection( NtCurrentProcess(), module );
|
if (status && module) NtUnmapViewOfSection( NtCurrentProcess(), module );
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -2532,7 +2536,7 @@ static NTSTATUS load_so_dll( LPCWSTR load_path, const UNICODE_STRING *nt_name,
|
||||||
{
|
{
|
||||||
SECTION_IMAGE_INFORMATION image_info = { 0 };
|
SECTION_IMAGE_INFORMATION image_info = { 0 };
|
||||||
|
|
||||||
if ((status = build_module( load_path, &win_name, &module, &image_info, NULL, flags, &wm )))
|
if ((status = build_module( load_path, &win_name, &module, &image_info, NULL, flags, FALSE, &wm )))
|
||||||
{
|
{
|
||||||
if (module) NtUnmapViewOfSection( NtCurrentProcess(), module );
|
if (module) NtUnmapViewOfSection( NtCurrentProcess(), module );
|
||||||
return status;
|
return status;
|
||||||
|
@ -2577,7 +2581,7 @@ static WINE_MODREF *build_main_module(void)
|
||||||
#endif
|
#endif
|
||||||
status = RtlDosPathNameToNtPathName_U_WithStatus( params->ImagePathName.Buffer, &nt_name, NULL, NULL );
|
status = RtlDosPathNameToNtPathName_U_WithStatus( params->ImagePathName.Buffer, &nt_name, NULL, NULL );
|
||||||
if (status) goto failed;
|
if (status) goto failed;
|
||||||
status = build_module( NULL, &nt_name, &module, &info, NULL, DONT_RESOLVE_DLL_REFERENCES, &wm );
|
status = build_module( NULL, &nt_name, &module, &info, NULL, DONT_RESOLVE_DLL_REFERENCES, FALSE, &wm );
|
||||||
RtlFreeUnicodeString( &nt_name );
|
RtlFreeUnicodeString( &nt_name );
|
||||||
if (!status) return wm;
|
if (!status) return wm;
|
||||||
failed:
|
failed:
|
||||||
|
@ -2965,18 +2969,25 @@ done:
|
||||||
* 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( const WCHAR *load_path, const WCHAR *libname, DWORD flags, WINE_MODREF** pwm )
|
static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, DWORD flags, WINE_MODREF** pwm, BOOL system )
|
||||||
{
|
{
|
||||||
UNICODE_STRING nt_name;
|
UNICODE_STRING nt_name;
|
||||||
struct file_id id;
|
struct file_id id;
|
||||||
HANDLE mapping = 0;
|
HANDLE mapping = 0;
|
||||||
SECTION_IMAGE_INFORMATION image_info;
|
SECTION_IMAGE_INFORMATION image_info;
|
||||||
NTSTATUS nts;
|
NTSTATUS nts = STATUS_DLL_NOT_FOUND;
|
||||||
ULONG64 prev;
|
ULONG64 prev;
|
||||||
|
|
||||||
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) );
|
||||||
|
|
||||||
|
if (system && system_dll_path.Buffer)
|
||||||
|
nts = search_dll_file( system_dll_path.Buffer, libname, &nt_name, pwm, &mapping, &image_info, &id );
|
||||||
|
|
||||||
|
if (nts)
|
||||||
|
{
|
||||||
nts = find_dll_file( load_path, libname, &nt_name, pwm, &mapping, &image_info, &id );
|
nts = find_dll_file( load_path, libname, &nt_name, pwm, &mapping, &image_info, &id );
|
||||||
|
system = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (*pwm) /* found already loaded module */
|
if (*pwm) /* found already loaded module */
|
||||||
{
|
{
|
||||||
|
@ -3009,7 +3020,7 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, DWORD fl
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STATUS_SUCCESS: /* valid PE file */
|
case STATUS_SUCCESS: /* valid PE file */
|
||||||
nts = load_native_dll( load_path, &nt_name, mapping, &image_info, &id, flags, pwm );
|
nts = load_native_dll( load_path, &nt_name, mapping, &image_info, &id, flags, system, pwm );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3071,7 +3082,7 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH LdrLoadDll(LPCWSTR path_name, DWORD flags,
|
||||||
|
|
||||||
RtlEnterCriticalSection( &loader_section );
|
RtlEnterCriticalSection( &loader_section );
|
||||||
|
|
||||||
nts = load_dll( path_name, dllname ? dllname : libname->Buffer, flags, &wm );
|
nts = load_dll( path_name, dllname ? dllname : libname->Buffer, flags, &wm, FALSE );
|
||||||
|
|
||||||
if (nts == STATUS_SUCCESS && !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS))
|
if (nts == STATUS_SUCCESS && !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS))
|
||||||
{
|
{
|
||||||
|
@ -3853,7 +3864,7 @@ static void init_wow64( CONTEXT *context )
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
static const WCHAR wow64_path[] = L"C:\\windows\\system32\\wow64.dll";
|
static const WCHAR wow64_path[] = L"C:\\windows\\system32\\wow64.dll";
|
||||||
|
|
||||||
if ((status = load_dll( NULL, wow64_path, 0, &wm )))
|
if ((status = load_dll( NULL, wow64_path, 0, &wm, FALSE )))
|
||||||
{
|
{
|
||||||
ERR( "could not load %s, status %x\n", debugstr_w(wow64_path), status );
|
ERR( "could not load %s, status %x\n", debugstr_w(wow64_path), status );
|
||||||
NtTerminateProcess( GetCurrentProcess(), status );
|
NtTerminateProcess( GetCurrentProcess(), status );
|
||||||
|
@ -4003,7 +4014,7 @@ void WINAPI LdrInitializeThunk( CONTEXT *context, ULONG_PTR unknown2, ULONG_PTR
|
||||||
|
|
||||||
if (NtCurrentTeb()->WowTebOffset) init_wow64( context );
|
if (NtCurrentTeb()->WowTebOffset) init_wow64( context );
|
||||||
|
|
||||||
if ((status = load_dll( NULL, L"kernel32.dll", 0, &kernel32 )) != STATUS_SUCCESS)
|
if ((status = load_dll( NULL, L"kernel32.dll", 0, &kernel32, FALSE )) != STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
MESSAGE( "wine: could not load kernel32.dll, status %x\n", status );
|
MESSAGE( "wine: could not load kernel32.dll, status %x\n", status );
|
||||||
NtTerminateProcess( GetCurrentProcess(), status );
|
NtTerminateProcess( GetCurrentProcess(), status );
|
||||||
|
|
Loading…
Reference in New Issue