Merge pull request #796 from alesliehughes/master
[mono.git] / mono / metadata / cominterop.c
index 8503fbf3f4e3b7e980b2e955b62390a725c31251..07a2e638c0b5747b09adc0438da16c2f39055e0f 100644 (file)
@@ -2408,32 +2408,51 @@ cominterop_ccw_get_ids_of_names (MonoCCWInterface* ccwe, gpointer riid,
                                                                                         gunichar2** rgszNames, guint32 cNames,
                                                                                         guint32 lcid, gint32 *rgDispId)
 {
-       int i,ret = MONO_S_OK;
-       MonoMethod* method;
-       gchar* methodname;
-       MonoClass *klass = NULL;
-       MonoCCW* ccw = ccwe->ccw;
-       MonoObject* object = mono_gchandle_get_target (ccw->gc_handle);
-
-       g_assert (object);
-       klass = mono_object_class (object);
-
-       if (!mono_domain_get ())
-               mono_thread_attach (mono_get_root_domain ());
-
-       for (i=0; i < cNames; i++) {
-               methodname = mono_unicode_to_external (rgszNames[i]);
-
-               method = mono_class_get_method_from_name(klass, methodname, -1);
-               if (method)
-                       rgDispId[i] = (gint32)method->token;
-               else {
-                       rgDispId[i] = MONO_E_DISPID_UNKNOWN;
-                       ret = MONO_E_DISP_E_UNKNOWNNAME;
-               }
-       }
-
-       return ret;
+       static MonoClass *ComDispIdAttribute = NULL;
+       MonoCustomAttrInfo *cinfo = NULL;
+       int i,ret = MONO_S_OK;
+       MonoMethod* method;
+       gchar* methodname;
+       MonoClass *klass = NULL;
+       MonoCCW* ccw = ccwe->ccw;
+       MonoObject* object = mono_gchandle_get_target (ccw->gc_handle);
+
+       /* Handle DispIdAttribute */
+       if (!ComDispIdAttribute)
+               ComDispIdAttribute = mono_class_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "DispIdAttribute");
+
+       g_assert (object);
+       klass = mono_object_class (object);
+
+       if (!mono_domain_get ())
+                mono_thread_attach (mono_get_root_domain ());
+
+       for (i=0; i < cNames; i++) {
+               methodname = mono_unicode_to_external (rgszNames[i]);
+
+               method = mono_class_get_method_from_name(klass, methodname, -1);
+               if (method) {
+                       cinfo = mono_custom_attrs_from_method (method);
+                       if (cinfo) {
+                               MonoObject *result = mono_custom_attrs_get_attr (cinfo, ComDispIdAttribute);
+
+                               if (result)
+                                       rgDispId[i] = *(gint32*)mono_object_unbox (result);
+                               else
+                                       rgDispId[i] = (gint32)method->token;
+
+                               if (!cinfo->cached)
+                                       mono_custom_attrs_free (cinfo);
+                       }
+                       else
+                               rgDispId[i] = (gint32)method->token;
+               } else {
+                       rgDispId[i] = MONO_E_DISPID_UNKNOWN;
+                       ret = MONO_E_DISP_E_UNKNOWNNAME;
+               }
+       }
+
+       return ret;
 }
 
 static int STDCALL