[PATCH 2/2] ntdll: make find_builtin_dll load 16 bit dlls.

Oleh Nykyforchyn oleh.nyk at gmail.com
Thu Oct 14 06:28:45 CDT 2021


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 <oleh.nyk at gmail.com>
---
 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




More information about the wine-devel mailing list