urlmon: Moved FindMimeFromData to mimefilter.c.
[wine/multimedia.git] / dlls / mscoree / corruntimehost.c
blob76b7d65924928976c8fcff343502e2cefb406295
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 <assert.h>
23 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "winnls.h"
29 #include "winreg.h"
30 #include "ole2.h"
31 #include "shellapi.h"
33 #include "cor.h"
34 #include "mscoree.h"
35 #include "metahost.h"
36 #include "corhdr.h"
37 #include "cordebug.h"
38 #include "wine/list.h"
39 #include "mscoree_private.h"
41 #include "wine/debug.h"
42 #include "wine/unicode.h"
44 WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
46 #include "initguid.h"
48 DEFINE_GUID(IID__AppDomain, 0x05f696dc,0x2b29,0x3663,0xad,0x8b,0xc4,0x38,0x9c,0xf2,0xa7,0x13);
50 struct DomainEntry
52 struct list entry;
53 MonoDomain *domain;
56 static HANDLE dll_fixup_heap; /* using a separate heap so we can have execute permission */
58 static struct list dll_fixups;
60 struct dll_fixup
62 struct list entry;
63 int done;
64 HMODULE dll;
65 void *thunk_code; /* pointer into dll_fixup_heap */
66 VTableFixup *fixup;
67 void *vtable;
68 void *tokens; /* pointer into process heap */
71 static HRESULT RuntimeHost_AddDomain(RuntimeHost *This, MonoDomain **result)
73 struct DomainEntry *entry;
74 char *mscorlib_path;
75 HRESULT res=S_OK;
77 EnterCriticalSection(&This->lock);
79 entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry));
80 if (!entry)
82 res = E_OUTOFMEMORY;
83 goto end;
86 mscorlib_path = WtoA(This->version->mscorlib_path);
87 if (!mscorlib_path)
89 HeapFree(GetProcessHeap(), 0, entry);
90 res = E_OUTOFMEMORY;
91 goto end;
94 entry->domain = This->mono->mono_jit_init(mscorlib_path);
96 HeapFree(GetProcessHeap(), 0, mscorlib_path);
98 if (!entry->domain)
100 HeapFree(GetProcessHeap(), 0, entry);
101 res = E_FAIL;
102 goto end;
105 This->mono->is_started = TRUE;
107 list_add_tail(&This->domains, &entry->entry);
109 *result = entry->domain;
111 end:
112 LeaveCriticalSection(&This->lock);
114 return res;
117 static HRESULT RuntimeHost_GetDefaultDomain(RuntimeHost *This, MonoDomain **result)
119 HRESULT res=S_OK;
121 EnterCriticalSection(&This->lock);
123 if (This->default_domain) goto end;
125 res = RuntimeHost_AddDomain(This, &This->default_domain);
127 end:
128 *result = This->default_domain;
130 LeaveCriticalSection(&This->lock);
132 return res;
135 static void RuntimeHost_DeleteDomain(RuntimeHost *This, MonoDomain *domain)
137 struct DomainEntry *entry;
139 EnterCriticalSection(&This->lock);
141 LIST_FOR_EACH_ENTRY(entry, &This->domains, struct DomainEntry, entry)
143 if (entry->domain == domain)
145 list_remove(&entry->entry);
146 if (This->default_domain == domain)
147 This->default_domain = NULL;
148 HeapFree(GetProcessHeap(), 0, entry);
149 break;
153 LeaveCriticalSection(&This->lock);
156 static HRESULT RuntimeHost_GetIUnknownForDomain(RuntimeHost *This, MonoDomain *domain, IUnknown **punk)
158 HRESULT hr;
159 void *args[1];
160 MonoAssembly *assembly;
161 MonoImage *image;
162 MonoClass *klass;
163 MonoMethod *method;
164 MonoObject *appdomain_object;
165 IUnknown *unk;
167 This->mono->mono_thread_attach(domain);
169 assembly = This->mono->mono_domain_assembly_open(domain, "mscorlib");
170 if (!assembly)
172 ERR("Cannot load mscorlib\n");
173 return E_FAIL;
176 image = This->mono->mono_assembly_get_image(assembly);
177 if (!image)
179 ERR("Couldn't get assembly image\n");
180 return E_FAIL;
183 klass = This->mono->mono_class_from_name(image, "System", "AppDomain");
184 if (!klass)
186 ERR("Couldn't get class from image\n");
187 return E_FAIL;
190 method = This->mono->mono_class_get_method_from_name(klass, "get_CurrentDomain", 0);
191 if (!method)
193 ERR("Couldn't get method from class\n");
194 return E_FAIL;
197 args[0] = NULL;
198 appdomain_object = This->mono->mono_runtime_invoke(method, NULL, args, NULL);
199 if (!appdomain_object)
201 ERR("Couldn't get result pointer\n");
202 return E_FAIL;
205 hr = RuntimeHost_GetIUnknownForObject(This, appdomain_object, &unk);
207 if (SUCCEEDED(hr))
209 hr = IUnknown_QueryInterface(unk, &IID__AppDomain, (void**)punk);
211 IUnknown_Release(unk);
214 return hr;
217 static inline RuntimeHost *impl_from_ICLRRuntimeHost( ICLRRuntimeHost *iface )
219 return CONTAINING_RECORD(iface, RuntimeHost, ICLRRuntimeHost_iface);
222 static inline RuntimeHost *impl_from_ICorRuntimeHost( ICorRuntimeHost *iface )
224 return CONTAINING_RECORD(iface, RuntimeHost, ICorRuntimeHost_iface);
227 /*** IUnknown methods ***/
228 static HRESULT WINAPI corruntimehost_QueryInterface(ICorRuntimeHost* iface,
229 REFIID riid,
230 void **ppvObject)
232 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
233 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
235 if ( IsEqualGUID( riid, &IID_ICorRuntimeHost ) ||
236 IsEqualGUID( riid, &IID_IUnknown ) )
238 *ppvObject = iface;
240 else
242 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
243 return E_NOINTERFACE;
246 ICorRuntimeHost_AddRef( iface );
248 return S_OK;
251 static ULONG WINAPI corruntimehost_AddRef(ICorRuntimeHost* iface)
253 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
255 return InterlockedIncrement( &This->ref );
258 static ULONG WINAPI corruntimehost_Release(ICorRuntimeHost* iface)
260 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
261 ULONG ref;
263 ref = InterlockedDecrement( &This->ref );
265 return ref;
268 /*** ICorRuntimeHost methods ***/
269 static HRESULT WINAPI corruntimehost_CreateLogicalThreadState(
270 ICorRuntimeHost* iface)
272 FIXME("stub %p\n", iface);
273 return E_NOTIMPL;
276 static HRESULT WINAPI corruntimehost_DeleteLogicalThreadState(
277 ICorRuntimeHost* iface)
279 FIXME("stub %p\n", iface);
280 return E_NOTIMPL;
283 static HRESULT WINAPI corruntimehost_SwitchInLogicalThreadState(
284 ICorRuntimeHost* iface,
285 DWORD *fiberCookie)
287 FIXME("stub %p\n", iface);
288 return E_NOTIMPL;
291 static HRESULT WINAPI corruntimehost_SwitchOutLogicalThreadState(
292 ICorRuntimeHost* iface,
293 DWORD **fiberCookie)
295 FIXME("stub %p\n", iface);
296 return E_NOTIMPL;
299 static HRESULT WINAPI corruntimehost_LocksHeldByLogicalThread(
300 ICorRuntimeHost* iface,
301 DWORD *pCount)
303 FIXME("stub %p\n", iface);
304 return E_NOTIMPL;
307 static HRESULT WINAPI corruntimehost_MapFile(
308 ICorRuntimeHost* iface,
309 HANDLE hFile,
310 HMODULE *mapAddress)
312 FIXME("stub %p\n", iface);
313 return E_NOTIMPL;
316 static HRESULT WINAPI corruntimehost_GetConfiguration(
317 ICorRuntimeHost* iface,
318 ICorConfiguration **pConfiguration)
320 FIXME("stub %p\n", iface);
321 return E_NOTIMPL;
324 static HRESULT WINAPI corruntimehost_Start(
325 ICorRuntimeHost* iface)
327 FIXME("stub %p\n", iface);
328 return S_OK;
331 static HRESULT WINAPI corruntimehost_Stop(
332 ICorRuntimeHost* iface)
334 FIXME("stub %p\n", iface);
335 return E_NOTIMPL;
338 static HRESULT WINAPI corruntimehost_CreateDomain(
339 ICorRuntimeHost* iface,
340 LPCWSTR friendlyName,
341 IUnknown *identityArray,
342 IUnknown **appDomain)
344 FIXME("stub %p\n", iface);
345 return E_NOTIMPL;
348 static HRESULT WINAPI corruntimehost_GetDefaultDomain(
349 ICorRuntimeHost* iface,
350 IUnknown **pAppDomain)
352 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
353 HRESULT hr;
354 MonoDomain *domain;
356 TRACE("(%p)\n", iface);
358 hr = RuntimeHost_GetDefaultDomain(This, &domain);
360 if (SUCCEEDED(hr))
362 hr = RuntimeHost_GetIUnknownForDomain(This, domain, pAppDomain);
365 return hr;
368 static HRESULT WINAPI corruntimehost_EnumDomains(
369 ICorRuntimeHost* iface,
370 HDOMAINENUM *hEnum)
372 FIXME("stub %p\n", iface);
373 return E_NOTIMPL;
376 static HRESULT WINAPI corruntimehost_NextDomain(
377 ICorRuntimeHost* iface,
378 HDOMAINENUM hEnum,
379 IUnknown **appDomain)
381 FIXME("stub %p\n", iface);
382 return E_NOTIMPL;
385 static HRESULT WINAPI corruntimehost_CloseEnum(
386 ICorRuntimeHost* iface,
387 HDOMAINENUM hEnum)
389 FIXME("stub %p\n", iface);
390 return E_NOTIMPL;
393 static HRESULT WINAPI corruntimehost_CreateDomainEx(
394 ICorRuntimeHost* iface,
395 LPCWSTR friendlyName,
396 IUnknown *setup,
397 IUnknown *evidence,
398 IUnknown **appDomain)
400 FIXME("stub %p\n", iface);
401 return E_NOTIMPL;
404 static HRESULT WINAPI corruntimehost_CreateDomainSetup(
405 ICorRuntimeHost* iface,
406 IUnknown **appDomainSetup)
408 FIXME("stub %p\n", iface);
409 return E_NOTIMPL;
412 static HRESULT WINAPI corruntimehost_CreateEvidence(
413 ICorRuntimeHost* iface,
414 IUnknown **evidence)
416 FIXME("stub %p\n", iface);
417 return E_NOTIMPL;
420 static HRESULT WINAPI corruntimehost_UnloadDomain(
421 ICorRuntimeHost* iface,
422 IUnknown *appDomain)
424 FIXME("stub %p\n", iface);
425 return E_NOTIMPL;
428 static HRESULT WINAPI corruntimehost_CurrentDomain(
429 ICorRuntimeHost* iface,
430 IUnknown **appDomain)
432 FIXME("stub %p\n", iface);
433 return E_NOTIMPL;
436 static const struct ICorRuntimeHostVtbl corruntimehost_vtbl =
438 corruntimehost_QueryInterface,
439 corruntimehost_AddRef,
440 corruntimehost_Release,
441 corruntimehost_CreateLogicalThreadState,
442 corruntimehost_DeleteLogicalThreadState,
443 corruntimehost_SwitchInLogicalThreadState,
444 corruntimehost_SwitchOutLogicalThreadState,
445 corruntimehost_LocksHeldByLogicalThread,
446 corruntimehost_MapFile,
447 corruntimehost_GetConfiguration,
448 corruntimehost_Start,
449 corruntimehost_Stop,
450 corruntimehost_CreateDomain,
451 corruntimehost_GetDefaultDomain,
452 corruntimehost_EnumDomains,
453 corruntimehost_NextDomain,
454 corruntimehost_CloseEnum,
455 corruntimehost_CreateDomainEx,
456 corruntimehost_CreateDomainSetup,
457 corruntimehost_CreateEvidence,
458 corruntimehost_UnloadDomain,
459 corruntimehost_CurrentDomain
462 static HRESULT WINAPI CLRRuntimeHost_QueryInterface(ICLRRuntimeHost* iface,
463 REFIID riid,
464 void **ppvObject)
466 RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
467 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
469 if ( IsEqualGUID( riid, &IID_ICLRRuntimeHost ) ||
470 IsEqualGUID( riid, &IID_IUnknown ) )
472 *ppvObject = iface;
474 else
476 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
477 return E_NOINTERFACE;
480 ICLRRuntimeHost_AddRef( iface );
482 return S_OK;
485 static ULONG WINAPI CLRRuntimeHost_AddRef(ICLRRuntimeHost* iface)
487 RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
488 return ICorRuntimeHost_AddRef(&This->ICorRuntimeHost_iface);
491 static ULONG WINAPI CLRRuntimeHost_Release(ICLRRuntimeHost* iface)
493 RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
494 return ICorRuntimeHost_Release(&This->ICorRuntimeHost_iface);
497 static HRESULT WINAPI CLRRuntimeHost_Start(ICLRRuntimeHost* iface)
499 FIXME("(%p)\n", iface);
500 return E_NOTIMPL;
503 static HRESULT WINAPI CLRRuntimeHost_Stop(ICLRRuntimeHost* iface)
505 FIXME("(%p)\n", iface);
506 return E_NOTIMPL;
509 static HRESULT WINAPI CLRRuntimeHost_SetHostControl(ICLRRuntimeHost* iface,
510 IHostControl *pHostControl)
512 FIXME("(%p,%p)\n", iface, pHostControl);
513 return E_NOTIMPL;
516 static HRESULT WINAPI CLRRuntimeHost_GetCLRControl(ICLRRuntimeHost* iface,
517 ICLRControl **pCLRControl)
519 FIXME("(%p,%p)\n", iface, pCLRControl);
520 return E_NOTIMPL;
523 static HRESULT WINAPI CLRRuntimeHost_UnloadAppDomain(ICLRRuntimeHost* iface,
524 DWORD dwAppDomainId, BOOL fWaitUntilDone)
526 FIXME("(%p,%u,%i)\n", iface, dwAppDomainId, fWaitUntilDone);
527 return E_NOTIMPL;
530 static HRESULT WINAPI CLRRuntimeHost_ExecuteInAppDomain(ICLRRuntimeHost* iface,
531 DWORD dwAppDomainId, FExecuteInAppDomainCallback pCallback, void *cookie)
533 FIXME("(%p,%u,%p,%p)\n", iface, dwAppDomainId, pCallback, cookie);
534 return E_NOTIMPL;
537 static HRESULT WINAPI CLRRuntimeHost_GetCurrentAppDomainId(ICLRRuntimeHost* iface,
538 DWORD *pdwAppDomainId)
540 FIXME("(%p,%p)\n", iface, pdwAppDomainId);
541 return E_NOTIMPL;
544 static HRESULT WINAPI CLRRuntimeHost_ExecuteApplication(ICLRRuntimeHost* iface,
545 LPCWSTR pwzAppFullName, DWORD dwManifestPaths, LPCWSTR *ppwzManifestPaths,
546 DWORD dwActivationData, LPCWSTR *ppwzActivationData, int *pReturnValue)
548 FIXME("(%p,%s,%u,%u)\n", iface, debugstr_w(pwzAppFullName), dwManifestPaths, dwActivationData);
549 return E_NOTIMPL;
552 static HRESULT WINAPI CLRRuntimeHost_ExecuteInDefaultAppDomain(ICLRRuntimeHost* iface,
553 LPCWSTR pwzAssemblyPath, LPCWSTR pwzTypeName, LPCWSTR pwzMethodName,
554 LPCWSTR pwzArgument, DWORD *pReturnValue)
556 RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
557 HRESULT hr;
558 MonoDomain *domain;
559 MonoAssembly *assembly;
560 MonoImage *image;
561 MonoClass *klass;
562 MonoMethod *method;
563 MonoObject *result;
564 MonoString *str;
565 void *args[2];
566 char *filenameA = NULL, *classA = NULL, *methodA = NULL;
567 char *argsA = NULL, *ns;
569 TRACE("(%p,%s,%s,%s,%s)\n", iface, debugstr_w(pwzAssemblyPath),
570 debugstr_w(pwzTypeName), debugstr_w(pwzMethodName), debugstr_w(pwzArgument));
572 hr = RuntimeHost_GetDefaultDomain(This, &domain);
573 if(hr != S_OK)
575 ERR("Couldn't get Default Domain\n");
576 return hr;
579 hr = E_FAIL;
581 This->mono->mono_thread_attach(domain);
583 filenameA = WtoA(pwzAssemblyPath);
584 assembly = This->mono->mono_domain_assembly_open(domain, filenameA);
585 if (!assembly)
587 ERR("Cannot open assembly %s\n", filenameA);
588 goto cleanup;
591 image = This->mono->mono_assembly_get_image(assembly);
592 if (!image)
594 ERR("Couldn't get assembly image\n");
595 goto cleanup;
598 classA = WtoA(pwzTypeName);
599 ns = strrchr(classA, '.');
600 *ns = '\0';
601 klass = This->mono->mono_class_from_name(image, classA, ns+1);
602 if (!klass)
604 ERR("Couldn't get class from image\n");
605 goto cleanup;
608 methodA = WtoA(pwzMethodName);
609 method = This->mono->mono_class_get_method_from_name(klass, methodA, 1);
610 if (!method)
612 ERR("Couldn't get method from class\n");
613 goto cleanup;
616 /* The .NET function we are calling has the following declaration
617 * public static int functionName(String param)
619 argsA = WtoA(pwzArgument);
620 str = This->mono->mono_string_new(domain, argsA);
621 args[0] = str;
622 args[1] = NULL;
623 result = This->mono->mono_runtime_invoke(method, NULL, args, NULL);
624 if (!result)
625 ERR("Couldn't get result pointer\n");
626 else
628 *pReturnValue = *(DWORD*)This->mono->mono_object_unbox(result);
629 hr = S_OK;
632 cleanup:
633 HeapFree(GetProcessHeap(), 0, filenameA);
634 HeapFree(GetProcessHeap(), 0, classA);
635 HeapFree(GetProcessHeap(), 0, argsA);
636 HeapFree(GetProcessHeap(), 0, methodA);
638 return hr;
641 static const struct ICLRRuntimeHostVtbl CLRHostVtbl =
643 CLRRuntimeHost_QueryInterface,
644 CLRRuntimeHost_AddRef,
645 CLRRuntimeHost_Release,
646 CLRRuntimeHost_Start,
647 CLRRuntimeHost_Stop,
648 CLRRuntimeHost_SetHostControl,
649 CLRRuntimeHost_GetCLRControl,
650 CLRRuntimeHost_UnloadAppDomain,
651 CLRRuntimeHost_ExecuteInAppDomain,
652 CLRRuntimeHost_GetCurrentAppDomainId,
653 CLRRuntimeHost_ExecuteApplication,
654 CLRRuntimeHost_ExecuteInDefaultAppDomain
657 /* Create an instance of a type given its name, by calling its constructor with
658 * no arguments. Note that result MUST be in the stack, or the garbage
659 * collector may free it prematurely. */
660 HRESULT RuntimeHost_CreateManagedInstance(RuntimeHost *This, LPCWSTR name,
661 MonoDomain *domain, MonoObject **result)
663 HRESULT hr=S_OK;
664 char *nameA=NULL;
665 MonoType *type;
666 MonoClass *klass;
667 MonoObject *obj;
669 if (!domain)
670 hr = RuntimeHost_GetDefaultDomain(This, &domain);
672 if (SUCCEEDED(hr))
674 nameA = WtoA(name);
675 if (!nameA)
676 hr = E_OUTOFMEMORY;
679 if (SUCCEEDED(hr))
681 This->mono->mono_thread_attach(domain);
683 type = This->mono->mono_reflection_type_from_name(nameA, NULL);
684 if (!type)
686 ERR("Cannot find type %s\n", debugstr_w(name));
687 hr = E_FAIL;
691 if (SUCCEEDED(hr))
693 klass = This->mono->mono_class_from_mono_type(type);
694 if (!klass)
696 ERR("Cannot convert type %s to a class\n", debugstr_w(name));
697 hr = E_FAIL;
701 if (SUCCEEDED(hr))
703 obj = This->mono->mono_object_new(domain, klass);
704 if (!obj)
706 ERR("Cannot allocate object of type %s\n", debugstr_w(name));
707 hr = E_FAIL;
711 if (SUCCEEDED(hr))
713 /* FIXME: Detect exceptions from the constructor? */
714 This->mono->mono_runtime_object_init(obj);
715 *result = obj;
718 HeapFree(GetProcessHeap(), 0, nameA);
720 return hr;
723 /* Get an IUnknown pointer for a Mono object.
725 * This is just a "light" wrapper around
726 * System.Runtime.InteropServices.Marshal:GetIUnknownForObject
728 * NOTE: The IUnknown* is created with a reference to the object.
729 * Until they have a reference, objects must be in the stack to prevent the
730 * garbage collector from freeing them.
732 * mono_thread_attach must have already been called for this thread. */
733 HRESULT RuntimeHost_GetIUnknownForObject(RuntimeHost *This, MonoObject *obj,
734 IUnknown **ppUnk)
736 MonoDomain *domain;
737 MonoAssembly *assembly;
738 MonoImage *image;
739 MonoClass *klass;
740 MonoMethod *method;
741 MonoObject *result;
742 void *args[2];
744 domain = This->mono->mono_object_get_domain(obj);
746 assembly = This->mono->mono_domain_assembly_open(domain, "mscorlib");
747 if (!assembly)
749 ERR("Cannot load mscorlib\n");
750 return E_FAIL;
753 image = This->mono->mono_assembly_get_image(assembly);
754 if (!image)
756 ERR("Couldn't get assembly image\n");
757 return E_FAIL;
760 klass = This->mono->mono_class_from_name(image, "System.Runtime.InteropServices", "Marshal");
761 if (!klass)
763 ERR("Couldn't get class from image\n");
764 return E_FAIL;
767 method = This->mono->mono_class_get_method_from_name(klass, "GetIUnknownForObject", 1);
768 if (!method)
770 ERR("Couldn't get method from class\n");
771 return E_FAIL;
774 args[0] = obj;
775 args[1] = NULL;
776 result = This->mono->mono_runtime_invoke(method, NULL, args, NULL);
777 if (!result)
779 ERR("Couldn't get result pointer\n");
780 return E_FAIL;
783 *ppUnk = *(IUnknown**)This->mono->mono_object_unbox(result);
784 if (!*ppUnk)
786 ERR("GetIUnknownForObject returned 0\n");
787 return E_FAIL;
790 return S_OK;
793 static void get_utf8_args(int *argc, char ***argv)
795 WCHAR **argvw;
796 int size=0, i;
797 char *current_arg;
799 argvw = CommandLineToArgvW(GetCommandLineW(), argc);
801 for (i=0; i<*argc; i++)
803 size += sizeof(char*);
804 size += WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, NULL, 0, NULL, NULL);
806 size += sizeof(char*);
808 *argv = HeapAlloc(GetProcessHeap(), 0, size);
809 current_arg = (char*)(*argv + *argc + 1);
811 for (i=0; i<*argc; i++)
813 (*argv)[i] = current_arg;
814 current_arg += WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, current_arg, size, NULL, NULL);
817 (*argv)[*argc] = NULL;
819 HeapFree(GetProcessHeap(), 0, argvw);
822 #if __i386__
824 # define CAN_FIXUP_VTABLE 1
826 #include "pshpack1.h"
828 struct vtable_fixup_thunk
830 /* push %ecx */
831 BYTE i7;
832 /* sub $0x4,%esp */
833 BYTE i1[3];
834 /* mov fixup,(%esp) */
835 BYTE i2[3];
836 struct dll_fixup *fixup;
837 /* mov function,%eax */
838 BYTE i3;
839 void (CDECL *function)(struct dll_fixup *);
840 /* call *%eax */
841 BYTE i4[2];
842 /* pop %eax */
843 BYTE i5;
844 /* pop %ecx */
845 BYTE i8;
846 /* jmp *vtable_entry */
847 BYTE i6[2];
848 void *vtable_entry;
851 static const struct vtable_fixup_thunk thunk_template = {
852 0x51,
853 {0x83,0xec,0x04},
854 {0xc7,0x04,0x24},
855 NULL,
856 0xb8,
857 NULL,
858 {0xff,0xd0},
859 0x58,
860 0x59,
861 {0xff,0x25},
862 NULL
865 #include "poppack.h"
867 #else /* !defined(__i386__) */
869 # define CAN_FIXUP_VTABLE 0
871 struct vtable_fixup_thunk
873 struct dll_fixup *fixup;
874 void (CDECL *function)(struct dll_fixup *fixup);
875 void *vtable_entry;
878 static const struct vtable_fixup_thunk thunk_template = {0};
880 #endif
882 static void CDECL ReallyFixupVTable(struct dll_fixup *fixup)
884 HRESULT hr=S_OK;
885 WCHAR filename[MAX_PATH];
886 ICLRRuntimeInfo *info=NULL;
887 RuntimeHost *host;
888 char *filenameA;
889 MonoImage *image=NULL;
890 MonoAssembly *assembly=NULL;
891 MonoImageOpenStatus status=0;
892 MonoDomain *domain;
894 if (fixup->done) return;
896 /* It's possible we'll have two threads doing this at once. This is
897 * considered preferable to the potential deadlock if we use a mutex. */
899 GetModuleFileNameW(fixup->dll, filename, MAX_PATH);
901 TRACE("%p,%p,%s\n", fixup, fixup->dll, debugstr_w(filename));
903 filenameA = WtoA(filename);
904 if (!filenameA)
905 hr = E_OUTOFMEMORY;
907 if (SUCCEEDED(hr))
908 hr = get_runtime_info(filename, NULL, NULL, 0, 0, FALSE, &info);
910 if (SUCCEEDED(hr))
911 hr = ICLRRuntimeInfo_GetRuntimeHost(info, &host);
913 if (SUCCEEDED(hr))
914 hr = RuntimeHost_GetDefaultDomain(host, &domain);
916 if (SUCCEEDED(hr))
918 host->mono->mono_thread_attach(domain);
920 assembly = host->mono->mono_assembly_open(filenameA, &status);
923 if (assembly)
925 int i;
927 /* Mono needs an image that belongs to an assembly. */
928 image = host->mono->mono_assembly_get_image(assembly);
930 if (fixup->fixup->type & COR_VTABLE_32BIT)
932 DWORD *vtable = fixup->vtable;
933 DWORD *tokens = fixup->tokens;
934 for (i=0; i<fixup->fixup->count; i++)
936 TRACE("%x\n", tokens[i]);
937 vtable[i] = PtrToUint(host->mono->mono_marshal_get_vtfixup_ftnptr(
938 image, tokens[i], fixup->fixup->type));
942 fixup->done = 1;
945 if (info != NULL)
946 ICLRRuntimeInfo_Release(info);
948 HeapFree(GetProcessHeap(), 0, filenameA);
950 if (!fixup->done)
952 ERR("unable to fixup vtable, hr=%x, status=%d\n", hr, status);
953 /* If we returned now, we'd get an infinite loop. */
954 assert(0);
958 static void FixupVTableEntry(HMODULE hmodule, VTableFixup *vtable_fixup)
960 /* We can't actually generate code for the functions without loading mono,
961 * and loading mono inside DllMain is a terrible idea. So we make thunks
962 * that call ReallyFixupVTable, which will load the runtime and fill in the
963 * vtable, then do an indirect jump using the (now filled in) vtable. Note
964 * that we have to keep the thunks around forever, as one of them may get
965 * called while we're filling in the table, and we can never be sure all
966 * threads are clear. */
967 struct dll_fixup *fixup;
969 fixup = HeapAlloc(GetProcessHeap(), 0, sizeof(*fixup));
971 fixup->dll = hmodule;
972 fixup->thunk_code = HeapAlloc(dll_fixup_heap, 0, sizeof(struct vtable_fixup_thunk) * vtable_fixup->count);
973 fixup->fixup = vtable_fixup;
974 fixup->vtable = (BYTE*)hmodule + vtable_fixup->rva;
975 fixup->done = 0;
977 if (vtable_fixup->type & COR_VTABLE_32BIT)
979 DWORD *vtable = fixup->vtable;
980 DWORD *tokens;
981 int i;
982 struct vtable_fixup_thunk *thunks = fixup->thunk_code;
984 if (sizeof(void*) > 4)
985 ERR("32-bit fixup in 64-bit mode; broken image?\n");
987 tokens = fixup->tokens = HeapAlloc(GetProcessHeap(), 0, sizeof(*tokens) * vtable_fixup->count);
988 memcpy(tokens, vtable, sizeof(*tokens) * vtable_fixup->count);
989 for (i=0; i<vtable_fixup->count; i++)
991 thunks[i] = thunk_template;
992 thunks[i].fixup = fixup;
993 thunks[i].function = ReallyFixupVTable;
994 thunks[i].vtable_entry = &vtable[i];
995 vtable[i] = PtrToUint(&thunks[i]);
998 else
1000 ERR("unsupported vtable fixup flags %x\n", vtable_fixup->type);
1001 HeapFree(dll_fixup_heap, 0, fixup->thunk_code);
1002 HeapFree(GetProcessHeap(), 0, fixup);
1003 return;
1006 list_add_tail(&dll_fixups, &fixup->entry);
1009 static void FixupVTable(HMODULE hmodule)
1011 ASSEMBLY *assembly;
1012 HRESULT hr;
1013 VTableFixup *vtable_fixups;
1014 ULONG vtable_fixup_count, i;
1016 hr = assembly_from_hmodule(&assembly, hmodule);
1017 if (SUCCEEDED(hr))
1019 hr = assembly_get_vtable_fixups(assembly, &vtable_fixups, &vtable_fixup_count);
1020 if (CAN_FIXUP_VTABLE)
1021 for (i=0; i<vtable_fixup_count; i++)
1022 FixupVTableEntry(hmodule, &vtable_fixups[i]);
1023 else if (vtable_fixup_count)
1024 FIXME("cannot fixup vtable; expect a crash\n");
1026 assembly_release(assembly);
1028 else
1029 ERR("failed to read CLR headers, hr=%x\n", hr);
1032 __int32 WINAPI _CorExeMain(void)
1034 int exit_code;
1035 int argc;
1036 char **argv;
1037 MonoDomain *domain;
1038 MonoImage *image;
1039 MonoImageOpenStatus status;
1040 MonoAssembly *assembly=NULL;
1041 WCHAR filename[MAX_PATH];
1042 char *filenameA;
1043 ICLRRuntimeInfo *info;
1044 RuntimeHost *host;
1045 HRESULT hr;
1046 int i;
1048 get_utf8_args(&argc, &argv);
1050 GetModuleFileNameW(NULL, filename, MAX_PATH);
1052 TRACE("%s", debugstr_w(filename));
1053 for (i=0; i<argc; i++)
1054 TRACE(" %s", debugstr_a(argv[i]));
1055 TRACE("\n");
1057 filenameA = WtoA(filename);
1058 if (!filenameA)
1059 return -1;
1061 FixupVTable(GetModuleHandleW(NULL));
1063 hr = get_runtime_info(filename, NULL, NULL, 0, 0, FALSE, &info);
1065 if (SUCCEEDED(hr))
1067 hr = ICLRRuntimeInfo_GetRuntimeHost(info, &host);
1069 if (SUCCEEDED(hr))
1070 hr = RuntimeHost_GetDefaultDomain(host, &domain);
1072 if (SUCCEEDED(hr))
1074 image = host->mono->mono_image_open_from_module_handle(GetModuleHandleW(NULL),
1075 filenameA, 1, &status);
1077 if (image)
1078 assembly = host->mono->mono_assembly_load_from(image, filenameA, &status);
1080 if (assembly)
1082 host->mono->mono_trace_set_assembly(assembly);
1084 exit_code = host->mono->mono_jit_exec(domain, assembly, argc, argv);
1086 else
1088 ERR("couldn't load %s, status=%d\n", debugstr_w(filename), status);
1089 exit_code = -1;
1092 RuntimeHost_DeleteDomain(host, domain);
1094 else
1095 exit_code = -1;
1097 ICLRRuntimeInfo_Release(info);
1099 else
1100 exit_code = -1;
1102 HeapFree(GetProcessHeap(), 0, argv);
1104 unload_all_runtimes();
1106 return exit_code;
1109 BOOL WINAPI _CorDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
1111 TRACE("(%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
1113 switch (fdwReason)
1115 case DLL_PROCESS_ATTACH:
1116 DisableThreadLibraryCalls(hinstDLL);
1117 FixupVTable(hinstDLL);
1118 break;
1119 case DLL_PROCESS_DETACH:
1120 /* FIXME: clean up the vtables */
1121 break;
1123 return TRUE;
1126 /* called from DLL_PROCESS_ATTACH */
1127 void runtimehost_init(void)
1129 dll_fixup_heap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0);
1130 list_init(&dll_fixups);
1133 /* called from DLL_PROCESS_DETACH */
1134 void runtimehost_uninit(void)
1136 struct dll_fixup *fixup, *fixup2;
1138 HeapDestroy(dll_fixup_heap);
1139 LIST_FOR_EACH_ENTRY_SAFE(fixup, fixup2, &dll_fixups, struct dll_fixup, entry)
1141 HeapFree(GetProcessHeap(), 0, fixup->tokens);
1142 HeapFree(GetProcessHeap(), 0, fixup);
1146 HRESULT RuntimeHost_Construct(const CLRRuntimeInfo *runtime_version,
1147 loaded_mono *loaded_mono, RuntimeHost** result)
1149 RuntimeHost *This;
1151 This = HeapAlloc( GetProcessHeap(), 0, sizeof *This );
1152 if ( !This )
1153 return E_OUTOFMEMORY;
1155 This->ICorRuntimeHost_iface.lpVtbl = &corruntimehost_vtbl;
1156 This->ICLRRuntimeHost_iface.lpVtbl = &CLRHostVtbl;
1158 This->ref = 1;
1159 This->version = runtime_version;
1160 This->mono = loaded_mono;
1161 list_init(&This->domains);
1162 This->default_domain = NULL;
1163 InitializeCriticalSection(&This->lock);
1164 This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": RuntimeHost.lock");
1166 *result = This;
1168 return S_OK;
1171 HRESULT RuntimeHost_GetInterface(RuntimeHost *This, REFCLSID clsid, REFIID riid, void **ppv)
1173 IUnknown *unk;
1174 HRESULT hr;
1176 if (IsEqualGUID(clsid, &CLSID_CorRuntimeHost))
1178 unk = (IUnknown*)&This->ICorRuntimeHost_iface;
1179 IUnknown_AddRef(unk);
1181 else if (IsEqualGUID(clsid, &CLSID_CLRRuntimeHost))
1183 unk = (IUnknown*)&This->ICLRRuntimeHost_iface;
1184 IUnknown_AddRef(unk);
1186 else if (IsEqualGUID(clsid, &CLSID_CorMetaDataDispenser) ||
1187 IsEqualGUID(clsid, &CLSID_CorMetaDataDispenserRuntime))
1189 hr = MetaDataDispenser_CreateInstance(&unk);
1190 if (FAILED(hr))
1191 return hr;
1193 else if (IsEqualGUID(clsid, &CLSID_CLRDebuggingLegacy))
1195 hr = CorDebug_Create(&This->ICLRRuntimeHost_iface, &unk);
1196 if (FAILED(hr))
1197 return hr;
1199 else
1200 unk = NULL;
1202 if (unk)
1204 hr = IUnknown_QueryInterface(unk, riid, ppv);
1206 IUnknown_Release(unk);
1208 return hr;
1210 else
1211 FIXME("not implemented for class %s\n", debugstr_guid(clsid));
1213 return CLASS_E_CLASSNOTAVAILABLE;
1216 HRESULT RuntimeHost_Destroy(RuntimeHost *This)
1218 struct DomainEntry *cursor, *cursor2;
1220 This->lock.DebugInfo->Spare[0] = 0;
1221 DeleteCriticalSection(&This->lock);
1223 LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->domains, struct DomainEntry, entry)
1225 list_remove(&cursor->entry);
1226 HeapFree(GetProcessHeap(), 0, cursor);
1229 HeapFree( GetProcessHeap(), 0, This );
1230 return S_OK;
1233 #define CHARS_IN_GUID 39
1234 #define ARRAYSIZE(array) (sizeof(array)/sizeof((array)[0]))
1236 HRESULT create_monodata(REFIID riid, LPVOID *ppObj )
1238 static const WCHAR wszAssembly[] = {'A','s','s','e','m','b','l','y',0};
1239 static const WCHAR wszCodebase[] = {'C','o','d','e','B','a','s','e',0};
1240 static const WCHAR wszClass[] = {'C','l','a','s','s',0};
1241 static const WCHAR wszFileSlash[] = {'f','i','l','e',':','/','/','/',0};
1242 static const WCHAR wszCLSIDSlash[] = {'C','L','S','I','D','\\',0};
1243 static const WCHAR wszInprocServer32[] = {'\\','I','n','p','r','o','c','S','e','r','v','e','r','3','2',0};
1244 WCHAR path[CHARS_IN_GUID + ARRAYSIZE(wszCLSIDSlash) + ARRAYSIZE(wszInprocServer32) - 1];
1245 MonoDomain *domain;
1246 MonoAssembly *assembly;
1247 ICLRRuntimeInfo *info = NULL;
1248 RuntimeHost *host;
1249 HRESULT hr;
1250 HKEY key, subkey;
1251 LONG res;
1252 int offset = 0;
1253 DWORD numKeys, keyLength;
1254 WCHAR codebase[MAX_PATH + 8];
1255 WCHAR classname[350], subkeyName[256];
1256 WCHAR filename[MAX_PATH];
1258 DWORD dwBufLen = 350;
1260 lstrcpyW(path, wszCLSIDSlash);
1261 StringFromGUID2(riid, path + lstrlenW(wszCLSIDSlash), CHARS_IN_GUID);
1262 lstrcatW(path, wszInprocServer32);
1264 TRACE("Registry key: %s\n", debugstr_w(path));
1266 res = RegOpenKeyExW(HKEY_CLASSES_ROOT, path, 0, KEY_READ, &key);
1267 if (res == ERROR_FILE_NOT_FOUND)
1268 return CLASS_E_CLASSNOTAVAILABLE;
1270 res = RegGetValueW( key, NULL, wszClass, RRF_RT_REG_SZ, NULL, classname, &dwBufLen);
1271 if(res != ERROR_SUCCESS)
1273 WARN("Class value cannot be found.\n");
1274 hr = CLASS_E_CLASSNOTAVAILABLE;
1275 goto cleanup;
1278 TRACE("classname (%s)\n", debugstr_w(classname));
1280 dwBufLen = MAX_PATH + 8;
1281 res = RegGetValueW( key, NULL, wszCodebase, RRF_RT_REG_SZ, NULL, codebase, &dwBufLen);
1282 if(res == ERROR_SUCCESS)
1284 /* Strip file:/// */
1285 if(strncmpW(codebase, wszFileSlash, strlenW(wszFileSlash)) == 0)
1286 offset = strlenW(wszFileSlash);
1288 strcpyW(filename, codebase + offset);
1290 else
1292 hr = CLASS_E_CLASSNOTAVAILABLE;
1293 WARN("CodeBase value cannot be found, trying Assembly.\n");
1294 /* get the last subkey of InprocServer32 */
1295 res = RegQueryInfoKeyW(key, 0, 0, 0, &numKeys, 0, 0, 0, 0, 0, 0, 0);
1296 if (res != ERROR_SUCCESS || numKeys == 0)
1297 goto cleanup;
1298 numKeys--;
1299 keyLength = sizeof(subkeyName) / sizeof(WCHAR);
1300 res = RegEnumKeyExW(key, numKeys, subkeyName, &keyLength, 0, 0, 0, 0);
1301 if (res != ERROR_SUCCESS)
1302 goto cleanup;
1303 res = RegOpenKeyExW(key, subkeyName, 0, KEY_READ, &subkey);
1304 if (res != ERROR_SUCCESS)
1305 goto cleanup;
1306 dwBufLen = MAX_PATH + 8;
1307 res = RegGetValueW(subkey, NULL, wszAssembly, RRF_RT_REG_SZ, NULL, codebase, &dwBufLen);
1308 RegCloseKey(subkey);
1309 if (res != ERROR_SUCCESS)
1310 goto cleanup;
1311 hr = get_file_from_strongname(codebase, filename, MAX_PATH);
1312 if (!SUCCEEDED(hr))
1313 goto cleanup;
1316 TRACE("codebase (%s)\n", debugstr_w(filename));
1318 *ppObj = NULL;
1321 hr = get_runtime_info(filename, NULL, NULL, 0, 0, FALSE, &info);
1322 if (SUCCEEDED(hr))
1324 hr = ICLRRuntimeInfo_GetRuntimeHost(info, &host);
1326 if (SUCCEEDED(hr))
1327 hr = RuntimeHost_GetDefaultDomain(host, &domain);
1329 if (SUCCEEDED(hr))
1331 MonoImage *image;
1332 MonoClass *klass;
1333 MonoObject *result;
1334 IUnknown *unk = NULL;
1335 char *filenameA, *ns;
1336 char *classA;
1338 hr = CLASS_E_CLASSNOTAVAILABLE;
1340 host->mono->mono_thread_attach(domain);
1342 filenameA = WtoA(filename);
1343 assembly = host->mono->mono_domain_assembly_open(domain, filenameA);
1344 HeapFree(GetProcessHeap(), 0, filenameA);
1345 if (!assembly)
1347 ERR("Cannot open assembly %s\n", filenameA);
1348 goto cleanup;
1351 image = host->mono->mono_assembly_get_image(assembly);
1352 if (!image)
1354 ERR("Couldn't get assembly image\n");
1355 goto cleanup;
1358 classA = WtoA(classname);
1359 ns = strrchr(classA, '.');
1360 *ns = '\0';
1362 klass = host->mono->mono_class_from_name(image, classA, ns+1);
1363 HeapFree(GetProcessHeap(), 0, classA);
1364 if (!klass)
1366 ERR("Couldn't get class from image\n");
1367 goto cleanup;
1371 * Use the default constructor for the .NET class.
1373 result = host->mono->mono_object_new(domain, klass);
1374 host->mono->mono_runtime_object_init(result);
1376 hr = RuntimeHost_GetIUnknownForObject(host, result, &unk);
1377 if (SUCCEEDED(hr))
1379 hr = IUnknown_QueryInterface(unk, &IID_IUnknown, ppObj);
1381 IUnknown_Release(unk);
1383 else
1384 hr = CLASS_E_CLASSNOTAVAILABLE;
1386 else
1387 hr = CLASS_E_CLASSNOTAVAILABLE;
1389 else
1390 hr = CLASS_E_CLASSNOTAVAILABLE;
1392 cleanup:
1393 if(info)
1394 ICLRRuntimeInfo_Release(info);
1396 RegCloseKey(key);
1398 return hr;