ntdll: Map the builtin or fake dll from the Wine dirs if it's missing from the prefix.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-03-30 10:12:07 +02:00
parent 4a10f3a188
commit bb065801a6
3 changed files with 88 additions and 61 deletions

View file

@ -422,10 +422,8 @@ static void testLoadLibraryEx(void)
/* load kernel32.dll with an absolute path that does not exist */
SetLastError(0xdeadbeef);
hmodule = LoadLibraryExA(path, NULL, LOAD_LIBRARY_AS_DATAFILE);
ok(hmodule == 0, "Expected 0, got %p\n", hmodule);
todo_wine
{
ok(hmodule == 0, "Expected 0, got %p\n", hmodule);
}
ok(GetLastError() == ERROR_FILE_NOT_FOUND,
"Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());

View file

@ -368,7 +368,7 @@ static void test_loadlibraryshim(void)
}
hr = pLoadLibraryShim(fusion, vbogus, NULL, &hdll);
todo_wine ok(hr == E_HANDLE, "LoadLibraryShim failed, hr=%x\n", hr);
ok(hr == E_HANDLE, "LoadLibraryShim failed, hr=%x\n", hr);
if (SUCCEEDED(hr))
FreeLibrary(hdll);
@ -406,7 +406,7 @@ static void test_loadlibraryshim(void)
FreeLibrary(hdll);
hr = pLoadLibraryShim(gdidll, latest, NULL, &hdll);
todo_wine ok(hr == E_HANDLE, "LoadLibraryShim failed, hr=%x\n", hr);
ok(hr == E_HANDLE, "LoadLibraryShim failed, hr=%x\n", hr);
if (SUCCEEDED(hr))
FreeLibrary(hdll);
}

View file

