If request ( create_mapping ) returns STATUS_IMAGE_INVALID_WIN_16 for a file, then the search fails, but STATUS_IMAGE_INVALID_NOT_MZ triggers attempt to load *.so file instead in ntdll. It allows to run 16 bin applications again.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51564 Signed-off-by: Oleh Nykyforchyn oleh.nyk@gmail.com --- server/mapping.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/server/mapping.c b/server/mapping.c index 93dae94b7c4..af9e92fcf25 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -697,6 +697,13 @@ static unsigned int get_image_params( struct mapping *mapping, file_pos_t file_s mz_size = size; pos = mz.dos.e_lfanew;
+ mapping->image.image_flags = 0; + mapping->image.loader_flags = 0; + if (mz_size == sizeof(mz) && !memcmp( mz.buffer, builtin_signature, sizeof(builtin_signature) )) + mapping->image.image_flags |= IMAGE_FLAGS_WineBuiltin; + else if (mz_size == sizeof(mz) && !memcmp( mz.buffer, fakedll_signature, sizeof(fakedll_signature) )) + mapping->image.image_flags |= IMAGE_FLAGS_WineFakeDll; + size = pread( unix_fd, &nt, sizeof(nt), pos ); if (size < sizeof(nt.Signature) + sizeof(nt.FileHeader)) return STATUS_INVALID_IMAGE_PROTECT; /* zero out Optional header in the case it's not present or partial */ @@ -707,7 +714,13 @@ static unsigned int get_image_params( struct mapping *mapping, file_pos_t file_s { IMAGE_OS2_HEADER *os2 = (IMAGE_OS2_HEADER *)&nt; if (os2->ne_magic != IMAGE_OS2_SIGNATURE) return STATUS_INVALID_IMAGE_PROTECT; - if (os2->ne_exetyp == 2) return STATUS_INVALID_IMAGE_WIN_16; + if (os2->ne_exetyp == 2) + { + if (mapping->image.image_flags & IMAGE_FLAGS_WineFakeDll) + return STATUS_INVALID_IMAGE_NOT_MZ; + else + return STATUS_INVALID_IMAGE_WIN_16; + } if (os2->ne_exetyp == 5) return STATUS_INVALID_IMAGE_PROTECT; return STATUS_INVALID_IMAGE_NE_FORMAT; } @@ -737,7 +750,6 @@ static unsigned int get_image_params( struct mapping *mapping, file_pos_t file_s nt.opt.hdr32.SectionAlignment & page_mask); mapping->image.header_size = nt.opt.hdr32.SizeOfHeaders; mapping->image.checksum = nt.opt.hdr32.CheckSum; - mapping->image.image_flags = 0; if (nt.opt.hdr32.SectionAlignment & page_mask) mapping->image.image_flags |= IMAGE_FLAGS_ImageMappedFlat; if ((nt.opt.hdr32.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) && @@ -769,7 +781,6 @@ static unsigned int get_image_params( struct mapping *mapping, file_pos_t file_s nt.opt.hdr64.SectionAlignment & page_mask); mapping->image.header_size = nt.opt.hdr64.SizeOfHeaders; mapping->image.checksum = nt.opt.hdr64.CheckSum; - mapping->image.image_flags = 0; if (nt.opt.hdr64.SectionAlignment & page_mask) mapping->image.image_flags |= IMAGE_FLAGS_ImageMappedFlat; if ((nt.opt.hdr64.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) && @@ -788,10 +799,6 @@ static unsigned int get_image_params( struct mapping *mapping, file_pos_t file_s mapping->image.zerobits = 0; /* FIXME */ mapping->image.file_size = file_size; mapping->image.loader_flags = clr_va && clr_size; - if (mz_size == sizeof(mz) && !memcmp( mz.buffer, builtin_signature, sizeof(builtin_signature) )) - mapping->image.image_flags |= IMAGE_FLAGS_WineBuiltin; - else if (mz_size == sizeof(mz) && !memcmp( mz.buffer, fakedll_signature, sizeof(fakedll_signature) )) - mapping->image.image_flags |= IMAGE_FLAGS_WineFakeDll;
/* load the section headers */
Don't release nt_name in find_builtin_without_file for STATUS_INVALID_IMAGE_NOT_MZ and use it to try to load *.so instead of 16 bit fake dll, 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, hence nt_name of the fake dll is cleared.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51564 Signed-off-by: Oleh Nykyforchyn oleh.nyk@gmail.com --- dlls/ntdll/loader.c | 48 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 797d72aedb6..d731b474e41 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -2723,15 +2723,17 @@ 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_NOT_MZ) + RtlFreeUnicodeString( new_name ); return status; }
@@ -2783,7 +2785,8 @@ static NTSTATUS search_dll_file( LPCWSTR paths, LPCWSTR search, UNICODE_STRING * if (found_image) status = STATUS_IMAGE_MACHINE_TYPE_MISMATCH; else if (is_prefix_bootstrap && !contains_path( search )) - status = find_builtin_without_file( search, nt_name, pwm, mapping, image_info, id ); + if ((status = find_builtin_without_file( search, nt_name, pwm, mapping, image_info, id ))) + RtlFreeUnicodeString( nt_name );
done: RtlFreeHeap( GetProcessHeap(), 0, name ); @@ -2800,7 +2803,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 +2857,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_NOT_MZ) + { + 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); + } + } + } + else + RtlFreeUnicodeString( nt_name ); + + }
if (status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) status = STATUS_INVALID_IMAGE_FORMAT;