3 #include <winpr/wtypes.h>
5 #include <winpr/assert.h>
6 #include <winpr/error.h>
7 #include <winpr/print.h>
8 #include <winpr/windows.h>
10 #define TESTCASE_BUFFER_SIZE 8192
13 #define MIN(x, y) (((x) < (y)) ? (x) : (y))
26 static const testcase_t unit_testcases[] = {
27 {
"foo", 3, (
const WCHAR*)
"f\x00o\x00o\x00\x00\x00", 3 },
28 {
"foo", 4, (
const WCHAR*)
"f\x00o\x00o\x00\x00\x00", 4 },
29 {
"βπ
ΔΚ₯κ£Έπa", 19,
30 (
const WCHAR*)
"\x0a\x27\x3c\xd8\x85\xdf\x19\x01\xa5\x02\xf8\xa8\x05\xd8\xca\xdd\x61\x00\x00"
35 static void create_prefix(
char* prefix,
size_t prefixlen,
size_t buffersize, SSIZE_T rc,
36 SSIZE_T inputlen,
const testcase_t* test,
const char* fkt,
size_t line)
38 (void)_snprintf(prefix, prefixlen,
39 "[%s:%" PRIuz
"] '%s' [utf8: %" PRIuz
", utf16: %" PRIuz
"] buffersize: %" PRIuz
40 ", rc: %" PRIdz
", inputlen: %" PRIdz
":: ",
41 fkt, line, test->utf8, test->utf8len, test->utf16len, buffersize, rc, inputlen);
44 static BOOL check_short_buffer(
const char* prefix,
int rc,
size_t buffersize,
45 const testcase_t* test, BOOL utf8)
47 if ((rc > 0) && ((
size_t)rc <= buffersize))
50 size_t len = test->utf8len;
57 "%s length does not match buffersize: %" PRId32
" != %" PRIuz
58 ",but is large enough to hold result\n",
59 prefix, rc, buffersize);
62 const DWORD err = GetLastError();
63 if (err != ERROR_INSUFFICIENT_BUFFER)
67 "%s length does not match buffersize: %" PRId32
" != %" PRIuz
68 ", unexpected GetLastError() 0x08%" PRIx32
"\n",
69 prefix, rc, buffersize, err);
76 #define compare_utf16(what, buffersize, rc, inputlen, test) \
77 compare_utf16_int((what), (buffersize), (rc), (inputlen), (test), __func__, __LINE__)
78 static BOOL compare_utf16_int(
const WCHAR* what,
size_t buffersize, SSIZE_T rc, SSIZE_T inputlen,
79 const testcase_t* test,
const char* fkt,
size_t line)
81 char prefix[8192] = { 0 };
82 create_prefix(prefix, ARRAYSIZE(prefix), buffersize, rc, inputlen, test, fkt, line);
84 WINPR_ASSERT(what || (buffersize == 0));
87 const size_t welen = _wcsnlen(test->utf16, test->utf16len);
88 if (buffersize > welen)
90 if ((rc < 0) || ((
size_t)rc != welen))
93 "%s length does not match expectation: %" PRIdz
" != %" PRIuz
"\n",
100 if (!check_short_buffer(prefix, rc, buffersize, test, FALSE))
104 if ((rc > 0) && (buffersize > (size_t)rc))
106 const size_t wlen = _wcsnlen(what, buffersize);
107 if ((rc < 0) || (wlen > (
size_t)rc))
109 (void)fprintf(stderr,
"%s length does not match wcslen: %" PRIdz
" < %" PRIuz
"\n",
117 if (memcmp(test->utf16, what, rc *
sizeof(WCHAR)) != 0)
119 (void)fprintf(stderr,
"%s contents does not match expectations: TODO '%s' != '%s'\n",
120 prefix, test->utf8, test->utf8);
125 printf(
"%s success\n", prefix);
130 #define compare_utf8(what, buffersize, rc, inputlen, test) \
131 compare_utf8_int((what), (buffersize), (rc), (inputlen), (test), __func__, __LINE__)
132 static BOOL compare_utf8_int(
const char* what,
size_t buffersize, SSIZE_T rc, SSIZE_T inputlen,
133 const testcase_t* test,
const char* fkt,
size_t line)
135 char prefix[8192] = { 0 };
136 create_prefix(prefix, ARRAYSIZE(prefix), buffersize, rc, inputlen, test, fkt, line);
138 WINPR_ASSERT(what || (buffersize == 0));
141 const size_t slen = strnlen(test->utf8, test->utf8len);
142 if (buffersize > slen)
144 if ((rc < 0) || ((
size_t)rc != slen))
146 (void)fprintf(stderr,
147 "%s length does not match expectation: %" PRIdz
" != %" PRIuz
"\n",
154 if (!check_short_buffer(prefix, rc, buffersize, test, TRUE))
158 if ((rc > 0) && (buffersize > (size_t)rc))
160 const size_t wlen = strnlen(what, buffersize);
161 if (wlen != (
size_t)rc)
163 (void)fprintf(stderr,
"%s length does not match strnlen: %" PRIdz
" != %" PRIuz
"\n",
171 if (memcmp(test->utf8, what, rc) != 0)
173 (void)fprintf(stderr,
"%s contents does not match expectations: '%s' != '%s'\n", prefix,
179 printf(
"%s success\n", prefix);
184 static BOOL test_convert_to_utf16(
const testcase_t* test)
186 const size_t len[] = { TESTCASE_BUFFER_SIZE, test->utf16len, test->utf16len + 1,
187 test->utf16len - 1 };
188 const size_t max = test->utf16len > 0 ? ARRAYSIZE(len) : ARRAYSIZE(len) - 1;
190 const SSIZE_T rc2 = ConvertUtf8ToWChar(test->utf8, NULL, 0);
191 const size_t wlen = _wcsnlen(test->utf16, test->utf16len);
192 if ((rc2 < 0) || ((
size_t)rc2 != wlen))
194 char prefix[8192] = { 0 };
195 create_prefix(prefix, ARRAYSIZE(prefix), 0, rc2, -1, test, __func__, __LINE__);
196 (void)fprintf(stderr,
197 "%s ConvertUtf8ToWChar(%s, NULL, 0) expected %" PRIuz
", got %" PRIdz
"\n",
198 prefix, test->utf8, wlen, rc2);
201 for (
size_t x = 0; x < max; x++)
203 WCHAR buffer[TESTCASE_BUFFER_SIZE] = { 0 };
204 const SSIZE_T rc = ConvertUtf8ToWChar(test->utf8, buffer, len[x]);
205 if (!compare_utf16(buffer, len[x], rc, -1, test))
212 static BOOL test_convert_to_utf16_n(
const testcase_t* test)
214 const size_t len[] = { TESTCASE_BUFFER_SIZE, test->utf16len, test->utf16len + 1,
215 test->utf16len - 1 };
216 const size_t max = test->utf16len > 0 ? ARRAYSIZE(len) : ARRAYSIZE(len) - 1;
218 const SSIZE_T rc2 = ConvertUtf8NToWChar(test->utf8, test->utf8len, NULL, 0);
219 const size_t wlen = _wcsnlen(test->utf16, test->utf16len);
220 if ((rc2 < 0) || ((
size_t)rc2 != wlen))
222 char prefix[8192] = { 0 };
223 create_prefix(prefix, ARRAYSIZE(prefix), 0, rc2, test->utf8len, test, __func__, __LINE__);
224 (void)fprintf(stderr,
225 "%s ConvertUtf8NToWChar(%s, %" PRIuz
", NULL, 0) expected %" PRIuz
226 ", got %" PRIdz
"\n",
227 prefix, test->utf8, test->utf8len, wlen, rc2);
231 for (
size_t x = 0; x < max; x++)
233 const size_t ilen[] = { TESTCASE_BUFFER_SIZE, test->utf8len, test->utf8len + 1,
235 const size_t imax = test->utf8len > 0 ? ARRAYSIZE(ilen) : ARRAYSIZE(ilen) - 1;
237 for (
size_t y = 0; y < imax; y++)
239 WCHAR buffer[TESTCASE_BUFFER_SIZE] = { 0 };
240 SSIZE_T rc = ConvertUtf8NToWChar(test->utf8, ilen[x], buffer, len[x]);
241 if (!compare_utf16(buffer, len[x], rc, ilen[x], test))
248 static BOOL test_convert_to_utf8(
const testcase_t* test)
250 const size_t len[] = { TESTCASE_BUFFER_SIZE, test->utf8len, test->utf8len + 1,
252 const size_t max = test->utf8len > 0 ? ARRAYSIZE(len) : ARRAYSIZE(len) - 1;
254 const SSIZE_T rc2 = ConvertWCharToUtf8(test->utf16, NULL, 0);
255 const size_t wlen = strnlen(test->utf8, test->utf8len);
256 if ((rc2 < 0) || ((
size_t)rc2 != wlen))
258 char prefix[8192] = { 0 };
259 create_prefix(prefix, ARRAYSIZE(prefix), 0, rc2, -1, test, __func__, __LINE__);
260 (void)fprintf(stderr,
261 "%s ConvertWCharToUtf8(%s, NULL, 0) expected %" PRIuz
", got %" PRIdz
"\n",
262 prefix, test->utf8, wlen, rc2);
266 for (
size_t x = 0; x < max; x++)
268 char buffer[TESTCASE_BUFFER_SIZE] = { 0 };
269 SSIZE_T rc = ConvertWCharToUtf8(test->utf16, buffer, len[x]);
270 if (!compare_utf8(buffer, len[x], rc, -1, test))
277 static BOOL test_convert_to_utf8_n(
const testcase_t* test)
279 const size_t len[] = { TESTCASE_BUFFER_SIZE, test->utf8len, test->utf8len + 1,
281 const size_t max = test->utf8len > 0 ? ARRAYSIZE(len) : ARRAYSIZE(len) - 1;
283 const SSIZE_T rc2 = ConvertWCharNToUtf8(test->utf16, test->utf16len, NULL, 0);
284 const size_t wlen = strnlen(test->utf8, test->utf8len);
285 if ((rc2 < 0) || ((
size_t)rc2 != wlen))
287 char prefix[8192] = { 0 };
288 create_prefix(prefix, ARRAYSIZE(prefix), 0, rc2, test->utf16len, test, __func__, __LINE__);
289 (void)fprintf(stderr,
290 "%s ConvertWCharNToUtf8(%s, %" PRIuz
", NULL, 0) expected %" PRIuz
291 ", got %" PRIdz
"\n",
292 prefix, test->utf8, test->utf16len, wlen, rc2);
296 for (
size_t x = 0; x < max; x++)
298 const size_t ilen[] = { TESTCASE_BUFFER_SIZE, test->utf16len, test->utf16len + 1,
299 test->utf16len - 1 };
300 const size_t imax = test->utf16len > 0 ? ARRAYSIZE(ilen) : ARRAYSIZE(ilen) - 1;
302 for (
size_t y = 0; y < imax; y++)
304 char buffer[TESTCASE_BUFFER_SIZE] = { 0 };
305 SSIZE_T rc = ConvertWCharNToUtf8(test->utf16, ilen[x], buffer, len[x]);
306 if (!compare_utf8(buffer, len[x], rc, ilen[x], test))
314 static BOOL test_conversion(
const testcase_t* testcases,
size_t count)
316 WINPR_ASSERT(testcases || (count == 0));
317 for (
size_t x = 0; x < count; x++)
319 const testcase_t* test = &testcases[x];
321 printf(
"Running test case %" PRIuz
" [%s]\n", x, test->utf8);
322 if (!test_convert_to_utf16(test))
324 if (!test_convert_to_utf16_n(test))
326 if (!test_convert_to_utf8(test))
328 if (!test_convert_to_utf8_n(test))
334 #if defined(WITH_WINPR_DEPRECATED)
336 #define compare_win_utf16(what, buffersize, rc, inputlen, test) \
337 compare_win_utf16_int((what), (buffersize), (rc), (inputlen), (test), __func__, __LINE__)
338 static BOOL compare_win_utf16_int(
const WCHAR* what,
size_t buffersize,
int rc,
int inputlen,
339 const testcase_t* test,
const char* fkt,
size_t line)
341 char prefix[8192] = { 0 };
342 create_prefix(prefix, ARRAYSIZE(prefix), buffersize, rc, inputlen, test, fkt, line);
344 WINPR_ASSERT(what || (buffersize == 0));
347 BOOL isNullTerminated = TRUE;
349 isNullTerminated = strnlen(test->utf8, inputlen) < inputlen;
350 size_t welen = _wcsnlen(test->utf16, buffersize);
351 if (isNullTerminated)
354 if (buffersize >= welen)
356 if ((inputlen >= 0) && (rc > buffersize))
358 (void)fprintf(stderr,
"%s length does not match expectation: %d > %" PRIuz
"\n", prefix,
362 else if ((inputlen < 0) && (rc != welen))
364 (void)fprintf(stderr,
"%s length does not match expectation: %d != %" PRIuz
"\n",
371 if (!check_short_buffer(prefix, rc, buffersize, test, FALSE))
375 if ((rc > 0) && (buffersize > rc))
377 size_t wlen = _wcsnlen(what, buffersize);
378 if (isNullTerminated)
380 if ((inputlen >= 0) && (buffersize < rc))
382 (void)fprintf(stderr,
"%s length does not match wcslen: %d > %" PRIuz
"\n", prefix, rc,
386 else if ((inputlen < 0) && (welen > rc))
388 (void)fprintf(stderr,
"%s length does not match wcslen: %d < %" PRIuz
"\n", prefix, rc,
394 const size_t cmp_size = MIN(rc, test->utf16len) *
sizeof(WCHAR);
395 if (memcmp(test->utf16, what, cmp_size) != 0)
397 (void)fprintf(stderr,
"%s contents does not match expectations: TODO '%s' != '%s'\n",
398 prefix, test->utf8, test->utf8);
402 printf(
"%s success\n", prefix);
407 #define compare_win_utf8(what, buffersize, rc, inputlen, test) \
408 compare_win_utf8_int((what), (buffersize), (rc), (inputlen), (test), __func__, __LINE__)
409 static BOOL compare_win_utf8_int(
const char* what,
size_t buffersize, SSIZE_T rc, SSIZE_T inputlen,
410 const testcase_t* test,
const char* fkt,
size_t line)
412 char prefix[8192] = { 0 };
413 create_prefix(prefix, ARRAYSIZE(prefix), buffersize, rc, inputlen, test, fkt, line);
415 WINPR_ASSERT(what || (buffersize == 0));
418 BOOL isNullTerminated = TRUE;
420 isNullTerminated = _wcsnlen(test->utf16, inputlen) < inputlen;
422 size_t slen = strnlen(test->utf8, test->utf8len);
423 if (isNullTerminated)
426 if (buffersize > slen)
428 if ((inputlen >= 0) && (rc > buffersize))
430 (void)fprintf(stderr,
"%s length does not match expectation: %" PRIdz
" > %" PRIuz
"\n",
431 prefix, rc, buffersize);
434 else if ((inputlen < 0) && (rc != slen))
436 (void)fprintf(stderr,
437 "%s length does not match expectation: %" PRIdz
" != %" PRIuz
"\n",
444 if (!check_short_buffer(prefix, rc, buffersize, test, TRUE))
448 if ((rc > 0) && (buffersize > rc))
450 size_t wlen = strnlen(what, buffersize);
451 if (isNullTerminated)
456 (void)fprintf(stderr,
"%s length does not match wcslen: %" PRIdz
" < %" PRIuz
"\n",
462 const size_t cmp_size = MIN(test->utf8len, rc);
463 if (memcmp(test->utf8, what, cmp_size) != 0)
465 (void)fprintf(stderr,
"%s contents does not match expectations: '%s' != '%s'\n", prefix,
469 printf(
"%s success\n", prefix);
475 #if defined(WITH_WINPR_DEPRECATED)
476 static BOOL test_win_convert_to_utf16(
const testcase_t* test)
478 const size_t len[] = { TESTCASE_BUFFER_SIZE, test->utf16len, test->utf16len + 1,
479 test->utf16len - 1 };
480 const size_t max = test->utf16len > 0 ? ARRAYSIZE(len) : ARRAYSIZE(len) - 1;
482 const int rc2 = MultiByteToWideChar(CP_UTF8, 0, test->utf8, -1, NULL, 0);
483 const size_t wlen = _wcsnlen(test->utf16, test->utf16len);
486 char prefix[8192] = { 0 };
487 create_prefix(prefix, ARRAYSIZE(prefix), 0, rc2, -1, test, __func__, __LINE__);
488 (void)fprintf(stderr,
489 "%s MultiByteToWideChar(CP_UTF8, 0, %s, [-1], NULL, 0) expected %" PRIuz
491 prefix, test->utf8, wlen + 1, rc2);
494 for (
size_t x = 0; x < max; x++)
496 WCHAR buffer[TESTCASE_BUFFER_SIZE] = { 0 };
497 const int rc = MultiByteToWideChar(CP_UTF8, 0, test->utf8, -1, buffer, len[x]);
498 if (!compare_win_utf16(buffer, len[x], rc, -1, test))
505 static BOOL test_win_convert_to_utf16_n(
const testcase_t* test)
507 const size_t len[] = { TESTCASE_BUFFER_SIZE, test->utf16len, test->utf16len + 1,
508 test->utf16len - 1 };
509 const size_t max = test->utf16len > 0 ? ARRAYSIZE(len) : ARRAYSIZE(len) - 1;
511 BOOL isNullTerminated = strnlen(test->utf8, test->utf8len) < test->utf8len;
512 const int rc2 = MultiByteToWideChar(CP_UTF8, 0, test->utf8, test->utf8len, NULL, 0);
513 size_t wlen = _wcsnlen(test->utf16, test->utf16len);
514 if (isNullTerminated)
519 char prefix[8192] = { 0 };
520 create_prefix(prefix, ARRAYSIZE(prefix), 0, rc2, test->utf8len, test, __func__, __LINE__);
521 (void)fprintf(stderr,
522 "%s MultiByteToWideChar(CP_UTF8, 0, %s, %" PRIuz
", NULL, 0) expected %" PRIuz
524 prefix, test->utf8, test->utf8len, wlen, rc2);
528 for (
size_t x = 0; x < max; x++)
530 const size_t ilen[] = { TESTCASE_BUFFER_SIZE, test->utf8len, test->utf8len + 1,
532 const size_t imax = test->utf8len > 0 ? ARRAYSIZE(ilen) : ARRAYSIZE(ilen) - 1;
534 for (
size_t y = 0; y < imax; y++)
536 char mbuffer[TESTCASE_BUFFER_SIZE] = { 0 };
537 WCHAR buffer[TESTCASE_BUFFER_SIZE] = { 0 };
538 strncpy(mbuffer, test->utf8, test->utf8len);
539 const int rc = MultiByteToWideChar(CP_UTF8, 0, mbuffer, ilen[x], buffer, len[x]);
540 if (!compare_win_utf16(buffer, len[x], rc, ilen[x], test))
548 #if defined(WITH_WINPR_DEPRECATED)
549 static BOOL test_win_convert_to_utf8(
const testcase_t* test)
551 const size_t len[] = { TESTCASE_BUFFER_SIZE, test->utf8len, test->utf8len + 1,
553 const size_t max = test->utf8len > 0 ? ARRAYSIZE(len) : ARRAYSIZE(len) - 1;
555 const int rc2 = WideCharToMultiByte(CP_UTF8, 0, test->utf16, -1, NULL, 0, NULL, NULL);
556 const size_t wlen = strnlen(test->utf8, test->utf8len) + 1;
559 char prefix[8192] = { 0 };
560 create_prefix(prefix, ARRAYSIZE(prefix), 0, rc2, -1, test, __func__, __LINE__);
563 "%s WideCharToMultiByte(CP_UTF8, 0, %s, -1, NULL, 0, NULL, NULL) expected %" PRIuz
565 prefix, test->utf8, wlen, rc2);
569 for (
size_t x = 0; x < max; x++)
571 char buffer[TESTCASE_BUFFER_SIZE] = { 0 };
572 int rc = WideCharToMultiByte(CP_UTF8, 0, test->utf16, -1, buffer, len[x], NULL, NULL);
573 if (!compare_win_utf8(buffer, len[x], rc, -1, test))
580 static BOOL test_win_convert_to_utf8_n(
const testcase_t* test)
582 const size_t len[] = { TESTCASE_BUFFER_SIZE, test->utf8len, test->utf8len + 1,
584 const size_t max = test->utf8len > 0 ? ARRAYSIZE(len) : ARRAYSIZE(len) - 1;
586 const BOOL isNullTerminated = _wcsnlen(test->utf16, test->utf16len) < test->utf16len;
588 WideCharToMultiByte(CP_UTF8, 0, test->utf16, test->utf16len, NULL, 0, NULL, NULL);
589 size_t wlen = strnlen(test->utf8, test->utf8len);
590 if (isNullTerminated)
595 char prefix[8192] = { 0 };
596 create_prefix(prefix, ARRAYSIZE(prefix), 0, rc2, test->utf16len, test, __func__, __LINE__);
597 (void)fprintf(stderr,
598 "%s WideCharToMultiByte(CP_UTF8, 0, %s, %" PRIuz
599 ", NULL, 0, NULL, NULL) expected %" PRIuz
", got %d\n",
600 prefix, test->utf8, test->utf16len, wlen, rc2);
604 for (
size_t x = 0; x < max; x++)
606 const size_t ilen[] = { TESTCASE_BUFFER_SIZE, test->utf16len, test->utf16len + 1,
607 test->utf16len - 1 };
608 const size_t imax = test->utf16len > 0 ? ARRAYSIZE(ilen) : ARRAYSIZE(ilen) - 1;
610 for (
size_t y = 0; y < imax; y++)
612 WCHAR wbuffer[TESTCASE_BUFFER_SIZE] = { 0 };
613 char buffer[TESTCASE_BUFFER_SIZE] = { 0 };
614 memcpy(wbuffer, test->utf16, test->utf16len *
sizeof(WCHAR));
616 WideCharToMultiByte(CP_UTF8, 0, wbuffer, ilen[x], buffer, len[x], NULL, NULL);
617 if (!compare_win_utf8(buffer, len[x], rc, ilen[x], test))
625 static BOOL test_win_conversion(
const testcase_t* testcases,
size_t count)
627 WINPR_ASSERT(testcases || (count == 0));
628 for (
size_t x = 0; x < count; x++)
630 const testcase_t* test = &testcases[x];
632 printf(
"Running test case %" PRIuz
" [%s]\n", x, test->utf8);
633 if (!test_win_convert_to_utf16(test))
635 if (!test_win_convert_to_utf16_n(test))
637 if (!test_win_convert_to_utf8(test))
639 if (!test_win_convert_to_utf8_n(test))
646 #if defined(WITH_WINPR_DEPRECATED)
649 static BYTE c_cedilla_UTF8[] =
"\xC3\xA7\x00";
650 static BYTE c_cedilla_UTF16[] =
"\xE7\x00\x00\x00";
651 static int c_cedilla_cchWideChar = 2;
652 static int c_cedilla_cbMultiByte = 3;
656 static BYTE en_Hello_UTF8[] =
"Hello\0";
657 static BYTE en_Hello_UTF16[] =
"\x48\x00\x65\x00\x6C\x00\x6C\x00\x6F\x00\x00\x00";
658 static int en_Hello_cchWideChar = 6;
659 static int en_Hello_cbMultiByte = 6;
661 static BYTE en_HowAreYou_UTF8[] =
"How are you?\0";
662 static BYTE en_HowAreYou_UTF16[] =
663 "\x48\x00\x6F\x00\x77\x00\x20\x00\x61\x00\x72\x00\x65\x00\x20\x00"
664 "\x79\x00\x6F\x00\x75\x00\x3F\x00\x00\x00";
665 static int en_HowAreYou_cchWideChar = 13;
666 static int en_HowAreYou_cbMultiByte = 13;
670 static BYTE fr_Hello_UTF8[] =
"Allo\0";
671 static BYTE fr_Hello_UTF16[] =
"\x41\x00\x6C\x00\x6C\x00\x6F\x00\x00\x00";
672 static int fr_Hello_cchWideChar = 5;
673 static int fr_Hello_cbMultiByte = 5;
675 static BYTE fr_HowAreYou_UTF8[] =
676 "\x43\x6F\x6D\x6D\x65\x6E\x74\x20\xC3\xA7\x61\x20\x76\x61\x3F\x00";
677 static BYTE fr_HowAreYou_UTF16[] =
678 "\x43\x00\x6F\x00\x6D\x00\x6D\x00\x65\x00\x6E\x00\x74\x00\x20\x00"
679 "\xE7\x00\x61\x00\x20\x00\x76\x00\x61\x00\x3F\x00\x00\x00";
680 static int fr_HowAreYou_cchWideChar = 15;
681 static int fr_HowAreYou_cbMultiByte = 16;
685 static BYTE ru_Hello_UTF8[] =
"\xD0\x97\xD0\xB4\xD0\xBE\xD1\x80\xD0\xBE\xD0\xB2\xD0\xBE\x00";
686 static BYTE ru_Hello_UTF16[] =
"\x17\x04\x34\x04\x3E\x04\x40\x04\x3E\x04\x32\x04\x3E\x04\x00\x00";
687 static int ru_Hello_cchWideChar = 8;
688 static int ru_Hello_cbMultiByte = 15;
690 static BYTE ru_HowAreYou_UTF8[] =
691 "\xD0\x9A\xD0\xB0\xD0\xBA\x20\xD0\xB4\xD0\xB5\xD0\xBB\xD0\xB0\x3F\x00";
692 static BYTE ru_HowAreYou_UTF16[] =
693 "\x1A\x04\x30\x04\x3A\x04\x20\x00\x34\x04\x35\x04\x3B\x04\x30\x04"
695 static int ru_HowAreYou_cchWideChar = 10;
696 static int ru_HowAreYou_cbMultiByte = 17;
700 static BYTE ar_Hello_UTF8[] =
"\xD8\xA7\xD9\x84\xD8\xB3\xD9\x84\xD8\xA7\xD9\x85\x20\xD8\xB9\xD9"
701 "\x84\xD9\x8A\xD9\x83\xD9\x85\x00";
702 static BYTE ar_Hello_UTF16[] =
"\x27\x06\x44\x06\x33\x06\x44\x06\x27\x06\x45\x06\x20\x00\x39\x06"
703 "\x44\x06\x4A\x06\x43\x06\x45\x06\x00\x00";
704 static int ar_Hello_cchWideChar = 13;
705 static int ar_Hello_cbMultiByte = 24;
707 static BYTE ar_HowAreYou_UTF8[] =
"\xD9\x83\xD9\x8A\xD9\x81\x20\xD8\xAD\xD8\xA7\xD9\x84\xD9\x83\xD8"
709 static BYTE ar_HowAreYou_UTF16[] =
710 "\x43\x06\x4A\x06\x41\x06\x20\x00\x2D\x06\x27\x06\x44\x06\x43\x06"
712 static int ar_HowAreYou_cchWideChar = 10;
713 static int ar_HowAreYou_cbMultiByte = 18;
717 static BYTE ch_Hello_UTF8[] =
"\xE4\xBD\xA0\xE5\xA5\xBD\x00";
718 static BYTE ch_Hello_UTF16[] =
"\x60\x4F\x7D\x59\x00\x00";
719 static int ch_Hello_cchWideChar = 3;
720 static int ch_Hello_cbMultiByte = 7;
722 static BYTE ch_HowAreYou_UTF8[] =
"\xE4\xBD\xA0\xE5\xA5\xBD\xE5\x90\x97\x00";
723 static BYTE ch_HowAreYou_UTF16[] =
"\x60\x4F\x7D\x59\x17\x54\x00\x00";
724 static int ch_HowAreYou_cchWideChar = 4;
725 static int ch_HowAreYou_cbMultiByte = 10;
729 static BYTE ru_Administrator_lower[] =
"\xd0\x90\xd0\xb4\xd0\xbc\xd0\xb8\xd0\xbd\xd0\xb8\xd1\x81"
730 "\xd1\x82\xd1\x80\xd0\xb0\xd1\x82\xd0\xbe\xd1\x80\x00";
732 static BYTE ru_Administrator_upper[] =
"\xd0\x90\xd0\x94\xd0\x9c\xd0\x98\xd0\x9d\xd0\x98\xd0\xa1"
733 "\xd0\xa2\xd0\xa0\xd0\x90\xd0\xa2\xd0\x9e\xd0\xa0\x00";
735 static void string_hexdump(
const BYTE* data,
size_t length)
739 char* str = winpr_BinToHexString(data, length, TRUE);
743 while (offset < length)
745 const size_t diff = (length - offset) * 3;
746 WINPR_ASSERT(diff <= INT_MAX);
747 printf(
"%04" PRIxz
" %.*s\n", offset, (
int)diff, &str[offset]);
754 static int convert_utf8_to_utf16(BYTE* lpMultiByteStr, BYTE* expected_lpWideCharStr,
755 int expected_cchWideChar)
759 size_t cbMultiByte = 0;
761 LPWSTR lpWideCharStr = NULL;
763 cbMultiByte = strlen((
char*)lpMultiByteStr);
764 cchWideChar = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)lpMultiByteStr, -1, NULL, 0);
766 printf(
"MultiByteToWideChar Input UTF8 String:\n");
767 string_hexdump(lpMultiByteStr, cbMultiByte + 1);
769 printf(
"MultiByteToWideChar required cchWideChar: %d\n", cchWideChar);
771 if (cchWideChar != expected_cchWideChar)
773 printf(
"MultiByteToWideChar unexpected cchWideChar: actual: %d expected: %d\n", cchWideChar,
774 expected_cchWideChar);
778 lpWideCharStr = (LPWSTR)calloc((
size_t)cchWideChar,
sizeof(WCHAR));
781 printf(
"MultiByteToWideChar: unable to allocate memory for test\n");
784 lpWideCharStr[cchWideChar - 1] =
786 length = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)lpMultiByteStr, cbMultiByte + 1, lpWideCharStr,
789 printf(
"MultiByteToWideChar converted length (WCHAR): %d\n", length);
793 DWORD error = GetLastError();
794 printf(
"MultiByteToWideChar error: 0x%08" PRIX32
"\n", error);
798 if (length != expected_cchWideChar)
800 printf(
"MultiByteToWideChar unexpected converted length (WCHAR): actual: %d expected: %d\n",
801 length, expected_cchWideChar);
805 if (_wcscmp(lpWideCharStr, (WCHAR*)expected_lpWideCharStr) != 0)
807 printf(
"MultiByteToWideChar unexpected string:\n");
809 printf(
"UTF8 String:\n");
810 string_hexdump(lpMultiByteStr, cbMultiByte + 1);
812 printf(
"UTF16 String (actual):\n");
813 string_hexdump((BYTE*)lpWideCharStr, length *
sizeof(WCHAR));
815 printf(
"UTF16 String (expected):\n");
816 string_hexdump(expected_lpWideCharStr, expected_cchWideChar *
sizeof(WCHAR));
821 printf(
"MultiByteToWideChar Output UTF16 String:\n");
822 string_hexdump((BYTE*)lpWideCharStr, length *
sizeof(WCHAR));
833 #if defined(WITH_WINPR_DEPRECATED)
834 static int convert_utf16_to_utf8(BYTE* lpWideCharStr, BYTE* expected_lpMultiByteStr,
835 int expected_cbMultiByte)
841 LPSTR lpMultiByteStr = NULL;
843 cchWideChar = _wcslen((WCHAR*)lpWideCharStr);
844 cbMultiByte = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)lpWideCharStr, -1, NULL, 0, NULL, NULL);
846 printf(
"WideCharToMultiByte Input UTF16 String:\n");
847 string_hexdump(lpWideCharStr, (cchWideChar + 1) *
sizeof(WCHAR));
849 printf(
"WideCharToMultiByte required cbMultiByte: %d\n", cbMultiByte);
851 if (cbMultiByte != expected_cbMultiByte)
853 printf(
"WideCharToMultiByte unexpected cbMultiByte: actual: %d expected: %d\n", cbMultiByte,
854 expected_cbMultiByte);
858 lpMultiByteStr = (LPSTR)malloc(cbMultiByte);
861 printf(
"WideCharToMultiByte: unable to allocate memory for test\n");
864 lpMultiByteStr[cbMultiByte - 1] =
866 length = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)lpWideCharStr, cchWideChar + 1,
867 lpMultiByteStr, cbMultiByte, NULL, NULL);
869 printf(
"WideCharToMultiByte converted length (BYTE): %d\n", length);
873 DWORD error = GetLastError();
874 printf(
"WideCharToMultiByte error: 0x%08" PRIX32
"\n", error);
878 if (length != expected_cbMultiByte)
880 printf(
"WideCharToMultiByte unexpected converted length (BYTE): actual: %d expected: %d\n",
881 length, expected_cbMultiByte);
885 if (strcmp(lpMultiByteStr, (
char*)expected_lpMultiByteStr) != 0)
887 printf(
"WideCharToMultiByte unexpected string:\n");
889 printf(
"UTF16 String:\n");
890 string_hexdump(lpWideCharStr, (cchWideChar + 1) *
sizeof(WCHAR));
892 printf(
"UTF8 String (actual):\n");
893 string_hexdump((BYTE*)lpMultiByteStr, cbMultiByte);
895 printf(
"UTF8 String (expected):\n");
896 string_hexdump(expected_lpMultiByteStr, expected_cbMultiByte);
901 printf(
"WideCharToMultiByte Output UTF8 String:\n");
902 string_hexdump((BYTE*)lpMultiByteStr, cbMultiByte);
907 free(lpMultiByteStr);
913 #if defined(WITH_WINPR_DEPRECATED)
914 static BOOL test_unicode_uppercasing(BYTE* lower, BYTE* upper)
916 WCHAR* lowerW = NULL;
918 WCHAR* upperW = NULL;
921 lowerLength = ConvertToUnicode(CP_UTF8, 0, (LPSTR)lower, -1, &lowerW, 0);
922 upperLength = ConvertToUnicode(CP_UTF8, 0, (LPSTR)upper, -1, &upperW, 0);
924 CharUpperBuffW(lowerW, lowerLength);
926 if (_wcscmp(lowerW, upperW) != 0)
928 printf(
"Lowercase String:\n");
929 string_hexdump((BYTE*)lowerW, lowerLength * 2);
931 printf(
"Uppercase String:\n");
932 string_hexdump((BYTE*)upperW, upperLength * 2);
940 printf(
"success\n\n");
945 #if defined(WITH_WINPR_DEPRECATED)
946 static BOOL test_ConvertFromUnicode_wrapper(
void)
949 "\x52\x00\x49\x00\x43\x00\x48\x00\x20\x00\x54\x00\x45\x00\x58\x00\x54\x00\x20\x00\x46\x00"
950 "\x4f\x00\x52\x00\x4d\x00\x41\x00\x54\x00\x40\x00\x40\x00\x40\x00";
951 const BYTE src2[] =
"\x52\x00\x49\x00\x43\x00\x48\x00\x20\x00\x54\x00\x45\x00\x58\x00\x54\x00"
952 "\x20\x00\x46\x00\x4f\x00\x52\x00\x4d\x00\x41\x00\x54\x00\x00\x00";
954 const CHAR cmp0[] = {
'R',
'I',
'C',
'H',
' ',
'T',
'E',
'X',
'T',
955 ' ',
'F',
'O',
'R',
'M',
'A',
'T', 0 };
963 printf(
"Input UTF16 String:\n");
964 string_hexdump((
const BYTE*)src1, 19 *
sizeof(WCHAR));
966 i = ConvertFromUnicode(CP_UTF8, 0, (
const WCHAR*)src1, 16, &dst, 0, NULL, NULL);
969 (void)fprintf(stderr,
970 "ConvertFromUnicode failure A1: unexpectedly returned %d instead of 16\n", i);
975 (void)fprintf(stderr,
"ConvertFromUnicode failure A2: destination ist NULL\n");
978 if ((i = strlen(dst)) != 16)
980 (void)fprintf(stderr,
"ConvertFromUnicode failure A3: dst length is %d instead of 16\n", i);
983 if (strcmp(dst, cmp0))
985 (void)fprintf(stderr,
"ConvertFromUnicode failure A4: data mismatch\n");
988 printf(
"Output UTF8 String:\n");
989 string_hexdump((BYTE*)dst, i + 1);
996 printf(
"Input UTF16 String:\n");
997 string_hexdump((
const BYTE*)src2, (_wcslen((
const WCHAR*)src2) + 1) *
sizeof(WCHAR));
999 i = ConvertFromUnicode(CP_UTF8, 0, (
const WCHAR*)src2, -1, &dst, 0, NULL, NULL);
1002 (void)fprintf(stderr,
1003 "ConvertFromUnicode failure B1: unexpectedly returned %d instead of 17\n", i);
1008 (void)fprintf(stderr,
"ConvertFromUnicode failure B2: destination ist NULL\n");
1011 if ((i = strlen(dst)) != 16)
1013 (void)fprintf(stderr,
"ConvertFromUnicode failure B3: dst length is %d instead of 16\n", i);
1016 if (strcmp(dst, cmp0))
1018 (void)fprintf(stderr,
"ConvertFromUnicode failure B: data mismatch\n");
1021 printf(
"Output UTF8 String:\n");
1022 string_hexdump((BYTE*)dst, i + 1);
1027 printf(
"success\n\n");
1036 static BOOL test_ConvertToUnicode_wrapper(
void)
1039 const CHAR src1[] = {
'R',
'I',
'C',
'H',
' ',
'T',
'E',
'X',
'T',
' ',
1040 'F',
'O',
'R',
'M',
'A',
'T',
'@',
'@',
'@' };
1041 const CHAR src2[] = {
'R',
'I',
'C',
'H',
' ',
'T',
'E',
'X',
'T',
1042 ' ',
'F',
'O',
'R',
'M',
'A',
'T', 0 };
1043 const BYTE cmp0[] =
"\x52\x00\x49\x00\x43\x00\x48\x00\x20\x00\x54\x00\x45\x00\x58\x00\x54\x00"
1044 "\x20\x00\x46\x00\x4f\x00\x52\x00\x4d\x00\x41\x00\x54\x00\x00\x00";
1051 char name[] =
"someteststring";
1052 const BYTE cmp[] = {
's', 0,
'o', 0,
'm', 0,
'e', 0,
't', 0,
'e', 0,
's', 0,
't', 0,
1053 's', 0,
't', 0,
'r', 0,
'i', 0,
'n', 0,
'g', 0, 0, 0 };
1054 WCHAR xname[128] = { 0 };
1055 LPWSTR aname = NULL;
1056 LPWSTR wname = &xname[0];
1057 const size_t len = strnlen(name, ARRAYSIZE(name) - 1);
1058 ii = ConvertToUnicode(CP_UTF8, 0, name, len, &wname, ARRAYSIZE(xname));
1059 if (ii != (SSIZE_T)len)
1062 if (memcmp(wname, cmp,
sizeof(cmp)) != 0)
1065 ii = ConvertToUnicode(CP_UTF8, 0, name, len, &aname, 0);
1066 if (ii != (SSIZE_T)len)
1068 ii = memcmp(aname, cmp,
sizeof(cmp));
1078 printf(
"Input UTF8 String:\n");
1079 string_hexdump((
const BYTE*)src1, 19);
1081 ii = ConvertToUnicode(CP_UTF8, 0, src1, 16, &dst, 0);
1084 (void)fprintf(stderr,
1085 "ConvertToUnicode failure A1: unexpectedly returned %d instead of 16\n", ii);
1091 (void)fprintf(stderr,
"ConvertToUnicode failure A2: destination ist NULL\n");
1094 if ((i = _wcslen(dst)) != 16)
1096 (void)fprintf(stderr,
1097 "ConvertToUnicode failure A3: dst length is %" PRIuz
" instead of 16\n", i);
1100 if (_wcscmp(dst, (
const WCHAR*)cmp0))
1102 (void)fprintf(stderr,
"ConvertToUnicode failure A4: data mismatch\n");
1105 printf(
"Output UTF16 String:\n");
1106 string_hexdump((
const BYTE*)dst, (i + 1) *
sizeof(WCHAR));
1113 printf(
"Input UTF8 String:\n");
1114 string_hexdump((
const BYTE*)src2, strlen(src2) + 1);
1116 i = ConvertToUnicode(CP_UTF8, 0, src2, -1, &dst, 0);
1120 stderr,
"ConvertToUnicode failure B1: unexpectedly returned %" PRIuz
" instead of 17\n",
1126 (void)fprintf(stderr,
"ConvertToUnicode failure B2: destination ist NULL\n");
1129 if ((i = _wcslen(dst)) != 16)
1131 (void)fprintf(stderr,
1132 "ConvertToUnicode failure B3: dst length is %" PRIuz
" instead of 16\n", i);
1135 if (_wcscmp(dst, (
const WCHAR*)cmp0))
1137 (void)fprintf(stderr,
"ConvertToUnicode failure B: data mismatch\n");
1140 printf(
"Output UTF16 String:\n");
1141 string_hexdump((BYTE*)dst, (i + 1) * 2);
1146 printf(
"success\n\n");
1156 int TestUnicodeConversion(
int argc,
char* argv[])
1161 if (!test_conversion(unit_testcases, ARRAYSIZE(unit_testcases)))
1164 #if defined(WITH_WINPR_DEPRECATED)
1165 if (!test_win_conversion(unit_testcases, ARRAYSIZE(unit_testcases)))
1170 printf(
"Letters\n");
1172 if (convert_utf8_to_utf16(c_cedilla_UTF8, c_cedilla_UTF16, c_cedilla_cchWideChar) < 1)
1175 if (convert_utf16_to_utf8(c_cedilla_UTF16, c_cedilla_UTF8, c_cedilla_cbMultiByte) < 1)
1180 printf(
"English\n");
1182 if (convert_utf8_to_utf16(en_Hello_UTF8, en_Hello_UTF16, en_Hello_cchWideChar) < 1)
1184 if (convert_utf8_to_utf16(en_HowAreYou_UTF8, en_HowAreYou_UTF16, en_HowAreYou_cchWideChar) < 1)
1187 if (convert_utf16_to_utf8(en_Hello_UTF16, en_Hello_UTF8, en_Hello_cbMultiByte) < 1)
1189 if (convert_utf16_to_utf8(en_HowAreYou_UTF16, en_HowAreYou_UTF8, en_HowAreYou_cbMultiByte) < 1)
1196 if (convert_utf8_to_utf16(fr_Hello_UTF8, fr_Hello_UTF16, fr_Hello_cchWideChar) < 1)
1198 if (convert_utf8_to_utf16(fr_HowAreYou_UTF8, fr_HowAreYou_UTF16, fr_HowAreYou_cchWideChar) < 1)
1201 if (convert_utf16_to_utf8(fr_Hello_UTF16, fr_Hello_UTF8, fr_Hello_cbMultiByte) < 1)
1203 if (convert_utf16_to_utf8(fr_HowAreYou_UTF16, fr_HowAreYou_UTF8, fr_HowAreYou_cbMultiByte) < 1)
1208 printf(
"Russian\n");
1210 if (convert_utf8_to_utf16(ru_Hello_UTF8, ru_Hello_UTF16, ru_Hello_cchWideChar) < 1)
1212 if (convert_utf8_to_utf16(ru_HowAreYou_UTF8, ru_HowAreYou_UTF16, ru_HowAreYou_cchWideChar) < 1)
1215 if (convert_utf16_to_utf8(ru_Hello_UTF16, ru_Hello_UTF8, ru_Hello_cbMultiByte) < 1)
1217 if (convert_utf16_to_utf8(ru_HowAreYou_UTF16, ru_HowAreYou_UTF8, ru_HowAreYou_cbMultiByte) < 1)
1224 if (convert_utf8_to_utf16(ar_Hello_UTF8, ar_Hello_UTF16, ar_Hello_cchWideChar) < 1)
1226 if (convert_utf8_to_utf16(ar_HowAreYou_UTF8, ar_HowAreYou_UTF16, ar_HowAreYou_cchWideChar) < 1)
1229 if (convert_utf16_to_utf8(ar_Hello_UTF16, ar_Hello_UTF8, ar_Hello_cbMultiByte) < 1)
1231 if (convert_utf16_to_utf8(ar_HowAreYou_UTF16, ar_HowAreYou_UTF8, ar_HowAreYou_cbMultiByte) < 1)
1236 printf(
"Chinese\n");
1238 if (convert_utf8_to_utf16(ch_Hello_UTF8, ch_Hello_UTF16, ch_Hello_cchWideChar) < 1)
1240 if (convert_utf8_to_utf16(ch_HowAreYou_UTF8, ch_HowAreYou_UTF16, ch_HowAreYou_cchWideChar) < 1)
1243 if (convert_utf16_to_utf8(ch_Hello_UTF16, ch_Hello_UTF8, ch_Hello_cbMultiByte) < 1)
1245 if (convert_utf16_to_utf8(ch_HowAreYou_UTF16, ch_HowAreYou_UTF8, ch_HowAreYou_cbMultiByte) < 1)
1251 #if defined(WITH_WINPR_DEPRECATED)
1252 printf(
"Uppercasing\n");
1254 if (!test_unicode_uppercasing(ru_Administrator_lower, ru_Administrator_upper))
1259 #if defined(WITH_WINPR_DEPRECATED)
1260 printf(
"ConvertFromUnicode\n");
1262 if (!test_ConvertFromUnicode_wrapper())
1267 printf(
"ConvertToUnicode\n");
1269 if (!test_ConvertToUnicode_wrapper())