5042f203d711bee633dcf30636fb697995243220
[reactos.git] / reactos / dll / win32 / mscoree / corruntimehost.c
1 /*
2 *
3 * Copyright 2008 Alistair Leslie-Hughes
4 *
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.
9 *
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.
14 *
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
18 */
19
20 #define COBJMACROS
21
22 #include <stdarg.h>
23
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"
31
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"
39
40 #include "wine/debug.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
43
44 #include "initguid.h"
45
46 DEFINE_GUID(IID__AppDomain, 0x05f696dc,0x2b29,0x3663,0xad,0x8b,0xc4,0x38,0x9c,0xf2,0xa7,0x13);
47
48 struct DomainEntry
49 {
50 struct list entry;
51 MonoDomain *domain;
52 };
53
54 static HRESULT RuntimeHost_AddDomain(RuntimeHost *This, MonoDomain **result)
55 {
56 struct DomainEntry *entry;
57 char *mscorlib_path;
58 HRESULT res=S_OK;
59
60 EnterCriticalSection(&This->lock);
61
62 entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry));
63 if (!entry)
64 {
65 res = E_OUTOFMEMORY;
66 goto end;
67 }
68
69 mscorlib_path = WtoA(This->version->mscorlib_path);
70 if (!mscorlib_path)
71 {
72 HeapFree(GetProcessHeap(), 0, entry);
73 res = E_OUTOFMEMORY;
74 goto end;
75 }
76
77 entry->domain = This->mono->mono_jit_init(mscorlib_path);
78
79 HeapFree(GetProcessHeap(), 0, mscorlib_path);
80
81 if (!entry->domain)
82 {
83 HeapFree(GetProcessHeap(), 0, entry);
84 res = E_FAIL;
85 goto end;
86 }
87
88 This->mono->is_started = TRUE;
89
90 list_add_tail(&This->domains, &entry->entry);
91
92 *result = entry->domain;
93
94 end:
95 LeaveCriticalSection(&This->lock);
96
97 return res;
98 }
99
100 static HRESULT RuntimeHost_GetDefaultDomain(RuntimeHost *This, MonoDomain **result)
101 {
102 HRESULT res=S_OK;
103
104 EnterCriticalSection(&This->lock);
105
106 if (This->default_domain) goto end;
107
108 res = RuntimeHost_AddDomain(This, &This->default_domain);
109
110 end:
111 *result = This->default_domain;
112
113 LeaveCriticalSection(&This->lock);
114
115 return res;
116 }
117
118 static void RuntimeHost_DeleteDomain(RuntimeHost *This, MonoDomain *domain)
119 {
120 struct DomainEntry *entry;
121
122 EnterCriticalSection(&This->lock);
123
124 LIST_FOR_EACH_ENTRY(entry, &This->domains, struct DomainEntry, entry)
125 {
126 if (entry->domain == domain)
127 {
128 list_remove(&entry->entry);
129 if (This->default_domain == domain)
130 This->default_domain = NULL;
131 HeapFree(GetProcessHeap(), 0, entry);
132 break;
133 }
134 }
135
136 LeaveCriticalSection(&This->lock);
137 }
138
139 static HRESULT RuntimeHost_GetIUnknownForDomain(RuntimeHost *This, MonoDomain *domain, IUnknown **punk)
140 {
141 HRESULT hr;
142 void *args[1];
143 MonoAssembly *assembly;
144 MonoImage *image;
145 MonoClass *klass;
146 MonoMethod *method;
147 MonoObject *appdomain_object;
148 IUnknown *unk;
149
150 assembly = This->mono->mono_domain_assembly_open(domain, "mscorlib");
151 if (!assembly)
152 {
153 ERR("Cannot load mscorlib\n");
154 return E_FAIL;
155 }
156
157 image = This->mono->mono_assembly_get_image(assembly);
158 if (!image)
159 {
160 ERR("Couldn't get assembly image\n");
161 return E_FAIL;
162 }
163
164 klass = This->mono->mono_class_from_name(image, "System", "AppDomain");
165 if (!klass)
166 {
167 ERR("Couldn't get class from image\n");
168 return E_FAIL;
169 }
170
171 method = This->mono->mono_class_get_method_from_name(klass, "get_CurrentDomain", 0);
172 if (!method)
173 {
174 ERR("Couldn't get method from class\n");
175 return E_FAIL;
176 }
177
178 args[0] = NULL;
179 appdomain_object = This->mono->mono_runtime_invoke(method, NULL, args, NULL);
180 if (!appdomain_object)
181 {
182 ERR("Couldn't get result pointer\n");
183 return E_FAIL;
184 }
185
186 hr = RuntimeHost_GetIUnknownForObject(This, appdomain_object, &unk);
187
188 if (SUCCEEDED(hr))
189 {
190 hr = IUnknown_QueryInterface(unk, &IID__AppDomain, (void**)punk);
191
192 IUnknown_Release(unk);
193 }
194
195 return hr;
196 }
197
198 static inline RuntimeHost *impl_from_ICLRRuntimeHost( ICLRRuntimeHost *iface )
199 {
200 return CONTAINING_RECORD(iface, RuntimeHost, ICLRRuntimeHost_iface);
201 }
202
203 static inline RuntimeHost *impl_from_ICorRuntimeHost( ICorRuntimeHost *iface )
204 {
205 return CONTAINING_RECORD(iface, RuntimeHost, ICorRuntimeHost_iface);
206 }
207
208 /*** IUnknown methods ***/
209 static HRESULT WINAPI corruntimehost_QueryInterface(ICorRuntimeHost* iface,
210 REFIID riid,
211 void **ppvObject)
212 {
213 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
214 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
215
216 if ( IsEqualGUID( riid, &IID_ICorRuntimeHost ) ||
217 IsEqualGUID( riid, &IID_IUnknown ) )
218 {
219 *ppvObject = iface;
220 }
221 else
222 {
223 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
224 return E_NOINTERFACE;
225 }
226
227 ICorRuntimeHost_AddRef( iface );
228
229 return S_OK;
230 }
231
232 static ULONG WINAPI corruntimehost_AddRef(ICorRuntimeHost* iface)
233 {
234 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
235
236 return InterlockedIncrement( &This->ref );
237 }
238
239 static ULONG WINAPI corruntimehost_Release(ICorRuntimeHost* iface)
240 {
241 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
242 ULONG ref;
243
244 ref = InterlockedDecrement( &This->ref );
245
246 return ref;
247 }
248
249 /*** ICorRuntimeHost methods ***/
250 static HRESULT WINAPI corruntimehost_CreateLogicalThreadState(
251 ICorRuntimeHost* iface)
252 {
253 FIXME("stub %p\n", iface);
254 return E_NOTIMPL;
255 }
256
257 static HRESULT WINAPI corruntimehost_DeleteLogicalThreadState(
258 ICorRuntimeHost* iface)
259 {
260 FIXME("stub %p\n", iface);
261 return E_NOTIMPL;
262 }
263
264 static HRESULT WINAPI corruntimehost_SwitchInLogicalThreadState(
265 ICorRuntimeHost* iface,
266 DWORD *fiberCookie)
267 {
268 FIXME("stub %p\n", iface);
269 return E_NOTIMPL;
270 }
271
272 static HRESULT WINAPI corruntimehost_SwitchOutLogicalThreadState(
273 ICorRuntimeHost* iface,
274 DWORD **fiberCookie)
275 {
276 FIXME("stub %p\n", iface);
277 return E_NOTIMPL;
278 }
279
280 static HRESULT WINAPI corruntimehost_LocksHeldByLogicalThread(
281 ICorRuntimeHost* iface,
282 DWORD *pCount)
283 {
284 FIXME("stub %p\n", iface);
285 return E_NOTIMPL;
286 }
287
288 static HRESULT WINAPI corruntimehost_MapFile(
289 ICorRuntimeHost* iface,
290 HANDLE hFile,
291 HMODULE *mapAddress)
292 {
293 FIXME("stub %p\n", iface);
294 return E_NOTIMPL;
295 }
296
297 static HRESULT WINAPI corruntimehost_GetConfiguration(
298 ICorRuntimeHost* iface,
299 ICorConfiguration **pConfiguration)
300 {
301 FIXME("stub %p\n", iface);
302 return E_NOTIMPL;
303 }
304
305 static HRESULT WINAPI corruntimehost_Start(
306 ICorRuntimeHost* iface)
307 {
308 FIXME("stub %p\n", iface);
309 return S_OK;
310 }
311
312 static HRESULT WINAPI corruntimehost_Stop(
313 ICorRuntimeHost* iface)
314 {
315 FIXME("stub %p\n", iface);
316 return E_NOTIMPL;
317 }
318
319 static HRESULT WINAPI corruntimehost_CreateDomain(
320 ICorRuntimeHost* iface,
321 LPCWSTR friendlyName,
322 IUnknown *identityArray,
323 IUnknown **appDomain)
324 {
325 FIXME("stub %p\n", iface);
326 return E_NOTIMPL;
327 }
328
329 static HRESULT WINAPI corruntimehost_GetDefaultDomain(
330 ICorRuntimeHost* iface,
331 IUnknown **pAppDomain)
332 {
333 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
334 HRESULT hr;
335 MonoDomain *domain;
336
337 TRACE("(%p)\n", iface);
338
339 hr = RuntimeHost_GetDefaultDomain(This, &domain);
340
341 if (SUCCEEDED(hr))
342 {
343 hr = RuntimeHost_GetIUnknownForDomain(This, domain, pAppDomain);
344 }
345
346 return hr;
347 }
348
349 static HRESULT WINAPI corruntimehost_EnumDomains(
350 ICorRuntimeHost* iface,
351 HDOMAINENUM *hEnum)
352 {
353 FIXME("stub %p\n", iface);
354 return E_NOTIMPL;
355 }
356
357 static HRESULT WINAPI corruntimehost_NextDomain(
358 ICorRuntimeHost* iface,
359 HDOMAINENUM hEnum,
360 IUnknown **appDomain)
361 {
362 FIXME("stub %p\n", iface);
363 return E_NOTIMPL;
364 }
365
366 static HRESULT WINAPI corruntimehost_CloseEnum(
367 ICorRuntimeHost* iface,
368 HDOMAINENUM hEnum)
369 {
370 FIXME("stub %p\n", iface);
371 return E_NOTIMPL;
372 }
373
374 static HRESULT WINAPI corruntimehost_CreateDomainEx(
375 ICorRuntimeHost* iface,
376 LPCWSTR friendlyName,
377 IUnknown *setup,
378 IUnknown *evidence,
379 IUnknown **appDomain)
380 {
381 FIXME("stub %p\n", iface);
382 return E_NOTIMPL;
383 }
384
385 static HRESULT WINAPI corruntimehost_CreateDomainSetup(
386 ICorRuntimeHost* iface,
387 IUnknown **appDomainSetup)
388 {
389 FIXME("stub %p\n", iface);
390 return E_NOTIMPL;
391 }
392
393 static HRESULT WINAPI corruntimehost_CreateEvidence(
394 ICorRuntimeHost* iface,
395 IUnknown **evidence)
396 {
397 FIXME("stub %p\n", iface);
398 return E_NOTIMPL;
399 }
400
401 static HRESULT WINAPI corruntimehost_UnloadDomain(
402 ICorRuntimeHost* iface,
403 IUnknown *appDomain)
404 {
405 FIXME("stub %p\n", iface);
406 return E_NOTIMPL;
407 }
408
409 static HRESULT WINAPI corruntimehost_CurrentDomain(
410 ICorRuntimeHost* iface,
411 IUnknown **appDomain)
412 {
413 FIXME("stub %p\n", iface);
414 return E_NOTIMPL;
415 }
416
417 static const struct ICorRuntimeHostVtbl corruntimehost_vtbl =
418 {
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,
430 corruntimehost_Stop,
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
441 };
442
443 static HRESULT WINAPI CLRRuntimeHost_QueryInterface(ICLRRuntimeHost* iface,
444 REFIID riid,
445 void **ppvObject)
446 {
447 RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
448 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
449
450 if ( IsEqualGUID( riid, &IID_ICLRRuntimeHost ) ||
451 IsEqualGUID( riid, &IID_IUnknown ) )
452 {
453 *ppvObject = iface;
454 }
455 else
456 {
457 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
458 return E_NOINTERFACE;
459 }
460
461 ICLRRuntimeHost_AddRef( iface );
462
463 return S_OK;
464 }
465
466 static ULONG WINAPI CLRRuntimeHost_AddRef(ICLRRuntimeHost* iface)
467 {
468 RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
469 return ICorRuntimeHost_AddRef(&This->ICorRuntimeHost_iface);
470 }
471
472 static ULONG WINAPI CLRRuntimeHost_Release(ICLRRuntimeHost* iface)
473 {
474 RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
475 return ICorRuntimeHost_Release(&This->ICorRuntimeHost_iface);
476 }
477
478 static HRESULT WINAPI CLRRuntimeHost_Start(ICLRRuntimeHost* iface)
479 {
480 FIXME("(%p)\n", iface);
481 return E_NOTIMPL;
482 }
483
484 static HRESULT WINAPI CLRRuntimeHost_Stop(ICLRRuntimeHost* iface)
485 {
486 FIXME("(%p)\n", iface);
487 return E_NOTIMPL;
488 }
489
490 static HRESULT WINAPI CLRRuntimeHost_SetHostControl(ICLRRuntimeHost* iface,
491 IHostControl *pHostControl)
492 {
493 FIXME("(%p,%p)\n", iface, pHostControl);
494 return E_NOTIMPL;
495 }
496
497 static HRESULT WINAPI CLRRuntimeHost_GetCLRControl(ICLRRuntimeHost* iface,
498 ICLRControl **pCLRControl)
499 {
500 FIXME("(%p,%p)\n", iface, pCLRControl);
501 return E_NOTIMPL;
502 }
503
504 static HRESULT WINAPI CLRRuntimeHost_UnloadAppDomain(ICLRRuntimeHost* iface,
505 DWORD dwAppDomainId, BOOL fWaitUntilDone)
506 {
507 FIXME("(%p,%u,%i)\n", iface, dwAppDomainId, fWaitUntilDone);
508 return E_NOTIMPL;
509 }
510
511 static HRESULT WINAPI CLRRuntimeHost_ExecuteInAppDomain(ICLRRuntimeHost* iface,
512 DWORD dwAppDomainId, FExecuteInAppDomainCallback pCallback, void *cookie)
513 {
514 FIXME("(%p,%u,%p,%p)\n", iface, dwAppDomainId, pCallback, cookie);
515 return E_NOTIMPL;
516 }
517
518 static HRESULT WINAPI CLRRuntimeHost_GetCurrentAppDomainId(ICLRRuntimeHost* iface,
519 DWORD *pdwAppDomainId)
520 {
521 FIXME("(%p,%p)\n", iface, pdwAppDomainId);
522 return E_NOTIMPL;
523 }
524
525 static HRESULT WINAPI CLRRuntimeHost_ExecuteApplication(ICLRRuntimeHost* iface,
526 LPCWSTR pwzAppFullName, DWORD dwManifestPaths, LPCWSTR *ppwzManifestPaths,
527 DWORD dwActivationData, LPCWSTR *ppwzActivationData, int *pReturnValue)
528 {
529 FIXME("(%p,%s,%u,%u)\n", iface, debugstr_w(pwzAppFullName), dwManifestPaths, dwActivationData);
530 return E_NOTIMPL;
531 }
532
533 static HRESULT WINAPI CLRRuntimeHost_ExecuteInDefaultAppDomain(ICLRRuntimeHost* iface,
534 LPCWSTR pwzAssemblyPath, LPCWSTR pwzTypeName, LPCWSTR pwzMethodName,
535 LPCWSTR pwzArgument, DWORD *pReturnValue)
536 {
537 RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
538 HRESULT hr;
539 MonoDomain *domain;
540 MonoAssembly *assembly;
541 MonoImage *image;
542 MonoClass *klass;
543 MonoMethod *method;
544 MonoObject *result;
545 MonoString *str;
546 void *args[2];
547 char *filenameA = NULL, *classA = NULL, *methodA = NULL;
548 char *argsA = NULL, *ns;
549
550 TRACE("(%p,%s,%s,%s,%s)\n", iface, debugstr_w(pwzAssemblyPath),
551 debugstr_w(pwzTypeName), debugstr_w(pwzMethodName), debugstr_w(pwzArgument));
552
553 hr = RuntimeHost_GetDefaultDomain(This, &domain);
554 if(hr != S_OK)
555 {
556 ERR("Couldn't get Default Domain\n");
557 return hr;
558 }
559
560 hr = E_FAIL;
561
562 filenameA = WtoA(pwzAssemblyPath);
563 assembly = This->mono->mono_domain_assembly_open(domain, filenameA);
564 if (!assembly)
565 {
566 ERR("Cannot open assembly %s\n", filenameA);
567 goto cleanup;
568 }
569
570 image = This->mono->mono_assembly_get_image(assembly);
571 if (!image)
572 {
573 ERR("Couldn't get assembly image\n");
574 goto cleanup;
575 }
576
577 classA = WtoA(pwzTypeName);
578 ns = strrchr(classA, '.');
579 *ns = '\0';
580 klass = This->mono->mono_class_from_name(image, classA, ns+1);
581 if (!klass)
582 {
583 ERR("Couldn't get class from image\n");
584 goto cleanup;
585 }
586
587 methodA = WtoA(pwzMethodName);
588 method = This->mono->mono_class_get_method_from_name(klass, methodA, 1);
589 if (!method)
590 {
591 ERR("Couldn't get method from class\n");
592 goto cleanup;
593 }
594
595 /* The .NET function we are calling has the following declaration
596 * public static int functionName(String param)
597 */
598 argsA = WtoA(pwzArgument);
599 str = This->mono->mono_string_new(domain, argsA);
600 args[0] = str;
601 args[1] = NULL;
602 result = This->mono->mono_runtime_invoke(method, NULL, args, NULL);
603 if (!result)
604 ERR("Couldn't get result pointer\n");
605 else
606 {
607 *pReturnValue = *(DWORD*)This->mono->mono_object_unbox(result);
608 hr = S_OK;
609 }
610
611 cleanup:
612 if(filenameA)
613 HeapFree(GetProcessHeap(), 0, filenameA);
614 if(classA)
615 HeapFree(GetProcessHeap(), 0, classA);
616 if(argsA)
617 HeapFree(GetProcessHeap(), 0, argsA);
618 if(methodA)
619 HeapFree(GetProcessHeap(), 0, methodA);
620
621 return hr;
622 }
623
624 static const struct ICLRRuntimeHostVtbl CLRHostVtbl =
625 {
626 CLRRuntimeHost_QueryInterface,
627 CLRRuntimeHost_AddRef,
628 CLRRuntimeHost_Release,
629 CLRRuntimeHost_Start,
630 CLRRuntimeHost_Stop,
631 CLRRuntimeHost_SetHostControl,
632 CLRRuntimeHost_GetCLRControl,
633 CLRRuntimeHost_UnloadAppDomain,
634 CLRRuntimeHost_ExecuteInAppDomain,
635 CLRRuntimeHost_GetCurrentAppDomainId,
636 CLRRuntimeHost_ExecuteApplication,
637 CLRRuntimeHost_ExecuteInDefaultAppDomain
638 };
639
640 /* Create an instance of a type given its name, by calling its constructor with
641 * no arguments. Note that result MUST be in the stack, or the garbage
642 * collector may free it prematurely. */
643 HRESULT RuntimeHost_CreateManagedInstance(RuntimeHost *This, LPCWSTR name,
644 MonoDomain *domain, MonoObject **result)
645 {
646 HRESULT hr=S_OK;
647 char *nameA=NULL;
648 MonoType *type;
649 MonoClass *klass;
650 MonoObject *obj;
651
652 if (!domain)
653 hr = RuntimeHost_GetDefaultDomain(This, &domain);
654
655 if (SUCCEEDED(hr))
656 {
657 nameA = WtoA(name);
658 if (!nameA)
659 hr = E_OUTOFMEMORY;
660 }
661
662 if (SUCCEEDED(hr))
663 {
664 type = This->mono->mono_reflection_type_from_name(nameA, NULL);
665 if (!type)
666 {
667 ERR("Cannot find type %s\n", debugstr_w(name));
668 hr = E_FAIL;
669 }
670 }
671
672 if (SUCCEEDED(hr))
673 {
674 klass = This->mono->mono_class_from_mono_type(type);
675 if (!klass)
676 {
677 ERR("Cannot convert type %s to a class\n", debugstr_w(name));
678 hr = E_FAIL;
679 }
680 }
681
682 if (SUCCEEDED(hr))
683 {
684 obj = This->mono->mono_object_new(domain, klass);
685 if (!obj)
686 {
687 ERR("Cannot allocate object of type %s\n", debugstr_w(name));
688 hr = E_FAIL;
689 }
690 }
691
692 if (SUCCEEDED(hr))
693 {
694 /* FIXME: Detect exceptions from the constructor? */
695 This->mono->mono_runtime_object_init(obj);
696 *result = obj;
697 }
698
699 HeapFree(GetProcessHeap(), 0, nameA);
700
701 return hr;
702 }
703
704 /* Get an IUnknown pointer for a Mono object.
705 *
706 * This is just a "light" wrapper around
707 * System.Runtime.InteropServices.Marshal:GetIUnknownForObject
708 *
709 * NOTE: The IUnknown* is created with a reference to the object.
710 * Until they have a reference, objects must be in the stack to prevent the
711 * garbage collector from freeing them. */
712 HRESULT RuntimeHost_GetIUnknownForObject(RuntimeHost *This, MonoObject *obj,
713 IUnknown **ppUnk)
714 {
715 MonoDomain *domain;
716 MonoAssembly *assembly;
717 MonoImage *image;
718 MonoClass *klass;
719 MonoMethod *method;
720 MonoObject *result;
721 void *args[2];
722
723 domain = This->mono->mono_object_get_domain(obj);
724
725 assembly = This->mono->mono_domain_assembly_open(domain, "mscorlib");
726 if (!assembly)
727 {
728 ERR("Cannot load mscorlib\n");
729 return E_FAIL;
730 }
731
732 image = This->mono->mono_assembly_get_image(assembly);
733 if (!image)
734 {
735 ERR("Couldn't get assembly image\n");
736 return E_FAIL;
737 }
738
739 klass = This->mono->mono_class_from_name(image, "System.Runtime.InteropServices", "Marshal");
740 if (!klass)
741 {
742 ERR("Couldn't get class from image\n");
743 return E_FAIL;
744 }
745
746 method = This->mono->mono_class_get_method_from_name(klass, "GetIUnknownForObject", 1);
747 if (!method)
748 {
749 ERR("Couldn't get method from class\n");
750 return E_FAIL;
751 }
752
753 args[0] = obj;
754 args[1] = NULL;
755 result = This->mono->mono_runtime_invoke(method, NULL, args, NULL);
756 if (!result)
757 {
758 ERR("Couldn't get result pointer\n");
759 return E_FAIL;
760 }
761
762 *ppUnk = *(IUnknown**)This->mono->mono_object_unbox(result);
763 if (!*ppUnk)
764 {
765 ERR("GetIUnknownForObject returned 0\n");
766 return E_FAIL;
767 }
768
769 return S_OK;
770 }
771
772 static void get_utf8_args(int *argc, char ***argv)
773 {
774 WCHAR **argvw;
775 int size=0, i;
776 char *current_arg;
777
778 argvw = CommandLineToArgvW(GetCommandLineW(), argc);
779
780 for (i=0; i<*argc; i++)
781 {
782 size += sizeof(char*);
783 size += WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, NULL, 0, NULL, NULL);
784 }
785 size += sizeof(char*);
786
787 *argv = HeapAlloc(GetProcessHeap(), 0, size);
788 current_arg = (char*)(*argv + *argc + 1);
789
790 for (i=0; i<*argc; i++)
791 {
792 (*argv)[i] = current_arg;
793 current_arg += WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, current_arg, size, NULL, NULL);
794 }
795
796 (*argv)[*argc] = NULL;
797
798 HeapFree(GetProcessHeap(), 0, argvw);
799 }
800
801 __int32 WINAPI _CorExeMain(void)
802 {
803 int exit_code;
804 int argc;
805 char **argv;
806 MonoDomain *domain;
807 MonoAssembly *assembly;
808 WCHAR filename[MAX_PATH];
809 char *filenameA;
810 ICLRRuntimeInfo *info;
811 RuntimeHost *host;
812 HRESULT hr;
813 int i;
814
815 get_utf8_args(&argc, &argv);
816
817 GetModuleFileNameW(NULL, filename, MAX_PATH);
818
819 TRACE("%s", debugstr_w(filename));
820 for (i=0; i<argc; i++)
821 TRACE(" %s", debugstr_a(argv[i]));
822 TRACE("\n");
823
824 filenameA = WtoA(filename);
825 if (!filenameA)
826 return -1;
827
828 hr = get_runtime_info(filename, NULL, NULL, 0, 0, FALSE, &info);
829
830 if (SUCCEEDED(hr))
831 {
832 hr = ICLRRuntimeInfo_GetRuntimeHost(info, &host);
833
834 if (SUCCEEDED(hr))
835 hr = RuntimeHost_GetDefaultDomain(host, &domain);
836
837 if (SUCCEEDED(hr))
838 {
839 assembly = host->mono->mono_domain_assembly_open(domain, filenameA);
840
841 exit_code = host->mono->mono_jit_exec(domain, assembly, argc, argv);
842
843 RuntimeHost_DeleteDomain(host, domain);
844 }
845 else
846 exit_code = -1;
847
848 ICLRRuntimeInfo_Release(info);
849 }
850 else
851 exit_code = -1;
852
853 HeapFree(GetProcessHeap(), 0, argv);
854
855 unload_all_runtimes();
856
857 return exit_code;
858 }
859
860 HRESULT RuntimeHost_Construct(const CLRRuntimeInfo *runtime_version,
861 loaded_mono *loaded_mono, RuntimeHost** result)
862 {
863 RuntimeHost *This;
864
865 This = HeapAlloc( GetProcessHeap(), 0, sizeof *This );
866 if ( !This )
867 return E_OUTOFMEMORY;
868
869 This->ICorRuntimeHost_iface.lpVtbl = &corruntimehost_vtbl;
870 This->ICLRRuntimeHost_iface.lpVtbl = &CLRHostVtbl;
871
872 This->ref = 1;
873 This->version = runtime_version;
874 This->mono = loaded_mono;
875 list_init(&This->domains);
876 This->default_domain = NULL;
877 InitializeCriticalSection(&This->lock);
878 This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": RuntimeHost.lock");
879
880 *result = This;
881
882 return S_OK;
883 }
884
885 HRESULT RuntimeHost_GetInterface(RuntimeHost *This, REFCLSID clsid, REFIID riid, void **ppv)
886 {
887 IUnknown *unk;
888 HRESULT hr;
889
890 if (IsEqualGUID(clsid, &CLSID_CorRuntimeHost))
891 {
892 unk = (IUnknown*)&This->ICorRuntimeHost_iface;
893 IUnknown_AddRef(unk);
894 }
895 else if (IsEqualGUID(clsid, &CLSID_CLRRuntimeHost))
896 {
897 unk = (IUnknown*)&This->ICLRRuntimeHost_iface;
898 IUnknown_AddRef(unk);
899 }
900 else if (IsEqualGUID(clsid, &CLSID_CorMetaDataDispenser) ||
901 IsEqualGUID(clsid, &CLSID_CorMetaDataDispenserRuntime))
902 {
903 hr = MetaDataDispenser_CreateInstance(&unk);
904 if (FAILED(hr))
905 return hr;
906 }
907 else if (IsEqualGUID(clsid, &CLSID_CLRDebuggingLegacy))
908 {
909 hr = CorDebug_Create(&This->ICLRRuntimeHost_iface, &unk);
910 if (FAILED(hr))
911 return hr;
912 }
913 else
914 unk = NULL;
915
916 if (unk)
917 {
918 hr = IUnknown_QueryInterface(unk, riid, ppv);
919
920 IUnknown_Release(unk);
921
922 return hr;
923 }
924 else
925 FIXME("not implemented for class %s\n", debugstr_guid(clsid));
926
927 return CLASS_E_CLASSNOTAVAILABLE;
928 }
929
930 HRESULT RuntimeHost_Destroy(RuntimeHost *This)
931 {
932 struct DomainEntry *cursor, *cursor2;
933
934 This->lock.DebugInfo->Spare[0] = 0;
935 DeleteCriticalSection(&This->lock);
936
937 LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->domains, struct DomainEntry, entry)
938 {
939 list_remove(&cursor->entry);
940 HeapFree(GetProcessHeap(), 0, cursor);
941 }
942
943 HeapFree( GetProcessHeap(), 0, This );
944 return S_OK;
945 }