Alexandre Julliard : ntdll: Load the COR header directly from the file handle.
Alexandre Julliard
julliard at winehq.org
Mon Jan 25 16:42:05 CST 2021
Module: wine
Branch: master
Commit: 7203ad0ecd06b451116fcfe3b08e4d620e853bd5
URL: https://source.winehq.org/git/wine.git/?a=commit;h=7203ad0ecd06b451116fcfe3b08e4d620e853bd5
Author: Alexandre Julliard <julliard at winehq.org>
Date: Thu Jan 21 12:31:34 2021 +0100
ntdll: Load the COR header directly from the file handle.
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ntdll/loader.c | 63 ++++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 53 insertions(+), 10 deletions(-)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 3f43062f9f8..fa757fefa90 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -2016,11 +2016,49 @@ static BOOL convert_to_pe64( HMODULE module, const SECTION_IMAGE_INFORMATION *in
NtProtectVirtualMemory( NtCurrentProcess(), &addr, &size, old_prot, &old_prot );
return TRUE;
}
+
+/* check COM header for ILONLY flag, ignoring runtime version */
+static BOOL get_cor_header( HANDLE file, const SECTION_IMAGE_INFORMATION *info, IMAGE_COR20_HEADER *cor )
+{
+ IMAGE_DOS_HEADER mz;
+ IMAGE_NT_HEADERS32 nt;
+ IO_STATUS_BLOCK io;
+ LARGE_INTEGER offset;
+ IMAGE_SECTION_HEADER sec[96];
+ unsigned int i, count;
+ DWORD va, size;
+
+ offset.QuadPart = 0;
+ if (NtReadFile( file, 0, NULL, NULL, &io, &mz, sizeof(mz), &offset, NULL )) return FALSE;
+ if (io.Information != sizeof(mz)) return FALSE;
+ if (mz.e_magic != IMAGE_DOS_SIGNATURE) return FALSE;
+ offset.QuadPart = mz.e_lfanew;
+ if (NtReadFile( file, 0, NULL, NULL, &io, &nt, sizeof(nt), &offset, NULL )) return FALSE;
+ if (io.Information != sizeof(nt)) return FALSE;
+ if (nt.Signature != IMAGE_NT_SIGNATURE) return FALSE;
+ if (nt.OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) return FALSE;
+ va = nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
+ size = nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size;
+ if (!va || size < sizeof(*cor)) return FALSE;
+ offset.QuadPart = offsetof( IMAGE_NT_HEADERS32, OptionalHeader ) + nt.FileHeader.SizeOfOptionalHeader;
+ count = min( 96, nt.FileHeader.NumberOfSections );
+ if (NtReadFile( file, 0, NULL, NULL, &io, &sec, count * sizeof(*sec), &offset, NULL )) return FALSE;
+ if (io.Information != count * sizeof(*sec)) return FALSE;
+ for (i = 0; i < count; i++)
+ {
+ if (va < sec[i].VirtualAddress) continue;
+ if (sec[i].Misc.VirtualSize && va - sec[i].VirtualAddress >= sec[i].Misc.VirtualSize) continue;
+ offset.QuadPart = sec->PointerToRawData + va - sec[i].VirtualAddress;
+ if (NtReadFile( file, 0, NULL, NULL, &io, cor, sizeof(*cor), &offset, NULL )) return FALSE;
+ return (io.Information == sizeof(*cor));
+ }
+ return FALSE;
+}
#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 */
-static BOOL is_valid_binary( HMODULE module, const SECTION_IMAGE_INFORMATION *info )
+static BOOL is_valid_binary( HANDLE file, const SECTION_IMAGE_INFORMATION *info )
{
#ifdef __i386__
return info->Machine == IMAGE_FILE_MACHINE_I386;
@@ -2037,13 +2075,11 @@ static BOOL is_valid_binary( HMODULE module, const SECTION_IMAGE_INFORMATION *in
if (!info->ImageContainsCode) return TRUE;
if (!(info->u.ImageFlags & IMAGE_FLAGS_ComPlusNativeReady))
{
- /* check COM header directly, ignoring runtime version */
- DWORD size;
- const IMAGE_COR20_HEADER *cor_header = RtlImageDirectoryEntryToData( module, TRUE,
- IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, &size );
- if (!cor_header || !(cor_header->Flags & COMIMAGE_FLAGS_ILONLY)) return FALSE;
+ IMAGE_COR20_HEADER cor_header;
+ if (!get_cor_header( file, info, &cor_header )) return FALSE;
+ if (!(cor_header.Flags & COMIMAGE_FLAGS_ILONLY)) return FALSE;
}
- return convert_to_pe64( module, info );
+ return TRUE;
#else
return FALSE; /* no wow64 support on other platforms */
#endif
@@ -2267,8 +2303,6 @@ static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, void
status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY |
SECTION_MAP_READ | SECTION_MAP_EXECUTE,
NULL, &size, PAGE_EXECUTE_READ, SEC_IMAGE, handle );
- NtClose( handle );
-
if (!status)
{
if (*module)
@@ -2282,13 +2316,22 @@ static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, void
if (status == STATUS_IMAGE_NOT_AT_BASE) status = STATUS_SUCCESS;
NtClose( mapping );
}
- if (!status && !is_valid_binary( *module, image_info ))
+ if (!status && !is_valid_binary( handle, image_info ))
{
TRACE( "%s is for arch %x, continuing search\n", debugstr_us(nt_name), image_info->Machine );
NtUnmapViewOfSection( NtCurrentProcess(), *module );
*module = NULL;
status = STATUS_IMAGE_MACHINE_TYPE_MISMATCH;
}
+#ifdef _WIN64
+ if (!status &&
+ image_info->Machine != IMAGE_FILE_MACHINE_AMD64 &&
+ image_info->Machine != IMAGE_FILE_MACHINE_ARM64)
+ {
+ if (!convert_to_pe64( *module, image_info )) status = STATUS_INVALID_IMAGE_FORMAT;
+ }
+#endif
+ NtClose( handle );
return status;
}
More information about the wine-cvs
mailing list