Investigating a crash at startup

Filip Navara navaraf at reactos.com
Sat Jun 12 12:17:39 CDT 2004


Hi!

One insteresting thing is that OpenOffice does the same and was reported 
to work under Wine. Anyway, an experimental patch is attached (it's 
completely untested).

Regards,
Filip

Phil Krylov wrote:

>Hello,
>
>I have a program here (IBM Translation Manager v.6.0.4) which crashes
>wine at startup. The program loads a DLL, and Wine starts importing
>this DLL's imports from kernel32.dll. It crashes on the first import
>in dlls/ntdll/loader.c:453, which says:
>
>thunk_list->u1.Function = (PDWORD)find_named_export( imp_mod, exports, exp_size,
>                                                     pe_name->Name, pe_name->Hint );
>
>This causes an exception because thunk_list happens to be located in
>.rdata section of the DLL, which is readonly.
>
>Currently I have hacked this around by making all PE sections
>read-write in map_image() in dlls/ntdll/virtual.c, and the program
>works.
>
>If a Wine guru would like to investigate this problem, I can give any
>support (e.g., ssh access to my computer with the program).
>If not - I will be using this hacked version of Wine.
>

-------------- next part --------------
--- dlls/ntdll/loader.c	Tue Apr 20 00:36:30 2004
+++ dlls/ntdll/loader.c	Sat Jun 12 16:23:34 2004
@@ -371,6 +371,9 @@
     WCHAR buffer[32];
     char *name = get_rva( module, descr->Name );
     DWORD len = strlen(name) + 1;
+    PVOID protect_base;
+    DWORD protect_size = 0;
+    DWORD protect_old;
 
     thunk_list = get_rva( module, (DWORD)descr->FirstThunk );
     if (descr->u.OriginalFirstThunk)
@@ -403,6 +406,20 @@
         return NULL;
     }
 
+    /* unprotect the import address table since it can be located in
+     * readonly section */
+    while (import_list[protect_size].u1.Ordinal)
+        protect_size++;
+    protect_base = import_list;
+    protect_size *= sizeof(PVOID *);
+    status = NtProtectVirtualMemory( GetCurrentProcess(), &protect_base,
+                                     &protect_size, PAGE_READWRITE, &protect_old );
+    if (status)
+    {
+        ERR("Can't unprotect IAT for %s\n", name);
+        return NULL;
+    }
+
     imp_mod = wmImp->ldr.BaseAddress;
     exports = RtlImageDirectoryEntryToData( imp_mod, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size );
 
@@ -427,6 +444,11 @@
             import_list++;
             thunk_list++;
         }
+
+        /* restore old protection of the import address table */
+        NtProtectVirtualMemory( GetCurrentProcess(), &protect_base,
+                                &protect_size, protect_old, NULL );
+        
         return wmImp;
     }
 
@@ -463,6 +485,11 @@
         import_list++;
         thunk_list++;
     }
+
+    /* restore old protection of the import address table */
+    NtProtectVirtualMemory( GetCurrentProcess(), &protect_base,
+                            &protect_size, protect_old, NULL );
+    
     return wmImp;
 }
 
--- dlls/ntdll/virtual.c	Tue Apr  6 23:13:48 2004
+++ dlls/ntdll/virtual.c	Sat Jun 12 17:10:06 2004
@@ -511,6 +511,10 @@
                            int delta, DWORD total_size )
 {
     IMAGE_BASE_RELOCATION *rel;
+    NTSTATUS status;
+    PVOID protect_base;
+    DWORD protect_size = page_size;
+    DWORD protect_old;
 
     TRACE_(module)( "relocating from %p-%p to %p-%p\n",
                     base - delta, base - delta + total_size, base, base + total_size );
@@ -537,6 +541,16 @@
 
         TRACE_(module)("%ld relocations for page %lx\n", rel->SizeOfBlock, rel->VirtualAddress);
 
+        /* unprotect the page we're about to relocate */
+        protect_base = page;
+        status = NtProtectVirtualMemory( GetCurrentProcess(), &protect_base,
+                                         &protect_size, PAGE_READWRITE, &protect_old );
+        if (status)
+        {
+            ERR("Can't unprotect page during relocation\n");
+            return 0;
+        }
+
         /* patching in reverse order */
         for (i = 0 ; i < count; i++)
         {
@@ -561,6 +575,10 @@
                 break;
             }
         }
+
+        /* restore old protection */
+        NtProtectVirtualMemory( GetCurrentProcess(), &protect_base,
+                                &protect_size, protect_old, NULL );
     }
     return 1;
 }


More information about the wine-devel mailing list