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 <xplatform.h>
6
7const WCHAR* strManaged = W("Managed\0String\0");
8size_t lenstrManaged = 7; // the length of strManaged
9
10const WCHAR* strReturn = W("a\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
11
12const WCHAR* strErrReturn = W("Error");
13
14const WCHAR* strNative = W(" Native\0String\0");
15size_t lenstrNative = 7; //the len of strNative
16
17extern "C" LPWSTR ReturnString()
18{
19 size_t length = wcslen(strReturn)+1;
20 LPWSTR ret = (LPWSTR)CoreClrAlloc(sizeof(WCHAR)*length);
21 memset(ret,'\0', sizeof(WCHAR)*length);
22 wcsncpy_s(ret,length,strReturn,length-1);
23 return ret;
24}
25
26extern "C" LPWSTR ReturnErrString()
27{
28 size_t length = wcslen(strErrReturn)+1;
29 LPWSTR ret = (LPWSTR)CoreClrAlloc(sizeof(WCHAR)*length);
30 memset(ret,'\0', sizeof(WCHAR)*length);
31 wcsncpy_s(ret,length,strErrReturn,length-1);
32 return ret;
33}
34
35//Test Method1
36
37//Test Method2
38extern "C" DLL_EXPORT LPWSTR Marshal_InOut(/*[In,Out]*/LPWSTR s)
39{
40
41 //Check the Input
42 size_t len = wcslen(s);
43
44 if((len != lenstrManaged)||(wmemcmp(s,(WCHAR*)strManaged,len)!=0))
45 {
46 printf("Error in Function Marshal_InOut(Native Client)\n");
47 return ReturnErrString();
48 }
49
50 //In-Place Change
51 wcsncpy_s(s,len+1,strNative,lenstrNative);
52
53 //Return
54 return ReturnString();
55}
56
57extern "C" DLL_EXPORT LPWSTR Marshal_Out(/*[Out]*/LPWSTR s)
58{
59 s = (LPWSTR)CoreClrAlloc(sizeof(WCHAR)*(lenstrNative+1));;
60 memset(s,0, sizeof(WCHAR)*(lenstrNative + 1));
61
62 //In-Place Change
63 wcsncpy_s(s,lenstrNative+1,strNative,lenstrNative);
64
65 //Return
66 return ReturnString();
67}
68
69
70extern "C" DLL_EXPORT LPWSTR MarshalPointer_InOut(/*[in,out]*/LPWSTR *s)
71{
72 //Check the Input
73 size_t len = wcslen(*s);
74 if((len != lenstrManaged)||(wmemcmp(*s,(WCHAR*)strManaged,len)!=0))
75 {
76 printf("Error in Function MarshalPointer_InOut\n");
77 return ReturnErrString();
78 }
79
80 //Allocate New
81 CoreClrFree(*s);
82
83 //Alloc New
84 size_t length = lenstrNative + 1;
85 *s = (LPWSTR)CoreClrAlloc(length * sizeof(WCHAR));
86 memset(*s,'\0',length * sizeof(WCHAR));
87 wcsncpy_s(*s,length,strNative,lenstrNative);
88
89 //Return
90 return ReturnString();
91}
92
93extern "C" DLL_EXPORT LPWSTR MarshalPointer_Out(/*[out]*/ LPWSTR *s)
94{
95 size_t length = lenstrNative+1;
96 *s = (LPWSTR)CoreClrAlloc(sizeof(WCHAR)*length);
97 memset(*s, '\0', length * sizeof(WCHAR));
98 wcsncpy_s(*s,length,strNative,lenstrNative);
99
100 return ReturnString();
101}
102
103typedef LPWSTR (__stdcall * Test_Del_MarshalStrB_InOut)(/*[in,out]*/ LPWSTR s);
104extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE ReverseP_MarshalStrB_InOut(Test_Del_MarshalStrB_InOut d, /*[in]*/ LPCWSTR s)
105{
106 LPWSTR ret = d((LPWSTR)s);
107 LPWSTR expectedret =(LPWSTR)W("Native");
108 LPWSTR expectedstr = (LPWSTR)W("m");
109
110 size_t lenret = wcslen(ret);
111 size_t lenexpectedret = wcslen(expectedret);
112 if((lenret != lenexpectedret)||(wcsncmp(ret,expectedret,lenret)!=0))
113 {
114 printf("Error in ReverseP_MarshalStrB_InOut, Returned value didn't match\n");
115 return FALSE;
116 }
117
118 size_t lenstr = wcslen(s);
119 size_t lenexpectedstr = wcslen(expectedstr);
120 if((lenstr != lenexpectedstr)||(wcsncmp(s,expectedstr,lenstr)!=0))
121 {
122 printf("Error in ReverseP_MarshalStrB_InOut, Changed value didn't reflect on native side.\n");
123 return FALSE;
124 }
125
126 return TRUE;
127}
128
129typedef LPWSTR (__cdecl * Test_Del_MarshalStrB_Out)(/*[out]*/ LPWSTR * s);
130extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE ReverseP_MarshalStrB_Out(Test_Del_MarshalStrB_Out d)
131{
132 LPWSTR s;
133 LPWSTR ret = d((LPWSTR*)&s);
134 LPWSTR expectedret = (LPWSTR)W("Native");
135 LPWSTR expectedstr = (LPWSTR)W("Managed");
136
137 size_t lenret = wcslen(ret);
138 size_t lenexpectedret = wcslen(expectedret);
139 if((lenret != lenexpectedret)||(wcsncmp(ret,expectedret,lenret)!=0))
140 {
141 printf("Error in ReverseP_MarshalStrB_Out, Returned value didn't match\n");
142 return FALSE;
143 }
144
145 size_t lenstr = wcslen(s);
146 size_t lenexpectedstr = wcslen(expectedstr);
147 if((lenstr != lenexpectedstr)||(wcsncmp(s,expectedstr,lenstr)!=0))
148 {
149 printf("Error in ReverseP_MarshalStrB_Out, Changed value didn't reflect on native side.\n");
150 return FALSE;
151 }
152
153 return TRUE;
154
155}
156
157// Verify that we append extra null terminators to our StringBuilder native buffers.
158// Although this is a hidden implementation detail, it would be breaking behavior to stop doing this
159// so we have a test for it. In particular, this detail prevents us from optimizing marshalling StringBuilders by pinning.
160extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Verify_NullTerminators_PastEnd(LPCWSTR buffer, int length)
161{
162 return buffer[length+1] == W('\0');
163}
164