4
#include <winpr/error.h>
5
#include <winpr/windows.h>
7
#if defined(WIN32) || defined(WIN64)
8
#ifndef __LITTLE_ENDIAN
9
#define __LITTLE_ENDIAN 1234
10
#define __BIG_ENDIAN 4321
13
#define __BYTE_ORDER __LITTLE_ENDIAN
21
static BYTE c_cedilla_UTF8[] = "\xC3\xA7\x00";
22
static BYTE c_cedilla_UTF16[] = "\xE7\x00\x00\x00";
23
static int c_cedilla_cchWideChar = 2;
24
static int c_cedilla_cbMultiByte = 3;
28
static BYTE en_Hello_UTF8[] = "Hello\0";
29
static BYTE en_Hello_UTF16[] = "\x48\x00\x65\x00\x6C\x00\x6C\x00\x6F\x00\x00\x00";
30
static int en_Hello_cchWideChar = 6;
31
static int en_Hello_cbMultiByte = 6;
33
static BYTE en_HowAreYou_UTF8[] = "How are you?\0";
34
static BYTE en_HowAreYou_UTF16[] = "\x48\x00\x6F\x00\x77\x00\x20\x00\x61\x00\x72\x00\x65\x00\x20\x00"
35
"\x79\x00\x6F\x00\x75\x00\x3F\x00\x00\x00";
36
static int en_HowAreYou_cchWideChar = 13;
37
static int en_HowAreYou_cbMultiByte = 13;
41
static BYTE fr_Hello_UTF8[] = "Allo\0";
42
static BYTE fr_Hello_UTF16[] = "\x41\x00\x6C\x00\x6C\x00\x6F\x00\x00\x00";
43
static int fr_Hello_cchWideChar = 5;
44
static int fr_Hello_cbMultiByte = 5;
46
static BYTE fr_HowAreYou_UTF8[] = "\x43\x6F\x6D\x6D\x65\x6E\x74\x20\xC3\xA7\x61\x20\x76\x61\x3F\x00";
47
static BYTE fr_HowAreYou_UTF16[] = "\x43\x00\x6F\x00\x6D\x00\x6D\x00\x65\x00\x6E\x00\x74\x00\x20\x00"
48
"\xE7\x00\x61\x00\x20\x00\x76\x00\x61\x00\x3F\x00\x00\x00";
49
static int fr_HowAreYou_cchWideChar = 15;
50
static int fr_HowAreYou_cbMultiByte = 16;
54
static BYTE ru_Hello_UTF8[] = "\xD0\x97\xD0\xB4\xD0\xBE\xD1\x80\xD0\xBE\xD0\xB2\xD0\xBE\x00";
55
static BYTE ru_Hello_UTF16[] = "\x17\x04\x34\x04\x3E\x04\x40\x04\x3E\x04\x32\x04\x3E\x04\x00\x00";
56
static int ru_Hello_cchWideChar = 8;
57
static int ru_Hello_cbMultiByte = 15;
59
static BYTE ru_HowAreYou_UTF8[] = "\xD0\x9A\xD0\xB0\xD0\xBA\x20\xD0\xB4\xD0\xB5\xD0\xBB\xD0\xB0\x3F\x00";
60
static BYTE ru_HowAreYou_UTF16[] = "\x1A\x04\x30\x04\x3A\x04\x20\x00\x34\x04\x35\x04\x3B\x04\x30\x04"
62
static int ru_HowAreYou_cchWideChar = 10;
63
static int ru_HowAreYou_cbMultiByte = 17;
67
static BYTE ar_Hello_UTF8[] = "\xD8\xA7\xD9\x84\xD8\xB3\xD9\x84\xD8\xA7\xD9\x85\x20\xD8\xB9\xD9"
68
"\x84\xD9\x8A\xD9\x83\xD9\x85\x00";
69
static BYTE ar_Hello_UTF16[] = "\x27\x06\x44\x06\x33\x06\x44\x06\x27\x06\x45\x06\x20\x00\x39\x06"
70
"\x44\x06\x4A\x06\x43\x06\x45\x06\x00\x00";
71
static int ar_Hello_cchWideChar = 13;
72
static int ar_Hello_cbMultiByte = 24;
74
static BYTE ar_HowAreYou_UTF8[] = "\xD9\x83\xD9\x8A\xD9\x81\x20\xD8\xAD\xD8\xA7\xD9\x84\xD9\x83\xD8"
76
static BYTE ar_HowAreYou_UTF16[] = "\x43\x06\x4A\x06\x41\x06\x20\x00\x2D\x06\x27\x06\x44\x06\x43\x06"
78
static int ar_HowAreYou_cchWideChar = 10;
79
static int ar_HowAreYou_cbMultiByte = 18;
83
static BYTE ch_Hello_UTF8[] = "\xE4\xBD\xA0\xE5\xA5\xBD\x00";
84
static BYTE ch_Hello_UTF16[] = "\x60\x4F\x7D\x59\x00\x00";
85
static int ch_Hello_cchWideChar = 3;
86
static int ch_Hello_cbMultiByte = 7;
88
static BYTE ch_HowAreYou_UTF8[] = "\xE4\xBD\xA0\xE5\xA5\xBD\xE5\x90\x97\x00";
89
static BYTE ch_HowAreYou_UTF16[] = "\x60\x4F\x7D\x59\x17\x54\x00\x00";
90
static int ch_HowAreYou_cchWideChar = 4;
91
static int ch_HowAreYou_cbMultiByte = 10;
93
void string_hexdump(BYTE* data, int length)
96
int i, line, offset = 0;
98
while (offset < length)
100
printf("%04x ", offset);
102
line = length - offset;
107
for (i = 0; i < line; i++)
108
printf("%02x ", p[i]);
113
for (i = 0; i < line; i++)
114
printf("%c", (p[i] >= 0x20 && p[i] < 0x7F) ? p[i] : '.');
123
void utf16_le_to_ne(BYTE *data, int length)
125
#if __BYTE_ORDER == __BIG_ENDIAN
128
for (i = 0; i < length / 2; i++)
133
data[i * 2] = data[i * 2 + 1];
139
int convert_utf8_to_utf16(BYTE* lpMultiByteStr, BYTE* expected_lpWideCharStr, int expected_cchWideChar)
144
LPWSTR lpWideCharStr;
146
cbMultiByte = strlen((char*) lpMultiByteStr);
147
cchWideChar = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) lpMultiByteStr, -1, NULL, 0);
149
printf("MultiByteToWideChar Input UTF8 String:\n");
150
string_hexdump(lpMultiByteStr, cbMultiByte + 1);
152
printf("MultiByteToWideChar required cchWideChar: %d\n", cchWideChar);
154
if (cchWideChar != expected_cchWideChar)
156
printf("MultiByteToWideChar unexpected cchWideChar: actual: %d expected: %d\n",
157
cchWideChar, expected_cchWideChar);
161
lpWideCharStr = (LPWSTR) malloc(cchWideChar * sizeof(WCHAR));
162
lpWideCharStr[cchWideChar - 1] = 0xFFFF; /* should be overwritten if null terminator is inserted properly */
163
length = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) lpMultiByteStr, cbMultiByte + 1, lpWideCharStr, cchWideChar);
165
printf("MultiByteToWideChar converted length (WCHAR): %d\n", length);
169
DWORD error = GetLastError();
170
printf("MultiByteToWideChar error: 0x%08lX\n", error);
174
if (length != expected_cchWideChar)
176
printf("MultiByteToWideChar unexpected converted length (WCHAR): actual: %d expected: %d\n",
177
length, expected_cchWideChar);
181
if (_wcscmp(lpWideCharStr, (WCHAR*) expected_lpWideCharStr) != 0)
183
printf("MultiByteToWideChar unexpected string:\n");
185
printf("UTF8 String:\n");
186
string_hexdump(lpMultiByteStr, cbMultiByte + 1);
188
printf("UTF16 String (actual):\n");
189
string_hexdump((BYTE*) lpWideCharStr, length * sizeof(WCHAR));
191
printf("UTF16 String (expected):\n");
192
string_hexdump((BYTE*) expected_lpWideCharStr, expected_cchWideChar * sizeof(WCHAR));
197
printf("MultiByteToWideChar Output UTF16 String:\n");
198
string_hexdump((BYTE*) lpWideCharStr, length * sizeof(WCHAR));
206
int convert_utf16_to_utf8(BYTE* lpWideCharStr, BYTE* expected_lpMultiByteStr, int expected_cbMultiByte)
211
LPSTR lpMultiByteStr = NULL;
213
cchWideChar = _wcslen((WCHAR*) lpWideCharStr);
214
cbMultiByte = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) lpWideCharStr, -1, NULL, 0, NULL, NULL);
216
printf("WideCharToMultiByte Input UTF16 String:\n");
217
string_hexdump(lpWideCharStr, (cchWideChar + 1) * sizeof(WCHAR));
219
printf("WideCharToMultiByte required cbMultiByte: %d\n", cbMultiByte);
221
if (cbMultiByte != expected_cbMultiByte)
223
printf("WideCharToMultiByte unexpected cbMultiByte: actual: %d expected: %d\n",
224
cbMultiByte, expected_cbMultiByte);
228
lpMultiByteStr = (LPSTR) malloc(cbMultiByte);
229
lpMultiByteStr[cbMultiByte - 1] = 0xFF; /* should be overwritten if null terminator is inserted properly */
230
length = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) lpWideCharStr, cchWideChar + 1, lpMultiByteStr, cbMultiByte, NULL, NULL);
232
printf("WideCharToMultiByte converted length (BYTE): %d\n", length);
236
DWORD error = GetLastError();
237
printf("WideCharToMultiByte error: 0x%08lX\n", error);
241
if (length != expected_cbMultiByte)
243
printf("WideCharToMultiByte unexpected converted length (BYTE): actual: %d expected: %d\n",
244
length, expected_cbMultiByte);
248
if (strcmp(lpMultiByteStr, (char*) expected_lpMultiByteStr) != 0)
250
printf("WideCharToMultiByte unexpected string:\n");
252
printf("UTF16 String:\n");
253
string_hexdump((BYTE*) lpWideCharStr, (cchWideChar + 1) * sizeof(WCHAR));
255
printf("UTF8 String (actual):\n");
256
string_hexdump((BYTE*) lpMultiByteStr, cbMultiByte);
258
printf("UTF8 String (expected):\n");
259
string_hexdump((BYTE*) expected_lpMultiByteStr, expected_cbMultiByte);
264
printf("WideCharToMultiByte Output UTF8 String:\n");
265
string_hexdump((BYTE*) lpMultiByteStr, cbMultiByte);
268
free(lpMultiByteStr);
273
int TestUnicodeConversion(int argc, char* argv[])
278
utf16_le_to_ne(c_cedilla_UTF16, sizeof(c_cedilla_UTF16));
280
if (convert_utf8_to_utf16(c_cedilla_UTF8, c_cedilla_UTF16, c_cedilla_cchWideChar) < 1)
283
if (convert_utf16_to_utf8(c_cedilla_UTF16, c_cedilla_UTF8, c_cedilla_cbMultiByte) < 1)
289
utf16_le_to_ne(en_Hello_UTF16, sizeof(en_Hello_UTF16));
290
utf16_le_to_ne(en_HowAreYou_UTF16, sizeof(en_HowAreYou_UTF16));
292
if (convert_utf8_to_utf16(en_Hello_UTF8, en_Hello_UTF16, en_Hello_cchWideChar) < 1)
294
if (convert_utf8_to_utf16(en_HowAreYou_UTF8, en_HowAreYou_UTF16, en_HowAreYou_cchWideChar) < 1)
297
if (convert_utf16_to_utf8(en_Hello_UTF16, en_Hello_UTF8, en_Hello_cbMultiByte) < 1)
299
if (convert_utf16_to_utf8(en_HowAreYou_UTF16, en_HowAreYou_UTF8, en_HowAreYou_cbMultiByte) < 1)
305
utf16_le_to_ne(fr_Hello_UTF16, sizeof(fr_Hello_UTF16));
306
utf16_le_to_ne(fr_HowAreYou_UTF16, sizeof(fr_HowAreYou_UTF16));
308
if (convert_utf8_to_utf16(fr_Hello_UTF8, fr_Hello_UTF16, fr_Hello_cchWideChar) < 1)
310
if (convert_utf8_to_utf16(fr_HowAreYou_UTF8, fr_HowAreYou_UTF16, fr_HowAreYou_cchWideChar) < 1)
313
if (convert_utf16_to_utf8(fr_Hello_UTF16, fr_Hello_UTF8, fr_Hello_cbMultiByte) < 1)
315
if (convert_utf16_to_utf8(fr_HowAreYou_UTF16, fr_HowAreYou_UTF8, fr_HowAreYou_cbMultiByte) < 1)
321
utf16_le_to_ne(ru_Hello_UTF16, sizeof(ru_Hello_UTF16));
322
utf16_le_to_ne(ru_HowAreYou_UTF16, sizeof(ru_HowAreYou_UTF16));
324
if (convert_utf8_to_utf16(ru_Hello_UTF8, ru_Hello_UTF16, ru_Hello_cchWideChar) < 1)
326
if (convert_utf8_to_utf16(ru_HowAreYou_UTF8, ru_HowAreYou_UTF16, ru_HowAreYou_cchWideChar) < 1)
329
if (convert_utf16_to_utf8(ru_Hello_UTF16, ru_Hello_UTF8, ru_Hello_cbMultiByte) < 1)
331
if (convert_utf16_to_utf8(ru_HowAreYou_UTF16, ru_HowAreYou_UTF8, ru_HowAreYou_cbMultiByte) < 1)
337
utf16_le_to_ne(ar_Hello_UTF16, sizeof(ar_Hello_UTF16));
338
utf16_le_to_ne(ar_HowAreYou_UTF16, sizeof(ar_HowAreYou_UTF16));
340
if (convert_utf8_to_utf16(ar_Hello_UTF8, ar_Hello_UTF16, ar_Hello_cchWideChar) < 1)
342
if (convert_utf8_to_utf16(ar_HowAreYou_UTF8, ar_HowAreYou_UTF16, ar_HowAreYou_cchWideChar) < 1)
345
if (convert_utf16_to_utf8(ar_Hello_UTF16, ar_Hello_UTF8, ar_Hello_cbMultiByte) < 1)
347
if (convert_utf16_to_utf8(ar_HowAreYou_UTF16, ar_HowAreYou_UTF8, ar_HowAreYou_cbMultiByte) < 1)
353
utf16_le_to_ne(ch_Hello_UTF16, sizeof(ch_Hello_UTF16));
354
utf16_le_to_ne(ch_HowAreYou_UTF16, sizeof(ch_HowAreYou_UTF16));
356
if (convert_utf8_to_utf16(ch_Hello_UTF8, ch_Hello_UTF16, ch_Hello_cchWideChar) < 1)
358
if (convert_utf8_to_utf16(ch_HowAreYou_UTF8, ch_HowAreYou_UTF16, ch_HowAreYou_cchWideChar) < 1)
361
if (convert_utf16_to_utf8(ch_Hello_UTF16, ch_Hello_UTF8, ch_Hello_cbMultiByte) < 1)
363
if (convert_utf16_to_utf8(ch_HowAreYou_UTF16, ch_HowAreYou_UTF8, ch_HowAreYou_cbMultiByte) < 1)