Merge pull request #2720 from mono/fix-39325
[mono.git] / mono / metadata / cominterop.c
index 162e7436406f30b3e0e3e46cb618c3a2e1031d19..08450558d9d27e9998da65efb7ea26943303570f 100644 (file)
@@ -95,6 +95,9 @@ 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 (guid_attribute, System.Runtime.InteropServices, GuidAttribute)
+
 /* 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
@@ -145,6 +148,10 @@ cominterop_get_managed_wrapper_adjusted (MonoMethod *method);
 static gpointer
 cominterop_get_ccw (MonoObject* object, MonoClass* itf);
 
+static gpointer
+cominterop_get_ccw_checked (MonoObject *object, MonoClass *itf, MonoError *error);
+
+
 static MonoObject*
 cominterop_get_ccw_object (MonoCCWInterface* ccw_entry, gboolean verify);
 
@@ -170,6 +177,22 @@ mono_marshal_safearray_set_value (gpointer safearray, gpointer indices, gpointer
 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
@@ -280,16 +303,14 @@ cominterop_object_is_rcw (MonoObject *obj)
 static int
 cominterop_get_com_slot_begin (MonoClass* klass)
 {
-       static MonoClass *interface_type_attribute = NULL;
+       MonoError error;
        MonoCustomAttrInfo *cinfo = NULL;
        MonoInterfaceTypeAttribute* itf_attr = NULL; 
 
-       if (!interface_type_attribute)
-               interface_type_attribute = mono_class_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "InterfaceTypeAttribute");
-       cinfo = mono_custom_attrs_from_class (klass);
+       cinfo = mono_custom_attrs_from_class_checked (klass, &error);
+       mono_error_assert_ok (&error);
        if (cinfo) {
-               MonoError error;
-               itf_attr = (MonoInterfaceTypeAttribute*)mono_custom_attrs_get_attr_checked (cinfo, interface_type_attribute, &error);
+               itf_attr = (MonoInterfaceTypeAttribute*)mono_custom_attrs_get_attr_checked (cinfo, mono_class_get_interface_type_attribute_class (), &error);
                g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
                if (!cinfo->cached)
                        mono_custom_attrs_free (cinfo);
@@ -388,17 +409,13 @@ cominterop_mono_string_to_guid (MonoString* string, guint8 *guid);
 static gboolean
 cominterop_class_guid (MonoClass* klass, guint8* guid)
 {
-       static MonoClass *GuidAttribute = NULL;
+       MonoError error;
        MonoCustomAttrInfo *cinfo;
 
-       /* Handle the GuidAttribute */
-       if (!GuidAttribute)
-               GuidAttribute = mono_class_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "GuidAttribute");
-
-       cinfo = mono_custom_attrs_from_class (klass);   
+       cinfo = mono_custom_attrs_from_class_checked (klass, &error);
+       mono_error_assert_ok (&error);
        if (cinfo) {
-               MonoError error;
-               MonoReflectionGuidAttribute *attr = (MonoReflectionGuidAttribute*)mono_custom_attrs_get_attr_checked (cinfo, GuidAttribute, &error);
+               MonoReflectionGuidAttribute *attr = (MonoReflectionGuidAttribute*)mono_custom_attrs_get_attr_checked (cinfo, mono_class_get_guid_attribute_class (), &error);
                g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
 
                if (!attr)
@@ -415,20 +432,15 @@ cominterop_class_guid (MonoClass* klass, guint8* guid)
 static gboolean
 cominterop_com_visible (MonoClass* klass)
 {
-       static MonoClass *ComVisibleAttribute = NULL;
        MonoError error;
        MonoCustomAttrInfo *cinfo;
        GPtrArray *ifaces;
        MonoBoolean visible = 1;
 
-       /* Handle the ComVisibleAttribute */
-       if (!ComVisibleAttribute)
-               ComVisibleAttribute = mono_class_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "ComVisibleAttribute");
-
-       cinfo = mono_custom_attrs_from_class (klass);
+       cinfo = mono_custom_attrs_from_class_checked (klass, &error);
+       mono_error_assert_ok (&error);
        if (cinfo) {
-               MonoError error;
-               MonoReflectionComVisibleAttribute *attr = (MonoReflectionComVisibleAttribute*)mono_custom_attrs_get_attr_checked (cinfo, ComVisibleAttribute, &error);
+               MonoReflectionComVisibleAttribute *attr = (MonoReflectionComVisibleAttribute*)mono_custom_attrs_get_attr_checked (cinfo, mono_class_get_guid_attribute_class (), &error);
                g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
 
                if (attr)
@@ -456,32 +468,40 @@ cominterop_com_visible (MonoClass* klass)
 
 }
 
-static void cominterop_raise_hr_exception (int hr)
+static void cominterop_set_hr_error (MonoError *oerror, int hr)
 {
        static MonoMethod* throw_exception_for_hr = NULL;
+       MonoError error;
        MonoException* ex;
        void* params[1] = {&hr};
+
        if (!throw_exception_for_hr)
                throw_exception_for_hr = mono_class_get_method_from_name (mono_defaults.marshal_class, "GetExceptionForHR", 1);
-       ex = (MonoException*)mono_runtime_invoke (throw_exception_for_hr, NULL, params, NULL);
-       mono_raise_exception (ex);
+
+       ex = (MonoException*)mono_runtime_invoke_checked (throw_exception_for_hr, NULL, params, &error);
+       mono_error_assert_ok (&error);
+
+       mono_error_set_exception_instance (oerror, ex);
 }
 
 /**
- * cominterop_get_interface:
+ * 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
+ * Returns: the COM interface requested. On failure returns NULL and sets @error
  */
 static gpointer
-cominterop_get_interface (MonoComObject* obj, MonoClass* ic, gboolean throw_exception)
+cominterop_get_interface_checked (MonoComObject* obj, MonoClass* ic, MonoError *error)
 {
        gpointer itf = NULL;
 
        g_assert (ic);
        g_assert (MONO_CLASS_IS_INTERFACE (ic));
 
+       mono_error_init (error);
+
        mono_cominterop_lock ();
        if (obj->itf_hash)
                itf = g_hash_table_lookup (obj->itf_hash, GUINT_TO_POINTER ((guint)ic->interface_id));
@@ -493,8 +513,8 @@ cominterop_get_interface (MonoComObject* obj, MonoClass* ic, gboolean throw_exce
                int hr;
                g_assert(found);
                hr = ves_icall_System_Runtime_InteropServices_Marshal_QueryInterfaceInternal (obj->iunknown, iid, &itf);
-               if (hr < 0 && throw_exception) {
-                       cominterop_raise_hr_exception (hr);     
+               if (hr < 0) {
+                       cominterop_set_hr_error (error, hr);
                }
 
                if (hr >= 0 && itf) {
@@ -506,6 +526,30 @@ cominterop_get_interface (MonoComObject* obj, MonoClass* ic, gboolean throw_exce
                }
 
        }
+       return itf;
+}
+
+/**
+ * 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, MonoClass *ic, gboolean throw_exception)
+{
+       MonoError error;
+       gpointer itf = cominterop_get_interface_checked (obj, ic, &error);
+       if (!is_ok (&error)) {
+               if (throw_exception) {
+                       mono_error_set_pending_exception (&error);
+                       return NULL;
+               } else {
+                       mono_error_cleanup (&error);
+               }
+       }
+
        if (throw_exception)
                g_assert (itf);
 
@@ -530,7 +574,7 @@ cominterop_type_from_handle (MonoType *handle)
        mono_class_init (klass);
 
        ret = mono_type_get_object_checked (domain, handle, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       mono_error_set_pending_exception (&error);
 
        return ret;
 }
@@ -597,7 +641,6 @@ mono_cominterop_emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type,
        case MONO_MARSHAL_CONV_OBJECT_INTERFACE:
        case MONO_MARSHAL_CONV_OBJECT_IUNKNOWN:
        case MONO_MARSHAL_CONV_OBJECT_IDISPATCH: {
-               static MonoClass* com_interop_proxy_class = NULL;
                static MonoMethod* com_interop_proxy_get_proxy = NULL;
                static MonoMethod* get_transparent_proxy = NULL;
                guint32 pos_null = 0, pos_ccw = 0, pos_end = 0;
@@ -622,16 +665,14 @@ mono_cominterop_emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type,
                mono_mb_emit_icall (mb, cominterop_get_ccw_object);
                pos_ccw = mono_mb_emit_short_branch (mb, CEE_BRTRUE_S);
 
-               if (!com_interop_proxy_class)
-                       com_interop_proxy_class = mono_class_from_name (mono_defaults.corlib, "Mono.Interop", "ComInteropProxy");
                if (!com_interop_proxy_get_proxy)
-                       com_interop_proxy_get_proxy = mono_class_get_method_from_name_flags (com_interop_proxy_class, "GetProxy", 2, METHOD_ATTRIBUTE_PRIVATE);
+                       com_interop_proxy_get_proxy = mono_class_get_method_from_name_flags (mono_class_get_interop_proxy_class (), "GetProxy", 2, METHOD_ATTRIBUTE_PRIVATE);
 #ifndef DISABLE_REMOTING
                if (!get_transparent_proxy)
                        get_transparent_proxy = mono_class_get_method_from_name (mono_defaults.real_proxy_class, "GetTransparentProxy", 0);
 #endif
 
-               mono_mb_add_local (mb, &com_interop_proxy_class->byval_arg);
+               mono_mb_add_local (mb, &mono_class_get_interop_proxy_class ()->byval_arg);
 
                mono_mb_emit_ldloc (mb, 0);
                mono_mb_emit_byte (mb, CEE_LDIND_I);
@@ -890,7 +931,7 @@ mono_cominterop_get_native_wrapper (MonoMethod *method)
        
        if (!method->klass->methods)
                mono_class_setup_methods (method->klass);
-       g_assert (!method->klass->exception_type); /*FIXME do proper error handling*/
+       g_assert (!mono_class_has_failure (method->klass)); /*FIXME do proper error handling*/
 
        sig = mono_method_signature (method);
        mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_COMINTEROP);
@@ -1033,13 +1074,10 @@ mono_cominterop_get_invoke (MonoMethod *method)
        }
 
        if (!strcmp(method->name, ".ctor"))     {
-               static MonoClass *com_interop_proxy_class = NULL;
                static MonoMethod *cache_proxy = NULL;
 
-               if (!com_interop_proxy_class)
-                       com_interop_proxy_class = mono_class_from_name (mono_defaults.corlib, "Mono.Interop", "ComInteropProxy");
                if (!cache_proxy)
-                       cache_proxy = mono_class_get_method_from_name (com_interop_proxy_class, "CacheProxy", 0);
+                       cache_proxy = mono_class_get_method_from_name (mono_class_get_interop_proxy_class (), "CacheProxy", 0);
 
                mono_mb_emit_ldarg (mb, 0);
                mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoTransparentProxy, rp));
