ddraw/tests: Add a small test for redundant mode setting calls.
[wine/multimedia.git] / dlls / mscoree / corruntimehost.c
blobbcdd485444052a55eddc19c054705cd63862f504
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 "wine/list.h"
36 #include "mscoree_private.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
42 struct RuntimeHost
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;
54 struct DomainEntry
56 struct list entry;
57 MonoDomain *domain;
60 static HRESULT RuntimeHost_AddDomain(RuntimeHost *This, MonoDomain **result)
62 struct DomainEntry *entry;
63 char *mscorlib_path;
64 HRESULT res=S_OK;
66 EnterCriticalSection(&This->lock);
68 entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry));
69 if (!entry)
71 res = E_OUTOFMEMORY;
72 goto end;
75 mscorlib_path = WtoA(This->version->mscorlib_path);
76 if (!mscorlib_path)
78 HeapFree(GetProcessHeap(), 0, entry);
79 res = E_OUTOFMEMORY;
80 goto end;
83 entry->domain = This->mono->mono_jit_init(mscorlib_path);
85 HeapFree(GetProcessHeap(), 0, mscorlib_path);
87 if (!entry->domain)
89 HeapFree(GetProcessHeap(), 0, entry);
90 res = E_FAIL;
91 goto end;
94 This->mono->is_started = TRUE;
96 list_add_tail(&This->domains, &entry->entry);
98 *result = entry->domain;
100 end:
101 LeaveCriticalSection(&This->lock);
103 return res;
106 static HRESULT RuntimeHost_GetDefaultDomain(RuntimeHost *This, MonoDomain **result)
108 HRESULT res=S_OK;
110 EnterCriticalSection(&This->lock);
112 if (This->default_domain) goto end;
114 res = RuntimeHost_AddDomain(This, &This->default_domain);
116 end:
117 *result = This->default_domain;
119 LeaveCriticalSection(&This->lock);
121 return res;
124 static void RuntimeHost_DeleteDomain(RuntimeHost *This, MonoDomain *domain)
126 struct DomainEntry *entry;
128 EnterCriticalSection(&This->lock);
130 LIST_FOR_EACH_ENTRY(entry, &This->domains, struct DomainEntry, entry)
132 if (entry->domain == domain)
134 list_remove(&entry->entry);
135 if (This->default_domain == domain)
136 This->default_domain = NULL;
137 HeapFree(GetProcessHeap(), 0, entry);
138 break;
142 LeaveCriticalSection(&This->lock);
145 static inline RuntimeHost *impl_from_ICLRRuntimeHost( ICLRRuntimeHost *iface )
147 return (RuntimeHost *)((char*)iface - FIELD_OFFSET(RuntimeHost, lpCLRHostVtbl));
150 static inline RuntimeHost *impl_from_ICorRuntimeHost( ICorRuntimeHost *iface )
152 return (RuntimeHost *)((char*)iface - FIELD_OFFSET(RuntimeHost, lpVtbl));
155 /*** IUnknown methods ***/
156 static HRESULT WINAPI corruntimehost_QueryInterface(ICorRuntimeHost* iface,
157 REFIID riid,
158 void **ppvObject)
160 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
161 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
163 if ( IsEqualGUID( riid, &IID_ICorRuntimeHost ) ||
164 IsEqualGUID( riid, &IID_IUnknown ) )
166 *ppvObject = iface;
168 else
170 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
171 return E_NOINTERFACE;
174 ICorRuntimeHost_AddRef( iface );
176 return S_OK;
179 static ULONG WINAPI corruntimehost_AddRef(ICorRuntimeHost* iface)
181 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
183 return InterlockedIncrement( &This->ref );
186 static ULONG WINAPI corruntimehost_Release(ICorRuntimeHost* iface)
188 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
189 ULONG ref;
191 ref = InterlockedDecrement( &This->ref );
193 return ref;
196 /*** ICorRuntimeHost methods ***/
197 static HRESULT WINAPI corruntimehost_CreateLogicalThreadState(
198 ICorRuntimeHost* iface)
200 FIXME("stub %p\n", iface);
201 return E_NOTIMPL;
204 static HRESULT WINAPI corruntimehost_DeleteLogicalThreadState(
205 ICorRuntimeHost* iface)
207 FIXME("stub %p\n", iface);
208 return E_NOTIMPL;
211 static HRESULT WINAPI corruntimehost_SwitchInLogicalThreadState(
212 ICorRuntimeHost* iface,
213 DWORD *fiberCookie)
215 FIXME("stub %p\n", iface);
216 return E_NOTIMPL;
219 static HRESULT WINAPI corruntimehost_SwitchOutLogicalThreadState(
220 ICorRuntimeHost* iface,
221 DWORD **fiberCookie)
223 FIXME("stub %p\n", iface);
224 return E_NOTIMPL;
227 static HRESULT WINAPI corruntimehost_LocksHeldByLogicalThread(
228 ICorRuntimeHost* iface,
229 DWORD *pCount)
231 FIXME("stub %p\n", iface);
232 return E_NOTIMPL;
235 static HRESULT WINAPI corruntimehost_MapFile(
236 ICorRuntimeHost* iface,
237 HANDLE hFile,
238 HMODULE *mapAddress)
240 FIXME("stub %p\n", iface);
241 return E_NOTIMPL;
244 static HRESULT WINAPI corruntimehost_GetConfiguration(
245 ICorRuntimeHost* iface,
246 ICorConfiguration **pConfiguration)
248 FIXME("stub %p\n", iface);
249 return E_NOTIMPL;
252 static HRESULT WINAPI corruntimehost_Start(
253 ICorRuntimeHost* iface)
255 FIXME("stub %p\n", iface);
256 return E_NOTIMPL;
259 static HRESULT WINAPI corruntimehost_Stop(
260 ICorRuntimeHost* iface)
262 FIXME("stub %p\n", iface);
263 return E_NOTIMPL;
266 static HRESULT WINAPI corruntimehost_CreateDomain(
267 ICorRuntimeHost* iface,
268 LPCWSTR friendlyName,
269 IUnknown *identityArray,
270 IUnknown **appDomain)
272 FIXME("stub %p\n", iface);
273 return E_NOTIMPL;
276 static HRESULT WINAPI corruntimehost_GetDefaultDomain(
277 ICorRuntimeHost* iface,
278 IUnknown **pAppDomain)
280 FIXME("stub %p\n", iface);
281 return E_NOTIMPL;
284 static HRESULT WINAPI corruntimehost_EnumDomains(
285 ICorRuntimeHost* iface,
286 HDOMAINENUM *hEnum)
288 FIXME("stub %p\n", iface);
289 return E_NOTIMPL;
292 static HRESULT WINAPI corruntimehost_NextDomain(
293 ICorRuntimeHost* iface,
294 HDOMAINENUM hEnum,
295 IUnknown **appDomain)
297 FIXME("stub %p\n", iface);
298 return E_NOTIMPL;
301 static HRESULT WINAPI corruntimehost_CloseEnum(
302 ICorRuntimeHost* iface,
303 HDOMAINENUM hEnum)
305 FIXME("stub %p\n", iface);
306 return E_NOTIMPL;
309 static HRESULT WINAPI corruntimehost_CreateDomainEx(
310 ICorRuntimeHost* iface,
311 LPCWSTR friendlyName,
312 IUnknown *setup,
313 IUnknown *evidence,
314 IUnknown **appDomain)
316 FIXME("stub %p\n", iface);
317 return E_NOTIMPL;
320 static HRESULT WINAPI corruntimehost_CreateDomainSetup(
321 ICorRuntimeHost* iface,
322 IUnknown **appDomainSetup)
324 FIXME("stub %p\n", iface);
325 return E_NOTIMPL;
328 static HRESULT WINAPI corruntimehost_CreateEvidence(
329 ICorRuntimeHost* iface,
330 IUnknown **evidence)
332 FIXME("stub %p\n", iface);
333 return E_NOTIMPL;
336 static HRESULT WINAPI corruntimehost_UnloadDomain(
337 ICorRuntimeHost* iface,
338 IUnknown *appDomain)
340 FIXME("stub %p\n", iface);
341 return E_NOTIMPL;
344 static HRESULT WINAPI corruntimehost_CurrentDomain(
345 ICorRuntimeHost* iface,
346 IUnknown **appDomain)
348 FIXME("stub %p\n", iface);
349 return E_NOTIMPL;
352 static const struct ICorRuntimeHostVtbl corruntimehost_vtbl =
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
378 static HRESULT WINAPI CLRRuntimeHost_QueryInterface(ICLRRuntimeHost* iface,
379 REFIID riid,
380 void **ppvObject)
382 RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
383 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
385 if ( IsEqualGUID( riid, &IID_ICLRRuntimeHost ) ||
386 IsEqualGUID( riid, &IID_IUnknown ) )
388 *ppvObject = iface;
390 else
392 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
393 return E_NOINTERFACE;
396 ICLRRuntimeHost_AddRef( iface );
398 return S_OK;
401 static ULONG WINAPI CLRRuntimeHost_AddRef(ICLRRuntimeHost* iface)
403 RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
404 return IUnknown_AddRef((IUnknown*)&This->lpVtbl);
407 static ULONG WINAPI CLRRuntimeHost_Release(ICLRRuntimeHost* iface)
409 RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
410 return IUnknown_Release((IUnknown*)&This->lpVtbl);
413 static HRESULT WINAPI CLRRuntimeHost_Start(ICLRRuntimeHost* iface)
415 FIXME("(%p)\n", iface);
416 return E_NOTIMPL;
419 static HRESULT WINAPI CLRRuntimeHost_Stop(ICLRRuntimeHost* iface)
421 FIXME("(%p)\n", iface);
422 return E_NOTIMPL;
425 static HRESULT WINAPI CLRRuntimeHost_SetHostControl(ICLRRuntimeHost* iface,
426 IHostControl *pHostControl)
428 FIXME("(%p,%p)\n", iface, pHostControl);
429 return E_NOTIMPL;
432 static HRESULT WINAPI CLRRuntimeHost_GetCLRControl(ICLRRuntimeHost* iface,
433 ICLRControl **pCLRControl)
435 FIXME("(%p,%p)\n", iface, pCLRControl);
436 return E_NOTIMPL;
439 static HRESULT WINAPI CLRRuntimeHost_UnloadAppDomain(ICLRRuntimeHost* iface,
440 DWORD dwAppDomainId, BOOL fWaitUntilDone)
442 FIXME("(%p,%u,%i)\n", iface, dwAppDomainId, fWaitUntilDone);
443 return E_NOTIMPL;
446 static HRESULT WINAPI CLRRuntimeHost_ExecuteInAppDomain(ICLRRuntimeHost* iface,
447 DWORD dwAppDomainId, FExecuteInAppDomainCallback pCallback, void *cookie)
449 FIXME("(%p,%u,%p,%p)\n", iface, dwAppDomainId, pCallback, cookie);
450 return E_NOTIMPL;
453 static HRESULT WINAPI CLRRuntimeHost_GetCurrentAppDomainId(ICLRRuntimeHost* iface,
454 DWORD *pdwAppDomainId)
456 FIXME("(%p,%p)\n", iface, pdwAppDomainId);
457 return E_NOTIMPL;
460 static HRESULT WINAPI CLRRuntimeHost_ExecuteApplication(ICLRRuntimeHost* iface,
461 LPCWSTR pwzAppFullName, DWORD dwManifestPaths, LPCWSTR *ppwzManifestPaths,
462 DWORD dwActivationData, LPCWSTR *ppwzActivationData, int *pReturnValue)
464 FIXME("(%p,%s,%u,%u)\n", iface, debugstr_w(pwzAppFullName), dwManifestPaths, dwActivationData);
465 return E_NOTIMPL;
468 static HRESULT WINAPI CLRRuntimeHost_ExecuteInDefaultAppDomain(ICLRRuntimeHost* iface,
469 LPCWSTR pwzAssemblyPath, LPCWSTR pwzTypeName, LPCWSTR pwzMethodName,
470 LPCWSTR pwzArgument, DWORD *pReturnValue)
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;
477 static const struct ICLRRuntimeHostVtbl CLRHostVtbl =
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
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)
499 HRESULT hr=S_OK;
500 char *nameA=NULL;
501 MonoType *type;
502 MonoClass *klass;
503 MonoObject *obj;
505 if (!domain)
506 hr = RuntimeHost_GetDefaultDomain(This, &domain);
508 if (SUCCEEDED(hr))
510 nameA = WtoA(name);
511 if (!nameA)
512 hr = E_OUTOFMEMORY;
515 if (SUCCEEDED(hr))
517 type = This->mono->mono_reflection_type_from_name(nameA, NULL);
518 if (!type)
520 ERR("Cannot find type %s\n", debugstr_w(name));
521 hr = E_FAIL;
525 if (SUCCEEDED(hr))
527 klass = This->mono->mono_class_from_mono_type(type);
528 if (!klass)
530 ERR("Cannot convert type %s to a class\n", debugstr_w(name));
531 hr = E_FAIL;
535 if (SUCCEEDED(hr))
537 obj = This->mono->mono_object_new(domain, klass);
538 if (!obj)
540 ERR("Cannot allocate object of type %s\n", debugstr_w(name));
541 hr = E_FAIL;
545 if (SUCCEEDED(hr))
547 /* FIXME: Detect exceptions from the constructor? */
548 This->mono->mono_runtime_object_init(obj);
549 *result = obj;
552 HeapFree(GetProcessHeap(), 0, nameA);
554 return hr;
557 /* Get an IUnknown pointer for a Mono object.
559 * This is just a "light" wrapper around
560 * System.Runtime.InteropServices.Marshal:GetIUnknownForObject
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)
568 MonoDomain *domain;
569 MonoAssembly *assembly;
570 MonoImage *image;
571 MonoClass *klass;
572 MonoMethod *method;
573 MonoObject *result;
574 void *args[2];
576 domain = This->mono->mono_object_get_domain(obj);
578 assembly = This->mono->mono_domain_assembly_open(domain, "mscorlib");
579 if (!assembly)
581 ERR("Cannot load mscorlib\n");
582 return E_FAIL;
585 image = This->mono->mono_assembly_get_image(assembly);
586 if (!image)
588 ERR("Couldn't get assembly image\n");
589 return E_FAIL;
592 klass = This->mono->mono_class_from_name(image, "System.Runtime.InteropServices", "Marshal");
593 if (!klass)
595 ERR("Couldn't get class from image\n");
596 return E_FAIL;
599 method = This->mono->mono_class_get_method_from_name(klass, "GetIUnknownForObject", 1);
600 if (!method)
602 ERR("Couldn't get method from class\n");
603 return E_FAIL;
606 args[0] = obj;
607 args[1] = NULL;
608 result = This->mono->mono_runtime_invoke(method, NULL, args, NULL);
609 if (!result)
611 ERR("Couldn't get result pointer\n");
612 return E_FAIL;
615 *ppUnk = *(IUnknown**)This->mono->mono_object_unbox(result);
616 if (!*ppUnk)
618 ERR("GetIUnknownForObject returned 0\n");
619 return E_FAIL;
622 return S_OK;
625 static void get_utf8_args(int *argc, char ***argv)
627 WCHAR **argvw;
628 int size=0, i;
629 char *current_arg;
631 argvw = CommandLineToArgvW(GetCommandLineW(), argc);
633 for (i=0; i<*argc; i++)
635 size += sizeof(char*);
636 size += WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, NULL, 0, NULL, NULL);
638 size += sizeof(char*);
640 *argv = HeapAlloc(GetProcessHeap(), 0, size);
641 current_arg = (char*)(*argv + *argc + 1);
643 for (i=0; i<*argc; i++)
645 (*argv)[i] = current_arg;
646 current_arg += WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, current_arg, size, NULL, NULL);
649 (*argv)[*argc] = NULL;
651 HeapFree(GetProcessHeap(), 0, argvw);
654 __int32 WINAPI _CorExeMain(void)
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;
668 get_utf8_args(&argc, &argv);
670 GetModuleFileNameW(NULL, filename, MAX_PATH);
672 TRACE("%s", debugstr_w(filename));
673 for (i=0; i<argc; i++)
674 TRACE(" %s", debugstr_a(argv[i]));
675 TRACE("\n");
677 filenameA = WtoA(filename);
678 if (!filenameA)
679 return -1;
681 hr = get_runtime_info(filename, NULL, NULL, 0, 0, FALSE, &info);
683 if (SUCCEEDED(hr))
685 hr = ICLRRuntimeInfo_GetRuntimeHost(info, &host);
687 if (SUCCEEDED(hr))
688 hr = RuntimeHost_GetDefaultDomain(host, &domain);
690 if (SUCCEEDED(hr))
692 assembly = host->mono->mono_domain_assembly_open(domain, filenameA);
694 exit_code = host->mono->mono_jit_exec(domain, assembly, argc, argv);
696 RuntimeHost_DeleteDomain(host, domain);
698 else
699 exit_code = -1;
701 ICLRRuntimeInfo_Release(info);
703 else
704 exit_code = -1;
706 HeapFree(GetProcessHeap(), 0, argv);
708 unload_all_runtimes();
710 return exit_code;
713 HRESULT RuntimeHost_Construct(const CLRRuntimeInfo *runtime_version,
714 loaded_mono *loaded_mono, RuntimeHost** result)
716 RuntimeHost *This;
718 This = HeapAlloc( GetProcessHeap(), 0, sizeof *This );
719 if ( !This )
720 return E_OUTOFMEMORY;
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");
732 *result = This;
734 return S_OK;
737 HRESULT RuntimeHost_GetInterface(RuntimeHost *This, REFCLSID clsid, REFIID riid, void **ppv)
739 IUnknown *unk;
740 HRESULT hr;
742 if (IsEqualGUID(clsid, &CLSID_CorRuntimeHost))
744 unk = (IUnknown*)&This->lpVtbl;
745 IUnknown_AddRef(unk);
747 else if (IsEqualGUID(clsid, &CLSID_CLRRuntimeHost))
749 unk = (IUnknown*)&This->lpCLRHostVtbl;
750 IUnknown_AddRef(unk);
752 else if (IsEqualGUID(clsid, &CLSID_CorMetaDataDispenser) ||
753 IsEqualGUID(clsid, &CLSID_CorMetaDataDispenserRuntime))
755 hr = MetaDataDispenser_CreateInstance(&unk);
756 if (FAILED(hr))
757 return hr;
759 else
760 unk = NULL;
762 if (unk)
764 hr = IUnknown_QueryInterface(unk, riid, ppv);
766 IUnknown_Release(unk);
768 return hr;
770 else
771 FIXME("not implemented for class %s\n", debugstr_guid(clsid));
773 return CLASS_E_CLASSNOTAVAILABLE;
776 HRESULT RuntimeHost_Destroy(RuntimeHost *This)
778 struct DomainEntry *cursor, *cursor2;
780 This->lock.DebugInfo->Spare[0] = 0;
781 DeleteCriticalSection(&This->lock);
783 LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->domains, struct DomainEntry, entry)
785 list_remove(&cursor->entry);
786 HeapFree(GetProcessHeap(), 0, cursor);
789 HeapFree( GetProcessHeap(), 0, This );
790 return S_OK;