Alexandre Julliard : ntdll: Convert PE header to 64-bit when loading a 32-bit IL-only module.

Alexandre Julliard julliard at winehq.org
Thu Oct 25 15:24:35 CDT 2018


Module: wine
Branch: master
Commit: 926dd780697852b375ec0a193c762e7723a3f5e6
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=926dd780697852b375ec0a193c762e7723a3f5e6

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Oct 25 13:48:46 2018 +0200

ntdll: Convert PE header to 64-bit when loading a 32-bit IL-only module.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/loader.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 51 insertions(+), 6 deletions(-)

diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 31168c0..c5e8d0d 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -1921,6 +1921,51 @@ static NTSTATUS perform_relocations( void *module, SIZE_T len )
     return STATUS_SUCCESS;
 }
 
+#ifdef _WIN64
+/* convert PE header to 64-bit when loading a 32-bit IL-only module into a 64-bit process */
+static BOOL convert_to_pe64( HMODULE module, const pe_image_info_t *info )
+{
+    static const ULONG copy_dirs[] = { IMAGE_DIRECTORY_ENTRY_RESOURCE,
+                                       IMAGE_DIRECTORY_ENTRY_SECURITY,
+                                       IMAGE_DIRECTORY_ENTRY_BASERELOC,
+                                       IMAGE_DIRECTORY_ENTRY_DEBUG,
+                                       IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR };
+    IMAGE_OPTIONAL_HEADER32 hdr32 = { IMAGE_NT_OPTIONAL_HDR32_MAGIC };
+    IMAGE_OPTIONAL_HEADER64 hdr64 = { IMAGE_NT_OPTIONAL_HDR64_MAGIC };
+    IMAGE_NT_HEADERS *nt = RtlImageNtHeader( module );
+    SIZE_T hdr_size = min( sizeof(hdr32), nt->FileHeader.SizeOfOptionalHeader );
+    IMAGE_SECTION_HEADER *sec = (IMAGE_SECTION_HEADER *)((char *)&nt->OptionalHeader + hdr_size);
+    SIZE_T size = (char *)(nt + 1) + nt->FileHeader.NumberOfSections * sizeof(*sec) - (char *)module;
+    void *addr = module;
+    ULONG i, old_prot;
+
+    TRACE( "%p\n", module );
+
+    if (size > info->header_size) return FALSE;
+    if (NtProtectVirtualMemory( NtCurrentProcess(), &addr, &size, PAGE_READWRITE, &old_prot ))
+        return FALSE;
+
+    memcpy( &hdr32, &nt->OptionalHeader, hdr_size );
+    memcpy( &hdr64, &hdr32, offsetof( IMAGE_OPTIONAL_HEADER64, SizeOfStackReserve ));
+    hdr64.Magic               = IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+    hdr64.AddressOfEntryPoint = 0;
+    hdr64.ImageBase           = hdr32.ImageBase;
+    hdr64.SizeOfStackReserve  = hdr32.SizeOfStackReserve;
+    hdr64.SizeOfStackCommit   = hdr32.SizeOfStackCommit;
+    hdr64.SizeOfHeapReserve   = hdr32.SizeOfHeapReserve;
+    hdr64.SizeOfHeapCommit    = hdr32.SizeOfHeapCommit;
+    hdr64.LoaderFlags         = hdr32.LoaderFlags;
+    hdr64.NumberOfRvaAndSizes = hdr32.NumberOfRvaAndSizes;
+    for (i = 0; i < ARRAY_SIZE( copy_dirs ); i++)
+        hdr64.DataDirectory[copy_dirs[i]] = hdr32.DataDirectory[copy_dirs[i]];
+
+    memmove( nt + 1, sec, nt->FileHeader.NumberOfSections * sizeof(*sec) );
+    nt->FileHeader.SizeOfOptionalHeader = sizeof(hdr64);
+    nt->OptionalHeader = hdr64;
+    NtProtectVirtualMemory( NtCurrentProcess(), &addr, &size, old_prot, &old_prot );
+    return TRUE;
+}
+#endif
 
 /* On WoW64 setups, an image mapping can also be created for the other 32/64 CPU */
 /* but it cannot necessarily be loaded as a dll, so we need some additional checks */
@@ -1932,18 +1977,18 @@ static BOOL is_valid_binary( HMODULE module, const pe_image_info_t *info )
     return info->machine == IMAGE_FILE_MACHINE_ARM ||
            info->machine == IMAGE_FILE_MACHINE_THUMB ||
            info->machine == IMAGE_FILE_MACHINE_ARMNT;
-#elif defined(__x86_64__) || defined(__aarch64__)  /* support 32-bit IL-only images on 64-bit */
-    const IMAGE_COR20_HEADER *cor_header;
-    DWORD size;
-
+#elif defined(_WIN64)  /* support 32-bit IL-only images on 64-bit */
 #ifdef __x86_64__
     if (info->machine == IMAGE_FILE_MACHINE_AMD64) return TRUE;
 #else
     if (info->machine == IMAGE_FILE_MACHINE_ARM64) return TRUE;
 #endif
     if (!info->contains_code) return TRUE;
-    cor_header = RtlImageDirectoryEntryToData( module, TRUE, IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, &size );
-    if (cor_header && (cor_header->Flags & COMIMAGE_FLAGS_ILONLY)) return TRUE;
+    if (info->image_flags & IMAGE_FLAGS_ComPlusNativeReady)
+    {
+        if (!convert_to_pe64( module, info )) return FALSE;
+    }
+    if (info->image_flags & IMAGE_FLAGS_ComPlusILOnly) return TRUE;
     return FALSE;
 #else
     return FALSE;  /* no wow64 support on other platforms */




More information about the wine-cvs mailing list