Something went wrong. Try again.
Reactos
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352/* * * Copyright 2008 Alistair Leslie-Hughes * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
#include "mscoree_private.h"
#include <assert.h>#include <shellapi.h>#include <initguid.h>
DEFINE_GUID(IID__AppDomain, 0x05f696dc,0x2b29,0x3663,0xad,0x8b,0xc4,0x38,0x9c,0xf2,0xa7,0x13);
struct DomainEntry{ struct list entry; 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){ struct DomainEntry *entry; char *mscorlib_path; HRESULT res=S_OK;
EnterCriticalSection(&This->lock);
entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry)); if (!entry) { res = E_OUTOFMEMORY; goto end; }
mscorlib_path = WtoA(This->version->mscorlib_path); if (!mscorlib_path) { HeapFree(GetProcessHeap(), 0, entry); res = E_OUTOFMEMORY; goto end; }
entry->domain = This->mono->mono_jit_init(mscorlib_path);
HeapFree(GetProcessHeap(), 0, mscorlib_path);
if (!entry->domain) { HeapFree(GetProcessHeap(), 0, entry); res = E_FAIL; goto end; }
This->mono->is_started = TRUE;
list_add_tail(&This->domains, &entry->entry);
*result = entry->domain;
end: LeaveCriticalSection(&This->lock);
return res;}
static HRESULT RuntimeHost_GetDefaultDomain(RuntimeHost *This, MonoDomain **result){ HRESULT res=S_OK;
EnterCriticalSection(&This->lock);
if (This->default_domain) goto end;
res = RuntimeHost_AddDomain(This, &This->default_domain);
end: *result = This->default_domain;
LeaveCriticalSection(&This->lock);
return res;}
static void RuntimeHost_DeleteDomain(RuntimeHost *This, MonoDomain *domain){ struct DomainEntry *entry;
EnterCriticalSection(&This->lock);
LIST_FOR_EACH_ENTRY(entry, &This->domains, struct DomainEntry, entry) { if (entry->domain == domain) { list_remove(&entry->entry); if (This->default_domain == domain) This->default_domain = NULL; HeapFree(GetProcessHeap(), 0, entry); break; } }
LeaveCriticalSection(&This->lock);}
static HRESULT RuntimeHost_GetIUnknownForDomain(RuntimeHost *This, MonoDomain *domain, IUnknown **punk){ HRESULT hr; void *args[1]; MonoAssembly *assembly; MonoImage *image; MonoClass *klass; MonoMethod *method; MonoObject *appdomain_object; IUnknown *unk;
This->mono->mono_thread_attach(domain);
assembly = This->mono->mono_domain_assembly_open(domain, "mscorlib"); if (!assembly) { ERR("Cannot load mscorlib\n"); return E_FAIL; }
image = This->mono->mono_assembly_get_image(assembly); if (!image) { ERR("Couldn't get assembly image\n"); return E_FAIL; }
klass = This->mono->mono_class_from_name(image, "System", "AppDomain"); if (!klass) { ERR("Couldn't get class from image\n"); return E_FAIL; }
method = This->mono->mono_class_get_method_from_name(klass, "get_CurrentDomain", 0); if (!method) { ERR("Couldn't get method from class\n"); return E_FAIL; }
args[0] = NULL; appdomain_object = This->mono->mono_runtime_invoke(method, NULL, args, NULL); if (!appdomain_object) { ERR("Couldn't get result pointer\n"); return E_FAIL; }
hr = RuntimeHost_GetIUnknownForObject(This, appdomain_object, &unk);
if (SUCCEEDED(hr)) { hr = IUnknown_QueryInterface(unk, &IID__AppDomain, (void**)punk);
IUnknown_Release(unk); }
return hr;}
static inline RuntimeHost *impl_from_ICLRRuntimeHost( ICLRRuntimeHost *iface ){ return CONTAINING_RECORD(iface, RuntimeHost, ICLRRuntimeHost_iface);}
static inline RuntimeHost *impl_from_ICorRuntimeHost( ICorRuntimeHost *iface ){ return CONTAINING_RECORD(iface, RuntimeHost, ICorRuntimeHost_iface);}
/*** IUnknown methods ***/static HRESULT WINAPI corruntimehost_QueryInterface(ICorRuntimeHost* iface, REFIID riid, void **ppvObject){ RuntimeHost *This = impl_from_ICorRuntimeHost( iface ); TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
if ( IsEqualGUID( riid, &IID_ICorRuntimeHost ) || IsEqualGUID( riid, &IID_IUnknown ) ) { *ppvObject = iface; } else { FIXME("Unsupported interface %s\n", debugstr_guid(riid)); return E_NOINTERFACE; }
ICorRuntimeHost_AddRef( iface );
return S_OK;}
static ULONG WINAPI corruntimehost_AddRef(ICorRuntimeHost* iface){ RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
return InterlockedIncrement( &This->ref );}
static ULONG WINAPI corruntimehost_Release(ICorRuntimeHost* iface){ RuntimeHost *This = impl_from_ICorRuntimeHost( iface ); ULONG ref;
ref = InterlockedDecrement( &This->ref );
return ref;}
/*** ICorRuntimeHost methods ***/static HRESULT WINAPI corruntimehost_CreateLogicalThreadState( ICorRuntimeHost* iface){ FIXME("stub %p\n", iface); return E_NOTIMPL;}
static HRESULT WINAPI corruntimehost_DeleteLogicalThreadState( ICorRuntimeHost* iface){ FIXME("stub %p\n", iface); return E_NOTIMPL;}
static HRESULT WINAPI corruntimehost_SwitchInLogicalThreadState( ICorRuntimeHost* iface, DWORD *fiberCookie){ FIXME("stub %p\n", iface); return E_NOTIMPL;}
static HRESULT WINAPI corruntimehost_SwitchOutLogicalThreadState( ICorRuntimeHost* iface, DWORD **fiberCookie){ FIXME("stub %p\n", iface); return E_NOTIMPL;}
static HRESULT WINAPI corruntimehost_LocksHeldByLogicalThread( ICorRuntimeHost* iface, DWORD *pCount){ FIXME("stub %p\n", iface); return E_NOTIMPL;}
static HRESULT WINAPI corruntimehost_MapFile( ICorRuntimeHost* iface, HANDLE hFile, HMODULE *mapAddress){ FIXME("stub %p\n", iface); return E_NOTIMPL;}
static HRESULT WINAPI corruntimehost_GetConfiguration( ICorRuntimeHost* iface, ICorConfiguration **pConfiguration){ FIXME("stub %p\n", iface); return E_NOTIMPL;}
static HRESULT WINAPI corruntimehost_Start( ICorRuntimeHost* iface){ FIXME("stub %p\n", iface); return S_OK;}
static HRESULT WINAPI corruntimehost_Stop( ICorRuntimeHost* iface){ FIXME("stub %p\n", iface); return E_NOTIMPL;}
static HRESULT WINAPI corruntimehost_CreateDomain( ICorRuntimeHost* iface, LPCWSTR friendlyName, IUnknown *identityArray, IUnknown **appDomain){ FIXME("stub %p\n", iface); return E_NOTIMPL;}
static HRESULT WINAPI corruntimehost_GetDefaultDomain( ICorRuntimeHost* iface, IUnknown **pAppDomain){ RuntimeHost *This = impl_from_ICorRuntimeHost( iface ); HRESULT hr; MonoDomain *domain;
TRACE("(%p)\n", iface);
hr = RuntimeHost_GetDefaultDomain(This, &domain);
if (SUCCEEDED(hr)) { hr = RuntimeHost_GetIUnknownForDomain(This, domain, pAppDomain); }
return hr;}
static HRESULT WINAPI corruntimehost_EnumDomains( ICorRuntimeHost* iface, HDOMAINENUM *hEnum){ FIXME("stub %p\n", iface); return E_NOTIMPL;}
static HRESULT WINAPI corruntimehost_NextDomain( ICorRuntimeHost* iface, HDOMAINENUM hEnum, IUnknown **appDomain){ FIXME("stub %p\n", iface); return E_NOTIMPL;}
static HRESULT WINAPI corruntimehost_CloseEnum( ICorRuntimeHost* iface, HDOMAINENUM hEnum){ FIXME("stub %p\n", iface); return E_NOTIMPL;}
static HRESULT WINAPI corruntimehost_CreateDomainEx( ICorRuntimeHost* iface, LPCWSTR friendlyName, IUnknown *setup, IUnknown *evidence, IUnknown **appDomain){ FIXME("stub %p\n", iface); return E_NOTIMPL;}
static HRESULT WINAPI corruntimehost_CreateDomainSetup( ICorRuntimeHost* iface, IUnknown **appDomainSetup){ FIXME("stub %p\n", iface); return E_NOTIMPL;}
static HRESULT WINAPI corruntimehost_CreateEvidence( ICorRuntimeHost* iface, IUnknown **evidence){ FIXME("stub %p\n", iface); return E_NOTIMPL;}
static HRESULT WINAPI corruntimehost_UnloadDomain( ICorRuntimeHost* iface, IUnknown *appDomain){ FIXME("stub %p\n", iface); return E_NOTIMPL;}
static HRESULT WINAPI corruntimehost_CurrentDomain( ICorRuntimeHost* iface, IUnknown **appDomain){ FIXME("stub %p\n", iface); return E_NOTIMPL;}
static const struct ICorRuntimeHostVtbl corruntimehost_vtbl ={ corruntimehost_QueryInterface, corruntimehost_AddRef, corruntimehost_Release, corruntimehost_CreateLogicalThreadState, corruntimehost_DeleteLogicalThreadState, corruntimehost_SwitchInLogicalThreadState, corruntimehost_SwitchOutLogicalThreadState, corruntimehost_LocksHeldByLogicalThread, corruntimehost_MapFile, corruntimehost_GetConfiguration, corruntimehost_Start, corruntimehost_Stop, corruntimehost_CreateDomain, corruntimehost_GetDefaultDomain, corruntimehost_EnumDomains, corruntimehost_NextDomain, corruntimehost_CloseEnum, corruntimehost_CreateDomainEx, corruntimehost_CreateDomainSetup, corruntimehost_CreateEvidence, corruntimehost_UnloadDomain, corruntimehost_CurrentDomain};
static HRESULT WINAPI CLRRuntimeHost_QueryInterface(ICLRRuntimeHost* iface, REFIID riid, void **ppvObject){ RuntimeHost *This = impl_from_ICLRRuntimeHost( iface ); TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
if ( IsEqualGUID( riid, &IID_ICLRRuntimeHost ) || IsEqualGUID( riid, &IID_IUnknown ) ) { *ppvObject = iface; } else { FIXME("Unsupported interface %s\n", debugstr_guid(riid)); return E_NOINTERFACE; }
ICLRRuntimeHost_AddRef( iface );
return S_OK;}
static ULONG WINAPI CLRRuntimeHost_AddRef(ICLRRuntimeHost* iface){ RuntimeHost *This = impl_from_ICLRRuntimeHost( iface ); return ICorRuntimeHost_AddRef(&This->ICorRuntimeHost_iface);}
static ULONG WINAPI CLRRuntimeHost_Release(ICLRRuntimeHost* iface){ RuntimeHost *This = impl_from_ICLRRuntimeHost( iface ); return ICorRuntimeHost_Release(&This->ICorRuntimeHost_iface);}
static HRESULT WINAPI CLRRuntimeHost_Start(ICLRRuntimeHost* iface){ FIXME("(%p)\n", iface); return E_NOTIMPL;}
static HRESULT WINAPI CLRRuntimeHost_Stop(ICLRRuntimeHost* iface){ FIXME("(%p)\n", iface); return E_NOTIMPL;}
static HRESULT WINAPI CLRRuntimeHost_SetHostControl(ICLRRuntimeHost* iface, IHostControl *pHostControl){ FIXME("(%p,%p)\n", iface, pHostControl); return E_NOTIMPL;}
static HRESULT WINAPI CLRRuntimeHost_GetCLRControl(ICLRRuntimeHost* iface, ICLRControl **pCLRControl){ FIXME("(%p,%p)\n", iface, pCLRControl); return E_NOTIMPL;}
static HRESULT WINAPI CLRRuntimeHost_UnloadAppDomain(ICLRRuntimeHost* iface, DWORD dwAppDomainId, BOOL fWaitUntilDone){ FIXME("(%p,%u,%i)\n", iface, dwAppDomainId, fWaitUntilDone); return E_NOTIMPL;}
static HRESULT WINAPI CLRRuntimeHost_ExecuteInAppDomain(ICLRRuntimeHost* iface, DWORD dwAppDomainId, FExecuteInAppDomainCallback pCallback, void *cookie){ FIXME("(%p,%u,%p,%p)\n", iface, dwAppDomainId, pCallback, cookie); return E_NOTIMPL;}
static HRESULT WINAPI CLRRuntimeHost_GetCurrentAppDomainId(ICLRRuntimeHost* iface, DWORD *pdwAppDomainId){ FIXME("(%p,%p)\n", iface, pdwAppDomainId); return E_NOTIMPL;}
static HRESULT WINAPI CLRRuntimeHost_ExecuteApplication(ICLRRuntimeHost* iface, LPCWSTR pwzAppFullName, DWORD dwManifestPaths, LPCWSTR *ppwzManifestPaths, DWORD dwActivationData, LPCWSTR *ppwzActivationData, int *pReturnValue){ FIXME("(%p,%s,%u,%u)\n", iface, debugstr_w(pwzAppFullName), dwManifestPaths, dwActivationData); return E_NOTIMPL;}
static HRESULT WINAPI CLRRuntimeHost_ExecuteInDefaultAppDomain(ICLRRuntimeHost* iface, LPCWSTR pwzAssemblyPath, LPCWSTR pwzTypeName, LPCWSTR pwzMethodName, LPCWSTR pwzArgument, DWORD *pReturnValue){ RuntimeHost *This = impl_from_ICLRRuntimeHost( iface ); HRESULT hr; MonoDomain *domain; MonoAssembly *assembly; MonoImage *image; MonoClass *klass; MonoMethod *method; MonoObject *result; MonoString *str; void *args[2]; char *filenameA = NULL, *classA = NULL, *methodA = NULL; char *argsA = NULL, *ns;
TRACE("(%p,%s,%s,%s,%s)\n", iface, debugstr_w(pwzAssemblyPath), debugstr_w(pwzTypeName), debugstr_w(pwzMethodName), debugstr_w(pwzArgument));
hr = RuntimeHost_GetDefaultDomain(This, &domain); if(hr != S_OK) { ERR("Couldn't get Default Domain\n"); return hr; }
hr = E_FAIL;
This->mono->mono_thread_attach(domain);
filenameA = WtoA(pwzAssemblyPath); assembly = This->mono->mono_domain_assembly_open(domain, filenameA); if (!assembly) { ERR("Cannot open assembly %s\n", filenameA); goto cleanup; }
image = This->mono->mono_assembly_get_image(assembly); if (!image) { ERR("Couldn't get assembly image\n"); goto cleanup; }
classA = WtoA(pwzTypeName); ns = strrchr(classA, '.'); *ns = '\0'; klass = This->mono->mono_class_from_name(image, classA, ns+1); if (!klass) { ERR("Couldn't get class from image\n"); goto cleanup; }
methodA = WtoA(pwzMethodName); method = This->mono->mono_class_get_method_from_name(klass, methodA, 1); if (!method) { ERR("Couldn't get method from class\n"); goto cleanup; }
/* The .NET function we are calling has the following declaration * public static int functionName(String param) */ argsA = WtoA(pwzArgument); str = This->mono->mono_string_new(domain, argsA); args[0] = str; args[1] = NULL; result = This->mono->mono_runtime_invoke(method, NULL, args, NULL); if (!result) ERR("Couldn't get result pointer\n"); else { *pReturnValue = *(DWORD*)This->mono->mono_object_unbox(result); hr = S_OK; }
cleanup: HeapFree(GetProcessHeap(), 0, filenameA); HeapFree(GetProcessHeap(), 0, classA); HeapFree(GetProcessHeap(), 0, argsA); HeapFree(GetProcessHeap(), 0, methodA);
return hr;}
static const struct ICLRRuntimeHostVtbl CLRHostVtbl ={ CLRRuntimeHost_QueryInterface, CLRRuntimeHost_AddRef, CLRRuntimeHost_Release, CLRRuntimeHost_Start, CLRRuntimeHost_Stop, CLRRuntimeHost_SetHostControl, CLRRuntimeHost_GetCLRControl, CLRRuntimeHost_UnloadAppDomain, CLRRuntimeHost_ExecuteInAppDomain, CLRRuntimeHost_GetCurrentAppDomainId, CLRRuntimeHost_ExecuteApplication, CLRRuntimeHost_ExecuteInDefaultAppDomain};
/* Create an instance of a type given its name, by calling its constructor with * no arguments. Note that result MUST be in the stack, or the garbage * collector may free it prematurely. */HRESULT RuntimeHost_CreateManagedInstance(RuntimeHost *This, LPCWSTR name, MonoDomain *domain, MonoObject **result){ HRESULT hr=S_OK; char *nameA=NULL; MonoType *type; MonoClass *klass; MonoObject *obj;
if (!domain) hr = RuntimeHost_GetDefaultDomain(This, &domain);
if (SUCCEEDED(hr)) { nameA = WtoA(name); if (!nameA) hr = E_OUTOFMEMORY; }
if (SUCCEEDED(hr)) { This->mono->mono_thread_attach(domain);
type = This->mono->mono_reflection_type_from_name(nameA, NULL); if (!type) { ERR("Cannot find type %s\n", debugstr_w(name)); hr = E_FAIL; } }
if (SUCCEEDED(hr)) { klass = This->mono->mono_class_from_mono_type(type); if (!klass) { ERR("Cannot convert type %s to a class\n", debugstr_w(name)); hr = E_FAIL; } }
if (SUCCEEDED(hr)) { obj = This->mono->mono_object_new(domain, klass); if (!obj) { ERR("Cannot allocate object of type %s\n", debugstr_w(name)); hr = E_FAIL; } }
if (SUCCEEDED(hr)) { /* FIXME: Detect exceptions from the constructor? */ This->mono->mono_runtime_object_init(obj); *result = obj; }
HeapFree(GetProcessHeap(), 0, nameA);
return hr;}
/* Get an IUnknown pointer for a Mono object. * * This is just a "light" wrapper around * System.Runtime.InteropServices.Marshal:GetIUnknownForObject * * 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 * garbage collector from freeing them. * * mono_thread_attach must have already been called for this thread. */HRESULT RuntimeHost_GetIUnknownForObject(RuntimeHost *This, MonoObject *obj, IUnknown **ppUnk){ MonoDomain *domain; MonoAssembly *assembly; MonoImage *image; MonoClass *klass; MonoMethod *method; MonoObject *result; void *args[2];
domain = This->mono->mono_object_get_domain(obj);
assembly = This->mono->mono_domain_assembly_open(domain, "mscorlib"); if (!assembly) { ERR("Cannot load mscorlib\n"); return E_FAIL; }
image = This->mono->mono_assembly_get_image(assembly); if (!image) { ERR("Couldn't get assembly image\n"); return E_FAIL; }
klass = This->mono->mono_class_from_name(image, "System.Runtime.InteropServices", "Marshal"); if (!klass) { ERR("Couldn't get class from image\n"); return E_FAIL; }
method = This->mono->mono_class_get_method_from_name(klass, "GetIUnknownForObject", 1); if (!method) { ERR("Couldn't get method from class\n"); return E_FAIL; }
args[0] = obj; args[1] = NULL; result = This->mono->mono_runtime_invoke(method, NULL, args, NULL); if (!result) { ERR("Couldn't get result pointer\n"); return E_FAIL; }
*ppUnk = *(IUnknown**)This->mono->mono_object_unbox(result); if (!*ppUnk) { ERR("GetIUnknownForObject returned 0\n"); return E_FAIL; }
return S_OK;}
static void get_utf8_args(int *argc, char ***argv){ WCHAR **argvw; int size=0, i; char *current_arg;
argvw = CommandLineToArgvW(GetCommandLineW(), argc);
for (i=0; i<*argc; i++) { size += sizeof(char*); size += WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, NULL, 0, NULL, NULL); } size += sizeof(char*);
*argv = HeapAlloc(GetProcessHeap(), 0, size); current_arg = (char*)(*argv + *argc + 1);
for (i=0; i<*argc; i++) { (*argv)[i] = current_arg; current_arg += WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, current_arg, size, NULL, NULL); }
(*argv)[*argc] = NULL;
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) ICLRRuntimeInfo_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){ int exit_code; int argc; char **argv; MonoDomain *domain; MonoImage *image; MonoImageOpenStatus status; MonoAssembly *assembly=NULL; WCHAR filename[MAX_PATH]; char *filenameA; ICLRRuntimeInfo *info; RuntimeHost *host; HRESULT hr; int i;
get_utf8_args(&argc, &argv);
GetModuleFileNameW(NULL, filename, MAX_PATH);
TRACE("%s", debugstr_w(filename)); for (i=0; i<argc; i++) TRACE(" %s", debugstr_a(argv[i])); TRACE("\n");
filenameA = WtoA(filename); if (!filenameA) return -1;
FixupVTable(GetModuleHandleW(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)) { image = host->mono->mono_image_open_from_module_handle(GetModuleHandleW(NULL), filenameA, 1, &status);
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); } else exit_code = -1;
ICLRRuntimeInfo_Release(info); } else exit_code = -1;
HeapFree(GetProcessHeap(), 0, argv);
unload_all_runtimes();
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, loaded_mono *loaded_mono, RuntimeHost** result){ RuntimeHost *This;
This = HeapAlloc( GetProcessHeap(), 0, sizeof *This ); if ( !This ) return E_OUTOFMEMORY;
This->ICorRuntimeHost_iface.lpVtbl = &corruntimehost_vtbl; This->ICLRRuntimeHost_iface.lpVtbl = &CLRHostVtbl;
This->ref = 1; This->version = runtime_version; This->mono = loaded_mono; list_init(&This->domains); This->default_domain = NULL; InitializeCriticalSection(&This->lock); This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": RuntimeHost.lock");
*result = This;
return S_OK;}
HRESULT RuntimeHost_GetInterface(RuntimeHost *This, REFCLSID clsid, REFIID riid, void **ppv){ IUnknown *unk; HRESULT hr;
if (IsEqualGUID(clsid, &CLSID_CorRuntimeHost)) { unk = (IUnknown*)&This->ICorRuntimeHost_iface; IUnknown_AddRef(unk); } else if (IsEqualGUID(clsid, &CLSID_CLRRuntimeHost)) { unk = (IUnknown*)&This->ICLRRuntimeHost_iface; IUnknown_AddRef(unk); } else if (IsEqualGUID(clsid, &CLSID_CorMetaDataDispenser) || IsEqualGUID(clsid, &CLSID_CorMetaDataDispenserRuntime)) { hr = MetaDataDispenser_CreateInstance(&unk); if (FAILED(hr)) return hr; } else if (IsEqualGUID(clsid, &CLSID_CLRDebuggingLegacy)) { hr = CorDebug_Create(&This->ICLRRuntimeHost_iface, &unk); if (FAILED(hr)) return hr; } else unk = NULL;
if (unk) { hr = IUnknown_QueryInterface(unk, riid, ppv);
IUnknown_Release(unk);
return hr; } else FIXME("not implemented for class %s\n", debugstr_guid(clsid));
return CLASS_E_CLASSNOTAVAILABLE;}
HRESULT RuntimeHost_Destroy(RuntimeHost *This){ struct DomainEntry *cursor, *cursor2;
This->lock.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&This->lock);
LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->domains, struct DomainEntry, entry) { list_remove(&cursor->entry); HeapFree(GetProcessHeap(), 0, cursor); }
HeapFree( GetProcessHeap(), 0, This ); return S_OK;}
#define CHARS_IN_GUID 39#undef ARRAYSIZE#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 = NULL; 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;}