Now with the correct patch...
- Filip
Filip Navara wrote:
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.
--- 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 = thunk_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;
}