ReactOS 0.4.16-dev-2206-gc56950d
codepage.c
Go to the documentation of this file.
1/*
2 * Unit tests for code page to/from unicode translations
3 *
4 * Copyright (c) 2002 Dmitry Timoshkov
5 * Copyright (c) 2008 Colin Finck
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22#include <stdarg.h>
23#include <stdio.h>
24#include <limits.h>
25
26#include "wine/test.h"
27#include "windef.h"
28#include "winbase.h"
29#include "winnls.h"
30
31static const char foobarA[] = "foobar";
32static const WCHAR foobarW[] = {'f','o','o','b','a','r',0};
33
34static void test_destination_buffer(void)
35{
38 INT needed;
39 INT len;
40
41 SetLastError(0xdeadbeef);
42 needed = WideCharToMultiByte(CP_ACP, 0, foobarW, -1, NULL, 0, NULL, NULL);
43 ok( (needed > 0), "returned %d with %lu (expected '> 0')\n",
44 needed, GetLastError());
45
46 maxsize = needed*2;
48 if (buffer == NULL) return;
49
50 maxsize--;
51 memset(buffer, 'x', maxsize);
52 buffer[maxsize] = '\0';
53 SetLastError(0xdeadbeef);
54 len = WideCharToMultiByte(CP_ACP, 0, foobarW, -1, buffer, needed+1, NULL, NULL);
55 ok( (len > 0), "returned %d with %lu and '%s' (expected '> 0')\n",
57 ok(!lstrcmpA(buffer, "foobar"), "expected \"foobar\" got \"%s\"\n", buffer);
58
59 memset(buffer, 'x', maxsize);
60 buffer[maxsize] = '\0';
61 SetLastError(0xdeadbeef);
62 len = WideCharToMultiByte(CP_ACP, 0, foobarW, -1, buffer, needed, NULL, NULL);
63 ok( (len > 0), "returned %d with %lu and '%s' (expected '> 0')\n",
65 ok(!lstrcmpA(buffer, "foobar"), "expected \"foobar\" got \"%s\"\n", buffer);
66
67 memset(buffer, 'x', maxsize);
68 buffer[maxsize] = '\0';
69 SetLastError(0xdeadbeef);
70 len = WideCharToMultiByte(CP_ACP, 0, foobarW, -1, buffer, needed-1, NULL, NULL);
72 "returned %d with %lu and '%s' (expected '0' with "
73 "ERROR_INSUFFICIENT_BUFFER)\n", len, GetLastError(), buffer);
74 ok(!strncmp(buffer, "foobar", 6), "expected \"foobar\" got \"%s\"\n", buffer);
75 ok(buffer[6] == 'x', "expected buf[5]=='x', got \"%s\"\n", buffer);
76
77 memset(buffer, 'x', maxsize);
78 buffer[maxsize] = '\0';
79 SetLastError(0xdeadbeef);
82 "returned %d with %lu and '%s' (expected '0' with "
83 "ERROR_INSUFFICIENT_BUFFER)\n", len, GetLastError(), buffer);
84 ok(buffer[0] == 'f', "expected buf[1]=='f', got \"%s\"\n", buffer);
85 ok(buffer[1] == 'x', "expected buf[1]=='x', got \"%s\"\n", buffer);
86
87 SetLastError(0xdeadbeef);
89 ok( (len > 0), "returned %d with %lu (expected '> 0')\n",
90 len, GetLastError());
91
92 SetLastError(0xdeadbeef);
93 len = WideCharToMultiByte(CP_ACP, 0, foobarW, -1, NULL, needed, NULL, NULL);
95 "returned %d with %lu (expected '0' with "
96 "ERROR_INVALID_PARAMETER)\n", len, GetLastError());
97
99}
100
101
102static void test_null_source(void)
103{
104 int len;
105 DWORD GLE;
106
107 SetLastError(0);
109 GLE = GetLastError();
111 "WideCharToMultiByte returned %d with GLE=%lu (expected 0 with ERROR_INVALID_PARAMETER)\n",
112 len, GLE);
113
114 SetLastError(0);
116 GLE = GetLastError();
118 "WideCharToMultiByte returned %d with GLE=%lu (expected 0 with ERROR_INVALID_PARAMETER)\n",
119 len, GLE);
120}
121
123{
124 int len;
125 char buf[10];
126 WCHAR bufW[10];
127
128 /* Test, whether any negative source length works as strlen() + 1 */
129 SetLastError( 0xdeadbeef );
130 memset(buf,'x',sizeof(buf));
131 len = WideCharToMultiByte(CP_ACP, 0, foobarW, -2002, buf, 10, NULL, NULL);
132 ok(len == 7 && GetLastError() == 0xdeadbeef,
133 "WideCharToMultiByte(-2002): len=%d error=%lu\n", len, GetLastError());
134 ok(!lstrcmpA(buf, "foobar"),
135 "WideCharToMultiByte(-2002): expected \"foobar\" got \"%s\"\n", buf);
136
137 SetLastError( 0xdeadbeef );
138 memset(bufW,'x',sizeof(bufW));
139 len = MultiByteToWideChar(CP_ACP, 0, "foobar", -2002, bufW, 10);
140 ok(len == 7 && !lstrcmpW(bufW, foobarW) && GetLastError() == 0xdeadbeef,
141 "MultiByteToWideChar(-2002): len=%d error=%lu\n", len, GetLastError());
142
143 SetLastError(0xdeadbeef);
144 memset(bufW, 'x', sizeof(bufW));
145 len = MultiByteToWideChar(CP_ACP, 0, "foobar", -1, bufW, 6);
147 "MultiByteToWideChar(-1): len=%d error=%lu\n", len, GetLastError());
148}
149
150#define LONGBUFLEN 100000
152{
153 int len, i;
154 static WCHAR bufW[LONGBUFLEN];
155 static char bufA[LONGBUFLEN];
156 static WCHAR originalW[LONGBUFLEN];
157 static char originalA[LONGBUFLEN];
158 DWORD theError;
159
160 /* Test return on -1 dest length */
161 SetLastError( 0xdeadbeef );
162 memset(bufA,'x',sizeof(bufA));
163 len = WideCharToMultiByte(CP_ACP, 0, foobarW, -1, bufA, -1, NULL, NULL);
165 "WideCharToMultiByte(destlen -1): len=%d error=%lx\n", len, GetLastError());
166
167 SetLastError( 0xdeadbeef );
168 memset(bufW,'x',sizeof(bufW));
169 len = MultiByteToWideChar(CP_ACP, 0, foobarA, -1, bufW, -1);
171 "MultiByteToWideChar(destlen -1): len=%d error=%lx\n", len, GetLastError());
172
173 /* Test return on -1000 dest length */
174 SetLastError( 0xdeadbeef );
175 memset(bufA,'x',sizeof(bufA));
176 len = WideCharToMultiByte(CP_ACP, 0, foobarW, -1, bufA, -1000, NULL, NULL);
178 "WideCharToMultiByte(destlen -1000): len=%d error=%lx\n", len, GetLastError());
179
180 SetLastError( 0xdeadbeef );
181 memset(bufW,'x',sizeof(bufW));
182 len = MultiByteToWideChar(CP_ACP, 0, foobarA, -1000, bufW, -1);
184 "MultiByteToWideChar(destlen -1000): len=%d error=%lx\n", len, GetLastError());
185
186 /* Test return on INT_MAX dest length */
187 SetLastError( 0xdeadbeef );
188 memset(bufA,'x',sizeof(bufA));
190 ok(len == 7 && !lstrcmpA(bufA, "foobar") && GetLastError() == 0xdeadbeef,
191 "WideCharToMultiByte(destlen INT_MAX): len=%d error=%lx\n", len, GetLastError());
192
193 /* Test return on INT_MAX dest length and very long input */
194 SetLastError( 0xdeadbeef );
195 memset(bufA,'x',sizeof(bufA));
196 for (i=0; i < LONGBUFLEN - 1; i++) {
197 originalW[i] = 'Q';
198 originalA[i] = 'Q';
199 }
200 originalW[LONGBUFLEN-1] = 0;
201 originalA[LONGBUFLEN-1] = 0;
202 len = WideCharToMultiByte(CP_ACP, 0, originalW, -1, bufA, INT_MAX, NULL, NULL);
203 theError = GetLastError();
204 ok(len == LONGBUFLEN && !lstrcmpA(bufA, originalA) && theError == 0xdeadbeef,
205 "WideCharToMultiByte(srclen %d, destlen INT_MAX): len %d error=%lx\n", LONGBUFLEN, len, theError);
206
207}
208
210{
211 char c_string[] = "Hello World";
212 size_t c_string_len = sizeof(c_string);
213 WCHAR w_string[] = {'H','e','l','l','o',' ','W','o','r','l','d',0};
214 size_t w_string_len = ARRAY_SIZE(w_string);
215 BOOL used;
216 INT len;
217
218 /* Unrecognized flag => ERROR_INVALID_FLAGS */
219 SetLastError(0xdeadbeef);
220 len = WideCharToMultiByte(CP_ACP, 0x100, w_string, -1, c_string, c_string_len, NULL, NULL);
221 ok(len == 0 && GetLastError() == ERROR_INVALID_FLAGS, "len=%d error=%lx\n", len, GetLastError());
222
223 SetLastError(0xdeadbeef);
224 len = WideCharToMultiByte(CP_ACP, 0x800, w_string, -1, c_string, c_string_len, NULL, NULL);
225 ok(len == 0 && GetLastError() == ERROR_INVALID_FLAGS, "len=%d error=%lx\n", len, GetLastError());
226
227 SetLastError(0xdeadbeef);
228 len = MultiByteToWideChar(CP_ACP, 0x10, c_string, -1, w_string, w_string_len);
229 ok(len == 0 && GetLastError() == ERROR_INVALID_FLAGS, "len=%d error=%lx\n", len, GetLastError());
230
231
232 /* Unrecognized flag and invalid codepage => ERROR_INVALID_PARAMETER */
233 SetLastError(0xdeadbeef);
234 len = WideCharToMultiByte(0xdeadbeef, 0x100, w_string, w_string_len, c_string, c_string_len, NULL, NULL);
235 ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%lx\n", len, GetLastError());
236
237 SetLastError(0xdeadbeef);
238 len = MultiByteToWideChar(0xdeadbeef, 0x10, c_string, c_string_len, w_string, w_string_len);
239 ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%lx\n", len, GetLastError());
240
241
242 /* Unrecognized flag and src is NULL => ERROR_INVALID_PARAMETER */
243 SetLastError(0xdeadbeef);
244 len = WideCharToMultiByte(CP_ACP, 0x100, NULL, -1, c_string, c_string_len, NULL, NULL);
245 ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%lx\n", len, GetLastError());
246
247 SetLastError(0xdeadbeef);
248 len = MultiByteToWideChar(CP_ACP, 0x10, NULL, -1, w_string, w_string_len);
249 ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%lx\n", len, GetLastError());
250
251
252 /* srclen=0 => ERROR_INVALID_PARAMETER */
253 SetLastError(0xdeadbeef);
254 len = WideCharToMultiByte(CP_ACP, 0, w_string, 0, c_string, c_string_len, NULL, NULL);
255 ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%lx\n", len, GetLastError());
256
257 SetLastError(0xdeadbeef);
258 len = MultiByteToWideChar(CP_ACP, 0, c_string, 0, w_string, w_string_len);
259 ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%lx\n", len, GetLastError());
260
261
262 /* dst=NULL but dstlen not 0 => ERROR_INVALID_PARAMETER */
263 SetLastError(0xdeadbeef);
264 len = WideCharToMultiByte(CP_ACP, 0, w_string, w_string_len, NULL, c_string_len, NULL, NULL);
265 ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%lx\n", len, GetLastError());
266
267 SetLastError(0xdeadbeef);
268 len = MultiByteToWideChar(CP_ACP, 0, c_string, c_string_len, NULL, w_string_len);
269 ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%lx\n", len, GetLastError());
270
271
272 /* CP_UTF7 or CP_SYMBOL and defchar not NULL => ERROR_INVALID_PARAMETER */
273 /* CP_UTF8 allows it since win10 1709 */
274 SetLastError(0xdeadbeef);
275 len = WideCharToMultiByte(CP_UTF7, 0, w_string, w_string_len, c_string, c_string_len, c_string, NULL);
276 ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%lx\n", len, GetLastError());
277
278 SetLastError(0xdeadbeef);
279 len = WideCharToMultiByte(CP_UTF8, 0, w_string, w_string_len, c_string, c_string_len, c_string, NULL);
280 ok(len == 12 || broken(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER),
281 "len=%d error=%lx\n", len, GetLastError());
282
283 SetLastError(0xdeadbeef);
284 len = WideCharToMultiByte(CP_SYMBOL, 0, w_string, w_string_len, c_string, c_string_len, c_string, NULL);
285 ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%lx\n", len, GetLastError());
286
287
288 /* CP_UTF7 or CP_SYMBOL and used not NULL => ERROR_INVALID_PARAMETER */
289 /* CP_UTF8 allows it since win10 1709 */
290 SetLastError(0xdeadbeef);
291 len = WideCharToMultiByte(CP_UTF7, 0, w_string, w_string_len, c_string, c_string_len, NULL, &used);
292 ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%lx\n", len, GetLastError());
293
294 SetLastError(0xdeadbeef);
295 len = WideCharToMultiByte(CP_UTF8, 0, w_string, w_string_len, c_string, c_string_len, NULL, &used);
296 ok(len == 12 || broken(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER),
297 "len=%d error=%lx\n", len, GetLastError());
298
299 SetLastError(0xdeadbeef);
300 len = WideCharToMultiByte(CP_SYMBOL, 0, w_string, w_string_len, c_string, c_string_len, NULL, &used);
301 ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%lx\n", len, GetLastError());
302
303
304 /* CP_UTF7, flags not 0 and used not NULL => ERROR_INVALID_PARAMETER */
305 /* (tests precedence of ERROR_INVALID_PARAMETER over ERROR_INVALID_FLAGS) */
306 /* The same test with CP_SYMBOL instead of CP_UTF7 gives ERROR_INVALID_FLAGS
307 instead except on Windows NT4 */
308 SetLastError(0xdeadbeef);
309 len = WideCharToMultiByte(CP_UTF7, 1, w_string, w_string_len, c_string, c_string_len, NULL, &used);
310 ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%lx\n", len, GetLastError());
311
312 /* CP_UTF8, unrecognized flag and used not NULL => ERROR_INVALID_PARAMETER */
313 SetLastError(0xdeadbeef);
314 len = WideCharToMultiByte(CP_UTF8, 0x100, w_string, w_string_len, c_string, c_string_len, NULL, &used);
315 ok(len == 0, "wrong ret %d\n", len);
317 || GetLastError() == ERROR_INVALID_FLAGS /* Win10 1709+ */, "wrong error %lu\n", GetLastError());
318}
319
320static void test_overlapped_buffers(void)
321{
322 static const WCHAR strW[] = {'j','u','s','t',' ','a',' ','t','e','s','t',0};
323 static const char strA[] = "just a test";
324 char buf[256];
325 int ret;
326
327 /* limit such that strA's NUL terminator overlaps strW's NUL */
328 size_t overlap_limit = (sizeof(strW)-sizeof(strA)) - (sizeof(strW[0])-sizeof(strA[0]));
329
330 SetLastError(0xdeadbeef);
331 memcpy(buf + 1, strW, sizeof(strW));
332 ret = WideCharToMultiByte(CP_ACP, 0, (WCHAR *)(buf + 1), -1, buf, sizeof(buf), NULL, NULL);
333 ok(ret == sizeof(strA), "unexpected ret %d\n", ret);
334 ok(!memcmp(buf, strA, sizeof(strA)), "conversion failed: %s\n", buf);
335 ok(GetLastError() == 0xdeadbeef, "GetLastError() is %lu\n", GetLastError());
336
337 SetLastError(0xdeadbeef);
338 memcpy(buf + overlap_limit, strA, sizeof(strA));
339 ret = MultiByteToWideChar(CP_ACP, 0, buf + overlap_limit, -1, (WCHAR *)buf, sizeof(buf) / sizeof(WCHAR));
340 ok(ret == ARRAY_SIZE(strW), "unexpected ret %d\n", ret);
341 ok(!memcmp(buf, strW, sizeof(strW)), "conversion failed: %s\n", wine_dbgstr_wn((WCHAR *)buf, ARRAY_SIZE(strW)));
342 ok(GetLastError() == 0xdeadbeef, "GetLastError() is %lu\n", GetLastError());
343}
344
345static void test_string_conversion(LPBOOL bUsedDefaultChar)
346{
347 char mbc;
348 char mbs[15];
349 int ret;
350 WCHAR wc1 = 228; /* Western Windows-1252 character */
351 WCHAR wc2 = 1088; /* Russian Windows-1251 character not displayable for Windows-1252 */
352 static const WCHAR wcs[] = {'T', 'h', 1088, 'i', 0}; /* String with ASCII characters and a Russian character */
353 static const WCHAR dbwcs[] = {28953, 25152, 0}; /* String with Chinese (codepage 950) characters */
354 static const WCHAR dbwcs2[] = {0x7bb8, 0x3d, 0xc813, 0xac00, 0xb77d, 0};
355 static const char default_char[] = {0xa3, 0xbf, 0};
356
357 SetLastError(0xdeadbeef);
358 ret = WideCharToMultiByte(1252, 0, &wc1, 1, &mbc, 1, NULL, bUsedDefaultChar);
359 ok(ret == 1, "ret is %d\n", ret);
360 ok(mbc == '\xe4', "mbc is %d\n", mbc);
361 if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
362 ok(GetLastError() == 0xdeadbeef, "GetLastError() is %lu\n", GetLastError());
363
364 SetLastError(0xdeadbeef);
365 ret = WideCharToMultiByte(1252, 0, &wc2, 1, &mbc, 1, NULL, bUsedDefaultChar);
366 ok(ret == 1, "ret is %d\n", ret);
367 ok(mbc == 63, "mbc is %d\n", mbc);
368 if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
369 ok(GetLastError() == 0xdeadbeef, "GetLastError() is %lu\n", GetLastError());
370
371 if (IsValidCodePage(1251))
372 {
373 SetLastError(0xdeadbeef);
374 ret = WideCharToMultiByte(1251, 0, &wc2, 1, &mbc, 1, NULL, bUsedDefaultChar);
375 ok(ret == 1, "ret is %d\n", ret);
376 ok(mbc == '\xf0', "mbc is %d\n", mbc);
377 if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
378 ok(GetLastError() == 0xdeadbeef ||
379 broken(GetLastError() == 0), /* win95 */
380 "GetLastError() is %lu\n", GetLastError());
381
382 SetLastError(0xdeadbeef);
383 ret = WideCharToMultiByte(1251, 0, &wc1, 1, &mbc, 1, NULL, bUsedDefaultChar);
384 ok(ret == 1, "ret is %d\n", ret);
385 ok(mbc == 97, "mbc is %d\n", mbc);
386 if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
387 ok(GetLastError() == 0xdeadbeef, "GetLastError() is %lu\n", GetLastError());
388 }
389 else
390 skip("Codepage 1251 not available\n");
391
392 /* This call triggers the last Win32 error */
393 SetLastError(0xdeadbeef);
394 ret = WideCharToMultiByte(1252, 0, wcs, -1, &mbc, 1, NULL, bUsedDefaultChar);
395 ok(ret == 0, "ret is %d\n", ret);
396 ok(mbc == 84, "mbc is %d\n", mbc);
397 if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
398 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetLastError() is %lu\n", GetLastError());
399
400 SetLastError(0xdeadbeef);
401 ret = WideCharToMultiByte(1252, 0, wcs, -1, mbs, sizeof(mbs), NULL, bUsedDefaultChar);
402 ok(ret == 5, "ret is %d\n", ret);
403 ok(!strcmp(mbs, "Th?i"), "mbs is %s\n", mbs);
404 if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
405 ok(GetLastError() == 0xdeadbeef, "GetLastError() is %lu\n", GetLastError());
406 mbs[0] = 0;
407
408 /* WideCharToMultiByte mustn't add any null character automatically.
409 So in this case, we should get the same string again, even if we only copied the first three bytes. */
410 SetLastError(0xdeadbeef);
411 ret = WideCharToMultiByte(1252, 0, wcs, 3, mbs, sizeof(mbs), NULL, bUsedDefaultChar);
412 ok(ret == 3, "ret is %d\n", ret);
413 ok(!strcmp(mbs, "Th?i"), "mbs is %s\n", mbs);
414 if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
415 ok(GetLastError() == 0xdeadbeef, "GetLastError() is %lu\n", GetLastError());
416 ZeroMemory(mbs, 5);
417
418 /* Now this shouldn't be the case like above as we zeroed the complete string buffer. */
419 SetLastError(0xdeadbeef);
420 ret = WideCharToMultiByte(1252, 0, wcs, 3, mbs, sizeof(mbs), NULL, bUsedDefaultChar);
421 ok(ret == 3, "ret is %d\n", ret);
422 ok(!strcmp(mbs, "Th?"), "mbs is %s\n", mbs);
423 if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
424 ok(GetLastError() == 0xdeadbeef, "GetLastError() is %lu\n", GetLastError());
425
426 /* Double-byte tests */
427 ret = WideCharToMultiByte(1252, 0, dbwcs, 3, mbs, sizeof(mbs), NULL, bUsedDefaultChar);
428 ok(ret == 3, "ret is %d\n", ret);
429 ok(!strcmp(mbs, "??"), "mbs is %s\n", mbs);
430 if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
431
432 ret = WideCharToMultiByte(936, WC_COMPOSITECHECK, dbwcs2, -1, mbs, sizeof(mbs), (const char *)default_char, bUsedDefaultChar);
433 ok(ret == 10, "ret is %d\n", ret);
434 ok(!strcmp(mbs, "\xf3\xe7\x3d\xa3\xbf\xa3\xbf\xa3\xbf"), "mbs is %s\n", mbs);
435 if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
436
437 /* Show that characters are not truncated */
438 ZeroMemory(mbs, 5);
439 ret = WideCharToMultiByte(936, 0, dbwcs2, -1, mbs, 1, (const char *)default_char, bUsedDefaultChar);
440 ok(!ret, "ret is %d\n", ret);
441 ok(mbs[0] == '\0', "mbs is %s\n", mbs);
442 if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
443 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetLastError() is %lu\n", GetLastError());
444
445 /* And destination is not null-terminated even when too short */
446 FillMemory(mbs, 5, 'x');
447 mbs[5] = '\0';
448 ret = WideCharToMultiByte(936, 0, dbwcs2, -1, mbs, 2, (const char *)default_char, bUsedDefaultChar);
449 ok(!ret, "ret is %d\n", ret);
450 ok(!strcmp(mbs, "\xf3\xe7""xxx"), "mbs is %s\n", mbs);
451 if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
452 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetLastError() is %lu\n", GetLastError());
453
454 /* Length-only tests */
455 SetLastError(0xdeadbeef);
456 ret = WideCharToMultiByte(1252, 0, &wc2, 1, NULL, 0, NULL, bUsedDefaultChar);
457 ok(ret == 1, "ret is %d\n", ret);
458 if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
459 ok(GetLastError() == 0xdeadbeef, "GetLastError() is %lu\n", GetLastError());
460
461 SetLastError(0xdeadbeef);
462 ret = WideCharToMultiByte(1252, 0, wcs, -1, NULL, 0, NULL, bUsedDefaultChar);
463 ok(ret == 5, "ret is %d\n", ret);
464 if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
465 ok(GetLastError() == 0xdeadbeef, "GetLastError() is %lu\n", GetLastError());
466
467 if (!IsValidCodePage(950))
468 {
469 skip("Codepage 950 not available\n");
470 return;
471 }
472
473 /* Double-byte tests */
474 SetLastError(0xdeadbeef);
475 ret = WideCharToMultiByte(950, 0, dbwcs, -1, mbs, sizeof(mbs), NULL, bUsedDefaultChar);
476 ok(ret == 5, "ret is %d\n", ret);
477 ok(!strcmp(mbs, "\xb5H\xa9\xd2"), "mbs is %s\n", mbs);
478 if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
479 ok(GetLastError() == 0xdeadbeef, "GetLastError() is %lu\n", GetLastError());
480
481 SetLastError(0xdeadbeef);
482 ret = WideCharToMultiByte(950, 0, dbwcs, 1, &mbc, 1, NULL, bUsedDefaultChar);
483 ok(ret == 0, "ret is %d\n", ret);
484 if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
485 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetLastError() is %lu\n", GetLastError());
486 ZeroMemory(mbs, 5);
487
488 SetLastError(0xdeadbeef);
489 ret = WideCharToMultiByte(950, 0, dbwcs, 1, mbs, sizeof(mbs), NULL, bUsedDefaultChar);
490 ok(ret == 2, "ret is %d\n", ret);
491 ok(!strcmp(mbs, "\xb5H"), "mbs is %s\n", mbs);
492 if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
493 ok(GetLastError() == 0xdeadbeef, "GetLastError() is %lu\n", GetLastError());
494
495 /* Length-only tests */
496 SetLastError(0xdeadbeef);
497 ret = WideCharToMultiByte(950, 0, dbwcs, 1, NULL, 0, NULL, bUsedDefaultChar);
498 ok(ret == 2, "ret is %d\n", ret);
499 if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
500 ok(GetLastError() == 0xdeadbeef, "GetLastError() is %lu\n", GetLastError());
501
502 SetLastError(0xdeadbeef);
503 ret = WideCharToMultiByte(950, 0, dbwcs, -1, NULL, 0, NULL, bUsedDefaultChar);
504 ok(ret == 5, "ret is %d\n", ret);
505 if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
506 ok(GetLastError() == 0xdeadbeef, "GetLastError() is %lu\n", GetLastError());
507}
508
509static void test_utf7_encoding(void)
510{
511 WCHAR input[16];
512 char output[16], expected[16];
513 int i, len, expected_len;
514
515 static const BOOL directly_encodable_table[] =
516 {
517 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, /* 0x00 - 0x0F */
518 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x1F */
519 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* 0x20 - 0x2F */
520 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x30 - 0x3F */
521 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 - 0x4F */
522 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x50 - 0x5F */
523 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 - 0x6F */
524 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 /* 0x70 - 0x7F */
525 };
526 static const char base64_encoding_table[] =
527 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
528
529 const struct
530 {
531 /* inputs */
532 WCHAR src[16];
533 int srclen;
534 char *dst;
535 int dstlen;
536 /* expected outputs */
537 char expected_dst[16];
538 int chars_written;
539 int len;
540 }
541 tests[] =
542 {
543 /* tests string conversion with srclen=-1 */
544 {
545 {0x4F60,0x597D,0x5417,0}, -1, output, sizeof(output) - 1,
546 "+T2BZfVQX-", 11, 11
547 },
548 /* tests string conversion with srclen=-2 */
549 {
550 {0x4F60,0x597D,0x5417,0}, -2, output, sizeof(output) - 1,
551 "+T2BZfVQX-", 11, 11
552 },
553 /* tests string conversion with dstlen=strlen(expected_dst) */
554 {
555 {0x4F60,0x597D,0x5417,0}, -1, output, 10,
556 "+T2BZfVQX-", 10, 0
557 },
558 /* tests string conversion with dstlen=strlen(expected_dst)+1 */
559 {
560 {0x4F60,0x597D,0x5417,0}, -1, output, 11,
561 "+T2BZfVQX-", 11, 11
562 },
563 /* tests string conversion with dstlen=strlen(expected_dst)+2 */
564 {
565 {0x4F60,0x597D,0x5417,0}, -1, output, 12,
566 "+T2BZfVQX-", 11, 11
567 },
568 /* tests dry run with dst=NULL and dstlen=0 */
569 {
570 {0x4F60,0x597D,0x5417,0}, -1, NULL, 0,
571#if defined(__REACTOS__) && defined(_MSC_VER)
572 {0}, 0, 11
573#else
574 {}, 0, 11
575#endif
576 },
577 /* tests dry run with dst!=NULL and dstlen=0 */
578 {
579 {0x4F60,0x597D,0x5417,0}, -1, output, 0,
580#if defined(__REACTOS__) && defined(_MSC_VER)
581 {0}, 0, 11
582#else
583 {}, 0, 11
584#endif
585 },
586 /* tests srclen < strlenW(src) with directly encodable chars */
587 {
588 {'h','e','l','l','o',0}, 2, output, sizeof(output) - 1,
589 "he", 2, 2
590 },
591 /* tests srclen < strlenW(src) with non-directly encodable chars */
592 {
593 {0x4F60,0x597D,0x5417,0}, 2, output, sizeof(output) - 1,
594 "+T2BZfQ-", 8, 8
595 },
596 /* tests a single null char */
597 {
598 {0}, -1, output, sizeof(output) - 1,
599 "", 1, 1
600 },
601 /* tests a buffer that runs out while not encoding a UTF-7 sequence */
602 {
603 {'h','e','l','l','o',0}, -1, output, 2,
604 "he", 2, 0
605 },
606 /* tests a buffer that runs out after writing 1 base64 character */
607 {
608 {0x4F60,0x0001,0}, -1, output, 2,
609 "+T", 2, 0
610 },
611 /* tests a buffer that runs out after writing 2 base64 characters */
612 {
613 {0x4F60,0x0001,0}, -1, output, 3,
614 "+T2", 3, 0
615 },
616 /* tests a buffer that runs out after writing 3 base64 characters */
617 {
618 {0x4F60,0x0001,0}, -1, output, 4,
619 "+T2A", 4, 0
620 },
621 /* tests a buffer that runs out just after writing the + sign */
622 {
623 {0x4F60,0}, -1, output, 1,
624 "+", 1, 0
625 },
626 /* tests a buffer that runs out just before writing the - sign
627 * the number of bits to encode here is evenly divisible by 6 */
628 {
629 {0x4F60,0x597D,0x5417,0}, -1, output, 9,
630 "+T2BZfVQX", 9, 0
631 },
632 /* tests a buffer that runs out just before writing the - sign
633 * the number of bits to encode here is NOT evenly divisible by 6 */
634 {
635 {0x4F60,0}, -1, output, 4,
636 "+T2", 3, 0
637 },
638 /* tests a buffer that runs out in the middle of escaping a + sign */
639 {
640 {'+',0}, -1, output, 1,
641 "+", 1, 0
642 }
643 };
644
645 /* test which characters are encoded if surrounded by non-encoded characters */
646 for (i = 0; i <= 0xFFFF; i++)
647 {
648 input[0] = ' ';
649 input[1] = i;
650 input[2] = ' ';
651 input[3] = 0;
652
653 memset(output, '#', sizeof(output) - 1);
654 output[sizeof(output) - 1] = 0;
655
656 len = WideCharToMultiByte(CP_UTF7, 0, input, 4, output, sizeof(output) - 1, NULL, NULL);
657
658 if (i == '+')
659 {
660 /* '+' is a special case and is encoded as "+-" */
661 expected_len = 5;
662 strcpy(expected, " +- ");
663 }
664 else if (i <= 0x7F && directly_encodable_table[i])
665 {
666 /* encodes directly */
667 expected_len = 4;
668 sprintf(expected, " %c ", i);
669 }
670 else
671 {
672 /* base64-encodes */
673 expected_len = 8;
674 sprintf(expected, " +%c%c%c- ",
675 base64_encoding_table[(i & 0xFC00) >> 10],
676 base64_encoding_table[(i & 0x03F0) >> 4],
677 base64_encoding_table[(i & 0x000F) << 2]);
678 }
679
680 ok(len == expected_len, "i=0x%04x: expected len=%i, got len=%i\n", i, expected_len, len);
681 ok(memcmp(output, expected, expected_len) == 0,
682 "i=0x%04x: expected output='%s', got output='%s'\n", i, expected, output);
683 ok(output[expected_len] == '#', "i=0x%04x: expected output[%i]='#', got output[%i]=%i\n",
684 i, expected_len, expected_len, output[expected_len]);
685 }
686
687 /* test which one-byte characters are absorbed into surrounding base64 blocks
688 * (Windows always ends the base64 block when it encounters a directly encodable character) */
689 for (i = 0; i <= 0xFFFF; i++)
690 {
691 input[0] = 0x2672;
692 input[1] = i;
693 input[2] = 0x2672;
694 input[3] = 0;
695
696 memset(output, '#', sizeof(output) - 1);
697 output[sizeof(output) - 1] = 0;
698
699 len = WideCharToMultiByte(CP_UTF7, 0, input, 4, output, sizeof(output) - 1, NULL, NULL);
700
701 if (i == '+')
702 {
703 /* '+' is a special case and is encoded as "+-" */
704 expected_len = 13;
705 strcpy(expected, "+JnI-+-+JnI-");
706 }
707 else if (i <= 0x7F && directly_encodable_table[i])
708 {
709 /* encodes directly */
710 expected_len = 12;
711 sprintf(expected, "+JnI-%c+JnI-", i);
712 }
713 else
714 {
715 /* base64-encodes */
716 expected_len = 11;
717 sprintf(expected, "+Jn%c%c%c%cZy-",
718 base64_encoding_table[8 | ((i & 0xC000) >> 14)],
719 base64_encoding_table[(i & 0x3F00) >> 8],
720 base64_encoding_table[(i & 0x00FC) >> 2],
721 base64_encoding_table[((i & 0x0003) << 4) | 2]);
722 }
723
724 ok(len == expected_len, "i=0x%04x: expected len=%i, got len=%i\n", i, expected_len, len);
725 ok(memcmp(output, expected, expected_len) == 0,
726 "i=0x%04x: expected output='%s', got output='%s'\n", i, expected, output);
727 ok(output[expected_len] == '#', "i=0x%04x: expected output[%i]='#', got output[%i]=%i\n",
728 i, expected_len, expected_len, output[expected_len]);
729 }
730
731 for (i = 0; i < ARRAY_SIZE(tests); i++)
732 {
733 memset(output, '#', sizeof(output) - 1);
734 output[sizeof(output) - 1] = 0;
735 SetLastError(0xdeadbeef);
736
739
740 if (!tests[i].len)
741 {
743 "tests[%i]: expected error=0x%x, got error=0x%lx\n",
745 }
746 ok(len == tests[i].len, "tests[%i]: expected len=%i, got len=%i\n", i, tests[i].len, len);
747
748 if (tests[i].dst)
749 {
750 ok(memcmp(tests[i].dst, tests[i].expected_dst, tests[i].chars_written) == 0,
751 "tests[%i]: expected dst='%s', got dst='%s'\n",
752 i, tests[i].expected_dst, tests[i].dst);
753 ok(tests[i].dst[tests[i].chars_written] == '#',
754 "tests[%i]: expected dst[%i]='#', got dst[%i]=%i\n",
755 i, tests[i].chars_written, tests[i].chars_written, tests[i].dst[tests[i].chars_written]);
756 }
757 }
758}
759
760static void test_utf7_decoding(void)
761{
762 char input[32];
763 WCHAR output[32], expected[32];
764 int i, len, expected_len;
765
766 static const signed char base64_decoding_table[] =
767 {
768 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00-0x0F */
769 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10-0x1F */
770 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 0x20-0x2F */
771 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, /* 0x30-0x3F */
772 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 0x40-0x4F */
773 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 0x50-0x5F */
774 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 0x60-0x6F */
775 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 /* 0x70-0x7F */
776 };
777
778 struct
779 {
780 /* inputs */
781 char src[32];
782 int srclen;
783 WCHAR *dst;
784 int dstlen;
785 /* expected outputs */
786 WCHAR expected_dst[32];
787 int chars_written;
788 int len;
789 }
790 tests[] =
791 {
792 /* tests string conversion with srclen=-1 */
793 {
794 "+T2BZfQ-", -1, output, ARRAY_SIZE(output) - 1,
795 {0x4F60,0x597D,0}, 3, 3
796 },
797 /* tests string conversion with srclen=-2 */
798 {
799 "+T2BZfQ-", -2, output, ARRAY_SIZE(output) - 1,
800 {0x4F60,0x597D,0}, 3, 3
801 },
802 /* tests string conversion with dstlen=strlen(expected_dst) */
803 {
804 "+T2BZfQ-", -1, output, 2,
805 {0x4F60,0x597D}, 2, 0
806 },
807 /* tests string conversion with dstlen=strlen(expected_dst)+1 */
808 {
809 "+T2BZfQ-", -1, output, 3,
810 {0x4F60,0x597D,0}, 3, 3
811 },
812 /* tests string conversion with dstlen=strlen(expected_dst)+2 */
813 {
814 "+T2BZfQ-", -1, output, 4,
815 {0x4F60,0x597D,0}, 3, 3
816 },
817 /* tests dry run with dst=NULL and dstlen=0 */
818 {
819 "+T2BZfQ-", -1, NULL, 0,
820#if defined(__REACTOS__) && defined(_MSC_VER)
821 {0}, 0, 3
822#else
823 {}, 0, 3
824#endif
825 },
826 /* tests dry run with dst!=NULL and dstlen=0 */
827 {
828 "+T2BZfQ-", -1, output, 0,
829#if defined(__REACTOS__) && defined(_MSC_VER)
830 {0}, 0, 3
831#else
832 {}, 0, 3
833#endif
834 },
835 /* tests ill-formed UTF-7: 6 bits, not enough for a byte pair */
836 {
837 "+T-+T-+T-hello", -1, output, ARRAY_SIZE(output) - 1,
838 {'h','e','l','l','o',0}, 6, 6
839 },
840 /* tests ill-formed UTF-7: 12 bits, not enough for a byte pair */
841 {
842 "+T2-+T2-+T2-hello", -1, output, ARRAY_SIZE(output) - 1,
843 {'h','e','l','l','o',0}, 6, 6
844 },
845 /* tests ill-formed UTF-7: 18 bits, not a multiple of 16 and the last bit is a 1 */
846 {
847 "+T2B-+T2B-+T2B-hello", -1, output, ARRAY_SIZE(output) - 1,
848 {0x4F60,0x4F60,0x4F60,'h','e','l','l','o',0}, 9, 9
849 },
850 /* tests ill-formed UTF-7: 24 bits, a multiple of 8 but not a multiple of 16 */
851 {
852 "+T2BZ-+T2BZ-+T2BZ-hello", -1, output, ARRAY_SIZE(output) - 1,
853 {0x4F60,0x4F60,0x4F60,'h','e','l','l','o',0}, 9, 9
854 },
855 /* tests UTF-7 followed by characters that should be encoded but aren't */
856 {
857 "+T2BZ-\x82\xFE", -1, output, ARRAY_SIZE(output) - 1,
858 {0x4F60,0x0082,0x00FE,0}, 4, 4
859 },
860 /* tests srclen > strlen(src) */
861 {
862 "a\0b", 4, output, ARRAY_SIZE(output) - 1,
863 {'a',0,'b',0}, 4, 4
864 },
865 /* tests srclen < strlen(src) outside of a UTF-7 sequence */
866 {
867 "hello", 2, output, ARRAY_SIZE(output) - 1,
868 {'h','e'}, 2, 2
869 },
870 /* tests srclen < strlen(src) inside of a UTF-7 sequence */
871 {
872 "+T2BZfQ-", 4, output, ARRAY_SIZE(output) - 1,
873 {0x4F60}, 1, 1
874 },
875 /* tests srclen < strlen(src) right at the beginning of a UTF-7 sequence */
876 {
877 "hi+T2A-", 3, output, ARRAY_SIZE(output) - 1,
878 {'h','i'}, 2, 2
879 },
880 /* tests srclen < strlen(src) right at the end of a UTF-7 sequence */
881 {
882 "+T2A-hi", 5, output, ARRAY_SIZE(output) - 1,
883 {0x4F60}, 1, 1
884 },
885 /* tests srclen < strlen(src) at the beginning of an escaped + sign */
886 {
887 "hi+-", 3, output, ARRAY_SIZE(output) - 1,
888 {'h','i'}, 2, 2
889 },
890 /* tests srclen < strlen(src) at the end of an escaped + sign */
891 {
892 "+-hi", 2, output, ARRAY_SIZE(output) - 1,
893 {'+'}, 1, 1
894 },
895 /* tests len=0 but no error */
896 {
897 "+", 1, output, ARRAY_SIZE(output) - 1,
898#if defined(__REACTOS__) && defined(_MSC_VER)
899 {0}, 0, 0
900#else
901 {}, 0, 0
902#endif
903 },
904 /* tests a single null char */
905 {
906 "", -1, output, ARRAY_SIZE(output) - 1,
907 {0}, 1, 1
908 },
909 /* tests a buffer that runs out while not decoding a UTF-7 sequence */
910 {
911 "hello", -1, output, 2,
912 {'h','e'}, 2, 0
913 },
914 /* tests a buffer that runs out in the middle of decoding a UTF-7 sequence */
915 {
916 "+T2BZfQ-", -1, output, 1,
917 {0x4F60}, 1, 0
918 }
919 };
920
921 /* test which one-byte characters remove stray + signs */
922 for (i = 0; i < 256; i++)
923 {
924 sprintf(input, "+%c+AAA", i);
925
926 memset(output, 0x23, sizeof(output) - sizeof(WCHAR));
927 output[ARRAY_SIZE(output) - 1] = 0;
928
929 len = MultiByteToWideChar(CP_UTF7, 0, input, 7, output, ARRAY_SIZE(output) - 1);
930
931 if (i == '-')
932 {
933 /* removes the - sign */
934 expected_len = 3;
935 expected[0] = 0x002B;
936 expected[1] = 0;
937 expected[2] = 0;
938 }
939 else if (i <= 0x7F && base64_decoding_table[i] != -1)
940 {
941 /* absorbs the character into the base64 sequence */
942 expected_len = 2;
943 expected[0] = (base64_decoding_table[i] << 10) | 0x03E0;
944 expected[1] = 0;
945 }
946 else
947 {
948 /* removes the + sign */
949 expected_len = 3;
950 expected[0] = i;
951 expected[1] = 0;
952 expected[2] = 0;
953 }
954 expected[expected_len] = 0x2323;
955
956 ok(len == expected_len, "i=0x%02x: expected len=%i, got len=%i\n", i, expected_len, len);
957 ok(memcmp(output, expected, (expected_len + 1) * sizeof(WCHAR)) == 0,
958 "i=0x%02x: expected output=%s, got output=%s\n",
959 i, wine_dbgstr_wn(expected, expected_len + 1), wine_dbgstr_wn(output, expected_len + 1));
960 }
961
962 /* test which one-byte characters terminate a sequence
963 * also test whether the unfinished byte pair is discarded or not */
964 for (i = 0; i < 256; i++)
965 {
966 sprintf(input, "+B%c+AAA", i);
967
968 memset(output, 0x23, sizeof(output) - sizeof(WCHAR));
969 output[ARRAY_SIZE(output) - 1] = 0;
970
971 len = MultiByteToWideChar(CP_UTF7, 0, input, 8, output, ARRAY_SIZE(output) - 1);
972
973 if (i == '-')
974 {
975 /* explicitly terminates */
976 expected_len = 2;
977 expected[0] = 0;
978 expected[1] = 0;
979 }
980 else if (i <= 0x7F)
981 {
982 if (base64_decoding_table[i] != -1)
983 {
984 /* absorbs the character into the base64 sequence */
985 expected_len = 3;
986 expected[0] = 0x0400 | (base64_decoding_table[i] << 4) | 0x000F;
987 expected[1] = 0x8000;
988 expected[2] = 0;
989 }
990 else
991 {
992 /* implicitly terminates and discards the unfinished byte pair */
993 expected_len = 3;
994 expected[0] = i;
995 expected[1] = 0;
996 expected[2] = 0;
997 }
998 }
999 else
1000 {
1001 /* implicitly terminates but does not the discard unfinished byte pair */
1002 expected_len = 3;
1003 expected[0] = i;
1004 expected[1] = 0x0400;
1005 expected[2] = 0;
1006 }
1007 expected[expected_len] = 0x2323;
1008
1009 ok(len == expected_len, "i=0x%02x: expected len=%i, got len=%i\n", i, expected_len, len);
1010 ok(memcmp(output, expected, (expected_len + 1) * sizeof(WCHAR)) == 0,
1011 "i=0x%02x: expected output=%s, got output=%s\n",
1012 i, wine_dbgstr_wn(expected, expected_len + 1), wine_dbgstr_wn(output, expected_len + 1));
1013 }
1014
1015 for (i = 0; i < ARRAY_SIZE(tests); i++)
1016 {
1017 memset(output, 0x23, sizeof(output) - sizeof(WCHAR));
1018 output[ARRAY_SIZE(output) - 1] = 0;
1019 SetLastError(0xdeadbeef);
1020
1022 tests[i].dst, tests[i].dstlen);
1023
1024 tests[i].expected_dst[tests[i].chars_written] = 0x2323;
1025
1026 if (!tests[i].len && tests[i].chars_written)
1027 {
1029 "tests[%i]: expected error=0x%x, got error=0x%lx\n",
1031 }
1032 ok(len == tests[i].len, "tests[%i]: expected len=%i, got len=%i\n", i, tests[i].len, len);
1033
1034 if (tests[i].dst)
1035 {
1036 ok(memcmp(tests[i].dst, tests[i].expected_dst, (tests[i].chars_written + 1) * sizeof(WCHAR)) == 0,
1037 "tests[%i]: expected dst=%s, got dst=%s\n",
1038 i, wine_dbgstr_wn(tests[i].expected_dst, tests[i].chars_written + 1),
1039 wine_dbgstr_wn(tests[i].dst, tests[i].chars_written + 1));
1040 }
1041 }
1042}
1043
1045{
1046 static const struct tag_testset {
1047 UINT codepage;
1048 LPCSTR str;
1049 BOOL is_error;
1050 } testset[] = {
1051 { 37, "\x6f", FALSE },
1052 { 874, "\xdd", TRUE },
1053 { 932, "\xfe", TRUE },
1054 { 932, "\x80", FALSE },
1055 { 932, "\x81\x45", FALSE },
1056 { 936, "\xff", TRUE },
1057 { 949, "\xff", TRUE },
1058 { 950, "\xff", TRUE },
1059 { 1252, "?", FALSE },
1060 { 1252, "\x90", FALSE },
1061 { 1253, "\xaa", TRUE },
1062 { 1255, "\xff", TRUE },
1063 { 1257, "\xa5", TRUE },
1064 };
1065 INT i, ret;
1066 DWORD err;
1067
1068 for (i = 0; i < ARRAY_SIZE(testset); i++) {
1069 if (! IsValidCodePage(testset[i].codepage))
1070 {
1071 skip("Codepage %d not available\n", testset[i].codepage);
1072 continue;
1073 }
1074
1075 SetLastError(0xdeadbeef);
1077 testset[i].str, -1, NULL, 0);
1078 err = GetLastError();
1079 if (testset[i].is_error) {
1080 ok(err == ERROR_NO_UNICODE_TRANSLATION, "Test %u: err is %lu\n", i, err);
1081 ok(ret == 0, "Test %u: ret is %d\n", i, ret);
1082 }
1083 else {
1084 ok(err == 0xdeadbeef, "Test %u: err is %lu\n", i, err);
1085 ok(ret == 2, "Test %u: ret is %d\n", i, ret);
1086 }
1087
1088 SetLastError(0xdeadbeef);
1089 ret = MultiByteToWideChar(testset[i].codepage, 0,
1090 testset[i].str, -1, NULL, 0);
1091 err = GetLastError();
1092 ok(err == 0xdeadbeef, "Test %u: err is %lu\n", i, err);
1093 ok(ret == 2, "Test %u: ret is %d\n", i, ret);
1094 }
1095}
1096
1097static void test_threadcp(void)
1098{
1105
1106 BOOL islead, islead_default;
1107 CPINFOEXA cpi;
1108 UINT cp, acp;
1109 int i, num;
1110 LCID last;
1111 BOOL ret;
1112
1113 struct test {
1114 LCID lcid;
1115 UINT threadcp;
1116 } lcids[] = {
1117 { HINDI, 0 },
1118 { GEORGIAN, 0 },
1119 { ENGLISH, 1252 },
1120 { RUSSIAN, 1251 },
1121 { JAPANESE, 932 },
1122 { CHINESE, 936 }
1123 };
1124
1125 struct test_islead_nocp {
1126 LCID lcid;
1127 BYTE testchar;
1128 } isleads_nocp[] = {
1129 { HINDI, 0x00 },
1130 { HINDI, 0x81 },
1131 { HINDI, 0xa0 },
1132 { HINDI, 0xe0 },
1133
1134 { GEORGIAN, 0x00 },
1135 { GEORGIAN, 0x81 },
1136 { GEORGIAN, 0xa0 },
1137 { GEORGIAN, 0xe0 },
1138 };
1139
1140 struct test_islead {
1141 LCID lcid;
1142 BYTE testchar;
1143 BOOL islead;
1144 } isleads[] = {
1145 { ENGLISH, 0x00, FALSE },
1146 { ENGLISH, 0x81, FALSE },
1147 { ENGLISH, 0xa0, FALSE },
1148 { ENGLISH, 0xe0, FALSE },
1149
1150 { RUSSIAN, 0x00, FALSE },
1151 { RUSSIAN, 0x81, FALSE },
1152 { RUSSIAN, 0xa0, FALSE },
1153 { RUSSIAN, 0xe0, FALSE },
1154
1155 { JAPANESE, 0x00, FALSE },
1156 { JAPANESE, 0x81, TRUE },
1157 { JAPANESE, 0xa0, FALSE },
1158 { JAPANESE, 0xe0, TRUE },
1159
1160 { CHINESE, 0x00, FALSE },
1161 { CHINESE, 0x81, TRUE },
1162 { CHINESE, 0xa0, TRUE },
1163 { CHINESE, 0xe0, TRUE },
1164 };
1165
1167 acp = GetACP();
1168
1169 for (i = 0; i < ARRAY_SIZE(lcids); i++)
1170 {
1171 SetThreadLocale(lcids[i].lcid);
1172
1173 cp = 0xdeadbeef;
1174 GetLocaleInfoA(lcids[i].lcid, LOCALE_IDEFAULTANSICODEPAGE|LOCALE_RETURN_NUMBER, (LPSTR)&cp, sizeof(cp));
1175 ok(cp == lcids[i].threadcp, "wrong codepage %u for lcid %04lx, should be %u\n", cp, lcids[i].lcid, lcids[i].threadcp);
1176
1177 /* GetCPInfoEx/GetCPInfo - CP_ACP */
1178 SetLastError(0xdeadbeef);
1179 memset(&cpi, 0, sizeof(cpi));
1180 ret = GetCPInfoExA(CP_ACP, 0, &cpi);
1181 ok(ret, "GetCPInfoExA failed for lcid %04lx, error %ld\n", lcids[i].lcid, GetLastError());
1182 ok(cpi.CodePage == acp, "wrong codepage %u for lcid %04lx, should be %u\n", cpi.CodePage, lcids[i].lcid, acp);
1183
1184 /* WideCharToMultiByte - CP_ACP */
1186 ok(num == 7, "ret is %d (%04lx)\n", num, lcids[i].lcid);
1187
1188 /* MultiByteToWideChar - CP_ACP */
1189 num = MultiByteToWideChar(CP_ACP, 0, "foobar", -1, NULL, 0);
1190 ok(num == 7, "ret is %d (%04lx)\n", num, lcids[i].lcid);
1191
1192 /* GetCPInfoEx/GetCPInfo - CP_THREAD_ACP */
1193 SetLastError(0xdeadbeef);
1194 memset(&cpi, 0, sizeof(cpi));
1195 ret = GetCPInfoExA(CP_THREAD_ACP, 0, &cpi);
1196 ok(ret, "GetCPInfoExA failed for lcid %04lx, error %ld\n", lcids[i].lcid, GetLastError());
1197 if (lcids[i].threadcp)
1198 ok(cpi.CodePage == lcids[i].threadcp || cpi.CodePage == CP_UTF8 /* Win10 1809+ */,
1199 "wrong codepage %u for lcid %04lx, should be %u\n",
1200 cpi.CodePage, lcids[i].lcid, lcids[i].threadcp);
1201 else
1202 ok(cpi.CodePage == acp || cpi.CodePage == CP_UTF8 /* Win10 1809+ */,
1203 "wrong codepage %u for lcid %04lx, should be %u\n", cpi.CodePage, lcids[i].lcid, acp);
1204
1205 /* WideCharToMultiByte - CP_THREAD_ACP */
1207 ok(num == 7, "ret is %d (%04lx)\n", num, lcids[i].lcid);
1208
1209 /* MultiByteToWideChar - CP_THREAD_ACP */
1210 num = MultiByteToWideChar(CP_THREAD_ACP, 0, "foobar", -1, NULL, 0);
1211 ok(num == 7, "ret is %d (%04lx)\n", num, lcids[i].lcid);
1212 }
1213
1214 /* IsDBCSLeadByteEx - locales without codepage */
1215 for (i = 0; i < ARRAY_SIZE(isleads_nocp); i++)
1216 {
1217 SetThreadLocale(isleads_nocp[i].lcid);
1218
1219 GetCPInfoExA(CP_THREAD_ACP, 0, &cpi);
1220 islead_default = IsDBCSLeadByteEx(cpi.CodePage, isleads_nocp[i].testchar);
1221 islead = IsDBCSLeadByteEx(CP_THREAD_ACP, isleads_nocp[i].testchar);
1222
1223 ok(islead == islead_default, "wrong islead %i for test char %x in lcid %04lx. should be %i\n",
1224 islead, isleads_nocp[i].testchar, isleads_nocp[i].lcid, islead_default);
1225 }
1226
1227 /* IsDBCSLeadByteEx - locales with codepage */
1228 for (i = 0; i < ARRAY_SIZE(isleads); i++)
1229 {
1230 SetThreadLocale(isleads[i].lcid);
1231
1232 GetCPInfoExA(CP_THREAD_ACP, 0, &cpi);
1233 islead = IsDBCSLeadByteEx(CP_THREAD_ACP, isleads[i].testchar);
1234 ok(islead == isleads[i].islead || (cpi.CodePage == CP_UTF8 && !islead),
1235 "wrong islead %i for test char %x in lcid %04lx. should be %i\n",
1236 islead, isleads[i].testchar, isleads[i].lcid, isleads[i].islead);
1237 }
1238
1240}
1241
1242static void test_dbcs_to_widechar(void)
1243{
1244 int i, count, count2;
1245 WCHAR wbuf[5];
1246 unsigned char buf[] = {0xbf, 0xb4, 0xc7, '\0', 'x'};
1247 static const DWORD flags[] = {
1250
1253
1256
1259 };
1260
1261 for (i = 0; i < ARRAY_SIZE(flags); ++i)
1262 {
1263 memset(wbuf, 0xff, sizeof(wbuf));
1264 count = MultiByteToWideChar(936, flags[i], (char*)&buf[0], 2, NULL, 0);
1265 count2 = MultiByteToWideChar(936, flags[i], (char*)&buf[0], 2, wbuf, count);
1266
1267 ok(count == 1, "%04lx: returned %d (expected 1)\n", flags[i], count);
1268 ok(count2 == 1, "%04lx: returned %d (expected 1)\n", flags[i], count2);
1269 ok(wbuf[0] == 0x770b, "%04lx: returned %04x (expected 770b)\n", flags[i], wbuf[0]);
1270 ok(wbuf[1] == 0xffff, "%04lx: returned %04x (expected ffff)\n", flags[i], wbuf[1]);
1271 }
1272
1273 for (i = 0; i < ARRAY_SIZE(flags); ++i)
1274 {
1275 memset(wbuf, 0xff, sizeof(wbuf));
1276 count = MultiByteToWideChar(936, flags[i], (char*)&buf[0], 3, NULL, 0);
1277 SetLastError( 0xdeadbeef );
1278 count2 = MultiByteToWideChar(936, flags[i], (char*)&buf[0], 3, wbuf, count);
1279
1281 {
1282 ok(count == 0, "%04lx: returned %d (expected 0)\n", flags[i], count);
1283 ok(count2 == 0, "%04lx: returned %d (expected 0)\n", flags[i], count2);
1284 ok(GetLastError() == ERROR_NO_UNICODE_TRANSLATION, "%04lx: returned %ld (expected %d)\n",
1286 }
1287 else
1288 {
1289 ok(count == 2, "%04lx: returned %d (expected 2)\n", flags[i], count);
1290 ok(count2 == 2, "%04lx: returned %d (expected 2)\n", flags[i], count2);
1291 ok(wbuf[0] == 0x770b, "%04lx: returned %04x (expected 770b)\n", flags[i], wbuf[0]);
1292 ok(wbuf[1] == 0x003f || broken(wbuf[1] == 0), /*windows xp*/
1293 "%04lx: wrong wide char: %04x\n", flags[i], wbuf[1]);
1294 ok(wbuf[2] == 0xffff, "%04lx: returned %04x (expected ffff)\n", flags[i], wbuf[2]);
1295 }
1296 }
1297
1298 /* src ends with null character */
1299 for (i = 0; i < ARRAY_SIZE(flags); ++i)
1300 {
1301 memset(wbuf, 0xff, sizeof(wbuf));
1302 count = MultiByteToWideChar(936, flags[i], (char*)&buf[0], 4, NULL, 0);
1303 SetLastError( 0xdeadbeef );
1304 count2 = MultiByteToWideChar(936, flags[i], (char*)&buf[0], 4, wbuf, count);
1305 ok(count == count2, "%04lx: returned %d (expected %d)\n", flags[i], count2, count);
1306
1308 {
1309 ok(count == 0, "%04lx: returned %d (expected 0)\n", flags[i], count);
1310 ok(GetLastError() == ERROR_NO_UNICODE_TRANSLATION, "%04lx: returned %ld (expected %d)\n",
1312 }
1313 else
1314 {
1315 WCHAR wbuf_ok[] = { 0x770b, 0x003f, '\0', 0xffff };
1316 WCHAR wbuf_broken[] = { 0x770b, '\0', 0xffff, 0xffff };
1317 ok(count == 3 || broken(count == 2 /*windows xp*/),
1318 "%04lx: returned %d (expected 3)\n", flags[i], count);
1319 ok(!memcmp(wbuf, wbuf_ok, sizeof(wbuf_ok))
1320 || broken(!memcmp(wbuf, wbuf_broken, sizeof(wbuf_broken))),
1321 "%04lx: returned %04x %04x %04x %04x (expected %04x %04x %04x %04x)\n",
1322 flags[i], wbuf[0], wbuf[1], wbuf[2], wbuf[3],
1323 wbuf_ok[0], wbuf_ok[1], wbuf_ok[2], wbuf_ok[3]);
1324 }
1325 }
1326
1327 /* src has null character, but not ends with it */
1328 for (i = 0; i < ARRAY_SIZE(flags); ++i)
1329 {
1330 memset(wbuf, 0xff, sizeof(wbuf));
1331 count = MultiByteToWideChar(936, flags[i], (char*)&buf[0], 5, NULL, 0);
1332 SetLastError( 0xdeadbeef );
1333 count2 = MultiByteToWideChar(936, flags[i], (char*)&buf[0], 5, wbuf, count);
1334 ok(count == count2, "%04lx: returned %d (expected %d)\n", flags[i], count2, count);
1335
1337 {
1338 ok(count == 0, "%04lx: returned %d (expected 0)\n", flags[i], count);
1339 ok(GetLastError() == ERROR_NO_UNICODE_TRANSLATION, "%04lx: returned %ld (expected %d)\n",
1341 }
1342 else
1343 {
1344 WCHAR wbuf_ok[] = { 0x770b, 0x003f, '\0', 'x', 0xffff };
1345 WCHAR wbuf_broken[] = { 0x770b, '\0', 'x', 0xffff, 0xffff };
1346 ok(count == 4 || broken(count == 3),
1347 "%04lx: returned %d (expected 4)\n", flags[i], count);
1348 ok(!memcmp(wbuf, wbuf_ok, sizeof(wbuf_ok))
1349 || broken(!memcmp(wbuf, wbuf_broken, sizeof(wbuf_broken))),
1350 "%04lx: returned %04x %04x %04x %04x %04x (expected %04x %04x %04x %04x %04x)\n",
1351 flags[i], wbuf[0], wbuf[1], wbuf[2], wbuf[3], wbuf[4],
1352 wbuf_ok[0], wbuf_ok[1], wbuf_ok[2], wbuf_ok[3], wbuf_ok[4]);
1353 }
1354 }
1355}
1356
1358{
1359 BOOL bUsedDefaultChar;
1360
1367
1368 /* WideCharToMultiByte has two code paths, test both here */
1370 test_string_conversion(&bUsedDefaultChar);
1371
1374
1376 test_threadcp();
1377
1379}
static int used
Definition: adh-main.c:39
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define broken(x)
Definition: atltest.h:178
#define START_TEST(x)
Definition: atltest.h:75
#define ARRAY_SIZE(A)
Definition: main.h:20
static void test_threadcp(void)
Definition: codepage.c:1097
static const WCHAR foobarW[]
Definition: codepage.c:32
static void test_other_invalid_parameters(void)
Definition: codepage.c:209
static void test_undefined_byte_char(void)
Definition: codepage.c:1044
static void test_negative_source_length(void)
Definition: codepage.c:122
static const char foobarA[]
Definition: codepage.c:31
static void test_null_source(void)
Definition: codepage.c:102
static void test_utf7_decoding(void)
Definition: codepage.c:760
static void test_destination_buffer(void)
Definition: codepage.c:34
#define LONGBUFLEN
Definition: codepage.c:150
static void test_negative_dest_length(void)
Definition: codepage.c:151
static void test_utf7_encoding(void)
Definition: codepage.c:509
static void test_overlapped_buffers(void)
Definition: codepage.c:320
static void test_dbcs_to_widechar(void)
Definition: codepage.c:1242
static void test_string_conversion(LPBOOL bUsedDefaultChar)
Definition: codepage.c:345
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define CP_ACP
Definition: compat.h:109
#define SetLastError(x)
Definition: compat.h:752
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
#define WideCharToMultiByte
Definition: compat.h:111
#define MultiByteToWideChar
Definition: compat.h:110
LCID WINAPI GetThreadLocale(void)
Definition: locale.c:2803
BOOL WINAPI SetThreadLocale(LCID lcid)
Definition: locale.c:2822
UINT WINAPI GetACP(void)
Definition: locale.c:2023
BOOL WINAPI IsValidCodePage(UINT codepage)
Definition: locale.c:2081
int WINAPI lstrcmpW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4246
INT WINAPI GetLocaleInfoA(LCID lcid, LCTYPE lctype, LPSTR buffer, INT len)
Definition: locale.c:1609
int WINAPI lstrcmpA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4198
BOOL WINAPI IsDBCSLeadByteEx(UINT codepage, BYTE testchar)
Definition: locale.c:2106
BOOL WINAPI GetCPInfoExA(UINT codepage, DWORD dwFlags, LPCPINFOEXA cpinfo)
Definition: locale.c:2204
LCID lcid
Definition: locale.c:5656
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2802
#define INT_MAX
Definition: limits.h:26
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
_ACRTIMP int __cdecl strncmp(const char *, const char *, size_t)
Definition: string.c:3330
return ret
Definition: mutex.c:146
#define FillMemory(BUF, SIZ, MASK)
Definition: strucsup.c:31
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLenum src
Definition: glext.h:6340
GLuint buffer
Definition: glext.h:5915
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum GLenum dst
Definition: glext.h:6340
GLbitfield flags
Definition: glext.h:7161
GLuint GLuint num
Definition: glext.h:9618
GLenum GLsizei len
Definition: glext.h:6722
GLenum GLenum GLenum input
Definition: glext.h:9031
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define MB_COMPOSITE
Definition: unicode.h:40
#define WC_COMPOSITECHECK
Definition: unicode.h:43
#define MB_USEGLYPHCHARS
Definition: unicode.h:42
#define MB_ERR_INVALID_CHARS
Definition: unicode.h:41
POINT cp
Definition: magnifier.c:59
#define ZeroMemory
Definition: minwinbase.h:31
BOOL * LPBOOL
Definition: minwindef.h:138
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static struct test_info tests[]
#define sprintf
Definition: sprintf.c:45
static DWORD GLE
Definition: registry.c:38
BOOL expected
Definition: store.c:2000
static UINT UINT last
Definition: font.c:45
static DWORD LPDWORD LPCSTR DWORD srclen
Definition: directory.c:52
static DWORD dstlen
Definition: directory.c:51
WCHAR strW[12]
Definition: clipboard.c:2025
char strA[12]
Definition: clipboard.c:2024
unsigned int UINT
Definition: ndis.h:50
#define SORT_DEFAULT
#define MAKELCID(lgid, srtid)
#define err(...)
#define test
Definition: rosglue.h:37
#define wine_dbgstr_wn
Definition: testlist.c:2
const WCHAR * str
#define LANG_HINDI
Definition: nls.h:68
#define SUBLANG_JAPANESE_JAPAN
Definition: nls.h:271
#define SUBLANG_HINDI_INDIA
Definition: nls.h:261
#define MAKELANGID(p, s)
Definition: nls.h:15
#define LANG_GEORGIAN
Definition: nls.h:61
#define LANG_ENGLISH
Definition: nls.h:52
#define SUBLANG_RUSSIAN_RUSSIA
Definition: nls.h:315
#define SUBLANG_CHINESE_SIMPLIFIED
Definition: nls.h:209
#define LANG_RUSSIAN
Definition: nls.h:113
#define LANG_CHINESE
Definition: nls.h:42
DWORD LCID
Definition: nls.h:13
#define CP_UTF8
Definition: nls.h:20
#define LANG_JAPANESE
Definition: nls.h:76
#define SUBLANG_GEORGIAN_GEORGIA
Definition: nls.h:250
#define SUBLANG_ENGLISH_US
Definition: nls.h:222
strcpy
Definition: string.h:131
#define memset(x, y, z)
Definition: compat.h:39
_In_ size_t const maxsize
Definition: strftime.cpp:120
UINT CodePage
Definition: winnls.h:659
int32_t INT
Definition: typedefs.h:58
char mbs[5]
wchar_t dbwcs[3]
char mbc
wchar_t wc1
wchar_t wcs[5]
wchar_t wc2
int codepage
Definition: win_iconv.c:156
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define ERROR_NO_UNICODE_TRANSLATION
Definition: winerror.h:973
#define ERROR_INVALID_FLAGS
Definition: winerror.h:907
#define CP_THREAD_ACP
Definition: winnls.h:251
#define CP_SYMBOL
Definition: winnls.h:252
#define CP_UTF7
Definition: winnls.h:253
#define MB_PRECOMPOSED
Definition: winnls.h:299
#define LOCALE_IDEFAULTANSICODEPAGE
Definition: winnls.h:45
const char * LPCSTR
Definition: xmlstorage.h:183
__wchar_t WCHAR
Definition: xmlstorage.h:180
char * LPSTR
Definition: xmlstorage.h:182
unsigned char BYTE
Definition: xxhash.c:193