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>
11 /* NOTE: Tested on Win10. We follow Win10 in this function.
12 Win10 might alter its design in future. */
14 /* TODO: Russian, French, Korean etc. codepages */
16 #define CP932 932 /* Japanese Shift_JIS (SJIS) codepage */
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";
36 WCHAR CheckDest
[MAX_BUFFER
];
41 static const ENTRY Entries
[] =
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 },
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 },
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 },
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 },
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__
, 0, ERROR_NO_UNICODE_TRANSLATION
, CP_UTF8
, MB_ERR_INVALID_CHARS
, "\xC0", 2 },
69 { __LINE__
, 0, ERROR_NO_UNICODE_TRANSLATION
, CP_UTF8
, MB_ERR_INVALID_CHARS
, "\xC0\xC0\x80", 4 },
70 { __LINE__
, 0, ERROR_NO_UNICODE_TRANSLATION
, CP_UTF8
, MB_ERR_INVALID_CHARS
, "\xE0\xC0", 3 },
71 { __LINE__
, 0, ERROR_NO_UNICODE_TRANSLATION
, CP_UTF8
, MB_ERR_INVALID_CHARS
, "\xE0\x20\xC0", 4 },
72 /* invalid UTF-8 sequences with buffer */
73 { __LINE__
, 2, 0xBEAF, CP_UTF8
, 0, "\xC0", 2, 4, {0xFFFD, 0, 0x7F7F}, 3},
74 { __LINE__
, 4, 0xBEAF, CP_UTF8
, 0, "\xC0\xC0\x80", 4, 5, {0xFFFD, 0xFFFD, 0xFFFD, 0, 0x7F7F}, 5 },
75 { __LINE__
, 3, 0xBEAF, CP_UTF8
, 0, "\xE0\xC0", 3, 4, {0xFFFD, 0xFFFD, 0, 0x7F7F}, 4 },
76 { __LINE__
, 4, 0xBEAF, CP_UTF8
, 0, "\xE0\x20\xC0", 4, 5, {0xFFFD, 0x0020, 0xFFFD, 0, 0x7F7F}, 5 },
77 { __LINE__
, 0, ERROR_NO_UNICODE_TRANSLATION
, CP_UTF8
, MB_ERR_INVALID_CHARS
, "\xC0", 2, 4, {0xFFFD, 0, 0x7F7F}, 3 },
78 { __LINE__
, 0, ERROR_NO_UNICODE_TRANSLATION
, CP_UTF8
, MB_ERR_INVALID_CHARS
, "\xC0\xC0\x80", 4, 5, {0xFFFD, 0xFFFD, 0xFFFD, 0, 0x7F7F}, 5 },
79 { __LINE__
, 0, ERROR_NO_UNICODE_TRANSLATION
, CP_UTF8
, MB_ERR_INVALID_CHARS
, "\xE0\xC0", 3, 4, {0xFFFD, 0xFFFD, 0, 0x7F7F}, 4 },
80 { __LINE__
, 0, ERROR_NO_UNICODE_TRANSLATION
, CP_UTF8
, MB_ERR_INVALID_CHARS
, "\xE0\x20\xC0", 4, 5, {0xFFFD, 0x0020, 0xFFFD, 0, 0x7F7F}, 5 },
81 /* invalid UTF-8 sequences with short buffer */
82 { __LINE__
, 0, ERROR_INSUFFICIENT_BUFFER
, CP_UTF8
, 0, "\xC0", 2, 1, {0xFFFD, 0x7F7F}, 2},
83 { __LINE__
, 0, ERROR_INSUFFICIENT_BUFFER
, CP_UTF8
, 0, "\xC0\xC0\x80", 4, 1, {0xFFFD, 0x7F7F}, 2 },
84 { __LINE__
, 0, ERROR_INSUFFICIENT_BUFFER
, CP_UTF8
, 0, "\xE0\xC0", 3, 1, {0xFFFD, 0x7F7F}, 2 },
85 { __LINE__
, 0, ERROR_INSUFFICIENT_BUFFER
, CP_UTF8
, 0, "\xE0\x20\xC0", 4, 1, {0xFFFD, 0x7F7F}, 2 },
86 { __LINE__
, 0, ERROR_INSUFFICIENT_BUFFER
, CP_UTF8
, MB_ERR_INVALID_CHARS
, "\xC0", 2, 1, {0xFFFD, 0x7F7F}, 2 },
87 { __LINE__
, 0, ERROR_INSUFFICIENT_BUFFER
, CP_UTF8
, MB_ERR_INVALID_CHARS
, "\xC0\xC0\x80", 4, 1, {0xFFFD, 0x7F7F}, 2 },
88 { __LINE__
, 0, ERROR_INSUFFICIENT_BUFFER
, CP_UTF8
, MB_ERR_INVALID_CHARS
, "\xE0\xC0", 3, 1, {0xFFFD, 0x7F7F}, 2 },
89 { __LINE__
, 0, ERROR_INSUFFICIENT_BUFFER
, CP_UTF8
, MB_ERR_INVALID_CHARS
, "\xE0\x20\xC0", 4, 1, {0xFFFD, 0x7F7F}, 2 },
90 /* Japanese UTF-8 without buffer */
91 { __LINE__
, 4, 0xBEAF, CP_UTF8
, 0, UTF8_Japanese
, sizeof(UTF8_Japanese
) },
92 { __LINE__
, 4, 0xBEAF, CP_UTF8
, MB_ERR_INVALID_CHARS
, UTF8_Japanese
, sizeof(UTF8_Japanese
) },
93 /* Japanese UTF-8 with buffer */
94 { __LINE__
, 4, 0xBEAF, CP_UTF8
, 0, UTF8_Japanese
, sizeof(UTF8_Japanese
), 4, {0x65E5, 0x672C, 0x8A9E, 0, 0x7F7F}, 5 },
95 { __LINE__
, 4, 0xBEAF, CP_UTF8
, MB_ERR_INVALID_CHARS
, UTF8_Japanese
, sizeof(UTF8_Japanese
), 4, {0x65E5, 0x672C, 0x8A9E, 0, 0x7F7F}, 5 },
96 /* Japanese UTF-8 with short buffer */
97 { __LINE__
, 0, ERROR_INSUFFICIENT_BUFFER
, CP_UTF8
, 0, UTF8_Japanese
, sizeof(UTF8_Japanese
), 1, {0x65E5, 0x7F7F}, 2 },
98 { __LINE__
, 0, ERROR_INSUFFICIENT_BUFFER
, CP_UTF8
, MB_ERR_INVALID_CHARS
, UTF8_Japanese
, sizeof(UTF8_Japanese
), 1, {0x65E5, 0x7F7F}, 2 },
99 /* Japanese UTF-8 truncated source */
100 { __LINE__
, 1, 0xBEAF, CP_UTF8
, 0, UTF8_Japanese
, 1, 4, {0xFFFD, 0x7F7F}, 2 },
101 { __LINE__
, 0, ERROR_NO_UNICODE_TRANSLATION
, CP_UTF8
, MB_ERR_INVALID_CHARS
, UTF8_Japanese
, 1, 4, {0xFFFD, 0x7F7F}, 2 },
102 /* Japanese CP932 without buffer */
103 { __LINE__
, 4, 0xBEAF, CP932
, 0, SJIS_Japanese
, sizeof(SJIS_Japanese
) },
104 { __LINE__
, 4, 0xBEAF, CP932
, MB_ERR_INVALID_CHARS
, SJIS_Japanese
, sizeof(SJIS_Japanese
) },
105 /* Japanese CP932 with buffer */
106 { __LINE__
, 4, 0xBEAF, CP932
, 0, SJIS_Japanese
, sizeof(SJIS_Japanese
), 4, {0x65E5, 0x672C, 0x8A9E, 0, 0x7F7F}, 5 },
107 { __LINE__
, 4, 0xBEAF, CP932
, MB_ERR_INVALID_CHARS
, SJIS_Japanese
, sizeof(SJIS_Japanese
), 4, {0x65E5, 0x672C, 0x8A9E, 0, 0x7F7F}, 5 },
108 /* Japanese CP932 with short buffer */
109 { __LINE__
, 0, ERROR_INSUFFICIENT_BUFFER
, CP932
, 0, SJIS_Japanese
, sizeof(SJIS_Japanese
), 1, {0x65E5, 0x7F7F}, 2 },
110 { __LINE__
, 0, ERROR_INSUFFICIENT_BUFFER
, CP932
, MB_ERR_INVALID_CHARS
, SJIS_Japanese
, sizeof(SJIS_Japanese
), 1, {0x65E5, 0x7F7F}, 2 },
111 /* Japanese CP932 truncated source */
112 { __LINE__
, 1, 0xBEAF, CP932
, 0, SJIS_Japanese
, 1, 4, {0x30FB, 0x7F7F}, 2 },
113 { __LINE__
, 0, ERROR_NO_UNICODE_TRANSLATION
, CP932
, MB_ERR_INVALID_CHARS
, SJIS_Japanese
, 1, 4, {0x7F7F, 0x7F7F}, 2 },
116 static void TestEntry(const ENTRY
*pEntry
)
119 WCHAR Buffer
[MAX_BUFFER
];
122 FillMemory(Buffer
, sizeof(Buffer
), 0x7F);
123 SetLastError(0xBEAF);
125 if (pEntry
->DestLen
== 0)
128 ret
= MultiByteToWideChar(pEntry
->CodePage
, pEntry
->Flags
, pEntry
->Src
,
129 pEntry
->SrcLen
, NULL
, 0);
133 ok(pEntry
->DestLen
>= pEntry
->CheckLen
- 1,
134 "Line %d: DestLen was shorter than (CheckLen - 1)\n", pEntry
->LineNo
);
136 if (pEntry
->SamePointer
)
138 /* src ptr == dest ptr */
139 ret
= MultiByteToWideChar(pEntry
->CodePage
, pEntry
->Flags
,
140 (const char *)Buffer
, pEntry
->SrcLen
,
141 Buffer
, pEntry
->DestLen
);
145 /* src ptr != dest ptr */
146 ret
= MultiByteToWideChar(pEntry
->CodePage
, pEntry
->Flags
,
147 pEntry
->Src
, pEntry
->SrcLen
,
148 Buffer
, pEntry
->DestLen
);
152 Error
= GetLastError();
155 ok(ret
== pEntry
->Return
, "Line %d: ret expected %d, got %d\n",
156 pEntry
->LineNo
, pEntry
->Return
, ret
);
158 /* check error code */
159 ok(Error
== pEntry
->Error
,
160 "Line %d: Wrong last error. Expected %lu, got %lu\n",
161 pEntry
->LineNo
, pEntry
->Error
, Error
);
166 for (i
= 0; i
< pEntry
->CheckLen
; ++i
)
168 ok(Buffer
[i
] == pEntry
->CheckDest
[i
], "Line %d: Buffer[%d] expected %d, got %d\n",
169 pEntry
->LineNo
, i
, pEntry
->CheckDest
[i
], Buffer
[i
]);
174 typedef NTSTATUS (WINAPI
* RTLGETVERSION
)(PRTL_OSVERSIONINFOW
);
176 static RTL_OSVERSIONINFOW
*GetRealOSVersion(void)
178 static RTL_OSVERSIONINFOW osvi
= { 0 };
179 RTL_OSVERSIONINFOW
*ptr
= NULL
;
180 HINSTANCE hNTDLL
= LoadLibraryW(L
"ntdll.dll");
184 fn
= (RTLGETVERSION
)GetProcAddress(hNTDLL
, "RtlGetVersion");
187 osvi
.dwOSVersionInfoSize
= sizeof(osvi
);
188 if (fn(&osvi
) == STATUS_SUCCESS
)
198 static BOOL
IsWin10Plus(void)
200 RTL_OSVERSIONINFOW
*info
= GetRealOSVersion();
204 return info
->dwMajorVersion
>= 10;
207 static BOOL
IsReactOS(void)
209 WCHAR szWinDir
[MAX_PATH
];
210 GetWindowsDirectoryW(szWinDir
, _countof(szWinDir
));
211 return (wcsstr(szWinDir
, L
"ReactOS") != NULL
);
214 START_TEST(MultiByteToWideChar
)
218 if (!IsWin10Plus() && !IsReactOS())
220 trace("This test is designed for Windows 10+ and ReactOS.\n"
221 "It is expected to report some failures on older Windows versions.\n");
228 for (i
= 0; i
< _countof(Entries
); ++i
)
230 TestEntry(&Entries
[i
]);