2010-01-18 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / metadata / cominterop.c
index 3fd1900ccb699ed032f79eaf958457f90aa5b186..bfb0dd5bf5725927291d67119323d99e6a459d33 100644 (file)
@@ -66,7 +66,7 @@ enum {
 static CRITICAL_SECTION cominterop_mutex;
 
 /* STDCALL on windows, CDECL everywhere else to work with XPCOM and MainWin COM */
-#ifdef  PLATFORM_WIN32
+#ifdef  HOST_WIN32
 #define STDCALL __stdcall
 #else
 #define STDCALL
@@ -81,7 +81,7 @@ typedef struct {
        guint32 ref_count;
        guint32 gc_handle;
        GHashTable* vtable_hash;
-#ifdef  PLATFORM_WIN32
+#ifdef  HOST_WIN32
        gpointer free_marshaler;
 #endif
 } MonoCCW;
@@ -195,7 +195,7 @@ cominterop_method_signature (MonoMethod* method)
        res->param_count = param_count;
 
        // STDCALL on windows, CDECL everywhere else to work with XPCOM and MainWin COM
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
        res->call_convention = MONO_CALL_STDCALL;
 #else
        res->call_convention = MONO_CALL_C;
@@ -277,18 +277,28 @@ cominterop_get_com_slot_begin (MonoClass* klass)
 static MonoClass*
 cominterop_get_method_interface (MonoMethod* method)
 {
+       MonoError 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(method->klass)) {
-               GPtrArray *ifaces = mono_class_get_implemented_interfaces (method->klass);
+               GPtrArray *ifaces = mono_class_get_implemented_interfaces (method->klass, &error);
+               g_assert (mono_error_ok (&error));
                if (ifaces) {
                        int i;
+                       mono_class_setup_vtable (method->klass);
                        for (i = 0; i < ifaces->len; ++i) {
-                               int offset;
+                               int j, offset;
+                               gboolean found = FALSE;
                                ic = g_ptr_array_index (ifaces, i);
                                offset = mono_class_interface_offset (method->klass, ic);
-                               if (method->slot >= offset && method->slot < offset + ic->method.count)
+                               for (j = 0; j < ic->method.count; ++j) {
+                                       if (method->klass->vtable [j + offset] == method) {
+                                               found = TRUE;
+                                               break;
+                                       }
+                               }
+                               if (found)
                                        break;
                                ic = NULL;
                        }
@@ -296,7 +306,8 @@ cominterop_get_method_interface (MonoMethod* method)
                }
        }
 
-       g_assert (ic);
+       if (!ic) 
+               g_assert (ic);
        g_assert (MONO_CLASS_IS_INTERFACE (ic));
 
        return ic;
@@ -317,10 +328,17 @@ cominterop_get_com_slot_for_method (MonoMethod* method)
        /* if method is on a class, we need to look up interface method exists on */
        if (!MONO_CLASS_IS_INTERFACE(ic)) {
                int offset = 0;
+               int i = 0;
                ic = cominterop_get_method_interface (method);
                offset = mono_class_interface_offset (method->klass, ic);
                g_assert(offset >= 0);
-               slot -= offset;
+               for(i = 0; i < ic->method.count; ++i) {
+                       if (method->klass->vtable [i + offset] == method)
+                       {
+                               slot = ic->methods[i]->slot;
+                               break;
+                       }
+               }
        }
 
        g_assert (ic);
@@ -362,6 +380,7 @@ static gboolean
 cominterop_com_visible (MonoClass* klass)
 {
        static MonoClass *ComVisibleAttribute = NULL;
+       MonoError error;
        MonoCustomAttrInfo *cinfo;
        GPtrArray *ifaces;
        MonoBoolean visible = 0;
@@ -382,7 +401,8 @@ cominterop_com_visible (MonoClass* klass)
                        return TRUE;
        }
 
-       ifaces = mono_class_get_implemented_interfaces (klass);
+       ifaces = mono_class_get_implemented_interfaces (klass, &error);
+       g_assert (mono_error_ok (&error));
        if (ifaces) {
                int i;
                for (i = 0; i < ifaces->len; ++i) {
@@ -840,6 +860,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*/
 
        sig = mono_method_signature (method);
        mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_COMINTEROP);
@@ -1763,7 +1784,7 @@ cominterop_setup_marshal_context (EmitMarshalContext *m, MonoMethod *method)
        /* csig = mono_metadata_signature_dup (sig); */
        
        /* STDCALL on windows, CDECL everywhere else to work with XPCOM and MainWin COM */
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
        csig->call_convention = MONO_CALL_STDCALL;
 #else
        csig->call_convention = MONO_CALL_C;
@@ -1842,7 +1863,7 @@ cominterop_get_ccw (MonoObject* object, MonoClass* itf)
 
        if (!ccw) {
                ccw = g_new0 (MonoCCW, 1);
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
                ccw->free_marshaler = 0;
 #endif
                ccw->vtable_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
@@ -2257,7 +2278,7 @@ cominterop_ccw_release (MonoCCWInterface* ccwe)
                /* allow gc of object */
                guint32 oldhandle = ccw->gc_handle;
                g_assert (oldhandle);
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
                if (ccw->free_marshaler)
                        ves_icall_System_Runtime_InteropServices_Marshal_ReleaseInternal (ccw->free_marshaler);
 #endif
@@ -2267,16 +2288,16 @@ cominterop_ccw_release (MonoCCWInterface* ccwe)
        return ref_count;
 }
 
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
 static const IID MONO_IID_IMarshal = {0x3, 0x0, 0x0, {0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46}};
 #endif
 
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
 /* All ccw objects are free threaded */
 static int
 cominterop_ccw_getfreethreadedmarshaler (MonoCCW* ccw, MonoObject* object, gpointer* ppv)
 {
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
        if (!ccw->free_marshaler) {
                int ret = 0;
                gpointer tunk;
@@ -2300,6 +2321,7 @@ cominterop_ccw_getfreethreadedmarshaler (MonoCCW* ccw, MonoObject* object, gpoin
 static int STDCALL 
 cominterop_ccw_queryinterface (MonoCCWInterface* ccwe, guint8* riid, gpointer* ppv)
 {
+       MonoError error;
        GPtrArray *ifaces;
        MonoClass *itf = NULL;
        int i;
@@ -2336,7 +2358,7 @@ cominterop_ccw_queryinterface (MonoCCWInterface* ccwe, guint8* riid, gpointer* p
                return MONO_S_OK;
        }
 
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
        /* handle IMarshal special */
        if (0 == memcmp (riid, &MONO_IID_IMarshal, sizeof (IID))) {
                return cominterop_ccw_getfreethreadedmarshaler (ccw, object, ppv);      
@@ -2344,7 +2366,8 @@ cominterop_ccw_queryinterface (MonoCCWInterface* ccwe, guint8* riid, gpointer* p
 #endif
        klass_iter = klass;
        while (klass_iter && klass_iter != mono_defaults.object_class) {
-               ifaces = mono_class_get_implemented_interfaces (klass_iter);
+               ifaces = mono_class_get_implemented_interfaces (klass_iter, &error);
+               g_assert (mono_error_ok (&error));
                if (ifaces) {
                        for (i = 0; i < ifaces->len; ++i) {
                                MonoClass *ic = NULL;
@@ -2504,7 +2527,7 @@ mono_string_to_bstr (MonoString *string_obj)
 {
        if (!string_obj)
                return NULL;
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
        return SysAllocStringLen (mono_string_chars (string_obj), mono_string_length (string_obj));
 #else
        if (com_provider == MONO_COM_DEFAULT) {
@@ -2540,7 +2563,7 @@ mono_string_from_bstr (gpointer bstr)
 {
        if (!bstr)
                return NULL;
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
        return mono_string_new_utf16 (mono_domain_get (), bstr, SysStringLen (bstr));
 #else
        if (com_provider == MONO_COM_DEFAULT) {
@@ -2566,7 +2589,7 @@ mono_free_bstr (gpointer bstr)
 {
        if (!bstr)
                return;
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
        SysFreeString ((BSTR)bstr);
 #else
        if (com_provider == MONO_COM_DEFAULT) {
@@ -2699,7 +2722,7 @@ static
 guint32 mono_marshal_safearray_get_dim (gpointer safearray)
 {
        guint32 result=0;
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
        result = SafeArrayGetDim (safearray);
 #else
        if (com_provider == MONO_COM_MS && init_com_provider_ms ()) {
@@ -2715,7 +2738,7 @@ static
 int mono_marshal_safe_array_get_lbound (gpointer psa, guint nDim, glong* plLbound)
 {
        int result=MONO_S_OK;
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
        result = SafeArrayGetLBound (psa, nDim, plLbound);
 #else
        if (com_provider == MONO_COM_MS && init_com_provider_ms ()) {
@@ -2731,7 +2754,7 @@ static
 int mono_marshal_safe_array_get_ubound (gpointer psa, guint nDim, glong* plUbound)
 {
        int result=MONO_S_OK;
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
        result = SafeArrayGetUBound (psa, nDim, plUbound);
 #else
        if (com_provider == MONO_COM_MS && init_com_provider_ms ()) {
@@ -2753,7 +2776,7 @@ mono_marshal_safearray_begin (gpointer safearray, MonoArray **result, gpointer *
        int i;
        gboolean bounded = FALSE;
 
-#ifndef PLATFORM_WIN32
+#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
@@ -2807,7 +2830,7 @@ static
 gpointer mono_marshal_safearray_get_value (gpointer safearray, gpointer indices)
 {
        gpointer result;
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
        int hr = SafeArrayPtrOfIndex (safearray, indices, &result);
        if (hr < 0) {
                cominterop_raise_hr_exception (hr);
@@ -2864,7 +2887,7 @@ static
 void mono_marshal_safearray_end (gpointer safearray, gpointer indices)
 {
        g_free(indices);
-#ifdef PLATFORM_WIN32
+#ifdef HOST_WIN32
        SafeArrayDestroy (safearray);
 #else
        if (com_provider == MONO_COM_MS && init_com_provider_ms ()) {