kernel32: Fix base for value returned with LOCALE_RETURN_NUMBER.
[wine/multimedia.git] / dlls / kernel32 / tests / locale.c
blob82bfdeccc83acaa58196a3c4a5da7769ba55c4bc
1 /*
2 * Unit tests for locale functions
4 * Copyright 2002 YASAR Mehmet
5 * Copyright 2003 Dmitry Timoshkov
6 * Copyright 2003 Jon Griffiths
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 * NOTES
23 * We must pass LOCALE_NOUSEROVERRIDE (NUO) to formatting functions so that
24 * even when the user has overridden their default i8n settings (e.g. in
25 * the control panel i8n page), we will still get the expected results.
28 #include <assert.h>
29 #include <stdlib.h>
30 #include <stdarg.h>
31 #include <stdio.h>
33 #include "wine/test.h"
34 #include "windef.h"
35 #include "winbase.h"
36 #include "winerror.h"
37 #include "winnls.h"
39 static const WCHAR upper_case[] = {'\t','J','U','S','T','!',' ','A',',',' ','T','E','S','T',';',' ','S','T','R','I','N','G',' ','1','/','*','+','-','.','\r','\n',0};
40 static const WCHAR lower_case[] = {'\t','j','u','s','t','!',' ','a',',',' ','t','e','s','t',';',' ','s','t','r','i','n','g',' ','1','/','*','+','-','.','\r','\n',0};
41 static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
42 static const WCHAR fooW[] = {'f','o','o',0};
44 static inline unsigned int strlenW( const WCHAR *str )
46 const WCHAR *s = str;
47 while (*s) s++;
48 return s - str;
51 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
53 if (n <= 0) return 0;
54 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
55 return *str1 - *str2;
58 static inline WCHAR *strchrW( const WCHAR *str, WCHAR ch )
60 do { if (*str == ch) return (WCHAR *)str; } while (*str++);
61 return NULL;
64 static inline int isdigitW( WCHAR wc )
66 WORD type;
67 GetStringTypeW( CT_CTYPE1, &wc, 1, &type );
68 return type & C1_DIGIT;
71 /* Some functions are only in later versions of kernel32.dll */
72 static HMODULE hKernel32;
73 static WORD enumCount;
75 static BOOL (WINAPI *pEnumSystemLanguageGroupsA)(LANGUAGEGROUP_ENUMPROC, DWORD, LONG_PTR);
76 static BOOL (WINAPI *pEnumLanguageGroupLocalesA)(LANGGROUPLOCALE_ENUMPROC, LGRPID, DWORD, LONG_PTR);
77 static BOOL (WINAPI *pEnumUILanguagesA)(UILANGUAGE_ENUMPROC, DWORD, LONG_PTR);
78 static BOOL (WINAPI *pEnumSystemLocalesEx)(LOCALE_ENUMPROCEX, DWORD, LPARAM, LPVOID);
79 static INT (WINAPI *pLCMapStringEx)(LPCWSTR, DWORD, LPCWSTR, INT, LPWSTR, INT, LPNLSVERSIONINFO, LPVOID, LPARAM);
80 static LCID (WINAPI *pLocaleNameToLCID)(LPCWSTR, DWORD);
81 static INT (WINAPI *pLCIDToLocaleName)(LCID, LPWSTR, INT, DWORD);
82 static INT (WINAPI *pFoldStringA)(DWORD, LPCSTR, INT, LPSTR, INT);
83 static INT (WINAPI *pFoldStringW)(DWORD, LPCWSTR, INT, LPWSTR, INT);
84 static BOOL (WINAPI *pIsValidLanguageGroup)(LGRPID, DWORD);
85 static INT (WINAPI *pIdnToNameprepUnicode)(DWORD, LPCWSTR, INT, LPWSTR, INT);
86 static INT (WINAPI *pIdnToAscii)(DWORD, LPCWSTR, INT, LPWSTR, INT);
87 static INT (WINAPI *pIdnToUnicode)(DWORD, LPCWSTR, INT, LPWSTR, INT);
88 static INT (WINAPI *pGetLocaleInfoEx)(LPCWSTR, LCTYPE, LPWSTR, INT);
90 static void InitFunctionPointers(void)
92 hKernel32 = GetModuleHandleA("kernel32");
93 pEnumSystemLanguageGroupsA = (void*)GetProcAddress(hKernel32, "EnumSystemLanguageGroupsA");
94 pEnumLanguageGroupLocalesA = (void*)GetProcAddress(hKernel32, "EnumLanguageGroupLocalesA");
95 pLocaleNameToLCID = (void*)GetProcAddress(hKernel32, "LocaleNameToLCID");
96 pLCIDToLocaleName = (void*)GetProcAddress(hKernel32, "LCIDToLocaleName");
97 pLCMapStringEx = (void*)GetProcAddress(hKernel32, "LCMapStringEx");
98 pFoldStringA = (void*)GetProcAddress(hKernel32, "FoldStringA");
99 pFoldStringW = (void*)GetProcAddress(hKernel32, "FoldStringW");
100 pIsValidLanguageGroup = (void*)GetProcAddress(hKernel32, "IsValidLanguageGroup");
101 pEnumUILanguagesA = (void*)GetProcAddress(hKernel32, "EnumUILanguagesA");
102 pEnumSystemLocalesEx = (void*)GetProcAddress(hKernel32, "EnumSystemLocalesEx");
103 pIdnToNameprepUnicode = (void*)GetProcAddress(hKernel32, "IdnToNameprepUnicode");
104 pIdnToAscii = (void*)GetProcAddress(hKernel32, "IdnToAscii");
105 pIdnToUnicode = (void*)GetProcAddress(hKernel32, "IdnToUnicode");
106 pGetLocaleInfoEx = (void*)GetProcAddress(hKernel32, "GetLocaleInfoEx");
109 #define eq(received, expected, label, type) \
110 ok((received) == (expected), "%s: got " type " instead of " type "\n", \
111 (label), (received), (expected))
113 #define BUFFER_SIZE 128
114 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
116 #define STRINGSA(x,y) strcpy(input, x); strcpy(Expected, y); SetLastError(0xdeadbeef); buffer[0] = '\0'
117 #define EXPECT_LENA ok(ret == lstrlen(Expected)+1, "Expected Len %d, got %d\n", lstrlen(Expected)+1, ret)
118 #define EXPECT_EQA ok(strncmp(buffer, Expected, strlen(Expected)) == 0, \
119 "Expected '%s', got '%s'\n", Expected, buffer)
121 #define STRINGSW(x,y) MultiByteToWideChar(CP_ACP,0,x,-1,input,COUNTOF(input)); \
122 MultiByteToWideChar(CP_ACP,0,y,-1,Expected,COUNTOF(Expected)); \
123 SetLastError(0xdeadbeef); buffer[0] = '\0'
124 #define EXPECT_LENW ok(ret == lstrlenW(Expected)+1, "Expected Len %d, got %d\n", lstrlenW(Expected)+1, ret)
125 #define EXPECT_EQW ok(strncmpW(buffer, Expected, strlenW(Expected)) == 0, "Bad conversion\n")
127 #define NUO LOCALE_NOUSEROVERRIDE
129 static void test_GetLocaleInfoA(void)
131 int ret;
132 int len;
133 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
134 char buffer[BUFFER_SIZE];
135 char expected[BUFFER_SIZE];
136 DWORD val;
138 ok(lcid == 0x409, "wrong LCID calculated - %d\n", lcid);
140 ret = GetLocaleInfoA(lcid, LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER, (char*)&val, sizeof(val));
141 ok(ret, "got %d\n", ret);
142 ok(val == lcid, "got 0x%08x\n", val);
144 /* en and ar use SUBLANG_NEUTRAL, but GetLocaleInfo assume SUBLANG_DEFAULT
145 Same is true for zh on pre-Vista, but on Vista and higher GetLocaleInfo
146 assumes SUBLANG_NEUTRAL for zh */
147 memset(expected, 0, COUNTOF(expected));
148 len = GetLocaleInfoA(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
149 SetLastError(0xdeadbeef);
150 memset(buffer, 0, COUNTOF(buffer));
151 ret = GetLocaleInfoA(LANG_ENGLISH, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
152 ok((ret == len) && !lstrcmpA(buffer, expected),
153 "got %d with '%s' (expected %d with '%s')\n",
154 ret, buffer, len, expected);
156 memset(expected, 0, COUNTOF(expected));
157 len = GetLocaleInfoA(MAKELANGID(LANG_ARABIC, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
158 if (len) {
159 SetLastError(0xdeadbeef);
160 memset(buffer, 0, COUNTOF(buffer));
161 ret = GetLocaleInfoA(LANG_ARABIC, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
162 ok((ret == len) && !lstrcmpA(buffer, expected),
163 "got %d with '%s' (expected %d with '%s')\n",
164 ret, buffer, len, expected);
166 else
167 win_skip("LANG_ARABIC not installed\n");
169 /* SUBLANG_DEFAULT is required for mlang.dll, but optional for GetLocaleInfo */
170 memset(expected, 0, COUNTOF(expected));
171 len = GetLocaleInfoA(MAKELANGID(LANG_GERMAN, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
172 SetLastError(0xdeadbeef);
173 memset(buffer, 0, COUNTOF(buffer));
174 ret = GetLocaleInfoA(LANG_GERMAN, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
175 ok((ret == len) && !lstrcmpA(buffer, expected),
176 "got %d with '%s' (expected %d with '%s')\n",
177 ret, buffer, len, expected);
180 /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
181 * partially fill the buffer even if it is too short. See bug 637.
183 SetLastError(0xdeadbeef);
184 memset(buffer, 0, COUNTOF(buffer));
185 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 0);
186 ok(ret == 7 && !buffer[0], "Expected len=7, got %d\n", ret);
188 SetLastError(0xdeadbeef);
189 memset(buffer, 0, COUNTOF(buffer));
190 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 3);
191 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
192 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
193 ok(!strcmp(buffer, "Mon"), "Expected 'Mon', got '%s'\n", buffer);
195 SetLastError(0xdeadbeef);
196 memset(buffer, 0, COUNTOF(buffer));
197 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 10);
198 ok(ret == 7, "Expected ret == 7, got %d, error %d\n", ret, GetLastError());
199 ok(!strcmp(buffer, "Monday"), "Expected 'Monday', got '%s'\n", buffer);
202 struct neutralsublang_name2_t {
203 WCHAR name[3];
204 LCID lcid;
205 LCID lcid_broken;
206 int todo;
209 static const struct neutralsublang_name2_t neutralsublang_names2[] = {
210 { {'a','r',0}, MAKELCID(MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA), SORT_DEFAULT) },
211 { {'a','z',0}, MAKELCID(MAKELANGID(LANG_AZERI, SUBLANG_AZERI_LATIN), SORT_DEFAULT) },
212 { {'d','e',0}, MAKELCID(MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN), SORT_DEFAULT) },
213 { {'e','n',0}, MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT) },
214 { {'e','s',0}, MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN), SORT_DEFAULT),
215 MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH), SORT_DEFAULT) /* vista */, 1 },
216 { {'g','a',0}, MAKELCID(MAKELANGID(LANG_IRISH, SUBLANG_IRISH_IRELAND), SORT_DEFAULT), 0, 1 },
217 { {'i','t',0}, MAKELCID(MAKELANGID(LANG_ITALIAN, SUBLANG_ITALIAN), SORT_DEFAULT) },
218 { {'m','s',0}, MAKELCID(MAKELANGID(LANG_MALAY, SUBLANG_MALAY_MALAYSIA), SORT_DEFAULT) },
219 { {'n','l',0}, MAKELCID(MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH), SORT_DEFAULT) },
220 { {'p','t',0}, MAKELCID(MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN), SORT_DEFAULT) },
221 { {'s','r',0}, MAKELCID(MAKELANGID(LANG_SERBIAN, SUBLANG_SERBIAN_CROATIA), SORT_DEFAULT) },
222 { {'s','v',0}, MAKELCID(MAKELANGID(LANG_SWEDISH, SUBLANG_SWEDISH), SORT_DEFAULT) },
223 { {'u','z',0}, MAKELCID(MAKELANGID(LANG_UZBEK, SUBLANG_UZBEK_LATIN), SORT_DEFAULT) },
224 { {'z','h',0}, MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT), 0, 1 },
225 { {0} }
228 static void test_GetLocaleInfoW(void)
230 LCID lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
231 LCID lcid_ru = MAKELCID(MAKELANGID(LANG_RUSSIAN, SUBLANG_NEUTRAL), SORT_DEFAULT);
232 LCID lcid_en_neut = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL), SORT_DEFAULT);
233 WCHAR bufferW[80], buffer2W[80];
234 CHAR bufferA[80];
235 DWORD val;
236 DWORD ret;
237 INT i;
239 ret = GetLocaleInfoW(lcid_en, LOCALE_SMONTHNAME1, bufferW, COUNTOF(bufferW));
240 if (!ret) {
241 win_skip("GetLocaleInfoW() isn't implemented\n");
242 return;
245 ret = GetLocaleInfoW(lcid_en, LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER, (WCHAR*)&val, sizeof(val)/sizeof(WCHAR));
246 ok(ret, "got %d\n", ret);
247 ok(val == lcid_en, "got 0x%08x\n", val);
249 ret = GetLocaleInfoW(lcid_en_neut, LOCALE_SNAME, bufferW, COUNTOF(bufferW));
250 if (ret)
252 static const WCHAR slangW[] = {'E','n','g','l','i','s','h',' ','(','U','n','i','t','e','d',' ',
253 'S','t','a','t','e','s',')',0};
254 static const WCHAR statesW[] = {'U','n','i','t','e','d',' ','S','t','a','t','e','s',0};
255 static const WCHAR enW[] = {'e','n','-','U','S',0};
256 const struct neutralsublang_name2_t *ptr = neutralsublang_names2;
258 ok(!lstrcmpW(bufferW, enW), "got wrong name %s\n", wine_dbgstr_w(bufferW));
260 ret = GetLocaleInfoW(lcid_en_neut, LOCALE_SCOUNTRY, bufferW, COUNTOF(bufferW));
261 ok(ret, "got %d\n", ret);
262 ok(!lstrcmpW(statesW, bufferW), "got wrong name %s\n", wine_dbgstr_w(bufferW));
264 ret = GetLocaleInfoW(lcid_en_neut, LOCALE_SLANGUAGE, bufferW, COUNTOF(bufferW));
265 ok(ret, "got %d\n", ret);
266 ok(!lstrcmpW(slangW, bufferW), "got wrong name %s\n", wine_dbgstr_w(bufferW));
268 while (*ptr->name)
270 LANGID langid;
272 /* make neutral lcid */
273 langid = MAKELANGID(PRIMARYLANGID(LANGIDFROMLCID(ptr->lcid)), SUBLANG_NEUTRAL);
275 val = 0;
276 GetLocaleInfoW(MAKELCID(langid, SORT_DEFAULT), LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER, (WCHAR*)&val, sizeof(val)/sizeof(WCHAR));
277 if (ptr->todo)
279 todo_wine
280 ok(val == ptr->lcid || (val && broken(val == ptr->lcid_broken)), "%s: got wrong lcid 0x%04x, expected 0x%04x\n",
281 wine_dbgstr_w(ptr->name), val, ptr->lcid);
283 else
284 ok(val == ptr->lcid || (val && broken(val == ptr->lcid_broken)), "%s: got wrong lcid 0x%04x, expected 0x%04x\n",
285 wine_dbgstr_w(ptr->name), val, ptr->lcid);
286 ptr++;
289 else
290 win_skip("English neutral locale not supported\n");
292 ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1, bufferW, COUNTOF(bufferW));
293 if (!ret) {
294 win_skip("LANG_RUSSIAN locale data unavailable\n");
295 return;
297 ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1|LOCALE_RETURN_GENITIVE_NAMES,
298 bufferW, COUNTOF(bufferW));
299 if (!ret) {
300 win_skip("LOCALE_RETURN_GENITIVE_NAMES isn't supported\n");
301 return;
304 /* LOCALE_RETURN_GENITIVE_NAMES isn't supported for GetLocaleInfoA */
305 bufferA[0] = 'a';
306 SetLastError(0xdeadbeef);
307 ret = GetLocaleInfoA(lcid_ru, LOCALE_SMONTHNAME1|LOCALE_RETURN_GENITIVE_NAMES,
308 bufferA, COUNTOF(bufferA));
309 ok(ret == 0, "LOCALE_RETURN_GENITIVE_NAMES should fail with GetLocaleInfoA\n");
310 ok(bufferA[0] == 'a', "Expected buffer to be untouched\n");
311 ok(GetLastError() == ERROR_INVALID_FLAGS,
312 "Expected ERROR_INVALID_FLAGS, got %x\n", GetLastError());
314 bufferW[0] = 'a';
315 SetLastError(0xdeadbeef);
316 ret = GetLocaleInfoW(lcid_ru, LOCALE_RETURN_GENITIVE_NAMES,
317 bufferW, COUNTOF(bufferW));
318 ok(ret == 0,
319 "LOCALE_RETURN_GENITIVE_NAMES itself doesn't return anything, got %d\n", ret);
320 ok(bufferW[0] == 'a', "Expected buffer to be untouched\n");
321 ok(GetLastError() == ERROR_INVALID_FLAGS,
322 "Expected ERROR_INVALID_FLAGS, got %x\n", GetLastError());
324 /* yes, test empty 13 month entry too */
325 for (i = 0; i < 12; i++) {
326 bufferW[0] = 0;
327 ret = GetLocaleInfoW(lcid_ru, (LOCALE_SMONTHNAME1+i)|LOCALE_RETURN_GENITIVE_NAMES,
328 bufferW, COUNTOF(bufferW));
329 ok(ret, "Expected non zero result\n");
330 ok(ret == lstrlenW(bufferW)+1, "Expected actual length, got %d, length %d\n",
331 ret, lstrlenW(bufferW));
332 buffer2W[0] = 0;
333 ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1+i,
334 buffer2W, COUNTOF(buffer2W));
335 ok(ret, "Expected non zero result\n");
336 ok(ret == lstrlenW(buffer2W)+1, "Expected actual length, got %d, length %d\n",
337 ret, lstrlenW(buffer2W));
339 ok(lstrcmpW(bufferW, buffer2W) != 0,
340 "Expected genitive name to differ, got the same for month %d\n", i+1);
342 /* for locale without genitive names nominative returned in both cases */
343 bufferW[0] = 0;
344 ret = GetLocaleInfoW(lcid_en, (LOCALE_SMONTHNAME1+i)|LOCALE_RETURN_GENITIVE_NAMES,
345 bufferW, COUNTOF(bufferW));
346 ok(ret, "Expected non zero result\n");
347 ok(ret == lstrlenW(bufferW)+1, "Expected actual length, got %d, length %d\n",
348 ret, lstrlenW(bufferW));
349 buffer2W[0] = 0;
350 ret = GetLocaleInfoW(lcid_en, LOCALE_SMONTHNAME1+i,
351 buffer2W, COUNTOF(buffer2W));
352 ok(ret, "Expected non zero result\n");
353 ok(ret == lstrlenW(buffer2W)+1, "Expected actual length, got %d, length %d\n",
354 ret, lstrlenW(buffer2W));
356 ok(lstrcmpW(bufferW, buffer2W) == 0,
357 "Expected same names, got different for month %d\n", i+1);
361 static void test_GetTimeFormatA(void)
363 int ret;
364 SYSTEMTIME curtime;
365 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
366 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
368 memset(&curtime, 2, sizeof(SYSTEMTIME));
369 STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
370 SetLastError(0xdeadbeef);
371 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
372 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
373 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
375 curtime.wHour = 8;
376 curtime.wMinute = 56;
377 curtime.wSecond = 13;
378 curtime.wMilliseconds = 22;
379 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
380 SetLastError(0xdeadbeef);
381 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
382 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
383 EXPECT_LENA; EXPECT_EQA;
385 /* MSDN: LOCALE_NOUSEROVERRIDE can't be specified with a format string */
386 SetLastError(0xdeadbeef);
387 ret = GetTimeFormatA(lcid, NUO|TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
388 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
389 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
391 STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficient buffer */
392 SetLastError(0xdeadbeef);
393 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, 2);
394 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
395 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
397 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
398 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, NULL, 0);
399 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
400 EXPECT_LENA;
402 STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
403 ret = GetTimeFormatA(lcid, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
404 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
405 EXPECT_LENA; EXPECT_EQA;
407 STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
408 ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
409 ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
410 ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "4" )), /* win9x */
411 "Expected '', got '%s'\n", buffer );
413 STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
414 ret = GetTimeFormatA(lcid, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
415 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
416 EXPECT_LENA; EXPECT_EQA;
418 STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
419 strcpy(Expected, "8:56 AM");
420 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
421 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
422 EXPECT_LENA; EXPECT_EQA;
424 STRINGSA("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
425 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
426 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
427 ok( !strcmp( buffer, "8.@:56AM" ) || broken( !strcmp( buffer, "8.@:56.@:AM" )) /* win9x */,
428 "Expected '8.@:56AM', got '%s'\n", buffer );
430 STRINGSA("s1s2s3", ""); /* Duplicate tokens */
431 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
432 ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
433 ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "3" )), /* win9x */
434 "Expected '', got '%s'\n", buffer );
436 STRINGSA("t/tt", "A/AM"); /* AM time marker */
437 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
438 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
439 EXPECT_LENA; EXPECT_EQA;
441 curtime.wHour = 13;
442 STRINGSA("t/tt", "P/PM"); /* PM time marker */
443 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
444 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
445 EXPECT_LENA; EXPECT_EQA;
447 STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
448 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
449 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
450 EXPECT_LENA; EXPECT_EQA;
452 STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
453 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
454 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
455 EXPECT_LENA; EXPECT_EQA;
457 STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
458 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
459 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
460 EXPECT_LENA; EXPECT_EQA;
462 curtime.wHour = 14; /* change this to 14 or 2pm */
463 curtime.wMinute = 5;
464 curtime.wSecond = 3;
465 STRINGSA("h hh H HH m mm s ss t tt", "2 02 14 14 5 05 3 03 P PM"); /* 24 hrs, leading 0 */
466 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
467 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
468 EXPECT_LENA; EXPECT_EQA;
470 curtime.wHour = 0;
471 STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
472 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
473 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
474 EXPECT_LENA; EXPECT_EQA;
476 STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
477 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
478 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
479 EXPECT_LENA; EXPECT_EQA;
481 /* try to convert formatting strings with more than two letters
482 * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
483 * NOTE: We expect any letter for which there is an upper case value
484 * we should see a replacement. For letters that DO NOT have
485 * upper case values we should see NO REPLACEMENT.
487 curtime.wHour = 8;
488 curtime.wMinute = 56;
489 curtime.wSecond = 13;
490 curtime.wMilliseconds = 22;
491 STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
492 "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
493 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
494 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
495 EXPECT_LENA; EXPECT_EQA;
497 STRINGSA("h", "text"); /* Don't write to buffer if len is 0 */
498 strcpy(buffer, "text");
499 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, 0);
500 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
501 EXPECT_EQA;
503 STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
504 "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
505 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
506 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
507 EXPECT_LENA; EXPECT_EQA;
509 STRINGSA("'''", "'"); /* invalid quoted string */
510 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
511 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
512 EXPECT_LENA; EXPECT_EQA;
514 /* test that msdn suggested single quotation usage works as expected */
515 STRINGSA("''''", "'"); /* single quote mark */
516 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
517 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
518 EXPECT_LENA; EXPECT_EQA;
520 STRINGSA("''HHHHHH", "08"); /* Normal use */
521 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
522 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
523 EXPECT_LENA; EXPECT_EQA;
525 /* and test for normal use of the single quotation mark */
526 STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
527 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
528 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
529 EXPECT_LENA; EXPECT_EQA;
531 STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
532 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
533 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
534 EXPECT_LENA; EXPECT_EQA;
536 STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
537 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
538 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
539 EXPECT_LENA; EXPECT_EQA;
541 curtime.wHour = 25;
542 STRINGSA("'123'tt", ""); /* Invalid time */
543 SetLastError(0xdeadbeef);
544 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
545 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
546 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
548 curtime.wHour = 12;
549 curtime.wMonth = 60; /* Invalid */
550 STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
551 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
552 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
553 EXPECT_LENA; EXPECT_EQA;
556 static void test_GetDateFormatA(void)
558 int ret;
559 SYSTEMTIME curtime;
560 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
561 LCID lcid_ru = MAKELCID(MAKELANGID(LANG_RUSSIAN, SUBLANG_NEUTRAL), SORT_DEFAULT);
562 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
563 char Broken[BUFFER_SIZE];
564 char short_day[10], month[10], genitive_month[10];
566 memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
567 STRINGSA("ddd',' MMM dd yy","");
568 SetLastError(0xdeadbeef);
569 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
570 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
571 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
573 curtime.wYear = 2002;
574 curtime.wMonth = 5;
575 curtime.wDay = 4;
576 curtime.wDayOfWeek = 3;
577 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
578 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
579 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
580 EXPECT_LENA; EXPECT_EQA;
582 /* Same as above but with LOCALE_NOUSEROVERRIDE */
583 STRINGSA("ddd',' MMM dd yy",""); /* Simple case */
584 SetLastError(0xdeadbeef);
585 ret = GetDateFormatA(lcid, NUO, &curtime, input, buffer, COUNTOF(buffer));
586 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
587 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
588 EXPECT_EQA;
590 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
591 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
592 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
593 EXPECT_LENA; EXPECT_EQA;
595 curtime.wHour = 36; /* Invalid */
596 STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
597 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
598 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
599 EXPECT_LENA; EXPECT_EQA;
601 STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
602 ret = GetDateFormatA(lcid, 0, &curtime, input, NULL, 0);
603 ok(ret == 16, "Expected ret == 16, got %d, error %d\n", ret, GetLastError());
604 EXPECT_EQA;
606 STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
607 SetLastError(0xdeadbeef);
608 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, 2);
609 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
610 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
612 STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
613 ret = GetDateFormat(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
614 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
615 if (strncmp(buffer, Expected, strlen(Expected)) && strncmp(buffer, "5/4/02", strlen(Expected)) != 0)
616 ok (0, "Expected '%s' or '5/4/02', got '%s'\n", Expected, buffer);
618 STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
619 ret = GetDateFormat(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
620 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
621 EXPECT_LENA; EXPECT_EQA;
623 /* test for expected DATE_YEARMONTH behavior with null format */
624 /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
625 STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
626 SetLastError(0xdeadbeef);
627 ret = GetDateFormat(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
628 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
629 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
630 EXPECT_EQA;
632 /* Test that using invalid DATE_* flags results in the correct error */
633 /* and return values */
634 STRINGSA("m/d/y", ""); /* Invalid flags */
635 SetLastError(0xdeadbeef);
636 ret = GetDateFormat(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
637 &curtime, input, buffer, COUNTOF(buffer));
638 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
639 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
641 ret = GetDateFormat(lcid_ru, 0, &curtime, "ddMMMM", buffer, COUNTOF(buffer));
642 if (!ret)
644 win_skip("LANG_RUSSIAN locale data unavailable\n");
645 return;
648 /* month part should be in genitive form */
649 strcpy(genitive_month, buffer + 2);
650 ret = GetDateFormat(lcid_ru, 0, &curtime, "MMMM", buffer, COUNTOF(buffer));
651 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
652 strcpy(month, buffer);
653 ok(strcmp(genitive_month, month) != 0, "Expected different month forms\n");
655 ret = GetDateFormat(lcid_ru, 0, &curtime, "ddd", buffer, COUNTOF(buffer));
656 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
657 strcpy(short_day, buffer);
659 STRINGSA("dd MMMMddd dd", "");
660 sprintf(Expected, "04 %s%s 04", genitive_month, short_day);
661 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
662 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
663 EXPECT_EQA;
665 STRINGSA("MMMMddd dd", "");
666 sprintf(Expected, "%s%s 04", month, short_day);
667 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
668 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
669 EXPECT_EQA;
671 STRINGSA("MMMMddd", "");
672 sprintf(Expected, "%s%s", month, short_day);
673 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
674 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
675 EXPECT_EQA;
677 STRINGSA("MMMMdd", "");
678 sprintf(Expected, "%s04", genitive_month);
679 sprintf(Broken, "%s04", month);
680 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
681 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
682 ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
683 broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
684 "Expected '%s', got '%s'\n", Expected, buffer);
686 STRINGSA("MMMMdd ddd", "");
687 sprintf(Expected, "%s04 %s", genitive_month, short_day);
688 sprintf(Broken, "%s04 %s", month, short_day);
689 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
690 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
691 ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
692 broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
693 "Expected '%s', got '%s'\n", Expected, buffer);
695 STRINGSA("dd dddMMMM", "");
696 sprintf(Expected, "04 %s%s", short_day, month);
697 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
698 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
699 EXPECT_EQA;
701 STRINGSA("dd dddMMMM ddd MMMMdd", "");
702 sprintf(Expected, "04 %s%s %s %s04", short_day, month, short_day, genitive_month);
703 sprintf(Broken, "04 %s%s %s %s04", short_day, month, short_day, month);
704 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
705 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
706 ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
707 broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
708 "Expected '%s', got '%s'\n", Expected, buffer);
710 /* with literal part */
711 STRINGSA("ddd',' MMMM dd", "");
712 sprintf(Expected, "%s, %s 04", short_day, genitive_month);
713 sprintf(Broken, "%s, %s 04", short_day, month);
714 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
715 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
716 ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
717 broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
718 "Expected '%s', got '%s'\n", Expected, buffer);
721 static void test_GetDateFormatW(void)
723 int ret;
724 SYSTEMTIME curtime;
725 WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
726 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
728 STRINGSW("",""); /* If flags is not zero then format must be NULL */
729 ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL,
730 input, buffer, COUNTOF(buffer));
731 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
733 win_skip("GetDateFormatW is not implemented\n");
734 return;
736 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
737 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
738 EXPECT_EQW;
740 STRINGSW("",""); /* NULL buffer, len > 0 */
741 SetLastError(0xdeadbeef);
742 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
743 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
744 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
746 STRINGSW("",""); /* NULL buffer, len == 0 */
747 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
748 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
749 EXPECT_LENW; EXPECT_EQW;
751 curtime.wYear = 2002;
752 curtime.wMonth = 10;
753 curtime.wDay = 23;
754 curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
755 curtime.wHour = 65432; /* Invalid */
756 curtime.wMinute = 34512; /* Invalid */
757 curtime.wSecond = 65535; /* Invalid */
758 curtime.wMilliseconds = 12345;
759 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
760 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
761 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
762 EXPECT_LENW; EXPECT_EQW;
764 /* Limit tests */
766 curtime.wYear = 1601;
767 curtime.wMonth = 1;
768 curtime.wDay = 1;
769 curtime.wDayOfWeek = 0; /* Irrelevant */
770 curtime.wHour = 0;
771 curtime.wMinute = 0;
772 curtime.wSecond = 0;
773 curtime.wMilliseconds = 0;
774 STRINGSW("dddd d MMMM yyyy","Monday 1 January 1601");
775 SetLastError(0xdeadbeef);
776 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
777 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
778 EXPECT_LENW; EXPECT_EQW;
780 curtime.wYear = 1600;
781 curtime.wMonth = 12;
782 curtime.wDay = 31;
783 curtime.wDayOfWeek = 0; /* Irrelevant */
784 curtime.wHour = 23;
785 curtime.wMinute = 59;
786 curtime.wSecond = 59;
787 curtime.wMilliseconds = 999;
788 STRINGSW("dddd d MMMM yyyy","Friday 31 December 1600");
789 SetLastError(0xdeadbeef);
790 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
791 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
792 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
796 #define CY_POS_LEFT 0
797 #define CY_POS_RIGHT 1
798 #define CY_POS_LEFT_SPACE 2
799 #define CY_POS_RIGHT_SPACE 3
801 static void test_GetCurrencyFormatA(void)
803 static char szDot[] = { '.', '\0' };
804 static char szComma[] = { ',', '\0' };
805 static char szDollar[] = { '$', '\0' };
806 int ret;
807 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
808 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
809 CURRENCYFMTA format;
811 memset(&format, 0, sizeof(format));
813 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
814 SetLastError(0xdeadbeef);
815 ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
816 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
817 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
819 STRINGSA("23,53",""); /* Invalid character --> Error */
820 SetLastError(0xdeadbeef);
821 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
822 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
823 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
825 STRINGSA("--",""); /* Double '-' --> Error */
826 SetLastError(0xdeadbeef);
827 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
828 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
829 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
831 STRINGSA("0-",""); /* Trailing '-' --> Error */
832 SetLastError(0xdeadbeef);
833 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
834 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
835 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
837 STRINGSA("0..",""); /* Double '.' --> Error */
838 SetLastError(0xdeadbeef);
839 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
840 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
841 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
843 STRINGSA(" 0.1",""); /* Leading space --> Error */
844 SetLastError(0xdeadbeef);
845 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
846 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
847 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
849 STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
850 SetLastError(0xdeadbeef);
851 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, 2);
852 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
853 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
855 STRINGSA("2353",""); /* Format and flags given --> Error */
856 SetLastError(0xdeadbeef);
857 ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
858 ok( !ret, "Expected ret == 0, got %d\n", ret);
859 ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
860 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
862 STRINGSA("2353",""); /* Invalid format --> Error */
863 SetLastError(0xdeadbeef);
864 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
865 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
866 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
868 STRINGSA("2353","$2,353.00"); /* Valid number */
869 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
870 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
871 EXPECT_LENA; EXPECT_EQA;
873 STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
874 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
875 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
876 EXPECT_LENA; EXPECT_EQA;
878 STRINGSA("2353.1","$2,353.10"); /* Valid real number */
879 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
880 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
881 EXPECT_LENA; EXPECT_EQA;
883 STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
884 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
885 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
886 EXPECT_LENA; EXPECT_EQA;
888 STRINGSA("2353.119","$2,353.12"); /* Too many DP --> Rounded */
889 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
890 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
891 EXPECT_LENA; EXPECT_EQA;
893 format.NumDigits = 0; /* No decimal separator */
894 format.LeadingZero = 0;
895 format.Grouping = 0; /* No grouping char */
896 format.NegativeOrder = 0;
897 format.PositiveOrder = CY_POS_LEFT;
898 format.lpDecimalSep = szDot;
899 format.lpThousandSep = szComma;
900 format.lpCurrencySymbol = szDollar;
902 STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
903 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
904 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
905 EXPECT_LENA; EXPECT_EQA;
907 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
908 STRINGSA("2353","$2353.0");
909 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
910 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
911 EXPECT_LENA; EXPECT_EQA;
913 format.Grouping = 2; /* Group by 100's */
914 STRINGSA("2353","$23,53.0");
915 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
916 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
917 EXPECT_LENA; EXPECT_EQA;
919 STRINGSA("235","$235.0"); /* Grouping of a positive number */
920 format.Grouping = 3;
921 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
922 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
923 EXPECT_LENA; EXPECT_EQA;
925 STRINGSA("-235","$-235.0"); /* Grouping of a negative number */
926 format.NegativeOrder = 2;
927 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
928 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
929 EXPECT_LENA; EXPECT_EQA;
931 format.LeadingZero = 1; /* Always provide leading zero */
932 STRINGSA(".5","$0.5");
933 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
934 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
935 EXPECT_LENA; EXPECT_EQA;
937 format.PositiveOrder = CY_POS_RIGHT;
938 STRINGSA("1","1.0$");
939 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
940 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
941 EXPECT_LENA; EXPECT_EQA;
943 format.PositiveOrder = CY_POS_LEFT_SPACE;
944 STRINGSA("1","$ 1.0");
945 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
946 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
947 EXPECT_LENA; EXPECT_EQA;
949 format.PositiveOrder = CY_POS_RIGHT_SPACE;
950 STRINGSA("1","1.0 $");
951 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
952 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
953 EXPECT_LENA; EXPECT_EQA;
955 format.NegativeOrder = 0;
956 STRINGSA("-1","($1.0)");
957 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
958 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
959 EXPECT_LENA; EXPECT_EQA;
961 format.NegativeOrder = 1;
962 STRINGSA("-1","-$1.0");
963 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
964 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
965 EXPECT_LENA; EXPECT_EQA;
967 format.NegativeOrder = 2;
968 STRINGSA("-1","$-1.0");
969 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
970 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
971 EXPECT_LENA; EXPECT_EQA;
973 format.NegativeOrder = 3;
974 STRINGSA("-1","$1.0-");
975 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
976 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
977 EXPECT_LENA; EXPECT_EQA;
979 format.NegativeOrder = 4;
980 STRINGSA("-1","(1.0$)");
981 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
982 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
983 EXPECT_LENA; EXPECT_EQA;
985 format.NegativeOrder = 5;
986 STRINGSA("-1","-1.0$");
987 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
988 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
989 EXPECT_LENA; EXPECT_EQA;
991 format.NegativeOrder = 6;
992 STRINGSA("-1","1.0-$");
993 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
994 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
995 EXPECT_LENA; EXPECT_EQA;
997 format.NegativeOrder = 7;
998 STRINGSA("-1","1.0$-");
999 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1000 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1001 EXPECT_LENA; EXPECT_EQA;
1003 format.NegativeOrder = 8;
1004 STRINGSA("-1","-1.0 $");
1005 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1006 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1007 EXPECT_LENA; EXPECT_EQA;
1009 format.NegativeOrder = 9;
1010 STRINGSA("-1","-$ 1.0");
1011 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1012 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1013 EXPECT_LENA; EXPECT_EQA;
1015 format.NegativeOrder = 10;
1016 STRINGSA("-1","1.0 $-");
1017 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1018 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1019 EXPECT_LENA; EXPECT_EQA;
1021 format.NegativeOrder = 11;
1022 STRINGSA("-1","$ 1.0-");
1023 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1024 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1025 EXPECT_LENA; EXPECT_EQA;
1027 format.NegativeOrder = 12;
1028 STRINGSA("-1","$ -1.0");
1029 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1030 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1031 EXPECT_LENA; EXPECT_EQA;
1033 format.NegativeOrder = 13;
1034 STRINGSA("-1","1.0- $");
1035 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1036 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1037 EXPECT_LENA; EXPECT_EQA;
1039 format.NegativeOrder = 14;
1040 STRINGSA("-1","($ 1.0)");
1041 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1042 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1043 EXPECT_LENA; EXPECT_EQA;
1045 format.NegativeOrder = 15;
1046 STRINGSA("-1","(1.0 $)");
1047 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1048 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1049 EXPECT_LENA; EXPECT_EQA;
1052 #define NEG_PARENS 0 /* "(1.1)" */
1053 #define NEG_LEFT 1 /* "-1.1" */
1054 #define NEG_LEFT_SPACE 2 /* "- 1.1" */
1055 #define NEG_RIGHT 3 /* "1.1-" */
1056 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
1058 static void test_GetNumberFormatA(void)
1060 static char szDot[] = { '.', '\0' };
1061 static char szComma[] = { ',', '\0' };
1062 int ret;
1063 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
1064 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
1065 NUMBERFMTA format;
1067 memset(&format, 0, sizeof(format));
1069 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
1070 SetLastError(0xdeadbeef);
1071 ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
1072 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1073 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1075 STRINGSA("23,53",""); /* Invalid character --> Error */
1076 SetLastError(0xdeadbeef);
1077 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1078 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1079 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1081 STRINGSA("--",""); /* Double '-' --> Error */
1082 SetLastError(0xdeadbeef);
1083 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1084 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1085 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1087 STRINGSA("0-",""); /* Trailing '-' --> Error */
1088 SetLastError(0xdeadbeef);
1089 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1090 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1091 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1093 STRINGSA("0..",""); /* Double '.' --> Error */
1094 SetLastError(0xdeadbeef);
1095 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1096 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1097 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1099 STRINGSA(" 0.1",""); /* Leading space --> Error */
1100 SetLastError(0xdeadbeef);
1101 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1102 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1103 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1105 STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
1106 SetLastError(0xdeadbeef);
1107 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, 2);
1108 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1109 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1111 STRINGSA("2353",""); /* Format and flags given --> Error */
1112 SetLastError(0xdeadbeef);
1113 ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
1114 ok( !ret, "Expected ret == 0, got %d\n", ret);
1115 ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
1116 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1118 STRINGSA("2353",""); /* Invalid format --> Error */
1119 SetLastError(0xdeadbeef);
1120 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1121 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1122 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1124 STRINGSA("2353","2,353.00"); /* Valid number */
1125 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1126 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1127 EXPECT_LENA; EXPECT_EQA;
1129 STRINGSA("-2353","-2,353.00"); /* Valid negative number */
1130 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1131 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1132 EXPECT_LENA; EXPECT_EQA;
1134 STRINGSA("-353","-353.00"); /* test for off by one error in grouping */
1135 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1136 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1137 EXPECT_LENA; EXPECT_EQA;
1139 STRINGSA("2353.1","2,353.10"); /* Valid real number */
1140 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1141 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1142 EXPECT_LENA; EXPECT_EQA;
1144 STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
1145 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1146 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1147 EXPECT_LENA; EXPECT_EQA;
1149 STRINGSA("2353.119","2,353.12"); /* Too many DP --> Rounded */
1150 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1151 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1152 EXPECT_LENA; EXPECT_EQA;
1154 format.NumDigits = 0; /* No decimal separator */
1155 format.LeadingZero = 0;
1156 format.Grouping = 0; /* No grouping char */
1157 format.NegativeOrder = 0;
1158 format.lpDecimalSep = szDot;
1159 format.lpThousandSep = szComma;
1161 STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
1162 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1163 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1164 EXPECT_LENA; EXPECT_EQA;
1166 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
1167 STRINGSA("2353","2353.0");
1168 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1169 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1170 EXPECT_LENA; EXPECT_EQA;
1172 format.Grouping = 2; /* Group by 100's */
1173 STRINGSA("2353","23,53.0");
1174 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1175 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1176 EXPECT_LENA; EXPECT_EQA;
1178 STRINGSA("235","235.0"); /* Grouping of a positive number */
1179 format.Grouping = 3;
1180 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1181 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1182 EXPECT_LENA; EXPECT_EQA;
1184 STRINGSA("-235","-235.0"); /* Grouping of a negative number */
1185 format.NegativeOrder = NEG_LEFT;
1186 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1187 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1188 EXPECT_LENA; EXPECT_EQA;
1190 format.LeadingZero = 1; /* Always provide leading zero */
1191 STRINGSA(".5","0.5");
1192 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1193 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1194 EXPECT_LENA; EXPECT_EQA;
1196 format.NegativeOrder = NEG_PARENS;
1197 STRINGSA("-1","(1.0)");
1198 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1199 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1200 EXPECT_LENA; EXPECT_EQA;
1202 format.NegativeOrder = NEG_LEFT;
1203 STRINGSA("-1","-1.0");
1204 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1205 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1206 EXPECT_LENA; EXPECT_EQA;
1208 format.NegativeOrder = NEG_LEFT_SPACE;
1209 STRINGSA("-1","- 1.0");
1210 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1211 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1212 EXPECT_LENA; EXPECT_EQA;
1214 format.NegativeOrder = NEG_RIGHT;
1215 STRINGSA("-1","1.0-");
1216 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1217 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1218 EXPECT_LENA; EXPECT_EQA;
1220 format.NegativeOrder = NEG_RIGHT_SPACE;
1221 STRINGSA("-1","1.0 -");
1222 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1223 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1224 EXPECT_LENA; EXPECT_EQA;
1226 lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
1228 if (IsValidLocale(lcid, 0))
1230 STRINGSA("-12345","-12 345,00"); /* Try French formatting */
1231 Expected[3] = 160; /* Non breaking space */
1232 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1233 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1234 EXPECT_LENA; EXPECT_EQA;
1238 struct comparestringa_entry {
1239 LCID lcid;
1240 DWORD flags;
1241 const char *first;
1242 int first_len;
1243 const char *second;
1244 int second_len;
1245 int ret;
1248 static const struct comparestringa_entry comparestringa_data[] = {
1249 { LOCALE_SYSTEM_DEFAULT, 0, "EndDialog", -1, "_Property", -1, CSTR_GREATER_THAN },
1250 { LOCALE_SYSTEM_DEFAULT, 0, "osp_vba.sreg0070", -1, "_IEWWBrowserComp", -1, CSTR_GREATER_THAN },
1251 { LOCALE_SYSTEM_DEFAULT, 0, "r", -1, "\\", -1, CSTR_GREATER_THAN },
1252 { LOCALE_SYSTEM_DEFAULT, 0, "osp_vba.sreg0031", -1, "OriginalDatabase", -1, CSTR_GREATER_THAN },
1253 { LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1, CSTR_GREATER_THAN },
1254 { LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1, CSTR_LESS_THAN },
1255 { LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1, CSTR_LESS_THAN },
1256 { LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1, CSTR_LESS_THAN },
1257 { LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1, CSTR_LESS_THAN },
1258 { LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1, CSTR_LESS_THAN },
1259 { LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1, CSTR_LESS_THAN },
1260 { LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1, CSTR_GREATER_THAN },
1261 { LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1, CSTR_LESS_THAN },
1262 { LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1, CSTR_LESS_THAN },
1263 { LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1, CSTR_GREATER_THAN },
1264 { LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1, CSTR_GREATER_THAN },
1265 { LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1, CSTR_LESS_THAN },
1266 { LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1, CSTR_LESS_THAN },
1267 { LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1, CSTR_LESS_THAN },
1268 /* hyphen and apostrophe are treated differently depending on whether SORT_STRINGSORT specified or not */
1269 { LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1, CSTR_GREATER_THAN },
1270 { LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1, CSTR_LESS_THAN },
1271 { LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1, CSTR_LESS_THAN },
1272 { LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1, CSTR_GREATER_THAN },
1273 { LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1, CSTR_GREATER_THAN },
1274 { LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1, CSTR_LESS_THAN },
1275 { LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1, CSTR_LESS_THAN },
1276 { LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1, CSTR_GREATER_THAN },
1277 { LOCALE_SYSTEM_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9, CSTR_EQUAL },
1278 { LOCALE_SYSTEM_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10, CSTR_LESS_THAN }
1281 static void test_CompareStringA(void)
1283 int ret, i;
1284 LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
1286 for (i = 0; i < sizeof(comparestringa_data)/sizeof(struct comparestringa_entry); i++)
1288 const struct comparestringa_entry *entry = &comparestringa_data[i];
1290 ret = CompareStringA(entry->lcid, entry->flags, entry->first, entry->first_len,
1291 entry->second, entry->second_len);
1292 ok(ret == entry->ret, "%d: got %d, expected %d\n", i, ret, entry->ret);
1295 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
1296 ok (ret == CSTR_LESS_THAN, "(Salut/Salute) Expected CSTR_LESS_THAN, got %d\n", ret);
1298 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
1299 ok (ret == CSTR_EQUAL, "(Salut/SaLuT) Expected CSTR_EQUAL, got %d\n", ret);
1301 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
1302 ok (ret == CSTR_GREATER_THAN, "(Salut/hola) Expected CSTR_GREATER_THAN, got %d\n", ret);
1304 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
1305 ok (ret == CSTR_LESS_THAN, "(haha/hoho) Expected CSTR_LESS_THAN, got %d\n", ret);
1307 lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
1309 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
1310 ok (ret == CSTR_LESS_THAN, "(haha/hoho) Expected CSTR_LESS_THAN, got %d\n", ret);
1312 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
1313 ok (ret == CSTR_GREATER_THAN, "(haha/hoho) Expected CSTR_GREATER_THAN, got %d\n", ret);
1315 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
1316 ok (ret == CSTR_EQUAL, "(Salut/saLuT) Expected CSTR_EQUAL, got %d\n", ret);
1318 /* test for CompareStringA flags */
1319 SetLastError(0xdeadbeef);
1320 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0x8, "NULL", -1, "NULL", -1);
1321 ok(GetLastError() == ERROR_INVALID_FLAGS,
1322 "unexpected error code %d\n", GetLastError());
1323 ok(!ret, "CompareStringA must fail with invalid flag\n");
1325 SetLastError(0xdeadbeef);
1326 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, LOCALE_USE_CP_ACP, "NULL", -1, "NULL", -1);
1327 ok(GetLastError() == 0xdeadbeef, "unexpected error code %d\n", GetLastError());
1328 ok(ret == CSTR_EQUAL, "CompareStringA error: %d != CSTR_EQUAL\n", ret);
1329 /* end of test for CompareStringA flags */
1331 ret = lstrcmpA("", "");
1332 ok (ret == 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret);
1334 ret = lstrcmpA(NULL, NULL);
1335 ok (ret == 0 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, NULL) should return 0, got %d\n", ret);
1337 ret = lstrcmpA("", NULL);
1338 ok (ret == 1 || broken(ret == -2) /* win9x */, "lstrcmpA(\"\", NULL) should return 1, got %d\n", ret);
1340 ret = lstrcmpA(NULL, "");
1341 ok (ret == -1 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret);
1344 if (0) { /* this requires collation table patch to make it MS compatible */
1345 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
1346 ok(ret == CSTR_LESS_THAN, "'o vs -o expected CSTR_LESS_THAN, got %d\n", ret);
1348 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
1349 ok(ret == CSTR_LESS_THAN, "'o vs -o expected CSTR_LESS_THAN, got %d\n", ret);
1351 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
1352 ok(ret == CSTR_LESS_THAN, "' vs - expected CSTR_LESS_THAN, got %d\n", ret);
1354 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
1355 ok(ret == CSTR_LESS_THAN, "' vs - expected CSTR_LESS_THAN, got %d\n", ret);
1357 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
1358 ok(ret == CSTR_GREATER_THAN, "`o vs /m CSTR_GREATER_THAN got %d\n", ret);
1360 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
1361 ok(ret == CSTR_LESS_THAN, "/m vs `o expected CSTR_LESS_THAN, got %d\n", ret);
1363 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
1364 ok(ret == CSTR_GREATER_THAN, "`o vs /m CSTR_GREATER_THAN got %d\n", ret);
1366 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
1367 ok(ret == CSTR_LESS_THAN, "/m vs `o expected CSTR_LESS_THAN, got %d\n", ret);
1369 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
1370 ok(ret == CSTR_LESS_THAN, "`o vs -m expected CSTR_LESS_THAN, got %d\n", ret);
1372 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
1373 ok(ret == CSTR_GREATER_THAN, "-m vs `o CSTR_GREATER_THAN got %d\n", ret);
1375 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
1376 ok(ret == CSTR_GREATER_THAN, "`o vs -m CSTR_GREATER_THAN got %d\n", ret);
1378 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
1379 ok(ret == CSTR_LESS_THAN, "-m vs `o expected CSTR_LESS_THAN, got %d\n", ret);
1383 /* WinXP handles embedded NULLs differently than earlier versions */
1384 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
1385 ok(ret == CSTR_LESS_THAN || ret == CSTR_EQUAL, "aLuZkUtZ vs aLuZkUtZ\\0A expected CSTR_LESS_THAN or CSTR_EQUAL, got %d\n", ret);
1387 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
1388 ok(ret == CSTR_LESS_THAN || ret == CSTR_EQUAL, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected CSTR_LESS_THAN or CSTR_EQUAL, got %d\n", ret);
1390 ret = CompareStringA(lcid, 0, "a\0b", -1, "a", -1);
1391 ok(ret == CSTR_EQUAL, "a vs a expected CSTR_EQUAL, got %d\n", ret);
1393 ret = CompareStringA(lcid, 0, "a\0b", 4, "a", 2);
1394 ok(ret == CSTR_EQUAL || /* win2k */
1395 ret == CSTR_GREATER_THAN,
1396 "a\\0b vs a expected CSTR_EQUAL or CSTR_GREATER_THAN, got %d\n", ret);
1398 ret = CompareStringA(lcid, 0, "\2", 2, "\1", 2);
1399 todo_wine ok(ret != CSTR_EQUAL, "\\2 vs \\1 expected unequal\n");
1401 ret = CompareStringA(lcid, NORM_IGNORECASE | LOCALE_USE_CP_ACP, "#", -1, ".", -1);
1402 todo_wine ok(ret == CSTR_LESS_THAN, "\"#\" vs \".\" expected CSTR_LESS_THAN, got %d\n", ret);
1404 ret = CompareStringA(lcid, NORM_IGNORECASE, "_", -1, ".", -1);
1405 todo_wine ok(ret == CSTR_GREATER_THAN, "\"_\" vs \".\" expected CSTR_GREATER_THAN, got %d\n", ret);
1407 ret = lstrcmpi("#", ".");
1408 todo_wine ok(ret == -1, "\"#\" vs \".\" expected -1, got %d\n", ret);
1410 lcid = MAKELCID(MAKELANGID(LANG_POLISH, SUBLANG_DEFAULT), SORT_DEFAULT);
1412 /* \xB9 character lies between a and b */
1413 ret = CompareStringA(lcid, 0, "a", 1, "\xB9", 1);
1414 todo_wine ok(ret == CSTR_LESS_THAN, "\'\\xB9\' character should be greater than \'a\'\n");
1415 ret = CompareStringA(lcid, 0, "\xB9", 1, "b", 1);
1416 ok(ret == CSTR_LESS_THAN, "\'\\xB9\' character should be smaller than \'b\'\n");
1419 static void test_LCMapStringA(void)
1421 int ret, ret2;
1422 char buf[256], buf2[256];
1423 static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
1424 static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
1425 static const char symbols_stripped[] = "justateststring1";
1427 SetLastError(0xdeadbeef);
1428 ret = LCMapStringA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP | LCMAP_LOWERCASE,
1429 lower_case, -1, buf, sizeof(buf));
1430 ok(ret == lstrlenA(lower_case) + 1,
1431 "ret %d, error %d, expected value %d\n",
1432 ret, GetLastError(), lstrlenA(lower_case) + 1);
1433 ok(!memcmp(buf, lower_case, ret), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1435 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1436 upper_case, -1, buf, sizeof(buf));
1437 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1438 ok(GetLastError() == ERROR_INVALID_FLAGS,
1439 "unexpected error code %d\n", GetLastError());
1441 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1442 upper_case, -1, buf, sizeof(buf));
1443 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1444 ok(GetLastError() == ERROR_INVALID_FLAGS,
1445 "unexpected error code %d\n", GetLastError());
1447 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1448 upper_case, -1, buf, sizeof(buf));
1449 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1450 ok(GetLastError() == ERROR_INVALID_FLAGS,
1451 "unexpected error code %d\n", GetLastError());
1453 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1454 upper_case, -1, buf, sizeof(buf));
1455 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1456 ok(GetLastError() == ERROR_INVALID_FLAGS,
1457 "unexpected error code %d\n", GetLastError());
1459 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1460 SetLastError(0xdeadbeef);
1461 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1462 upper_case, -1, buf, sizeof(buf));
1463 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1464 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1466 /* test LCMAP_LOWERCASE */
1467 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1468 upper_case, -1, buf, sizeof(buf));
1469 ok(ret == lstrlenA(upper_case) + 1,
1470 "ret %d, error %d, expected value %d\n",
1471 ret, GetLastError(), lstrlenA(upper_case) + 1);
1472 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1474 /* test LCMAP_UPPERCASE */
1475 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1476 lower_case, -1, buf, sizeof(buf));
1477 ok(ret == lstrlenA(lower_case) + 1,
1478 "ret %d, error %d, expected value %d\n",
1479 ret, GetLastError(), lstrlenA(lower_case) + 1);
1480 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1482 /* test buffer overflow */
1483 SetLastError(0xdeadbeef);
1484 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1485 lower_case, -1, buf, 4);
1486 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1487 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1489 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1490 lstrcpyA(buf, lower_case);
1491 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1492 buf, -1, buf, sizeof(buf));
1493 if (!ret) /* Win9x */
1494 trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1495 else
1497 ok(ret == lstrlenA(lower_case) + 1,
1498 "ret %d, error %d, expected value %d\n",
1499 ret, GetLastError(), lstrlenA(lower_case) + 1);
1500 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1502 lstrcpyA(buf, upper_case);
1503 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1504 buf, -1, buf, sizeof(buf));
1505 if (!ret) /* Win9x */
1506 trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1507 else
1509 ok(ret == lstrlenA(upper_case) + 1,
1510 "ret %d, error %d, expected value %d\n",
1511 ret, GetLastError(), lstrlenA(lower_case) + 1);
1512 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1515 /* otherwise src == dst should fail */
1516 SetLastError(0xdeadbeef);
1517 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1518 buf, 10, buf, sizeof(buf));
1519 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1520 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1521 "unexpected error code %d\n", GetLastError());
1522 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1524 /* test whether '\0' is always appended */
1525 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1526 upper_case, -1, buf, sizeof(buf));
1527 ok(ret, "LCMapStringA must succeed\n");
1528 ok(buf[ret-1] == 0, "LCMapStringA not null-terminated\n");
1529 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1530 upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1531 ok(ret2, "LCMapStringA must succeed\n");
1532 ok(buf2[ret2-1] == 0, "LCMapStringA not null-terminated\n" );
1533 ok(ret == ret2, "lengths of sort keys must be equal\n");
1534 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1536 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1537 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1538 upper_case, -1, buf, sizeof(buf));
1539 ok(ret, "LCMapStringA must succeed\n");
1540 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1541 lower_case, -1, buf2, sizeof(buf2));
1542 ok(ret2, "LCMapStringA must succeed\n");
1543 ok(ret == ret2, "lengths of sort keys must be equal\n");
1544 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1546 /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1547 results from plain LCMAP_SORTKEY on Vista */
1549 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1550 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1551 lower_case, -1, buf, sizeof(buf));
1552 ok(ret, "LCMapStringA must succeed\n");
1553 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1554 symbols_stripped, -1, buf2, sizeof(buf2));
1555 ok(ret2, "LCMapStringA must succeed\n");
1556 ok(ret == ret2, "lengths of sort keys must be equal\n");
1557 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1559 /* test NORM_IGNORENONSPACE */
1560 lstrcpyA(buf, "foo");
1561 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1562 lower_case, -1, buf, sizeof(buf));
1563 ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1564 lstrlenA(lower_case) + 1, ret);
1565 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1567 /* test NORM_IGNORESYMBOLS */
1568 lstrcpyA(buf, "foo");
1569 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1570 lower_case, -1, buf, sizeof(buf));
1571 ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1572 lstrlenA(symbols_stripped) + 1, ret);
1573 ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1575 /* test srclen = 0 */
1576 SetLastError(0xdeadbeef);
1577 ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1578 ok(!ret, "LCMapStringA should fail with srclen = 0\n");
1579 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1580 "unexpected error code %d\n", GetLastError());
1583 typedef INT (*lcmapstring_wrapper)(DWORD, LPCWSTR, INT, LPWSTR, INT);
1585 static void test_lcmapstring_unicode(lcmapstring_wrapper func_ptr, const char *func_name)
1587 int ret, ret2;
1588 WCHAR buf[256], buf2[256];
1589 char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1591 ret = func_ptr(LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1592 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1593 if (broken(ret))
1594 ok(lstrcmpW(buf, upper_case) == 0, "Expected upper case string\n");
1595 else
1597 ok(!ret, "%s LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n", func_name);
1598 ok(GetLastError() == ERROR_INVALID_FLAGS, "%s unexpected error code %d\n",
1599 func_name, GetLastError());
1602 ret = func_ptr(LCMAP_HIRAGANA | LCMAP_KATAKANA,
1603 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1604 ok(!ret, "%s LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n", func_name);
1605 ok(GetLastError() == ERROR_INVALID_FLAGS, "%s unexpected error code %d\n",
1606 func_name, GetLastError());
1608 ret = func_ptr(LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1609 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1610 ok(!ret, "%s LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n", func_name);
1611 ok(GetLastError() == ERROR_INVALID_FLAGS, "%s unexpected error code %d\n",
1612 func_name, GetLastError());
1614 ret = func_ptr(LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1615 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1616 ok(!ret, "%s LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n",
1617 func_name);
1618 ok(GetLastError() == ERROR_INVALID_FLAGS, "%s unexpected error code %d\n",
1619 func_name, GetLastError());
1621 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1622 SetLastError(0xdeadbeef);
1623 ret = func_ptr(LCMAP_LOWERCASE | SORT_STRINGSORT,
1624 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1625 ok(GetLastError() == ERROR_INVALID_FLAGS, "%s expected ERROR_INVALID_FLAGS, got %d\n",
1626 func_name, GetLastError());
1627 ok(!ret, "%s SORT_STRINGSORT without LCMAP_SORTKEY must fail\n", func_name);
1629 /* test LCMAP_LOWERCASE */
1630 ret = func_ptr(LCMAP_LOWERCASE,
1631 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1632 ok(ret == lstrlenW(upper_case) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
1633 ret, GetLastError(), lstrlenW(upper_case) + 1);
1634 ok(!lstrcmpW(buf, lower_case), "%s string compare mismatch\n", func_name);
1636 /* test LCMAP_UPPERCASE */
1637 ret = func_ptr(LCMAP_UPPERCASE,
1638 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1639 ok(ret == lstrlenW(lower_case) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
1640 ret, GetLastError(), lstrlenW(lower_case) + 1);
1641 ok(!lstrcmpW(buf, upper_case), "%s string compare mismatch\n", func_name);
1643 /* test buffer overflow */
1644 SetLastError(0xdeadbeef);
1645 ret = func_ptr(LCMAP_UPPERCASE,
1646 lower_case, -1, buf, 4);
1647 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1648 "%s should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", func_name, ret);
1650 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1651 lstrcpyW(buf, lower_case);
1652 ret = func_ptr(LCMAP_UPPERCASE,
1653 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1654 ok(ret == lstrlenW(lower_case) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
1655 ret, GetLastError(), lstrlenW(lower_case) + 1);
1656 ok(!lstrcmpW(buf, upper_case), "%s string compare mismatch\n", func_name);
1658 lstrcpyW(buf, upper_case);
1659 ret = func_ptr(LCMAP_LOWERCASE,
1660 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1661 ok(ret == lstrlenW(upper_case) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
1662 ret, GetLastError(), lstrlenW(lower_case) + 1);
1663 ok(!lstrcmpW(buf, lower_case), "%s string compare mismatch\n", func_name);
1665 /* otherwise src == dst should fail */
1666 SetLastError(0xdeadbeef);
1667 ret = func_ptr(LCMAP_SORTKEY | LCMAP_UPPERCASE,
1668 buf, 10, buf, sizeof(buf));
1669 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1670 GetLastError() == ERROR_INVALID_PARAMETER /* Win7+ */,
1671 "%s unexpected error code %d\n", func_name, GetLastError());
1672 ok(!ret, "%s src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n", func_name);
1674 /* test whether '\0' is always appended */
1675 ret = func_ptr(LCMAP_SORTKEY,
1676 upper_case, -1, buf, sizeof(buf));
1677 ok(ret, "%s func_ptr must succeed\n", func_name);
1678 ret2 = func_ptr(LCMAP_SORTKEY,
1679 upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1680 ok(ret, "%s func_ptr must succeed\n", func_name);
1681 ok(ret == ret2, "%s lengths of sort keys must be equal\n", func_name);
1682 ok(!lstrcmpA(p_buf, p_buf2), "%s sort keys must be equal\n", func_name);
1684 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1685 ret = func_ptr(LCMAP_SORTKEY | NORM_IGNORECASE,
1686 upper_case, -1, buf, sizeof(buf));
1687 ok(ret, "%s func_ptr must succeed\n", func_name);
1688 ret2 = func_ptr(LCMAP_SORTKEY,
1689 lower_case, -1, buf2, sizeof(buf2));
1690 ok(ret2, "%s func_ptr must succeed\n", func_name);
1691 ok(ret == ret2, "%s lengths of sort keys must be equal\n", func_name);
1692 ok(!lstrcmpA(p_buf, p_buf2), "%s sort keys must be equal\n", func_name);
1694 /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1695 results from plain LCMAP_SORTKEY on Vista */
1697 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1698 ret = func_ptr(LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1699 lower_case, -1, buf, sizeof(buf));
1700 ok(ret, "%s func_ptr must succeed\n", func_name);
1701 ret2 = func_ptr(LCMAP_SORTKEY,
1702 symbols_stripped, -1, buf2, sizeof(buf2));
1703 ok(ret2, "%s func_ptr must succeed\n", func_name);
1704 ok(ret == ret2, "%s lengths of sort keys must be equal\n", func_name);
1705 ok(!lstrcmpA(p_buf, p_buf2), "%s sort keys must be equal\n", func_name);
1707 /* test NORM_IGNORENONSPACE */
1708 lstrcpyW(buf, fooW);
1709 ret = func_ptr(NORM_IGNORENONSPACE,
1710 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1711 ok(ret == lstrlenW(lower_case) + 1, "%s func_ptr should return %d, ret = %d\n", func_name,
1712 lstrlenW(lower_case) + 1, ret);
1713 ok(!lstrcmpW(buf, lower_case), "%s string comparison mismatch\n", func_name);
1715 /* test NORM_IGNORESYMBOLS */
1716 lstrcpyW(buf, fooW);
1717 ret = func_ptr(NORM_IGNORESYMBOLS,
1718 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1719 ok(ret == lstrlenW(symbols_stripped) + 1, "%s func_ptr should return %d, ret = %d\n", func_name,
1720 lstrlenW(symbols_stripped) + 1, ret);
1721 ok(!lstrcmpW(buf, symbols_stripped), "%s string comparison mismatch\n", func_name);
1723 /* test srclen = 0 */
1724 SetLastError(0xdeadbeef);
1725 ret = func_ptr(0, upper_case, 0, buf, sizeof(buf)/sizeof(WCHAR));
1726 ok(!ret, "%s func_ptr should fail with srclen = 0\n", func_name);
1727 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1728 "%s unexpected error code %d\n", func_name, GetLastError());
1731 static INT LCMapStringW_wrapper(DWORD flags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen)
1733 return LCMapStringW(LOCALE_USER_DEFAULT, flags, src, srclen, dst, dstlen);
1736 static void test_LCMapStringW(void)
1738 int ret;
1739 WCHAR buf[256];
1741 trace("testing LCMapStringW\n");
1743 SetLastError(0xdeadbeef);
1744 ret = LCMapStringW((LCID)-1, LCMAP_LOWERCASE, upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1745 todo_wine {
1746 ok(!ret, "LCMapStringW should fail with bad lcid\n");
1747 ok(GetLastError() == ERROR_INVALID_PARAMETER, "unexpected error code %d\n", GetLastError());
1750 test_lcmapstring_unicode(LCMapStringW_wrapper, "LCMapStringW:");
1753 static INT LCMapStringEx_wrapper(DWORD flags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen)
1755 return pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, flags, src, srclen, dst, dstlen, NULL, NULL, 0);
1758 static void test_LCMapStringEx(void)
1760 int ret;
1761 WCHAR buf[256], badname[] = {'w', 'i', 'n', 'e', 't', 'e', 's', 't', 0};
1763 if (!pLCMapStringEx)
1765 win_skip( "LCMapStringEx not available\n" );
1766 return;
1769 trace("testing LCMapStringEx\n");
1771 SetLastError(0xdeadbeef);
1772 ret = pLCMapStringEx(badname, LCMAP_LOWERCASE,
1773 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), NULL, NULL, 0);
1774 todo_wine {
1775 ok(!ret, "LCMapStringEx should fail with bad locale name\n");
1776 ok(GetLastError() == ERROR_INVALID_PARAMETER, "unexpected error code %d\n", GetLastError());
1779 /* test reserved parameters */
1780 ret = pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_LOWERCASE,
1781 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), NULL, NULL, 1);
1782 ok(ret == lstrlenW(upper_case) + 1, "ret %d, error %d, expected value %d\n",
1783 ret, GetLastError(), lstrlenW(upper_case) + 1);
1784 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1786 ret = pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_LOWERCASE,
1787 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), NULL, (void*)1, 0);
1788 ok(ret == lstrlenW(upper_case) + 1, "ret %d, error %d, expected value %d\n",
1789 ret, GetLastError(), lstrlenW(upper_case) + 1);
1790 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1792 /* crashes on native */
1793 if(0)
1794 ret = pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_LOWERCASE,
1795 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), (void*)1, NULL, 0);
1797 test_lcmapstring_unicode(LCMapStringEx_wrapper, "LCMapStringEx:");
1800 struct neutralsublang_name_t {
1801 WCHAR name[3];
1802 LCID lcid;
1803 int todo;
1806 static const struct neutralsublang_name_t neutralsublang_names[] = {
1807 { {'a','r',0}, MAKELCID(MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA), SORT_DEFAULT) },
1808 { {'a','z',0}, MAKELCID(MAKELANGID(LANG_AZERI, SUBLANG_AZERI_LATIN), SORT_DEFAULT) },
1809 { {'d','e',0}, MAKELCID(MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN), SORT_DEFAULT) },
1810 { {'e','n',0}, MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT) },
1811 { {'e','s',0}, MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN), SORT_DEFAULT), 1 },
1812 { {'g','a',0}, MAKELCID(MAKELANGID(LANG_IRISH, SUBLANG_IRISH_IRELAND), SORT_DEFAULT), 1 },
1813 { {'i','t',0}, MAKELCID(MAKELANGID(LANG_ITALIAN, SUBLANG_ITALIAN), SORT_DEFAULT) },
1814 { {'m','s',0}, MAKELCID(MAKELANGID(LANG_MALAY, SUBLANG_MALAY_MALAYSIA), SORT_DEFAULT) },
1815 { {'n','l',0}, MAKELCID(MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH), SORT_DEFAULT) },
1816 { {'p','t',0}, MAKELCID(MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN), SORT_DEFAULT) },
1817 { {'s','r',0}, MAKELCID(MAKELANGID(LANG_SERBIAN, SUBLANG_SERBIAN_SERBIA_LATIN), SORT_DEFAULT), 1 },
1818 { {'s','v',0}, MAKELCID(MAKELANGID(LANG_SWEDISH, SUBLANG_SWEDISH), SORT_DEFAULT) },
1819 { {'u','z',0}, MAKELCID(MAKELANGID(LANG_UZBEK, SUBLANG_UZBEK_LATIN), SORT_DEFAULT) },
1820 { {'z','h',0}, MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT), 1 },
1821 { {0} }
1824 static void test_LocaleNameToLCID(void)
1826 LCID lcid;
1827 INT ret;
1828 WCHAR buffer[LOCALE_NAME_MAX_LENGTH];
1829 static const WCHAR enW[] = {'e','n',0};
1831 if (!pLocaleNameToLCID)
1833 win_skip( "LocaleNameToLCID not available\n" );
1834 return;
1837 /* special cases */
1838 buffer[0] = 0;
1839 lcid = pLocaleNameToLCID(LOCALE_NAME_USER_DEFAULT, 0);
1840 ok(lcid == GetUserDefaultLCID() || broken(GetLastError() == ERROR_INVALID_PARAMETER /* Vista */),
1841 "Expected lcid == %08x, got %08x, error %d\n", lcid, GetUserDefaultLCID(), GetLastError());
1842 ret = pLCIDToLocaleName(lcid, buffer, LOCALE_NAME_MAX_LENGTH, 0);
1843 ok(ret > 0, "Expected ret > 0, got %d, error %d\n", ret, GetLastError());
1844 trace("%08x, %s\n", lcid, wine_dbgstr_w(buffer));
1846 buffer[0] = 0;
1847 lcid = pLocaleNameToLCID(LOCALE_NAME_SYSTEM_DEFAULT, 0);
1848 todo_wine ok(!lcid && GetLastError() == ERROR_INVALID_PARAMETER,
1849 "Expected lcid != 0, got %08x, error %d\n", lcid, GetLastError());
1850 ret = pLCIDToLocaleName(lcid, buffer, LOCALE_NAME_MAX_LENGTH, 0);
1851 ok(ret > 0, "Expected ret > 0, got %d, error %d\n", ret, GetLastError());
1852 trace("%08x, %s\n", lcid, wine_dbgstr_w(buffer));
1854 buffer[0] = 0;
1855 lcid = pLocaleNameToLCID(LOCALE_NAME_INVARIANT, 0);
1856 todo_wine ok(lcid == 0x7F, "Expected lcid = 0x7F, got %08x, error %d\n", lcid, GetLastError());
1857 ret = pLCIDToLocaleName(lcid, buffer, LOCALE_NAME_MAX_LENGTH, 0);
1858 ok(ret > 0, "Expected ret > 0, got %d, error %d\n", ret, GetLastError());
1859 trace("%08x, %s\n", lcid, wine_dbgstr_w(buffer));
1861 /* english neutral name */
1862 lcid = pLocaleNameToLCID(enW, 0);
1863 ok(lcid == MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT) ||
1864 broken(lcid == 0) /* Vista */, "got 0x%04x\n", lcid);
1865 if (lcid)
1867 const struct neutralsublang_name_t *ptr = neutralsublang_names;
1869 while (*ptr->name)
1871 lcid = pLocaleNameToLCID(ptr->name, 0);
1872 if (ptr->todo)
1873 todo_wine
1874 ok(lcid == ptr->lcid, "%s: got wrong lcid 0x%04x, expected 0x%04x\n",
1875 wine_dbgstr_w(ptr->name), lcid, ptr->lcid);
1876 else
1877 ok(lcid == ptr->lcid, "%s: got wrong lcid 0x%04x, expected 0x%04x\n",
1878 wine_dbgstr_w(ptr->name), lcid, ptr->lcid);
1879 ptr++;
1884 /* this requires collation table patch to make it MS compatible */
1885 static const char * const strings_sorted[] =
1887 "'",
1888 "-",
1889 "!",
1890 "\"",
1891 ".",
1892 ":",
1893 "\\",
1894 "_",
1895 "`",
1896 "{",
1897 "}",
1898 "+",
1899 "0",
1900 "1",
1901 "2",
1902 "3",
1903 "4",
1904 "5",
1905 "6",
1906 "7",
1907 "8",
1908 "9",
1909 "a",
1910 "A",
1911 "b",
1912 "B",
1913 "c",
1917 static const char * const strings[] =
1919 "C",
1920 "\"",
1921 "9",
1922 "'",
1923 "}",
1924 "-",
1925 "7",
1926 "+",
1927 "`",
1928 "1",
1929 "a",
1930 "5",
1931 "\\",
1932 "8",
1933 "B",
1934 "3",
1935 "_",
1936 "6",
1937 "{",
1938 "2",
1939 "c",
1940 "4",
1941 "!",
1942 "0",
1943 "A",
1944 ":",
1945 "b",
1949 static int compare_string1(const void *e1, const void *e2)
1951 const char *s1 = *(const char *const *)e1;
1952 const char *s2 = *(const char *const *)e2;
1954 return lstrcmpA(s1, s2);
1957 static int compare_string2(const void *e1, const void *e2)
1959 const char *s1 = *(const char *const *)e1;
1960 const char *s2 = *(const char *const *)e2;
1962 return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1965 static int compare_string3(const void *e1, const void *e2)
1967 const char *s1 = *(const char *const *)e1;
1968 const char *s2 = *(const char *const *)e2;
1969 char key1[256], key2[256];
1971 LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
1972 LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
1973 return strcmp(key1, key2);
1976 static void test_sorting(void)
1978 char buf[256];
1979 char **str_buf = (char **)buf;
1980 int i;
1982 assert(sizeof(buf) >= sizeof(strings));
1984 /* 1. sort using lstrcmpA */
1985 memcpy(buf, strings, sizeof(strings));
1986 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
1987 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1989 ok(!strcmp(strings_sorted[i], str_buf[i]),
1990 "qsort using lstrcmpA failed for element %d\n", i);
1992 /* 2. sort using CompareStringA */
1993 memcpy(buf, strings, sizeof(strings));
1994 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
1995 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1997 ok(!strcmp(strings_sorted[i], str_buf[i]),
1998 "qsort using CompareStringA failed for element %d\n", i);
2000 /* 3. sort using sort keys */
2001 memcpy(buf, strings, sizeof(strings));
2002 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
2003 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
2005 ok(!strcmp(strings_sorted[i], str_buf[i]),
2006 "qsort using sort keys failed for element %d\n", i);
2010 static void test_FoldStringA(void)
2012 int ret, i, j;
2013 BOOL is_special;
2014 char src[256], dst[256];
2015 static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0' };
2016 static const char digits_dst[] = { '1','2','3','\0' };
2017 static const char composite_src[] =
2019 0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
2020 0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
2021 0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
2022 0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
2023 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
2024 0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
2025 0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
2026 0xfb,0xfc,0xfd,0xff,'\0'
2028 static const char composite_dst[] =
2030 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
2031 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
2032 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
2033 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
2034 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
2035 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
2036 0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
2037 0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
2038 0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
2039 0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
2040 0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
2041 0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
2042 0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
2043 0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
2044 0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
2046 static const char composite_dst_alt[] =
2048 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
2049 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
2050 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
2051 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
2052 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
2053 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
2054 0x4f,0x7e,0x4f,0xa8,0xd8,0x55,0x60,0x55,
2055 0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,0x61,
2056 0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,0x61,
2057 0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,0x65,
2058 0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,0x69,
2059 0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,0x6f,
2060 0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,0x6f,
2061 0xa8,0xf8,0x75,0x60,0x75,0xb4,0x75,0x5e,
2062 0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
2064 static const char ligatures_src[] =
2066 0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
2068 static const char ligatures_dst[] =
2070 'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
2072 static const struct special
2074 char src;
2075 char dst[4];
2076 } foldczone_special[] =
2078 /* src dst */
2079 { 0x85, { 0x2e, 0x2e, 0x2e, 0x00 } },
2080 { 0x98, { 0x20, 0x7e, 0x00 } },
2081 { 0x99, { 0x54, 0x4d, 0x00 } },
2082 { 0xa0, { 0x20, 0x00 } },
2083 { 0xa8, { 0x20, 0xa8, 0x00 } },
2084 { 0xaa, { 0x61, 0x00 } },
2085 { 0xaf, { 0x20, 0xaf, 0x00 } },
2086 { 0xb2, { 0x32, 0x00 } },
2087 { 0xb3, { 0x33, 0x00 } },
2088 { 0xb4, { 0x20, 0xb4, 0x00 } },
2089 { 0xb8, { 0x20, 0xb8, 0x00 } },
2090 { 0xb9, { 0x31, 0x00 } },
2091 { 0xba, { 0x6f, 0x00 } },
2092 { 0xbc, { 0x31, 0x2f, 0x34, 0x00 } },
2093 { 0xbd, { 0x31, 0x2f, 0x32, 0x00 } },
2094 { 0xbe, { 0x33, 0x2f, 0x34, 0x00 } },
2095 { 0x00 }
2098 if (!pFoldStringA)
2099 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
2101 /* these tests are locale specific */
2102 if (GetACP() != 1252)
2104 trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
2105 return;
2108 /* MAP_FOLDDIGITS */
2109 SetLastError(0);
2110 ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
2111 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2113 win_skip("FoldStringA is not implemented\n");
2114 return;
2116 ok(ret == 4, "Expected ret == 4, got %d, error %d\n", ret, GetLastError());
2117 ok(strcmp(dst, digits_dst) == 0,
2118 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
2119 for (i = 1; i < 256; i++)
2121 if (!strchr(digits_src, i))
2123 src[0] = i;
2124 src[1] = '\0';
2125 SetLastError(0);
2126 ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
2127 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2128 ok(dst[0] == src[0],
2129 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
2133 /* MAP_EXPAND_LIGATURES */
2134 SetLastError(0);
2135 ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
2136 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
2137 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
2138 ok(ret == sizeof(ligatures_dst), "Got %d, error %d\n", ret, GetLastError());
2139 ok(strcmp(dst, ligatures_dst) == 0,
2140 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
2141 for (i = 1; i < 256; i++)
2143 if (!strchr(ligatures_src, i))
2145 src[0] = i;
2146 src[1] = '\0';
2147 SetLastError(0);
2148 ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
2149 if (ret == 3)
2151 /* Vista */
2152 ok((i == 0xDC && lstrcmpA(dst, "UE") == 0) ||
2153 (i == 0xFC && lstrcmpA(dst, "ue") == 0),
2154 "Got %s for %d\n", dst, i);
2156 else
2158 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2159 ok(dst[0] == src[0],
2160 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
2166 /* MAP_COMPOSITE */
2167 SetLastError(0);
2168 ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
2169 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2170 ok(ret == 121 || ret == 119, "Expected 121 or 119, got %d\n", ret);
2171 ok(strcmp(dst, composite_dst) == 0 || strcmp(dst, composite_dst_alt) == 0,
2172 "MAP_COMPOSITE: Mismatch, got '%s'\n", dst);
2174 for (i = 1; i < 256; i++)
2176 if (!strchr(composite_src, i))
2178 src[0] = i;
2179 src[1] = '\0';
2180 SetLastError(0);
2181 ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
2182 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2183 ok(dst[0] == src[0],
2184 "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
2185 (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
2189 /* MAP_FOLDCZONE */
2190 for (i = 1; i < 256; i++)
2192 src[0] = i;
2193 src[1] = '\0';
2194 SetLastError(0);
2195 ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
2196 is_special = FALSE;
2197 for (j = 0; foldczone_special[j].src != 0 && ! is_special; j++)
2199 if (foldczone_special[j].src == src[0])
2201 ok(ret == 2 || ret == lstrlenA(foldczone_special[j].dst) + 1,
2202 "Expected ret == 2 or %d, got %d, error %d\n",
2203 lstrlenA(foldczone_special[j].dst) + 1, ret, GetLastError());
2204 ok(src[0] == dst[0] || lstrcmpA(foldczone_special[j].dst, dst) == 0,
2205 "MAP_FOLDCZONE: string mismatch for 0x%02x\n",
2206 (unsigned char)src[0]);
2207 is_special = TRUE;
2210 if (! is_special)
2212 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2213 ok(src[0] == dst[0],
2214 "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
2215 (unsigned char)src[0], (unsigned char)dst[0]);
2219 /* MAP_PRECOMPOSED */
2220 for (i = 1; i < 256; i++)
2222 src[0] = i;
2223 src[1] = '\0';
2224 SetLastError(0);
2225 ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
2226 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2227 ok(src[0] == dst[0],
2228 "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
2229 (unsigned char)src[0], (unsigned char)dst[0]);
2233 static void test_FoldStringW(void)
2235 int ret;
2236 unsigned int i, j;
2237 WCHAR src[256], dst[256], ch, prev_ch = 1;
2238 static const DWORD badFlags[] =
2241 MAP_PRECOMPOSED|MAP_COMPOSITE,
2242 MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
2243 MAP_COMPOSITE|MAP_EXPAND_LIGATURES
2245 /* Ranges of digits 0-9 : Must be sorted! */
2246 static const WCHAR digitRanges[] =
2248 0x0030, /* '0'-'9' */
2249 0x0660, /* Eastern Arabic */
2250 0x06F0, /* Arabic - Hindu */
2251 0x0966, /* Devengari */
2252 0x09E6, /* Bengalii */
2253 0x0A66, /* Gurmukhi */
2254 0x0AE6, /* Gujarati */
2255 0x0B66, /* Oriya */
2256 0x0BE6, /* Tamil - No 0 */
2257 0x0C66, /* Telugu */
2258 0x0CE6, /* Kannada */
2259 0x0D66, /* Maylayalam */
2260 0x0E50, /* Thai */
2261 0x0ED0, /* Laos */
2262 0x0F29, /* Tibet - 0 is out of sequence */
2263 0x2070, /* Superscript - 1, 2, 3 are out of sequence */
2264 0x2080, /* Subscript */
2265 0x245F, /* Circled - 0 is out of sequence */
2266 0x2473, /* Bracketed */
2267 0x2487, /* Full stop */
2268 0x2775, /* Inverted circled - No 0 */
2269 0x277F, /* Patterned circled - No 0 */
2270 0x2789, /* Inverted Patterned circled - No 0 */
2271 0x3020, /* Hangzhou */
2272 0xff10, /* Pliene chasse (?) */
2273 0xffff /* Terminator */
2275 /* Digits which are represented, but out of sequence */
2276 static const WCHAR outOfSequenceDigits[] =
2278 0xB9, /* Superscript 1 */
2279 0xB2, /* Superscript 2 */
2280 0xB3, /* Superscript 3 */
2281 0x0F33, /* Tibetan half zero */
2282 0x24EA, /* Circled 0 */
2283 0x3007, /* Ideographic number zero */
2284 '\0' /* Terminator */
2286 /* Digits in digitRanges for which no representation is available */
2287 static const WCHAR noDigitAvailable[] =
2289 0x0BE6, /* No Tamil 0 */
2290 0x0F29, /* No Tibetan half zero (out of sequence) */
2291 0x2473, /* No Bracketed 0 */
2292 0x2487, /* No 0 Full stop */
2293 0x2775, /* No inverted circled 0 */
2294 0x277F, /* No patterned circled */
2295 0x2789, /* No inverted Patterned circled */
2296 0x3020, /* No Hangzhou 0 */
2297 '\0' /* Terminator */
2299 static const WCHAR foldczone_src[] =
2301 'W', 'i', 'n', 'e', 0x0348, 0x0551, 0x1323, 0x280d,
2302 0xff37, 0xff49, 0xff4e, 0xff45, '\0'
2304 static const WCHAR foldczone_dst[] =
2306 'W','i','n','e',0x0348,0x0551,0x1323,0x280d,'W','i','n','e','\0'
2308 static const WCHAR foldczone_todo_src[] =
2310 0x3c5,0x308,0x6a,0x30c,0xa0,0xaa,0
2312 static const WCHAR foldczone_todo_dst[] =
2314 0x3cb,0x1f0,' ','a',0
2316 static const WCHAR foldczone_todo_broken_dst[] =
2318 0x3cb,0x1f0,0xa0,0xaa,0
2320 static const WCHAR ligatures_src[] =
2322 'W', 'i', 'n', 'e', 0x03a6, 0x03b9, 0x03bd, 0x03b5,
2323 0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
2324 0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
2325 0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
2326 0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
2327 0xfb04, 0xfb05, 0xfb06, '\0'
2329 static const WCHAR ligatures_dst[] =
2331 'W','i','n','e',0x03a6,0x03b9,0x03bd,0x03b5,
2332 'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
2333 'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
2334 'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
2335 0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
2336 'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
2339 if (!pFoldStringW)
2341 win_skip("FoldStringW is not available\n");
2342 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
2345 /* Invalid flag combinations */
2346 for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
2348 src[0] = dst[0] = '\0';
2349 SetLastError(0);
2350 ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
2351 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
2353 win_skip("FoldStringW is not implemented\n");
2354 return;
2356 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
2357 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2360 /* src & dst cannot be the same */
2361 SetLastError(0);
2362 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
2363 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2364 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2366 /* src can't be NULL */
2367 SetLastError(0);
2368 ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
2369 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2370 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2372 /* srclen can't be 0 */
2373 SetLastError(0);
2374 ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
2375 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2376 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2378 /* dstlen can't be < 0 */
2379 SetLastError(0);
2380 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
2381 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2382 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2384 /* Ret includes terminating NUL which is appended if srclen = -1 */
2385 SetLastError(0);
2386 src[0] = 'A';
2387 src[1] = '\0';
2388 dst[0] = '\0';
2389 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
2390 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2391 ok(dst[0] == 'A' && dst[1] == '\0',
2392 "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%d\n",
2393 'A', '\0', ret, dst[0], dst[1], GetLastError());
2395 /* If size is given, result is not NUL terminated */
2396 SetLastError(0);
2397 src[0] = 'A';
2398 src[1] = 'A';
2399 dst[0] = 'X';
2400 dst[1] = 'X';
2401 ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
2402 ok(ret == 1, "Expected ret == 1, got %d, error %d\n", ret, GetLastError());
2403 ok(dst[0] == 'A' && dst[1] == 'X',
2404 "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%d\n",
2405 'A','X', ret, dst[0], dst[1], GetLastError());
2407 /* MAP_FOLDDIGITS */
2408 for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
2410 /* Check everything before this range */
2411 for (ch = prev_ch; ch < digitRanges[j]; ch++)
2413 SetLastError(0);
2414 src[0] = ch;
2415 src[1] = dst[0] = '\0';
2416 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2417 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2419 ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
2420 /* Wine (correctly) maps all Unicode 4.0+ digits */
2421 isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF || ch == 0x19da ||
2422 (ch >= 0x1369 && ch <= 0x1371),
2423 "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
2426 if (digitRanges[j] == 0xffff)
2427 break; /* Finished the whole code point space */
2429 for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
2431 WCHAR c;
2433 /* Map out of sequence characters */
2434 if (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
2435 else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
2436 else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
2437 else if (ch == 0x245F) c = 0x24EA; /* Circled 0 */
2438 else c = ch;
2439 SetLastError(0);
2440 src[0] = c;
2441 src[1] = dst[0] = '\0';
2442 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2443 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2445 ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
2446 broken( dst[0] == ch ) || /* old Windows versions don't have all mappings */
2447 (digitRanges[j] == 0x3020 && dst[0] == ch) || /* Hangzhou not present in all Windows versions */
2448 (digitRanges[j] == 0x0F29 && dst[0] == ch) || /* Tibetan not present in all Windows versions */
2449 strchrW(noDigitAvailable, c),
2450 "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
2451 ch, '0' + digitRanges[j] - ch, dst[0]);
2453 prev_ch = ch;
2456 /* MAP_FOLDCZONE */
2457 SetLastError(0);
2458 ret = pFoldStringW(MAP_FOLDCZONE, foldczone_src, -1, dst, 256);
2459 ok(ret == sizeof(foldczone_dst)/sizeof(foldczone_dst[0]),
2460 "Got %d, error %d\n", ret, GetLastError());
2461 ok(!memcmp(dst, foldczone_dst, sizeof(foldczone_dst)),
2462 "MAP_FOLDCZONE: Expanded incorrectly\n");
2464 ret = pFoldStringW(MAP_FOLDCZONE|MAP_PRECOMPOSED, foldczone_todo_src, -1, dst, 256);
2465 todo_wine ok(ret == sizeof(foldczone_todo_dst)/sizeof(foldczone_todo_dst[0]),
2466 "Got %d, error %d\n", ret, GetLastError());
2467 todo_wine ok(!memcmp(dst, foldczone_todo_dst, sizeof(foldczone_todo_dst))
2468 || broken(!memcmp(dst, foldczone_todo_broken_dst, sizeof(foldczone_todo_broken_dst))),
2469 "MAP_FOLDCZONE: Expanded incorrectly (%s)\n", wine_dbgstr_w(dst));
2471 /* MAP_EXPAND_LIGATURES */
2472 SetLastError(0);
2473 ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
2474 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
2475 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
2476 ok(ret == sizeof(ligatures_dst)/sizeof(ligatures_dst[0]),
2477 "Got %d, error %d\n", ret, GetLastError());
2478 ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
2479 "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
2482 /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
2487 #define LCID_OK(l) \
2488 ok(lcid == l, "Expected lcid = %08x, got %08x\n", l, lcid)
2489 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
2490 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
2491 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
2492 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
2494 static void test_ConvertDefaultLocale(void)
2496 LCID lcid;
2498 /* Doesn't change lcid, even if non default sublang/sort used */
2499 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_US, SORT_DEFAULT);
2500 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_UK, SORT_DEFAULT);
2501 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT);
2502 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE);
2504 /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
2505 LCID_RES(MKLCID(LANG_ENGLISH, SUBLANG_NEUTRAL, SORT_DEFAULT),
2506 MKLCID(LANG_ENGLISH, SUBLANG_DEFAULT, SORT_DEFAULT));
2507 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
2508 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
2510 /* Invariant language is not treated specially */
2511 TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
2513 /* User/system default languages alone are not mapped */
2514 TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
2515 TEST_LCIDLANG(LANG_USER_DEFAULT, SORT_JAPANESE_UNICODE);
2517 /* Default lcids */
2518 LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
2519 LCID_RES(LOCALE_USER_DEFAULT, GetUserDefaultLCID());
2520 LCID_RES(LOCALE_NEUTRAL, GetUserDefaultLCID());
2523 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
2524 DWORD dwFlags, LONG_PTR lParam)
2526 trace("%08x, %s, %s, %08x, %08lx\n",
2527 lgrpid, lpszNum, lpszName, dwFlags, lParam);
2529 ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
2530 "Enumerated grp %d not valid (flags %d)\n", lgrpid, dwFlags);
2532 /* If lParam is one, we are calling with flags defaulted from 0 */
2533 ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
2534 "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %d\n", dwFlags);
2536 return TRUE;
2539 static void test_EnumSystemLanguageGroupsA(void)
2541 BOOL ret;
2543 if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
2545 win_skip("EnumSystemLanguageGroupsA and/or IsValidLanguageGroup are not available\n");
2546 return;
2549 /* No enumeration proc */
2550 SetLastError(0);
2551 ret = pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
2552 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2554 win_skip("EnumSystemLanguageGroupsA is not implemented\n");
2555 return;
2557 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2558 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2560 /* Invalid flags */
2561 SetLastError(0);
2562 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
2563 ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2565 /* No flags - defaults to LGRPID_INSTALLED */
2566 SetLastError(0xdeadbeef);
2567 pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
2568 ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
2570 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
2571 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
2574 static BOOL CALLBACK enum_func( LPWSTR name, DWORD flags, LPARAM lparam )
2576 trace( "%s %x\n", wine_dbgstr_w(name), flags );
2577 return TRUE;
2580 static void test_EnumSystemLocalesEx(void)
2582 BOOL ret;
2584 if (!pEnumSystemLocalesEx)
2586 win_skip( "EnumSystemLocalesEx not available\n" );
2587 return;
2589 SetLastError( 0xdeadbeef );
2590 ret = pEnumSystemLocalesEx( enum_func, LOCALE_ALL, 0, (void *)1 );
2591 ok( !ret, "should have failed\n" );
2592 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
2593 SetLastError( 0xdeadbeef );
2594 ret = pEnumSystemLocalesEx( enum_func, 0, 0, NULL );
2595 ok( ret, "failed err %u\n", GetLastError() );
2598 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
2599 LONG_PTR lParam)
2601 trace("%08x, %08x, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
2603 /* invalid locale enumerated on some platforms */
2604 if (lcid == 0)
2605 return TRUE;
2607 ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
2608 "Enumerated grp %d not valid\n", lgrpid);
2609 ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
2610 "Enumerated grp locale %d not valid\n", lcid);
2611 return TRUE;
2614 static void test_EnumLanguageGroupLocalesA(void)
2616 BOOL ret;
2618 if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
2620 win_skip("EnumLanguageGroupLocalesA and/or IsValidLanguageGroup are not available\n");
2621 return;
2624 /* No enumeration proc */
2625 SetLastError(0);
2626 ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
2627 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2629 win_skip("EnumLanguageGroupLocalesA is not implemented\n");
2630 return;
2632 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2633 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2635 /* lgrpid too small */
2636 SetLastError(0);
2637 ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
2638 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2639 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2641 /* lgrpid too big */
2642 SetLastError(0);
2643 ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
2644 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2645 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2647 /* dwFlags is reserved */
2648 SetLastError(0);
2649 ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
2650 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2651 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2653 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2656 static void test_SetLocaleInfoA(void)
2658 BOOL bRet;
2659 LCID lcid = GetUserDefaultLCID();
2661 /* Null data */
2662 SetLastError(0);
2663 bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2664 ok( !bRet && GetLastError() == ERROR_INVALID_PARAMETER,
2665 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2667 /* IDATE */
2668 SetLastError(0);
2669 bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, "test_SetLocaleInfoA");
2670 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2671 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2673 /* ILDATE */
2674 SetLastError(0);
2675 bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, "test_SetLocaleInfoA");
2676 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2677 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2680 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2682 trace("%s %08lx\n", value, lParam);
2683 return(TRUE);
2686 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2688 ok(!enumCount, "callback called again unexpected\n");
2689 enumCount++;
2690 return(FALSE);
2693 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2695 ok(0,"callback called unexpected\n");
2696 return(FALSE);
2699 static void test_EnumUILanguageA(void)
2701 BOOL ret;
2702 if (!pEnumUILanguagesA) {
2703 win_skip("EnumUILanguagesA is not available on Win9x or NT4\n");
2704 return;
2707 SetLastError(ERROR_SUCCESS);
2708 ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2709 if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2711 win_skip("EnumUILanguagesA is not implemented\n");
2712 return;
2714 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2716 enumCount = 0;
2717 SetLastError(ERROR_SUCCESS);
2718 ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2719 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2721 SetLastError(ERROR_SUCCESS);
2722 ret = pEnumUILanguagesA(NULL, 0, 0);
2723 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2724 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2725 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2727 SetLastError(ERROR_SUCCESS);
2728 ret = pEnumUILanguagesA(luilocale_proc3A, 0x5a5a5a5a, 0);
2729 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2730 ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2732 SetLastError(ERROR_SUCCESS);
2733 ret = pEnumUILanguagesA(NULL, 0x5a5a5a5a, 0);
2734 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2735 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2736 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2739 static char date_fmt_buf[1024];
2741 static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
2743 lstrcatA(date_fmt_buf, fmt);
2744 lstrcatA(date_fmt_buf, "\n");
2745 return TRUE;
2748 static void test_EnumDateFormatsA(void)
2750 char *p, buf[256];
2751 BOOL ret;
2752 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2754 trace("EnumDateFormatsA 0\n");
2755 date_fmt_buf[0] = 0;
2756 SetLastError(0xdeadbeef);
2757 ret = EnumDateFormatsA(enum_datetime_procA, lcid, 0);
2758 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2760 win_skip("0 for dwFlags is not supported\n");
2762 else
2764 ok(ret, "EnumDateFormatsA(0) error %d\n", GetLastError());
2765 trace("%s\n", date_fmt_buf);
2766 /* test the 1st enumerated format */
2767 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2768 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2769 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2770 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2773 trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n");
2774 date_fmt_buf[0] = 0;
2775 SetLastError(0xdeadbeef);
2776 ret = EnumDateFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2777 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2779 win_skip("LOCALE_USE_CP_ACP is not supported\n");
2781 else
2783 ok(ret, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2784 trace("%s\n", date_fmt_buf);
2785 /* test the 1st enumerated format */
2786 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2787 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2788 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2789 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2792 trace("EnumDateFormatsA DATE_SHORTDATE\n");
2793 date_fmt_buf[0] = 0;
2794 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_SHORTDATE);
2795 ok(ret, "EnumDateFormatsA(DATE_SHORTDATE) error %d\n", GetLastError());
2796 trace("%s\n", date_fmt_buf);
2797 /* test the 1st enumerated format */
2798 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2799 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2800 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2801 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2803 trace("EnumDateFormatsA DATE_LONGDATE\n");
2804 date_fmt_buf[0] = 0;
2805 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_LONGDATE);
2806 ok(ret, "EnumDateFormatsA(DATE_LONGDATE) error %d\n", GetLastError());
2807 trace("%s\n", date_fmt_buf);
2808 /* test the 1st enumerated format */
2809 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2810 ret = GetLocaleInfoA(lcid, LOCALE_SLONGDATE, buf, sizeof(buf));
2811 ok(ret, "GetLocaleInfoA(LOCALE_SLONGDATE) error %d\n", GetLastError());
2812 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2814 trace("EnumDateFormatsA DATE_YEARMONTH\n");
2815 date_fmt_buf[0] = 0;
2816 SetLastError(0xdeadbeef);
2817 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_YEARMONTH);
2818 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2820 skip("DATE_YEARMONTH is only present on W2K and later\n");
2821 return;
2823 ok(ret, "EnumDateFormatsA(DATE_YEARMONTH) error %d\n", GetLastError());
2824 trace("%s\n", date_fmt_buf);
2825 /* test the 1st enumerated format */
2826 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2827 ret = GetLocaleInfoA(lcid, LOCALE_SYEARMONTH, buf, sizeof(buf));
2828 ok(ret, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %d\n", GetLastError());
2829 ok(!lstrcmpA(date_fmt_buf, buf) || broken(!buf[0]) /* win9x */,
2830 "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2833 static void test_EnumTimeFormatsA(void)
2835 char *p, buf[256];
2836 BOOL ret;
2837 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2839 trace("EnumTimeFormatsA 0\n");
2840 date_fmt_buf[0] = 0;
2841 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, 0);
2842 ok(ret, "EnumTimeFormatsA(0) error %d\n", GetLastError());
2843 trace("%s\n", date_fmt_buf);
2844 /* test the 1st enumerated format */
2845 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2846 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2847 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2848 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2850 trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n");
2851 date_fmt_buf[0] = 0;
2852 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2853 ok(ret, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2854 trace("%s\n", date_fmt_buf);
2855 /* test the 1st enumerated format */
2856 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2857 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2858 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2859 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2862 static void test_GetCPInfo(void)
2864 BOOL ret;
2865 CPINFO cpinfo;
2867 SetLastError(0xdeadbeef);
2868 ret = GetCPInfo(CP_SYMBOL, &cpinfo);
2869 ok(!ret, "GetCPInfo(CP_SYMBOL) should fail\n");
2870 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2871 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2873 SetLastError(0xdeadbeef);
2874 ret = GetCPInfo(CP_UTF7, &cpinfo);
2875 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2877 skip("Codepage CP_UTF7 is not installed/available\n");
2879 else
2881 ok(ret, "GetCPInfo(CP_UTF7) error %u\n", GetLastError());
2882 ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2883 ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2884 ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2885 ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2886 ok(cpinfo.MaxCharSize == 5, "expected 5, got 0x%x\n", cpinfo.MaxCharSize);
2889 SetLastError(0xdeadbeef);
2890 ret = GetCPInfo(CP_UTF8, &cpinfo);
2891 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2893 skip("Codepage CP_UTF8 is not installed/available\n");
2895 else
2897 ok(ret, "GetCPInfo(CP_UTF8) error %u\n", GetLastError());
2898 ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2899 ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2900 ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2901 ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2902 ok(cpinfo.MaxCharSize == 4 || broken(cpinfo.MaxCharSize == 3) /* win9x */,
2903 "expected 4, got %u\n", cpinfo.MaxCharSize);
2908 * The CT_TYPE1 has varied over windows version.
2909 * The current target for correct behavior is windows 7.
2910 * There was a big shift between windows 2000 (first introduced) and windows Xp
2911 * Most of the old values below are from windows 2000.
2912 * A smaller subset of changes happened between windows Xp and Window vista/7
2914 static void test_GetStringTypeW(void)
2916 static const WCHAR blanks[] = {0x9, 0x20, 0xa0, 0x3000, 0xfeff};
2917 static const WORD blanks_new[] = {C1_SPACE | C1_CNTRL | C1_BLANK | C1_DEFINED,
2918 C1_SPACE | C1_BLANK | C1_DEFINED,
2919 C1_SPACE | C1_BLANK | C1_DEFINED,
2920 C1_SPACE | C1_BLANK | C1_DEFINED,
2921 C1_CNTRL | C1_BLANK | C1_DEFINED};
2922 static const WORD blanks_old[] ={C1_SPACE | C1_CNTRL | C1_BLANK,
2923 C1_SPACE | C1_BLANK,
2924 C1_SPACE | C1_BLANK,
2925 C1_SPACE | C1_BLANK,
2926 C1_SPACE | C1_BLANK};
2928 static const WCHAR undefined[] = {0x378, 0x379, 0x604, 0xfff8, 0xfffe};
2930 /* Lu, Ll, Lt */
2931 static const WCHAR alpha[] = {0x47, 0x67, 0x1c5};
2932 static const WORD alpha_old[] = {C1_UPPER | C1_ALPHA,
2933 C1_LOWER | C1_ALPHA,
2934 C1_UPPER | C1_LOWER | C1_ALPHA,
2935 C1_ALPHA};
2937 /* Sk, Sk, Mn, So, Me */
2938 static const WCHAR oldpunc[] = { 0x2c2, 0x2e5, 0x322, 0x482, 0x6de,
2939 /* Sc, Sm, No,*/
2940 0xffe0, 0xffe9, 0x2153};
2942 /* Lm, Nl, Cf, 0xad(Cf), 0x1f88 (Lt), Lo, Mc */
2943 static const WCHAR changed[] = {0x2b0, 0x2160, 0x600, 0xad, 0x1f88, 0x294, 0x903};
2944 static const WORD changed_old[] = { C1_PUNCT, C1_PUNCT, 0, C1_PUNCT, C1_UPPER | C1_ALPHA, C1_ALPHA, C1_PUNCT };
2945 static const WORD changed_xp[] = {C1_ALPHA | C1_DEFINED,
2946 C1_ALPHA | C1_DEFINED,
2947 C1_CNTRL | C1_DEFINED,
2948 C1_PUNCT | C1_DEFINED,
2949 C1_UPPER | C1_LOWER | C1_ALPHA | C1_DEFINED,
2950 C1_ALPHA | C1_LOWER | C1_DEFINED,
2951 C1_ALPHA | C1_DEFINED };
2952 static const WORD changed_new[] = { C1_ALPHA | C1_DEFINED,
2953 C1_ALPHA | C1_DEFINED,
2954 C1_CNTRL | C1_DEFINED,
2955 C1_PUNCT | C1_CNTRL | C1_DEFINED,
2956 C1_UPPER | C1_LOWER | C1_ALPHA | C1_DEFINED,
2957 C1_ALPHA | C1_DEFINED,
2958 C1_DEFINED
2960 /* Pc, Pd, Ps, Pe, Pi, Pf, Po*/
2961 static const WCHAR punct[] = { 0x5f, 0x2d, 0x28, 0x29, 0xab, 0xbb, 0x21 };
2963 static const WCHAR punct_special[] = {0x24, 0x2b, 0x3c, 0x3e, 0x5e, 0x60,
2964 0x7c, 0x7e, 0xa2, 0xbe, 0xd7, 0xf7};
2965 static const WCHAR digit_special[] = {0xb2, 0xb3, 0xb9};
2966 static const WCHAR lower_special[] = {0x2071, 0x207f};
2967 static const WCHAR cntrl_special[] = {0x070f, 0x200c, 0x200d,
2968 0x200e, 0x200f, 0x202a, 0x202b, 0x202c, 0x202d, 0x202e,
2969 0x206a, 0x206b, 0x206c, 0x206d, 0x206e, 0x206f, 0xfeff,
2970 0xfff9, 0xfffa, 0xfffb};
2971 static const WCHAR space_special[] = {0x09, 0x0d, 0x85};
2973 WORD types[20];
2974 int i;
2976 memset(types,0,sizeof(types));
2977 GetStringTypeW(CT_CTYPE1, blanks, 5, types);
2978 for (i = 0; i < 5; i++)
2979 ok(types[i] == blanks_new[i] || broken(types[i] == blanks_old[i] || broken(types[i] == 0)), "incorrect type1 returned for %x -> (%x != %x)\n",blanks[i],types[i],blanks_new[i]);
2981 memset(types,0,sizeof(types));
2982 GetStringTypeW(CT_CTYPE1, alpha, 3, types);
2983 for (i = 0; i < 3; i++)
2984 ok(types[i] == (C1_DEFINED | alpha_old[i]) || broken(types[i] == alpha_old[i]) || broken(types[i] == 0), "incorrect types returned for %x -> (%x != %x)\n",alpha[i], types[i],(C1_DEFINED | alpha_old[i]));
2985 memset(types,0,sizeof(types));
2986 GetStringTypeW(CT_CTYPE1, undefined, 5, types);
2987 for (i = 0; i < 5; i++)
2988 ok(types[i] == 0, "incorrect types returned for %x -> (%x != 0)\n",undefined[i], types[i]);
2990 memset(types,0,sizeof(types));
2991 GetStringTypeW(CT_CTYPE1, oldpunc, 8, types);
2992 for (i = 0; i < 8; i++)
2993 ok(types[i] == C1_DEFINED || broken(types[i] == C1_PUNCT) || broken(types[i] == 0), "incorrect types returned for %x -> (%x != %x)\n",oldpunc[i], types[i], C1_DEFINED);
2995 memset(types,0,sizeof(types));
2996 GetStringTypeW(CT_CTYPE1, changed, 7, types);
2997 for (i = 0; i < 7; i++)
2998 ok(types[i] == changed_new[i] || broken(types[i] == changed_old[i]) || broken(types[i] == changed_xp[i]) || broken(types[i] == 0), "incorrect types returned for %x -> (%x != %x)\n",changed[i], types[i], changed_new[i]);
3000 memset(types,0,sizeof(types));
3001 GetStringTypeW(CT_CTYPE1, punct, 7, types);
3002 for (i = 0; i < 7; i++)
3003 ok(types[i] == (C1_PUNCT | C1_DEFINED) || broken(types[i] == C1_PUNCT) || broken(types[i] == 0), "incorrect types returned for %x -> (%x != %x)\n",punct[i], types[i], (C1_PUNCT | C1_DEFINED));
3006 memset(types,0,sizeof(types));
3007 GetStringTypeW(CT_CTYPE1, punct_special, 12, types);
3008 for (i = 0; i < 12; i++)
3009 ok(types[i] & C1_PUNCT || broken(types[i] == 0), "incorrect types returned for %x -> (%x doest not have %x)\n",punct_special[i], types[i], C1_PUNCT);
3011 memset(types,0,sizeof(types));
3012 GetStringTypeW(CT_CTYPE1, digit_special, 3, types);
3013 for (i = 0; i < 3; i++)
3014 ok(types[i] & C1_DIGIT || broken(types[i] == 0), "incorrect types returned for %x -> (%x doest not have = %x)\n",digit_special[i], types[i], C1_DIGIT);
3016 memset(types,0,sizeof(types));
3017 GetStringTypeW(CT_CTYPE1, lower_special, 2, types);
3018 for (i = 0; i < 2; i++)
3019 ok(types[i] & C1_LOWER || broken(types[i] == C1_PUNCT) || broken(types[i] == 0), "incorrect types returned for %x -> (%x does not have %x)\n",lower_special[i], types[i], C1_LOWER);
3021 memset(types,0,sizeof(types));
3022 GetStringTypeW(CT_CTYPE1, cntrl_special, 20, types);
3023 for (i = 0; i < 20; i++)
3024 ok(types[i] & C1_CNTRL || broken(types[i] == (C1_BLANK|C1_SPACE)) || broken(types[i] == C1_PUNCT) || broken(types[i] == 0), "incorrect types returned for %x -> (%x does not have %x)\n",cntrl_special[i], types[i], C1_CNTRL);
3026 memset(types,0,sizeof(types));
3027 GetStringTypeW(CT_CTYPE1, space_special, 3, types);
3028 for (i = 0; i < 3; i++)
3029 ok(types[i] & C1_SPACE || broken(types[i] == C1_CNTRL) || broken(types[i] == 0), "incorrect types returned for %x -> (%x does not have %x)\n",space_special[i], types[i], C1_SPACE );
3032 static void test_IdnToNameprepUnicode(void)
3034 struct {
3035 DWORD in_len;
3036 const WCHAR in[64];
3037 DWORD ret;
3038 const WCHAR out[64];
3039 DWORD flags;
3040 DWORD err;
3041 DWORD todo;
3042 } test_data[] = {
3044 5, {'t','e','s','t',0},
3045 5, {'t','e','s','t',0},
3046 0, 0xdeadbeef
3049 3, {'a',0xe111,'b'},
3050 0, {0},
3051 0, ERROR_INVALID_NAME
3054 4, {'t',0,'e',0},
3055 0, {0},
3056 0, ERROR_INVALID_NAME
3059 1, {'T',0},
3060 1, {'T',0},
3061 0, 0xdeadbeef
3064 1, {0},
3065 0, {0},
3066 0, ERROR_INVALID_NAME
3069 6, {' ','-','/','[',']',0},
3070 6, {' ','-','/','[',']',0},
3071 0, 0xdeadbeef
3074 3, {'a','-','a'},
3075 3, {'a','-','a'},
3076 IDN_USE_STD3_ASCII_RULES, 0xdeadbeef
3079 3, {'a','a','-'},
3080 0, {0},
3081 IDN_USE_STD3_ASCII_RULES, ERROR_INVALID_NAME
3083 { /* FoldString is not working as expected when MAP_FOLDCZONE is specified (composition+compatibility) */
3084 10, {'T',0xdf,0x130,0x143,0x37a,0x6a,0x30c,' ',0xaa,0},
3085 12, {'t','s','s','i',0x307,0x144,' ',0x3b9,0x1f0,' ','a',0},
3086 0, 0xdeadbeef, TRUE
3089 11, {'t',0xad,0x34f,0x1806,0x180b,0x180c,0x180d,0x200b,0x200c,0x200d,0},
3090 2, {'t',0},
3091 0, 0xdeadbeef
3093 { /* Another example of incorrectly working FoldString (composition) */
3094 2, {0x3b0, 0},
3095 2, {0x3b0, 0},
3096 0, 0xdeadbeef, TRUE
3099 2, {0x221, 0},
3100 0, {0},
3101 0, ERROR_NO_UNICODE_TRANSLATION
3104 2, {0x221, 0},
3105 2, {0x221, 0},
3106 IDN_ALLOW_UNASSIGNED, 0xdeadbeef
3109 5, {'a','.','.','a',0},
3110 0, {0},
3111 0, ERROR_INVALID_NAME
3114 3, {'a','.',0},
3115 3, {'a','.',0},
3116 0, 0xdeadbeef
3120 WCHAR buf[1024];
3121 DWORD i, ret, err;
3123 if (!pIdnToNameprepUnicode)
3125 win_skip("IdnToNameprepUnicode is not available\n");
3126 return;
3129 ret = pIdnToNameprepUnicode(0, test_data[0].in,
3130 test_data[0].in_len, NULL, 0);
3131 ok(ret == test_data[0].ret, "ret = %d\n", ret);
3133 SetLastError(0xdeadbeef);
3134 ret = pIdnToNameprepUnicode(0, test_data[1].in,
3135 test_data[1].in_len, NULL, 0);
3136 err = GetLastError();
3137 ok(ret == test_data[1].ret, "ret = %d\n", ret);
3138 ok(err == test_data[1].err, "err = %d\n", err);
3140 SetLastError(0xdeadbeef);
3141 ret = pIdnToNameprepUnicode(0, test_data[0].in, -1,
3142 buf, sizeof(buf)/sizeof(WCHAR));
3143 err = GetLastError();
3144 ok(ret == test_data[0].ret, "ret = %d\n", ret);
3145 ok(err == 0xdeadbeef, "err = %d\n", err);
3147 SetLastError(0xdeadbeef);
3148 ret = pIdnToNameprepUnicode(0, test_data[0].in, -2,
3149 buf, sizeof(buf)/sizeof(WCHAR));
3150 err = GetLastError();
3151 ok(ret == 0, "ret = %d\n", ret);
3152 ok(err == ERROR_INVALID_PARAMETER, "err = %d\n", err);
3154 SetLastError(0xdeadbeef);
3155 ret = pIdnToNameprepUnicode(0, test_data[0].in, 0,
3156 buf, sizeof(buf)/sizeof(WCHAR));
3157 err = GetLastError();
3158 ok(ret == 0, "ret = %d\n", ret);
3159 ok(err == ERROR_INVALID_NAME, "err = %d\n", err);
3161 ret = pIdnToNameprepUnicode(IDN_ALLOW_UNASSIGNED|IDN_USE_STD3_ASCII_RULES,
3162 test_data[0].in, -1, buf, sizeof(buf)/sizeof(WCHAR));
3163 ok(ret == test_data[0].ret, "ret = %d\n", ret);
3165 SetLastError(0xdeadbeef);
3166 ret = pIdnToNameprepUnicode(0, NULL, 0, NULL, 0);
3167 err = GetLastError();
3168 ok(ret == 0, "ret = %d\n", ret);
3169 ok(err == ERROR_INVALID_PARAMETER, "err = %d\n", err);
3171 SetLastError(0xdeadbeef);
3172 ret = pIdnToNameprepUnicode(4, NULL, 0, NULL, 0);
3173 err = GetLastError();
3174 ok(ret == 0, "ret = %d\n", ret);
3175 ok(err == ERROR_INVALID_FLAGS, "err = %d\n", err);
3177 for (i=0; i<sizeof(test_data)/sizeof(*test_data); i++)
3179 SetLastError(0xdeadbeef);
3180 ret = pIdnToNameprepUnicode(test_data[i].flags, test_data[i].in,
3181 test_data[i].in_len, buf, sizeof(buf)/sizeof(WCHAR));
3182 err = GetLastError();
3183 if(!test_data[i].todo) {
3184 ok(ret == test_data[i].ret, "%d) ret = %d\n", i, ret);
3185 ok(err == test_data[i].err, "%d) err = %d\n", i, err);
3186 ok(!memcmp(test_data[i].out, buf, ret*sizeof(WCHAR)),
3187 "%d) buf = %s\n", i, wine_dbgstr_wn(buf, ret));
3188 }else {
3189 todo_wine ok(!memcmp(test_data[i].out, buf, ret*sizeof(WCHAR)),
3190 "%d) buf = %s\n", i, wine_dbgstr_wn(buf, ret));
3195 static void test_IdnToAscii(void)
3197 struct {
3198 DWORD in_len;
3199 const WCHAR in[64];
3200 DWORD ret;
3201 const WCHAR out[64];
3202 DWORD flags;
3203 DWORD err;
3204 } test_data[] = {
3206 5, {'T','e','s','t',0},
3207 5, {'T','e','s','t',0},
3208 0, 0xdeadbeef
3211 5, {'T','e',0x017c,'s','t',0},
3212 12, {'x','n','-','-','t','e','s','t','-','c','b','b',0},
3213 0, 0xdeadbeef
3216 12, {'t','e',0x0105,'s','t','.','t','e',0x017c,'s','t',0},
3217 26, {'x','n','-','-','t','e','s','t','-','c','t','a','.','x','n','-','-','t','e','s','t','-','c','b','b',0},
3218 0, 0xdeadbeef
3221 3, {0x0105,'.',0},
3222 9, {'x','n','-','-','2','d','a','.',0},
3223 0, 0xdeadbeef
3226 10, {'h','t','t','p',':','/','/','t',0x0106,0},
3227 17, {'x','n','-','-','h','t','t','p',':','/','/','t','-','7','8','a',0},
3228 0, 0xdeadbeef
3231 10, {0x4e3a,0x8bf4,0x4e0d,0x4ed6,0x5011,0x10d,0x11b,0x305c,0x306a,0},
3232 35, {'x','n','-','-','b','e','a','2','a','1','6','3','1','a','v','b','a',
3233 'v','4','4','t','y','h','a','3','2','b','9','1','e','g','s','2','t',0},
3234 0, 0xdeadbeef
3237 2, {0x221,0},
3238 8, {'x','n','-','-','6','l','a',0},
3239 IDN_ALLOW_UNASSIGNED, 0xdeadbeef
3243 WCHAR buf[1024];
3244 DWORD i, ret, err;
3246 if (!pIdnToAscii)
3248 win_skip("IdnToAscii is not available\n");
3249 return;
3252 for (i=0; i<sizeof(test_data)/sizeof(*test_data); i++)
3254 SetLastError(0xdeadbeef);
3255 ret = pIdnToAscii(test_data[i].flags, test_data[i].in,
3256 test_data[i].in_len, buf, sizeof(buf));
3257 err = GetLastError();
3258 ok(ret == test_data[i].ret, "%d) ret = %d\n", i, ret);
3259 ok(err == test_data[i].err, "%d) err = %d\n", i, err);
3260 ok(!memcmp(test_data[i].out, buf, ret*sizeof(WCHAR)),
3261 "%d) buf = %s\n", i, wine_dbgstr_wn(buf, ret));
3265 static void test_IdnToUnicode(void)
3267 struct {
3268 DWORD in_len;
3269 const WCHAR in[64];
3270 DWORD ret;
3271 const WCHAR out[64];
3272 DWORD flags;
3273 DWORD err;
3274 } test_data[] = {
3276 5, {'T','e','s','.',0},
3277 5, {'T','e','s','.',0},
3278 0, 0xdeadbeef
3281 2, {0x105,0},
3282 0, {0},
3283 0, ERROR_INVALID_NAME
3286 33, {'x','n','-','-','4','d','b','c','a','g','d','a','h','y','m','b',
3287 'x','e','k','h','e','h','6','e','0','a','7','f','e','i','0','b',0},
3288 23, {0x05dc,0x05de,0x05d4,0x05d4,0x05dd,0x05e4,0x05e9,0x05d5,0x05d8,
3289 0x05dc,0x05d0,0x05de,0x05d3,0x05d1,0x05e8,0x05d9,0x05dd,0x05e2,
3290 0x05d1,0x05e8,0x05d9,0x05ea,0},
3291 0, 0xdeadbeef
3294 34, {'t','e','s','t','.','x','n','-','-','k','d','a','9','a','g','5','e',
3295 '9','j','n','f','s','j','.','x','n','-','-','p','d','-','f','n','a'},
3296 16, {'t','e','s','t','.',0x0105,0x0119,0x015b,0x0107,
3297 0x0142,0x00f3,0x017c,'.','p',0x0119,'d'},
3298 0, 0xdeadbeef
3301 64, {'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
3302 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
3303 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
3304 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a'},
3305 0, {0},
3306 0, ERROR_INVALID_NAME
3309 8, {'x','n','-','-','6','l','a',0},
3310 2, {0x221,0},
3311 IDN_ALLOW_UNASSIGNED, 0xdeadbeef
3315 WCHAR buf[1024];
3316 DWORD i, ret, err;
3318 if (!pIdnToUnicode)
3320 win_skip("IdnToUnicode is not available\n");
3321 return;
3324 for (i=0; i<sizeof(test_data)/sizeof(*test_data); i++)
3326 SetLastError(0xdeadbeef);
3327 ret = pIdnToUnicode(test_data[i].flags, test_data[i].in,
3328 test_data[i].in_len, buf, sizeof(buf));
3329 err = GetLastError();
3330 ok(ret == test_data[i].ret, "%d) ret = %d\n", i, ret);
3331 ok(err == test_data[i].err, "%d) err = %d\n", i, err);
3332 ok(!memcmp(test_data[i].out, buf, ret*sizeof(WCHAR)),
3333 "%d) buf = %s\n", i, wine_dbgstr_wn(buf, ret));
3337 static void test_GetLocaleInfoEx(void)
3339 static const WCHAR enW[] = {'e','n',0};
3340 WCHAR bufferW[80];
3341 INT ret;
3343 if (!pGetLocaleInfoEx)
3345 win_skip("GetLocaleInfoEx not supported\n");
3346 return;
3349 ret = pGetLocaleInfoEx(enW, LOCALE_SNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3350 ok(ret || broken(ret == 0) /* Vista */, "got %d\n", ret);
3351 if (ret)
3353 static const WCHAR statesW[] = {'U','n','i','t','e','d',' ','S','t','a','t','e','s',0};
3354 static const WCHAR dummyW[] = {'d','u','m','m','y',0};
3355 static const WCHAR enusW[] = {'e','n','-','U','S',0};
3356 static const WCHAR usaW[] = {'U','S','A',0};
3357 static const WCHAR enuW[] = {'E','N','U',0};
3358 const struct neutralsublang_name_t *ptr = neutralsublang_names;
3359 DWORD val;
3361 todo_wine
3362 ok(!lstrcmpW(bufferW, enW), "got %s\n", wine_dbgstr_w(bufferW));
3364 ret = pGetLocaleInfoEx(enusW, LOCALE_SNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3365 ok(ret, "got %d\n", ret);
3366 ok(!lstrcmpW(bufferW, enusW), "got %s\n", wine_dbgstr_w(bufferW));
3368 ret = pGetLocaleInfoEx(enW, LOCALE_SABBREVCTRYNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3369 ok(ret, "got %d\n", ret);
3370 ok(!lstrcmpW(bufferW, usaW), "got %s\n", wine_dbgstr_w(bufferW));
3372 ret = pGetLocaleInfoEx(enW, LOCALE_SABBREVLANGNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3373 ok(ret, "got %d\n", ret);
3374 ok(!lstrcmpW(bufferW, enuW), "got %s\n", wine_dbgstr_w(bufferW));
3376 ret = pGetLocaleInfoEx(enW, LOCALE_SCOUNTRY, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3377 ok(ret, "got %d\n", ret);
3378 ok(!lstrcmpW(bufferW, statesW), "got %s\n", wine_dbgstr_w(bufferW));
3380 bufferW[0] = 0;
3381 ret = pGetLocaleInfoEx(dummyW, LOCALE_SNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3382 todo_wine
3383 ok(!ret, "got %d\n", ret);
3385 while (*ptr->name)
3387 val = 0;
3388 pGetLocaleInfoEx(ptr->name, LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER, (WCHAR*)&val, sizeof(val)/sizeof(WCHAR));
3389 if (ptr->todo)
3390 todo_wine
3391 ok(val == ptr->lcid, "%s: got wrong lcid 0x%04x, expected 0x%04x\n", wine_dbgstr_w(ptr->name), val, ptr->lcid);
3392 else
3393 ok(val == ptr->lcid, "%s: got wrong lcid 0x%04x, expected 0x%04x\n", wine_dbgstr_w(ptr->name), val, ptr->lcid);
3394 ptr++;
3399 START_TEST(locale)
3401 InitFunctionPointers();
3404 test_EnumTimeFormatsA();
3405 test_EnumDateFormatsA();
3406 test_GetLocaleInfoA();
3407 test_GetLocaleInfoW();
3408 test_GetLocaleInfoEx();
3409 test_GetTimeFormatA();
3410 test_GetDateFormatA();
3411 test_GetDateFormatW();
3412 test_GetCurrencyFormatA(); /* Also tests the W version */
3413 test_GetNumberFormatA(); /* Also tests the W version */
3414 test_CompareStringA();
3415 test_LCMapStringA();
3416 test_LCMapStringW();
3417 test_LCMapStringEx();
3418 test_LocaleNameToLCID();
3419 test_FoldStringA();
3420 test_FoldStringW();
3421 test_ConvertDefaultLocale();
3422 test_EnumSystemLanguageGroupsA();
3423 test_EnumSystemLocalesEx();
3424 test_EnumLanguageGroupLocalesA();
3425 test_SetLocaleInfoA();
3426 test_EnumUILanguageA();
3427 test_GetCPInfo();
3428 test_GetStringTypeW();
3429 test_IdnToNameprepUnicode();
3430 test_IdnToAscii();
3431 test_IdnToUnicode();
3432 /* this requires collation table patch to make it MS compatible */
3433 if (0) test_sorting();