@@ -1441,20 +1479,23 @@ static gboolean cominterop_can_support_dispatch (MonoClass* klass)
 }
 
 static void*
-cominterop_get_idispatch_for_object (MonoObject* object)
+cominterop_get_idispatch_for_object (MonoObject* object, MonoError *error)
 {
+       mono_error_init (error);
        if (!object)
                return NULL;
 
        if (cominterop_object_is_rcw (object)) {
-               return cominterop_get_interface (((MonoComInteropProxy*)((MonoTransparentProxy*)object)->rp)->com_object, 
-                       mono_class_get_idispatch_class (), TRUE);
+               return cominterop_get_interface_checked (((MonoComInteropProxy*)((MonoTransparentProxy*)object)->rp)->com_object,
+                                                        mono_class_get_idispatch_class (), error);
        }
        else {
                MonoClass* klass = mono_object_class (object);
-               if (!cominterop_can_support_dispatch (klass) )
-                       cominterop_raise_hr_exception (MONO_E_NOINTERFACE);
-               return cominterop_get_ccw (object, mono_class_get_idispatch_class ());
+               if (!cominterop_can_support_dispatch (klass) ) {
+                       cominterop_set_hr_error (error, MONO_E_NOINTERFACE);
+                       return NULL;
+               }
+               return cominterop_get_ccw_checked (object, mono_class_get_idispatch_class (), error);
        }
 }
 
