Did you mean something like the below? This also fixes my test case - but I feel like my original patch was a lot safer (obviously the 'imports' reference should be fixed regardless).
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c index af1509eae5d..9be494ba57f 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -1364,7 +1364,7 @@ static NTSTATUS map_image( HANDLE hmapping, ACCESS_MASK access, int fd, SIZE_T m IMAGE_NT_HEADERS *nt; IMAGE_SECTION_HEADER sections[96]; IMAGE_SECTION_HEADER *sec; - IMAGE_DATA_DIRECTORY *imports; + IMAGE_DATA_DIRECTORY *imports = NULL; NTSTATUS status = STATUS_CONFLICTING_ADDRESSES; SIZE_T header_size, total_size = image_info->map_size; int i; @@ -1423,7 +1423,47 @@ static NTSTATUS map_image( HANDLE hmapping, ACCESS_MASK access, int fd, SIZE_T m memcpy(sections, header_start, sizeof(*sections) * nt->FileHeader.NumberOfSections); sec = sections;
- imports = nt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_IMPORT; + if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC && is_win64 && + !(nt->FileHeader.Characteristics & IMAGE_FILE_DLL)) { + IMAGE_OPTIONAL_HEADER32 *hdr32 = (IMAGE_OPTIONAL_HEADER32 *) &nt->OptionalHeader; + /* check if there is room in the header for generating a PE64 header, + * if not - we'll leave it and hope for the best */ + if (header_start + sizeof(IMAGE_OPTIONAL_HEADER64) - sizeof(IMAGE_OPTIONAL_HEADER32) + + sizeof(*sections) * nt->FileHeader.NumberOfSections <= header_end) { + /* We'll convert the IMAGE_OPTIONAL_HEADER32 to IMAGE_OPTIONAL_HEADER64 + * we'll splat the sections area - but this was just copied. + * we copy from back to front so we don't splat the data we still need */ + memmove(nt->OptionalHeader.DataDirectory, hdr32->DataDirectory, + hdr32->NumberOfRvaAndSizes * sizeof(hdr32->DataDirectory[0])); + nt->OptionalHeader.NumberOfRvaAndSizes = hdr32->NumberOfRvaAndSizes; + nt->OptionalHeader.LoaderFlags = hdr32->LoaderFlags; + nt->OptionalHeader.SizeOfHeapCommit = hdr32->SizeOfHeapCommit; + nt->OptionalHeader.SizeOfHeapReserve = hdr32->SizeOfHeapReserve; + nt->OptionalHeader.SizeOfStackCommit = hdr32->SizeOfStackCommit; + nt->OptionalHeader.SizeOfStackReserve = hdr32->SizeOfStackReserve; + nt->OptionalHeader.ImageBase = hdr32->ImageBase; + /* the rest of the values align between the 32bit and 64bit optional header */ + + /* update the magic value and the size of optional header */ + nt->OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC; + nt->FileHeader.SizeOfOptionalHeader += sizeof(IMAGE_OPTIONAL_HEADER64) + - sizeof(IMAGE_OPTIONAL_HEADER32); + + /* copy the sections back + * Will this will break apps that map over the top of the section headers? + * (hopefully none of these are 32bit .NET/Mono apps anyway) */ + memcpy((char*)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader, + sections, sizeof(*sections) * nt->FileHeader.NumberOfSections); + } else { + /* even though we can't create a PE64 header, we can still make sure + * imports points to the correct location */ + imports = hdr32->DataDirectory + IMAGE_DIRECTORY_ENTRY_IMPORT; + } + } + + if (!imports) + imports = nt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_IMPORT; + if (!imports->Size || !imports->VirtualAddress) imports = NULL;
/* check for non page-aligned binary */
On 19/10/18 5:32 am, Alexandre Julliard wrote:
Brendan McGrath brendan@redmandi.com writes:
But if you run: wine64 mono32
you get the Out of Memory error that is fixed by this patch. Applying this patch allows these applications to work as they currently do under Windows.
For .NET binaries this should be solved by generating a PE64 header to replace the PE32 one.