Vincent Povirk : mscoree: Detect when a CLR DLL requests vtable fixups.

Alexandre Julliard julliard at winehq.org
Thu May 3 14:23:47 CDT 2012


Module: wine
Branch: master
Commit: d2d1c6d8246df302a8c91596fec43b66fd338f97
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=d2d1c6d8246df302a8c91596fec43b66fd338f97

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Thu Oct 20 13:23:35 2011 -0500

mscoree: Detect when a CLR DLL requests vtable fixups.

---

 dlls/mscoree/assembly.c        |  102 +++++++++++++++++++++++++++++++++-------
 dlls/mscoree/corruntimehost.c  |   38 +++++++++++++++
 dlls/mscoree/mscoree_main.c    |   15 ------
 dlls/mscoree/mscoree_private.h |   15 +++++-
 4 files changed, 134 insertions(+), 36 deletions(-)

diff --git a/dlls/mscoree/assembly.c b/dlls/mscoree/assembly.c
index 07723f9..a1e3dc7 100644
--- a/dlls/mscoree/assembly.c
+++ b/dlls/mscoree/assembly.c
@@ -63,10 +63,13 @@ typedef struct tagCLRTABLE
 
 struct tagASSEMBLY
 {
-    LPWSTR path;
+    int is_mapped_file;
 
+    /* mapped files */
+    LPWSTR path;
     HANDLE hfile;
     HANDLE hmap;
+
     BYTE *data;
 
     IMAGE_NT_HEADERS *nthdr;
@@ -89,6 +92,29 @@ static inline LPWSTR strdupW(LPCWSTR src)
     return dest;
 }
 
+void* assembly_rva_to_va(ASSEMBLY *assembly, ULONG rva)
+{
+    if (assembly->is_mapped_file)
+        return ImageRvaToVa(assembly->nthdr, assembly->data, rva, NULL);
+    else
+        return assembly->data + rva;
+}
+
+static ULONG assembly_datadir_get_data(ASSEMBLY *assembly,
+    IMAGE_DATA_DIRECTORY *datadir, void **data)
+{
+    if (!datadir->VirtualAddress || !datadir->Size)
+    {
+        *data = NULL;
+        return 0;
+    }
+    else
+    {
+        *data = assembly_rva_to_va(assembly, datadir->VirtualAddress);
+        return datadir->Size;
+    }
+}
+
 static HRESULT parse_metadata_header(ASSEMBLY *assembly, DWORD *hdrsz)
 {
     METADATAHDR *metadatahdr;
@@ -97,7 +123,7 @@ static HRESULT parse_metadata_header(ASSEMBLY *assembly, DWORD *hdrsz)
     ULONG rva;
 
     rva = assembly->corhdr->MetaData.VirtualAddress;
-    ptr = ImageRvaToVa(assembly->nthdr, assembly->data, rva, NULL);
+    ptr = assembly_rva_to_va(assembly, rva);
     if (!ptr)
         return E_FAIL;
 
@@ -158,20 +184,24 @@ static HRESULT parse_pe_header(ASSEMBLY *assembly)
     if (!datadirs)
         return E_FAIL;
 
-    if (!datadirs[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress ||
-        !datadirs[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size)
-    {
-        return E_FAIL;
-    }
-
-    assembly->corhdr = ImageRvaToVa(assembly->nthdr, assembly->data,
-        datadirs[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress, NULL);
-    if (!assembly->corhdr)
+    if (!assembly_datadir_get_data(assembly, &datadirs[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR], (void**)&assembly->corhdr))
         return E_FAIL;
 
     return S_OK;
 }
 
+HRESULT parse_headers(ASSEMBLY *assembly)
+{
+    HRESULT hr;
+
+    hr = parse_pe_header(assembly);
+
+    if (SUCCEEDED(hr))
+        hr = parse_clr_metadata(assembly);
+
+    return hr;
+}
+
 HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file)
 {
     ASSEMBLY *assembly;
@@ -183,6 +213,8 @@ HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file)
     if (!assembly)
         return E_OUTOFMEMORY;
 
+    assembly->is_mapped_file = 1;
+
     assembly->path = strdupW(file);
     if (!assembly->path)
     {
@@ -213,10 +245,7 @@ HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file)
         goto failed;
     }
 
-    hr = parse_pe_header(assembly);
-    if (FAILED(hr)) goto failed;
-
-    hr = parse_clr_metadata(assembly);
+    hr = parse_headers(assembly);
     if (FAILED(hr)) goto failed;
 
     *out = assembly;
@@ -227,16 +256,43 @@ failed:
     return hr;
 }
 
+HRESULT assembly_from_hmodule(ASSEMBLY **out, HMODULE hmodule)
+{
+    ASSEMBLY *assembly;
+    HRESULT hr;
+
+    *out = NULL;
+
+    assembly = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ASSEMBLY));
+    if (!assembly)
+        return E_OUTOFMEMORY;
+
+    assembly->is_mapped_file = 0;
+
+    assembly->data = (BYTE*)hmodule;
+
+    hr = parse_headers(assembly);
+    if (SUCCEEDED(hr))
+        *out = assembly;
+    else
+        assembly_release(assembly);
+
+    return hr;
+}
+
 HRESULT assembly_release(ASSEMBLY *assembly)
 {
     if (!assembly)
         return S_OK;
 
+    if (assembly->is_mapped_file)
+    {
+        UnmapViewOfFile(assembly->data);
+        CloseHandle(assembly->hmap);
+        CloseHandle(assembly->hfile);
+    }
     HeapFree(GetProcessHeap(), 0, assembly->metadatahdr);
     HeapFree(GetProcessHeap(), 0, assembly->path);
-    UnmapViewOfFile(assembly->data);
-    CloseHandle(assembly->hmap);
-    CloseHandle(assembly->hfile);
     HeapFree(GetProcessHeap(), 0, assembly);
 
     return S_OK;
@@ -248,3 +304,13 @@ HRESULT assembly_get_runtime_version(ASSEMBLY *assembly, LPSTR *version)
 
     return S_OK;
 }
