mmdevapi: Indicate data flow direction in IMMDevice::GetId result.
[wine.git] / dlls / mscoree / corruntimehost.c
blobff789d4547c0fc757d9ed12594fa8df712dee056
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 assembly = This->mono->mono_domain_assembly_open(domain, "mscorlib");
152 if (!assembly)
154 ERR("Cannot load mscorlib\n");
155 return E_FAIL;
158 image = This->mono->mono_assembly_get_image(assembly);
159 if (!image)
161 ERR("Couldn't get assembly image\n");
162 return E_FAIL;
165 klass = This->mono->mono_class_from_name(image, "System", "AppDomain");
166 if (!klass)
168 ERR("Couldn't get class from image\n");
169 return E_FAIL;
172 method = This->mono->mono_class_get_method_from_name(klass, "get_CurrentDomain", 0);
173 if (!method)
175 ERR("Couldn't get method from class\n");
176 return E_FAIL;
179 args[0] = NULL;
180 appdomain_object = This->mono->mono_runtime_invoke(method, NULL, args, NULL);
181 if (!appdomain_object)
183 ERR("Couldn't get result pointer\n");
184 return E_FAIL;
187 hr = RuntimeHost_GetIUnknownForObject(This, appdomain_object, &unk);
189 if (SUCCEEDED(hr))
191 hr = IUnknown_QueryInterface(unk, &IID__AppDomain, (void**)punk);
193 IUnknown_Release(unk);
196 return hr;
199 static inline RuntimeHost *impl_from_ICLRRuntimeHost( ICLRRuntimeHost *iface )
201 return CONTAINING_RECORD(iface, RuntimeHost, ICLRRuntimeHost_iface);
204 static inline RuntimeHost *impl_from_ICorRuntimeHost( ICorRuntimeHost *iface )
206 return CONTAINING_RECORD(iface, RuntimeHost, ICorRuntimeHost_iface);
209 /*** IUnknown methods ***/
210 static HRESULT WINAPI corruntimehost_QueryInterface(ICorRuntimeHost* iface,
211 REFIID riid,
212 void **ppvObject)
214 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
215 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
217 if ( IsEqualGUID( riid, &IID_ICorRuntimeHost ) ||
218 IsEqualGUID( riid, &IID_IUnknown ) )
220 *ppvObject = iface;
222 else
224 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
225 return E_NOINTERFACE;
228 ICorRuntimeHost_AddRef( iface );
230 return S_OK;
233 static ULONG WINAPI corruntimehost_AddRef(ICorRuntimeHost* iface)
235 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
237 return InterlockedIncrement( &This->ref );
240 static ULONG WINAPI corruntimehost_Release(ICorRuntimeHost* iface)
242 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
243 ULONG ref;
245 ref = InterlockedDecrement( &This->ref );
247 return ref;
250 /*** ICorRuntimeHost methods ***/
251 static HRESULT WINAPI corruntimehost_CreateLogicalThreadState(
252 ICorRuntimeHost* iface)
254 FIXME("stub %p\n", iface);
255 return E_NOTIMPL;
258 static HRESULT WINAPI corruntimehost_DeleteLogicalThreadState(
259 ICorRuntimeHost* iface)
261 FIXME("stub %p\n", iface);
262 return E_NOTIMPL;
265 static HRESULT WINAPI corruntimehost_SwitchInLogicalThreadState(
266 ICorRuntimeHost* iface,
267 DWORD *fiberCookie)
269 FIXME("stub %p\n", iface);
270 return E_NOTIMPL;
273 static HRESULT WINAPI corruntimehost_SwitchOutLogicalThreadState(
274 ICorRuntimeHost* iface,
275 DWORD **fiberCookie)
277 FIXME("stub %p\n", iface);
278 return E_NOTIMPL;
281 static HRESULT WINAPI corruntimehost_LocksHeldByLogicalThread(
282 ICorRuntimeHost* iface,
283 DWORD *pCount)
285 FIXME("stub %p\n", iface);
286 return E_NOTIMPL;
289 static HRESULT WINAPI corruntimehost_MapFile(
290 ICorRuntimeHost* iface,
291 HANDLE hFile,
292 HMODULE *mapAddress)
294 FIXME("stub %p\n", iface);
295 return E_NOTIMPL;
298 static HRESULT WINAPI corruntimehost_GetConfiguration(
299 ICorRuntimeHost* iface,
300 ICorConfiguration **pConfiguration)
302 FIXME("stub %p\n", iface);
303 return E_NOTIMPL;
306 static HRESULT WINAPI corruntimehost_Start(
307 ICorRuntimeHost* iface)
309 FIXME("stub %p\n", iface);
310 return S_OK;
313 static HRESULT WINAPI corruntimehost_Stop(
314 ICorRuntimeHost* iface)
316 FIXME("stub %p\n", iface);
317 return E_NOTIMPL;
320 static HRESULT WINAPI corruntimehost_CreateDomain(
321 ICorRuntimeHost* iface,
322 LPCWSTR friendlyName,
323 IUnknown *identityArray,
324 IUnknown **appDomain)
326 FIXME("stub %p\n", iface);
327 return E_NOTIMPL;
330 static HRESULT WINAPI corruntimehost_GetDefaultDomain(
331 ICorRuntimeHost* iface,
332 IUnknown **pAppDomain)
334 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
335 HRESULT hr;
336 MonoDomain *domain;
338 TRACE("(%p)\n", iface);
340 hr = RuntimeHost_GetDefaultDomain(This, &domain);
342 if (SUCCEEDED(hr))
344 hr = RuntimeHost_GetIUnknownForDomain(This, domain, pAppDomain);
347 return hr;
350 static HRESULT WINAPI corruntimehost_EnumDomains(
351 ICorRuntimeHost* iface,
352 HDOMAINENUM *hEnum)
354 FIXME("stub %p\n", iface);
355 return E_NOTIMPL;
358 static HRESULT WINAPI corruntimehost_NextDomain(
359 ICorRuntimeHost* iface,
360 HDOMAINENUM hEnum,
361 IUnknown **appDomain)
363 FIXME("stub %p\n", iface);
364 return E_NOTIMPL;
367 static HRESULT WINAPI corruntimehost_CloseEnum(
368 ICorRuntimeHost* iface,
369 HDOMAINENUM hEnum)
371 FIXME("stub %p\n", iface);
372 return E_NOTIMPL;
375 static HRESULT WINAPI corruntimehost_CreateDomainEx(
376 ICorRuntimeHost* iface,
377 LPCWSTR friendlyName,
378 IUnknown *setup,
379 IUnknown *evidence,
380 IUnknown **appDomain)
382 FIXME("stub %p\n", iface);
383 return E_NOTIMPL;
386 static HRESULT WINAPI corruntimehost_CreateDomainSetup(
387 ICorRuntimeHost* iface,
388 IUnknown **appDomainSetup)
390 FIXME("stub %p\n", iface);
391 return E_NOTIMPL;
394 static HRESULT WINAPI corruntimehost_CreateEvidence(
395 ICorRuntimeHost* iface,
396 IUnknown **evidence)
398 FIXME("stub %p\n", iface);
399 return E_NOTIMPL;
402 static HRESULT WINAPI corruntimehost_UnloadDomain(
403 ICorRuntimeHost* iface,
404 IUnknown *appDomain)
406 FIXME("stub %p\n", iface);
407 return E_NOTIMPL;
410 static HRESULT WINAPI corruntimehost_CurrentDomain(
411 ICorRuntimeHost* iface,
412 IUnknown **appDomain)
414 FIXME("stub %p\n", iface);
415 return E_NOTIMPL;
418 static const struct ICorRuntimeHostVtbl corruntimehost_vtbl =
420 corruntimehost_QueryInterface,
421 corruntimehost_AddRef,
422 corruntimehost_Release,
423 corruntimehost_CreateLogicalThreadState,
424 corruntimehost_DeleteLogicalThreadState,
425 corruntimehost_SwitchInLogicalThreadState,
426 corruntimehost_SwitchOutLogicalThreadState,
427 corruntimehost_LocksHeldByLogicalThread,
428 corruntimehost_MapFile,
429 corruntimehost_GetConfiguration,
430 corruntimehost_Start,
431 corruntimehost_Stop,
432 corruntimehost_CreateDomain,
433 corruntimehost_GetDefaultDomain,
434 corruntimehost_EnumDomains,
435 corruntimehost_NextDomain,
436 corruntimehost_CloseEnum,
437 corruntimehost_CreateDomainEx,
438 corruntimehost_CreateDomainSetup,
439 corruntimehost_CreateEvidence,
440 corruntimehost_UnloadDomain,
441 corruntimehost_CurrentDomain
444 static HRESULT WINAPI CLRRuntimeHost_QueryInterface(ICLRRuntimeHost* iface,
445 REFIID riid,
446 void **ppvObject)
448 RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
449 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
451 if ( IsEqualGUID( riid, &IID_ICLRRuntimeHost ) ||
452 IsEqualGUID( riid, &IID_IUnknown ) )
454 *ppvObject = iface;
456 else
458 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
459 return E_NOINTERFACE;
462 ICLRRuntimeHost_AddRef( iface );
464 return S_OK;
467 static ULONG WINAPI CLRRuntimeHost_AddRef(ICLRRuntimeHost* iface)
469 RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
470 return ICorRuntimeHost_AddRef(&This->ICorRuntimeHost_iface);
473 static ULONG WINAPI CLRRuntimeHost_Release(ICLRRuntimeHost* iface)
475 RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
476 return ICorRuntimeHost_Release(&This->ICorRuntimeHost_iface);
479 static HRESULT WINAPI CLRRuntimeHost_Start(ICLRRuntimeHost* iface)
481 FIXME("(%p)\n", iface);
482 return E_NOTIMPL;
485 static HRESULT WINAPI CLRRuntimeHost_Stop(ICLRRuntimeHost* iface)
487 FIXME("(%p)\n", iface);
488 return E_NOTIMPL;
491 static HRESULT WINAPI CLRRuntimeHost_SetHostControl(ICLRRuntimeHost* iface,
492 IHostControl *pHostControl)
494 FIXME("(%p,%p)\n", iface, pHostControl);
495 return E_NOTIMPL;
498 static HRESULT WINAPI CLRRuntimeHost_GetCLRControl(ICLRRuntimeHost* iface,
499 ICLRControl **pCLRControl)
501 FIXME("(%p,%p)\n", iface, pCLRControl);
502 return E_NOTIMPL;
505 static HRESULT WINAPI CLRRuntimeHost_UnloadAppDomain(ICLRRuntimeHost* iface,
506 DWORD dwAppDomainId, BOOL fWaitUntilDone)
508 FIXME("(%p,%u,%i)\n", iface, dwAppDomainId, fWaitUntilDone);
509 return E_NOTIMPL;
512 static HRESULT WINAPI CLRRuntimeHost_ExecuteInAppDomain(ICLRRuntimeHost* iface,
513 DWORD dwAppDomainId, FExecuteInAppDomainCallback pCallback, void *cookie)
515 FIXME("(%p,%u,%p,%p)\n", iface, dwAppDomainId, pCallback, cookie);
516 return E_NOTIMPL;
519 static HRESULT WINAPI CLRRuntimeHost_GetCurrentAppDomainId(ICLRRuntimeHost* iface,
520 DWORD *pdwAppDomainId)
522 FIXME("(%p,%p)\n", iface, pdwAppDomainId);
523 return E_NOTIMPL;
526 static HRESULT WINAPI CLRRuntimeHost_ExecuteApplication(ICLRRuntimeHost* iface,
527 LPCWSTR pwzAppFullName, DWORD dwManifestPaths, LPCWSTR *ppwzManifestPaths,
528 DWORD dwActivationData, LPCWSTR *ppwzActivationData, int *pReturnValue)
530 FIXME("(%p,%s,%u,%u)\n", iface, debugstr_w(pwzAppFullName), dwManifestPaths, dwActivationData);
531 return E_NOTIMPL;
534 static HRESULT WINAPI CLRRuntimeHost_ExecuteInDefaultAppDomain(ICLRRuntimeHost* iface,
535 LPCWSTR pwzAssemblyPath, LPCWSTR pwzTypeName, LPCWSTR pwzMethodName,
536 LPCWSTR pwzArgument, DWORD *pReturnValue)
538 RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
539 HRESULT hr;
540 MonoDomain *domain;
541 MonoAssembly *assembly;
542 MonoImage *image;
543 MonoClass *klass;
544 MonoMethod *method;
545 MonoObject *result;
546 MonoString *str;
547 void *args[2];
548 char *filenameA = NULL, *classA = NULL, *methodA = NULL;
549 char *argsA = NULL, *ns;
551 TRACE("(%p,%s,%s,%s,%s)\n", iface, debugstr_w(pwzAssemblyPath),
552 debugstr_w(pwzTypeName), debugstr_w(pwzMethodName), debugstr_w(pwzArgument));
554 hr = RuntimeHost_GetDefaultDomain(This, &domain);
555 if(hr != S_OK)
557 ERR("Couldn't get Default Domain\n");
558 return hr;
561 hr = E_FAIL;
563 filenameA = WtoA(pwzAssemblyPath);
564 assembly = This->mono->mono_domain_assembly_open(domain, filenameA);
565 if (!assembly)
567 ERR("Cannot open assembly %s\n", filenameA);
568 goto cleanup;
571 image = This->mono->mono_assembly_get_image(assembly);
572 if (!image)
574 ERR("Couldn't get assembly image\n");
575 goto cleanup;
578 classA = WtoA(pwzTypeName);
579 ns = strrchr(classA, '.');
580 *ns = '\0';
581 klass = This->mono->mono_class_from_name(image, classA, ns+1);
582 if (!klass)
584 ERR("Couldn't get class from image\n");
585 goto cleanup;
588 methodA = WtoA(pwzMethodName);
589 method = This->mono->mono_class_get_method_from_name(klass, methodA, 1);
590 if (!method)
592 ERR("Couldn't get method from class\n");
593 goto cleanup;
596 /* The .NET function we are calling has the following declaration
597 * public static int functionName(String param)
599 argsA = WtoA(pwzArgument);
600 str = This->mono->mono_string_new(domain, argsA);
601 args[0] = str;
602 args[1] = NULL;
603 result = This->mono->mono_runtime_invoke(method, NULL, args, NULL);
604 if (!result)
605 ERR("Couldn't get result pointer\n");
606 else
608 *pReturnValue = *(DWORD*)This->mono->mono_object_unbox(result);
609 hr = S_OK;
612 cleanup:
613 HeapFree(GetProcessHeap(), 0, filenameA);
614 HeapFree(GetProcessHeap(), 0, classA);
615 HeapFree(GetProcessHeap(), 0, argsA);
616 HeapFree(GetProcessHeap(), 0, methodA);
618 return hr;
621 static const struct ICLRRuntimeHostVtbl CLRHostVtbl =
623 CLRRuntimeHost_QueryInterface,
624 CLRRuntimeHost_AddRef,
625 CLRRuntimeHost_Release,
626 CLRRuntimeHost_Start,
627 CLRRuntimeHost_Stop,
628 CLRRuntimeHost_SetHostControl,
629 CLRRuntimeHost_GetCLRControl,
630 CLRRuntimeHost_UnloadAppDomain,
631 CLRRuntimeHost_ExecuteInAppDomain,
632 CLRRuntimeHost_GetCurrentAppDomainId,
633 CLRRuntimeHost_ExecuteApplication,
634 CLRRuntimeHost_ExecuteInDefaultAppDomain
637 /* Create an instance of a type given its name, by calling its constructor with
638 * no arguments. Note that result MUST be in the stack, or the garbage
639 * collector may free it prematurely. */
640 HRESULT RuntimeHost_CreateManagedInstance(RuntimeHost *This, LPCWSTR name,
641 MonoDomain *domain, MonoObject **result)
643 HRESULT hr=S_OK;
644 char *nameA=NULL;
645 MonoType *type;
646 MonoClass *klass;
647 MonoObject *obj;
649 if (!domain)
650 hr = RuntimeHost_GetDefaultDomain(This, &domain);
652 if (SUCCEEDED(hr))
654 nameA = WtoA(name);
655 if (!nameA)
656 hr = E_OUTOFMEMORY;
659 if (SUCCEEDED(hr))
661 type = This->mono->mono_reflection_type_from_name(nameA, NULL);
662 if (!type)
664 ERR("Cannot find type %s\n", debugstr_w(name));
665 hr = E_FAIL;
669 if (SUCCEEDED(hr))
671 klass = This->mono->mono_class_from_mono_type(type);
672 if (!klass)
674 ERR("Cannot convert type %s to a class\n", debugstr_w(name));
675 hr = E_FAIL;
679 if (SUCCEEDED(hr))
681 obj = This->mono->mono_object_new(domain, klass);
682 if (!obj)
684 ERR("Cannot allocate object of type %s\n", debugstr_w(name));
685 hr = E_FAIL;
689 if (SUCCEEDED(hr))
691 /* FIXME: Detect exceptions from the constructor? */
692 This->mono->mono_runtime_object_init(obj);
693 *result = obj;
696 HeapFree(GetProcessHeap(), 0, nameA);
698 return hr;
701 /* Get an IUnknown pointer for a Mono object.
703 * This is just a "light" wrapper around
704 * System.Runtime.InteropServices.Marshal:GetIUnknownForObject
706 * NOTE: The IUnknown* is created with a reference to the object.
707 * Until they have a reference, objects must be in the stack to prevent the
708 * garbage collector from freeing them. */
709 HRESULT RuntimeHost_GetIUnknownForObject(RuntimeHost *This, MonoObject *obj,
710 IUnknown **ppUnk)
712 MonoDomain *domain;
713 MonoAssembly *assembly;
714 MonoImage *image;
715 MonoClass *klass;
716 MonoMethod *method;
717 MonoObject *result;
718 void *args[2];
720 domain = This->mono->mono_object_get_domain(obj);
722 assembly = This->mono->mono_domain_assembly_open(domain, "mscorlib");
723 if (!assembly)
725 ERR("Cannot load mscorlib\n");
726 return E_FAIL;
729 image = This->mono->mono_assembly_get_image(assembly);
730 if (!image)
732 ERR("Couldn't get assembly image\n");
733 return E_FAIL;
736 klass = This->mono->mono_class_from_name(image, "System.Runtime.InteropServices", "Marshal");
737 if (!klass)
739 ERR("Couldn't get class from image\n");
740 return E_FAIL;
743 method = This->mono->mono_class_get_method_from_name(klass, "GetIUnknownForObject", 1);
744 if (!method)
746 ERR("Couldn't get method from class\n");
747 return E_FAIL;
750 args[0] = obj;
751 args[1] = NULL;
752 result = This->mono->mono_runtime_invoke(method, NULL, args, NULL);
753 if (!result)
755 ERR("Couldn't get result pointer\n");
756 return E_FAIL;
759 *ppUnk = *(IUnknown**)This->mono->mono_object_unbox(result);
760 if (!*ppUnk)
762 ERR("GetIUnknownForObject returned 0\n");
763 return E_FAIL;
766 return S_OK;
769 static void get_utf8_args(int *argc, char ***argv)
771 WCHAR **argvw;
772 int size=0, i;
773 char *current_arg;
775 argvw = CommandLineToArgvW(GetCommandLineW(), argc);
777 for (i=0; i<*argc; i++)
779 size += sizeof(char*);
780 size += WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, NULL, 0, NULL, NULL);
782 size += sizeof(char*);
784 *argv = HeapAlloc(GetProcessHeap(), 0, size);
785 current_arg = (char*)(*argv + *argc + 1);
787 for (i=0; i<*argc; i++)
789 (*argv)[i] = current_arg;
790 current_arg += WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, current_arg, size, NULL, NULL);
793 (*argv)[*argc] = NULL;
795 HeapFree(GetProcessHeap(), 0, argvw);
798 __int32 WINAPI _CorExeMain(void)
800 int exit_code;
801 int argc;
802 char **argv;
803 MonoDomain *domain;
804 MonoAssembly *assembly;
805 WCHAR filename[MAX_PATH];
806 char *filenameA;
807 ICLRRuntimeInfo *info;
808 RuntimeHost *host;
809 HRESULT hr;
810 int i;
812 get_utf8_args(&argc, &argv);
814 GetModuleFileNameW(NULL, filename, MAX_PATH);
816 TRACE("%s", debugstr_w(filename));
817 for (i=0; i<argc; i++)
818 TRACE(" %s", debugstr_a(argv[i]));
819 TRACE("\n");
821 filenameA = WtoA(filename);
822 if (!filenameA)
823 return -1;
825 hr = get_runtime_info(filename, NULL, NULL, 0, 0, FALSE, &info);
827 if (SUCCEEDED(hr))
829 hr = ICLRRuntimeInfo_GetRuntimeHost(info, &host);
831 if (SUCCEEDED(hr))
832 hr = RuntimeHost_GetDefaultDomain(host, &domain);
834 if (SUCCEEDED(hr))
836 assembly = host->mono->mono_domain_assembly_open(domain, filenameA);
838 exit_code = host->mono->mono_jit_exec(domain, assembly, argc, argv);
840 RuntimeHost_DeleteDomain(host, domain);
842 else
843 exit_code = -1;
845 ICLRRuntimeInfo_Release(info);
847 else
848 exit_code = -1;
850 HeapFree(GetProcessHeap(), 0, argv);
852 unload_all_runtimes();
854 return exit_code;
857 HRESULT RuntimeHost_Construct(const CLRRuntimeInfo *runtime_version,
858 loaded_mono *loaded_mono, RuntimeHost** result)
860 RuntimeHost *This;
862 This = HeapAlloc( GetProcessHeap(), 0, sizeof *This );
863 if ( !This )
864 return E_OUTOFMEMORY;
866 This->ICorRuntimeHost_iface.lpVtbl = &corruntimehost_vtbl;
867 This->ICLRRuntimeHost_iface.lpVtbl = &CLRHostVtbl;
869 This->ref = 1;
870 This->version = runtime_version;
871 This->mono = loaded_mono;
872 list_init(&This->domains);
873 This->default_domain = NULL;
874 InitializeCriticalSection(&This->lock);
875 This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": RuntimeHost.lock");
877 *result = This;
879 return S_OK;
882 HRESULT RuntimeHost_GetInterface(RuntimeHost *This, REFCLSID clsid, REFIID riid, void **ppv)
884 IUnknown *unk;
885 HRESULT hr;
887 if (IsEqualGUID(clsid, &CLSID_CorRuntimeHost))
889 unk = (IUnknown*)&This->ICorRuntimeHost_iface;
890 IUnknown_AddRef(unk);
892 else if (IsEqualGUID(clsid, &CLSID_CLRRuntimeHost))
894 unk = (IUnknown*)&This->ICLRRuntimeHost_iface;
895 IUnknown_AddRef(unk);
897 else if (IsEqualGUID(clsid, &CLSID_CorMetaDataDispenser) ||
898 IsEqualGUID(clsid, &CLSID_CorMetaDataDispenserRuntime))
900 hr = MetaDataDispenser_CreateInstance(&unk);
901 if (FAILED(hr))
902 return hr;
904 else if (IsEqualGUID(clsid, &CLSID_CLRDebuggingLegacy))
906 hr = CorDebug_Create(&This->ICLRRuntimeHost_iface, &unk);
907 if (FAILED(hr))
908 return hr;
910 else
911 unk = NULL;
913 if (unk)
915 hr = IUnknown_QueryInterface(unk, riid, ppv);
917 IUnknown_Release(unk);
919 return hr;
921 else
922 FIXME("not implemented for class %s\n", debugstr_guid(clsid));
924 return CLASS_E_CLASSNOTAVAILABLE;
927 HRESULT RuntimeHost_Destroy(RuntimeHost *This)
929 struct DomainEntry *cursor, *cursor2;
931 This->lock.DebugInfo->Spare[0] = 0;
932 DeleteCriticalSection(&This->lock);
934 LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->domains, struct DomainEntry, entry)
936 list_remove(&cursor->entry);
937 HeapFree(GetProcessHeap(), 0, cursor);
940 HeapFree( GetProcessHeap(), 0, This );
941 return S_OK;
944 #define CHARS_IN_GUID 39
945 #define ARRAYSIZE(array) (sizeof(array)/sizeof((array)[0]))
947 HRESULT create_monodata(REFIID riid, LPVOID *ppObj )
949 static const WCHAR wszCodebase[] = {'C','o','d','e','B','a','s','e',0};
950 static const WCHAR wszClass[] = {'C','l','a','s','s',0};
951 static const WCHAR wszFileSlash[] = {'f','i','l','e',':','/','/','/',0};
952 static const WCHAR wszCLSIDSlash[] = {'C','L','S','I','D','\\',0};
953 static const WCHAR wszInprocServer32[] = {'\\','I','n','p','r','o','c','S','e','r','v','e','r','3','2',0};
954 WCHAR path[CHARS_IN_GUID + ARRAYSIZE(wszCLSIDSlash) + ARRAYSIZE(wszInprocServer32) - 1];
955 MonoDomain *domain;
956 MonoAssembly *assembly;
957 ICLRRuntimeInfo *info;
958 RuntimeHost *host;
959 HRESULT hr;
960 HKEY key;
961 LONG res;
962 int offset = 0;
963 WCHAR codebase[MAX_PATH + 8];
964 WCHAR classname[350];
965 WCHAR filename[MAX_PATH];
967 DWORD dwBufLen = 350;
969 lstrcpyW(path, wszCLSIDSlash);
970 StringFromGUID2(riid, path + lstrlenW(wszCLSIDSlash), CHARS_IN_GUID);
971 lstrcatW(path, wszInprocServer32);
973 TRACE("Registry key: %s\n", debugstr_w(path));
975 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, path, 0, KEY_READ, &key);
976 if (res == ERROR_FILE_NOT_FOUND)
977 return CLASS_E_CLASSNOTAVAILABLE;
979 res = RegGetValueW( key, NULL, wszClass, RRF_RT_REG_SZ, NULL, classname, &dwBufLen);
980 if(res != ERROR_SUCCESS)
982 WARN("Class value cannot be found.\n");
983 hr = CLASS_E_CLASSNOTAVAILABLE;
984 goto cleanup;
987 TRACE("classname (%s)\n", debugstr_w(classname));
989 dwBufLen = MAX_PATH + 8;
990 res = RegGetValueW( key, NULL, wszCodebase, RRF_RT_REG_SZ, NULL, codebase, &dwBufLen);
991 if(res != ERROR_SUCCESS)
993 WARN("CodeBase value cannot be found.\n");
994 hr = CLASS_E_CLASSNOTAVAILABLE;
995 goto cleanup;
998 /* Strip file:/// */
999 if(strncmpW(codebase, wszFileSlash, strlenW(wszFileSlash)) == 0)
1000 offset = strlenW(wszFileSlash);
1002 strcpyW(filename, codebase + offset);
1004 TRACE("codebase (%s)\n", debugstr_w(filename));
1006 *ppObj = NULL;
1009 hr = get_runtime_info(filename, NULL, NULL, 0, 0, FALSE, &info);
1010 if (SUCCEEDED(hr))
1012 hr = ICLRRuntimeInfo_GetRuntimeHost(info, &host);
1014 if (SUCCEEDED(hr))
1015 hr = RuntimeHost_GetDefaultDomain(host, &domain);
1017 if (SUCCEEDED(hr))
1019 MonoImage *image;
1020 MonoClass *klass;
1021 MonoObject *result;
1022 IUnknown *unk = NULL;
1023 char *filenameA, *ns;
1024 char *classA;
1026 hr = CLASS_E_CLASSNOTAVAILABLE;
1028 filenameA = WtoA(filename);
1029 assembly = host->mono->mono_domain_assembly_open(domain, filenameA);
1030 HeapFree(GetProcessHeap(), 0, filenameA);
1031 if (!assembly)
1033 ERR("Cannot open assembly %s\n", filenameA);
1034 goto cleanup;
1037 image = host->mono->mono_assembly_get_image(assembly);
1038 if (!image)
1040 ERR("Couldn't get assembly image\n");
1041 goto cleanup;
1044 classA = WtoA(classname);
1045 ns = strrchr(classA, '.');
1046 *ns = '\0';
1048 klass = host->mono->mono_class_from_name(image, classA, ns+1);
1049 HeapFree(GetProcessHeap(), 0, classA);
1050 if (!klass)
1052 ERR("Couldn't get class from image\n");
1053 goto cleanup;
1057 * Use the default constructor for the .NET class.
1059 result = host->mono->mono_object_new(domain, klass);
1060 host->mono->mono_runtime_object_init(result);
1062 hr = RuntimeHost_GetIUnknownForObject(host, result, &unk);
1063 if (SUCCEEDED(hr))
1065 hr = IUnknown_QueryInterface(unk, &IID_IUnknown, ppObj);
1067 IUnknown_Release(unk);
1069 else
1070 hr = CLASS_E_CLASSNOTAVAILABLE;
1072 else
1073 hr = CLASS_E_CLASSNOTAVAILABLE;
1075 else
1076 hr = CLASS_E_CLASSNOTAVAILABLE;
1078 cleanup:
1079 if(info)
1080 ICLRRuntimeInfo_Release(info);
1082 RegCloseKey(key);
1084 return hr;