From: Zhiyi Zhang zzhang@codeweavers.com
SxS DLLs are found via find_actctx_dll(). When activation contexts are inactive, GetModuleHandle() shouldn't find SxS DLLs with the same base name of a normal DLL. Whether a DLL is a SxS DLL is marked by the LDR_REDIRECTED(0x10000000) flag in LDR_DATA_TABLE_ENTRY.Flags. Manual testing also shows that LDR_REDIRECTED is not present for DLLs redirected via the API set mechanism. --- dlls/kernel32/tests/actctx.c | 3 --- dlls/ntdll/loader.c | 39 +++++++++++++++++++++++++----------- 2 files changed, 27 insertions(+), 15 deletions(-)
diff --git a/dlls/kernel32/tests/actctx.c b/dlls/kernel32/tests/actctx.c index 1879572dcaf..939c9b62772 100644 --- a/dlls/kernel32/tests/actctx.c +++ b/dlls/kernel32/tests/actctx.c @@ -3862,7 +3862,6 @@ static void _check_redirected_flag(int line, HMODULE module, BOOL redirected) continue;
if (redirected) - todo_wine ok_(__FILE__, line)(mod->Flags & LDR_REDIRECTED, "Got unexpected flags %#lx.\n", mod->Flags); else ok_(__FILE__, line)(!(mod->Flags & LDR_REDIRECTED), "Got unexpected flags %#lx.\n", mod->Flags); @@ -3911,7 +3910,6 @@ static void test_one_with_sxs_and_GetModuleHandleA(void)
/* Normal loaded dll should be found while context is inactive */ module_temp = GetModuleHandleA("sxs_dll.dll"); - todo_wine ok(module_temp == module, "Got unexpected module.\n");
if (module) @@ -3919,7 +3917,6 @@ static void test_one_with_sxs_and_GetModuleHandleA(void)
/* Loaded SxS dll can't be found while context is inactive */ module_temp = GetModuleHandleA("sxs_dll.dll"); - todo_wine ok(module_temp == NULL, "Got unexpected module.\n");
if (dll.module) diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index b1a8544999c..c5c34935efd 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -600,14 +600,16 @@ static WINE_MODREF *find_basename_module( LPCWSTR name )
RtlInitUnicodeString( &name_str, name );
- if (cached_modref && RtlEqualUnicodeString( &name_str, &cached_modref->ldr.BaseDllName, TRUE )) + if (cached_modref && !(cached_modref->ldr.Flags & LDR_REDIRECTED) + && RtlEqualUnicodeString( &name_str, &cached_modref->ldr.BaseDllName, TRUE )) return cached_modref;
mark = &hash_table[hash_basename( &name_str )]; for (entry = mark->Flink; entry != mark; entry = entry->Flink) { WINE_MODREF *mod = CONTAINING_RECORD(entry, WINE_MODREF, ldr.HashLinks); - if (RtlEqualUnicodeString( &name_str, &mod->ldr.BaseDllName, TRUE ) && !mod->system) + if (!mod->system && !(mod->ldr.Flags & LDR_REDIRECTED) + && RtlEqualUnicodeString( &name_str, &mod->ldr.BaseDllName, TRUE )) { cached_modref = CONTAINING_RECORD(mod, WINE_MODREF, ldr); return cached_modref; @@ -2249,7 +2251,7 @@ done: */ 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, - DWORD flags, BOOL system, WINE_MODREF **pwm ) + DWORD flags, BOOL system, BOOL redirected, WINE_MODREF **pwm ) { static const char builtin_signature[] = "Wine builtin DLL"; char *signature = (char *)((IMAGE_DOS_HEADER *)*module + 1); @@ -2274,6 +2276,7 @@ static NTSTATUS build_module( LPCWSTR load_path, const UNICODE_STRING *nt_name, if (id) wm->id = *id; if (image_info->LoaderFlags) wm->ldr.Flags |= LDR_COR_IMAGE; if (image_info->ComPlusILOnly) wm->ldr.Flags |= LDR_COR_ILONLY; + if (redirected) wm->ldr.Flags |= LDR_REDIRECTED; wm->system = system;
update_load_config( *module ); @@ -2798,7 +2801,7 @@ static WINE_MODREF *find_existing_module( HMODULE module ) */ 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, - DWORD flags, BOOL system, WINE_MODREF** pwm ) + DWORD flags, BOOL system, BOOL redirected, WINE_MODREF** pwm ) { void *module = NULL; SIZE_T len = 0; @@ -2820,7 +2823,8 @@ static NTSTATUS load_native_dll( LPCWSTR load_path, const UNICODE_STRING *nt_nam if (status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH && !convert_to_pe64( module, image_info )) status = STATUS_INVALID_IMAGE_FORMAT; #endif - if (NT_SUCCESS(status)) status = build_module( load_path, nt_name, &module, image_info, id, flags, system, pwm ); + if (NT_SUCCESS(status)) status = build_module( load_path, nt_name, &module, image_info, id, + flags, system, redirected, pwm ); if (status && module) NtUnmapViewOfSection( NtCurrentProcess(), module ); return status; } @@ -2855,7 +2859,8 @@ static NTSTATUS load_so_dll( LPCWSTR load_path, const UNICODE_STRING *nt_name, { SECTION_IMAGE_INFORMATION image_info = { 0 };
- if ((status = build_module( load_path, ¶ms.nt_name, &module, &image_info, NULL, flags, FALSE, &wm ))) + if ((status = build_module( load_path, ¶ms.nt_name, &module, &image_info, NULL, flags, + FALSE, FALSE, &wm ))) { if (module) NtUnmapViewOfSection( NtCurrentProcess(), module ); return status; @@ -2895,7 +2900,8 @@ static WINE_MODREF *build_main_module(void) #endif status = RtlDosPathNameToNtPathName_U_WithStatus( params->ImagePathName.Buffer, &nt_name, NULL, NULL ); if (status) goto failed; - status = build_module( NULL, &nt_name, &module, &info, NULL, DONT_RESOLVE_DLL_REFERENCES, FALSE, &wm ); + status = build_module( NULL, &nt_name, &module, &info, NULL, DONT_RESOLVE_DLL_REFERENCES, FALSE, + FALSE, &wm ); if (status) goto failed; RtlFreeUnicodeString( &nt_name ); wm->ldr.LoadCount = -1; @@ -3249,13 +3255,14 @@ done: */ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, UNICODE_STRING *nt_name, WINE_MODREF **pwm, HANDLE *mapping, SECTION_IMAGE_INFORMATION *image_info, - struct file_id *id, BOOL find_loaded ) + struct file_id *id, BOOL *redirected, BOOL find_loaded ) { WCHAR *fullname = NULL; NTSTATUS status; ULONG wow64_old_value = 0;
*pwm = NULL; + *redirected = FALSE; nt_name->Buffer = NULL;
if (!contains_path( libname )) @@ -3263,7 +3270,11 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, UNI status = find_apiset_dll( libname, &fullname ); if (status == STATUS_DLL_NOT_FOUND) return status;
- if (status) status = find_actctx_dll( libname, &fullname ); + if (status) + { + status = find_actctx_dll( libname, &fullname ); + if (status == STATUS_SUCCESS) *redirected = TRUE; + }
if (status == STATUS_SUCCESS) { @@ -3316,6 +3327,7 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, DWORD fl HANDLE mapping = 0; SECTION_IMAGE_INFORMATION image_info; NTSTATUS nts = STATUS_DLL_NOT_FOUND; + BOOL redirected; void *prev;
TRACE( "looking for %s in %s\n", debugstr_w(libname), debugstr_w(load_path) ); @@ -3325,7 +3337,8 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, DWORD fl
if (nts) { - nts = find_dll_file( load_path, libname, &nt_name, pwm, &mapping, &image_info, &id, FALSE ); + nts = find_dll_file( load_path, libname, &nt_name, pwm, &mapping, &image_info, &id, + &redirected, FALSE ); system = FALSE; }
@@ -3352,7 +3365,8 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, DWORD fl break;
case STATUS_SUCCESS: /* valid PE file */ - nts = load_native_dll( load_path, &nt_name, mapping, &image_info, &id, flags, system, pwm ); + nts = load_native_dll( load_path, &nt_name, mapping, &image_info, &id, flags, system, + redirected, pwm ); break; }
@@ -3493,6 +3507,7 @@ NTSTATUS WINAPI LdrGetDllHandleEx( ULONG flags, LPCWSTR load_path, ULONG *dll_ch SECTION_IMAGE_INFORMATION image_info; UNICODE_STRING nt_name; struct file_id id; + BOOL redirected; NTSTATUS status; WINE_MODREF *wm; WCHAR *dllname; @@ -3515,7 +3530,7 @@ NTSTATUS WINAPI LdrGetDllHandleEx( ULONG flags, LPCWSTR load_path, ULONG *dll_ch RtlEnterCriticalSection( &loader_section );
status = find_dll_file( load_path, dllname ? dllname : name->Buffer, - &nt_name, &wm, &mapping, &image_info, &id, TRUE ); + &nt_name, &wm, &mapping, &image_info, &id, &redirected, TRUE );
if (wm) *base = wm->ldr.DllBase; else