Index: rostests/apitests/kernel32/MultiByteToWideChar.c =================================================================== --- rostests/apitests/kernel32/MultiByteToWideChar.c (revision 74717) +++ rostests/apitests/kernel32/MultiByteToWideChar.c (working copy) @@ -2,7 +2,8 @@ * PROJECT: ReactOS api tests * LICENSE: GPLv2+ - See COPYING in the top level directory * PURPOSE: Test for MultiByteToWideChar - * PROGRAMMER: Mike "tamlin" Nordell + * PROGRAMMERS: Mike "tamlin" Nordell + * Katayama Hirofumi MZ */ #include @@ -9,13 +10,176 @@ #include -START_TEST(MultiByteToWideChar) +/* "日本語" in UTF-8 */ +static const char UTF8_Japanese[] = "\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E"; +/* "日本語" in Shift_JIS */ +static const char SJIS_Japanese[] = "\x93\xFA\x96\x7B\x8C\xEA"; + +#define CP932 932 /* Japanese Shift_JIS (SJIS) CodePage */ + +#define MAX_BUFFER 8 + +typedef struct ENTRY { - int ret; + int EntryNumber; /* # */ + int Return; + DWORD Error; + UINT CodePage; + DWORD Flags; + const char *Src; + int SrcLen; + int DestLen; + WCHAR CheckDest[MAX_BUFFER]; + int CheckLen; + BOOL SamePointer; +} ENTRY; - ret = MultiByteToWideChar(CP_UTF8, 0, "a", sizeof("a"), 0, 0); - ok(ret == 2, "ret should be 2, is %d\n", ret); +static const ENTRY Entries[] = +{ + /* without buffer */ + { 0, 1, 0xBEAF, CP_UTF8, 0, "a", 1 }, + { 1, 2, 0xBEAF, CP_UTF8, 0, "a", 2 }, + { 2, 2, 0xBEAF, CP_UTF8, MB_ERR_INVALID_CHARS, "a", 2 }, + /* negative length */ + { 3, 2, 0xBEAF, CP_UTF8, 0, "a", -1 }, + { 4, 2, 0xBEAF, CP_UTF8, 0, "a", -2 }, + { 5, 2, 0xBEAF, CP_UTF8, MB_ERR_INVALID_CHARS, "a", -1 }, + { 6, 2, 0xBEAF, CP_UTF8, MB_ERR_INVALID_CHARS, "a", -3 }, + /* with buffer */ + { 7, 1, 0xBEAF, CP_UTF8, 0, "a", 1, 1, {'a', 0x7F7F}, 2 }, + { 8, 2, 0xBEAF, CP_UTF8, 0, "a", 2, 4, {'a', 0, 0x7F7F}, 3 }, + { 9, 2, 0xBEAF, CP_UTF8, MB_ERR_INVALID_CHARS, "a", 2, 4, {'a', 0, 0x7F7F}, 3 }, + /* short buffer */ + { 10, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, 0, "a", 2, 1, {'a', 0x7F7F}, 2 }, + { 11, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, 0, "a", 2, 1, {'a', 0x7F7F}, 2 }, + { 12, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, MB_ERR_INVALID_CHARS, "a", 2, 1, {'a', 0x7F7F}, 2 }, + /* invalid flags without buffer */ + { 13, 0, ERROR_INVALID_FLAGS, CP_UTF8, MB_COMPOSITE, "a", 1 }, + { 14, 0, ERROR_INVALID_FLAGS, CP_UTF8, MB_ERR_INVALID_CHARS | MB_PRECOMPOSED, "a", 2 }, + /* invalid flags with buffer */ + { 15, 0, ERROR_INVALID_FLAGS, CP_UTF8, MB_COMPOSITE, "a", 2, 4, { 0x7F7F }, 1 }, + { 16, 0, ERROR_INVALID_FLAGS, CP_UTF8, MB_ERR_INVALID_CHARS | MB_PRECOMPOSED, "a", 2, 4, { 0x7F7F }, 1 }, + /* invalid flags and short buffer */ + { 17, 0, ERROR_INVALID_FLAGS, CP_UTF8, MB_COMPOSITE, "a", 1, 1, { 0x7F7F }, 1 }, + { 18, 0, ERROR_INVALID_FLAGS, CP_UTF8, MB_ERR_INVALID_CHARS | MB_PRECOMPOSED, "a", 2, 1, { 0x7F7F }, 1 }, + /* same pointer */ + { 19, 0, ERROR_INVALID_PARAMETER, CP_UTF8, 0, "", 1, 1, { 0x7F7F }, 1, TRUE }, + { 20, 0, ERROR_INVALID_PARAMETER, CP_UTF8, MB_ERR_INVALID_CHARS, "", 1, 1, { 0x7F7F }, 1, TRUE }, + /* invalid UTF-8 sequences without buffer */ + { 21, 2, 0xBEAF, CP_UTF8, 0, "\xC0", 2 }, + { 22, 4, 0xBEAF, CP_UTF8, 0, "\xC0\xC0\x80", 4 }, + { 23, 3, 0xBEAF, CP_UTF8, 0, "\xE0\xC0", 3 }, + { 24, 4, 0xBEAF, CP_UTF8, 0, "\xE0\x20\xC0", 4 }, + { 25, 0, ERROR_NO_UNICODE_TRANSLATION, CP_UTF8, MB_ERR_INVALID_CHARS, "\xC0", 2 }, + { 26, 0, ERROR_NO_UNICODE_TRANSLATION, CP_UTF8, MB_ERR_INVALID_CHARS, "\xC0\xC0\x80", 4 }, + { 27, 0, ERROR_NO_UNICODE_TRANSLATION, CP_UTF8, MB_ERR_INVALID_CHARS, "\xE0\xC0", 3 }, + { 28, 0, ERROR_NO_UNICODE_TRANSLATION, CP_UTF8, MB_ERR_INVALID_CHARS, "\xE0\x20\xC0", 4 }, + /* invalid UTF-8 sequences with buffer */ + { 29, 2, 0xBEAF, CP_UTF8, 0, "\xC0", 2, 4, {0xFFFD, 0, 0x7F7F}, 3}, + { 30, 4, 0xBEAF, CP_UTF8, 0, "\xC0\xC0\x80", 4, 5, {0xFFFD, 0xFFFD, 0xFFFD, 0, 0x7F7F}, 5 }, + { 31, 3, 0xBEAF, CP_UTF8, 0, "\xE0\xC0", 3, 4, {0xFFFD, 0xFFFD, 0, 0x7F7F}, 4 }, + { 32, 4, 0xBEAF, CP_UTF8, 0, "\xE0\x20\xC0", 4, 5, {0xFFFD, 0x0020, 0xFFFD, 0, 0x7F7F}, 5 }, + { 33, 0, ERROR_NO_UNICODE_TRANSLATION, CP_UTF8, MB_ERR_INVALID_CHARS, "\xC0", 2, 4, {0xFFFD, 0, 0x7F7F}, 3 }, + { 34, 0, ERROR_NO_UNICODE_TRANSLATION, CP_UTF8, MB_ERR_INVALID_CHARS, "\xC0\xC0\x80", 4, 5, {0xFFFD, 0xFFFD, 0xFFFD, 0, 0x7F7F}, 5 }, + { 35, 0, ERROR_NO_UNICODE_TRANSLATION, CP_UTF8, MB_ERR_INVALID_CHARS, "\xE0\xC0", 3, 4, {0xFFFD, 0xFFFD, 0, 0x7F7F}, 4 }, + { 36, 0, ERROR_NO_UNICODE_TRANSLATION, CP_UTF8, MB_ERR_INVALID_CHARS, "\xE0\x20\xC0", 4, 5, {0xFFFD, 0x0020, 0xFFFD, 0, 0x7F7F}, 5 }, + /* invalid UTF-8 sequences with short buffer */ + { 37, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, 0, "\xC0", 2, 1, {0xFFFD, 0x7F7F}, 2}, + { 38, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, 0, "\xC0\xC0\x80", 4, 1, {0xFFFD, 0x7F7F}, 2 }, + { 39, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, 0, "\xE0\xC0", 3, 1, {0xFFFD, 0x7F7F}, 2 }, + { 40, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, 0, "\xE0\x20\xC0", 4, 1, {0xFFFD, 0x7F7F}, 2 }, + { 41, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, MB_ERR_INVALID_CHARS, "\xC0", 2, 1, {0xFFFD, 0x7F7F}, 2 }, + { 42, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, MB_ERR_INVALID_CHARS, "\xC0\xC0\x80", 4, 1, {0xFFFD, 0x7F7F}, 2 }, + { 43, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, MB_ERR_INVALID_CHARS, "\xE0\xC0", 3, 1, {0xFFFD, 0x7F7F}, 2 }, + { 44, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, MB_ERR_INVALID_CHARS, "\xE0\x20\xC0", 4, 1, {0xFFFD, 0x7F7F}, 2 }, + /* Japanese UTF-8 without buffer */ + { 45, 4, 0xBEAF, CP_UTF8, 0, UTF8_Japanese, sizeof(UTF8_Japanese) }, + { 46, 4, 0xBEAF, CP_UTF8, MB_ERR_INVALID_CHARS, UTF8_Japanese, sizeof(UTF8_Japanese) }, + /* Japanese UTF-8 with buffer */ + { 47, 4, 0xBEAF, CP_UTF8, 0, UTF8_Japanese, sizeof(UTF8_Japanese), 4, {0x65E5, 0x672C, 0x8A9E, 0, 0x7F7F}, 5 }, + { 48, 4, 0xBEAF, CP_UTF8, MB_ERR_INVALID_CHARS, UTF8_Japanese, sizeof(UTF8_Japanese), 4, {0x65E5, 0x672C, 0x8A9E, 0, 0x7F7F}, 5 }, + /* Japanese UTF-8 with short buffer */ + { 49, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, 0, UTF8_Japanese, sizeof(UTF8_Japanese), 1, {0x65E5, 0x7F7F}, 2 }, + { 50, 0, ERROR_INSUFFICIENT_BUFFER, CP_UTF8, MB_ERR_INVALID_CHARS, UTF8_Japanese, sizeof(UTF8_Japanese), 1, {0x65E5, 0x7F7F}, 2 }, + /* Japanese CP932 without buffer */ + { 51, 4, 0xBEAF, CP932, 0, SJIS_Japanese, sizeof(SJIS_Japanese) }, + { 52, 4, 0xBEAF, CP932, MB_ERR_INVALID_CHARS, SJIS_Japanese, sizeof(SJIS_Japanese) }, + /* Japanese CP932 with buffer */ + { 53, 4, 0xBEAF, CP932, 0, SJIS_Japanese, sizeof(SJIS_Japanese), 4, {0x65E5, 0x672C, 0x8A9E, 0, 0x7F7F}, 5 }, + { 54, 4, 0xBEAF, CP932, MB_ERR_INVALID_CHARS, SJIS_Japanese, sizeof(SJIS_Japanese), 4, {0x65E5, 0x672C, 0x8A9E, 0, 0x7F7F}, 5 }, + /* Japanese CP932 with short buffer */ + { 55, 0, ERROR_INSUFFICIENT_BUFFER, CP932, 0, SJIS_Japanese, sizeof(SJIS_Japanese), 1, {0x65E5, 0x7F7F}, 2 }, + { 56, 0, ERROR_INSUFFICIENT_BUFFER, CP932, MB_ERR_INVALID_CHARS, SJIS_Japanese, sizeof(SJIS_Japanese), 1, {0x65E5, 0x7F7F}, 2 }, +}; - ret = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, "a", sizeof("a"), 0, 0); - ok(ret == 2, "ret should be 2, is %d\n", ret); +static void TestEntry(const ENTRY *pEntry) +{ + int ret, i; + WCHAR Buffer[MAX_BUFFER]; + DWORD Error; + + FillMemory(Buffer, sizeof(Buffer), 0x7F); + SetLastError(0xBEAF); + + if (pEntry->DestLen == 0) + { + ret = MultiByteToWideChar( + pEntry->CodePage, + pEntry->Flags, + pEntry->Src, + pEntry->SrcLen, + NULL, + 0); + } + else + { + ok(pEntry->DestLen >= pEntry->CheckLen - 1, + "#%d: DestLen was shorter than (CheckLen - 1)\n", pEntry->EntryNumber); + if (pEntry->SamePointer) + { + ret = MultiByteToWideChar( + pEntry->CodePage, + pEntry->Flags, + (const char *)Buffer, + pEntry->SrcLen, + Buffer, + pEntry->DestLen); + } + else + { + ret = MultiByteToWideChar( + pEntry->CodePage, + pEntry->Flags, + pEntry->Src, + pEntry->SrcLen, + Buffer, + pEntry->DestLen); + } + } + + Error = GetLastError(); + + ok(ret == pEntry->Return, "#%d: ret expected %d, got %d\n", + pEntry->EntryNumber, pEntry->Return, ret); + ok(Error == pEntry->Error, + "#%d: Wrong last error. Expected %lu, got %lu\n", + pEntry->EntryNumber, pEntry->Error, Error); + + if (pEntry->DestLen) + { + for (i = 0; i < pEntry->CheckLen; ++i) + { + ok(Buffer[i] == pEntry->CheckDest[i], "#%d: Buffer[%d] expected %d, got %d\n", + pEntry->EntryNumber, i, pEntry->CheckDest[i], Buffer[i]); + } + } } + +START_TEST(MultiByteToWideChar) +{ + int i; + for (i = 0; i < _countof(Entries); ++i) + { + TestEntry(&Entries[i]); + } +}