Module: wine Branch: master Commit: f55a5812edb255d0a2f1f15ecc3d8b99df09fe97 URL: https://gitlab.winehq.org/wine/wine/-/commit/f55a5812edb255d0a2f1f15ecc3d8b9...
Author: Alexandre Julliard julliard@winehq.org Date: Tue May 9 11:59:13 2023 +0200
ntdll: Add a helper function to read a PE image directory.
---
dlls/ntdll/loader.c | 79 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 27 deletions(-)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 5a53f4bcb9d..a4f87a3e4c3 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -2255,43 +2255,73 @@ static BOOL convert_to_pe64( HMODULE module, const SECTION_IMAGE_INFORMATION *in 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 ) +/* read data out of a PE image directory */ +static ULONG read_image_directory( HANDLE file, const SECTION_IMAGE_INFORMATION *info, + ULONG dir, void *buffer, ULONG maxlen, USHORT *magic ) { 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; + union + { + IMAGE_NT_HEADERS32 nt32; + IMAGE_NT_HEADERS64 nt64; + } nt;
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; + if (NtReadFile( file, 0, NULL, NULL, &io, &mz, sizeof(mz), &offset, NULL )) return 0; + if (io.Information != sizeof(mz)) return 0; + if (mz.e_magic != IMAGE_DOS_SIGNATURE) return 0; 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; + if (NtReadFile( file, 0, NULL, NULL, &io, &nt, sizeof(nt), &offset, NULL )) return 0; + if (io.Information != sizeof(nt)) return 0; + if (nt.nt32.Signature != IMAGE_NT_SIGNATURE) return 0; + *magic = nt.nt32.OptionalHeader.Magic; + switch (nt.nt32.OptionalHeader.Magic) + { + case IMAGE_NT_OPTIONAL_HDR32_MAGIC: + va = nt.nt32.OptionalHeader.DataDirectory[dir].VirtualAddress; + size = nt.nt32.OptionalHeader.DataDirectory[dir].Size; + break; + case IMAGE_NT_OPTIONAL_HDR64_MAGIC: + va = nt.nt64.OptionalHeader.DataDirectory[dir].VirtualAddress; + size = nt.nt64.OptionalHeader.DataDirectory[dir].Size; + break; + default: + return 0; + } + if (!va) return 0; + offset.QuadPart += offsetof( IMAGE_NT_HEADERS32, OptionalHeader ) + nt.nt32.FileHeader.SizeOfOptionalHeader; + count = min( 96, nt.nt32.FileHeader.NumberOfSections ); + if (NtReadFile( file, 0, NULL, NULL, &io, &sec, count * sizeof(*sec), &offset, NULL )) return 0; + if (io.Information != count * sizeof(*sec)) return 0; 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[i].PointerToRawData + va - sec[i].VirtualAddress; - if (NtReadFile( file, 0, NULL, NULL, &io, cor, sizeof(*cor), &offset, NULL )) return FALSE; - return (io.Information == sizeof(*cor)); + if (NtReadFile( file, 0, NULL, NULL, &io, buffer, min( maxlen, size ), &offset, NULL )) return 0; + return io.Information; } - return FALSE; + return 0; } + +/* check COM header for ILONLY flag, ignoring runtime version */ +static BOOL is_com_ilonly( HANDLE file, const SECTION_IMAGE_INFORMATION *info ) +{ + USHORT magic; + IMAGE_COR20_HEADER cor_header; + ULONG len = read_image_directory( file, info, IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, + &cor_header, sizeof(cor_header), &magic ); + + if (len != sizeof(cor_header)) return FALSE; + if (magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) return FALSE; + return !!(cor_header.Flags & COMIMAGE_FLAGS_ILONLY); +} + #endif
/* On WoW64 setups, an image mapping can also be created for the other 32/64 CPU */ @@ -2312,13 +2342,8 @@ static BOOL is_valid_binary( HANDLE file, const SECTION_IMAGE_INFORMATION *info #endif if (NtCurrentTeb()->WowTebOffset) return TRUE; if (!info->ImageContainsCode) return TRUE; - if (!(info->u.s.ComPlusNativeReady)) - { - 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 TRUE; + if (info->u.s.ComPlusNativeReady) return TRUE; + return is_com_ilonly( file, info ); #else return FALSE; /* no wow64 support on other platforms */ #endif