From f93713b157411efabfa6ceabf137364b249106f6 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 26 Apr 2021 12:43:10 +0200 Subject: [PATCH] ntdll: Support loading builtins from the architecture-specific PE directory. Based on a patch by Jacek Caban. Signed-off-by: Alexandre Julliard --- dlls/ntdll/loader.c | 21 +++++++++++++++++++- dlls/ntdll/unix/loader.c | 43 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 38dd276608b..85ae6aac15f 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -51,6 +51,18 @@ WINE_DECLARE_DEBUG_CHANNEL(imports); #define DEFAULT_SECURITY_COOKIE_32 0xbb40e64e #define DEFAULT_SECURITY_COOKIE_16 (DEFAULT_SECURITY_COOKIE_32 >> 16) +#ifdef __i386__ +static const WCHAR pe_dir[] = L"\\i386-windows"; +#elif defined __x86_64__ +static const WCHAR pe_dir[] = L"\\x86_64-windows"; +#elif defined __arm__ +static const WCHAR pe_dir[] = L"\\arm-windows"; +#elif defined __aarch64__ +static const WCHAR pe_dir[] = L"\\aarch64-windows"; +#else +static const WCHAR pe_dir[] = L""; +#endif + /* we don't want to include winuser.h */ #define RT_MANIFEST ((ULONG_PTR)24) #define ISOLATIONAWARE_MANIFEST_RESOURCE_ID ((ULONG_PTR)2) @@ -2640,11 +2652,18 @@ static NTSTATUS find_builtin_without_file( const WCHAR *name, UNICODE_STRING *ne if (status != STATUS_DLL_NOT_FOUND) goto done; RtlFreeUnicodeString( new_name ); } + for (i = 0; ; i++) { swprintf( dllpath, ARRAY_SIZE(dllpath), L"WINEDLLDIR%u", i ); - if (get_env_var( dllpath, 20 + wcslen(name), new_name )) break; + if (get_env_var( dllpath, wcslen(pe_dir) + wcslen(name) + 1, new_name )) break; len = new_name->Length; + RtlAppendUnicodeToString( new_name, pe_dir ); + RtlAppendUnicodeToString( new_name, L"\\" ); + RtlAppendUnicodeToString( new_name, name ); + status = open_dll_file( new_name, pwm, mapping, image_info, id ); + if (status != STATUS_DLL_NOT_FOUND) goto done; + new_name->Length = len; RtlAppendUnicodeToString( new_name, L"\\" ); RtlAppendUnicodeToString( new_name, name ); status = open_dll_file( new_name, pwm, mapping, image_info, id ); diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 9947ff2f447..30e1f972ae1 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -237,10 +237,27 @@ static char *build_path( const char *dir, const char *name ) memcpy( ret, dir, len ); if (len && ret[len - 1] != '/') ret[len++] = '/'; + if (name[0] == '/') name++; strcpy( ret + len, name ); return ret; } + +static const char *get_pe_dir( WORD machine ) +{ + if (!machine) machine = current_machine; + + switch(machine) + { + case IMAGE_FILE_MACHINE_I386: return "/i386-windows"; + case IMAGE_FILE_MACHINE_AMD64: return "/x86_64-windows"; + case IMAGE_FILE_MACHINE_ARMNT: return "/arm-windows"; + case IMAGE_FILE_MACHINE_ARM64: return "/aarch64-windows"; + default: return ""; + } +} + + static void set_dll_path(void) { char *p, *path = getenv( "WINEDLLPATH" ); @@ -1257,6 +1274,7 @@ static NTSTATUS find_builtin_dll( UNICODE_STRING *nt_name, void **module, SIZE_T unsigned int i, pos, namepos, namelen, maxlen = 0; unsigned int len = nt_name->Length / sizeof(WCHAR); char *ptr = NULL, *file, *ext = NULL; + const char *pe_dir = get_pe_dir( machine ); OBJECT_ATTRIBUTES attr; NTSTATUS status = STATUS_DLL_NOT_FOUND; BOOL found_image = FALSE; @@ -1268,7 +1286,7 @@ static NTSTATUS find_builtin_dll( UNICODE_STRING *nt_name, void **module, SIZE_T InitializeObjectAttributes( &attr, nt_name, 0, 0, NULL ); if (build_dir) maxlen = strlen(build_dir) + sizeof("/programs/") + len; - maxlen = max( maxlen, dll_path_maxlen + 1 ) + len + sizeof(".so"); + maxlen = max( maxlen, dll_path_maxlen + 1 ) + len + sizeof("/aarch64-windows") + sizeof(".so"); if (!(file = malloc( maxlen ))) return STATUS_NO_MEMORY; @@ -1310,8 +1328,16 @@ static NTSTATUS find_builtin_dll( UNICODE_STRING *nt_name, void **module, SIZE_T for (i = 0; dll_paths[i]; i++) { + ptr = file + pos; + file[pos + len + 1] = 0; + ptr = prepend( ptr, pe_dir, strlen(pe_dir) ); + ptr = prepend( ptr, dll_paths[i], strlen(dll_paths[i]) ); + status = open_builtin_file( ptr, &attr, module, size_ptr, image_info, machine, prefer_native ); + /* use so dir for unix lib */ + ptr = file + pos; file[pos + len + 1] = 0; ptr = prepend( file + pos, dll_paths[i], strlen(dll_paths[i]) ); + if (status != STATUS_DLL_NOT_FOUND) goto done; status = open_builtin_file( ptr, &attr, module, size_ptr, image_info, machine, prefer_native ); if (status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) found_image = TRUE; else if (status != STATUS_DLL_NOT_FOUND) goto done; @@ -1652,13 +1678,26 @@ static void load_ntdll(void) UNICODE_STRING str; void *module; SIZE_T size = 0; - char *name = build_path( dll_dir, "ntdll.dll.so" ); + char *name; + + if (!build_dir) + { + char *dir = build_path( dll_dir, get_pe_dir(current_machine) ); + name = build_path( dir, "ntdll.dll.so" ); + free( dir ); + } + else name = build_path( build_dir, "dlls/ntdll/ntdll.dll.so" ); init_unicode_string( &str, path ); InitializeObjectAttributes( &attr, &str, 0, 0, NULL ); name[strlen(name) - 3] = 0; /* remove .so */ status = open_builtin_file( name, &attr, &module, &size, &info, current_machine, FALSE ); if (status == STATUS_IMAGE_NOT_AT_BASE) relocate_ntdll( module ); + else if (status == STATUS_DLL_NOT_FOUND) + { + free( name ); + name = build_path( dll_dir, "ntdll.dll.so" ); + } else if (status) fatal_error( "failed to load %s error %x\n", name, status ); free( name ); load_ntdll_functions( module );