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 const struct ICorRuntimeHostVtbl
*lpVtbl
;
45 const struct ICLRRuntimeHostVtbl
*lpCLRHostVtbl
;
46 const CLRRuntimeInfo
*version
;
47 const loaded_mono
*mono
;
49 MonoDomain
*default_domain
;
50 CRITICAL_SECTION lock
;
60 static HRESULT
RuntimeHost_AddDomain(RuntimeHost
*This
, MonoDomain
**result
)
62 struct DomainEntry
*entry
;
66 EnterCriticalSection(&This
->lock
);
68 entry
= HeapAlloc(GetProcessHeap(), 0, sizeof(*entry
));
75 mscorlib_path
= WtoA(This
->version
->mscorlib_path
);
78 HeapFree(GetProcessHeap(), 0, entry
);
83 entry
->domain
= This
->mono
->mono_jit_init(mscorlib_path
);
85 HeapFree(GetProcessHeap(), 0, mscorlib_path
);
89 HeapFree(GetProcessHeap(), 0, entry
);
94 list_add_tail(&This
->domains
, &entry
->entry
);
98 *result
= entry
->domain
;
101 LeaveCriticalSection(&This
->lock
);
106 static HRESULT
RuntimeHost_GetDefaultDomain(RuntimeHost
*This
, MonoDomain
**result
)
110 EnterCriticalSection(&This
->lock
);
112 if (This
->default_domain
) goto end
;
114 res
= RuntimeHost_AddDomain(This
, &This
->default_domain
);
117 *result
= This
->default_domain
;
119 LeaveCriticalSection(&This
->lock
);
124 static void RuntimeHost_DeleteDomain(RuntimeHost
*This
, MonoDomain
*domain
)
126 struct DomainEntry
*entry
;
128 EnterCriticalSection(&This
->lock
);
130 LIST_FOR_EACH_ENTRY(entry
, &This
->domains
, struct DomainEntry
, entry
)
132 if (entry
->domain
== domain
)
134 This
->mono
->mono_jit_cleanup(domain
);
135 list_remove(&entry
->entry
);
136 if (This
->default_domain
== domain
)
137 This
->default_domain
= NULL
;
138 HeapFree(GetProcessHeap(), 0, entry
);
139 MSCOREE_UnlockModule();
144 LeaveCriticalSection(&This
->lock
);
147 static inline RuntimeHost
*impl_from_ICLRRuntimeHost( ICLRRuntimeHost
*iface
)
149 return (RuntimeHost
*)((char*)iface
- FIELD_OFFSET(RuntimeHost
, lpCLRHostVtbl
));
152 static inline RuntimeHost
*impl_from_ICorRuntimeHost( ICorRuntimeHost
*iface
)
154 return (RuntimeHost
*)((char*)iface
- FIELD_OFFSET(RuntimeHost
, lpVtbl
));
157 /*** IUnknown methods ***/
158 static HRESULT WINAPI
corruntimehost_QueryInterface(ICorRuntimeHost
* iface
,
162 RuntimeHost
*This
= impl_from_ICorRuntimeHost( iface
);
163 TRACE("%p %s %p\n", This
, debugstr_guid(riid
), ppvObject
);
165 if ( IsEqualGUID( riid
, &IID_ICorRuntimeHost
) ||
166 IsEqualGUID( riid
, &IID_IUnknown
) )
172 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
173 return E_NOINTERFACE
;
176 ICorRuntimeHost_AddRef( iface
);
181 static ULONG WINAPI
corruntimehost_AddRef(ICorRuntimeHost
* iface
)
183 RuntimeHost
*This
= impl_from_ICorRuntimeHost( iface
);
185 MSCOREE_LockModule();
187 return InterlockedIncrement( &This
->ref
);
190 static ULONG WINAPI
corruntimehost_Release(ICorRuntimeHost
* iface
)
192 RuntimeHost
*This
= impl_from_ICorRuntimeHost( iface
);
195 MSCOREE_UnlockModule();
197 ref
= InterlockedDecrement( &This
->ref
);
202 /*** ICorRuntimeHost methods ***/
203 static HRESULT WINAPI
corruntimehost_CreateLogicalThreadState(
204 ICorRuntimeHost
* iface
)
206 FIXME("stub %p\n", iface
);
210 static HRESULT WINAPI
corruntimehost_DeleteLogicalThreadState(
211 ICorRuntimeHost
* iface
)
213 FIXME("stub %p\n", iface
);
217 static HRESULT WINAPI
corruntimehost_SwitchInLogicalThreadState(
218 ICorRuntimeHost
* iface
,
221 FIXME("stub %p\n", iface
);
225 static HRESULT WINAPI
corruntimehost_SwitchOutLogicalThreadState(
226 ICorRuntimeHost
* iface
,
229 FIXME("stub %p\n", iface
);
233 static HRESULT WINAPI
corruntimehost_LocksHeldByLogicalThread(
234 ICorRuntimeHost
* iface
,
237 FIXME("stub %p\n", iface
);
241 static HRESULT WINAPI
corruntimehost_MapFile(
242 ICorRuntimeHost
* iface
,
246 FIXME("stub %p\n", iface
);
250 static HRESULT WINAPI
corruntimehost_GetConfiguration(
251 ICorRuntimeHost
* iface
,
252 ICorConfiguration
**pConfiguration
)
254 FIXME("stub %p\n", iface
);
258 static HRESULT WINAPI
corruntimehost_Start(
259 ICorRuntimeHost
* iface
)
261 FIXME("stub %p\n", iface
);
265 static HRESULT WINAPI
corruntimehost_Stop(
266 ICorRuntimeHost
* iface
)
268 FIXME("stub %p\n", iface
);
272 static HRESULT WINAPI
corruntimehost_CreateDomain(
273 ICorRuntimeHost
* iface
,
274 LPCWSTR friendlyName
,
275 IUnknown
*identityArray
,
276 IUnknown
**appDomain
)
278 FIXME("stub %p\n", iface
);
282 static HRESULT WINAPI
corruntimehost_GetDefaultDomain(
283 ICorRuntimeHost
* iface
,
284 IUnknown
**pAppDomain
)
286 FIXME("stub %p\n", iface
);
290 static HRESULT WINAPI
corruntimehost_EnumDomains(
291 ICorRuntimeHost
* iface
,
294 FIXME("stub %p\n", iface
);
298 static HRESULT WINAPI
corruntimehost_NextDomain(
299 ICorRuntimeHost
* iface
,
301 IUnknown
**appDomain
)
303 FIXME("stub %p\n", iface
);
307 static HRESULT WINAPI
corruntimehost_CloseEnum(
308 ICorRuntimeHost
* iface
,
311 FIXME("stub %p\n", iface
);
315 static HRESULT WINAPI
corruntimehost_CreateDomainEx(
316 ICorRuntimeHost
* iface
,
317 LPCWSTR friendlyName
,
320 IUnknown
**appDomain
)
322 FIXME("stub %p\n", iface
);
326 static HRESULT WINAPI
corruntimehost_CreateDomainSetup(
327 ICorRuntimeHost
* iface
,
328 IUnknown
**appDomainSetup
)
330 FIXME("stub %p\n", iface
);
334 static HRESULT WINAPI
corruntimehost_CreateEvidence(
335 ICorRuntimeHost
* iface
,
338 FIXME("stub %p\n", iface
);
342 static HRESULT WINAPI
corruntimehost_UnloadDomain(
343 ICorRuntimeHost
* iface
,
346 FIXME("stub %p\n", iface
);
350 static HRESULT WINAPI
corruntimehost_CurrentDomain(
351 ICorRuntimeHost
* iface
,
352 IUnknown
**appDomain
)
354 FIXME("stub %p\n", iface
);
358 static const struct ICorRuntimeHostVtbl corruntimehost_vtbl
=
360 corruntimehost_QueryInterface
,
361 corruntimehost_AddRef
,
362 corruntimehost_Release
,
363 corruntimehost_CreateLogicalThreadState
,
364 corruntimehost_DeleteLogicalThreadState
,
365 corruntimehost_SwitchInLogicalThreadState
,
366 corruntimehost_SwitchOutLogicalThreadState
,
367 corruntimehost_LocksHeldByLogicalThread
,
368 corruntimehost_MapFile
,
369 corruntimehost_GetConfiguration
,
370 corruntimehost_Start
,
372 corruntimehost_CreateDomain
,
373 corruntimehost_GetDefaultDomain
,
374 corruntimehost_EnumDomains
,
375 corruntimehost_NextDomain
,
376 corruntimehost_CloseEnum
,
377 corruntimehost_CreateDomainEx
,
378 corruntimehost_CreateDomainSetup
,
379 corruntimehost_CreateEvidence
,
380 corruntimehost_UnloadDomain
,
381 corruntimehost_CurrentDomain
384 static HRESULT WINAPI
CLRRuntimeHost_QueryInterface(ICLRRuntimeHost
* iface
,
388 RuntimeHost
*This
= impl_from_ICLRRuntimeHost( iface
);
389 TRACE("%p %s %p\n", This
, debugstr_guid(riid
), ppvObject
);
391 if ( IsEqualGUID( riid
, &IID_ICLRRuntimeHost
) ||
392 IsEqualGUID( riid
, &IID_IUnknown
) )
398 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
399 return E_NOINTERFACE
;
402 ICLRRuntimeHost_AddRef( iface
);
407 static ULONG WINAPI
CLRRuntimeHost_AddRef(ICLRRuntimeHost
* iface
)
409 RuntimeHost
*This
= impl_from_ICLRRuntimeHost( iface
);
410 return IUnknown_AddRef((IUnknown
*)&This
->lpVtbl
);
413 static ULONG WINAPI
CLRRuntimeHost_Release(ICLRRuntimeHost
* iface
)
415 RuntimeHost
*This
= impl_from_ICLRRuntimeHost( iface
);
416 return IUnknown_Release((IUnknown
*)&This
->lpVtbl
);
419 static HRESULT WINAPI
CLRRuntimeHost_Start(ICLRRuntimeHost
* iface
)
421 FIXME("(%p)\n", iface
);
425 static HRESULT WINAPI
CLRRuntimeHost_Stop(ICLRRuntimeHost
* iface
)
427 FIXME("(%p)\n", iface
);
431 static HRESULT WINAPI
CLRRuntimeHost_SetHostControl(ICLRRuntimeHost
* iface
,
432 IHostControl
*pHostControl
)
434 FIXME("(%p,%p)\n", iface
, pHostControl
);
438 static HRESULT WINAPI
CLRRuntimeHost_GetCLRControl(ICLRRuntimeHost
* iface
,
439 ICLRControl
**pCLRControl
)
441 FIXME("(%p,%p)\n", iface
, pCLRControl
);
445 static HRESULT WINAPI
CLRRuntimeHost_UnloadAppDomain(ICLRRuntimeHost
* iface
,
446 DWORD dwAppDomainId
, BOOL fWaitUntilDone
)
448 FIXME("(%p,%u,%i)\n", iface
, dwAppDomainId
, fWaitUntilDone
);
452 static HRESULT WINAPI
CLRRuntimeHost_ExecuteInAppDomain(ICLRRuntimeHost
* iface
,
453 DWORD dwAppDomainId
, FExecuteInAppDomainCallback pCallback
, void *cookie
)
455 FIXME("(%p,%u,%p,%p)\n", iface
, dwAppDomainId
, pCallback
, cookie
);
459 static HRESULT WINAPI
CLRRuntimeHost_GetCurrentAppDomainId(ICLRRuntimeHost
* iface
,
460 DWORD
*pdwAppDomainId
)
462 FIXME("(%p,%p)\n", iface
, pdwAppDomainId
);
466 static HRESULT WINAPI
CLRRuntimeHost_ExecuteApplication(ICLRRuntimeHost
* iface
,
467 LPCWSTR pwzAppFullName
, DWORD dwManifestPaths
, LPCWSTR
*ppwzManifestPaths
,
468 DWORD dwActivationData
, LPCWSTR
*ppwzActivationData
, int *pReturnValue
)
470 FIXME("(%p,%s,%u,%u)\n", iface
, debugstr_w(pwzAppFullName
), dwManifestPaths
, dwActivationData
);
474 static HRESULT WINAPI
CLRRuntimeHost_ExecuteInDefaultAppDomain(ICLRRuntimeHost
* iface
,
475 LPCWSTR pwzAssemblyPath
, LPCWSTR pwzTypeName
, LPCWSTR pwzMethodName
,
476 LPCWSTR pwzArgument
, DWORD
*pReturnValue
)
478 FIXME("(%p,%s,%s,%s,%s)\n", iface
, debugstr_w(pwzAssemblyPath
),
479 debugstr_w(pwzTypeName
), debugstr_w(pwzMethodName
), debugstr_w(pwzArgument
));
483 static const struct ICLRRuntimeHostVtbl CLRHostVtbl
=
485 CLRRuntimeHost_QueryInterface
,
486 CLRRuntimeHost_AddRef
,
487 CLRRuntimeHost_Release
,
488 CLRRuntimeHost_Start
,
490 CLRRuntimeHost_SetHostControl
,
491 CLRRuntimeHost_GetCLRControl
,
492 CLRRuntimeHost_UnloadAppDomain
,
493 CLRRuntimeHost_ExecuteInAppDomain
,
494 CLRRuntimeHost_GetCurrentAppDomainId
,
495 CLRRuntimeHost_ExecuteApplication
,
496 CLRRuntimeHost_ExecuteInDefaultAppDomain
499 /* Create an instance of a type given its name, by calling its constructor with
500 * no arguments. Note that result MUST be in the stack, or the garbage
501 * collector may free it prematurely. */
502 HRESULT
RuntimeHost_CreateManagedInstance(RuntimeHost
*This
, LPCWSTR name
,
503 MonoDomain
*domain
, MonoObject
**result
)
512 hr
= RuntimeHost_GetDefaultDomain(This
, &domain
);
523 type
= This
->mono
->mono_reflection_type_from_name(nameA
, NULL
);
526 ERR("Cannot find type %s\n", debugstr_w(name
));
533 klass
= This
->mono
->mono_class_from_mono_type(type
);
536 ERR("Cannot convert type %s to a class\n", debugstr_w(name
));
543 obj
= This
->mono
->mono_object_new(domain
, klass
);
546 ERR("Cannot allocate object of type %s\n", debugstr_w(name
));
553 /* FIXME: Detect exceptions from the constructor? */
554 This
->mono
->mono_runtime_object_init(obj
);
558 HeapFree(GetProcessHeap(), 0, nameA
);
563 /* Get an IUnknown pointer for a Mono object.
565 * This is just a "light" wrapper around
566 * System.Runtime.InteropServices.Marshal:GetIUnknownForObject
568 * NOTE: The IUnknown* is created with a reference to the object.
569 * Until they have a reference, objects must be in the stack to prevent the
570 * garbage collector from freeing them. */
571 HRESULT
RuntimeHost_GetIUnknownForObject(RuntimeHost
*This
, MonoObject
*obj
,
575 MonoAssembly
*assembly
;
582 domain
= This
->mono
->mono_object_get_domain(obj
);
584 assembly
= This
->mono
->mono_domain_assembly_open(domain
, "mscorlib");
587 ERR("Cannot load mscorlib\n");
591 image
= This
->mono
->mono_assembly_get_image(assembly
);
594 ERR("Couldn't get assembly image\n");
598 klass
= This
->mono
->mono_class_from_name(image
, "System.Runtime.InteropServices", "Marshal");
601 ERR("Couldn't get class from image\n");
605 method
= This
->mono
->mono_class_get_method_from_name(klass
, "GetIUnknownForObject", 1);
608 ERR("Couldn't get method from class\n");
614 result
= This
->mono
->mono_runtime_invoke(method
, NULL
, args
, NULL
);
617 ERR("Couldn't get result pointer\n");
621 *ppUnk
= *(IUnknown
**)This
->mono
->mono_object_unbox(result
);
624 ERR("GetIUnknownForObject returned 0\n");
631 static void get_utf8_args(int *argc
, char ***argv
)
637 argvw
= CommandLineToArgvW(GetCommandLineW(), argc
);
639 for (i
=0; i
<*argc
; i
++)
641 size
+= sizeof(char*);
642 size
+= WideCharToMultiByte(CP_UTF8
, 0, argvw
[i
], -1, NULL
, 0, NULL
, NULL
);
644 size
+= sizeof(char*);
646 *argv
= HeapAlloc(GetProcessHeap(), 0, size
);
647 current_arg
= (char*)(*argv
+ *argc
+ 1);
649 for (i
=0; i
<*argc
; i
++)
651 (*argv
)[i
] = current_arg
;
652 current_arg
+= WideCharToMultiByte(CP_UTF8
, 0, argvw
[i
], -1, current_arg
, size
, NULL
, NULL
);
655 (*argv
)[*argc
] = NULL
;
657 HeapFree(GetProcessHeap(), 0, argvw
);
660 __int32 WINAPI
_CorExeMain(void)
666 MonoAssembly
*assembly
;
667 WCHAR filename
[MAX_PATH
];
669 ICLRRuntimeInfo
*info
;
674 get_utf8_args(&argc
, &argv
);
676 GetModuleFileNameW(NULL
, filename
, MAX_PATH
);
678 TRACE("%s", debugstr_w(filename
));
679 for (i
=0; i
<argc
; i
++)
680 TRACE(" %s", debugstr_a(argv
[i
]));
683 filenameA
= WtoA(filename
);
687 hr
= get_runtime_info(filename
, NULL
, NULL
, 0, 0, FALSE
, &info
);
691 hr
= ICLRRuntimeInfo_GetRuntimeHost(info
, &host
);
694 hr
= RuntimeHost_GetDefaultDomain(host
, &domain
);
698 assembly
= host
->mono
->mono_domain_assembly_open(domain
, filenameA
);
700 exit_code
= host
->mono
->mono_jit_exec(domain
, assembly
, argc
, argv
);
702 RuntimeHost_DeleteDomain(host
, domain
);
707 ICLRRuntimeInfo_Release(info
);
712 HeapFree(GetProcessHeap(), 0, argv
);
717 HRESULT
RuntimeHost_Construct(const CLRRuntimeInfo
*runtime_version
,
718 const loaded_mono
*loaded_mono
, RuntimeHost
** result
)
722 This
= HeapAlloc( GetProcessHeap(), 0, sizeof *This
);
724 return E_OUTOFMEMORY
;
726 This
->lpVtbl
= &corruntimehost_vtbl
;
727 This
->lpCLRHostVtbl
= &CLRHostVtbl
;
729 This
->version
= runtime_version
;
730 This
->mono
= loaded_mono
;
731 list_init(&This
->domains
);
732 This
->default_domain
= NULL
;
733 InitializeCriticalSection(&This
->lock
);
734 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": RuntimeHost.lock");
741 HRESULT
RuntimeHost_GetInterface(RuntimeHost
*This
, REFCLSID clsid
, REFIID riid
, void **ppv
)
746 if (IsEqualGUID(clsid
, &CLSID_CorRuntimeHost
))
748 unk
= (IUnknown
*)&This
->lpVtbl
;
749 IUnknown_AddRef(unk
);
751 else if (IsEqualGUID(clsid
, &CLSID_CLRRuntimeHost
))
753 unk
= (IUnknown
*)&This
->lpCLRHostVtbl
;
754 IUnknown_AddRef(unk
);
756 else if (IsEqualGUID(clsid
, &CLSID_CorMetaDataDispenser
) ||
757 IsEqualGUID(clsid
, &CLSID_CorMetaDataDispenserRuntime
))
759 hr
= MetaDataDispenser_CreateInstance(&unk
);
768 hr
= IUnknown_QueryInterface(unk
, riid
, ppv
);
770 IUnknown_Release(unk
);
775 FIXME("not implemented for class %s\n", debugstr_guid(clsid
));
777 return CLASS_E_CLASSNOTAVAILABLE
;
780 HRESULT
RuntimeHost_Destroy(RuntimeHost
*This
)
782 struct DomainEntry
*cursor
, *cursor2
;
784 This
->lock
.DebugInfo
->Spare
[0] = 0;
785 DeleteCriticalSection(&This
->lock
);
787 LIST_FOR_EACH_ENTRY_SAFE(cursor
, cursor2
, &This
->domains
, struct DomainEntry
, entry
)
789 This
->mono
->mono_jit_cleanup(cursor
->domain
);
790 list_remove(&cursor
->entry
);
791 HeapFree(GetProcessHeap(), 0, cursor
);
794 HeapFree( GetProcessHeap(), 0, This
);