X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fcominterop.c;h=f6adfcd1ce07c3ca3923a3a0db0de8237d5a4fa4;hb=28d30f12aeba96f2c7c8218ca4552a3352017993;hp=15359bf318f891708aab6e867291948c11ff0290;hpb=da08584c88b25b4d139458c1d1388492313e1063;p=mono.git diff --git a/mono/metadata/cominterop.c b/mono/metadata/cominterop.c index 15359bf318f..f6adfcd1ce0 100644 --- a/mono/metadata/cominterop.c +++ b/mono/metadata/cominterop.c @@ -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; @@ -125,6 +125,28 @@ cominterop_get_ccw (MonoObject* object, MonoClass* itf); static MonoObject* cominterop_get_ccw_object (MonoCCWInterface* ccw_entry, gboolean verify); +/* SAFEARRAY marshalling */ +static gboolean +mono_marshal_safearray_begin (gpointer safearray, MonoArray **result, gpointer *indices, gpointer empty, gpointer parameter, gboolean allocateNewArray); + +static gpointer +mono_marshal_safearray_get_value (gpointer safearray, gpointer indices); + +static gboolean +mono_marshal_safearray_next (gpointer safearray, gpointer indices); + +static void +mono_marshal_safearray_end (gpointer safearray, gpointer indices); + +static gboolean +mono_marshal_safearray_create (MonoArray *input, gpointer *newsafearray, gpointer *indices, gpointer empty); + +static void +mono_marshal_safearray_set_value (gpointer safearray, gpointer indices, gpointer value); + +static void +mono_marshal_safearray_free_indices (gpointer indices); + /** * cominterop_method_signature: * @method: a method @@ -147,7 +169,7 @@ cominterop_method_signature (MonoMethod* method) param_count++; res = mono_metadata_signature_alloc (image, param_count); - sigsize = sizeof (MonoMethodSignature) + ((sig->param_count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType *)); + sigsize = MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *); memcpy (res, sig, sigsize); // now move args forward one @@ -182,7 +204,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; @@ -264,18 +286,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; } @@ -283,7 +315,8 @@ cominterop_get_method_interface (MonoMethod* method) } } - g_assert (ic); + if (!ic) + g_assert (ic); g_assert (MONO_CLASS_IS_INTERFACE (ic)); return ic; @@ -304,10 +337,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); @@ -318,7 +358,7 @@ cominterop_get_com_slot_for_method (MonoMethod* method) static void -cominterop_mono_string_to_guid (const MonoString* string, guint8 *guid); +cominterop_mono_string_to_guid (MonoString* string, guint8 *guid); static gboolean cominterop_class_guid (MonoClass* klass, guint8* guid) @@ -349,9 +389,10 @@ static gboolean cominterop_com_visible (MonoClass* klass) { static MonoClass *ComVisibleAttribute = NULL; + MonoError error; MonoCustomAttrInfo *cinfo; GPtrArray *ifaces; - MonoBoolean visible = 0; + MonoBoolean visible = 1; /* Handle the ComVisibleAttribute */ if (!ComVisibleAttribute) @@ -369,7 +410,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) { @@ -449,7 +491,7 @@ cominterop_get_hresult_for_exception (MonoException* exc) } static MonoReflectionType * -type_from_handle (MonoType *handle) +cominterop_type_from_handle (MonoType *handle) { MonoDomain *domain = mono_domain_get (); MonoClass *klass = mono_class_from_mono_type (handle); @@ -490,6 +532,16 @@ mono_cominterop_init (void) register_icall (mono_string_to_bstr, "mono_string_to_bstr", "ptr obj", FALSE); register_icall (mono_string_from_bstr, "mono_string_from_bstr", "obj ptr", FALSE); register_icall (mono_free_bstr, "mono_free_bstr", "void ptr", FALSE); + register_icall (cominterop_type_from_handle, "cominterop_type_from_handle", "object ptr", FALSE); + + /* SAFEARRAY marshalling */ + register_icall (mono_marshal_safearray_begin, "mono_marshal_safearray_begin", "int32 ptr ptr ptr ptr ptr int32", FALSE); + register_icall (mono_marshal_safearray_get_value, "mono_marshal_safearray_get_value", "ptr ptr ptr", FALSE); + register_icall (mono_marshal_safearray_next, "mono_marshal_safearray_next", "int32 ptr ptr", FALSE); + register_icall (mono_marshal_safearray_end, "mono_marshal_safearray_end", "void ptr ptr", FALSE); + register_icall (mono_marshal_safearray_create, "mono_marshal_safearray_create", "int32 object ptr ptr ptr", FALSE); + register_icall (mono_marshal_safearray_set_value, "mono_marshal_safearray_set_value", "void ptr ptr ptr", FALSE); + register_icall (mono_marshal_safearray_free_indices, "mono_marshal_safearray_free_indices", "void ptr", FALSE); } void @@ -561,7 +613,7 @@ mono_cominterop_emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *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_icall (mb, type_from_handle); + 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); if (conv == MONO_MARSHAL_CONV_OBJECT_INTERFACE) { @@ -749,7 +801,7 @@ cominterop_get_native_wrapper_adjusted (MonoMethod *method) mspecs[mspec_index] = g_new0 (MonoMarshalSpec, 1); mspecs[mspec_index]->native = MONO_NATIVE_INTERFACE; } - else if (sig_native->params[i]->type == MONO_NATIVE_BOOLEAN) { + else if (sig_native->params[i]->type == MONO_TYPE_BOOLEAN) { mspecs[mspec_index] = g_new0 (MonoMarshalSpec, 1); mspecs[mspec_index]->native = MONO_NATIVE_VARIANTBOOL; } @@ -772,14 +824,14 @@ cominterop_get_native_wrapper_adjusted (MonoMethod *method) mspecs[0] = g_new0 (MonoMarshalSpec, 1); mspecs[0]->native = MONO_NATIVE_INTERFACE; } - else if (sig->ret->type == MONO_NATIVE_BOOLEAN) { + else if (sig->ret->type == MONO_TYPE_BOOLEAN) { mspecs[0] = g_new0 (MonoMarshalSpec, 1); mspecs[0]->native = MONO_NATIVE_VARIANTBOOL; } } } - mono_marshal_emit_native_wrapper (method->klass->image, mb_native, sig_native, piinfo, mspecs, piinfo->addr, FALSE, TRUE); + mono_marshal_emit_native_wrapper (method->klass->image, mb_native, sig_native, piinfo, mspecs, piinfo->addr, FALSE, TRUE, FALSE); res = mono_mb_create_method (mb_native, sig_native, sig_native->param_count + 16); @@ -820,6 +872,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); @@ -1060,7 +1113,7 @@ mono_cominterop_emit_marshal_com_interface (EmitMarshalContext *m, int argnum, if (klass && klass != mono_defaults.object_class) { mono_mb_emit_ptr (mb, t); - mono_mb_emit_icall (mb, type_from_handle); + mono_mb_emit_icall (mb, cominterop_type_from_handle); mono_mb_emit_managed_call (mb, get_com_interface_for_object_internal, NULL); } else if (spec->native == MONO_NATIVE_IUNKNOWN) @@ -1241,8 +1294,11 @@ mono_cominterop_emit_marshal_com_interface (EmitMarshalContext *m, int argnum, if (!AddRef) AddRef = mono_class_get_method_from_name (mono_defaults.marshal_class, "AddRef", 1); + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_byte (mb, CEE_LDC_I4_0); + mono_mb_emit_byte (mb, CEE_STIND_I); + mono_mb_emit_ldloc (mb, conv_arg); - /* if null just break, conv arg was already inited to 0 */ pos_null = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S); /* to store later */ @@ -1250,7 +1306,7 @@ mono_cominterop_emit_marshal_com_interface (EmitMarshalContext *m, int argnum, mono_mb_emit_ldloc (mb, conv_arg); if (klass && klass != mono_defaults.object_class) { mono_mb_emit_ptr (mb, t); - mono_mb_emit_icall (mb, type_from_handle); + mono_mb_emit_icall (mb, cominterop_type_from_handle); mono_mb_emit_managed_call (mb, get_com_interface_for_object_internal, NULL); } else if (spec->native == MONO_NATIVE_IUNKNOWN) @@ -1293,7 +1349,7 @@ mono_cominterop_emit_marshal_com_interface (EmitMarshalContext *m, int argnum, mono_mb_emit_ldloc (mb, ccw_obj); if (klass && klass != mono_defaults.object_class) { mono_mb_emit_ptr (mb, t); - mono_mb_emit_icall (mb, type_from_handle); + mono_mb_emit_icall (mb, cominterop_type_from_handle); mono_mb_emit_managed_call (mb, get_com_interface_for_object_internal, NULL); } else if (spec->native == MONO_NATIVE_IUNKNOWN) @@ -1469,6 +1525,9 @@ 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)); + itf = cominterop_get_ccw (object, klass); g_assert (itf); return itf; @@ -1501,7 +1560,11 @@ ves_icall_System_Runtime_InteropServices_Marshal_ReleaseComObjectInternal (MonoO proxy = (MonoComInteropProxy*)((MonoTransparentProxy*)object)->rp; g_assert (proxy); + if (proxy->ref_count == 0) + return -1; + ref_count = InterlockedDecrement (&proxy->ref_count); + g_assert (ref_count >= 0); if (ref_count == 0) @@ -1544,7 +1607,7 @@ ves_icall_System_ComObject_CreateRCW (MonoReflectionType *type) * is called by the corresponding real proxy to create the real RCW. * Constructor does not need to be called. Will be called later. */ - obj = mono_object_new_alloc_specific (mono_class_vtable (domain, klass)); + obj = mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE)); return obj; } @@ -1620,7 +1683,11 @@ gpointer ves_icall_System_ComObject_GetInterfaceInternal (MonoComObject* obj, MonoReflectionType* type, MonoBoolean throw_exception) { #ifndef DISABLE_COM - return cominterop_get_interface (obj, mono_type_get_class (type->type), (gboolean)throw_exception); + MonoClass *class = mono_type_get_class (type->type); + if (!mono_class_init (class)) + mono_raise_exception (mono_class_get_exception_for_failure (class)); + + return cominterop_get_interface (obj, class, (gboolean)throw_exception); #else g_assert_not_reached (); #endif @@ -1672,30 +1739,6 @@ ves_icall_Mono_Interop_ComInteropProxy_FindProxy (gpointer pUnk) #endif } -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); -} - /** * cominterop_get_ccw_object: * @ccw_entry: a pointer to the CCWEntry @@ -1736,7 +1779,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; @@ -1781,12 +1824,14 @@ cominterop_get_ccw (MonoObject* object, MonoClass* itf) klass = mono_object_get_class (object); + mono_cominterop_lock (); if (!ccw_hash) ccw_hash = g_hash_table_new (mono_aligned_addr_hash, NULL); if (!ccw_interface_hash) ccw_interface_hash = g_hash_table_new (mono_aligned_addr_hash, NULL); ccw_list = g_hash_table_lookup (ccw_hash, GINT_TO_POINTER (mono_object_hash (object))); + mono_cominterop_unlock (); ccw_list_item = ccw_list; while (ccw_list_item) { @@ -1813,7 +1858,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); @@ -1827,7 +1872,9 @@ cominterop_get_ccw (MonoObject* object, MonoClass* itf) } else ccw_list = g_list_append (ccw_list, ccw); + mono_cominterop_lock (); g_hash_table_insert (ccw_hash, GINT_TO_POINTER (mono_object_hash (object)), ccw_list); + mono_cominterop_unlock (); /* register for finalization to clean up ccw */ mono_object_register_finalizer (object); } @@ -1905,10 +1952,16 @@ cominterop_get_ccw (MonoObject* object, MonoClass* itf) mspecs[mspec_index] = g_new0 (MonoMarshalSpec, 1); mspecs[mspec_index]->native = MONO_NATIVE_INTERFACE; } - else if (sig_adjusted->params[param_index]->type == MONO_NATIVE_BOOLEAN) { + else if (sig_adjusted->params[param_index]->type == MONO_TYPE_BOOLEAN) { mspecs[mspec_index] = g_new0 (MonoMarshalSpec, 1); mspecs[mspec_index]->native = MONO_NATIVE_VARIANTBOOL; } + } else { + /* increase SizeParamIndex since we've added a param */ + if (sig_adjusted->params[param_index]->type == MONO_TYPE_ARRAY || + sig_adjusted->params[param_index]->type == MONO_TYPE_SZARRAY) + if (mspecs[mspec_index]->data.array_data.param_num != -1) + mspecs[mspec_index]->data.array_data.param_num++; } } @@ -1930,7 +1983,7 @@ cominterop_get_ccw (MonoObject* object, MonoClass* itf) mspecs[0] = g_new0 (MonoMarshalSpec, 1); mspecs[0]->native = MONO_NATIVE_INTERFACE; } - else if (sig_adjusted->params[sig_adjusted->param_count-1]->type == MONO_NATIVE_BOOLEAN) { + else if (sig_adjusted->params[sig_adjusted->param_count-1]->type == MONO_TYPE_BOOLEAN) { mspecs[0] = g_new0 (MonoMarshalSpec, 1); mspecs[0]->native = MONO_NATIVE_VARIANTBOOL; } @@ -1945,7 +1998,7 @@ cominterop_get_ccw (MonoObject* object, MonoClass* itf) cominterop_setup_marshal_context (&m, adjust_method); m.mb = mb; - mono_marshal_emit_managed_wrapper (mb, sig_adjusted, mspecs, &m, adjust_method, NULL); + 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); @@ -1974,6 +2027,7 @@ cominterop_get_ccw (MonoObject* object, MonoClass* itf) static gboolean mono_marshal_free_ccw_entry (gpointer key, gpointer value, gpointer user_data) { + g_hash_table_remove (ccw_interface_hash, value); g_assert (value); g_free (value); return TRUE; @@ -2082,11 +2136,13 @@ cominterop_get_managed_wrapper_adjusted (MonoMethod *method) if (!preserve_sig) { hr = mono_mb_add_local (mb, &mono_defaults.int32_class->byval_arg); - - /* try */ - main_clause = g_new0 (MonoExceptionClause, 1); - main_clause->try_offset = mono_mb_get_label (mb); } + else if (!MONO_TYPE_IS_VOID (sig->ret)) + hr = mono_mb_add_local (mb, sig->ret); + + /* try */ + main_clause = g_new0 (MonoExceptionClause, 1); + main_clause->try_offset = mono_mb_get_label (mb); /* load last param to store result if not preserve_sig and not void */ if (!preserve_sig && !MONO_TYPE_IS_VOID (sig->ret)) @@ -2102,32 +2158,46 @@ cominterop_get_managed_wrapper_adjusted (MonoMethod *method) mono_mb_emit_managed_call (mb, method, NULL); - if (!preserve_sig) { - /* store result if not preserve_sig and we have one */ - if (!MONO_TYPE_IS_VOID (sig->ret)) - mono_mb_emit_byte (mb, mono_type_to_stind (sig->ret)); + if (!MONO_TYPE_IS_VOID (sig->ret)) { + if (!preserve_sig) { + MonoClass *rclass = mono_class_from_mono_type (sig->ret); + if (rclass->valuetype) { + mono_mb_emit_op (mb, CEE_STOBJ, rclass); + } else { + mono_mb_emit_byte (mb, mono_type_to_stind (sig->ret)); + } + } else + mono_mb_emit_stloc (mb, hr); + } - pos_leave = mono_mb_emit_branch (mb, CEE_LEAVE); + pos_leave = mono_mb_emit_branch (mb, CEE_LEAVE); - /* Main exception catch */ - main_clause->flags = MONO_EXCEPTION_CLAUSE_NONE; - main_clause->try_len = mono_mb_get_pos (mb) - main_clause->try_offset; - main_clause->data.catch_class = mono_defaults.object_class; + /* Main exception catch */ + main_clause->flags = MONO_EXCEPTION_CLAUSE_NONE; + main_clause->try_len = mono_mb_get_pos (mb) - main_clause->try_offset; + main_clause->data.catch_class = mono_defaults.object_class; - /* handler code */ - main_clause->handler_offset = mono_mb_get_label (mb); + /* handler code */ + main_clause->handler_offset = mono_mb_get_label (mb); + + if (!preserve_sig || (sig->ret && !sig->ret->byref && (sig->ret->type == MONO_TYPE_U4 || sig->ret->type == MONO_TYPE_I4))) { mono_mb_emit_managed_call (mb, get_hr_for_exception, NULL); mono_mb_emit_stloc (mb, hr); - mono_mb_emit_branch (mb, CEE_LEAVE); - main_clause->handler_len = mono_mb_get_pos (mb) - main_clause->handler_offset; - /* end catch */ + } + else { + mono_mb_emit_byte (mb, CEE_POP); + } + + mono_mb_emit_branch (mb, CEE_LEAVE); + main_clause->handler_len = mono_mb_get_pos (mb) - main_clause->handler_offset; + /* end catch */ - mono_mb_set_clauses (mb, 1, main_clause); + mono_mb_set_clauses (mb, 1, main_clause); - mono_mb_patch_branch (mb, pos_leave); + mono_mb_patch_branch (mb, pos_leave); + if (!preserve_sig || !MONO_TYPE_IS_VOID (sig->ret)) mono_mb_emit_ldloc (mb, hr); - } mono_mb_emit_byte (mb, CEE_RET); @@ -2154,7 +2224,7 @@ cominterop_get_managed_wrapper_adjusted (MonoMethod *method) * to a 16 byte Microsoft GUID. */ static void -cominterop_mono_string_to_guid (const MonoString* string, guint8 *guid) { +cominterop_mono_string_to_guid (MonoString* string, guint8 *guid) { gunichar2 * chars = mono_string_chars (string); int i = 0; static guint8 indexes[16] = {7, 5, 3, 1, 12, 10, 17, 15, 20, 22, 25, 27, 29, 31, 33, 35}; @@ -2203,7 +2273,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 @@ -2213,16 +2283,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; @@ -2246,11 +2316,13 @@ 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; MonoCCW* ccw = ccwe->ccw; MonoClass* klass = NULL; + MonoClass* klass_iter = NULL; MonoObject* object = mono_gchandle_get_target (ccw->gc_handle); g_assert (object); @@ -2281,24 +2353,32 @@ 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); } #endif - - ifaces = mono_class_get_implemented_interfaces (klass); - if (ifaces) { - for (i = 0; i < ifaces->len; ++i) { - MonoClass *ic = NULL; - ic = g_ptr_array_index (ifaces, i); - if (cominterop_class_guid_equal (riid, ic)) { - itf = ic; - break; + klass_iter = klass; + while (klass_iter && klass_iter != mono_defaults.object_class) { + 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; + ic = g_ptr_array_index (ifaces, i); + if (cominterop_class_guid_equal (riid, ic)) { + itf = ic; + break; + } } + g_ptr_array_free (ifaces, TRUE); } - g_ptr_array_free (ifaces, TRUE); + + if (itf) + break; + + klass_iter = klass_iter->parent; } if (itf) { *ppv = cominterop_get_ccw (object, itf); @@ -2340,14 +2420,40 @@ cominterop_ccw_invoke (MonoCCWInterface* ccwe, guint32 dispIdMember, return MONO_E_NOTIMPL; } -typedef gpointer (*SysAllocStringLenFunc)(gunichar* str, guint32 len); -typedef guint32 (*SysStringLenFunc)(gpointer bstr); -typedef void (*SysFreeStringFunc)(gunichar* str); +typedef gpointer (STDCALL *SysAllocStringLenFunc)(gunichar* str, guint32 len); +typedef guint32 (STDCALL *SysStringLenFunc)(gpointer bstr); +typedef void (STDCALL *SysFreeStringFunc)(gunichar* str); static SysAllocStringLenFunc sys_alloc_string_len_ms = NULL; static SysStringLenFunc sys_string_len_ms = NULL; static SysFreeStringFunc sys_free_string_ms = NULL; +#ifndef HOST_WIN32 + +typedef struct tagSAFEARRAYBOUND { + ULONG cElements; + LONG lLbound; +}SAFEARRAYBOUND,*LPSAFEARRAYBOUND; +#define VT_VARIANT 12 + +#endif + +typedef guint32 (STDCALL *SafeArrayGetDimFunc)(gpointer psa); +typedef int (STDCALL *SafeArrayGetLBoundFunc)(gpointer psa, guint32 nDim, glong* plLbound); +typedef int (STDCALL *SafeArrayGetUBoundFunc)(gpointer psa, guint32 nDim, glong* plUbound); +typedef int (STDCALL *SafeArrayPtrOfIndexFunc)(gpointer psa, glong* rgIndices, gpointer* ppvData); +typedef int (STDCALL *SafeArrayDestroyFunc)(gpointer psa); +typedef int (STDCALL *SafeArrayPutElementFunc)(gpointer psa, glong* rgIndices, gpointer* ppvData); +typedef gpointer (STDCALL *SafeArrayCreateFunc)(int vt, guint32 cDims, SAFEARRAYBOUND* rgsabound); + +static SafeArrayGetDimFunc safe_array_get_dim_ms = NULL; +static SafeArrayGetLBoundFunc safe_array_get_lbound_ms = NULL; +static SafeArrayGetUBoundFunc safe_array_get_ubound_ms = NULL; +static SafeArrayPtrOfIndexFunc safe_array_ptr_of_index_ms = NULL; +static SafeArrayDestroyFunc safe_array_destroy_ms = NULL; +static SafeArrayPutElementFunc safe_array_put_element_ms = NULL; +static SafeArrayCreateFunc safe_array_create_ms = NULL; + static gboolean init_com_provider_ms (void) { @@ -2386,6 +2492,55 @@ init_com_provider_ms (void) return FALSE; } + error_msg = mono_dl_symbol (module, "SafeArrayGetDim", (gpointer*)&safe_array_get_dim_ms); + if (error_msg) { + g_warning ("Error loading entry point '%s' in COM support library '%s': %s", "SafeArrayGetDim", scope, error_msg); + g_assert_not_reached (); + return FALSE; + } + + error_msg = mono_dl_symbol (module, "SafeArrayGetLBound", (gpointer*)&safe_array_get_lbound_ms); + if (error_msg) { + g_warning ("Error loading entry point '%s' in COM support library '%s': %s", "SafeArrayGetLBound", scope, error_msg); + g_assert_not_reached (); + return FALSE; + } + + error_msg = mono_dl_symbol (module, "SafeArrayGetUBound", (gpointer*)&safe_array_get_ubound_ms); + if (error_msg) { + g_warning ("Error loading entry point '%s' in COM support library '%s': %s", "SafeArrayGetUBound", scope, error_msg); + g_assert_not_reached (); + return FALSE; + } + + error_msg = mono_dl_symbol (module, "SafeArrayPtrOfIndex", (gpointer*)&safe_array_ptr_of_index_ms); + if (error_msg) { + g_warning ("Error loading entry point '%s' in COM support library '%s': %s", "SafeArrayPtrOfIndex", scope, error_msg); + g_assert_not_reached (); + return FALSE; + } + + error_msg = mono_dl_symbol (module, "SafeArrayDestroy", (gpointer*)&safe_array_destroy_ms); + if (error_msg) { + g_warning ("Error loading entry point '%s' in COM support library '%s': %s", "SafeArrayDestroy", scope, error_msg); + g_assert_not_reached (); + return FALSE; + } + + error_msg = mono_dl_symbol (module, "SafeArrayPutElement", (gpointer*)&safe_array_put_element_ms); + if (error_msg) { + g_warning ("Error loading entry point '%s' in COM support library '%s': %s", "SafeArrayPutElement", scope, error_msg); + g_assert_not_reached (); + return FALSE; + } + + error_msg = mono_dl_symbol (module, "SafeArrayCreate", (gpointer*)&safe_array_create_ms); + if (error_msg) { + g_warning ("Error loading entry point '%s' in COM support library '%s': %s", "SafeArrayCreate", scope, error_msg); + g_assert_not_reached (); + return FALSE; + } + initialized = TRUE; return TRUE; } @@ -2395,7 +2550,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) { @@ -2431,7 +2586,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) { @@ -2457,7 +2612,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) { @@ -2471,6 +2626,517 @@ mono_free_bstr (gpointer bstr) #endif } + +/* SAFEARRAY marshalling */ +int +mono_cominterop_emit_marshal_safearray (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, + int conv_arg, MonoType **conv_arg_type, + MarshalAction action) +{ + MonoMethodBuilder *mb = m->mb; + + mono_init_com_types (); + + switch (action) { + + case MARSHAL_ACTION_CONV_IN: { + + if (t->attrs & PARAM_ATTRIBUTE_IN) { + + /* Generates IL code for the following algorithm: + + SafeArray safearray; // safearray_var + IntPtr indices; // indices_var + int empty; // empty_var + if (mono_marshal_safearray_create (array, out safearray, out indices, out empty)) { + if (!empty) { + int index=0; // index_var + do { // label3 + variant elem = Marshal.GetNativeVariantForObject (array.GetValueImpl(index)); + mono_marshal_safearray_set_value (safearray, indices, elem); + ++index; + } + while (mono_marshal_safearray_next (safearray, indices)); + } // label2 + mono_marshal_safearray_free_indices (indices); + } // label1 + */ + + int safearray_var, indices_var, empty_var, elem_var, index_var; + guint32 label1 = 0, label2 = 0, label3 = 0; + static MonoMethod *get_native_variant_for_object = NULL; + static MonoMethod *get_value_impl = NULL; + static MonoMethod *variant_clear = NULL; + + conv_arg = safearray_var = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg); + indices_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg); + empty_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg); + + if (t->byref) { + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_byte (mb, CEE_LDIND_REF); + } else + mono_mb_emit_ldarg (mb, argnum); + + mono_mb_emit_ldloc_addr (mb, safearray_var); + mono_mb_emit_ldloc_addr (mb, indices_var); + mono_mb_emit_ldloc_addr (mb, empty_var); + mono_mb_emit_icall (mb, mono_marshal_safearray_create); + + label1 = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S); + + mono_mb_emit_ldloc (mb, empty_var); + + label2 = mono_mb_emit_short_branch (mb, CEE_BRTRUE_S); + + index_var = mono_mb_add_local (mb, &mono_defaults.int32_class->byval_arg); + mono_mb_emit_byte (mb, CEE_LDC_I4_0); + mono_mb_emit_stloc (mb, index_var); + + label3 = mono_mb_get_label (mb); + + if (!get_value_impl) + get_value_impl = mono_class_get_method_from_name (mono_defaults.array_class, "GetValueImpl", 1); + g_assert (get_value_impl); + + if (t->byref) { + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_byte (mb, CEE_LDIND_REF); + } else + mono_mb_emit_ldarg (mb, argnum); + + mono_mb_emit_ldloc (mb, index_var); + + mono_mb_emit_managed_call (mb, get_value_impl, NULL); + + if (!get_native_variant_for_object) + 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); + mono_mb_emit_ldloc_addr (mb, elem_var); + + mono_mb_emit_managed_call (mb, get_native_variant_for_object, NULL); + + mono_mb_emit_ldloc (mb, safearray_var); + mono_mb_emit_ldloc (mb, indices_var); + mono_mb_emit_ldloc_addr (mb, elem_var); + 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); + + mono_mb_emit_ldloc_addr (mb, elem_var); + mono_mb_emit_managed_call (mb, variant_clear, NULL); + + mono_mb_emit_add_to_local (mb, index_var, 1); + + mono_mb_emit_ldloc (mb, safearray_var); + mono_mb_emit_ldloc (mb, indices_var); + mono_mb_emit_icall (mb, mono_marshal_safearray_next); + mono_mb_emit_branch_label (mb, CEE_BRTRUE, label3); + + mono_mb_patch_short_branch (mb, label2); + + mono_mb_emit_ldloc (mb, indices_var); + mono_mb_emit_icall (mb, mono_marshal_safearray_free_indices); + + mono_mb_patch_short_branch (mb, label1); + } + break; + } + + case MARSHAL_ACTION_PUSH: + if (t->byref) + mono_mb_emit_ldloc_addr (mb, conv_arg); + else + mono_mb_emit_ldloc (mb, conv_arg); + break; + + case MARSHAL_ACTION_CONV_OUT: { + + if (t->attrs & PARAM_ATTRIBUTE_OUT) { + /* Generates IL code for the following algorithm: + + Array result; // result_var + IntPtr indices; // indices_var + int empty; // empty_var + bool byValue = !t->byref && (t->attrs & PARAM_ATTRIBUTE_IN); + if (mono_marshal_safearray_begin(safearray, out result, out indices, out empty, parameter, byValue)) { + if (!empty) { + int index=0; // index_var + do { // label3 + if (!byValue || (index < parameter.Length)) { + object elem = Variant.GetObjectForNativeVariant(mono_marshal_safearray_get_value(safearray, indices)); + result.SetValueImpl(elem, index); + } + ++index; + } + while (mono_marshal_safearray_next(safearray, indices)); + } // label2 + mono_marshal_safearray_end(safearray, indices); + } // label1 + if (!byValue) + return result; + */ + + int result_var, indices_var, empty_var, elem_var, index_var; + guint32 label1 = 0, label2 = 0, label3 = 0, label4 = 0; + static MonoMethod *get_object_for_native_variant = NULL; + static MonoMethod *set_value_impl = NULL; + gboolean byValue = !t->byref && (t->attrs & PARAM_ATTRIBUTE_IN); + + result_var = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg); + indices_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg); + empty_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg); + + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_ldloc_addr (mb, result_var); + mono_mb_emit_ldloc_addr (mb, indices_var); + mono_mb_emit_ldloc_addr (mb, empty_var); + mono_mb_emit_ldarg (mb, argnum); + if (byValue) + mono_mb_emit_byte (mb, CEE_LDC_I4_0); + else + mono_mb_emit_byte (mb, CEE_LDC_I4_1); + mono_mb_emit_icall (mb, mono_marshal_safearray_begin); + + label1 = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S); + + mono_mb_emit_ldloc (mb, empty_var); + + label2 = mono_mb_emit_short_branch (mb, CEE_BRTRUE_S); + + index_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg); + mono_mb_emit_byte (mb, CEE_LDC_I4_0); + mono_mb_emit_stloc (mb, index_var); + + label3 = mono_mb_get_label (mb); + + if (byValue) { + mono_mb_emit_ldloc (mb, index_var); + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_byte (mb, CEE_LDLEN); + label4 = mono_mb_emit_branch (mb, CEE_BGE); + } + + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_ldloc (mb, indices_var); + mono_mb_emit_icall (mb, mono_marshal_safearray_get_value); + + if (!get_object_for_native_variant) + get_object_for_native_variant = mono_class_get_method_from_name (mono_defaults.marshal_class, "GetObjectForNativeVariant", 1); + g_assert (get_object_for_native_variant); + + if (!set_value_impl) + set_value_impl = mono_class_get_method_from_name (mono_defaults.array_class, "SetValueImpl", 2); + g_assert (set_value_impl); + + elem_var = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg); + + mono_mb_emit_managed_call (mb, get_object_for_native_variant, NULL); + mono_mb_emit_stloc (mb, elem_var); + + mono_mb_emit_ldloc (mb, result_var); + mono_mb_emit_ldloc (mb, elem_var); + mono_mb_emit_ldloc (mb, index_var); + mono_mb_emit_managed_call (mb, set_value_impl, NULL); + + if (byValue) + mono_mb_patch_short_branch (mb, label4); + + mono_mb_emit_add_to_local (mb, index_var, 1); + + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_ldloc (mb, indices_var); + mono_mb_emit_icall (mb, mono_marshal_safearray_next); + mono_mb_emit_branch_label (mb, CEE_BRTRUE, label3); + + mono_mb_patch_short_branch (mb, label2); + + mono_mb_emit_ldloc (mb, conv_arg); + mono_mb_emit_ldloc (mb, indices_var); + mono_mb_emit_icall (mb, mono_marshal_safearray_end); + + mono_mb_patch_short_branch (mb, label1); + + if (!byValue) { + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_ldloc (mb, result_var); + mono_mb_emit_byte (mb, CEE_STIND_REF); + } + } + break; + } + + default: + g_assert_not_reached (); + } + + return conv_arg; +} + +static +guint32 mono_marshal_safearray_get_dim (gpointer safearray) +{ + guint32 result=0; +#ifdef HOST_WIN32 + result = SafeArrayGetDim (safearray); +#else + if (com_provider == MONO_COM_MS && init_com_provider_ms ()) { + result = safe_array_get_dim_ms (safearray); + } else { + g_assert_not_reached (); + } +#endif + return result; +} + +static +int mono_marshal_safe_array_get_lbound (gpointer psa, guint nDim, glong* plLbound) +{ + int result=MONO_S_OK; +#ifdef HOST_WIN32 + result = SafeArrayGetLBound (psa, nDim, plLbound); +#else + if (com_provider == MONO_COM_MS && init_com_provider_ms ()) { + result = safe_array_get_lbound_ms (psa, nDim, plLbound); + } else { + g_assert_not_reached (); + } +#endif + return result; +} + +static +int mono_marshal_safe_array_get_ubound (gpointer psa, guint nDim, glong* plUbound) +{ + int result=MONO_S_OK; +#ifdef HOST_WIN32 + result = SafeArrayGetUBound (psa, nDim, plUbound); +#else + if (com_provider == MONO_COM_MS && init_com_provider_ms ()) { + result = safe_array_get_ubound_ms (psa, nDim, plUbound); + } else { + g_assert_not_reached (); + } +#endif + return result; +} + +static gboolean +mono_marshal_safearray_begin (gpointer safearray, MonoArray **result, gpointer *indices, gpointer empty, gpointer parameter, gboolean allocateNewArray) +{ + int dim; + uintptr_t *sizes; + intptr_t *bounds; + MonoClass *aklass; + int i; + gboolean bounded = FALSE; + +#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 + // function will prevent the other mono_marshal_safearray_xxx functions + // from being called. + if ((com_provider != MONO_COM_MS) || !init_com_provider_ms ()) { + return FALSE; + } +#endif + + (*(int*)empty) = TRUE; + + if (safearray != NULL) { + + dim = mono_marshal_safearray_get_dim (safearray); + + if (dim > 0) { + + *indices = g_malloc (dim * sizeof(int)); + + sizes = alloca (dim * sizeof(uintptr_t)); + bounds = alloca (dim * sizeof(intptr_t)); + + for (i=0; i=0; --i) + { + glong lbound, ubound; + + hr = mono_marshal_safe_array_get_ubound (safearray, i+1, &ubound); + if (hr < 0) { + cominterop_raise_hr_exception (hr); + } + + if (++pIndices[i] <= ubound) { + break; + } + + hr = mono_marshal_safe_array_get_lbound (safearray, i+1, &lbound); + if (hr < 0) { + cominterop_raise_hr_exception (hr); + } + + pIndices[i] = lbound; + + if (i == 0) + ret = FALSE; + } + return ret; +} + +static +void mono_marshal_safearray_end (gpointer safearray, gpointer indices) +{ + g_free(indices); +#ifdef HOST_WIN32 + SafeArrayDestroy (safearray); +#else + if (com_provider == MONO_COM_MS && init_com_provider_ms ()) { + safe_array_destroy_ms (safearray); + } else { + g_assert_not_reached (); + } +#endif +} + +static gboolean +mono_marshal_safearray_create (MonoArray *input, gpointer *newsafearray, gpointer *indices, gpointer empty) +{ + int dim; + SAFEARRAYBOUND *bounds; + int i; + int max_array_length; + +#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 + // function will prevent the other mono_marshal_safearray_xxx functions + // from being called. + if ((com_provider != MONO_COM_MS) || !init_com_provider_ms ()) { + return FALSE; + } +#endif + + max_array_length = mono_array_length (input); + dim = ((MonoObject *)input)->vtable->klass->rank; + + *indices = g_malloc (dim * sizeof (int)); + bounds = alloca (dim * sizeof (SAFEARRAYBOUND)); + (*(int*)empty) = (max_array_length == 0); + + if (dim > 1) { + for (i=0; ibounds [i].lower_bound; + bounds [i].cElements = input->bounds [i].length; + } + } else { + ((int*)*indices) [0] = 0; + bounds [0].cElements = max_array_length; + bounds [0].lLbound = 0; + } + +#ifdef HOST_WIN32 + *newsafearray = SafeArrayCreate (VT_VARIANT, dim, bounds); +#else + *newsafearray = safe_array_create_ms (VT_VARIANT, dim, bounds); +#endif + + return TRUE; +} + +static +void mono_marshal_safearray_set_value (gpointer safearray, gpointer indices, gpointer value) +{ +#ifdef HOST_WIN32 + int hr = SafeArrayPutElement (safearray, indices, value); + if (hr < 0) + cominterop_raise_hr_exception (hr); +#else + if (com_provider == MONO_COM_MS && init_com_provider_ms ()) { + int hr = safe_array_put_element_ms (safearray, indices, value); + if (hr < 0) { + cominterop_raise_hr_exception (hr); + } + } else + g_assert_not_reached (); +#endif +} + +static +void mono_marshal_safearray_free_indices (gpointer indices) +{ + g_free (indices); +} + #else /* DISABLE_COM */ void @@ -2497,21 +3163,94 @@ mono_marshal_free_ccw (MonoObject* object) gpointer mono_string_to_bstr (MonoString *string_obj) { - g_assert_not_reached (); - return NULL; + if (!string_obj) + return NULL; +#ifdef HOST_WIN32 + return SysAllocStringLen (mono_string_chars (string_obj), mono_string_length (string_obj)); +#else + { + int slen = mono_string_length (string_obj); + /* allocate len + 1 utf16 characters plus 4 byte integer for length*/ + char *ret = g_malloc ((slen + 1) * sizeof(gunichar2) + sizeof(guint32)); + if (ret == NULL) + return NULL; + memcpy (ret + sizeof(guint32), mono_string_chars (string_obj), slen * sizeof(gunichar2)); + * ((guint32 *) ret) = slen * sizeof(gunichar2); + ret [4 + slen * sizeof(gunichar2)] = 0; + ret [5 + slen * sizeof(gunichar2)] = 0; + + return ret + 4; + } +#endif } MonoString * mono_string_from_bstr (gpointer bstr) { - g_assert_not_reached (); - return NULL; + if (!bstr) + return NULL; +#ifdef HOST_WIN32 + return mono_string_new_utf16 (mono_domain_get (), bstr, SysStringLen (bstr)); +#else + return mono_string_new_utf16 (mono_domain_get (), bstr, *((guint32 *)bstr - 1) / sizeof(gunichar2)); +#endif } void mono_free_bstr (gpointer bstr) +{ + if (!bstr) + return; +#ifdef HOST_WIN32 + SysFreeString ((BSTR)bstr); +#else + g_free (((char *)bstr) - 4); +#endif +} + +int +ves_icall_System_Runtime_InteropServices_Marshal_AddRefInternal (gpointer pUnk) +{ + g_assert_not_reached (); + return 0; +} + +int +ves_icall_System_Runtime_InteropServices_Marshal_ReleaseInternal (gpointer pUnk) +{ + g_assert_not_reached (); + return 0; +} + +int +ves_icall_System_Runtime_InteropServices_Marshal_QueryInterfaceInternal (gpointer pUnk, gpointer riid, gpointer* ppv) { g_assert_not_reached (); + return 0; } #endif /* DISABLE_COM */ + +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); +}