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 WIN32_NO_STATUS
22 #define COM_NO_WINDOWS_H
31 //#include "winuser.h"
38 //#include "mscoree.h"
42 #include <wine/list.h>
43 #include "mscoree_private.h"
45 #include <wine/debug.h>
46 #include <wine/unicode.h>
47 //#include "wine/list.h"
49 WINE_DEFAULT_DEBUG_CHANNEL( mscoree
);
53 DEFINE_GUID(IID__AppDomain
, 0x05f696dc,0x2b29,0x3663,0xad,0x8b,0xc4,0x38,0x9c,0xf2,0xa7,0x13);
61 static HANDLE dll_fixup_heap
; /* using a separate heap so we can have execute permission */
63 static struct list dll_fixups
;
70 void *thunk_code
; /* pointer into dll_fixup_heap */
73 void *tokens
; /* pointer into process heap */
76 static HRESULT
RuntimeHost_AddDomain(RuntimeHost
*This
, MonoDomain
**result
)
78 struct DomainEntry
*entry
;
82 EnterCriticalSection(&This
->lock
);
84 entry
= HeapAlloc(GetProcessHeap(), 0, sizeof(*entry
));
91 mscorlib_path
= WtoA(This
->version
->mscorlib_path
);
94 HeapFree(GetProcessHeap(), 0, entry
);
99 entry
->domain
= This
->mono
->mono_jit_init(mscorlib_path
);
101 HeapFree(GetProcessHeap(), 0, mscorlib_path
);
105 HeapFree(GetProcessHeap(), 0, entry
);
110 This
->mono
->is_started
= TRUE
;
112 list_add_tail(&This
->domains
, &entry
->entry
);
114 *result
= entry
->domain
;
117 LeaveCriticalSection(&This
->lock
);
122 static HRESULT
RuntimeHost_GetDefaultDomain(RuntimeHost
*This
, MonoDomain
**result
)
126 EnterCriticalSection(&This
->lock
);
128 if (This
->default_domain
) goto end
;
130 res
= RuntimeHost_AddDomain(This
, &This
->default_domain
);
133 *result
= This
->default_domain
;
135 LeaveCriticalSection(&This
->lock
);
140 static void RuntimeHost_DeleteDomain(RuntimeHost
*This
, MonoDomain
*domain
)
142 struct DomainEntry
*entry
;
144 EnterCriticalSection(&This
->lock
);
146 LIST_FOR_EACH_ENTRY(entry
, &This
->domains
, struct DomainEntry
, entry
)
148 if (entry
->domain
== domain
)
150 list_remove(&entry
->entry
);
151 if (This
->default_domain
== domain
)
152 This
->default_domain
= NULL
;
153 HeapFree(GetProcessHeap(), 0, entry
);
158 LeaveCriticalSection(&This
->lock
);
161 static HRESULT
RuntimeHost_GetIUnknownForDomain(RuntimeHost
*This
, MonoDomain
*domain
, IUnknown
**punk
)
165 MonoAssembly
*assembly
;
169 MonoObject
*appdomain_object
;
172 This
->mono
->mono_thread_attach(domain
);
174 assembly
= This
->mono
->mono_domain_assembly_open(domain
, "mscorlib");
177 ERR("Cannot load mscorlib\n");
181 image
= This
->mono
->mono_assembly_get_image(assembly
);
184 ERR("Couldn't get assembly image\n");
188 klass
= This
->mono
->mono_class_from_name(image
, "System", "AppDomain");
191 ERR("Couldn't get class from image\n");
195 method
= This
->mono
->mono_class_get_method_from_name(klass
, "get_CurrentDomain", 0);
198 ERR("Couldn't get method from class\n");
203 appdomain_object
= This
->mono
->mono_runtime_invoke(method
, NULL
, args
, NULL
);
204 if (!appdomain_object
)
206 ERR("Couldn't get result pointer\n");
210 hr
= RuntimeHost_GetIUnknownForObject(This
, appdomain_object
, &unk
);
214 hr
= IUnknown_QueryInterface(unk
, &IID__AppDomain
, (void**)punk
);
216 IUnknown_Release(unk
);
222 static inline RuntimeHost
*impl_from_ICLRRuntimeHost( ICLRRuntimeHost
*iface
)
224 return CONTAINING_RECORD(iface
, RuntimeHost
, ICLRRuntimeHost_iface
);
227 static inline RuntimeHost
*impl_from_ICorRuntimeHost( ICorRuntimeHost
*iface
)
229 return CONTAINING_RECORD(iface
, RuntimeHost
, ICorRuntimeHost_iface
);
232 /*** IUnknown methods ***/
233 static HRESULT WINAPI
corruntimehost_QueryInterface(ICorRuntimeHost
* iface
,
237 RuntimeHost
*This
= impl_from_ICorRuntimeHost( iface
);
238 TRACE("%p %s %p\n", This
, debugstr_guid(riid
), ppvObject
);
240 if ( IsEqualGUID( riid
, &IID_ICorRuntimeHost
) ||
241 IsEqualGUID( riid
, &IID_IUnknown
) )
247 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
248 return E_NOINTERFACE
;
251 ICorRuntimeHost_AddRef( iface
);
256 static ULONG WINAPI
corruntimehost_AddRef(ICorRuntimeHost
* iface
)
258 RuntimeHost
*This
= impl_from_ICorRuntimeHost( iface
);
260 return InterlockedIncrement( &This
->ref
);
263 static ULONG WINAPI
corruntimehost_Release(ICorRuntimeHost
* iface
)
265 RuntimeHost
*This
= impl_from_ICorRuntimeHost( iface
);
268 ref
= InterlockedDecrement( &This
->ref
);
273 /*** ICorRuntimeHost methods ***/
274 static HRESULT WINAPI
corruntimehost_CreateLogicalThreadState(
275 ICorRuntimeHost
* iface
)
277 FIXME("stub %p\n", iface
);
281 static HRESULT WINAPI
corruntimehost_DeleteLogicalThreadState(
282 ICorRuntimeHost
* iface
)
284 FIXME("stub %p\n", iface
);
288 static HRESULT WINAPI
corruntimehost_SwitchInLogicalThreadState(
289 ICorRuntimeHost
* iface
,
292 FIXME("stub %p\n", iface
);
296 static HRESULT WINAPI
corruntimehost_SwitchOutLogicalThreadState(
297 ICorRuntimeHost
* iface
,
300 FIXME("stub %p\n", iface
);
304 static HRESULT WINAPI
corruntimehost_LocksHeldByLogicalThread(
305 ICorRuntimeHost
* iface
,
308 FIXME("stub %p\n", iface
);
312 static HRESULT WINAPI
corruntimehost_MapFile(
313 ICorRuntimeHost
* iface
,
317 FIXME("stub %p\n", iface
);
321 static HRESULT WINAPI
corruntimehost_GetConfiguration(
322 ICorRuntimeHost
* iface
,
323 ICorConfiguration
**pConfiguration
)
325 FIXME("stub %p\n", iface
);
329 static HRESULT WINAPI
corruntimehost_Start(
330 ICorRuntimeHost
* iface
)
332 FIXME("stub %p\n", iface
);
336 static HRESULT WINAPI
corruntimehost_Stop(
337 ICorRuntimeHost
* iface
)
339 FIXME("stub %p\n", iface
);
343 static HRESULT WINAPI
corruntimehost_CreateDomain(
344 ICorRuntimeHost
* iface
,
345 LPCWSTR friendlyName
,
346 IUnknown
*identityArray
,
347 IUnknown
**appDomain
)
349 FIXME("stub %p\n", iface
);
353 static HRESULT WINAPI
corruntimehost_GetDefaultDomain(
354 ICorRuntimeHost
* iface
,
355 IUnknown
**pAppDomain
)
357 RuntimeHost
*This
= impl_from_ICorRuntimeHost( iface
);
361 TRACE("(%p)\n", iface
);
363 hr
= RuntimeHost_GetDefaultDomain(This
, &domain
);
367 hr
= RuntimeHost_GetIUnknownForDomain(This
, domain
, pAppDomain
);
373 static HRESULT WINAPI
corruntimehost_EnumDomains(
374 ICorRuntimeHost
* iface
,
377 FIXME("stub %p\n", iface
);
381 static HRESULT WINAPI
corruntimehost_NextDomain(
382 ICorRuntimeHost
* iface
,
384 IUnknown
**appDomain
)
386 FIXME("stub %p\n", iface
);
390 static HRESULT WINAPI
corruntimehost_CloseEnum(
391 ICorRuntimeHost
* iface
,
394 FIXME("stub %p\n", iface
);
398 static HRESULT WINAPI
corruntimehost_CreateDomainEx(
399 ICorRuntimeHost
* iface
,
400 LPCWSTR friendlyName
,
403 IUnknown
**appDomain
)
405 FIXME("stub %p\n", iface
);
409 static HRESULT WINAPI
corruntimehost_CreateDomainSetup(
410 ICorRuntimeHost
* iface
,
411 IUnknown
**appDomainSetup
)
413 FIXME("stub %p\n", iface
);
417 static HRESULT WINAPI
corruntimehost_CreateEvidence(
418 ICorRuntimeHost
* iface
,
421 FIXME("stub %p\n", iface
);
425 static HRESULT WINAPI
corruntimehost_UnloadDomain(
426 ICorRuntimeHost
* iface
,
429 FIXME("stub %p\n", iface
);
433 static HRESULT WINAPI
corruntimehost_CurrentDomain(
434 ICorRuntimeHost
* iface
,
435 IUnknown
**appDomain
)
437 FIXME("stub %p\n", iface
);
441 static const struct ICorRuntimeHostVtbl corruntimehost_vtbl
=
443 corruntimehost_QueryInterface
,
444 corruntimehost_AddRef
,
445 corruntimehost_Release
,
446 corruntimehost_CreateLogicalThreadState
,
447 corruntimehost_DeleteLogicalThreadState
,
448 corruntimehost_SwitchInLogicalThreadState
,
449 corruntimehost_SwitchOutLogicalThreadState
,
450 corruntimehost_LocksHeldByLogicalThread
,
451 corruntimehost_MapFile
,
452 corruntimehost_GetConfiguration
,
453 corruntimehost_Start
,
455 corruntimehost_CreateDomain
,
456 corruntimehost_GetDefaultDomain
,
457 corruntimehost_EnumDomains
,
458 corruntimehost_NextDomain
,
459 corruntimehost_CloseEnum
,
460 corruntimehost_CreateDomainEx
,
461 corruntimehost_CreateDomainSetup
,
462 corruntimehost_CreateEvidence
,
463 corruntimehost_UnloadDomain
,
464 corruntimehost_CurrentDomain
467 static HRESULT WINAPI
CLRRuntimeHost_QueryInterface(ICLRRuntimeHost
* iface
,
471 RuntimeHost
*This
= impl_from_ICLRRuntimeHost( iface
);
472 TRACE("%p %s %p\n", This
, debugstr_guid(riid
), ppvObject
);
474 if ( IsEqualGUID( riid
, &IID_ICLRRuntimeHost
) ||
475 IsEqualGUID( riid
, &IID_IUnknown
) )
481 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
482 return E_NOINTERFACE
;
485 ICLRRuntimeHost_AddRef( iface
);
490 static ULONG WINAPI
CLRRuntimeHost_AddRef(ICLRRuntimeHost
* iface
)
492 RuntimeHost
*This
= impl_from_ICLRRuntimeHost( iface
);
493 return ICorRuntimeHost_AddRef(&This
->ICorRuntimeHost_iface
);
496 static ULONG WINAPI
CLRRuntimeHost_Release(ICLRRuntimeHost
* iface
)
498 RuntimeHost
*This
= impl_from_ICLRRuntimeHost( iface
);
499 return ICorRuntimeHost_Release(&This
->ICorRuntimeHost_iface
);
502 static HRESULT WINAPI
CLRRuntimeHost_Start(ICLRRuntimeHost
* iface
)
504 FIXME("(%p)\n", iface
);
508 static HRESULT WINAPI
CLRRuntimeHost_Stop(ICLRRuntimeHost
* iface
)
510 FIXME("(%p)\n", iface
);
514 static HRESULT WINAPI
CLRRuntimeHost_SetHostControl(ICLRRuntimeHost
* iface
,
515 IHostControl
*pHostControl
)
517 FIXME("(%p,%p)\n", iface
, pHostControl
);
521 static HRESULT WINAPI
CLRRuntimeHost_GetCLRControl(ICLRRuntimeHost
* iface
,
522 ICLRControl
**pCLRControl
)
524 FIXME("(%p,%p)\n", iface
, pCLRControl
);
528 static HRESULT WINAPI
CLRRuntimeHost_UnloadAppDomain(ICLRRuntimeHost
* iface
,
529 DWORD dwAppDomainId
, BOOL fWaitUntilDone
)
531 FIXME("(%p,%u,%i)\n", iface
, dwAppDomainId
, fWaitUntilDone
);
535 static HRESULT WINAPI
CLRRuntimeHost_ExecuteInAppDomain(ICLRRuntimeHost
* iface
,
536 DWORD dwAppDomainId
, FExecuteInAppDomainCallback pCallback
, void *cookie
)
538 FIXME("(%p,%u,%p,%p)\n", iface
, dwAppDomainId
, pCallback
, cookie
);
542 static HRESULT WINAPI
CLRRuntimeHost_GetCurrentAppDomainId(ICLRRuntimeHost
* iface
,
543 DWORD
*pdwAppDomainId
)
545 FIXME("(%p,%p)\n", iface
, pdwAppDomainId
);
549 static HRESULT WINAPI
CLRRuntimeHost_ExecuteApplication(ICLRRuntimeHost
* iface
,
550 LPCWSTR pwzAppFullName
, DWORD dwManifestPaths
, LPCWSTR
*ppwzManifestPaths
,
551 DWORD dwActivationData
, LPCWSTR
*ppwzActivationData
, int *pReturnValue
)
553 FIXME("(%p,%s,%u,%u)\n", iface
, debugstr_w(pwzAppFullName
), dwManifestPaths
, dwActivationData
);
557 static HRESULT WINAPI
CLRRuntimeHost_ExecuteInDefaultAppDomain(ICLRRuntimeHost
* iface
,
558 LPCWSTR pwzAssemblyPath
, LPCWSTR pwzTypeName
, LPCWSTR pwzMethodName
,
559 LPCWSTR pwzArgument
, DWORD
*pReturnValue
)
561 RuntimeHost
*This
= impl_from_ICLRRuntimeHost( iface
);
564 MonoAssembly
*assembly
;
571 char *filenameA
= NULL
, *classA
= NULL
, *methodA
= NULL
;
572 char *argsA
= NULL
, *ns
;
574 TRACE("(%p,%s,%s,%s,%s)\n", iface
, debugstr_w(pwzAssemblyPath
),
575 debugstr_w(pwzTypeName
), debugstr_w(pwzMethodName
), debugstr_w(pwzArgument
));
577 hr
= RuntimeHost_GetDefaultDomain(This
, &domain
);
580 ERR("Couldn't get Default Domain\n");
586 This
->mono
->mono_thread_attach(domain
);
588 filenameA
= WtoA(pwzAssemblyPath
);
589 assembly
= This
->mono
->mono_domain_assembly_open(domain
, filenameA
);
592 ERR("Cannot open assembly %s\n", filenameA
);
596 image
= This
->mono
->mono_assembly_get_image(assembly
);
599 ERR("Couldn't get assembly image\n");
603 classA
= WtoA(pwzTypeName
);
604 ns
= strrchr(classA
, '.');
606 klass
= This
->mono
->mono_class_from_name(image
, classA
, ns
+1);
609 ERR("Couldn't get class from image\n");
613 methodA
= WtoA(pwzMethodName
);
614 method
= This
->mono
->mono_class_get_method_from_name(klass
, methodA
, 1);
617 ERR("Couldn't get method from class\n");
621 /* The .NET function we are calling has the following declaration
622 * public static int functionName(String param)
624 argsA
= WtoA(pwzArgument
);
625 str
= This
->mono
->mono_string_new(domain
, argsA
);
628 result
= This
->mono
->mono_runtime_invoke(method
, NULL
, args
, NULL
);
630 ERR("Couldn't get result pointer\n");
633 *pReturnValue
= *(DWORD
*)This
->mono
->mono_object_unbox(result
);
638 HeapFree(GetProcessHeap(), 0, filenameA
);
639 HeapFree(GetProcessHeap(), 0, classA
);
640 HeapFree(GetProcessHeap(), 0, argsA
);
641 HeapFree(GetProcessHeap(), 0, methodA
);
646 static const struct ICLRRuntimeHostVtbl CLRHostVtbl
=
648 CLRRuntimeHost_QueryInterface
,
649 CLRRuntimeHost_AddRef
,
650 CLRRuntimeHost_Release
,
651 CLRRuntimeHost_Start
,
653 CLRRuntimeHost_SetHostControl
,
654 CLRRuntimeHost_GetCLRControl
,
655 CLRRuntimeHost_UnloadAppDomain
,
656 CLRRuntimeHost_ExecuteInAppDomain
,
657 CLRRuntimeHost_GetCurrentAppDomainId
,
658 CLRRuntimeHost_ExecuteApplication
,
659 CLRRuntimeHost_ExecuteInDefaultAppDomain
662 /* Create an instance of a type given its name, by calling its constructor with
663 * no arguments. Note that result MUST be in the stack, or the garbage
664 * collector may free it prematurely. */
665 HRESULT
RuntimeHost_CreateManagedInstance(RuntimeHost
*This
, LPCWSTR name
,
666 MonoDomain
*domain
, MonoObject
**result
)
675 hr
= RuntimeHost_GetDefaultDomain(This
, &domain
);
686 This
->mono
->mono_thread_attach(domain
);
688 type
= This
->mono
->mono_reflection_type_from_name(nameA
, NULL
);
691 ERR("Cannot find type %s\n", debugstr_w(name
));
698 klass
= This
->mono
->mono_class_from_mono_type(type
);
701 ERR("Cannot convert type %s to a class\n", debugstr_w(name
));
708 obj
= This
->mono
->mono_object_new(domain
, klass
);
711 ERR("Cannot allocate object of type %s\n", debugstr_w(name
));
718 /* FIXME: Detect exceptions from the constructor? */
719 This
->mono
->mono_runtime_object_init(obj
);
723 HeapFree(GetProcessHeap(), 0, nameA
);
728 /* Get an IUnknown pointer for a Mono object.
730 * This is just a "light" wrapper around
731 * System.Runtime.InteropServices.Marshal:GetIUnknownForObject
733 * NOTE: The IUnknown* is created with a reference to the object.
734 * Until they have a reference, objects must be in the stack to prevent the
735 * garbage collector from freeing them.
737 * mono_thread_attach must have already been called for this thread. */
738 HRESULT
RuntimeHost_GetIUnknownForObject(RuntimeHost
*This
, MonoObject
*obj
,
742 MonoAssembly
*assembly
;
749 domain
= This
->mono
->mono_object_get_domain(obj
);
751 assembly
= This
->mono
->mono_domain_assembly_open(domain
, "mscorlib");
754 ERR("Cannot load mscorlib\n");
758 image
= This
->mono
->mono_assembly_get_image(assembly
);
761 ERR("Couldn't get assembly image\n");
765 klass
= This
->mono
->mono_class_from_name(image
, "System.Runtime.InteropServices", "Marshal");
768 ERR("Couldn't get class from image\n");
772 method
= This
->mono
->mono_class_get_method_from_name(klass
, "GetIUnknownForObject", 1);
775 ERR("Couldn't get method from class\n");
781 result
= This
->mono
->mono_runtime_invoke(method
, NULL
, args
, NULL
);
784 ERR("Couldn't get result pointer\n");
788 *ppUnk
= *(IUnknown
**)This
->mono
->mono_object_unbox(result
);
791 ERR("GetIUnknownForObject returned 0\n");
798 static void get_utf8_args(int *argc
, char ***argv
)
804 argvw
= CommandLineToArgvW(GetCommandLineW(), argc
);
806 for (i
=0; i
<*argc
; i
++)
808 size
+= sizeof(char*);
809 size
+= WideCharToMultiByte(CP_UTF8
, 0, argvw
[i
], -1, NULL
, 0, NULL
, NULL
);
811 size
+= sizeof(char*);
813 *argv
= HeapAlloc(GetProcessHeap(), 0, size
);
814 current_arg
= (char*)(*argv
+ *argc
+ 1);
816 for (i
=0; i
<*argc
; i
++)
818 (*argv
)[i
] = current_arg
;
819 current_arg
+= WideCharToMultiByte(CP_UTF8
, 0, argvw
[i
], -1, current_arg
, size
, NULL
, NULL
);
822 (*argv
)[*argc
] = NULL
;
824 HeapFree(GetProcessHeap(), 0, argvw
);
829 # define CAN_FIXUP_VTABLE 1
831 #include "pshpack1.h"
833 struct vtable_fixup_thunk
837 /* mov fixup,(%esp) */
839 struct dll_fixup
*fixup
;
840 /* mov function,%eax */
842 void (CDECL
*function
)(struct dll_fixup
*);
847 /* jmp *vtable_entry */
852 static const struct vtable_fixup_thunk thunk_template
= {
866 #else /* !defined(__i386__) */
868 # define CAN_FIXUP_VTABLE 0
870 struct vtable_fixup_thunk
872 struct dll_fixup
*fixup
;
873 void (CDECL
*function
)(struct dll_fixup
*fixup
);
877 static const struct vtable_fixup_thunk thunk_template
= {0};
881 static void CDECL
ReallyFixupVTable(struct dll_fixup
*fixup
)
884 WCHAR filename
[MAX_PATH
];
885 ICLRRuntimeInfo
*info
=NULL
;
888 MonoImage
*image
=NULL
;
889 MonoAssembly
*assembly
=NULL
;
890 MonoImageOpenStatus status
=0;
893 if (fixup
->done
) return;
895 /* It's possible we'll have two threads doing this at once. This is
896 * considered preferable to the potential deadlock if we use a mutex. */
898 GetModuleFileNameW(fixup
->dll
, filename
, MAX_PATH
);
900 TRACE("%p,%p,%s\n", fixup
, fixup
->dll
, debugstr_w(filename
));
902 filenameA
= WtoA(filename
);
907 hr
= get_runtime_info(filename
, NULL
, NULL
, 0, 0, FALSE
, &info
);
910 hr
= ICLRRuntimeInfo_GetRuntimeHost(info
, &host
);
913 hr
= RuntimeHost_GetDefaultDomain(host
, &domain
);
917 host
->mono
->mono_thread_attach(domain
);
919 image
= host
->mono
->mono_image_open_from_module_handle(fixup
->dll
,
920 filenameA
, 1, &status
);
924 assembly
= host
->mono
->mono_assembly_load_from(image
, filenameA
, &status
);
930 /* Mono needs an image that belongs to an assembly. */
931 image
= host
->mono
->mono_assembly_get_image(assembly
);
933 if (fixup
->fixup
->type
& COR_VTABLE_32BIT
)
935 DWORD
*vtable
= fixup
->vtable
;
936 DWORD
*tokens
= fixup
->tokens
;
937 for (i
=0; i
<fixup
->fixup
->count
; i
++)
939 TRACE("%x\n", tokens
[i
]);
940 vtable
[i
] = PtrToUint(host
->mono
->mono_marshal_get_vtfixup_ftnptr(
941 image
, tokens
[i
], fixup
->fixup
->type
));
949 ICLRRuntimeHost_Release(info
);
951 HeapFree(GetProcessHeap(), 0, filenameA
);
955 ERR("unable to fixup vtable, hr=%x, status=%d\n", hr
, status
);
956 /* If we returned now, we'd get an infinite loop. */
961 static void FixupVTableEntry(HMODULE hmodule
, VTableFixup
*vtable_fixup
)
963 /* We can't actually generate code for the functions without loading mono,
964 * and loading mono inside DllMain is a terrible idea. So we make thunks
965 * that call ReallyFixupVTable, which will load the runtime and fill in the
966 * vtable, then do an indirect jump using the (now filled in) vtable. Note
967 * that we have to keep the thunks around forever, as one of them may get
968 * called while we're filling in the table, and we can never be sure all
969 * threads are clear. */
970 struct dll_fixup
*fixup
;
972 fixup
= HeapAlloc(GetProcessHeap(), 0, sizeof(*fixup
));
974 fixup
->dll
= hmodule
;
975 fixup
->thunk_code
= HeapAlloc(dll_fixup_heap
, 0, sizeof(struct vtable_fixup_thunk
) * vtable_fixup
->count
);
976 fixup
->fixup
= vtable_fixup
;
977 fixup
->vtable
= (BYTE
*)hmodule
+ vtable_fixup
->rva
;
980 if (vtable_fixup
->type
& COR_VTABLE_32BIT
)
982 DWORD
*vtable
= fixup
->vtable
;
985 struct vtable_fixup_thunk
*thunks
= fixup
->thunk_code
;
987 if (sizeof(void*) > 4)
988 ERR("32-bit fixup in 64-bit mode; broken image?\n");
990 tokens
= fixup
->tokens
= HeapAlloc(GetProcessHeap(), 0, sizeof(*tokens
) * vtable_fixup
->count
);
991 memcpy(tokens
, vtable
, sizeof(*tokens
) * vtable_fixup
->count
);
992 for (i
=0; i
<vtable_fixup
->count
; i
++)
994 memcpy(&thunks
[i
], &thunk_template
, sizeof(thunk_template
));
995 thunks
[i
].fixup
= fixup
;
996 thunks
[i
].function
= ReallyFixupVTable
;
997 thunks
[i
].vtable_entry
= &vtable
[i
];
998 vtable
[i
] = PtrToUint(&thunks
[i
]);
1003 ERR("unsupported vtable fixup flags %x\n", vtable_fixup
->type
);
1004 HeapFree(dll_fixup_heap
, 0, fixup
->thunk_code
);
1005 HeapFree(GetProcessHeap(), 0, fixup
);
1009 list_add_tail(&dll_fixups
, &fixup
->entry
);
1012 static void FixupVTable(HMODULE hmodule
)
1016 VTableFixup
*vtable_fixups
;
1017 ULONG vtable_fixup_count
, i
;
1019 hr
= assembly_from_hmodule(&assembly
, hmodule
);
1022 hr
= assembly_get_vtable_fixups(assembly
, &vtable_fixups
, &vtable_fixup_count
);
1023 if (CAN_FIXUP_VTABLE
)
1024 for (i
=0; i
<vtable_fixup_count
; i
++)
1025 FixupVTableEntry(hmodule
, &vtable_fixups
[i
]);
1026 else if (vtable_fixup_count
)
1027 FIXME("cannot fixup vtable; expect a crash\n");
1029 assembly_release(assembly
);
1032 ERR("failed to read CLR headers, hr=%x\n", hr
);
1035 __int32 WINAPI
_CorExeMain(void)
1042 MonoImageOpenStatus status
;
1043 MonoAssembly
*assembly
=NULL
;
1044 WCHAR filename
[MAX_PATH
];
1046 ICLRRuntimeInfo
*info
;
1051 get_utf8_args(&argc
, &argv
);
1053 GetModuleFileNameW(NULL
, filename
, MAX_PATH
);
1055 TRACE("%s", debugstr_w(filename
));
1056 for (i
=0; i
<argc
; i
++)
1057 TRACE(" %s", debugstr_a(argv
[i
]));
1060 filenameA
= WtoA(filename
);
1064 FixupVTable(GetModuleHandleW(NULL
));
1066 hr
= get_runtime_info(filename
, NULL
, NULL
, 0, 0, FALSE
, &info
);
1070 hr
= ICLRRuntimeInfo_GetRuntimeHost(info
, &host
);
1073 hr
= RuntimeHost_GetDefaultDomain(host
, &domain
);
1077 image
= host
->mono
->mono_image_open_from_module_handle(GetModuleHandleW(NULL
),
1078 filenameA
, 1, &status
);
1081 assembly
= host
->mono
->mono_assembly_load_from(image
, filenameA
, &status
);
1085 exit_code
= host
->mono
->mono_jit_exec(domain
, assembly
, argc
, argv
);
1089 ERR("couldn't load %s, status=%d\n", debugstr_w(filename
), status
);
1093 RuntimeHost_DeleteDomain(host
, domain
);
1098 ICLRRuntimeInfo_Release(info
);
1103 HeapFree(GetProcessHeap(), 0, argv
);
1105 unload_all_runtimes();
1110 BOOL WINAPI
_CorDllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
1112 TRACE("(%p, %d, %p)\n", hinstDLL
, fdwReason
, lpvReserved
);
1116 case DLL_PROCESS_ATTACH
:
1117 DisableThreadLibraryCalls(hinstDLL
);
1118 FixupVTable(hinstDLL
);
1120 case DLL_PROCESS_DETACH
:
1121 /* FIXME: clean up the vtables */
1127 /* called from DLL_PROCESS_ATTACH */
1128 void runtimehost_init(void)
1130 dll_fixup_heap
= HeapCreate(HEAP_CREATE_ENABLE_EXECUTE
, 0, 0);
1131 list_init(&dll_fixups
);
1134 /* called from DLL_PROCESS_DETACH */
1135 void runtimehost_uninit(void)
1137 struct dll_fixup
*fixup
, *fixup2
;
1139 HeapDestroy(dll_fixup_heap
);
1140 LIST_FOR_EACH_ENTRY_SAFE(fixup
, fixup2
, &dll_fixups
, struct dll_fixup
, entry
)
1142 HeapFree(GetProcessHeap(), 0, fixup
->tokens
);
1143 HeapFree(GetProcessHeap(), 0, fixup
);
1147 HRESULT
RuntimeHost_Construct(const CLRRuntimeInfo
*runtime_version
,
1148 loaded_mono
*loaded_mono
, RuntimeHost
** result
)
1152 This
= HeapAlloc( GetProcessHeap(), 0, sizeof *This
);
1154 return E_OUTOFMEMORY
;
1156 This
->ICorRuntimeHost_iface
.lpVtbl
= &corruntimehost_vtbl
;
1157 This
->ICLRRuntimeHost_iface
.lpVtbl
= &CLRHostVtbl
;
1160 This
->version
= runtime_version
;
1161 This
->mono
= loaded_mono
;
1162 list_init(&This
->domains
);
1163 This
->default_domain
= NULL
;
1164 InitializeCriticalSection(&This
->lock
);
1165 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": RuntimeHost.lock");
1172 HRESULT
RuntimeHost_GetInterface(RuntimeHost
*This
, REFCLSID clsid
, REFIID riid
, void **ppv
)
1177 if (IsEqualGUID(clsid
, &CLSID_CorRuntimeHost
))
1179 unk
= (IUnknown
*)&This
->ICorRuntimeHost_iface
;
1180 IUnknown_AddRef(unk
);
1182 else if (IsEqualGUID(clsid
, &CLSID_CLRRuntimeHost
))
1184 unk
= (IUnknown
*)&This
->ICLRRuntimeHost_iface
;
1185 IUnknown_AddRef(unk
);
1187 else if (IsEqualGUID(clsid
, &CLSID_CorMetaDataDispenser
) ||
1188 IsEqualGUID(clsid
, &CLSID_CorMetaDataDispenserRuntime
))
1190 hr
= MetaDataDispenser_CreateInstance(&unk
);
1194 else if (IsEqualGUID(clsid
, &CLSID_CLRDebuggingLegacy
))
1196 hr
= CorDebug_Create(&This
->ICLRRuntimeHost_iface
, &unk
);
1205 hr
= IUnknown_QueryInterface(unk
, riid
, ppv
);
1207 IUnknown_Release(unk
);
1212 FIXME("not implemented for class %s\n", debugstr_guid(clsid
));
1214 return CLASS_E_CLASSNOTAVAILABLE
;
1217 HRESULT
RuntimeHost_Destroy(RuntimeHost
*This
)
1219 struct DomainEntry
*cursor
, *cursor2
;
1221 This
->lock
.DebugInfo
->Spare
[0] = 0;
1222 DeleteCriticalSection(&This
->lock
);
1224 LIST_FOR_EACH_ENTRY_SAFE(cursor
, cursor2
, &This
->domains
, struct DomainEntry
, entry
)
1226 list_remove(&cursor
->entry
);
1227 HeapFree(GetProcessHeap(), 0, cursor
);
1230 HeapFree( GetProcessHeap(), 0, This
);
1234 #define CHARS_IN_GUID 39
1235 #define ARRAYSIZE(array) (sizeof(array)/sizeof((array)[0]))
1237 HRESULT
create_monodata(REFIID riid
, LPVOID
*ppObj
)
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];
1246 MonoAssembly
*assembly
;
1247 ICLRRuntimeInfo
*info
;
1253 WCHAR codebase
[MAX_PATH
+ 8];
1254 WCHAR classname
[350];
1255 WCHAR filename
[MAX_PATH
];
1257 DWORD dwBufLen
= 350;
1259 lstrcpyW(path
, wszCLSIDSlash
);
1260 StringFromGUID2(riid
, path
+ lstrlenW(wszCLSIDSlash
), CHARS_IN_GUID
);
1261 lstrcatW(path
, wszInprocServer32
);
1263 TRACE("Registry key: %s\n", debugstr_w(path
));
1265 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, path
, 0, KEY_READ
, &key
);
1266 if (res
== ERROR_FILE_NOT_FOUND
)
1267 return CLASS_E_CLASSNOTAVAILABLE
;
1269 res
= RegGetValueW( key
, NULL
, wszClass
, RRF_RT_REG_SZ
, NULL
, classname
, &dwBufLen
);
1270 if(res
!= ERROR_SUCCESS
)
1272 WARN("Class value cannot be found.\n");
1273 hr
= CLASS_E_CLASSNOTAVAILABLE
;
1277 TRACE("classname (%s)\n", debugstr_w(classname
));
1279 dwBufLen
= MAX_PATH
+ 8;
1280 res
= RegGetValueW( key
, NULL
, wszCodebase
, RRF_RT_REG_SZ
, NULL
, codebase
, &dwBufLen
);
1281 if(res
!= ERROR_SUCCESS
)
1283 WARN("CodeBase value cannot be found.\n");
1284 hr
= CLASS_E_CLASSNOTAVAILABLE
;
1288 /* Strip file:/// */
1289 if(strncmpW(codebase
, wszFileSlash
, strlenW(wszFileSlash
)) == 0)
1290 offset
= strlenW(wszFileSlash
);
1292 strcpyW(filename
, codebase
+ offset
);
1294 TRACE("codebase (%s)\n", debugstr_w(filename
));
1299 hr
= get_runtime_info(filename
, NULL
, NULL
, 0, 0, FALSE
, &info
);
1302 hr
= ICLRRuntimeInfo_GetRuntimeHost(info
, &host
);
1305 hr
= RuntimeHost_GetDefaultDomain(host
, &domain
);
1312 IUnknown
*unk
= NULL
;
1313 char *filenameA
, *ns
;
1316 hr
= CLASS_E_CLASSNOTAVAILABLE
;
1318 host
->mono
->mono_thread_attach(domain
);
1320 filenameA
= WtoA(filename
);
1321 assembly
= host
->mono
->mono_domain_assembly_open(domain
, filenameA
);
1322 HeapFree(GetProcessHeap(), 0, filenameA
);
1325 ERR("Cannot open assembly %s\n", filenameA
);
1329 image
= host
->mono
->mono_assembly_get_image(assembly
);
1332 ERR("Couldn't get assembly image\n");
1336 classA
= WtoA(classname
);
1337 ns
= strrchr(classA
, '.');
1340 klass
= host
->mono
->mono_class_from_name(image
, classA
, ns
+1);
1341 HeapFree(GetProcessHeap(), 0, classA
);
1344 ERR("Couldn't get class from image\n");
1349 * Use the default constructor for the .NET class.
1351 result
= host
->mono
->mono_object_new(domain
, klass
);
1352 host
->mono
->mono_runtime_object_init(result
);
1354 hr
= RuntimeHost_GetIUnknownForObject(host
, result
, &unk
);
1357 hr
= IUnknown_QueryInterface(unk
, &IID_IUnknown
, ppObj
);
1359 IUnknown_Release(unk
);
1362 hr
= CLASS_E_CLASSNOTAVAILABLE
;
1365 hr
= CLASS_E_CLASSNOTAVAILABLE
;
1368 hr
= CLASS_E_CLASSNOTAVAILABLE
;
1372 ICLRRuntimeInfo_Release(info
);