#endif // WIN32
#endif // DISABLE_COM
+// This function is used regardless of the BSTR type, so cast the return value
+// Inputted string length, in bytes, should include the null terminator
+// Returns the start of the string itself
+static gpointer
+mono_bstr_alloc (size_t str_byte_len)
+{
+ // Allocate string length plus pointer-size integer to store the length, aligned to 16 bytes
+ size_t alloc_size = str_byte_len + SIZEOF_VOID_P;
+ alloc_size += (16 - 1);
+ alloc_size &= ~(16 - 1);
+ gpointer ret = g_malloc0 (alloc_size);
+ return ret ? (char *)ret + SIZEOF_VOID_P : NULL;
+}
+
+static void
+mono_bstr_set_length (gunichar2 *bstr, int slen)
+{
+ *((guint32 *)bstr - 1) = slen * sizeof (gunichar2);
+}
+
/* PTR can be NULL */
mono_bstr
mono_ptr_to_bstr (const gunichar2* ptr, int slen)
#ifndef DISABLE_COM
if (com_provider == MONO_COM_DEFAULT) {
#endif
+ // In Mono, historically BSTR was allocated with a guaranteed size prefix of 4 bytes regardless of platform.
+ // Presumably this is due to the BStr documentation page, which indicates that behavior and then directs you to call
+ // SysAllocString on Windows to handle the allocation for you. Unfortunately, this is not actually how it works:
+ // The allocation pre-string is pointer-sized, and then only 4 bytes are used for the length regardless. Additionally,
+ // the total length is also aligned to a 16-byte boundary. This preserves the old behavior on legacy and fixes it for
+ // netcore moving forward.
+#ifdef ENABLE_NETCORE
+ mono_bstr const s = (mono_bstr)mono_bstr_alloc ((slen + 1) * sizeof (gunichar2));
+ if (s == NULL)
+ return NULL;
+#else
/* allocate len + 1 utf16 characters plus 4 byte integer for length*/
guint32 * const ret = (guint32 *)g_malloc ((slen + 1) * sizeof (gunichar2) + sizeof (guint32));
if (ret == NULL)
return NULL;
mono_bstr const s = (mono_bstr)(ret + 1);
- *ret = slen * sizeof (gunichar2);
+#endif
+ mono_bstr_set_length (s, slen);
if (ptr)
memcpy (s, ptr, slen * sizeof (gunichar2));
s [slen] = 0;
#endif
}
-static MonoStringHandle
+char *
+mono_ptr_to_ansibstr (const char *ptr, size_t slen)
+{
+ // FIXME: should this behave differently without DISABLE_COM?
+ char *s = (char *)mono_bstr_alloc ((slen + 1) * sizeof(char));
+ if (s == NULL)
+ return NULL;
+ *((guint32 *)s - 1) = slen * sizeof (char);
+ if (ptr)
+ memcpy (s, ptr, slen * sizeof (char));
+ s [slen] = 0;
+ return s;
+}
+
+MonoStringHandle
mono_string_from_bstr_checked (mono_bstr_const bstr, MonoError *error)
{
if (!bstr)
#ifndef DISABLE_COM
if (com_provider == MONO_COM_DEFAULT) {
#endif
+#ifdef ENABLE_NETCORE
+ g_free (((char *)bstr) - SIZEOF_VOID_P);
+#else // In Mono, historically BSTR was allocated with a guaranteed size prefix of 4 bytes regardless of platform
g_free (((char *)bstr) - 4);
+#endif
#ifndef DISABLE_COM
} else if (com_provider == MONO_COM_MS && init_com_provider_ms ()) {
sys_free_string_ms ((mono_bstr_const)bstr);
MONO_HANDLE_REGISTER_ICALL (mono_object_isinst_icall, MonoObject, 2, (MonoObject, MonoClass_ptr))
MONO_HANDLE_REGISTER_ICALL (mono_string_builder_to_utf16, gunichar2_ptr, 1, (MonoStringBuilder))
MONO_HANDLE_REGISTER_ICALL (mono_string_builder_to_utf8, char_ptr, 1, (MonoStringBuilder))
+MONO_HANDLE_REGISTER_ICALL (mono_string_from_ansibstr, MonoString, 1, (const_char_ptr))
MONO_HANDLE_REGISTER_ICALL (mono_string_from_bstr_icall, MonoString, 1, (mono_bstr_const))
MONO_HANDLE_REGISTER_ICALL (mono_string_from_byvalstr, MonoString, 2, (const_char_ptr, int))
MONO_HANDLE_REGISTER_ICALL (mono_string_from_byvalwstr, MonoString, 2, (const_gunichar2_ptr, int))
+MONO_HANDLE_REGISTER_ICALL (mono_string_from_tbstr, MonoString, 1, (gpointer))
MONO_HANDLE_REGISTER_ICALL (mono_string_new_len_wrapper, MonoString, 2, (const_char_ptr, guint))
MONO_HANDLE_REGISTER_ICALL (mono_string_new_wrapper_internal, MonoString, 1, (const_char_ptr))
-MONO_HANDLE_REGISTER_ICALL (mono_string_to_ansibstr, gpointer, 1, (MonoString))
+MONO_HANDLE_REGISTER_ICALL (mono_string_to_ansibstr, char_ptr, 1, (MonoString))
MONO_HANDLE_REGISTER_ICALL (mono_string_to_bstr, mono_bstr, 1, (MonoString))
MONO_HANDLE_REGISTER_ICALL (mono_string_to_byvalstr, void, 3, (char_ptr, MonoString, int))
MONO_HANDLE_REGISTER_ICALL (mono_string_to_byvalwstr, void, 3, (gunichar2_ptr, MonoString, int))
+MONO_HANDLE_REGISTER_ICALL (mono_string_to_tbstr, gpointer, 1, (MonoString))
MONO_HANDLE_REGISTER_ICALL (mono_string_to_utf16_internal, mono_unichar2_ptr, 1, (MonoString))
MONO_HANDLE_REGISTER_ICALL (mono_string_to_utf32_internal, mono_unichar4_ptr, 1, (MonoString)) // embedding API
MONO_HANDLE_REGISTER_ICALL (mono_string_utf16_to_builder, void, 2, (MonoStringBuilder, const_gunichar2_ptr))
static void
emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object, int offset_of_first_child_field, MonoMarshalNative string_encoding);
+static MonoJitICallId
+conv_to_icall (MonoMarshalConv conv, int *ind_store_type);
+
+static MonoMarshalConv
+conv_str_inverse (MonoMarshalConv conv);
+
/**
* mono_mb_strdup:
* \param mb the MethodBuilder
}
mono_mb_emit_byte (mb, CEE_STIND_REF);
break;
- case MONO_MARSHAL_CONV_STR_LPTSTR:
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_byte (mb, CEE_LDIND_I);
-#ifdef TARGET_WIN32
- mono_mb_emit_icall (mb, ves_icall_mono_string_from_utf16);
-#else
- mono_mb_emit_icall (mb, ves_icall_string_new_wrapper);
-#endif
- mono_mb_emit_byte (mb, CEE_STIND_REF);
- break;
- // In Mono historically LPSTR was treated as a UTF8STR
- case MONO_MARSHAL_CONV_STR_LPSTR:
+ case MONO_MARSHAL_CONV_STR_ANSIBSTR:
+ case MONO_MARSHAL_CONV_STR_TBSTR:
case MONO_MARSHAL_CONV_STR_UTF8STR:
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_icall (mb, ves_icall_string_new_wrapper);
- mono_mb_emit_byte (mb, CEE_STIND_REF);
- break;
case MONO_MARSHAL_CONV_STR_LPWSTR:
+ case MONO_MARSHAL_CONV_STR_LPSTR:
+ case MONO_MARSHAL_CONV_STR_LPTSTR:
+ case MONO_MARSHAL_CONV_STR_BSTR: {
mono_mb_emit_ldloc (mb, 1);
mono_mb_emit_ldloc (mb, 0);
mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_icall (mb, ves_icall_mono_string_from_utf16);
+ mono_mb_emit_icall_id (mb, conv_to_icall (conv_str_inverse (conv), NULL));
mono_mb_emit_byte (mb, CEE_STIND_REF);
break;
+ }
+
case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
MonoClass *klass = mono_class_from_mono_type_internal (type);
int src_var, dst_var;
break;
}
- case MONO_MARSHAL_CONV_STR_BSTR:
- case MONO_MARSHAL_CONV_STR_ANSIBSTR:
- case MONO_MARSHAL_CONV_STR_TBSTR:
case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
default: {
char *msg = g_strdup_printf ("marshaling conversion %d not implemented", conv);
}
}
+// On legacy Mono, LPTSTR was either UTF16 or UTF8 depending on platform
+static inline MonoJitICallId
+mono_string_to_platform_unicode (void)
+{
+#ifdef TARGET_WIN32
+ return MONO_JIT_ICALL_mono_marshal_string_to_utf16;
+#else
+ return MONO_JIT_ICALL_mono_string_to_utf8str;
+#endif
+}
+
+static inline MonoJitICallId
+mono_string_from_platform_unicode (void)
+{
+#ifdef TARGET_WIN32
+ return MONO_JIT_ICALL_ves_icall_mono_string_from_utf16;
+#else
+ return MONO_JIT_ICALL_ves_icall_string_new_wrapper;
+#endif
+}
+
+static inline MonoJitICallId
+mono_string_builder_to_platform_unicode (void)
+{
+#ifdef TARGET_WIN32
+ return MONO_JIT_ICALL_mono_string_builder_to_utf16;
+#else
+ return MONO_JIT_ICALL_mono_string_builder_to_utf8;
+#endif
+}
+
+static inline MonoJitICallId
+mono_string_builder_from_platform_unicode (void)
+{
+#ifdef TARGET_WIN32
+ return MONO_JIT_ICALL_mono_string_utf16_to_builder;
+#else
+ return MONO_JIT_ICALL_mono_string_utf8_to_builder;
+#endif
+}
+
+static MonoMarshalConv
+conv_str_inverse (MonoMarshalConv conv)
+{
+ switch (conv) {
+ // AnsiBStr
+ case MONO_MARSHAL_CONV_STR_ANSIBSTR:
+ return MONO_MARSHAL_CONV_ANSIBSTR_STR;
+ case MONO_MARSHAL_CONV_ANSIBSTR_STR:
+ return MONO_MARSHAL_CONV_STR_ANSIBSTR;
+
+ // BStr
+ case MONO_MARSHAL_CONV_STR_BSTR:
+ return MONO_MARSHAL_CONV_BSTR_STR;
+ case MONO_MARSHAL_CONV_BSTR_STR:
+ return MONO_MARSHAL_CONV_STR_BSTR;
+
+ // LPStr
+ case MONO_MARSHAL_CONV_STR_LPSTR:
+ return MONO_MARSHAL_CONV_LPSTR_STR;
+ case MONO_MARSHAL_CONV_LPSTR_STR:
+ return MONO_MARSHAL_CONV_STR_LPSTR;
+
+ // LPTStr
+ case MONO_MARSHAL_CONV_STR_LPTSTR:
+ return MONO_MARSHAL_CONV_LPTSTR_STR;
+ case MONO_MARSHAL_CONV_LPTSTR_STR:
+ return MONO_MARSHAL_CONV_STR_LPTSTR;
+
+ // LPUTF8Str
+ case MONO_MARSHAL_CONV_STR_UTF8STR:
+ return MONO_MARSHAL_CONV_UTF8STR_STR;
+ case MONO_MARSHAL_CONV_UTF8STR_STR:
+ return MONO_MARSHAL_CONV_STR_UTF8STR;
+
+ // LPWStr
+ case MONO_MARSHAL_CONV_STR_LPWSTR:
+ return MONO_MARSHAL_CONV_LPWSTR_STR;
+ case MONO_MARSHAL_CONV_LPWSTR_STR:
+ return MONO_MARSHAL_CONV_STR_LPWSTR;
+
+ // TBStr
+ case MONO_MARSHAL_CONV_STR_TBSTR:
+ return MONO_MARSHAL_CONV_TBSTR_STR;
+ case MONO_MARSHAL_CONV_TBSTR_STR:
+ return MONO_MARSHAL_CONV_STR_TBSTR;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
static MonoJitICallId
conv_to_icall (MonoMarshalConv conv, int *ind_store_type)
{
ind_store_type = &dummy;
*ind_store_type = CEE_STIND_I;
switch (conv) {
- case MONO_MARSHAL_CONV_STR_LPWSTR:
- return MONO_JIT_ICALL_mono_marshal_string_to_utf16;
- case MONO_MARSHAL_CONV_LPWSTR_STR:
+ // AnsiBStr
+ case MONO_MARSHAL_CONV_STR_ANSIBSTR:
+ return MONO_JIT_ICALL_mono_string_to_ansibstr;
+ case MONO_MARSHAL_CONV_ANSIBSTR_STR:
*ind_store_type = CEE_STIND_REF;
- return MONO_JIT_ICALL_ves_icall_mono_string_from_utf16;
- case MONO_MARSHAL_CONV_LPTSTR_STR:
+ return MONO_JIT_ICALL_mono_string_from_ansibstr;
+
+ // BStr
+ case MONO_MARSHAL_CONV_STR_BSTR:
+ return MONO_JIT_ICALL_mono_string_to_bstr;
+ case MONO_MARSHAL_CONV_BSTR_STR:
*ind_store_type = CEE_STIND_REF;
- return MONO_JIT_ICALL_ves_icall_string_new_wrapper;
- case MONO_MARSHAL_CONV_UTF8STR_STR:
+ return MONO_JIT_ICALL_mono_string_from_bstr_icall;
+
+ // LPStr
+ // In Mono, LPSTR was historically treated as UTF8STR
+ case MONO_MARSHAL_CONV_STR_LPSTR:
+ return MONO_JIT_ICALL_mono_string_to_utf8str;
case MONO_MARSHAL_CONV_LPSTR_STR:
*ind_store_type = CEE_STIND_REF;
return MONO_JIT_ICALL_ves_icall_string_new_wrapper;
+ case MONO_MARSHAL_CONV_SB_LPSTR:
+ return MONO_JIT_ICALL_mono_string_builder_to_utf8;
+ case MONO_MARSHAL_CONV_LPSTR_SB:
+ *ind_store_type = CEE_STIND_REF;
+ return MONO_JIT_ICALL_mono_string_utf8_to_builder;
+
+ // LPTStr
+ // FIXME: This is how LPTStr was handled on legacy, but it's not correct and for netcore we should implement this more properly.
+ // This type is supposed to detect ANSI or UTF16 (as LPTStr can be either depending on _UNICODE) and handle it accordingly.
+ // The CoreCLR test for this type only tests as LPWSTR regardless of platform.
case MONO_MARSHAL_CONV_STR_LPTSTR:
-#ifdef TARGET_WIN32
- return MONO_JIT_ICALL_mono_marshal_string_to_utf16;
-#else
- return MONO_JIT_ICALL_mono_string_to_utf8str;
-#endif
- // In Mono historically LPSTR was treated as a UTF8STR
+ return mono_string_to_platform_unicode ();
+ case MONO_MARSHAL_CONV_LPTSTR_STR:
+ *ind_store_type = CEE_STIND_REF;
+ return mono_string_from_platform_unicode ();
+ case MONO_MARSHAL_CONV_SB_LPTSTR:
+ return mono_string_builder_to_platform_unicode ();
+ case MONO_MARSHAL_CONV_LPTSTR_SB:
+ *ind_store_type = CEE_STIND_REF;
+ return mono_string_builder_from_platform_unicode ();
+
+ // LPUTF8Str
case MONO_MARSHAL_CONV_STR_UTF8STR:
- case MONO_MARSHAL_CONV_STR_LPSTR:
return MONO_JIT_ICALL_mono_string_to_utf8str;
- case MONO_MARSHAL_CONV_STR_BSTR:
- return MONO_JIT_ICALL_mono_string_to_bstr;
- case MONO_MARSHAL_CONV_BSTR_STR:
+ case MONO_MARSHAL_CONV_UTF8STR_STR:
*ind_store_type = CEE_STIND_REF;
- return MONO_JIT_ICALL_mono_string_from_bstr_icall;
- case MONO_MARSHAL_CONV_STR_TBSTR:
- case MONO_MARSHAL_CONV_STR_ANSIBSTR:
- return MONO_JIT_ICALL_mono_string_to_ansibstr;
+ return MONO_JIT_ICALL_ves_icall_string_new_wrapper;
case MONO_MARSHAL_CONV_SB_UTF8STR:
- case MONO_MARSHAL_CONV_SB_LPSTR:
- return MONO_JIT_ICALL_mono_string_builder_to_utf8;
- case MONO_MARSHAL_CONV_SB_LPTSTR:
-#ifdef TARGET_WIN32
- return MONO_JIT_ICALL_mono_string_builder_to_utf16;
-#else
return MONO_JIT_ICALL_mono_string_builder_to_utf8;
-#endif
- case MONO_MARSHAL_CONV_SB_LPWSTR:
- return MONO_JIT_ICALL_mono_string_builder_to_utf16;
- case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
- return MONO_JIT_ICALL_mono_array_to_savearray;
- case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
- return MONO_JIT_ICALL_mono_array_to_lparray;
- case MONO_MARSHAL_FREE_LPARRAY:
- return MONO_JIT_ICALL_mono_free_lparray;
- case MONO_MARSHAL_CONV_DEL_FTN:
- return MONO_JIT_ICALL_mono_delegate_to_ftnptr;
- case MONO_MARSHAL_CONV_FTN_DEL:
- *ind_store_type = CEE_STIND_REF;
- return MONO_JIT_ICALL_mono_ftnptr_to_delegate;
case MONO_MARSHAL_CONV_UTF8STR_SB:
- case MONO_MARSHAL_CONV_LPSTR_SB:
*ind_store_type = CEE_STIND_REF;
return MONO_JIT_ICALL_mono_string_utf8_to_builder;
- case MONO_MARSHAL_CONV_LPTSTR_SB:
+
+ // LPWStr
+ case MONO_MARSHAL_CONV_STR_LPWSTR:
+ return MONO_JIT_ICALL_mono_marshal_string_to_utf16;
+ case MONO_MARSHAL_CONV_LPWSTR_STR:
*ind_store_type = CEE_STIND_REF;
-#ifdef TARGET_WIN32
- return MONO_JIT_ICALL_mono_string_utf16_to_builder;
-#else
- return MONO_JIT_ICALL_mono_string_utf8_to_builder;
-#endif
+ return MONO_JIT_ICALL_ves_icall_mono_string_from_utf16;
+ case MONO_MARSHAL_CONV_SB_LPWSTR:
+ return MONO_JIT_ICALL_mono_string_builder_to_utf16;
case MONO_MARSHAL_CONV_LPWSTR_SB:
*ind_store_type = CEE_STIND_REF;
return MONO_JIT_ICALL_mono_string_utf16_to_builder;
- case MONO_MARSHAL_FREE_ARRAY:
- return MONO_JIT_ICALL_mono_marshal_free_array;
+
+ // TBStr
+ case MONO_MARSHAL_CONV_STR_TBSTR:
+ return MONO_JIT_ICALL_mono_string_to_tbstr;
+ case MONO_MARSHAL_CONV_TBSTR_STR:
+ *ind_store_type = CEE_STIND_REF;
+ return MONO_JIT_ICALL_mono_string_from_tbstr;
+
case MONO_MARSHAL_CONV_STR_BYVALSTR:
return MONO_JIT_ICALL_mono_string_to_byvalstr;
case MONO_MARSHAL_CONV_STR_BYVALWSTR:
return MONO_JIT_ICALL_mono_string_to_byvalwstr;
+
+ case MONO_MARSHAL_CONV_DEL_FTN:
+ return MONO_JIT_ICALL_mono_delegate_to_ftnptr;
+ case MONO_MARSHAL_CONV_FTN_DEL:
+ *ind_store_type = CEE_STIND_REF;
+ return MONO_JIT_ICALL_mono_ftnptr_to_delegate;
+
+ case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
+ return MONO_JIT_ICALL_mono_array_to_savearray;
+ case MONO_MARSHAL_FREE_ARRAY:
+ return MONO_JIT_ICALL_mono_marshal_free_array;
+
+ case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
+ return MONO_JIT_ICALL_mono_array_to_lparray;
+ case MONO_MARSHAL_FREE_LPARRAY:
+ return MONO_JIT_ICALL_mono_free_lparray;
+
default:
g_assert_not_reached ();
}
mono_mb_emit_byte (mb, CEE_NEG);
mono_mb_emit_byte (mb, CEE_STIND_I2);
break;
- // In Mono historically LPSTR was treated as a UTF8STR
case MONO_MARSHAL_CONV_STR_UTF8STR:
case MONO_MARSHAL_CONV_STR_LPWSTR:
case MONO_MARSHAL_CONV_STR_LPSTR:
return conv_arg;
}
+static inline void
+emit_string_free_icall (MonoMethodBuilder *mb, MonoMarshalConv conv)
+{
+ if (conv == MONO_MARSHAL_CONV_BSTR_STR || conv == MONO_MARSHAL_CONV_ANSIBSTR_STR || conv == MONO_MARSHAL_CONV_TBSTR_STR)
+ mono_mb_emit_icall (mb, mono_free_bstr);
+ else
+ mono_mb_emit_icall (mb, mono_marshal_free);
+}
+
static int
emit_marshal_string_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
MonoMarshalSpec *spec,
if (need_free) {
mono_mb_emit_ldloc (mb, conv_arg);
- if (conv == MONO_MARSHAL_CONV_BSTR_STR)
- mono_mb_emit_icall (mb, mono_free_bstr);
- else
- mono_mb_emit_icall (mb, mono_marshal_free);
+ emit_string_free_icall (mb, conv);
}
break;
/* free the string */
mono_mb_emit_ldloc (mb, 0);
- if (conv == MONO_MARSHAL_CONV_BSTR_STR)
- mono_mb_emit_icall (mb, mono_free_bstr);
- else
- mono_mb_emit_icall (mb, mono_marshal_free);
+ emit_string_free_icall (mb, conv);
break;
case MARSHAL_ACTION_MANAGED_CONV_IN:
register_icall (ves_icall_mono_string_from_utf16, mono_icall_sig_obj_ptr, FALSE);
register_icall (mono_string_from_byvalstr, mono_icall_sig_obj_ptr_int, FALSE);
register_icall (mono_string_from_byvalwstr, mono_icall_sig_obj_ptr_int, FALSE);
+ register_icall (mono_string_from_ansibstr, mono_icall_sig_obj_ptr, FALSE);
+ register_icall (mono_string_from_tbstr, mono_icall_sig_obj_ptr, FALSE);
register_icall (mono_string_new_wrapper_internal, mono_icall_sig_obj_ptr, FALSE);
register_icall (ves_icall_string_new_wrapper, mono_icall_sig_obj_ptr, FALSE);
register_icall (mono_string_new_len_wrapper, mono_icall_sig_obj_ptr_int, FALSE);
register_icall (ves_icall_mono_string_to_utf8, mono_icall_sig_ptr_obj, FALSE);
register_icall (mono_string_to_utf8str, mono_icall_sig_ptr_obj, FALSE);
register_icall (mono_string_to_ansibstr, mono_icall_sig_ptr_object, FALSE);
+ register_icall (mono_string_to_tbstr, mono_icall_sig_ptr_object, FALSE);
register_icall (mono_string_builder_to_utf8, mono_icall_sig_ptr_object, FALSE);
register_icall (mono_string_builder_to_utf16, mono_icall_sig_ptr_object, FALSE);
register_icall (mono_array_to_savearray, mono_icall_sig_ptr_object, FALSE);
#endif
-gpointer
+// Assume ANSI == UTF8 for now, same as LPSTR
+
+/* This is a JIT icall, it sets the pending exception (in wrapper) and returns NULL on error. */
+char *
mono_string_to_ansibstr_impl (MonoStringHandle string_obj, MonoError *error)
{
- g_error ("UnmanagedMarshal.BStr is not implemented.");
- return NULL;
+ if (MONO_HANDLE_IS_NULL (string_obj))
+ return NULL;
+
+ char *utf8_str = mono_string_handle_to_utf8 (string_obj, error);
+ return_val_if_nok (error, NULL);
+ char *res = mono_ptr_to_ansibstr (utf8_str, g_utf8_strlen (utf8_str, -1));
+ g_free (utf8_str);
+ return res;
+}
+
+/* This is a JIT icall, it sets the pending exception (in wrapper) and returns NULL on error. */
+MonoStringHandle
+mono_string_from_ansibstr_impl (const char *data, MonoError *error)
+{
+ if (!data)
+ return NULL_HANDLE_STRING;
+
+ return mono_string_new_utf8_len (mono_domain_get (), data, *((guint32 *)data - 1) / sizeof (char), error);
+}
+
+/* This is a JIT icall, it sets the pending exception (in wrapper) and returns NULL on error. */
+gpointer
+mono_string_to_tbstr_impl (MonoStringHandle string_obj, MonoError *error)
+{
+#ifdef TARGET_WIN32
+ return mono_string_to_bstr_impl (string_obj, error);
+#else
+ return mono_string_to_ansibstr_impl (string_obj, error);
+#endif
+}
+
+/* This is a JIT icall, it sets the pending exception (in wrapper) and returns NULL on error. */
+MonoStringHandle
+mono_string_from_tbstr_impl (gpointer data, MonoError *error)
+{
+#ifdef TARGET_WIN32
+ return mono_string_from_bstr_checked ((mono_bstr)data, error);
+#else
+ return mono_string_from_ansibstr_impl ((char *)data, error);
+#endif
}
/**
return MONO_MARSHAL_CONV_STR_BSTR;
case MONO_NATIVE_UTF8STR:
return MONO_MARSHAL_CONV_STR_UTF8STR;
+ case MONO_NATIVE_ANSIBSTR:
+ return MONO_MARSHAL_CONV_STR_ANSIBSTR;
+ case MONO_NATIVE_TBSTR:
+ return MONO_MARSHAL_CONV_STR_TBSTR;
default:
return MONO_MARSHAL_CONV_INVALID;
}
return MONO_MARSHAL_CONV_LPTSTR_STR;
case MONO_NATIVE_BSTR:
return MONO_MARSHAL_CONV_BSTR_STR;
+ case MONO_NATIVE_ANSIBSTR:
+ return MONO_MARSHAL_CONV_ANSIBSTR_STR;
+ case MONO_NATIVE_TBSTR:
+ return MONO_MARSHAL_CONV_TBSTR_STR;
default:
return MONO_MARSHAL_CONV_INVALID;
}
break;
#endif
case MONO_MARSHAL_CONV_STR_LPSTR:
- case MONO_MARSHAL_CONV_STR_ANSIBSTR:
- case MONO_MARSHAL_CONV_STR_TBSTR:
case MONO_MARSHAL_CONV_STR_UTF8STR:
mono_marshal_free (*(gpointer *)cpos);
break;
+
+ case MONO_MARSHAL_CONV_STR_ANSIBSTR:
+ case MONO_MARSHAL_CONV_STR_TBSTR:
case MONO_MARSHAL_CONV_STR_BSTR:
mono_free_bstr (*(gpointer*)cpos);
break;