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