mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 00:45:24 +00:00
[MSCOREE]
* Sync to Wine 1.5.4. svn path=/trunk/; revision=56692
This commit is contained in:
parent
8c7e9cfe10
commit
b28cf69af4
9 changed files with 723 additions and 61 deletions
|
@ -2,7 +2,9 @@
|
||||||
add_definitions(-D__WINESRC__)
|
add_definitions(-D__WINESRC__)
|
||||||
include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine)
|
include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine)
|
||||||
|
|
||||||
set_rc_compiler()
|
remove_definitions(-D_WIN32_WINNT=0x502)
|
||||||
|
add_definitions(-D_WIN32_WINNT=0x600)
|
||||||
|
|
||||||
spec2def(mscoree.dll mscoree.spec)
|
spec2def(mscoree.dll mscoree.spec)
|
||||||
|
|
||||||
list(APPEND SOURCE
|
list(APPEND SOURCE
|
||||||
|
|
|
@ -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)
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static 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)
|
||||||
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)
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static 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)
|
||||||
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)
|
||||||
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:
|
||||||
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)
|
||||||
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
|
@ -425,7 +425,7 @@ static HRESULT parse_config(VARIANT input, parsed_config_file *result)
|
||||||
ISAXXMLReader_Release(reader);
|
ISAXXMLReader_Release(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
IUnknown_Release((IUnknown*)handler);
|
ISAXContentHandler_Release(&handler->ISAXContentHandler_iface);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -445,7 +445,7 @@ HRESULT parse_config_file(LPCWSTR filename, parsed_config_file *result)
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
V_VT(&var) = VT_UNKNOWN|VT_DISPATCH;
|
V_VT(&var) = VT_UNKNOWN;
|
||||||
V_UNKNOWN(&var) = (IUnknown*)stream;
|
V_UNKNOWN(&var) = (IUnknown*)stream;
|
||||||
|
|
||||||
hr = parse_config(var, result);
|
hr = parse_config(var, result);
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#define COBJMACROS
|
#define COBJMACROS
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
|
@ -38,6 +39,8 @@
|
||||||
#include "mscoree_private.h"
|
#include "mscoree_private.h"
|
||||||
|
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
#include "wine/unicode.h"
|
||||||
|
#include "wine/list.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
|
WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
|
||||||
|
|
||||||
|
@ -51,6 +54,21 @@ struct DomainEntry
|
||||||
MonoDomain *domain;
|
MonoDomain *domain;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static HANDLE dll_fixup_heap; /* using a separate heap so we can have execute permission */
|
||||||
|
|
||||||
|
static struct list dll_fixups;
|
||||||
|
|
||||||
|
struct dll_fixup
|
||||||
|
{
|
||||||
|
struct list entry;
|
||||||
|
int done;
|
||||||
|
HMODULE dll;
|
||||||
|
void *thunk_code; /* pointer into dll_fixup_heap */
|
||||||
|
VTableFixup *fixup;
|
||||||
|
void *vtable;
|
||||||
|
void *tokens; /* pointer into process heap */
|
||||||
|
};
|
||||||
|
|
||||||
static HRESULT RuntimeHost_AddDomain(RuntimeHost *This, MonoDomain **result)
|
static HRESULT RuntimeHost_AddDomain(RuntimeHost *This, MonoDomain **result)
|
||||||
{
|
{
|
||||||
struct DomainEntry *entry;
|
struct DomainEntry *entry;
|
||||||
|
@ -147,6 +165,8 @@ static HRESULT RuntimeHost_GetIUnknownForDomain(RuntimeHost *This, MonoDomain *d
|
||||||
MonoObject *appdomain_object;
|
MonoObject *appdomain_object;
|
||||||
IUnknown *unk;
|
IUnknown *unk;
|
||||||
|
|
||||||
|
This->mono->mono_thread_attach(domain);
|
||||||
|
|
||||||
assembly = This->mono->mono_domain_assembly_open(domain, "mscorlib");
|
assembly = This->mono->mono_domain_assembly_open(domain, "mscorlib");
|
||||||
if (!assembly)
|
if (!assembly)
|
||||||
{
|
{
|
||||||
|
@ -559,6 +579,8 @@ static HRESULT WINAPI CLRRuntimeHost_ExecuteInDefaultAppDomain(ICLRRuntimeHost*
|
||||||
|
|
||||||
hr = E_FAIL;
|
hr = E_FAIL;
|
||||||
|
|
||||||
|
This->mono->mono_thread_attach(domain);
|
||||||
|
|
||||||
filenameA = WtoA(pwzAssemblyPath);
|
filenameA = WtoA(pwzAssemblyPath);
|
||||||
assembly = This->mono->mono_domain_assembly_open(domain, filenameA);
|
assembly = This->mono->mono_domain_assembly_open(domain, filenameA);
|
||||||
if (!assembly)
|
if (!assembly)
|
||||||
|
@ -609,14 +631,10 @@ static HRESULT WINAPI CLRRuntimeHost_ExecuteInDefaultAppDomain(ICLRRuntimeHost*
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if(filenameA)
|
HeapFree(GetProcessHeap(), 0, filenameA);
|
||||||
HeapFree(GetProcessHeap(), 0, filenameA);
|
HeapFree(GetProcessHeap(), 0, classA);
|
||||||
if(classA)
|
HeapFree(GetProcessHeap(), 0, argsA);
|
||||||
HeapFree(GetProcessHeap(), 0, classA);
|
HeapFree(GetProcessHeap(), 0, methodA);
|
||||||
if(argsA)
|
|
||||||
HeapFree(GetProcessHeap(), 0, argsA);
|
|
||||||
if(methodA)
|
|
||||||
HeapFree(GetProcessHeap(), 0, methodA);
|
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
@ -661,6 +679,8 @@ HRESULT RuntimeHost_CreateManagedInstance(RuntimeHost *This, LPCWSTR name,
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
|
This->mono->mono_thread_attach(domain);
|
||||||
|
|
||||||
type = This->mono->mono_reflection_type_from_name(nameA, NULL);
|
type = This->mono->mono_reflection_type_from_name(nameA, NULL);
|
||||||
if (!type)
|
if (!type)
|
||||||
{
|
{
|
||||||
|
@ -708,7 +728,9 @@ HRESULT RuntimeHost_CreateManagedInstance(RuntimeHost *This, LPCWSTR name,
|
||||||
*
|
*
|
||||||
* NOTE: The IUnknown* is created with a reference to the object.
|
* NOTE: The IUnknown* is created with a reference to the object.
|
||||||
* Until they have a reference, objects must be in the stack to prevent the
|
* Until they have a reference, objects must be in the stack to prevent the
|
||||||
* garbage collector from freeing them. */
|
* garbage collector from freeing them.
|
||||||
|
*
|
||||||
|
* mono_thread_attach must have already been called for this thread. */
|
||||||
HRESULT RuntimeHost_GetIUnknownForObject(RuntimeHost *This, MonoObject *obj,
|
HRESULT RuntimeHost_GetIUnknownForObject(RuntimeHost *This, MonoObject *obj,
|
||||||
IUnknown **ppUnk)
|
IUnknown **ppUnk)
|
||||||
{
|
{
|
||||||
|
@ -798,13 +820,223 @@ static void get_utf8_args(int *argc, char ***argv)
|
||||||
HeapFree(GetProcessHeap(), 0, argvw);
|
HeapFree(GetProcessHeap(), 0, argvw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if __i386__
|
||||||
|
|
||||||
|
# define CAN_FIXUP_VTABLE 1
|
||||||
|
|
||||||
|
#include "pshpack1.h"
|
||||||
|
|
||||||
|
struct vtable_fixup_thunk
|
||||||
|
{
|
||||||
|
/* sub $0x4,%esp */
|
||||||
|
BYTE i1[3];
|
||||||
|
/* mov fixup,(%esp) */
|
||||||
|
BYTE i2[3];
|
||||||
|
struct dll_fixup *fixup;
|
||||||
|
/* mov function,%eax */
|
||||||
|
BYTE i3;
|
||||||
|
void (CDECL *function)(struct dll_fixup *);
|
||||||
|
/* call *%eax */
|
||||||
|
BYTE i4[2];
|
||||||
|
/* pop %eax */
|
||||||
|
BYTE i5;
|
||||||
|
/* jmp *vtable_entry */
|
||||||
|
BYTE i6[2];
|
||||||
|
void *vtable_entry;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct vtable_fixup_thunk thunk_template = {
|
||||||
|
{0x83,0xec,0x04},
|
||||||
|
{0xc7,0x04,0x24},
|
||||||
|
NULL,
|
||||||
|
0xb8,
|
||||||
|
NULL,
|
||||||
|
{0xff,0xd0},
|
||||||
|
0x58,
|
||||||
|
{0xff,0x25},
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "poppack.h"
|
||||||
|
|
||||||
|
#else /* !defined(__i386__) */
|
||||||
|
|
||||||
|
# define CAN_FIXUP_VTABLE 0
|
||||||
|
|
||||||
|
struct vtable_fixup_thunk
|
||||||
|
{
|
||||||
|
struct dll_fixup *fixup;
|
||||||
|
void (CDECL *function)(struct dll_fixup *fixup);
|
||||||
|
void *vtable_entry;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct vtable_fixup_thunk thunk_template = {0};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void CDECL ReallyFixupVTable(struct dll_fixup *fixup)
|
||||||
|
{
|
||||||
|
HRESULT hr=S_OK;
|
||||||
|
WCHAR filename[MAX_PATH];
|
||||||
|
ICLRRuntimeInfo *info=NULL;
|
||||||
|
RuntimeHost *host;
|
||||||
|
char *filenameA;
|
||||||
|
MonoImage *image=NULL;
|
||||||
|
MonoAssembly *assembly=NULL;
|
||||||
|
MonoImageOpenStatus status=0;
|
||||||
|
MonoDomain *domain;
|
||||||
|
|
||||||
|
if (fixup->done) return;
|
||||||
|
|
||||||
|
/* It's possible we'll have two threads doing this at once. This is
|
||||||
|
* considered preferable to the potential deadlock if we use a mutex. */
|
||||||
|
|
||||||
|
GetModuleFileNameW(fixup->dll, filename, MAX_PATH);
|
||||||
|
|
||||||
|
TRACE("%p,%p,%s\n", fixup, fixup->dll, debugstr_w(filename));
|
||||||
|
|
||||||
|
filenameA = WtoA(filename);
|
||||||
|
if (!filenameA)
|
||||||
|
hr = E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
hr = get_runtime_info(filename, NULL, NULL, 0, 0, FALSE, &info);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
hr = ICLRRuntimeInfo_GetRuntimeHost(info, &host);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
hr = RuntimeHost_GetDefaultDomain(host, &domain);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
host->mono->mono_thread_attach(domain);
|
||||||
|
|
||||||
|
image = host->mono->mono_image_open_from_module_handle(fixup->dll,
|
||||||
|
filenameA, 1, &status);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (image)
|
||||||
|
assembly = host->mono->mono_assembly_load_from(image, filenameA, &status);
|
||||||
|
|
||||||
|
if (assembly)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Mono needs an image that belongs to an assembly. */
|
||||||
|
image = host->mono->mono_assembly_get_image(assembly);
|
||||||
|
|
||||||
|
if (fixup->fixup->type & COR_VTABLE_32BIT)
|
||||||
|
{
|
||||||
|
DWORD *vtable = fixup->vtable;
|
||||||
|
DWORD *tokens = fixup->tokens;
|
||||||
|
for (i=0; i<fixup->fixup->count; i++)
|
||||||
|
{
|
||||||
|
TRACE("%x\n", tokens[i]);
|
||||||
|
vtable[i] = PtrToUint(host->mono->mono_marshal_get_vtfixup_ftnptr(
|
||||||
|
image, tokens[i], fixup->fixup->type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fixup->done = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info != NULL)
|
||||||
|
ICLRRuntimeHost_Release(info);
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, filenameA);
|
||||||
|
|
||||||
|
if (!fixup->done)
|
||||||
|
{
|
||||||
|
ERR("unable to fixup vtable, hr=%x, status=%d\n", hr, status);
|
||||||
|
/* If we returned now, we'd get an infinite loop. */
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FixupVTableEntry(HMODULE hmodule, VTableFixup *vtable_fixup)
|
||||||
|
{
|
||||||
|
/* We can't actually generate code for the functions without loading mono,
|
||||||
|
* and loading mono inside DllMain is a terrible idea. So we make thunks
|
||||||
|
* that call ReallyFixupVTable, which will load the runtime and fill in the
|
||||||
|
* vtable, then do an indirect jump using the (now filled in) vtable. Note
|
||||||
|
* that we have to keep the thunks around forever, as one of them may get
|
||||||
|
* called while we're filling in the table, and we can never be sure all
|
||||||
|
* threads are clear. */
|
||||||
|
struct dll_fixup *fixup;
|
||||||
|
|
||||||
|
fixup = HeapAlloc(GetProcessHeap(), 0, sizeof(*fixup));
|
||||||
|
|
||||||
|
fixup->dll = hmodule;
|
||||||
|
fixup->thunk_code = HeapAlloc(dll_fixup_heap, 0, sizeof(struct vtable_fixup_thunk) * vtable_fixup->count);
|
||||||
|
fixup->fixup = vtable_fixup;
|
||||||
|
fixup->vtable = (BYTE*)hmodule + vtable_fixup->rva;
|
||||||
|
fixup->done = 0;
|
||||||
|
|
||||||
|
if (vtable_fixup->type & COR_VTABLE_32BIT)
|
||||||
|
{
|
||||||
|
DWORD *vtable = fixup->vtable;
|
||||||
|
DWORD *tokens;
|
||||||
|
int i;
|
||||||
|
struct vtable_fixup_thunk *thunks = fixup->thunk_code;
|
||||||
|
|
||||||
|
if (sizeof(void*) > 4)
|
||||||
|
ERR("32-bit fixup in 64-bit mode; broken image?\n");
|
||||||
|
|
||||||
|
tokens = fixup->tokens = HeapAlloc(GetProcessHeap(), 0, sizeof(*tokens) * vtable_fixup->count);
|
||||||
|
memcpy(tokens, vtable, sizeof(*tokens) * vtable_fixup->count);
|
||||||
|
for (i=0; i<vtable_fixup->count; i++)
|
||||||
|
{
|
||||||
|
memcpy(&thunks[i], &thunk_template, sizeof(thunk_template));
|
||||||
|
thunks[i].fixup = fixup;
|
||||||
|
thunks[i].function = ReallyFixupVTable;
|
||||||
|
thunks[i].vtable_entry = &vtable[i];
|
||||||
|
vtable[i] = PtrToUint(&thunks[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERR("unsupported vtable fixup flags %x\n", vtable_fixup->type);
|
||||||
|
HeapFree(dll_fixup_heap, 0, fixup->thunk_code);
|
||||||
|
HeapFree(GetProcessHeap(), 0, fixup);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_add_tail(&dll_fixups, &fixup->entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
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;
|
||||||
int argc;
|
int argc;
|
||||||
char **argv;
|
char **argv;
|
||||||
MonoDomain *domain;
|
MonoDomain *domain;
|
||||||
MonoAssembly *assembly;
|
MonoImage *image;
|
||||||
|
MonoImageOpenStatus status;
|
||||||
|
MonoAssembly *assembly=NULL;
|
||||||
WCHAR filename[MAX_PATH];
|
WCHAR filename[MAX_PATH];
|
||||||
char *filenameA;
|
char *filenameA;
|
||||||
ICLRRuntimeInfo *info;
|
ICLRRuntimeInfo *info;
|
||||||
|
@ -825,6 +1057,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))
|
||||||
|
@ -836,9 +1070,21 @@ __int32 WINAPI _CorExeMain(void)
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
assembly = host->mono->mono_domain_assembly_open(domain, filenameA);
|
image = host->mono->mono_image_open_from_module_handle(GetModuleHandleW(NULL),
|
||||||
|
filenameA, 1, &status);
|
||||||
|
|
||||||
exit_code = host->mono->mono_jit_exec(domain, assembly, argc, argv);
|
if (image)
|
||||||
|
assembly = host->mono->mono_assembly_load_from(image, filenameA, &status);
|
||||||
|
|
||||||
|
if (assembly)
|
||||||
|
{
|
||||||
|
exit_code = host->mono->mono_jit_exec(domain, assembly, argc, argv);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERR("couldn't load %s, status=%d\n", debugstr_w(filename), status);
|
||||||
|
exit_code = -1;
|
||||||
|
}
|
||||||
|
|
||||||
RuntimeHost_DeleteDomain(host, domain);
|
RuntimeHost_DeleteDomain(host, domain);
|
||||||
}
|
}
|
||||||
|
@ -857,6 +1103,43 @@ __int32 WINAPI _CorExeMain(void)
|
||||||
return exit_code;
|
return exit_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI _CorDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||||
|
{
|
||||||
|
TRACE("(%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
|
||||||
|
|
||||||
|
switch (fdwReason)
|
||||||
|
{
|
||||||
|
case DLL_PROCESS_ATTACH:
|
||||||
|
DisableThreadLibraryCalls(hinstDLL);
|
||||||
|
FixupVTable(hinstDLL);
|
||||||
|
break;
|
||||||
|
case DLL_PROCESS_DETACH:
|
||||||
|
/* FIXME: clean up the vtables */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* called from DLL_PROCESS_ATTACH */
|
||||||
|
void runtimehost_init(void)
|
||||||
|
{
|
||||||
|
dll_fixup_heap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0);
|
||||||
|
list_init(&dll_fixups);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* called from DLL_PROCESS_DETACH */
|
||||||
|
void runtimehost_uninit(void)
|
||||||
|
{
|
||||||
|
struct dll_fixup *fixup, *fixup2;
|
||||||
|
|
||||||
|
HeapDestroy(dll_fixup_heap);
|
||||||
|
LIST_FOR_EACH_ENTRY_SAFE(fixup, fixup2, &dll_fixups, struct dll_fixup, entry)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, fixup->tokens);
|
||||||
|
HeapFree(GetProcessHeap(), 0, fixup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
@ -943,3 +1226,148 @@ HRESULT RuntimeHost_Destroy(RuntimeHost *This)
|
||||||
HeapFree( GetProcessHeap(), 0, This );
|
HeapFree( GetProcessHeap(), 0, This );
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define CHARS_IN_GUID 39
|
||||||
|
#define ARRAYSIZE(array) (sizeof(array)/sizeof((array)[0]))
|
||||||
|
|
||||||
|
HRESULT create_monodata(REFIID riid, LPVOID *ppObj )
|
||||||
|
{
|
||||||
|
static const WCHAR wszCodebase[] = {'C','o','d','e','B','a','s','e',0};
|
||||||
|
static const WCHAR wszClass[] = {'C','l','a','s','s',0};
|
||||||
|
static const WCHAR wszFileSlash[] = {'f','i','l','e',':','/','/','/',0};
|
||||||
|
static const WCHAR wszCLSIDSlash[] = {'C','L','S','I','D','\\',0};
|
||||||
|
static const WCHAR wszInprocServer32[] = {'\\','I','n','p','r','o','c','S','e','r','v','e','r','3','2',0};
|
||||||
|
WCHAR path[CHARS_IN_GUID + ARRAYSIZE(wszCLSIDSlash) + ARRAYSIZE(wszInprocServer32) - 1];
|
||||||
|
MonoDomain *domain;
|
||||||
|
MonoAssembly *assembly;
|
||||||
|
ICLRRuntimeInfo *info;
|
||||||
|
RuntimeHost *host;
|
||||||
|
HRESULT hr;
|
||||||
|
HKEY key;
|
||||||
|
LONG res;
|
||||||
|
int offset = 0;
|
||||||
|
WCHAR codebase[MAX_PATH + 8];
|
||||||
|
WCHAR classname[350];
|
||||||
|
WCHAR filename[MAX_PATH];
|
||||||
|
|
||||||
|
DWORD dwBufLen = 350;
|
||||||
|
|
||||||
|
lstrcpyW(path, wszCLSIDSlash);
|
||||||
|
StringFromGUID2(riid, path + lstrlenW(wszCLSIDSlash), CHARS_IN_GUID);
|
||||||
|
lstrcatW(path, wszInprocServer32);
|
||||||
|
|
||||||
|
TRACE("Registry key: %s\n", debugstr_w(path));
|
||||||
|
|
||||||
|
res = RegOpenKeyExW(HKEY_CLASSES_ROOT, path, 0, KEY_READ, &key);
|
||||||
|
if (res == ERROR_FILE_NOT_FOUND)
|
||||||
|
return CLASS_E_CLASSNOTAVAILABLE;
|
||||||
|
|
||||||
|
res = RegGetValueW( key, NULL, wszClass, RRF_RT_REG_SZ, NULL, classname, &dwBufLen);
|
||||||
|
if(res != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
WARN("Class value cannot be found.\n");
|
||||||
|
hr = CLASS_E_CLASSNOTAVAILABLE;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("classname (%s)\n", debugstr_w(classname));
|
||||||
|
|
||||||
|
dwBufLen = MAX_PATH + 8;
|
||||||
|
res = RegGetValueW( key, NULL, wszCodebase, RRF_RT_REG_SZ, NULL, codebase, &dwBufLen);
|
||||||
|
if(res != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
WARN("CodeBase value cannot be found.\n");
|
||||||
|
hr = CLASS_E_CLASSNOTAVAILABLE;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Strip file:/// */
|
||||||
|
if(strncmpW(codebase, wszFileSlash, strlenW(wszFileSlash)) == 0)
|
||||||
|
offset = strlenW(wszFileSlash);
|
||||||
|
|
||||||
|
strcpyW(filename, codebase + offset);
|
||||||
|
|
||||||
|
TRACE("codebase (%s)\n", debugstr_w(filename));
|
||||||
|
|
||||||
|
*ppObj = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
hr = get_runtime_info(filename, NULL, NULL, 0, 0, FALSE, &info);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = ICLRRuntimeInfo_GetRuntimeHost(info, &host);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
hr = RuntimeHost_GetDefaultDomain(host, &domain);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
MonoImage *image;
|
||||||
|
MonoClass *klass;
|
||||||
|
MonoObject *result;
|
||||||
|
IUnknown *unk = NULL;
|
||||||
|
char *filenameA, *ns;
|
||||||
|
char *classA;
|
||||||
|
|
||||||
|
hr = CLASS_E_CLASSNOTAVAILABLE;
|
||||||
|
|
||||||
|
host->mono->mono_thread_attach(domain);
|
||||||
|
|
||||||
|
filenameA = WtoA(filename);
|
||||||
|
assembly = host->mono->mono_domain_assembly_open(domain, filenameA);
|
||||||
|
HeapFree(GetProcessHeap(), 0, filenameA);
|
||||||
|
if (!assembly)
|
||||||
|
{
|
||||||
|
ERR("Cannot open assembly %s\n", filenameA);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
image = host->mono->mono_assembly_get_image(assembly);
|
||||||
|
if (!image)
|
||||||
|
{
|
||||||
|
ERR("Couldn't get assembly image\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
classA = WtoA(classname);
|
||||||
|
ns = strrchr(classA, '.');
|
||||||
|
*ns = '\0';
|
||||||
|
|
||||||
|
klass = host->mono->mono_class_from_name(image, classA, ns+1);
|
||||||
|
HeapFree(GetProcessHeap(), 0, classA);
|
||||||
|
if (!klass)
|
||||||
|
{
|
||||||
|
ERR("Couldn't get class from image\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use the default constructor for the .NET class.
|
||||||
|
*/
|
||||||
|
result = host->mono->mono_object_new(domain, klass);
|
||||||
|
host->mono->mono_runtime_object_init(result);
|
||||||
|
|
||||||
|
hr = RuntimeHost_GetIUnknownForObject(host, result, &unk);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = IUnknown_QueryInterface(unk, &IID_IUnknown, ppObj);
|
||||||
|
|
||||||
|
IUnknown_Release(unk);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
hr = CLASS_E_CLASSNOTAVAILABLE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
hr = CLASS_E_CLASSNOTAVAILABLE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
hr = CLASS_E_CLASSNOTAVAILABLE;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if(info)
|
||||||
|
ICLRRuntimeInfo_Release(info);
|
||||||
|
|
||||||
|
RegCloseKey(key);
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
|
@ -165,16 +165,19 @@ static HRESULT load_mono(CLRRuntimeInfo *This, loaded_mono **result)
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
LOAD_MONO_FUNCTION(mono_assembly_get_image);
|
LOAD_MONO_FUNCTION(mono_assembly_get_image);
|
||||||
|
LOAD_MONO_FUNCTION(mono_assembly_load_from);
|
||||||
LOAD_MONO_FUNCTION(mono_assembly_open);
|
LOAD_MONO_FUNCTION(mono_assembly_open);
|
||||||
LOAD_MONO_FUNCTION(mono_config_parse);
|
LOAD_MONO_FUNCTION(mono_config_parse);
|
||||||
LOAD_MONO_FUNCTION(mono_class_from_mono_type);
|
LOAD_MONO_FUNCTION(mono_class_from_mono_type);
|
||||||
LOAD_MONO_FUNCTION(mono_class_from_name);
|
LOAD_MONO_FUNCTION(mono_class_from_name);
|
||||||
LOAD_MONO_FUNCTION(mono_class_get_method_from_name);
|
LOAD_MONO_FUNCTION(mono_class_get_method_from_name);
|
||||||
LOAD_MONO_FUNCTION(mono_domain_assembly_open);
|
LOAD_MONO_FUNCTION(mono_domain_assembly_open);
|
||||||
|
LOAD_MONO_FUNCTION(mono_image_open_from_module_handle);
|
||||||
LOAD_MONO_FUNCTION(mono_install_assembly_preload_hook);
|
LOAD_MONO_FUNCTION(mono_install_assembly_preload_hook);
|
||||||
LOAD_MONO_FUNCTION(mono_jit_exec);
|
LOAD_MONO_FUNCTION(mono_jit_exec);
|
||||||
LOAD_MONO_FUNCTION(mono_jit_init);
|
LOAD_MONO_FUNCTION(mono_jit_init);
|
||||||
LOAD_MONO_FUNCTION(mono_jit_set_trace_options);
|
LOAD_MONO_FUNCTION(mono_jit_set_trace_options);
|
||||||
|
LOAD_MONO_FUNCTION(mono_marshal_get_vtfixup_ftnptr);
|
||||||
LOAD_MONO_FUNCTION(mono_object_get_domain);
|
LOAD_MONO_FUNCTION(mono_object_get_domain);
|
||||||
LOAD_MONO_FUNCTION(mono_object_new);
|
LOAD_MONO_FUNCTION(mono_object_new);
|
||||||
LOAD_MONO_FUNCTION(mono_object_unbox);
|
LOAD_MONO_FUNCTION(mono_object_unbox);
|
||||||
|
@ -186,6 +189,7 @@ static HRESULT load_mono(CLRRuntimeInfo *This, loaded_mono **result)
|
||||||
LOAD_MONO_FUNCTION(mono_set_dirs);
|
LOAD_MONO_FUNCTION(mono_set_dirs);
|
||||||
LOAD_MONO_FUNCTION(mono_stringify_assembly_name);
|
LOAD_MONO_FUNCTION(mono_stringify_assembly_name);
|
||||||
LOAD_MONO_FUNCTION(mono_string_new);
|
LOAD_MONO_FUNCTION(mono_string_new);
|
||||||
|
LOAD_MONO_FUNCTION(mono_thread_attach);
|
||||||
|
|
||||||
/* GLib imports obsoleted by the 2.0 ABI */
|
/* GLib imports obsoleted by the 2.0 ABI */
|
||||||
if (This->mono_abi_version == 1)
|
if (This->mono_abi_version == 1)
|
||||||
|
@ -564,6 +568,14 @@ HRESULT ICLRRuntimeInfo_GetRuntimeHost(ICLRRuntimeInfo *iface, RuntimeHost **res
|
||||||
return CLRRuntimeInfo_GetRuntimeHost(This, result);
|
return CLRRuntimeInfo_GetRuntimeHost(This, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __i386__
|
||||||
|
static const WCHAR libmono2_arch_dll[] = {'\\','b','i','n','\\','l','i','b','m','o','n','o','-','2','.','0','-','x','8','6','.','d','l','l',0};
|
||||||
|
#elif defined(__x86_64__)
|
||||||
|
static const WCHAR libmono2_arch_dll[] = {'\\','b','i','n','\\','l','i','b','m','o','n','o','-','2','.','0','-','x','8','6','_','6','4','.','d','l','l',0};
|
||||||
|
#else
|
||||||
|
static const WCHAR libmono2_arch_dll[] = {'\\','b','i','n','\\','l','i','b','m','o','n','o','-','2','.','0','.','d','l','l',0};
|
||||||
|
#endif
|
||||||
|
|
||||||
static BOOL find_mono_dll(LPCWSTR path, LPWSTR dll_path, int abi_version)
|
static BOOL find_mono_dll(LPCWSTR path, LPWSTR dll_path, int abi_version)
|
||||||
{
|
{
|
||||||
static const WCHAR mono_dll[] = {'\\','b','i','n','\\','m','o','n','o','.','d','l','l',0};
|
static const WCHAR mono_dll[] = {'\\','b','i','n','\\','m','o','n','o','.','d','l','l',0};
|
||||||
|
@ -588,9 +600,16 @@ static BOOL find_mono_dll(LPCWSTR path, LPWSTR dll_path, int abi_version)
|
||||||
else if (abi_version == 2)
|
else if (abi_version == 2)
|
||||||
{
|
{
|
||||||
strcpyW(dll_path, path);
|
strcpyW(dll_path, path);
|
||||||
strcatW(dll_path, mono2_dll);
|
strcatW(dll_path, libmono2_arch_dll);
|
||||||
attributes = GetFileAttributesW(dll_path);
|
attributes = GetFileAttributesW(dll_path);
|
||||||
|
|
||||||
|
if (attributes == INVALID_FILE_ATTRIBUTES)
|
||||||
|
{
|
||||||
|
strcpyW(dll_path, path);
|
||||||
|
strcatW(dll_path, mono2_dll);
|
||||||
|
attributes = GetFileAttributesW(dll_path);
|
||||||
|
}
|
||||||
|
|
||||||
if (attributes == INVALID_FILE_ATTRIBUTES)
|
if (attributes == INVALID_FILE_ATTRIBUTES)
|
||||||
{
|
{
|
||||||
strcpyW(dll_path, path);
|
strcpyW(dll_path, path);
|
||||||
|
@ -973,7 +992,7 @@ static BOOL parse_runtime_version(LPCWSTR version, DWORD *major, DWORD *minor, D
|
||||||
*minor = 0;
|
*minor = 0;
|
||||||
*build = 0;
|
*build = 0;
|
||||||
|
|
||||||
if (version[0] == 'v')
|
if (version[0] == 'v' || version[0] == 'V')
|
||||||
{
|
{
|
||||||
version++;
|
version++;
|
||||||
if (!isdigit(*version))
|
if (!isdigit(*version))
|
||||||
|
@ -1310,11 +1329,21 @@ HRESULT get_runtime_info(LPCWSTR exefile, LPCWSTR version, LPCWSTR config_file,
|
||||||
|
|
||||||
if (version)
|
if (version)
|
||||||
{
|
{
|
||||||
return CLRMetaHost_GetRuntime(0, version, &IID_ICLRRuntimeInfo, (void**)result);
|
hr = CLRMetaHost_GetRuntime(0, version, &IID_ICLRRuntimeInfo, (void**)result);
|
||||||
|
if(SUCCEEDED(hr))
|
||||||
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runtimeinfo_flags & RUNTIME_INFO_UPGRADE_VERSION)
|
if (runtimeinfo_flags & RUNTIME_INFO_UPGRADE_VERSION)
|
||||||
{
|
{
|
||||||
|
DWORD major, minor, build;
|
||||||
|
|
||||||
|
if (version && !parse_runtime_version(version, &major, &minor, &build))
|
||||||
|
{
|
||||||
|
ERR("Cannot parse %s\n", debugstr_w(version));
|
||||||
|
return CLR_E_SHIM_RUNTIME;
|
||||||
|
}
|
||||||
|
|
||||||
find_runtimes();
|
find_runtimes();
|
||||||
|
|
||||||
if (legacy)
|
if (legacy)
|
||||||
|
@ -1325,8 +1354,16 @@ HRESULT get_runtime_info(LPCWSTR exefile, LPCWSTR version, LPCWSTR config_file,
|
||||||
while (i--)
|
while (i--)
|
||||||
{
|
{
|
||||||
if (runtimes[i].mono_abi_version)
|
if (runtimes[i].mono_abi_version)
|
||||||
return ICLRRuntimeInfo_QueryInterface(&runtimes[i].ICLRRuntimeInfo_iface,
|
{
|
||||||
&IID_ICLRRuntimeInfo, (void **)result);
|
/* Must be greater or equal to the version passed in. */
|
||||||
|
if (!version || ((runtimes[i].major >= major && runtimes[i].minor >= minor && runtimes[i].build >= build) ||
|
||||||
|
(runtimes[i].major >= major && runtimes[i].minor > minor) ||
|
||||||
|
(runtimes[i].major > major)))
|
||||||
|
{
|
||||||
|
return ICLRRuntimeInfo_QueryInterface(&runtimes[i].ICLRRuntimeInfo_iface,
|
||||||
|
&IID_ICLRRuntimeInfo, (void **)result);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (legacy)
|
if (legacy)
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
@ stub CloseCtrs
|
@ stub CloseCtrs
|
||||||
@ stdcall CLRCreateInstance(ptr ptr ptr)
|
@ stdcall CLRCreateInstance(ptr ptr ptr)
|
||||||
@ stdcall ClrCreateManagedInstance(wstr ptr ptr)
|
@ stdcall ClrCreateManagedInstance(wstr ptr ptr)
|
||||||
@ stub CoEEShutDownCOM
|
@ stdcall CoEEShutDownCOM()
|
||||||
@ stdcall CoInitializeCor(long)
|
@ stdcall CoInitializeCor(long)
|
||||||
@ stub CoInitializeEE
|
@ stub CoInitializeEE
|
||||||
@ stub CoUninitializeCor
|
@ stub CoUninitializeCor
|
||||||
|
|
|
@ -52,6 +52,8 @@ WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
|
||||||
|
|
||||||
static HINSTANCE MSCOREE_hInstance;
|
static HINSTANCE MSCOREE_hInstance;
|
||||||
|
|
||||||
|
typedef HRESULT (*fnCreateInstance)(REFIID riid, LPVOID *ppObj);
|
||||||
|
|
||||||
char *WtoA(LPCWSTR wstr)
|
char *WtoA(LPCWSTR wstr)
|
||||||
{
|
{
|
||||||
int length;
|
int length;
|
||||||
|
@ -89,6 +91,105 @@ static BOOL get_install_root(LPWSTR install_dir)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct mscorecf
|
||||||
|
{
|
||||||
|
IClassFactory IClassFactory_iface;
|
||||||
|
LONG ref;
|
||||||
|
|
||||||
|
fnCreateInstance pfnCreateInstance;
|
||||||
|
|
||||||
|
CLSID clsid;
|
||||||
|
} mscorecf;
|
||||||
|
|
||||||
|
static inline mscorecf *impl_from_IClassFactory( IClassFactory *iface )
|
||||||
|
{
|
||||||
|
return CONTAINING_RECORD(iface, mscorecf, IClassFactory_iface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI mscorecf_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppobj )
|
||||||
|
{
|
||||||
|
TRACE("%s %p\n", debugstr_guid(riid), ppobj);
|
||||||
|
|
||||||
|
if (IsEqualGUID(riid, &IID_IUnknown) ||
|
||||||
|
IsEqualGUID(riid, &IID_IClassFactory))
|
||||||
|
{
|
||||||
|
IClassFactory_AddRef( iface );
|
||||||
|
*ppobj = iface;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ERR("interface %s not implemented\n", debugstr_guid(riid));
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI mscorecf_AddRef(IClassFactory *iface )
|
||||||
|
{
|
||||||
|
mscorecf *This = impl_from_IClassFactory(iface);
|
||||||
|
ULONG ref = InterlockedIncrement(&This->ref);
|
||||||
|
|
||||||
|
TRACE("%p ref=%u\n", This, ref);
|
||||||
|
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI mscorecf_Release(IClassFactory *iface )
|
||||||
|
{
|
||||||
|
mscorecf *This = impl_from_IClassFactory(iface);
|
||||||
|
ULONG ref = InterlockedDecrement(&This->ref);
|
||||||
|
|
||||||
|
TRACE("%p ref=%u\n", This, ref);
|
||||||
|
|
||||||
|
if (ref == 0)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, This);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI mscorecf_CreateInstance(IClassFactory *iface,LPUNKNOWN pOuter,
|
||||||
|
REFIID riid, LPVOID *ppobj )
|
||||||
|
{
|
||||||
|
mscorecf *This = impl_from_IClassFactory( iface );
|
||||||
|
HRESULT hr;
|
||||||
|
IUnknown *punk;
|
||||||
|
|
||||||
|
TRACE("%p %s %p\n", pOuter, debugstr_guid(riid), ppobj );
|
||||||
|
|
||||||
|
*ppobj = NULL;
|
||||||
|
|
||||||
|
if (pOuter)
|
||||||
|
return CLASS_E_NOAGGREGATION;
|
||||||
|
|
||||||
|
hr = This->pfnCreateInstance( &This->clsid, (LPVOID*) &punk );
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = IUnknown_QueryInterface( punk, riid, ppobj );
|
||||||
|
|
||||||
|
IUnknown_Release( punk );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WARN("Cannot create an instance object. 0x%08x\n", hr);
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI mscorecf_LockServer(IClassFactory *iface, BOOL dolock)
|
||||||
|
{
|
||||||
|
FIXME("(%p)->(%d),stub!\n",iface,dolock);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct IClassFactoryVtbl mscorecf_vtbl =
|
||||||
|
{
|
||||||
|
mscorecf_QueryInterface,
|
||||||
|
mscorecf_AddRef,
|
||||||
|
mscorecf_Release,
|
||||||
|
mscorecf_CreateInstance,
|
||||||
|
mscorecf_LockServer
|
||||||
|
};
|
||||||
|
|
||||||
HRESULT WINAPI CorBindToRuntimeHost(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor,
|
HRESULT WINAPI CorBindToRuntimeHost(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor,
|
||||||
LPCWSTR pwszHostConfigFile, VOID *pReserved,
|
LPCWSTR pwszHostConfigFile, VOID *pReserved,
|
||||||
DWORD startupFlags, REFCLSID rclsid,
|
DWORD startupFlags, REFCLSID rclsid,
|
||||||
|
@ -126,25 +227,13 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||||
case DLL_WINE_PREATTACH:
|
case DLL_WINE_PREATTACH:
|
||||||
return FALSE; /* prefer native version */
|
return FALSE; /* prefer native version */
|
||||||
case DLL_PROCESS_ATTACH:
|
case DLL_PROCESS_ATTACH:
|
||||||
|
runtimehost_init();
|
||||||
DisableThreadLibraryCalls(hinstDLL);
|
DisableThreadLibraryCalls(hinstDLL);
|
||||||
break;
|
break;
|
||||||
case DLL_PROCESS_DETACH:
|
case DLL_PROCESS_DETACH:
|
||||||
expect_no_runtimes();
|
expect_no_runtimes();
|
||||||
break;
|
if (lpvReserved) break; /* process is terminating */
|
||||||
}
|
runtimehost_uninit();
|
||||||
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;
|
break;
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -246,6 +335,9 @@ HRESULT WINAPI GetRequestedRuntimeInfo(LPCWSTR pExe, LPCWSTR pwszVersion, LPCWST
|
||||||
|
|
||||||
if (SUCCEEDED(ret))
|
if (SUCCEEDED(ret))
|
||||||
{
|
{
|
||||||
|
if(pwszVersion)
|
||||||
|
pVersion[0] = pwszVersion[0];
|
||||||
|
|
||||||
*dwDirectoryLength = dwDirectory;
|
*dwDirectoryLength = dwDirectory;
|
||||||
ret = ICLRRuntimeInfo_GetRuntimeDirectory(info, pDirectory, dwDirectoryLength);
|
ret = ICLRRuntimeInfo_GetRuntimeDirectory(info, pDirectory, dwDirectoryLength);
|
||||||
}
|
}
|
||||||
|
@ -258,7 +350,7 @@ HRESULT WINAPI GetRequestedRuntimeInfo(LPCWSTR pExe, LPCWSTR pwszVersion, LPCWST
|
||||||
|
|
||||||
HRESULT WINAPI GetRequestedRuntimeVersion(LPWSTR pExe, LPWSTR pVersion, DWORD cchBuffer, DWORD *dwlength)
|
HRESULT WINAPI GetRequestedRuntimeVersion(LPWSTR pExe, LPWSTR pVersion, DWORD cchBuffer, DWORD *dwlength)
|
||||||
{
|
{
|
||||||
TRACE("(%s, %p, %d, %p)\n", debugstr_w(pExe), debugstr_w(pExe), cchBuffer, dwlength);
|
TRACE("(%s, %p, %d, %p)\n", debugstr_w(pExe), pVersion, cchBuffer, dwlength);
|
||||||
|
|
||||||
if(!dwlength)
|
if(!dwlength)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
@ -504,11 +596,25 @@ HRESULT WINAPI CLRCreateInstance(REFCLSID clsid, REFIID riid, LPVOID *ppInterfac
|
||||||
|
|
||||||
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
|
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
|
||||||
{
|
{
|
||||||
FIXME("(%s, %s, %p): stub\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
|
mscorecf *This;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
TRACE("(%s, %s, %p): stub\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
|
||||||
|
|
||||||
if(!ppv)
|
if(!ppv)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
return E_NOTIMPL;
|
This = HeapAlloc(GetProcessHeap(), 0, sizeof(mscorecf));
|
||||||
|
|
||||||
|
This->IClassFactory_iface.lpVtbl = &mscorecf_vtbl;
|
||||||
|
This->pfnCreateInstance = &create_monodata;
|
||||||
|
This->ref = 1;
|
||||||
|
This->clsid = *rclsid;
|
||||||
|
|
||||||
|
hr = IClassFactory_QueryInterface( &This->IClassFactory_iface, riid, ppv );
|
||||||
|
IClassFactory_Release(&This->IClassFactory_iface);
|
||||||
|
|
||||||
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI DllRegisterServer(void)
|
HRESULT WINAPI DllRegisterServer(void)
|
||||||
|
@ -526,6 +632,11 @@ HRESULT WINAPI DllCanUnloadNow(VOID)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WINAPI CoEEShutDownCOM(void)
|
||||||
|
{
|
||||||
|
FIXME("stub.\n");
|
||||||
|
}
|
||||||
|
|
||||||
INT WINAPI ND_RU1( const void *ptr, INT offset )
|
INT WINAPI ND_RU1( const void *ptr, INT offset )
|
||||||
{
|
{
|
||||||
return *((const BYTE *)ptr + offset);
|
return *((const BYTE *)ptr + offset);
|
||||||
|
|
|
@ -27,11 +27,19 @@ 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 HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file) DECLSPEC_HIDDEN;
|
||||||
HRESULT assembly_release(ASSEMBLY *assembly) DECLSPEC_HIDDEN;
|
extern HRESULT assembly_from_hmodule(ASSEMBLY **out, HMODULE hmodule) DECLSPEC_HIDDEN;
|
||||||
HRESULT assembly_get_runtime_version(ASSEMBLY *assembly, LPSTR *version) 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;
|
||||||
|
@ -44,6 +52,7 @@ typedef struct _MonoObject MonoObject;
|
||||||
typedef struct _MonoString MonoString;
|
typedef struct _MonoString MonoString;
|
||||||
typedef struct _MonoMethod MonoMethod;
|
typedef struct _MonoMethod MonoMethod;
|
||||||
typedef struct _MonoProfiler MonoProfiler;
|
typedef struct _MonoProfiler MonoProfiler;
|
||||||
|
typedef struct _MonoThread MonoThread;
|
||||||
|
|
||||||
typedef struct loaded_mono loaded_mono;
|
typedef struct loaded_mono loaded_mono;
|
||||||
typedef struct RuntimeHost RuntimeHost;
|
typedef struct RuntimeHost RuntimeHost;
|
||||||
|
@ -137,6 +146,7 @@ struct loaded_mono
|
||||||
BOOL is_shutdown;
|
BOOL is_shutdown;
|
||||||
|
|
||||||
MonoImage* (CDECL *mono_assembly_get_image)(MonoAssembly *assembly);
|
MonoImage* (CDECL *mono_assembly_get_image)(MonoAssembly *assembly);
|
||||||
|
MonoAssembly* (CDECL *mono_assembly_load_from)(MonoImage *image, const char *fname, MonoImageOpenStatus *status);
|
||||||
MonoAssembly* (CDECL *mono_assembly_open)(const char *filename, MonoImageOpenStatus *status);
|
MonoAssembly* (CDECL *mono_assembly_open)(const char *filename, MonoImageOpenStatus *status);
|
||||||
MonoClass* (CDECL *mono_class_from_mono_type)(MonoType *type);
|
MonoClass* (CDECL *mono_class_from_mono_type)(MonoType *type);
|
||||||
MonoClass* (CDECL *mono_class_from_name)(MonoImage *image, const char* name_space, const char *name);
|
MonoClass* (CDECL *mono_class_from_name)(MonoImage *image, const char* name_space, const char *name);
|
||||||
|
@ -144,10 +154,12 @@ struct loaded_mono
|
||||||
void (CDECL *mono_config_parse)(const char *filename);
|
void (CDECL *mono_config_parse)(const char *filename);
|
||||||
MonoAssembly* (CDECL *mono_domain_assembly_open) (MonoDomain *domain, const char *name);
|
MonoAssembly* (CDECL *mono_domain_assembly_open) (MonoDomain *domain, const char *name);
|
||||||
void (CDECL *mono_free)(void *);
|
void (CDECL *mono_free)(void *);
|
||||||
|
MonoImage* (CDECL *mono_image_open_from_module_handle)(HMODULE module_handle, char* fname, UINT has_entry_point, MonoImageOpenStatus* status);
|
||||||
void (CDECL *mono_install_assembly_preload_hook)(MonoAssemblyPreLoadFunc func, void *user_data);
|
void (CDECL *mono_install_assembly_preload_hook)(MonoAssemblyPreLoadFunc func, void *user_data);
|
||||||
int (CDECL *mono_jit_exec)(MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[]);
|
int (CDECL *mono_jit_exec)(MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[]);
|
||||||
MonoDomain* (CDECL *mono_jit_init)(const char *file);
|
MonoDomain* (CDECL *mono_jit_init)(const char *file);
|
||||||
int (CDECL *mono_jit_set_trace_options)(const char* options);
|
int (CDECL *mono_jit_set_trace_options)(const char* options);
|
||||||
|
void* (CDECL *mono_marshal_get_vtfixup_ftnptr)(MonoImage *image, DWORD token, WORD type);
|
||||||
MonoDomain* (CDECL *mono_object_get_domain)(MonoObject *obj);
|
MonoDomain* (CDECL *mono_object_get_domain)(MonoObject *obj);
|
||||||
MonoObject* (CDECL *mono_object_new)(MonoDomain *domain, MonoClass *klass);
|
MonoObject* (CDECL *mono_object_new)(MonoDomain *domain, MonoClass *klass);
|
||||||
void* (CDECL *mono_object_unbox)(MonoObject *obj);
|
void* (CDECL *mono_object_unbox)(MonoObject *obj);
|
||||||
|
@ -163,6 +175,7 @@ struct loaded_mono
|
||||||
void (CDECL *mono_thread_suspend_all_other_threads)(void);
|
void (CDECL *mono_thread_suspend_all_other_threads)(void);
|
||||||
void (CDECL *mono_threads_set_shutting_down)(void);
|
void (CDECL *mono_threads_set_shutting_down)(void);
|
||||||
MonoString* (CDECL *mono_string_new)(MonoDomain *domain, const char *str);
|
MonoString* (CDECL *mono_string_new)(MonoDomain *domain, const char *str);
|
||||||
|
MonoThread* (CDECL *mono_thread_attach)(MonoDomain *domain);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* loaded runtime interfaces */
|
/* loaded runtime interfaces */
|
||||||
|
@ -186,4 +199,9 @@ HRESULT WINAPI CLRMetaHost_GetRuntime(ICLRMetaHost* iface, LPCWSTR pwzVersion, R
|
||||||
|
|
||||||
extern HRESULT CorDebug_Create(ICLRRuntimeHost *runtimehost, IUnknown** ppUnk) DECLSPEC_HIDDEN;
|
extern HRESULT CorDebug_Create(ICLRRuntimeHost *runtimehost, IUnknown** ppUnk) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
extern HRESULT create_monodata(REFIID riid, LPVOID *ppObj) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
extern void runtimehost_init(void);
|
||||||
|
extern void runtimehost_uninit(void);
|
||||||
|
|
||||||
#endif /* __MSCOREE_PRIVATE__ */
|
#endif /* __MSCOREE_PRIVATE__ */
|
||||||
|
|
|
@ -95,7 +95,7 @@ reactos/dll/win32/msacm32 # Autosync
|
||||||
reactos/dll/win32/msadp32.acm # Synced to Wine-1.3.37
|
reactos/dll/win32/msadp32.acm # Synced to Wine-1.3.37
|
||||||
reactos/dll/win32/mscat32 # Synced to Wine-1.3.37
|
reactos/dll/win32/mscat32 # Synced to Wine-1.3.37
|
||||||
reactos/dll/win32/mscms # Synced to Wine-1.5.4
|
reactos/dll/win32/mscms # Synced to Wine-1.5.4
|
||||||
reactos/dll/win32/mscoree # Synced to Wine-1.3.37
|
reactos/dll/win32/mscoree # Synced to Wine-1.5.4
|
||||||
reactos/dll/win32/msctf # Synced to Wine-1.3.37
|
reactos/dll/win32/msctf # Synced to Wine-1.3.37
|
||||||
reactos/dll/win32/msftedit # Synced to Wine-1.3.37
|
reactos/dll/win32/msftedit # Synced to Wine-1.3.37
|
||||||
reactos/dll/win32/msg711.acm # Synced to Wine-1.3.37
|
reactos/dll/win32/msg711.acm # Synced to Wine-1.3.37
|
||||||
|
|
Loading…
Reference in a new issue