+
+HRESULT assembly_get_vtable_fixups(ASSEMBLY *assembly, VTableFixup **fixups, DWORD *count)
+{
+    ULONG size;
+
+    size = assembly_datadir_get_data(assembly, &assembly->corhdr->VTableFixups, (void**)fixups);
+    *count = size / sizeof(VTableFixup);
+
+    return S_OK;
+}
diff --git a/dlls/mscoree/corruntimehost.c b/dlls/mscoree/corruntimehost.c
index 1750f12..31c02ea 100644
--- a/dlls/mscoree/corruntimehost.c
+++ b/dlls/mscoree/corruntimehost.c
@@ -803,6 +803,26 @@ static void get_utf8_args(int *argc, char ***argv)
     HeapFree(GetProcessHeap(), 0, argvw);
 }
 
+static void FixupVTable(HMODULE hmodule)
+{
+    ASSEMBLY *assembly;
+    HRESULT hr;
+    VTableFixup *vtable_fixups;
+    ULONG vtable_fixup_count;
+
+    hr = assembly_from_hmodule(&assembly, hmodule);
+    if (SUCCEEDED(hr))
+    {
+        hr = assembly_get_vtable_fixups(assembly, &vtable_fixups, &vtable_fixup_count);
+        if (vtable_fixup_count)
+            FIXME("vtable fixups are not implemented; expect a crash\n");
+
+        assembly_release(assembly);
+    }
+    else
+        ERR("failed to read CLR headers, hr=%x\n", hr);
+}
+
 __int32 WINAPI _CorExeMain(void)
 {
     int exit_code;
@@ -830,6 +850,8 @@ __int32 WINAPI _CorExeMain(void)
     if (!filenameA)
         return -1;
 
+    FixupVTable(GetModuleHandleW(NULL));
+
     hr = get_runtime_info(filename, NULL, NULL, 0, 0, FALSE, &info);
 
     if (SUCCEEDED(hr))
@@ -862,6 +884,22 @@ __int32 WINAPI _CorExeMain(void)
     return exit_code;
 }
 
+BOOL WINAPI _CorDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+    FIXME("(%p, %d, %p): stub\n", hinstDLL, fdwReason, lpvReserved);
+
+    switch (fdwReason)
+    {
+    case DLL_PROCESS_ATTACH:
+        DisableThreadLibraryCalls(hinstDLL);
+        FixupVTable(hinstDLL);
+        break;
+    case DLL_PROCESS_DETACH:
+        break;
+    }
+    return TRUE;
+}
+
 HRESULT RuntimeHost_Construct(const CLRRuntimeInfo *runtime_version,
     loaded_mono *loaded_mono, RuntimeHost** result)
 {
diff --git a/dlls/mscoree/mscoree_main.c b/dlls/mscoree/mscoree_main.c
index 1e06909..09f6dad 100644
--- a/dlls/mscoree/mscoree_main.c
+++ b/dlls/mscoree/mscoree_main.c
@@ -236,21 +236,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
     return TRUE;
 }
 
-BOOL WINAPI _CorDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
-{
-    FIXME("(%p, %d, %p): stub\n", hinstDLL, fdwReason, lpvReserved);
-
-    switch (fdwReason)
-    {
-    case DLL_PROCESS_ATTACH:
-        DisableThreadLibraryCalls(hinstDLL);
-        break;
-    case DLL_PROCESS_DETACH:
-        break;
-    }
-    return TRUE;
-}
-
 __int32 WINAPI _CorExeMain2(PBYTE ptrMemory, DWORD cntMemory, LPWSTR imageName, LPWSTR loaderName, LPWSTR cmdLine)
 {
     TRACE("(%p, %u, %s, %s, %s)\n", ptrMemory, cntMemory, debugstr_w(imageName), debugstr_w(loaderName), debugstr_w(cmdLine));
diff --git a/dlls/mscoree/mscoree_private.h b/dlls/mscoree/mscoree_private.h
index 62cf240..12a1e56 100644
--- a/dlls/mscoree/mscoree_private.h
+++ b/dlls/mscoree/mscoree_private.h
@@ -27,11 +27,20 @@ extern HRESULT CLRMetaHost_CreateInstance(REFIID riid, void **ppobj) DECLSPEC_HI
 extern HRESULT WINAPI CLRMetaHost_GetVersionFromFile(ICLRMetaHost* iface,
     LPCWSTR pwzFilePath, LPWSTR pwzBuffer, DWORD *pcchBuffer) DECLSPEC_HIDDEN;
 
+typedef struct _VTableFixup {
+    DWORD rva;
+    WORD count;
+    WORD type;
+} VTableFixup;
+
 typedef struct tagASSEMBLY ASSEMBLY;
 
-HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file) DECLSPEC_HIDDEN;
-HRESULT assembly_release(ASSEMBLY *assembly) DECLSPEC_HIDDEN;
-HRESULT assembly_get_runtime_version(ASSEMBLY *assembly, LPSTR *version) DECLSPEC_HIDDEN;
+extern void* assembly_rva_to_va(ASSEMBLY *assembly, ULONG rva) DECLSPEC_HIDDEN;
+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;
 
 /* Mono embedding */
 typedef struct _MonoDomain MonoDomain;




More information about the wine-cvs mailing list