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
39 #include "wine/list.h"
40 #include "mscoree_private.h"
42 #include "wine/debug.h"
43 #include "wine/heap.h"
45 WINE_DEFAULT_DEBUG_CHANNEL( mscoree
);
49 DEFINE_GUID(IID__AppDomain
, 0x05f696dc,0x2b29,0x3663,0xad,0x8b,0xc4,0x38,0x9c,0xf2,0xa7,0x13);
57 static HANDLE dll_fixup_heap
; /* using a separate heap so we can have execute permission */
59 static CRITICAL_SECTION fixup_list_cs
;
60 static CRITICAL_SECTION_DEBUG fixup_list_cs_debug
=
63 { &fixup_list_cs_debug
.ProcessLocksList
,
64 &fixup_list_cs_debug
.ProcessLocksList
},
65 0, 0, { (DWORD_PTR
)(__FILE__
": fixup_list_cs") }
67 static CRITICAL_SECTION fixup_list_cs
= { &fixup_list_cs_debug
, -1, 0, 0, 0, 0 };
69 static struct list dll_fixups
;
71 WCHAR
**private_path
= NULL
;
78 void *thunk_code
; /* pointer into dll_fixup_heap */
81 void *tokens
; /* pointer into process heap */
84 struct comclassredirect_data
100 DWORD miscstatuscontent
;
101 DWORD miscstatusthumbnail
;
102 DWORD miscstatusicon
;
103 DWORD miscstatusdocprint
;
115 ULONG version_offset
;
119 static MonoDomain
* domain_attach(MonoDomain
*domain
)
121 MonoDomain
*prev_domain
= mono_domain_get();
123 if (prev_domain
== domain
)
124 /* Do not set or restore domain. */
127 mono_thread_attach(domain
);
132 static void domain_restore(MonoDomain
*prev_domain
)
134 if (prev_domain
!= NULL
)
135 mono_domain_set(prev_domain
, FALSE
);
138 static HRESULT
RuntimeHost_GetDefaultDomain(RuntimeHost
*This
, const WCHAR
*config_path
, MonoDomain
**result
)
140 WCHAR config_dir
[MAX_PATH
];
141 WCHAR base_dir
[MAX_PATH
];
142 char *base_dirA
, *config_pathA
, *slash
;
144 static BOOL configured_domain
;
146 *result
= get_root_domain();
148 EnterCriticalSection(&This
->lock
);
150 if (configured_domain
) goto end
;
154 DWORD len
= ARRAY_SIZE(config_dir
);
156 static const WCHAR machine_configW
[] = {'\\','C','O','N','F','I','G','\\','m','a','c','h','i','n','e','.','c','o','n','f','i','g',0};
158 res
= ICLRRuntimeInfo_GetRuntimeDirectory(&This
->version
->ICLRRuntimeInfo_iface
,
163 lstrcatW(config_dir
, machine_configW
);
165 config_path
= config_dir
;
168 config_pathA
= WtoA(config_path
);
175 GetModuleFileNameW(NULL
, base_dir
, ARRAY_SIZE(base_dir
));
176 base_dirA
= WtoA(base_dir
);
179 HeapFree(GetProcessHeap(), 0, config_pathA
);
184 slash
= strrchr(base_dirA
, '\\');
188 TRACE("setting base_dir: %s, config_path: %s\n", base_dirA
, config_pathA
);
189 mono_domain_set_config(*result
, base_dirA
, config_pathA
);
191 HeapFree(GetProcessHeap(), 0, config_pathA
);
192 HeapFree(GetProcessHeap(), 0, base_dirA
);
196 configured_domain
= TRUE
;
198 LeaveCriticalSection(&This
->lock
);
203 static BOOL
RuntimeHost_GetMethod(MonoDomain
*domain
, const char *assemblyname
,
204 const char *namespace, const char *typename
, const char *methodname
, int arg_count
,
207 MonoAssembly
*assembly
;
213 image
= mono_get_corlib();
217 MonoImageOpenStatus status
;
218 assembly
= mono_assembly_open(assemblyname
, &status
);
221 ERR("Cannot load assembly %s, status=%i\n", assemblyname
, status
);
225 image
= mono_assembly_get_image(assembly
);
228 ERR("Couldn't get assembly image for %s\n", assemblyname
);
233 klass
= mono_class_from_name(image
, namespace, typename
);
236 ERR("Couldn't get class %s.%s from image\n", namespace, typename
);
240 *method
= mono_class_get_method_from_name(klass
, methodname
, arg_count
);
243 ERR("Couldn't get method %s from class %s.%s\n", methodname
, namespace, typename
);
250 static HRESULT
RuntimeHost_Invoke(RuntimeHost
*This
, MonoDomain
*domain
,
251 const char *assemblyname
, const char *namespace, const char *typename
, const char *methodname
,
252 MonoObject
*obj
, void **args
, int arg_count
, MonoObject
**result
);
254 static HRESULT
RuntimeHost_DoInvoke(RuntimeHost
*This
, MonoDomain
*domain
,
255 const char *methodname
, MonoMethod
*method
, MonoObject
*obj
, void **args
, MonoObject
**result
)
258 static const char *get_hresult
= "get_HResult";
260 *result
= mono_runtime_invoke(method
, obj
, args
, &exc
);
264 MonoObject
*hr_object
;
266 if (methodname
!= get_hresult
)
268 /* Map the exception to an HRESULT. */
269 hr
= RuntimeHost_Invoke(This
, domain
, NULL
, "System", "Exception", get_hresult
,
270 exc
, NULL
, 0, &hr_object
);
272 hr
= *(HRESULT
*)mono_object_unbox(hr_object
);
285 static HRESULT
RuntimeHost_Invoke(RuntimeHost
*This
, MonoDomain
*domain
,
286 const char *assemblyname
, const char *namespace, const char *typename
, const char *methodname
,
287 MonoObject
*obj
, void **args
, int arg_count
, MonoObject
**result
)
290 MonoDomain
*prev_domain
;
295 prev_domain
= domain_attach(domain
);
297 if (!RuntimeHost_GetMethod(domain
, assemblyname
, namespace, typename
, methodname
,
300 domain_restore(prev_domain
);
304 hr
= RuntimeHost_DoInvoke(This
, domain
, methodname
, method
, obj
, args
, result
);
307 ERR("Method %s.%s:%s raised an exception, hr=%x\n", namespace, typename
, methodname
, hr
);
310 domain_restore(prev_domain
);
315 static HRESULT
RuntimeHost_VirtualInvoke(RuntimeHost
*This
, MonoDomain
*domain
,
316 const char *assemblyname
, const char *namespace, const char *typename
, const char *methodname
,
317 MonoObject
*obj
, void **args
, int arg_count
, MonoObject
**result
)
320 MonoDomain
*prev_domain
;
327 ERR("\"this\" object cannot be null\n");
331 prev_domain
= domain_attach(domain
);
333 if (!RuntimeHost_GetMethod(domain
, assemblyname
, namespace, typename
, methodname
,
336 domain_restore(prev_domain
);
340 method
= mono_object_get_virtual_method(obj
, method
);
343 ERR("Object %p does not support method %s.%s:%s\n", obj
, namespace, typename
, methodname
);
344 domain_restore(prev_domain
);
348 hr
= RuntimeHost_DoInvoke(This
, domain
, methodname
, method
, obj
, args
, result
);
351 ERR("Method %s.%s:%s raised an exception, hr=%x\n", namespace, typename
, methodname
, hr
);
354 domain_restore(prev_domain
);
359 static HRESULT
RuntimeHost_GetObjectForIUnknown(RuntimeHost
*This
, MonoDomain
*domain
,
360 IUnknown
*unk
, MonoObject
**obj
)
367 hr
= RuntimeHost_Invoke(This
, domain
, NULL
, "System.Runtime.InteropServices", "Marshal", "GetObjectForIUnknown",
368 NULL
, args
, 1, &result
);
377 static HRESULT
RuntimeHost_AddDomain(RuntimeHost
*This
, const WCHAR
*name
, IUnknown
*setup
,
378 IUnknown
*evidence
, MonoDomain
**result
)
384 MonoObject
*new_domain
, *id
;
386 res
= RuntimeHost_GetDefaultDomain(This
, NULL
, &domain
);
395 return E_OUTOFMEMORY
;
398 args
[0] = mono_string_new(domain
, nameA
);
399 HeapFree(GetProcessHeap(), 0, nameA
);
403 return E_OUTOFMEMORY
;
408 res
= RuntimeHost_GetObjectForIUnknown(This
, domain
, evidence
, (MonoObject
**)&args
[1]);
421 res
= RuntimeHost_GetObjectForIUnknown(This
, domain
, setup
, (MonoObject
**)&args
[2]);
432 res
= RuntimeHost_Invoke(This
, domain
, NULL
, "System", "AppDomain", "CreateDomain",
433 NULL
, args
, 3, &new_domain
);
440 /* new_domain is not the AppDomain itself, but a transparent proxy.
441 * So, we'll retrieve its ID, and use that to get the real domain object.
442 * We can't do a regular invoke, because that will bypass the proxy.
443 * Instead, do a vcall.
446 res
= RuntimeHost_VirtualInvoke(This
, domain
, NULL
, "System", "AppDomain", "get_Id",
447 new_domain
, NULL
, 0, &id
);
454 TRACE("returning domain id %d\n", *(int *)mono_object_unbox(id
));
456 *result
= mono_domain_get_by_id(*(int *)mono_object_unbox(id
));
461 static HRESULT
RuntimeHost_GetIUnknownForDomain(RuntimeHost
*This
, MonoDomain
*domain
, IUnknown
**punk
)
464 MonoObject
*appdomain_object
;
467 hr
= RuntimeHost_Invoke(This
, domain
, NULL
, "System", "AppDomain", "get_CurrentDomain",
468 NULL
, NULL
, 0, &appdomain_object
);
471 hr
= RuntimeHost_GetIUnknownForObject(This
, appdomain_object
, &unk
);
475 hr
= IUnknown_QueryInterface(unk
, &IID__AppDomain
, (void**)punk
);
477 IUnknown_Release(unk
);
483 void RuntimeHost_ExitProcess(RuntimeHost
*This
, INT exitcode
)
490 hr
= RuntimeHost_GetDefaultDomain(This
, NULL
, &domain
);
493 ERR("Cannot get domain, hr=%x\n", hr
);
499 RuntimeHost_Invoke(This
, domain
, NULL
, "System", "Environment", "Exit",
500 NULL
, args
, 1, &dummy
);
502 ERR("Process should have exited\n");
505 static inline RuntimeHost
*impl_from_ICLRRuntimeHost( ICLRRuntimeHost
*iface
)
507 return CONTAINING_RECORD(iface
, RuntimeHost
, ICLRRuntimeHost_iface
);
510 static inline RuntimeHost
*impl_from_ICorRuntimeHost( ICorRuntimeHost
*iface
)
512 return CONTAINING_RECORD(iface
, RuntimeHost
, ICorRuntimeHost_iface
);
515 /*** IUnknown methods ***/
516 static HRESULT WINAPI
corruntimehost_QueryInterface(ICorRuntimeHost
* iface
,
520 RuntimeHost
*This
= impl_from_ICorRuntimeHost( iface
);
521 TRACE("%p %s %p\n", This
, debugstr_guid(riid
), ppvObject
);
523 if ( IsEqualGUID( riid
, &IID_ICorRuntimeHost
) ||
524 IsEqualGUID( riid
, &IID_IUnknown
) )
530 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
531 return E_NOINTERFACE
;
534 ICorRuntimeHost_AddRef( iface
);
539 static ULONG WINAPI
corruntimehost_AddRef(ICorRuntimeHost
* iface
)
541 RuntimeHost
*This
= impl_from_ICorRuntimeHost( iface
);
543 return InterlockedIncrement( &This
->ref
);
546 static ULONG WINAPI
corruntimehost_Release(ICorRuntimeHost
* iface
)
548 RuntimeHost
*This
= impl_from_ICorRuntimeHost( iface
);
551 ref
= InterlockedDecrement( &This
->ref
);
556 /*** ICorRuntimeHost methods ***/
557 static HRESULT WINAPI
corruntimehost_CreateLogicalThreadState(
558 ICorRuntimeHost
* iface
)
560 FIXME("stub %p\n", iface
);
564 static HRESULT WINAPI
corruntimehost_DeleteLogicalThreadState(
565 ICorRuntimeHost
* iface
)
567 FIXME("stub %p\n", iface
);
571 static HRESULT WINAPI
corruntimehost_SwitchInLogicalThreadState(
572 ICorRuntimeHost
* iface
,
575 FIXME("stub %p\n", iface
);
579 static HRESULT WINAPI
corruntimehost_SwitchOutLogicalThreadState(
580 ICorRuntimeHost
* iface
,
583 FIXME("stub %p\n", iface
);
587 static HRESULT WINAPI
corruntimehost_LocksHeldByLogicalThread(
588 ICorRuntimeHost
* iface
,
591 FIXME("stub %p\n", iface
);
595 static HRESULT WINAPI
corruntimehost_MapFile(
596 ICorRuntimeHost
* iface
,
600 FIXME("stub %p\n", iface
);
604 static HRESULT WINAPI
corruntimehost_GetConfiguration(
605 ICorRuntimeHost
* iface
,
606 ICorConfiguration
**pConfiguration
)
608 FIXME("stub %p\n", iface
);
612 static HRESULT WINAPI
corruntimehost_Start(
613 ICorRuntimeHost
* iface
)
615 RuntimeHost
*This
= impl_from_ICorRuntimeHost( iface
);
620 return RuntimeHost_GetDefaultDomain(This
, NULL
, &dummy
);
623 static HRESULT WINAPI
corruntimehost_Stop(
624 ICorRuntimeHost
* iface
)
626 FIXME("stub %p\n", iface
);
630 static HRESULT WINAPI
corruntimehost_CreateDomain(
631 ICorRuntimeHost
* iface
,
632 LPCWSTR friendlyName
,
633 IUnknown
*identityArray
,
634 IUnknown
**appDomain
)
636 return ICorRuntimeHost_CreateDomainEx(iface
, friendlyName
, NULL
, NULL
, appDomain
);
639 static HRESULT WINAPI
corruntimehost_GetDefaultDomain(
640 ICorRuntimeHost
* iface
,
641 IUnknown
**pAppDomain
)
643 RuntimeHost
*This
= impl_from_ICorRuntimeHost( iface
);
647 TRACE("(%p)\n", iface
);
649 hr
= RuntimeHost_GetDefaultDomain(This
, NULL
, &domain
);
653 hr
= RuntimeHost_GetIUnknownForDomain(This
, domain
, pAppDomain
);
659 static HRESULT WINAPI
corruntimehost_EnumDomains(
660 ICorRuntimeHost
* iface
,
663 FIXME("stub %p\n", iface
);
667 static HRESULT WINAPI
corruntimehost_NextDomain(
668 ICorRuntimeHost
* iface
,
670 IUnknown
**appDomain
)
672 FIXME("stub %p\n", iface
);
676 static HRESULT WINAPI
corruntimehost_CloseEnum(
677 ICorRuntimeHost
* iface
,
680 FIXME("stub %p\n", iface
);
684 static HRESULT WINAPI
corruntimehost_CreateDomainEx(
685 ICorRuntimeHost
* iface
,
686 LPCWSTR friendlyName
,
689 IUnknown
**appDomain
)
691 RuntimeHost
*This
= impl_from_ICorRuntimeHost( iface
);
695 if (!friendlyName
|| !appDomain
)
699 if (!is_mono_started
)
704 TRACE("(%p)\n", iface
);
706 hr
= RuntimeHost_AddDomain(This
, friendlyName
, setup
, evidence
, &domain
);
710 hr
= RuntimeHost_GetIUnknownForDomain(This
, domain
, appDomain
);
716 static HRESULT WINAPI
corruntimehost_CreateDomainSetup(
717 ICorRuntimeHost
* iface
,
718 IUnknown
**appDomainSetup
)
720 RuntimeHost
*This
= impl_from_ICorRuntimeHost( iface
);
724 static const WCHAR classnameW
[] = {'S','y','s','t','e','m','.','A','p','p','D','o','m','a','i','n','S','e','t','u','p',',','m','s','c','o','r','l','i','b',0};
726 TRACE("(%p)\n", iface
);
728 hr
= RuntimeHost_GetDefaultDomain(This
, NULL
, &domain
);
731 hr
= RuntimeHost_CreateManagedInstance(This
, classnameW
, domain
, &obj
);
734 hr
= RuntimeHost_GetIUnknownForObject(This
, obj
, appDomainSetup
);
739 static HRESULT WINAPI
corruntimehost_CreateEvidence(
740 ICorRuntimeHost
* iface
,
743 FIXME("stub %p\n", iface
);
747 static HRESULT WINAPI
corruntimehost_UnloadDomain(
748 ICorRuntimeHost
* iface
,
751 FIXME("stub %p\n", iface
);
755 static HRESULT WINAPI
corruntimehost_CurrentDomain(
756 ICorRuntimeHost
* iface
,
757 IUnknown
**appDomain
)
759 FIXME("stub %p\n", iface
);
763 static const struct ICorRuntimeHostVtbl corruntimehost_vtbl
=
765 corruntimehost_QueryInterface
,
766 corruntimehost_AddRef
,
767 corruntimehost_Release
,
768 corruntimehost_CreateLogicalThreadState
,
769 corruntimehost_DeleteLogicalThreadState
,
770 corruntimehost_SwitchInLogicalThreadState
,
771 corruntimehost_SwitchOutLogicalThreadState
,
772 corruntimehost_LocksHeldByLogicalThread
,
773 corruntimehost_MapFile
,
774 corruntimehost_GetConfiguration
,
775 corruntimehost_Start
,
777 corruntimehost_CreateDomain
,
778 corruntimehost_GetDefaultDomain
,
779 corruntimehost_EnumDomains
,
780 corruntimehost_NextDomain
,
781 corruntimehost_CloseEnum
,
782 corruntimehost_CreateDomainEx
,
783 corruntimehost_CreateDomainSetup
,
784 corruntimehost_CreateEvidence
,
785 corruntimehost_UnloadDomain
,
786 corruntimehost_CurrentDomain
789 static HRESULT WINAPI
CLRRuntimeHost_QueryInterface(ICLRRuntimeHost
* iface
,
793 RuntimeHost
*This
= impl_from_ICLRRuntimeHost( iface
);
794 TRACE("%p %s %p\n", This
, debugstr_guid(riid
), ppvObject
);
796 if ( IsEqualGUID( riid
, &IID_ICLRRuntimeHost
) ||
797 IsEqualGUID( riid
, &IID_IUnknown
) )
803 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
804 return E_NOINTERFACE
;
807 ICLRRuntimeHost_AddRef( iface
);
812 static ULONG WINAPI
CLRRuntimeHost_AddRef(ICLRRuntimeHost
* iface
)
814 RuntimeHost
*This
= impl_from_ICLRRuntimeHost( iface
);
815 return ICorRuntimeHost_AddRef(&This
->ICorRuntimeHost_iface
);
818 static ULONG WINAPI
CLRRuntimeHost_Release(ICLRRuntimeHost
* iface
)
820 RuntimeHost
*This
= impl_from_ICLRRuntimeHost( iface
);
821 return ICorRuntimeHost_Release(&This
->ICorRuntimeHost_iface
);
824 static HRESULT WINAPI
CLRRuntimeHost_Start(ICLRRuntimeHost
* iface
)
826 FIXME("(%p)\n", iface
);
830 static HRESULT WINAPI
CLRRuntimeHost_Stop(ICLRRuntimeHost
* iface
)
832 FIXME("(%p)\n", iface
);
836 static HRESULT WINAPI
CLRRuntimeHost_SetHostControl(ICLRRuntimeHost
* iface
,
837 IHostControl
*pHostControl
)
839 FIXME("(%p,%p)\n", iface
, pHostControl
);
843 static HRESULT WINAPI
CLRRuntimeHost_GetCLRControl(ICLRRuntimeHost
* iface
,
844 ICLRControl
**pCLRControl
)
846 FIXME("(%p,%p)\n", iface
, pCLRControl
);
850 static HRESULT WINAPI
CLRRuntimeHost_UnloadAppDomain(ICLRRuntimeHost
* iface
,
851 DWORD dwAppDomainId
, BOOL fWaitUntilDone
)
853 FIXME("(%p,%u,%i)\n", iface
, dwAppDomainId
, fWaitUntilDone
);
857 static HRESULT WINAPI
CLRRuntimeHost_ExecuteInAppDomain(ICLRRuntimeHost
* iface
,
858 DWORD dwAppDomainId
, FExecuteInAppDomainCallback pCallback
, void *cookie
)
860 FIXME("(%p,%u,%p,%p)\n", iface
, dwAppDomainId
, pCallback
, cookie
);
864 static HRESULT WINAPI
CLRRuntimeHost_GetCurrentAppDomainId(ICLRRuntimeHost
* iface
,
865 DWORD
*pdwAppDomainId
)
867 FIXME("(%p,%p)\n", iface
, pdwAppDomainId
);
871 static HRESULT WINAPI
CLRRuntimeHost_ExecuteApplication(ICLRRuntimeHost
* iface
,
872 LPCWSTR pwzAppFullName
, DWORD dwManifestPaths
, LPCWSTR
*ppwzManifestPaths
,
873 DWORD dwActivationData
, LPCWSTR
*ppwzActivationData
, int *pReturnValue
)
875 FIXME("(%p,%s,%u,%u)\n", iface
, debugstr_w(pwzAppFullName
), dwManifestPaths
, dwActivationData
);
879 static HRESULT WINAPI
CLRRuntimeHost_ExecuteInDefaultAppDomain(ICLRRuntimeHost
* iface
,
880 LPCWSTR pwzAssemblyPath
, LPCWSTR pwzTypeName
, LPCWSTR pwzMethodName
,
881 LPCWSTR pwzArgument
, DWORD
*pReturnValue
)
883 RuntimeHost
*This
= impl_from_ICLRRuntimeHost( iface
);
885 MonoDomain
*domain
, *prev_domain
;
888 char *filenameA
= NULL
, *classA
= NULL
, *methodA
= NULL
;
889 char *argsA
= NULL
, *ns
;
891 TRACE("(%p,%s,%s,%s,%s)\n", iface
, debugstr_w(pwzAssemblyPath
),
892 debugstr_w(pwzTypeName
), debugstr_w(pwzMethodName
), debugstr_w(pwzArgument
));
894 hr
= RuntimeHost_GetDefaultDomain(This
, NULL
, &domain
);
899 prev_domain
= domain_attach(domain
);
903 filenameA
= WtoA(pwzAssemblyPath
);
904 if (!filenameA
) hr
= E_OUTOFMEMORY
;
909 classA
= WtoA(pwzTypeName
);
910 if (!classA
) hr
= E_OUTOFMEMORY
;
915 ns
= strrchr(classA
, '.');
924 methodA
= WtoA(pwzMethodName
);
925 if (!methodA
) hr
= E_OUTOFMEMORY
;
928 /* The .NET function we are calling has the following declaration
929 * public static int functionName(String param)
933 argsA
= WtoA(pwzArgument
);
934 if (!argsA
) hr
= E_OUTOFMEMORY
;
939 str
= mono_string_new(domain
, argsA
);
940 if (!str
) hr
= E_OUTOFMEMORY
;
945 hr
= RuntimeHost_Invoke(This
, domain
, filenameA
, classA
, ns
+1, methodA
,
946 NULL
, (void**)&str
, 1, &result
);
950 *pReturnValue
= *(DWORD
*)mono_object_unbox(result
);
952 domain_restore(prev_domain
);
954 HeapFree(GetProcessHeap(), 0, filenameA
);
955 HeapFree(GetProcessHeap(), 0, classA
);
956 HeapFree(GetProcessHeap(), 0, argsA
);
957 HeapFree(GetProcessHeap(), 0, methodA
);
962 static const struct ICLRRuntimeHostVtbl CLRHostVtbl
=
964 CLRRuntimeHost_QueryInterface
,
965 CLRRuntimeHost_AddRef
,
966 CLRRuntimeHost_Release
,
967 CLRRuntimeHost_Start
,
969 CLRRuntimeHost_SetHostControl
,
970 CLRRuntimeHost_GetCLRControl
,
971 CLRRuntimeHost_UnloadAppDomain
,
972 CLRRuntimeHost_ExecuteInAppDomain
,
973 CLRRuntimeHost_GetCurrentAppDomainId
,
974 CLRRuntimeHost_ExecuteApplication
,
975 CLRRuntimeHost_ExecuteInDefaultAppDomain
978 /* Create an instance of a type given its name, by calling its constructor with
979 * no arguments. Note that result MUST be in the stack, or the garbage
980 * collector may free it prematurely. */
981 HRESULT
RuntimeHost_CreateManagedInstance(RuntimeHost
*This
, LPCWSTR name
,
982 MonoDomain
*domain
, MonoObject
**result
)
989 MonoDomain
*prev_domain
;
992 hr
= RuntimeHost_GetDefaultDomain(This
, NULL
, &domain
);
997 prev_domain
= domain_attach(domain
);
1008 type
= mono_reflection_type_from_name(nameA
, NULL
);
1011 ERR("Cannot find type %s\n", debugstr_w(name
));
1018 klass
= mono_class_from_mono_type(type
);
1021 ERR("Cannot convert type %s to a class\n", debugstr_w(name
));
1028 obj
= mono_object_new(domain
, klass
);
1031 ERR("Cannot allocate object of type %s\n", debugstr_w(name
));
1038 /* FIXME: Detect exceptions from the constructor? */
1039 mono_runtime_object_init(obj
);
1043 domain_restore(prev_domain
);
1045 HeapFree(GetProcessHeap(), 0, nameA
);
1050 /* Get an IUnknown pointer for a Mono object.
1052 * This is just a "light" wrapper around
1053 * System.Runtime.InteropServices.Marshal:GetIUnknownForObject
1055 * NOTE: The IUnknown* is created with a reference to the object.
1056 * Until they have a reference, objects must be in the stack to prevent the
1057 * garbage collector from freeing them. */
1058 HRESULT
RuntimeHost_GetIUnknownForObject(RuntimeHost
*This
, MonoObject
*obj
,
1065 domain
= mono_object_get_domain(obj
);
1067 hr
= RuntimeHost_Invoke(This
, domain
, NULL
, "System.Runtime.InteropServices", "Marshal", "GetIUnknownForObject",
1068 NULL
, (void**)&obj
, 1, &result
);
1071 *ppUnk
= *(IUnknown
**)mono_object_unbox(result
);
1078 static void get_utf8_args(int *argc
, char ***argv
)
1084 argvw
= CommandLineToArgvW(GetCommandLineW(), argc
);
1086 for (i
=0; i
<*argc
; i
++)
1088 size
+= sizeof(char*);
1089 size
+= WideCharToMultiByte(CP_UTF8
, 0, argvw
[i
], -1, NULL
, 0, NULL
, NULL
);
1091 size
+= sizeof(char*);
1093 *argv
= HeapAlloc(GetProcessHeap(), 0, size
);
1094 current_arg
= (char*)(*argv
+ *argc
+ 1);
1096 for (i
=0; i
<*argc
; i
++)
1098 (*argv
)[i
] = current_arg
;
1099 current_arg
+= WideCharToMultiByte(CP_UTF8
, 0, argvw
[i
], -1, current_arg
, size
, NULL
, NULL
);
1102 (*argv
)[*argc
] = NULL
;
1104 HeapFree(GetProcessHeap(), 0, argvw
);
1109 # define CAN_FIXUP_VTABLE 1
1111 #include "pshpack1.h"
1113 struct vtable_fixup_thunk
1119 /* mov fixup,(%esp) */
1121 struct dll_fixup
*fixup
;
1122 /* mov function,%eax */
1124 void (CDECL
*function
)(struct dll_fixup
*);
1131 /* jmp *vtable_entry */
1136 static const struct vtable_fixup_thunk thunk_template
= {
1150 #include "poppack.h"
1152 #elif __x86_64__ /* !__i386__ */
1154 # define CAN_FIXUP_VTABLE 1
1156 #include "pshpack1.h"
1158 struct vtable_fixup_thunk
1162 sub $0x80, %rsp ; 0x8*4 + 0x10*4 + 0x20
1166 mov %rcx, 0x60(%rsp); mov %rdx, 0x68(%rsp); mov %r8, 0x70(%rsp); mov %r9, 0x78(%rsp);
1167 movaps %xmm0,0x20(%rsp); ...; movaps %xmm3,0x50(%esp)
1170 /* mov function,%rax */
1172 void (CDECL
*function
)(struct dll_fixup
*);
1173 /* mov fixup,%rcx */
1175 struct dll_fixup
*fixup
;
1179 mov 0x60(%rsp),%rcx; mov 0x68(%rsp),%rdx; mov 0x70(%rsp),%r8; mov 0x78(%rsp),%r9;
1180 movaps 0x20(%rsp),xmm0; ...; movaps 0x50(%esp),xmm3
1187 /* mov vtable_entry, %rax */
1195 static const struct vtable_fixup_thunk thunk_template
= {
1196 {0x55,0x48,0x89,0xE5, 0x48,0x81,0xEC,0x80,0x00,0x00,0x00},
1197 {0x48,0x89,0x4C,0x24,0x60, 0x48,0x89,0x54,0x24,0x68,
1198 0x4C,0x89,0x44,0x24,0x70, 0x4C,0x89,0x4C,0x24,0x78,
1199 0x0F,0x29,0x44,0x24,0x20, 0x0F,0x29,0x4C,0x24,0x30,
1200 0x0F,0x29,0x54,0x24,0x40, 0x0F,0x29,0x5C,0x24,0x50,
1207 {0x48,0x8B,0x4C,0x24,0x60, 0x48,0x8B,0x54,0x24,0x68,
1208 0x4C,0x8B,0x44,0x24,0x70, 0x4C,0x8B,0x4C,0x24,0x78,
1209 0x0F,0x28,0x44,0x24,0x20, 0x0F,0x28,0x4C,0x24,0x30,
1210 0x0F,0x28,0x54,0x24,0x40, 0x0F,0x28,0x5C,0x24,0x50,
1212 {0x48,0x89,0xEC, 0x5D},
1215 {0x48,0x8B,0x00,0xFF,0xE0}
1218 #include "poppack.h"
1220 #else /* !__i386__ && !__x86_64__ */
1222 # define CAN_FIXUP_VTABLE 0
1224 struct vtable_fixup_thunk
1226 struct dll_fixup
*fixup
;
1227 void (CDECL
*function
)(struct dll_fixup
*fixup
);
1231 static const struct vtable_fixup_thunk thunk_template
= {0};
1235 DWORD WINAPI
GetTokenForVTableEntry(HINSTANCE hinst
, BYTE
**ppVTEntry
)
1237 struct dll_fixup
*fixup
;
1242 TRACE("%p,%p\n", hinst
, ppVTEntry
);
1244 rva
= (BYTE
*)ppVTEntry
- (BYTE
*)hinst
;
1246 EnterCriticalSection(&fixup_list_cs
);
1247 LIST_FOR_EACH_ENTRY(fixup
, &dll_fixups
, struct dll_fixup
, entry
)
1249 if (fixup
->dll
!= hinst
)
1251 if (rva
< fixup
->fixup
->rva
|| (rva
- fixup
->fixup
->rva
>= fixup
->fixup
->count
* sizeof(ULONG_PTR
)))
1253 i
= (rva
- fixup
->fixup
->rva
) / sizeof(ULONG_PTR
);
1254 result
= ((ULONG_PTR
*)fixup
->tokens
)[i
];
1257 LeaveCriticalSection(&fixup_list_cs
);
1259 TRACE("<-- %x\n", result
);
1263 static void CDECL
ReallyFixupVTable(struct dll_fixup
*fixup
)
1266 WCHAR filename
[MAX_PATH
];
1267 ICLRRuntimeInfo
*info
=NULL
;
1270 MonoImage
*image
=NULL
;
1271 MonoAssembly
*assembly
=NULL
;
1272 MonoImageOpenStatus status
=0;
1275 if (fixup
->done
) return;
1277 /* It's possible we'll have two threads doing this at once. This is
1278 * considered preferable to the potential deadlock if we use a mutex. */
1280 GetModuleFileNameW(fixup
->dll
, filename
, MAX_PATH
);
1282 TRACE("%p,%p,%s\n", fixup
, fixup
->dll
, debugstr_w(filename
));
1284 filenameA
= WtoA(filename
);
1289 hr
= get_runtime_info(filename
, NULL
, NULL
, NULL
, 0, 0, FALSE
, &info
);
1292 hr
= ICLRRuntimeInfo_GetRuntimeHost(info
, &host
);
1295 hr
= RuntimeHost_GetDefaultDomain(host
, NULL
, &domain
);
1299 MonoDomain
*prev_domain
;
1301 prev_domain
= domain_attach(domain
);
1303 assembly
= mono_assembly_open(filenameA
, &status
);
1309 /* Mono needs an image that belongs to an assembly. */
1310 image
= mono_assembly_get_image(assembly
);
1313 if (fixup
->fixup
->type
& COR_VTABLE_64BIT
)
1315 if (fixup
->fixup
->type
& COR_VTABLE_32BIT
)
1318 void **vtable
= fixup
->vtable
;
1319 ULONG_PTR
*tokens
= fixup
->tokens
;
1320 for (i
=0; i
<fixup
->fixup
->count
; i
++)
1322 vtable
[i
] = mono_marshal_get_vtfixup_ftnptr(
1323 image
, tokens
[i
], fixup
->fixup
->type
);
1330 domain_restore(prev_domain
);
1334 ICLRRuntimeInfo_Release(info
);
1336 HeapFree(GetProcessHeap(), 0, filenameA
);
1340 ERR("unable to fixup vtable, hr=%x, status=%d\n", hr
, status
);
1341 /* If we returned now, we'd get an infinite loop. */
1346 static void FixupVTableEntry(HMODULE hmodule
, VTableFixup
*vtable_fixup
)
1348 /* We can't actually generate code for the functions without loading mono,
1349 * and loading mono inside DllMain is a terrible idea. So we make thunks
1350 * that call ReallyFixupVTable, which will load the runtime and fill in the
1351 * vtable, then do an indirect jump using the (now filled in) vtable. Note
1352 * that we have to keep the thunks around forever, as one of them may get
1353 * called while we're filling in the table, and we can never be sure all
1354 * threads are clear. */
1355 struct dll_fixup
*fixup
;
1357 fixup
= HeapAlloc(GetProcessHeap(), 0, sizeof(*fixup
));
1359 fixup
->dll
= hmodule
;
1360 fixup
->thunk_code
= HeapAlloc(dll_fixup_heap
, 0, sizeof(struct vtable_fixup_thunk
) * vtable_fixup
->count
);
1361 fixup
->fixup
= vtable_fixup
;
1362 fixup
->vtable
= (BYTE
*)hmodule
+ vtable_fixup
->rva
;
1363 fixup
->done
= FALSE
;
1366 if (vtable_fixup
->type
& COR_VTABLE_64BIT
)
1368 if (vtable_fixup
->type
& COR_VTABLE_32BIT
)
1371 void **vtable
= fixup
->vtable
;
1374 struct vtable_fixup_thunk
*thunks
= fixup
->thunk_code
;
1376 tokens
= fixup
->tokens
= HeapAlloc(GetProcessHeap(), 0, sizeof(*tokens
) * vtable_fixup
->count
);
1377 memcpy(tokens
, vtable
, sizeof(*tokens
) * vtable_fixup
->count
);
1378 for (i
=0; i
<vtable_fixup
->count
; i
++)
1380 thunks
[i
] = thunk_template
;
1381 thunks
[i
].fixup
= fixup
;
1382 thunks
[i
].function
= ReallyFixupVTable
;
1383 thunks
[i
].vtable_entry
= &vtable
[i
];
1384 vtable
[i
] = &thunks
[i
];
1389 ERR("unsupported vtable fixup flags %x\n", vtable_fixup
->type
);
1390 HeapFree(dll_fixup_heap
, 0, fixup
->thunk_code
);
1391 HeapFree(GetProcessHeap(), 0, fixup
);
1395 EnterCriticalSection(&fixup_list_cs
);
1396 list_add_tail(&dll_fixups
, &fixup
->entry
);
1397 LeaveCriticalSection(&fixup_list_cs
);
1400 static void FixupVTable_Assembly(HMODULE hmodule
, ASSEMBLY
*assembly
)
1402 VTableFixup
*vtable_fixups
;
1403 ULONG vtable_fixup_count
, i
;
1405 assembly_get_vtable_fixups(assembly
, &vtable_fixups
, &vtable_fixup_count
);
1406 if (CAN_FIXUP_VTABLE
)
1407 for (i
=0; i
<vtable_fixup_count
; i
++)
1408 FixupVTableEntry(hmodule
, &vtable_fixups
[i
]);
1409 else if (vtable_fixup_count
)
1410 FIXME("cannot fixup vtable; expect a crash\n");
1413 static void FixupVTable(HMODULE hmodule
)
1418 hr
= assembly_from_hmodule(&assembly
, hmodule
);
1421 FixupVTable_Assembly(hmodule
, assembly
);
1422 assembly_release(assembly
);
1425 ERR("failed to read CLR headers, hr=%x\n", hr
);
1428 __int32 WINAPI
_CorExeMain(void)
1430 static const WCHAR dotconfig
[] = {'.','c','o','n','f','i','g',0};
1431 static const WCHAR scW
[] = {';',0};
1435 MonoDomain
*domain
=NULL
;
1437 MonoImageOpenStatus status
;
1438 MonoAssembly
*assembly
=NULL
;
1439 WCHAR filename
[MAX_PATH
], config_file
[MAX_PATH
], *temp
, **priv_path
;
1440 SIZE_T config_file_dir_size
;
1442 ICLRRuntimeInfo
*info
;
1444 parsed_config_file parsed_config
;
1446 int i
, number_of_private_paths
= 0;
1448 get_utf8_args(&argc
, &argv
);
1450 GetModuleFileNameW(NULL
, filename
, MAX_PATH
);
1452 TRACE("%s", debugstr_w(filename
));
1453 for (i
=0; i
<argc
; i
++)
1454 TRACE(" %s", debugstr_a(argv
[i
]));
1457 filenameA
= WtoA(filename
);
1460 HeapFree(GetProcessHeap(), 0, argv
);
1464 FixupVTable(GetModuleHandleW(NULL
));
1466 wcscpy(config_file
, filename
);
1467 wcscat(config_file
, dotconfig
);
1469 hr
= parse_config_file(config_file
, &parsed_config
);
1470 if (SUCCEEDED(hr
) && parsed_config
.private_path
&& parsed_config
.private_path
[0])
1473 for(i
= 0; parsed_config
.private_path
[i
] != 0; i
++)
1474 if (parsed_config
.private_path
[i
] == ';') number_of_private_paths
++;
1475 if (parsed_config
.private_path
[wcslen(parsed_config
.private_path
) - 1] != ';') number_of_private_paths
++;
1476 config_file_dir_size
= (wcsrchr(config_file
, '\\') - config_file
) + 1;
1477 priv_path
= HeapAlloc(GetProcessHeap(), 0, (number_of_private_paths
+ 1) * sizeof(WCHAR
*));
1478 /* wcstok ignores trailing semicolons */
1479 temp
= wcstok_s(parsed_config
.private_path
, scW
, &save
);
1480 for (i
= 0; i
< number_of_private_paths
; i
++)
1482 priv_path
[i
] = HeapAlloc(GetProcessHeap(), 0, (config_file_dir_size
+ wcslen(temp
) + 1) * sizeof(WCHAR
));
1483 memcpy(priv_path
[i
], config_file
, config_file_dir_size
* sizeof(WCHAR
));
1484 wcscpy(priv_path
[i
] + config_file_dir_size
, temp
);
1485 temp
= wcstok_s(NULL
, scW
, &save
);
1487 priv_path
[number_of_private_paths
] = NULL
;
1488 if (InterlockedCompareExchangePointer((void **)&private_path
, priv_path
, NULL
))
1489 ERR("private_path was already set\n");
1492 free_parsed_config_file(&parsed_config
);
1494 hr
= get_runtime_info(filename
, NULL
, NULL
, NULL
, 0, 0, FALSE
, &info
);
1498 hr
= ICLRRuntimeInfo_GetRuntimeHost(info
, &host
);
1501 hr
= RuntimeHost_GetDefaultDomain(host
, config_file
, &domain
);
1505 image
= mono_image_open_from_module_handle(GetModuleHandleW(NULL
),
1506 filenameA
, 1, &status
);
1509 assembly
= mono_assembly_load_from(image
, filenameA
, &status
);
1513 mono_callspec_set_assembly(assembly
);
1515 exit_code
= mono_jit_exec(domain
, assembly
, argc
, argv
);
1519 ERR("couldn't load %s, status=%d\n", debugstr_w(filename
), status
);
1526 ICLRRuntimeInfo_Release(info
);
1531 HeapFree(GetProcessHeap(), 0, argv
);
1535 mono_thread_manage();
1536 mono_runtime_quit();
1539 ExitProcess(exit_code
);
1544 BOOL WINAPI
_CorDllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
1546 ASSEMBLY
*assembly
=NULL
;
1549 TRACE("(%p, %d, %p)\n", hinstDLL
, fdwReason
, lpvReserved
);
1551 hr
= assembly_from_hmodule(&assembly
, hinstDLL
);
1554 NativeEntryPointFunc NativeEntryPoint
=NULL
;
1556 assembly_get_native_entrypoint(assembly
, &NativeEntryPoint
);
1557 if (fdwReason
== DLL_PROCESS_ATTACH
)
1559 if (!NativeEntryPoint
)
1560 DisableThreadLibraryCalls(hinstDLL
);
1561 FixupVTable_Assembly(hinstDLL
,assembly
);
1563 assembly_release(assembly
);
1564 /* FIXME: clean up the vtables on DLL_PROCESS_DETACH */
1565 if (NativeEntryPoint
)
1566 return NativeEntryPoint(hinstDLL
, fdwReason
, lpvReserved
);
1569 ERR("failed to read CLR headers, hr=%x\n", hr
);
1574 /* called from DLL_PROCESS_ATTACH */
1575 void runtimehost_init(void)
1577 dll_fixup_heap
= HeapCreate(HEAP_CREATE_ENABLE_EXECUTE
, 0, 0);
1578 list_init(&dll_fixups
);
1581 /* called from DLL_PROCESS_DETACH */
1582 void runtimehost_uninit(void)
1584 struct dll_fixup
*fixup
, *fixup2
;
1586 HeapDestroy(dll_fixup_heap
);
1587 LIST_FOR_EACH_ENTRY_SAFE(fixup
, fixup2
, &dll_fixups
, struct dll_fixup
, entry
)
1589 HeapFree(GetProcessHeap(), 0, fixup
->tokens
);
1590 HeapFree(GetProcessHeap(), 0, fixup
);
1594 HRESULT
RuntimeHost_Construct(CLRRuntimeInfo
*runtime_version
, RuntimeHost
** result
)
1598 This
= HeapAlloc( GetProcessHeap(), 0, sizeof *This
);
1600 return E_OUTOFMEMORY
;
1602 This
->ICorRuntimeHost_iface
.lpVtbl
= &corruntimehost_vtbl
;
1603 This
->ICLRRuntimeHost_iface
.lpVtbl
= &CLRHostVtbl
;
1606 This
->version
= runtime_version
;
1607 InitializeCriticalSection(&This
->lock
);
1608 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": RuntimeHost.lock");
1615 HRESULT
RuntimeHost_GetInterface(RuntimeHost
*This
, REFCLSID clsid
, REFIID riid
, void **ppv
)
1620 if (IsEqualGUID(clsid
, &CLSID_CorRuntimeHost
))
1622 unk
= (IUnknown
*)&This
->ICorRuntimeHost_iface
;
1623 IUnknown_AddRef(unk
);
1625 else if (IsEqualGUID(clsid
, &CLSID_CLRRuntimeHost
))
1627 unk
= (IUnknown
*)&This
->ICLRRuntimeHost_iface
;
1628 IUnknown_AddRef(unk
);
1630 else if (IsEqualGUID(clsid
, &CLSID_CorMetaDataDispenser
) ||
1631 IsEqualGUID(clsid
, &CLSID_CorMetaDataDispenserRuntime
))
1633 hr
= MetaDataDispenser_CreateInstance(&unk
);
1637 else if (IsEqualGUID(clsid
, &CLSID_CLRDebuggingLegacy
))
1639 hr
= CorDebug_Create(&This
->ICLRRuntimeHost_iface
, &unk
);
1648 hr
= IUnknown_QueryInterface(unk
, riid
, ppv
);
1650 IUnknown_Release(unk
);
1655 FIXME("not implemented for class %s\n", debugstr_guid(clsid
));
1657 return CLASS_E_CLASSNOTAVAILABLE
;
1660 static BOOL
try_create_registration_free_com(REFIID clsid
, WCHAR
*classname
, UINT classname_size
, WCHAR
*filename
, UINT filename_size
)
1662 ACTCTX_SECTION_KEYED_DATA guid_info
= { sizeof(ACTCTX_SECTION_KEYED_DATA
) };
1663 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION
*assembly_info
= NULL
;
1664 SIZE_T bytes_assembly_info
;
1665 struct comclassredirect_data
*redirect_data
;
1666 struct clrclass_data
*class_data
;
1668 const WCHAR
*ptr_path_start
, *ptr_path_end
;
1669 WCHAR path
[MAX_PATH
] = {0};
1670 WCHAR str_dll
[] = {'.','d','l','l',0};
1673 if (!FindActCtxSectionGuid(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
, 0, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
, clsid
, &guid_info
))
1675 DWORD error
= GetLastError();
1676 if (error
!= ERROR_SXS_KEY_NOT_FOUND
)
1677 ERR("Failed to find guid: %d\n", error
);
1681 QueryActCtxW(0, guid_info
.hActCtx
, &guid_info
.ulAssemblyRosterIndex
, AssemblyDetailedInformationInActivationContext
, NULL
, 0, &bytes_assembly_info
);
1682 assembly_info
= heap_alloc(bytes_assembly_info
);
1683 if (!QueryActCtxW(0, guid_info
.hActCtx
, &guid_info
.ulAssemblyRosterIndex
,
1684 AssemblyDetailedInformationInActivationContext
, assembly_info
, bytes_assembly_info
, &bytes_assembly_info
))
1686 ERR("QueryActCtxW failed: %d!\n", GetLastError());
1690 redirect_data
= guid_info
.lpData
;
1691 class_data
= (void *)((char *)redirect_data
+ redirect_data
->clrdata_offset
);
1693 ptr_name
= (char *)class_data
+ class_data
->name_offset
;
1694 if (lstrlenW(ptr_name
) + 1 > classname_size
) /* Include null-terminator */
1696 ERR("Buffer is too small\n");
1699 lstrcpyW(classname
, ptr_name
);
1701 ptr_path_start
= assembly_info
->lpAssemblyEncodedAssemblyIdentity
;
1702 ptr_path_end
= wcschr(ptr_path_start
, ',');
1703 memcpy(path
, ptr_path_start
, (char*)ptr_path_end
- (char*)ptr_path_start
);
1705 GetModuleFileNameW(NULL
, filename
, filename_size
);
1706 PathRemoveFileSpecW(filename
);
1708 if (lstrlenW(filename
) + lstrlenW(path
) + ARRAY_SIZE(str_dll
) + 1 > filename_size
) /* Include blackslash */
1710 ERR("Buffer is too small\n");
1714 PathAppendW(filename
, path
);
1715 lstrcatW(filename
, str_dll
);
1720 heap_free(assembly_info
);
1722 if (guid_info
.hActCtx
)
1723 ReleaseActCtx(guid_info
.hActCtx
);
1728 #define CHARS_IN_GUID 39
1730 HRESULT
create_monodata(REFIID riid
, LPVOID
*ppObj
)
1732 static const WCHAR wszAssembly
[] = {'A','s','s','e','m','b','l','y',0};
1733 static const WCHAR wszCodebase
[] = {'C','o','d','e','B','a','s','e',0};
1734 static const WCHAR wszClass
[] = {'C','l','a','s','s',0};
1735 static const WCHAR wszFileSlash
[] = {'f','i','l','e',':','/','/','/',0};
1736 static const WCHAR wszCLSIDSlash
[] = {'C','L','S','I','D','\\',0};
1737 static const WCHAR wszInprocServer32
[] = {'\\','I','n','p','r','o','c','S','e','r','v','e','r','3','2',0};
1738 static const WCHAR wszDLL
[] = {'.','d','l','l',0};
1739 WCHAR path
[CHARS_IN_GUID
+ ARRAY_SIZE(wszCLSIDSlash
) + ARRAY_SIZE(wszInprocServer32
) - 1];
1741 MonoAssembly
*assembly
;
1742 ICLRRuntimeInfo
*info
= NULL
;
1748 HANDLE file
= INVALID_HANDLE_VALUE
;
1749 DWORD numKeys
, keyLength
;
1750 WCHAR codebase
[MAX_PATH
+ 8];
1751 WCHAR classname
[350], subkeyName
[256];
1752 WCHAR filename
[MAX_PATH
];
1754 DWORD dwBufLen
= 350;
1756 lstrcpyW(path
, wszCLSIDSlash
);
1757 StringFromGUID2(riid
, path
+ lstrlenW(wszCLSIDSlash
), CHARS_IN_GUID
);
1758 lstrcatW(path
, wszInprocServer32
);
1760 TRACE("Registry key: %s\n", debugstr_w(path
));
1762 res
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, path
, 0, KEY_READ
, &key
);
1763 if (res
!= ERROR_FILE_NOT_FOUND
)
1765 res
= RegGetValueW( key
, NULL
, wszClass
, RRF_RT_REG_SZ
, NULL
, classname
, &dwBufLen
);
1766 if(res
!= ERROR_SUCCESS
)
1768 WARN("Class value cannot be found.\n");
1769 hr
= CLASS_E_CLASSNOTAVAILABLE
;
1773 TRACE("classname (%s)\n", debugstr_w(classname
));
1775 dwBufLen
= MAX_PATH
+ 8;
1776 res
= RegGetValueW( key
, NULL
, wszCodebase
, RRF_RT_REG_SZ
, NULL
, codebase
, &dwBufLen
);
1777 if(res
== ERROR_SUCCESS
)
1779 /* Strip file:/// */
1780 if(wcsncmp(codebase
, wszFileSlash
, lstrlenW(wszFileSlash
)) == 0)
1781 offset
= lstrlenW(wszFileSlash
);
1783 lstrcpyW(filename
, codebase
+ offset
);
1785 file
= CreateFileW(path
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, 0);
1788 if (file
!= INVALID_HANDLE_VALUE
)
1792 WCHAR assemblyname
[MAX_PATH
+ 8];
1794 hr
= CLASS_E_CLASSNOTAVAILABLE
;
1795 WARN("CodeBase value cannot be found, trying Assembly.\n");
1796 /* get the last subkey of InprocServer32 */
1797 res
= RegQueryInfoKeyW(key
, 0, 0, 0, &numKeys
, 0, 0, 0, 0, 0, 0, 0);
1798 if (res
!= ERROR_SUCCESS
)
1803 keyLength
= ARRAY_SIZE(subkeyName
);
1804 res
= RegEnumKeyExW(key
, numKeys
, subkeyName
, &keyLength
, 0, 0, 0, 0);
1805 if (res
!= ERROR_SUCCESS
)
1807 res
= RegOpenKeyExW(key
, subkeyName
, 0, KEY_READ
, &subkey
);
1808 if (res
!= ERROR_SUCCESS
)
1810 dwBufLen
= MAX_PATH
+ 8;
1811 res
= RegGetValueW(subkey
, NULL
, wszAssembly
, RRF_RT_REG_SZ
, NULL
, assemblyname
, &dwBufLen
);
1812 RegCloseKey(subkey
);
1813 if (res
!= ERROR_SUCCESS
)
1818 dwBufLen
= MAX_PATH
+ 8;
1819 res
= RegGetValueW(key
, NULL
, wszAssembly
, RRF_RT_REG_SZ
, NULL
, assemblyname
, &dwBufLen
);
1820 if (res
!= ERROR_SUCCESS
)
1824 hr
= get_file_from_strongname(assemblyname
, filename
, MAX_PATH
);
1828 * The registry doesn't have a CodeBase entry or the file isn't there, and it's not in the GAC.
1830 * Use the Assembly Key to retrieve the filename.
1831 * Assembly : REG_SZ : AssemblyName, Version=X.X.X.X, Culture=neutral, PublicKeyToken=null
1835 WARN("Attempt to load from the application directory.\n");
1836 GetModuleFileNameW(NULL
, filename
, MAX_PATH
);
1837 ns
= wcsrchr(filename
, '\\');
1840 ns
= wcschr(assemblyname
, ',');
1842 lstrcatW(filename
, assemblyname
);
1844 lstrcatW(filename
, wszDLL
);
1850 if (!try_create_registration_free_com(riid
, classname
, ARRAY_SIZE(classname
), filename
, ARRAY_SIZE(filename
)))
1851 return CLASS_E_CLASSNOTAVAILABLE
;
1853 TRACE("classname (%s)\n", debugstr_w(classname
));
1856 TRACE("filename (%s)\n", debugstr_w(filename
));
1861 hr
= get_runtime_info(filename
, NULL
, NULL
, NULL
, 0, 0, FALSE
, &info
);
1864 hr
= ICLRRuntimeInfo_GetRuntimeHost(info
, &host
);
1867 hr
= RuntimeHost_GetDefaultDomain(host
, NULL
, &domain
);
1874 MonoDomain
*prev_domain
;
1875 MonoImageOpenStatus status
;
1876 IUnknown
*unk
= NULL
;
1877 char *filenameA
, *ns
;
1880 hr
= CLASS_E_CLASSNOTAVAILABLE
;
1882 prev_domain
= domain_attach(domain
);
1884 filenameA
= WtoA(filename
);
1885 assembly
= mono_assembly_open(filenameA
, &status
);
1886 HeapFree(GetProcessHeap(), 0, filenameA
);
1889 ERR("Cannot open assembly %s, status=%i\n", filenameA
, status
);
1890 domain_restore(prev_domain
);
1894 image
= mono_assembly_get_image(assembly
);
1897 ERR("Couldn't get assembly image\n");
1898 domain_restore(prev_domain
);
1902 classA
= WtoA(classname
);
1903 ns
= strrchr(classA
, '.');
1906 klass
= mono_class_from_name(image
, classA
, ns
+1);
1907 HeapFree(GetProcessHeap(), 0, classA
);
1910 ERR("Couldn't get class from image\n");
1911 domain_restore(prev_domain
);
1916 * Use the default constructor for the .NET class.
1918 result
= mono_object_new(domain
, klass
);
1919 mono_runtime_object_init(result
);
1921 hr
= RuntimeHost_GetIUnknownForObject(host
, result
, &unk
);
1924 hr
= IUnknown_QueryInterface(unk
, &IID_IUnknown
, ppObj
);
1926 IUnknown_Release(unk
);
1929 hr
= CLASS_E_CLASSNOTAVAILABLE
;
1931 domain_restore(prev_domain
);
1934 hr
= CLASS_E_CLASSNOTAVAILABLE
;
1937 hr
= CLASS_E_CLASSNOTAVAILABLE
;
1941 ICLRRuntimeInfo_Release(info
);