[xbuild] Use the env var $MSBuildExtensionsPath before trying other paths.
[mono.git] / mono / metadata / marshal.c
index 2bd85408e29f25d709fa3a71122b62aa98b10ba6..0e6a259a4376a1f5abaf7352ece91310eae26458 100644 (file)
@@ -86,6 +86,9 @@ delegate_hash_table_add (MonoDelegate *d);
 static void
 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object);
 
+static void
+emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object, MonoMarshalNative string_encoding);
+
 static void 
 mono_struct_delete_old (MonoClass *klass, char *ptr);
 
@@ -1434,12 +1437,14 @@ conv_to_icall (MonoMarshalConv conv)
                return mono_marshal_string_to_utf16;            
        case MONO_MARSHAL_CONV_LPWSTR_STR:
                return mono_string_from_utf16;
-       case MONO_MARSHAL_CONV_LPSTR_STR:
+       case MONO_MARSHAL_CONV_LPTSTR_STR:
 #ifdef TARGET_WIN32
                return mono_string_from_utf16;
 #else
                return mono_string_new_wrapper;
 #endif
+       case MONO_MARSHAL_CONV_LPSTR_STR:
+               return mono_string_new_wrapper;
        case MONO_MARSHAL_CONV_STR_LPTSTR:
 #ifdef TARGET_WIN32
                return mono_marshal_string_to_utf16;
@@ -1766,7 +1771,8 @@ emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv
 }
 
 static void
-emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
+emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object,
+                                          MonoMarshalNative string_encoding)
 {
        MonoMarshalType *info;
        int i;
@@ -1869,7 +1875,7 @@ emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
                        case MONO_TYPE_R8:
                                mono_mb_emit_ldloc (mb, 1);
                                mono_mb_emit_ldloc (mb, 0);
-                               if (ntype == MONO_NATIVE_U1) {
+                               if (t == MONO_TYPE_CHAR && ntype == MONO_NATIVE_U1 && string_encoding != MONO_NATIVE_LPWSTR) {
                                        if (to_object) {
                                                mono_mb_emit_byte (mb, CEE_LDIND_U1);
                                                mono_mb_emit_byte (mb, CEE_STIND_I2);
@@ -1985,6 +1991,12 @@ emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
        }
 }
 
+static void
+emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
+{
+       emit_struct_conv_full (mb, klass, to_object, -1);
+}
+
 static void
 emit_struct_free (MonoMethodBuilder *mb, MonoClass *klass, int struct_var)
 {
@@ -4013,6 +4025,8 @@ mono_marshal_get_delegate_invoke (MonoMethod *method, MonoDelegate *del)
                        res = newm;
                        new_key = g_new0 (SignatureMethodPair, 1);
                        *new_key = key;
+                       if (static_method_with_first_arg_bound)
+                               new_key->sig = signature_dup (del->method->klass->image, key.sig);
                        g_hash_table_insert (cache, new_key, res);
                        mono_marshal_set_wrapper_info (res, new_key);
                        mono_marshal_unlock ();
@@ -4594,6 +4608,10 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual)
        csig->params [2] = &mono_defaults.int_class->byval_arg;
        csig->params [3] = &mono_defaults.int_class->byval_arg;
        csig->pinvoke = 1;
+#if TARGET_WIN32
+       /* This is called from runtime code so it has to be cdecl */
+       csig->call_convention = MONO_CALL_C;
+#endif
 
        name = mono_signature_to_name (callsig, virtual ? "runtime_invoke_virtual" : "runtime_invoke");
        mb = mono_mb_new (target_klass, name,  MONO_WRAPPER_RUNTIME_INVOKE);
@@ -5368,7 +5386,7 @@ emit_marshal_custom (EmitMarshalContext *m, int argnum, MonoType *t,
        static MonoClass *ICustomMarshaler = NULL;
        static MonoMethod *cleanup_native, *cleanup_managed;
        static MonoMethod *marshal_managed_to_native, *marshal_native_to_managed;
-       MonoMethod *get_instance;
+       MonoMethod *get_instance = NULL;
        MonoMethodBuilder *mb = m->mb;
        char *exception_msg = NULL;
        guint32 loc1;
@@ -5376,7 +5394,10 @@ emit_marshal_custom (EmitMarshalContext *m, int argnum, MonoType *t,
 
        if (!ICustomMarshaler) {
                ICustomMarshaler = mono_class_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "ICustomMarshaler");
-               g_assert (ICustomMarshaler);
+               if (!ICustomMarshaler) {
+                       exception_msg = g_strdup ("Current profile doesn't support ICustomMarshaler");
+                       goto handle_exception;
+               }
 
                cleanup_native = mono_class_get_method_from_name (ICustomMarshaler, "CleanUpNativeData", 1);
                g_assert (cleanup_native);
@@ -5408,6 +5429,7 @@ emit_marshal_custom (EmitMarshalContext *m, int argnum, MonoType *t,
        if (!get_instance)
                exception_msg = g_strdup_printf ("Custom marshaler '%s' does not implement a static GetInstance method that takes a single string parameter and returns an ICustomMarshaler.", mklass->name);
 
+handle_exception:
        /* Throw exception and emit compensation code if neccesary */
        if (exception_msg) {
                switch (action) {
@@ -6597,7 +6619,7 @@ emit_marshal_object (EmitMarshalContext *m, int argnum, MonoType *t,
                                }
 
                                mono_mb_emit_ldloc (mb, conv_arg);
-                               mono_mb_emit_icall (mb, g_free);
+                               mono_mb_emit_icall (mb, mono_marshal_free);
 
                                mono_mb_patch_branch (mb, pos2);
                        }
@@ -6659,7 +6681,7 @@ emit_marshal_object (EmitMarshalContext *m, int argnum, MonoType *t,
        
                        /* Free the pointer allocated by unmanaged code */
                        mono_mb_emit_ldloc (mb, loc);
-                       mono_mb_emit_icall (mb, g_free);
+                       mono_mb_emit_icall (mb, mono_marshal_free);
                        mono_mb_patch_branch (mb, pos);
                }
                break;
@@ -7099,7 +7121,7 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
                                mono_mb_emit_stloc (mb, 1);
 
                                /* emit valuetype conversion code */
-                               emit_struct_conv (mb, eklass, FALSE);
+                               emit_struct_conv_full (mb, eklass, FALSE, eklass == mono_defaults.char_class ? encoding : -1);
                        }
 
                        mono_mb_emit_add_to_local (mb, index_var, 1);
@@ -7217,7 +7239,7 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
                                        mono_mb_emit_stloc (mb, 1);
 
                                        /* emit valuetype conversion code */
-                                       emit_struct_conv (mb, eklass, TRUE);
+                                       emit_struct_conv_full (mb, eklass, TRUE, eklass == mono_defaults.char_class ? encoding : -1);
                                }
 
                                if (need_free) {
@@ -10114,10 +10136,18 @@ mono_marshal_get_virtual_stelemref (MonoClass *array_class)
        res = mono_mb_create_method (mb, signature, 4);
        res->flags |= METHOD_ATTRIBUTE_VIRTUAL;
        mono_marshal_set_wrapper_info (res, GUINT_TO_POINTER (kind + 1));
-       cached_methods [kind] = res;
+
+       mono_marshal_lock ();
+       if (!cached_methods [kind]) {
+               cached_methods [kind] = res;
+               mono_marshal_unlock ();
+       } else {
+               mono_marshal_unlock ();
+               mono_free_method (res);
+       }
 
        mono_mb_free (mb);
-       return res;
+       return cached_methods [kind];
 }
 
 MonoMethod*