diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c index 7795b47..7e3c918 100644 --- a/dlls/kernel32/process.c +++ b/dlls/kernel32/process.c @@ -1082,16 +1082,11 @@ static inline DWORD call_process_entry( PEB *peb, LPTHREAD_START_ROUTINE entry ) * * Startup routine of a new process. Runs on the new process stack. */ -static DWORD WINAPI start_process( PEB *peb ) +static DWORD WINAPI start_process( LPTHREAD_START_ROUTINE entry ) { - IMAGE_NT_HEADERS *nt; - LPTHREAD_START_ROUTINE entry; - - nt = RtlImageNtHeader( peb->ImageBaseAddress ); - entry = (LPTHREAD_START_ROUTINE)((char *)peb->ImageBaseAddress + - nt->OptionalHeader.AddressOfEntryPoint); + PEB *peb = NtCurrentTeb()->Peb; - if (!nt->OptionalHeader.AddressOfEntryPoint) + if (!entry) { ERR( "%s doesn't have an entry point, it cannot be executed\n", debugstr_w(peb->ProcessParameters->ImagePathName.Buffer) ); diff --git a/dlls/mscoree/mscoree_main.c b/dlls/mscoree/mscoree_main.c index 8b46fd5..a76dfc9 100644 --- a/dlls/mscoree/mscoree_main.c +++ b/dlls/mscoree/mscoree_main.c @@ -21,11 +21,14 @@ #include +#include "ntstatus.h" +#define WIN32_NO_STATUS #define COBJMACROS #include "wine/unicode.h" #include "wine/library.h" #include "windef.h" #include "winbase.h" +#include "winternl.h" #include "winuser.h" #include "winnls.h" #include "winreg.h" @@ -257,10 +260,156 @@ VOID WINAPI _CorImageUnloading(PVOID imageBase) TRACE("(%p): stub\n", imageBase); } -HRESULT WINAPI _CorValidateImage(PVOID* imageBase, LPCWSTR imageName) -{ - TRACE("(%p, %s): stub\n", imageBase, debugstr_w(imageName)); - return E_FAIL; +STDAPI _CorValidateImage(PVOID *ImageBase, LPCWSTR FileName) +{ + IMAGE_DOS_HEADER* DosHeader; + IMAGE_NT_HEADERS32* NtHeaders32; + IMAGE_DATA_DIRECTORY* CliHeaderDir; +#ifdef _WIN64 + IMAGE_NT_HEADERS64* NtHeaders64; + IMAGE_COR20_HEADER* CliHeader; + DWORD SizeOfHeaders; +#else + DWORD* Address; +#endif + DWORD OldProtect; + + TRACE("(%p, %s)\n", ImageBase, debugstr_w(FileName)); + + DosHeader = (IMAGE_DOS_HEADER*)*ImageBase; + if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE) + return STATUS_INVALID_IMAGE_FORMAT; + + NtHeaders32 = (IMAGE_NT_HEADERS32*)((DWORD_PTR)DosHeader + DosHeader->e_lfanew); + if (NtHeaders32->Signature != IMAGE_NT_SIGNATURE) + return STATUS_INVALID_IMAGE_FORMAT; + +#ifdef _WIN64 + NtHeaders64 = (IMAGE_NT_HEADERS64*)NtHeaders32; + if (NtHeaders64->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) + { + if (NtHeaders64->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR) + return STATUS_INVALID_IMAGE_FORMAT; + + CliHeaderDir = &NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR]; + if (!CliHeaderDir->VirtualAddress) + return STATUS_INVALID_IMAGE_FORMAT; + + CliHeader = (IMAGE_COR20_HEADER*)((DWORD_PTR)DosHeader + CliHeaderDir->VirtualAddress); + if (CliHeader->Flags & COMIMAGE_FLAGS_32BITREQUIRED) + return STATUS_INVALID_IMAGE_FORMAT; + + return STATUS_SUCCESS; + } + + if (NtHeaders32->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) + return STATUS_INVALID_IMAGE_FORMAT; + + if (NtHeaders32->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR) + return STATUS_INVALID_IMAGE_FORMAT; + + CliHeaderDir = &NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR]; + if (!CliHeaderDir->VirtualAddress) + return STATUS_INVALID_IMAGE_FORMAT; + + CliHeader = (IMAGE_COR20_HEADER*)((DWORD_PTR)DosHeader + CliHeaderDir->VirtualAddress); + if (!(CliHeader->Flags & COMIMAGE_FLAGS_ILONLY) || (CliHeader->Flags & COMIMAGE_FLAGS_32BITREQUIRED)) + return STATUS_INVALID_IMAGE_FORMAT; + + /* Fixup IMAGE_NT_HEADERS32 to IMAGE_NT_HEADERS64. */ + SizeOfHeaders = NtHeaders32->OptionalHeader.SizeOfHeaders; + if (SizeOfHeaders < DosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS64) + (sizeof(IMAGE_SECTION_HEADER) * NtHeaders32->FileHeader.NumberOfSections)) + return STATUS_INVALID_IMAGE_FORMAT; + + if (!VirtualProtect(DosHeader, SizeOfHeaders, PAGE_READWRITE, &OldProtect)) + return E_UNEXPECTED; + + memmove(NtHeaders64 + 1, IMAGE_FIRST_SECTION(NtHeaders32), sizeof(IMAGE_SECTION_HEADER) * NtHeaders32->FileHeader.NumberOfSections); + + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES - 1].Size = 0; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES - 1].VirtualAddress = 0; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].Size = 0; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress = 0; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = 0; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = 0; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].Size = 0; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress = 0; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size = 0; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress = 0; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_GLOBALPTR].Size = 0; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_GLOBALPTR].VirtualAddress = 0; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COPYRIGHT].Size = 0; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COPYRIGHT].VirtualAddress = 0; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = 0; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = 0; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size = 0; + NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = 0; + + NtHeaders64->OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES; + NtHeaders64->OptionalHeader.LoaderFlags = NtHeaders32->OptionalHeader.LoaderFlags; + NtHeaders64->OptionalHeader.SizeOfHeapCommit = (ULONGLONG)NtHeaders32->OptionalHeader.SizeOfHeapCommit; + NtHeaders64->OptionalHeader.SizeOfHeapReserve = (ULONGLONG)NtHeaders32->OptionalHeader.SizeOfHeapReserve; + NtHeaders64->OptionalHeader.SizeOfStackCommit = (ULONGLONG)NtHeaders32->OptionalHeader.SizeOfStackCommit; + NtHeaders64->OptionalHeader.SizeOfStackReserve = (ULONGLONG)NtHeaders32->OptionalHeader.SizeOfStackReserve; + NtHeaders64->OptionalHeader.DllCharacteristics = NtHeaders32->OptionalHeader.DllCharacteristics; + NtHeaders64->OptionalHeader.Subsystem = NtHeaders32->OptionalHeader.Subsystem; + NtHeaders64->OptionalHeader.CheckSum = NtHeaders32->OptionalHeader.CheckSum; + NtHeaders64->OptionalHeader.SizeOfHeaders = NtHeaders32->OptionalHeader.SizeOfHeaders; + NtHeaders64->OptionalHeader.SizeOfImage = NtHeaders32->OptionalHeader.SizeOfImage; + NtHeaders64->OptionalHeader.Win32VersionValue = NtHeaders32->OptionalHeader.Win32VersionValue; + NtHeaders64->OptionalHeader.MinorSubsystemVersion = NtHeaders32->OptionalHeader.MinorSubsystemVersion; + NtHeaders64->OptionalHeader.MajorSubsystemVersion = NtHeaders32->OptionalHeader.MajorSubsystemVersion; + NtHeaders64->OptionalHeader.MinorImageVersion = NtHeaders32->OptionalHeader.MinorImageVersion; + NtHeaders64->OptionalHeader.MajorImageVersion = NtHeaders32->OptionalHeader.MajorImageVersion; + NtHeaders64->OptionalHeader.MinorOperatingSystemVersion = NtHeaders32->OptionalHeader.MinorOperatingSystemVersion; + NtHeaders64->OptionalHeader.MajorOperatingSystemVersion = NtHeaders32->OptionalHeader.MajorOperatingSystemVersion; + NtHeaders64->OptionalHeader.FileAlignment = NtHeaders32->OptionalHeader.FileAlignment; + NtHeaders64->OptionalHeader.SectionAlignment = NtHeaders32->OptionalHeader.SectionAlignment; + NtHeaders64->OptionalHeader.ImageBase = (ULONGLONG)NtHeaders32->OptionalHeader.ImageBase; + /* BaseOfCode is at the same offset. */ + NtHeaders64->OptionalHeader.AddressOfEntryPoint = 0; + NtHeaders64->OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC; + NtHeaders64->FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER64); + + if (!VirtualProtect(DosHeader, SizeOfHeaders, OldProtect, &OldProtect)) + return E_UNEXPECTED; +#else + if (NtHeaders32->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) + return STATUS_INVALID_IMAGE_FORMAT; + + if (NtHeaders32->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR) + return STATUS_INVALID_IMAGE_FORMAT; + + CliHeaderDir = &NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR]; + if (!CliHeaderDir->VirtualAddress) + return STATUS_INVALID_IMAGE_FORMAT; + + Address = &NtHeaders32->OptionalHeader.AddressOfEntryPoint; + if (!VirtualProtect(Address, sizeof(DWORD), PAGE_READWRITE, &OldProtect)) + return E_UNEXPECTED; + if (NtHeaders32->FileHeader.Characteristics & IMAGE_FILE_DLL) + *Address = (DWORD)((DWORD_PTR)&_CorDllMain - (DWORD_PTR)DosHeader); + else + *Address = (DWORD)((DWORD_PTR)&_CorExeMain - (DWORD_PTR)DosHeader); + if (!VirtualProtect(Address, sizeof(DWORD), OldProtect, &OldProtect)) + return E_UNEXPECTED; +#endif + + return STATUS_SUCCESS; } HRESULT WINAPI GetCORSystemDirectory(LPWSTR pbuffer, DWORD cchBuffer, DWORD *dwLength) diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 74feb97..b8d24a2 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -104,6 +104,10 @@ static UINT tls_module_count; /* number of modules with TLS directory */ static IMAGE_TLS_DIRECTORY *tls_dirs; /* array of TLS directories */ LIST_ENTRY tls_links = { &tls_links, &tls_links }; +static HRESULT (WINAPI *p_CorValidateImage)(PVOID* ImageBase, LPCWSTR FileName); +static __int32 (WINAPI *p_CorExeMain)(void); +static BOOL (WINAPI *p_CorDllMain)(HINSTANCE hInst, DWORD dwReason, LPVOID lpReserved); + static RTL_CRITICAL_SECTION loader_section; static RTL_CRITICAL_SECTION_DEBUG critsect_debug = { @@ -337,6 +341,78 @@ static inline ULONG_PTR allocate_stub( const char *dll, const char *name ) { ret /************************************************************************* + * is_cli_only_image + * + * Checks if an image is a CLI/.NET image which does not contain any + * native code. + */ +static BOOL is_cli_only_image( HMODULE image ) +{ + IMAGE_COR20_HEADER *cliheader; + ULONG size; + + cliheader = RtlImageDirectoryEntryToData( image, TRUE, IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, &size ); + if (!cliheader || size < sizeof(*cliheader)) + return FALSE; + + return (cliheader->Flags & COMIMAGE_FLAGS_ILONLY) != 0; +} + + +/************************************************************************* + * load_mscoree + * + * Load _CorValidateImage and the _Cor{Exe,Dll}Main functions from mscoree. + * The loader_section must be locked while calling this function. + */ +static BOOL load_mscoree( void ) +{ + static const WCHAR mscoree_dllW[] = {'m','s','c','o','r','e','e','.','d','l','l',0}; + UNICODE_STRING unicode_str; + ANSI_STRING ansi_str; + HMODULE module; + + if (p_CorValidateImage) + return TRUE; + + RtlInitUnicodeString( &unicode_str, mscoree_dllW ); + if (LdrLoadDll( NULL, LOAD_LIBRARY_SEARCH_SYSTEM32, &unicode_str, &module )) + { + ERR( "Failed to load mscoree.dll\n" ); + return FALSE; + } + + /* Load _CorValidateImage */ + RtlInitAnsiString( &ansi_str, "_CorValidateImage" ); + if (LdrGetProcedureAddress( module, &ansi_str, 0, (void **)&p_CorValidateImage) ) + { + ERR( "Failed to get import for _CorValidateImage\n" ); + LdrUnloadDll( module ); + return FALSE; + } + + /* Load _CorExeMain */ + RtlInitAnsiString( &ansi_str, "_CorExeMain" ); + if (LdrGetProcedureAddress( module, &ansi_str, 0, (void **)&p_CorExeMain) ) + { + ERR( "Failed to get import for _CorExeMain\n" ); + p_CorExeMain = NULL; + } + + /* Load _CorDllMain */ + RtlInitAnsiString( &ansi_str, "_CorDllMain" ); + if (LdrGetProcedureAddress( module, &ansi_str, 0, (void **)&p_CorDllMain) ) + { + ERR( "Failed to get import for _CorDllMain\n" ); + p_CorDllMain = NULL; + } + + /* FIXME: Unload mscoree again when no longer needed */ + return TRUE; +} + + +/************************************************************************* * get_modref * * Looks for the referenced HMODULE in the current process @@ -875,6 +951,10 @@ static NTSTATUS fixup_imports( WINE_MODREF *wm, LPCWSTR load_path ) if (!(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS)) return STATUS_SUCCESS; /* already done */ wm->ldr.Flags &= ~LDR_DONT_RESOLVE_REFS; + /* For a CLI-only image there is nothing to do. Do not allocate a TLS slot + * and do not resolve any external dependencies. */ + if (is_cli_only_image( wm->ldr.BaseAddress )) return STATUS_SUCCESS; + wm->ldr.TlsIndex = alloc_tls_slot( &wm->ldr ); if (!(imports = RtlImageDirectoryEntryToData( wm->ldr.BaseAddress, TRUE, @@ -1082,8 +1162,43 @@ static NTSTATUS MODULE_InitDLL( WINE_MODREF *wm, UINT reason, LPVOID lpReserved BOOL retv = FALSE; /* Skip calls for modules loaded with special load flags */ - if (wm->ldr.Flags & LDR_DONT_RESOLVE_REFS) return STATUS_SUCCESS; + + /* Yes, Windows also has hardcoded exceptions for mscoree in ntdll */ + if (is_cli_only_image( module )) + { + #ifndef __x86_64__ + IMAGE_NT_HEADERS *nt = RtlImageNtHeader( module ); + #endif + + if (reason == DLL_WINE_PREATTACH) + return STATUS_SUCCESS; + + if (reason == DLL_PROCESS_ATTACH) + { + HRESULT hr; + + if (!load_mscoree()) + return STATUS_DLL_INIT_FAILED; + + hr = p_CorValidateImage( &module, wm->ldr.FullDllName.Buffer ); + if (hr) + { + ERR( "failed to validate CLI image, error 0x%x\n", hr ); + wm->ldr.EntryPoint = NULL; + return STATUS_DLL_INIT_FAILED; + } + + #ifdef __x86_64__ + wm->ldr.EntryPoint = (wm->ldr.Flags & LDR_IMAGE_IS_DLL) ? + (void *)p_CorDllMain : (void *)p_CorExeMain; + #else + wm->ldr.EntryPoint = (char *)module + nt->OptionalHeader.AddressOfEntryPoint; + #endif + entry = wm->ldr.EntryPoint; + } + } + if (wm->ldr.TlsIndex != -1) call_tls_callbacks( wm->ldr.BaseAddress, reason ); if (!entry || !(wm->ldr.Flags & LDR_IMAGE_IS_DLL)) return STATUS_SUCCESS; @@ -3037,7 +3152,20 @@ static void load_global_options(void) */ static void start_process( void *kernel_start ) { - call_thread_entry_point( kernel_start, NtCurrentTeb()->Peb ); + IMAGE_NT_HEADERS *nt; + LPTHREAD_START_ROUTINE entry; + PEB *peb = NtCurrentTeb()->Peb; + + nt = RtlImageNtHeader( peb->ImageBaseAddress ); + entry = (LPTHREAD_START_ROUTINE)((char *)peb->ImageBaseAddress + + nt->OptionalHeader.AddressOfEntryPoint); + +#ifdef __x86_64__ + if (is_cli_only_image( peb->ImageBaseAddress )) + entry = (LPTHREAD_START_ROUTINE)p_CorExeMain; +#endif + + call_thread_entry_point( kernel_start, entry ); } /****************************************************************** diff --git a/server/mapping.c b/server/mapping.c index f66f326..7c31c1a 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -411,8 +411,8 @@ static unsigned int get_image_params( struct mapping *mapping, int unix_fd, int if (nt.opt.hdr32.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) return STATUS_INVALID_IMAGE_FORMAT; break; case CPU_x86_64: - if (nt.FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64) return STATUS_INVALID_IMAGE_FORMAT; - if (nt.opt.hdr64.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) return STATUS_INVALID_IMAGE_FORMAT; + //if (nt.FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64) return STATUS_INVALID_IMAGE_FORMAT; + //if (nt.opt.hdr64.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) return STATUS_INVALID_IMAGE_FORMAT; break; case CPU_POWERPC: if (nt.FileHeader.Machine != IMAGE_FILE_MACHINE_POWERPC) return STATUS_INVALID_IMAGE_FORMAT;