1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5#include <platformdefines.h>
6
7WCHAR strManaged[] = W("Managed\0String\0");
8size_t lenstrManaged = sizeof(strManaged) - sizeof(WCHAR);
9
10WCHAR strReturn[] = W("a\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
11WCHAR strerrReturn[] = W("error");
12
13WCHAR strNative[] = W(" Native");
14size_t lenstrNative = sizeof(strNative) - sizeof(WCHAR);
15
16//Test Method1
17extern "C" BSTR ReturnString()
18{
19 return TP_SysAllocString(strReturn);
20}
21
22extern "C" BSTR ReturnErrorString()
23{
24 return TP_SysAllocString(strerrReturn);
25}
26
27//Test Method2
28extern "C" DLL_EXPORT BSTR Marshal_InOut(/*[In,Out]*/BSTR s)
29{
30 //Check the Input
31 size_t len = TP_SysStringByteLen(s);
32
33 if (len != lenstrManaged || memcmp(s,strManaged,lenstrManaged) != 0)
34 {
35 printf("Error in Function Marshal_InOut(Native Client)\n");
36 printf("Error: Actual: %d, Expected: %d\n",(int32_t) len, (int32_t)lenstrManaged);
37
38 return ReturnErrorString();
39 }
40
41 //In-Place Change
42 memcpy(s, strNative, len);
43
44 //Return
45 return ReturnString();
46}
47
48
49extern "C" DLL_EXPORT BSTR Marshal_Out(/*[Out]*/BSTR s)
50{
51 s = TP_SysAllocString(strNative);
52
53 //Return
54 return ReturnString();
55}
56
57
58extern "C" DLL_EXPORT BSTR MarshalPointer_InOut(/*[in,out]*/BSTR *s)
59{
60 //Check the Input
61 size_t len = TP_SysStringByteLen(*s);
62
63 if (len != lenstrManaged || memcmp(*s,strManaged,lenstrManaged)!=0)
64 {
65 printf("Error in Function MarshalPointer_InOut\n");
66 printf("Error: Expected: %d, Actual: %d", (int32_t)lenstrManaged, (int32_t)len);
67
68 return ReturnErrorString();
69 }
70
71 //Allocate New
72 TP_SysFreeString(*s);
73 *s = TP_SysAllocString(strNative);
74
75 //Return
76 return ReturnString();
77}
78
79extern "C" DLL_EXPORT BSTR MarshalPointer_Out(/*[out]*/ BSTR *s)
80{
81 *s = TP_SysAllocString(strNative);
82 return ReturnString();
83}
84
85typedef BSTR (__stdcall * Test_DelMarshal_InOut)(/*[in]*/ BSTR s);
86extern "C" DLL_EXPORT BOOL __cdecl RPinvoke_DelMarshal_InOut(Test_DelMarshal_InOut d, /*[in]*/ BSTR s)
87{
88 BSTR str = d(s);
89 WCHAR ret[] = W("Return\0Return\0");
90
91 size_t lenstr = TP_SysStringByteLen(str);
92 size_t lenret = sizeof(ret) - sizeof(WCHAR);
93
94 if (lenret != lenstr || memcmp(str,ret,lenstr) != 0)
95 {
96 printf("Error in RPinvoke_DelMarshal_InOut, Returned value didn't match\n");
97 return FALSE;
98 }
99
100 TP_SysFreeString(str);
101 return TRUE;
102}
103
104//
105// PInvokeDef.cs explicitly declares that RPinvoke_DelMarshalPointer_Out uses STDCALL
106//
107typedef BSTR (__cdecl * Test_DelMarshalPointer_Out)(/*[out]*/ BSTR * s);
108extern "C" DLL_EXPORT BOOL __stdcall RPinvoke_DelMarshalPointer_Out(Test_DelMarshalPointer_Out d)
109{
110 BSTR str;
111 BSTR ret = d(&str);
112
113 WCHAR changedstr[] = W("Native\0String\0");
114
115 size_t lenstr = TP_SysStringByteLen(str);
116 size_t lenchangedstr = sizeof(changedstr) - sizeof(WCHAR);
117
118 if ( lenstr != lenchangedstr || (memcmp(str,changedstr,lenstr)!=0))
119 {
120 printf("Error in RPinvoke_DelMarshalPointer_Out, Value didn't change\n");
121 return FALSE;
122 }
123
124 WCHAR expected[] = W("Return\0Return\0");
125 size_t lenret = TP_SysStringByteLen(ret);
126 size_t lenexpected = sizeof(expected) - sizeof(WCHAR);
127
128 if (lenret != lenexpected || memcmp(ret,expected,lenret)!=0)
129 {
130 printf("Error in RPinvoke_DelMarshalPointer_Out, Return vaue is different than expected\n");
131 return FALSE;
132 }
133
134 return TRUE;
135}
136
137//
138// PInvokeDef.cs explicitly declares that ReverseP_MarshalStrB_InOut uses STDCALL
139//
140typedef BSTR (__stdcall * Test_Del_MarshalStrB_InOut)(/*[in,out]*/ BSTR s);
141extern "C" DLL_EXPORT BOOL __stdcall ReverseP_MarshalStrB_InOut(Test_Del_MarshalStrB_InOut d, /*[in]*/ BSTR s)
142{
143 BSTR ret = d((BSTR)s);
144 WCHAR expected[] = W("Return");
145 size_t lenret = TP_SysStringByteLen(ret);
146 size_t lenexpected = sizeof(expected) - sizeof(WCHAR);
147
148 if (lenret != lenexpected || memcmp(ret,expected,lenret) != 0)
149 {
150 printf("Error in ReverseP_MarshalStrB_InOut, Return vaue is different than expected\n");
151 return FALSE;
152 }
153
154 WCHAR expectedchange[] = W("m");
155 size_t lenstr = TP_SysStringByteLen(s);
156 size_t lenexpectedchange = sizeof(expectedchange) - sizeof(WCHAR);
157
158 if (lenstr != lenexpectedchange || memcmp(s,expectedchange,lenstr) != 0)
159 {
160 printf("Error in ReverseP_MarshalStrB_InOut, Value didn't get change\n");
161 return FALSE;
162 }
163 return TRUE;
164}
165
166typedef struct Person Person;
167struct Person{
168 int age;
169 int _padding;
170 BSTR name;
171};
172
173extern "C" DLL_EXPORT BOOL Marshal_Struct_In(Person person)
174{
175 if (person.age != 12)
176 {
177 printf("Error in Marshal_Struct_In, The value for age field is incorrect\n");
178 return FALSE;
179 }
180
181 size_t len = TP_SysStringByteLen(person.name);
182 if (len != lenstrManaged || memcmp(person.name, strManaged, lenstrManaged) != 0)
183 {
184 printf("Error in Marshal_Struct_In, The value for name field is incorrect\n");
185 return FALSE;
186 }
187
188 return TRUE;
189}
190
191extern "C" DLL_EXPORT BOOL MarshalPointer_Struct_InOut(Person* person)
192{
193 if (person->age != 12)
194 {
195 printf("Error in MarshalPointer_Struct_InOut, The value for age field is incorrect\n");
196 return FALSE;
197 }
198
199 size_t len = TP_SysStringByteLen(person->name);
200 if (len != lenstrManaged || memcmp(person->name, strManaged, lenstrManaged) != 0)
201 {
202 printf("Error in MarshalPointer_Struct_InOut, The value for name field is incorrect\n");
203 return FALSE;
204 }
205
206 person->age = 21;
207 person->name = TP_SysAllocString(strNative);
208 return TRUE;
209}
210
211typedef BOOL (* Test_DelMarshal_Struct_In)(Person person);
212extern "C" DLL_EXPORT BOOL RPInvoke_DelMarshal_Struct_In(Test_DelMarshal_Struct_In d)
213{
214 Person * pPerson = (Person *)TP_CoTaskMemAlloc(sizeof(Person));
215 pPerson->age = 21;
216 pPerson->name = TP_SysAllocString(strNative);
217
218 if (!d(*pPerson))
219 {
220 printf("Error in RPInvoke_DelMarshal_Struct_In, Managed delegate return false\n");
221 return FALSE;
222 }
223
224 return TRUE;
225}
226
227typedef BOOL (* Test_DelMarshalPointer_Struct_InOut)(Person * person);
228extern "C" DLL_EXPORT BOOL RPInvoke_DelMarshalStructPointer_InOut(Test_DelMarshalPointer_Struct_InOut d)
229{
230 Person * pPerson = (Person *)TP_CoTaskMemAlloc(sizeof(Person));
231 pPerson->age = 21;
232 pPerson->name = TP_SysAllocString(strNative);
233
234 if (!d(pPerson))
235 {
236 printf("Error in RPInvoke_DelMarshalStructPointer_InOut,The delegate return false\n");
237 return FALSE;
238 }
239
240 size_t len = TP_SysStringByteLen(pPerson->name);
241 if (len != lenstrManaged || memcmp(pPerson->name, strManaged, lenstrManaged) != 0)
242 {
243 printf("Error in RPInvoke_DelMarshalStructPointer_InOut,The value for name field for pPerson is incorrect\n");
244 return FALSE;
245 }
246
247 return TRUE;
248}
249
250