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
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
);
48 DEFINE_GUID(IID__AppDomain
, 0x05f696dc,0x2b29,0x3663,0xad,0x8b,0xc4,0x38,0x9c,0xf2,0xa7,0x13);
56 static HANDLE dll_fixup_heap
; /* using a separate heap so we can have execute permission */
58 static struct list dll_fixups
;
65 void *thunk_code
; /* pointer into dll_fixup_heap */
68 void *tokens
; /* pointer into process heap */
71 static HRESULT
RuntimeHost_AddDomain(RuntimeHost
*This
, MonoDomain
**result
)
73 struct DomainEntry
*entry
;
77 EnterCriticalSection(&This
->lock
);
79 entry
= HeapAlloc(GetProcessHeap(), 0, sizeof(*entry
));
86 mscorlib_path
= WtoA(This
->version
->mscorlib_path
);
89 HeapFree(GetProcessHeap(), 0, entry
);
94 entry
->domain
= mono_jit_init(mscorlib_path
);
96 HeapFree(GetProcessHeap(), 0, mscorlib_path
);
100 HeapFree(GetProcessHeap(), 0, entry
);
105 is_mono_started
= TRUE
;
107 list_add_tail(&This
->domains
, &entry
->entry
);
109 *result
= entry
->domain
;
112 LeaveCriticalSection(&This
->lock
);
117 static HRESULT
RuntimeHost_GetDefaultDomain(RuntimeHost
*This
, MonoDomain
**result
)
121 EnterCriticalSection(&This
->lock
);
123 if (This
->default_domain
) goto end
;
125 res
= RuntimeHost_AddDomain(This
, &This
->default_domain
);
128 *result
= This
->default_domain
;
130 LeaveCriticalSection(&This
->lock
);
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
);
153 LeaveCriticalSection(&This
->lock
);
156 static HRESULT
RuntimeHost_GetIUnknownForDomain(RuntimeHost
*This
, MonoDomain
*domain
, IUnknown
**punk
)
160 MonoAssembly
*assembly
;
164 MonoObject
*appdomain_object
;
167 mono_thread_attach(domain
);
169 assembly
= mono_domain_assembly_open(domain
, "mscorlib");
172 ERR("Cannot load mscorlib\n");
176 image
= mono_assembly_get_image(assembly
);
179 ERR("Couldn't get assembly image\n");
183 klass
= mono_class_from_name(image
, "System", "AppDomain");
186 ERR("Couldn't get class from image\n");
190 method
= mono_class_get_method_from_name(klass
, "get_CurrentDomain", 0);
193 ERR("Couldn't get method from class\n");
198 appdomain_object
= mono_runtime_invoke(method
, NULL
, args
, NULL
);
199 if (!appdomain_object
)
201 ERR("Couldn't get result pointer\n");
205 hr
= RuntimeHost_GetIUnknownForObject(This
, appdomain_object
, &unk
);
209 hr
= IUnknown_QueryInterface(unk
, &IID__AppDomain
, (void**)punk
);
211 IUnknown_Release(unk
);
217 void RuntimeHost_ExitProcess(RuntimeHost
*This
, INT exitcode
)
222 MonoAssembly
*assembly
;
227 hr
= RuntimeHost_GetDefaultDomain(This
, &domain
);
230 ERR("Cannot get domain, hr=%x\n", hr
);
234 mono_thread_attach(domain
);
236 assembly
= mono_domain_assembly_open(domain
, "mscorlib");
239 ERR("Cannot load mscorlib\n");
243 image
= mono_assembly_get_image(assembly
);
246 ERR("Couldn't get assembly image\n");
250 klass
= mono_class_from_name(image
, "System", "Environment");
253 ERR("Couldn't get class from image\n");
257 method
= mono_class_get_method_from_name(klass
, "Exit", 1);
260 ERR("Couldn't get method from class\n");
266 mono_runtime_invoke(method
, NULL
, args
, NULL
);
268 ERR("Process should have exited\n");
271 static inline RuntimeHost
*impl_from_ICLRRuntimeHost( ICLRRuntimeHost
*iface
)
273 return CONTAINING_RECORD(iface
, RuntimeHost
, ICLRRuntimeHost_iface
);
276 static inline RuntimeHost
*impl_from_ICorRuntimeHost( ICorRuntimeHost
*iface
)
278 return CONTAINING_RECORD(iface
, RuntimeHost
, ICorRuntimeHost_iface
);
281 /*** IUnknown methods ***/
282 static HRESULT WINAPI
corruntimehost_QueryInterface(ICorRuntimeHost
* iface
,
286 RuntimeHost
*This
= impl_from_ICorRuntimeHost( iface
);
287 TRACE("%p %s %p\n", This
, debugstr_guid(riid
), ppvObject
);
289 if ( IsEqualGUID( riid
, &IID_ICorRuntimeHost
) ||
290 IsEqualGUID( riid
, &IID_IUnknown
) )
296 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
297 return E_NOINTERFACE
;
300 ICorRuntimeHost_AddRef( iface
);
305 static ULONG WINAPI
corruntimehost_AddRef(ICorRuntimeHost
* iface
)
307 RuntimeHost
*This
= impl_from_ICorRuntimeHost( iface
);
309 return InterlockedIncrement( &This
->ref
);
312 static ULONG WINAPI
corruntimehost_Release(ICorRuntimeHost
* iface
)
314 RuntimeHost
*This
= impl_from_ICorRuntimeHost( iface
);
317 ref
= InterlockedDecrement( &This
->ref
);
322 /*** ICorRuntimeHost methods ***/
323 static HRESULT WINAPI
corruntimehost_CreateLogicalThreadState(
324 ICorRuntimeHost
* iface
)
326 FIXME("stub %p\n", iface
);
330 static HRESULT WINAPI
corruntimehost_DeleteLogicalThreadState(
331 ICorRuntimeHost
* iface
)
333 FIXME("stub %p\n", iface
);
337 static HRESULT WINAPI
corruntimehost_SwitchInLogicalThreadState(
338 ICorRuntimeHost
* iface
,
341 FIXME("stub %p\n", iface
);
345 static HRESULT WINAPI
corruntimehost_SwitchOutLogicalThreadState(
346 ICorRuntimeHost
* iface
,
349 FIXME("stub %p\n", iface
);
353 static HRESULT WINAPI
corruntimehost_LocksHeldByLogicalThread(
354 ICorRuntimeHost
* iface
,
357 FIXME("stub %p\n", iface
);
361 static HRESULT WINAPI
corruntimehost_MapFile(
362 ICorRuntimeHost
* iface
,
366 FIXME("stub %p\n", iface
);
370 static HRESULT WINAPI
corruntimehost_GetConfiguration(
371 ICorRuntimeHost
* iface
,
372 ICorConfiguration
**pConfiguration
)
374 FIXME("stub %p\n", iface
);
378 static HRESULT WINAPI
corruntimehost_Start(
379 ICorRuntimeHost
* iface
)
381 FIXME("stub %p\n", iface
);
385 static HRESULT WINAPI
corruntimehost_Stop(
386 ICorRuntimeHost
* iface
)
388 FIXME("stub %p\n", iface
);
392 static HRESULT WINAPI
corruntimehost_CreateDomain(
393 ICorRuntimeHost
* iface
,
394 LPCWSTR friendlyName
,
395 IUnknown
*identityArray
,
396 IUnknown
**appDomain
)
398 FIXME("stub %p\n", iface
);
402 static HRESULT WINAPI
corruntimehost_GetDefaultDomain(
403 ICorRuntimeHost
* iface
,
404 IUnknown
**pAppDomain
)
406 RuntimeHost
*This
= impl_from_ICorRuntimeHost( iface
);
410 TRACE("(%p)\n", iface
);
412 hr
= RuntimeHost_GetDefaultDomain(This
, &domain
);
416 hr
= RuntimeHost_GetIUnknownForDomain(This
, domain
, pAppDomain
);
422 static HRESULT WINAPI
corruntimehost_EnumDomains(
423 ICorRuntimeHost
* iface
,
426 FIXME("stub %p\n", iface
);
430 static HRESULT WINAPI
corruntimehost_NextDomain(
431 ICorRuntimeHost
* iface
,
433 IUnknown
**appDomain
)
435 FIXME("stub %p\n", iface
);
439 static HRESULT WINAPI
corruntimehost_CloseEnum(
440 ICorRuntimeHost
* iface
,
443 FIXME("stub %p\n", iface
);
447 static HRESULT WINAPI
corruntimehost_CreateDomainEx(
448 ICorRuntimeHost
* iface
,
449 LPCWSTR friendlyName
,
452 IUnknown
**appDomain
)
454 FIXME("stub %p\n", iface
);
458 static HRESULT WINAPI
corruntimehost_CreateDomainSetup(
459 ICorRuntimeHost
* iface
,
460 IUnknown
**appDomainSetup
)
462 FIXME("stub %p\n", iface
);
466 static HRESULT WINAPI
corruntimehost_CreateEvidence(
467 ICorRuntimeHost
* iface
,
470 FIXME("stub %p\n", iface
);
474 static HRESULT WINAPI
corruntimehost_UnloadDomain(
475 ICorRuntimeHost
* iface
,
478 FIXME("stub %p\n", iface
);
482 static HRESULT WINAPI
corruntimehost_CurrentDomain(
483 ICorRuntimeHost
* iface
,
484 IUnknown
**appDomain
)
486 FIXME("stub %p\n", iface
);
490 static const struct ICorRuntimeHostVtbl corruntimehost_vtbl
=
492 corruntimehost_QueryInterface
,
493 corruntimehost_AddRef
,
494 corruntimehost_Release
,
495 corruntimehost_CreateLogicalThreadState
,
496 corruntimehost_DeleteLogicalThreadState
,
497 corruntimehost_SwitchInLogicalThreadState
,
498 corruntimehost_SwitchOutLogicalThreadState
,
499 corruntimehost_LocksHeldByLogicalThread
,
500 corruntimehost_MapFile
,
501 corruntimehost_GetConfiguration
,
502 corruntimehost_Start
,
504 corruntimehost_CreateDomain
,
505 corruntimehost_GetDefaultDomain
,
506 corruntimehost_EnumDomains
,
507 corruntimehost_NextDomain
,
508 corruntimehost_CloseEnum
,
509 corruntimehost_CreateDomainEx
,
510 corruntimehost_CreateDomainSetup
,
511 corruntimehost_CreateEvidence
,
512 corruntimehost_UnloadDomain
,
513 corruntimehost_CurrentDomain
516 static HRESULT WINAPI
CLRRuntimeHost_QueryInterface(ICLRRuntimeHost
* iface
,
520 RuntimeHost
*This
= impl_from_ICLRRuntimeHost( iface
);
521 TRACE("%p %s %p\n", This
, debugstr_guid(riid
), ppvObject
);
523 if ( IsEqualGUID( riid
, &IID_ICLRRuntimeHost
) ||
524 IsEqualGUID( riid
, &IID_IUnknown
) )
530 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
531 return E_NOINTERFACE
;
534 ICLRRuntimeHost_AddRef( iface
);
539 static ULONG WINAPI
CLRRuntimeHost_AddRef(ICLRRuntimeHost
* iface
)
541 RuntimeHost
*This
= impl_from_ICLRRuntimeHost( iface
);
542 return ICorRuntimeHost_AddRef(&This
->ICorRuntimeHost_iface
);
545 static ULONG WINAPI
CLRRuntimeHost_Release(ICLRRuntimeHost
* iface
)
547 RuntimeHost
*This
= impl_from_ICLRRuntimeHost( iface
);
548 return ICorRuntimeHost_Release(&This
->ICorRuntimeHost_iface
);
551 static HRESULT WINAPI
CLRRuntimeHost_Start(ICLRRuntimeHost
* iface
)
553 FIXME("(%p)\n", iface
);
557 static HRESULT WINAPI
CLRRuntimeHost_Stop(ICLRRuntimeHost
* iface
)
559 FIXME("(%p)\n", iface
);
563 static HRESULT WINAPI
CLRRuntimeHost_SetHostControl(ICLRRuntimeHost
* iface
,
564 IHostControl
*pHostControl
)
566 FIXME("(%p,%p)\n", iface
, pHostControl
);
570 static HRESULT WINAPI
CLRRuntimeHost_GetCLRControl(ICLRRuntimeHost
* iface
,
571 ICLRControl
**pCLRControl
)
573 FIXME("(%p,%p)\n", iface
, pCLRControl
);
577 static HRESULT WINAPI
CLRRuntimeHost_UnloadAppDomain(ICLRRuntimeHost
* iface
,
578 DWORD dwAppDomainId
, BOOL fWaitUntilDone
)
580 FIXME("(%p,%u,%i)\n", iface
, dwAppDomainId
, fWaitUntilDone
);
584 static HRESULT WINAPI
CLRRuntimeHost_ExecuteInAppDomain(ICLRRuntimeHost
* iface
,
585 DWORD dwAppDomainId
, FExecuteInAppDomainCallback pCallback
, void *cookie
)
587 FIXME("(%p,%u,%p,%p)\n", iface
, dwAppDomainId
, pCallback
, cookie
);
591 static HRESULT WINAPI
CLRRuntimeHost_GetCurrentAppDomainId(ICLRRuntimeHost
* iface
,
592 DWORD
*pdwAppDomainId
)
594 FIXME("(%p,%p)\n", iface
, pdwAppDomainId
);
598 static HRESULT WINAPI
CLRRuntimeHost_ExecuteApplication(ICLRRuntimeHost
* iface
,
599 LPCWSTR pwzAppFullName
, DWORD dwManifestPaths
, LPCWSTR
*ppwzManifestPaths
,
600 DWORD dwActivationData
, LPCWSTR
*ppwzActivationData
, int *pReturnValue
)
602 FIXME("(%p,%s,%u,%u)\n", iface
, debugstr_w(pwzAppFullName
), dwManifestPaths
, dwActivationData
);
606 static HRESULT WINAPI
CLRRuntimeHost_ExecuteInDefaultAppDomain(ICLRRuntimeHost
* iface
,
607 LPCWSTR pwzAssemblyPath
, LPCWSTR pwzTypeName
, LPCWSTR pwzMethodName
,
608 LPCWSTR pwzArgument
, DWORD
*pReturnValue
)
610 RuntimeHost
*This
= impl_from_ICLRRuntimeHost( iface
);
613 MonoAssembly
*assembly
;
620 char *filenameA
= NULL
, *classA
= NULL
, *methodA
= NULL
;
621 char *argsA
= NULL
, *ns
;
623 TRACE("(%p,%s,%s,%s,%s)\n", iface
, debugstr_w(pwzAssemblyPath
),
624 debugstr_w(pwzTypeName
), debugstr_w(pwzMethodName
), debugstr_w(pwzArgument
));
626 hr
= RuntimeHost_GetDefaultDomain(This
, &domain
);
629 ERR("Couldn't get Default Domain\n");
635 mono_thread_attach(domain
);
637 filenameA
= WtoA(pwzAssemblyPath
);
638 assembly
= mono_domain_assembly_open(domain
, filenameA
);
641 ERR("Cannot open assembly %s\n", filenameA
);
645 image
= mono_assembly_get_image(assembly
);
648 ERR("Couldn't get assembly image\n");
652 classA
= WtoA(pwzTypeName
);
653 ns
= strrchr(classA
, '.');
655 klass
= mono_class_from_name(image
, classA
, ns
+1);
658 ERR("Couldn't get class from image\n");
662 methodA
= WtoA(pwzMethodName
);
663 method
= mono_class_get_method_from_name(klass
, methodA
, 1);
666 ERR("Couldn't get method from class\n");
670 /* The .NET function we are calling has the following declaration
671 * public static int functionName(String param)
673 argsA
= WtoA(pwzArgument
);
674 str
= mono_string_new(domain
, argsA
);
677 result
= mono_runtime_invoke(method
, NULL
, args
, NULL
);
679 ERR("Couldn't get result pointer\n");
682 *pReturnValue
= *(DWORD
*)mono_object_unbox(result
);
687 HeapFree(GetProcessHeap(), 0, filenameA
);
688 HeapFree(GetProcessHeap(), 0, classA
);
689 HeapFree(GetProcessHeap(), 0, argsA
);
690 HeapFree(GetProcessHeap(), 0, methodA
);
695 static const struct ICLRRuntimeHostVtbl CLRHostVtbl
=
697 CLRRuntimeHost_QueryInterface
,
698 CLRRuntimeHost_AddRef
,
699 CLRRuntimeHost_Release
,
700 CLRRuntimeHost_Start
,
702 CLRRuntimeHost_SetHostControl
,
703 CLRRuntimeHost_GetCLRControl
,
704 CLRRuntimeHost_UnloadAppDomain
,
705 CLRRuntimeHost_ExecuteInAppDomain
,
706 CLRRuntimeHost_GetCurrentAppDomainId
,
707 CLRRuntimeHost_ExecuteApplication
,
708 CLRRuntimeHost_ExecuteInDefaultAppDomain
711 /* Create an instance of a type given its name, by calling its constructor with
712 * no arguments. Note that result MUST be in the stack, or the garbage
713 * collector may free it prematurely. */
714 HRESULT
RuntimeHost_CreateManagedInstance(RuntimeHost
*This
, LPCWSTR name
,
715 MonoDomain
*domain
, MonoObject
**result
)
724 hr
= RuntimeHost_GetDefaultDomain(This
, &domain
);
735 mono_thread_attach(domain
);
737 type
= mono_reflection_type_from_name(nameA
, NULL
);
740 ERR("Cannot find type %s\n", debugstr_w(name
));
747 klass
= mono_class_from_mono_type(type
);
750 ERR("Cannot convert type %s to a class\n", debugstr_w(name
));
757 obj
= mono_object_new(domain
, klass
);
760 ERR("Cannot allocate object of type %s\n", debugstr_w(name
));
767 /* FIXME: Detect exceptions from the constructor? */
768 mono_runtime_object_init(obj
);
772 HeapFree(GetProcessHeap(), 0, nameA
);
777 /* Get an IUnknown pointer for a Mono object.
779 * This is just a "light" wrapper around
780 * System.Runtime.InteropServices.Marshal:GetIUnknownForObject
782 * NOTE: The IUnknown* is created with a reference to the object.
783 * Until they have a reference, objects must be in the stack to prevent the
784 * garbage collector from freeing them.
786 * mono_thread_attach must have already been called for this thread. */
787 HRESULT
RuntimeHost_GetIUnknownForObject(RuntimeHost
*This
, MonoObject
*obj
,
791 MonoAssembly
*assembly
;
798 domain
= mono_object_get_domain(obj
);
800 assembly
= mono_domain_assembly_open(domain
, "mscorlib");
803 ERR("Cannot load mscorlib\n");
807 image
= mono_assembly_get_image(assembly
);
810 ERR("Couldn't get assembly image\n");
814 klass
= mono_class_from_name(image
, "System.Runtime.InteropServices", "Marshal");
817 ERR("Couldn't get class from image\n");
821 method
= mono_class_get_method_from_name(klass
, "GetIUnknownForObject", 1);
824 ERR("Couldn't get method from class\n");
830 result
= mono_runtime_invoke(method
, NULL
, args
, NULL
);
833 ERR("Couldn't get result pointer\n");
837 *ppUnk
= *(IUnknown
**)mono_object_unbox(result
);
840 ERR("GetIUnknownForObject returned 0\n");
847 static void get_utf8_args(int *argc
, char ***argv
)
853 argvw
= CommandLineToArgvW(GetCommandLineW(), argc
);
855 for (i
=0; i
<*argc
; i
++)
857 size
+= sizeof(char*);
858 size
+= WideCharToMultiByte(CP_UTF8
, 0, argvw
[i
], -1, NULL
, 0, NULL
, NULL
);
860 size
+= sizeof(char*);
862 *argv
= HeapAlloc(GetProcessHeap(), 0, size
);
863 current_arg
= (char*)(*argv
+ *argc
+ 1);
865 for (i
=0; i
<*argc
; i
++)
867 (*argv
)[i
] = current_arg
;
868 current_arg
+= WideCharToMultiByte(CP_UTF8
, 0, argvw
[i
], -1, current_arg
, size
, NULL
, NULL
);
871 (*argv
)[*argc
] = NULL
;
873 HeapFree(GetProcessHeap(), 0, argvw
);
878 # define CAN_FIXUP_VTABLE 1
880 #include "pshpack1.h"
882 struct vtable_fixup_thunk
888 /* mov fixup,(%esp) */
890 struct dll_fixup
*fixup
;
891 /* mov function,%eax */
893 void (CDECL
*function
)(struct dll_fixup
*);
900 /* jmp *vtable_entry */
905 static const struct vtable_fixup_thunk thunk_template
= {
921 #else /* !defined(__i386__) */
923 # define CAN_FIXUP_VTABLE 0
925 struct vtable_fixup_thunk
927 struct dll_fixup
*fixup
;
928 void (CDECL
*function
)(struct dll_fixup
*fixup
);
932 static const struct vtable_fixup_thunk thunk_template
= {0};
936 static void CDECL
ReallyFixupVTable(struct dll_fixup
*fixup
)
939 WCHAR filename
[MAX_PATH
];
940 ICLRRuntimeInfo
*info
=NULL
;
943 MonoImage
*image
=NULL
;
944 MonoAssembly
*assembly
=NULL
;
945 MonoImageOpenStatus status
=0;
948 if (fixup
->done
) return;
950 /* It's possible we'll have two threads doing this at once. This is
951 * considered preferable to the potential deadlock if we use a mutex. */
953 GetModuleFileNameW(fixup
->dll
, filename
, MAX_PATH
);
955 TRACE("%p,%p,%s\n", fixup
, fixup
->dll
, debugstr_w(filename
));
957 filenameA
= WtoA(filename
);
962 hr
= get_runtime_info(filename
, NULL
, NULL
, 0, 0, FALSE
, &info
);
965 hr
= ICLRRuntimeInfo_GetRuntimeHost(info
, &host
);
968 hr
= RuntimeHost_GetDefaultDomain(host
, &domain
);
972 mono_thread_attach(domain
);
974 assembly
= mono_assembly_open(filenameA
, &status
);
981 /* Mono needs an image that belongs to an assembly. */
982 image
= mono_assembly_get_image(assembly
);
984 if (fixup
->fixup
->type
& COR_VTABLE_32BIT
)
986 DWORD
*vtable
= fixup
->vtable
;
987 DWORD
*tokens
= fixup
->tokens
;
988 for (i
=0; i
<fixup
->fixup
->count
; i
++)
990 TRACE("%x\n", tokens
[i
]);
991 vtable
[i
] = PtrToUint(mono_marshal_get_vtfixup_ftnptr(
992 image
, tokens
[i
], fixup
->fixup
->type
));
1000 ICLRRuntimeInfo_Release(info
);
1002 HeapFree(GetProcessHeap(), 0, filenameA
);
1006 ERR("unable to fixup vtable, hr=%x, status=%d\n", hr
, status
);
1007 /* If we returned now, we'd get an infinite loop. */
1012 static void FixupVTableEntry(HMODULE hmodule
, VTableFixup
*vtable_fixup
)
1014 /* We can't actually generate code for the functions without loading mono,
1015 * and loading mono inside DllMain is a terrible idea. So we make thunks
1016 * that call ReallyFixupVTable, which will load the runtime and fill in the
1017 * vtable, then do an indirect jump using the (now filled in) vtable. Note
1018 * that we have to keep the thunks around forever, as one of them may get
1019 * called while we're filling in the table, and we can never be sure all
1020 * threads are clear. */
1021 struct dll_fixup
*fixup
;
1023 fixup
= HeapAlloc(GetProcessHeap(), 0, sizeof(*fixup
));
1025 fixup
->dll
= hmodule
;
1026 fixup
->thunk_code
= HeapAlloc(dll_fixup_heap
, 0, sizeof(struct vtable_fixup_thunk
) * vtable_fixup
->count
);
1027 fixup
->fixup
= vtable_fixup
;
1028 fixup
->vtable
= (BYTE
*)hmodule
+ vtable_fixup
->rva
;
1029 fixup
->done
= FALSE
;
1031 if (vtable_fixup
->type
& COR_VTABLE_32BIT
)
1033 DWORD
*vtable
= fixup
->vtable
;
1036 struct vtable_fixup_thunk
*thunks
= fixup
->thunk_code
;
1038 if (sizeof(void*) > 4)
1039 ERR("32-bit fixup in 64-bit mode; broken image?\n");
1041 tokens
= fixup
->tokens
= HeapAlloc(GetProcessHeap(), 0, sizeof(*tokens
) * vtable_fixup
->count
);
1042 memcpy(tokens
, vtable
, sizeof(*tokens
) * vtable_fixup
->count
);
1043 for (i
=0; i
<vtable_fixup
->count
; i
++)
1045 thunks
[i
] = thunk_template
;
1046 thunks
[i
].fixup
= fixup
;
1047 thunks
[i
].function
= ReallyFixupVTable
;
1048 thunks
[i
].vtable_entry
= &vtable
[i
];
1049 vtable
[i
] = PtrToUint(&thunks
[i
]);
1054 ERR("unsupported vtable fixup flags %x\n", vtable_fixup
->type
);
1055 HeapFree(dll_fixup_heap
, 0, fixup
->thunk_code
);
1056 HeapFree(GetProcessHeap(), 0, fixup
);
1060 list_add_tail(&dll_fixups
, &fixup
->entry
);
1063 static void FixupVTable(HMODULE hmodule
)
1067 VTableFixup
*vtable_fixups
;
1068 ULONG vtable_fixup_count
, i
;
1070 hr
= assembly_from_hmodule(&assembly
, hmodule
);
1073 hr
= assembly_get_vtable_fixups(assembly
, &vtable_fixups
, &vtable_fixup_count
);
1074 if (CAN_FIXUP_VTABLE
)
1075 for (i
=0; i
<vtable_fixup_count
; i
++)
1076 FixupVTableEntry(hmodule
, &vtable_fixups
[i
]);
1077 else if (vtable_fixup_count
)
1078 FIXME("cannot fixup vtable; expect a crash\n");
1080 assembly_release(assembly
);
1083 ERR("failed to read CLR headers, hr=%x\n", hr
);
1086 __int32 WINAPI
_CorExeMain(void)
1091 MonoDomain
*domain
=NULL
;
1093 MonoImageOpenStatus status
;
1094 MonoAssembly
*assembly
=NULL
;
1095 WCHAR filename
[MAX_PATH
];
1097 ICLRRuntimeInfo
*info
;
1102 get_utf8_args(&argc
, &argv
);
1104 GetModuleFileNameW(NULL
, filename
, MAX_PATH
);
1106 TRACE("%s", debugstr_w(filename
));
1107 for (i
=0; i
<argc
; i
++)
1108 TRACE(" %s", debugstr_a(argv
[i
]));
1111 filenameA
= WtoA(filename
);
1115 FixupVTable(GetModuleHandleW(NULL
));
1117 hr
= get_runtime_info(filename
, NULL
, NULL
, 0, 0, FALSE
, &info
);
1121 hr
= ICLRRuntimeInfo_GetRuntimeHost(info
, &host
);
1124 hr
= RuntimeHost_GetDefaultDomain(host
, &domain
);
1128 image
= mono_image_open_from_module_handle(GetModuleHandleW(NULL
),
1129 filenameA
, 1, &status
);
1132 assembly
= mono_assembly_load_from(image
, filenameA
, &status
);
1136 mono_trace_set_assembly(assembly
);
1138 exit_code
= mono_jit_exec(domain
, assembly
, argc
, argv
);
1142 ERR("couldn't load %s, status=%d\n", debugstr_w(filename
), status
);
1146 RuntimeHost_DeleteDomain(host
, domain
);
1151 ICLRRuntimeInfo_Release(info
);
1156 HeapFree(GetProcessHeap(), 0, argv
);
1160 mono_thread_manage();
1161 mono_jit_cleanup(domain
);
1167 BOOL WINAPI
_CorDllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
1169 TRACE("(%p, %d, %p)\n", hinstDLL
, fdwReason
, lpvReserved
);
1173 case DLL_PROCESS_ATTACH
:
1174 DisableThreadLibraryCalls(hinstDLL
);
1175 FixupVTable(hinstDLL
);
1177 case DLL_PROCESS_DETACH
:
1178 /* FIXME: clean up the vtables */
1184 /* called from DLL_PROCESS_ATTACH */
1185 void runtimehost_init(void)
1187 dll_fixup_heap
= HeapCreate(HEAP_CREATE_ENABLE_EXECUTE
, 0, 0);
1188 list_init(&dll_fixups
);
1191 /* called from DLL_PROCESS_DETACH */
1192 void runtimehost_uninit(void)
1194 struct dll_fixup
*fixup
, *fixup2
;
1196 HeapDestroy(dll_fixup_heap
);
1197 LIST_FOR_EACH_ENTRY_SAFE(fixup
, fixup2
, &dll_fixups
, struct dll_fixup
, entry
)
1199 HeapFree(GetProcessHeap(), 0, fixup
->tokens
);
1200 HeapFree(GetProcessHeap(), 0, fixup
);
1204 HRESULT
RuntimeHost_Construct(const CLRRuntimeInfo
*runtime_version
, RuntimeHost
** result
)
1208 This
= HeapAlloc( GetProcessHeap(), 0, sizeof *This
);
1210 return E_OUTOFMEMORY
;
1212 This
->ICorRuntimeHost_iface
.lpVtbl
= &corruntimehost_vtbl
;
1213 This
->ICLRRuntimeHost_iface
.lpVtbl
= &CLRHostVtbl
;
1216 This
->version
= runtime_version
;
1217 list_init(&This
->domains
);
1218 This
->default_domain
= NULL
;
1219 InitializeCriticalSection(&This
->lock
);
1220 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": RuntimeHost.lock");
1227 HRESULT
RuntimeHost_GetInterface(RuntimeHost
*This
, REFCLSID clsid
, REFIID riid
, void **ppv
)
1232 if (IsEqualGUID(clsid
, &CLSID_CorRuntimeHost
))
1234 unk
= (IUnknown
*)&This
->ICorRuntimeHost_iface
;
1235 IUnknown_AddRef(unk
);
1237 else if (IsEqualGUID(clsid
, &CLSID_CLRRuntimeHost
))
1239 unk
= (IUnknown
*)&This
->ICLRRuntimeHost_iface
;
1240 IUnknown_AddRef(unk
);
1242 else if (IsEqualGUID(clsid
, &CLSID_CorMetaDataDispenser
) ||
1243 IsEqualGUID(clsid
, &CLSID_CorMetaDataDispenserRuntime
))
1245 hr
= MetaDataDispenser_CreateInstance(&unk
);
1249 else if (IsEqualGUID(clsid
, &CLSID_CLRDebuggingLegacy
))
1251 hr
= CorDebug_Create(&This
->ICLRRuntimeHost_iface
, &unk
);
1260 hr
= IUnknown_QueryInterface(unk
, riid
, ppv
);
1262 IUnknown_Release(unk
);
1267 FIXME("not implemented for class %s\n", debugstr_guid(clsid
));
1269 return CLASS_E_CLASSNOTAVAILABLE
;
1272 #define CHARS_IN_GUID 39
1273 #define ARRAYSIZE(array) (sizeof(array)/sizeof((array)[0]))
1275 HRESULT
create_monodata(REFIID riid
, LPVOID
*ppObj
)
1277 static const WCHAR wszAssembly
[] = {'A','s','s','e','m','b','l','y',0};
1278 static const WCHAR wszCodebase
[] = {'C','o','d','e','B','a','s','e',0};
1279 static const WCHAR wszClass
[] = {'C','l','a','s','s',0};
1280 static const WCHAR wszFileSlash
[] = {'f','i','l','e',':','/','/','/',0};
1281 static const WCHAR wszCLSIDSlash
[] = {'C','L','S','I','D','\\',0};
1282 static const WCHAR wszInprocServer32
[] = {'\\','I','n','p','r','o','c','S','e','r','v','e','r','3','2',0};
1283 static const WCHAR wszDLL
[] = {'.','d','l','l',0};
1284 WCHAR path
[CHARS_IN_GUID
+ ARRAYSIZE(wszCLSIDSlash
) + ARRAYSIZE(wszInprocServer32
) - 1];
1286 MonoAssembly
*assembly
;
1287 ICLRRuntimeInfo
*info
= NULL
;
1293 DWORD numKeys
, keyLength
;
1294 WCHAR codebase
[MAX_PATH
+ 8];
1295 WCHAR classname
[350], subkeyName
[256];
1296 WCHAR filename
[MAX_PATH
];
1298 DWORD dwBufLen
= 350;
1300 lstrcpyW(path
, wszCLSIDSlash
);
1301 StringFromGUID2(riid
, path
+ lstrlenW(wszCLSIDSlash
), CHARS_IN_GUID
);
1302 lstrcatW(path
, wszInprocServer32
);
1304 TRACE("Registry key: %s\n", debugstr_w(path
));
1306 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, path
, 0, KEY_READ
, &key
);
1307 if (res
== ERROR_FILE_NOT_FOUND
)
1308 return CLASS_E_CLASSNOTAVAILABLE
;
1310 res
= RegGetValueW( key
, NULL
, wszClass
, RRF_RT_REG_SZ
, NULL
, classname
, &dwBufLen
);
1311 if(res
!= ERROR_SUCCESS
)
1313 WARN("Class value cannot be found.\n");
1314 hr
= CLASS_E_CLASSNOTAVAILABLE
;
1318 TRACE("classname (%s)\n", debugstr_w(classname
));
1320 dwBufLen
= MAX_PATH
+ 8;
1321 res
= RegGetValueW( key
, NULL
, wszCodebase
, RRF_RT_REG_SZ
, NULL
, codebase
, &dwBufLen
);
1322 if(res
== ERROR_SUCCESS
)
1324 /* Strip file:/// */
1325 if(strncmpW(codebase
, wszFileSlash
, strlenW(wszFileSlash
)) == 0)
1326 offset
= strlenW(wszFileSlash
);
1328 strcpyW(filename
, codebase
+ offset
);
1332 WCHAR assemblyname
[MAX_PATH
+ 8];
1334 hr
= CLASS_E_CLASSNOTAVAILABLE
;
1335 WARN("CodeBase value cannot be found, trying Assembly.\n");
1336 /* get the last subkey of InprocServer32 */
1337 res
= RegQueryInfoKeyW(key
, 0, 0, 0, &numKeys
, 0, 0, 0, 0, 0, 0, 0);
1338 if (res
!= ERROR_SUCCESS
|| numKeys
== 0)
1341 keyLength
= sizeof(subkeyName
) / sizeof(WCHAR
);
1342 res
= RegEnumKeyExW(key
, numKeys
, subkeyName
, &keyLength
, 0, 0, 0, 0);
1343 if (res
!= ERROR_SUCCESS
)
1345 res
= RegOpenKeyExW(key
, subkeyName
, 0, KEY_READ
, &subkey
);
1346 if (res
!= ERROR_SUCCESS
)
1348 dwBufLen
= MAX_PATH
+ 8;
1349 res
= RegGetValueW(subkey
, NULL
, wszAssembly
, RRF_RT_REG_SZ
, NULL
, assemblyname
, &dwBufLen
);
1350 RegCloseKey(subkey
);
1351 if (res
!= ERROR_SUCCESS
)
1354 hr
= get_file_from_strongname(assemblyname
, filename
, MAX_PATH
);
1358 * The registry doesn't have a CodeBase entry and it's not in the GAC.
1360 * Use the Assembly Key to retrieve the filename.
1361 * Assembly : REG_SZ : AssemblyName, Version=X.X.X.X, Culture=neutral, PublicKeyToken=null
1365 WARN("Attempt to load from the application directory.\n");
1366 GetModuleFileNameW(NULL
, filename
, MAX_PATH
);
1367 ns
= strrchrW(filename
, '\\');
1370 ns
= strchrW(assemblyname
, ',');
1372 strcatW(filename
, assemblyname
);
1374 strcatW(filename
, wszDLL
);
1378 TRACE("filename (%s)\n", debugstr_w(filename
));
1383 hr
= get_runtime_info(filename
, NULL
, NULL
, 0, 0, FALSE
, &info
);
1386 hr
= ICLRRuntimeInfo_GetRuntimeHost(info
, &host
);
1389 hr
= RuntimeHost_GetDefaultDomain(host
, &domain
);
1396 IUnknown
*unk
= NULL
;
1397 char *filenameA
, *ns
;
1400 hr
= CLASS_E_CLASSNOTAVAILABLE
;
1402 mono_thread_attach(domain
);
1404 filenameA
= WtoA(filename
);
1405 assembly
= mono_domain_assembly_open(domain
, filenameA
);
1406 HeapFree(GetProcessHeap(), 0, filenameA
);
1409 ERR("Cannot open assembly %s\n", filenameA
);
1413 image
= mono_assembly_get_image(assembly
);
1416 ERR("Couldn't get assembly image\n");
1420 classA
= WtoA(classname
);
1421 ns
= strrchr(classA
, '.');
1424 klass
= mono_class_from_name(image
, classA
, ns
+1);
1425 HeapFree(GetProcessHeap(), 0, classA
);
1428 ERR("Couldn't get class from image\n");
1433 * Use the default constructor for the .NET class.
1435 result
= mono_object_new(domain
, klass
);
1436 mono_runtime_object_init(result
);
1438 hr
= RuntimeHost_GetIUnknownForObject(host
, result
, &unk
);
1441 hr
= IUnknown_QueryInterface(unk
, &IID_IUnknown
, ppObj
);
1443 IUnknown_Release(unk
);
1446 hr
= CLASS_E_CLASSNOTAVAILABLE
;
1449 hr
= CLASS_E_CLASSNOTAVAILABLE
;
1452 hr
= CLASS_E_CLASSNOTAVAILABLE
;
1456 ICLRRuntimeInfo_Release(info
);