3 * Copyright 2008 Alistair Leslie-Hughes
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
37 #include "wine/list.h"
38 #include "mscoree_private.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
46 DEFINE_GUID(IID__AppDomain, 0x05f696dc,0x2b29,0x3663,0xad,0x8b,0xc4,0x38,0x9c,0xf2,0xa7,0x13);
54 static HRESULT RuntimeHost_AddDomain(RuntimeHost *This, MonoDomain **result)
56 struct DomainEntry *entry;
60 EnterCriticalSection(&This->lock);
62 entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry));
69 mscorlib_path = WtoA(This->version->mscorlib_path);
72 HeapFree(GetProcessHeap(), 0, entry);
77 entry->domain = This->mono->mono_jit_init(mscorlib_path);
79 HeapFree(GetProcessHeap(), 0, mscorlib_path);
83 HeapFree(GetProcessHeap(), 0, entry);
88 This->mono->is_started = TRUE;
90 list_add_tail(&This->domains, &entry->entry);
92 *result = entry->domain;
95 LeaveCriticalSection(&This->lock);
100 static HRESULT RuntimeHost_GetDefaultDomain(RuntimeHost *This, MonoDomain **result)
104 EnterCriticalSection(&This->lock);
106 if (This->default_domain) goto end;
108 res = RuntimeHost_AddDomain(This, &This->default_domain);
111 *result = This->default_domain;
113 LeaveCriticalSection(&This->lock);
118 static void RuntimeHost_DeleteDomain(RuntimeHost *This, MonoDomain *domain)
120 struct DomainEntry *entry;
122 EnterCriticalSection(&This->lock);
124 LIST_FOR_EACH_ENTRY(entry, &This->domains, struct DomainEntry, entry)
126 if (entry->domain == domain)
128 list_remove(&entry->entry);
129 if (This->default_domain == domain)
130 This->default_domain = NULL;
131 HeapFree(GetProcessHeap(), 0, entry);
136 LeaveCriticalSection(&This->lock);
139 static HRESULT RuntimeHost_GetIUnknownForDomain(RuntimeHost *This, MonoDomain *domain, IUnknown **punk)
143 MonoAssembly *assembly;
147 MonoObject *appdomain_object;
150 assembly = This->mono->mono_domain_assembly_open(domain, "mscorlib");
153 ERR("Cannot load mscorlib\n");
157 image = This->mono->mono_assembly_get_image(assembly);
160 ERR("Couldn't get assembly image\n");
164 klass = This->mono->mono_class_from_name(image, "System", "AppDomain");
167 ERR("Couldn't get class from image\n");
171 method = This->mono->mono_class_get_method_from_name(klass, "get_CurrentDomain", 0);
174 ERR("Couldn't get method from class\n");
179 appdomain_object = This->mono->mono_runtime_invoke(method, NULL, args, NULL);
180 if (!appdomain_object)
182 ERR("Couldn't get result pointer\n");
186 hr = RuntimeHost_GetIUnknownForObject(This, appdomain_object, &unk);
190 hr = IUnknown_QueryInterface(unk, &IID__AppDomain, (void**)punk);
192 IUnknown_Release(unk);
198 static inline RuntimeHost *impl_from_ICLRRuntimeHost( ICLRRuntimeHost *iface )
200 return CONTAINING_RECORD(iface, RuntimeHost, ICLRRuntimeHost_iface);
203 static inline RuntimeHost *impl_from_ICorRuntimeHost( ICorRuntimeHost *iface )
205 return CONTAINING_RECORD(iface, RuntimeHost, ICorRuntimeHost_iface);
208 /*** IUnknown methods ***/
209 static HRESULT WINAPI corruntimehost_QueryInterface(ICorRuntimeHost* iface,
213 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
214 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
216 if ( IsEqualGUID( riid, &IID_ICorRuntimeHost ) ||
217 IsEqualGUID( riid, &IID_IUnknown ) )
223 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
224 return E_NOINTERFACE;
227 ICorRuntimeHost_AddRef( iface );
232 static ULONG WINAPI corruntimehost_AddRef(ICorRuntimeHost* iface)
234 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
236 return InterlockedIncrement( &This->ref );
239 static ULONG WINAPI corruntimehost_Release(ICorRuntimeHost* iface)
241 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
244 ref = InterlockedDecrement( &This->ref );
249 /*** ICorRuntimeHost methods ***/
250 static HRESULT WINAPI corruntimehost_CreateLogicalThreadState(
251 ICorRuntimeHost* iface)
253 FIXME("stub %p\n", iface);
257 static HRESULT WINAPI corruntimehost_DeleteLogicalThreadState(
258 ICorRuntimeHost* iface)
260 FIXME("stub %p\n", iface);
264 static HRESULT WINAPI corruntimehost_SwitchInLogicalThreadState(
265 ICorRuntimeHost* iface,
268 FIXME("stub %p\n", iface);
272 static HRESULT WINAPI corruntimehost_SwitchOutLogicalThreadState(
273 ICorRuntimeHost* iface,
276 FIXME("stub %p\n", iface);
280 static HRESULT WINAPI corruntimehost_LocksHeldByLogicalThread(
281 ICorRuntimeHost* iface,
284 FIXME("stub %p\n", iface);
288 static HRESULT WINAPI corruntimehost_MapFile(
289 ICorRuntimeHost* iface,
293 FIXME("stub %p\n", iface);
297 static HRESULT WINAPI corruntimehost_GetConfiguration(
298 ICorRuntimeHost* iface,
299 ICorConfiguration **pConfiguration)
301 FIXME("stub %p\n", iface);
305 static HRESULT WINAPI corruntimehost_Start(
306 ICorRuntimeHost* iface)
308 FIXME("stub %p\n", iface);
312 static HRESULT WINAPI corruntimehost_Stop(
313 ICorRuntimeHost* iface)
315 FIXME("stub %p\n", iface);
319 static HRESULT WINAPI corruntimehost_CreateDomain(
320 ICorRuntimeHost* iface,
321 LPCWSTR friendlyName,
322 IUnknown *identityArray,
323 IUnknown **appDomain)
325 FIXME("stub %p\n", iface);
329 static HRESULT WINAPI corruntimehost_GetDefaultDomain(
330 ICorRuntimeHost* iface,
331 IUnknown **pAppDomain)
333 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
337 TRACE("(%p)\n", iface);
339 hr = RuntimeHost_GetDefaultDomain(This, &domain);
343 hr = RuntimeHost_GetIUnknownForDomain(This, domain, pAppDomain);
349 static HRESULT WINAPI corruntimehost_EnumDomains(
350 ICorRuntimeHost* iface,
353 FIXME("stub %p\n", iface);
357 static HRESULT WINAPI corruntimehost_NextDomain(
358 ICorRuntimeHost* iface,
360 IUnknown **appDomain)
362 FIXME("stub %p\n", iface);
366 static HRESULT WINAPI corruntimehost_CloseEnum(
367 ICorRuntimeHost* iface,
370 FIXME("stub %p\n", iface);
374 static HRESULT WINAPI corruntimehost_CreateDomainEx(
375 ICorRuntimeHost* iface,
376 LPCWSTR friendlyName,
379 IUnknown **appDomain)
381 FIXME("stub %p\n", iface);
385 static HRESULT WINAPI corruntimehost_CreateDomainSetup(
386 ICorRuntimeHost* iface,
387 IUnknown **appDomainSetup)
389 FIXME("stub %p\n", iface);
393 static HRESULT WINAPI corruntimehost_CreateEvidence(
394 ICorRuntimeHost* iface,
397 FIXME("stub %p\n", iface);
401 static HRESULT WINAPI corruntimehost_UnloadDomain(
402 ICorRuntimeHost* iface,
405 FIXME("stub %p\n", iface);
409 static HRESULT WINAPI corruntimehost_CurrentDomain(
410 ICorRuntimeHost* iface,
411 IUnknown **appDomain)
413 FIXME("stub %p\n", iface);
417 static const struct ICorRuntimeHostVtbl corruntimehost_vtbl =
419 corruntimehost_QueryInterface,
420 corruntimehost_AddRef,
421 corruntimehost_Release,
422 corruntimehost_CreateLogicalThreadState,
423 corruntimehost_DeleteLogicalThreadState,
424 corruntimehost_SwitchInLogicalThreadState,
425 corruntimehost_SwitchOutLogicalThreadState,
426 corruntimehost_LocksHeldByLogicalThread,
427 corruntimehost_MapFile,
428 corruntimehost_GetConfiguration,
429 corruntimehost_Start,
431 corruntimehost_CreateDomain,
432 corruntimehost_GetDefaultDomain,
433 corruntimehost_EnumDomains,
434 corruntimehost_NextDomain,
435 corruntimehost_CloseEnum,
436 corruntimehost_CreateDomainEx,
437 corruntimehost_CreateDomainSetup,
438 corruntimehost_CreateEvidence,
439 corruntimehost_UnloadDomain,
440 corruntimehost_CurrentDomain
443 static HRESULT WINAPI CLRRuntimeHost_QueryInterface(ICLRRuntimeHost* iface,
447 RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
448 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
450 if ( IsEqualGUID( riid, &IID_ICLRRuntimeHost ) ||
451 IsEqualGUID( riid, &IID_IUnknown ) )
457 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
458 return E_NOINTERFACE;
461 ICLRRuntimeHost_AddRef( iface );
466 static ULONG WINAPI CLRRuntimeHost_AddRef(ICLRRuntimeHost* iface)
468 RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
469 return ICorRuntimeHost_AddRef(&This->ICorRuntimeHost_iface);
472 static ULONG WINAPI CLRRuntimeHost_Release(ICLRRuntimeHost* iface)
474 RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
475 return ICorRuntimeHost_Release(&This->ICorRuntimeHost_iface);
478 static HRESULT WINAPI CLRRuntimeHost_Start(ICLRRuntimeHost* iface)
480 FIXME("(%p)\n", iface);
484 static HRESULT WINAPI CLRRuntimeHost_Stop(ICLRRuntimeHost* iface)
486 FIXME("(%p)\n", iface);
490 static HRESULT WINAPI CLRRuntimeHost_SetHostControl(ICLRRuntimeHost* iface,
491 IHostControl *pHostControl)
493 FIXME("(%p,%p)\n", iface, pHostControl);
497 static HRESULT WINAPI CLRRuntimeHost_GetCLRControl(ICLRRuntimeHost* iface,
498 ICLRControl **pCLRControl)
500 FIXME("(%p,%p)\n", iface, pCLRControl);
504 static HRESULT WINAPI CLRRuntimeHost_UnloadAppDomain(ICLRRuntimeHost* iface,
505 DWORD dwAppDomainId, BOOL fWaitUntilDone)
507 FIXME("(%p,%u,%i)\n", iface, dwAppDomainId, fWaitUntilDone);
511 static HRESULT WINAPI CLRRuntimeHost_ExecuteInAppDomain(ICLRRuntimeHost* iface,
512 DWORD dwAppDomainId, FExecuteInAppDomainCallback pCallback, void *cookie)
514 FIXME("(%p,%u,%p,%p)\n", iface, dwAppDomainId, pCallback, cookie);
518 static HRESULT WINAPI CLRRuntimeHost_GetCurrentAppDomainId(ICLRRuntimeHost* iface,
519 DWORD *pdwAppDomainId)
521 FIXME("(%p,%p)\n", iface, pdwAppDomainId);
525 static HRESULT WINAPI CLRRuntimeHost_ExecuteApplication(ICLRRuntimeHost* iface,
526 LPCWSTR pwzAppFullName, DWORD dwManifestPaths, LPCWSTR *ppwzManifestPaths,
527 DWORD dwActivationData, LPCWSTR *ppwzActivationData, int *pReturnValue)
529 FIXME("(%p,%s,%u,%u)\n", iface, debugstr_w(pwzAppFullName), dwManifestPaths, dwActivationData);
533 static HRESULT WINAPI CLRRuntimeHost_ExecuteInDefaultAppDomain(ICLRRuntimeHost* iface,
534 LPCWSTR pwzAssemblyPath, LPCWSTR pwzTypeName, LPCWSTR pwzMethodName,
535 LPCWSTR pwzArgument, DWORD *pReturnValue)
537 FIXME("(%p,%s,%s,%s,%s)\n", iface, debugstr_w(pwzAssemblyPath),
538 debugstr_w(pwzTypeName), debugstr_w(pwzMethodName), debugstr_w(pwzArgument));
542 static const struct ICLRRuntimeHostVtbl CLRHostVtbl =
544 CLRRuntimeHost_QueryInterface,
545 CLRRuntimeHost_AddRef,
546 CLRRuntimeHost_Release,
547 CLRRuntimeHost_Start,
549 CLRRuntimeHost_SetHostControl,
550 CLRRuntimeHost_GetCLRControl,
551 CLRRuntimeHost_UnloadAppDomain,
552 CLRRuntimeHost_ExecuteInAppDomain,
553 CLRRuntimeHost_GetCurrentAppDomainId,
554 CLRRuntimeHost_ExecuteApplication,
555 CLRRuntimeHost_ExecuteInDefaultAppDomain
558 /* Create an instance of a type given its name, by calling its constructor with
559 * no arguments. Note that result MUST be in the stack, or the garbage
560 * collector may free it prematurely. */
561 HRESULT RuntimeHost_CreateManagedInstance(RuntimeHost *This, LPCWSTR name,
562 MonoDomain *domain, MonoObject **result)
571 hr = RuntimeHost_GetDefaultDomain(This, &domain);
582 type = This->mono->mono_reflection_type_from_name(nameA, NULL);
585 ERR("Cannot find type %s\n", debugstr_w(name));
592 klass = This->mono->mono_class_from_mono_type(type);
595 ERR("Cannot convert type %s to a class\n", debugstr_w(name));
602 obj = This->mono->mono_object_new(domain, klass);
605 ERR("Cannot allocate object of type %s\n", debugstr_w(name));
612 /* FIXME: Detect exceptions from the constructor? */
613 This->mono->mono_runtime_object_init(obj);
617 HeapFree(GetProcessHeap(), 0, nameA);
622 /* Get an IUnknown pointer for a Mono object.
624 * This is just a "light" wrapper around
625 * System.Runtime.InteropServices.Marshal:GetIUnknownForObject
627 * NOTE: The IUnknown* is created with a reference to the object.
628 * Until they have a reference, objects must be in the stack to prevent the
629 * garbage collector from freeing them. */
630 HRESULT RuntimeHost_GetIUnknownForObject(RuntimeHost *This, MonoObject *obj,
634 MonoAssembly *assembly;
641 domain = This->mono->mono_object_get_domain(obj);
643 assembly = This->mono->mono_domain_assembly_open(domain, "mscorlib");
646 ERR("Cannot load mscorlib\n");
650 image = This->mono->mono_assembly_get_image(assembly);
653 ERR("Couldn't get assembly image\n");
657 klass = This->mono->mono_class_from_name(image, "System.Runtime.InteropServices", "Marshal");
660 ERR("Couldn't get class from image\n");
664 method = This->mono->mono_class_get_method_from_name(klass, "GetIUnknownForObject", 1);
667 ERR("Couldn't get method from class\n");
673 result = This->mono->mono_runtime_invoke(method, NULL, args, NULL);
676 ERR("Couldn't get result pointer\n");
680 *ppUnk = *(IUnknown**)This->mono->mono_object_unbox(result);
683 ERR("GetIUnknownForObject returned 0\n");
690 static void get_utf8_args(int *argc, char ***argv)
696 argvw = CommandLineToArgvW(GetCommandLineW(), argc);
698 for (i=0; i<*argc; i++)
700 size += sizeof(char*);
701 size += WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, NULL, 0, NULL, NULL);
703 size += sizeof(char*);
705 *argv = HeapAlloc(GetProcessHeap(), 0, size);
706 current_arg = (char*)(*argv + *argc + 1);
708 for (i=0; i<*argc; i++)
710 (*argv)[i] = current_arg;
711 current_arg += WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, current_arg, size, NULL, NULL);
714 (*argv)[*argc] = NULL;
716 HeapFree(GetProcessHeap(), 0, argvw);
719 __int32 WINAPI _CorExeMain(void)
725 MonoAssembly *assembly;
726 WCHAR filename[MAX_PATH];
728 ICLRRuntimeInfo *info;
733 get_utf8_args(&argc, &argv);
735 GetModuleFileNameW(NULL, filename, MAX_PATH);
737 TRACE("%s", debugstr_w(filename));
738 for (i=0; i<argc; i++)
739 TRACE(" %s", debugstr_a(argv[i]));
742 filenameA = WtoA(filename);
746 hr = get_runtime_info(filename, NULL, NULL, 0, 0, FALSE, &info);
750 hr = ICLRRuntimeInfo_GetRuntimeHost(info, &host);
753 hr = RuntimeHost_GetDefaultDomain(host, &domain);
757 assembly = host->mono->mono_domain_assembly_open(domain, filenameA);
759 exit_code = host->mono->mono_jit_exec(domain, assembly, argc, argv);
761 RuntimeHost_DeleteDomain(host, domain);
766 ICLRRuntimeInfo_Release(info);
771 HeapFree(GetProcessHeap(), 0, argv);
773 unload_all_runtimes();
778 HRESULT RuntimeHost_Construct(const CLRRuntimeInfo *runtime_version,
779 loaded_mono *loaded_mono, RuntimeHost** result)
783 This = HeapAlloc( GetProcessHeap(), 0, sizeof *This );
785 return E_OUTOFMEMORY;
787 This->ICorRuntimeHost_iface.lpVtbl = &corruntimehost_vtbl;
788 This->ICLRRuntimeHost_iface.lpVtbl = &CLRHostVtbl;
791 This->version = runtime_version;
792 This->mono = loaded_mono;
793 list_init(&This->domains);
794 This->default_domain = NULL;
795 InitializeCriticalSection(&This->lock);
796 This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": RuntimeHost.lock");
803 HRESULT RuntimeHost_GetInterface(RuntimeHost *This, REFCLSID clsid, REFIID riid, void **ppv)
808 if (IsEqualGUID(clsid, &CLSID_CorRuntimeHost))
810 unk = (IUnknown*)&This->ICorRuntimeHost_iface;
811 IUnknown_AddRef(unk);
813 else if (IsEqualGUID(clsid, &CLSID_CLRRuntimeHost))
815 unk = (IUnknown*)&This->ICLRRuntimeHost_iface;
816 IUnknown_AddRef(unk);
818 else if (IsEqualGUID(clsid, &CLSID_CorMetaDataDispenser) ||
819 IsEqualGUID(clsid, &CLSID_CorMetaDataDispenserRuntime))
821 hr = MetaDataDispenser_CreateInstance(&unk);
825 else if (IsEqualGUID(clsid, &CLSID_CLRDebuggingLegacy))
827 hr = CorDebug_Create(&This->ICLRRuntimeHost_iface, &unk);
836 hr = IUnknown_QueryInterface(unk, riid, ppv);
838 IUnknown_Release(unk);
843 FIXME("not implemented for class %s\n", debugstr_guid(clsid));
845 return CLASS_E_CLASSNOTAVAILABLE;
848 HRESULT RuntimeHost_Destroy(RuntimeHost *This)
850 struct DomainEntry *cursor, *cursor2;
852 This->lock.DebugInfo->Spare[0] = 0;
853 DeleteCriticalSection(&This->lock);
855 LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->domains, struct DomainEntry, entry)
857 list_remove(&cursor->entry);
858 HeapFree(GetProcessHeap(), 0, cursor);
861 HeapFree( GetProcessHeap(), 0, This );