calling dll native entry point for mixed assemblies

Paul Gofman gofmanp at gmail.com
Tue Jan 26 13:42:56 CST 2016


Hi Vincent,

    thank you for your help so far and sorry for disturbing you with my
patches again so soon.
    While looking a bit further into my app under Wine I found out that
some mixed assemblies are completely broken under Wine/Mono due to the
fact that native entry point is not called at all. It relates to both 32
bit and 64 bit. 32 bit works fine under native MS .Net which apparently
does call the entry point. The entry point address is present in
IMAGE_COR20_HEADER (when appropriate flag is set in Flags member). It is
DllMain-type entry point having the same parameters. This entry point
does static initialization, e. g. calls all the constructors for static
classes.
    I am attaching preliminary patch to illustrate what I am talking
about. It would be great if you could give some high level feedback on
whether you like the idea of doing this in general before I will be
spamming it to wine-patches.
   
    The potential issue which I can imagine with it is that if there are
some old apps (built with VS 2003) which called CLR code in native init
but by chance worked if native init was not called at all, may stop
working. MSDN says that such apps could non-deterministically deadlock
when loaded; with Wine/Mono they will lock deterministically I think (
https://msdn.microsoft.com/en-us/library/ms173266.aspx). Still I suppose
the issue with entry point should be addressed somehow since it affects
"normal" newer applications.

Regards,
    Paul.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.winehq.org/pipermail/wine-devel/attachments/20160126/08938f34/attachment.html>
-------------- next part --------------
From 6c720fff06854273c55b305bf181dcdae92e6f8e Mon Sep 17 00:00:00 2001
From: Paul Gofman <gofmanp at gmail.com>
Date: Tue, 26 Jan 2016 21:18:07 +0300
Subject: [PATCH] mscoree: call native DllEntryPoint when it is defined in COR
 header.

Signed-off-by: Paul Gofman <gofmanp at gmail.com>
---
 dlls/mscoree/assembly.c        | 14 ++++++++++++++
 dlls/mscoree/corruntimehost.c  | 43 ++++++++++++++++++++++++++++++++----------
 dlls/mscoree/mscoree_private.h |  3 +++
 include/winnt.h                |  1 +
 4 files changed, 51 insertions(+), 10 deletions(-)

diff --git a/dlls/mscoree/assembly.c b/dlls/mscoree/assembly.c
index 7cfc359..4af6f28 100644
--- a/dlls/mscoree/assembly.c
+++ b/dlls/mscoree/assembly.c
@@ -314,3 +314,17 @@ HRESULT assembly_get_vtable_fixups(ASSEMBLY *assembly, VTableFixup **fixups, DWO
 
     return S_OK;
 }
+
+HRESULT assembly_get_native_entrypoint(ASSEMBLY *assembly, NativeEntryPointFunc *func)
+{
+    if (assembly->corhdr->Flags & COMIMAGE_FLAGS_NATIVE_ENTRYPOINT)
+    {
+        *func = assembly_rva_to_va(assembly, assembly->corhdr->EntryPointRVA);
+        return S_OK;
+    }
+    else
+    {
+        *func = NULL;
+        return S_FALSE;
+    }
+}
diff --git a/dlls/mscoree/corruntimehost.c b/dlls/mscoree/corruntimehost.c
index c790c44..1aeb937 100644
--- a/dlls/mscoree/corruntimehost.c
+++ b/dlls/mscoree/corruntimehost.c
@@ -1135,23 +1135,28 @@ static void FixupVTableEntry(HMODULE hmodule, VTableFixup *vtable_fixup)
     list_add_tail(&dll_fixups, &fixup->entry);
 }
 
