Commit d2d1c6d8 authored by Vincent Povirk's avatar Vincent Povirk Committed by Alexandre Julliard

mscoree: Detect when a CLR DLL requests vtable fixups.

parent 29893d81
...@@ -63,10 +63,13 @@ typedef struct tagCLRTABLE ...@@ -63,10 +63,13 @@ typedef struct tagCLRTABLE
struct tagASSEMBLY struct tagASSEMBLY
{ {
LPWSTR path; int is_mapped_file;
/* mapped files */
LPWSTR path;
HANDLE hfile; HANDLE hfile;
HANDLE hmap; HANDLE hmap;
BYTE *data; BYTE *data;
IMAGE_NT_HEADERS *nthdr; IMAGE_NT_HEADERS *nthdr;
...@@ -89,6 +92,29 @@ static inline LPWSTR strdupW(LPCWSTR src) ...@@ -89,6 +92,29 @@ static inline LPWSTR strdupW(LPCWSTR src)
return dest; 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) static HRESULT parse_metadata_header(ASSEMBLY *assembly, DWORD *hdrsz)
{ {
METADATAHDR *metadatahdr; METADATAHDR *metadatahdr;
...@@ -97,7 +123,7 @@ static HRESULT parse_metadata_header(ASSEMBLY *assembly, DWORD *hdrsz) ...@@ -97,7 +123,7 @@ static HRESULT parse_metadata_header(ASSEMBLY *assembly, DWORD *hdrsz)
ULONG rva; ULONG rva;
rva = assembly->corhdr->MetaData.VirtualAddress; rva = assembly->corhdr->MetaData.VirtualAddress;
ptr = ImageRvaToVa(assembly->nthdr, assembly->data, rva, NULL); ptr = assembly_rva_to_va(assembly, rva);
if (!ptr) if (!ptr)
return E_FAIL; return E_FAIL;
...@@ -158,20 +184,24 @@ static HRESULT parse_pe_header(ASSEMBLY *assembly) ...@@ -158,20 +184,24 @@ static HRESULT parse_pe_header(ASSEMBLY *assembly)
if (!datadirs) if (!datadirs)
return E_FAIL; return E_FAIL;
if (!datadirs[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress || if (!assembly_datadir_get_data(assembly, &datadirs[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR], (void**)&assembly->corhdr))
!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)
return E_FAIL; return E_FAIL;
return S_OK; 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) HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file)
{ {
ASSEMBLY *assembly; ASSEMBLY *assembly;
...@@ -183,6 +213,8 @@ HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file) ...@@ -183,6 +213,8 @@ HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file)
if (!assembly) if (!assembly)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
assembly->is_mapped_file = 1;
assembly->path = strdupW(file); assembly->path = strdupW(file);
if (!assembly->path) if (!assembly->path)
{ {
...@@ -213,10 +245,7 @@ HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file) ...@@ -213,10 +245,7 @@ HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file)
goto failed; goto failed;
} }
hr = parse_pe_header(assembly); hr = parse_headers(assembly);
if (FAILED(hr)) goto failed;
hr = parse_clr_metadata(assembly);
if (FAILED(hr)) goto failed; if (FAILED(hr)) goto failed;
*out = assembly; *out = assembly;
...@@ -227,16 +256,43 @@ failed: ...@@ -227,16 +256,43 @@ failed:
return hr; 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) HRESULT assembly_release(ASSEMBLY *assembly)
{ {
if (!assembly) if (!assembly)
return S_OK; 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->metadatahdr);
HeapFree(GetProcessHeap(), 0, assembly->path); HeapFree(GetProcessHeap(), 0, assembly->path);
UnmapViewOfFile(assembly->data);
CloseHandle(assembly->hmap);
CloseHandle(assembly->hfile);
HeapFree(GetProcessHeap(), 0, assembly); HeapFree(GetProcessHeap(), 0, assembly);
return S_OK; return S_OK;
...@@ -248,3 +304,13 @@ HRESULT assembly_get_runtime_version(ASSEMBLY *assembly, LPSTR *version) ...@@ -248,3 +304,13 @@ HRESULT assembly_get_runtime_version(ASSEMBLY *assembly, LPSTR *version)
return S_OK; 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;
}
...@@ -803,6 +803,26 @@ static void get_utf8_args(int *argc, char ***argv) ...@@ -803,6 +803,26 @@ static void get_utf8_args(int *argc, char ***argv)
HeapFree(GetProcessHeap(), 0, argvw); 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) __int32 WINAPI _CorExeMain(void)
{ {
int exit_code; int exit_code;
...@@ -830,6 +850,8 @@ __int32 WINAPI _CorExeMain(void) ...@@ -830,6 +850,8 @@ __int32 WINAPI _CorExeMain(void)
if (!filenameA) if (!filenameA)
return -1; return -1;
FixupVTable(GetModuleHandleW(NULL));
hr = get_runtime_info(filename, NULL, NULL, 0, 0, FALSE, &info); hr = get_runtime_info(filename, NULL, NULL, 0, 0, FALSE, &info);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
...@@ -862,6 +884,22 @@ __int32 WINAPI _CorExeMain(void) ...@@ -862,6 +884,22 @@ __int32 WINAPI _CorExeMain(void)
return exit_code; 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, HRESULT RuntimeHost_Construct(const CLRRuntimeInfo *runtime_version,
loaded_mono *loaded_mono, RuntimeHost** result) loaded_mono *loaded_mono, RuntimeHost** result)
{ {
......
...@@ -236,21 +236,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) ...@@ -236,21 +236,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
return TRUE; 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) __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)); TRACE("(%p, %u, %s, %s, %s)\n", ptrMemory, cntMemory, debugstr_w(imageName), debugstr_w(loaderName), debugstr_w(cmdLine));
......
...@@ -27,11 +27,20 @@ extern HRESULT CLRMetaHost_CreateInstance(REFIID riid, void **ppobj) DECLSPEC_HI ...@@ -27,11 +27,20 @@ extern HRESULT CLRMetaHost_CreateInstance(REFIID riid, void **ppobj) DECLSPEC_HI
extern HRESULT WINAPI CLRMetaHost_GetVersionFromFile(ICLRMetaHost* iface, extern HRESULT WINAPI CLRMetaHost_GetVersionFromFile(ICLRMetaHost* iface,
LPCWSTR pwzFilePath, LPWSTR pwzBuffer, DWORD *pcchBuffer) DECLSPEC_HIDDEN; LPCWSTR pwzFilePath, LPWSTR pwzBuffer, DWORD *pcchBuffer) DECLSPEC_HIDDEN;
typedef struct _VTableFixup {
DWORD rva;
WORD count;
WORD type;
} VTableFixup;
typedef struct tagASSEMBLY ASSEMBLY; typedef struct tagASSEMBLY ASSEMBLY;
HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file) DECLSPEC_HIDDEN; extern void* assembly_rva_to_va(ASSEMBLY *assembly, ULONG rva) DECLSPEC_HIDDEN;
HRESULT assembly_release(ASSEMBLY *assembly) DECLSPEC_HIDDEN; extern HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file) DECLSPEC_HIDDEN;
HRESULT assembly_get_runtime_version(ASSEMBLY *assembly, LPSTR *version) 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 */ /* Mono embedding */
typedef struct _MonoDomain MonoDomain; typedef struct _MonoDomain MonoDomain;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment