mscoree: Always call mono_thread_attach before invoking managed code.
[wine/multimedia.git] / dlls / mscoree / corruntimehost.c
blob1750f12926a0dfb2ff0267a88e16029dfe77700e
1 /*
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
20 #define COBJMACROS
22 #include <stdarg.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "winnls.h"
28 #include "winreg.h"
29 #include "ole2.h"
30 #include "shellapi.h"
32 #include "cor.h"
33 #include "mscoree.h"
34 #include "metahost.h"
35 #include "corhdr.h"
36 #include "cordebug.h"
37 #include "wine/list.h"
38 #include "mscoree_private.h"
40 #include "wine/debug.h"
41 #include "wine/unicode.h"
43 WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
45 #include "initguid.h"
47 DEFINE_GUID(IID__AppDomain, 0x05f696dc,0x2b29,0x3663,0xad,0x8b,0xc4,0x38,0x9c,0xf2,0xa7,0x13);
49 struct DomainEntry
51 struct list entry;
52 MonoDomain *domain;
55 static HRESULT RuntimeHost_AddDomain(RuntimeHost *This, MonoDomain **result)
57 struct DomainEntry *entry;
58 char *mscorlib_path;
59 HRESULT res=S_OK;
61 EnterCriticalSection(&This->lock);
63 entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry));
64 if (!entry)
66 res = E_OUTOFMEMORY;
67 goto end;
70 mscorlib_path = WtoA(This->version->mscorlib_path);
71 if (!mscorlib_path)
73 HeapFree(GetProcessHeap(), 0, entry);
74 res = E_OUTOFMEMORY;
75 goto end;
78 entry->domain = This->mono->mono_jit_init(mscorlib_path);
80 HeapFree(GetProcessHeap(), 0, mscorlib_path);
82 if (!entry->domain)
84 HeapFree(GetProcessHeap(), 0, entry);
85 res = E_FAIL;
86 goto end;
89 This->mono->is_started = TRUE;
91 list_add_tail(&This->domains, &entry->entry);
93 *result = entry->domain;
95 end:
96 LeaveCriticalSection(&This->lock);
98 return res;
101 static HRESULT RuntimeHost_GetDefaultDomain(RuntimeHost *This, MonoDomain **result)
103 HRESULT res=S_OK;
105 EnterCriticalSection(&This->lock);
107 if (This->default_domain) goto end;
109 res = RuntimeHost_AddDomain(This, &This->default_domain);
111 end:
112 *result = This->default_domain;
114 LeaveCriticalSection(&This->lock);
116 return res;
119 static void RuntimeHost_DeleteDomain(RuntimeHost *This, MonoDomain *domain)
121 struct DomainEntry *entry;
123 EnterCriticalSection(&This->lock);
125 LIST_FOR_EACH_ENTRY(entry, &This->domains, struct DomainEntry, entry)
127 if (entry->domain == domain)
129 list_remove(&entry->entry);
130 if (This->default_domain == domain)
131 This->default_domain = NULL;
132 HeapFree(GetProcessHeap(), 0, entry);
133 break;
137 LeaveCriticalSection(&This->lock);
140 static HRESULT RuntimeHost_GetIUnknownForDomain(RuntimeHost *This, MonoDomain *domain, IUnknown **punk)
142 HRESULT hr;
143 void *args[1];
144 MonoAssembly *assembly;
145 MonoImage *image;
146 MonoClass *klass;
147 MonoMethod *method;
148 MonoObject *appdomain_object;
149 IUnknown *unk;
151 This->mono->mono_thread_attach(domain);
153 assembly = This->mono->mono_domain_assembly_open(domain, "mscorlib");
154 if (!assembly)
156 ERR("Cannot load mscorlib\n");
157 return E_FAIL;
160 image = This->mono->mono_assembly_get_image(assembly);
161 if (!image)
163 ERR("Couldn't get assembly image\n");
164 return E_FAIL;
167 klass = This->mono->mono_class_from_name(image, "System", "AppDomain");
168 if (!klass)
170 ERR("Couldn't get class from image\n");
171 return E_FAIL;
174 method = This->mono->mono_class_get_method_from_name(klass, "get_CurrentDomain", 0);
175 if (!method)
177 ERR("Couldn't get method from class\n");
178 return E_FAIL;
181 args[0] = NULL;
182 appdomain_object = This->mono->mono_runtime_invoke(method, NULL, args, NULL);
183 if (!appdomain_object)
185 ERR("Couldn't get result pointer\n");
186 return E_FAIL;
189 hr = RuntimeHost_GetIUnknownForObject(This, appdomain_object, &unk);
191 if (SUCCEEDED(hr))
193 hr = IUnknown_QueryInterface(unk, &IID__AppDomain, (void**)punk);
195 IUnknown_Release(unk);
198 return hr;
201 static inline RuntimeHost *impl_from_ICLRRuntimeHost( ICLRRuntimeHost *iface )
203 return CONTAINING_RECORD(iface, RuntimeHost, ICLRRuntimeHost_iface);
206 static inline RuntimeHost *impl_from_ICorRuntimeHost( ICorRuntimeHost *iface )
208 return CONTAINING_RECORD(iface, RuntimeHost, ICorRuntimeHost_iface);
211 /*** IUnknown methods ***/
212 static HRESULT WINAPI corruntimehost_QueryInterface(ICorRuntimeHost* iface,
213 REFIID riid,
214 void **ppvObject)
216 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
217 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
219 if ( IsEqualGUID( riid, &IID_ICorRuntimeHost ) ||
220 IsEqualGUID( riid, &IID_IUnknown ) )
222 *ppvObject = iface;
224 else
226 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
227 return E_NOINTERFACE;
230 ICorRuntimeHost_AddRef( iface );
232 return S_OK;
235 static ULONG WINAPI corruntimehost_AddRef(ICorRuntimeHost* iface)
237 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
239 return InterlockedIncrement( &This->ref );
242 static ULONG WINAPI corruntimehost_Release(ICorRuntimeHost* iface)
244 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
245 ULONG ref;
247 ref = InterlockedDecrement( &This->ref );
249 return ref;
252 /*** ICorRuntimeHost methods ***/
253 static HRESULT WINAPI corruntimehost_CreateLogicalThreadState(
254 ICorRuntimeHost* iface)
256 FIXME("stub %p\n", iface);
257 return E_NOTIMPL;
260 static HRESULT WINAPI corruntimehost_DeleteLogicalThreadState(
261 ICorRuntimeHost* iface)
263 FIXME("stub %p\n", iface);
264 return E_NOTIMPL;
267 static HRESULT WINAPI corruntimehost_SwitchInLogicalThreadState(
268 ICorRuntimeHost* iface,
269 DWORD *fiberCookie)
271 FIXME("stub %p\n", iface);
272 return E_NOTIMPL;
275 static HRESULT WINAPI corruntimehost_SwitchOutLogicalThreadState(
276 ICorRuntimeHost* iface,
277 DWORD **fiberCookie)
279 FIXME("stub %p\n", iface);
280 return E_NOTIMPL;
283 static HRESULT WINAPI corruntimehost_LocksHeldByLogicalThread(
284 ICorRuntimeHost* iface,
285 DWORD *pCount)
287 FIXME("stub %p\n", iface);
288 return E_NOTIMPL;
291 static HRESULT WINAPI corruntimehost_MapFile(
292 ICorRuntimeHost* iface,
293 HANDLE hFile,
294 HMODULE *mapAddress)
296 FIXME("stub %p\n", iface);
297 return E_NOTIMPL;
300 static HRESULT WINAPI corruntimehost_GetConfiguration(
301 ICorRuntimeHost* iface,
302 ICorConfiguration **pConfiguration)
304 FIXME("stub %p\n", iface);
305 return E_NOTIMPL;
308 static HRESULT WINAPI corruntimehost_Start(
309 ICorRuntimeHost* iface)
311 FIXME("stub %p\n", iface);
312 return S_OK;
315 static HRESULT WINAPI corruntimehost_Stop(
316 ICorRuntimeHost* iface)
318 FIXME("stub %p\n", iface);
319 return E_NOTIMPL;
322 static HRESULT WINAPI corruntimehost_CreateDomain(
323 ICorRuntimeHost* iface,
324 LPCWSTR friendlyName,
325 IUnknown *identityArray,
326 IUnknown **appDomain)
328 FIXME("stub %p\n", iface);
329 return E_NOTIMPL;
332 static HRESULT WINAPI corruntimehost_GetDefaultDomain(
333 ICorRuntimeHost* iface,
334 IUnknown **pAppDomain)
336 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
337 HRESULT hr;
338 MonoDomain *domain;
340 TRACE("(%p)\n", iface);
342 hr = RuntimeHost_GetDefaultDomain(This, &domain);
344 if (SUCCEEDED(hr))
346 hr = RuntimeHost_GetIUnknownForDomain(This, domain, pAppDomain);
349 return hr;
352 static HRESULT WINAPI corruntimehost_EnumDomains(
353 ICorRuntimeHost* iface,
354 HDOMAINENUM *hEnum)
356 FIXME("stub %p\n", iface);
357 return E_NOTIMPL;
360 static HRESULT WINAPI corruntimehost_NextDomain(
361 ICorRuntimeHost* iface,
362 HDOMAINENUM hEnum,
363 IUnknown **appDomain)
365 FIXME("stub %p\n", iface);
366 return E_NOTIMPL;
369 static HRESULT WINAPI corruntimehost_CloseEnum(
370 ICorRuntimeHost* iface,
371 HDOMAINENUM hEnum)
373 FIXME("stub %p\n", iface);
374 return E_NOTIMPL;
377 static HRESULT WINAPI corruntimehost_CreateDomainEx(
378 ICorRuntimeHost* iface,
379 LPCWSTR friendlyName,
380 IUnknown *setup,
381 IUnknown *evidence,
382 IUnknown **appDomain)
384 FIXME("stub %p\n", iface);
385 return E_NOTIMPL;
388 static HRESULT WINAPI corruntimehost_CreateDomainSetup(
389 ICorRuntimeHost* iface,
390 IUnknown **appDomainSetup)
392 FIXME("stub %p\n", iface);
393 return E_NOTIMPL;
396 static HRESULT WINAPI corruntimehost_CreateEvidence(
397 ICorRuntimeHost* iface,
398 IUnknown **evidence)
400 FIXME("stub %p\n", iface);
401 return E_NOTIMPL;
404 static HRESULT WINAPI corruntimehost_UnloadDomain(
405 ICorRuntimeHost* iface,
406 IUnknown *appDomain)
408 FIXME("stub %p\n", iface);
409 return E_NOTIMPL;
412 static HRESULT WINAPI corruntimehost_CurrentDomain(
413 ICorRuntimeHost* iface,
414 IUnknown **appDomain)
416 FIXME("stub %p\n", iface);
417 return E_NOTIMPL;
420 static const struct ICorRuntimeHostVtbl corruntimehost_vtbl =
422 corruntimehost_QueryInterface,
423 corruntimehost_AddRef,
424 corruntimehost_Release,
425 corruntimehost_CreateLogicalThreadState,
426 corruntimehost_DeleteLogicalThreadState,
427 corruntimehost_SwitchInLogicalThreadState,
428 corruntimehost_SwitchOutLogicalThreadState,
429 corruntimehost_LocksHeldByLogicalThread,
430 corruntimehost_MapFile,
431 corruntimehost_GetConfiguration,
432 corruntimehost_Start,
433 corruntimehost_Stop,
434 corruntimehost_CreateDomain,
435 corruntimehost_GetDefaultDomain,
436 corruntimehost_EnumDomains,
437 corruntimehost_NextDomain,
438 corruntimehost_CloseEnum,
439 corruntimehost_CreateDomainEx,
440 corruntimehost_CreateDomainSetup,
441 corruntimehost_CreateEvidence,
442 corruntimehost_UnloadDomain,
443 corruntimehost_CurrentDomain
446 static HRESULT WINAPI CLRRuntimeHost_QueryInterface(ICLRRuntimeHost* iface,
447 REFIID riid,
448 void **ppvObject)
450 RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
451 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
453 if ( IsEqualGUID( riid, &IID_ICLRRuntimeHost ) ||
454 IsEqualGUID( riid, &IID_IUnknown ) )
456 *ppvObject = iface;
458 else
460 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
461 return E_NOINTERFACE;
464 ICLRRuntimeHost_AddRef( iface );
466 return S_OK;
469 static ULONG WINAPI CLRRuntimeHost_AddRef(ICLRRuntimeHost* iface)
471 RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
472 return ICorRuntimeHost_AddRef(&This->ICorRuntimeHost_iface);
475 static ULONG WINAPI CLRRuntimeHost_Release(ICLRRuntimeHost* iface)
477 RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
478 return ICorRuntimeHost_Release(&This->ICorRuntimeHost_iface);
481 static HRESULT WINAPI CLRRuntimeHost_Start(ICLRRuntimeHost* iface)
483 FIXME("(%p)\n", iface);
484 return E_NOTIMPL;
487 static HRESULT WINAPI CLRRuntimeHost_Stop(ICLRRuntimeHost* iface)
489 FIXME("(%p)\n", iface);
490 return E_NOTIMPL;
493 static HRESULT WINAPI CLRRuntimeHost_SetHostControl(ICLRRuntimeHost* iface,
494 IHostControl *pHostControl)
496 FIXME("(%p,%p)\n", iface, pHostControl);
497 return E_NOTIMPL;
500 static HRESULT WINAPI CLRRuntimeHost_GetCLRControl(ICLRRuntimeHost* iface,
501 ICLRControl **pCLRControl)
503 FIXME("(%p,%p)\n", iface, pCLRControl);
504 return E_NOTIMPL;
507 static HRESULT WINAPI CLRRuntimeHost_UnloadAppDomain(ICLRRuntimeHost* iface,
508 DWORD dwAppDomainId, BOOL fWaitUntilDone)
510 FIXME("(%p,%u,%i)\n", iface, dwAppDomainId, fWaitUntilDone);
511 return E_NOTIMPL;
514 static HRESULT WINAPI CLRRuntimeHost_ExecuteInAppDomain(ICLRRuntimeHost* iface,
515 DWORD dwAppDomainId, FExecuteInAppDomainCallback pCallback, void *cookie)
517 FIXME("(%p,%u,%p,%p)\n", iface, dwAppDomainId, pCallback, cookie);
518 return E_NOTIMPL;
521 static HRESULT WINAPI CLRRuntimeHost_GetCurrentAppDomainId(ICLRRuntimeHost* iface,
522 DWORD *pdwAppDomainId)
524 FIXME("(%p,%p)\n", iface, pdwAppDomainId);
525 return E_NOTIMPL;
528 static HRESULT WINAPI CLRRuntimeHost_ExecuteApplication(ICLRRuntimeHost* iface,
529 LPCWSTR pwzAppFullName, DWORD dwManifestPaths, LPCWSTR *ppwzManifestPaths,
530 DWORD dwActivationData, LPCWSTR *ppwzActivationData, int *pReturnValue)
532 FIXME("(%p,%s,%u,%u)\n", iface, debugstr_w(pwzAppFullName), dwManifestPaths, dwActivationData);
533 return E_NOTIMPL;
536 static HRESULT WINAPI CLRRuntimeHost_ExecuteInDefaultAppDomain(ICLRRuntimeHost* iface,
537 LPCWSTR pwzAssemblyPath, LPCWSTR pwzTypeName, LPCWSTR pwzMethodName,
538 LPCWSTR pwzArgument, DWORD *pReturnValue)
540 RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
541 HRESULT hr;
542 MonoDomain *domain;
543 MonoAssembly *assembly;
544 MonoImage *image;
545 MonoClass *klass;
546 MonoMethod *method;
547 MonoObject *result;
548 MonoString *str;
549 void *args[2];
550 char *filenameA = NULL, *classA = NULL, *methodA = NULL;
551 char *argsA = NULL, *ns;
553 TRACE("(%p,%s,%s,%s,%s)\n", iface, debugstr_w(pwzAssemblyPath),
554 debugstr_w(pwzTypeName), debugstr_w(pwzMethodName), debugstr_w(pwzArgument));
556 hr = RuntimeHost_GetDefaultDomain(This, &domain);
557 if(hr != S_OK)
559 ERR("Couldn't get Default Domain\n");
560 return hr;
563 hr = E_FAIL;
565 This->mono->mono_thread_attach(domain);
567 filenameA = WtoA(pwzAssemblyPath);
568 assembly = This->mono->mono_domain_assembly_open(domain, filenameA);
569 if (!assembly)
571 ERR("Cannot open assembly %s\n", filenameA);
572 goto cleanup;
575 image = This->mono->mono_assembly_get_image(assembly);
576 if (!image)
578 ERR("Couldn't get assembly image\n");
579 goto cleanup;
582 classA = WtoA(pwzTypeName);
583 ns = strrchr(classA, '.');
584 *ns = '\0';
585 klass = This->mono->mono_class_from_name(image, classA, ns+1);
586 if (!klass)
588 ERR("Couldn't get class from image\n");
589 goto cleanup;
592 methodA = WtoA(pwzMethodName);
593 method = This->mono->mono_class_get_method_from_name(klass, methodA, 1);
594 if (!method)
596 ERR("Couldn't get method from class\n");
597 goto cleanup;
600 /* The .NET function we are calling has the following declaration
601 * public static int functionName(String param)
603 argsA = WtoA(pwzArgument);
604 str = This->mono->mono_string_new(domain, argsA);
605 args[0] = str;
606 args[1] = NULL;
607 result = This->mono->mono_runtime_invoke(method, NULL, args, NULL);
608 if (!result)
609 ERR("Couldn't get result pointer\n");
610 else
612 *pReturnValue = *(DWORD*)This->mono->mono_object_unbox(result);
613 hr = S_OK;
616 cleanup:
617 HeapFree(GetProcessHeap(), 0, filenameA);
618 HeapFree(GetProcessHeap(), 0, classA);
619 HeapFree(GetProcessHeap(), 0, argsA);
620 HeapFree(GetProcessHeap(), 0, methodA);
622 return hr;
625 static const struct ICLRRuntimeHostVtbl CLRHostVtbl =
627 CLRRuntimeHost_QueryInterface,
628 CLRRuntimeHost_AddRef,
629 CLRRuntimeHost_Release,
630 CLRRuntimeHost_Start,
631 CLRRuntimeHost_Stop,
632 CLRRuntimeHost_SetHostControl,
633 CLRRuntimeHost_GetCLRControl,
634 CLRRuntimeHost_UnloadAppDomain,
635 CLRRuntimeHost_ExecuteInAppDomain,
636 CLRRuntimeHost_GetCurrentAppDomainId,
637 CLRRuntimeHost_ExecuteApplication,
638 CLRRuntimeHost_ExecuteInDefaultAppDomain
641 /* Create an instance of a type given its name, by calling its constructor with
642 * no arguments. Note that result MUST be in the stack, or the garbage
643 * collector may free it prematurely. */
644 HRESULT RuntimeHost_CreateManagedInstance(RuntimeHost *This, LPCWSTR name,
645 MonoDomain *domain, MonoObject **result)
647 HRESULT hr=S_OK;
648 char *nameA=NULL;
649 MonoType *type;
650 MonoClass *klass;
651 MonoObject *obj;
653 if (!domain)
654 hr = RuntimeHost_GetDefaultDomain(This, &domain);
656 if (SUCCEEDED(hr))
658 nameA = WtoA(name);
659 if (!nameA)
660 hr = E_OUTOFMEMORY;
663 if (SUCCEEDED(hr))
665 This->mono->mono_thread_attach(domain);
667 type = This->mono->mono_reflection_type_from_name(nameA, NULL);
668 if (!type)
670 ERR("Cannot find type %s\n", debugstr_w(name));
671 hr = E_FAIL;
675 if (SUCCEEDED(hr))
677 klass = This->mono->mono_class_from_mono_type(type);
678 if (!klass)
680 ERR("Cannot convert type %s to a class\n", debugstr_w(name));
681 hr = E_FAIL;
685 if (SUCCEEDED(hr))
687 obj = This->mono->mono_object_new(domain, klass);
688 if (!obj)
690 ERR("Cannot allocate object of type %s\n", debugstr_w(name));
691 hr = E_FAIL;
695 if (SUCCEEDED(hr))
697 /* FIXME: Detect exceptions from the constructor? */
698 This->mono->mono_runtime_object_init(obj);
699 *result = obj;
702 HeapFree(GetProcessHeap(), 0, nameA);
704 return hr;
707 /* Get an IUnknown pointer for a Mono object.
709 * This is just a "light" wrapper around
710 * System.Runtime.InteropServices.Marshal:GetIUnknownForObject
712 * NOTE: The IUnknown* is created with a reference to the object.
713 * Until they have a reference, objects must be in the stack to prevent the
714 * garbage collector from freeing them.
716 * mono_thread_attach must have already been called for this thread. */
717 HRESULT RuntimeHost_GetIUnknownForObject(RuntimeHost *This, MonoObject *obj,
718 IUnknown **ppUnk)
720 MonoDomain *domain;
721 MonoAssembly *assembly;
722 MonoImage *image;
723 MonoClass *klass;
724 MonoMethod *method;
725 MonoObject *result;
726 void *args[2];
728 domain = This->mono->mono_object_get_domain(obj);
730 assembly = This->mono->mono_domain_assembly_open(domain, "mscorlib");
731 if (!assembly)
733 ERR("Cannot load mscorlib\n");
734 return E_FAIL;
737 image = This->mono->mono_assembly_get_image(assembly);
738 if (!image)
740 ERR("Couldn't get assembly image\n");
741 return E_FAIL;
744 klass = This->mono->mono_class_from_name(image, "System.Runtime.InteropServices", "Marshal");
745 if (!klass)
747 ERR("Couldn't get class from image\n");
748 return E_FAIL;
751 method = This->mono->mono_class_get_method_from_name(klass, "GetIUnknownForObject", 1);
752 if (!method)
754 ERR("Couldn't get method from class\n");
755 return E_FAIL;
758 args[0] = obj;
759 args[1] = NULL;
760 result = This->mono->mono_runtime_invoke(method, NULL, args, NULL);
761 if (!result)
763 ERR("Couldn't get result pointer\n");
764 return E_FAIL;
767 *ppUnk = *(IUnknown**)This->mono->mono_object_unbox(result);
768 if (!*ppUnk)
770 ERR("GetIUnknownForObject returned 0\n");
771 return E_FAIL;
774 return S_OK;
777 static void get_utf8_args(int *argc, char ***argv)
779 WCHAR **argvw;
780 int size=0, i;
781 char *current_arg;
783 argvw = CommandLineToArgvW(GetCommandLineW(), argc);
785 for (i=0; i<*argc; i++)
787 size += sizeof(char*);
788 size += WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, NULL, 0, NULL, NULL);
790 size += sizeof(char*);
792 *argv = HeapAlloc(GetProcessHeap(), 0, size);
793 current_arg = (char*)(*argv + *argc + 1);
795 for (i=0; i<*argc; i++)
797 (*argv)[i] = current_arg;
798 current_arg += WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, current_arg, size, NULL, NULL);
801 (*argv)[*argc] = NULL;
803 HeapFree(GetProcessHeap(), 0, argvw);
806 __int32 WINAPI _CorExeMain(void)
808 int exit_code;
809 int argc;
810 char **argv;
811 MonoDomain *domain;
812 MonoAssembly *assembly;
813 WCHAR filename[MAX_PATH];
814 char *filenameA;
815 ICLRRuntimeInfo *info;
816 RuntimeHost *host;
817 HRESULT hr;
818 int i;
820 get_utf8_args(&argc, &argv);
822 GetModuleFileNameW(NULL, filename, MAX_PATH);
824 TRACE("%s", debugstr_w(filename));
825 for (i=0; i<argc; i++)
826 TRACE(" %s", debugstr_a(argv[i]));
827 TRACE("\n");
829 filenameA = WtoA(filename);
830 if (!filenameA)
831 return -1;
833 hr = get_runtime_info(filename, NULL, NULL, 0, 0, FALSE, &info);
835 if (SUCCEEDED(hr))
837 hr = ICLRRuntimeInfo_GetRuntimeHost(info, &host);
839 if (SUCCEEDED(hr))
840 hr = RuntimeHost_GetDefaultDomain(host, &domain);
842 if (SUCCEEDED(hr))
844 assembly = host->mono->mono_domain_assembly_open(domain, filenameA);
846 exit_code = host->mono->mono_jit_exec(domain, assembly, argc, argv);
848 RuntimeHost_DeleteDomain(host, domain);
850 else
851 exit_code = -1;
853 ICLRRuntimeInfo_Release(info);
855 else
856 exit_code = -1;
858 HeapFree(GetProcessHeap(), 0, argv);
860 unload_all_runtimes();
862 return exit_code;
865 HRESULT RuntimeHost_Construct(const CLRRuntimeInfo *runtime_version,
866 loaded_mono *loaded_mono, RuntimeHost** result)
868 RuntimeHost *This;
870 This = HeapAlloc( GetProcessHeap(), 0, sizeof *This );
871 if ( !This )
872 return E_OUTOFMEMORY;
874 This->ICorRuntimeHost_iface.lpVtbl = &corruntimehost_vtbl;
875 This->ICLRRuntimeHost_iface.lpVtbl = &CLRHostVtbl;
877 This->ref = 1;
878 This->version = runtime_version;
879 This->mono = loaded_mono;
880 list_init(&This->domains);
881 This->default_domain = NULL;
882 InitializeCriticalSection(&This->lock);
883 This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": RuntimeHost.lock");
885 *result = This;
887 return S_OK;
890 HRESULT RuntimeHost_GetInterface(RuntimeHost *This, REFCLSID clsid, REFIID riid, void **ppv)
892 IUnknown *unk;
893 HRESULT hr;
895 if (IsEqualGUID(clsid, &CLSID_CorRuntimeHost))
897 unk = (IUnknown*)&This->ICorRuntimeHost_iface;
898 IUnknown_AddRef(unk);
900 else if (IsEqualGUID(clsid, &CLSID_CLRRuntimeHost))
902 unk = (IUnknown*)&This->ICLRRuntimeHost_iface;
903 IUnknown_AddRef(unk);
905 else if (IsEqualGUID(clsid, &CLSID_CorMetaDataDispenser) ||
906 IsEqualGUID(clsid, &CLSID_CorMetaDataDispenserRuntime))
908 hr = MetaDataDispenser_CreateInstance(&unk);
909 if (FAILED(hr))
910 return hr;
912 else if (IsEqualGUID(clsid, &CLSID_CLRDebuggingLegacy))
914 hr = CorDebug_Create(&This->ICLRRuntimeHost_iface, &unk);
915 if (FAILED(hr))
916 return hr;
918 else
919 unk = NULL;
921 if (unk)
923 hr = IUnknown_QueryInterface(unk, riid, ppv);
925 IUnknown_Release(unk);
927 return hr;
929 else
930 FIXME("not implemented for class %s\n", debugstr_guid(clsid));
932 return CLASS_E_CLASSNOTAVAILABLE;
935 HRESULT RuntimeHost_Destroy(RuntimeHost *This)
937 struct DomainEntry *cursor, *cursor2;
939 This->lock.DebugInfo->Spare[0] = 0;
940 DeleteCriticalSection(&This->lock);
942 LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->domains, struct DomainEntry, entry)
944 list_remove(&cursor->entry);
945 HeapFree(GetProcessHeap(), 0, cursor);
948 HeapFree( GetProcessHeap(), 0, This );
949 return S_OK;
952 #define CHARS_IN_GUID 39
953 #define ARRAYSIZE(array) (sizeof(array)/sizeof((array)[0]))
955 HRESULT create_monodata(REFIID riid, LPVOID *ppObj )
957 static const WCHAR wszCodebase[] = {'C','o','d','e','B','a','s','e',0};
958 static const WCHAR wszClass[] = {'C','l','a','s','s',0};
959 static const WCHAR wszFileSlash[] = {'f','i','l','e',':','/','/','/',0};
960 static const WCHAR wszCLSIDSlash[] = {'C','L','S','I','D','\\',0};
961 static const WCHAR wszInprocServer32[] = {'\\','I','n','p','r','o','c','S','e','r','v','e','r','3','2',0};
962 WCHAR path[CHARS_IN_GUID + ARRAYSIZE(wszCLSIDSlash) + ARRAYSIZE(wszInprocServer32) - 1];
963 MonoDomain *domain;
964 MonoAssembly *assembly;
965 ICLRRuntimeInfo *info;
966 RuntimeHost *host;
967 HRESULT hr;
968 HKEY key;
969 LONG res;
970 int offset = 0;
971 WCHAR codebase[MAX_PATH + 8];
972 WCHAR classname[350];
973 WCHAR filename[MAX_PATH];
975 DWORD dwBufLen = 350;
977 lstrcpyW(path, wszCLSIDSlash);
978 StringFromGUID2(riid, path + lstrlenW(wszCLSIDSlash), CHARS_IN_GUID);
979 lstrcatW(path, wszInprocServer32);
981 TRACE("Registry key: %s\n", debugstr_w(path));
983 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, path, 0, KEY_READ, &key);
984 if (res == ERROR_FILE_NOT_FOUND)
985 return CLASS_E_CLASSNOTAVAILABLE;
987 res = RegGetValueW( key, NULL, wszClass, RRF_RT_REG_SZ, NULL, classname, &dwBufLen);
988 if(res != ERROR_SUCCESS)
990 WARN("Class value cannot be found.\n");
991 hr = CLASS_E_CLASSNOTAVAILABLE;
992 goto cleanup;
995 TRACE("classname (%s)\n", debugstr_w(classname));
997 dwBufLen = MAX_PATH + 8;
998 res = RegGetValueW( key, NULL, wszCodebase, RRF_RT_REG_SZ, NULL, codebase, &dwBufLen);
999 if(res != ERROR_SUCCESS)
1001 WARN("CodeBase value cannot be found.\n");
1002 hr = CLASS_E_CLASSNOTAVAILABLE;
1003 goto cleanup;
1006 /* Strip file:/// */
1007 if(strncmpW(codebase, wszFileSlash, strlenW(wszFileSlash)) == 0)
1008 offset = strlenW(wszFileSlash);
1010 strcpyW(filename, codebase + offset);
1012 TRACE("codebase (%s)\n", debugstr_w(filename));
1014 *ppObj = NULL;
1017 hr = get_runtime_info(filename, NULL, NULL, 0, 0, FALSE, &info);
1018 if (SUCCEEDED(hr))
1020 hr = ICLRRuntimeInfo_GetRuntimeHost(info, &host);
1022 if (SUCCEEDED(hr))
1023 hr = RuntimeHost_GetDefaultDomain(host, &domain);
1025 if (SUCCEEDED(hr))
1027 MonoImage *image;
1028 MonoClass *klass;
1029 MonoObject *result;
1030 IUnknown *unk = NULL;
1031 char *filenameA, *ns;
1032 char *classA;
1034 hr = CLASS_E_CLASSNOTAVAILABLE;
1036 host->mono->mono_thread_attach(domain);
1038 filenameA = WtoA(filename);
1039 assembly = host->mono->mono_domain_assembly_open(domain, filenameA);
1040 HeapFree(GetProcessHeap(), 0, filenameA);
1041 if (!assembly)
1043 ERR("Cannot open assembly %s\n", filenameA);
1044 goto cleanup;
1047 image = host->mono->mono_assembly_get_image(assembly);
1048 if (!image)
1050 ERR("Couldn't get assembly image\n");
1051 goto cleanup;
1054 classA = WtoA(classname);
1055 ns = strrchr(classA, '.');
1056 *ns = '\0';
1058 klass = host->mono->mono_class_from_name(image, classA, ns+1);
1059 HeapFree(GetProcessHeap(), 0, classA);
1060 if (!klass)
1062 ERR("Couldn't get class from image\n");
1063 goto cleanup;
1067 * Use the default constructor for the .NET class.
1069 result = host->mono->mono_object_new(domain, klass);
1070 host->mono->mono_runtime_object_init(result);
1072 hr = RuntimeHost_GetIUnknownForObject(host, result, &unk);
1073 if (SUCCEEDED(hr))
1075 hr = IUnknown_QueryInterface(unk, &IID_IUnknown, ppObj);
1077 IUnknown_Release(unk);
1079 else
1080 hr = CLASS_E_CLASSNOTAVAILABLE;
1082 else
1083 hr = CLASS_E_CLASSNOTAVAILABLE;
1085 else
1086 hr = CLASS_E_CLASSNOTAVAILABLE;
1088 cleanup:
1089 if(info)
1090 ICLRRuntimeInfo_Release(info);
1092 RegCloseKey(key);
1094 return hr;