From 89e08d9918e7234e8e6f09d3180bf2726b779a5c Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 31 Jan 2024 12:31:36 -0800 Subject: [PATCH 01/12] Remove built-in COM interop support from Mono runtime --- src/mono/CMakeLists.txt | 2 - .../src/System/RuntimeTypeHandle.cs | 8 +- src/mono/cmake/config.h.in | 3 - src/mono/cmake/options.cmake | 1 - src/mono/mono/component/marshal-ilgen.c | 128 - .../eventpipe/ep-rt-mono-runtime-provider.c | 2 - src/mono/mono/metadata/class-accessors.c | 10 - src/mono/mono/metadata/class-getters.h | 1 - src/mono/mono/metadata/class-init.c | 35 +- src/mono/mono/metadata/class-internals.h | 20 - .../mono/metadata/class-private-definition.h | 7 +- src/mono/mono/metadata/cominterop.c | 4212 +---------------- src/mono/mono/metadata/cominterop.h | 47 - src/mono/mono/metadata/icall-def.h | 1 - src/mono/mono/metadata/icall.c | 77 - src/mono/mono/metadata/jit-icall-reg.h | 16 - src/mono/mono/metadata/marshal-lightweight.c | 49 +- src/mono/mono/metadata/marshal-shared.c | 34 - src/mono/mono/metadata/marshal.c | 65 +- src/mono/mono/metadata/marshal.h | 12 - src/mono/mono/metadata/metadata.c | 241 - src/mono/mono/metadata/object.c | 86 +- 22 files changed, 107 insertions(+), 4950 deletions(-) diff --git a/src/mono/CMakeLists.txt b/src/mono/CMakeLists.txt index d5374b3bca6a8a..f79c2ca477812b 100644 --- a/src/mono/CMakeLists.txt +++ b/src/mono/CMakeLists.txt @@ -84,8 +84,6 @@ if(ENABLE_MINIMAL) process_enable_minimal() endif() -set(DISABLE_COM 1) - # Dependencies between options if(ENABLE_INTERP_LIB) set(DISABLE_INTERPRETER 1) diff --git a/src/mono/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs b/src/mono/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs index 7646247d0545d8..d155989bb3c92c 100644 --- a/src/mono/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs +++ b/src/mono/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs @@ -205,9 +205,6 @@ internal static bool HasElementType(RuntimeType type) [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern bool HasInstantiation(QCallTypeHandle type); - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern bool IsComObject(QCallTypeHandle type); - [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern bool IsInstanceOfType(QCallTypeHandle type, [NotNullWhen(true)] object? o); @@ -234,10 +231,13 @@ internal static bool HasInstantiation(RuntimeType type) return HasInstantiation(new QCallTypeHandle(ref type)); } +#pragma warning disable IDE0060 internal static bool IsComObject(RuntimeType type, bool isGenericCOM) { - return isGenericCOM ? false : IsComObject(new QCallTypeHandle(ref type)); + // Mono runtime doesn't support built-in COM. + return false; } +#pragma warning restore IDE0060 #pragma warning disable IDE0060 internal static bool IsEquivalentTo(RuntimeType rtType1, RuntimeType rtType2) diff --git a/src/mono/cmake/config.h.in b/src/mono/cmake/config.h.in index 41286766d7bc44..e484a802aed9b5 100644 --- a/src/mono/cmake/config.h.in +++ b/src/mono/cmake/config.h.in @@ -235,9 +235,6 @@ /* Disable support debug logging */ #cmakedefine DISABLE_LOGGING 1 -/* Disable COM support */ -#cmakedefine DISABLE_COM 1 - /* Disable advanced SSA JIT optimizations */ #cmakedefine DISABLE_SSA 1 diff --git a/src/mono/cmake/options.cmake b/src/mono/cmake/options.cmake index e5921ac358f5fd..bf37c2583f97d4 100644 --- a/src/mono/cmake/options.cmake +++ b/src/mono/cmake/options.cmake @@ -6,7 +6,6 @@ option (DISABLE_AOT "Disable AOT Compiler") option (DISABLE_DEBUG "Disable runtime debugging support") option (DISABLE_REFLECTION_EMIT "Disable reflection emit support") option (DISABLE_LOGGING "Disable support debug logging") -option (DISABLE_COM "Disable COM support") option (DISABLE_SSA "Disable advanced SSA JIT optimizations") option (DISABLE_JIT "Disable the JIT, only full-aot mode or interpreter will be supported by the runtime.") option (DISABLE_INTERPRETER "Disable the interpreter.") diff --git a/src/mono/mono/component/marshal-ilgen.c b/src/mono/mono/component/marshal-ilgen.c index 65d8ee64b6eae2..ee5c60bd419535 100644 --- a/src/mono/mono/component/marshal-ilgen.c +++ b/src/mono/mono/component/marshal-ilgen.c @@ -414,15 +414,6 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, switch (spec->native) { case MONO_NATIVE_LPARRAY: break; - case MONO_NATIVE_SAFEARRAY: -#ifndef DISABLE_COM - if (spec->data.safearray_data.elem_type != MONO_VARIANT_VARIANT) { - char *msg = g_strdup ("Only SAFEARRAY(VARIANT) marshalling to managed code is implemented."); - cb_to_mono->methodBuilder.emit_exception_marshal_directive (mb, msg); - return conv_arg; - } - return mono_cominterop_emit_marshal_safearray (m, argnum, t, spec, conv_arg, conv_arg_type, action); -#endif default: { char *msg = g_strdup ("Unsupported array type marshalling to managed code."); cb_to_mono->methodBuilder.emit_exception_marshal_directive (mb, msg); @@ -2618,108 +2609,6 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, return conv_arg; } -static int -emit_marshal_variant_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, - MarshalAction action) -{ -#ifndef DISABLE_COM - MonoMethodBuilder *mb = m->mb; - MonoType *variant_type = m_class_get_byval_arg (mono_class_get_variant_class ()); - MonoType *variant_type_byref = mono_class_get_byref_type (mono_class_get_variant_class ()); - MonoType *object_type = cb_to_mono->get_object_type (); - - switch (action) { - case MARSHAL_ACTION_CONV_IN: { - conv_arg = cb_to_mono->methodBuilder.add_local (mb, variant_type); - - if (m_type_is_byref (t)) - *conv_arg_type = variant_type_byref; - else - *conv_arg_type = variant_type; - - if (m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && t->attrs & PARAM_ATTRIBUTE_OUT) - break; - - cb_to_mono->methodBuilder.emit_ldarg (mb, argnum); - if (m_type_is_byref (t)) - cb_to_mono->methodBuilder.emit_byte(mb, CEE_LDIND_REF); - cb_to_mono->methodBuilder.emit_ldloc_addr (mb, conv_arg); - cb_to_mono->methodBuilder.emit_managed_call (mb, mono_get_Marshal_GetNativeVariantForObject (), NULL); - break; - } - - case MARSHAL_ACTION_CONV_OUT: { - if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN))) { - cb_to_mono->methodBuilder.emit_ldarg (mb, argnum); - cb_to_mono->methodBuilder.emit_ldloc_addr (mb, conv_arg); - cb_to_mono->methodBuilder.emit_managed_call (mb, mono_get_Marshal_GetObjectForNativeVariant (), NULL); - cb_to_mono->methodBuilder.emit_byte (mb, CEE_STIND_REF); - } - - cb_to_mono->methodBuilder.emit_ldloc_addr (mb, conv_arg); - cb_to_mono->methodBuilder.emit_managed_call (mb, mono_get_Variant_Clear (), NULL); - break; - } - - case MARSHAL_ACTION_PUSH: - if (m_type_is_byref (t)) - cb_to_mono->methodBuilder.emit_ldloc_addr (mb, conv_arg); - else - cb_to_mono->methodBuilder.emit_ldloc (mb, conv_arg); - break; - - case MARSHAL_ACTION_CONV_RESULT: { - char *msg = g_strdup ("Marshalling of VARIANT not supported as a return type."); - cb_to_mono->methodBuilder.emit_exception_marshal_directive (mb, msg); - break; - } - - case MARSHAL_ACTION_MANAGED_CONV_IN: { - conv_arg = cb_to_mono->methodBuilder.add_local (mb, object_type); - - if (m_type_is_byref (t)) - *conv_arg_type = variant_type_byref; - else - *conv_arg_type = variant_type; - - if (m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && t->attrs & PARAM_ATTRIBUTE_OUT) - break; - - if (m_type_is_byref (t)) - cb_to_mono->methodBuilder.emit_ldarg (mb, argnum); - else - cb_to_mono->methodBuilder.emit_ldarg_addr (mb, argnum); - cb_to_mono->methodBuilder.emit_managed_call (mb, mono_get_Marshal_GetObjectForNativeVariant (), NULL); - cb_to_mono->methodBuilder.emit_stloc (mb, conv_arg); - break; - } - - case MARSHAL_ACTION_MANAGED_CONV_OUT: { - if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN))) { - cb_to_mono->methodBuilder.emit_ldloc (mb, conv_arg); - cb_to_mono->methodBuilder.emit_ldarg (mb, argnum); - cb_to_mono->methodBuilder.emit_managed_call (mb, mono_get_Marshal_GetNativeVariantForObject (), NULL); - } - break; - } - - case MARSHAL_ACTION_MANAGED_CONV_RESULT: { - char *msg = g_strdup ("Marshalling of VARIANT not supported as a return type."); - cb_to_mono->methodBuilder.emit_exception_marshal_directive (mb, msg); - break; - } - - default: - g_assert_not_reached (); - } -#endif /* DISABLE_COM */ - - return conv_arg; -} - - static int emit_marshal_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, MonoMarshalSpec *spec, int conv_arg, @@ -2741,23 +2630,6 @@ emit_marshal_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, return emit_marshal_string_ilgen (m, argnum, t, spec, conv_arg, conv_arg_type, action); case MONO_TYPE_CLASS: case MONO_TYPE_OBJECT: -#if !defined(DISABLE_COM) - if (spec && spec->native == MONO_NATIVE_STRUCT) - return emit_marshal_variant_ilgen (m, argnum, t, spec, conv_arg, conv_arg_type, action); -#endif - -#if !defined(DISABLE_COM) - if ((spec && (spec->native == MONO_NATIVE_IUNKNOWN || - spec->native == MONO_NATIVE_IDISPATCH || - spec->native == MONO_NATIVE_INTERFACE)) || - (t->type == MONO_TYPE_CLASS && mono_cominterop_is_interface(t->data.klass))) - return mono_cominterop_emit_marshal_com_interface (m, argnum, t, spec, conv_arg, conv_arg_type, action); - if (spec && (spec->native == MONO_NATIVE_SAFEARRAY) && - (spec->data.safearray_data.elem_type == MONO_VARIANT_VARIANT) && - ((action == MARSHAL_ACTION_CONV_OUT) || (action == MARSHAL_ACTION_CONV_IN) || (action == MARSHAL_ACTION_PUSH))) - return mono_cominterop_emit_marshal_safearray (m, argnum, t, spec, conv_arg, conv_arg_type, action); -#endif - if (cb_to_mono->try_get_safehandle_class () != NULL && t->data.klass && cb_to_mono->is_subclass_of_internal (t->data.klass, cb_to_mono->try_get_safehandle_class (), FALSE)) return emit_marshal_safehandle_ilgen (m, argnum, t, spec, conv_arg, conv_arg_type, action); diff --git a/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c b/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c index 0b31632fd53b17..e559d666017061 100644 --- a/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c +++ b/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c @@ -1547,8 +1547,6 @@ bulk_type_log_single_type ( val->fixed_sized_data.flags |= TYPE_FLAGS_FINALIZABLE; if (m_class_is_delegate (klass)) val->fixed_sized_data.flags |= TYPE_FLAGS_DELEGATE; - if (mono_class_is_com_object (klass)) - val->fixed_sized_data.flags |= TYPE_FLAGS_EXTERNALLY_IMPLEMENTED_COM_OBJECT; val->fixed_sized_data.cor_element_type = (uint8_t)mono_underlying_type->type; // Sets val variable sized parameter type data, type_parameters_count, and mono_type_parameters associated diff --git a/src/mono/mono/metadata/class-accessors.c b/src/mono/mono/metadata/class-accessors.c index f74b2dc4dbe704..b18b16b985df49 100644 --- a/src/mono/mono/metadata/class-accessors.c +++ b/src/mono/mono/metadata/class-accessors.c @@ -437,16 +437,6 @@ mono_class_set_declsec_flags (MonoClass *klass, guint32 value) mono_property_bag_add (m_class_get_infrequent_data (klass), prop); } -void -mono_class_set_is_com_object (MonoClass *klass) -{ -#ifndef DISABLE_COM - mono_loader_lock (); - klass->is_com_object = 1; - mono_loader_unlock (); -#endif -} - void mono_class_set_is_simd_type (MonoClass *klass, gboolean is_simd) { diff --git a/src/mono/mono/metadata/class-getters.h b/src/mono/mono/metadata/class-getters.h index c0e15059991ad6..eb69558a1d01b1 100644 --- a/src/mono/mono/metadata/class-getters.h +++ b/src/mono/mono/metadata/class-getters.h @@ -41,7 +41,6 @@ MONO_CLASS_GETTER(m_class_has_cctor, gboolean, , MonoClass, has_cctor) MONO_CLASS_GETTER(m_class_has_references, gboolean, , MonoClass, has_references) MONO_CLASS_GETTER(m_class_has_static_refs, gboolean, , MonoClass, has_static_refs) MONO_CLASS_GETTER(m_class_has_no_special_static_fields, gboolean, , MonoClass, no_special_static_fields) -MONO_CLASS_GETTER(m_class_is_com_object, gboolean, , MonoClass, is_com_object) MONO_CLASS_GETTER(m_class_is_nested_classes_inited, gboolean, , MonoClass, nested_classes_inited) MONO_CLASS_GETTER(m_class_get_class_kind, guint8, , MonoClass, class_kind) MONO_CLASS_GETTER(m_class_is_interfaces_inited, gboolean, , MonoClass, interfaces_inited) diff --git a/src/mono/mono/metadata/class-init.c b/src/mono/mono/metadata/class-init.c index ff73588c613d2d..584ba25dcfdf26 100644 --- a/src/mono/mono/metadata/class-init.c +++ b/src/mono/mono/metadata/class-init.c @@ -564,6 +564,11 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError } } + if (MONO_CLASS_IS_IMPORT (klass)) { + mono_class_set_failure_and_error (klass, error, "Built-in COM interop is not supported on the Mono runtime."); + goto parent_failure; + } + mono_class_setup_parent (klass, parent); /* uses ->valuetype, which is initialized by mono_class_setup_parent above */ @@ -3196,20 +3201,6 @@ mono_class_init_checked (MonoClass *klass, MonoError *error) return success; } -#ifndef DISABLE_COM -/* - * COM initialization is delayed until needed. - * However when a [ComImport] attribute is present on a type it will trigger - * the initialization. This is not a problem unless the BCL being executed - * lacks the types that COM depends on (e.g. Variant on Silverlight). - */ -static void -init_com_from_comimport (MonoClass *klass) -{ - /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */ -} -#endif /*DISABLE_COM*/ - /* * LOCKING: this assumes the loader lock is held */ @@ -3234,14 +3225,6 @@ mono_class_setup_parent (MonoClass *klass, MonoClass *parent) } if (!MONO_CLASS_IS_INTERFACE_INTERNAL (klass)) { - /* Imported COM Objects always derive from __ComObject. */ -#ifndef DISABLE_COM - if (MONO_CLASS_IS_IMPORT (klass)) { - init_com_from_comimport (klass); - if (parent == mono_defaults.object_class) - parent = mono_class_get_com_object_class (); - } -#endif if (!parent) { /* set the parent to something useful and safe, but mark the type as broken */ parent = mono_defaults.object_class; @@ -3262,9 +3245,6 @@ mono_class_setup_parent (MonoClass *klass, MonoClass *parent) klass->delegate = parent->delegate; - if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent)) - mono_class_set_is_com_object (klass); - if (system_namespace) { if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate")) klass->delegate = 1; @@ -3278,11 +3258,6 @@ mono_class_setup_parent (MonoClass *klass, MonoClass *parent) } /*klass->enumtype = klass->parent->enumtype; */ } else { - /* initialize com types if COM interfaces are present */ -#ifndef DISABLE_COM - if (MONO_CLASS_IS_IMPORT (klass)) - init_com_from_comimport (klass); -#endif klass->parent = NULL; } diff --git a/src/mono/mono/metadata/class-internals.h b/src/mono/mono/metadata/class-internals.h index 0015177d5c2c33..192d138c57783d 100644 --- a/src/mono/mono/metadata/class-internals.h +++ b/src/mono/mono/metadata/class-internals.h @@ -332,13 +332,6 @@ int mono_class_interface_match (const uint8_t *bitmap, int id); #define MONO_VTABLE_AVAILABLE_GC_BITS 4 -#ifdef DISABLE_COM -#define mono_class_is_com_object(klass) (FALSE) -#else -#define mono_class_is_com_object(klass) (m_class_is_com_object (klass)) -#endif - - MONO_API int mono_class_interface_offset (MonoClass *klass, MonoClass *itf); MONO_COMPONENT_API int mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match); @@ -980,16 +973,6 @@ mono_class_try_get_##shortname##_class (void) \ GENERATE_TRY_GET_CLASS_WITH_CACHE_DECL (safehandle) -#ifndef DISABLE_COM - -GENERATE_GET_CLASS_WITH_CACHE_DECL (interop_proxy) -GENERATE_GET_CLASS_WITH_CACHE_DECL (idispatch) -GENERATE_GET_CLASS_WITH_CACHE_DECL (iunknown) -GENERATE_GET_CLASS_WITH_CACHE_DECL (com_object) -GENERATE_GET_CLASS_WITH_CACHE_DECL (variant) - -#endif - MonoClass* mono_class_get_appdomain_class (void); GENERATE_GET_CLASS_WITH_CACHE_DECL (appdomain_unloaded_exception) @@ -1371,9 +1354,6 @@ mono_class_get_declsec_flags (MonoClass *klass); void mono_class_set_declsec_flags (MonoClass *klass, guint32 value); -void -mono_class_set_is_com_object (MonoClass *klass); - void mono_class_set_weak_bitmap (MonoClass *klass, int nbits, gsize *bits); diff --git a/src/mono/mono/metadata/class-private-definition.h b/src/mono/mono/metadata/class-private-definition.h index ee104bb40a6668..9beb3d40bad0f4 100644 --- a/src/mono/mono/metadata/class-private-definition.h +++ b/src/mono/mono/metadata/class-private-definition.h @@ -66,12 +66,7 @@ struct _MonoClass { guint has_ref_fields : 1; /* it has byref fields */ guint has_static_refs : 1; /* it has static fields that are GC-tracked */ guint no_special_static_fields : 1; /* has no thread/context static fields */ - /* directly or indirectly derives from ComImport attributed class. - * this means we need to create a proxy for instances of this class - * for COM Interop. set this flag on loading so all we need is a quick check - * during object creation rather than having to traverse supertypes - */ - guint is_com_object : 1; + guint nested_classes_inited : 1; /* Whenever nested_class is initialized */ /* next byte*/ diff --git a/src/mono/mono/metadata/cominterop.c b/src/mono/mono/metadata/cominterop.c index e9685553876062..86db9edad4231f 100644 --- a/src/mono/mono/metadata/cominterop.c +++ b/src/mono/mono/metadata/cominterop.c @@ -52,41 +52,6 @@ MONO_PRAGMA_WARNING_POP() #include "icall-decl.h" #include "icall-signatures.h" -static void -mono_System_ComObject_ReleaseInterfaces (MonoComObjectHandle obj); - -#if !defined (DISABLE_COM) || defined (HOST_WIN32) - -static int -mono_IUnknown_QueryInterface (MonoIUnknown *pUnk, gconstpointer riid, gpointer* ppv) -{ - g_assert (pUnk); - return pUnk->vtable->QueryInterface (pUnk, riid, ppv); -} - -static int -mono_IUnknown_AddRef (MonoIUnknown *pUnk) -{ - // The return value is a reference count, generally transient, generally not to be used, except for debugging, - // or to assert that it is > 0. - g_assert (pUnk); - return pUnk->vtable->AddRef (pUnk); -} - -static int -mono_IUnknown_Release (MonoIUnknown *pUnk) -{ - // Release is like free -- null is silently ignored. - // Also, the return value is a reference count, generally transient, generally not to be used, except for debugging. - return pUnk ? pUnk->vtable->Release (pUnk) : 0; -} - -#endif - -/* -Code shared between the DISABLE_COM and !DISABLE_COM -*/ - // func is an identifier, that names a function, and is also in jit-icall-reg.h, // and therefore a field in mono_jit_icall_info and can be token pasted into an enum value. // @@ -114,4132 +79,143 @@ mono_string_to_bstr_impl (MonoStringHandle s, MonoError *error) return res; } -static void* -mono_cominterop_get_com_interface_internal (gboolean icall, MonoObjectHandle object, MonoClass *ic, MonoError *error); - -#ifndef DISABLE_COM - -#define OPDEF(a,b,c,d,e,f,g,h,i,j) \ - a = i, -typedef enum { - MONO_MARSHAL_NONE, /* No marshalling needed */ - MONO_MARSHAL_COPY, /* Can be copied by value to the new domain */ - MONO_MARSHAL_COPY_OUT, /* out parameter that needs to be copied back to the original instance */ - MONO_MARSHAL_SERIALIZE /* Value needs to be serialized into the new domain */ -} MonoXDomainMarshalType; - -typedef enum { - MONO_COM_DEFAULT, - MONO_COM_MS -} MonoCOMProvider; - -static MonoCOMProvider com_provider = MONO_COM_DEFAULT; - -enum { -#include "mono/cil/opcode.def" - LAST = 0xff -}; -#undef OPDEF - -/* This mutex protects the various cominterop related caches in MonoImage */ -#define mono_cominterop_lock() mono_os_mutex_lock (&cominterop_mutex) -#define mono_cominterop_unlock() mono_os_mutex_unlock (&cominterop_mutex) -static mono_mutex_t cominterop_mutex; - -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") - -static GENERATE_GET_CLASS_WITH_CACHE (interface_type_attribute, "System.Runtime.InteropServices", "InterfaceTypeAttribute") -static GENERATE_GET_CLASS_WITH_CACHE (com_visible_attribute, "System.Runtime.InteropServices", "ComVisibleAttribute") -static GENERATE_GET_CLASS_WITH_CACHE (com_default_interface_attribute, "System.Runtime.InteropServices", "ComDefaultInterfaceAttribute") -static GENERATE_GET_CLASS_WITH_CACHE (class_interface_attribute, "System.Runtime.InteropServices", "ClassInterfaceAttribute") - -/* 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 - * goes back to 0, convert back to a weak handle. - */ -typedef struct { - guint32 ref_count; - MonoGCHandle gc_handle; - GHashTable* vtable_hash; -#ifdef HOST_WIN32 - MonoIUnknown *free_marshaler; // actually IMarshal -#endif -} MonoCCW; - -/* This type is the actual pointer passed to unmanaged code - * to represent a COM interface. - */ -typedef struct { - gpointer vtable; - MonoCCW* ccw; -} MonoCCWInterface; - -/* - * COM Callable Wrappers - * - * CCWs may be called on threads that aren't attached to the runtime, they can - * then run managed code or the method implementations may use coop handles. - * Use the macros below to setup the thread state. - * - * For managed methods, the runtime marshaling wrappers handle attaching and - * coop state switching. - */ - -#define MONO_CCW_CALL_ENTER do { \ - gpointer dummy; \ - gpointer orig_domain = mono_threads_attach_coop (mono_domain_get (), &dummy); \ - MONO_ENTER_GC_UNSAFE; \ - HANDLE_FUNCTION_ENTER (); \ - do {} while (0) - -#define MONO_CCW_CALL_EXIT \ - HANDLE_FUNCTION_RETURN (); \ - MONO_EXIT_GC_UNSAFE; \ - mono_threads_detach_coop (orig_domain, &dummy); \ - } while (0) - - -/* IUnknown */ -static int STDCALL cominterop_ccw_addref (MonoCCWInterface* ccwe); - -static int STDCALL cominterop_ccw_release (MonoCCWInterface* ccwe); - -static int STDCALL cominterop_ccw_queryinterface (MonoCCWInterface* ccwe, const guint8* riid, gpointer* ppv); - -/* IDispatch */ -static int STDCALL cominterop_ccw_get_type_info_count (MonoCCWInterface* ccwe, guint32 *pctinfo); - -static int STDCALL cominterop_ccw_get_type_info (MonoCCWInterface* ccwe, guint32 iTInfo, guint32 lcid, gpointer *ppTInfo); - -static int STDCALL cominterop_ccw_get_ids_of_names (MonoCCWInterface* ccwe, gpointer riid, - gunichar2** rgszNames, guint32 cNames, - guint32 lcid, gint32 *rgDispId); - -static int STDCALL cominterop_ccw_invoke (MonoCCWInterface* ccwe, guint32 dispIdMember, - gpointer riid, guint32 lcid, - guint16 wFlags, gpointer pDispParams, - gpointer pVarResult, gpointer pExcepInfo, - guint32 *puArgErr); - -static MonoMethod * -cominterop_get_managed_wrapper_adjusted (MonoMethod *method); - -static gpointer -cominterop_get_ccw (MonoObject* object, MonoClass* itf); - -static gpointer -cominterop_get_ccw_checked (MonoObjectHandle object, MonoClass *itf, MonoError *error); - -static MonoObject* -cominterop_get_ccw_object (MonoCCWInterface* ccw_entry, gboolean verify); - -static MonoObjectHandle -cominterop_get_ccw_handle (MonoCCWInterface* ccw_entry, gboolean verify); - -static MonoObject* -cominterop_set_ccw_object_domain (MonoObject *object, MonoDomain **prev_domain); - -static void -cominterop_restore_domain (MonoDomain *domain); - -/* SAFEARRAY marshalling */ -static gboolean -mono_marshal_safearray_begin (gpointer safearray, MonoArray **result, gpointer *indices, gpointer empty, gpointer parameter, gboolean allocateNewArray); - -static gpointer -mono_marshal_safearray_get_value (gpointer safearray, gpointer indices); - -static gboolean -mono_marshal_safearray_next (gpointer safearray, gpointer indices); - -static void -mono_marshal_safearray_end (gpointer safearray, gpointer indices); - -static gboolean -mono_marshal_safearray_create (MonoArray *input, gpointer *newsafearray, gpointer *indices, gpointer empty); - -static void -mono_marshal_safearray_set_value (gpointer safearray, gpointer indices, gpointer value); - -static void -mono_marshal_safearray_free_indices (gpointer indices); - -MonoClass* -mono_class_try_get_com_object_class (void) -{ - static MonoClass *tmp_class; - static gboolean inited; - MonoClass *klass; - if (!inited) { - klass = mono_class_load_from_name (mono_defaults.corlib, "System", "__ComObject"); - mono_memory_barrier (); - tmp_class = klass; - mono_memory_barrier (); - inited = TRUE; - } - return tmp_class; -} - -/** - * cominterop_method_signature: - * @method: a method - * - * Returns: the corresponding unmanaged method signature for a managed COM - * method. - */ -static MonoMethodSignature* -cominterop_method_signature (MonoMethod* method) +void +mono_cominterop_init (void) { - MonoMethodSignature *res; - MonoImage *image = m_class_get_image (method->klass); - MonoMethodSignature *sig = mono_method_signature_internal (method); - gboolean const preserve_sig = (method->iflags & METHOD_IMPL_ATTRIBUTE_PRESERVE_SIG) != 0; - int sigsize; - int i; - int param_count = sig->param_count + 1; // convert this arg into IntPtr arg - - if (!preserve_sig &&!MONO_TYPE_IS_VOID (sig->ret)) - param_count++; - - res = mono_metadata_signature_alloc (image, param_count); - sigsize = MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *); - memcpy (res, sig, sigsize); - - // now move args forward one - for (i = sig->param_count-1; i >= 0; i--) - res->params[i+1] = sig->params[i]; - - // first arg is interface pointer - res->params[0] = mono_get_int_type (); - - if (preserve_sig) { - res->ret = sig->ret; - } - else { - // last arg is return type - if (!MONO_TYPE_IS_VOID (sig->ret)) { - res->params[param_count-1] = mono_metadata_type_dup (image, sig->ret); - res->params[param_count-1]->byref__ = 1; - res->params[param_count-1]->attrs = PARAM_ATTRIBUTE_OUT; - } - - // return type is always int32 (HRESULT) - res->ret = mono_get_int32_type (); - } - - // no pinvoke - res->pinvoke = FALSE; - - // no hasthis - res->hasthis = 0; + /*FIXME - // set param_count - res->param_count = param_count; + This icalls are used by the marshal code when doing PtrToStructure and StructureToPtr and pinvoke. - // STDCALL on windows, CDECL everywhere else to work with XPCOM and MainWin COM -#ifdef HOST_WIN32 - res->call_convention = MONO_CALL_STDCALL; -#else - res->call_convention = MONO_CALL_C; -#endif + If we leave them out and the FullAOT compiler finds the need to emit one of the above 3 wrappers it will + g_assert. - return res; + 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_icall_sig_ptr_obj, FALSE); + register_icall (mono_string_from_bstr_icall, mono_icall_sig_obj_ptr, FALSE); + register_icall (mono_free_bstr, mono_icall_sig_void_ptr, FALSE); } -/** - * cominterop_get_function_pointer: - * @itf: a pointer to the COM interface - * @slot: the vtable slot of the method pointer to return - * - * Returns: the unmanaged vtable function pointer from the interface - */ +// This function is used regardless of the BSTR type, so cast the return value +// Inputted string length, in bytes, should include the null terminator +// Returns the start of the string itself static gpointer -cominterop_get_function_pointer (gpointer itf, int slot) -{ - gpointer func; - func = *((*(gpointer**)itf)+slot); - return func; -} - -/** - * cominterop_object_is_com_object: - * @obj: a pointer to the object - * - * Returns: a value indicating if the object is a - * Runtime Callable Wrapper (RCW) for a COM object - */ -static gboolean -cominterop_object_is_rcw_handle (MonoObjectHandle obj, MonoRealProxyHandle *real_proxy) -{ - MonoClass *klass; - - return !MONO_HANDLE_IS_NULL (obj) - && (klass = mono_handle_class (obj)) - && !MONO_HANDLE_IS_NULL (*real_proxy = MONO_HANDLE_NEW_GET (MonoRealProxy, MONO_HANDLE_CAST (MonoTransparentProxy, obj), rp)) - && (klass = mono_handle_class (*real_proxy)) - && klass == mono_class_get_interop_proxy_class (); -} - -static gboolean -cominterop_object_is_rcw (MonoObject *obj_raw) +mono_bstr_alloc (size_t str_byte_len) { - if (!obj_raw) - return FALSE; - HANDLE_FUNCTION_ENTER (); - MONO_HANDLE_DCL (MonoObject, obj); - MonoRealProxyHandle real_proxy; - gboolean const result = cominterop_object_is_rcw_handle (obj, &real_proxy); - HANDLE_FUNCTION_RETURN_VAL (result); + // Allocate string length plus pointer-size integer to store the length, aligned to 16 bytes + size_t alloc_size = str_byte_len + SIZEOF_VOID_P; + alloc_size += (16 - 1); + alloc_size &= ~(16 - 1); + gpointer ret = g_malloc0 (alloc_size); + return ret ? (char *)ret + SIZEOF_VOID_P : NULL; } -static int -cominterop_get_com_slot_begin (MonoClass* klass) +static void +mono_bstr_set_length (gunichar2 *bstr, int slen) { - ERROR_DECL (error); - MonoCustomAttrInfo *cinfo = NULL; - MonoInterfaceTypeAttribute* itf_attr = NULL; - - cinfo = mono_custom_attrs_from_class_checked (klass, error); - mono_error_assert_ok (error); - if (cinfo) { - itf_attr = (MonoInterfaceTypeAttribute*)mono_custom_attrs_get_attr_checked (cinfo, mono_class_get_interface_type_attribute_class (), error); - mono_error_assert_ok (error); /*FIXME proper error handling*/ - if (!cinfo->cached) - mono_custom_attrs_free (cinfo); - } - - if (itf_attr && itf_attr->intType == 1) - return 3; /* 3 methods in IUnknown*/ - else - return 7; /* 7 methods in IDispatch*/ + *((guint32 *)bstr - 1) = slen * sizeof (gunichar2); } -/** - * cominterop_get_method_interface: - * @method: method being called - * - * Returns: the MonoClass* representing the interface on which - * the method is defined. - */ -static MonoClass* -cominterop_get_method_interface (MonoMethod* method) +static mono_bstr +default_ptr_to_bstr (const gunichar2* ptr, int slen) { - ERROR_DECL (error); - MonoClass *ic = method->klass; - - /* if method is on a class, we need to look up interface method exists on */ - if (!MONO_CLASS_IS_INTERFACE_INTERNAL (method->klass)) { - GPtrArray *ifaces = mono_class_get_implemented_interfaces (method->klass, error); - mono_error_assert_ok (error); - if (ifaces) { - int i; - mono_class_setup_vtable (method->klass); - for (i = 0; i < ifaces->len; ++i) { - int j, offset; - gboolean found = FALSE; - ic = (MonoClass *)g_ptr_array_index (ifaces, i); - offset = mono_class_interface_offset (method->klass, ic); - int mcount = mono_class_get_method_count (ic); - MonoMethod **method_klass_vtable = m_class_get_vtable (method->klass); - for (j = 0; j < mcount; ++j) { - if (method_klass_vtable [j + offset] == method) { - found = TRUE; - break; - } - } - if (found) - break; - ic = NULL; - } - g_ptr_array_free (ifaces, TRUE); - } - } - - return ic; -} + // In Mono, historically BSTR was allocated with a guaranteed size prefix of 4 bytes regardless of platform. + // Presumably this is due to the BStr documentation page, which indicates that behavior and then directs you to call + // SysAllocString on Windows to handle the allocation for you. Unfortunately, this is not actually how it works: + // The allocation pre-string is pointer-sized, and then only 4 bytes are used for the length regardless. Additionally, + // the total length is also aligned to a 16-byte boundary. This preserves the old behavior on legacy and fixes it for + // netcore moving forward. + mono_bstr const s = (mono_bstr)mono_bstr_alloc ((slen + 1) * sizeof (gunichar2)); + if (s == NULL) + return NULL; -static void -mono_cominterop_get_interface_missing_error (MonoError* error, MonoMethod* method) -{ - mono_error_set_invalid_operation (error, "Method '%s' in ComImport class '%s' must implement an interface method.", method->name, m_class_get_name (method->klass)); + mono_bstr_set_length (s, slen); + if (ptr) + memcpy (s, ptr, slen * sizeof (gunichar2)); + s [slen] = 0; + return s; } -/** - * cominterop_get_com_slot_for_method: - * @method: a method - * @error: set on error - * - * Returns: the method's slot in the COM interface vtable - */ -static int -cominterop_get_com_slot_for_method (MonoMethod* method, MonoError* error) +/* PTR can be NULL */ +mono_bstr +mono_ptr_to_bstr (const gunichar2* ptr, int slen) { - guint32 slot = method->slot; - MonoClass *ic = method->klass; - - error_init (error); - - /* if method is on a class, we need to look up interface method exists on */ - if (!MONO_CLASS_IS_INTERFACE_INTERNAL (ic)) { - int offset = 0; - int i = 0; - ic = cominterop_get_method_interface (method); - if (!ic || !MONO_CLASS_IS_INTERFACE_INTERNAL (ic)) { - mono_cominterop_get_interface_missing_error (error, method); - return -1; - } - offset = mono_class_interface_offset (method->klass, ic); - g_assert(offset >= 0); - int mcount = mono_class_get_method_count (ic); - MonoMethod **ic_methods = m_class_get_methods (ic); - MonoMethod **method_klass_vtable = m_class_get_vtable (method->klass); - for(i = 0; i < mcount; ++i) { - if (method_klass_vtable [i + offset] == method) - { - slot = ic_methods[i]->slot; - break; - } - } - } - - g_assert (ic); - g_assert (MONO_CLASS_IS_INTERFACE_INTERNAL (ic)); - - return slot + cominterop_get_com_slot_begin (ic); +#if HAVE_API_SUPPORT_WIN32_BSTR + return SysAllocStringLen (ptr, slen); +#else + return default_ptr_to_bstr (ptr, slen); +#endif // HAVE_API_SUPPORT_WIN32_BSTR } -static gboolean -cominterop_class_guid (MonoClass* klass, guint8* guid) +char * +mono_ptr_to_ansibstr (const char *ptr, size_t slen) { - ERROR_DECL (error); - mono_metadata_get_class_guid (klass, guid, error); - mono_error_assert_ok (error); /*FIXME proper error handling*/ - return TRUE; + char *s = (char *)mono_bstr_alloc ((slen + 1) * sizeof(char)); + if (s == NULL) + return NULL; + *((guint32 *)s - 1) = (guint32)(slen * sizeof (char)); + if (ptr) + memcpy (s, ptr, slen * sizeof (char)); + s [slen] = 0; + return s; } -static gboolean -cominterop_com_visible (MonoClass* klass) +MonoStringHandle +mono_string_from_bstr_checked (mono_bstr_const bstr, MonoError *error) { - ERROR_DECL (error); - MonoCustomAttrInfo *cinfo; - GPtrArray *ifaces; - MonoBoolean visible = 1; - - cinfo = mono_custom_attrs_from_class_checked (klass, error); - mono_error_assert_ok (error); - if (cinfo) { - MonoReflectionComVisibleAttribute *attr = (MonoReflectionComVisibleAttribute*)mono_custom_attrs_get_attr_checked (cinfo, mono_class_get_com_visible_attribute_class (), error); - mono_error_assert_ok (error); /*FIXME proper error handling*/ - - if (attr) - visible = attr->visible; - if (!cinfo->cached) - mono_custom_attrs_free (cinfo); - if (visible) - return TRUE; - } - - ifaces = mono_class_get_implemented_interfaces (klass, error); - mono_error_assert_ok (error); - if (ifaces) { - int i; - for (i = 0; i < ifaces->len; ++i) { - MonoClass *ic = NULL; - ic = (MonoClass *)g_ptr_array_index (ifaces, i); - if (MONO_CLASS_IS_IMPORT (ic)) - visible = TRUE; - - } - g_ptr_array_free (ifaces, TRUE); - } - return visible; - + if (!bstr) + return NULL_HANDLE_STRING; +#if HAVE_API_SUPPORT_WIN32_BSTR + return mono_string_new_utf16_handle (bstr, SysStringLen ((BSTR)bstr), error); +#else + return mono_string_new_utf16_handle (bstr, *((guint32 *)bstr - 1) / sizeof (gunichar2), error); +#endif // HAVE_API_SUPPORT_WIN32_BSTR } -gboolean -mono_cominterop_method_com_visible (MonoMethod *method) +MonoString * +mono_string_from_bstr (/*mono_bstr_const*/gpointer bstr) { + // FIXME gcmode + HANDLE_FUNCTION_ENTER (); ERROR_DECL (error); - MonoCustomAttrInfo *cinfo; - MonoBoolean visible = 1; - - cinfo = mono_custom_attrs_from_method_checked (method, error); - mono_error_assert_ok (error); - if (cinfo) { - MonoReflectionComVisibleAttribute *attr = (MonoReflectionComVisibleAttribute*)mono_custom_attrs_get_attr_checked (cinfo, mono_class_get_com_visible_attribute_class (), error); - mono_error_assert_ok (error); /*FIXME proper error handling*/ - - if (attr) - visible = attr->visible; - if (!cinfo->cached) - mono_custom_attrs_free (cinfo); - } - return visible; + MonoStringHandle result = mono_string_from_bstr_checked ((mono_bstr_const)bstr, error); + mono_error_cleanup (error); + HANDLE_FUNCTION_RETURN_OBJ (result); } -static void -cominterop_set_hr_error (MonoError *oerror, int hr) +MonoStringHandle +mono_string_from_bstr_icall_impl (mono_bstr_const bstr, MonoError *error) { - ERROR_DECL (error); - MonoException* ex; - void* params[1] = {&hr}; - - MONO_STATIC_POINTER_INIT (MonoMethod, throw_exception_for_hr) - - throw_exception_for_hr = mono_class_get_method_from_name_checked (mono_defaults.marshal_class, "GetExceptionForHR", 1, 0, error); - mono_error_assert_ok (error); - - MONO_STATIC_POINTER_INIT_END (MonoMethod, throw_exception_for_hr) - - ex = (MonoException*)mono_runtime_invoke_checked (throw_exception_for_hr, NULL, params, error); - g_assert (ex); - mono_error_assert_ok (error); - - mono_error_set_exception_instance (oerror, ex); + return mono_string_from_bstr_checked (bstr, error); } -/** - * cominterop_get_interface_checked: - * @obj: managed wrapper object containing COM object - * @ic: interface type to retrieve for COM object - * @error: set on error - * - * Returns: the COM interface requested. On failure returns NULL and sets @error - */ -static gpointer -cominterop_get_interface_checked (MonoComObjectHandle obj, MonoClass* ic, MonoError *error) +MONO_API void +mono_free_bstr (/*mono_bstr_const*/gpointer bstr) { - gpointer itf = NULL; - - g_assert (ic); - g_assert (MONO_CLASS_IS_INTERFACE_INTERNAL (ic)); - - error_init (error); - - mono_cominterop_lock (); - if (MONO_HANDLE_GETVAL (obj, itf_hash)) - itf = g_hash_table_lookup (MONO_HANDLE_GETVAL (obj, itf_hash), GUINT_TO_POINTER ((guint)m_class_get_interface_id (ic))); - mono_cominterop_unlock (); - - if (itf) - return itf; - - guint8 iid [16]; - gboolean const found = cominterop_class_guid (ic, iid); - g_assert (found); - g_assert (MONO_HANDLE_GETVAL (obj, iunknown)); - int const hr = mono_IUnknown_QueryInterface (MONO_HANDLE_GETVAL (obj, iunknown), iid, &itf); - if (hr < 0) { - g_assert (!itf); - cominterop_set_hr_error (error, hr); - g_assert (!is_ok (error)); - return NULL; - } - - g_assert (itf); - mono_cominterop_lock (); - if (!MONO_HANDLE_GETVAL (obj, itf_hash)) - MONO_HANDLE_SETVAL (obj, itf_hash, GHashTable*, g_hash_table_new (mono_aligned_addr_hash, NULL)); - g_hash_table_insert (MONO_HANDLE_GETVAL (obj, itf_hash), GUINT_TO_POINTER ((guint)m_class_get_interface_id (ic)), itf); - mono_cominterop_unlock (); - - return itf; + if (!bstr) + return; +#if HAVE_API_SUPPORT_WIN32_BSTR + SysFreeString ((BSTR)bstr); +#else + g_free (((char *)bstr) - SIZEOF_VOID_P); +#endif // HAVE_API_SUPPORT_WIN32_BSTR } -/** - * cominterop_get_interface: - * @obj: managed wrapper object containing COM object - * @ic: interface type to retrieve for COM object - * - * Returns: the COM interface requested - */ -static gpointer -cominterop_get_interface (MonoComObject *obj_raw, MonoClass *ic) +gboolean +mono_marshal_free_ccw (MonoObject* object) { - HANDLE_FUNCTION_ENTER (); - ERROR_DECL (error); - MONO_HANDLE_DCL (MonoComObject, obj); - gpointer const itf = cominterop_get_interface_checked (obj, ic, error); - g_assert (!!itf == is_ok (error)); // two equal success indicators - mono_error_set_pending_exception (error); - HANDLE_FUNCTION_RETURN_VAL (itf); + return FALSE; } -// This is an icall, it will return NULL and set pending exception (in -// mono_type_from_handle wrapper) on failure. -static MonoReflectionType * -cominterop_type_from_handle (MonoType *handle) +mono_bstr +ves_icall_System_Runtime_InteropServices_Marshal_BufferToBSTR (const gunichar2* ptr, int len) { - return mono_type_from_handle (handle); + return mono_ptr_to_bstr (ptr, len); } -#endif // DISABLE_COM - void -mono_cominterop_init (void) -{ -#ifndef DISABLE_COM - mono_os_mutex_init_recursive (&cominterop_mutex); - - char* const com_provider_env = g_getenv ("MONO_COM"); - if (com_provider_env && !strcmp(com_provider_env, "MS")) - com_provider = MONO_COM_MS; - g_free (com_provider_env); - - register_icall (cominterop_get_method_interface, mono_icall_sig_ptr_ptr, FALSE); - register_icall (cominterop_get_function_pointer, mono_icall_sig_ptr_ptr_int32, FALSE); - register_icall (cominterop_object_is_rcw, mono_icall_sig_int32_object, FALSE); - register_icall (cominterop_get_ccw, mono_icall_sig_ptr_object_ptr, FALSE); - register_icall (cominterop_get_ccw_object, mono_icall_sig_object_ptr_int32, FALSE); - register_icall (cominterop_get_interface, mono_icall_sig_ptr_object_ptr, FALSE); - - register_icall (cominterop_type_from_handle, mono_icall_sig_object_ptr, FALSE); - - register_icall (cominterop_set_ccw_object_domain, mono_icall_sig_object_object_ptr, FALSE); - register_icall (cominterop_restore_domain, mono_icall_sig_void_ptr, FALSE); - - /* SAFEARRAY marshalling */ - register_icall (mono_marshal_safearray_begin, mono_icall_sig_int32_ptr_ptr_ptr_ptr_ptr_int32, FALSE); - register_icall (mono_marshal_safearray_get_value, mono_icall_sig_ptr_ptr_ptr, FALSE); - register_icall (mono_marshal_safearray_next, mono_icall_sig_int32_ptr_ptr, FALSE); - register_icall (mono_marshal_safearray_end, mono_icall_sig_void_ptr_ptr, FALSE); - register_icall (mono_marshal_safearray_create, mono_icall_sig_int32_object_ptr_ptr_ptr, FALSE); - register_icall (mono_marshal_safearray_set_value, mono_icall_sig_void_ptr_ptr_ptr, FALSE); - register_icall (mono_marshal_safearray_free_indices, mono_icall_sig_void_ptr, FALSE); -#endif // DISABLE_COM - /*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_icall_sig_ptr_obj, FALSE); - register_icall (mono_string_from_bstr_icall, mono_icall_sig_obj_ptr, FALSE); - register_icall (mono_free_bstr, mono_icall_sig_void_ptr, FALSE); -} - -#ifndef DISABLE_COM - -void -mono_mb_emit_cominterop_get_function_pointer (MonoMethodBuilder *mb, MonoMethod *method) -{ -#ifndef DISABLE_JIT - int slot; - ERROR_DECL (error); - // get function pointer from 1st arg, the COM interface pointer - mono_mb_emit_ldarg (mb, 0); - slot = cominterop_get_com_slot_for_method (method, error); - if (is_ok (error)) { - mono_mb_emit_icon (mb, slot); - mono_mb_emit_icall (mb, cominterop_get_function_pointer); - /* Leaves the function pointer on top of the stack */ - } - else { - mono_mb_emit_exception_for_error (mb, error); - } - mono_error_cleanup (error); -#endif -} - -void -mono_mb_emit_cominterop_call_function_pointer (MonoMethodBuilder *mb, MonoMethodSignature *sig) -{ -#ifndef DISABLE_JIT - mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); - mono_mb_emit_byte (mb, CEE_MONO_SAVE_LMF); - mono_mb_emit_calli (mb, sig); - mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); - mono_mb_emit_byte (mb, CEE_MONO_RESTORE_LMF); -#endif /* DISABLE_JIT */ -} - -void -mono_mb_emit_cominterop_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethod* method) -{ -#ifndef DISABLE_JIT - mono_mb_emit_cominterop_get_function_pointer (mb, method); - - mono_mb_emit_cominterop_call_function_pointer (mb, sig); -#endif /* DISABLE_JIT */ -} - -void -mono_cominterop_emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, MonoMarshalSpec *mspec) -{ -#ifndef DISABLE_JIT - switch (conv) { - case MONO_MARSHAL_CONV_OBJECT_INTERFACE: - case MONO_MARSHAL_CONV_OBJECT_IUNKNOWN: - case MONO_MARSHAL_CONV_OBJECT_IDISPATCH: { - - guint32 pos_null = 0, pos_ccw = 0, pos_end = 0; - MonoClass *klass = NULL; - - klass = mono_class_from_mono_type_internal (type); - - mono_mb_emit_ldloc (mb, 1); - mono_mb_emit_byte (mb, CEE_LDNULL); - mono_mb_emit_byte (mb, CEE_STIND_REF); - - mono_mb_emit_ldloc (mb, 0); - mono_mb_emit_byte (mb, CEE_LDIND_I); - pos_null = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S); - - /* load dst to store later */ - mono_mb_emit_ldloc (mb, 1); - - mono_mb_emit_ldloc (mb, 0); - mono_mb_emit_byte (mb, CEE_LDIND_I); - mono_mb_emit_icon (mb, TRUE); - mono_mb_emit_icall (mb, cominterop_get_ccw_object); - pos_ccw = mono_mb_emit_short_branch (mb, CEE_BRTRUE_S); - - MONO_STATIC_POINTER_INIT (MonoMethod, com_interop_proxy_get_proxy) - - ERROR_DECL (error); - com_interop_proxy_get_proxy = mono_class_get_method_from_name_checked (mono_class_get_interop_proxy_class (), "GetProxy", 2, METHOD_ATTRIBUTE_PRIVATE, error); - mono_error_assert_ok (error); - - MONO_STATIC_POINTER_INIT_END (MonoMethod, com_interop_proxy_get_proxy) - - static MonoMethod* const get_transparent_proxy = NULL; // FIXME? - - mono_mb_add_local (mb, m_class_get_byval_arg (mono_class_get_interop_proxy_class ())); - - mono_mb_emit_ldloc (mb, 0); - mono_mb_emit_byte (mb, CEE_LDIND_I); - mono_mb_emit_ptr (mb, m_class_get_byval_arg (mono_class_get_com_object_class ())); - 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); - if (conv == MONO_MARSHAL_CONV_OBJECT_INTERFACE) { - g_assert (klass); - mono_mb_emit_op (mb, CEE_CASTCLASS, klass); - } - mono_mb_emit_byte (mb, CEE_STIND_REF); - pos_end = mono_mb_emit_short_branch (mb, CEE_BR_S); - - /* is already managed object */ - mono_mb_patch_short_branch (mb, pos_ccw); - mono_mb_emit_ldloc (mb, 0); - mono_mb_emit_byte (mb, CEE_LDIND_I); - mono_mb_emit_icon (mb, TRUE); - mono_mb_emit_icall (mb, cominterop_get_ccw_object); - - if (conv == MONO_MARSHAL_CONV_OBJECT_INTERFACE) { - g_assert (klass); - mono_mb_emit_op (mb, CEE_CASTCLASS, klass); - } - mono_mb_emit_byte (mb, CEE_STIND_REF); - - mono_mb_patch_short_branch (mb, pos_end); - /* case if null */ - mono_mb_patch_short_branch (mb, pos_null); - break; - } - default: - g_assert_not_reached (); - } -#endif /* DISABLE_JIT */ -} - -void -mono_cominterop_emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, MonoMarshalSpec *mspec) -{ -#ifndef DISABLE_JIT - switch (conv) { - case MONO_MARSHAL_CONV_OBJECT_INTERFACE: - case MONO_MARSHAL_CONV_OBJECT_IDISPATCH: - case MONO_MARSHAL_CONV_OBJECT_IUNKNOWN: { - guint32 pos_null = 0, pos_rcw = 0, pos_end = 0; - - mono_mb_emit_ldloc (mb, 1); - mono_mb_emit_icon (mb, 0); - mono_mb_emit_byte (mb, CEE_CONV_U); - mono_mb_emit_byte (mb, CEE_STIND_I); - - mono_mb_emit_ldloc (mb, 0); - mono_mb_emit_byte (mb, CEE_LDIND_REF); - - // if null just break, dst was already inited to 0 - pos_null = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S); - - mono_mb_emit_ldloc (mb, 0); - mono_mb_emit_byte (mb, CEE_LDIND_REF); - mono_mb_emit_icall (mb, cominterop_object_is_rcw); - pos_rcw = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S); - - // load dst to store later - mono_mb_emit_ldloc (mb, 1); - - // load src - mono_mb_emit_ldloc (mb, 0); - mono_mb_emit_byte (mb, CEE_LDIND_REF); - mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoTransparentProxy, rp)); - mono_mb_emit_byte (mb, CEE_LDIND_REF); - - /* load the RCW from the ComInteropProxy*/ - mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoComInteropProxy, com_object)); - mono_mb_emit_byte (mb, CEE_LDIND_REF); - - if (conv == MONO_MARSHAL_CONV_OBJECT_INTERFACE) { - mono_mb_emit_ptr (mb, mono_type_get_class_internal (type)); - mono_mb_emit_icall (mb, cominterop_get_interface); - } - else if (conv == MONO_MARSHAL_CONV_OBJECT_IUNKNOWN) { - - MONO_STATIC_POINTER_INIT (MonoProperty, iunknown) - iunknown = mono_class_get_property_from_name_internal (mono_class_get_com_object_class (), "IUnknown"); - MONO_STATIC_POINTER_INIT_END (MonoProperty, iunknown) - - mono_mb_emit_managed_call (mb, iunknown->get, NULL); - } - else if (conv == MONO_MARSHAL_CONV_OBJECT_IDISPATCH) { - - MONO_STATIC_POINTER_INIT (MonoProperty, idispatch) - idispatch = mono_class_get_property_from_name_internal (mono_class_get_com_object_class (), "IDispatch"); - MONO_STATIC_POINTER_INIT_END (MonoProperty, idispatch) - - mono_mb_emit_managed_call (mb, idispatch->get, NULL); - } - else { - g_assert_not_reached (); - } - mono_mb_emit_byte (mb, CEE_STIND_I); - pos_end = mono_mb_emit_short_branch (mb, CEE_BR_S); - - // if not rcw - mono_mb_patch_short_branch (mb, pos_rcw); - /* load dst to store later */ - mono_mb_emit_ldloc (mb, 1); - /* load src */ - mono_mb_emit_ldloc (mb, 0); - mono_mb_emit_byte (mb, CEE_LDIND_REF); - - if (conv == MONO_MARSHAL_CONV_OBJECT_INTERFACE) - mono_mb_emit_ptr (mb, mono_type_get_class_internal (type)); - else if (conv == MONO_MARSHAL_CONV_OBJECT_IUNKNOWN) - mono_mb_emit_ptr (mb, mono_class_get_iunknown_class ()); - else if (conv == MONO_MARSHAL_CONV_OBJECT_IDISPATCH) - mono_mb_emit_ptr (mb, mono_class_get_idispatch_class ()); - else - g_assert_not_reached (); - mono_mb_emit_icall (mb, cominterop_get_ccw); - mono_mb_emit_byte (mb, CEE_STIND_I); - - mono_mb_patch_short_branch (mb, pos_end); - mono_mb_patch_short_branch (mb, pos_null); - break; - } - default: - g_assert_not_reached (); - } -#endif /* DISABLE_JIT */ -} - -/** - * cominterop_get_native_wrapper_adjusted: - * @method: managed COM Interop method - * - * Returns: the generated method to call with signature matching - * the unmanaged COM Method signature - */ -static MonoMethod * -cominterop_get_native_wrapper_adjusted (MonoMethod *method) -{ - MonoMethod *res; - MonoMethodBuilder *mb_native; - MonoMarshalSpec **mspecs; - MonoMethodSignature *sig, *sig_native; - MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *) method; - int i; - - sig = mono_method_signature_internal (method); - - // create unmanaged wrapper - mb_native = mono_mb_new (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_NATIVE); - sig_native = cominterop_method_signature (method); - - mspecs = g_new0 (MonoMarshalSpec*, sig_native->param_count + 1); - - mono_method_get_marshal_info (method, mspecs); - - // move managed args up one - for (i = sig->param_count; i >= 1; i--) - mspecs[i+1] = mspecs[i]; - - // first arg is IntPtr for interface - mspecs[1] = NULL; - - if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_PRESERVE_SIG)) { - // move return spec to last param - if (!MONO_TYPE_IS_VOID (sig->ret)) - mspecs[sig_native->param_count] = mspecs[0]; - - mspecs[0] = NULL; - } - - for (i = 1; i < sig_native->param_count; i++) { - int mspec_index = i + 1; - if (mspecs[mspec_index] == NULL) { - // default object to VARIANT - if (sig_native->params[i]->type == MONO_TYPE_OBJECT) { - mspecs[mspec_index] = g_new0 (MonoMarshalSpec, 1); - mspecs[mspec_index]->native = MONO_NATIVE_STRUCT; - } - else if (sig_native->params[i]->type == MONO_TYPE_STRING) { - mspecs[mspec_index] = g_new0 (MonoMarshalSpec, 1); - mspecs[mspec_index]->native = MONO_NATIVE_BSTR; - } - else if (sig_native->params[i]->type == MONO_TYPE_CLASS) { - mspecs[mspec_index] = g_new0 (MonoMarshalSpec, 1); - mspecs[mspec_index]->native = MONO_NATIVE_INTERFACE; - } - else if (sig_native->params[i]->type == MONO_TYPE_BOOLEAN) { - mspecs[mspec_index] = g_new0 (MonoMarshalSpec, 1); - mspecs[mspec_index]->native = MONO_NATIVE_VARIANTBOOL; - } - } - } - - if (method->iflags & METHOD_IMPL_ATTRIBUTE_PRESERVE_SIG) { - // move return spec to last param - if (!MONO_TYPE_IS_VOID (sig->ret) && mspecs[0] == NULL) { - // default object to VARIANT - if (sig->ret->type == MONO_TYPE_OBJECT) { - mspecs[0] = g_new0 (MonoMarshalSpec, 1); - mspecs[0]->native = MONO_NATIVE_STRUCT; - } - else if (sig->ret->type == MONO_TYPE_STRING) { - mspecs[0] = g_new0 (MonoMarshalSpec, 1); - mspecs[0]->native = MONO_NATIVE_BSTR; - } - else if (sig->ret->type == MONO_TYPE_CLASS) { - mspecs[0] = g_new0 (MonoMarshalSpec, 1); - mspecs[0]->native = MONO_NATIVE_INTERFACE; - } - else if (sig->ret->type == MONO_TYPE_BOOLEAN) { - mspecs[0] = g_new0 (MonoMarshalSpec, 1); - mspecs[0]->native = MONO_NATIVE_VARIANTBOOL; - } - } - } - - mono_marshal_emit_native_wrapper (m_class_get_image (method->klass), mb_native, sig_native, piinfo, mspecs, piinfo->addr, EMIT_NATIVE_WRAPPER_CHECK_EXCEPTIONS | EMIT_NATIVE_WRAPPER_RUNTIME_MARSHALLING_ENABLED); - - res = mono_mb_create_method (mb_native, sig_native, sig_native->param_count + 16); - - mono_mb_free (mb_native); - - for (i = sig_native->param_count; i >= 0; i--) - if (mspecs [i]) - mono_metadata_free_marshal_spec (mspecs [i]); - g_free (mspecs); - - return res; -} - -/** - * mono_cominterop_get_native_wrapper: - * \param method managed method - * \returns the generated method to call - */ -MonoMethod * -mono_cominterop_get_native_wrapper (MonoMethod *method) -{ - MonoMethod *res; - GHashTable *cache; - MonoMethodBuilder *mb; - MonoMethodSignature *sig, *csig; - - g_assert (method); - - cache = mono_marshal_get_cache (&mono_method_get_wrapper_cache (method)->cominterop_wrapper_cache, mono_aligned_addr_hash, NULL); - - if ((res = mono_marshal_find_in_cache (cache, method))) - return res; - - if (!m_class_get_vtable (method->klass)) - mono_class_setup_vtable (method->klass); - - if (!m_class_get_methods (method->klass)) - mono_class_setup_methods (method->klass); - g_assert (!mono_class_has_failure (method->klass)); /*FIXME do proper error handling*/ - - sig = mono_method_signature_internal (method); - mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_COMINTEROP); - -#ifndef DISABLE_JIT - /* if method klass is import, that means method - * is really a com call. let interop system emit it. - */ - if (MONO_CLASS_IS_IMPORT(method->klass)) { - /* FIXME: we have to call actual class .ctor - * instead of just __ComObject .ctor. - */ - if (!strcmp(method->name, ".ctor")) { - - MONO_STATIC_POINTER_INIT (MonoMethod, ctor) - - ERROR_DECL (error); - ctor = mono_class_get_method_from_name_checked (mono_class_get_com_object_class (), ".ctor", 0, 0, error); - mono_error_assert_ok (error); - - MONO_STATIC_POINTER_INIT_END (MonoMethod, ctor) - - mono_mb_emit_ldarg (mb, 0); - mono_mb_emit_managed_call (mb, ctor, NULL); - mono_mb_emit_byte (mb, CEE_RET); - } - else if (method->flags & METHOD_ATTRIBUTE_STATIC) { - /* - * The method's class must implement an interface. - * However, no interfaces are allowed to have static methods. - * Thus, calling it should invariably lead to an exception. - */ - ERROR_DECL (error); - mono_cominterop_get_interface_missing_error (error, method); - mono_mb_emit_exception_for_error (mb, error); - mono_error_cleanup (error); - } - else { - MonoMethod *adjusted_method; - int retval = 0; - int ptr_this; - int i; - gboolean const preserve_sig = (method->iflags & METHOD_IMPL_ATTRIBUTE_PRESERVE_SIG) != 0; - - // add local variables - ptr_this = mono_mb_add_local (mb, mono_get_int_type ()); - if (!MONO_TYPE_IS_VOID (sig->ret)) - retval = mono_mb_add_local (mb, sig->ret); - - // get the type for the interface the method is defined on - // and then get the underlying COM interface for that type - mono_mb_emit_ldarg (mb, 0); - mono_mb_emit_ptr (mb, method); - mono_mb_emit_icall (mb, cominterop_get_method_interface); - mono_mb_emit_icall (mb, cominterop_get_interface); - mono_mb_emit_stloc (mb, ptr_this); - - // arg 1 is unmanaged this pointer - mono_mb_emit_ldloc (mb, ptr_this); - - // load args - for (i = 1; i <= sig->param_count; i++) - mono_mb_emit_ldarg (mb, i); - - // push managed return value as byref last argument - if (!MONO_TYPE_IS_VOID (sig->ret) && !preserve_sig) - mono_mb_emit_ldloc_addr (mb, retval); - - adjusted_method = cominterop_get_native_wrapper_adjusted (method); - mono_mb_emit_managed_call (mb, adjusted_method, NULL); - - if (!preserve_sig) { - - MONO_STATIC_POINTER_INIT (MonoMethod, ThrowExceptionForHR) - - ERROR_DECL (error); - ThrowExceptionForHR = mono_class_get_method_from_name_checked (mono_defaults.marshal_class, "ThrowExceptionForHR", 1, 0, error); - mono_error_assert_ok (error); - - MONO_STATIC_POINTER_INIT_END (MonoMethod, ThrowExceptionForHR) - - mono_mb_emit_managed_call (mb, ThrowExceptionForHR, NULL); - - // load return value managed is expecting - if (!MONO_TYPE_IS_VOID (sig->ret)) - mono_mb_emit_ldloc (mb, retval); - } - - mono_mb_emit_byte (mb, CEE_RET); - } - - - } - /* Does this case ever get hit? */ - else { - char *msg = g_strdup ("non imported interfaces on \ - imported classes is not yet implemented."); - mono_mb_emit_exception (mb, "NotSupportedException", msg); - } -#endif /* DISABLE_JIT */ - - csig = mono_metadata_signature_dup_full (m_class_get_image (method->klass), sig); - csig->pinvoke = 0; - res = mono_mb_create_and_cache (cache, method, - mb, csig, csig->param_count + 16); - mono_mb_free (mb); - return res; -} - -/** - * mono_cominterop_get_invoke: - * \param method managed method - * \returns the generated method that calls the underlying \c __ComObject - * rather than the proxy object. - */ -MonoMethod * -mono_cominterop_get_invoke (MonoMethod *method) -{ - MonoMethodSignature *sig; - MonoMethodBuilder *mb; - MonoMethod *res; - int i; - GHashTable* cache; - - cache = mono_marshal_get_cache (&mono_method_get_wrapper_cache (method)->cominterop_invoke_cache, mono_aligned_addr_hash, NULL); - - g_assert (method); - - if ((res = mono_marshal_find_in_cache (cache, method))) - return res; - - sig = mono_signature_no_pinvoke (method); - - /* we cant remote methods without this pointer */ - if (!sig->hasthis) - return method; - - mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_COMINTEROP_INVOKE); - -#ifndef DISABLE_JIT - /* get real proxy object, which is a ComInteropProxy in this case*/ - mono_mb_add_local (mb, mono_get_object_type ()); - mono_mb_emit_ldarg (mb, 0); - mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoTransparentProxy, rp)); - mono_mb_emit_byte (mb, CEE_LDIND_REF); - - /* load the RCW from the ComInteropProxy*/ - mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoComInteropProxy, com_object)); - mono_mb_emit_byte (mb, CEE_LDIND_REF); - - /* load args and make the call on the RCW */ - for (i = 1; i <= sig->param_count; i++) - mono_mb_emit_ldarg (mb, i); - - if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || mono_class_is_interface (method->klass)) { - MonoMethod * native_wrapper = mono_cominterop_get_native_wrapper(method); - mono_mb_emit_managed_call (mb, native_wrapper, NULL); - } - else { - if (method->flags & METHOD_ATTRIBUTE_VIRTUAL) - mono_mb_emit_op (mb, CEE_CALLVIRT, method); - else - mono_mb_emit_op (mb, CEE_CALL, method); - } - - if (!strcmp(method->name, ".ctor")) { - MONO_STATIC_POINTER_INIT (MonoMethod, cache_proxy) - - ERROR_DECL (error); - cache_proxy = mono_class_get_method_from_name_checked (mono_class_get_interop_proxy_class (), "CacheProxy", 0, 0, error); - mono_error_assert_ok (error); - - MONO_STATIC_POINTER_INIT_END (MonoMethod, cache_proxy) - - mono_mb_emit_ldarg (mb, 0); - mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoTransparentProxy, rp)); - mono_mb_emit_byte (mb, CEE_LDIND_REF); - mono_mb_emit_managed_call (mb, cache_proxy, NULL); - } - - mono_marshal_emit_thread_interrupt_checkpoint (mb); - - mono_mb_emit_byte (mb, CEE_RET); -#endif /* DISABLE_JIT */ - - res = mono_mb_create_and_cache (cache, method, mb, sig, sig->param_count + 16); - mono_mb_free (mb); - - return res; -} - -/* Maps a managed object to its unmanaged representation - * i.e. it's COM Callable Wrapper (CCW). - * Key: MonoObject* - * Value: MonoCCW* - */ -static GHashTable* ccw_hash = NULL; - -/* Maps a CCW interface to it's containing CCW. - * Note that a CCW support many interfaces. - * Key: MonoCCW* - * Value: MonoCCWInterface* - */ -static GHashTable* ccw_interface_hash = NULL; - -/* Maps the IUnknown value of a RCW to - * it's MonoComInteropProxy*. - * Key: void* - * Value: gchandle - */ -static GHashTable* rcw_hash = NULL; - -static MonoMethod* -mono_get_addref (void) -{ - MONO_STATIC_POINTER_INIT (MonoMethod, AddRef) - ERROR_DECL (error); - AddRef = mono_class_get_method_from_name_checked (mono_defaults.marshal_class, "AddRef", 1, 0, error); - mono_error_assert_ok (error); - MONO_STATIC_POINTER_INIT_END (MonoMethod, AddRef) - - return AddRef; -} - -int -mono_cominterop_emit_marshal_com_interface (EmitMarshalContext *m, int argnum, - MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, - MarshalAction action) -{ - MonoMethodBuilder *mb = m->mb; - MonoClass *klass = t->data.klass; - ERROR_DECL (error); - - MONO_STATIC_POINTER_INIT (MonoMethod, get_object_for_iunknown) - get_object_for_iunknown = mono_class_get_method_from_name_checked (mono_defaults.marshal_class, "GetObjectForIUnknown", 1, 0, error); - mono_error_assert_ok (error); - MONO_STATIC_POINTER_INIT_END (MonoMethod, get_object_for_iunknown) - - MONO_STATIC_POINTER_INIT (MonoMethod, get_iunknown_for_object_internal) - get_iunknown_for_object_internal = mono_class_get_method_from_name_checked (mono_defaults.marshal_class, "GetIUnknownForObjectInternal", 1, 0, error); - mono_error_assert_ok (error); - MONO_STATIC_POINTER_INIT_END (MonoMethod, get_iunknown_for_object_internal) - - MONO_STATIC_POINTER_INIT (MonoMethod, get_idispatch_for_object_internal) - get_idispatch_for_object_internal = mono_class_get_method_from_name_checked (mono_defaults.marshal_class, "GetIDispatchForObjectInternal", 1, 0, error); - mono_error_assert_ok (error); - MONO_STATIC_POINTER_INIT_END (MonoMethod, get_idispatch_for_object_internal) - - MONO_STATIC_POINTER_INIT (MonoMethod, get_com_interface_for_object_internal) - get_com_interface_for_object_internal = mono_class_get_method_from_name_checked (mono_defaults.marshal_class, "GetComInterfaceForObjectInternal", 2, 0, error); - mono_error_assert_ok (error); - MONO_STATIC_POINTER_INIT_END (MonoMethod, get_com_interface_for_object_internal) - - MONO_STATIC_POINTER_INIT (MonoMethod, marshal_release) - marshal_release = mono_class_get_method_from_name_checked (mono_defaults.marshal_class, "Release", 1, 0, error); - mono_error_assert_ok (error); - MONO_STATIC_POINTER_INIT_END (MonoMethod, marshal_release) - - -#ifdef DISABLE_JIT - switch (action) { - case MARSHAL_ACTION_CONV_IN: - *conv_arg_type = mono_get_int_type (); - break; - case MARSHAL_ACTION_MANAGED_CONV_IN: - *conv_arg_type = mono_get_int_type (); - break; - default: - break; - } -#else - switch (action) { - case MARSHAL_ACTION_CONV_IN: { - guint32 pos_null = 0; - - MonoType *int_type = mono_get_int_type (); - *conv_arg_type = int_type; - conv_arg = mono_mb_add_local (mb, int_type); - - mono_mb_emit_ptr (mb, NULL); - mono_mb_emit_stloc (mb, conv_arg); - - /* we dont need any conversions for out parameters */ - if (m_type_is_byref (t) && t->attrs & PARAM_ATTRIBUTE_OUT) - break; - - mono_mb_emit_ldarg (mb, argnum); - if (m_type_is_byref (t)) - mono_mb_emit_byte (mb, CEE_LDIND_REF); - /* if null just break, conv arg was already inited to 0 */ - pos_null = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S); - - mono_mb_emit_ldarg (mb, argnum); - if (m_type_is_byref (t)) - mono_mb_emit_byte (mb, CEE_LDIND_REF); - - if (klass && klass != mono_defaults.object_class) { - mono_mb_emit_ptr (mb, t); - mono_mb_emit_icall (mb, cominterop_type_from_handle); - mono_mb_emit_managed_call (mb, get_com_interface_for_object_internal, NULL); - } - else if (spec->native == MONO_NATIVE_IUNKNOWN) - mono_mb_emit_managed_call (mb, get_iunknown_for_object_internal, NULL); - else if (spec->native == MONO_NATIVE_IDISPATCH) - mono_mb_emit_managed_call (mb, get_idispatch_for_object_internal, NULL); - else if (!klass && spec->native == MONO_NATIVE_INTERFACE) - mono_mb_emit_managed_call (mb, get_iunknown_for_object_internal, NULL); - else - g_assert_not_reached (); - mono_mb_emit_stloc (mb, conv_arg); - mono_mb_patch_short_branch (mb, pos_null); - break; - } - - case MARSHAL_ACTION_CONV_OUT: { - if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT)) { - int ccw_obj; - guint32 pos_null = 0, pos_ccw = 0, pos_end = 0; - ccw_obj = mono_mb_add_local (mb, mono_get_object_type ()); - - mono_mb_emit_ldarg (mb, argnum); - mono_mb_emit_byte (mb, CEE_LDNULL); - mono_mb_emit_byte (mb, CEE_STIND_REF); - - mono_mb_emit_ldloc (mb, conv_arg); - pos_null = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S); - - mono_mb_emit_ldloc (mb, conv_arg); - mono_mb_emit_icon (mb, TRUE); - mono_mb_emit_icall (mb, cominterop_get_ccw_object); - mono_mb_emit_stloc (mb, ccw_obj); - mono_mb_emit_ldloc (mb, ccw_obj); - pos_ccw = mono_mb_emit_short_branch (mb, CEE_BRTRUE_S); - - mono_mb_emit_ldarg (mb, argnum); - mono_mb_emit_ldloc (mb, conv_arg); - mono_mb_emit_managed_call (mb, get_object_for_iunknown, NULL); - - if (klass && klass != mono_defaults.object_class) - mono_mb_emit_op (mb, CEE_CASTCLASS, klass); - mono_mb_emit_byte (mb, CEE_STIND_REF); - - pos_end = mono_mb_emit_short_branch (mb, CEE_BR_S); - - /* is already managed object */ - mono_mb_patch_short_branch (mb, pos_ccw); - mono_mb_emit_ldarg (mb, argnum); - mono_mb_emit_ldloc (mb, ccw_obj); - - if (klass && klass != mono_defaults.object_class) - mono_mb_emit_op (mb, CEE_CASTCLASS, klass); - mono_mb_emit_byte (mb, CEE_STIND_REF); - - mono_mb_patch_short_branch (mb, pos_end); - - /* need to call Release to follow COM rules of ownership */ - mono_mb_emit_ldloc (mb, conv_arg); - mono_mb_emit_managed_call (mb, marshal_release, NULL); - mono_mb_emit_byte (mb, CEE_POP); - - /* case if null */ - mono_mb_patch_short_branch (mb, pos_null); - } - break; - } - case MARSHAL_ACTION_PUSH: - if (m_type_is_byref (t)) - mono_mb_emit_ldloc_addr (mb, conv_arg); - else - mono_mb_emit_ldloc (mb, conv_arg); - break; - - case MARSHAL_ACTION_CONV_RESULT: { - int ccw_obj, ret_ptr; - guint32 pos_null = 0, pos_ccw = 0, pos_end = 0; - ccw_obj = mono_mb_add_local (mb, mono_get_object_type ()); - ret_ptr = mono_mb_add_local (mb, mono_get_int_type ()); - - /* store return value */ - mono_mb_emit_stloc (mb, ret_ptr); - - mono_mb_emit_ldloc (mb, ret_ptr); - pos_null = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S); - - mono_mb_emit_ldloc (mb, ret_ptr); - mono_mb_emit_icon (mb, TRUE); - mono_mb_emit_icall (mb, cominterop_get_ccw_object); - mono_mb_emit_stloc (mb, ccw_obj); - mono_mb_emit_ldloc (mb, ccw_obj); - pos_ccw = mono_mb_emit_short_branch (mb, CEE_BRTRUE_S); - - mono_mb_emit_ldloc (mb, ret_ptr); - mono_mb_emit_managed_call (mb, get_object_for_iunknown, NULL); - - if (klass && klass != mono_defaults.object_class) - mono_mb_emit_op (mb, CEE_CASTCLASS, klass); - mono_mb_emit_stloc (mb, 3); - - pos_end = mono_mb_emit_short_branch (mb, CEE_BR_S); - - /* is already managed object */ - mono_mb_patch_short_branch (mb, pos_ccw); - mono_mb_emit_ldloc (mb, ccw_obj); - - if (klass && klass != mono_defaults.object_class) - mono_mb_emit_op (mb, CEE_CASTCLASS, klass); - mono_mb_emit_stloc (mb, 3); - - mono_mb_patch_short_branch (mb, pos_end); - - /* need to call Release to follow COM rules of ownership */ - mono_mb_emit_ldloc (mb, ret_ptr); - mono_mb_emit_managed_call (mb, marshal_release, NULL); - mono_mb_emit_byte (mb, CEE_POP); - - /* case if null */ - mono_mb_patch_short_branch (mb, pos_null); - break; - } - - case MARSHAL_ACTION_MANAGED_CONV_IN: { - int ccw_obj; - guint32 pos_null = 0, pos_ccw = 0, pos_end = 0; - ccw_obj = mono_mb_add_local (mb, mono_get_object_type ()); - - klass = mono_class_from_mono_type_internal (t); - conv_arg = mono_mb_add_local (mb, m_class_get_byval_arg (klass)); - *conv_arg_type = mono_get_int_type (); - - mono_mb_emit_byte (mb, CEE_LDNULL); - mono_mb_emit_stloc (mb, conv_arg); - if (t->attrs & PARAM_ATTRIBUTE_OUT) - break; - - mono_mb_emit_ldarg (mb, argnum); - if (m_type_is_byref (t)) - mono_mb_emit_byte (mb, CEE_LDIND_REF); - pos_null = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S); - - mono_mb_emit_ldarg (mb, argnum); - if (m_type_is_byref (t)) - mono_mb_emit_byte (mb, CEE_LDIND_REF); - mono_mb_emit_icon (mb, TRUE); - mono_mb_emit_icall (mb, cominterop_get_ccw_object); - mono_mb_emit_stloc (mb, ccw_obj); - mono_mb_emit_ldloc (mb, ccw_obj); - pos_ccw = mono_mb_emit_short_branch (mb, CEE_BRTRUE_S); - - - mono_mb_emit_ldarg (mb, argnum); - if (m_type_is_byref (t)) - mono_mb_emit_byte (mb, CEE_LDIND_REF); - mono_mb_emit_managed_call (mb, get_object_for_iunknown, NULL); - - if (klass && klass != mono_defaults.object_class) - mono_mb_emit_op (mb, CEE_CASTCLASS, klass); - mono_mb_emit_stloc (mb, conv_arg); - pos_end = mono_mb_emit_short_branch (mb, CEE_BR_S); - - /* is already managed object */ - mono_mb_patch_short_branch (mb, pos_ccw); - mono_mb_emit_ldloc (mb, ccw_obj); - if (klass && klass != mono_defaults.object_class) - mono_mb_emit_op (mb, CEE_CASTCLASS, klass); - mono_mb_emit_stloc (mb, conv_arg); - - mono_mb_patch_short_branch (mb, pos_end); - /* case if null */ - mono_mb_patch_short_branch (mb, pos_null); - break; - } - - case MARSHAL_ACTION_MANAGED_CONV_OUT: { - if (m_type_is_byref (t) && t->attrs & PARAM_ATTRIBUTE_OUT) { - guint32 pos_null = 0; - - mono_mb_emit_ldarg (mb, argnum); - mono_mb_emit_byte (mb, CEE_LDC_I4_0); - mono_mb_emit_byte (mb, CEE_STIND_I); - - mono_mb_emit_ldloc (mb, conv_arg); - pos_null = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S); - - /* to store later */ - mono_mb_emit_ldarg (mb, argnum); - mono_mb_emit_ldloc (mb, conv_arg); - if (klass && klass != mono_defaults.object_class) { - mono_mb_emit_ptr (mb, t); - mono_mb_emit_icall (mb, cominterop_type_from_handle); - mono_mb_emit_managed_call (mb, get_com_interface_for_object_internal, NULL); - } - else if (spec->native == MONO_NATIVE_IUNKNOWN) - mono_mb_emit_managed_call (mb, get_iunknown_for_object_internal, NULL); - else if (spec->native == MONO_NATIVE_IDISPATCH) - mono_mb_emit_managed_call (mb, get_idispatch_for_object_internal, NULL); - else if (!klass && spec->native == MONO_NATIVE_INTERFACE) - mono_mb_emit_managed_call (mb, get_iunknown_for_object_internal, NULL); - else - g_assert_not_reached (); - mono_mb_emit_byte (mb, CEE_STIND_I); - - mono_mb_emit_ldarg (mb, argnum); - mono_mb_emit_byte (mb, CEE_LDIND_I); - mono_mb_emit_managed_call (mb, mono_get_addref (), NULL); - mono_mb_emit_byte (mb, CEE_POP); - - mono_mb_patch_short_branch (mb, pos_null); - } - break; - } - - case MARSHAL_ACTION_MANAGED_CONV_RESULT: { - guint32 pos_null = 0; - int ccw_obj; - ccw_obj = mono_mb_add_local (mb, mono_get_object_type ()); - - /* store return value */ - mono_mb_emit_stloc (mb, ccw_obj); - - mono_mb_emit_ldloc (mb, ccw_obj); - - /* if null just break, conv arg was already inited to 0 */ - pos_null = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S); - - /* to store later */ - mono_mb_emit_ldloc (mb, ccw_obj); - if (klass && klass != mono_defaults.object_class) { - mono_mb_emit_ptr (mb, t); - mono_mb_emit_icall (mb, cominterop_type_from_handle); - mono_mb_emit_managed_call (mb, get_com_interface_for_object_internal, NULL); - } - else if (spec->native == MONO_NATIVE_IUNKNOWN) - mono_mb_emit_managed_call (mb, get_iunknown_for_object_internal, NULL); - else if (spec->native == MONO_NATIVE_IDISPATCH) - mono_mb_emit_managed_call (mb, get_idispatch_for_object_internal, NULL); - else if (!klass && spec->native == MONO_NATIVE_INTERFACE) - mono_mb_emit_managed_call (mb, get_iunknown_for_object_internal, NULL); - else - g_assert_not_reached (); - mono_mb_emit_stloc (mb, 3); - mono_mb_emit_ldloc (mb, 3); - - mono_mb_emit_managed_call (mb, mono_get_addref (), NULL); - mono_mb_emit_byte (mb, CEE_POP); - - mono_mb_patch_short_branch (mb, pos_null); - break; - } - - default: - g_assert_not_reached (); - } -#endif /* DISABLE_JIT */ - - return conv_arg; -} - -#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 (MonoIUnknown *pUnk) -{ - return mono_IUnknown_AddRef (pUnk); -} - -int -ves_icall_System_Runtime_InteropServices_Marshal_QueryInterfaceInternal (MonoIUnknown *pUnk, gconstpointer riid, gpointer* ppv) -{ - return mono_IUnknown_QueryInterface (pUnk, riid, ppv); -} - -int -ves_icall_System_Runtime_InteropServices_Marshal_ReleaseInternal (MonoIUnknown *pUnk) -{ - g_assert (pUnk); - return mono_IUnknown_Release (pUnk); -} - -static gboolean -cominterop_can_support_dispatch (MonoClass* klass) -{ - if (!mono_class_is_public (klass)) - return FALSE; - - if (!cominterop_com_visible (klass)) - return FALSE; - - return TRUE; -} - -void* -ves_icall_System_Runtime_InteropServices_Marshal_GetIUnknownForObjectInternal (MonoObjectHandle object, MonoError *error) -{ - return mono_cominterop_get_com_interface_internal (TRUE, object, NULL, error); -} - -MonoObjectHandle -ves_icall_System_Runtime_InteropServices_Marshal_GetObjectForCCW (void* pUnk, MonoError *error) -{ -#ifndef DISABLE_COM - /* see if it is a CCW */ - return pUnk ? cominterop_get_ccw_handle ((MonoCCWInterface*)pUnk, TRUE) : NULL_HANDLE; -#else - g_assert_not_reached (); -#endif -} - -void* -ves_icall_System_Runtime_InteropServices_Marshal_GetIDispatchForObjectInternal (MonoObjectHandle object, MonoError *error) -{ -#ifndef DISABLE_COM - if (MONO_HANDLE_IS_NULL (object)) - return NULL; - - MonoRealProxyHandle real_proxy; - - if (cominterop_object_is_rcw_handle (object, &real_proxy)) { - MonoComInteropProxyHandle com_interop_proxy = MONO_HANDLE_CAST (MonoComInteropProxy, real_proxy); - MonoComObjectHandle com_object = MONO_HANDLE_NEW_GET (MonoComObject, com_interop_proxy, com_object); - return cominterop_get_interface_checked (com_object, mono_class_get_idispatch_class (), error); - } - else if (!cominterop_can_support_dispatch (mono_handle_class (object)) ) { - cominterop_set_hr_error (error, MONO_E_NOINTERFACE); - return NULL; - } - return cominterop_get_ccw_checked (object, mono_class_get_idispatch_class (), error); -#else - g_assert_not_reached (); -#endif -} - -void* -ves_icall_System_Runtime_InteropServices_Marshal_GetCCW (MonoObjectHandle object, MonoReflectionTypeHandle ref_type, MonoError *error) -{ -#ifndef DISABLE_COM - g_assert (!MONO_HANDLE_IS_NULL (ref_type)); - MonoType * const type = MONO_HANDLE_GETVAL (ref_type, type); - g_assert (type); - MonoClass * klass = mono_type_get_class_internal (type); - g_assert (klass); - if (!mono_class_init_checked (klass, error)) - return NULL; - - MonoCustomAttrInfo *cinfo = mono_custom_attrs_from_class_checked (klass, error); - mono_error_assert_ok (error); - if (cinfo) { - MonoReflectionComDefaultInterfaceAttribute *attr = (MonoReflectionComDefaultInterfaceAttribute *) - mono_custom_attrs_get_attr_checked (cinfo, mono_class_get_com_default_interface_attribute_class (), error); - mono_error_assert_ok (error); /*FIXME proper error handling*/ - - if (attr) { - MonoType *def_itf = attr->type->type; - if (def_itf->type == MONO_TYPE_CLASS) - klass = mono_type_get_class_internal (def_itf); - } - if (!cinfo->cached) - mono_custom_attrs_free (cinfo); - } - - return cominterop_get_ccw_checked (object, klass, error); -#else - g_assert_not_reached (); -#endif -} - -MonoBoolean -ves_icall_System_Runtime_InteropServices_Marshal_IsComObject (MonoObjectHandle object, MonoError *error) -{ -#ifndef DISABLE_COM - MonoRealProxyHandle real_proxy; - return (MonoBoolean)cominterop_object_is_rcw_handle (object, &real_proxy); -#else - g_assert_not_reached (); -#endif -} - -gint32 -ves_icall_System_Runtime_InteropServices_Marshal_ReleaseComObjectInternal (MonoObjectHandle object, MonoError *error) -{ -#ifndef DISABLE_COM - g_assert (!MONO_HANDLE_IS_NULL (object)); - - MonoRealProxyHandle real_proxy; - gboolean const is_rcw = cominterop_object_is_rcw_handle (object, &real_proxy); - g_assert (is_rcw); - - MonoComInteropProxyHandle proxy = MONO_HANDLE_CAST (MonoComInteropProxy, real_proxy); - g_assert (!MONO_HANDLE_IS_NULL (proxy)); - - if (MONO_HANDLE_GETVAL (proxy, ref_count) == 0) - return -1; - - gint32 ref_count = mono_atomic_dec_i32 (&MONO_HANDLE_GETVAL (proxy, ref_count)); - g_assert (ref_count >= 0); - - if (ref_count == 0) - mono_System_ComObject_ReleaseInterfaces (MONO_HANDLE_NEW_GET (MonoComObject, proxy, com_object)); - - return ref_count; -#else - g_assert_not_reached (); -#endif -} - -guint32 -ves_icall_System_Runtime_InteropServices_Marshal_GetComSlotForMethodInfoInternal (MonoReflectionMethodHandle m, MonoError *error) -{ -#ifndef DISABLE_COM - int const slot = cominterop_get_com_slot_for_method (MONO_HANDLE_GETVAL (m, method), error); - mono_error_assert_ok (error); - return slot; -#else - g_assert_not_reached (); -#endif -} - -/* Only used for COM RCWs */ -MonoObjectHandle -ves_icall_System_ComObject_CreateRCW (MonoReflectionTypeHandle ref_type, MonoError *error) -{ - MonoDomain * const domain = MONO_HANDLE_DOMAIN (ref_type); - MonoType * const type = MONO_HANDLE_GETVAL (ref_type, type); - MonoClass * const klass = mono_class_from_mono_type_internal (type); - - /* Call mono_object_new_alloc_by_vtable instead of mono_object_new_by_vtable - * because we want to actually create object. mono_object_new_by_vtable checks - * to see if type is import and creates transparent proxy. This method - * is called by the corresponding real proxy to create the real RCW. - * Constructor does not need to be called. Will be called later. - */ - MonoVTable *vtable = mono_class_vtable_checked (klass, error); - return_val_if_nok (error, NULL_HANDLE); - return mono_object_new_alloc_by_vtable (vtable, error); -} - -static gboolean -cominterop_rcw_interface_finalizer (gpointer key, gpointer value, gpointer user_data) -{ - mono_IUnknown_Release ((MonoIUnknown*)value); - return TRUE; -} - -void -mono_System_ComObject_ReleaseInterfaces (MonoComObjectHandle obj) -{ - g_assert (!MONO_HANDLE_IS_NULL (obj)); - if (!MONO_HANDLE_GETVAL (obj, itf_hash)) - return; - - mono_cominterop_lock (); - MonoGCHandle gchandle = (MonoGCHandle)g_hash_table_lookup (rcw_hash, MONO_HANDLE_GETVAL (obj, iunknown)); - if (gchandle) { - mono_gchandle_free_internal (gchandle); - g_hash_table_remove (rcw_hash, MONO_HANDLE_GETVAL (obj, iunknown)); - } - - g_hash_table_foreach_remove (MONO_HANDLE_GETVAL (obj, itf_hash), cominterop_rcw_interface_finalizer, NULL); - g_hash_table_destroy (MONO_HANDLE_GETVAL (obj, itf_hash)); - mono_IUnknown_Release (MONO_HANDLE_GETVAL (obj, iunknown)); - MONO_HANDLE_SETVAL (obj, iunknown, MonoIUnknown*, NULL); - MONO_HANDLE_SETVAL (obj, itf_hash, GHashTable*, NULL); - mono_cominterop_unlock (); -} - -void -ves_icall_System_ComObject_ReleaseInterfaces (MonoComObjectHandle obj, MonoError *error) -{ - mono_System_ComObject_ReleaseInterfaces (obj); -} - -gpointer -ves_icall_System_ComObject_GetInterfaceInternal (MonoComObjectHandle obj, MonoReflectionTypeHandle ref_type, MonoBoolean throw_exception, MonoError *error) -{ -#ifndef DISABLE_COM - MonoType * const type = MONO_HANDLE_GETVAL (ref_type, type); - MonoClass * const klass = mono_class_from_mono_type_internal (type); - if (!mono_class_init_checked (klass, error)) - return NULL; - - ERROR_DECL (error_ignored); - gpointer const itf = cominterop_get_interface_checked (obj, klass, throw_exception ? error : error_ignored); - mono_error_cleanup (error_ignored); - return itf; -#else - g_assert_not_reached (); -#endif -} - -/** - * cominterop_get_ccw_object: - * @ccw_entry: a pointer to the CCWEntry - * @verify: verify ccw_entry is in fact a ccw - * - * Returns: the corresponding object for the CCW - */ -static MonoGCHandle -cominterop_get_ccw_gchandle (MonoCCWInterface* ccw_entry, gboolean verify) -{ - /* no CCW's exist yet */ - if (!ccw_interface_hash) - return 0; - - MonoCCW * const ccw = verify ? (MonoCCW *)g_hash_table_lookup (ccw_interface_hash, ccw_entry) : ccw_entry->ccw; - g_assert (verify || ccw); - return ccw ? ccw->gc_handle : 0; -} - -static MonoObjectHandle -cominterop_get_ccw_handle (MonoCCWInterface* ccw_entry, gboolean verify) -{ - MonoGCHandle const gchandle = cominterop_get_ccw_gchandle (ccw_entry, verify); - return gchandle ? mono_gchandle_get_target_handle (gchandle) : NULL_HANDLE; -} - -static MonoObject* -cominterop_get_ccw_object (MonoCCWInterface* ccw_entry, gboolean verify) -{ - MonoGCHandle const gchandle = cominterop_get_ccw_gchandle (ccw_entry, verify); - return gchandle ? mono_gchandle_get_target_internal (gchandle) : NULL; -} - -static MonoDomain* -cominterop_get_domain_for_appdomain (MonoAppDomain *ad_raw) -{ - HANDLE_FUNCTION_ENTER (); - MONO_HANDLE_DCL (MonoAppDomain, ad); - MonoDomain * result = MONO_HANDLE_GETVAL (ad, data); - HANDLE_FUNCTION_RETURN_VAL (result); -} - -static MonoObject* -cominterop_set_ccw_object_domain (MonoObject *object, MonoDomain **prev_domain) -{ - MonoDomain *current = mono_domain_get (), *obj_domain; - - if (mono_object_class (object) == mono_defaults.appdomain_class) - obj_domain = cominterop_get_domain_for_appdomain ((MonoAppDomain *)object); - else - obj_domain = mono_object_domain (object); - - if (obj_domain != current) { - *prev_domain = current; - mono_domain_set_internal_with_options (obj_domain, FALSE); - } - else - *prev_domain = NULL; - - return object; -} - -static void -cominterop_restore_domain (MonoDomain *domain) -{ - if (!domain) - return; - - mono_domain_set_internal_with_options (domain, FALSE); -} - -static void -cominterop_setup_marshal_context (EmitMarshalContext *m, MonoMethod *method) -{ - MonoMethodSignature *sig, *csig; - MonoImage *method_klass_image = m_class_get_image (method->klass); - sig = mono_method_signature_internal (method); - /* we copy the signature, so that we can modify it */ - /* FIXME: which to use? */ - csig = mono_metadata_signature_dup_full (method_klass_image, sig); - /* csig = mono_metadata_signature_dup (sig); */ - - /* STDCALL on windows, CDECL everywhere else to work with XPCOM and MainWin COM */ -#ifdef HOST_WIN32 - csig->call_convention = MONO_CALL_STDCALL; -#else - csig->call_convention = MONO_CALL_C; -#endif - csig->hasthis = 0; - csig->pinvoke = 1; - - m->image = method_klass_image; - m->piinfo = NULL; - m->retobj_var = 0; - m->sig = sig; - m->csig = csig; -} - -static MonoMarshalSpec* -cominterop_get_ccw_default_mspec (const MonoType *param_type) -{ - MonoMarshalVariant elem_type; - MonoMarshalNative native; - MonoMarshalSpec *result; - - switch (param_type->type) { - case MONO_TYPE_OBJECT: - native = MONO_NATIVE_STRUCT; - break; - case MONO_TYPE_STRING: - native = MONO_NATIVE_BSTR; - break; - case MONO_TYPE_CLASS: - native = MONO_NATIVE_INTERFACE; - break; - case MONO_TYPE_BOOLEAN: - native = MONO_NATIVE_VARIANTBOOL; - break; - case MONO_TYPE_SZARRAY: - /* object[] -> SAFEARRAY(VARIANT) */ - native = MONO_NATIVE_SAFEARRAY; - if (param_type->data.array->eklass == mono_defaults.object_class) - elem_type = MONO_VARIANT_VARIANT; - else - return NULL; - break; - default: - return NULL; - } - - result = g_new0 (MonoMarshalSpec, 1); - result->native = native; - if (native == MONO_NATIVE_SAFEARRAY) - result->data.safearray_data.elem_type = elem_type; - - return result; -} - -static MonoClass* -cominterop_get_default_iface (MonoClass *klass) -{ - if (mono_class_is_interface (klass)) - return klass; - - ERROR_DECL (error); - MonoCustomAttrInfo *cinfo = mono_custom_attrs_from_class_checked (klass, error); - mono_error_assert_ok (error); - - if (!cinfo) - return mono_class_get_idispatch_class (); - - MonoClassInterfaceAttribute *class_attr = (MonoClassInterfaceAttribute *)mono_custom_attrs_get_attr_checked (cinfo, mono_class_get_class_interface_attribute_class (), error); - MonoClass *ret; - - if (class_attr) - { - if (class_attr->intType == 0) { - ret = mono_defaults.object_class; - for (guint16 i = 0; i < m_class_get_interface_count (klass); i++) { - MonoClass *iface = m_class_get_interfaces (klass) [i]; - if (cominterop_com_visible (iface)) { - ret = iface; - break; - } - } - } - else if (class_attr->intType == 1) - ret = mono_class_get_idispatch_class (); - else - ret = klass; - } else - ret = mono_class_get_idispatch_class (); - - if (!cinfo->cached) - mono_custom_attrs_free (cinfo); - return ret; -} - -static gboolean -cominterop_class_method_is_visible (MonoMethod *method) -{ - guint16 flags = method->flags; - - if ((flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PUBLIC) - return FALSE; - - if (flags & METHOD_ATTRIBUTE_STATIC) - return FALSE; - - if (flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME) - return FALSE; - - if (!mono_cominterop_method_com_visible (method)) - return FALSE; - - /* if the method is an override, ignore it and use the original definition */ - if ((flags & METHOD_ATTRIBUTE_VIRTUAL) && !(flags & METHOD_ATTRIBUTE_NEW_SLOT)) - return FALSE; - - return TRUE; -} - -static gpointer -cominterop_get_ccw_method (MonoClass *iface, MonoMethod *method, MonoError *error) -{ - int param_index = 0; - MonoMethodBuilder *mb; - MonoMarshalSpec ** mspecs; - MonoMethod *wrapper_method, *adjust_method; - MonoMethodSignature* sig_adjusted; - MonoMethodSignature* sig = mono_method_signature_internal (method); - gboolean const preserve_sig = (method->iflags & METHOD_IMPL_ATTRIBUTE_PRESERVE_SIG) != 0; - EmitMarshalContext m; - - mb = mono_mb_new (iface, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED); - adjust_method = cominterop_get_managed_wrapper_adjusted (method); - sig_adjusted = mono_method_signature_internal (adjust_method); - - mspecs = g_new0 (MonoMarshalSpec*, sig_adjusted->param_count + 1); - mono_method_get_marshal_info (method, mspecs); - - /* move managed args up one */ - for (param_index = sig->param_count; param_index >= 1; param_index--) { - int mspec_index = param_index+1; - mspecs [mspec_index] = mspecs [param_index]; - - if (mspecs[mspec_index] == NULL) { - mspecs[mspec_index] = cominterop_get_ccw_default_mspec (sig_adjusted->params[param_index]); - } else { - /* increase SizeParamIndex since we've added a param */ - if (sig_adjusted->params[param_index]->type == MONO_TYPE_ARRAY || - sig_adjusted->params[param_index]->type == MONO_TYPE_SZARRAY) - if (mspecs[mspec_index]->data.array_data.param_num != -1) - mspecs[mspec_index]->data.array_data.param_num++; - } - } - - /* first arg is IntPtr for interface */ - mspecs [1] = NULL; - - /* move return spec to last param */ - if (!preserve_sig && !MONO_TYPE_IS_VOID (sig->ret)) { - if (mspecs [0] == NULL) - mspecs[0] = cominterop_get_ccw_default_mspec (sig_adjusted->params[sig_adjusted->param_count-1]); - - mspecs [sig_adjusted->param_count] = mspecs [0]; - mspecs [0] = NULL; - } - -#ifndef DISABLE_JIT - /* skip visiblity since we call internal methods */ - mb->skip_visibility = TRUE; -#endif - - cominterop_setup_marshal_context (&m, adjust_method); - m.mb = mb; - m.runtime_marshalling_enabled = TRUE; - mono_marshal_emit_managed_wrapper (mb, sig_adjusted, mspecs, &m, adjust_method, 0, error); - - gpointer ret = NULL; - if (is_ok (error)) { - mono_cominterop_lock (); - wrapper_method = mono_mb_create_method (mb, m.csig, m.csig->param_count + 16); - mono_cominterop_unlock (); - - ret = mono_compile_method_checked (wrapper_method, error); - } - - mono_mb_free (mb); - for (param_index = sig_adjusted->param_count; param_index >= 0; param_index--) - if (mspecs [param_index]) - mono_metadata_free_marshal_spec (mspecs [param_index]); - g_free (mspecs); - - return ret; -} - -/** - * cominterop_get_ccw_checked: - * @object: a pointer to the object - * @itf: interface type needed - * @error: set on error - * - * Returns: a value indicating if the object is a - * Runtime Callable Wrapper (RCW) for a COM object. - * On failure returns NULL and sets @error. - */ -static gpointer -cominterop_get_ccw_checked (MonoObjectHandle object, MonoClass* itf, MonoError *error) -{ - int i, j; - MonoCCW *ccw = NULL; - MonoCCWInterface* ccw_entry = NULL; - gpointer *vtable = NULL; - MonoClass* iface = NULL; - int start_slot = 3; - int method_count = 0; - GList *ccw_list, *ccw_list_item; - MonoCustomAttrInfo *cinfo = NULL; - - if (MONO_HANDLE_IS_NULL (object)) - return NULL; - - MonoClass* klass = mono_handle_class (object); - - mono_cominterop_lock (); - if (!ccw_hash) - ccw_hash = g_hash_table_new (mono_aligned_addr_hash, NULL); - if (!ccw_interface_hash) - ccw_interface_hash = g_hash_table_new (mono_aligned_addr_hash, NULL); - - ccw_list = (GList *)g_hash_table_lookup (ccw_hash, GINT_TO_POINTER (mono_handle_hash (object))); - mono_cominterop_unlock (); - - ccw_list_item = ccw_list; - while (ccw_list_item) { - MonoCCW* ccw_iter = (MonoCCW *)ccw_list_item->data; - if (mono_gchandle_target_equal (ccw_iter->gc_handle, object)) { - ccw = ccw_iter; - break; - } - ccw_list_item = g_list_next(ccw_list_item); - } - - if (!ccw) { - ccw = g_new0 (MonoCCW, 1); -#ifdef HOST_WIN32 - ccw->free_marshaler = 0; -#endif - ccw->vtable_hash = g_hash_table_new (mono_aligned_addr_hash, NULL); - ccw->ref_count = 0; - /* just alloc a weak handle until we are addref'd*/ - ccw->gc_handle = mono_gchandle_new_weakref_from_handle (object); - - if (!ccw_list) { - ccw_list = g_list_alloc (); - ccw_list->data = ccw; - } - else - ccw_list = g_list_append (ccw_list, ccw); - mono_cominterop_lock (); - g_hash_table_insert (ccw_hash, GINT_TO_POINTER (mono_handle_hash (object)), ccw_list); - mono_cominterop_unlock (); - /* register for finalization to clean up ccw */ - mono_object_register_finalizer_handle (object); - } - - cinfo = mono_custom_attrs_from_class_checked (itf, error); - mono_error_assert_ok (error); - if (cinfo) { - MONO_STATIC_POINTER_INIT (MonoClass, coclass_attribute) - - coclass_attribute = mono_class_load_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "CoClassAttribute"); - - MONO_STATIC_POINTER_INIT_END (MonoClass, coclass_attribute) - - if (mono_custom_attrs_has_attr (cinfo, coclass_attribute)) { - g_assert(m_class_get_interface_count (itf) && m_class_get_interfaces (itf)[0]); - itf = m_class_get_interfaces (itf)[0]; - } - if (!cinfo->cached) - mono_custom_attrs_free (cinfo); - } - - iface = cominterop_get_default_iface(itf); - if (iface == mono_class_get_iunknown_class ()) { - start_slot = 3; - } - else if (iface == mono_class_get_idispatch_class ()) { - start_slot = 7; - } - else if (mono_class_is_interface (iface)) { - method_count += mono_class_get_method_count (iface); - start_slot = cominterop_get_com_slot_begin (iface); - } - else { - /* auto-dual object */ - start_slot = 7; - - MonoClass *klass_iter; - for (klass_iter = iface; klass_iter; klass_iter = m_class_get_parent (klass_iter)) { - int mcount = mono_class_get_method_count (klass_iter); - if (mcount && !m_class_get_methods (klass_iter)) - mono_class_setup_methods (klass_iter); - - for (i = 0; i < mcount; ++i) { - MonoMethod *method = m_class_get_methods (klass_iter) [i]; - if (cominterop_class_method_is_visible (method)) - ++method_count; - } - - /* FIXME: accessors for public fields */ - } - } - - ccw_entry = (MonoCCWInterface *)g_hash_table_lookup (ccw->vtable_hash, itf); - - if (!ccw_entry) { - int vtable_index = method_count-1+start_slot; - vtable = (void **)mono_image_alloc0 (m_class_get_image (klass), sizeof (gpointer)*(method_count+start_slot)); - vtable [0] = (gpointer)cominterop_ccw_queryinterface; - vtable [1] = (gpointer)cominterop_ccw_addref; - vtable [2] = (gpointer)cominterop_ccw_release; - if (start_slot == 7) { - vtable [3] = (gpointer)cominterop_ccw_get_type_info_count; - vtable [4] = (gpointer)cominterop_ccw_get_type_info; - vtable [5] = (gpointer)cominterop_ccw_get_ids_of_names; - vtable [6] = (gpointer)cominterop_ccw_invoke; - } - - if (mono_class_is_interface (iface)) { - if (method_count && !m_class_get_methods (iface)) - mono_class_setup_methods (iface); - - for (i = method_count - 1; i >= 0; i--) { - vtable [vtable_index--] = cominterop_get_ccw_method (iface, m_class_get_methods (iface) [i], error); - return_val_if_nok (error, NULL); - } - } - else { - /* Auto-dual object. The methods on an auto-dual interface are - * exposed starting from the innermost parent (i.e. Object) and - * proceeding outwards. The methods within each interfaces are - * exposed in the following order: - * - * 1. Virtual methods - * 2. Interface methods - * 3. Nonvirtual methods - * 4. Fields (get, then put) - * - * Interface methods are exposed in the order that the interface - * was declared. Child interface methods are exposed before parents. - * - * Because we need to expose superclass methods starting from the - * innermost parent, we expose methods in reverse order, so that - * we can just iterate using m_class_get_parent (). */ - - mono_class_setup_vtable (iface); - - MonoClass *klass_iter; - for (klass_iter = iface; klass_iter; klass_iter = m_class_get_parent (klass_iter)) { - mono_class_setup_vtable (klass_iter); - - /* 3. Nonvirtual methods */ - for (i = mono_class_get_method_count (klass_iter) - 1; i >= 0; i--) { - MonoMethod *method = m_class_get_methods (klass_iter) [i]; - if (cominterop_class_method_is_visible (method) && !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) { - vtable [vtable_index--] = cominterop_get_ccw_method (iface, method, error); - return_val_if_nok (error, NULL); - } - } - - /* 2. Interface methods */ - GPtrArray *ifaces = mono_class_get_implemented_interfaces (klass_iter, error); - mono_error_assert_ok (error); - if (ifaces) { - for (i = ifaces->len - 1; i >= 0; i--) { - MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i); - int offset = mono_class_interface_offset (iface, ic); - g_assert (offset >= 0); - for (j = mono_class_get_method_count (ic) - 1; j >= 0; j--) { - MonoMethod *method = m_class_get_methods (ic) [j]; - vtable [vtable_index--] = cominterop_get_ccw_method (iface, m_class_get_vtable (iface) [offset + method->slot], error); - if (!is_ok (error)) { - g_ptr_array_free (ifaces, TRUE); - return NULL; - } - } - } - g_ptr_array_free (ifaces, TRUE); - } - - /* 1. Virtual methods */ - for (i = mono_class_get_method_count (klass_iter) - 1; i >= 0; i--) { - MonoMethod *method = m_class_get_methods (klass_iter) [i]; - if (cominterop_class_method_is_visible (method) && (method->flags & METHOD_ATTRIBUTE_VIRTUAL) - && !cominterop_get_method_interface (method)) { - vtable [vtable_index--] = cominterop_get_ccw_method (iface, m_class_get_vtable (iface) [method->slot], error); - return_val_if_nok (error, NULL); - } - } - } - } - - ccw_entry = g_new0 (MonoCCWInterface, 1); - ccw_entry->ccw = ccw; - ccw_entry->vtable = vtable; - g_hash_table_insert (ccw->vtable_hash, itf, ccw_entry); - g_hash_table_insert (ccw_interface_hash, ccw_entry, ccw); - } - - return ccw_entry; -} - -/** - * cominterop_get_ccw: - * @object: a pointer to the object - * @itf: interface type needed - * - * Returns: a value indicating if the object is a - * Runtime Callable Wrapper (RCW) for a COM object - */ -static gpointer -cominterop_get_ccw (MonoObject* object_raw, MonoClass* itf) -{ - HANDLE_FUNCTION_ENTER (); - ERROR_DECL (error); - MONO_HANDLE_DCL (MonoObject, object); - gpointer const ccw_entry = cominterop_get_ccw_checked (object, itf, error); - mono_error_set_pending_exception (error); - HANDLE_FUNCTION_RETURN_VAL (ccw_entry); -} - -static gboolean -mono_marshal_free_ccw_entry (gpointer key, gpointer value, gpointer user_data) -{ - g_hash_table_remove (ccw_interface_hash, value); - g_assert (value); - g_free (value); - return TRUE; -} - -/** - * mono_marshal_free_ccw: - * \param object the mono object - * \returns whether the object had a CCW - */ -static gboolean -mono_marshal_free_ccw_handle (MonoObjectHandle object) -{ - /* no ccw's were created */ - if (!ccw_hash || g_hash_table_size (ccw_hash) == 0) - return FALSE; - - mono_cominterop_lock (); - GList *ccw_list = (GList *)g_hash_table_lookup (ccw_hash, GINT_TO_POINTER (mono_handle_hash (object))); - mono_cominterop_unlock (); - - if (!ccw_list) - return FALSE; - - /* need to cache orig list address to remove from hash_table if empty */ - GList * const ccw_list_orig = ccw_list; - - for (GList* ccw_list_item = ccw_list; ccw_list_item; ) { - MonoCCW* ccw_iter = (MonoCCW *)ccw_list_item->data; - gboolean is_null = FALSE; - gboolean is_equal = FALSE; - mono_gchandle_target_is_null_or_equal (ccw_iter->gc_handle, object, &is_null, &is_equal); - - /* Looks like the GC NULLs the weakref handle target before running the - * finalizer. So if we get a NULL target, destroy the CCW as well. - * Unless looking up the object from the CCW shows it not the right object. - */ - gboolean destroy_ccw = is_null || is_equal; - if (is_null) { - MonoCCWInterface* ccw_entry = (MonoCCWInterface *)g_hash_table_lookup (ccw_iter->vtable_hash, mono_class_get_iunknown_class ()); - MonoGCHandle gchandle = NULL; - if (!(ccw_entry && (gchandle = cominterop_get_ccw_gchandle (ccw_entry, FALSE)) && mono_gchandle_target_equal (gchandle, object))) - destroy_ccw = FALSE; - } - if (destroy_ccw) { - /* remove all interfaces */ - g_hash_table_foreach_remove (ccw_iter->vtable_hash, mono_marshal_free_ccw_entry, NULL); - g_hash_table_destroy (ccw_iter->vtable_hash); - - /* get next before we delete */ - ccw_list_item = g_list_next (ccw_list_item); - - /* remove ccw from list */ - ccw_list = g_list_remove (ccw_list, ccw_iter); -#ifdef HOST_WIN32 - mono_IUnknown_Release (ccw_iter->free_marshaler); -#endif - g_free (ccw_iter); - } - else - ccw_list_item = g_list_next (ccw_list_item); - } - - /* if list is empty remove original address from hash */ - if (g_list_length (ccw_list) == 0) - g_hash_table_remove (ccw_hash, GINT_TO_POINTER (mono_handle_hash (object))); - else if (ccw_list != ccw_list_orig) - g_hash_table_insert (ccw_hash, GINT_TO_POINTER (mono_handle_hash (object)), ccw_list); - - return TRUE; -} - -gboolean -mono_marshal_free_ccw (MonoObject* object_raw) -{ - /* no ccw's were created */ - if (!ccw_hash || g_hash_table_size (ccw_hash) == 0) - return FALSE; - - HANDLE_FUNCTION_ENTER (); - MONO_HANDLE_DCL (MonoObject, object); - gboolean const result = mono_marshal_free_ccw_handle (object); - HANDLE_FUNCTION_RETURN_VAL (result); -} - -/** - * cominterop_get_managed_wrapper_adjusted: - * @method: managed COM Interop method - * - * Returns: the generated method to call with signature matching - * the unmanaged COM Method signature - */ -static MonoMethod * -cominterop_get_managed_wrapper_adjusted (MonoMethod *method) -{ - MonoMethod *res = NULL; - MonoMethodBuilder *mb; - MonoMarshalSpec **mspecs; - MonoMethodSignature *sig, *sig_native; - MonoExceptionClause *main_clause = NULL; - int hr = 0, retval = 0; - int pos_leave, domain_var; - int i; - gboolean const preserve_sig = (method->iflags & METHOD_IMPL_ATTRIBUTE_PRESERVE_SIG) != 0; - MonoType *int_type = mono_get_int_type (); - - MONO_STATIC_POINTER_INIT (MonoMethod, get_hr_for_exception) - - ERROR_DECL (error); - get_hr_for_exception = mono_class_get_method_from_name_checked (mono_defaults.marshal_class, "GetHRForException", -1, 0, error); - mono_error_assert_ok (error); - - MONO_STATIC_POINTER_INIT_END (MonoMethod, get_hr_for_exception) - - sig = mono_method_signature_internal (method); - - /* create unmanaged wrapper */ - mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_COMINTEROP); - - sig_native = cominterop_method_signature (method); - - mspecs = g_new0 (MonoMarshalSpec*, sig_native->param_count+1); - - mono_method_get_marshal_info (method, mspecs); - - /* move managed args up one */ - for (i = sig->param_count; i >= 1; i--) - mspecs [i+1] = mspecs [i]; - - /* first arg is IntPtr for interface */ - mspecs [1] = NULL; - - /* move return spec to last param */ - if (!preserve_sig && !MONO_TYPE_IS_VOID (sig->ret)) - mspecs [sig_native->param_count] = mspecs [0]; - - mspecs [0] = NULL; - -#ifndef DISABLE_JIT - if (!preserve_sig) { - if (!MONO_TYPE_IS_VOID (sig->ret)) - retval = mono_mb_add_local (mb, sig->ret); - hr = mono_mb_add_local (mb, mono_get_int32_type ()); - } - else if (!MONO_TYPE_IS_VOID (sig->ret)) - hr = mono_mb_add_local (mb, sig->ret); - - /* try */ - main_clause = g_new0 (MonoExceptionClause, 1); - main_clause->try_offset = mono_mb_get_label (mb); - - domain_var = mono_mb_add_local (mb, int_type); - - /* the CCW -> object conversion */ - mono_mb_emit_ldarg (mb, 0); - mono_mb_emit_icon (mb, FALSE); - mono_mb_emit_icall (mb, cominterop_get_ccw_object); - - /* Object is left on stack */ - mono_mb_emit_ldloc_addr (mb, domain_var); - mono_mb_emit_icall (mb, cominterop_set_ccw_object_domain); - - for (i = 0; i < sig->param_count; i++) - mono_mb_emit_ldarg (mb, i+1); - - mono_mb_emit_managed_call (mb, method, NULL); - - if (!MONO_TYPE_IS_VOID (sig->ret)) { - if (!preserve_sig) { - mono_mb_emit_stloc (mb, retval); - mono_mb_emit_ldarg (mb, sig_native->param_count - 1); - const int pos_null = mono_mb_emit_branch (mb, CEE_BRFALSE); - - mono_mb_emit_ldarg (mb, sig_native->param_count - 1); - mono_mb_emit_ldloc (mb, retval); - - MonoClass *rclass = mono_class_from_mono_type_internal (sig->ret); - if (m_class_is_valuetype (rclass)) { - mono_mb_emit_op (mb, CEE_STOBJ, rclass); - } else { - mono_mb_emit_byte (mb, mono_type_to_stind (sig->ret)); - } - - mono_mb_patch_branch (mb, pos_null); - } else - mono_mb_emit_stloc (mb, hr); - } - - pos_leave = mono_mb_emit_branch (mb, CEE_LEAVE); - - /* Main exception catch */ - main_clause->flags = MONO_EXCEPTION_CLAUSE_NONE; - main_clause->try_len = mono_mb_get_pos (mb) - main_clause->try_offset; - main_clause->data.catch_class = mono_defaults.object_class; - - /* handler code */ - main_clause->handler_offset = mono_mb_get_label (mb); - - if (!preserve_sig || (sig->ret && !m_type_is_byref (sig->ret) && (sig->ret->type == MONO_TYPE_U4 || sig->ret->type == MONO_TYPE_I4))) { - mono_mb_emit_managed_call (mb, get_hr_for_exception, NULL); - mono_mb_emit_stloc (mb, hr); - } - else { - mono_mb_emit_byte (mb, CEE_POP); - } - - mono_mb_emit_branch (mb, CEE_LEAVE); - main_clause->handler_len = mono_mb_get_pos (mb) - main_clause->handler_offset; - /* end catch */ - - mono_mb_set_clauses (mb, 1, main_clause); - - mono_mb_patch_branch (mb, pos_leave); - - if (!preserve_sig || !MONO_TYPE_IS_VOID (sig->ret)) - mono_mb_emit_ldloc (mb, hr); - - mono_mb_emit_ldloc (mb, domain_var); - mono_mb_emit_icall (mb, cominterop_restore_domain); - - mono_mb_emit_byte (mb, CEE_RET); -#endif /* DISABLE_JIT */ - - mono_cominterop_lock (); - res = mono_mb_create_method (mb, sig_native, sig_native->param_count + 16); - mono_cominterop_unlock (); - - mono_mb_free (mb); - - for (i = sig_native->param_count; i >= 0; i--) - mono_metadata_free_marshal_spec (mspecs [i]); - g_free (mspecs); - - return res; -} - -static gboolean -cominterop_class_guid_equal (const guint8* guid, MonoClass* klass) -{ - guint8 klass_guid [16]; - if (cominterop_class_guid (klass, klass_guid)) - return !memcmp (guid, klass_guid, sizeof (klass_guid)); - return FALSE; -} - -static int STDCALL -cominterop_ccw_addref_impl (MonoCCWInterface* ccwe); - -static int STDCALL -cominterop_ccw_addref (MonoCCWInterface* ccwe) -{ - int result; - MONO_CCW_CALL_ENTER; - result = cominterop_ccw_addref_impl (ccwe); - MONO_CCW_CALL_EXIT; - return result; -} - -static int STDCALL -cominterop_ccw_addref_impl (MonoCCWInterface* ccwe) -{ - MONO_REQ_GC_UNSAFE_MODE; - MonoCCW* ccw = ccwe->ccw; - g_assert (ccw); - g_assert (ccw->gc_handle); - gint32 const ref_count = mono_atomic_inc_i32 ((gint32*)&ccw->ref_count); - if (ref_count == 1) { - MonoGCHandle oldhandle = ccw->gc_handle; - g_assert (oldhandle); - /* since we now have a ref count, alloc a strong handle*/ - ccw->gc_handle = mono_gchandle_from_handle (mono_gchandle_get_target_handle (oldhandle), FALSE); - mono_gchandle_free_internal (oldhandle); - } - return ref_count; -} - -static int STDCALL -cominterop_ccw_release_impl (MonoCCWInterface* ccwe); - -static int STDCALL -cominterop_ccw_release (MonoCCWInterface* ccwe) -{ - int result; - MONO_CCW_CALL_ENTER; - result = cominterop_ccw_release_impl (ccwe); - MONO_CCW_CALL_EXIT; - return result; -} - -static int STDCALL -cominterop_ccw_release_impl (MonoCCWInterface* ccwe) -{ - MONO_REQ_GC_UNSAFE_MODE; - MonoCCW* ccw = ccwe->ccw; - g_assert (ccw); - g_assert (ccw->ref_count > 0); - gint32 const ref_count = mono_atomic_dec_i32 ((gint32*)&ccw->ref_count); - if (ref_count == 0) { - /* allow gc of object */ - MonoGCHandle oldhandle = ccw->gc_handle; - g_assert (oldhandle); - ccw->gc_handle = mono_gchandle_new_weakref_from_handle (mono_gchandle_get_target_handle (oldhandle)); - mono_gchandle_free_internal (oldhandle); - } - return ref_count; -} - -#ifdef HOST_WIN32 -static const IID MONO_IID_IMarshal = {0x3, 0x0, 0x0, {0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46}}; - -/* All ccw objects are free threaded */ -static int -cominterop_ccw_getfreethreadedmarshaler (MonoCCW* ccw, MonoObjectHandle object, gpointer* ppv, MonoError *error) -{ - if (!ccw->free_marshaler) { - gpointer const tunk = cominterop_get_ccw_checked (object, mono_class_get_iunknown_class (), error); - return_val_if_nok (error, MONO_E_NOINTERFACE); - int const ret = CoCreateFreeThreadedMarshaler ((LPUNKNOWN)tunk, (LPUNKNOWN*)&ccw->free_marshaler); - } - - return ccw->free_marshaler ? mono_IUnknown_QueryInterface (ccw->free_marshaler, &MONO_IID_IMarshal, ppv) - : MONO_E_NOINTERFACE; -} -#endif - -static int STDCALL -cominterop_ccw_queryinterface_impl (MonoCCWInterface* ccwe, const guint8* riid, gpointer* ppv); - -static int STDCALL -cominterop_ccw_queryinterface (MonoCCWInterface* ccwe, const guint8* riid, gpointer* ppv) -{ - int result; - MONO_CCW_CALL_ENTER; - result = cominterop_ccw_queryinterface_impl (ccwe, riid, ppv); - MONO_CCW_CALL_EXIT; - return result; -} - -static int STDCALL -cominterop_ccw_queryinterface_impl (MonoCCWInterface* ccwe, const guint8* riid, gpointer* ppv) -{ - MONO_REQ_GC_UNSAFE_MODE; - ERROR_DECL (error); - GPtrArray *ifaces; - MonoClass *itf = NULL; - int i; - MonoCCW* ccw = ccwe->ccw; - MonoClass* klass_iter = NULL; - MonoObjectHandle object = mono_gchandle_get_target_handle (ccw->gc_handle); - - g_assert (!MONO_HANDLE_IS_NULL (object)); - MonoClass* const klass = mono_handle_class (object); - - if (ppv) - *ppv = NULL; - - if (!mono_domain_get ()) - mono_thread_attach_external_native_thread (mono_get_root_domain (), FALSE); - - /* handle IUnknown special */ - if (cominterop_class_guid_equal (riid, mono_class_get_iunknown_class ())) { - *ppv = cominterop_get_ccw_checked (object, mono_class_get_iunknown_class (), error); - mono_error_assert_ok (error); - /* remember to addref on QI */ - cominterop_ccw_addref_impl ((MonoCCWInterface *)*ppv); - return MONO_S_OK; - } - - /* handle IDispatch special */ - 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_checked (object, mono_class_get_idispatch_class (), error); - mono_error_assert_ok (error); - /* remember to addref on QI */ - cominterop_ccw_addref_impl ((MonoCCWInterface *)*ppv); - return MONO_S_OK; - } - -#ifdef HOST_WIN32 - /* handle IMarshal special */ - if (0 == memcmp (riid, &MONO_IID_IMarshal, sizeof (IID))) { - int const res = cominterop_ccw_getfreethreadedmarshaler (ccw, object, ppv, error); - mono_error_assert_ok (error); - return res; - } -#endif - klass_iter = klass; - while (klass_iter && klass_iter != mono_defaults.object_class) { - ifaces = mono_class_get_implemented_interfaces (klass_iter, error); - mono_error_assert_ok (error); - if (ifaces) { - for (i = 0; i < ifaces->len; ++i) { - MonoClass *ic = NULL; - ic = (MonoClass *)g_ptr_array_index (ifaces, i); - if (cominterop_class_guid_equal (riid, ic)) { - itf = ic; - break; - } - } - g_ptr_array_free (ifaces, TRUE); - } - - if (itf) - break; - - klass_iter = m_class_get_parent (klass_iter); - } - if (itf) { - *ppv = cominterop_get_ccw_checked (object, itf, error); - if (!is_ok (error)) { - mono_error_cleanup (error); /* FIXME don't swallow the error */ - return MONO_E_NOINTERFACE; - } - /* remember to addref on QI */ - cominterop_ccw_addref_impl ((MonoCCWInterface *)*ppv); - return MONO_S_OK; - } - - return MONO_E_NOINTERFACE; -} - -static int STDCALL -cominterop_ccw_get_type_info_count (MonoCCWInterface* ccwe, guint32 *pctinfo) -{ - if(!pctinfo) - return MONO_E_INVALIDARG; - - *pctinfo = 1; - - return MONO_S_OK; -} - -static int STDCALL -cominterop_ccw_get_type_info (MonoCCWInterface* ccwe, guint32 iTInfo, guint32 lcid, gpointer *ppTInfo) -{ - return MONO_E_NOTIMPL; -} - -static int STDCALL -cominterop_ccw_get_ids_of_names_impl (MonoCCWInterface* ccwe, gpointer riid, - gunichar2** rgszNames, guint32 cNames, - guint32 lcid, gint32 *rgDispId); - - -static int STDCALL -cominterop_ccw_get_ids_of_names (MonoCCWInterface* ccwe, gpointer riid, - gunichar2** rgszNames, guint32 cNames, - guint32 lcid, gint32 *rgDispId) -{ - int result; - MONO_CCW_CALL_ENTER; - result = cominterop_ccw_get_ids_of_names_impl (ccwe, riid, rgszNames, cNames, lcid, rgDispId); - MONO_CCW_CALL_EXIT; - return result; -} - - -/** - * unicode_to_external: - * \param uni a UTF-16 string to convert to an external representation. - * Turns NULL-terminated UTF-16 into UTF-8. If the conversion doesn't - * work, then NULL is returned. - * Callers must free the returned string. - */ -static gchar * -unicode_to_external (const gunichar2 *uni) -{ - gchar *utf8; - GError *gerr = NULL; - - utf8 = g_utf16_to_utf8 (uni, -1, NULL, NULL, &gerr); - if (utf8 == NULL) { - mono_error_set_argument (err, "uni", gerr->message); - g_error_free (gerr); - return NULL; - } - - return(utf8); -} - -static int STDCALL -cominterop_ccw_get_ids_of_names_impl (MonoCCWInterface* ccwe, gpointer riid, - gunichar2** rgszNames, guint32 cNames, - guint32 lcid, gint32 *rgDispId) -{ - MONO_REQ_GC_UNSAFE_MODE; - ERROR_DECL (error); - 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_internal (ccw->gc_handle); - - /* Handle DispIdAttribute */ - - MONO_STATIC_POINTER_INIT (MonoClass, ComDispIdAttribute) - - ComDispIdAttribute = mono_class_load_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "DispIdAttribute"); - - MONO_STATIC_POINTER_INIT_END (MonoClass, ComDispIdAttribute) - - g_assert (object); - klass = mono_object_class (object); - - if (!mono_domain_get ()) - mono_thread_attach_external_native_thread (mono_get_root_domain (), FALSE); - - for (i=0; i < cNames; i++) { - methodname = unicode_to_external (rgszNames[i]); - - method = mono_class_get_method_from_name_checked(klass, methodname, -1, 0, error); - if (method && is_ok (error)) { - cinfo = mono_custom_attrs_from_method_checked (method, error); - mono_error_assert_ok (error); /* FIXME what's reasonable to do here */ - if (cinfo) { - MonoObject *result = mono_custom_attrs_get_attr_checked (cinfo, ComDispIdAttribute, error); - mono_error_assert_ok (error); /*FIXME proper error handling*/; - - if (result) - rgDispId[i] = *(gint32*)mono_object_unbox_internal (result); - else - rgDispId[i] = (gint32)method->token; - - if (!cinfo->cached) - mono_custom_attrs_free (cinfo); - } - else - rgDispId[i] = (gint32)method->token; - } else { - mono_error_cleanup (error); - error_init (error); /* reuse for next iteration */ - rgDispId[i] = MONO_E_DISPID_UNKNOWN; - ret = MONO_E_DISP_E_UNKNOWNNAME; - } - } - - return ret; -} - -static int STDCALL -cominterop_ccw_invoke (MonoCCWInterface* ccwe, guint32 dispIdMember, - gpointer riid, guint32 lcid, - guint16 wFlags, gpointer pDispParams, - gpointer pVarResult, gpointer pExcepInfo, - guint32 *puArgErr) -{ - return MONO_E_NOTIMPL; -} - -#ifndef HOST_WIN32 - -typedef mono_bstr (STDCALL *SysAllocStringLenFunc)(const gunichar* str, guint32 len); -typedef guint32 (STDCALL *SysStringLenFunc)(mono_bstr_const bstr); -typedef void (STDCALL *SysFreeStringFunc)(mono_bstr_const str); - -static SysAllocStringLenFunc sys_alloc_string_len_ms = NULL; -static SysStringLenFunc sys_string_len_ms = NULL; -static SysFreeStringFunc sys_free_string_ms = NULL; - -typedef struct tagSAFEARRAYBOUND { - ULONG cElements; - LONG lLbound; -}SAFEARRAYBOUND,*LPSAFEARRAYBOUND; -#define VT_VARIANT 12 - -typedef guint32 (STDCALL *SafeArrayGetDimFunc)(gpointer psa); -typedef int (STDCALL *SafeArrayGetLBoundFunc)(gpointer psa, guint32 nDim, glong* plLbound); -typedef int (STDCALL *SafeArrayGetUBoundFunc)(gpointer psa, guint32 nDim, glong* plUbound); -typedef int (STDCALL *SafeArrayPtrOfIndexFunc)(gpointer psa, glong* rgIndices, gpointer* ppvData); -typedef int (STDCALL *SafeArrayDestroyFunc)(gpointer psa); -typedef int (STDCALL *SafeArrayPutElementFunc)(gpointer psa, glong* rgIndices, gpointer* ppvData); -typedef gpointer (STDCALL *SafeArrayCreateFunc)(int vt, guint32 cDims, SAFEARRAYBOUND* rgsabound); - -static SafeArrayGetDimFunc safe_array_get_dim_ms = NULL; -static SafeArrayGetLBoundFunc safe_array_get_lbound_ms = NULL; -static SafeArrayGetUBoundFunc safe_array_get_ubound_ms = NULL; -static SafeArrayPtrOfIndexFunc safe_array_ptr_of_index_ms = NULL; -static SafeArrayDestroyFunc safe_array_destroy_ms = NULL; -static SafeArrayPutElementFunc safe_array_put_element_ms = NULL; -static SafeArrayCreateFunc safe_array_create_ms = NULL; - -static gboolean -init_com_provider_ms (void) -{ - ERROR_DECL (error); - - static gboolean initialized = FALSE; - MonoDl *module = NULL; - const char* scope = "liboleaut32.so"; - - if (initialized) { - // Barrier here prevents reads of sys_alloc_string_len_ms etc. - // from being reordered before initialized. - mono_memory_barrier (); - return TRUE; - } - - module = mono_dl_open (scope, MONO_DL_LAZY, error); - if (!module) { - g_warning ("Error loading COM support library '%s': %s", scope, mono_error_get_message_without_fields (error)); - mono_error_cleanup (error); - g_assert_not_reached (); - return FALSE; - } - - sys_alloc_string_len_ms = (SysAllocStringLenFunc)mono_dl_symbol (module, "SysAllocStringLen", error); - if (!sys_alloc_string_len_ms) { - g_warning ("Error loading entry point '%s' in COM support library '%s': %s", "SysAllocStringLen", scope, mono_error_get_message_without_fields (error)); - mono_error_cleanup (error); - g_assert_not_reached (); - return FALSE; - } - - sys_string_len_ms = (SysStringLenFunc)mono_dl_symbol (module, "SysStringLen", error); - if (!sys_string_len_ms) { - g_warning ("Error loading entry point '%s' in COM support library '%s': %s", "SysStringLen", scope, mono_error_get_message_without_fields (error)); - mono_error_cleanup (error); - g_assert_not_reached (); - return FALSE; - } - - sys_free_string_ms = (SysFreeStringFunc)mono_dl_symbol (module, "SysFreeString", error); - if (!sys_free_string_ms) { - g_warning ("Error loading entry point '%s' in COM support library '%s': %s", "SysFreeString", scope, mono_error_get_message_without_fields (error)); - mono_error_cleanup (error); - g_assert_not_reached (); - return FALSE; - } - - safe_array_get_dim_ms = (SafeArrayGetDimFunc)mono_dl_symbol (module, "SafeArrayGetDim", error); - if (!safe_array_get_dim_ms) { - g_warning ("Error loading entry point '%s' in COM support library '%s': %s", "SafeArrayGetDim", scope, mono_error_get_message_without_fields (error)); - mono_error_cleanup (error); - g_assert_not_reached (); - return FALSE; - } - - safe_array_get_lbound_ms = (SafeArrayGetLBoundFunc)mono_dl_symbol (module, "SafeArrayGetLBound", error); - if (!safe_array_get_lbound_ms) { - g_warning ("Error loading entry point '%s' in COM support library '%s': %s", "SafeArrayGetLBound", scope, mono_error_get_message_without_fields (error)); - mono_error_cleanup (error); - g_assert_not_reached (); - return FALSE; - } - - safe_array_get_ubound_ms = (SafeArrayGetUBoundFunc)mono_dl_symbol (module, "SafeArrayGetUBound", error); - if (!safe_array_get_ubound_ms) { - g_warning ("Error loading entry point '%s' in COM support library '%s': %s", "SafeArrayGetUBound", scope, mono_error_get_message_without_fields (error)); - mono_error_cleanup (error); - g_assert_not_reached (); - return FALSE; - } - - safe_array_ptr_of_index_ms = (SafeArrayPtrOfIndexFunc)mono_dl_symbol (module, "SafeArrayPtrOfIndex", error); - if (!safe_array_ptr_of_index_ms) { - g_warning ("Error loading entry point '%s' in COM support library '%s': %s", "SafeArrayPtrOfIndex", scope, mono_error_get_message_without_fields (error)); - mono_error_cleanup (error); - g_assert_not_reached (); - return FALSE; - } - - safe_array_destroy_ms = (SafeArrayDestroyFunc)mono_dl_symbol (module, "SafeArrayDestroy", error); - if (!safe_array_destroy_ms) { - g_warning ("Error loading entry point '%s' in COM support library '%s': %s", "SafeArrayDestroy", scope, mono_error_get_message_without_fields (error)); - mono_error_cleanup (error); - g_assert_not_reached (); - return FALSE; - } - - safe_array_put_element_ms = (SafeArrayPutElementFunc)mono_dl_symbol (module, "SafeArrayPutElement", error); - if (!safe_array_put_element_ms) { - g_warning ("Error loading entry point '%s' in COM support library '%s': %s", "SafeArrayPutElement", scope, mono_error_get_message_without_fields (error)); - mono_error_cleanup (error); - g_assert_not_reached (); - return FALSE; - } - - safe_array_create_ms = (SafeArrayCreateFunc)mono_dl_symbol (module, "SafeArrayCreate", error); - if (!safe_array_create_ms) { - g_warning ("Error loading entry point '%s' in COM support library '%s': %s", "SafeArrayCreate", scope, mono_error_get_message_without_fields (error)); - mono_error_cleanup (error); - g_assert_not_reached (); - return FALSE; - } - - mono_memory_barrier (); - initialized = TRUE; - return TRUE; -} - -#endif // WIN32 -#endif // DISABLE_COM - -// This function is used regardless of the BSTR type, so cast the return value -// Inputted string length, in bytes, should include the null terminator -// Returns the start of the string itself -static gpointer -mono_bstr_alloc (size_t str_byte_len) -{ - // Allocate string length plus pointer-size integer to store the length, aligned to 16 bytes - size_t alloc_size = str_byte_len + SIZEOF_VOID_P; - alloc_size += (16 - 1); - alloc_size &= ~(16 - 1); - gpointer ret = g_malloc0 (alloc_size); - return ret ? (char *)ret + SIZEOF_VOID_P : NULL; -} - -static void -mono_bstr_set_length (gunichar2 *bstr, int slen) -{ - *((guint32 *)bstr - 1) = slen * sizeof (gunichar2); -} - -static mono_bstr -default_ptr_to_bstr (const gunichar2* ptr, int slen) -{ - // In Mono, historically BSTR was allocated with a guaranteed size prefix of 4 bytes regardless of platform. - // Presumably this is due to the BStr documentation page, which indicates that behavior and then directs you to call - // SysAllocString on Windows to handle the allocation for you. Unfortunately, this is not actually how it works: - // The allocation pre-string is pointer-sized, and then only 4 bytes are used for the length regardless. Additionally, - // the total length is also aligned to a 16-byte boundary. This preserves the old behavior on legacy and fixes it for - // netcore moving forward. - mono_bstr const s = (mono_bstr)mono_bstr_alloc ((slen + 1) * sizeof (gunichar2)); - if (s == NULL) - return NULL; - - mono_bstr_set_length (s, slen); - if (ptr) - memcpy (s, ptr, slen * sizeof (gunichar2)); - s [slen] = 0; - return s; -} - -/* PTR can be NULL */ -mono_bstr -mono_ptr_to_bstr (const gunichar2* ptr, int slen) -{ -#ifdef HOST_WIN32 -#if HAVE_API_SUPPORT_WIN32_BSTR - return SysAllocStringLen (ptr, slen); -#else - return default_ptr_to_bstr (ptr, slen); -#endif -#else -#ifndef DISABLE_COM - if (com_provider == MONO_COM_DEFAULT) { -#endif - return default_ptr_to_bstr (ptr, slen); -#ifndef DISABLE_COM - } - else if (com_provider == MONO_COM_MS && init_com_provider_ms ()) { - guint32 const len = slen; - gunichar* const str = ptr ? g_utf16_to_ucs4 (ptr, len, NULL, NULL, NULL) : NULL; - mono_bstr const ret = sys_alloc_string_len_ms (str, len); - g_free (str); - return ret; - } - else { - g_assert_not_reached(); - } -#endif -#endif -} - -char * -mono_ptr_to_ansibstr (const char *ptr, size_t slen) -{ - // FIXME: should this behave differently without DISABLE_COM? - char *s = (char *)mono_bstr_alloc ((slen + 1) * sizeof(char)); - if (s == NULL) - return NULL; - *((guint32 *)s - 1) = (guint32)(slen * sizeof (char)); - if (ptr) - memcpy (s, ptr, slen * sizeof (char)); - s [slen] = 0; - return s; -} - -MonoStringHandle -mono_string_from_bstr_checked (mono_bstr_const bstr, MonoError *error) -{ - if (!bstr) - return NULL_HANDLE_STRING; -#ifdef HOST_WIN32 -#if HAVE_API_SUPPORT_WIN32_BSTR - return mono_string_new_utf16_handle (bstr, SysStringLen ((BSTR)bstr), error); -#else - return mono_string_new_utf16_handle (bstr, *((guint32 *)bstr - 1) / sizeof (gunichar2), error); -#endif /* HAVE_API_SUPPORT_WIN32_BSTR */ -#else -#ifndef DISABLE_COM - if (com_provider == MONO_COM_DEFAULT) -#endif - return mono_string_new_utf16_handle (bstr, *((guint32 *)bstr - 1) / sizeof (gunichar2), error); -#ifndef DISABLE_COM - else if (com_provider == MONO_COM_MS && init_com_provider_ms ()) { - glong written = 0; - // FIXME mono_string_new_utf32_handle to combine g_ucs4_to_utf16 and mono_string_new_utf16_handle. - gunichar2* utf16 = g_ucs4_to_utf16 ((const gunichar *)bstr, sys_string_len_ms (bstr), NULL, &written, NULL); - MonoStringHandle res = mono_string_new_utf16_handle (utf16, written, error); - g_free (utf16); - return res; - } else { - g_assert_not_reached (); - } -#endif // DISABLE_COM -#endif // HOST_WIN32 -} - -MonoString * -mono_string_from_bstr (/*mono_bstr_const*/gpointer bstr) -{ - // FIXME gcmode - HANDLE_FUNCTION_ENTER (); - ERROR_DECL (error); - MonoStringHandle result = mono_string_from_bstr_checked ((mono_bstr_const)bstr, error); - mono_error_cleanup (error); - HANDLE_FUNCTION_RETURN_OBJ (result); -} - -MonoStringHandle -mono_string_from_bstr_icall_impl (mono_bstr_const bstr, MonoError *error) -{ - return mono_string_from_bstr_checked (bstr, error); -} - -MONO_API void -mono_free_bstr (/*mono_bstr_const*/gpointer bstr) -{ - if (!bstr) - return; -#ifdef HOST_WIN32 -#if HAVE_API_SUPPORT_WIN32_BSTR - SysFreeString ((BSTR)bstr); -#else - g_free (((char *)bstr) - 4); -#endif /* HAVE_API_SUPPORT_WIN32_BSTR */ -#else -#ifndef DISABLE_COM - if (com_provider == MONO_COM_DEFAULT) { -#endif - g_free (((char *)bstr) - SIZEOF_VOID_P); -#ifndef DISABLE_COM - } else if (com_provider == MONO_COM_MS && init_com_provider_ms ()) { - sys_free_string_ms ((mono_bstr_const)bstr); - } else { - g_assert_not_reached (); - } -#endif // DISABLE_COM -#endif // HOST_WIN32 -} - -// FIXME There are multiple caches of "GetObjectForNativeVariant". -G_GNUC_UNUSED -static MonoMethod* -mono_get_Marshal_GetObjectForNativeVariant (void) -{ - MONO_STATIC_POINTER_INIT (MonoMethod, get_object_for_native_variant) - ERROR_DECL (error); - get_object_for_native_variant = mono_class_get_method_from_name_checked (mono_defaults.marshal_class, "GetObjectForNativeVariant", 1, 0, error); - mono_error_assert_ok (error); - MONO_STATIC_POINTER_INIT_END (MonoMethod, get_object_for_native_variant) - - g_assert (get_object_for_native_variant); - - return get_object_for_native_variant; -} - -// FIXME There are multiple caches of "GetNativeVariantForObject". -G_GNUC_UNUSED -static MonoMethod* -mono_get_Marshal_GetNativeVariantForObject (void) -{ - MONO_STATIC_POINTER_INIT (MonoMethod, get_native_variant_for_object) - - ERROR_DECL (error); - get_native_variant_for_object = mono_class_get_method_from_name_checked (mono_defaults.marshal_class, "GetNativeVariantForObject", 2, 0, error); - mono_error_assert_ok (error); - - MONO_STATIC_POINTER_INIT_END (MonoMethod, get_native_variant_for_object) - - g_assert (get_native_variant_for_object); - - return get_native_variant_for_object; -} - -G_GNUC_UNUSED -static MonoMethod* -mono_get_Array_SetValueImpl (void) -{ - MONO_STATIC_POINTER_INIT (MonoMethod, set_value_impl) - - ERROR_DECL (error); - set_value_impl = mono_class_get_method_from_name_checked (mono_defaults.array_class, "SetValueImpl", 2, 0, error); - mono_error_assert_ok (error); - - MONO_STATIC_POINTER_INIT_END (MonoMethod, set_value_impl) - - g_assert (set_value_impl); - - return set_value_impl; -} - -#ifndef DISABLE_COM - -// FIXME There are multiple caches of "Clear". -G_GNUC_UNUSED -static MonoMethod* -mono_get_Variant_Clear (void) -{ - MONO_STATIC_POINTER_INIT (MonoMethod, variant_clear) - ERROR_DECL (error); - variant_clear = mono_class_get_method_from_name_checked (mono_class_get_variant_class (), "Clear", 0, 0, error); - mono_error_assert_ok (error); - MONO_STATIC_POINTER_INIT_END (MonoMethod, variant_clear) - - g_assert (variant_clear); - return variant_clear; -} - -/* SAFEARRAY marshalling */ -int -mono_cominterop_emit_marshal_safearray (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, - MarshalAction action) -{ - MonoMethodBuilder *mb = m->mb; - -#ifndef DISABLE_JIT - switch (action) { - case MARSHAL_ACTION_CONV_IN: { - if ((t->attrs & (PARAM_ATTRIBUTE_IN | PARAM_ATTRIBUTE_OUT)) == PARAM_ATTRIBUTE_OUT) - break; - - /* Generates IL code for the following algorithm: - - SafeArray safearray; // safearray_var - IntPtr indices; // indices_var - int empty; // empty_var - if (mono_marshal_safearray_create (array, out safearray, out indices, out empty)) { - if (!empty) { - int index=0; // index_var - do { // label3 - variant elem = Marshal.GetNativeVariantForObject (array.GetValueImpl(index)); - mono_marshal_safearray_set_value (safearray, indices, elem); - ++index; - } - while (mono_marshal_safearray_next (safearray, indices)); - } // label2 - mono_marshal_safearray_free_indices (indices); - } // label1 - */ - - int safearray_var, indices_var, empty_var, elem_var, index_var; - guint32 label1 = 0, label2 = 0, label3 = 0; - - MonoType *int_type = mono_get_int_type (); - conv_arg = safearray_var = mono_mb_add_local (mb, mono_get_object_type ()); - indices_var = mono_mb_add_local (mb, int_type); - empty_var = mono_mb_add_local (mb, int_type); - - if (m_type_is_byref (t)) { - mono_mb_emit_ldarg (mb, argnum); - mono_mb_emit_byte (mb, CEE_LDIND_REF); - } else - mono_mb_emit_ldarg (mb, argnum); - - mono_mb_emit_ldloc_addr (mb, safearray_var); - mono_mb_emit_ldloc_addr (mb, indices_var); - mono_mb_emit_ldloc_addr (mb, empty_var); - mono_mb_emit_icall (mb, mono_marshal_safearray_create); - - label1 = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S); - - mono_mb_emit_ldloc (mb, empty_var); - - label2 = mono_mb_emit_short_branch (mb, CEE_BRTRUE_S); - - index_var = mono_mb_add_local (mb, mono_get_int32_type ()); - mono_mb_emit_byte (mb, CEE_LDC_I4_0); - mono_mb_emit_stloc (mb, index_var); - - label3 = mono_mb_get_label (mb); - - MONO_STATIC_POINTER_INIT (MonoMethod, get_value_impl) - - ERROR_DECL (error); - get_value_impl = mono_class_get_method_from_name_checked (mono_defaults.array_class, "GetValueImpl", 1, 0, error); - mono_error_assert_ok (error); - - MONO_STATIC_POINTER_INIT_END (MonoMethod, get_value_impl) - - g_assert (get_value_impl); - - if (m_type_is_byref (t)) { - mono_mb_emit_ldarg (mb, argnum); - mono_mb_emit_byte (mb, CEE_LDIND_REF); - } else - mono_mb_emit_ldarg (mb, argnum); - - mono_mb_emit_ldloc (mb, index_var); - - mono_mb_emit_managed_call (mb, get_value_impl, NULL); - - elem_var = mono_mb_add_local (mb, m_class_get_byval_arg (mono_class_get_variant_class ())); - mono_mb_emit_ldloc_addr (mb, elem_var); - - mono_mb_emit_managed_call (mb, mono_get_Marshal_GetNativeVariantForObject (), NULL); - - mono_mb_emit_ldloc (mb, safearray_var); - mono_mb_emit_ldloc (mb, indices_var); - mono_mb_emit_ldloc_addr (mb, elem_var); - mono_mb_emit_icall (mb, mono_marshal_safearray_set_value); - - mono_mb_emit_ldloc_addr (mb, elem_var); - mono_mb_emit_managed_call (mb, mono_get_Variant_Clear (), NULL); - - mono_mb_emit_add_to_local (mb, index_var, 1); - - mono_mb_emit_ldloc (mb, safearray_var); - mono_mb_emit_ldloc (mb, indices_var); - mono_mb_emit_icall (mb, mono_marshal_safearray_next); - mono_mb_emit_branch_label (mb, CEE_BRTRUE, label3); - - mono_mb_patch_short_branch (mb, label2); - - mono_mb_emit_ldloc (mb, indices_var); - mono_mb_emit_icall (mb, mono_marshal_safearray_free_indices); - - mono_mb_patch_short_branch (mb, label1); - break; - } - - case MARSHAL_ACTION_PUSH: - if (m_type_is_byref (t)) - mono_mb_emit_ldloc_addr (mb, conv_arg); - else - mono_mb_emit_ldloc (mb, conv_arg); - break; - - case MARSHAL_ACTION_CONV_OUT: { - if (t->attrs & PARAM_ATTRIBUTE_OUT) { - /* Generates IL code for the following algorithm: - - Array result; // result_var - IntPtr indices; // indices_var - int empty; // empty_var - bool byValue = !m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_IN); - if (mono_marshal_safearray_begin(safearray, out result, out indices, out empty, parameter, byValue)) { - if (!empty) { - int index=0; // index_var - do { // label3 - if (!byValue || (index < parameter.Length)) { - object elem = Variant.GetObjectForNativeVariant(mono_marshal_safearray_get_value(safearray, indices)); - result.SetValueImpl(elem, index); - } - ++index; - } - while (mono_marshal_safearray_next(safearray, indices)); - } // label2 - mono_marshal_safearray_end(safearray, indices); - } // label1 - if (!byValue) - return result; - */ - - int result_var, indices_var, empty_var, elem_var, index_var; - guint32 label1 = 0, label2 = 0, label3 = 0, label4 = 0; - gboolean byValue = !m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_IN); - - MonoType *object_type = mono_get_object_type (); - MonoType *int_type = mono_get_int_type (); - result_var = mono_mb_add_local (mb, object_type); - indices_var = mono_mb_add_local (mb, int_type); - empty_var = mono_mb_add_local (mb, int_type); - - mono_mb_emit_ldloc (mb, conv_arg); - mono_mb_emit_ldloc_addr (mb, result_var); - mono_mb_emit_ldloc_addr (mb, indices_var); - mono_mb_emit_ldloc_addr (mb, empty_var); - mono_mb_emit_ldarg (mb, argnum); - if (byValue) - mono_mb_emit_byte (mb, CEE_LDC_I4_0); - else - mono_mb_emit_byte (mb, CEE_LDC_I4_1); - mono_mb_emit_icall (mb, mono_marshal_safearray_begin); - - label1 = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S); - - mono_mb_emit_ldloc (mb, empty_var); - - label2 = mono_mb_emit_short_branch (mb, CEE_BRTRUE_S); - - index_var = mono_mb_add_local (mb, int_type); - mono_mb_emit_byte (mb, CEE_LDC_I4_0); - mono_mb_emit_stloc (mb, index_var); - - label3 = mono_mb_get_label (mb); - - if (byValue) { - mono_mb_emit_ldloc (mb, index_var); - mono_mb_emit_ldarg (mb, argnum); - mono_mb_emit_byte (mb, CEE_LDLEN); - label4 = mono_mb_emit_branch (mb, CEE_BGE); - } - - mono_mb_emit_ldloc (mb, conv_arg); - mono_mb_emit_ldloc (mb, indices_var); - mono_mb_emit_icall (mb, mono_marshal_safearray_get_value); - - elem_var = mono_mb_add_local (mb, object_type); - - mono_mb_emit_managed_call (mb, mono_get_Marshal_GetObjectForNativeVariant (), NULL); - mono_mb_emit_stloc (mb, elem_var); - - mono_mb_emit_ldloc (mb, result_var); - mono_mb_emit_ldloc (mb, elem_var); - mono_mb_emit_ldloc (mb, index_var); - mono_mb_emit_managed_call (mb, mono_get_Array_SetValueImpl (), NULL); - - if (byValue) - mono_mb_patch_short_branch (mb, label4); - - mono_mb_emit_add_to_local (mb, index_var, 1); - - mono_mb_emit_ldloc (mb, conv_arg); - mono_mb_emit_ldloc (mb, indices_var); - mono_mb_emit_icall (mb, mono_marshal_safearray_next); - mono_mb_emit_branch_label (mb, CEE_BRTRUE, label3); - - mono_mb_patch_short_branch (mb, label2); - - mono_mb_emit_ldloc (mb, conv_arg); - mono_mb_emit_ldloc (mb, indices_var); - mono_mb_emit_icall (mb, mono_marshal_safearray_end); - - mono_mb_patch_short_branch (mb, label1); - - if (!byValue) { - mono_mb_emit_ldarg (mb, argnum); - mono_mb_emit_ldloc (mb, result_var); - mono_mb_emit_byte (mb, CEE_STIND_REF); - } - } - break; - } - case MARSHAL_ACTION_MANAGED_CONV_IN: { - if ((t->attrs & (PARAM_ATTRIBUTE_IN | PARAM_ATTRIBUTE_OUT)) == PARAM_ATTRIBUTE_OUT) - break; - - /* Generates IL code for the following algorithm: - - Array result; // result_var - IntPtr indices; // indices_var - int empty; // empty_var - if (mono_marshal_safearray_begin(safearray, out result, out indices, out empty, NULL, TRUE)) { - if (!empty) { - int index=0; // index_var - do { // label3 - object elem = Variant.GetObjectForNativeVariant(mono_marshal_safearray_get_value(safearray, indices)); - result.SetValueImpl(elem, index); - ++index; - } - while (mono_marshal_safearray_next(safearray, indices)); - } // label2 - mono_marshal_safearray_free_indices(indices); - } // label1 - */ - - int result_var, indices_var, empty_var, elem_var, index_var; - guint32 label1 = 0, label2 = 0, label3 = 0; - - MonoType *object_type = mono_get_object_type (); - MonoType *int_type = mono_get_int_type (); - result_var = mono_mb_add_local (mb, object_type); - indices_var = mono_mb_add_local (mb, int_type); - empty_var = mono_mb_add_local (mb, int_type); - - mono_mb_emit_ldarg (mb, argnum); - mono_mb_emit_ldloc_addr (mb, result_var); - mono_mb_emit_ldloc_addr (mb, indices_var); - mono_mb_emit_ldloc_addr (mb, empty_var); - mono_mb_emit_byte (mb, CEE_LDC_I4_0); - mono_mb_emit_byte (mb, CEE_CONV_I); - mono_mb_emit_byte (mb, CEE_LDC_I4_1); - mono_mb_emit_icall (mb, mono_marshal_safearray_begin); - - label1 = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S); - - mono_mb_emit_ldloc (mb, empty_var); - - label2 = mono_mb_emit_short_branch (mb, CEE_BRTRUE_S); - - index_var = mono_mb_add_local (mb, int_type); - mono_mb_emit_byte (mb, CEE_LDC_I4_0); - mono_mb_emit_stloc (mb, index_var); - - label3 = mono_mb_get_label (mb); - - mono_mb_emit_ldarg (mb, argnum); - mono_mb_emit_ldloc (mb, indices_var); - mono_mb_emit_icall (mb, mono_marshal_safearray_get_value); - - elem_var = mono_mb_add_local (mb, object_type); - - mono_mb_emit_managed_call (mb, mono_get_Marshal_GetObjectForNativeVariant (), NULL); - mono_mb_emit_stloc (mb, elem_var); - - mono_mb_emit_ldloc (mb, result_var); - mono_mb_emit_ldloc (mb, elem_var); - mono_mb_emit_ldloc (mb, index_var); - mono_mb_emit_managed_call (mb, mono_get_Array_SetValueImpl (), NULL); - - mono_mb_emit_add_to_local (mb, index_var, 1); - - mono_mb_emit_ldarg (mb, argnum); - mono_mb_emit_ldloc (mb, indices_var); - mono_mb_emit_icall (mb, mono_marshal_safearray_next); - mono_mb_emit_branch_label (mb, CEE_BRTRUE, label3); - - mono_mb_patch_short_branch (mb, label2); - - mono_mb_emit_ldloc (mb, indices_var); - mono_mb_emit_icall (mb, mono_marshal_safearray_free_indices); - - mono_mb_patch_short_branch (mb, label1); - - mono_mb_emit_ldloc (mb, result_var); - mono_mb_emit_stloc (mb, conv_arg); - - break; - } - default: - g_assert_not_reached (); - } -#endif /* DISABLE_JIT */ - - return conv_arg; -} - -#ifdef HOST_WIN32 -#if HAVE_API_SUPPORT_WIN32_SAFE_ARRAY -static guint32 -mono_marshal_win_safearray_get_dim (gpointer safearray) -{ - return SafeArrayGetDim ((SAFEARRAY*)safearray); -} -#elif !HAVE_EXTERN_DEFINED_WIN32_SAFE_ARRAY -static guint32 -mono_marshal_win_safearray_get_dim (gpointer safearray) -{ - g_unsupported_api ("SafeArrayGetDim"); - SetLastError (ERROR_NOT_SUPPORTED); - return MONO_E_NOTIMPL; -} -#endif /* HAVE_API_SUPPORT_WIN32_SAFE_ARRAY */ - -static guint32 -mono_marshal_safearray_get_dim (gpointer safearray) -{ - return mono_marshal_win_safearray_get_dim (safearray); -} - -#else /* HOST_WIN32 */ - -static guint32 -mono_marshal_safearray_get_dim (gpointer safearray) -{ - guint32 result=0; - if (com_provider == MONO_COM_MS && init_com_provider_ms ()) { - result = safe_array_get_dim_ms (safearray); - } else { - g_assert_not_reached (); - } - return result; -} -#endif /* HOST_WIN32 */ - -#ifdef HOST_WIN32 -#if HAVE_API_SUPPORT_WIN32_SAFE_ARRAY -static int -mono_marshal_win_safe_array_get_lbound (gpointer psa, guint nDim, glong* plLbound) -{ - return SafeArrayGetLBound ((SAFEARRAY*)psa, nDim, plLbound); -} -#elif !HAVE_EXTERN_DEFINED_WIN32_SAFE_ARRAY -static int -mono_marshal_win_safe_array_get_lbound (gpointer psa, guint nDim, glong* plLbound) -{ - g_unsupported_api ("SafeArrayGetLBound"); - SetLastError (ERROR_NOT_SUPPORTED); - return MONO_E_NOTIMPL; -} -#endif /* HAVE_API_SUPPORT_WIN32_SAFE_ARRAY */ - -static int -mono_marshal_safe_array_get_lbound (gpointer psa, guint nDim, glong* plLbound) -{ - return mono_marshal_win_safe_array_get_lbound (psa, nDim, plLbound); -} - -#else /* HOST_WIN32 */ - -static int -mono_marshal_safe_array_get_lbound (gpointer psa, guint nDim, glong* plLbound) -{ - int result=MONO_S_OK; - if (com_provider == MONO_COM_MS && init_com_provider_ms ()) { - result = safe_array_get_lbound_ms (psa, nDim, plLbound); - } else { - g_assert_not_reached (); - } - return result; -} -#endif /* HOST_WIN32 */ - -#ifdef HOST_WIN32 -#if HAVE_API_SUPPORT_WIN32_SAFE_ARRAY -static int -mono_marshal_win_safe_array_get_ubound (gpointer psa, guint nDim, glong* plUbound) -{ - return SafeArrayGetUBound ((SAFEARRAY*)psa, nDim, plUbound); -} -#elif !HAVE_EXTERN_DEFINED_WIN32_SAFE_ARRAY -static int -mono_marshal_win_safe_array_get_ubound (gpointer psa, guint nDim, glong* plUbound) -{ - g_unsupported_api ("SafeArrayGetUBound"); - SetLastError (ERROR_NOT_SUPPORTED); - return MONO_E_NOTIMPL; -} -#endif /* HAVE_API_SUPPORT_WIN32_SAFE_ARRAY */ - -static int -mono_marshal_safe_array_get_ubound (gpointer psa, guint nDim, glong* plUbound) -{ - return mono_marshal_win_safe_array_get_ubound (psa, nDim, plUbound); -} - -#else /* HOST_WIN32 */ - -static int -mono_marshal_safe_array_get_ubound (gpointer psa, guint nDim, glong* plUbound) -{ - int result=MONO_S_OK; - if (com_provider == MONO_COM_MS && init_com_provider_ms ()) { - result = safe_array_get_ubound_ms (psa, nDim, plUbound); - } else { - g_assert_not_reached (); - } - return result; -} -#endif /* HOST_WIN32 */ - -/* This is an icall */ -static gboolean -mono_marshal_safearray_begin (gpointer safearray, MonoArray **result, gpointer *indices, gpointer empty, gpointer parameter, gboolean allocateNewArray) -{ - ERROR_DECL (error); - int dim; - uintptr_t *sizes; - intptr_t *bounds; - MonoClass *aklass; - int i; - gboolean bounded = FALSE; - -#ifndef HOST_WIN32 - // If not on windows, check that the MS provider is used as it is - // required for SAFEARRAY support. - // If SAFEARRAYs are not supported, returning FALSE from this - // function will prevent the other mono_marshal_safearray_xxx functions - // from being called. - if ((com_provider != MONO_COM_MS) || !init_com_provider_ms ()) { - return FALSE; - } -#endif - - (*(int*)empty) = TRUE; - - if (safearray != NULL) { - - dim = mono_marshal_safearray_get_dim (safearray); - - if (dim > 0) { - - *indices = g_malloc (dim * sizeof(int)); - - sizes = g_newa (uintptr_t, dim); - bounds = g_newa (intptr_t, dim); - - for (i=0; i=0; --i) - { - glong lbound, ubound; - - hr = mono_marshal_safe_array_get_ubound (safearray, i+1, &ubound); - if (hr < 0) { - cominterop_set_hr_error (error, hr); - mono_error_set_pending_exception (error); - return FALSE; - } - - if (++pIndices[i] <= ubound) { - break; - } - - hr = mono_marshal_safe_array_get_lbound (safearray, i+1, &lbound); - if (hr < 0) { - cominterop_set_hr_error (error, hr); - mono_error_set_pending_exception (error); - return FALSE; - } - - pIndices[i] = lbound; - - if (i == 0) - ret = FALSE; - } - return ret; -} - -#ifdef HOST_WIN32 -#if HAVE_API_SUPPORT_WIN32_SAFE_ARRAY -static void -mono_marshal_win_safearray_end (gpointer safearray, gpointer indices) -{ - g_free(indices); - SafeArrayDestroy ((SAFEARRAY*)safearray); -} -#elif !HAVE_EXTERN_DEFINED_WIN32_SAFE_ARRAY -static void -mono_marshal_win_safearray_end (gpointer safearray, gpointer indices) -{ - g_free(indices); - g_unsupported_api ("SafeArrayDestroy"); - SetLastError (ERROR_NOT_SUPPORTED); -} -#endif /* HAVE_API_SUPPORT_WIN32_SAFE_ARRAY */ - -static void -mono_marshal_safearray_end (gpointer safearray, gpointer indices) -{ - mono_marshal_win_safearray_end (safearray, indices); -} - -#else /* HOST_WIN32 */ - -static void -mono_marshal_safearray_end (gpointer safearray, gpointer indices) -{ - g_free(indices); - if (com_provider == MONO_COM_MS && init_com_provider_ms ()) { - safe_array_destroy_ms (safearray); - } else { - g_assert_not_reached (); - } -} -#endif /* HOST_WIN32 */ - -#ifdef HOST_WIN32 -#if HAVE_API_SUPPORT_WIN32_SAFE_ARRAY -static gboolean -mono_marshal_win_safearray_create_internal (UINT cDims, SAFEARRAYBOUND *rgsabound, gpointer *newsafearray) -{ - *newsafearray = SafeArrayCreate (VT_VARIANT, cDims, rgsabound); - return TRUE; -} -#elif !HAVE_EXTERN_DEFINED_WIN32_SAFE_ARRAY -static gboolean -mono_marshal_win_safearray_create_internal (UINT cDims, SAFEARRAYBOUND *rgsabound, gpointer *newsafearray) -{ - g_unsupported_api ("SafeArrayCreate"); - SetLastError (ERROR_NOT_SUPPORTED); - *newsafearray = NULL; - return FALSE; -} -#endif /* HAVE_API_SUPPORT_WIN32_SAFE_ARRAY */ - -static gboolean -mono_marshal_safearray_create_internal (UINT cDims, SAFEARRAYBOUND *rgsabound, gpointer *newsafearray) -{ - return mono_marshal_win_safearray_create_internal (cDims, rgsabound, newsafearray); -} - -#else /* HOST_WIN32 */ - -static gboolean -mono_marshal_safearray_create_internal (UINT cDims, SAFEARRAYBOUND *rgsabound, gpointer *newsafearray) -{ - *newsafearray = safe_array_create_ms (VT_VARIANT, cDims, rgsabound); - return TRUE; -} - -#endif /* HOST_WIN32 */ - -static gboolean -mono_marshal_safearray_create (MonoArray *input, gpointer *newsafearray, gpointer *indices, gpointer empty) -{ -#ifndef HOST_WIN32 - // If not on windows, check that the MS provider is used as it is - // required for SAFEARRAY support. - // If SAFEARRAYs are not supported, returning FALSE from this - // function will prevent the other mono_marshal_safearray_xxx functions - // from being called. - if (com_provider != MONO_COM_MS || !init_com_provider_ms ()) { - return FALSE; - } -#endif - - int const max_array_length = mono_array_length_internal (input); - int const dim = m_class_get_rank (mono_object_class (input)); - - *indices = g_malloc (dim * sizeof (int)); - SAFEARRAYBOUND * const bounds = g_newa (SAFEARRAYBOUND, dim); - (*(int*)empty) = (max_array_length == 0); - - if (dim > 1) { - for (int i = 0; i < dim; ++i) { - ((int*)*indices) [i] = bounds [i].lLbound = input->bounds [i].lower_bound; - bounds [i].cElements = input->bounds [i].length; - } - } else { - ((int*)*indices) [0] = 0; - bounds [0].cElements = max_array_length; - bounds [0].lLbound = 0; - } - - return mono_marshal_safearray_create_internal (dim, bounds, newsafearray); -} - -/* This is an icall */ -#ifdef HOST_WIN32 -#if HAVE_API_SUPPORT_WIN32_SAFE_ARRAY -static int -mono_marshal_win_safearray_set_value (gpointer safearray, gpointer indices, gpointer value) -{ - return SafeArrayPutElement ((SAFEARRAY*)safearray, (LONG*)indices, value); -} -#elif !HAVE_EXTERN_DEFINED_WIN32_SAFE_ARRAY -static int -mono_marshal_win_safearray_set_value (gpointer safearray, gpointer indices, gpointer value) -{ - ERROR_DECL (error); - g_unsupported_api ("SafeArrayPutElement"); - mono_error_set_not_supported (error, G_UNSUPPORTED_API, "SafeArrayPutElement"); - mono_error_set_pending_exception (error); - SetLastError (ERROR_NOT_SUPPORTED); - return MONO_E_NOTIMPL; -} -#endif /* HAVE_API_SUPPORT_WIN32_SAFE_ARRAY */ - -#endif /* HOST_WIN32 */ - -static void -mono_marshal_safearray_set_value (gpointer safearray, gpointer indices, gpointer value) -{ - ERROR_DECL (error); -#ifdef HOST_WIN32 - int const hr = mono_marshal_win_safearray_set_value (safearray, indices, value); -#else - int hr = 0; - if (com_provider == MONO_COM_MS && init_com_provider_ms ()) - hr = safe_array_put_element_ms (safearray, (glong *)indices, (void **)value); - else - g_assert_not_reached (); -#endif - if (hr < 0) { - cominterop_set_hr_error (error, hr); - mono_error_set_pending_exception (error); - } -} - -static -void mono_marshal_safearray_free_indices (gpointer indices) -{ - g_free (indices); -} - -#else /* DISABLE_COM */ - -gboolean -mono_marshal_free_ccw (MonoObject* object) -{ - return FALSE; -} - -#ifdef HOST_WIN32 - -int -ves_icall_System_Runtime_InteropServices_Marshal_AddRefInternal (MonoIUnknown *pUnk) -{ - return mono_IUnknown_AddRef (pUnk); -} - -int -ves_icall_System_Runtime_InteropServices_Marshal_ReleaseInternal (MonoIUnknown *pUnk) -{ - g_assert (pUnk); - return mono_IUnknown_Release (pUnk); -} - -int -ves_icall_System_Runtime_InteropServices_Marshal_QueryInterfaceInternal (MonoIUnknown *pUnk, gconstpointer riid, gpointer* ppv) -{ - return mono_IUnknown_QueryInterface (pUnk, riid, ppv); -} - -#else /* HOST_WIN32 */ - -int -ves_icall_System_Runtime_InteropServices_Marshal_AddRefInternal (MonoIUnknown *pUnk) -{ - g_assert_not_reached (); - return 0; -} - -int -ves_icall_System_Runtime_InteropServices_Marshal_ReleaseInternal (MonoIUnknown *pUnk) -{ - g_assert_not_reached (); - return 0; -} - - -int -ves_icall_System_Runtime_InteropServices_Marshal_QueryInterfaceInternal (MonoIUnknown *pUnk, gconstpointer riid, gpointer* ppv) -{ - g_assert_not_reached (); - return 0; -} - -#endif /* HOST_WIN32 */ -#endif /* DISABLE_COM */ - -mono_bstr -ves_icall_System_Runtime_InteropServices_Marshal_BufferToBSTR (const gunichar2* ptr, int len) -{ - return mono_ptr_to_bstr (ptr, len); -} - -void -ves_icall_System_Runtime_InteropServices_Marshal_FreeBSTR (mono_bstr_const ptr) +ves_icall_System_Runtime_InteropServices_Marshal_FreeBSTR (mono_bstr_const ptr) { mono_free_bstr ((gpointer)ptr); } - -void* -mono_cominterop_get_com_interface (MonoObject *object_raw, MonoClass *ic, MonoError *error) -{ - HANDLE_FUNCTION_ENTER (); - MONO_HANDLE_DCL (MonoObject, object); - void* const result = mono_cominterop_get_com_interface_internal (FALSE, object, ic, error); - HANDLE_FUNCTION_RETURN_VAL (result); -} - -static void* -mono_cominterop_get_com_interface_internal (gboolean icall, MonoObjectHandle object, MonoClass *ic, MonoError *error) -{ - // Common code for mono_cominterop_get_com_interface and - // ves_icall_System_Runtime_InteropServices_Marshal_GetIUnknownForObjectInternal, - // which are almost identical. -#ifndef DISABLE_COM - if (MONO_HANDLE_IS_NULL (object)) - return NULL; - - MonoRealProxyHandle real_proxy; - - if (cominterop_object_is_rcw_handle (object, &real_proxy)) { - MonoClass *klass = NULL; - klass = mono_handle_class (object); - if (TRUE) { - g_assertf (!icall, "Class is not transparent"); - mono_error_set_invalid_operation (error, "Class is not transparent"); - return NULL; - } - - if (MONO_HANDLE_IS_NULL (real_proxy)) { - g_assertf (!icall, "RealProxy is null"); - mono_error_set_invalid_operation (error, "RealProxy is null"); - return NULL; - } - - klass = mono_handle_class (real_proxy); - if (klass != mono_class_get_interop_proxy_class ()) { - g_assertf (!icall, "Object is not a proxy"); - mono_error_set_invalid_operation (error, "Object is not a proxy"); - return NULL; - } - - MonoComInteropProxyHandle com_interop_proxy = MONO_HANDLE_CAST (MonoComInteropProxy, real_proxy); - MonoComObjectHandle com_object = MONO_HANDLE_NEW_GET (MonoComObject, com_interop_proxy, com_object); - - if (MONO_HANDLE_IS_NULL (com_object)) { - g_assertf (!icall, "Proxy points to null COM object"); - mono_error_set_invalid_operation (error, "Proxy points to null COM object"); - return NULL; - } - - if (icall) - return MONO_HANDLE_GETVAL (com_object, iunknown); - return cominterop_get_interface_checked (com_object, ic, error); - } - else { - if (icall) - ic = mono_class_get_iunknown_class (); - return cominterop_get_ccw_checked (object, ic, error); - } -#else - g_assert_not_reached (); -#endif -} - -gboolean -mono_cominterop_is_interface (MonoClass* klass) -{ -#ifndef DISABLE_COM - ERROR_DECL (error); - MonoCustomAttrInfo* cinfo = NULL; - gboolean ret = FALSE; - int i; - - cinfo = mono_custom_attrs_from_class_checked (klass, error); - mono_error_assert_ok (error); - if (cinfo) { - for (i = 0; i < cinfo->num_attrs; ++i) { - MonoClass *ctor_class = cinfo->attrs [i].ctor->klass; - if (mono_class_has_parent (ctor_class, mono_class_get_interface_type_attribute_class ())) { - ret = TRUE; - break; - } - } - if (!cinfo->cached) - mono_custom_attrs_free (cinfo); - } - - return ret; -#else - g_assert_not_reached (); -#endif -} diff --git a/src/mono/mono/metadata/cominterop.h b/src/mono/mono/metadata/cominterop.h index 2bd129ca7d7cde..6ad9f5cbab73ee 100644 --- a/src/mono/mono/metadata/cominterop.h +++ b/src/mono/mono/metadata/cominterop.h @@ -17,41 +17,6 @@ void mono_cominterop_init (void); -void -mono_mb_emit_cominterop_get_function_pointer (MonoMethodBuilder *mb, MonoMethod* method); - -void -mono_mb_emit_cominterop_call_function_pointer (MonoMethodBuilder *mb, MonoMethodSignature *sig); - -void -mono_mb_emit_cominterop_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethod* method); - -void -mono_cominterop_emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, MonoMarshalSpec *mspec); - -void -mono_cominterop_emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, MonoMarshalSpec *mspec); - -MonoMethod * -mono_cominterop_get_native_wrapper (MonoMethod *method); - -MonoMethod * -mono_cominterop_get_invoke (MonoMethod *method); - -int -mono_cominterop_emit_marshal_com_interface (EmitMarshalContext *m, int argnum, - MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, - MarshalAction action); - -int -mono_cominterop_emit_marshal_safearray (EmitMarshalContext *m, int argnum, - MonoType *t, - MonoMarshalSpec *spec, - int conv_arg, MonoType **conv_arg_type, - MarshalAction action); - MONO_API MONO_RT_EXTERNAL_ONLY MonoString * mono_string_from_bstr (/*mono_bstr*/gpointer bstr); @@ -61,16 +26,4 @@ mono_string_from_bstr_checked (mono_bstr_const bstr, MonoError *error); MONO_API void mono_free_bstr (/*mono_bstr_const*/gpointer bstr); -MonoClass* -mono_class_try_get_com_object_class (void); - -void* -mono_cominterop_get_com_interface (MonoObject* object, MonoClass* ic, MonoError *error); - -gboolean -mono_cominterop_is_interface (MonoClass* klass); - -gboolean -mono_cominterop_method_com_visible (MonoMethod *method); - #endif /* __MONO_COMINTEROP_H__ */ diff --git a/src/mono/mono/metadata/icall-def.h b/src/mono/mono/metadata/icall-def.h index f1dbaf70c90a44..06f3ab888b729d 100644 --- a/src/mono/mono/metadata/icall-def.h +++ b/src/mono/mono/metadata/icall-def.h @@ -533,7 +533,6 @@ HANDLES(RTH_8, "GetModule", ves_icall_RuntimeTypeHandle_GetModule, void, 2, (Mon NOHANDLES(ICALL(RTH_9, "HasInstantiation", ves_icall_RuntimeTypeHandle_HasInstantiation)) HANDLES(RTH_20, "HasReferences", ves_icall_RuntimeTypeHandle_HasReferences, MonoBoolean, 1, (MonoQCallTypeHandle)) HANDLES(RTH_21, "IsByRefLike", ves_icall_RuntimeTypeHandle_IsByRefLike, MonoBoolean, 1, (MonoQCallTypeHandle)) -HANDLES(RTH_12, "IsComObject", ves_icall_RuntimeTypeHandle_IsComObject, MonoBoolean, 1, (MonoQCallTypeHandle)) NOHANDLES(ICALL(RTH_13, "IsGenericTypeDefinition", ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition)) HANDLES(RTH_15, "IsInstanceOfType", ves_icall_RuntimeTypeHandle_IsInstanceOfType, guint32, 2, (MonoQCallTypeHandle, MonoObject)) HANDLES(RTH_17a, "internal_from_name", ves_icall_System_RuntimeTypeHandle_internal_from_name, void, 5, (char_ptr, MonoStackCrawlMark_ptr, MonoObjectHandleOnStack, MonoBoolean, MonoBoolean)) diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c index 953c0230a9a728..b5e21c54dbf5be 100644 --- a/src/mono/mono/metadata/icall.c +++ b/src/mono/mono/metadata/icall.c @@ -2931,17 +2931,6 @@ ves_icall_RuntimeType_GetFunctionPointerTypeModifiers (MonoQCallTypeHandle type_ } } -MonoBoolean -ves_icall_RuntimeTypeHandle_IsComObject (MonoQCallTypeHandle type_handle, MonoError *error) -{ - MonoType *type = type_handle.type; - MonoClass *klass = mono_class_from_mono_type_internal (type); - mono_class_init_checked (klass, error); - return_val_if_nok (error, FALSE); - - return mono_class_is_com_object (klass); -} - void ves_icall_InvokeClassConstructor (MonoQCallTypeHandle type_handle, MonoError *error) { @@ -6694,72 +6683,6 @@ ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObjectHandle obj, return mono_reflection_get_custom_attrs_data_checked (obj, error); } -#ifndef DISABLE_COM - -int -ves_icall_System_Runtime_InteropServices_Marshal_GetHRForException_WinRT(MonoExceptionHandle ex, MonoError *error) -{ - mono_error_set_not_implemented (error, "System.Runtime.InteropServices.Marshal.GetHRForException_WinRT internal call is not implemented."); - return 0; -} - -MonoObjectHandle -ves_icall_System_Runtime_InteropServices_Marshal_GetNativeActivationFactory(MonoObjectHandle type, MonoError *error) -{ - mono_error_set_not_implemented (error, "System.Runtime.InteropServices.Marshal.GetNativeActivationFactory internal call is not implemented."); - return NULL_HANDLE; -} - -void* -ves_icall_System_Runtime_InteropServices_Marshal_GetRawIUnknownForComObjectNoAddRef(MonoObjectHandle obj, MonoError *error) -{ - mono_error_set_not_implemented (error, "System.Runtime.InteropServices.Marshal.GetRawIUnknownForComObjectNoAddRef internal call is not implemented."); - return NULL; -} - -MonoObjectHandle -ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_GetRestrictedErrorInfo(MonoError *error) -{ - mono_error_set_not_implemented (error, "System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.GetRestrictedErrorInfo internal call is not implemented."); - return NULL_HANDLE; -} - -MonoBoolean -ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoOriginateLanguageException (int ierr, MonoStringHandle message, void* languageException, MonoError *error) -{ - mono_error_set_not_implemented (error, "System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.RoOriginateLanguageException internal call is not implemented."); - return FALSE; -} - -void -ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoReportUnhandledError (MonoObjectHandle oerr, MonoError *error) -{ - mono_error_set_not_implemented (error, "System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.RoReportUnhandledError internal call is not implemented."); -} - -int -ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsCreateString(MonoStringHandle sourceString, int length, void** hstring, MonoError *error) -{ - mono_error_set_not_implemented (error, "System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsCreateString internal call is not implemented."); - return 0; -} - -int -ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsDeleteString(void* hstring, MonoError *error) -{ - mono_error_set_not_implemented (error, "System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsDeleteString internal call is not implemented."); - return 0; -} - -mono_unichar2* -ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsGetStringRawBuffer(void* hstring, unsigned* length, MonoError *error) -{ - mono_error_set_not_implemented (error, "System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsGetStringRawBuffer internal call is not implemented."); - return NULL; -} - -#endif - static const MonoIcallTableCallbacks *icall_table; static mono_mutex_t icall_mutex; static GHashTable *icall_hash = NULL; diff --git a/src/mono/mono/metadata/jit-icall-reg.h b/src/mono/mono/metadata/jit-icall-reg.h index 31ca69e8bab0c9..e412fdd5448dca 100644 --- a/src/mono/mono/metadata/jit-icall-reg.h +++ b/src/mono/mono/metadata/jit-icall-reg.h @@ -118,15 +118,6 @@ MONO_JIT_ICALL (__emul_rconv_to_ovf_u8) \ MONO_JIT_ICALL (__emul_rconv_to_u4) \ MONO_JIT_ICALL (__emul_rconv_to_u8) \ MONO_JIT_ICALL (__emul_rrem) \ -MONO_JIT_ICALL (cominterop_get_ccw) \ -MONO_JIT_ICALL (cominterop_get_ccw_object) \ -MONO_JIT_ICALL (cominterop_get_function_pointer) \ -MONO_JIT_ICALL (cominterop_get_interface) \ -MONO_JIT_ICALL (cominterop_get_method_interface) \ -MONO_JIT_ICALL (cominterop_object_is_rcw) \ -MONO_JIT_ICALL (cominterop_restore_domain) \ -MONO_JIT_ICALL (cominterop_set_ccw_object_domain) \ -MONO_JIT_ICALL (cominterop_type_from_handle) \ MONO_JIT_ICALL (g_free) \ MONO_JIT_ICALL (interp_to_native_trampoline) \ MONO_JIT_ICALL (mini_llvm_init_method) \ @@ -242,13 +233,6 @@ MONO_JIT_ICALL (mono_marshal_free_array) \ MONO_JIT_ICALL (mono_marshal_free_asany) \ MONO_JIT_ICALL (mono_marshal_get_type_object) \ MONO_JIT_ICALL (mono_marshal_isinst_with_cache) \ -MONO_JIT_ICALL (mono_marshal_safearray_begin) \ -MONO_JIT_ICALL (mono_marshal_safearray_create) \ -MONO_JIT_ICALL (mono_marshal_safearray_end) \ -MONO_JIT_ICALL (mono_marshal_safearray_free_indices) \ -MONO_JIT_ICALL (mono_marshal_safearray_get_value) \ -MONO_JIT_ICALL (mono_marshal_safearray_next) \ -MONO_JIT_ICALL (mono_marshal_safearray_set_value) \ MONO_JIT_ICALL (mono_marshal_set_domain_by_id) \ MONO_JIT_ICALL (mono_marshal_set_last_error) \ MONO_JIT_ICALL (mono_marshal_set_last_error_windows) \ diff --git a/src/mono/mono/metadata/marshal-lightweight.c b/src/mono/mono/metadata/marshal-lightweight.c index 80a4a000f14c04..3418a37cc1fbe0 100644 --- a/src/mono/mono/metadata/marshal-lightweight.c +++ b/src/mono/mono/metadata/marshal-lightweight.c @@ -89,23 +89,6 @@ mono_mb_strdup (MonoMethodBuilder *mb, const char *s) return res; } -#ifndef DISABLE_COM - -// FIXME There are multiple caches of "Clear". -G_GNUC_UNUSED -static MonoMethod* -mono_get_Variant_Clear (void) -{ - MONO_STATIC_POINTER_INIT (MonoMethod, variant_clear) - variant_clear = mono_marshal_shared_get_method_nofail (mono_class_get_variant_class (), "Clear", 0, 0); - MONO_STATIC_POINTER_INIT_END (MonoMethod, variant_clear) - - g_assert (variant_clear); - return variant_clear; -} - -#endif - // FIXME There are multiple caches of "GetObjectForNativeVariant". G_GNUC_UNUSED static MonoMethod* @@ -602,9 +585,6 @@ typedef struct EmitGCSafeTransitionBuilder { MonoMethodBuilder *mb; gboolean func_param; int coop_gc_var; -#ifndef DISABLE_COM - int coop_cominterop_fnptr; -#endif } GCSafeTransitionBuilder; static gboolean @@ -613,9 +593,6 @@ gc_safe_transition_builder_init (GCSafeTransitionBuilder *builder, MonoMethodBui builder->mb = mb; builder->func_param = func_param; builder->coop_gc_var = -1; -#ifndef DISABLE_COM - builder->coop_cominterop_fnptr = -1; -#endif #if defined (TARGET_WASM) #ifndef DISABLE_THREADS return TRUE; @@ -637,11 +614,6 @@ gc_safe_transition_builder_add_locals (GCSafeTransitionBuilder *builder) MonoType *int_type = mono_get_int_type(); /* local 4, the local to be used when calling the suspend funcs */ builder->coop_gc_var = mono_mb_add_local (builder->mb, int_type); -#ifndef DISABLE_COM - if (!builder->func_param && MONO_CLASS_IS_IMPORT (builder->mb->method->klass)) { - builder->coop_cominterop_fnptr = mono_mb_add_local (builder->mb, int_type); - } -#endif } /** @@ -661,13 +633,6 @@ gc_safe_transition_builder_emit_enter (GCSafeTransitionBuilder *builder, MonoMet mono_mb_emit_byte (builder->mb, CEE_POP); // Result not needed yet } -#ifndef DISABLE_COM - if (!builder->func_param && MONO_CLASS_IS_IMPORT (builder->mb->method->klass)) { - mono_mb_emit_cominterop_get_function_pointer (builder->mb, method); - mono_mb_emit_stloc (builder->mb, builder->coop_cominterop_fnptr); - } -#endif - mono_mb_emit_byte (builder->mb, MONO_CUSTOM_PREFIX); mono_mb_emit_byte (builder->mb, CEE_MONO_GET_SP); mono_mb_emit_icall (builder->mb, mono_threads_enter_gc_safe_region_unbalanced); @@ -693,9 +658,6 @@ gc_safe_transition_builder_cleanup (GCSafeTransitionBuilder *builder) { builder->mb = NULL; builder->coop_gc_var = -1; -#ifndef DISABLE_COM - builder->coop_cominterop_fnptr = -1; -#endif } typedef struct EmitGCUnsafeTransitionBuilder { @@ -998,16 +960,7 @@ emit_native_wrapper_ilgen (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSi } mono_mb_emit_calli (mb, csig); } else if (MONO_CLASS_IS_IMPORT (mb->method->klass)) { -#ifndef DISABLE_COM - mono_mb_emit_ldloc (mb, gc_safe_transition_builder.coop_cominterop_fnptr); - if (piinfo->piflags & PINVOKE_ATTRIBUTE_SUPPORTS_LAST_ERROR) { - mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); - mono_mb_emit_byte (mb, CEE_MONO_SAVE_LAST_ERROR); - } - mono_mb_emit_cominterop_call_function_pointer (mb, csig); -#else - g_assert_not_reached (); -#endif + g_assert_not_reached(); } else { if (func_addr_local != -1) { mono_mb_emit_ldloc (mb, func_addr_local); diff --git a/src/mono/mono/metadata/marshal-shared.c b/src/mono/mono/metadata/marshal-shared.c index fd7f216e2b5cca..508b823d6324fe 100644 --- a/src/mono/mono/metadata/marshal-shared.c +++ b/src/mono/mono/metadata/marshal-shared.c @@ -705,14 +705,6 @@ mono_marshal_shared_emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *ty break; } -#ifndef DISABLE_COM - case MONO_MARSHAL_CONV_OBJECT_INTERFACE: - case MONO_MARSHAL_CONV_OBJECT_IUNKNOWN: - case MONO_MARSHAL_CONV_OBJECT_IDISPATCH: - mono_cominterop_emit_ptr_to_object_conv (mb, type, conv, mspec); - break; -#endif /* DISABLE_COM */ - case MONO_MARSHAL_CONV_SAFEHANDLE: { /* * Passing SafeHandles as ref does not allow the unmanaged code @@ -912,26 +904,8 @@ mono_marshal_shared_emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *kla break; } case MONO_TYPE_OBJECT: { -#ifndef DISABLE_COM - if (to_object) { - mono_mb_emit_ldloc (mb, 1); - mono_mb_emit_ldloc (mb, 0); - mono_mb_emit_managed_call (mb, mono_get_Marshal_GetObjectForNativeVariant (), NULL); - mono_mb_emit_byte (mb, CEE_STIND_REF); - - mono_mb_emit_ldloc (mb, 0); - mono_mb_emit_managed_call (mb, mono_get_Variant_Clear (), NULL); - } - else { - mono_mb_emit_ldloc (mb, 0); - mono_mb_emit_byte(mb, CEE_LDIND_REF); - mono_mb_emit_ldloc (mb, 1); - mono_mb_emit_managed_call (mb, mono_get_Marshal_GetNativeVariantForObject (), NULL); - } -#else char *msg = g_strdup_printf ("COM support was disabled at compilation time."); mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg); -#endif break; } @@ -1225,14 +1199,6 @@ mono_marshal_shared_emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *ty break; } -#ifndef DISABLE_COM - case MONO_MARSHAL_CONV_OBJECT_INTERFACE: - case MONO_MARSHAL_CONV_OBJECT_IDISPATCH: - case MONO_MARSHAL_CONV_OBJECT_IUNKNOWN: - mono_cominterop_emit_object_to_ptr_conv (mb, type, conv, mspec); - break; -#endif /* DISABLE_COM */ - case MONO_MARSHAL_CONV_SAFEHANDLE: { mono_mb_emit_ldloc (mb, 0); mono_mb_emit_byte (mb, CEE_LDIND_I); diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index 8d68b450556f27..7fb70fa8c8d9de 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -690,72 +690,12 @@ mono_array_to_lparray_impl (MonoArrayHandle array_handle, MonoError *error) return NULL; MonoArray *array = MONO_HANDLE_RAW (array_handle); // FIXMEcoop - -#ifndef DISABLE_COM - gpointer *nativeArray = NULL; - int nativeArraySize = 0; - int i = 0; - MonoClass *klass = array->obj.vtable->klass; - MonoClass *klass_element_class = m_class_get_element_class (klass); - - switch (m_class_get_byval_arg (klass_element_class)->type) { - case MONO_TYPE_VOID: - g_assert_not_reached (); - break; - case MONO_TYPE_CLASS: - nativeArraySize = array->max_length; - nativeArray = g_new (gpointer, nativeArraySize); - for (i = 0; i < nativeArraySize; ++i) { - nativeArray [i] = mono_cominterop_get_com_interface (((MonoObject **)array->vector)[i], klass_element_class, error); - if (!is_ok (error)) { - // FIXME? Returns uninitialized. - break; - } - } - return nativeArray; - case MONO_TYPE_U1: - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_I1: - case MONO_TYPE_U2: - case MONO_TYPE_CHAR: - case MONO_TYPE_I2: - case MONO_TYPE_I: - case MONO_TYPE_U: - case MONO_TYPE_I4: - case MONO_TYPE_U4: - case MONO_TYPE_U8: - case MONO_TYPE_I8: - case MONO_TYPE_R4: - case MONO_TYPE_R8: - case MONO_TYPE_VALUETYPE: - case MONO_TYPE_PTR: - /* nothing to do */ - break; - case MONO_TYPE_GENERICINST: - case MONO_TYPE_OBJECT: - case MONO_TYPE_ARRAY: - case MONO_TYPE_SZARRAY: - case MONO_TYPE_STRING: - default: - g_warning ("type 0x%x not handled", m_class_get_byval_arg (klass_element_class)->type); - g_assert_not_reached (); - } -#endif return array->vector; } void mono_free_lparray_impl (MonoArrayHandle array, gpointer* nativeArray, MonoError *error) { -#ifndef DISABLE_COM - if (!nativeArray || MONO_HANDLE_IS_NULL (array)) - return; - - MonoClass * const klass = mono_handle_class (array); - - if (m_class_get_byval_arg (m_class_get_element_class (klass))->type == MONO_TYPE_CLASS) - g_free (nativeArray); -#endif } /* This is a JIT icall, it sets the pending exception (in wrapper) and returns on error */ @@ -3474,11 +3414,8 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions, /* The COM code is not AOT compatible, it calls mono_custom_attrs_get_attr_checked () */ if (aot) return method; -#ifndef DISABLE_COM - return mono_cominterop_get_native_wrapper (method); -#else + g_assert_not_reached (); -#endif } sig = mono_method_signature_internal (method); diff --git a/src/mono/mono/metadata/marshal.h b/src/mono/mono/metadata/marshal.h index eaef14bf7bdcf1..79bf8bd5e78577 100644 --- a/src/mono/mono/metadata/marshal.h +++ b/src/mono/mono/metadata/marshal.h @@ -708,18 +708,6 @@ ICALL_EXPORT void ves_icall_System_Runtime_InteropServices_Marshal_FreeBSTR (mono_bstr_const ptr); -ICALL_EXPORT -int -ves_icall_System_Runtime_InteropServices_Marshal_AddRefInternal (MonoIUnknown *pUnk); - -ICALL_EXPORT -int -ves_icall_System_Runtime_InteropServices_Marshal_QueryInterfaceInternal (MonoIUnknown *pUnk, gconstpointer riid, gpointer* ppv); - -ICALL_EXPORT -int -ves_icall_System_Runtime_InteropServices_Marshal_ReleaseInternal (MonoIUnknown *pUnk); - void mono_marshal_find_nonzero_bit_offset (guint8 *buf, int len, int *byte_offset, guint8 *bitmask); diff --git a/src/mono/mono/metadata/metadata.c b/src/mono/mono/metadata/metadata.c index 9b64083fdfd794..ba16a2739aae28 100644 --- a/src/mono/mono/metadata/metadata.c +++ b/src/mono/mono/metadata/metadata.c @@ -7053,12 +7053,6 @@ mono_type_to_unmanaged (MonoType *type, MonoMarshalSpec *mspec, gboolean as_fiel *conv = MONO_MARSHAL_CONV_SAFEHANDLE; return MONO_NATIVE_INT; } -#ifndef DISABLE_COM - if (t == MONO_TYPE_CLASS && mono_cominterop_is_interface (type->data.klass)){ - *conv = MONO_MARSHAL_CONV_OBJECT_INTERFACE; - return MONO_NATIVE_INTERFACE; - } -#endif *conv = MONO_MARSHAL_CONV_OBJECT_STRUCT; return MONO_NATIVE_STRUCT; } @@ -7981,235 +7975,6 @@ mono_type_set_amods (MonoType *t, MonoAggregateModContainer *amods) t_full->mods.amods = amods; } -#ifndef DISABLE_COM -static void -mono_signature_append_class_name (GString *res, MonoClass *klass) -{ - if (!klass) { - g_string_append (res, ""); - return; - } - if (m_class_get_nested_in (klass)) { - mono_signature_append_class_name (res, m_class_get_nested_in (klass)); - g_string_append_c (res, '+'); - } - else if (*m_class_get_name_space (klass)) { - g_string_append (res, m_class_get_name_space (klass)); - g_string_append_c (res, '.'); - } - g_string_append (res, m_class_get_name (klass)); -} - -static void -mono_guid_signature_append_method (GString *res, MonoMethodSignature *sig); - -static void -mono_guid_signature_append_type (GString *res, MonoType *type) -{ - int i; - switch (type->type) { - case MONO_TYPE_VOID: - g_string_append (res, "void"); break; - case MONO_TYPE_BOOLEAN: - g_string_append (res, "bool"); break; - case MONO_TYPE_CHAR: - g_string_append (res, "wchar"); break; - case MONO_TYPE_I1: - g_string_append (res, "int8"); break; - case MONO_TYPE_U1: - g_string_append (res, "unsigned int8"); break; - case MONO_TYPE_I2: - g_string_append (res, "int16"); break; - case MONO_TYPE_U2: - g_string_append (res, "unsigned int16"); break; - case MONO_TYPE_I4: - g_string_append (res, "int32"); break; - case MONO_TYPE_U4: - g_string_append (res, "unsigned int32"); break; - case MONO_TYPE_I8: - g_string_append (res, "int64"); break; - case MONO_TYPE_U8: - g_string_append (res, "unsigned int64"); break; - case MONO_TYPE_R4: - g_string_append (res, "float32"); break; - case MONO_TYPE_R8: - g_string_append (res, "float64"); break; - case MONO_TYPE_U: - g_string_append (res, "unsigned int"); break; - case MONO_TYPE_I: - g_string_append (res, "int"); break; - case MONO_TYPE_OBJECT: - g_string_append (res, "class System.Object"); break; - case MONO_TYPE_STRING: - g_string_append (res, "class System.String"); break; - case MONO_TYPE_TYPEDBYREF: - g_string_append (res, "refany"); - break; - case MONO_TYPE_VALUETYPE: - g_string_append (res, "value class "); - mono_signature_append_class_name (res, type->data.klass); - break; - case MONO_TYPE_CLASS: - g_string_append (res, "class "); - mono_signature_append_class_name (res, type->data.klass); - break; - case MONO_TYPE_SZARRAY: - mono_guid_signature_append_type (res, m_class_get_byval_arg (type->data.klass)); - g_string_append (res, "[]"); - break; - case MONO_TYPE_ARRAY: - mono_guid_signature_append_type (res, m_class_get_byval_arg (type->data.array->eklass)); - g_string_append_c (res, '['); - if (type->data.array->rank == 0) g_string_append (res, "??"); - for (i = 0; i < type->data.array->rank; ++i) - { - if (i > 0) g_string_append_c (res, ','); - if (type->data.array->sizes[i] == 0 || type->data.array->lobounds[i] == 0) continue; - g_string_append_printf (res, "%d", type->data.array->lobounds[i]); - g_string_append (res, "..."); - g_string_append_printf (res, "%d", type->data.array->lobounds[i] + type->data.array->sizes[i] + 1); - } - g_string_append_c (res, ']'); - break; - case MONO_TYPE_MVAR: - case MONO_TYPE_VAR: - if (type->data.generic_param) - g_string_append_printf (res, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", mono_generic_param_num (type->data.generic_param)); - else - g_string_append (res, ""); - break; - case MONO_TYPE_GENERICINST: { - MonoGenericContext *context; - mono_guid_signature_append_type (res, m_class_get_byval_arg (type->data.generic_class->container_class)); - g_string_append (res, "<"); - context = &type->data.generic_class->context; - if (context->class_inst) { - for (i = 0; i < context->class_inst->type_argc; ++i) { - if (i > 0) - g_string_append (res, ","); - mono_guid_signature_append_type (res, context->class_inst->type_argv [i]); - } - } - else if (context->method_inst) { - for (i = 0; i < context->method_inst->type_argc; ++i) { - if (i > 0) - g_string_append (res, ","); - mono_guid_signature_append_type (res, context->method_inst->type_argv [i]); - } - } - g_string_append (res, ">"); - break; - } - case MONO_TYPE_FNPTR: - g_string_append (res, "fnptr "); - mono_guid_signature_append_method (res, type->data.method); - break; - case MONO_TYPE_PTR: - mono_guid_signature_append_type (res, type->data.type); - g_string_append_c (res, '*'); - break; - default: - break; - } - if (m_type_is_byref (type)) g_string_append_c (res, '&'); -} - -static void -mono_guid_signature_append_method (GString *res, MonoMethodSignature *sig) -{ - int i, j; - - if (mono_signature_is_instance (sig)) g_string_append (res, "instance "); - if (sig->generic_param_count) g_string_append (res, "generic "); - - switch (mono_signature_get_call_conv (sig)) - { - case MONO_CALL_DEFAULT: break; - case MONO_CALL_C: g_string_append (res, "unmanaged cdecl "); break; - case MONO_CALL_STDCALL: g_string_append (res, "unmanaged stdcall "); break; - case MONO_CALL_THISCALL: g_string_append (res, "unmanaged thiscall "); break; - case MONO_CALL_FASTCALL: g_string_append (res, "unmanaged fastcall "); break; - case MONO_CALL_VARARG: g_string_append (res, "vararg "); break; - default: break; - } - - mono_guid_signature_append_type (res, mono_signature_get_return_type_internal(sig)); - - g_string_append_c (res, '('); - for (i = 0, j = 0; i < sig->param_count && j < sig->param_count; ++i, ++j) { - if (i > 0) g_string_append_c (res, ','); - if (sig->params [j]->attrs & PARAM_ATTRIBUTE_IN) - { - /*.NET runtime "incorrectly" shifts the parameter signatures too...*/ - g_string_append (res, "required_modifier System.Runtime.InteropServices.InAttribute"); - if (++i == sig->param_count) break; - g_string_append_c (res, ','); - } - mono_guid_signature_append_type (res, sig->params [j]); - } - g_string_append_c (res, ')'); -} - -static void -mono_generate_v3_guid_for_interface (MonoClass* klass, guint8* guid) -{ - /* COM+ Runtime GUID {69f9cbc9-da05-11d1-9408-0000f8083460} */ - static const guchar guid_name_space[] = {0x69,0xf9,0xcb,0xc9,0xda,0x05,0x11,0xd1,0x94,0x08,0x00,0x00,0xf8,0x08,0x34,0x60}; - - MonoMD5Context ctx; - MonoMethod *method; - gpointer iter = NULL; - guchar byte; - glong items_read, items_written; - int i; - - mono_md5_init (&ctx); - mono_md5_update (&ctx, guid_name_space, sizeof(guid_name_space)); - - GString *name = g_string_new (""); - mono_signature_append_class_name (name, klass); - gunichar2 *unicode_name = g_utf8_to_utf16 (name->str, name->len, &items_read, &items_written, NULL); - mono_md5_update (&ctx, (guchar *)unicode_name, items_written * sizeof(gunichar2)); - - g_free (unicode_name); - g_string_free (name, TRUE); - - while ((method = mono_class_get_methods(klass, &iter)) != NULL) - { - ERROR_DECL (error); - if (!mono_cominterop_method_com_visible(method)) continue; - - MonoMethodSignature *sig = mono_method_signature_checked (method, error); - mono_error_assert_ok (error); /*FIXME proper error handling*/ - - GString *res = g_string_new (""); - mono_guid_signature_append_method (res, sig); - mono_md5_update (&ctx, (guchar *)res->str, res->len); - g_string_free (res, TRUE); - - for (i = 0; i < sig->param_count; ++i) { - byte = sig->params [i]->attrs; - mono_md5_update (&ctx, &byte, 1); - } - } - - byte = 0; - if (mono_md5_ctx_byte_length (&ctx) & 1) - mono_md5_update (&ctx, &byte, 1); - mono_md5_final (&ctx, (guchar *)guid); - - guid[6] &= 0x0f; - guid[6] |= 0x30; /* v3 (md5) */ - - guid[8] &= 0x3F; - guid[8] |= 0x80; - - *(guint32 *)(guid + 0) = GUINT32_FROM_BE(*(guint32 *)(guid + 0)); - *(guint16 *)(guid + 4) = GUINT16_FROM_BE(*(guint16 *)(guid + 4)); - *(guint16 *)(guid + 6) = GUINT16_FROM_BE(*(guint16 *)(guid + 6)); -} -#endif - static gint mono_unichar_xdigit_value (gunichar c) { @@ -8258,12 +8023,6 @@ mono_metadata_get_class_guid (MonoClass* klass, guint8* guid, MonoError *error) memset(guid, 0, 16); if (attr) mono_string_to_guid (attr->guid, guid); -#ifndef DISABLE_COM - else if (mono_class_is_interface (klass)) - mono_generate_v3_guid_for_interface (klass, guid); - else - g_warning ("Generated GUIDs only implemented for interfaces!"); -#endif } uint32_t diff --git a/src/mono/mono/metadata/object.c b/src/mono/mono/metadata/object.c index e39bece1f9e508..37638c06388444 100644 --- a/src/mono/mono/metadata/object.c +++ b/src/mono/mono/metadata/object.c @@ -5217,10 +5217,6 @@ mono_runtime_try_invoke_byrefs (MonoMethod *method, void *obj, gpointer *params_ return res; } -// FIXME these will move to header soon -static MonoObjectHandle -mono_object_new_by_vtable (MonoVTable *vtable, MonoError *error); - /** * object_new_common_tail: * @@ -5357,7 +5353,7 @@ mono_object_new_handle (MonoClass *klass, MonoError *error) return_val_if_nok (error, MONO_HANDLE_NEW (MonoObject, NULL)); - return mono_object_new_by_vtable (vtable, error); + return mono_object_new_alloc_by_vtable (vtable, error); } /** @@ -5418,91 +5414,11 @@ mono_object_new_specific_checked (MonoVTable *vtable, MonoError *error) { MONO_REQ_GC_UNSAFE_MODE; - MonoObject *o; - error_init (error); - /* check for is_com_object for COM Interop */ - if (mono_class_is_com_object (vtable->klass)) { - gpointer pa [1]; - MonoMethod *im = create_proxy_for_type_method; - - if (im == NULL) { - MonoClass *klass = mono_class_get_activation_services_class (); - - if (!m_class_is_inited (klass)) - mono_class_init_internal (klass); - - im = mono_class_get_method_from_name_checked (klass, "CreateProxyForType", 1, 0, error); - return_val_if_nok (error, NULL); - if (!im) { - mono_error_set_not_supported (error, "Linked away."); - return NULL; - } - create_proxy_for_type_method = im; - } - - pa [0] = mono_type_get_object_checked (m_class_get_byval_arg (vtable->klass), error); - if (!is_ok (error)) - return NULL; - - o = mono_runtime_invoke_checked (im, NULL, pa, error); - if (!is_ok (error)) - return NULL; - - if (o != NULL) - return o; - } - return mono_object_new_alloc_specific_checked (vtable, error); } -static MonoObjectHandle -mono_object_new_by_vtable (MonoVTable *vtable, MonoError *error) -{ - // This function handles remoting and COM. - // mono_object_new_alloc_by_vtable does not. - - MONO_REQ_GC_UNSAFE_MODE; - - MonoObjectHandle o = MONO_HANDLE_NEW (MonoObject, NULL); - - error_init (error); - - /* check for is_com_object for COM Interop */ - if (mono_class_is_com_object (vtable->klass)) { - MonoMethod *im = create_proxy_for_type_method; - - if (im == NULL) { - MonoClass *klass = mono_class_get_activation_services_class (); - - if (!m_class_is_inited (klass)) - mono_class_init_internal (klass); - - im = mono_class_get_method_from_name_checked (klass, "CreateProxyForType", 1, 0, error); - return_val_if_nok (error, mono_new_null ()); - if (!im) { - mono_error_set_not_supported (error, "Linked away."); - return MONO_HANDLE_NEW (MonoObject, NULL); - } - create_proxy_for_type_method = im; - } - - // FIXMEcoop - gpointer pa[ ] = { mono_type_get_object_checked (m_class_get_byval_arg (vtable->klass), error) }; - return_val_if_nok (error, MONO_HANDLE_NEW (MonoObject, NULL)); - - // FIXMEcoop - o = MONO_HANDLE_NEW (MonoObject, mono_runtime_invoke_checked (im, NULL, pa, error)); - return_val_if_nok (error, MONO_HANDLE_NEW (MonoObject, NULL)); - - if (!MONO_HANDLE_IS_NULL (o)) - return o; - } - - return mono_object_new_alloc_by_vtable (vtable, error); -} - MonoObject * ves_icall_object_new_specific (MonoVTable *vtable) { From 6cc9ab459d20c2658251e752884ecc299227b27f Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 31 Jan 2024 13:11:56 -0800 Subject: [PATCH 02/12] Merge bstr support into marshal.c, delete cominterop.h/c, remove remaining cominterop references in mono runtime. --- src/mono/mono/metadata/CMakeLists.txt | 2 - src/mono/mono/metadata/cominterop.c | 221 ------------------ src/mono/mono/metadata/cominterop.h | 29 --- src/mono/mono/metadata/gc.c | 11 - src/mono/mono/metadata/icall-table.h | 1 - src/mono/mono/metadata/loader-internals.h | 2 - src/mono/mono/metadata/marshal-lightweight.c | 1 - src/mono/mono/metadata/marshal.c | 155 +++++++++++- src/mono/mono/metadata/marshal.h | 31 +-- src/mono/mono/metadata/metadata.c | 1 - src/mono/mono/metadata/object-internals.h | 8 - src/mono/mono/metadata/object-offsets.h | 2 - src/mono/mono/metadata/object.c | 1 - src/mono/mono/metadata/wrapper-types.h | 2 - src/mono/mono/mini/aot-compiler.c | 3 - src/mono/mono/mini/method-to-ir.c | 2 - .../mono/tools/offsets-tool/offsets-tool.py | 1 - 17 files changed, 149 insertions(+), 324 deletions(-) delete mode 100644 src/mono/mono/metadata/cominterop.c delete mode 100644 src/mono/mono/metadata/cominterop.h diff --git a/src/mono/mono/metadata/CMakeLists.txt b/src/mono/mono/metadata/CMakeLists.txt index a98f21069427ab..773381d6c1c9ad 100644 --- a/src/mono/mono/metadata/CMakeLists.txt +++ b/src/mono/mono/metadata/CMakeLists.txt @@ -61,8 +61,6 @@ set(metadata_common_sources class-private-definition.h class-accessors.c class-setup-vtable.c - cominterop.c - cominterop.h components.h components.c debug-helpers.c diff --git a/src/mono/mono/metadata/cominterop.c b/src/mono/mono/metadata/cominterop.c deleted file mode 100644 index 86db9edad4231f..00000000000000 --- a/src/mono/mono/metadata/cominterop.c +++ /dev/null @@ -1,221 +0,0 @@ -/** - * \file - * COM Interop Support - * - * - * (C) 2002 Ximian, Inc. http://www.ximian.com - * - */ - -#include "config.h" -#include -#ifdef HAVE_ALLOCA_H -#include -#endif - -#include -#include -#include "cil-coff.h" -#include "metadata/abi-details.h" -#include "metadata/cominterop.h" -#include "metadata/marshal.h" -#include "metadata/method-builder.h" -#include "metadata/tabledefs.h" -#include -#include -#include "metadata/reflection-internals.h" -#include "mono/metadata/class-init.h" -#include "mono/metadata/class-internals.h" -#include "mono/metadata/debug-helpers.h" -#include "mono/metadata/threads.h" -#include "mono/metadata/monitor.h" -#include "mono/metadata/metadata-internals.h" -#include "mono/metadata/method-builder-ilgen-internals.h" -#include "mono/metadata/domain-internals.h" -#include "mono/metadata/gc-internals.h" -#include "mono/metadata/threads-types.h" -#include "mono/metadata/string-icalls.h" -#include "mono/metadata/attrdefs.h" -#include "mono/utils/atomic.h" -#include "mono/utils/mono-error.h" -#include "mono/utils/mono-error-internals.h" -#include -#include -#include -#if defined (HOST_WIN32) -MONO_PRAGMA_WARNING_PUSH() -MONO_PRAGMA_WARNING_DISABLE (4115) // warning C4115: 'IRpcStubBuffer': named type definition in parentheses -#include -MONO_PRAGMA_WARNING_POP() -#include -#endif -#include "icall-decl.h" -#include "icall-signatures.h" - -// func is an identifier, that names a function, and is also in jit-icall-reg.h, -// and therefore a field in mono_jit_icall_info and can be token pasted into an enum value. -// -// The name of func must be linkable for AOT, for example g_free does not work (monoeg_g_free instead), -// nor does the C++ overload fmod (mono_fmod instead). These functions therefore -// must be extern "C". -#ifndef DISABLE_JIT -#define register_icall(func, sig, no_wrapper) \ - (mono_register_jit_icall_info (&mono_get_jit_icall_info ()->func, (gconstpointer)func, #func, (sig), (no_wrapper), #func)) -#else -/* No need for the name/C symbol */ -#define register_icall(func, sig, no_wrapper) \ - (mono_register_jit_icall_info (&mono_get_jit_icall_info ()->func, (gconstpointer)func, NULL, (sig), (no_wrapper), NULL)) -#endif - -mono_bstr -mono_string_to_bstr_impl (MonoStringHandle s, MonoError *error) -{ - if (MONO_HANDLE_IS_NULL (s)) - return NULL; - - MonoGCHandle gchandle = NULL; - mono_bstr const res = mono_ptr_to_bstr (mono_string_handle_pin_chars (s, &gchandle), mono_string_handle_length (s)); - mono_gchandle_free_internal (gchandle); - return res; -} - -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_icall_sig_ptr_obj, FALSE); - register_icall (mono_string_from_bstr_icall, mono_icall_sig_obj_ptr, FALSE); - register_icall (mono_free_bstr, mono_icall_sig_void_ptr, FALSE); -} - -// This function is used regardless of the BSTR type, so cast the return value -// Inputted string length, in bytes, should include the null terminator -// Returns the start of the string itself -static gpointer -mono_bstr_alloc (size_t str_byte_len) -{ - // Allocate string length plus pointer-size integer to store the length, aligned to 16 bytes - size_t alloc_size = str_byte_len + SIZEOF_VOID_P; - alloc_size += (16 - 1); - alloc_size &= ~(16 - 1); - gpointer ret = g_malloc0 (alloc_size); - return ret ? (char *)ret + SIZEOF_VOID_P : NULL; -} - -static void -mono_bstr_set_length (gunichar2 *bstr, int slen) -{ - *((guint32 *)bstr - 1) = slen * sizeof (gunichar2); -} - -static mono_bstr -default_ptr_to_bstr (const gunichar2* ptr, int slen) -{ - // In Mono, historically BSTR was allocated with a guaranteed size prefix of 4 bytes regardless of platform. - // Presumably this is due to the BStr documentation page, which indicates that behavior and then directs you to call - // SysAllocString on Windows to handle the allocation for you. Unfortunately, this is not actually how it works: - // The allocation pre-string is pointer-sized, and then only 4 bytes are used for the length regardless. Additionally, - // the total length is also aligned to a 16-byte boundary. This preserves the old behavior on legacy and fixes it for - // netcore moving forward. - mono_bstr const s = (mono_bstr)mono_bstr_alloc ((slen + 1) * sizeof (gunichar2)); - if (s == NULL) - return NULL; - - mono_bstr_set_length (s, slen); - if (ptr) - memcpy (s, ptr, slen * sizeof (gunichar2)); - s [slen] = 0; - return s; -} - -/* PTR can be NULL */ -mono_bstr -mono_ptr_to_bstr (const gunichar2* ptr, int slen) -{ -#if HAVE_API_SUPPORT_WIN32_BSTR - return SysAllocStringLen (ptr, slen); -#else - return default_ptr_to_bstr (ptr, slen); -#endif // HAVE_API_SUPPORT_WIN32_BSTR -} - -char * -mono_ptr_to_ansibstr (const char *ptr, size_t slen) -{ - char *s = (char *)mono_bstr_alloc ((slen + 1) * sizeof(char)); - if (s == NULL) - return NULL; - *((guint32 *)s - 1) = (guint32)(slen * sizeof (char)); - if (ptr) - memcpy (s, ptr, slen * sizeof (char)); - s [slen] = 0; - return s; -} - -MonoStringHandle -mono_string_from_bstr_checked (mono_bstr_const bstr, MonoError *error) -{ - if (!bstr) - return NULL_HANDLE_STRING; -#if HAVE_API_SUPPORT_WIN32_BSTR - return mono_string_new_utf16_handle (bstr, SysStringLen ((BSTR)bstr), error); -#else - return mono_string_new_utf16_handle (bstr, *((guint32 *)bstr - 1) / sizeof (gunichar2), error); -#endif // HAVE_API_SUPPORT_WIN32_BSTR -} - -MonoString * -mono_string_from_bstr (/*mono_bstr_const*/gpointer bstr) -{ - // FIXME gcmode - HANDLE_FUNCTION_ENTER (); - ERROR_DECL (error); - MonoStringHandle result = mono_string_from_bstr_checked ((mono_bstr_const)bstr, error); - mono_error_cleanup (error); - HANDLE_FUNCTION_RETURN_OBJ (result); -} - -MonoStringHandle -mono_string_from_bstr_icall_impl (mono_bstr_const bstr, MonoError *error) -{ - return mono_string_from_bstr_checked (bstr, error); -} - -MONO_API void -mono_free_bstr (/*mono_bstr_const*/gpointer bstr) -{ - if (!bstr) - return; -#if HAVE_API_SUPPORT_WIN32_BSTR - SysFreeString ((BSTR)bstr); -#else - g_free (((char *)bstr) - SIZEOF_VOID_P); -#endif // HAVE_API_SUPPORT_WIN32_BSTR -} - -gboolean -mono_marshal_free_ccw (MonoObject* object) -{ - return FALSE; -} - -mono_bstr -ves_icall_System_Runtime_InteropServices_Marshal_BufferToBSTR (const gunichar2* ptr, int len) -{ - return mono_ptr_to_bstr (ptr, len); -} - -void -ves_icall_System_Runtime_InteropServices_Marshal_FreeBSTR (mono_bstr_const ptr) -{ - mono_free_bstr ((gpointer)ptr); -} diff --git a/src/mono/mono/metadata/cominterop.h b/src/mono/mono/metadata/cominterop.h deleted file mode 100644 index 6ad9f5cbab73ee..00000000000000 --- a/src/mono/mono/metadata/cominterop.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - * \file - * COM Interop Support - * - * - * (C) 2002 Ximian, Inc. http://www.ximian.com - * - */ - -#ifndef __MONO_COMINTEROP_H__ -#define __MONO_COMINTEROP_H__ - -#include -#include -#include - -void -mono_cominterop_init (void); - -MONO_API MONO_RT_EXTERNAL_ONLY MonoString * -mono_string_from_bstr (/*mono_bstr*/gpointer bstr); - -MonoStringHandle -mono_string_from_bstr_checked (mono_bstr_const bstr, MonoError *error); - -MONO_API void -mono_free_bstr (/*mono_bstr_const*/gpointer bstr); - -#endif /* __MONO_COMINTEROP_H__ */ diff --git a/src/mono/mono/metadata/gc.c b/src/mono/mono/metadata/gc.c index a5c67062b0e78b..6fd74008ea9697 100644 --- a/src/mono/mono/metadata/gc.c +++ b/src/mono/mono/metadata/gc.c @@ -283,17 +283,6 @@ mono_gc_run_finalize (void *obj, void *data) finalizer = mono_class_get_finalizer (o->vtable->klass); - /* If object has a CCW but has no finalizer, it was only - * registered for finalization in order to free the CCW. - * Else it needs the regular finalizer run. - * FIXME: what to do about resurrection and suppression - * of finalizer on object with CCW. - */ - if (mono_marshal_free_ccw (o) && !finalizer) { - mono_domain_set_internal_with_options (caller_domain, TRUE); - return; - } - /* * To avoid the locking plus the other overhead of mono_runtime_invoke_checked (), * create and precompile a wrapper which calls the finalize method using diff --git a/src/mono/mono/metadata/icall-table.h b/src/mono/mono/metadata/icall-table.h index e65726b7503130..1336ed368e9d24 100644 --- a/src/mono/mono/metadata/icall-table.h +++ b/src/mono/mono/metadata/icall-table.h @@ -202,7 +202,6 @@ typedef MonoStringHandle MonoStringOutHandle; #define MONO_HANDLE_TYPE_WRAP_MonoArray ICALL_HANDLES_WRAP_OBJ #define MONO_HANDLE_TYPE_WRAP_MonoAsyncResult ICALL_HANDLES_WRAP_OBJ #define MONO_HANDLE_TYPE_WRAP_MonoCalendarData ICALL_HANDLES_WRAP_OBJ -#define MONO_HANDLE_TYPE_WRAP_MonoComInteropProxy ICALL_HANDLES_WRAP_OBJ #define MONO_HANDLE_TYPE_WRAP_MonoComObject ICALL_HANDLES_WRAP_OBJ #define MONO_HANDLE_TYPE_WRAP_MonoCultureData ICALL_HANDLES_WRAP_OBJ #define MONO_HANDLE_TYPE_WRAP_MonoCultureInfo ICALL_HANDLES_WRAP_OBJ diff --git a/src/mono/mono/metadata/loader-internals.h b/src/mono/mono/metadata/loader-internals.h index 3d055c5b6e9b3a..17a7a1968621d4 100644 --- a/src/mono/mono/metadata/loader-internals.h +++ b/src/mono/mono/metadata/loader-internals.h @@ -74,8 +74,6 @@ typedef struct { GHashTable *native_func_wrapper_indirect_cache; /* Indexed by MonoMethodSignature. Protected by the marshal lock */ GHashTable *synchronized_cache; GHashTable *unbox_wrapper_cache; - GHashTable *cominterop_invoke_cache; - GHashTable *cominterop_wrapper_cache; /* LOCKING: marshal lock */ GHashTable *thunk_invoke_cache; GHashTable *unsafe_accessor_cache; } MonoWrapperCaches; diff --git a/src/mono/mono/metadata/marshal-lightweight.c b/src/mono/mono/metadata/marshal-lightweight.c index 3418a37cc1fbe0..53b9d041ddc434 100644 --- a/src/mono/mono/metadata/marshal-lightweight.c +++ b/src/mono/mono/metadata/marshal-lightweight.c @@ -34,7 +34,6 @@ #include "mono/metadata/threads-types.h" #include "mono/metadata/string-icalls.h" #include "mono/metadata/attrdefs.h" -#include "mono/metadata/cominterop.h" #include "mono/metadata/reflection-internals.h" #include "mono/metadata/handle.h" #include "mono/metadata/custom-attrs-internals.h" diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index 7fb70fa8c8d9de..b67c8fb7af4070 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -17,6 +17,7 @@ #include #endif +#include #if defined(HOST_WIN32) #include MONO_PRAGMA_WARNING_PUSH() @@ -24,8 +25,11 @@ MONO_PRAGMA_WARNING_DISABLE (4115) // warning C4115: 'IRpcStubBuffer': named typ #include #include #include +#include MONO_PRAGMA_WARNING_POP() +#include #endif +#include #include #include @@ -53,7 +57,6 @@ MONO_PRAGMA_WARNING_POP() #include "mono/metadata/threads-types.h" #include "mono/metadata/string-icalls.h" #include "mono/metadata/attrdefs.h" -#include "mono/metadata/cominterop.h" #include "mono/metadata/reflection-internals.h" #include "mono/metadata/handle.h" #include "mono/metadata/object-internals.h" @@ -320,6 +323,9 @@ mono_marshal_init (void) register_icall (mono_marshal_free_array, mono_icall_sig_void_ptr_int32, FALSE); register_icall (mono_string_to_byvalstr, mono_icall_sig_void_ptr_ptr_int32, FALSE); register_icall (mono_string_to_byvalwstr, mono_icall_sig_void_ptr_ptr_int32, FALSE); + register_icall (mono_string_to_bstr, mono_icall_sig_ptr_obj, FALSE); + register_icall (mono_string_from_bstr_icall, mono_icall_sig_obj_ptr, FALSE); + register_icall (mono_free_bstr, mono_icall_sig_void_ptr, FALSE); // Because #define g_free monoeg_g_free. register_icall (monoeg_g_free, mono_icall_sig_void_ptr, FALSE); register_icall (mono_object_isinst_icall, mono_icall_sig_object_object_ptr, TRUE); @@ -339,8 +345,6 @@ mono_marshal_init (void) register_icall (mono_marshal_get_type_object, mono_icall_sig_object_ptr, TRUE); register_icall (mono_marshal_lookup_pinvoke, mono_icall_sig_ptr_ptr, FALSE); - mono_cominterop_init (); - mono_counters_register ("MonoClass::class_marshal_info_count count", MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_marshal_info_count); } @@ -1087,6 +1091,18 @@ mono_string_to_tbstr_impl (MonoStringHandle string_obj, MonoError *error) #endif } +static MonoStringHandle +mono_string_from_bstr_checked (mono_bstr_const bstr, MonoError *error) +{ + if (!bstr) + return NULL_HANDLE_STRING; +#if HAVE_API_SUPPORT_WIN32_BSTR + return mono_string_new_utf16_handle (bstr, SysStringLen ((BSTR)bstr), error); +#else + return mono_string_new_utf16_handle (bstr, *((guint32 *)bstr - 1) / sizeof (gunichar2), error); +#endif // HAVE_API_SUPPORT_WIN32_BSTR +} + /* This is a JIT icall, it sets the pending exception (in wrapper) and returns NULL on error. */ MonoStringHandle mono_string_from_tbstr_impl (gpointer data, MonoError *error) @@ -1166,6 +1182,125 @@ mono_string_new_len_wrapper_impl (const char *text, guint length, MonoError *err return MONO_HANDLE_NEW (MonoString, s); } + +mono_bstr +mono_string_to_bstr_impl (MonoStringHandle s, MonoError *error) +{ + if (MONO_HANDLE_IS_NULL (s)) + return NULL; + + MonoGCHandle gchandle = NULL; + mono_bstr const res = mono_ptr_to_bstr (mono_string_handle_pin_chars (s, &gchandle), mono_string_handle_length (s)); + mono_gchandle_free_internal (gchandle); + return res; +} + +// This function is used regardless of the BSTR type, so cast the return value +// Inputted string length, in bytes, should include the null terminator +// Returns the start of the string itself +static gpointer +mono_bstr_alloc (size_t str_byte_len) +{ + // Allocate string length plus pointer-size integer to store the length, aligned to 16 bytes + size_t alloc_size = str_byte_len + SIZEOF_VOID_P; + alloc_size += (16 - 1); + alloc_size &= ~(16 - 1); + gpointer ret = g_malloc0 (alloc_size); + return ret ? (char *)ret + SIZEOF_VOID_P : NULL; +} + +static void +mono_bstr_set_length (gunichar2 *bstr, int slen) +{ + *((guint32 *)bstr - 1) = slen * sizeof (gunichar2); +} + +static mono_bstr +default_ptr_to_bstr (const gunichar2* ptr, int slen) +{ + // In Mono, historically BSTR was allocated with a guaranteed size prefix of 4 bytes regardless of platform. + // Presumably this is due to the BStr documentation page, which indicates that behavior and then directs you to call + // SysAllocString on Windows to handle the allocation for you. Unfortunately, this is not actually how it works: + // The allocation pre-string is pointer-sized, and then only 4 bytes are used for the length regardless. Additionally, + // the total length is also aligned to a 16-byte boundary. This preserves the old behavior on legacy and fixes it for + // netcore moving forward. + mono_bstr const s = (mono_bstr)mono_bstr_alloc ((slen + 1) * sizeof (gunichar2)); + if (s == NULL) + return NULL; + + mono_bstr_set_length (s, slen); + if (ptr) + memcpy (s, ptr, slen * sizeof (gunichar2)); + s [slen] = 0; + return s; +} + +/* PTR can be NULL */ +mono_bstr +mono_ptr_to_bstr (const gunichar2* ptr, int slen) +{ +#if HAVE_API_SUPPORT_WIN32_BSTR + return SysAllocStringLen (ptr, slen); +#else + return default_ptr_to_bstr (ptr, slen); +#endif // HAVE_API_SUPPORT_WIN32_BSTR +} + +char * +mono_ptr_to_ansibstr (const char *ptr, size_t slen) +{ + char *s = (char *)mono_bstr_alloc ((slen + 1) * sizeof(char)); + if (s == NULL) + return NULL; + *((guint32 *)s - 1) = (guint32)(slen * sizeof (char)); + if (ptr) + memcpy (s, ptr, slen * sizeof (char)); + s [slen] = 0; + return s; +} + +MonoString * +mono_string_from_bstr (/*mono_bstr_const*/gpointer bstr) +{ + // FIXME gcmode + HANDLE_FUNCTION_ENTER (); + ERROR_DECL (error); + MonoStringHandle result = mono_string_from_bstr_checked ((mono_bstr_const)bstr, error); + mono_error_cleanup (error); + HANDLE_FUNCTION_RETURN_OBJ (result); +} + +MonoStringHandle +mono_string_from_bstr_icall_impl (mono_bstr_const bstr, MonoError *error) +{ + return mono_string_from_bstr_checked (bstr, error); +} + +MONO_API void +mono_free_bstr (/*mono_bstr_const*/gpointer bstr) +{ + if (!bstr) + return; +#if HAVE_API_SUPPORT_WIN32_BSTR + SysFreeString ((BSTR)bstr); +#else + g_free (((char *)bstr) - SIZEOF_VOID_P); +#endif // HAVE_API_SUPPORT_WIN32_BSTR +} + +mono_bstr +ves_icall_System_Runtime_InteropServices_Marshal_BufferToBSTR (const gunichar2* ptr, int len) +{ + return mono_ptr_to_bstr (ptr, len); +} + +void +ves_icall_System_Runtime_InteropServices_Marshal_FreeBSTR (mono_bstr_const ptr) +{ + mono_free_bstr ((gpointer)ptr); +} + + guint8 mono_type_to_ldind (MonoType *type) { @@ -1495,13 +1630,13 @@ get_cache (GHashTable **var, GHashFunc hash_func, GCompareFunc equal_func) return *var; } -GHashTable* +static GHashTable* mono_marshal_get_cache (GHashTable **var, GHashFunc hash_func, GCompareFunc equal_func) { return get_cache (var, hash_func, equal_func); } -MonoMethod* +static MonoMethod* mono_marshal_find_in_cache (GHashTable *cache, gpointer key) { MonoMethod *res; @@ -1530,7 +1665,7 @@ mono_mb_create (MonoMethodBuilder *mb, MonoMethodSignature *sig, } /* Create the method from the builder and place it in the cache */ -MonoMethod* +static MonoMethod* mono_mb_create_and_cache_full (GHashTable *cache, gpointer key, MonoMethodBuilder *mb, MonoMethodSignature *sig, int max_stack, WrapperInfo *info, gboolean *out_found) @@ -1564,7 +1699,7 @@ mono_mb_create_and_cache_full (GHashTable *cache, gpointer key, return res; } -MonoMethod* +static MonoMethod* mono_mb_create_and_cache (GHashTable *cache, gpointer key, MonoMethodBuilder *mb, MonoMethodSignature *sig, int max_stack) @@ -3352,6 +3487,8 @@ mono_marshal_set_callconv_from_unmanaged_callers_only_attribute (MonoMethod *met mono_custom_attrs_free(cinfo); } +static void +mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethodPInvoke *piinfo, MonoMarshalSpec **mspecs, gpointer func, MonoNativeWrapperFlags flags); /** * mono_marshal_get_native_wrapper: @@ -3833,7 +3970,7 @@ mono_marshal_get_native_func_wrapper_indirect (MonoClass *caller_class, MonoMeth * it could have fewer parameters than the method it wraps. * THIS_LOC is the memory location where the target of the delegate is stored. */ -void +static void mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, MonoGCHandle target_handle, MonoError *error) { get_marshal_cb ()->emit_managed_wrapper (mb, invoke_sig, mspecs, m, method, target_handle, FALSE, error); @@ -6418,8 +6555,6 @@ mono_wrapper_caches_free (MonoWrapperCaches *cache) free_hash (cache->native_func_wrapper_indirect_cache); free_hash (cache->synchronized_cache); free_hash (cache->unbox_wrapper_cache); - free_hash (cache->cominterop_invoke_cache); - free_hash (cache->cominterop_wrapper_cache); free_hash (cache->thunk_invoke_cache); free_hash (cache->unsafe_accessor_cache); } diff --git a/src/mono/mono/metadata/marshal.h b/src/mono/mono/metadata/marshal.h index 79bf8bd5e78577..3396646d8df00c 100644 --- a/src/mono/mono/metadata/marshal.h +++ b/src/mono/mono/metadata/marshal.h @@ -40,7 +40,7 @@ GENERATE_TRY_GET_CLASS_WITH_CACHE_DECL(stringbuilder) /* * This structure holds the state kept by the emit_ marshalling functions. - * This is exported so it can be used by cominterop.c. + * This is exported so it can be used by marshal-ilgen.c. */ typedef struct { MonoMethodBuilder *mb; @@ -623,12 +623,12 @@ ICALL_EXPORT void mono_marshal_free_array (gpointer *ptr, int size); -gboolean -mono_marshal_free_ccw (MonoObject* obj); - MONO_API void * mono_marshal_string_to_utf16 (MonoString *s); +MONO_API void +mono_free_bstr (gpointer bstr); + ICALL_EXPORT void mono_marshal_set_last_error_windows (int error); @@ -714,24 +714,6 @@ mono_marshal_find_nonzero_bit_offset (guint8 *buf, int len, int *byte_offset, gu MonoMethodSignature* mono_signature_no_pinvoke (MonoMethod *method); -/* Called from cominterop.c/remoting.c */ - -void -mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethodPInvoke *piinfo, MonoMarshalSpec **mspecs, gpointer func, MonoNativeWrapperFlags flags); - -void -mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, MonoGCHandle target_handle, MonoError *error); - -GHashTable* -mono_marshal_get_cache (GHashTable **var, GHashFunc hash_func, GCompareFunc equal_func); - -MonoMethod* -mono_marshal_find_in_cache (GHashTable *cache, gpointer key); - -MonoMethod* -mono_mb_create_and_cache (GHashTable *cache, gpointer key, - MonoMethodBuilder *mb, MonoMethodSignature *sig, - int max_stack); void mono_marshal_emit_thread_interrupt_checkpoint (MonoMethodBuilder *mb); @@ -751,11 +733,6 @@ MonoMethod* mono_mb_create (MonoMethodBuilder *mb, MonoMethodSignature *sig, int max_stack, WrapperInfo *info); -MonoMethod* -mono_mb_create_and_cache_full (GHashTable *cache, gpointer key, - MonoMethodBuilder *mb, MonoMethodSignature *sig, - int max_stack, WrapperInfo *info, gboolean *out_found); - IlgenCallbacksToMono* mono_marshal_get_mono_callbacks_for_ilgen (void); diff --git a/src/mono/mono/metadata/metadata.c b/src/mono/mono/metadata/metadata.c index ba16a2739aae28..7cccf658976d66 100644 --- a/src/mono/mono/metadata/metadata.c +++ b/src/mono/mono/metadata/metadata.c @@ -29,7 +29,6 @@ #include "marshal.h" #include #include "abi-details.h" -#include "cominterop.h" #include "components.h" #include #include diff --git a/src/mono/mono/metadata/object-internals.h b/src/mono/mono/metadata/object-internals.h index 1909411c7d03ef..257d06a915da99 100644 --- a/src/mono/mono/metadata/object-internals.h +++ b/src/mono/mono/metadata/object-internals.h @@ -509,14 +509,6 @@ typedef struct { TYPED_HANDLE_DECL (MonoComObject); -typedef struct { - MonoRealProxy real_proxy; - MonoComObject *com_object; - gint32 ref_count; -} MonoComInteropProxy; - -TYPED_HANDLE_DECL (MonoComInteropProxy); - typedef struct { MonoObject object; MonoRealProxy *rp; diff --git a/src/mono/mono/metadata/object-offsets.h b/src/mono/mono/metadata/object-offsets.h index a1ab49ff43a091..017ff752d7d2c5 100644 --- a/src/mono/mono/metadata/object-offsets.h +++ b/src/mono/mono/metadata/object-offsets.h @@ -118,8 +118,6 @@ DECL_OFFSET(MonoSafeHandle, handle) DECL_OFFSET(MonoHandleRef, handle) -DECL_OFFSET(MonoComInteropProxy, com_object) - DECL_OFFSET(MonoString, length) DECL_OFFSET(MonoString, chars) diff --git a/src/mono/mono/metadata/object.c b/src/mono/mono/metadata/object.c index 37638c06388444..76cda048c263d9 100644 --- a/src/mono/mono/metadata/object.c +++ b/src/mono/mono/metadata/object.c @@ -51,7 +51,6 @@ #include #include #include -#include "cominterop.h" #include #include #include "external-only.h" diff --git a/src/mono/mono/metadata/wrapper-types.h b/src/mono/mono/metadata/wrapper-types.h index 403357649f7667..ce7b25ae5f44f9 100644 --- a/src/mono/mono/metadata/wrapper-types.h +++ b/src/mono/mono/metadata/wrapper-types.h @@ -20,6 +20,4 @@ WRAPPER(STELEMREF, "stelemref") WRAPPER(UNBOX, "unbox") WRAPPER(WRITE_BARRIER, "write-barrier") WRAPPER(OTHER, "other") -WRAPPER(COMINTEROP_INVOKE, "cominterop-invoke") -WRAPPER(COMINTEROP, "cominterop") WRAPPER(ALLOC, "alloc") diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index e30602dbca0bd6..bb5eef90fb79bb 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -9530,9 +9530,6 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method) // FIXME: The wrapper should be generic too, but it is not return; - if (method->wrapper_type == MONO_WRAPPER_COMINTEROP) - return; - if (acfg->aot_opts.profile_only && !g_hash_table_lookup (acfg->profile_methods, method)) { if (acfg->aot_opts.llvm_only) { gboolean keep = FALSE; diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index 96a9859e9eae87..f19adc66a17e4b 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -6431,8 +6431,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b /* serialization and xdomain stuff may need access to private fields and methods */ dont_verify = FALSE; dont_verify |= method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE; /* bug #77896 */ - dont_verify |= method->wrapper_type == MONO_WRAPPER_COMINTEROP; - dont_verify |= method->wrapper_type == MONO_WRAPPER_COMINTEROP_INVOKE; /* still some type unsafety issues in marshal wrappers... (unknown is PtrToStructure) */ dont_verify_stloc = method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE; diff --git a/src/mono/mono/tools/offsets-tool/offsets-tool.py b/src/mono/mono/tools/offsets-tool/offsets-tool.py index 2dbaa1c2eacb68..008bf3c5aa4860 100644 --- a/src/mono/mono/tools/offsets-tool/offsets-tool.py +++ b/src/mono/mono/tools/offsets-tool/offsets-tool.py @@ -245,7 +245,6 @@ def run_clang(self): "MonoArrayBounds", "MonoSafeHandle", "MonoHandleRef", - "MonoComInteropProxy", "MonoString", "MonoException", "MonoTypedRef", From 2422f0f81dbbf00a53c01ef46fd4ee6abf71e55e Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 31 Jan 2024 13:15:53 -0800 Subject: [PATCH 03/12] Remove some more checks and make them asserts instead --- src/mono/mono/metadata/marshal-lightweight.c | 8 +++----- src/mono/mono/metadata/marshal.c | 8 +------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/mono/mono/metadata/marshal-lightweight.c b/src/mono/mono/metadata/marshal-lightweight.c index 53b9d041ddc434..86f64eeb40bba6 100644 --- a/src/mono/mono/metadata/marshal-lightweight.c +++ b/src/mono/mono/metadata/marshal-lightweight.c @@ -623,10 +623,9 @@ gc_safe_transition_builder_add_locals (GCSafeTransitionBuilder *builder) static void gc_safe_transition_builder_emit_enter (GCSafeTransitionBuilder *builder, MonoMethod *method, gboolean aot) { - // Perform an extra, early lookup of the function address, so any exceptions // potentially resulting from the lookup occur before entering blocking mode. - if (!builder->func_param && !MONO_CLASS_IS_IMPORT (builder->mb->method->klass) && aot) { + if (!builder->func_param && aot) { mono_mb_emit_byte (builder->mb, MONO_CUSTOM_PREFIX); mono_mb_emit_op (builder->mb, CEE_MONO_ICALL_ADDR, method); mono_mb_emit_byte (builder->mb, CEE_POP); // Result not needed yet @@ -798,6 +797,7 @@ emit_native_wrapper_validate_signature (MonoMethodBuilder *mb, MonoMethodSignatu static void emit_native_wrapper_ilgen (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethodPInvoke *piinfo, MonoMarshalSpec **mspecs, gpointer func, MonoNativeWrapperFlags flags) { + g_assert (!MONO_CLASS_IS_IMPORT (mb->method->klass)); gboolean aot = (flags & EMIT_NATIVE_WRAPPER_AOT) != 0; gboolean check_exceptions = (flags & EMIT_NATIVE_WRAPPER_CHECK_EXCEPTIONS) != 0; gboolean func_param = (flags & EMIT_NATIVE_WRAPPER_FUNC_PARAM) != 0; @@ -863,7 +863,7 @@ emit_native_wrapper_ilgen (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSi if (need_gc_safe) gc_safe_transition_builder_add_locals (&gc_safe_transition_builder); - if (!func && !aot && !func_param && !MONO_CLASS_IS_IMPORT (mb->method->klass)) { + if (!func && !aot && !func_param) { /* * On netcore, its possible to register pinvoke resolvers at runtime, so * a pinvoke lookup can fail, and then succeed later. So if the @@ -958,8 +958,6 @@ emit_native_wrapper_ilgen (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSi mono_mb_emit_byte (mb, CEE_MONO_SAVE_LAST_ERROR); } mono_mb_emit_calli (mb, csig); - } else if (MONO_CLASS_IS_IMPORT (mb->method->klass)) { - g_assert_not_reached(); } else { if (func_addr_local != -1) { mono_mb_emit_ldloc (mb, func_addr_local); diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index b67c8fb7af4070..2b8e4a9186b6b4 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -3547,13 +3547,7 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions, } } - if (MONO_CLASS_IS_IMPORT (method->klass)) { - /* The COM code is not AOT compatible, it calls mono_custom_attrs_get_attr_checked () */ - if (aot) - return method; - - g_assert_not_reached (); - } + g_assert (!MONO_CLASS_IS_IMPORT (method->klass)); sig = mono_method_signature_internal (method); From 92b8ed84476ad3bba16d8704bc08544c9a8bbded Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 31 Jan 2024 14:29:54 -0800 Subject: [PATCH 04/12] Add prototype for mono_string_from_bstr --- src/mono/mono/metadata/marshal.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mono/mono/metadata/marshal.h b/src/mono/mono/metadata/marshal.h index 3396646d8df00c..3ca837e81a6016 100644 --- a/src/mono/mono/metadata/marshal.h +++ b/src/mono/mono/metadata/marshal.h @@ -708,6 +708,9 @@ ICALL_EXPORT void ves_icall_System_Runtime_InteropServices_Marshal_FreeBSTR (mono_bstr_const ptr); +MONO_API MONO_RT_EXTERNAL_ONLY MonoString * +mono_string_from_bstr (/*mono_bstr*/gpointer bstr); + void mono_marshal_find_nonzero_bit_offset (guint8 *buf, int len, int *byte_offset, guint8 *bitmask); From 664500dcc86b130c00f3e1ac85b70c05abb20100 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 31 Jan 2024 14:45:22 -0800 Subject: [PATCH 05/12] Remove unused variable --- src/mono/mono/metadata/object.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/mono/mono/metadata/object.c b/src/mono/mono/metadata/object.c index 76cda048c263d9..ecdcae6b35d31e 100644 --- a/src/mono/mono/metadata/object.c +++ b/src/mono/mono/metadata/object.c @@ -100,8 +100,6 @@ static GENERATE_TRY_GET_CLASS_WITH_CACHE (execution_context, "System.Threading", #define ldstr_lock() mono_coop_mutex_lock (&ldstr_section) #define ldstr_unlock() mono_coop_mutex_unlock (&ldstr_section) static MonoCoopMutex ldstr_section; -/* Used by remoting proxies */ -static MonoMethod *create_proxy_for_type_method; static MonoGHashTable *ldstr_table; static GString * From a229363fdf48e184cb8f5414f87dac7cd01770aa Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 31 Jan 2024 16:48:25 -0800 Subject: [PATCH 06/12] Inline finalizer check into Wasm-only branch --- src/mono/mono/metadata/gc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/mono/mono/metadata/gc.c b/src/mono/mono/metadata/gc.c index 6fd74008ea9697..49fd0c2553dfef 100644 --- a/src/mono/mono/metadata/gc.c +++ b/src/mono/mono/metadata/gc.c @@ -189,7 +189,6 @@ mono_gc_run_finalize (void *obj, void *data) #ifndef HAVE_SGEN_GC MonoObject *o2; #endif - MonoMethod* finalizer = NULL; MonoDomain *caller_domain = mono_domain_get (); // This function is called from the innards of the GC, so our best alternative for now is to do polling here @@ -281,7 +280,6 @@ mono_gc_run_finalize (void *obj, void *data) return; } - finalizer = mono_class_get_finalizer (o->vtable->klass); /* * To avoid the locking plus the other overhead of mono_runtime_invoke_checked (), @@ -318,6 +316,7 @@ mono_gc_run_finalize (void *obj, void *data) MONO_PROFILER_RAISE (gc_finalizing_object, (o)); #ifdef HOST_WASM + MonoMethod* finalizer = mono_class_get_finalizer (o->vtable->klass); if (finalizer) { // null finalizers work fine when using the vcall invoke as Object has an empty one gpointer params [1]; params [0] = NULL; From 349e780de369a7045794c1aedf4242d05eb1c7cb Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 5 Feb 2024 10:57:16 -0800 Subject: [PATCH 07/12] Don't fail the AOT compiler when encountering a COM type --- src/mono/mono/mini/aot-compiler.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index bb5eef90fb79bb..8601db819acac4 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -13067,6 +13067,17 @@ collect_methods (MonoAotCompile *acfg) method = mono_get_method_checked (acfg->image, token, NULL, NULL, error); if (!method) { + if (mono_error_get_error_code (error) == MONO_ERROR_TYPE_LOAD) { + // If we failed to load the method due to a type load failure, + // make sure the type isn't a ComImport or WindowsRuntimeImport type. + // We'll ignore the COM interop types here, since they're not supported on any flavor of the Mono runtime. + guint32 type_token = mono_metadata_typedef_from_method (image, i + 1); + guint32 type_flags = mono_metadata_decode_table_row_col (image, MONO_TABLE_TYPEDEF, type_token, MONO_TYPEDEF_FLAGS); + if (type_flags & (TYPE_ATTRIBUTE_IMPORT | TYPE_ATTRIBUTE_WINDOWS_RUNTIME)) { + mono_error_cleanup (error); + continue; + } + } aot_printerrf (acfg, "Failed to load method 0x%x from '%s' due to %s.\n", token, image->name, mono_error_get_message (error)); aot_printerrf (acfg, "Run with MONO_LOG_LEVEL=debug for more information.\n"); mono_error_cleanup (error); From b2b6e3d9f2c8a5cca8b140204d91fabf80612fc2 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 7 Feb 2024 11:25:15 -0800 Subject: [PATCH 08/12] Block constructing RCW types at construction time. We need to allow ComImport types to be loaded as ComImport interfaces can also be implemented entirely in managed code, but we can block objects of ComImport-based types from being created. --- src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c | 2 +- src/mono/mono/metadata/class-init.c | 5 ----- src/mono/mono/metadata/object.c | 10 ++++++++++ src/mono/mono/mini/aot-compiler.c | 11 ----------- 4 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c b/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c index e559d666017061..381164d8f94039 100644 --- a/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c +++ b/src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c @@ -187,7 +187,7 @@ typedef struct _AssemblyEventData AssemblyEventData; typedef enum { TYPE_FLAGS_DELEGATE = 0x1, TYPE_FLAGS_FINALIZABLE = 0x2, - TYPE_FLAGS_EXTERNALLY_IMPLEMENTED_COM_OBJECT = 0x4, + // unused = 0x4, TYPE_FLAGS_ARRAY = 0x8, TYPE_FLAGS_ARRAY_RANK_MASK = 0x3F00, diff --git a/src/mono/mono/metadata/class-init.c b/src/mono/mono/metadata/class-init.c index 584ba25dcfdf26..dd2d54a33a1d81 100644 --- a/src/mono/mono/metadata/class-init.c +++ b/src/mono/mono/metadata/class-init.c @@ -564,11 +564,6 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError } } - if (MONO_CLASS_IS_IMPORT (klass)) { - mono_class_set_failure_and_error (klass, error, "Built-in COM interop is not supported on the Mono runtime."); - goto parent_failure; - } - mono_class_setup_parent (klass, parent); /* uses ->valuetype, which is initialized by mono_class_setup_parent above */ diff --git a/src/mono/mono/metadata/object.c b/src/mono/mono/metadata/object.c index ecdcae6b35d31e..9ed07a0aa5aac4 100644 --- a/src/mono/mono/metadata/object.c +++ b/src/mono/mono/metadata/object.c @@ -5345,6 +5345,11 @@ MonoObjectHandle mono_object_new_handle (MonoClass *klass, MonoError *error) { MONO_REQ_GC_UNSAFE_MODE; + + if (MONO_CLASS_IS_IMPORT(klass)) { + mono_error_set_not_supported (error, "Built-in COM interop is not supported on Mono."); + return NULL; + } MonoVTable* const vtable = mono_class_vtable_checked (klass, error); @@ -5413,6 +5418,11 @@ mono_object_new_specific_checked (MonoVTable *vtable, MonoError *error) error_init (error); + if (MONO_CLASS_IS_IMPORT(vtable->klass)) { + mono_error_set_not_supported (error, "Built-in COM interop is not supported on Mono."); + return NULL; + } + return mono_object_new_alloc_specific_checked (vtable, error); } diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 8601db819acac4..bb5eef90fb79bb 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -13067,17 +13067,6 @@ collect_methods (MonoAotCompile *acfg) method = mono_get_method_checked (acfg->image, token, NULL, NULL, error); if (!method) { - if (mono_error_get_error_code (error) == MONO_ERROR_TYPE_LOAD) { - // If we failed to load the method due to a type load failure, - // make sure the type isn't a ComImport or WindowsRuntimeImport type. - // We'll ignore the COM interop types here, since they're not supported on any flavor of the Mono runtime. - guint32 type_token = mono_metadata_typedef_from_method (image, i + 1); - guint32 type_flags = mono_metadata_decode_table_row_col (image, MONO_TABLE_TYPEDEF, type_token, MONO_TYPEDEF_FLAGS); - if (type_flags & (TYPE_ATTRIBUTE_IMPORT | TYPE_ATTRIBUTE_WINDOWS_RUNTIME)) { - mono_error_cleanup (error); - continue; - } - } aot_printerrf (acfg, "Failed to load method 0x%x from '%s' due to %s.\n", token, image->name, mono_error_get_message (error)); aot_printerrf (acfg, "Run with MONO_LOG_LEVEL=debug for more information.\n"); mono_error_cleanup (error); From 99252dc12b85b1bca918fe43cada763bba2e2048 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 7 Feb 2024 11:59:59 -0800 Subject: [PATCH 09/12] Emit PNSE for COMImport wrapper generation --- src/mono/mono/metadata/marshal.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index 1de708961efb8e..f82d647bcdcc1b 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -3527,14 +3527,8 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions, method->name, method->flags, method->iflags, mono_method_signature_internal (method)->param_count); if (MONO_CLASS_IS_IMPORT (method->klass)) { - /* The COM code is not AOT compatible, it calls mono_custom_attrs_get_attr_checked () */ - if (aot) - return method; -#ifndef DISABLE_COM - return mono_cominterop_get_native_wrapper (method); -#else - g_assert_not_reached (); -#endif + mono_error_set_generic_error (emitted_error, "System", "PlatformNotSupportedException", "Built-in COM interop is not supported on Mono"); + goto emit_exception_for_error; } if (aot) { From 3ce9c7f5e6e9cebb00f7ff6d80e40b023980e6ff Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 7 Feb 2024 12:43:27 -0800 Subject: [PATCH 10/12] Move check --- src/mono/mono/metadata/marshal.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index f82d647bcdcc1b..9876523cc61920 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -3526,11 +3526,6 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions, g_assertf (mono_method_signature_internal (method)->pinvoke, "%s flags:%X iflags:%X param_count:%X", method->name, method->flags, method->iflags, mono_method_signature_internal (method)->param_count); - if (MONO_CLASS_IS_IMPORT (method->klass)) { - mono_error_set_generic_error (emitted_error, "System", "PlatformNotSupportedException", "Built-in COM interop is not supported on Mono"); - goto emit_exception_for_error; - } - if (aot) { if (check_exceptions) cache_ptr = &mono_method_get_wrapper_cache (method)->native_wrapper_aot_check_cache; @@ -3548,6 +3543,11 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions, if ((res = mono_marshal_find_in_cache (cache, method))) return res; + if (MONO_CLASS_IS_IMPORT (method->klass)) { + mono_error_set_generic_error (emitted_error, "System", "PlatformNotSupportedException", "Built-in COM interop is not supported on Mono"); + goto emit_exception_for_error; + } + if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) { guint32 icall_flags = 0; if (mono_lookup_internal_call_full_with_flags (method, FALSE, &icall_flags)) { @@ -3556,8 +3556,6 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions, } } - g_assert (!MONO_CLASS_IS_IMPORT (method->klass)); - sig = mono_method_signature_internal (method); if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && From 60799ccbb6a3efea3d5d780c4625dfcb07296d29 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 7 Feb 2024 16:36:07 -0800 Subject: [PATCH 11/12] Fix null handle return --- src/mono/mono/metadata/object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mono/mono/metadata/object.c b/src/mono/mono/metadata/object.c index 899442c6d3f98b..d6ddb751fe3a74 100644 --- a/src/mono/mono/metadata/object.c +++ b/src/mono/mono/metadata/object.c @@ -5358,7 +5358,7 @@ mono_object_new_handle (MonoClass *klass, MonoError *error) if (MONO_CLASS_IS_IMPORT(klass)) { mono_error_set_not_supported (error, "Built-in COM interop is not supported on Mono."); - return NULL; + return MONO_HANDLE_NEW (MonoObject, NULL); } MonoVTable* const vtable = mono_class_vtable_checked (klass, error); From 822ee46bb96e1087abf5001c895947e75eb80cb8 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 7 Feb 2024 17:09:02 -0800 Subject: [PATCH 12/12] Let the regular flow emit the error. --- src/mono/mono/metadata/marshal.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index 9876523cc61920..1e10d82ee40885 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -3526,6 +3526,10 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions, g_assertf (mono_method_signature_internal (method)->pinvoke, "%s flags:%X iflags:%X param_count:%X", method->name, method->flags, method->iflags, mono_method_signature_internal (method)->param_count); + if (MONO_CLASS_IS_IMPORT (method->klass)) { + mono_error_set_generic_error (emitted_error, "System", "PlatformNotSupportedException", "Built-in COM interop is not supported on Mono"); + } + if (aot) { if (check_exceptions) cache_ptr = &mono_method_get_wrapper_cache (method)->native_wrapper_aot_check_cache; @@ -3543,11 +3547,6 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions, if ((res = mono_marshal_find_in_cache (cache, method))) return res; - if (MONO_CLASS_IS_IMPORT (method->klass)) { - mono_error_set_generic_error (emitted_error, "System", "PlatformNotSupportedException", "Built-in COM interop is not supported on Mono"); - goto emit_exception_for_error; - } - if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) { guint32 icall_flags = 0; if (mono_lookup_internal_call_full_with_flags (method, FALSE, &icall_flags)) {