[KERNEL32_APITEST] Strengthen MultiByteToWideChar(CP_UTF8, ...) testcase (#2008)
[reactos.git] / modules / rostests / apitests / kernel32 / MultiByteToWideChar.c
1 /*
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Test for MultiByteToWideChar
5 * PROGRAMMERS: Mike "tamlin" Nordell
6 * Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
7 */
8
9 #include "precomp.h"
10
11 /* NOTE: Tested on Win10. We follow Win10 in this function.
12 Win10 might alter its design in future. */
13
14 /* TODO: Russian, French, Korean etc. codepages */
15
16 #define CP932 932 /* Japanese Shift_JIS (SJIS) codepage */
17
18 /* "Japanese" in Japanese UTF-8 */
19 static const char UTF8_Japanese[] = "\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E";
20 /* "Japanese" in Japanese Shift_JIS */
21 static const char SJIS_Japanese[] = "\x93\xFA\x96\x7B\x8C\xEA";
22
23 #define MAX_BUFFER 10
24
25 /* test entry */
26 typedef struct ENTRY
27 {
28 int LineNo;
29 int Return;
30 DWORD Error;
31 UINT CodePage;
32 DWORD Flags;
33 const char *Src;
34 int SrcLen;
35 int DestLen;
36 WCHAR CheckDest[MAX_BUFFER];
37 int CheckLen;
38 BOOL SamePointer;
39 } ENTRY;
40
41 static const ENTRY Entries[] =
42 {
43 /* without buffer */
44 { __LINE__, 1, 0xBEAF, CP_UTF8, 0, "a", 1 },
45 { __LINE__, 2, 0xBEAF, CP_UTF8, 0, "a", 2 },
46 { __LINE__, 2, 0xBEAF, CP_UTF8, MB_ERR_INVALID_CHARS, "a", 2 },
47 /* negative length */
48 { __LINE__, 2, 0xBEAF, CP_UTF8, 0, "a", -1 },
49 { __LINE__, 2, 0xBEAF, CP_UTF8, 0, "a", -2 },
50 { __LINE__, 2, 0xBEAF, CP_UTF8, MB_ERR_INVALID_CHARS, "a", -1 },
51 { __LINE__, 2, 0xBEAF, CP_UTF8, MB_ERR_INVALID_CHARS, "a", -3 },
52 /* with buffer */
53 { __LINE__, 1, 0xBEAF, CP_UTF8, 0, "a", 1, 1, {'a', 0x7F7F}, 2 },
54 { __LINE__, 2, 0xBEAF, CP_UTF8, 0, "a", 2, 4, {'a', 0, 0x7F7F}, 3 },
55 { __LINE__, 2, 0xBEAF, CP_UTF8, MB_ERR_INVALID_CHARS, "a", 2, 4, {'a', 0, 0x7F7F}, 3 },
56 /* short buffer */
57 { __LINE__, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, 0, "a", 2, 1, {'a', 0x7F7F}, 2 },
58 { __LINE__, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, 0, "a", 2, 1, {'a', 0x7F7F}, 2 },
59 { __LINE__, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, MB_ERR_INVALID_CHARS, "a", 2, 1, {'a', 0x7F7F}, 2 },
60 /* same pointer */
61 { __LINE__, 0, ERROR_INVALID_PARAMETER, CP_UTF8, 0, "", 1, 1, { 0x7F7F }, 1, TRUE },
62 { __LINE__, 0, ERROR_INVALID_PARAMETER, CP_UTF8, MB_ERR_INVALID_CHARS, "", 1, 1, { 0x7F7F }, 1, TRUE },
63 /* invalid UTF-8 sequences without buffer */
64 { __LINE__, 2, 0xBEAF, CP_UTF8, 0, "\xC0", 2 },
65 { __LINE__, 4, 0xBEAF, CP_UTF8, 0, "\xC0\xC0\x80", 4 },
66 { __LINE__, 3, 0xBEAF, CP_UTF8, 0, "\xE0\xC0", 3 },
67 { __LINE__, 4, 0xBEAF, CP_UTF8, 0, "\xE0\x20\xC0", 4 },
68 { __LINE__, 5, 0xBEAF, CP_UTF8, 0, "\x82\xA0\x82\xA2", -1 },
69 { __LINE__, 6, 0xBEAF, CP_UTF8, 0, "\x82\xA0\x82\xA2\x82", -1 },
70 { __LINE__, 0, ERROR_NO_UNICODE_TRANSLATION, CP_UTF8, MB_ERR_INVALID_CHARS, "\xC0", 2 },
71 { __LINE__, 0, ERROR_NO_UNICODE_TRANSLATION, CP_UTF8, MB_ERR_INVALID_CHARS, "\xC0\xC0\x80", 4 },
72 { __LINE__, 0, ERROR_NO_UNICODE_TRANSLATION, CP_UTF8, MB_ERR_INVALID_CHARS, "\xE0\xC0", 3 },
73 { __LINE__, 0, ERROR_NO_UNICODE_TRANSLATION, CP_UTF8, MB_ERR_INVALID_CHARS, "\xE0\x20\xC0", 4 },
74 { __LINE__, 0, ERROR_NO_UNICODE_TRANSLATION, CP_UTF8, MB_ERR_INVALID_CHARS, "\x82\xA0\x82\xA2", -1 },
75 { __LINE__, 0, ERROR_NO_UNICODE_TRANSLATION, CP_UTF8, MB_ERR_INVALID_CHARS, "\x82\xA0\x82\xA2\x82", -1 },
76 /* invalid UTF-8 sequences with buffer */
77 { __LINE__, 2, 0xBEAF, CP_UTF8, 0, "\xC0", 2, 4, {0xFFFD, 0, 0x7F7F}, 3},
78 { __LINE__, 4, 0xBEAF, CP_UTF8, 0, "\xC0\xC0\x80", 4, 5, {0xFFFD, 0xFFFD, 0xFFFD, 0, 0x7F7F}, 5 },
79 { __LINE__, 3, 0xBEAF, CP_UTF8, 0, "\xE0\xC0", 3, 4, {0xFFFD, 0xFFFD, 0, 0x7F7F}, 4 },
80 { __LINE__, 4, 0xBEAF, CP_UTF8, 0, "\xE0\x20\xC0", 4, 5, {0xFFFD, 0x0020, 0xFFFD, 0, 0x7F7F}, 5 },
81 { __LINE__, 5, 0xBEAF, CP_UTF8, 0, "\x82\xA0\x82\xA2", -1, 5, {0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0}, 5 },
82 { __LINE__, 6, 0xBEAF, CP_UTF8, 0, "\x82\xA0\x82\xA2\x82", -1, 8, {0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0}, 6 },
83 { __LINE__, 0, ERROR_NO_UNICODE_TRANSLATION, CP_UTF8, MB_ERR_INVALID_CHARS, "\xC0", 2, 4, {0xFFFD, 0, 0x7F7F}, 3 },
84 { __LINE__, 0, ERROR_NO_UNICODE_TRANSLATION, CP_UTF8, MB_ERR_INVALID_CHARS, "\xC0\xC0\x80", 4, 5, {0xFFFD, 0xFFFD, 0xFFFD, 0, 0x7F7F}, 5 },
85 { __LINE__, 0, ERROR_NO_UNICODE_TRANSLATION, CP_UTF8, MB_ERR_INVALID_CHARS, "\xE0\xC0", 3, 4, {0xFFFD, 0xFFFD, 0, 0x7F7F}, 4 },
86 { __LINE__, 0, ERROR_NO_UNICODE_TRANSLATION, CP_UTF8, MB_ERR_INVALID_CHARS, "\xE0\x20\xC0", 4, 5, {0xFFFD, 0x0020, 0xFFFD, 0, 0x7F7F}, 5 },
87 { __LINE__, 0, ERROR_NO_UNICODE_TRANSLATION, CP_UTF8, MB_ERR_INVALID_CHARS, "\x82\xA0\x82\xA2", -1, 6, {0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0, 0x7F7F}, 6 },
88 { __LINE__, 0, ERROR_NO_UNICODE_TRANSLATION, CP_UTF8, MB_ERR_INVALID_CHARS, "\x82\xA0\x82\xA2\x82", -1, 7, {0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0, 0x7F7F}, 7 },
89 /* invalid UTF-8 sequences with short buffer */
90 { __LINE__, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, 0, "\xC0", 2, 1, {0xFFFD, 0x7F7F}, 2},
91 { __LINE__, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, 0, "\xC0\xC0\x80", 4, 1, {0xFFFD, 0x7F7F}, 2 },
92 { __LINE__, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, 0, "\xE0\xC0", 3, 1, {0xFFFD, 0x7F7F}, 2 },
93 { __LINE__, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, 0, "\xE0\x20\xC0", 4, 1, {0xFFFD, 0x7F7F}, 2 },
94 { __LINE__, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, 0, "\x82\xA0\x82\xA2", -1, 1, {0xFFFD, 0x7F7F}, 2 },
95 { __LINE__, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, 0, "\x82\xA0\x82\xA2\x82", -1, 1, {0xFFFD, 0x7F7F}, 2 },
96 { __LINE__, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, MB_ERR_INVALID_CHARS, "\xC0", 2, 1, {0xFFFD, 0x7F7F}, 2 },
97 { __LINE__, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, MB_ERR_INVALID_CHARS, "\xC0\xC0\x80", 4, 1, {0xFFFD, 0x7F7F}, 2 },
98 { __LINE__, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, MB_ERR_INVALID_CHARS, "\xE0\xC0", 3, 1, {0xFFFD, 0x7F7F}, 2 },
99 { __LINE__, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, MB_ERR_INVALID_CHARS, "\xE0\x20\xC0", 4, 1, {0xFFFD, 0x7F7F}, 2 },
100 { __LINE__, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, MB_ERR_INVALID_CHARS, "\x82\xA0\x82\xA2", -1, 1, {0xFFFD, 0x7F7F}, 2 },
101 { __LINE__, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, MB_ERR_INVALID_CHARS, "\x82\xA0\x82\xA2\x82", -1, 1, {0xFFFD, 0x7F7F}, 2 },
102 /* Japanese UTF-8 without buffer */
103 { __LINE__, 4, 0xBEAF, CP_UTF8, 0, UTF8_Japanese, sizeof(UTF8_Japanese) },
104 { __LINE__, 4, 0xBEAF, CP_UTF8, MB_ERR_INVALID_CHARS, UTF8_Japanese, sizeof(UTF8_Japanese) },
105 /* Japanese UTF-8 with buffer */
106 { __LINE__, 4, 0xBEAF, CP_UTF8, 0, UTF8_Japanese, sizeof(UTF8_Japanese), 4, {0x65E5, 0x672C, 0x8A9E, 0, 0x7F7F}, 5 },
107 { __LINE__, 4, 0xBEAF, CP_UTF8, MB_ERR_INVALID_CHARS, UTF8_Japanese, sizeof(UTF8_Japanese), 4, {0x65E5, 0x672C, 0x8A9E, 0, 0x7F7F}, 5 },
108 /* Japanese UTF-8 with short buffer */
109 { __LINE__, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, 0, UTF8_Japanese, sizeof(UTF8_Japanese), 1, {0x65E5, 0x7F7F}, 2 },
110 { __LINE__, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, MB_ERR_INVALID_CHARS, UTF8_Japanese, sizeof(UTF8_Japanese), 1, {0x65E5, 0x7F7F}, 2 },
111 /* Japanese UTF-8 truncated source */
112 { __LINE__, 1, 0xBEAF, CP_UTF8, 0, UTF8_Japanese, 1, 4, {0xFFFD, 0x7F7F}, 2 },
113 { __LINE__, 0, ERROR_NO_UNICODE_TRANSLATION, CP_UTF8, MB_ERR_INVALID_CHARS, UTF8_Japanese, 1, 4, {0xFFFD, 0x7F7F}, 2 },
114 /* Japanese CP932 without buffer */
115 { __LINE__, 4, 0xBEAF, CP932, 0, SJIS_Japanese, sizeof(SJIS_Japanese) },
116 { __LINE__, 4, 0xBEAF, CP932, MB_ERR_INVALID_CHARS, SJIS_Japanese, sizeof(SJIS_Japanese) },
117 /* Japanese CP932 with buffer */
118 { __LINE__, 4, 0xBEAF, CP932, 0, SJIS_Japanese, sizeof(SJIS_Japanese), 4, {0x65E5, 0x672C, 0x8A9E, 0, 0x7F7F}, 5 },
119 { __LINE__, 4, 0xBEAF, CP932, MB_ERR_INVALID_CHARS, SJIS_Japanese, sizeof(SJIS_Japanese), 4, {0x65E5, 0x672C, 0x8A9E, 0, 0x7F7F}, 5 },
120 /* Japanese CP932 with short buffer */
121 { __LINE__, 0, ERROR_INSUFFICIENT_BUFFER, CP932, 0, SJIS_Japanese, sizeof(SJIS_Japanese), 1, {0x65E5, 0x7F7F}, 2 },
122 { __LINE__, 0, ERROR_INSUFFICIENT_BUFFER, CP932, MB_ERR_INVALID_CHARS, SJIS_Japanese, sizeof(SJIS_Japanese), 1, {0x65E5, 0x7F7F}, 2 },
123 /* Japanese CP932 truncated source */
124 { __LINE__, 1, 0xBEAF, CP932, 0, SJIS_Japanese, 1, 4, {0x30FB, 0x7F7F}, 2 },
125 { __LINE__, 0, ERROR_NO_UNICODE_TRANSLATION, CP932, MB_ERR_INVALID_CHARS, SJIS_Japanese, 1, 4, {0x7F7F, 0x7F7F}, 2 },
126 /* invalid 5-byte UTF-8 sequences */
127 { __LINE__, 1, 0xBEAF, CP_UTF8, 0, "\xF8\xA3\xA3\xA3\xA3", 1, 8, {0xFFFD, 0x7F7F}, 2 },
128 { __LINE__, 2, 0xBEAF, CP_UTF8, 0, "\xF8\xA3\xA3\xA3\xA3", 2, 8, {0xFFFD, 0xFFFD, 0x7F7F}, 3 },
129 { __LINE__, 3, 0xBEAF, CP_UTF8, 0, "\xF8\xA3\xA3\xA3\xA3", 3, 8, {0xFFFD, 0xFFFD, 0xFFFD, 0x7F7F}, 4 },
130 { __LINE__, 4, 0xBEAF, CP_UTF8, 0, "\xF8\xA3\xA3\xA3\xA3", 4, 8, {0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x7F7F}, 5 },
131 { __LINE__, 5, 0xBEAF, CP_UTF8, 0, "\xF8\xA3\xA3\xA3\xA3", 5, 8, {0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x7F7F}, 6 },
132 { __LINE__, 6, 0xBEAF, CP_UTF8, 0, "\xF8\xA3\xA3\xA3\xA3", 6, 8, {0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0}, 6 },
133 /* invalid 6-byte UTF-8 sequences */
134 { __LINE__, 1, 0xBEAF, CP_UTF8, 0, "\xFC\xA3\xA3\xA3\xA3\xA3", 1, 8, {0xFFFD, 0x7F7F}, 2 },
135 { __LINE__, 2, 0xBEAF, CP_UTF8, 0, "\xFC\xA3\xA3\xA3\xA3\xA3", 2, 8, {0xFFFD, 0xFFFD, 0x7F7F}, 3 },
136 { __LINE__, 3, 0xBEAF, CP_UTF8, 0, "\xFC\xA3\xA3\xA3\xA3\xA3", 3, 8, {0xFFFD, 0xFFFD, 0xFFFD, 0x7F7F}, 4 },
137 { __LINE__, 4, 0xBEAF, CP_UTF8, 0, "\xFC\xA3\xA3\xA3\xA3\xA3", 4, 8, {0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x7F7F}, 5 },
138 { __LINE__, 5, 0xBEAF, CP_UTF8, 0, "\xFC\xA3\xA3\xA3\xA3\xA3", 5, 8, {0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x7F7F}, 6 },
139 { __LINE__, 6, 0xBEAF, CP_UTF8, 0, "\xFC\xA3\xA3\xA3\xA3\xA3", 6, 8, {0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x7F7F}, 7 },
140 { __LINE__, 7, 0xBEAF, CP_UTF8, 0, "\xFC\xA3\xA3\xA3\xA3\xA3", 7, 8, {0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0}, 7 },
141 /* invalid 7-byte UTF-8 sequences */
142 { __LINE__, 1, 0xBEAF, CP_UTF8, 0, "\xFE\xA3\xA3\xA3\xA3\xA3\xA3", 1, 8, {0xFFFD, 0x7F7F}, 2 },
143 { __LINE__, 2, 0xBEAF, CP_UTF8, 0, "\xFE\xA3\xA3\xA3\xA3\xA3\xA3", 2, 8, {0xFFFD, 0xFFFD, 0x7F7F}, 3 },
144 { __LINE__, 3, 0xBEAF, CP_UTF8, 0, "\xFE\xA3\xA3\xA3\xA3\xA3\xA3", 3, 8, {0xFFFD, 0xFFFD, 0xFFFD, 0x7F7F}, 4 },
145 { __LINE__, 4, 0xBEAF, CP_UTF8, 0, "\xFE\xA3\xA3\xA3\xA3\xA3\xA3", 4, 8, {0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x7F7F}, 5 },
146 { __LINE__, 5, 0xBEAF, CP_UTF8, 0, "\xFE\xA3\xA3\xA3\xA3\xA3\xA3", 5, 8, {0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x7F7F}, 6 },
147 { __LINE__, 6, 0xBEAF, CP_UTF8, 0, "\xFE\xA3\xA3\xA3\xA3\xA3\xA3", 6, 8, {0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x7F7F}, 7 },
148 { __LINE__, 7, 0xBEAF, CP_UTF8, 0, "\xFE\xA3\xA3\xA3\xA3\xA3\xA3", 7, 8, {0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x7F7F}, 8 },
149 { __LINE__, 8, 0xBEAF, CP_UTF8, 0, "\xFE\xA3\xA3\xA3\xA3\xA3\xA3", 8, 8, {0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0}, 8 },
150 /* invalid UTF-8 sequences */
151 { __LINE__, 1, 0xBEAF, CP_UTF8, 0, "\xFF\xA3\xA3\xA3\xA3\xA3\xA3\xA3", 1, 8, {0xFFFD, 0x7F7F}, 2 },
152 { __LINE__, 2, 0xBEAF, CP_UTF8, 0, "\xFF\xA3\xA3\xA3\xA3\xA3\xA3\xA3", 2, 8, {0xFFFD, 0xFFFD, 0x7F7F}, 3 },
153 { __LINE__, 3, 0xBEAF, CP_UTF8, 0, "\xFF\xA3\xA3\xA3\xA3\xA3\xA3\xA3", 3, 8, {0xFFFD, 0xFFFD, 0xFFFD, 0x7F7F}, 4 },
154 { __LINE__, 4, 0xBEAF, CP_UTF8, 0, "\xFF\xA3\xA3\xA3\xA3\xA3\xA3\xA3", 4, 8, {0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x7F7F}, 5 },
155 { __LINE__, 5, 0xBEAF, CP_UTF8, 0, "\xFF\xA3\xA3\xA3\xA3\xA3\xA3\xA3", 5, 8, {0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x7F7F}, 6 },
156 { __LINE__, 6, 0xBEAF, CP_UTF8, 0, "\xFF\xA3\xA3\xA3\xA3\xA3\xA3\xA3", 6, 8, {0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x7F7F}, 7 },
157 { __LINE__, 7, 0xBEAF, CP_UTF8, 0, "\xFF\xA3\xA3\xA3\xA3\xA3\xA3\xA3", 7, 8, {0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x7F7F}, 8 },
158 { __LINE__, 8, 0xBEAF, CP_UTF8, 0, "\xFF\xA3\xA3\xA3\xA3\xA3\xA3\xA3", 8, 8, {0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x7F7F}, 9 },
159 { __LINE__, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, 0, "\xFF\xA3\xA3\xA3\xA3\xA3\xA3\xA3", 9, 8, {0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x7F7F}, 9 },
160 };
161
162 static void TestEntry(const ENTRY *pEntry)
163 {
164 int ret, i;
165 WCHAR Buffer[MAX_BUFFER];
166 DWORD Error;
167
168 FillMemory(Buffer, sizeof(Buffer), 0x7F);
169 SetLastError(0xBEAF);
170
171 if (pEntry->DestLen == 0)
172 {
173 /* dest is NULL */
174 ret = MultiByteToWideChar(pEntry->CodePage, pEntry->Flags, pEntry->Src,
175 pEntry->SrcLen, NULL, 0);
176 }
177 else
178 {
179 ok(pEntry->DestLen >= pEntry->CheckLen - 1,
180 "Line %d: DestLen was shorter than (CheckLen - 1)\n", pEntry->LineNo);
181
182 if (pEntry->SamePointer)
183 {
184 /* src ptr == dest ptr */
185 ret = MultiByteToWideChar(pEntry->CodePage, pEntry->Flags,
186 (const char *)Buffer, pEntry->SrcLen,
187 Buffer, pEntry->DestLen);
188 }
189 else
190 {
191 /* src ptr != dest ptr */
192 ret = MultiByteToWideChar(pEntry->CodePage, pEntry->Flags,
193 pEntry->Src, pEntry->SrcLen,
194 Buffer, pEntry->DestLen);
195 }
196 }
197
198 Error = GetLastError();
199
200 /* check ret */
201 ok(ret == pEntry->Return, "Line %d: ret expected %d, got %d\n",
202 pEntry->LineNo, pEntry->Return, ret);
203
204 /* check error code */
205 ok(Error == pEntry->Error,
206 "Line %d: Wrong last error. Expected %lu, got %lu\n",
207 pEntry->LineNo, pEntry->Error, Error);
208
209 if (pEntry->DestLen)
210 {
211 /* check buffer */
212 for (i = 0; i < pEntry->CheckLen; ++i)
213 {
214 ok(Buffer[i] == pEntry->CheckDest[i], "Line %d: Buffer[%d] expected %d, got %d\n",
215 pEntry->LineNo, i, pEntry->CheckDest[i], Buffer[i]);
216 }
217 }
218 }
219
220 typedef NTSTATUS (WINAPI* RTLGETVERSION)(PRTL_OSVERSIONINFOW);
221
222 static RTL_OSVERSIONINFOW *GetRealOSVersion(void)
223 {
224 static RTL_OSVERSIONINFOW osvi = { 0 };
225 RTL_OSVERSIONINFOW *ptr = NULL;
226 HINSTANCE hNTDLL = LoadLibraryW(L"ntdll.dll");
227 RTLGETVERSION fn;
228 if (hNTDLL)
229 {
230 fn = (RTLGETVERSION)GetProcAddress(hNTDLL, "RtlGetVersion");
231 if (fn)
232 {
233 osvi.dwOSVersionInfoSize = sizeof(osvi);
234 if (fn(&osvi) == STATUS_SUCCESS)
235 {
236 ptr = &osvi;
237 }
238 }
239 FreeLibrary(hNTDLL);
240 }
241 return ptr;
242 }
243
244 static BOOL IsWin10Plus(void)
245 {
246 RTL_OSVERSIONINFOW *info = GetRealOSVersion();
247 if (!info)
248 return FALSE;
249
250 return info->dwMajorVersion >= 10;
251 }
252
253 static BOOL IsReactOS(void)
254 {
255 WCHAR szWinDir[MAX_PATH];
256 GetWindowsDirectoryW(szWinDir, _countof(szWinDir));
257 return (wcsstr(szWinDir, L"ReactOS") != NULL);
258 }
259
260 START_TEST(MultiByteToWideChar)
261 {
262 size_t i;
263
264 if (!IsWin10Plus() && !IsReactOS())
265 {
266 trace("This test is designed for Windows 10+ and ReactOS.\n"
267 "It is expected to report some failures on older Windows versions.\n");
268 #if 0
269 skip("\n");
270 return;
271 #endif
272 }
273
274 for (i = 0; i < _countof(Entries); ++i)
275 {
276 TestEntry(&Entries[i]);
277 }
278 }