Author: joncham
Date: 2006-08-10 22:26:15 -0400 (Thu, 10 Aug 2006)
New Revision: 63629
Modified:
trunk/mono/mono/metadata/ChangeLog
trunk/mono/mono/metadata/class-internals.h
trunk/mono/mono/metadata/class.c
trunk/mono/mono/metadata/icall.c
trunk/mono/mono/metadata/marshal.c
trunk/mono/mono/metadata/object.c
trunk/mono/mono/mini/ChangeLog
trunk/mono/mono/mini/mini.c
trunk/mono/mono/tests/ChangeLog
trunk/mono/mono/tests/cominterop.cs
trunk/mono/mono/tests/libtest.c
Log:
2006-08-10 Jonathan Chambers <[EMAIL PROTECTED]>
* class.c (mono_class_setup_parent): setup is_com_object during class
initialization.
* object.c (mono_remote_class_vtable/mono_object_new_specific): Changed
checks
to use is_com_object instead of MONO_CLASS_IS_IMPORT() macro.
* class-internals.h: add is_com_object to class structure.
* marshal.c: Fixed marshalling for IDispatch and IUnknown, added
null checks to COM object marshalling. Fix .ctor call on RCW.
* icall.c: Added icall implementation for MonoType.IsCOMObjectImpl.
* mini.c: Don't verify COM proxy invoke calls
All code is contributed under the MIT/X11 license.
Modified: trunk/mono/mono/metadata/ChangeLog
===================================================================
--- trunk/mono/mono/metadata/ChangeLog 2006-08-11 00:19:34 UTC (rev 63628)
+++ trunk/mono/mono/metadata/ChangeLog 2006-08-11 02:26:15 UTC (rev 63629)
@@ -1,3 +1,15 @@
+2006-08-10 Jonathan Chambers <[EMAIL PROTECTED]>
+
+ * class.c (mono_class_setup_parent): setup is_com_object during class
initialization.
+ * object.c (mono_remote_class_vtable/mono_object_new_specific): Changed
checks
+ to use is_com_object instead of MONO_CLASS_IS_IMPORT() macro.
+ * class-internals.h: add is_com_object to class structure.
+ * marshal.c: Fixed marshalling for IDispatch and IUnknown, added
+ null checks to COM object marshalling. Fix .ctor call on RCW.
+ * icall.c: Added icall implementation for MonoType.IsCOMObjectImpl.
+
+ All code is contributed under the MIT/X11 license.
+
2006-08-09 Dick Porter <[EMAIL PROTECTED]>
* monitor.c (mono_monitor_cleanup): mono_monitor_cleanup() is
Modified: trunk/mono/mono/metadata/class-internals.h
===================================================================
--- trunk/mono/mono/metadata/class-internals.h 2006-08-11 00:19:34 UTC (rev
63628)
+++ trunk/mono/mono/metadata/class-internals.h 2006-08-11 02:26:15 UTC (rev
63629)
@@ -268,6 +268,12 @@
/* next byte */
guint has_static_refs : 1; /* it has static fields that are GC-tracked
*/
guint no_special_static_fields : 1; /* has no thread/context static
fields */
+ /* directly or indirectly derives from ComImport attributed class.
+ * this means we need to create a proxy for instances of this class
+ * for COM Interop. set this flag on loading so all we need is a quick
check
+ * during object creation rather than having to traverse supertypes
+ */
+ guint is_com_object : 1;
guint8 exception_type; /* MONO_EXCEPTION_* */
void* exception_data; /* Additional information about the
exception */
Modified: trunk/mono/mono/metadata/class.c
===================================================================
--- trunk/mono/mono/metadata/class.c 2006-08-11 00:19:34 UTC (rev 63628)
+++ trunk/mono/mono/metadata/class.c 2006-08-11 02:26:15 UTC (rev 63629)
@@ -2656,10 +2656,13 @@
if (!MONO_CLASS_IS_INTERFACE (class)) {
/* Imported COM Objects always derive from __ComObject. */
- if (MONO_CLASS_IS_IMPORT (class) && parent ==
mono_defaults.object_class)
- parent = mono_defaults.com_object_class;
+ if (MONO_CLASS_IS_IMPORT (class)) {
+ if (parent == mono_defaults.object_class)
+ parent = mono_defaults.com_object_class;
+ }
class->parent = parent;
+
if (!parent)
g_assert_not_reached (); /* FIXME */
@@ -2675,6 +2678,10 @@
class->marshalbyref = parent->marshalbyref;
class->contextbound = parent->contextbound;
class->delegate = parent->delegate;
+ if (MONO_CLASS_IS_IMPORT (class))
+ class->is_com_object = 1;
+ else
+ class->is_com_object = parent->is_com_object;
if (system_namespace) {
if (*class->name == 'M' && !strcmp (class->name,
"MarshalByRefObject"))
Modified: trunk/mono/mono/metadata/icall.c
===================================================================
--- trunk/mono/mono/metadata/icall.c 2006-08-11 00:19:34 UTC (rev 63628)
+++ trunk/mono/mono/metadata/icall.c 2006-08-11 02:26:15 UTC (rev 63629)
@@ -1819,6 +1819,15 @@
return type->type->byref;
}
+static MonoBoolean
+ves_icall_type_iscomobject (MonoReflectionType *type)
+{
+ MonoClass *klass = mono_class_from_mono_type (type->type);
+ MONO_ARCH_SAVE_REGS;
+
+ return (klass && klass->is_com_object);
+}
+
static MonoReflectionModule*
ves_icall_MonoType_get_Module (MonoReflectionType *type)
{
@@ -6756,6 +6765,7 @@
{"GetPropertiesByName", ves_icall_Type_GetPropertiesByName},
{"InternalGetEvent", ves_icall_MonoType_GetEvent},
{"IsByRefImpl", ves_icall_type_isbyref},
+ {"IsCOMObjectImpl", ves_icall_type_iscomobject},
{"IsPointerImpl", ves_icall_type_ispointer},
{"IsPrimitiveImpl", ves_icall_type_isprimitive},
{"getFullName", ves_icall_System_MonoType_getFullName},
Modified: trunk/mono/mono/metadata/marshal.c
===================================================================
--- trunk/mono/mono/metadata/marshal.c 2006-08-11 00:19:34 UTC (rev 63628)
+++ trunk/mono/mono/metadata/marshal.c 2006-08-11 02:26:15 UTC (rev 63629)
@@ -271,7 +271,7 @@
guint32 offset = 7;
guint32 slot = method->slot;
GPtrArray *ifaces;
- MonoClass *ic;
+ MonoClass *ic = method->klass;
int i;
ifaces = mono_class_get_implemented_interfaces (method->klass);
@@ -290,7 +290,7 @@
if (!interface_type_attribute)
interface_type_attribute = mono_class_from_name
(mono_defaults.corlib, "System.Runtime.InteropServices",
"InterfaceTypeAttribute");
- cinfo = mono_custom_attrs_from_class (method->klass);
+ cinfo = mono_custom_attrs_from_class (ic);
if (cinfo) {
itf_attr =
(MonoInterfaceTypeAttribute*)mono_custom_attrs_get_attr (cinfo,
interface_type_attribute);
if (!cinfo->cached)
@@ -3018,8 +3018,23 @@
mono_mb_emit_i4 (mb, mono_mb_add_data (mb, 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);
+
+ mono_mb_emit_ldarg (mb, 0);
+ mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoTransparentProxy,
rp));
+ mono_mb_emit_byte (mb, CEE_LDIND_REF);
+ mono_mb_emit_managed_call (mb, cache_proxy, NULL);
+ }
+
emit_thread_interrupt_checkpoint (mb);
-
+
mono_mb_emit_byte (mb, CEE_RET);
res = mono_mb_create_and_cache (cache, method, mb, sig,
sig->param_count + 16);
@@ -3042,7 +3057,7 @@
return method;
/* this seems to be the best plase to put this, as all remoting invokes
seem to get filtered through here */
- if ((MONO_CLASS_IS_IMPORT(method->klass) || method->klass ==
mono_defaults.com_object_class) && !mono_class_vtable (mono_domain_get (),
method->klass)->remote)
+ if ((method->klass->is_com_object || method->klass ==
mono_defaults.com_object_class) && !mono_class_vtable (mono_domain_get (),
method->klass)->remote)
return cominterop_get_invoke(method);
sig = signature_no_pinvoke (method);
@@ -5732,10 +5747,11 @@
}
} else {
- static MonoMethod* GetInterface = NULL;
-
- if (!GetInterface)
- GetInterface =
mono_class_get_method_from_name (mono_defaults.com_object_class,
"GetInterface", 1);
+ guint32 pos_failed = 0;
+ mono_mb_emit_ldarg (mb, argnum);
+ // if null just break, conv arg was already
inited to 0
+ pos_failed = mono_mb_emit_branch (mb,
CEE_BRFALSE);
+
mono_mb_emit_ldarg (mb, argnum);
mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET
(MonoTransparentProxy, rp));
mono_mb_emit_byte (mb, CEE_LDIND_REF);
@@ -5744,10 +5760,35 @@
mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET
(MonoComInteropProxy, com_object));
mono_mb_emit_byte (mb, CEE_LDIND_REF);
- mono_mb_emit_ptr (mb, t);
- mono_mb_emit_icall (mb, type_from_handle);
- mono_mb_emit_managed_call (mb, GetInterface,
NULL);
+ if (klass && klass !=
mono_defaults.object_class) {
+ static MonoMethod* GetInterface = NULL;
+
+ if (!GetInterface)
+ GetInterface =
mono_class_get_method_from_name (mono_defaults.com_object_class,
"GetInterface", 1);
+ mono_mb_emit_ptr (mb, t);
+ mono_mb_emit_icall (mb,
type_from_handle);
+ mono_mb_emit_managed_call (mb,
GetInterface, NULL);
+ }
+ else if (spec->native == MONO_NATIVE_IUNKNOWN) {
+ static MonoProperty* iunknown = NULL;
+
+ if (!iunknown)
+ iunknown =
mono_class_get_property_from_name (mono_defaults.com_object_class, "IUnknown");
+ mono_mb_emit_managed_call (mb,
iunknown->get, NULL);
+ }
+ else if (spec->native == MONO_NATIVE_IDISPATCH)
{
+ static MonoProperty* idispatch = NULL;
+
+ if (!idispatch)
+ idispatch =
mono_class_get_property_from_name (mono_defaults.com_object_class, "IDispatch");
+ mono_mb_emit_managed_call (mb,
idispatch->get, NULL);
+ }
+ else {
+ }
mono_mb_emit_stloc (mb, conv_arg);
+
+ // case if null
+ mono_mb_patch_addr (mb, pos_failed, mb->pos -
(pos_failed + 4));
}
}
else if (klass->delegate) {
@@ -5866,10 +5907,22 @@
static MonoMethod* com_interop_proxy_get_proxy
= NULL;
static MonoMethod* get_transparent_proxy = NULL;
int real_proxy;
- com_interop_proxy_class = mono_class_from_name
(mono_defaults.corlib, "Mono.Interop", "ComInteropProxy");
- com_interop_proxy_get_proxy =
mono_class_get_method_from_name_flags (com_interop_proxy_class, "GetProxy", 2,
METHOD_ATTRIBUTE_PRIVATE);
- get_transparent_proxy =
mono_class_get_method_from_name (mono_defaults.real_proxy_class,
"GetTransparentProxy", 0);
+ guint32 pos_failed = 0;
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_byte (mb, CEE_LDNULL);
+ mono_mb_emit_byte (mb, CEE_STIND_REF);
+
+ mono_mb_emit_ldloc (mb, conv_arg);
+ pos_failed = mono_mb_emit_branch (mb,
CEE_BRFALSE);
+
+ 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);
+ if (!get_transparent_proxy)
+ get_transparent_proxy =
mono_class_get_method_from_name (mono_defaults.real_proxy_class,
"GetTransparentProxy", 0);
+
real_proxy = mono_mb_add_local (mb,
&com_interop_proxy_class->byval_arg);
mono_mb_emit_ldloc (mb, conv_arg);
@@ -5887,6 +5940,9 @@
mono_mb_emit_i4 (mb, mono_mb_add_data
(mb, klass));
}
mono_mb_emit_byte (mb, CEE_STIND_REF);
+
+ // case if null
+ mono_mb_patch_addr (mb, pos_failed, mb->pos -
(pos_failed + 4));
}
break;
}
@@ -9169,6 +9225,7 @@
{
MonoClass *klass;
MonoDomain *domain;
+ MonoObject *obj;
MONO_ARCH_SAVE_REGS;
@@ -9179,8 +9236,10 @@
* because we want to actually create object. mono_object_new checks
* to see if type is import and creates transparent proxy. this method
* is called by the corresponding real proxy to create the real RCW.
+ * Constructor does not need to be called. Will be called later.
*/
- return mono_object_new_alloc_specific (mono_class_vtable (domain,
klass));
+ obj = mono_object_new_alloc_specific (mono_class_vtable (domain,
klass));
+ return obj;
}
static gboolean
Modified: trunk/mono/mono/metadata/object.c
===================================================================
--- trunk/mono/mono/metadata/object.c 2006-08-11 00:19:34 UTC (rev 63628)
+++ trunk/mono/mono/metadata/object.c 2006-08-11 02:26:15 UTC (rev 63629)
@@ -1278,7 +1278,7 @@
MonoClass *klass;
type = ((MonoReflectionType *)rp->class_to_proxy)->type;
klass = mono_class_from_mono_type (type);
- if ((MONO_CLASS_IS_IMPORT(klass) || klass ==
mono_defaults.com_object_class) && !mono_class_vtable (mono_domain_get (),
klass)->remote)
+ if ((klass->is_com_object || klass ==
mono_defaults.com_object_class) && !mono_class_vtable (mono_domain_get (),
klass)->remote)
remote_class->default_vtable = mono_class_proxy_vtable
(domain, remote_class, MONO_REMOTING_TARGET_COMINTEROP);
else
remote_class->default_vtable = mono_class_proxy_vtable
(domain, remote_class, MONO_REMOTING_TARGET_UNKNOWN);
@@ -2447,8 +2447,8 @@
MONO_ARCH_SAVE_REGS;
- /* check for MONO_CLASS_IS_IMPORT for COM Interop */
- if (vtable->remote || MONO_CLASS_IS_IMPORT(vtable->klass))
+ /* check for is_com_object for COM Interop */
+ if (vtable->remote || vtable->klass->is_com_object)
{
gpointer pa [1];
MonoMethod *im = vtable->domain->create_proxy_for_type_method;
Modified: trunk/mono/mono/mini/ChangeLog
===================================================================
--- trunk/mono/mono/mini/ChangeLog 2006-08-11 00:19:34 UTC (rev 63628)
+++ trunk/mono/mono/mini/ChangeLog 2006-08-11 02:26:15 UTC (rev 63629)
@@ -1,3 +1,8 @@
+2006-08-10 Jonathan Chambers <[EMAIL PROTECTED]>
+
+ * mini.c: Don't verify COM proxy invoke calls
+
+
2006-08-10 Dick Porter <[EMAIL PROTECTED]>
* wapihandles.c (mini_wapi_seminfo): More info, to help track down
Modified: trunk/mono/mono/mini/mini.c
===================================================================
--- trunk/mono/mono/mini/mini.c 2006-08-11 00:19:34 UTC (rev 63628)
+++ trunk/mono/mono/mini/mini.c 2006-08-11 02:26:15 UTC (rev 63629)
@@ -3733,6 +3733,7 @@
dont_verify |= method->wrapper_type == MONO_WRAPPER_XDOMAIN_DISPATCH;
dont_verify |= method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE;
/* bug #77896 */
dont_verify |= method->wrapper_type == MONO_WRAPPER_COMINTEROP;
+ dont_verify |= method->wrapper_type == MONO_WRAPPER_COMINTEROP_INVOKE;
/* still some type unsafety issues in marshal wrappers... (unknown is
PtrToStructure) */
dont_verify_stloc = method->wrapper_type ==
MONO_WRAPPER_MANAGED_TO_NATIVE;
Modified: trunk/mono/mono/tests/ChangeLog
===================================================================
--- trunk/mono/mono/tests/ChangeLog 2006-08-11 00:19:34 UTC (rev 63628)
+++ trunk/mono/mono/tests/ChangeLog 2006-08-11 02:26:15 UTC (rev 63629)
@@ -1,3 +1,8 @@
+2006-08-09 Jonathan Chambers <[EMAIL PROTECTED]>
+
+ * cominterop.cs: Added COM Interop tests for accessing IUnknown and
IDispatch.
+ * libtest.c: Implemented QueryInterface correctly.
+
2006-08-08 Zoltan Varga <[EMAIL PROTECTED]>
* vararg.il: Add a test for #79027.
Modified: trunk/mono/mono/tests/cominterop.cs
===================================================================
--- trunk/mono/mono/tests/cominterop.cs 2006-08-11 00:19:34 UTC (rev 63628)
+++ trunk/mono/mono/tests/cominterop.cs 2006-08-11 02:26:15 UTC (rev 63629)
@@ -92,13 +92,7 @@
[DllImport ("libtest")]
public static extern int mono_test_marshal_com_object_ref_count (IntPtr
pUnk);
- public static int Main ()
- {
- int i = Main2 ();
- Console.WriteLine (i);
- return i;
- }
- public static int Main2() {
+ public static int Main() {
bool isWindows = !(((int)Environment.OSVersion.Platform == 4) ||
((int)Environment.OSVersion.Platform == 128));
@@ -230,7 +224,21 @@
Marshal.ReleaseComObject (diff2) != 0)
return 41;
+ IntPtr pUnk2 = Marshal.GetIUnknownForObject (imath);
+ if (pUnk2 == IntPtr.Zero)
+ return 50;
+ if (pUnk != pUnk2)
+ return 51;
+
+ IntPtr pDisp = Marshal.GetIDispatchForObject (imath);
+ if (pDisp == IntPtr.Zero)
+ return 52;
+
+ if (pUnk != pDisp)
+ return 53;
+
+
//if (mono_test_marshal_com_object_destroy (pUnk) != 0)
// return 31;
#endregion // Marshal COM Interop Tests
@@ -240,7 +248,7 @@
}
[ComImport()]
- [Guid ("00000000-0000-0000-0000-000000000000")]
+ [Guid ("00000000-0000-0000-0000-000000000001")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IMath
{
@@ -253,4 +261,18 @@
[MethodImplAttribute (MethodImplOptions.InternalCall,
MethodCodeType = MethodCodeType.Runtime)]
int Different ([MarshalAs (UnmanagedType.Interface)] out IMath
imath);
}
+
+ [ComImport ()]
+ [Guid ("00000000-0000-0000-0000-000000000002")]
+ public class Foo : IMath
+ {
+ [MethodImplAttribute (MethodImplOptions.InternalCall,
MethodCodeType = MethodCodeType.Runtime)]
+ public extern int Add (int a, int b);
+ [MethodImplAttribute (MethodImplOptions.InternalCall,
MethodCodeType = MethodCodeType.Runtime)]
+ public extern int Subtract (int a, int b);
+ [MethodImplAttribute (MethodImplOptions.InternalCall,
MethodCodeType = MethodCodeType.Runtime)]
+ public extern int Same ([MarshalAs (UnmanagedType.Interface)]
out IMath imath);
+ [MethodImplAttribute (MethodImplOptions.InternalCall,
MethodCodeType = MethodCodeType.Runtime)]
+ public extern int Different ([MarshalAs
(UnmanagedType.Interface)] out IMath imath);
+ }
}
Modified: trunk/mono/mono/tests/libtest.c
===================================================================
--- trunk/mono/mono/tests/libtest.c 2006-08-11 00:19:34 UTC (rev 63628)
+++ trunk/mono/mono/tests/libtest.c 2006-08-11 02:26:15 UTC (rev 63629)
@@ -7,6 +7,7 @@
#ifdef WIN32
#include <windows.h>
+#include "initguid.h"
#endif
#ifdef WIN32
@@ -2065,10 +2066,26 @@
int m_ref;
};
+DEFINE_GUID(IID_IMath, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
+DEFINE_GUID(IID_IMonoUnknown, 0, 0, 0, 0xC0, 0, 0, 0, 0, 0, 0, 0x46);
+DEFINE_GUID(IID_IMonoDispatch, 0x00020400, 0, 0, 0xC0, 0, 0, 0, 0, 0, 0, 0x46);
+
int COM_STDCALL MonoQueryInterface(MonoComObject* pUnk, gpointer riid,
gpointer* ppv)
{
- *ppv = pUnk;
- return 0;
+ *ppv = NULL;
+ if (!memcmp(riid, &IID_IMonoUnknown, sizeof(GUID))) {
+ *ppv = pUnk;
+ return S_OK;
+ }
+ else if (!memcmp(riid, &IID_IMath, sizeof(GUID))) {
+ *ppv = pUnk;
+ return S_OK;
+ }
+ else if (!memcmp(riid, &IID_IMonoDispatch, sizeof(GUID))) {
+ *ppv = pUnk;
+ return S_OK;
+ }
+ return E_NOINTERFACE;
}
int COM_STDCALL MonoAddRef(MonoComObject* pUnk)
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches