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; }