ntdll: Support loading builtins from the architecture-specific PE directory.

Based on a patch by Jacek Caban.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-04-26 12:43:10 +02:00
parent 51a0cdf52d
commit f93713b157
2 changed files with 61 additions and 3 deletions

View file

@ -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 );

View file

@ -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 );