[PATCH] mscoree: Implement VTable fixup for x86_64 architecture.

Vincent Povirk madewokherd at gmail.com
Thu Jan 21 16:32:40 CST 2016


I took a different approach to testing this, and it doesn't seem to be
working quite right.

Instead of building x64 class dll's, I hacked something together based
on wine-staging's related patches, mono's implementation of
_CorValidateImage, and disabling a check in wineserver. I'm attaching
a diff of that.

Instead of working around managed c++ issues, I looked for a way to
use dll fixups more directly from a C# library:
https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports

So I have a C# dll that exports an "add" function, like the example,
and a win32 console exe that calls it via LoadLibrary/GetProcAddress.
On Windows, I can call it multiple times and then exit with no
problems. In Wine with your patch, everything works except that the
result is incorrect the first time add() is called. I suspect
ReallyFixupVTable is changing some registers, and the thunk will have
to preserve them.

Thanks for working on this, by the way. Seeing this *almost* work even
for a simple test case is very cool. :)
-------------- next part --------------
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 <stdarg.h>
 
+#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;


More information about the wine-devel mailing list