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 | |
14 | static int fails = 0; //record the fail numbers |
15 | // Overload methods for reportfailure |
16 | static int ReportFailure(const char* s) |
17 | { |
18 | printf(" === Fail:%s\n" , s); |
19 | return (++fails); |
20 | } |
21 | |
22 | extern "C" DLL_EXPORT int __cdecl GetResult() |
23 | { |
24 | return fails; |
25 | } |
26 | |
27 | //This method is used on Windows Only |
28 | extern "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 |
48 | bool 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 |
83 | extern "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 | |
99 | extern "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 | |
111 | extern "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 | |
127 | extern "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 | |
143 | extern "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 | |
155 | extern "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 | |
171 | typedef LPSTR (__cdecl* delegate_cdecl)(LPSTR* ppstr); |
172 | extern "C" DLL_EXPORT delegate_cdecl __cdecl CLPStr_DelegatePInvoke() |
173 | { |
174 | return CLPStr_InOutByRef; |
175 | } |
176 | |
177 | //stdcall |
178 | |
179 | extern "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 | |
194 | extern "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 | |
205 | extern "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 | |
220 | extern "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 | |
234 | extern "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 | |
247 | extern "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 | |
262 | typedef LPSTR (STDMETHODCALLTYPE *delegate_stdcall)(LPSTR* ppstr); |
263 | extern "C" DLL_EXPORT delegate_stdcall SLPStr_DelegatePInvoke() |
264 | { |
265 | return SLPStr_InOutByRef; |
266 | } |
267 | |
268 | ///Cdecl, Reverse PInvoke |
269 | |
270 | typedef LPSTR (__cdecl *CCallBackIn)(LPSTR pstr); |
271 | extern "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 | |
285 | typedef LPSTR (__cdecl *CCallBackOut)(LPSTR pstr); |
286 | extern "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 | |
303 | typedef LPSTR (__cdecl *CCallBackInOut)(LPSTR pstr); |
304 | extern "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 | |
322 | typedef LPSTR (__cdecl *CallBackInByRef)(LPSTR* pstr); |
323 | extern "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 | |
337 | typedef LPSTR (__cdecl *CCallBackOutByRef)(LPSTR* pstr); |
338 | extern "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 | |
354 | typedef LPSTR (__cdecl *CCallBackInOutByRef)(LPSTR* pstr); |
355 | extern "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 |
374 | typedef LPSTR (STDMETHODCALLTYPE *SCallBackIn)(LPSTR pstr); |
375 | extern "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 | |
389 | typedef LPSTR (STDMETHODCALLTYPE *SCallBackOut)(LPSTR pstr); |
390 | extern "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 | |
407 | typedef LPSTR (STDMETHODCALLTYPE *SCallBackInOut)(LPSTR pstr); |
408 | extern "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 | |
426 | typedef LPSTR (STDMETHODCALLTYPE *SCallBackInByRef)(LPSTR* pstr); |
427 | extern "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 | |
441 | typedef LPSTR (STDMETHODCALLTYPE *SCallBackOutByRef)(LPSTR* pstr); |
442 | extern "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 | |
458 | typedef LPSTR (STDMETHODCALLTYPE *SCallBackInOutByRef)(LPSTR* pstr); |
459 | extern "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 ) |