2 * PROJECT: ReactOS API tests
3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Test for WideCharToMultiByte
5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
12 #define ntv6(x) (LOBYTE(LOWORD(GetVersion())) >= 6 ? (x) : 0)
17 _In_ PCWSTR WideString
,
18 _In_ PCSTR ExpectedUtf8_2003
,
19 _In_ PCSTR ExpectedUtf8_Vista
,
32 ExpectedUtf8
= ntv6(1) ? ExpectedUtf8_Vista
: ExpectedUtf8_2003
;
33 WideLen
= wcslen(WideString
);
34 Utf8Len
= strlen(ExpectedUtf8
);
37 Ret
= WideCharToMultiByte(CP_UTF8
, 0, WideString
, WideLen
, NULL
, 0, NULL
, NULL
);
38 ok_(File
, Line
)(Ret
== Utf8Len
, "Length check: Ret = %d\n", Ret
);
40 /* Get length including nul */
41 Ret
= WideCharToMultiByte(CP_UTF8
, 0, WideString
, WideLen
+ 1, NULL
, 0, NULL
, NULL
);
42 ok_(File
, Line
)(Ret
== Utf8Len
+ 1, "Length check with null: Ret = %d\n", Ret
);
44 /* Convert, excluding null */
45 FillMemory(Buffer
, sizeof(Buffer
), 0x55);
46 Ret
= WideCharToMultiByte(CP_UTF8
, 0, WideString
, WideLen
, Buffer
, sizeof(Buffer
), NULL
, NULL
);
47 ok_(File
, Line
)(Ret
== Utf8Len
, "Convert: Ret = %d\n", Ret
);
48 for (i
= 0; i
< Utf8Len
; i
++)
50 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
]);
53 /* Convert, including null */
54 FillMemory(Buffer
, sizeof(Buffer
), 0x55);
55 Ret
= WideCharToMultiByte(CP_UTF8
, 0, WideString
, WideLen
+ 1, Buffer
, sizeof(Buffer
), NULL
, NULL
);
56 ok_(File
, Line
)(Ret
== Utf8Len
+ 1, "Convert with null: Ret = %d\n", Ret
);
57 for (i
= 0; i
< Utf8Len
+ 1; i
++)
59 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
]);
62 /* Get length, reject invalid */
63 SetLastError(0xfeedf00d);
64 Ret
= WideCharToMultiByte(CP_UTF8
, WC_ERR_INVALID_CHARS
, WideString
, WideLen
+ 1, NULL
, 0, NULL
, NULL
);
65 Error
= GetLastError();
68 ok_(File
, Line
)(Ret
== 0, "Length check, reject invalid, NT5: Ret = %d\n", Ret
);
69 ok_(File
, Line
)(Error
== ERROR_INVALID_FLAGS
, "Length check, reject invalid, NT5: Error = %lu\n", Error
);
73 ok_(File
, Line
)(Ret
== 0, "Length check, reject invalid: Ret = %d\n", Ret
);
74 ok_(File
, Line
)(Error
== ERROR_NO_UNICODE_TRANSLATION
, "Length check, reject invalid: Error = %lu\n", Error
);
78 ok_(File
, Line
)(Ret
== Utf8Len
+ 1, "Length check, reject invalid: Ret = %d\n", Ret
);
81 /* Convert, reject invalid */
82 FillMemory(Buffer
, sizeof(Buffer
), 0x55);
83 SetLastError(0xfeedf00d);
84 Ret
= WideCharToMultiByte(CP_UTF8
, WC_ERR_INVALID_CHARS
, WideString
, WideLen
+ 1, Buffer
, sizeof(Buffer
), NULL
, NULL
);
85 Error
= GetLastError();
88 ok_(File
, Line
)(Ret
== 0, "Convert, reject invalid, NT5: Ret = %d\n", Ret
);
89 ok_(File
, Line
)(Error
== ERROR_INVALID_FLAGS
, "Convert, reject invalid, NT5: Error = %lu\n", Error
);
93 ok_(File
, Line
)(Ret
== 0, "Convert, reject invalid: Ret = %d\n", Ret
);
94 ok_(File
, Line
)(Error
== ERROR_NO_UNICODE_TRANSLATION
, "Convert, reject invalid: Error = %lu\n", Error
);
95 for (i
= 0; i
< Utf8Len
+ 1; i
++)
97 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
]);
102 ok_(File
, Line
)(Ret
== Utf8Len
+ 1, "Convert, reject invalid: Ret = %d\n", Ret
);
103 for (i
= 0; i
< Utf8Len
+ 1; i
++)
105 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
]);
109 #define Utf8Convert(w, e, i) Utf8Convert_(w, e, e, i, __FILE__, __LINE__)
110 #define Utf8Convert_Vista(w, e, i, e2) Utf8Convert_(w, e, e2, i, __FILE__, __LINE__)
116 Utf8Convert(L
"", "", FALSE
);
118 /* Various character ranges */
119 Utf8Convert(L
"A", "A", FALSE
);
120 Utf8Convert(L
"\x007f", "\x7f", FALSE
);
121 Utf8Convert(L
"\x0080", "\xc2\x80", FALSE
);
122 Utf8Convert(L
"\x00ff", "\xc3\xbf", FALSE
);
123 Utf8Convert(L
"\x0100", "\xc4\x80", FALSE
);
124 Utf8Convert(L
"\x07ff", "\xdf\xbf", FALSE
);
125 Utf8Convert(L
"\x0800", "\xe0\xa0\x80", FALSE
);
126 Utf8Convert(L
"\xd7ff", "\xed\x9f\xbf", FALSE
);
127 Utf8Convert(L
"\xe000", "\xee\x80\x80", FALSE
);
128 Utf8Convert(L
"\xffff", "\xef\xbf\xbf", FALSE
);
130 /* surrogate pairs */
131 Utf8Convert(L
"\xd800\xdc00", "\xf0\x90\x80\x80", FALSE
); /* U+10000 */
132 Utf8Convert(L
"\xd800\xdfff", "\xf0\x90\x8f\xbf", FALSE
); /* U+103ff */
133 Utf8Convert(L
"\xd801\xdc00", "\xf0\x90\x90\x80", FALSE
); /* U+10400 */
134 Utf8Convert(L
"\xdbff\xdfff", "\xf4\x8f\xbf\xbf", FALSE
); /* U+10ffff */
136 /* standalone lead surrogate becomes 0xfffd on Vista, goes through verbatim on 2003 */
137 Utf8Convert_Vista(L
"\xd800", "\xed\xa0\x80", TRUE
,
139 Utf8Convert_Vista(L
"\xd800-", "\xed\xa0\x80-", TRUE
,
141 Utf8Convert_Vista(L
"\xdbff", "\xed\xaf\xbf", TRUE
,
143 Utf8Convert_Vista(L
"\xdbff-", "\xed\xaf\xbf-", TRUE
,
146 /* standalone trail surrogate becomes 0xfffd */
147 Utf8Convert_Vista(L
"\xdc00", "\xed\xb0\x80", TRUE
,
149 Utf8Convert_Vista(L
"\xdc00-", "\xed\xb0\x80-", TRUE
,
151 Utf8Convert_Vista(L
"\xdfff", "\xed\xbf\xbf", TRUE
,
153 Utf8Convert_Vista(L
"\xdfff-", "\xed\xbf\xbf-", TRUE
,
156 /* Reverse surrogate pair */
157 Utf8Convert_Vista(L
"\xdfff\xdbff", "\xed\xbf\xbf\xed\xaf\xbf", TRUE
,
158 "\xef\xbf\xbd\xef\xbf\xbd");
160 /* Byte order marks */
161 Utf8Convert(L
"\xfeff", "\xef\xbb\xbf", FALSE
);
162 Utf8Convert(L
"\xfffe", "\xef\xbf\xbe", FALSE
);
164 /* canonically equivalent representations -- no normalization should happen */
165 Utf8Convert(L
"\x1e09", "\xe1\xb8\x89", FALSE
);
166 Utf8Convert(L
"\x0107\x0327", "\xc4\x87\xcc\xa7", FALSE
);
167 Utf8Convert(L
"\x00e7\x0301", "\xc3\xa7\xcc\x81", FALSE
);
168 Utf8Convert(L
"\x0063\x0327\x0301", "\x63\xcc\xa7\xcc\x81", FALSE
);
169 Utf8Convert(L
"\x0063\x0301\x0327", "\x63\xcc\x81\xcc\xa7", FALSE
);
172 START_TEST(WideCharToMultiByte
)