1 /*
2  * PROJECT:         ReactOS api tests
3  * LICENSE:         GPLv2+ - See COPYING in the top level directory
4  * PURPOSE:         Tests for (Rtl)IsTextUnicode.
5  * PROGRAMMERS:     Hermes Belusca-Maito
6  *                  Dmitry Chapyshev
7  */
8 
9 #include "precomp.h"
10 
11 #include <stdio.h>
12 
13 PVOID LoadCodePageData(ULONG Code)
14 {
15     char filename[MAX_PATH], sysdir[MAX_PATH];
16     HANDLE hFile;
17     PVOID Data = NULL;
18     GetSystemDirectoryA(sysdir, MAX_PATH);
19 
20     if (Code != -1)
21         StringCbPrintfA(filename, sizeof(filename),  "%s\\c_%lu.nls", sysdir, Code);
22     else
23         StringCbPrintfA(filename, sizeof(filename),  "%s\\l_intl.nls", sysdir);
24 
25     hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
26     if (hFile != INVALID_HANDLE_VALUE)
27     {
28         DWORD dwRead;
29         DWORD dwFileSize = GetFileSize(hFile, NULL);
30         Data = malloc(dwFileSize);
31         ReadFile(hFile, Data, dwFileSize, &dwRead, NULL);
32         CloseHandle(hFile);
33     }
34     return Data;
35 }
36 
37 /* https://www.microsoft.com/resources/msdn/goglobal/default.mspx */
38 void SetupLocale(ULONG AnsiCode, ULONG OemCode, ULONG Unicode)
39 {
40     NLSTABLEINFO NlsTable;
41     PVOID AnsiCodePageData;
42     PVOID OemCodePageData;
43     PVOID UnicodeCaseTableData;
44 
45     AnsiCodePageData = LoadCodePageData(AnsiCode);
46     OemCodePageData = LoadCodePageData(OemCode);
47     UnicodeCaseTableData = LoadCodePageData(Unicode);
48 
49     RtlInitNlsTables(AnsiCodePageData, OemCodePageData, UnicodeCaseTableData, &NlsTable);
50     RtlResetRtlTranslations(&NlsTable);
51     /* Do NOT free the buffers here, they are directly used!
52         Yes, we leak the old buffers, but this is a test anyway... */
53 
54 }
55 
56 START_TEST(IsTextUnicode)
57 {
58 #define INVALID_FLAG    0xFFFFFFFF
59 
60 #define NEW_TEST(Buffer, Flags, ResultFlags, Success)   \
61     { (PVOID)(Buffer), sizeof((Buffer)), (Flags), (ResultFlags), (Success) }
62 
63     static struct
64     {
65         /* Input */
66         PVOID Buffer;
67         INT   Size;
68         INT   Flags;
69 
70         /* Output */
71         INT   ResultFlags;
72         BOOL  Success;
73     } Tests[] =
74     {
75         /* ANSI string */
76 
77         // 0
78         NEW_TEST("ANSI string", IS_TEXT_UNICODE_ASCII16, 0, FALSE),
79         NEW_TEST("ANSI string", IS_TEXT_UNICODE_STATISTICS, 0, FALSE),
80         NEW_TEST("ANSI string", INVALID_FLAG, 0, FALSE),
81 
82         /* UNICODE strings */
83 
84         // 3
85         NEW_TEST(L"a", IS_TEXT_UNICODE_ASCII16, IS_TEXT_UNICODE_ASCII16, TRUE),
86         NEW_TEST(L"a", IS_TEXT_UNICODE_UNICODE_MASK, IS_TEXT_UNICODE_STATISTICS | IS_TEXT_UNICODE_ASCII16, TRUE),
87         NEW_TEST(L"a", IS_TEXT_UNICODE_STATISTICS, IS_TEXT_UNICODE_STATISTICS, TRUE),
88         NEW_TEST(L"a", INVALID_FLAG, 0, TRUE),
89 
90         // 7
91         NEW_TEST(L"UNICODE String 0", IS_TEXT_UNICODE_ASCII16, 0, FALSE),
92         NEW_TEST(L"UNICODE String 0", IS_TEXT_UNICODE_UNICODE_MASK, IS_TEXT_UNICODE_CONTROLS | IS_TEXT_UNICODE_STATISTICS, TRUE),
93         NEW_TEST(L"UNICODE String 0", IS_TEXT_UNICODE_STATISTICS, IS_TEXT_UNICODE_STATISTICS, TRUE),
94         NEW_TEST(L"UNICODE String 0", INVALID_FLAG, 0, TRUE),
95 
96         // 11
97         NEW_TEST(L"\xFEFF" L"UNICODE String 1", IS_TEXT_UNICODE_ASCII16, 0, FALSE),
98         NEW_TEST(L"\xFEFF" L"UNICODE String 1", IS_TEXT_UNICODE_UNICODE_MASK, IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_CONTROLS, TRUE),
99         NEW_TEST(L"\xFEFF" L"UNICODE String 1", IS_TEXT_UNICODE_STATISTICS, 0, FALSE),
100         NEW_TEST(L"\xFEFF" L"UNICODE String 1", INVALID_FLAG, 0, TRUE),
101 
102         // 15
103         NEW_TEST(L"\xFFFE" L"UNICODE String 2", IS_TEXT_UNICODE_ASCII16, 0, FALSE),
104         NEW_TEST(L"\xFFFE" L"UNICODE String 2", IS_TEXT_UNICODE_UNICODE_MASK, IS_TEXT_UNICODE_CONTROLS, TRUE),
105         NEW_TEST(L"\xFFFE" L"UNICODE String 2", IS_TEXT_UNICODE_STATISTICS, 0, FALSE),
106         NEW_TEST(L"\xFFFE" L"UNICODE String 2", INVALID_FLAG, 0, FALSE),
107 
108         // 19
109         NEW_TEST(L"UNICODE String 3 Привет!", IS_TEXT_UNICODE_ASCII16, 0, FALSE),
110         NEW_TEST(L"UNICODE String 3 Привет!", IS_TEXT_UNICODE_UNICODE_MASK, IS_TEXT_UNICODE_CONTROLS | IS_TEXT_UNICODE_STATISTICS, TRUE),
111         NEW_TEST(L"UNICODE String 3 Привет!", IS_TEXT_UNICODE_STATISTICS, IS_TEXT_UNICODE_STATISTICS, TRUE),
112         NEW_TEST(L"UNICODE String 3 Привет!", INVALID_FLAG, 0, TRUE),
113 
114         // 23
115         NEW_TEST(L"\xFEFF" L"UNICODE String 4 Привет!", IS_TEXT_UNICODE_ASCII16, 0, FALSE),
116         NEW_TEST(L"\xFEFF" L"UNICODE String 4 Привет!", IS_TEXT_UNICODE_UNICODE_MASK, IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_CONTROLS, TRUE),
117         NEW_TEST(L"\xFEFF" L"UNICODE String 4 Привет!", IS_TEXT_UNICODE_STATISTICS, 0, FALSE),
118         NEW_TEST(L"\xFEFF" L"UNICODE String 4 Привет!", INVALID_FLAG, 0, TRUE),
119 
120         // 27
121         NEW_TEST(L"\xFFFE" L"UNICODE String 5 Привет!", IS_TEXT_UNICODE_ASCII16, 0, FALSE),
122         NEW_TEST(L"\xFFFE" L"UNICODE String 5 Привет!", IS_TEXT_UNICODE_UNICODE_MASK, IS_TEXT_UNICODE_CONTROLS, TRUE),
123         NEW_TEST(L"\xFFFE" L"UNICODE String 5 Привет!", IS_TEXT_UNICODE_STATISTICS, 0, FALSE),
124         NEW_TEST(L"\xFFFE" L"UNICODE String 5 Привет!", INVALID_FLAG, 0, FALSE),
125 
126         // 31
127         /* Reverse BOM */
128         NEW_TEST(L"UNICODE S" L"\xFFFE" L"tring 5 Привет!", IS_TEXT_UNICODE_ILLEGAL_CHARS, IS_TEXT_UNICODE_ILLEGAL_CHARS, FALSE),
129         /* UNICODE_NUL */
130         NEW_TEST(L"UNICODE S" L"\x0000" L"tring 5 Привет!", IS_TEXT_UNICODE_ILLEGAL_CHARS, IS_TEXT_UNICODE_ILLEGAL_CHARS, FALSE),
131         /* ASCII CRLF (packed into one word) */
132         NEW_TEST(L"UNICODE S" L"\x0A0D" L"tring 5 Привет!", IS_TEXT_UNICODE_ILLEGAL_CHARS, IS_TEXT_UNICODE_ILLEGAL_CHARS, FALSE),
133         /* Unicode 0xFFFF */
134         NEW_TEST(L"UNICODE S" L"\xFFFF" L"tring 5 Привет!", IS_TEXT_UNICODE_ILLEGAL_CHARS, IS_TEXT_UNICODE_ILLEGAL_CHARS, FALSE),
135 
136         // 35
137         NEW_TEST(L"UNICODE String 0", IS_TEXT_UNICODE_DBCS_LEADBYTE, 0, FALSE)
138     };
139 
140     const char japanese_with_lead[] = "ABC" "\x83\x40" "D";
141     const char simplfied_chinese_with_lead[] = "ABC" "\xC5\xC5" "D";
142     const char korean_with_lead[] = "ABC" "\xBF\xAD" "D";
143     const char traditional_chinese_with_lead[] = "ABC" "\xB1\xC1" "D";
144 
145     UINT i;
146     BOOL Success;
147     INT Result;
148 
149     for (i = 0; i < ARRAYSIZE(Tests); ++i)
150     {
151         Result = Tests[i].Flags;
152         Success = IsTextUnicode(Tests[i].Buffer, Tests[i].Size, ((Result != INVALID_FLAG) ? &Result : NULL));
153         ok(Success == Tests[i].Success, "IsTextUnicode(%u) returned 0x%x, expected %s\n", i, Success, (Tests[i].Success ? "TRUE" : "FALSE"));
154         if (Result != INVALID_FLAG)
155             ok(Result == Tests[i].ResultFlags, "IsTextUnicode(%u) Result returned 0x%x, expected 0x%x\n", i, Result, Tests[i].ResultFlags);
156     }
157 
158     /* Japanese */
159     SetupLocale(932, 932, -1);
160 
161     Result = IS_TEXT_UNICODE_DBCS_LEADBYTE;
162     ok(!IsTextUnicode(japanese_with_lead, sizeof(japanese_with_lead), &Result), "IsTextUnicode() returned TRUE, expected FALSE\n");
163     ok(Result == IS_TEXT_UNICODE_DBCS_LEADBYTE, "Result returned 0x%x, expected 0x%x\n", Result, IS_TEXT_UNICODE_DBCS_LEADBYTE);
164 
165     /* Simplified Chinese */
166     SetupLocale(936, 936, -1);
167 
168     Result = IS_TEXT_UNICODE_DBCS_LEADBYTE;
169     ok(!IsTextUnicode(simplfied_chinese_with_lead, sizeof(simplfied_chinese_with_lead), &Result), "IsTextUnicode() returned TRUE, expected FALSE\n");
170     ok(Result == IS_TEXT_UNICODE_DBCS_LEADBYTE, "Result returned 0x%x, expected 0x%x\n", Result, IS_TEXT_UNICODE_DBCS_LEADBYTE);
171 
172     /* Korean */
173     SetupLocale(949, 949, -1);
174 
175     Result = IS_TEXT_UNICODE_DBCS_LEADBYTE;
176     ok(!IsTextUnicode(korean_with_lead, sizeof(korean_with_lead), &Result), "IsTextUnicode() returned TRUE, expected FALSE\n");
177     ok(Result == IS_TEXT_UNICODE_DBCS_LEADBYTE, "Result returned 0x%x, expected 0x%x\n", Result, IS_TEXT_UNICODE_DBCS_LEADBYTE);
178 
179     /* Traditional Chinese */
180     SetupLocale(950, 950, -1);
181 
182     Result = IS_TEXT_UNICODE_DBCS_LEADBYTE;
183     ok(!IsTextUnicode(traditional_chinese_with_lead, sizeof(traditional_chinese_with_lead), &Result), "IsTextUnicode() returned TRUE, expected FALSE\n");
184     ok(Result == IS_TEXT_UNICODE_DBCS_LEADBYTE, "Result returned 0x%x, expected 0x%x\n", Result, IS_TEXT_UNICODE_DBCS_LEADBYTE);
185 }
186