1 /*
2  * PROJECT:     ReactOS API tests
3  * LICENSE:     0BSD (https://spdx.org/licenses/0BSD)
4  * PURPOSE:     Test for RtlUnicodeToOemN
5  * COPYRIGHT:   Copyright 2021 Jérôme Gardou <jerome.gardou@reactos.org>
6  */
7 
8 #include "precomp.h"
9 
10 static const struct
11 {
12     ULONG AnsiCp;
13     ULONG OemCp;
14     struct
15     {
16         LPCWSTR StrW;
17         NTSTATUS Status;
18         ULONG ReturnedSize;
19         LPCSTR StrOem;
20     } Test[10];
21 } TestData[] =
22 {
23     {
24         1252, 1252, /* Western SBCS */
25         {
26             {
27                 L"ABCDEF",
28                 STATUS_SUCCESS,
29                 6,
30                 "ABCDEF"
31             },
32             {
33                 L"ABCDEF",
34                 STATUS_SUCCESS,
35                 6,
36                 "ABCDEF\xAA\xAA\xAA"
37             },
38             {
39                 L"ABCDEF",
40                 STATUS_BUFFER_OVERFLOW,
41                 3,
42                 "ABC"
43             },
44             {
45                 L"\u30c7\u30b9\u30af\u30c8\u30c3\u30d7",
46                 STATUS_SUCCESS,
47                 6,
48                 "??????"
49             },
50             {
51                 L"\u30c7\u30b9\u30af\u30c8\u30c3\u30d7",
52                 STATUS_BUFFER_OVERFLOW,
53                 3,
54                 "???"
55             },
56         }
57     },
58     {
59         1252, 932, /* Western SBCS - Modified SJIS */
60         {
61             {
62                 L"\u30c7\u30b9\u30af\u30c8\u30c3\u30d7",
63                 STATUS_SUCCESS,
64                 12,
65                 "\x83\x66\x83\x58\x83\x4e\x83\x67\x83\x62\x83\x76"
66             },
67             {
68                 L"\u30c7\u30b9\u30af\u30c8\u30c3\u30d7",
69                 STATUS_SUCCESS,
70                 12,
71                 "\x83\x66\x83\x58\x83\x4e\x83\x67\x83\x62\x83\x76\xAA\xAA\xAA"
72             },
73         }
74     },
75     {
76         932, 1252, /* Modified SJIS - Western SBCS */
77         {
78             {
79                 L"\u30c7\u30b9\u30af\u30c8\u30c3\u30d7",
80                 STATUS_SUCCESS,
81                 6,
82                 "??????"
83             },
84             {
85                 L"\u30c7\u30b9\u30afABC",
86                 STATUS_SUCCESS,
87                 6,
88                 "???ABC"
89             },
90             {
91                 L"\u30c7\u30b9\u30af\u30c8\u30c3\u30d7",
92                 STATUS_BUFFER_OVERFLOW,
93                 3,
94                 "???"
95             },
96         }
97     },
98     {
99         932, 932, /* Modified SJIS - Modified SJIS */
100         {
101             {
102                 L"\u30c7\u30b9\u30af\u30c8\u30c3\u30d7",
103                 STATUS_SUCCESS,
104                 12,
105                 "\x83\x66\x83\x58\x83\x4e\x83\x67\x83\x62\x83\x76"
106             }
107         }
108     },
109 };
110 
111 START_TEST(RtlUnicodeToOemN)
112 {
113     ULONG Length;
114     LPSTR StrOem;
115     ULONG ResultSize;
116     NTSTATUS Status;
117     CHAR OemBuffer[4];
118 
119     /* Basic things */
120     Status = RtlUnicodeToOemN(NULL, 0, NULL, NULL, 0);
121     ok_ntstatus(Status, STATUS_SUCCESS);
122 
123     Status = RtlUnicodeToOemN(NULL, 0, NULL, L"ABCDEF", 0);
124     ok_ntstatus(Status, STATUS_SUCCESS);
125 
126     Status = RtlUnicodeToOemN(NULL, 0, NULL, NULL, 2);
127     ok_ntstatus(Status, STATUS_BUFFER_OVERFLOW);
128 
129     Status = RtlUnicodeToOemN(NULL, 0, NULL, L"A", 2);
130     ok_ntstatus(Status, STATUS_BUFFER_OVERFLOW);
131 
132     Status = RtlUnicodeToOemN(NULL, 0, NULL, L"A", 2);
133     ok_ntstatus(Status, STATUS_BUFFER_OVERFLOW);
134 
135     StartSeh()
136     Status = RtlUnicodeToOemN(NULL, 1, NULL, L"A", 2);
137     EndSeh(STATUS_ACCESS_VIOLATION)
138 
139     OemBuffer[0] = 0xAA;
140     OemBuffer[1] = 0xAA;
141     Status = RtlUnicodeToOemN(OemBuffer, 1, NULL, L"A", 2);
142     ok_ntstatus(Status, STATUS_SUCCESS);
143     ok_char(OemBuffer[0], 'A');
144     ok_char(OemBuffer[1], (CHAR)0xAA);
145 
146     OemBuffer[0] = 0xAA;
147     OemBuffer[1] = 0xAA;
148     Status = RtlUnicodeToOemN(OemBuffer, 1, NULL, L"AB", 4);
149     ok_ntstatus(Status, STATUS_BUFFER_OVERFLOW);
150     ok_char(OemBuffer[0], 'A');
151     ok_char(OemBuffer[1], (CHAR)0xAA);
152 
153     OemBuffer[0] = 0xAA;
154     OemBuffer[1] = 0xAA;
155     Status = RtlUnicodeToOemN(OemBuffer, 2, NULL, L"A", 4);
156     ok_ntstatus(Status, STATUS_SUCCESS);
157     ok_char(OemBuffer[0], 'A');
158     ok_char(OemBuffer[1], '\0');
159 
160     /* RtlUnicodeToOemN doesn't care about string termination */
161     OemBuffer[0] = 0xAA;
162     OemBuffer[1] = 0xAA;
163     Status = RtlUnicodeToOemN(OemBuffer, 1, NULL, L"A", 4);
164     ok_ntstatus(Status, STATUS_BUFFER_OVERFLOW);
165     ok_char(OemBuffer[0], 'A');
166     ok_char(OemBuffer[1], (CHAR)0xAA);
167 
168     OemBuffer[0] = 0xAA;
169     OemBuffer[1] = 0xAA;
170     OemBuffer[2] = 0xAA;
171     OemBuffer[3] = 0xAA;
172     Status = RtlUnicodeToOemN(OemBuffer, 4, NULL, L"A\0B", 8);
173     ok_ntstatus(Status, STATUS_SUCCESS);
174     ok_char(OemBuffer[0], 'A');
175     ok_char(OemBuffer[1], '\0');
176     ok_char(OemBuffer[2], 'B');
177     ok_char(OemBuffer[3], '\0');
178 
179     /* Odd Unicode buffer size */
180     OemBuffer[0] = 0xAA;
181     OemBuffer[1] = 0xAA;
182     OemBuffer[2] = 0xAA;
183     OemBuffer[3] = 0xAA;
184     Status = RtlUnicodeToOemN(OemBuffer, 2, NULL, L"AB", 5);
185     ok_ntstatus(Status, STATUS_SUCCESS);
186     ok_char(OemBuffer[0], 'A');
187     ok_char(OemBuffer[1], 'B');
188     ok_char(OemBuffer[2], (CHAR)0xAA);
189     ok_char(OemBuffer[3], (CHAR)0xAA);
190 
191     /* Odd Unicode buffer size */
192     OemBuffer[0] = 0xAA;
193     OemBuffer[1] = 0xAA;
194     OemBuffer[2] = 0xAA;
195     OemBuffer[3] = 0xAA;
196     Status = RtlUnicodeToOemN(OemBuffer, 3, NULL, L"AB", 5);
197     ok_ntstatus(Status, STATUS_SUCCESS);
198     ok_char(OemBuffer[0], 'A');
199     ok_char(OemBuffer[1], 'B');
200     ok_char(OemBuffer[2], (CHAR)0xAA);
201     ok_char(OemBuffer[3], (CHAR)0xAA);
202 
203     for (int i = 0; i < _countof(TestData); i++)
204     {
205         SetupLocale(TestData[i].AnsiCp, TestData[i].OemCp, -1);
206 
207         for (int j = 0; TestData[i].Test[j].StrW != NULL; j++)
208         {
209             Length = strlen(TestData[i].Test[j].StrOem);
210             StrOem = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length + 1);
211 
212             memset(StrOem, 0xAA, Length + 1);
213             ResultSize = 0x0BADF00D;
214 
215             Status = RtlUnicodeToOemN(StrOem,
216                                       Length,
217                                       &ResultSize,
218                                       TestData[i].Test[j].StrW,
219                                       wcslen(TestData[i].Test[j].StrW) * sizeof(WCHAR));
220 
221             ok_ntstatus(Status, TestData[i].Test[j].Status);
222             ok_long(ResultSize, TestData[i].Test[j].ReturnedSize);
223             for (int k = 0; k < ResultSize; k++)
224             {
225                 ok(StrOem[k] == TestData[i].Test[j].StrOem[k],
226                    "Wrong char \\x%02x, expected TestData[%u].Test[%u].StrOem[%u] (\\x%02x)\n",
227                    StrOem[k], i, j, k, TestData[i].Test[j].StrOem[k]);
228             }
229             for (int k = ResultSize; k < (Length + 1); k++)
230             {
231                 ok_char(StrOem[k], (CHAR)0xAA);
232             }
233 
234             RtlFreeHeap(RtlGetProcessHeap(), 0, StrOem);
235         }
236     }
237 }
238