@ -2378,38 +2378,6 @@ static NTSTATUS load_so_dll( LPCWSTR load_path, const UNICODE_STRING *nt_name,
}
/***********************************************************************
* load_builtin_dll
*/
static NTSTATUS load_builtin_dll( LPCWSTR load_path, UNICODE_STRING *nt_name,
DWORD flags, WINE_MODREF** pwm, BOOL prefer_native )
{
NTSTATUS status;
void *module;
SECTION_IMAGE_INFORMATION image_info;
TRACE("Trying built-in %s\n", debugstr_us(nt_name));
status = unix_funcs->load_builtin_dll( nt_name, &module, &image_info, prefer_native );
if (status) return status;
if ((*pwm = find_existing_module( module ))) /* already loaded */
{
if ((*pwm)->ldr.LoadCount != -1) (*pwm)->ldr.LoadCount++;
TRACE( "Found %s for %s at %p, count=%d\n",
debugstr_us(&(*pwm)->ldr.FullDllName), debugstr_us(nt_name),
(*pwm)->ldr.DllBase, (*pwm)->ldr.LoadCount);
if (module != (*pwm)->ldr.DllBase) NtUnmapViewOfSection( NtCurrentProcess(), module );
return STATUS_SUCCESS;
}
TRACE( "loading %s\n", debugstr_us(nt_name) );
status = build_module( load_path, nt_name, &module, &image_info, NULL, flags, pwm );
if (status && module) NtUnmapViewOfSection( NtCurrentProcess(), module );
return status;
}
/*************************************************************************
* build_main_module
*
@ -2553,6 +2521,86 @@ done:
}
/***********************************************************************
* get_env_var
*/
static NTSTATUS get_env_var( const WCHAR *name, SIZE_T extra, UNICODE_STRING *ret )
{
NTSTATUS status;
SIZE_T len, size = 1024 + extra;
for (;;)
{
ret->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, size );
status = RtlQueryEnvironmentVariable( NULL, name, wcslen(name),
ret->Buffer, size - extra - 1, &len );
if (!status)
{
ret->Buffer[len] = 0;
ret->Length = len * sizeof(WCHAR);
ret->MaximumLength = size * sizeof(WCHAR);
return status;
}
RtlFreeHeap( GetProcessHeap(), 0, ret->Buffer );
if (status != STATUS_BUFFER_TOO_SMALL) return status;
size = len + 1 + extra;
}
}
/***********************************************************************
* find_builtin_without_file
*
* Find a builtin dll when the corresponding file cannot be found in the prefix.
* This is used during prefix bootstrap.
*/
static NTSTATUS find_builtin_without_file( const WCHAR *name, UNICODE_STRING *new_name,
WINE_MODREF **pwm, HANDLE *mapping,
SECTION_IMAGE_INFORMATION *image_info, struct file_id *id )
{
const WCHAR *ext;
WCHAR dllpath[32];
DWORD i, len;
NTSTATUS status = STATUS_DLL_NOT_FOUND;
BOOL found_image = FALSE;
if (!get_env_var( L"WINEBUILDDIR", 20 + 2 * wcslen(name), new_name ))
{
RtlAppendUnicodeToString( new_name, L"\\dlls\\" );
RtlAppendUnicodeToString( new_name, name );
if ((ext = wcsrchr( name, '.' )) && !wcscmp( ext, L".dll" )) new_name->Length -= 4 * sizeof(WCHAR);
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) return status;
RtlAppendUnicodeToString( new_name, L".fake" );
status = open_dll_file( new_name, pwm, mapping, image_info, id );
if (status != STATUS_DLL_NOT_FOUND) return status;
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;
len = new_name->Length;
RtlAppendUnicodeToString( new_name, L"\\" );
RtlAppendUnicodeToString( new_name, name );
status = open_dll_file( new_name, pwm, mapping, image_info, id );
if (status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) found_image = TRUE;
else if (status != STATUS_DLL_NOT_FOUND) return status;
new_name->Length = len;
RtlAppendUnicodeToString( new_name, L"\\fakedlls\\" );
RtlAppendUnicodeToString( new_name, name );
status = open_dll_file( new_name, pwm, mapping, image_info, id );
if (status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) found_image = TRUE;
else if (status != STATUS_DLL_NOT_FOUND) return status;
RtlFreeUnicodeString( new_name );
}
if (found_image) status = STATUS_IMAGE_MACHINE_TYPE_MISMATCH;
return status;
}
/***********************************************************************
* search_dll_file
*
@ -2597,14 +2645,10 @@ static NTSTATUS search_dll_file( LPCWSTR paths, LPCWSTR search, UNICODE_STRING *
paths = ptr;
}
if (!found_image)
{
/* not found, return file in the system dir to be loaded as builtin */
wcscpy( name, system_dir );
wcscat( name, search );
if (!RtlDosPathNameToNtPathName_U( name, nt_name, NULL, NULL )) status = STATUS_NO_MEMORY;
}
else status = STATUS_IMAGE_MACHINE_TYPE_MISMATCH;
if (found_image)
status = STATUS_IMAGE_MACHINE_TYPE_MISMATCH;
else if (!wcspbrk( search, L":/\\" ))
status = find_builtin_without_file( search, nt_name, pwm, mapping, image_info, id );
done:
RtlFreeHeap( GetProcessHeap(), 0, name );
@ -2713,7 +2757,7 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC
return STATUS_SUCCESS;
}
if (nts && nts != STATUS_DLL_NOT_FOUND && nts != STATUS_INVALID_IMAGE_NOT_MZ) goto done;
if (nts && nts != STATUS_INVALID_IMAGE_NOT_MZ) goto done;
prev = NtCurrentTeb()->Tib.ArbitraryUserPointer;
NtCurrentTeb()->Tib.ArbitraryUserPointer = nt_name.Buffer + 4;
@ -2727,21 +2771,6 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC
case STATUS_SUCCESS: /* valid PE file */
nts = load_native_dll( load_path, &nt_name, mapping, &image_info, &id, flags, pwm );
break;
case STATUS_DLL_NOT_FOUND: /* no file found, try builtin */
switch (unix_funcs->get_load_order( &nt_name ))
{
case LO_NATIVE_BUILTIN:
case LO_BUILTIN:
case LO_BUILTIN_NATIVE:
case LO_DEFAULT:
nts = load_builtin_dll( load_path, &nt_name, flags, pwm, FALSE );
break;
default:
nts = STATUS_DLL_NOT_FOUND;
break;
}
break;
}
NtCurrentTeb()->Tib.ArbitraryUserPointer = prev;