1c2c66affSColin Finck /*
2c2c66affSColin Finck * PROJECT: ReactOS API tests
3c2c66affSColin Finck * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4c2c66affSColin Finck * PURPOSE: Test for WideCharToMultiByte
5c2c66affSColin Finck * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
6c2c66affSColin Finck */
7c2c66affSColin Finck
8e00cc972SAmine Khaldi #include "precomp.h"
9c2c66affSColin Finck
10c2c66affSColin Finck #define ntv6(x) (LOBYTE(LOWORD(GetVersion())) >= 6 ? (x) : 0)
11c2c66affSColin Finck
12c2c66affSColin Finck static
13c2c66affSColin Finck VOID
Utf8Convert_(_In_ PCWSTR WideString,_In_ PCSTR ExpectedUtf8_2003,_In_ PCSTR ExpectedUtf8_Vista,_In_ BOOL IsInvalid,_In_ PCSTR File,_In_ INT Line)14c2c66affSColin Finck Utf8Convert_(
15c2c66affSColin Finck _In_ PCWSTR WideString,
16c2c66affSColin Finck _In_ PCSTR ExpectedUtf8_2003,
17c2c66affSColin Finck _In_ PCSTR ExpectedUtf8_Vista,
18c2c66affSColin Finck _In_ BOOL IsInvalid,
19c2c66affSColin Finck _In_ PCSTR File,
20c2c66affSColin Finck _In_ INT Line)
21c2c66affSColin Finck {
22*42d2d5ecSTimo Kreuzer int WideLen;
23*42d2d5ecSTimo Kreuzer int Utf8Len;
24c2c66affSColin Finck char Buffer[32];
25c2c66affSColin Finck int Ret;
26c2c66affSColin Finck ULONG i;
27c2c66affSColin Finck ULONG Error;
28c2c66affSColin Finck PCSTR ExpectedUtf8;
29c2c66affSColin Finck
30c2c66affSColin Finck ExpectedUtf8 = ntv6(1) ? ExpectedUtf8_Vista : ExpectedUtf8_2003;
31*42d2d5ecSTimo Kreuzer WideLen = lstrlenW(WideString);
32*42d2d5ecSTimo Kreuzer Utf8Len = lstrlenA(ExpectedUtf8);
33c2c66affSColin Finck
34c2c66affSColin Finck /* Get length only */
35c2c66affSColin Finck Ret = WideCharToMultiByte(CP_UTF8, 0, WideString, WideLen, NULL, 0, NULL, NULL);
36c2c66affSColin Finck ok_(File, Line)(Ret == Utf8Len, "Length check: Ret = %d\n", Ret);
37c2c66affSColin Finck
38c2c66affSColin Finck /* Get length including nul */
39c2c66affSColin Finck Ret = WideCharToMultiByte(CP_UTF8, 0, WideString, WideLen + 1, NULL, 0, NULL, NULL);
40c2c66affSColin Finck ok_(File, Line)(Ret == Utf8Len + 1, "Length check with null: Ret = %d\n", Ret);
41c2c66affSColin Finck
42c2c66affSColin Finck /* Convert, excluding null */
43c2c66affSColin Finck FillMemory(Buffer, sizeof(Buffer), 0x55);
44c2c66affSColin Finck Ret = WideCharToMultiByte(CP_UTF8, 0, WideString, WideLen, Buffer, sizeof(Buffer), NULL, NULL);
45c2c66affSColin Finck ok_(File, Line)(Ret == Utf8Len, "Convert: Ret = %d\n", Ret);
46c2c66affSColin Finck for (i = 0; i < Utf8Len; i++)
47c2c66affSColin Finck {
48c2c66affSColin Finck ok_(File, Line)(Buffer[i] == ExpectedUtf8[i], "Convert: Buffer[%lu] = 0x%x, expected 0x%x\n", i, (unsigned char)Buffer[i], (unsigned char)ExpectedUtf8[i]);
49c2c66affSColin Finck }
50c2c66affSColin Finck
51c2c66affSColin Finck /* Convert, including null */
52c2c66affSColin Finck FillMemory(Buffer, sizeof(Buffer), 0x55);
53c2c66affSColin Finck Ret = WideCharToMultiByte(CP_UTF8, 0, WideString, WideLen + 1, Buffer, sizeof(Buffer), NULL, NULL);
54c2c66affSColin Finck ok_(File, Line)(Ret == Utf8Len + 1, "Convert with null: Ret = %d\n", Ret);
55c2c66affSColin Finck for (i = 0; i < Utf8Len + 1; i++)
56c2c66affSColin Finck {
57c2c66affSColin Finck ok_(File, Line)(Buffer[i] == ExpectedUtf8[i], "Convert with null: Buffer[%lu] = 0x%x, expected 0x%x\n", i, (unsigned char)Buffer[i], (unsigned char)ExpectedUtf8[i]);
58c2c66affSColin Finck }
59c2c66affSColin Finck
60c2c66affSColin Finck /* Get length, reject invalid */
61c2c66affSColin Finck SetLastError(0xfeedf00d);
62c2c66affSColin Finck Ret = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, WideString, WideLen + 1, NULL, 0, NULL, NULL);
63c2c66affSColin Finck Error = GetLastError();
64c2c66affSColin Finck if (!ntv6(1))
65c2c66affSColin Finck {
66c2c66affSColin Finck ok_(File, Line)(Ret == 0, "Length check, reject invalid, NT5: Ret = %d\n", Ret);
67c2c66affSColin Finck ok_(File, Line)(Error == ERROR_INVALID_FLAGS, "Length check, reject invalid, NT5: Error = %lu\n", Error);
68c2c66affSColin Finck }
69c2c66affSColin Finck else if (IsInvalid)
70c2c66affSColin Finck {
71c2c66affSColin Finck ok_(File, Line)(Ret == 0, "Length check, reject invalid: Ret = %d\n", Ret);
72c2c66affSColin Finck ok_(File, Line)(Error == ERROR_NO_UNICODE_TRANSLATION, "Length check, reject invalid: Error = %lu\n", Error);
73c2c66affSColin Finck }
74c2c66affSColin Finck else
75c2c66affSColin Finck {
76c2c66affSColin Finck ok_(File, Line)(Ret == Utf8Len + 1, "Length check, reject invalid: Ret = %d\n", Ret);
77c2c66affSColin Finck }
78c2c66affSColin Finck
79c2c66affSColin Finck /* Convert, reject invalid */
80c2c66affSColin Finck FillMemory(Buffer, sizeof(Buffer), 0x55);
81c2c66affSColin Finck SetLastError(0xfeedf00d);
82c2c66affSColin Finck Ret = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, WideString, WideLen + 1, Buffer, sizeof(Buffer), NULL, NULL);
83c2c66affSColin Finck Error = GetLastError();
84c2c66affSColin Finck if (!ntv6(1))
85c2c66affSColin Finck {
86c2c66affSColin Finck ok_(File, Line)(Ret == 0, "Convert, reject invalid, NT5: Ret = %d\n", Ret);
87c2c66affSColin Finck ok_(File, Line)(Error == ERROR_INVALID_FLAGS, "Convert, reject invalid, NT5: Error = %lu\n", Error);
88c2c66affSColin Finck }
89c2c66affSColin Finck else if (IsInvalid)
90c2c66affSColin Finck {
91c2c66affSColin Finck ok_(File, Line)(Ret == 0, "Convert, reject invalid: Ret = %d\n", Ret);
92c2c66affSColin Finck ok_(File, Line)(Error == ERROR_NO_UNICODE_TRANSLATION, "Convert, reject invalid: Error = %lu\n", Error);
93c2c66affSColin Finck for (i = 0; i < Utf8Len + 1; i++)
94c2c66affSColin Finck {
95c2c66affSColin Finck ok_(File, Line)(Buffer[i] == ExpectedUtf8[i], "Convert, reject invalid: Buffer[%lu] = 0x%x, expected 0x%x\n", i, (unsigned char)Buffer[i], (unsigned char)ExpectedUtf8[i]);
96c2c66affSColin Finck }
97c2c66affSColin Finck }
98c2c66affSColin Finck else
99c2c66affSColin Finck {
100c2c66affSColin Finck ok_(File, Line)(Ret == Utf8Len + 1, "Convert, reject invalid: Ret = %d\n", Ret);
101c2c66affSColin Finck for (i = 0; i < Utf8Len + 1; i++)
102c2c66affSColin Finck {
103c2c66affSColin Finck ok_(File, Line)(Buffer[i] == ExpectedUtf8[i], "Convert, reject invalid: Buffer[%lu] = 0x%x, expected 0x%x\n", i, (unsigned char)Buffer[i], (unsigned char)ExpectedUtf8[i]);
104c2c66affSColin Finck }
105c2c66affSColin Finck }
106c2c66affSColin Finck }
107c2c66affSColin Finck #define Utf8Convert(w, e, i) Utf8Convert_(w, e, e, i, __FILE__, __LINE__)
108c2c66affSColin Finck #define Utf8Convert_Vista(w, e, i, e2) Utf8Convert_(w, e, e2, i, __FILE__, __LINE__)
109c2c66affSColin Finck
110c2c66affSColin Finck static
111c2c66affSColin Finck VOID
TestUtf8(VOID)112c2c66affSColin Finck TestUtf8(VOID)
113c2c66affSColin Finck {
114c2c66affSColin Finck Utf8Convert(L"", "", FALSE);
115c2c66affSColin Finck
116c2c66affSColin Finck /* Various character ranges */
117c2c66affSColin Finck Utf8Convert(L"A", "A", FALSE);
118c2c66affSColin Finck Utf8Convert(L"\x007f", "\x7f", FALSE);
119c2c66affSColin Finck Utf8Convert(L"\x0080", "\xc2\x80", FALSE);
120c2c66affSColin Finck Utf8Convert(L"\x00ff", "\xc3\xbf", FALSE);
121c2c66affSColin Finck Utf8Convert(L"\x0100", "\xc4\x80", FALSE);
122c2c66affSColin Finck Utf8Convert(L"\x07ff", "\xdf\xbf", FALSE);
123c2c66affSColin Finck Utf8Convert(L"\x0800", "\xe0\xa0\x80", FALSE);
124c2c66affSColin Finck Utf8Convert(L"\xd7ff", "\xed\x9f\xbf", FALSE);
125c2c66affSColin Finck Utf8Convert(L"\xe000", "\xee\x80\x80", FALSE);
126c2c66affSColin Finck Utf8Convert(L"\xffff", "\xef\xbf\xbf", FALSE);
127c2c66affSColin Finck
128c2c66affSColin Finck /* surrogate pairs */
129c2c66affSColin Finck Utf8Convert(L"\xd800\xdc00", "\xf0\x90\x80\x80", FALSE); /* U+10000 */
130c2c66affSColin Finck Utf8Convert(L"\xd800\xdfff", "\xf0\x90\x8f\xbf", FALSE); /* U+103ff */
131c2c66affSColin Finck Utf8Convert(L"\xd801\xdc00", "\xf0\x90\x90\x80", FALSE); /* U+10400 */
132c2c66affSColin Finck Utf8Convert(L"\xdbff\xdfff", "\xf4\x8f\xbf\xbf", FALSE); /* U+10ffff */
133c2c66affSColin Finck
134c2c66affSColin Finck /* standalone lead surrogate becomes 0xfffd on Vista, goes through verbatim on 2003 */
135c2c66affSColin Finck Utf8Convert_Vista(L"\xd800", "\xed\xa0\x80", TRUE,
136c2c66affSColin Finck "\xef\xbf\xbd");
137c2c66affSColin Finck Utf8Convert_Vista(L"\xd800-", "\xed\xa0\x80-", TRUE,
138c2c66affSColin Finck "\xef\xbf\xbd-");
139c2c66affSColin Finck Utf8Convert_Vista(L"\xdbff", "\xed\xaf\xbf", TRUE,
140c2c66affSColin Finck "\xef\xbf\xbd");
141c2c66affSColin Finck Utf8Convert_Vista(L"\xdbff-", "\xed\xaf\xbf-", TRUE,
142c2c66affSColin Finck "\xef\xbf\xbd-");
143c2c66affSColin Finck
144c2c66affSColin Finck /* standalone trail surrogate becomes 0xfffd */
145c2c66affSColin Finck Utf8Convert_Vista(L"\xdc00", "\xed\xb0\x80", TRUE,
146c2c66affSColin Finck "\xef\xbf\xbd");
147c2c66affSColin Finck Utf8Convert_Vista(L"\xdc00-", "\xed\xb0\x80-", TRUE,
148c2c66affSColin Finck "\xef\xbf\xbd-");
149c2c66affSColin Finck Utf8Convert_Vista(L"\xdfff", "\xed\xbf\xbf", TRUE,
150c2c66affSColin Finck "\xef\xbf\xbd");
151c2c66affSColin Finck Utf8Convert_Vista(L"\xdfff-", "\xed\xbf\xbf-", TRUE,
152c2c66affSColin Finck "\xef\xbf\xbd-");
153c2c66affSColin Finck
154c2c66affSColin Finck /* Reverse surrogate pair */
155c2c66affSColin Finck Utf8Convert_Vista(L"\xdfff\xdbff", "\xed\xbf\xbf\xed\xaf\xbf", TRUE,
156c2c66affSColin Finck "\xef\xbf\xbd\xef\xbf\xbd");
157c2c66affSColin Finck
158c2c66affSColin Finck /* Byte order marks */
159c2c66affSColin Finck Utf8Convert(L"\xfeff", "\xef\xbb\xbf", FALSE);
160c2c66affSColin Finck Utf8Convert(L"\xfffe", "\xef\xbf\xbe", FALSE);
161c2c66affSColin Finck
162c2c66affSColin Finck /* canonically equivalent representations -- no normalization should happen */
163c2c66affSColin Finck Utf8Convert(L"\x1e09", "\xe1\xb8\x89", FALSE);
164c2c66affSColin Finck Utf8Convert(L"\x0107\x0327", "\xc4\x87\xcc\xa7", FALSE);
165c2c66affSColin Finck Utf8Convert(L"\x00e7\x0301", "\xc3\xa7\xcc\x81", FALSE);
166c2c66affSColin Finck Utf8Convert(L"\x0063\x0327\x0301", "\x63\xcc\xa7\xcc\x81", FALSE);
167c2c66affSColin Finck Utf8Convert(L"\x0063\x0301\x0327", "\x63\xcc\x81\xcc\xa7", FALSE);
168c2c66affSColin Finck }
169c2c66affSColin Finck
START_TEST(WideCharToMultiByte)170c2c66affSColin Finck START_TEST(WideCharToMultiByte)
171c2c66affSColin Finck {
172c2c66affSColin Finck TestUtf8();
173c2c66affSColin Finck }
174