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