X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=mono%2Fmetadata%2Fcominterop.c;h=07a2e638c0b5747b09adc0438da16c2f39055e0f;hb=424595ea7043f30b0553f2842654db13baeda3ca;hp=f6adfcd1ce07c3ca3923a3a0db0de8237d5a4fa4;hpb=c133ae2dc82c0533f5790333a3c93b2635b9c43c;p=mono.git diff --git a/mono/metadata/cominterop.c b/mono/metadata/cominterop.c index f6adfcd1ce0..07a2e638c0b 100644 --- a/mono/metadata/cominterop.c +++ b/mono/metadata/cominterop.c @@ -32,9 +32,22 @@ #include "mono/metadata/attrdefs.h" #include "mono/metadata/gc-internal.h" #include "mono/utils/mono-counters.h" +#include "mono/utils/strenc.h" +#include "mono/utils/atomic.h" #include #include +/* +Code shared between the DISABLE_COM and !DISABLE_COM +*/ +static void +register_icall (gpointer func, const char *name, const char *sigstr, gboolean save) +{ + MonoMethodSignature *sig = mono_create_icall_signature (sigstr); + + mono_register_jit_icall (func, name, sig, save); +} + #ifndef DISABLE_COM #define OPDEF(a,b,c,d,e,f,g,h,i,j) \ @@ -72,6 +85,13 @@ static CRITICAL_SECTION cominterop_mutex; #define STDCALL #endif +GENERATE_GET_CLASS_WITH_CACHE (interop_proxy, Mono.Interop, ComInteropProxy) +GENERATE_GET_CLASS_WITH_CACHE (idispatch, Mono.Interop, IDispatch) +GENERATE_GET_CLASS_WITH_CACHE (iunknown, Mono.Interop, IUnknown) + +GENERATE_GET_CLASS_WITH_CACHE (com_object, System, __ComObject) +GENERATE_GET_CLASS_WITH_CACHE (variant, System, Variant) + /* Upon creation of a CCW, only allocate a weak handle and set the * reference count to 0. If the unmanaged client code decides to addref and * hold onto the CCW, I then allocate a strong handle. Once the reference count @@ -243,7 +263,7 @@ cominterop_object_is_rcw (MonoObject *obj) if (!obj) return FALSE; klass = mono_object_class (obj); - if (klass != mono_defaults.transparent_proxy_class) + if (!mono_class_is_transparent_proxy (klass)) return FALSE; real_proxy = ((MonoTransparentProxy*)obj)->rp; @@ -251,7 +271,7 @@ cominterop_object_is_rcw (MonoObject *obj) return FALSE; klass = mono_object_class (real_proxy); - return (klass && klass == mono_defaults.com_interop_proxy_class); + return (klass && klass == mono_class_get_interop_proxy_class ()); } static int @@ -502,22 +522,14 @@ cominterop_type_from_handle (MonoType *handle) return mono_type_get_object (domain, handle); } -static void -register_icall (gpointer func, const char *name, const char *sigstr, gboolean save) -{ - MonoMethodSignature *sig = mono_create_icall_signature (sigstr); - - mono_register_jit_icall (func, name, sig, save); -} - void mono_cominterop_init (void) { - char* com_provider_env = NULL; + const char* com_provider_env; InitializeCriticalSection (&cominterop_mutex); - com_provider_env = getenv ("MONO_COM"); + com_provider_env = g_getenv ("MONO_COM"); if (com_provider_env && !strcmp(com_provider_env, "MS")) com_provider = MONO_COM_MS; @@ -578,9 +590,6 @@ mono_cominterop_emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, int real_proxy; guint32 pos_null = 0, pos_ccw = 0, pos_end = 0; MonoClass *klass = NULL; - - /* COM types are initialized lazily */ - mono_init_com_types (); klass = mono_class_from_mono_type (type); @@ -605,14 +614,16 @@ mono_cominterop_emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, com_interop_proxy_class = mono_class_from_name (mono_defaults.corlib, "Mono.Interop", "ComInteropProxy"); if (!com_interop_proxy_get_proxy) com_interop_proxy_get_proxy = mono_class_get_method_from_name_flags (com_interop_proxy_class, "GetProxy", 2, METHOD_ATTRIBUTE_PRIVATE); +#ifndef DISABLE_REMOTING if (!get_transparent_proxy) get_transparent_proxy = mono_class_get_method_from_name (mono_defaults.real_proxy_class, "GetTransparentProxy", 0); +#endif real_proxy = mono_mb_add_local (mb, &com_interop_proxy_class->byval_arg); mono_mb_emit_ldloc (mb, 0); mono_mb_emit_byte (mb, CEE_LDIND_I); - mono_mb_emit_ptr (mb, &mono_defaults.com_object_class->byval_arg); + mono_mb_emit_ptr (mb, &mono_class_get_com_object_class ()->byval_arg); mono_mb_emit_icall (mb, cominterop_type_from_handle); mono_mb_emit_managed_call (mb, com_interop_proxy_get_proxy, NULL); mono_mb_emit_managed_call (mb, get_transparent_proxy, NULL); @@ -654,10 +665,6 @@ mono_cominterop_emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, case MONO_MARSHAL_CONV_OBJECT_IDISPATCH: case MONO_MARSHAL_CONV_OBJECT_IUNKNOWN: { guint32 pos_null = 0, pos_rcw = 0, pos_end = 0; - - /* COM types are initialized lazily */ - mono_init_com_types (); - mono_mb_emit_ldloc (mb, 1); mono_mb_emit_icon (mb, 0); @@ -698,14 +705,14 @@ mono_cominterop_emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, static MonoProperty* iunknown = NULL; if (!iunknown) - iunknown = mono_class_get_property_from_name (mono_defaults.com_object_class, "IUnknown"); + iunknown = mono_class_get_property_from_name (mono_class_get_com_object_class (), "IUnknown"); mono_mb_emit_managed_call (mb, iunknown->get, NULL); } else if (conv == MONO_MARSHAL_CONV_OBJECT_IDISPATCH) { static MonoProperty* idispatch = NULL; if (!idispatch) - idispatch = mono_class_get_property_from_name (mono_defaults.com_object_class, "IDispatch"); + idispatch = mono_class_get_property_from_name (mono_class_get_com_object_class (), "IDispatch"); mono_mb_emit_managed_call (mb, idispatch->get, NULL); } else { @@ -725,9 +732,9 @@ mono_cominterop_emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, if (conv == MONO_MARSHAL_CONV_OBJECT_INTERFACE) mono_mb_emit_ptr (mb, mono_type_get_class (type)); else if (conv == MONO_MARSHAL_CONV_OBJECT_IUNKNOWN) - mono_mb_emit_ptr (mb, mono_defaults.iunknown_class); + mono_mb_emit_ptr (mb, mono_class_get_iunknown_class ()); else if (conv == MONO_MARSHAL_CONV_OBJECT_IDISPATCH) - mono_mb_emit_ptr (mb, mono_defaults.idispatch_class); + mono_mb_emit_ptr (mb, mono_class_get_idispatch_class ()); else g_assert_not_reached (); mono_mb_emit_icall (mb, cominterop_get_ccw); @@ -865,8 +872,6 @@ mono_cominterop_get_native_wrapper (MonoMethod *method) if ((res = mono_marshal_find_in_cache (cache, method))) return res; - mono_init_com_types (); - if (!method->klass->vtable) mono_class_setup_vtable (method->klass); @@ -888,7 +893,7 @@ mono_cominterop_get_native_wrapper (MonoMethod *method) static MonoMethod *ctor = NULL; if (!ctor) - ctor = mono_class_get_method_from_name (mono_defaults.com_object_class, ".ctor", 0); + ctor = mono_class_get_method_from_name (mono_class_get_com_object_class (), ".ctor", 0); mono_mb_emit_ldarg (mb, 0); mono_mb_emit_managed_call (mb, ctor, NULL); mono_mb_emit_byte (mb, CEE_RET); @@ -1084,9 +1089,6 @@ mono_cominterop_emit_marshal_com_interface (EmitMarshalContext *m, int argnum, if (!marshal_release) marshal_release = mono_class_get_method_from_name (mono_defaults.marshal_class, "Release", 1); - /* COM types are initialized lazily */ - mono_init_com_types (); - switch (action) { case MARSHAL_ACTION_CONV_IN: { guint32 pos_null = 0; @@ -1387,6 +1389,9 @@ typedef struct #define MONO_S_OK 0x00000000L #define MONO_E_NOINTERFACE 0x80004002L #define MONO_E_NOTIMPL 0x80004001L +#define MONO_E_INVALIDARG 0x80070057L +#define MONO_E_DISP_E_UNKNOWNNAME 0x80020006L +#define MONO_E_DISPID_UNKNOWN (gint32)-1 int ves_icall_System_Runtime_InteropServices_Marshal_AddRefInternal (gpointer pUnk) @@ -1428,13 +1433,13 @@ cominterop_get_idispatch_for_object (MonoObject* object) if (cominterop_object_is_rcw (object)) { return cominterop_get_interface (((MonoComInteropProxy*)((MonoTransparentProxy*)object)->rp)->com_object, - mono_defaults.idispatch_class, TRUE); + mono_class_get_idispatch_class (), TRUE); } else { MonoClass* klass = mono_object_class (object); if (!cominterop_can_support_dispatch (klass) ) cominterop_raise_hr_exception (MONO_E_NOINTERFACE); - return cominterop_get_ccw (object, mono_defaults.idispatch_class); + return cominterop_get_ccw (object, mono_class_get_idispatch_class ()); } } @@ -1445,15 +1450,13 @@ ves_icall_System_Runtime_InteropServices_Marshal_GetIUnknownForObjectInternal (M if (!object) return NULL; - mono_init_com_types (); - if (cominterop_object_is_rcw (object)) { MonoClass *klass = NULL; MonoRealProxy* real_proxy = NULL; if (!object) return NULL; klass = mono_object_class (object); - if (klass != mono_defaults.transparent_proxy_class) { + if (!mono_class_is_transparent_proxy (klass)) { g_assert_not_reached (); return NULL; } @@ -1465,7 +1468,7 @@ ves_icall_System_Runtime_InteropServices_Marshal_GetIUnknownForObjectInternal (M } klass = mono_object_class (real_proxy); - if (klass != mono_defaults.com_interop_proxy_class) { + if (klass != mono_class_get_interop_proxy_class ()) { g_assert_not_reached (); return NULL; } @@ -1478,7 +1481,7 @@ ves_icall_System_Runtime_InteropServices_Marshal_GetIUnknownForObjectInternal (M return ((MonoComInteropProxy*)real_proxy)->com_object->iunknown; } else { - return cominterop_get_ccw (object, mono_defaults.iunknown_class); + return cominterop_get_ccw (object, mono_class_get_iunknown_class ()); } #else g_assert_not_reached (); @@ -1507,8 +1510,6 @@ void* ves_icall_System_Runtime_InteropServices_Marshal_GetIDispatchForObjectInternal (MonoObject* object) { #ifndef DISABLE_COM - mono_init_com_types (); - return cominterop_get_idispatch_for_object (object); #else g_assert_not_reached (); @@ -1893,10 +1894,10 @@ cominterop_get_ccw (MonoObject* object, MonoClass* itf) } iface = itf; - if (iface == mono_defaults.iunknown_class) { + if (iface == mono_class_get_iunknown_class ()) { start_slot = 3; } - else if (iface == mono_defaults.idispatch_class) { + else if (iface == mono_class_get_idispatch_class ()) { start_slot = 7; } else { @@ -1999,11 +2000,9 @@ cominterop_get_ccw (MonoObject* object, MonoClass* itf) cominterop_setup_marshal_context (&m, adjust_method); m.mb = mb; mono_marshal_emit_managed_wrapper (mb, sig_adjusted, mspecs, &m, adjust_method, 0); - mono_loader_lock (); mono_cominterop_lock (); wrapper_method = mono_mb_create_method (mb, m.csig, m.csig->param_count + 16); mono_cominterop_unlock (); - mono_loader_unlock (); vtable [vtable_index--] = mono_compile_method (wrapper_method); @@ -2072,6 +2071,12 @@ mono_marshal_free_ccw (MonoObject* object) /* remove ccw from list */ ccw_list = g_list_remove (ccw_list, ccw_iter); + +#ifdef HOST_WIN32 + if (ccw_iter->free_marshaler) + ves_icall_System_Runtime_InteropServices_Marshal_ReleaseInternal (ccw_iter->free_marshaler); +#endif + g_free (ccw_iter); } else @@ -2201,11 +2206,9 @@ cominterop_get_managed_wrapper_adjusted (MonoMethod *method) mono_mb_emit_byte (mb, CEE_RET); - mono_loader_lock (); mono_cominterop_lock (); res = mono_mb_create_method (mb, sig_native, sig_native->param_count + 16); mono_cominterop_unlock (); - mono_loader_unlock (); mono_mb_free (mb); @@ -2273,10 +2276,6 @@ cominterop_ccw_release (MonoCCWInterface* ccwe) /* allow gc of object */ guint32 oldhandle = ccw->gc_handle; g_assert (oldhandle); -#ifdef HOST_WIN32 - if (ccw->free_marshaler) - ves_icall_System_Runtime_InteropServices_Marshal_ReleaseInternal (ccw->free_marshaler); -#endif ccw->gc_handle = mono_gchandle_new_weakref (mono_gchandle_get_target (oldhandle), FALSE); mono_gchandle_free (oldhandle); } @@ -2296,11 +2295,8 @@ cominterop_ccw_getfreethreadedmarshaler (MonoCCW* ccw, MonoObject* object, gpoin if (!ccw->free_marshaler) { int ret = 0; gpointer tunk; - tunk = cominterop_get_ccw (object, mono_defaults.iunknown_class); - /* remember to addref on QI */ - cominterop_ccw_addref (tunk); + tunk = cominterop_get_ccw (object, mono_class_get_iunknown_class ()); ret = CoCreateFreeThreadedMarshaler (tunk, (LPUNKNOWN*)&ccw->free_marshaler); - cominterop_ccw_release(tunk); } if (!ccw->free_marshaler) @@ -2335,19 +2331,19 @@ cominterop_ccw_queryinterface (MonoCCWInterface* ccwe, guint8* riid, gpointer* p mono_thread_attach (mono_get_root_domain ()); /* handle IUnknown special */ - if (cominterop_class_guid_equal (riid, mono_defaults.iunknown_class)) { - *ppv = cominterop_get_ccw (object, mono_defaults.iunknown_class); + if (cominterop_class_guid_equal (riid, mono_class_get_iunknown_class ())) { + *ppv = cominterop_get_ccw (object, mono_class_get_iunknown_class ()); /* remember to addref on QI */ cominterop_ccw_addref (*ppv); return MONO_S_OK; } /* handle IDispatch special */ - if (cominterop_class_guid_equal (riid, mono_defaults.idispatch_class)) { + if (cominterop_class_guid_equal (riid, mono_class_get_idispatch_class ())) { if (!cominterop_can_support_dispatch (klass)) return MONO_E_NOINTERFACE; - *ppv = cominterop_get_ccw (object, mono_defaults.idispatch_class); + *ppv = cominterop_get_ccw (object, mono_class_get_idispatch_class ()); /* remember to addref on QI */ cominterop_ccw_addref (*ppv); return MONO_S_OK; @@ -2393,7 +2389,12 @@ cominterop_ccw_queryinterface (MonoCCWInterface* ccwe, guint8* riid, gpointer* p static int STDCALL cominterop_ccw_get_type_info_count (MonoCCWInterface* ccwe, guint32 *pctinfo) { - return MONO_E_NOTIMPL; + if(!pctinfo) + return MONO_E_INVALIDARG; + + *pctinfo = 1; + + return MONO_S_OK; } static int STDCALL @@ -2407,7 +2408,51 @@ cominterop_ccw_get_ids_of_names (MonoCCWInterface* ccwe, gpointer riid, gunichar2** rgszNames, guint32 cNames, guint32 lcid, gint32 *rgDispId) { - return MONO_E_NOTIMPL; + static MonoClass *ComDispIdAttribute = NULL; + MonoCustomAttrInfo *cinfo = NULL; + int i,ret = MONO_S_OK; + MonoMethod* method; + gchar* methodname; + MonoClass *klass = NULL; + MonoCCW* ccw = ccwe->ccw; + MonoObject* object = mono_gchandle_get_target (ccw->gc_handle); + + /* Handle DispIdAttribute */ + if (!ComDispIdAttribute) + ComDispIdAttribute = mono_class_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "DispIdAttribute"); + + g_assert (object); + klass = mono_object_class (object); + + if (!mono_domain_get ()) + mono_thread_attach (mono_get_root_domain ()); + + for (i=0; i < cNames; i++) { + methodname = mono_unicode_to_external (rgszNames[i]); + + method = mono_class_get_method_from_name(klass, methodname, -1); + if (method) { + cinfo = mono_custom_attrs_from_method (method); + if (cinfo) { + MonoObject *result = mono_custom_attrs_get_attr (cinfo, ComDispIdAttribute); + + if (result) + rgDispId[i] = *(gint32*)mono_object_unbox (result); + else + rgDispId[i] = (gint32)method->token; + + if (!cinfo->cached) + mono_custom_attrs_free (cinfo); + } + else + rgDispId[i] = (gint32)method->token; + } else { + rgDispId[i] = MONO_E_DISPID_UNKNOWN; + ret = MONO_E_DISP_E_UNKNOWNNAME; + } + } + + return ret; } static int STDCALL @@ -2636,8 +2681,6 @@ mono_cominterop_emit_marshal_safearray (EmitMarshalContext *m, int argnum, MonoT { MonoMethodBuilder *mb = m->mb; - mono_init_com_types (); - switch (action) { case MARSHAL_ACTION_CONV_IN: { @@ -2714,7 +2757,7 @@ mono_cominterop_emit_marshal_safearray (EmitMarshalContext *m, int argnum, MonoT get_native_variant_for_object = mono_class_get_method_from_name (mono_defaults.marshal_class, "GetNativeVariantForObject", 2); g_assert (get_native_variant_for_object); - elem_var = mono_mb_add_local (mb, &mono_defaults.variant_class->byval_arg); + elem_var = mono_mb_add_local (mb, &mono_class_get_variant_class ()->byval_arg); mono_mb_emit_ldloc_addr (mb, elem_var); mono_mb_emit_managed_call (mb, get_native_variant_for_object, NULL); @@ -2725,7 +2768,7 @@ mono_cominterop_emit_marshal_safearray (EmitMarshalContext *m, int argnum, MonoT mono_mb_emit_icall (mb, mono_marshal_safearray_set_value); if (!variant_clear) - variant_clear = mono_class_get_method_from_name (mono_defaults.variant_class, "Clear", 0); + variant_clear = mono_class_get_method_from_name (mono_class_get_variant_class (), "Clear", 0); mono_mb_emit_ldloc_addr (mb, elem_var); mono_mb_emit_managed_call (mb, variant_clear, NULL); @@ -3142,6 +3185,19 @@ void mono_marshal_safearray_free_indices (gpointer indices) void mono_cominterop_init (void) { + /*FIXME + + This icalls are used by the marshal code when doing PtrToStructure and StructureToPtr and pinvoke. + + If we leave them out and the FullAOT compiler finds the need to emit one of the above 3 wrappers it will + g_assert. + + The proper fix would be to emit warning, remove them from marshal.c when DISABLE_COM is used and + emit an exception in the generated IL. + */ + register_icall (mono_string_to_bstr, "mono_string_to_bstr", "ptr obj", FALSE); + register_icall (mono_string_from_bstr, "mono_string_from_bstr", "obj ptr", FALSE); + register_icall (mono_free_bstr, "mono_free_bstr", "void ptr", FALSE); } void