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 <stdio.h>
6#include <stdlib.h>
7#include <locale.h>
8#include <xplatform.h>
9
10#pragma warning( push )
11#pragma warning( disable : 4996)
12
13
14static int fails = 0; //record the fail numbers
15// Overload methods for reportfailure
16static int ReportFailure(const char* s)
17{
18 printf(" === Fail:%s\n", s);
19 return (++fails);
20}
21
22extern "C" DLL_EXPORT int __cdecl GetResult()
23{
24 return fails;
25}
26
27//This method is used on Windows Only
28extern "C" DLL_EXPORT char __cdecl GetByteForWideChar()
29{
30#ifdef WINDOWS
31 char * p = new char[3];
32 WideCharToMultiByte(CP_ACP, 0, W("\x263c"), -1, p, 2, NULL, NULL);
33 p[1] = '\0';
34 char breturn = p[0];
35
36 delete p;
37
38 return breturn;
39#else
40 return 0; //It wont be called MAC
41#endif
42
43}
44
45//x86: Managed(Encoding: utf8)---->Marshaler(Encoding:ASCII)---->Native(Encoding:utf8)
46//MAC(x64):Managed(Encoding:utf8)----->Marshaler(Encoding:utf8)---->Native(Encoding:utf8)
47//Now both side(Managed Side and native side) takes the utf8 encoding when comparing string
48bool CheckInput(LPSTR str)
49{
50 //int WideCharToMultiByte(
51 // UINT CodePage,
52 // DWORD dwFlags,
53 // LPCWSTR lpWideCharStr,
54 // int cchWideChar,
55 // LPSTR lpMultiByteStr,
56 // int cbMultiByte,
57 // LPCSTR lpDefaultChar,
58 // LPBOOL lpUsedDefaultChar
59 //);
60#ifdef WINDOWS
61 char * p = new char[3];
62 WideCharToMultiByte(CP_ACP, 0, W("\x263c"), -1, p, 2, NULL, NULL);
63 p[1] = '\0';
64#else
65 char* p = new char[4]; //00bc98e2,the utf8 code of "\263c",we can get these char value through the following code with C#
66 p[0] = (char)0xe2; //Encoding enc = Encoding.Default;//UTF8 Encoding
67 p[1] = (char)0x98; //Byte[] by = enc.GetBytes("\x263c");
68 p[2] = (char)0xbc;
69 p[3] = (char)0;
70#endif
71 if (0 != strncmp(str, p, 4))
72 {
73 printf("CheckInput:Expected:%s,Actual:%d\n", p, str[0]);
74 delete[]p;
75 return false;
76 }
77 delete[]p;
78 return true;
79
80}
81
82//C Call,In attribute,LPstr
83extern "C" DLL_EXPORT LPSTR __cdecl CLPStr_In(LPSTR pStr)
84{
85 //Check the Input
86 if (!CheckInput(pStr))
87 {
88 ReportFailure("CLPStr_In:Native Side");
89 }
90
91 //alloc,copy, since we cannot depend the Marshaler's activity.
92 size_t len = strlen(pStr) + 1; //+1, Include the NULL Character.
93 LPSTR pBack = (LPSTR)CoreClrAlloc(sizeof(char) * len);
94 strncpy(pBack, pStr, len);
95
96 return pBack;
97}
98
99extern "C" DLL_EXPORT LPSTR __cdecl CLPStr_Out(LPSTR pStr)
100{
101 const char* pTemp = "AAAA";
102 size_t len = strlen(pTemp) + 1; //+1, Include the NULL Character.
103 LPSTR pBack = (LPSTR)CoreClrAlloc(sizeof(char) * len);
104 strncpy(pBack, pTemp, strlen(pTemp) + 1);
105
106 strncpy(pStr, pTemp, strlen(pTemp) + 1);
107
108 return pBack;
109}
110
111extern "C" DLL_EXPORT LPSTR __cdecl CLPStr_InOut(LPSTR pStr)
112{
113 //Check the Input
114 if (!CheckInput(pStr))
115 {
116 ReportFailure("CLPStr_InOut:Native Side");
117 }
118
119 //alloc,copy, since we cannot depend the Marshaler's activity.
120 size_t len = strlen(pStr) + 1; //+1, Include the NULL Character.
121 LPSTR pBack = (LPSTR)CoreClrAlloc(len);
122 strncpy(pBack, pStr, len);
123
124 return pBack;
125}
126
127extern "C" DLL_EXPORT LPSTR __cdecl CLPStr_InByRef(LPSTR* ppStr)
128{
129 //Check the Input
130 if (!CheckInput(*ppStr))
131 {
132 ReportFailure("CLPStr_InByRef:Native Side");
133 }
134
135 //alloc,copy, since we cannot depend the Marshaler's activity.
136 size_t len = strlen(*ppStr) + 1; //+1, Include the NULL Character.
137 LPSTR pBack = (LPSTR)CoreClrAlloc(len);
138 strncpy(pBack, *ppStr, len);
139
140 return pBack;
141}
142
143extern "C" DLL_EXPORT LPSTR __cdecl CLPStr_OutByRef(LPSTR* ppStr)
144{
145 const char* pTemp = "AAAA";
146 size_t len = strlen(pTemp) + 1; //+1, Include the NULL Character.
147 LPSTR pBack = (LPSTR)CoreClrAlloc(sizeof(char) * len);
148 strncpy(pBack, pTemp, strlen(pTemp) + 1);
149
150 *ppStr = (LPSTR)CoreClrAlloc(sizeof(char) * len);
151 strncpy(*ppStr, pTemp, strlen(pTemp) + 1);
152 return pBack;
153}
154
155extern "C" DLL_EXPORT LPSTR __cdecl CLPStr_InOutByRef(LPSTR* ppStr)
156{
157 //Check the Input
158 if (!CheckInput(*ppStr))
159 {
160 ReportFailure("CLPStr_InOutByRef:Native Side");
161 }
162
163 //alloc,copy, since we cannot depend the Marshaler's activity.
164 size_t len = strlen(*ppStr) + 1; //+1, Include the NULL Character.
165 LPSTR pBack = (LPSTR)CoreClrAlloc(len);
166 strncpy(pBack, *ppStr, len);
167 return pBack;
168}
169
170
171typedef LPSTR (__cdecl* delegate_cdecl)(LPSTR* ppstr);
172extern "C" DLL_EXPORT delegate_cdecl __cdecl CLPStr_DelegatePInvoke()
173{
174 return CLPStr_InOutByRef;
175}
176
177//stdcall
178
179extern "C" DLL_EXPORT LPSTR STDMETHODCALLTYPE SLPStr_In(LPSTR pStr)
180{
181 //Check the Input
182 if (!CheckInput(pStr))
183 {
184 ReportFailure("SLPStr_In:NativeSide");
185 }
186
187 //alloc,copy, since we cannot depend the Marshaler's activity.
188 size_t len = strlen(pStr) + 1; //+1, Include the NULL Character.
189 LPSTR pBack = (LPSTR)CoreClrAlloc(len);
190 strncpy(pBack, pStr, len);
191 return pBack;
192}
193
194extern "C" DLL_EXPORT LPSTR STDMETHODCALLTYPE SLPStr_Out(LPSTR pStr)
195{
196 const char* pTemp = "AAAA";
197 size_t len = strlen(pTemp) + 1; //+1, Include the NULL Character.
198 LPSTR pBack = (LPSTR)CoreClrAlloc(sizeof(char) * len);
199 strncpy(pBack, pTemp, strlen(pTemp) + 1);
200
201 strncpy(pStr, pTemp, strlen(pTemp) + 1);
202 return pBack;
203}
204
205extern "C" DLL_EXPORT LPSTR STDMETHODCALLTYPE SLPStr_InOut(LPSTR pStr)
206{
207 //Check the Input
208 if (!CheckInput(pStr))
209 {
210 ReportFailure("SLPStr_InOut:NativeSide");
211 }
212
213 //alloc,copy, since we cannot depend the Marshaler's activity.
214 size_t len = strlen(pStr) + 1; //+1, Include the NULL Character.
215 LPSTR pBack = (LPSTR)CoreClrAlloc(len);
216 strncpy(pBack, pStr, len);
217 return pBack;
218}
219
220extern "C" DLL_EXPORT LPSTR STDMETHODCALLTYPE SLPStr_InByRef(LPSTR* ppStr)
221{
222 //Check the Input
223 if (!CheckInput(*ppStr))
224 {
225 ReportFailure("SLPStr_InByRef:NativeSide");
226 }
227 //alloc,copy, since we cannot depend the Marshaler's activity.
228 size_t len = strlen(*ppStr) + 1; //+1, Include the NULL Character.
229 LPSTR pBack = (LPSTR)CoreClrAlloc(len);
230 strncpy(pBack, *ppStr, len);
231 return pBack;
232}
233
234extern "C" DLL_EXPORT LPSTR STDMETHODCALLTYPE SLPStr_OutByRef(LPSTR* ppStr)
235{
236 const char* pTemp = "AAAA";
237 size_t len = strlen(pTemp) + 1; //+1, Include the NULL Character.
238 LPSTR pBack = (LPSTR)CoreClrAlloc(sizeof(char) * len);
239 strncpy(pBack, pTemp, strlen(pTemp) + 1);
240
241 *ppStr = (LPSTR)CoreClrAlloc(sizeof(char) * len);
242 strncpy(*ppStr, pTemp, strlen(pTemp) + 1);
243
244 return pBack;
245}
246
247extern "C" DLL_EXPORT LPSTR STDMETHODCALLTYPE SLPStr_InOutByRef(LPSTR* ppStr)
248{
249 //Check the Input
250 if (!CheckInput(*ppStr))
251 {
252 ReportFailure("SLPStr_InOutByRef:NativeSide");
253 }
254
255 //alloc,copy, since we cannot depend the Marshaler's activity.
256 size_t len = strlen(*ppStr) + 1; //+1, Include the NULL Character.
257 LPSTR pBack = (LPSTR)CoreClrAlloc(len);
258 strncpy(pBack, *ppStr, len);
259 return pBack;
260}
261
262typedef LPSTR (STDMETHODCALLTYPE *delegate_stdcall)(LPSTR* ppstr);
263extern "C" DLL_EXPORT delegate_stdcall SLPStr_DelegatePInvoke()
264{
265 return SLPStr_InOutByRef;
266}
267
268///Cdecl, Reverse PInvoke
269
270typedef LPSTR (__cdecl *CCallBackIn)(LPSTR pstr);
271extern "C" DLL_EXPORT void __cdecl DoCCallBack_LPSTR_In(CCallBackIn callback)
272{
273 const char* pTemp = "AAAA";
274 size_t len = strlen(pTemp)+1;
275 LPSTR pStr = (LPSTR)CoreClrAlloc(len);
276 strncpy(pStr,pTemp,len);
277
278 if(!CheckInput(callback(pStr)))
279 {
280 ReportFailure("DoCCallBack_LPSTR_In:NativeSide");
281 }
282 CoreClrFree(pStr);
283}
284
285typedef LPSTR (__cdecl *CCallBackOut)(LPSTR pstr);
286extern "C" DLL_EXPORT void __cdecl DoCCallBack_LPSTR_Out(CCallBackOut callback)
287{
288 size_t len = 10;
289 LPSTR pStr = (LPSTR)CoreClrAlloc(len);
290
291 //Check the return value
292 if (!CheckInput(callback(pStr)))
293 {
294 ReportFailure("DoCCallBack_LPSTR_Out:NativeSide,the first check");
295 }
296 if (!CheckInput(pStr))
297 {
298 ReportFailure("DoCCallBack_LPSTR_Out:NativeSide,the Second Check");
299 }
300 CoreClrFree(pStr);
301}
302
303typedef LPSTR (__cdecl *CCallBackInOut)(LPSTR pstr);
304extern "C" DLL_EXPORT void __cdecl DoCCallBack_LPSTR_InOut(CCallBackInOut callback)
305{
306 const char* pTemp = "AAAA";
307 size_t len = strlen(pTemp) + 1;
308 LPSTR pStr = (LPSTR)CoreClrAlloc(len);
309 strncpy(pStr, pTemp, len);
310
311 if (!CheckInput(callback(pStr)))
312 {
313 ReportFailure("DoCCallBack_LPSTR_InOut:NativeSide,the first check");
314 }
315 if (!CheckInput(pStr))
316 {
317 ReportFailure("DoCCallBack_LPSTR_InOut:NativeSide,the Second Check");
318 }
319 CoreClrFree(pStr);
320}
321
322typedef LPSTR (__cdecl *CallBackInByRef)(LPSTR* pstr);
323extern "C" DLL_EXPORT void __cdecl DoCCallBack_LPSTR_InByRef(CallBackInByRef callback)
324{
325 const char* pTemp = "AAAA";
326 size_t len = strlen(pTemp) + 1;
327 LPSTR pStr = (LPSTR)CoreClrAlloc(len);
328 strncpy(pStr, pTemp, len);
329
330 if (!CheckInput(callback(&pStr)))
331 {
332 ReportFailure("DoCCallBack_LPSTR_InByRef:NativeSide");
333 }
334 CoreClrFree(pStr);
335}
336
337typedef LPSTR (__cdecl *CCallBackOutByRef)(LPSTR* pstr);
338extern "C" DLL_EXPORT void __cdecl DoCCallBack_LPSTR_OutByRef(CCallBackOutByRef callback)
339{
340 size_t len = 10;
341 LPSTR pStr = (LPSTR)CoreClrAlloc(len);
342
343 if (!CheckInput(callback(&pStr)))
344 {
345 ReportFailure("DoCCallBack_LPSTR_OutByRef:NativeSide,the first Check");
346 }
347 if (!CheckInput(pStr))
348 {
349 ReportFailure("DoCCallBack_LPSTR_OutByRef:NativeSide,the Second Check");
350 }
351 CoreClrFree(pStr);
352}
353
354typedef LPSTR (__cdecl *CCallBackInOutByRef)(LPSTR* pstr);
355extern "C" DLL_EXPORT void __cdecl DoCCallBack_LPSTR_InOutByRef(CCallBackInOutByRef callback)
356{
357 const char* pTemp = "AAAA";
358 size_t len = strlen(pTemp) + 1;
359 LPSTR pStr = (LPSTR)CoreClrAlloc(len);
360 strncpy(pStr, pTemp, len);
361
362 if (!CheckInput(callback(&pStr)))
363 {
364 ReportFailure("DoCCallBack_LPSTR_InOutByRef:NativeSide");
365 }
366 if (!CheckInput(pStr))
367 {
368 ReportFailure("DoCCallBack_LPSTR_InOutByRef:NativeSide,the Second Check");
369 }
370 CoreClrFree(pStr);
371}
372
373///STDCALL Reverse PInvoke
374typedef LPSTR (STDMETHODCALLTYPE *SCallBackIn)(LPSTR pstr);
375extern "C" DLL_EXPORT void __cdecl DoSCallBack_LPSTR_In(SCallBackIn callback)
376{
377 const char* pTemp = "AAAA";
378 size_t len = strlen(pTemp) + 1;
379 LPSTR pStr = (LPSTR)CoreClrAlloc(len);
380 strncpy(pStr, pTemp, len);
381
382 if (!CheckInput(callback(pStr)))
383 {
384 ReportFailure("DoSCallBack_LPSTR_In:NativeSide");
385 }
386 CoreClrFree(pStr);
387}
388
389typedef LPSTR (STDMETHODCALLTYPE *SCallBackOut)(LPSTR pstr);
390extern "C" DLL_EXPORT void __cdecl DoSCallBack_LPSTR_Out(SCallBackOut callback)
391{
392
393 size_t len = 10;
394 LPSTR pStr = (LPSTR)CoreClrAlloc(len);
395
396 if (!CheckInput(callback(pStr)))
397 {
398 ReportFailure("DoSCallBack_LPSTR_Out:NativeSide,the first check");
399 }
400 if (!CheckInput(pStr))
401 {
402 ReportFailure("DoSCallBack_LPSTR_Out:NativeSide,the Second Check");
403 }
404 CoreClrFree(pStr);
405}
406
407typedef LPSTR (STDMETHODCALLTYPE *SCallBackInOut)(LPSTR pstr);
408extern "C" DLL_EXPORT void __cdecl DoSCallBack_LPSTR_InOut(SCallBackInOut callback)
409{
410 const char* pTemp = "AAAA";
411 size_t len = strlen(pTemp) + 1;
412 LPSTR pStr = (LPSTR)CoreClrAlloc(len);
413 strncpy(pStr, pTemp, len);
414
415 if (!CheckInput(callback(pStr)))
416 {
417 ReportFailure("DoSCallBack_LPSTR_InOut:NativeSide,the first check");
418 }
419 if (!CheckInput(pStr))
420 {
421 ReportFailure("DoSCallBack_LPSTR_InOut:NativeSide,the second Check");
422 }
423 CoreClrFree(pStr);
424}
425
426typedef LPSTR (STDMETHODCALLTYPE *SCallBackInByRef)(LPSTR* pstr);
427extern "C" DLL_EXPORT void __cdecl DoSCallBack_LPSTR_InByRef(SCallBackInByRef callback)
428{
429 const char* pTemp = "AAAA";
430 size_t len = strlen(pTemp) + 1;
431 LPSTR pStr = (LPSTR)CoreClrAlloc(len);
432 strncpy(pStr, pTemp, len);
433
434 if (!CheckInput(callback(&pStr)))
435 {
436 ReportFailure("DoSCallBack_LPSTR_InByRef:NativeSide");
437 }
438 CoreClrFree(pStr);
439}
440
441typedef LPSTR (STDMETHODCALLTYPE *SCallBackOutByRef)(LPSTR* pstr);
442extern "C" DLL_EXPORT void __cdecl DoSCallBack_LPSTR_OutByRef(SCallBackOutByRef callback)
443{
444 size_t len = 10;
445 LPSTR pStr = (LPSTR)CoreClrAlloc(len);
446
447 if (!CheckInput(callback(&pStr)))
448 {
449 ReportFailure("DoSCallBack_LPSTR_OutByRef:NativeSide,the first check");
450 }
451 if (!CheckInput(pStr))
452 {
453 ReportFailure("DoSCallBack_LPSTR_OutByRef:NativeSide,the second Check");
454 }
455 CoreClrFree(pStr);
456}
457
458typedef LPSTR (STDMETHODCALLTYPE *SCallBackInOutByRef)(LPSTR* pstr);
459extern "C" DLL_EXPORT void __cdecl DoSCallBack_LPSTR_InOutByRef(SCallBackInOutByRef callback)
460{
461 const char* pTemp = "AAAA";
462 size_t len = strlen(pTemp) + 1;
463 LPSTR pStr = (LPSTR)CoreClrAlloc(len);
464 strncpy(pStr, pTemp, len);
465
466 if (!CheckInput(callback(&pStr)))
467 {
468 ReportFailure("DoSCallBack_LPSTR_InOutByRef:NativeSide,the first check");
469 }
470 if (!CheckInput(pStr))
471 {
472 ReportFailure("DoSCallBack_LPSTR_InOutByRef:NativeSide,the second Check");
473 }
474 CoreClrFree(pStr);
475}
476#pragma warning( pop )