From: Oleh Nykyforchyn Subject: [PATCH 2/2] ntdll: make find_builtin_dll load 16 bit dlls. Message-Id: <20211014112845.25330-2-olen.nyk@gmail.com> Date: Thu, 14 Oct 2021 14:28:45 +0300 In-Reply-To: <20211014112845.25330-1-olen.nyk@gmail.com> References: <20211014112845.25330-1-olen.nyk@gmail.com> If NtCreateSection returns STATUS_INVALID_IMAGE_WIN_16 with WineFakeDll flag in image_info, stop search by open_dll_file and replace the status with STATUS_INVALID_IMAGE_NOT_MZ to make find_builtin_dll try .so library instead. Replace "-windows", if found in the path, with "-unix", and append ".so". -- Now Wine can't start any 16 bit app because if fails to load krnl386.exe16. To load any 16 bit dll, ntdll uses find_builtin_without_file -> open_dll_file -> NtCreateSection which makes a request ( create_mapping ) to wineserver, which in turn fails with STATUS_INVALID_IMAGE_WIN_16 and returns no mapping. Upon a previously submitted patch to server, for a fake 16 bit dll create_mapping returns a fake mapping with WineFakeDll flag set. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51564 Signed-off-by: Oleh Nykyforchyn --- dlls/ntdll/loader.c | 65 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 4 deletions(-) diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 797d72aedb6..6befe778c90 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -2315,10 +2315,24 @@ static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, HANDL status = NtCreateSection( mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_EXECUTE, NULL, &size, PAGE_EXECUTE_READ, SEC_IMAGE, handle ); - if (!status) + if (!status || (status == STATUS_INVALID_IMAGE_WIN_16)) { NtQuerySection( *mapping, SectionImageInformation, image_info, sizeof(*image_info), NULL ); - if (!is_valid_binary( handle, image_info )) + if (status == STATUS_INVALID_IMAGE_WIN_16) + { + if ((image_info->DUMMYUNIONNAME.DUMMYSTRUCTNAME.WineFakeDll)) + { + TRACE( "Found fake 16 bit %s, search complete\n", debugstr_us(nt_name)); + } + else + { + TRACE( "%s is 16 bit, but not fake, continuing search\n", debugstr_us(nt_name)); + status = STATUS_IMAGE_MACHINE_TYPE_MISMATCH; + NtClose( *mapping ); + *mapping = NULL; + } + } + else if (!is_valid_binary( handle, image_info )) { TRACE( "%s is for arch %x, continuing search\n", debugstr_us(nt_name), image_info->Machine ); status = STATUS_IMAGE_MACHINE_TYPE_MISMATCH; @@ -2723,15 +2737,19 @@ static NTSTATUS find_builtin_without_file( const WCHAR *name, UNICODE_STRING *ne if (found_image) status = STATUS_IMAGE_MACHINE_TYPE_MISMATCH; done: - RtlFreeUnicodeString( new_name ); + if (!status) { + RtlFreeUnicodeString( new_name ); new_name->Length = (4 + wcslen(system_dir) + wcslen(name)) * sizeof(WCHAR); new_name->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, new_name->Length + sizeof(WCHAR) ); wcscpy( new_name->Buffer, L"\\??\\" ); wcscat( new_name->Buffer, system_dir ); wcscat( new_name->Buffer, name ); } + else if (status != STATUS_INVALID_IMAGE_WIN_16) + RtlFreeUnicodeString( new_name ); + return status; } @@ -2800,7 +2818,7 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, con UNICODE_STRING *nt_name, WINE_MODREF **pwm, HANDLE *mapping, SECTION_IMAGE_INFORMATION *image_info, struct file_id *id ) { - WCHAR *ext, *dllname; + WCHAR *ext, *dllname, *ch; NTSTATUS status; ULONG wow64_old_value = 0; @@ -2854,7 +2872,46 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, con /* 16-bit files can't be loaded from the prefix */ if (status && libname[0] && libname[1] && !wcscmp( libname + wcslen(libname) - 2, L"16" ) && !contains_path( libname )) + { status = find_builtin_without_file( libname, nt_name, pwm, mapping, image_info, id ); + if ((status == STATUS_INVALID_IMAGE_WIN_16) && image_info->DUMMYUNIONNAME.DUMMYSTRUCTNAME.WineFakeDll) + { + TRACE( "Name %s ", debugstr_us(nt_name) ); + ch =wcsstr( nt_name->Buffer, L"-windows\\" ); + if (ch) + { + *(++ch) = L'u'; + *(++ch) = L'n'; + *(++ch) = L'i'; + *(++ch) = L'x'; + ch++; + do *ch = *(ch + 3); + while (*(ch++)); + nt_name->Length -= 3 * sizeof(WCHAR); + } + if ((nt_name->Length < 3 * sizeof(WCHAR)) || wcsncmp( nt_name->Buffer + (nt_name->Length / sizeof(WCHAR) - 3 ), L".so", 3)) + { + if (ch) + { + wcscat( nt_name->Buffer, L".so" ); + nt_name->Length += 3 * sizeof(WCHAR); + } + else + { + if (!(ch = RtlAllocateHeap( GetProcessHeap(), 0, + (nt_name->Length + 4 * sizeof(WCHAR))))) + return STATUS_NO_MEMORY; + wcscpy( ch, nt_name->Buffer ); + wcscat( ch, L".so" ); + RtlFreeHeap( GetProcessHeap(), 0, nt_name->Buffer ); + nt_name->Buffer = ch; + nt_name->Length += 3 * sizeof(WCHAR); + } + } + TRACE( " converted to %s\n", debugstr_us(nt_name) ); + status = STATUS_INVALID_IMAGE_NOT_MZ; + } + } if (status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) status = STATUS_INVALID_IMAGE_FORMAT; -- 2.33.0