+static void FixupVTable_Assembly(HMODULE hmodule, ASSEMBLY *assembly)
+{
+    VTableFixup *vtable_fixups;
+    ULONG vtable_fixup_count, i;
+
+    assembly_get_vtable_fixups(assembly, &vtable_fixups, &vtable_fixup_count);
+    if (CAN_FIXUP_VTABLE)
+        for (i=0; i<vtable_fixup_count; i++)
+            FixupVTableEntry(hmodule, &vtable_fixups[i]);
+    else if (vtable_fixup_count)
+        FIXME("cannot fixup vtable; expect a crash\n");
+}
+
 static void FixupVTable(HMODULE hmodule)
 {
     ASSEMBLY *assembly;
     HRESULT hr;
-    VTableFixup *vtable_fixups;
-    ULONG vtable_fixup_count, i;
 
     hr = assembly_from_hmodule(&assembly, hmodule);
     if (SUCCEEDED(hr))
     {
-        hr = assembly_get_vtable_fixups(assembly, &vtable_fixups, &vtable_fixup_count);
-        if (CAN_FIXUP_VTABLE)
-            for (i=0; i<vtable_fixup_count; i++)
-                FixupVTableEntry(hmodule, &vtable_fixups[i]);
-        else if (vtable_fixup_count)
-            FIXME("cannot fixup vtable; expect a crash\n");
-
+        FixupVTable_Assembly(hmodule, assembly);
         assembly_release(assembly);
     }
     else
@@ -1249,15 +1254,33 @@ __int32 WINAPI _CorExeMain(void)
 
 BOOL WINAPI _CorDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
 {
+ASSEMBLY *assembly;
+HRESULT hr;
+NativeEntryPointFunc NativeEntryPoint;
     TRACE("(%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
 
+    NativeEntryPoint = NULL;
+    hr = assembly_from_hmodule(&assembly, hinstDLL);
+    if (SUCCEEDED(hr))
+        assembly_get_native_entrypoint(assembly, &NativeEntryPoint);
+    else
+        ERR("failed to read CLR headers, hr=%x\n", hr);
+
     switch (fdwReason)
     {
     case DLL_PROCESS_ATTACH:
         DisableThreadLibraryCalls(hinstDLL);
-        FixupVTable(hinstDLL);
+        if (SUCCEEDED(hr))
+        {
+            FixupVTable_Assembly(hinstDLL,assembly);
+            assembly_release(assembly);
+        }
+        if (NativeEntryPoint) return NativeEntryPoint(hinstDLL, fdwReason, lpvReserved);
         break;
     case DLL_PROCESS_DETACH:
+        if (SUCCEEDED(hr))
+            assembly_release(assembly);
+        if (NativeEntryPoint) return NativeEntryPoint(hinstDLL, fdwReason, lpvReserved);
         /* FIXME: clean up the vtables */
         break;
     }
diff --git a/dlls/mscoree/mscoree_private.h b/dlls/mscoree/mscoree_private.h
index 7843407..8226463 100644
--- a/dlls/mscoree/mscoree_private.h
+++ b/dlls/mscoree/mscoree_private.h
@@ -36,11 +36,14 @@ typedef struct _VTableFixup {
 
 typedef struct tagASSEMBLY ASSEMBLY;
 
+typedef BOOL (WINAPI *NativeEntryPointFunc)(HINSTANCE, DWORD, LPVOID);
+
 extern HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file) DECLSPEC_HIDDEN;
 extern HRESULT assembly_from_hmodule(ASSEMBLY **out, HMODULE hmodule) DECLSPEC_HIDDEN;
 extern HRESULT assembly_release(ASSEMBLY *assembly) DECLSPEC_HIDDEN;
 extern HRESULT assembly_get_runtime_version(ASSEMBLY *assembly, LPSTR *version) DECLSPEC_HIDDEN;
 extern HRESULT assembly_get_vtable_fixups(ASSEMBLY *assembly, VTableFixup **fixups, DWORD *count) DECLSPEC_HIDDEN;
+extern HRESULT assembly_get_native_entrypoint(ASSEMBLY *assembly, NativeEntryPointFunc *func) DECLSPEC_HIDDEN;
 
 /* Mono embedding */
 typedef struct _MonoDomain MonoDomain;
diff --git a/include/winnt.h b/include/winnt.h
index c7874dd..2309ae3 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -3549,6 +3549,7 @@ typedef enum ReplacesCorHdrNumericDefines
     COMIMAGE_FLAGS_32BITREQUIRED    = 0x00000002,
     COMIMAGE_FLAGS_IL_LIBRARY       = 0x00000004,
     COMIMAGE_FLAGS_STRONGNAMESIGNED = 0x00000008,
+    COMIMAGE_FLAGS_NATIVE_ENTRYPOINT= 0x00000010,
     COMIMAGE_FLAGS_TRACKDEBUGDATA   = 0x00010000,
 
     COR_VERSION_MAJOR_V2       = 2,
-- 
2.5.0



More information about the wine-devel mailing list