@@ -1462,6 +1503,8 @@ void*
 ves_icall_System_Runtime_InteropServices_Marshal_GetIUnknownForObjectInternal (MonoObject* object)
 {
 #ifndef DISABLE_COM
+       MonoError error;
+
        if (!object)
                return NULL;
 
@@ -1496,7 +1539,9 @@ ves_icall_System_Runtime_InteropServices_Marshal_GetIUnknownForObjectInternal (M
                return ((MonoComInteropProxy*)real_proxy)->com_object->iunknown;
        }
        else {
-               return cominterop_get_ccw (object, mono_class_get_iunknown_class ());
+               void* ccw_entry = cominterop_get_ccw_checked (object, mono_class_get_iunknown_class (), &error);
+               mono_error_set_pending_exception (&error);
+               return ccw_entry;
        }
 #else
        g_assert_not_reached ();
@@ -1525,7 +1570,10 @@ void*
 ves_icall_System_Runtime_InteropServices_Marshal_GetIDispatchForObjectInternal (MonoObject* object)
 {
 #ifndef DISABLE_COM
-       return cominterop_get_idispatch_for_object (object);
+       MonoError error;
+       void* idisp = cominterop_get_idispatch_for_object (object, &error);
+       mono_error_set_pending_exception (&error);
+       return idisp;
 #else
        g_assert_not_reached ();
 #endif
@@ -1535,6 +1583,7 @@ void*
 ves_icall_System_Runtime_InteropServices_Marshal_GetCCW (MonoObject* object, MonoReflectionType* type)
 {
 #ifndef DISABLE_COM
+       MonoError error;
        MonoClass* klass = NULL;
        void* itf = NULL;
        g_assert (type);
@@ -1546,8 +1595,8 @@ ves_icall_System_Runtime_InteropServices_Marshal_GetCCW (MonoObject* object, Mon
                return NULL;
        }
 
-       itf = cominterop_get_ccw (object, klass);
-       g_assert (itf);
+       itf = cominterop_get_ccw_checked (object, klass, &error);
+       mono_error_set_pending_exception (&error);
        return itf;
 #else
        g_assert_not_reached ();
@@ -1622,7 +1671,9 @@ ves_icall_System_ComObject_CreateRCW (MonoReflectionType *type)
         * is called by the corresponding real proxy to create the real RCW.
         * Constructor does not need to be called. Will be called later.
        */
-       obj = mono_object_new_alloc_specific_checked (mono_class_vtable_full (domain, klass, TRUE), &error);
+       MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
+       mono_error_raise_exception (&error);
+       obj = mono_object_new_alloc_specific_checked (vtable, &error);
        mono_error_raise_exception (&error);
 
        return obj;
@@ -1702,13 +1753,19 @@ gpointer
 ves_icall_System_ComObject_GetInterfaceInternal (MonoComObject* obj, MonoReflectionType* type, MonoBoolean throw_exception)
 {
 #ifndef DISABLE_COM
+       MonoError error;
        MonoClass *klass = mono_type_get_class (type->type);
        if (!mono_class_init (klass)) {
                mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
                return NULL;
        }
 
-       return cominterop_get_interface (obj, klass, (gboolean)throw_exception);
+       gpointer itf = cominterop_get_interface_checked (obj, klass, &error);
+       if (throw_exception)
+               mono_error_set_pending_exception (&error);
+       else
+               mono_error_cleanup (&error);
+       return itf;
 #else
        g_assert_not_reached ();
 #endif
@@ -1816,15 +1873,17 @@ cominterop_setup_marshal_context (EmitMarshalContext *m, MonoMethod *method)
 }
 
 /**
- * cominterop_get_ccw:
+ * 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
+ * Runtime Callable Wrapper (RCW) for a COM object.
+ * On failure returns NULL and sets @error.
  */
 static gpointer
-cominterop_get_ccw (MonoObject* object, MonoClass* itf)
+cominterop_get_ccw_checked (MonoObject* object, MonoClass* itf, MonoError *error)
 {
        int i;
        MonoCCW *ccw = NULL;
@@ -1840,6 +1899,8 @@ cominterop_get_ccw (MonoObject* object, MonoClass* itf)
        GList *ccw_list, *ccw_list_item;
        MonoCustomAttrInfo *cinfo = NULL;
 
+       mono_error_init (error);
+       
        if (!object)
                return NULL;
 
@@ -1897,14 +1958,16 @@ cominterop_get_ccw (MonoObject* object, MonoClass* itf)
                g_hash_table_insert (ccw_hash, GINT_TO_POINTER (mono_object_hash (object)), ccw_list);
                mono_cominterop_unlock ();
                /* register for finalization to clean up ccw */
-               mono_object_register_finalizer (object);
+               mono_object_register_finalizer (object, error);
+               return_val_if_nok (error, NULL);
        }
 
-       cinfo = mono_custom_attrs_from_class (itf);
+       cinfo = mono_custom_attrs_from_class_checked (itf, error);
+       mono_error_assert_ok (error);
        if (cinfo) {
                static MonoClass* coclass_attribute = NULL;
                if (!coclass_attribute)
-                       coclass_attribute = mono_class_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "CoClassAttribute");
+                       coclass_attribute = mono_class_load_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "CoClassAttribute");
                if (mono_custom_attrs_has_attr (cinfo, coclass_attribute)) {
                        g_assert(itf->interface_count && itf->interfaces[0]);
                        itf = itf->interfaces[0];
@@ -2043,6 +2106,23 @@ cominterop_get_ccw (MonoObject* object, MonoClass* itf)
        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, MonoClass* itf)
+{
+       MonoError error;
+       gpointer ccw_entry = cominterop_get_ccw_checked (object, itf, &error);
+       mono_error_set_pending_exception (&error);
+       return ccw_entry;
+}
+
 static gboolean
 mono_marshal_free_ccw_entry (gpointer key, gpointer value, gpointer user_data)
 {
@@ -2321,10 +2401,12 @@ static int
 cominterop_ccw_getfreethreadedmarshaler (MonoCCW* ccw, MonoObject* object, gpointer* ppv)
 {
 #ifdef HOST_WIN32
+       MonoError error;
        if (!ccw->free_marshaler) {
                int ret = 0;
                gpointer tunk;
-               tunk = cominterop_get_ccw (object, mono_class_get_iunknown_class ());
+               tunk = cominterop_get_ccw_checked (object, mono_class_get_iunknown_class (), &error);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
                ret = CoCreateFreeThreadedMarshaler (tunk, (LPUNKNOWN*)&ccw->free_marshaler);
        }
                
@@ -2361,7 +2443,8 @@ cominterop_ccw_queryinterface (MonoCCWInterface* ccwe, guint8* riid, gpointer* p
 
        /* handle IUnknown special */
        if (cominterop_class_guid_equal (riid, mono_class_get_iunknown_class ())) {
-               *ppv = cominterop_get_ccw (object, 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 ((MonoCCWInterface *)*ppv);
                return MONO_S_OK;
@@ -2372,7 +2455,8 @@ cominterop_ccw_queryinterface (MonoCCWInterface* ccwe, guint8* riid, gpointer* p
                if (!cominterop_can_support_dispatch (klass))
                        return MONO_E_NOINTERFACE;
                
-               *ppv = cominterop_get_ccw (object, mono_class_get_idispatch_class ());
+               *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 ((MonoCCWInterface *)*ppv);
                return MONO_S_OK;
@@ -2406,7 +2490,11 @@ cominterop_ccw_queryinterface (MonoCCWInterface* ccwe, guint8* riid, gpointer* p
                klass_iter = klass_iter->parent;
        }
        if (itf) {
-               *ppv = cominterop_get_ccw (object, 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 ((MonoCCWInterface *)*ppv);
                return MONO_S_OK;
@@ -2438,6 +2526,7 @@ cominterop_ccw_get_ids_of_names (MonoCCWInterface* ccwe, gpointer riid,
                                                                                         guint32 lcid, gint32 *rgDispId)
 {
        static MonoClass *ComDispIdAttribute = NULL;
+       MonoError error;
        MonoCustomAttrInfo *cinfo = NULL;
        int i,ret = MONO_S_OK;
        MonoMethod* method;
@@ -2448,7 +2537,7 @@ cominterop_ccw_get_ids_of_names (MonoCCWInterface* ccwe, gpointer riid,
 
        /* Handle DispIdAttribute */
        if (!ComDispIdAttribute)
-               ComDispIdAttribute = mono_class_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "DispIdAttribute");
+               ComDispIdAttribute = mono_class_load_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "DispIdAttribute");
 
        g_assert (object);
        klass = mono_object_class (object);
@@ -2461,9 +2550,9 @@ cominterop_ccw_get_ids_of_names (MonoCCWInterface* ccwe, gpointer riid,
 
                method = mono_class_get_method_from_name(klass, methodname, -1);
                if (method) {
-                       cinfo = mono_custom_attrs_from_method (method);
+                       cinfo = mono_custom_attrs_from_method_checked (method, &error);
+                       mono_error_assert_ok (&error); /* FIXME what's reasonable to do here */
                        if (cinfo) {
-                               MonoError error;
                                MonoObject *result = mono_custom_attrs_get_attr_checked (cinfo, ComDispIdAttribute, &error);
                                g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/;
 
@@ -2660,27 +2749,32 @@ mono_string_to_bstr (MonoString *string_obj)
 MonoString *
 mono_string_from_bstr (gpointer bstr)
 {
+       MonoError error;
+       MonoString * res = NULL;
+       
        if (!bstr)
                return NULL;
 #ifdef HOST_WIN32
-       return mono_string_new_utf16 (mono_domain_get (), bstr, SysStringLen (bstr));
+       res = mono_string_new_utf16_checked (mono_domain_get (), bstr, SysStringLen (bstr), &error);
 #else
        if (com_provider == MONO_COM_DEFAULT) {
-               return mono_string_new_utf16 (mono_domain_get (), (const mono_unichar2 *)bstr, *((guint32 *)bstr - 1) / sizeof(gunichar2));
+               res = mono_string_new_utf16_checked (mono_domain_get (), (const mono_unichar2 *)bstr, *((guint32 *)bstr - 1) / sizeof(gunichar2), &error);
        } else if (com_provider == MONO_COM_MS && init_com_provider_ms ()) {
                MonoString* str = NULL;
                glong written = 0;
                gunichar2* utf16 = NULL;
 
                utf16 = g_ucs4_to_utf16 ((const gunichar *)bstr, sys_string_len_ms (bstr), NULL, &written, NULL);
-               str = mono_string_new_utf16 (mono_domain_get (), utf16, written);
+               str = mono_string_new_utf16_checked (mono_domain_get (), utf16, written, &error);
                g_free (utf16);
-               return str;
+               res = str;
        } else {
                g_assert_not_reached ();
        }
 
 #endif
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       return res;
 }
 
 void
@@ -3041,13 +3135,15 @@ mono_marshal_safearray_begin (gpointer safearray, MonoArray **result, gpointer *
 
                                hr = mono_marshal_safe_array_get_lbound (safearray, i+1, &lbound);
                                if (hr < 0) {
-                                       cominterop_raise_hr_exception (hr);
+                                       cominterop_set_hr_error (&error, hr);
+                                       mono_error_raise_exception (&error); /* FIXME don't raise here */
                                }
                                if (lbound != 0)
                                        bounded = TRUE;
                                hr = mono_marshal_safe_array_get_ubound (safearray, i+1, &ubound);
                                if (hr < 0) {
-                                       cominterop_raise_hr_exception (hr);
+                                       cominterop_set_hr_error (&error, hr);
+                                       mono_error_raise_exception (&error); /* FIXME don't raise here */
                                }
                                cursize = ubound-lbound+1;
                                sizes [i] = cursize;
@@ -3074,17 +3170,20 @@ mono_marshal_safearray_begin (gpointer safearray, MonoArray **result, gpointer *
 static 
 gpointer mono_marshal_safearray_get_value (gpointer safearray, gpointer indices)
 {
+       MonoError error;
        gpointer result;
 #ifdef HOST_WIN32
        int hr = SafeArrayPtrOfIndex (safearray, indices, &result);
        if (hr < 0) {
-               cominterop_raise_hr_exception (hr);
+                       cominterop_set_hr_error (&error, hr);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
        }
 #else
        if (com_provider == MONO_COM_MS && init_com_provider_ms ()) {
                int hr = safe_array_ptr_of_index_ms (safearray, (glong *)indices, &result);
                if (hr < 0) {
-                       cominterop_raise_hr_exception (hr);
+                       cominterop_set_hr_error (&error, hr);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
                }
        } else {
                g_assert_not_reached ();
@@ -3096,6 +3195,7 @@ gpointer mono_marshal_safearray_get_value (gpointer safearray, gpointer indices)
 static 
 gboolean mono_marshal_safearray_next (gpointer safearray, gpointer indices)
 {
+       MonoError error;
        int i;
        int dim = mono_marshal_safearray_get_dim (safearray);
        gboolean ret= TRUE;
@@ -3108,7 +3208,8 @@ gboolean mono_marshal_safearray_next (gpointer safearray, gpointer indices)
 
                hr = mono_marshal_safe_array_get_ubound (safearray, i+1, &ubound);
                if (hr < 0) {
-                       cominterop_raise_hr_exception (hr);
+                       cominterop_set_hr_error (&error, hr);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
                }
 
                if (++pIndices[i] <= ubound) {
@@ -3117,7 +3218,8 @@ gboolean mono_marshal_safearray_next (gpointer safearray, gpointer indices)
 
                hr = mono_marshal_safe_array_get_lbound (safearray, i+1, &lbound);
                if (hr < 0) {
-                       cominterop_raise_hr_exception (hr);
+                       cominterop_set_hr_error (&error, hr);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
                }
 
                pIndices[i] = lbound;
@@ -3192,15 +3294,19 @@ mono_marshal_safearray_create (MonoArray *input, gpointer *newsafearray, gpointe
 static 
 void mono_marshal_safearray_set_value (gpointer safearray, gpointer indices, gpointer value)
 {
+       MonoError error;
 #ifdef HOST_WIN32
        int hr = SafeArrayPutElement (safearray, indices, value);
-       if (hr < 0)
-               cominterop_raise_hr_exception (hr);
+       if (hr < 0) {
+               cominterop_set_hr_error (&error, hr);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
+       }
 #else
        if (com_provider == MONO_COM_MS && init_com_provider_ms ()) {
                int hr = safe_array_put_element_ms (safearray, (glong *)indices, (void **)value);
                if (hr < 0) {
-                       cominterop_raise_hr_exception (hr);
+                       cominterop_set_hr_error (&error, hr);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
                }
        } else
                g_assert_not_reached ();
@@ -3270,13 +3376,17 @@ mono_string_to_bstr (MonoString *string_obj)
 MonoString *
 mono_string_from_bstr (gpointer bstr)
 {
+       MonoString *res = NULL;
+       MonoError error;
        if (!bstr)
                return NULL;
 #ifdef HOST_WIN32
-       return mono_string_new_utf16 (mono_domain_get (), bstr, SysStringLen (bstr));
+       res = mono_string_new_utf16_checked (mono_domain_get (), bstr, SysStringLen (bstr), &error);
 #else
-       return mono_string_new_utf16 (mono_domain_get (), bstr, *((guint32 *)bstr - 1) / sizeof(gunichar2));
+       res = mono_string_new_utf16_checked (mono_domain_get (), bstr, *((guint32 *)bstr - 1) / sizeof(gunichar2), &error);
 #endif
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       return res;
 }
 
 void