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
);