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
35 #include "wine/list.h"
36 #include "mscoree_private.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL( mscoree
);
44 DEFINE_GUID(IID__AppDomain
, 0x05f696dc,0x2b29,0x3663,0xad,0x8b,0xc4,0x38,0x9c,0xf2,0xa7,0x13);
48 ICorRuntimeHost ICorRuntimeHost_iface
;
49 ICLRRuntimeHost ICLRRuntimeHost_iface
;
50 const CLRRuntimeInfo
*version
;
53 MonoDomain
*default_domain
;
54 CRITICAL_SECTION lock
;
64 static HRESULT
RuntimeHost_AddDomain(RuntimeHost
*This
, MonoDomain
**result
)
66 struct DomainEntry
*entry
;
70 EnterCriticalSection(&This
->lock
);
72 entry
= HeapAlloc(GetProcessHeap(), 0, sizeof(*entry
));
79 mscorlib_path
= WtoA(This
->version
->mscorlib_path
);
82 HeapFree(GetProcessHeap(), 0, entry
);
87 entry
->domain
= This
->mono
->mono_jit_init(mscorlib_path
);
89 HeapFree(GetProcessHeap(), 0, mscorlib_path
);
93 HeapFree(GetProcessHeap(), 0, entry
);
98 This
->mono
->is_started
= TRUE
;
100 list_add_tail(&This
->domains
, &entry
->entry
);
102 *result
= entry
->domain
;
105 LeaveCriticalSection(&This
->lock
);
110 static HRESULT
RuntimeHost_GetDefaultDomain(RuntimeHost
*This
, MonoDomain
**result
)
114 EnterCriticalSection(&This
->lock
);
116 if (This
->default_domain
) goto end
;
118 res
= RuntimeHost_AddDomain(This
, &This
->default_domain
);
121 *result
= This
->default_domain
;
123 LeaveCriticalSection(&This
->lock
);
128 static void RuntimeHost_DeleteDomain(RuntimeHost
*This
, MonoDomain
*domain
)
130 struct DomainEntry
*entry
;
132 EnterCriticalSection(&This
->lock
);
134 LIST_FOR_EACH_ENTRY(entry
, &This
->domains
, struct DomainEntry
, entry
)
136 if (entry
->domain
== domain
)
138 list_remove(&entry
->entry
);
139 if (This
->default_domain
== domain
)
140 This
->default_domain
= NULL
;
141 HeapFree(GetProcessHeap(), 0, entry
);
146 LeaveCriticalSection(&This
->lock
);
149 static HRESULT
RuntimeHost_GetIUnknownForDomain(RuntimeHost
*This
, MonoDomain
*domain
, IUnknown
**punk
)
153 MonoAssembly
*assembly
;
157 MonoObject
*appdomain_object
;
160 assembly
= This
->mono
->mono_domain_assembly_open(domain
, "mscorlib");
163 ERR("Cannot load mscorlib\n");
167 image
= This
->mono
->mono_assembly_get_image(assembly
);
170 ERR("Couldn't get assembly image\n");
174 klass
= This
->mono
->mono_class_from_name(image
, "System", "AppDomain");
177 ERR("Couldn't get class from image\n");
181 method
= This
->mono
->mono_class_get_method_from_name(klass
, "get_CurrentDomain", 0);
184 ERR("Couldn't get method from class\n");
189 appdomain_object
= This
->mono
->mono_runtime_invoke(method
, NULL
, args
, NULL
);
190 if (!appdomain_object
)
192 ERR("Couldn't get result pointer\n");
196 hr
= RuntimeHost_GetIUnknownForObject(This
, appdomain_object
, &unk
);
200 hr
= IUnknown_QueryInterface(unk
, &IID__AppDomain
, (void**)punk
);
202 IUnknown_Release(unk
);
208 static inline RuntimeHost
*impl_from_ICLRRuntimeHost( ICLRRuntimeHost
*iface
)
210 return CONTAINING_RECORD(iface
, RuntimeHost
, ICLRRuntimeHost_iface
);
213 static inline RuntimeHost
*impl_from_ICorRuntimeHost( ICorRuntimeHost
*iface
)
215 return CONTAINING_RECORD(iface
, RuntimeHost
, ICorRuntimeHost_iface
);
218 /*** IUnknown methods ***/
219 static HRESULT WINAPI
corruntimehost_QueryInterface(ICorRuntimeHost
* iface
,
223 RuntimeHost
*This
= impl_from_ICorRuntimeHost( iface
);
224 TRACE("%p %s %p\n", This
, debugstr_guid(riid
), ppvObject
);
226 if ( IsEqualGUID( riid
, &IID_ICorRuntimeHost
) ||
227 IsEqualGUID( riid
, &IID_IUnknown
) )
233 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
234 return E_NOINTERFACE
;
237 ICorRuntimeHost_AddRef( iface
);
242 static ULONG WINAPI
corruntimehost_AddRef(ICorRuntimeHost
* iface
)
244 RuntimeHost
*This
= impl_from_ICorRuntimeHost( iface
);
246 return InterlockedIncrement( &This
->ref
);
249 static ULONG WINAPI
corruntimehost_Release(ICorRuntimeHost
* iface
)
251 RuntimeHost
*This
= impl_from_ICorRuntimeHost( iface
);
254 ref
= InterlockedDecrement( &This
->ref
);
259 /*** ICorRuntimeHost methods ***/
260 static HRESULT WINAPI
corruntimehost_CreateLogicalThreadState(
261 ICorRuntimeHost
* iface
)
263 FIXME("stub %p\n", iface
);
267 static HRESULT WINAPI
corruntimehost_DeleteLogicalThreadState(
268 ICorRuntimeHost
* iface
)
270 FIXME("stub %p\n", iface
);
274 static HRESULT WINAPI
corruntimehost_SwitchInLogicalThreadState(
275 ICorRuntimeHost
* iface
,
278 FIXME("stub %p\n", iface
);
282 static HRESULT WINAPI
corruntimehost_SwitchOutLogicalThreadState(
283 ICorRuntimeHost
* iface
,
286 FIXME("stub %p\n", iface
);
290 static HRESULT WINAPI
corruntimehost_LocksHeldByLogicalThread(
291 ICorRuntimeHost
* iface
,
294 FIXME("stub %p\n", iface
);
298 static HRESULT WINAPI
corruntimehost_MapFile(
299 ICorRuntimeHost
* iface
,
303 FIXME("stub %p\n", iface
);
307 static HRESULT WINAPI
corruntimehost_GetConfiguration(
308 ICorRuntimeHost
* iface
,
309 ICorConfiguration
**pConfiguration
)
311 FIXME("stub %p\n", iface
);
315 static HRESULT WINAPI
corruntimehost_Start(
316 ICorRuntimeHost
* iface
)
318 FIXME("stub %p\n", iface
);
322 static HRESULT WINAPI
corruntimehost_Stop(
323 ICorRuntimeHost
* iface
)
325 FIXME("stub %p\n", iface
);
329 static HRESULT WINAPI
corruntimehost_CreateDomain(
330 ICorRuntimeHost
* iface
,
331 LPCWSTR friendlyName
,
332 IUnknown
*identityArray
,
333 IUnknown
**appDomain
)
335 FIXME("stub %p\n", iface
);
339 static HRESULT WINAPI
corruntimehost_GetDefaultDomain(
340 ICorRuntimeHost
* iface
,
341 IUnknown
**pAppDomain
)
343 RuntimeHost
*This
= impl_from_ICorRuntimeHost( iface
);
347 TRACE("(%p)\n", iface
);
349 hr
= RuntimeHost_GetDefaultDomain(This
, &domain
);
353 hr
= RuntimeHost_GetIUnknownForDomain(This
, domain
, pAppDomain
);
359 static HRESULT WINAPI
corruntimehost_EnumDomains(
360 ICorRuntimeHost
* iface
,
363 FIXME("stub %p\n", iface
);
367 static HRESULT WINAPI
corruntimehost_NextDomain(
368 ICorRuntimeHost
* iface
,
370 IUnknown
**appDomain
)
372 FIXME("stub %p\n", iface
);
376 static HRESULT WINAPI
corruntimehost_CloseEnum(
377 ICorRuntimeHost
* iface
,
380 FIXME("stub %p\n", iface
);
384 static HRESULT WINAPI
corruntimehost_CreateDomainEx(
385 ICorRuntimeHost
* iface
,
386 LPCWSTR friendlyName
,
389 IUnknown
**appDomain
)
391 FIXME("stub %p\n", iface
);
395 static HRESULT WINAPI
corruntimehost_CreateDomainSetup(
396 ICorRuntimeHost
* iface
,
397 IUnknown
**appDomainSetup
)
399 FIXME("stub %p\n", iface
);
403 static HRESULT WINAPI
corruntimehost_CreateEvidence(
404 ICorRuntimeHost
* iface
,
407 FIXME("stub %p\n", iface
);
411 static HRESULT WINAPI
corruntimehost_UnloadDomain(
412 ICorRuntimeHost
* iface
,
415 FIXME("stub %p\n", iface
);
419 static HRESULT WINAPI
corruntimehost_CurrentDomain(
420 ICorRuntimeHost
* iface
,
421 IUnknown
**appDomain
)
423 FIXME("stub %p\n", iface
);
427 static const struct ICorRuntimeHostVtbl corruntimehost_vtbl
=
429 corruntimehost_QueryInterface
,
430 corruntimehost_AddRef
,
431 corruntimehost_Release
,
432 corruntimehost_CreateLogicalThreadState
,
433 corruntimehost_DeleteLogicalThreadState
,
434 corruntimehost_SwitchInLogicalThreadState
,
435 corruntimehost_SwitchOutLogicalThreadState
,
436 corruntimehost_LocksHeldByLogicalThread
,
437 corruntimehost_MapFile
,
438 corruntimehost_GetConfiguration
,
439 corruntimehost_Start
,
441 corruntimehost_CreateDomain
,
442 corruntimehost_GetDefaultDomain
,
443 corruntimehost_EnumDomains
,
444 corruntimehost_NextDomain
,
445 corruntimehost_CloseEnum
,
446 corruntimehost_CreateDomainEx
,
447 corruntimehost_CreateDomainSetup
,
448 corruntimehost_CreateEvidence
,
449 corruntimehost_UnloadDomain
,
450 corruntimehost_CurrentDomain
453 static HRESULT WINAPI
CLRRuntimeHost_QueryInterface(ICLRRuntimeHost
* iface
,
457 RuntimeHost
*This
= impl_from_ICLRRuntimeHost( iface
);
458 TRACE("%p %s %p\n", This
, debugstr_guid(riid
), ppvObject
);
460 if ( IsEqualGUID( riid
, &IID_ICLRRuntimeHost
) ||
461 IsEqualGUID( riid
, &IID_IUnknown
) )
467 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
468 return E_NOINTERFACE
;
471 ICLRRuntimeHost_AddRef( iface
);
476 static ULONG WINAPI
CLRRuntimeHost_AddRef(ICLRRuntimeHost
* iface
)
478 RuntimeHost
*This
= impl_from_ICLRRuntimeHost( iface
);
479 return ICorRuntimeHost_AddRef(&This
->ICorRuntimeHost_iface
);
482 static ULONG WINAPI
CLRRuntimeHost_Release(ICLRRuntimeHost
* iface
)
484 RuntimeHost
*This
= impl_from_ICLRRuntimeHost( iface
);
485 return ICorRuntimeHost_Release(&This
->ICorRuntimeHost_iface
);
488 static HRESULT WINAPI
CLRRuntimeHost_Start(ICLRRuntimeHost
* iface
)
490 FIXME("(%p)\n", iface
);
494 static HRESULT WINAPI
CLRRuntimeHost_Stop(ICLRRuntimeHost
* iface
)
496 FIXME("(%p)\n", iface
);
500 static HRESULT WINAPI
CLRRuntimeHost_SetHostControl(ICLRRuntimeHost
* iface
,
501 IHostControl
*pHostControl
)
503 FIXME("(%p,%p)\n", iface
, pHostControl
);
507 static HRESULT WINAPI
CLRRuntimeHost_GetCLRControl(ICLRRuntimeHost
* iface
,
508 ICLRControl
**pCLRControl
)
510 FIXME("(%p,%p)\n", iface
, pCLRControl
);
514 static HRESULT WINAPI
CLRRuntimeHost_UnloadAppDomain(ICLRRuntimeHost
* iface
,
515 DWORD dwAppDomainId
, BOOL fWaitUntilDone
)
517 FIXME("(%p,%u,%i)\n", iface
, dwAppDomainId
, fWaitUntilDone
);
521 static HRESULT WINAPI
CLRRuntimeHost_ExecuteInAppDomain(ICLRRuntimeHost
* iface
,
522 DWORD dwAppDomainId
, FExecuteInAppDomainCallback pCallback
, void *cookie
)
524 FIXME("(%p,%u,%p,%p)\n", iface
, dwAppDomainId
, pCallback
, cookie
);
528 static HRESULT WINAPI
CLRRuntimeHost_GetCurrentAppDomainId(ICLRRuntimeHost
* iface
,
529 DWORD
*pdwAppDomainId
)
531 FIXME("(%p,%p)\n", iface
, pdwAppDomainId
);
535 static HRESULT WINAPI
CLRRuntimeHost_ExecuteApplication(ICLRRuntimeHost
* iface
,
536 LPCWSTR pwzAppFullName
, DWORD dwManifestPaths
, LPCWSTR
*ppwzManifestPaths
,
537 DWORD dwActivationData
, LPCWSTR
*ppwzActivationData
, int *pReturnValue
)
539 FIXME("(%p,%s,%u,%u)\n", iface
, debugstr_w(pwzAppFullName
), dwManifestPaths
, dwActivationData
);
543 static HRESULT WINAPI
CLRRuntimeHost_ExecuteInDefaultAppDomain(ICLRRuntimeHost
* iface
,
544 LPCWSTR pwzAssemblyPath
, LPCWSTR pwzTypeName
, LPCWSTR pwzMethodName
,
545 LPCWSTR pwzArgument
, DWORD
*pReturnValue
)
547 FIXME("(%p,%s,%s,%s,%s)\n", iface
, debugstr_w(pwzAssemblyPath
),
548 debugstr_w(pwzTypeName
), debugstr_w(pwzMethodName
), debugstr_w(pwzArgument
));
552 static const struct ICLRRuntimeHostVtbl CLRHostVtbl
=
554 CLRRuntimeHost_QueryInterface
,
555 CLRRuntimeHost_AddRef
,
556 CLRRuntimeHost_Release
,
557 CLRRuntimeHost_Start
,
559 CLRRuntimeHost_SetHostControl
,
560 CLRRuntimeHost_GetCLRControl
,
561 CLRRuntimeHost_UnloadAppDomain
,
562 CLRRuntimeHost_ExecuteInAppDomain
,
563 CLRRuntimeHost_GetCurrentAppDomainId
,
564 CLRRuntimeHost_ExecuteApplication
,
565 CLRRuntimeHost_ExecuteInDefaultAppDomain
568 /* Create an instance of a type given its name, by calling its constructor with
569 * no arguments. Note that result MUST be in the stack, or the garbage
570 * collector may free it prematurely. */
571 HRESULT
RuntimeHost_CreateManagedInstance(RuntimeHost
*This
, LPCWSTR name
,
572 MonoDomain
*domain
, MonoObject
**result
)
581 hr
= RuntimeHost_GetDefaultDomain(This
, &domain
);
592 type
= This
->mono
->mono_reflection_type_from_name(nameA
, NULL
);
595 ERR("Cannot find type %s\n", debugstr_w(name
));
602 klass
= This
->mono
->mono_class_from_mono_type(type
);
605 ERR("Cannot convert type %s to a class\n", debugstr_w(name
));
612 obj
= This
->mono
->mono_object_new(domain
, klass
);
615 ERR("Cannot allocate object of type %s\n", debugstr_w(name
));
622 /* FIXME: Detect exceptions from the constructor? */
623 This
->mono
->mono_runtime_object_init(obj
);
627 HeapFree(GetProcessHeap(), 0, nameA
);
632 /* Get an IUnknown pointer for a Mono object.
634 * This is just a "light" wrapper around
635 * System.Runtime.InteropServices.Marshal:GetIUnknownForObject
637 * NOTE: The IUnknown* is created with a reference to the object.
638 * Until they have a reference, objects must be in the stack to prevent the
639 * garbage collector from freeing them. */
640 HRESULT
RuntimeHost_GetIUnknownForObject(RuntimeHost
*This
, MonoObject
*obj
,
644 MonoAssembly
*assembly
;
651 domain
= This
->mono
->mono_object_get_domain(obj
);
653 assembly
= This
->mono
->mono_domain_assembly_open(domain
, "mscorlib");
656 ERR("Cannot load mscorlib\n");
660 image
= This
->mono
->mono_assembly_get_image(assembly
);
663 ERR("Couldn't get assembly image\n");
667 klass
= This
->mono
->mono_class_from_name(image
, "System.Runtime.InteropServices", "Marshal");
670 ERR("Couldn't get class from image\n");
674 method
= This
->mono
->mono_class_get_method_from_name(klass
, "GetIUnknownForObject", 1);
677 ERR("Couldn't get method from class\n");
683 result
= This
->mono
->mono_runtime_invoke(method
, NULL
, args
, NULL
);
686 ERR("Couldn't get result pointer\n");
690 *ppUnk
= *(IUnknown
**)This
->mono
->mono_object_unbox(result
);
693 ERR("GetIUnknownForObject returned 0\n");
700 static void get_utf8_args(int *argc
, char ***argv
)
706 argvw
= CommandLineToArgvW(GetCommandLineW(), argc
);
708 for (i
=0; i
<*argc
; i
++)
710 size
+= sizeof(char*);
711 size
+= WideCharToMultiByte(CP_UTF8
, 0, argvw
[i
], -1, NULL
, 0, NULL
, NULL
);
713 size
+= sizeof(char*);
715 *argv
= HeapAlloc(GetProcessHeap(), 0, size
);
716 current_arg
= (char*)(*argv
+ *argc
+ 1);
718 for (i
=0; i
<*argc
; i
++)
720 (*argv
)[i
] = current_arg
;
721 current_arg
+= WideCharToMultiByte(CP_UTF8
, 0, argvw
[i
], -1, current_arg
, size
, NULL
, NULL
);
724 (*argv
)[*argc
] = NULL
;
726 HeapFree(GetProcessHeap(), 0, argvw
);
729 __int32 WINAPI
_CorExeMain(void)
735 MonoAssembly
*assembly
;
736 WCHAR filename
[MAX_PATH
];
738 ICLRRuntimeInfo
*info
;
743 get_utf8_args(&argc
, &argv
);
745 GetModuleFileNameW(NULL
, filename
, MAX_PATH
);
747 TRACE("%s", debugstr_w(filename
));
748 for (i
=0; i
<argc
; i
++)
749 TRACE(" %s", debugstr_a(argv
[i
]));
752 filenameA
= WtoA(filename
);
756 hr
= get_runtime_info(filename
, NULL
, NULL
, 0, 0, FALSE
, &info
);
760 hr
= ICLRRuntimeInfo_GetRuntimeHost(info
, &host
);
763 hr
= RuntimeHost_GetDefaultDomain(host
, &domain
);
767 assembly
= host
->mono
->mono_domain_assembly_open(domain
, filenameA
);
769 exit_code
= host
->mono
->mono_jit_exec(domain
, assembly
, argc
, argv
);
771 RuntimeHost_DeleteDomain(host
, domain
);
776 ICLRRuntimeInfo_Release(info
);
781 HeapFree(GetProcessHeap(), 0, argv
);
783 unload_all_runtimes();
788 HRESULT
RuntimeHost_Construct(const CLRRuntimeInfo
*runtime_version
,
789 loaded_mono
*loaded_mono
, RuntimeHost
** result
)
793 This
= HeapAlloc( GetProcessHeap(), 0, sizeof *This
);
795 return E_OUTOFMEMORY
;
797 This
->ICorRuntimeHost_iface
.lpVtbl
= &corruntimehost_vtbl
;
798 This
->ICLRRuntimeHost_iface
.lpVtbl
= &CLRHostVtbl
;
800 This
->version
= runtime_version
;
801 This
->mono
= loaded_mono
;
802 list_init(&This
->domains
);
803 This
->default_domain
= NULL
;
804 InitializeCriticalSection(&This
->lock
);
805 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": RuntimeHost.lock");
812 HRESULT
RuntimeHost_GetInterface(RuntimeHost
*This
, REFCLSID clsid
, REFIID riid
, void **ppv
)
817 if (IsEqualGUID(clsid
, &CLSID_CorRuntimeHost
))
819 unk
= (IUnknown
*)&This
->ICorRuntimeHost_iface
;
820 IUnknown_AddRef(unk
);
822 else if (IsEqualGUID(clsid
, &CLSID_CLRRuntimeHost
))
824 unk
= (IUnknown
*)&This
->ICLRRuntimeHost_iface
;
825 IUnknown_AddRef(unk
);
827 else if (IsEqualGUID(clsid
, &CLSID_CorMetaDataDispenser
) ||
828 IsEqualGUID(clsid
, &CLSID_CorMetaDataDispenserRuntime
))
830 hr
= MetaDataDispenser_CreateInstance(&unk
);
839 hr
= IUnknown_QueryInterface(unk
, riid
, ppv
);
841 IUnknown_Release(unk
);
846 FIXME("not implemented for class %s\n", debugstr_guid(clsid
));
848 return CLASS_E_CLASSNOTAVAILABLE
;
851 HRESULT
RuntimeHost_Destroy(RuntimeHost
*This
)
853 struct DomainEntry
*cursor
, *cursor2
;
855 This
->lock
.DebugInfo
->Spare
[0] = 0;
856 DeleteCriticalSection(&This
->lock
);
858 LIST_FOR_EACH_ENTRY_SAFE(cursor
, cursor2
, &This
->domains
, struct DomainEntry
, entry
)
860 list_remove(&cursor
->entry
);
861 HeapFree(GetProcessHeap(), 0, cursor
);
864 HeapFree( GetProcessHeap(), 0, This
);