#include "mono/metadata/attrdefs.h"
#include "mono/metadata/gc-internal.h"
#include "mono/utils/mono-counters.h"
+#include "mono/utils/strenc.h"
+#include "mono/utils/atomic.h"
#include <string.h>
#include <errno.h>
#define STDCALL
#endif
+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)
+
/* 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
if (!obj)
return FALSE;
klass = mono_object_class (obj);
- if (mono_class_is_transparent_proxy (klass))
+ if (!mono_class_is_transparent_proxy (klass))
return FALSE;
real_proxy = ((MonoTransparentProxy*)obj)->rp;
return FALSE;
klass = mono_object_class (real_proxy);
- return (klass && klass == mono_defaults.com_interop_proxy_class);
+ return (klass && klass == mono_class_get_interop_proxy_class ());
}
static int
void
mono_cominterop_init (void)
{
- char* com_provider_env = NULL;
+ const char* com_provider_env;
InitializeCriticalSection (&cominterop_mutex);
- com_provider_env = getenv ("MONO_COM");
+ com_provider_env = g_getenv ("MONO_COM");
if (com_provider_env && !strcmp(com_provider_env, "MS"))
com_provider = MONO_COM_MS;
int real_proxy;
guint32 pos_null = 0, pos_ccw = 0, pos_end = 0;
MonoClass *klass = NULL;
-
- /* COM types are initialized lazily */
- mono_init_com_types ();
klass = mono_class_from_mono_type (type);
mono_mb_emit_ldloc (mb, 0);
mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_ptr (mb, &mono_defaults.com_object_class->byval_arg);
+ mono_mb_emit_ptr (mb, &mono_class_get_com_object_class ()->byval_arg);
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);
case MONO_MARSHAL_CONV_OBJECT_IDISPATCH:
case MONO_MARSHAL_CONV_OBJECT_IUNKNOWN: {
guint32 pos_null = 0, pos_rcw = 0, pos_end = 0;
-
- /* COM types are initialized lazily */
- mono_init_com_types ();
-
mono_mb_emit_ldloc (mb, 1);
mono_mb_emit_icon (mb, 0);
static MonoProperty* iunknown = NULL;
if (!iunknown)
- iunknown = mono_class_get_property_from_name (mono_defaults.com_object_class, "IUnknown");
+ iunknown = mono_class_get_property_from_name (mono_class_get_com_object_class (), "IUnknown");
mono_mb_emit_managed_call (mb, iunknown->get, NULL);
}
else if (conv == MONO_MARSHAL_CONV_OBJECT_IDISPATCH) {
static MonoProperty* idispatch = NULL;
if (!idispatch)
- idispatch = mono_class_get_property_from_name (mono_defaults.com_object_class, "IDispatch");
+ idispatch = mono_class_get_property_from_name (mono_class_get_com_object_class (), "IDispatch");
mono_mb_emit_managed_call (mb, idispatch->get, NULL);
}
else {
if (conv == MONO_MARSHAL_CONV_OBJECT_INTERFACE)
mono_mb_emit_ptr (mb, mono_type_get_class (type));
else if (conv == MONO_MARSHAL_CONV_OBJECT_IUNKNOWN)
- mono_mb_emit_ptr (mb, mono_defaults.iunknown_class);
+ mono_mb_emit_ptr (mb, mono_class_get_iunknown_class ());
else if (conv == MONO_MARSHAL_CONV_OBJECT_IDISPATCH)
- mono_mb_emit_ptr (mb, mono_defaults.idispatch_class);
+ mono_mb_emit_ptr (mb, mono_class_get_idispatch_class ());
else
g_assert_not_reached ();
mono_mb_emit_icall (mb, cominterop_get_ccw);
if ((res = mono_marshal_find_in_cache (cache, method)))
return res;
- mono_init_com_types ();
-
if (!method->klass->vtable)
mono_class_setup_vtable (method->klass);
static MonoMethod *ctor = NULL;
if (!ctor)
- ctor = mono_class_get_method_from_name (mono_defaults.com_object_class, ".ctor", 0);
+ ctor = mono_class_get_method_from_name (mono_class_get_com_object_class (), ".ctor", 0);
mono_mb_emit_ldarg (mb, 0);
mono_mb_emit_managed_call (mb, ctor, NULL);
mono_mb_emit_byte (mb, CEE_RET);
if (!marshal_release)
marshal_release = mono_class_get_method_from_name (mono_defaults.marshal_class, "Release", 1);
- /* COM types are initialized lazily */
- mono_init_com_types ();
-
switch (action) {
case MARSHAL_ACTION_CONV_IN: {
guint32 pos_null = 0;
#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 (gpointer pUnk)
if (cominterop_object_is_rcw (object)) {
return cominterop_get_interface (((MonoComInteropProxy*)((MonoTransparentProxy*)object)->rp)->com_object,
- mono_defaults.idispatch_class, TRUE);
+ mono_class_get_idispatch_class (), TRUE);
}
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_defaults.idispatch_class);
+ return cominterop_get_ccw (object, mono_class_get_idispatch_class ());
}
}
if (!object)
return NULL;
- mono_init_com_types ();
-
if (cominterop_object_is_rcw (object)) {
MonoClass *klass = NULL;
MonoRealProxy* real_proxy = NULL;
if (!object)
return NULL;
klass = mono_object_class (object);
- if (mono_class_is_transparent_proxy (klass)) {
+ if (!mono_class_is_transparent_proxy (klass)) {
g_assert_not_reached ();
return NULL;
}
}
klass = mono_object_class (real_proxy);
- if (klass != mono_defaults.com_interop_proxy_class) {
+ if (klass != mono_class_get_interop_proxy_class ()) {
g_assert_not_reached ();
return NULL;
}
return ((MonoComInteropProxy*)real_proxy)->com_object->iunknown;
}
else {
- return cominterop_get_ccw (object, mono_defaults.iunknown_class);
+ return cominterop_get_ccw (object, mono_class_get_iunknown_class ());
}
#else
g_assert_not_reached ();
ves_icall_System_Runtime_InteropServices_Marshal_GetIDispatchForObjectInternal (MonoObject* object)
{
#ifndef DISABLE_COM
- mono_init_com_types ();
-
return cominterop_get_idispatch_for_object (object);
#else
g_assert_not_reached ();
}
iface = itf;
- if (iface == mono_defaults.iunknown_class) {
+ if (iface == mono_class_get_iunknown_class ()) {
start_slot = 3;
}
- else if (iface == mono_defaults.idispatch_class) {
+ else if (iface == mono_class_get_idispatch_class ()) {
start_slot = 7;
}
else {
cominterop_setup_marshal_context (&m, adjust_method);
m.mb = mb;
mono_marshal_emit_managed_wrapper (mb, sig_adjusted, mspecs, &m, adjust_method, 0);
- mono_loader_lock ();
mono_cominterop_lock ();
wrapper_method = mono_mb_create_method (mb, m.csig, m.csig->param_count + 16);
mono_cominterop_unlock ();
- mono_loader_unlock ();
vtable [vtable_index--] = mono_compile_method (wrapper_method);
mono_mb_emit_byte (mb, CEE_RET);
- mono_loader_lock ();
mono_cominterop_lock ();
res = mono_mb_create_method (mb, sig_native, sig_native->param_count + 16);
mono_cominterop_unlock ();
- mono_loader_unlock ();
mono_mb_free (mb);
if (!ccw->free_marshaler) {
int ret = 0;
gpointer tunk;
- tunk = cominterop_get_ccw (object, mono_defaults.iunknown_class);
+ tunk = cominterop_get_ccw (object, mono_class_get_iunknown_class ());
ret = CoCreateFreeThreadedMarshaler (tunk, (LPUNKNOWN*)&ccw->free_marshaler);
}
mono_thread_attach (mono_get_root_domain ());
/* handle IUnknown special */
- if (cominterop_class_guid_equal (riid, mono_defaults.iunknown_class)) {
- *ppv = cominterop_get_ccw (object, mono_defaults.iunknown_class);
+ if (cominterop_class_guid_equal (riid, mono_class_get_iunknown_class ())) {
+ *ppv = cominterop_get_ccw (object, mono_class_get_iunknown_class ());
/* remember to addref on QI */
cominterop_ccw_addref (*ppv);
return MONO_S_OK;
}
/* handle IDispatch special */
- if (cominterop_class_guid_equal (riid, mono_defaults.idispatch_class)) {
+ 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 (object, mono_defaults.idispatch_class);
+ *ppv = cominterop_get_ccw (object, mono_class_get_idispatch_class ());
/* remember to addref on QI */
cominterop_ccw_addref (*ppv);
return MONO_S_OK;
static int STDCALL
cominterop_ccw_get_type_info_count (MonoCCWInterface* ccwe, guint32 *pctinfo)
{
- return MONO_E_NOTIMPL;
+ if(!pctinfo)
+ return MONO_E_INVALIDARG;
+
+ *pctinfo = 1;
+
+ return MONO_S_OK;
}
static int STDCALL
gunichar2** rgszNames, guint32 cNames,
guint32 lcid, gint32 *rgDispId)
{
- return MONO_E_NOTIMPL;
+ 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
{
MonoMethodBuilder *mb = m->mb;
- mono_init_com_types ();
-
switch (action) {
case MARSHAL_ACTION_CONV_IN: {
get_native_variant_for_object = mono_class_get_method_from_name (mono_defaults.marshal_class, "GetNativeVariantForObject", 2);
g_assert (get_native_variant_for_object);
- elem_var = mono_mb_add_local (mb, &mono_defaults.variant_class->byval_arg);
+ elem_var = mono_mb_add_local (mb, &mono_class_get_variant_class ()->byval_arg);
mono_mb_emit_ldloc_addr (mb, elem_var);
mono_mb_emit_managed_call (mb, get_native_variant_for_object, NULL);
mono_mb_emit_icall (mb, mono_marshal_safearray_set_value);
if (!variant_clear)
- variant_clear = mono_class_get_method_from_name (mono_defaults.variant_class, "Clear", 0);
+ variant_clear = mono_class_get_method_from_name (mono_class_get_variant_class (), "Clear", 0);
mono_mb_emit_ldloc_addr (mb, elem_var);
mono_mb_emit_managed_call (mb, variant_clear, NULL);