[coop] Add missing coop checks for WFSO and WFMO.
[mono.git] / mono / metadata / cominterop.c
index f722716d1e6f80c2defff89c66e0395d25f37b88..31d794f6b1fd4f696056d7b627cef95a131acc09 100644 (file)
@@ -76,9 +76,9 @@ enum {
 #undef OPDEF
 
 /* This mutex protects the various cominterop related caches in MonoImage */
-#define mono_cominterop_lock() EnterCriticalSection (&cominterop_mutex)
-#define mono_cominterop_unlock() LeaveCriticalSection (&cominterop_mutex)
-static CRITICAL_SECTION cominterop_mutex;
+#define mono_cominterop_lock() mono_mutex_lock (&cominterop_mutex)
+#define mono_cominterop_unlock() mono_mutex_unlock (&cominterop_mutex)
+static mono_mutex_t cominterop_mutex;
 
 /* STDCALL on windows, CDECL everywhere else to work with XPCOM and MainWin COM */
 #ifdef  HOST_WIN32
@@ -524,8 +524,6 @@ cominterop_type_from_handle (MonoType *handle)
        MonoDomain *domain = mono_domain_get (); 
        MonoClass *klass = mono_class_from_mono_type (handle);
 
-       MONO_ARCH_SAVE_REGS;
-
        mono_class_init (klass);
        return mono_type_get_object (domain, handle);
 }
@@ -535,7 +533,7 @@ mono_cominterop_init (void)
 {
        const char* com_provider_env;
 
-       InitializeCriticalSection (&cominterop_mutex);
+       mono_mutex_init_recursive (&cominterop_mutex);
 
        com_provider_env = g_getenv ("MONO_COM");
        if (com_provider_env && !strcmp(com_provider_env, "MS"))
@@ -567,7 +565,7 @@ mono_cominterop_init (void)
 void
 mono_cominterop_cleanup (void)
 {
-       DeleteCriticalSection (&cominterop_mutex);
+       mono_mutex_destroy (&cominterop_mutex);
 }
 
 void
@@ -595,7 +593,6 @@ mono_cominterop_emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type,
                static MonoClass* com_interop_proxy_class = NULL;
                static MonoMethod* com_interop_proxy_get_proxy = NULL;
                static MonoMethod* get_transparent_proxy = NULL;
-               int real_proxy;
                guint32 pos_null = 0, pos_ccw = 0, pos_end = 0;
                MonoClass *klass = NULL; 
 
@@ -627,7 +624,7 @@ mono_cominterop_emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type,
                        get_transparent_proxy = mono_class_get_method_from_name (mono_defaults.real_proxy_class, "GetTransparentProxy", 0);
 #endif
 
-               real_proxy = mono_mb_add_local (mb, &com_interop_proxy_class->byval_arg);
+               mono_mb_add_local (mb, &com_interop_proxy_class->byval_arg);
 
                mono_mb_emit_ldloc (mb, 0);
                mono_mb_emit_byte (mb, CEE_LDIND_I);
@@ -984,7 +981,7 @@ mono_cominterop_get_invoke (MonoMethod *method)
        MonoMethodSignature *sig;
        MonoMethodBuilder *mb;
        MonoMethod *res;
-       int i, temp_obj;
+       int i;
        GHashTable* cache = mono_marshal_get_cache (&method->klass->image->cominterop_invoke_cache, mono_aligned_addr_hash, NULL);
 
        g_assert (method);
@@ -1001,7 +998,7 @@ mono_cominterop_get_invoke (MonoMethod *method)
        mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_COMINTEROP_INVOKE);
 
        /* get real proxy object, which is a ComInteropProxy in this case*/
-       temp_obj = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
+       mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
        mono_mb_emit_ldarg (mb, 0);
        mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoTransparentProxy, rp));
        mono_mb_emit_byte (mb, CEE_LDIND_REF);
@@ -1534,8 +1531,10 @@ ves_icall_System_Runtime_InteropServices_Marshal_GetCCW (MonoObject* object, Mon
        g_assert (type->type);
        klass = mono_type_get_class (type->type);
        g_assert (klass);
-       if (!mono_class_init (klass))
-               mono_raise_exception (mono_class_get_exception_for_failure (klass));
+       if (!mono_class_init (klass)) {
+               mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
+               return NULL;
+       }
 
        itf = cominterop_get_ccw (object, klass);
        g_assert (itf);
@@ -1588,8 +1587,6 @@ ves_icall_System_Runtime_InteropServices_Marshal_ReleaseComObjectInternal (MonoO
 guint32
 ves_icall_System_Runtime_InteropServices_Marshal_GetComSlotForMethodInfoInternal (MonoReflectionMethod *m)
 {
-       MONO_ARCH_SAVE_REGS;
-
 #ifndef DISABLE_COM
        return cominterop_get_com_slot_for_method (m->method);
 #else
@@ -1605,8 +1602,6 @@ ves_icall_System_ComObject_CreateRCW (MonoReflectionType *type)
        MonoDomain *domain;
        MonoObject *obj;
        
-       MONO_ARCH_SAVE_REGS;
-
        domain = mono_object_domain (type);
        klass = mono_class_from_mono_type (type->type);
 
@@ -1693,8 +1688,10 @@ ves_icall_System_ComObject_GetInterfaceInternal (MonoComObject* obj, MonoReflect
 {
 #ifndef DISABLE_COM
        MonoClass *class = mono_type_get_class (type->type);
-       if (!mono_class_init (class))
-               mono_raise_exception (mono_class_get_exception_for_failure (class));
+       if (!mono_class_init (class)) {
+               mono_set_pending_exception (mono_class_get_exception_for_failure (class));
+               return NULL;
+       }
 
        return cominterop_get_interface (obj, class, (gboolean)throw_exception);
 #else
@@ -2068,8 +2065,17 @@ mono_marshal_free_ccw (MonoObject* object)
                MonoObject* handle_target = mono_gchandle_get_target (ccw_iter->gc_handle);
 
                /* 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. */
-               if (!handle_target || handle_target == object) {
+                * 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 = !handle_target || handle_target == object;
+               if (!handle_target) {
+                       MonoCCWInterface* ccw_entry = g_hash_table_lookup (ccw_iter->vtable_hash, mono_class_get_iunknown_class ());
+                       if (!(ccw_entry && object == cominterop_get_ccw_object (ccw_entry, FALSE)))
+                               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);
@@ -2088,13 +2094,14 @@ mono_marshal_free_ccw (MonoObject* object)
                        g_free (ccw_iter);
                }
                else
-                       ccw_list_item = g_list_next(ccw_list_item);
+                       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_object_hash (object)));
-
+       else if (ccw_list != ccw_list_orig)
+               g_hash_table_insert (ccw_hash, GINT_TO_POINTER (mono_object_hash (object)), ccw_list);
 
        return TRUE;
 }
@@ -3299,23 +3306,17 @@ ves_icall_System_Runtime_InteropServices_Marshal_QueryInterfaceInternal (gpointe
 MonoString *
 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr)
 {
-       MONO_ARCH_SAVE_REGS;
-
        return mono_string_from_bstr(ptr);
 }
 
 gpointer
 ves_icall_System_Runtime_InteropServices_Marshal_StringToBSTR (MonoString* ptr)
 {
-       MONO_ARCH_SAVE_REGS;
-
        return mono_string_to_bstr(ptr);
 }
 
 void
 ves_icall_System_Runtime_InteropServices_Marshal_FreeBSTR (gpointer ptr)
 {
-       MONO_ARCH_SAVE_REGS;
-
        mono_free_bstr (ptr);
 }