X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fcominterop.c;h=bedd740079bfdc160e07c76ae65b67134f7af777;hb=c5cdfaec1e0973ced3f97ef589cd0bece56067ad;hp=88f1ea21b1950338417d4d9cd0f1f3b8c6b30a1c;hpb=df9c98dda18083ec63171490267e08342621ef45;p=mono.git diff --git a/mono/metadata/cominterop.c b/mono/metadata/cominterop.c index 88f1ea21b19..bedd740079b 100644 --- a/mono/metadata/cominterop.c +++ b/mono/metadata/cominterop.c @@ -51,6 +51,15 @@ register_icall (gpointer func, const char *name, const char *sigstr, gboolean sa mono_register_jit_icall (func, name, sig, save); } +gpointer +mono_string_to_bstr(MonoString* ptr) +{ + if (!ptr) + return NULL; + + return mono_ptr_to_bstr(mono_string_chars(ptr), mono_string_length(ptr)); +} + #ifndef DISABLE_COM #define OPDEF(a,b,c,d,e,f,g,h,i,j) \ @@ -97,7 +106,6 @@ GENERATE_GET_CLASS_WITH_CACHE (variant, System, Variant) static GENERATE_GET_CLASS_WITH_CACHE (interface_type_attribute, System.Runtime.InteropServices, InterfaceTypeAttribute) static GENERATE_GET_CLASS_WITH_CACHE (guid_attribute, System.Runtime.InteropServices, GuidAttribute) -static GENERATE_GET_CLASS_WITH_CACHE (com_visible_attribute, System.Runtime.InteropServices, ComVisibleAttribute) /* 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 @@ -600,7 +608,7 @@ mono_cominterop_init (void) register_icall (cominterop_get_interface, "cominterop_get_interface", "ptr object ptr int32", FALSE); 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_string_from_bstr_icall, "mono_string_from_bstr_icall", "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); @@ -623,6 +631,7 @@ mono_cominterop_cleanup (void) void mono_mb_emit_cominterop_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethod* method) { +#ifndef DISABLE_JIT // get function pointer from 1st arg, the COM interface pointer mono_mb_emit_ldarg (mb, 0); mono_mb_emit_icon (mb, cominterop_get_com_slot_for_method (method)); @@ -633,11 +642,13 @@ mono_mb_emit_cominterop_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, M mono_mb_emit_calli (mb, sig); mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); mono_mb_emit_byte (mb, CEE_MONO_RESTORE_LMF); +#endif /* DISABLE_JIT */ } void mono_cominterop_emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, MonoMarshalSpec *mspec) { +#ifndef DISABLE_JIT switch (conv) { case MONO_MARSHAL_CONV_OBJECT_INTERFACE: case MONO_MARSHAL_CONV_OBJECT_IUNKNOWN: @@ -709,11 +720,13 @@ mono_cominterop_emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, default: g_assert_not_reached (); } +#endif /* DISABLE_JIT */ } void mono_cominterop_emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, MonoMarshalSpec *mspec) { +#ifndef DISABLE_JIT switch (conv) { case MONO_MARSHAL_CONV_OBJECT_INTERFACE: case MONO_MARSHAL_CONV_OBJECT_IDISPATCH: @@ -801,6 +814,7 @@ mono_cominterop_emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, default: g_assert_not_reached (); } +#endif /* DISABLE_JIT */ } /** @@ -937,6 +951,7 @@ mono_cominterop_get_native_wrapper (MonoMethod *method) sig = mono_method_signature (method); mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_COMINTEROP); +#ifndef DISABLE_JIT /* if method klass is import, that means method * is really a com call. let interop system emit it. */ @@ -1010,6 +1025,8 @@ mono_cominterop_get_native_wrapper (MonoMethod *method) imported classes is not yet implemented."); mono_mb_emit_exception (mb, "NotSupportedException", msg); } +#endif /* DISABLE_JIT */ + csig = mono_metadata_signature_dup_full (method->klass->image, sig); csig->pinvoke = 0; res = mono_mb_create_and_cache (cache, method, @@ -1049,6 +1066,7 @@ mono_cominterop_get_invoke (MonoMethod *method) mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_COMINTEROP_INVOKE); +#ifndef DISABLE_JIT /* get real proxy object, which is a ComInteropProxy in this case*/ mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg); mono_mb_emit_ldarg (mb, 0); @@ -1089,6 +1107,7 @@ mono_cominterop_get_invoke (MonoMethod *method) mono_marshal_emit_thread_interrupt_checkpoint (mb); mono_mb_emit_byte (mb, CEE_RET); +#endif /* DISABLE_JIT */ res = mono_mb_create_and_cache (cache, method, mb, sig, sig->param_count + 16); mono_mb_free (mb); @@ -1143,6 +1162,18 @@ mono_cominterop_emit_marshal_com_interface (EmitMarshalContext *m, int argnum, if (!marshal_release) marshal_release = mono_class_get_method_from_name (mono_defaults.marshal_class, "Release", 1); +#ifdef DISABLE_JIT + switch (action) { + case MARSHAL_ACTION_CONV_IN: + *conv_arg_type = &mono_defaults.int_class->byval_arg; + break; + case MARSHAL_ACTION_MANAGED_CONV_IN: + *conv_arg_type = &mono_defaults.int_class->byval_arg; + break; + default: + break; + } +#else switch (action) { case MARSHAL_ACTION_CONV_IN: { guint32 pos_null = 0; @@ -1429,6 +1460,7 @@ mono_cominterop_emit_marshal_com_interface (EmitMarshalContext *m, int argnum, default: g_assert_not_reached (); } +#endif /* DISABLE_JIT */ return conv_arg; } @@ -1673,9 +1705,11 @@ ves_icall_System_ComObject_CreateRCW (MonoReflectionType *type) * Constructor does not need to be called. Will be called later. */ MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error); - mono_error_raise_exception (&error); + if (mono_error_set_pending_exception (&error)) + return NULL; obj = mono_object_new_alloc_specific_checked (vtable, &error); - mono_error_raise_exception (&error); + if (mono_error_set_pending_exception (&error)) + return NULL; return obj; } @@ -1959,8 +1993,7 @@ cominterop_get_ccw_checked (MonoObject* object, MonoClass* itf, MonoError *error 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, error); - return_val_if_nok (error, NULL); + mono_object_register_finalizer (object); } cinfo = mono_custom_attrs_from_class_checked (itf, error); @@ -2078,8 +2111,10 @@ cominterop_get_ccw_checked (MonoObject* object, MonoClass* itf, MonoError *error mspecs [0] = NULL; } +#ifndef DISABLE_JIT /* skip visiblity since we call internal methods */ mb->skip_visibility = TRUE; +#endif cominterop_setup_marshal_context (&m, adjust_method); m.mb = mb; @@ -2088,13 +2123,14 @@ cominterop_get_ccw_checked (MonoObject* object, MonoClass* itf, MonoError *error wrapper_method = mono_mb_create_method (mb, m.csig, m.csig->param_count + 16); mono_cominterop_unlock (); - vtable [vtable_index--] = mono_compile_method (wrapper_method); + vtable [vtable_index--] = mono_compile_method_checked (wrapper_method, error); - + // cleanup, then error out if compile_method failed for (param_index = sig_adjusted->param_count; param_index >= 0; param_index--) if (mspecs [param_index]) mono_metadata_free_marshal_spec (mspecs [param_index]); g_free (mspecs); + return_val_if_nok (error, NULL); } ccw_entry = g_new0 (MonoCCWInterface, 1); @@ -2250,9 +2286,9 @@ cominterop_get_managed_wrapper_adjusted (MonoMethod *method) mspecs [0] = NULL; - if (!preserve_sig) { +#ifndef DISABLE_JIT + if (!preserve_sig) hr = mono_mb_add_local (mb, &mono_defaults.int32_class->byval_arg); - } else if (!MONO_TYPE_IS_VOID (sig->ret)) hr = mono_mb_add_local (mb, sig->ret); @@ -2316,6 +2352,7 @@ cominterop_get_managed_wrapper_adjusted (MonoMethod *method) mono_mb_emit_ldloc (mb, hr); mono_mb_emit_byte (mb, CEE_RET); +#endif /* DISABLE_JIT */ mono_cominterop_lock (); res = mono_mb_create_method (mb, sig_native, sig_native->param_count + 16); @@ -2399,15 +2436,15 @@ static const IID MONO_IID_IMarshal = {0x3, 0x0, 0x0, {0xC0, 0x0, 0x0, 0x0, 0x0, #ifdef HOST_WIN32 /* All ccw objects are free threaded */ static int -cominterop_ccw_getfreethreadedmarshaler (MonoCCW* ccw, MonoObject* object, gpointer* ppv) +cominterop_ccw_getfreethreadedmarshaler (MonoCCW* ccw, MonoObject* object, gpointer* ppv, MonoError *error) { + mono_error_init (error); #ifdef HOST_WIN32 - MonoError error; if (!ccw->free_marshaler) { int ret = 0; gpointer tunk; - tunk = cominterop_get_ccw_checked (object, mono_class_get_iunknown_class (), &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + tunk = cominterop_get_ccw_checked (object, mono_class_get_iunknown_class (), error); + return_val_if_nok (error, MONO_E_NOINTERFACE); ret = CoCreateFreeThreadedMarshaler (tunk, (LPUNKNOWN*)&ccw->free_marshaler); } @@ -2466,7 +2503,9 @@ cominterop_ccw_queryinterface (MonoCCWInterface* ccwe, guint8* riid, gpointer* p #ifdef HOST_WIN32 /* handle IMarshal special */ if (0 == memcmp (riid, &MONO_IID_IMarshal, sizeof (IID))) { - return cominterop_ccw_getfreethreadedmarshaler (ccw, object, ppv); + int res = cominterop_ccw_getfreethreadedmarshaler (ccw, object, ppv, &error); + mono_error_assert_ok (&error); + return res; } #endif klass_iter = klass; @@ -2712,37 +2751,37 @@ init_com_provider_ms (void) } gpointer -mono_string_to_bstr (MonoString *string_obj) +mono_ptr_to_bstr(gpointer ptr, int slen) { - if (!string_obj) + if (!ptr) return NULL; #ifdef HOST_WIN32 - return SysAllocStringLen (mono_string_chars (string_obj), mono_string_length (string_obj)); + return SysAllocStringLen (ptr, slen); #else if (com_provider == MONO_COM_DEFAULT) { - int slen = mono_string_length (string_obj); /* allocate len + 1 utf16 characters plus 4 byte integer for length*/ - char *ret = (char *)g_malloc ((slen + 1) * sizeof(gunichar2) + sizeof(guint32)); + char *ret = (char *)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; + memcpy(ret + sizeof(guint32), ptr, slen * sizeof(gunichar2)); + *((guint32 *)ret) = slen * sizeof(gunichar2); + ret[4 + slen * sizeof(gunichar2)] = 0; + ret[5 + slen * sizeof(gunichar2)] = 0; return ret + 4; - } else if (com_provider == MONO_COM_MS && init_com_provider_ms ()) { + } + else if (com_provider == MONO_COM_MS && init_com_provider_ms()) { gpointer ret = NULL; gunichar* str = NULL; - guint32 len; - len = mono_string_length (string_obj); - str = g_utf16_to_ucs4 (mono_string_chars (string_obj), len, + guint32 len = slen; + str = g_utf16_to_ucs4(ptr, len, NULL, NULL, NULL); - ret = sys_alloc_string_len_ms (str, len); + ret = sys_alloc_string_len_ms(str, len); g_free(str); return ret; - } else { - g_assert_not_reached (); + } + else { + g_assert_not_reached(); } #endif } @@ -2751,22 +2790,41 @@ MonoString * mono_string_from_bstr (gpointer bstr) { MonoError error; + MonoString *result = mono_string_from_bstr_checked (bstr, &error); + mono_error_cleanup (&error); + return result; +} + +MonoString * +mono_string_from_bstr_icall (gpointer bstr) +{ + MonoError error; + MonoString *result = mono_string_from_bstr_checked (bstr, &error); + mono_error_set_pending_exception (&error); + return result; +} + +MonoString * +mono_string_from_bstr_checked (gpointer bstr, MonoError *error) +{ MonoString * res = NULL; + mono_error_init (error); + if (!bstr) return NULL; #ifdef HOST_WIN32 - res = mono_string_new_utf16_checked (mono_domain_get (), bstr, SysStringLen (bstr), &error); + res = mono_string_new_utf16_checked (mono_domain_get (), bstr, SysStringLen (bstr), error); #else if (com_provider == MONO_COM_DEFAULT) { - res = mono_string_new_utf16_checked (mono_domain_get (), (const mono_unichar2 *)bstr, *((guint32 *)bstr - 1) / sizeof(gunichar2), &error); + res = mono_string_new_utf16_checked (mono_domain_get (), (const mono_unichar2 *)bstr, *((guint32 *)bstr - 1) / sizeof(gunichar2), error); } else if (com_provider == MONO_COM_MS && init_com_provider_ms ()) { MonoString* str = NULL; glong written = 0; gunichar2* utf16 = NULL; utf16 = g_ucs4_to_utf16 ((const gunichar *)bstr, sys_string_len_ms (bstr), NULL, &written, NULL); - str = mono_string_new_utf16_checked (mono_domain_get (), utf16, written, &error); + str = mono_string_new_utf16_checked (mono_domain_get (), utf16, written, error); g_free (utf16); res = str; } else { @@ -2774,7 +2832,6 @@ mono_string_from_bstr (gpointer bstr) } #endif - mono_error_raise_exception (&error); /* FIXME don't raise here */ return res; } @@ -2807,10 +2864,9 @@ mono_cominterop_emit_marshal_safearray (EmitMarshalContext *m, int argnum, MonoT { MonoMethodBuilder *mb = m->mb; +#ifndef DISABLE_JIT switch (action) { - case MARSHAL_ACTION_CONV_IN: { - if (t->attrs & PARAM_ATTRIBUTE_IN) { /* Generates IL code for the following algorithm: @@ -2924,7 +2980,6 @@ mono_cominterop_emit_marshal_safearray (EmitMarshalContext *m, int argnum, MonoT break; case MARSHAL_ACTION_CONV_OUT: { - if (t->attrs & PARAM_ATTRIBUTE_OUT) { /* Generates IL code for the following algorithm: @@ -3042,6 +3097,7 @@ mono_cominterop_emit_marshal_safearray (EmitMarshalContext *m, int argnum, MonoT default: g_assert_not_reached (); } +#endif /* DISABLE_JIT */ return conv_arg; } @@ -3094,6 +3150,7 @@ int mono_marshal_safe_array_get_ubound (gpointer psa, guint nDim, glong* plUboun return result; } +/* This is an icall */ static gboolean mono_marshal_safearray_begin (gpointer safearray, MonoArray **result, gpointer *indices, gpointer empty, gpointer parameter, gboolean allocateNewArray) { @@ -3137,14 +3194,16 @@ mono_marshal_safearray_begin (gpointer safearray, MonoArray **result, gpointer * hr = mono_marshal_safe_array_get_lbound (safearray, i+1, &lbound); if (hr < 0) { cominterop_set_hr_error (&error, hr); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + if (mono_error_set_pending_exception (&error)) + return FALSE; } if (lbound != 0) bounded = TRUE; hr = mono_marshal_safe_array_get_ubound (safearray, i+1, &ubound); if (hr < 0) { cominterop_set_hr_error (&error, hr); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + if (mono_error_set_pending_exception (&error)) + return FALSE; } cursize = ubound-lbound+1; sizes [i] = cursize; @@ -3159,7 +3218,8 @@ mono_marshal_safearray_begin (gpointer safearray, MonoArray **result, gpointer * if (allocateNewArray) { aklass = mono_bounded_array_class_get (mono_defaults.object_class, dim, bounded); *result = mono_array_new_full_checked (mono_domain_get (), aklass, sizes, bounds, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + if (mono_error_set_pending_exception (&error)) + return FALSE; } else { *result = (MonoArray *)parameter; } @@ -3168,6 +3228,7 @@ mono_marshal_safearray_begin (gpointer safearray, MonoArray **result, gpointer * return TRUE; } +/* This is an icall */ static gpointer mono_marshal_safearray_get_value (gpointer safearray, gpointer indices) { @@ -3177,14 +3238,16 @@ gpointer mono_marshal_safearray_get_value (gpointer safearray, gpointer indices) int hr = SafeArrayPtrOfIndex (safearray, indices, &result); if (hr < 0) { cominterop_set_hr_error (&error, hr); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + mono_error_set_pending_exception (&error); + return NULL; } #else if (com_provider == MONO_COM_MS && init_com_provider_ms ()) { int hr = safe_array_ptr_of_index_ms (safearray, (glong *)indices, &result); if (hr < 0) { cominterop_set_hr_error (&error, hr); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + mono_error_set_pending_exception (&error); + return NULL; } } else { g_assert_not_reached (); @@ -3193,6 +3256,7 @@ gpointer mono_marshal_safearray_get_value (gpointer safearray, gpointer indices) return result; } +/* This is an icall */ static gboolean mono_marshal_safearray_next (gpointer safearray, gpointer indices) { @@ -3210,7 +3274,8 @@ gboolean mono_marshal_safearray_next (gpointer safearray, gpointer indices) hr = mono_marshal_safe_array_get_ubound (safearray, i+1, &ubound); if (hr < 0) { cominterop_set_hr_error (&error, hr); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + mono_error_set_pending_exception (&error); + return FALSE; } if (++pIndices[i] <= ubound) { @@ -3220,7 +3285,8 @@ gboolean mono_marshal_safearray_next (gpointer safearray, gpointer indices) hr = mono_marshal_safe_array_get_lbound (safearray, i+1, &lbound); if (hr < 0) { cominterop_set_hr_error (&error, hr); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + mono_error_set_pending_exception (&error); + return FALSE; } pIndices[i] = lbound; @@ -3292,6 +3358,7 @@ mono_marshal_safearray_create (MonoArray *input, gpointer *newsafearray, gpointe return TRUE; } +/* This is an icall */ static void mono_marshal_safearray_set_value (gpointer safearray, gpointer indices, gpointer value) { @@ -3300,14 +3367,16 @@ void mono_marshal_safearray_set_value (gpointer safearray, gpointer indices, gpo int hr = SafeArrayPutElement (safearray, indices, value); if (hr < 0) { cominterop_set_hr_error (&error, hr); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + mono_error_set_pending_exception (&error); + return; } #else if (com_provider == MONO_COM_MS && init_com_provider_ms ()) { int hr = safe_array_put_element_ms (safearray, (glong *)indices, (void **)value); if (hr < 0) { cominterop_set_hr_error (&error, hr); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + mono_error_set_pending_exception (&error); + return; } } else g_assert_not_reached (); @@ -3336,7 +3405,7 @@ mono_cominterop_init (void) emit an exception in the generated IL. */ 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_string_from_bstr_icall, "mono_string_from_bstr_icall", "obj ptr", FALSE); register_icall (mono_free_bstr, "mono_free_bstr", "void ptr", FALSE); } @@ -3351,20 +3420,19 @@ cominterop_release_all_rcws (void) } gpointer -mono_string_to_bstr (MonoString *string_obj) +mono_ptr_to_bstr (gpointer ptr, int slen) { - if (!string_obj) + if (!ptr) return NULL; #ifdef HOST_WIN32 - return SysAllocStringLen (mono_string_chars (string_obj), mono_string_length (string_obj)); + return SysAllocStringLen (ptr, slen); #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)); + memcpy (ret + sizeof(guint32), ptr, slen * sizeof(gunichar2)); * ((guint32 *) ret) = slen * sizeof(gunichar2); ret [4 + slen * sizeof(gunichar2)] = 0; ret [5 + slen * sizeof(gunichar2)] = 0; @@ -3374,19 +3442,37 @@ mono_string_to_bstr (MonoString *string_obj) #endif } + MonoString * mono_string_from_bstr (gpointer bstr) { - MonoString *res = NULL; MonoError error; + MonoString *result = mono_string_from_bstr_checked (bstr, &error); + mono_error_cleanup (&error); + return result; +} + +MonoString * +mono_string_from_bstr_icall (gpointer bstr) +{ + MonoError error; + MonoString *result = mono_string_from_bstr_checked (bstr, &error); + mono_error_set_pending_exception (&error); + return result; +} + +MonoString * +mono_string_from_bstr_checked (gpointer bstr, MonoError *error) +{ + MonoString *res = NULL; + mono_error_init (error); if (!bstr) return NULL; #ifdef HOST_WIN32 - res = mono_string_new_utf16_checked (mono_domain_get (), bstr, SysStringLen (bstr), &error); + res = mono_string_new_utf16_checked (mono_domain_get (), bstr, SysStringLen (bstr), error); #else - res = mono_string_new_utf16_checked (mono_domain_get (), bstr, *((guint32 *)bstr - 1) / sizeof(gunichar2), &error); + res = mono_string_new_utf16_checked (mono_domain_get (), bstr, *((guint32 *)bstr - 1) / sizeof(gunichar2), error); #endif - mono_error_raise_exception (&error); /* FIXME don't raise here */ return res; } @@ -3434,7 +3520,10 @@ ves_icall_System_Runtime_InteropServices_Marshal_QueryInterfaceInternal (gpointe MonoString * ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR (gpointer ptr) { - return mono_string_from_bstr(ptr); + MonoError error; + MonoString *result = mono_string_from_bstr_checked (ptr, &error); + mono_error_set_pending_exception (&error); + return result; } gpointer @@ -3443,6 +3532,12 @@ ves_icall_System_Runtime_InteropServices_Marshal_StringToBSTR (MonoString* ptr) return mono_string_to_bstr(ptr); } +gpointer +ves_icall_System_Runtime_InteropServices_Marshal_BufferToBSTR (MonoArray* ptr, int len) +{ + return mono_ptr_to_bstr (ptr->vector, len); +} + void ves_icall_System_Runtime_InteropServices_Marshal_FreeBSTR (gpointer ptr) {