-
Notifications
You must be signed in to change notification settings - Fork 27
/
0008-2020-02-marshal-Fix-VARIANT-and-BSTR-marshaling-in-s.patch
251 lines (229 loc) · 7.99 KB
/
0008-2020-02-marshal-Fix-VARIANT-and-BSTR-marshaling-in-s.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
From acb8d8ed6fd7fc7034b57157db1119bb5e259cc3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Aleksey=20Kliger=20=28=CE=BBgeek=29?= <alklig@microsoft.com>
Date: Thu, 11 Mar 2021 12:38:52 -0500
Subject: [PATCH 08/32] [2020-02][marshal] Fix VARIANT and BSTR marshaling in
structs (#20918)
* [tests] Add BStr and VARIANT in structs interop tests
* [marshal] Fix reverse P/Invoke marshaling VARIANT fields
Partial revert of https://github.com/mono/mono/pull/8732
If a managed struct is declared as
public struct StructWithVariant
{
[MarshalAs (UnmanagedType.Struct)]
public object data;
};
Then the `data` field should be marshalled as a VARIANT.
The fix checks that the field's type is `object` and uses VARIANT for
marshaling, otherwise it continues as in mono/mono#8732 and uses
MONO_MARSHAL_CONV_OBJECT_STRUCT
* [marshal] Marshal BSTR from reverse pinvokes
---
mono/metadata/marshal-ilgen.c | 8 ++++-
mono/metadata/metadata.c | 12 ++++++-
mono/tests/cominterop.cs | 65 +++++++++++++++++++++++++++++++++--
mono/tests/libtest.c | 48 ++++++++++++++++++++++++++
4 files changed, 129 insertions(+), 4 deletions(-)
diff --git a/mono/metadata/marshal-ilgen.c b/mono/metadata/marshal-ilgen.c
index 5472727ef0f..de6fefed06e 100644
--- a/mono/metadata/marshal-ilgen.c
+++ b/mono/metadata/marshal-ilgen.c
@@ -488,6 +488,13 @@ emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv
mono_mb_emit_icall (mb, ves_icall_mono_string_from_utf16);
mono_mb_emit_byte (mb, CEE_STIND_REF);
break;
+ 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, mono_string_from_bstr_icall);
+ 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;
@@ -576,7 +583,6 @@ emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv
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:
diff --git a/mono/metadata/metadata.c b/mono/metadata/metadata.c
index 5f6568da9b0..b2987016ef2 100644
--- a/mono/metadata/metadata.c
+++ b/mono/metadata/metadata.c
@@ -6781,7 +6781,17 @@ handle_enum:
if (mspec) {
switch (mspec->native) {
case MONO_NATIVE_STRUCT:
- *conv = MONO_MARSHAL_CONV_OBJECT_STRUCT;
+ // [MarshalAs(UnmanagedType.Struct)]
+ // object field;
+ //
+ // becomes a VARIANT
+ //
+ // [MarshalAs(UnmangedType.Struct)]
+ // SomeClass field;
+ //
+ // becomes uses the CONV_OBJECT_STRUCT conversion
+ if (t != MONO_TYPE_OBJECT)
+ *conv = MONO_MARSHAL_CONV_OBJECT_STRUCT;
return MONO_NATIVE_STRUCT;
case MONO_NATIVE_CUSTOM:
return MONO_NATIVE_CUSTOM;
diff --git a/mono/tests/cominterop.cs b/mono/tests/cominterop.cs
index e83cafd0625..11cb68bcdbc 100644
--- a/mono/tests/cominterop.cs
+++ b/mono/tests/cominterop.cs
@@ -224,7 +224,21 @@ public class Tests
[DllImport ("libtest")]
public static extern int mono_test_marshal_variant_out_bool_false_unmanaged (VarRefFunc func);
- [DllImport ("libtest")]
+ public delegate int CheckStructWithVariantFunc ([MarshalAs (UnmanagedType.Struct)] StructWithVariant obj);
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_struct_with_variant_in_unmanaged (CheckStructWithVariantFunc func);
+
+ public delegate int CheckStructWithBstrFunc ([MarshalAs (UnmanagedType.Struct)] StructWithBstr obj);
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_struct_with_bstr_in_unmanaged (CheckStructWithBstrFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_struct_with_variant_out_unmanaged ([MarshalAs (UnmanagedType.Struct)] StructWithVariant obj);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_struct_with_bstr_out_unmanaged ([MarshalAs (UnmanagedType.Struct)] StructWithBstr obj);
+
+ [DllImport ("libtest")]
public static extern int mono_test_marshal_com_object_create (out IntPtr pUnk);
[DllImport ("libtest")]
@@ -338,7 +352,6 @@ public class Tests
public static int Main ()
{
-
bool isWindows = !(((int)Environment.OSVersion.Platform == 4) ||
((int)Environment.OSVersion.Platform == 128));
@@ -356,6 +369,15 @@ public static int Main ()
if (mono_test_marshal_bstr_out_null (out str) != 0 || str != null)
return 2;
+ var sbfunc = new CheckStructWithBstrFunc(mono_test_marshal_struct_with_bstr_callback);
+ if (mono_test_marshal_struct_with_bstr_in_unmanaged(sbfunc) != 0)
+ return 3;
+
+ StructWithBstr swithB;
+ swithB.data = "this is a test string";
+ if (mono_test_marshal_struct_with_bstr_out_unmanaged (swithB) != 0)
+ return 4;
+
#endregion // BSTR Tests
#region VARIANT Tests
@@ -481,6 +503,15 @@ public static int Main ()
if (mono_test_marshal_variant_out_bstr_byref (out obj) != 0 || (string)obj != "PI")
return 107;
+ var svfunc = new CheckStructWithVariantFunc(mono_test_marshal_struct_with_variant_callback);
+ if (mono_test_marshal_struct_with_variant_in_unmanaged(svfunc) != 0)
+ return 108;
+
+ StructWithVariant swithV;
+ swithV.data = (object)-123;
+ if (mono_test_marshal_struct_with_variant_out_unmanaged (swithV) != 0)
+ return 109;
+
#endregion // VARIANT Tests
#region Runtime Callable Wrapper Tests
@@ -1581,8 +1612,38 @@ public static int TestITestDelegate (ITest itest)
public static int TestIfaceNoIcall (ITestPresSig itest) {
return itest.Return22NoICall () == 22 ? 0 : 1;
}
+
+ public static int mono_test_marshal_struct_with_variant_callback(StructWithVariant sv)
+ {
+ if (sv.data.GetType() != typeof(int))
+ return 1;
+ if ((int)sv.data != -123)
+ return 2;
+ return 0;
+ }
+
+ public static int mono_test_marshal_struct_with_bstr_callback(StructWithBstr sb)
+ {
+ if (sb.data.GetType() != typeof(string))
+ return 1;
+ if ((string)sb.data != "this is a test string")
+ return 2;
+ return 0;
+ }
}
public class TestVisible
{
}
+
+public struct StructWithVariant
+{
+ [MarshalAs (UnmanagedType.Struct)]
+ public object data;
+}
+
+public struct StructWithBstr
+{
+ [MarshalAs (UnmanagedType.BStr)]
+ public string data;
+}
diff --git a/mono/tests/libtest.c b/mono/tests/libtest.c
index 3f14636bb25..e5e5f2f14d3 100644
--- a/mono/tests/libtest.c
+++ b/mono/tests/libtest.c
@@ -3378,6 +3378,54 @@ mono_test_marshal_variant_out_bool_false_unmanaged(VarRefFunc func)
return 1;
}
+typedef struct _StructWithVariant {
+ VARIANT data;
+} StructWithVariant;
+typedef int (STDCALL *CheckStructWithVariantFunc) (StructWithVariant sv);
+
+LIBTEST_API int STDCALL
+mono_test_marshal_struct_with_variant_in_unmanaged(CheckStructWithVariantFunc func)
+{
+ StructWithVariant sv;
+ sv.data.vt = VT_I4;
+ sv.data.lVal = -123;
+ return func(sv);
+}
+
+LIBTEST_API int STDCALL
+mono_test_marshal_struct_with_variant_out_unmanaged (StructWithVariant sv)
+{
+ if (sv.data.vt != VT_I4)
+ return 1;
+ if (sv.data.lVal != -123)
+ return 2;
+ return 0;
+}
+
+typedef struct _StructWithBstr {
+ gunichar2* data;
+} StructWithBstr;
+typedef int (STDCALL *CheckStructWithBstrFunc) (StructWithBstr sb);
+
+LIBTEST_API int STDCALL
+mono_test_marshal_struct_with_bstr_in_unmanaged(CheckStructWithBstrFunc func)
+{
+ StructWithBstr sb;
+ sb.data = marshal_bstr_alloc("this is a test string");
+ return func(sb);
+}
+
+LIBTEST_API int STDCALL
+mono_test_marshal_struct_with_bstr_out_unmanaged (StructWithBstr sb)
+{
+ char *s = g_utf16_to_utf8 (sb.data, g_utf16_len (sb.data), NULL, NULL, NULL);
+ gboolean same = !strcmp (s, "this is a test string");
+ g_free (s);
+ if (!same)
+ return 1;
+ return 0;
+}
+
typedef struct MonoComObject MonoComObject;
typedef struct MonoDefItfObject MonoDefItfObject;
--
2.31.1