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
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.
33 #include "wine/test.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 )
51 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
54 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
58 static inline WCHAR *strchrW( const WCHAR *str, WCHAR ch )
60 do { if (*str == ch) return (WCHAR *)str; } while (*str++);
64 static inline int isdigitW( WCHAR wc )
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);
89 static BOOL (WINAPI *pIsValidLocaleName)(LPCWSTR);
90 static INT (WINAPI *pCompareStringOrdinal)(const WCHAR *, INT, const WCHAR *, INT, BOOL);
92 static void InitFunctionPointers(void)
94 hKernel32 = GetModuleHandleA("kernel32");
95 pEnumSystemLanguageGroupsA = (void*)GetProcAddress(hKernel32, "EnumSystemLanguageGroupsA");
96 pEnumLanguageGroupLocalesA = (void*)GetProcAddress(hKernel32, "EnumLanguageGroupLocalesA");
97 pLocaleNameToLCID = (void*)GetProcAddress(hKernel32, "LocaleNameToLCID");
98 pLCIDToLocaleName = (void*)GetProcAddress(hKernel32, "LCIDToLocaleName");
99 pLCMapStringEx = (void*)GetProcAddress(hKernel32, "LCMapStringEx");
100 pFoldStringA = (void*)GetProcAddress(hKernel32, "FoldStringA");
101 pFoldStringW = (void*)GetProcAddress(hKernel32, "FoldStringW");
102 pIsValidLanguageGroup = (void*)GetProcAddress(hKernel32, "IsValidLanguageGroup");
103 pEnumUILanguagesA = (void*)GetProcAddress(hKernel32, "EnumUILanguagesA");
104 pEnumSystemLocalesEx = (void*)GetProcAddress(hKernel32, "EnumSystemLocalesEx");
105 pIdnToNameprepUnicode = (void*)GetProcAddress(hKernel32, "IdnToNameprepUnicode");
106 pIdnToAscii = (void*)GetProcAddress(hKernel32, "IdnToAscii");
107 pIdnToUnicode = (void*)GetProcAddress(hKernel32, "IdnToUnicode");
108 pGetLocaleInfoEx = (void*)GetProcAddress(hKernel32, "GetLocaleInfoEx");
109 pIsValidLocaleName = (void*)GetProcAddress(hKernel32, "IsValidLocaleName");
110 pCompareStringOrdinal = (void*)GetProcAddress(hKernel32, "CompareStringOrdinal");
113 #define eq(received, expected, label, type) \
114 ok((received) == (expected), "%s: got " type " instead of " type "\n", \
115 (label), (received), (expected))
117 #define BUFFER_SIZE 128
118 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
120 #define STRINGSA(x,y) strcpy(input, x); strcpy(Expected, y); SetLastError(0xdeadbeef); buffer[0] = '\0'
121 #define EXPECT_LENA ok(ret == lstrlen(Expected)+1, "Expected Len %d, got %d\n", lstrlen(Expected)+1, ret)
122 #define EXPECT_EQA ok(strncmp(buffer, Expected, strlen(Expected)) == 0, \
123 "Expected '%s', got '%s'\n", Expected, buffer)
125 #define STRINGSW(x,y) MultiByteToWideChar(CP_ACP,0,x,-1,input,COUNTOF(input)); \
126 MultiByteToWideChar(CP_ACP,0,y,-1,Expected,COUNTOF(Expected)); \
127 SetLastError(0xdeadbeef); buffer[0] = '\0'
128 #define EXPECT_LENW ok(ret == lstrlenW(Expected)+1, "Expected Len %d, got %d\n", lstrlenW(Expected)+1, ret)
129 #define EXPECT_EQW ok(strncmpW(buffer, Expected, strlenW(Expected)) == 0, "Bad conversion\n")
131 #define NUO LOCALE_NOUSEROVERRIDE
133 static void test_GetLocaleInfoA(void)
137 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
138 char buffer[BUFFER_SIZE];
139 char expected[BUFFER_SIZE];
142 ok(lcid == 0x409, "wrong LCID calculated - %d\n", lcid);
144 ret = GetLocaleInfoA(lcid, LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER, (char*)&val, sizeof(val));
145 ok(ret, "got %d\n", ret);
146 ok(val == lcid, "got 0x%08x\n", val);
148 /* en and ar use SUBLANG_NEUTRAL, but GetLocaleInfo assume SUBLANG_DEFAULT
149 Same is true for zh on pre-Vista, but on Vista and higher GetLocaleInfo
150 assumes SUBLANG_NEUTRAL for zh */
151 memset(expected, 0, COUNTOF(expected));
152 len = GetLocaleInfoA(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
153 SetLastError(0xdeadbeef);
154 memset(buffer, 0, COUNTOF(buffer));
155 ret = GetLocaleInfoA(LANG_ENGLISH, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
156 ok((ret == len) && !lstrcmpA(buffer, expected),
157 "got %d with '%s' (expected %d with '%s')\n",
158 ret, buffer, len, expected);
160 memset(expected, 0, COUNTOF(expected));
161 len = GetLocaleInfoA(MAKELANGID(LANG_ARABIC, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
163 SetLastError(0xdeadbeef);
164 memset(buffer, 0, COUNTOF(buffer));
165 ret = GetLocaleInfoA(LANG_ARABIC, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
166 ok((ret == len) && !lstrcmpA(buffer, expected),
167 "got %d with '%s' (expected %d with '%s')\n",
168 ret, buffer, len, expected);
171 win_skip("LANG_ARABIC not installed\n");
173 /* SUBLANG_DEFAULT is required for mlang.dll, but optional for GetLocaleInfo */
174 memset(expected, 0, COUNTOF(expected));
175 len = GetLocaleInfoA(MAKELANGID(LANG_GERMAN, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
176 SetLastError(0xdeadbeef);
177 memset(buffer, 0, COUNTOF(buffer));
178 ret = GetLocaleInfoA(LANG_GERMAN, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
179 ok((ret == len) && !lstrcmpA(buffer, expected),
180 "got %d with '%s' (expected %d with '%s')\n",
181 ret, buffer, len, expected);
184 /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
185 * partially fill the buffer even if it is too short. See bug 637.
187 SetLastError(0xdeadbeef);
188 memset(buffer, 0, COUNTOF(buffer));
189 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 0);
190 ok(ret == 7 && !buffer[0], "Expected len=7, got %d\n", ret);
192 SetLastError(0xdeadbeef);
193 memset(buffer, 0, COUNTOF(buffer));
194 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 3);
195 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
196 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
197 ok(!strcmp(buffer, "Mon"), "Expected 'Mon', got '%s'\n", buffer);
199 SetLastError(0xdeadbeef);
200 memset(buffer, 0, COUNTOF(buffer));
201 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 10);
202 ok(ret == 7, "Expected ret == 7, got %d, error %d\n", ret, GetLastError());
203 ok(!strcmp(buffer, "Monday"), "Expected 'Monday', got '%s'\n", buffer);
206 struct neutralsublang_name2_t {
211 WCHAR sname_broken[15];
215 static const struct neutralsublang_name2_t neutralsublang_names2[] = {
216 { {'a','r',0}, {'a','r','-','S','A',0},
217 MAKELCID(MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA), SORT_DEFAULT) },
218 { {'a','z',0}, {'a','z','-','L','a','t','n','-','A','Z',0},
219 MAKELCID(MAKELANGID(LANG_AZERI, SUBLANG_AZERI_LATIN), SORT_DEFAULT) },
220 { {'d','e',0}, {'d','e','-','D','E',0},
221 MAKELCID(MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN), SORT_DEFAULT) },
222 { {'e','n',0}, {'e','n','-','U','S',0},
223 MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT) },
224 { {'e','s',0}, {'e','s','-','E','S',0},
225 MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN), SORT_DEFAULT),
226 MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH), SORT_DEFAULT) /* vista */,
227 {'e','s','-','E','S','_','t','r','a','d','n','l',0}, 0x1 },
228 { {'g','a',0}, {'g','a','-','I','E',0},
229 MAKELCID(MAKELANGID(LANG_IRISH, SUBLANG_IRISH_IRELAND), SORT_DEFAULT), 0, {0}, 0x3 },
230 { {'i','t',0}, {'i','t','-','I','T',0},
231 MAKELCID(MAKELANGID(LANG_ITALIAN, SUBLANG_ITALIAN), SORT_DEFAULT) },
232 { {'m','s',0}, {'m','s','-','M','Y',0},
233 MAKELCID(MAKELANGID(LANG_MALAY, SUBLANG_MALAY_MALAYSIA), SORT_DEFAULT) },
234 { {'n','l',0}, {'n','l','-','N','L',0},
235 MAKELCID(MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH), SORT_DEFAULT) },
236 { {'p','t',0}, {'p','t','-','B','R',0},
237 MAKELCID(MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN), SORT_DEFAULT) },
238 { {'s','r',0}, {'h','r','-','H','R',0},
239 MAKELCID(MAKELANGID(LANG_SERBIAN, SUBLANG_SERBIAN_CROATIA), SORT_DEFAULT) },
240 { {'s','v',0}, {'s','v','-','S','E',0},
241 MAKELCID(MAKELANGID(LANG_SWEDISH, SUBLANG_SWEDISH), SORT_DEFAULT) },
242 { {'u','z',0}, {'u','z','-','L','a','t','n','-','U','Z',0},
243 MAKELCID(MAKELANGID(LANG_UZBEK, SUBLANG_UZBEK_LATIN), SORT_DEFAULT) },
244 { {'z','h',0}, {'z','h','-','C','N',0},
245 MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT), 0, {0}, 0x3 },
249 static void test_GetLocaleInfoW(void)
251 LCID lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
252 LCID lcid_ru = MAKELCID(MAKELANGID(LANG_RUSSIAN, SUBLANG_NEUTRAL), SORT_DEFAULT);
253 LCID lcid_en_neut = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL), SORT_DEFAULT);
254 WCHAR bufferW[80], buffer2W[80];
260 ret = GetLocaleInfoW(lcid_en, LOCALE_SMONTHNAME1, bufferW, COUNTOF(bufferW));
262 win_skip("GetLocaleInfoW() isn't implemented\n");
266 ret = GetLocaleInfoW(lcid_en, LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER, (WCHAR*)&val, sizeof(val)/sizeof(WCHAR));
267 ok(ret, "got %d\n", ret);
268 ok(val == lcid_en, "got 0x%08x\n", val);
270 ret = GetLocaleInfoW(lcid_en_neut, LOCALE_SNAME, bufferW, COUNTOF(bufferW));
273 static const WCHAR slangW[] = {'E','n','g','l','i','s','h',' ','(','U','n','i','t','e','d',' ',
274 'S','t','a','t','e','s',')',0};
275 static const WCHAR statesW[] = {'U','n','i','t','e','d',' ','S','t','a','t','e','s',0};
276 static const WCHAR enW[] = {'e','n','-','U','S',0};
277 const struct neutralsublang_name2_t *ptr = neutralsublang_names2;
279 ok(!lstrcmpW(bufferW, enW), "got wrong name %s\n", wine_dbgstr_w(bufferW));
281 ret = GetLocaleInfoW(lcid_en_neut, LOCALE_SCOUNTRY, bufferW, COUNTOF(bufferW));
282 ok(ret, "got %d\n", ret);
283 ok(!lstrcmpW(statesW, bufferW), "got wrong name %s\n", wine_dbgstr_w(bufferW));
285 ret = GetLocaleInfoW(lcid_en_neut, LOCALE_SLANGUAGE, bufferW, COUNTOF(bufferW));
286 ok(ret, "got %d\n", ret);
287 ok(!lstrcmpW(slangW, bufferW), "got wrong name %s\n", wine_dbgstr_w(bufferW));
294 /* make neutral lcid */
295 langid = MAKELANGID(PRIMARYLANGID(LANGIDFROMLCID(ptr->lcid)), SUBLANG_NEUTRAL);
296 lcid = MAKELCID(langid, SORT_DEFAULT);
299 GetLocaleInfoW(lcid, LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER, (WCHAR*)&val, sizeof(val)/sizeof(WCHAR));
303 ok(val == ptr->lcid || (val && broken(val == ptr->lcid_broken)), "%s: got wrong lcid 0x%04x, expected 0x%04x\n",
304 wine_dbgstr_w(ptr->name), val, ptr->lcid);
307 ok(val == ptr->lcid || (val && broken(val == ptr->lcid_broken)), "%s: got wrong lcid 0x%04x, expected 0x%04x\n",
308 wine_dbgstr_w(ptr->name), val, ptr->lcid);
310 /* now check LOCALE_SNAME */
311 GetLocaleInfoW(lcid, LOCALE_SNAME, bufferW, COUNTOF(bufferW));
314 ok(!lstrcmpW(bufferW, ptr->sname) ||
315 (*ptr->sname_broken && broken(!lstrcmpW(bufferW, ptr->sname_broken))),
316 "%s: got %s\n", wine_dbgstr_w(ptr->name), wine_dbgstr_w(bufferW));
318 ok(!lstrcmpW(bufferW, ptr->sname) ||
319 (*ptr->sname_broken && broken(!lstrcmpW(bufferW, ptr->sname_broken))),
320 "%s: got %s\n", wine_dbgstr_w(ptr->name), wine_dbgstr_w(bufferW));
325 win_skip("English neutral locale not supported\n");
327 ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1, bufferW, COUNTOF(bufferW));
329 win_skip("LANG_RUSSIAN locale data unavailable\n");
332 ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1|LOCALE_RETURN_GENITIVE_NAMES,
333 bufferW, COUNTOF(bufferW));
335 win_skip("LOCALE_RETURN_GENITIVE_NAMES isn't supported\n");
339 /* LOCALE_RETURN_GENITIVE_NAMES isn't supported for GetLocaleInfoA */
341 SetLastError(0xdeadbeef);
342 ret = GetLocaleInfoA(lcid_ru, LOCALE_SMONTHNAME1|LOCALE_RETURN_GENITIVE_NAMES,
343 bufferA, COUNTOF(bufferA));
344 ok(ret == 0, "LOCALE_RETURN_GENITIVE_NAMES should fail with GetLocaleInfoA\n");
345 ok(bufferA[0] == 'a', "Expected buffer to be untouched\n");
346 ok(GetLastError() == ERROR_INVALID_FLAGS,
347 "Expected ERROR_INVALID_FLAGS, got %x\n", GetLastError());
350 SetLastError(0xdeadbeef);
351 ret = GetLocaleInfoW(lcid_ru, LOCALE_RETURN_GENITIVE_NAMES,
352 bufferW, COUNTOF(bufferW));
354 "LOCALE_RETURN_GENITIVE_NAMES itself doesn't return anything, got %d\n", ret);
355 ok(bufferW[0] == 'a', "Expected buffer to be untouched\n");
356 ok(GetLastError() == ERROR_INVALID_FLAGS,
357 "Expected ERROR_INVALID_FLAGS, got %x\n", GetLastError());
359 /* yes, test empty 13 month entry too */
360 for (i = 0; i < 12; i++) {
362 ret = GetLocaleInfoW(lcid_ru, (LOCALE_SMONTHNAME1+i)|LOCALE_RETURN_GENITIVE_NAMES,
363 bufferW, COUNTOF(bufferW));
364 ok(ret, "Expected non zero result\n");
365 ok(ret == lstrlenW(bufferW)+1, "Expected actual length, got %d, length %d\n",
366 ret, lstrlenW(bufferW));
368 ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1+i,
369 buffer2W, COUNTOF(buffer2W));
370 ok(ret, "Expected non zero result\n");
371 ok(ret == lstrlenW(buffer2W)+1, "Expected actual length, got %d, length %d\n",
372 ret, lstrlenW(buffer2W));
374 ok(lstrcmpW(bufferW, buffer2W) != 0,
375 "Expected genitive name to differ, got the same for month %d\n", i+1);
377 /* for locale without genitive names nominative returned in both cases */
379 ret = GetLocaleInfoW(lcid_en, (LOCALE_SMONTHNAME1+i)|LOCALE_RETURN_GENITIVE_NAMES,
380 bufferW, COUNTOF(bufferW));
381 ok(ret, "Expected non zero result\n");
382 ok(ret == lstrlenW(bufferW)+1, "Expected actual length, got %d, length %d\n",
383 ret, lstrlenW(bufferW));
385 ret = GetLocaleInfoW(lcid_en, LOCALE_SMONTHNAME1+i,
386 buffer2W, COUNTOF(buffer2W));
387 ok(ret, "Expected non zero result\n");
388 ok(ret == lstrlenW(buffer2W)+1, "Expected actual length, got %d, length %d\n",
389 ret, lstrlenW(buffer2W));
391 ok(lstrcmpW(bufferW, buffer2W) == 0,
392 "Expected same names, got different for month %d\n", i+1);
396 static void test_GetTimeFormatA(void)
400 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
401 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
403 memset(&curtime, 2, sizeof(SYSTEMTIME));
404 STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
405 SetLastError(0xdeadbeef);
406 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
407 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
408 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
411 curtime.wMinute = 56;
412 curtime.wSecond = 13;
413 curtime.wMilliseconds = 22;
414 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
415 SetLastError(0xdeadbeef);
416 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
417 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
418 EXPECT_LENA; EXPECT_EQA;
420 /* MSDN: LOCALE_NOUSEROVERRIDE can't be specified with a format string */
421 SetLastError(0xdeadbeef);
422 ret = GetTimeFormatA(lcid, NUO|TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
423 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
424 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
426 STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficient buffer */
427 SetLastError(0xdeadbeef);
428 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, 2);
429 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
430 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
432 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
433 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, NULL, 0);
434 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
437 STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
438 ret = GetTimeFormatA(lcid, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
439 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
440 EXPECT_LENA; EXPECT_EQA;
442 STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
443 ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
444 ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
445 ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "4" )), /* win9x */
446 "Expected '', got '%s'\n", buffer );
448 STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
449 ret = GetTimeFormatA(lcid, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
450 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
451 EXPECT_LENA; EXPECT_EQA;
453 STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
454 strcpy(Expected, "8:56 AM");
455 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
456 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
457 EXPECT_LENA; EXPECT_EQA;
459 STRINGSA("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
460 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
461 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
462 ok( !strcmp( buffer, "8.@:56AM" ) || broken( !strcmp( buffer, "8.@:56.@:AM" )) /* win9x */,
463 "Expected '8.@:56AM', got '%s'\n", buffer );
465 STRINGSA("s1s2s3", ""); /* Duplicate tokens */
466 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
467 ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
468 ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "3" )), /* win9x */
469 "Expected '', got '%s'\n", buffer );
471 STRINGSA("t/tt", "A/AM"); /* AM time marker */
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;
477 STRINGSA("t/tt", "P/PM"); /* PM time marker */
478 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
479 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
480 EXPECT_LENA; EXPECT_EQA;
482 STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
483 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
484 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
485 EXPECT_LENA; EXPECT_EQA;
487 STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
488 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
489 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
490 EXPECT_LENA; EXPECT_EQA;
492 STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
493 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
494 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
495 EXPECT_LENA; EXPECT_EQA;
497 curtime.wHour = 14; /* change this to 14 or 2pm */
500 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 */
501 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
502 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
503 EXPECT_LENA; EXPECT_EQA;
506 STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
507 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
508 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
509 EXPECT_LENA; EXPECT_EQA;
511 STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
512 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
513 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
514 EXPECT_LENA; EXPECT_EQA;
516 /* try to convert formatting strings with more than two letters
517 * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
518 * NOTE: We expect any letter for which there is an upper case value
519 * we should see a replacement. For letters that DO NOT have
520 * upper case values we should see NO REPLACEMENT.
523 curtime.wMinute = 56;
524 curtime.wSecond = 13;
525 curtime.wMilliseconds = 22;
526 STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
527 "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
528 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
529 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
530 EXPECT_LENA; EXPECT_EQA;
532 STRINGSA("h", "text"); /* Don't write to buffer if len is 0 */
533 strcpy(buffer, "text");
534 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, 0);
535 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
538 STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
539 "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
540 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
541 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
542 EXPECT_LENA; EXPECT_EQA;
544 STRINGSA("'''", "'"); /* invalid quoted string */
545 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
546 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
547 EXPECT_LENA; EXPECT_EQA;
549 /* test that msdn suggested single quotation usage works as expected */
550 STRINGSA("''''", "'"); /* single quote mark */
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;
555 STRINGSA("''HHHHHH", "08"); /* Normal use */
556 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
557 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
558 EXPECT_LENA; EXPECT_EQA;
560 /* and test for normal use of the single quotation mark */
561 STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
562 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
563 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
564 EXPECT_LENA; EXPECT_EQA;
566 STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
567 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
568 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
569 EXPECT_LENA; EXPECT_EQA;
571 STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
572 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
573 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
574 EXPECT_LENA; EXPECT_EQA;
577 STRINGSA("'123'tt", ""); /* Invalid time */
578 SetLastError(0xdeadbeef);
579 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
580 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
581 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
584 curtime.wMonth = 60; /* Invalid */
585 STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
586 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
587 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
588 EXPECT_LENA; EXPECT_EQA;
591 static void test_GetDateFormatA(void)
595 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
596 LCID lcid_ru = MAKELCID(MAKELANGID(LANG_RUSSIAN, SUBLANG_NEUTRAL), SORT_DEFAULT);
597 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
598 char Broken[BUFFER_SIZE];
599 char short_day[10], month[10], genitive_month[10];
601 memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
602 STRINGSA("ddd',' MMM dd yy","");
603 SetLastError(0xdeadbeef);
604 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
605 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
606 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
608 curtime.wYear = 2002;
611 curtime.wDayOfWeek = 3;
612 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
613 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
614 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
615 EXPECT_LENA; EXPECT_EQA;
617 /* Same as above but with LOCALE_NOUSEROVERRIDE */
618 STRINGSA("ddd',' MMM dd yy",""); /* Simple case */
619 SetLastError(0xdeadbeef);
620 ret = GetDateFormatA(lcid, NUO, &curtime, input, buffer, COUNTOF(buffer));
621 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
622 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
625 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
626 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
627 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
628 EXPECT_LENA; EXPECT_EQA;
630 curtime.wHour = 36; /* Invalid */
631 STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
632 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
633 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
634 EXPECT_LENA; EXPECT_EQA;
636 STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
637 ret = GetDateFormatA(lcid, 0, &curtime, input, NULL, 0);
638 ok(ret == 16, "Expected ret == 16, got %d, error %d\n", ret, GetLastError());
641 STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
642 SetLastError(0xdeadbeef);
643 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, 2);
644 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
645 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
647 STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
648 ret = GetDateFormat(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
649 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
650 if (strncmp(buffer, Expected, strlen(Expected)) && strncmp(buffer, "5/4/02", strlen(Expected)) != 0)
651 ok (0, "Expected '%s' or '5/4/02', got '%s'\n", Expected, buffer);
653 STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
654 ret = GetDateFormat(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
655 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
656 EXPECT_LENA; EXPECT_EQA;
658 /* test for expected DATE_YEARMONTH behavior with null format */
659 /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
660 STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
661 SetLastError(0xdeadbeef);
662 ret = GetDateFormat(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
663 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
664 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
667 /* Test that using invalid DATE_* flags results in the correct error */
668 /* and return values */
669 STRINGSA("m/d/y", ""); /* Invalid flags */
670 SetLastError(0xdeadbeef);
671 ret = GetDateFormat(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
672 &curtime, input, buffer, COUNTOF(buffer));
673 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
674 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
676 ret = GetDateFormat(lcid_ru, 0, &curtime, "ddMMMM", buffer, COUNTOF(buffer));
679 win_skip("LANG_RUSSIAN locale data unavailable\n");
683 /* month part should be in genitive form */
684 strcpy(genitive_month, buffer + 2);
685 ret = GetDateFormat(lcid_ru, 0, &curtime, "MMMM", buffer, COUNTOF(buffer));
686 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
687 strcpy(month, buffer);
688 ok(strcmp(genitive_month, month) != 0, "Expected different month forms\n");
690 ret = GetDateFormat(lcid_ru, 0, &curtime, "ddd", buffer, COUNTOF(buffer));
691 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
692 strcpy(short_day, buffer);
694 STRINGSA("dd MMMMddd dd", "");
695 sprintf(Expected, "04 %s%s 04", genitive_month, short_day);
696 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
697 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
700 STRINGSA("MMMMddd dd", "");
701 sprintf(Expected, "%s%s 04", month, short_day);
702 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
703 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
706 STRINGSA("MMMMddd", "");
707 sprintf(Expected, "%s%s", month, short_day);
708 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
709 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
712 STRINGSA("MMMMdd", "");
713 sprintf(Expected, "%s04", genitive_month);
714 sprintf(Broken, "%s04", month);
715 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
716 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
717 ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
718 broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
719 "Expected '%s', got '%s'\n", Expected, buffer);
721 STRINGSA("MMMMdd ddd", "");
722 sprintf(Expected, "%s04 %s", genitive_month, short_day);
723 sprintf(Broken, "%s04 %s", month, short_day);
724 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
725 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
726 ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
727 broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
728 "Expected '%s', got '%s'\n", Expected, buffer);
730 STRINGSA("dd dddMMMM", "");
731 sprintf(Expected, "04 %s%s", short_day, month);
732 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
733 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
736 STRINGSA("dd dddMMMM ddd MMMMdd", "");
737 sprintf(Expected, "04 %s%s %s %s04", short_day, month, short_day, genitive_month);
738 sprintf(Broken, "04 %s%s %s %s04", short_day, month, short_day, month);
739 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
740 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
741 ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
742 broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
743 "Expected '%s', got '%s'\n", Expected, buffer);
745 /* with literal part */
746 STRINGSA("ddd',' MMMM dd", "");
747 sprintf(Expected, "%s, %s 04", short_day, genitive_month);
748 sprintf(Broken, "%s, %s 04", short_day, month);
749 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
750 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
751 ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
752 broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
753 "Expected '%s', got '%s'\n", Expected, buffer);
756 static void test_GetDateFormatW(void)
760 WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
761 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
763 STRINGSW("",""); /* If flags is not zero then format must be NULL */
764 ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL,
765 input, buffer, COUNTOF(buffer));
766 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
768 win_skip("GetDateFormatW is not implemented\n");
771 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
772 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
775 STRINGSW("",""); /* NULL buffer, len > 0 */
776 SetLastError(0xdeadbeef);
777 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
778 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
779 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
781 STRINGSW("",""); /* NULL buffer, len == 0 */
782 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
783 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
784 EXPECT_LENW; EXPECT_EQW;
786 curtime.wYear = 2002;
789 curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
790 curtime.wHour = 65432; /* Invalid */
791 curtime.wMinute = 34512; /* Invalid */
792 curtime.wSecond = 65535; /* Invalid */
793 curtime.wMilliseconds = 12345;
794 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
795 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
796 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
797 EXPECT_LENW; EXPECT_EQW;
801 curtime.wYear = 1601;
804 curtime.wDayOfWeek = 0; /* Irrelevant */
808 curtime.wMilliseconds = 0;
809 STRINGSW("dddd d MMMM yyyy","Monday 1 January 1601");
810 SetLastError(0xdeadbeef);
811 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
812 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
813 EXPECT_LENW; EXPECT_EQW;
815 curtime.wYear = 1600;
818 curtime.wDayOfWeek = 0; /* Irrelevant */
820 curtime.wMinute = 59;
821 curtime.wSecond = 59;
822 curtime.wMilliseconds = 999;
823 STRINGSW("dddd d MMMM yyyy","Friday 31 December 1600");
824 SetLastError(0xdeadbeef);
825 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
826 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
827 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
831 #define CY_POS_LEFT 0
832 #define CY_POS_RIGHT 1
833 #define CY_POS_LEFT_SPACE 2
834 #define CY_POS_RIGHT_SPACE 3
836 static void test_GetCurrencyFormatA(void)
838 static char szDot[] = { '.', '\0' };
839 static char szComma[] = { ',', '\0' };
840 static char szDollar[] = { '$', '\0' };
842 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
843 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
846 memset(&format, 0, sizeof(format));
848 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
849 SetLastError(0xdeadbeef);
850 ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
851 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
852 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
854 STRINGSA("23,53",""); /* Invalid character --> Error */
855 SetLastError(0xdeadbeef);
856 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
857 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
858 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
860 STRINGSA("--",""); /* Double '-' --> Error */
861 SetLastError(0xdeadbeef);
862 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
863 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
864 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
866 STRINGSA("0-",""); /* Trailing '-' --> Error */
867 SetLastError(0xdeadbeef);
868 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
869 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
870 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
872 STRINGSA("0..",""); /* Double '.' --> Error */
873 SetLastError(0xdeadbeef);
874 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
875 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
876 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
878 STRINGSA(" 0.1",""); /* Leading space --> Error */
879 SetLastError(0xdeadbeef);
880 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
881 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
882 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
884 STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
885 SetLastError(0xdeadbeef);
886 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, 2);
887 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
888 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
890 STRINGSA("2353",""); /* Format and flags given --> Error */
891 SetLastError(0xdeadbeef);
892 ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
893 ok( !ret, "Expected ret == 0, got %d\n", ret);
894 ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
895 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
897 STRINGSA("2353",""); /* Invalid format --> Error */
898 SetLastError(0xdeadbeef);
899 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
900 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
901 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
903 STRINGSA("2353","$2,353.00"); /* Valid number */
904 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
905 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
906 EXPECT_LENA; EXPECT_EQA;
908 STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
909 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
910 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
911 EXPECT_LENA; EXPECT_EQA;
913 STRINGSA("2353.1","$2,353.10"); /* Valid real number */
914 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
915 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
916 EXPECT_LENA; EXPECT_EQA;
918 STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
919 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
920 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
921 EXPECT_LENA; EXPECT_EQA;
923 STRINGSA("2353.119","$2,353.12"); /* Too many DP --> Rounded */
924 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
925 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
926 EXPECT_LENA; EXPECT_EQA;
928 format.NumDigits = 0; /* No decimal separator */
929 format.LeadingZero = 0;
930 format.Grouping = 0; /* No grouping char */
931 format.NegativeOrder = 0;
932 format.PositiveOrder = CY_POS_LEFT;
933 format.lpDecimalSep = szDot;
934 format.lpThousandSep = szComma;
935 format.lpCurrencySymbol = szDollar;
937 STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
938 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
939 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
940 EXPECT_LENA; EXPECT_EQA;
942 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
943 STRINGSA("2353","$2353.0");
944 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
945 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
946 EXPECT_LENA; EXPECT_EQA;
948 format.Grouping = 2; /* Group by 100's */
949 STRINGSA("2353","$23,53.0");
950 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
951 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
952 EXPECT_LENA; EXPECT_EQA;
954 STRINGSA("235","$235.0"); /* Grouping of a positive number */
956 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
957 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
958 EXPECT_LENA; EXPECT_EQA;
960 STRINGSA("-235","$-235.0"); /* Grouping of a negative number */
961 format.NegativeOrder = 2;
962 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
963 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
964 EXPECT_LENA; EXPECT_EQA;
966 format.LeadingZero = 1; /* Always provide leading zero */
967 STRINGSA(".5","$0.5");
968 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
969 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
970 EXPECT_LENA; EXPECT_EQA;
972 format.PositiveOrder = CY_POS_RIGHT;
973 STRINGSA("1","1.0$");
974 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
975 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
976 EXPECT_LENA; EXPECT_EQA;
978 format.PositiveOrder = CY_POS_LEFT_SPACE;
979 STRINGSA("1","$ 1.0");
980 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
981 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
982 EXPECT_LENA; EXPECT_EQA;
984 format.PositiveOrder = CY_POS_RIGHT_SPACE;
985 STRINGSA("1","1.0 $");
986 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
987 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
988 EXPECT_LENA; EXPECT_EQA;
990 format.NegativeOrder = 0;
991 STRINGSA("-1","($1.0)");
992 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
993 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
994 EXPECT_LENA; EXPECT_EQA;
996 format.NegativeOrder = 1;
997 STRINGSA("-1","-$1.0");
998 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
999 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1000 EXPECT_LENA; EXPECT_EQA;
1002 format.NegativeOrder = 2;
1003 STRINGSA("-1","$-1.0");
1004 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1005 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1006 EXPECT_LENA; EXPECT_EQA;
1008 format.NegativeOrder = 3;
1009 STRINGSA("-1","$1.0-");
1010 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1011 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1012 EXPECT_LENA; EXPECT_EQA;
1014 format.NegativeOrder = 4;
1015 STRINGSA("-1","(1.0$)");
1016 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1017 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1018 EXPECT_LENA; EXPECT_EQA;
1020 format.NegativeOrder = 5;
1021 STRINGSA("-1","-1.0$");
1022 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1023 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1024 EXPECT_LENA; EXPECT_EQA;
1026 format.NegativeOrder = 6;
1027 STRINGSA("-1","1.0-$");
1028 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1029 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1030 EXPECT_LENA; EXPECT_EQA;
1032 format.NegativeOrder = 7;
1033 STRINGSA("-1","1.0$-");
1034 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1035 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1036 EXPECT_LENA; EXPECT_EQA;
1038 format.NegativeOrder = 8;
1039 STRINGSA("-1","-1.0 $");
1040 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1041 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1042 EXPECT_LENA; EXPECT_EQA;
1044 format.NegativeOrder = 9;
1045 STRINGSA("-1","-$ 1.0");
1046 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1047 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1048 EXPECT_LENA; EXPECT_EQA;
1050 format.NegativeOrder = 10;
1051 STRINGSA("-1","1.0 $-");
1052 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1053 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1054 EXPECT_LENA; EXPECT_EQA;
1056 format.NegativeOrder = 11;
1057 STRINGSA("-1","$ 1.0-");
1058 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1059 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1060 EXPECT_LENA; EXPECT_EQA;
1062 format.NegativeOrder = 12;
1063 STRINGSA("-1","$ -1.0");
1064 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1065 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1066 EXPECT_LENA; EXPECT_EQA;
1068 format.NegativeOrder = 13;
1069 STRINGSA("-1","1.0- $");
1070 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1071 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1072 EXPECT_LENA; EXPECT_EQA;
1074 format.NegativeOrder = 14;
1075 STRINGSA("-1","($ 1.0)");
1076 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1077 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1078 EXPECT_LENA; EXPECT_EQA;
1080 format.NegativeOrder = 15;
1081 STRINGSA("-1","(1.0 $)");
1082 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1083 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1084 EXPECT_LENA; EXPECT_EQA;
1087 #define NEG_PARENS 0 /* "(1.1)" */
1088 #define NEG_LEFT 1 /* "-1.1" */
1089 #define NEG_LEFT_SPACE 2 /* "- 1.1" */
1090 #define NEG_RIGHT 3 /* "1.1-" */
1091 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
1093 static void test_GetNumberFormatA(void)
1095 static char szDot[] = { '.', '\0' };
1096 static char szComma[] = { ',', '\0' };
1098 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
1099 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
1102 memset(&format, 0, sizeof(format));
1104 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
1105 SetLastError(0xdeadbeef);
1106 ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
1107 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1108 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1110 STRINGSA("23,53",""); /* Invalid character --> Error */
1111 SetLastError(0xdeadbeef);
1112 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1113 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1114 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1116 STRINGSA("--",""); /* Double '-' --> Error */
1117 SetLastError(0xdeadbeef);
1118 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1119 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1120 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1122 STRINGSA("0-",""); /* Trailing '-' --> Error */
1123 SetLastError(0xdeadbeef);
1124 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1125 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1126 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1128 STRINGSA("0..",""); /* Double '.' --> Error */
1129 SetLastError(0xdeadbeef);
1130 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1131 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1132 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1134 STRINGSA(" 0.1",""); /* Leading space --> Error */
1135 SetLastError(0xdeadbeef);
1136 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1137 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1138 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1140 STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
1141 SetLastError(0xdeadbeef);
1142 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, 2);
1143 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1144 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1146 STRINGSA("2353",""); /* Format and flags given --> Error */
1147 SetLastError(0xdeadbeef);
1148 ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
1149 ok( !ret, "Expected ret == 0, got %d\n", ret);
1150 ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
1151 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1153 STRINGSA("2353",""); /* Invalid format --> Error */
1154 SetLastError(0xdeadbeef);
1155 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1156 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1157 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1159 STRINGSA("2353","2,353.00"); /* Valid number */
1160 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1161 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1162 EXPECT_LENA; EXPECT_EQA;
1164 STRINGSA("-2353","-2,353.00"); /* Valid negative number */
1165 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1166 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1167 EXPECT_LENA; EXPECT_EQA;
1169 STRINGSA("-353","-353.00"); /* test for off by one error in grouping */
1170 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1171 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1172 EXPECT_LENA; EXPECT_EQA;
1174 STRINGSA("2353.1","2,353.10"); /* Valid real number */
1175 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1176 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1177 EXPECT_LENA; EXPECT_EQA;
1179 STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
1180 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1181 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1182 EXPECT_LENA; EXPECT_EQA;
1184 STRINGSA("2353.119","2,353.12"); /* Too many DP --> Rounded */
1185 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1186 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1187 EXPECT_LENA; EXPECT_EQA;
1189 format.NumDigits = 0; /* No decimal separator */
1190 format.LeadingZero = 0;
1191 format.Grouping = 0; /* No grouping char */
1192 format.NegativeOrder = 0;
1193 format.lpDecimalSep = szDot;
1194 format.lpThousandSep = szComma;
1196 STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
1197 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1198 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1199 EXPECT_LENA; EXPECT_EQA;
1201 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
1202 STRINGSA("2353","2353.0");
1203 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1204 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1205 EXPECT_LENA; EXPECT_EQA;
1207 format.Grouping = 2; /* Group by 100's */
1208 STRINGSA("2353","23,53.0");
1209 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1210 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1211 EXPECT_LENA; EXPECT_EQA;
1213 STRINGSA("235","235.0"); /* Grouping of a positive number */
1214 format.Grouping = 3;
1215 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1216 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1217 EXPECT_LENA; EXPECT_EQA;
1219 STRINGSA("-235","-235.0"); /* Grouping of a negative number */
1220 format.NegativeOrder = NEG_LEFT;
1221 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1222 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1223 EXPECT_LENA; EXPECT_EQA;
1225 format.LeadingZero = 1; /* Always provide leading zero */
1226 STRINGSA(".5","0.5");
1227 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1228 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1229 EXPECT_LENA; EXPECT_EQA;
1231 format.NegativeOrder = NEG_PARENS;
1232 STRINGSA("-1","(1.0)");
1233 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1234 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1235 EXPECT_LENA; EXPECT_EQA;
1237 format.NegativeOrder = NEG_LEFT;
1238 STRINGSA("-1","-1.0");
1239 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1240 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1241 EXPECT_LENA; EXPECT_EQA;
1243 format.NegativeOrder = NEG_LEFT_SPACE;
1244 STRINGSA("-1","- 1.0");
1245 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1246 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1247 EXPECT_LENA; EXPECT_EQA;
1249 format.NegativeOrder = NEG_RIGHT;
1250 STRINGSA("-1","1.0-");
1251 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1252 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1253 EXPECT_LENA; EXPECT_EQA;
1255 format.NegativeOrder = NEG_RIGHT_SPACE;
1256 STRINGSA("-1","1.0 -");
1257 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1258 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1259 EXPECT_LENA; EXPECT_EQA;
1261 lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
1263 if (IsValidLocale(lcid, 0))
1265 STRINGSA("-12345","-12 345,00"); /* Try French formatting */
1266 Expected[3] = 160; /* Non breaking space */
1267 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1268 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1269 EXPECT_LENA; EXPECT_EQA;
1273 struct comparestringa_entry {
1283 static const struct comparestringa_entry comparestringa_data[] = {
1284 { LOCALE_SYSTEM_DEFAULT, 0, "EndDialog", -1, "_Property", -1, CSTR_GREATER_THAN },
1285 { LOCALE_SYSTEM_DEFAULT, 0, "osp_vba.sreg0070", -1, "_IEWWBrowserComp", -1, CSTR_GREATER_THAN },
1286 { LOCALE_SYSTEM_DEFAULT, 0, "r", -1, "\\", -1, CSTR_GREATER_THAN },
1287 { LOCALE_SYSTEM_DEFAULT, 0, "osp_vba.sreg0031", -1, "OriginalDatabase", -1, CSTR_GREATER_THAN },
1288 { LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1, CSTR_GREATER_THAN },
1289 { LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1, CSTR_LESS_THAN },
1290 { LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1, CSTR_LESS_THAN },
1291 { LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1, CSTR_LESS_THAN },
1292 { LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1, CSTR_LESS_THAN },
1293 { LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1, CSTR_LESS_THAN },
1294 { LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1, CSTR_LESS_THAN },
1295 { LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1, CSTR_GREATER_THAN },
1296 { LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1, CSTR_LESS_THAN },
1297 { LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1, CSTR_LESS_THAN },
1298 { LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1, CSTR_GREATER_THAN },
1299 { LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1, CSTR_GREATER_THAN },
1300 { LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1, CSTR_LESS_THAN },
1301 { LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1, CSTR_LESS_THAN },
1302 { LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1, CSTR_LESS_THAN },
1303 /* hyphen and apostrophe are treated differently depending on whether SORT_STRINGSORT specified or not */
1304 { LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1, CSTR_GREATER_THAN },
1305 { LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1, CSTR_LESS_THAN },
1306 { LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1, CSTR_LESS_THAN },
1307 { LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1, CSTR_GREATER_THAN },
1308 { LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1, CSTR_GREATER_THAN },
1309 { LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1, CSTR_LESS_THAN },
1310 { LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1, CSTR_LESS_THAN },
1311 { LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1, CSTR_GREATER_THAN },
1312 { LOCALE_SYSTEM_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9, CSTR_EQUAL },
1313 { LOCALE_SYSTEM_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10, CSTR_LESS_THAN }
1316 static void test_CompareStringA(void)
1319 LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
1321 for (i = 0; i < sizeof(comparestringa_data)/sizeof(struct comparestringa_entry); i++)
1323 const struct comparestringa_entry *entry = &comparestringa_data[i];
1325 ret = CompareStringA(entry->lcid, entry->flags, entry->first, entry->first_len,
1326 entry->second, entry->second_len);
1327 ok(ret == entry->ret, "%d: got %d, expected %d\n", i, ret, entry->ret);
1330 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
1331 ok (ret == CSTR_LESS_THAN, "(Salut/Salute) Expected CSTR_LESS_THAN, got %d\n", ret);
1333 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
1334 ok (ret == CSTR_EQUAL, "(Salut/SaLuT) Expected CSTR_EQUAL, got %d\n", ret);
1336 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
1337 ok (ret == CSTR_GREATER_THAN, "(Salut/hola) Expected CSTR_GREATER_THAN, got %d\n", ret);
1339 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
1340 ok (ret == CSTR_LESS_THAN, "(haha/hoho) Expected CSTR_LESS_THAN, got %d\n", ret);
1342 lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
1344 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
1345 ok (ret == CSTR_LESS_THAN, "(haha/hoho) Expected CSTR_LESS_THAN, got %d\n", ret);
1347 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
1348 ok (ret == CSTR_GREATER_THAN, "(haha/hoho) Expected CSTR_GREATER_THAN, got %d\n", ret);
1350 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
1351 ok (ret == CSTR_EQUAL, "(Salut/saLuT) Expected CSTR_EQUAL, got %d\n", ret);
1353 /* test for CompareStringA flags */
1354 SetLastError(0xdeadbeef);
1355 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0x8, "NULL", -1, "NULL", -1);
1356 ok(GetLastError() == ERROR_INVALID_FLAGS,
1357 "unexpected error code %d\n", GetLastError());
1358 ok(!ret, "CompareStringA must fail with invalid flag\n");
1360 SetLastError(0xdeadbeef);
1361 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, LOCALE_USE_CP_ACP, "NULL", -1, "NULL", -1);
1362 ok(GetLastError() == 0xdeadbeef, "unexpected error code %d\n", GetLastError());
1363 ok(ret == CSTR_EQUAL, "CompareStringA error: %d != CSTR_EQUAL\n", ret);
1364 /* end of test for CompareStringA flags */
1366 ret = lstrcmpA("", "");
1367 ok (ret == 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret);
1369 ret = lstrcmpA(NULL, NULL);
1370 ok (ret == 0 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, NULL) should return 0, got %d\n", ret);
1372 ret = lstrcmpA("", NULL);
1373 ok (ret == 1 || broken(ret == -2) /* win9x */, "lstrcmpA(\"\", NULL) should return 1, got %d\n", ret);
1375 ret = lstrcmpA(NULL, "");
1376 ok (ret == -1 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret);
1379 if (0) { /* this requires collation table patch to make it MS compatible */
1380 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
1381 ok(ret == CSTR_LESS_THAN, "'o vs -o expected CSTR_LESS_THAN, got %d\n", ret);
1383 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
1384 ok(ret == CSTR_LESS_THAN, "'o vs -o expected CSTR_LESS_THAN, got %d\n", ret);
1386 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
1387 ok(ret == CSTR_LESS_THAN, "' vs - expected CSTR_LESS_THAN, got %d\n", ret);
1389 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
1390 ok(ret == CSTR_LESS_THAN, "' vs - expected CSTR_LESS_THAN, got %d\n", ret);
1392 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
1393 ok(ret == CSTR_GREATER_THAN, "`o vs /m CSTR_GREATER_THAN got %d\n", ret);
1395 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
1396 ok(ret == CSTR_LESS_THAN, "/m vs `o expected CSTR_LESS_THAN, got %d\n", ret);
1398 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
1399 ok(ret == CSTR_GREATER_THAN, "`o vs /m CSTR_GREATER_THAN got %d\n", ret);
1401 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
1402 ok(ret == CSTR_LESS_THAN, "/m vs `o expected CSTR_LESS_THAN, got %d\n", ret);
1404 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
1405 ok(ret == CSTR_LESS_THAN, "`o vs -m expected CSTR_LESS_THAN, got %d\n", ret);
1407 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
1408 ok(ret == CSTR_GREATER_THAN, "-m vs `o CSTR_GREATER_THAN got %d\n", ret);
1410 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
1411 ok(ret == CSTR_GREATER_THAN, "`o vs -m CSTR_GREATER_THAN got %d\n", ret);
1413 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
1414 ok(ret == CSTR_LESS_THAN, "-m vs `o expected CSTR_LESS_THAN, got %d\n", ret);
1418 /* WinXP handles embedded NULLs differently than earlier versions */
1419 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
1420 ok(ret == CSTR_LESS_THAN || ret == CSTR_EQUAL, "aLuZkUtZ vs aLuZkUtZ\\0A expected CSTR_LESS_THAN or CSTR_EQUAL, got %d\n", ret);
1422 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
1423 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);
1425 ret = CompareStringA(lcid, 0, "a\0b", -1, "a", -1);
1426 ok(ret == CSTR_EQUAL, "a vs a expected CSTR_EQUAL, got %d\n", ret);
1428 ret = CompareStringA(lcid, 0, "a\0b", 4, "a", 2);
1429 ok(ret == CSTR_EQUAL || /* win2k */
1430 ret == CSTR_GREATER_THAN,
1431 "a\\0b vs a expected CSTR_EQUAL or CSTR_GREATER_THAN, got %d\n", ret);
1433 ret = CompareStringA(lcid, 0, "\2", 2, "\1", 2);
1434 todo_wine ok(ret != CSTR_EQUAL, "\\2 vs \\1 expected unequal\n");
1436 ret = CompareStringA(lcid, NORM_IGNORECASE | LOCALE_USE_CP_ACP, "#", -1, ".", -1);
1437 todo_wine ok(ret == CSTR_LESS_THAN, "\"#\" vs \".\" expected CSTR_LESS_THAN, got %d\n", ret);
1439 ret = CompareStringA(lcid, NORM_IGNORECASE, "_", -1, ".", -1);
1440 todo_wine ok(ret == CSTR_GREATER_THAN, "\"_\" vs \".\" expected CSTR_GREATER_THAN, got %d\n", ret);
1442 ret = lstrcmpi("#", ".");
1443 todo_wine ok(ret == -1, "\"#\" vs \".\" expected -1, got %d\n", ret);
1445 lcid = MAKELCID(MAKELANGID(LANG_POLISH, SUBLANG_DEFAULT), SORT_DEFAULT);
1447 /* \xB9 character lies between a and b */
1448 ret = CompareStringA(lcid, 0, "a", 1, "\xB9", 1);
1449 todo_wine ok(ret == CSTR_LESS_THAN, "\'\\xB9\' character should be greater than \'a\'\n");
1450 ret = CompareStringA(lcid, 0, "\xB9", 1, "b", 1);
1451 ok(ret == CSTR_LESS_THAN, "\'\\xB9\' character should be smaller than \'b\'\n");
1454 static void test_LCMapStringA(void)
1457 char buf[256], buf2[256];
1458 static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
1459 static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
1460 static const char symbols_stripped[] = "justateststring1";
1462 SetLastError(0xdeadbeef);
1463 ret = LCMapStringA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP | LCMAP_LOWERCASE,
1464 lower_case, -1, buf, sizeof(buf));
1465 ok(ret == lstrlenA(lower_case) + 1,
1466 "ret %d, error %d, expected value %d\n",
1467 ret, GetLastError(), lstrlenA(lower_case) + 1);
1468 ok(!memcmp(buf, lower_case, ret), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1470 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1471 upper_case, -1, buf, sizeof(buf));
1472 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1473 ok(GetLastError() == ERROR_INVALID_FLAGS,
1474 "unexpected error code %d\n", GetLastError());
1476 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1477 upper_case, -1, buf, sizeof(buf));
1478 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1479 ok(GetLastError() == ERROR_INVALID_FLAGS,
1480 "unexpected error code %d\n", GetLastError());
1482 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1483 upper_case, -1, buf, sizeof(buf));
1484 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1485 ok(GetLastError() == ERROR_INVALID_FLAGS,
1486 "unexpected error code %d\n", GetLastError());
1488 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1489 upper_case, -1, buf, sizeof(buf));
1490 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1491 ok(GetLastError() == ERROR_INVALID_FLAGS,
1492 "unexpected error code %d\n", GetLastError());
1494 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1495 SetLastError(0xdeadbeef);
1496 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1497 upper_case, -1, buf, sizeof(buf));
1498 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1499 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1501 /* test LCMAP_LOWERCASE */
1502 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1503 upper_case, -1, buf, sizeof(buf));
1504 ok(ret == lstrlenA(upper_case) + 1,
1505 "ret %d, error %d, expected value %d\n",
1506 ret, GetLastError(), lstrlenA(upper_case) + 1);
1507 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1509 /* test LCMAP_UPPERCASE */
1510 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1511 lower_case, -1, buf, sizeof(buf));
1512 ok(ret == lstrlenA(lower_case) + 1,
1513 "ret %d, error %d, expected value %d\n",
1514 ret, GetLastError(), lstrlenA(lower_case) + 1);
1515 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1517 /* test buffer overflow */
1518 SetLastError(0xdeadbeef);
1519 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1520 lower_case, -1, buf, 4);
1521 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1522 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1524 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1525 lstrcpyA(buf, lower_case);
1526 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1527 buf, -1, buf, sizeof(buf));
1528 if (!ret) /* Win9x */
1529 trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1532 ok(ret == lstrlenA(lower_case) + 1,
1533 "ret %d, error %d, expected value %d\n",
1534 ret, GetLastError(), lstrlenA(lower_case) + 1);
1535 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1537 lstrcpyA(buf, upper_case);
1538 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1539 buf, -1, buf, sizeof(buf));
1540 if (!ret) /* Win9x */
1541 trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1544 ok(ret == lstrlenA(upper_case) + 1,
1545 "ret %d, error %d, expected value %d\n",
1546 ret, GetLastError(), lstrlenA(lower_case) + 1);
1547 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1550 /* otherwise src == dst should fail */
1551 SetLastError(0xdeadbeef);
1552 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1553 buf, 10, buf, sizeof(buf));
1554 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1555 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1556 "unexpected error code %d\n", GetLastError());
1557 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1559 /* test whether '\0' is always appended */
1560 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1561 upper_case, -1, buf, sizeof(buf));
1562 ok(ret, "LCMapStringA must succeed\n");
1563 ok(buf[ret-1] == 0, "LCMapStringA not null-terminated\n");
1564 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1565 upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1566 ok(ret2, "LCMapStringA must succeed\n");
1567 ok(buf2[ret2-1] == 0, "LCMapStringA not null-terminated\n" );
1568 ok(ret == ret2, "lengths of sort keys must be equal\n");
1569 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1571 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1572 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1573 upper_case, -1, buf, sizeof(buf));
1574 ok(ret, "LCMapStringA must succeed\n");
1575 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1576 lower_case, -1, buf2, sizeof(buf2));
1577 ok(ret2, "LCMapStringA must succeed\n");
1578 ok(ret == ret2, "lengths of sort keys must be equal\n");
1579 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1581 /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1582 results from plain LCMAP_SORTKEY on Vista */
1584 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1585 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1586 lower_case, -1, buf, sizeof(buf));
1587 ok(ret, "LCMapStringA must succeed\n");
1588 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1589 symbols_stripped, -1, buf2, sizeof(buf2));
1590 ok(ret2, "LCMapStringA must succeed\n");
1591 ok(ret == ret2, "lengths of sort keys must be equal\n");
1592 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1594 /* test NORM_IGNORENONSPACE */
1595 lstrcpyA(buf, "foo");
1596 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1597 lower_case, -1, buf, sizeof(buf));
1598 ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1599 lstrlenA(lower_case) + 1, ret);
1600 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1602 /* test NORM_IGNORESYMBOLS */
1603 lstrcpyA(buf, "foo");
1604 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1605 lower_case, -1, buf, sizeof(buf));
1606 ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1607 lstrlenA(symbols_stripped) + 1, ret);
1608 ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1610 /* test srclen = 0 */
1611 SetLastError(0xdeadbeef);
1612 ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1613 ok(!ret, "LCMapStringA should fail with srclen = 0\n");
1614 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1615 "unexpected error code %d\n", GetLastError());
1618 typedef INT (*lcmapstring_wrapper)(DWORD, LPCWSTR, INT, LPWSTR, INT);
1620 static void test_lcmapstring_unicode(lcmapstring_wrapper func_ptr, const char *func_name)
1623 WCHAR buf[256], buf2[256];
1624 char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1626 ret = func_ptr(LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1627 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1629 ok(lstrcmpW(buf, upper_case) == 0, "Expected upper case string\n");
1632 ok(!ret, "%s LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n", func_name);
1633 ok(GetLastError() == ERROR_INVALID_FLAGS, "%s unexpected error code %d\n",
1634 func_name, GetLastError());
1637 ret = func_ptr(LCMAP_HIRAGANA | LCMAP_KATAKANA,
1638 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1639 ok(!ret, "%s LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n", func_name);
1640 ok(GetLastError() == ERROR_INVALID_FLAGS, "%s unexpected error code %d\n",
1641 func_name, GetLastError());
1643 ret = func_ptr(LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1644 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1645 ok(!ret, "%s LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n", func_name);
1646 ok(GetLastError() == ERROR_INVALID_FLAGS, "%s unexpected error code %d\n",
1647 func_name, GetLastError());
1649 ret = func_ptr(LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1650 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1651 ok(!ret, "%s LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n",
1653 ok(GetLastError() == ERROR_INVALID_FLAGS, "%s unexpected error code %d\n",
1654 func_name, GetLastError());
1656 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1657 SetLastError(0xdeadbeef);
1658 ret = func_ptr(LCMAP_LOWERCASE | SORT_STRINGSORT,
1659 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1660 ok(GetLastError() == ERROR_INVALID_FLAGS, "%s expected ERROR_INVALID_FLAGS, got %d\n",
1661 func_name, GetLastError());
1662 ok(!ret, "%s SORT_STRINGSORT without LCMAP_SORTKEY must fail\n", func_name);
1664 /* test LCMAP_LOWERCASE */
1665 ret = func_ptr(LCMAP_LOWERCASE,
1666 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1667 ok(ret == lstrlenW(upper_case) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
1668 ret, GetLastError(), lstrlenW(upper_case) + 1);
1669 ok(!lstrcmpW(buf, lower_case), "%s string compare mismatch\n", func_name);
1671 /* test LCMAP_UPPERCASE */
1672 ret = func_ptr(LCMAP_UPPERCASE,
1673 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1674 ok(ret == lstrlenW(lower_case) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
1675 ret, GetLastError(), lstrlenW(lower_case) + 1);
1676 ok(!lstrcmpW(buf, upper_case), "%s string compare mismatch\n", func_name);
1678 /* test buffer overflow */
1679 SetLastError(0xdeadbeef);
1680 ret = func_ptr(LCMAP_UPPERCASE,
1681 lower_case, -1, buf, 4);
1682 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1683 "%s should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", func_name, ret);
1685 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1686 lstrcpyW(buf, lower_case);
1687 ret = func_ptr(LCMAP_UPPERCASE,
1688 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1689 ok(ret == lstrlenW(lower_case) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
1690 ret, GetLastError(), lstrlenW(lower_case) + 1);
1691 ok(!lstrcmpW(buf, upper_case), "%s string compare mismatch\n", func_name);
1693 lstrcpyW(buf, upper_case);
1694 ret = func_ptr(LCMAP_LOWERCASE,
1695 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1696 ok(ret == lstrlenW(upper_case) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
1697 ret, GetLastError(), lstrlenW(lower_case) + 1);
1698 ok(!lstrcmpW(buf, lower_case), "%s string compare mismatch\n", func_name);
1700 /* otherwise src == dst should fail */
1701 SetLastError(0xdeadbeef);
1702 ret = func_ptr(LCMAP_SORTKEY | LCMAP_UPPERCASE,
1703 buf, 10, buf, sizeof(buf));
1704 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1705 GetLastError() == ERROR_INVALID_PARAMETER /* Win7+ */,
1706 "%s unexpected error code %d\n", func_name, GetLastError());
1707 ok(!ret, "%s src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n", func_name);
1709 /* test whether '\0' is always appended */
1710 ret = func_ptr(LCMAP_SORTKEY,
1711 upper_case, -1, buf, sizeof(buf));
1712 ok(ret, "%s func_ptr must succeed\n", func_name);
1713 ret2 = func_ptr(LCMAP_SORTKEY,
1714 upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1715 ok(ret, "%s func_ptr must succeed\n", func_name);
1716 ok(ret == ret2, "%s lengths of sort keys must be equal\n", func_name);
1717 ok(!lstrcmpA(p_buf, p_buf2), "%s sort keys must be equal\n", func_name);
1719 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1720 ret = func_ptr(LCMAP_SORTKEY | NORM_IGNORECASE,
1721 upper_case, -1, buf, sizeof(buf));
1722 ok(ret, "%s func_ptr must succeed\n", func_name);
1723 ret2 = func_ptr(LCMAP_SORTKEY,
1724 lower_case, -1, buf2, sizeof(buf2));
1725 ok(ret2, "%s func_ptr must succeed\n", func_name);
1726 ok(ret == ret2, "%s lengths of sort keys must be equal\n", func_name);
1727 ok(!lstrcmpA(p_buf, p_buf2), "%s sort keys must be equal\n", func_name);
1729 /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1730 results from plain LCMAP_SORTKEY on Vista */
1732 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1733 ret = func_ptr(LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1734 lower_case, -1, buf, sizeof(buf));
1735 ok(ret, "%s func_ptr must succeed\n", func_name);
1736 ret2 = func_ptr(LCMAP_SORTKEY,
1737 symbols_stripped, -1, buf2, sizeof(buf2));
1738 ok(ret2, "%s func_ptr must succeed\n", func_name);
1739 ok(ret == ret2, "%s lengths of sort keys must be equal\n", func_name);
1740 ok(!lstrcmpA(p_buf, p_buf2), "%s sort keys must be equal\n", func_name);
1742 /* test NORM_IGNORENONSPACE */
1743 lstrcpyW(buf, fooW);
1744 ret = func_ptr(NORM_IGNORENONSPACE,
1745 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1746 ok(ret == lstrlenW(lower_case) + 1, "%s func_ptr should return %d, ret = %d\n", func_name,
1747 lstrlenW(lower_case) + 1, ret);
1748 ok(!lstrcmpW(buf, lower_case), "%s string comparison mismatch\n", func_name);
1750 /* test NORM_IGNORESYMBOLS */
1751 lstrcpyW(buf, fooW);
1752 ret = func_ptr(NORM_IGNORESYMBOLS,
1753 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1754 ok(ret == lstrlenW(symbols_stripped) + 1, "%s func_ptr should return %d, ret = %d\n", func_name,
1755 lstrlenW(symbols_stripped) + 1, ret);
1756 ok(!lstrcmpW(buf, symbols_stripped), "%s string comparison mismatch\n", func_name);
1758 /* test srclen = 0 */
1759 SetLastError(0xdeadbeef);
1760 ret = func_ptr(0, upper_case, 0, buf, sizeof(buf)/sizeof(WCHAR));
1761 ok(!ret, "%s func_ptr should fail with srclen = 0\n", func_name);
1762 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1763 "%s unexpected error code %d\n", func_name, GetLastError());
1766 static INT LCMapStringW_wrapper(DWORD flags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen)
1768 return LCMapStringW(LOCALE_USER_DEFAULT, flags, src, srclen, dst, dstlen);
1771 static void test_LCMapStringW(void)
1776 trace("testing LCMapStringW\n");
1778 SetLastError(0xdeadbeef);
1779 ret = LCMapStringW((LCID)-1, LCMAP_LOWERCASE, upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1781 ok(!ret, "LCMapStringW should fail with bad lcid\n");
1782 ok(GetLastError() == ERROR_INVALID_PARAMETER, "unexpected error code %d\n", GetLastError());
1785 test_lcmapstring_unicode(LCMapStringW_wrapper, "LCMapStringW:");
1788 static INT LCMapStringEx_wrapper(DWORD flags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen)
1790 return pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, flags, src, srclen, dst, dstlen, NULL, NULL, 0);
1793 static void test_LCMapStringEx(void)
1798 if (!pLCMapStringEx)
1800 win_skip( "LCMapStringEx not available\n" );
1804 trace("testing LCMapStringEx\n");
1806 SetLastError(0xdeadbeef);
1807 ret = pLCMapStringEx(fooW, LCMAP_LOWERCASE,
1808 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), NULL, NULL, 0);
1810 ok(!ret, "LCMapStringEx should fail with bad locale name\n");
1811 ok(GetLastError() == ERROR_INVALID_PARAMETER, "unexpected error code %d\n", GetLastError());
1814 /* test reserved parameters */
1815 ret = pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_LOWERCASE,
1816 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), NULL, NULL, 1);
1817 ok(ret == lstrlenW(upper_case) + 1, "ret %d, error %d, expected value %d\n",
1818 ret, GetLastError(), lstrlenW(upper_case) + 1);
1819 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1821 ret = pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_LOWERCASE,
1822 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), NULL, (void*)1, 0);
1823 ok(ret == lstrlenW(upper_case) + 1, "ret %d, error %d, expected value %d\n",
1824 ret, GetLastError(), lstrlenW(upper_case) + 1);
1825 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1827 /* crashes on native */
1829 ret = pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_LOWERCASE,
1830 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), (void*)1, NULL, 0);
1832 test_lcmapstring_unicode(LCMapStringEx_wrapper, "LCMapStringEx:");
1835 struct neutralsublang_name_t {
1841 static const struct neutralsublang_name_t neutralsublang_names[] = {
1842 { {'a','r',0}, MAKELCID(MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA), SORT_DEFAULT) },
1843 { {'a','z',0}, MAKELCID(MAKELANGID(LANG_AZERI, SUBLANG_AZERI_LATIN), SORT_DEFAULT) },
1844 { {'d','e',0}, MAKELCID(MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN), SORT_DEFAULT) },
1845 { {'e','n',0}, MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT) },
1846 { {'e','s',0}, MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN), SORT_DEFAULT), 1 },
1847 { {'g','a',0}, MAKELCID(MAKELANGID(LANG_IRISH, SUBLANG_IRISH_IRELAND), SORT_DEFAULT), 1 },
1848 { {'i','t',0}, MAKELCID(MAKELANGID(LANG_ITALIAN, SUBLANG_ITALIAN), SORT_DEFAULT) },
1849 { {'m','s',0}, MAKELCID(MAKELANGID(LANG_MALAY, SUBLANG_MALAY_MALAYSIA), SORT_DEFAULT) },
1850 { {'n','l',0}, MAKELCID(MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH), SORT_DEFAULT) },
1851 { {'p','t',0}, MAKELCID(MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN), SORT_DEFAULT) },
1852 { {'s','r',0}, MAKELCID(MAKELANGID(LANG_SERBIAN, SUBLANG_SERBIAN_SERBIA_LATIN), SORT_DEFAULT), 1 },
1853 { {'s','v',0}, MAKELCID(MAKELANGID(LANG_SWEDISH, SUBLANG_SWEDISH), SORT_DEFAULT) },
1854 { {'u','z',0}, MAKELCID(MAKELANGID(LANG_UZBEK, SUBLANG_UZBEK_LATIN), SORT_DEFAULT) },
1855 { {'z','h',0}, MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT), 1 },
1859 static void test_LocaleNameToLCID(void)
1863 WCHAR buffer[LOCALE_NAME_MAX_LENGTH];
1864 static const WCHAR enW[] = {'e','n',0};
1866 if (!pLocaleNameToLCID)
1868 win_skip( "LocaleNameToLCID not available\n" );
1874 SetLastError(0xdeadbeef);
1875 lcid = pLocaleNameToLCID(LOCALE_NAME_USER_DEFAULT, 0);
1876 ok(lcid == GetUserDefaultLCID() || broken(GetLastError() == ERROR_INVALID_PARAMETER /* Vista */),
1877 "Expected lcid == %08x, got %08x, error %d\n", GetUserDefaultLCID(), lcid, GetLastError());
1878 ret = pLCIDToLocaleName(lcid, buffer, LOCALE_NAME_MAX_LENGTH, 0);
1879 ok(ret > 0, "Expected ret > 0, got %d, error %d\n", ret, GetLastError());
1880 trace("%08x, %s\n", lcid, wine_dbgstr_w(buffer));
1883 SetLastError(0xdeadbeef);
1884 lcid = pLocaleNameToLCID(LOCALE_NAME_SYSTEM_DEFAULT, 0);
1885 ok(!lcid && GetLastError() == ERROR_INVALID_PARAMETER,
1886 "Expected lcid == 0, got %08x, error %d\n", lcid, GetLastError());
1887 ret = pLCIDToLocaleName(lcid, buffer, LOCALE_NAME_MAX_LENGTH, 0);
1888 ok(ret > 0, "Expected ret > 0, got %d, error %d\n", ret, GetLastError());
1889 trace("%08x, %s\n", lcid, wine_dbgstr_w(buffer));
1892 SetLastError(0xdeadbeef);
1893 lcid = pLocaleNameToLCID(LOCALE_NAME_INVARIANT, 0);
1894 todo_wine ok(lcid == 0x7F, "Expected lcid = 0x7F, got %08x, error %d\n", lcid, GetLastError());
1895 ret = pLCIDToLocaleName(lcid, buffer, LOCALE_NAME_MAX_LENGTH, 0);
1896 ok(ret > 0, "Expected ret > 0, got %d, error %d\n", ret, GetLastError());
1897 trace("%08x, %s\n", lcid, wine_dbgstr_w(buffer));
1900 SetLastError(0xdeadbeef);
1901 lcid = pLocaleNameToLCID(fooW, 0);
1902 ok(!lcid && GetLastError() == ERROR_INVALID_PARAMETER,
1903 "Expected lcid == 0, got got %08x, error %d\n", lcid, GetLastError());
1905 /* english neutral name */
1906 lcid = pLocaleNameToLCID(enW, 0);
1907 ok(lcid == MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT) ||
1908 broken(lcid == 0) /* Vista */, "got 0x%04x\n", lcid);
1911 const struct neutralsublang_name_t *ptr = neutralsublang_names;
1915 lcid = pLocaleNameToLCID(ptr->name, 0);
1918 ok(lcid == ptr->lcid, "%s: got wrong lcid 0x%04x, expected 0x%04x\n",
1919 wine_dbgstr_w(ptr->name), lcid, ptr->lcid);
1921 ok(lcid == ptr->lcid, "%s: got wrong lcid 0x%04x, expected 0x%04x\n",
1922 wine_dbgstr_w(ptr->name), lcid, ptr->lcid);
1925 ret = pLCIDToLocaleName(lcid, buffer, sizeof(buffer)/sizeof(WCHAR), 0);
1926 ok(ret > 0, "%s: got %d\n", wine_dbgstr_w(ptr->name), ret);
1927 ok(lstrcmpW(ptr->name, buffer), "%s: got wrong locale name %s\n",
1928 wine_dbgstr_w(ptr->name), wine_dbgstr_w(buffer));
1935 /* this requires collation table patch to make it MS compatible */
1936 static const char * const strings_sorted[] =
1968 static const char * const strings[] =
2000 static int compare_string1(const void *e1, const void *e2)
2002 const char *s1 = *(const char *const *)e1;
2003 const char *s2 = *(const char *const *)e2;
2005 return lstrcmpA(s1, s2);
2008 static int compare_string2(const void *e1, const void *e2)
2010 const char *s1 = *(const char *const *)e1;
2011 const char *s2 = *(const char *const *)e2;
2013 return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
2016 static int compare_string3(const void *e1, const void *e2)
2018 const char *s1 = *(const char *const *)e1;
2019 const char *s2 = *(const char *const *)e2;
2020 char key1[256], key2[256];
2022 LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
2023 LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
2024 return strcmp(key1, key2);
2027 static void test_sorting(void)
2030 char **str_buf = (char **)buf;
2033 assert(sizeof(buf) >= sizeof(strings));
2035 /* 1. sort using lstrcmpA */
2036 memcpy(buf, strings, sizeof(strings));
2037 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
2038 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
2040 ok(!strcmp(strings_sorted[i], str_buf[i]),
2041 "qsort using lstrcmpA failed for element %d\n", i);
2043 /* 2. sort using CompareStringA */
2044 memcpy(buf, strings, sizeof(strings));
2045 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
2046 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
2048 ok(!strcmp(strings_sorted[i], str_buf[i]),
2049 "qsort using CompareStringA failed for element %d\n", i);
2051 /* 3. sort using sort keys */
2052 memcpy(buf, strings, sizeof(strings));
2053 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
2054 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
2056 ok(!strcmp(strings_sorted[i], str_buf[i]),
2057 "qsort using sort keys failed for element %d\n", i);
2061 static void test_FoldStringA(void)
2065 char src[256], dst[256];
2066 static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0' };
2067 static const char digits_dst[] = { '1','2','3','\0' };
2068 static const char composite_src[] =
2070 0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
2071 0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
2072 0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
2073 0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
2074 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
2075 0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
2076 0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
2077 0xfb,0xfc,0xfd,0xff,'\0'
2079 static const char composite_dst[] =
2081 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
2082 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
2083 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
2084 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
2085 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
2086 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
2087 0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
2088 0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
2089 0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
2090 0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
2091 0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
2092 0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
2093 0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
2094 0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
2095 0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
2097 static const char composite_dst_alt[] =
2099 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
2100 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
2101 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
2102 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
2103 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
2104 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
2105 0x4f,0x7e,0x4f,0xa8,0xd8,0x55,0x60,0x55,
2106 0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,0x61,
2107 0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,0x61,
2108 0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,0x65,
2109 0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,0x69,
2110 0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,0x6f,
2111 0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,0x6f,
2112 0xa8,0xf8,0x75,0x60,0x75,0xb4,0x75,0x5e,
2113 0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
2115 static const char ligatures_src[] =
2117 0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
2119 static const char ligatures_dst[] =
2121 'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
2123 static const struct special
2127 } foldczone_special[] =
2130 { 0x85, { 0x2e, 0x2e, 0x2e, 0x00 } },
2131 { 0x98, { 0x20, 0x7e, 0x00 } },
2132 { 0x99, { 0x54, 0x4d, 0x00 } },
2133 { 0xa0, { 0x20, 0x00 } },
2134 { 0xa8, { 0x20, 0xa8, 0x00 } },
2135 { 0xaa, { 0x61, 0x00 } },
2136 { 0xaf, { 0x20, 0xaf, 0x00 } },
2137 { 0xb2, { 0x32, 0x00 } },
2138 { 0xb3, { 0x33, 0x00 } },
2139 { 0xb4, { 0x20, 0xb4, 0x00 } },
2140 { 0xb8, { 0x20, 0xb8, 0x00 } },
2141 { 0xb9, { 0x31, 0x00 } },
2142 { 0xba, { 0x6f, 0x00 } },
2143 { 0xbc, { 0x31, 0x2f, 0x34, 0x00 } },
2144 { 0xbd, { 0x31, 0x2f, 0x32, 0x00 } },
2145 { 0xbe, { 0x33, 0x2f, 0x34, 0x00 } },
2150 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
2152 /* these tests are locale specific */
2153 if (GetACP() != 1252)
2155 trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
2159 /* MAP_FOLDDIGITS */
2161 ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
2162 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2164 win_skip("FoldStringA is not implemented\n");
2167 ok(ret == 4, "Expected ret == 4, got %d, error %d\n", ret, GetLastError());
2168 ok(strcmp(dst, digits_dst) == 0,
2169 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
2170 for (i = 1; i < 256; i++)
2172 if (!strchr(digits_src, i))
2177 ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
2178 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2179 ok(dst[0] == src[0],
2180 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
2184 /* MAP_EXPAND_LIGATURES */
2186 ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
2187 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
2188 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
2189 ok(ret == sizeof(ligatures_dst), "Got %d, error %d\n", ret, GetLastError());
2190 ok(strcmp(dst, ligatures_dst) == 0,
2191 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
2192 for (i = 1; i < 256; i++)
2194 if (!strchr(ligatures_src, i))
2199 ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
2203 ok((i == 0xDC && lstrcmpA(dst, "UE") == 0) ||
2204 (i == 0xFC && lstrcmpA(dst, "ue") == 0),
2205 "Got %s for %d\n", dst, i);
2209 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2210 ok(dst[0] == src[0],
2211 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
2219 ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
2220 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2221 ok(ret == 121 || ret == 119, "Expected 121 or 119, got %d\n", ret);
2222 ok(strcmp(dst, composite_dst) == 0 || strcmp(dst, composite_dst_alt) == 0,
2223 "MAP_COMPOSITE: Mismatch, got '%s'\n", dst);
2225 for (i = 1; i < 256; i++)
2227 if (!strchr(composite_src, i))
2232 ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
2233 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2234 ok(dst[0] == src[0],
2235 "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
2236 (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
2241 for (i = 1; i < 256; i++)
2246 ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
2248 for (j = 0; foldczone_special[j].src != 0 && ! is_special; j++)
2250 if (foldczone_special[j].src == src[0])
2252 ok(ret == 2 || ret == lstrlenA(foldczone_special[j].dst) + 1,
2253 "Expected ret == 2 or %d, got %d, error %d\n",
2254 lstrlenA(foldczone_special[j].dst) + 1, ret, GetLastError());
2255 ok(src[0] == dst[0] || lstrcmpA(foldczone_special[j].dst, dst) == 0,
2256 "MAP_FOLDCZONE: string mismatch for 0x%02x\n",
2257 (unsigned char)src[0]);
2263 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2264 ok(src[0] == dst[0],
2265 "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
2266 (unsigned char)src[0], (unsigned char)dst[0]);
2270 /* MAP_PRECOMPOSED */
2271 for (i = 1; i < 256; i++)
2276 ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
2277 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2278 ok(src[0] == dst[0],
2279 "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
2280 (unsigned char)src[0], (unsigned char)dst[0]);
2284 static void test_FoldStringW(void)
2288 WCHAR src[256], dst[256], ch, prev_ch = 1;
2289 static const DWORD badFlags[] =
2292 MAP_PRECOMPOSED|MAP_COMPOSITE,
2293 MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
2294 MAP_COMPOSITE|MAP_EXPAND_LIGATURES
2296 /* Ranges of digits 0-9 : Must be sorted! */
2297 static const WCHAR digitRanges[] =
2299 0x0030, /* '0'-'9' */
2300 0x0660, /* Eastern Arabic */
2301 0x06F0, /* Arabic - Hindu */
2302 0x0966, /* Devengari */
2303 0x09E6, /* Bengalii */
2304 0x0A66, /* Gurmukhi */
2305 0x0AE6, /* Gujarati */
2307 0x0BE6, /* Tamil - No 0 */
2308 0x0C66, /* Telugu */
2309 0x0CE6, /* Kannada */
2310 0x0D66, /* Maylayalam */
2313 0x0F29, /* Tibet - 0 is out of sequence */
2314 0x2070, /* Superscript - 1, 2, 3 are out of sequence */
2315 0x2080, /* Subscript */
2316 0x245F, /* Circled - 0 is out of sequence */
2317 0x2473, /* Bracketed */
2318 0x2487, /* Full stop */
2319 0x2775, /* Inverted circled - No 0 */
2320 0x277F, /* Patterned circled - No 0 */
2321 0x2789, /* Inverted Patterned circled - No 0 */
2322 0x3020, /* Hangzhou */
2323 0xff10, /* Pliene chasse (?) */
2324 0xffff /* Terminator */
2326 /* Digits which are represented, but out of sequence */
2327 static const WCHAR outOfSequenceDigits[] =
2329 0xB9, /* Superscript 1 */
2330 0xB2, /* Superscript 2 */
2331 0xB3, /* Superscript 3 */
2332 0x0F33, /* Tibetan half zero */
2333 0x24EA, /* Circled 0 */
2334 0x3007, /* Ideographic number zero */
2335 '\0' /* Terminator */
2337 /* Digits in digitRanges for which no representation is available */
2338 static const WCHAR noDigitAvailable[] =
2340 0x0BE6, /* No Tamil 0 */
2341 0x0F29, /* No Tibetan half zero (out of sequence) */
2342 0x2473, /* No Bracketed 0 */
2343 0x2487, /* No 0 Full stop */
2344 0x2775, /* No inverted circled 0 */
2345 0x277F, /* No patterned circled */
2346 0x2789, /* No inverted Patterned circled */
2347 0x3020, /* No Hangzhou 0 */
2348 '\0' /* Terminator */
2350 static const WCHAR foldczone_src[] =
2352 'W', 'i', 'n', 'e', 0x0348, 0x0551, 0x1323, 0x280d,
2353 0xff37, 0xff49, 0xff4e, 0xff45, '\0'
2355 static const WCHAR foldczone_dst[] =
2357 'W','i','n','e',0x0348,0x0551,0x1323,0x280d,'W','i','n','e','\0'
2359 static const WCHAR foldczone_todo_src[] =
2361 0x3c5,0x308,0x6a,0x30c,0xa0,0xaa,0
2363 static const WCHAR foldczone_todo_dst[] =
2365 0x3cb,0x1f0,' ','a',0
2367 static const WCHAR foldczone_todo_broken_dst[] =
2369 0x3cb,0x1f0,0xa0,0xaa,0
2371 static const WCHAR ligatures_src[] =
2373 'W', 'i', 'n', 'e', 0x03a6, 0x03b9, 0x03bd, 0x03b5,
2374 0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
2375 0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
2376 0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
2377 0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
2378 0xfb04, 0xfb05, 0xfb06, '\0'
2380 static const WCHAR ligatures_dst[] =
2382 'W','i','n','e',0x03a6,0x03b9,0x03bd,0x03b5,
2383 'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
2384 'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
2385 'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
2386 0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
2387 'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
2392 win_skip("FoldStringW is not available\n");
2393 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
2396 /* Invalid flag combinations */
2397 for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
2399 src[0] = dst[0] = '\0';
2401 ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
2402 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
2404 win_skip("FoldStringW is not implemented\n");
2407 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
2408 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2411 /* src & dst cannot be the same */
2413 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
2414 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2415 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2417 /* src can't be NULL */
2419 ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
2420 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2421 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2423 /* srclen can't be 0 */
2425 ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
2426 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2427 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2429 /* dstlen can't be < 0 */
2431 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
2432 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2433 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2435 /* Ret includes terminating NUL which is appended if srclen = -1 */
2440 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
2441 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2442 ok(dst[0] == 'A' && dst[1] == '\0',
2443 "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%d\n",
2444 'A', '\0', ret, dst[0], dst[1], GetLastError());
2446 /* If size is given, result is not NUL terminated */
2452 ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
2453 ok(ret == 1, "Expected ret == 1, got %d, error %d\n", ret, GetLastError());
2454 ok(dst[0] == 'A' && dst[1] == 'X',
2455 "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%d\n",
2456 'A','X', ret, dst[0], dst[1], GetLastError());
2458 /* MAP_FOLDDIGITS */
2459 for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
2461 /* Check everything before this range */
2462 for (ch = prev_ch; ch < digitRanges[j]; ch++)
2466 src[1] = dst[0] = '\0';
2467 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2468 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2470 ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
2471 /* Wine (correctly) maps all Unicode 4.0+ digits */
2472 isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF || ch == 0x19da ||
2473 (ch >= 0x1369 && ch <= 0x1371),
2474 "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
2477 if (digitRanges[j] == 0xffff)
2478 break; /* Finished the whole code point space */
2480 for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
2484 /* Map out of sequence characters */
2485 if (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
2486 else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
2487 else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
2488 else if (ch == 0x245F) c = 0x24EA; /* Circled 0 */
2492 src[1] = dst[0] = '\0';
2493 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2494 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2496 ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
2497 broken( dst[0] == ch ) || /* old Windows versions don't have all mappings */
2498 (digitRanges[j] == 0x3020 && dst[0] == ch) || /* Hangzhou not present in all Windows versions */
2499 (digitRanges[j] == 0x0F29 && dst[0] == ch) || /* Tibetan not present in all Windows versions */
2500 strchrW(noDigitAvailable, c),
2501 "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
2502 ch, '0' + digitRanges[j] - ch, dst[0]);
2509 ret = pFoldStringW(MAP_FOLDCZONE, foldczone_src, -1, dst, 256);
2510 ok(ret == sizeof(foldczone_dst)/sizeof(foldczone_dst[0]),
2511 "Got %d, error %d\n", ret, GetLastError());
2512 ok(!memcmp(dst, foldczone_dst, sizeof(foldczone_dst)),
2513 "MAP_FOLDCZONE: Expanded incorrectly\n");
2515 ret = pFoldStringW(MAP_FOLDCZONE|MAP_PRECOMPOSED, foldczone_todo_src, -1, dst, 256);
2516 todo_wine ok(ret == sizeof(foldczone_todo_dst)/sizeof(foldczone_todo_dst[0]),
2517 "Got %d, error %d\n", ret, GetLastError());
2518 todo_wine ok(!memcmp(dst, foldczone_todo_dst, sizeof(foldczone_todo_dst))
2519 || broken(!memcmp(dst, foldczone_todo_broken_dst, sizeof(foldczone_todo_broken_dst))),
2520 "MAP_FOLDCZONE: Expanded incorrectly (%s)\n", wine_dbgstr_w(dst));
2522 /* MAP_EXPAND_LIGATURES */
2524 ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
2525 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
2526 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
2527 ok(ret == sizeof(ligatures_dst)/sizeof(ligatures_dst[0]),
2528 "Got %d, error %d\n", ret, GetLastError());
2529 ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
2530 "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
2533 /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
2538 #define LCID_OK(l) \
2539 ok(lcid == l, "Expected lcid = %08x, got %08x\n", l, lcid)
2540 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
2541 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
2542 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
2543 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
2545 static void test_ConvertDefaultLocale(void)
2549 /* Doesn't change lcid, even if non default sublang/sort used */
2550 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_US, SORT_DEFAULT);
2551 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_UK, SORT_DEFAULT);
2552 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT);
2553 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE);
2555 /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
2556 LCID_RES(MKLCID(LANG_ENGLISH, SUBLANG_NEUTRAL, SORT_DEFAULT),
2557 MKLCID(LANG_ENGLISH, SUBLANG_DEFAULT, SORT_DEFAULT));
2558 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
2559 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
2561 /* Invariant language is not treated specially */
2562 TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
2564 /* User/system default languages alone are not mapped */
2565 TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
2566 TEST_LCIDLANG(LANG_USER_DEFAULT, SORT_JAPANESE_UNICODE);
2569 LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
2570 LCID_RES(LOCALE_USER_DEFAULT, GetUserDefaultLCID());
2571 LCID_RES(LOCALE_NEUTRAL, GetUserDefaultLCID());
2574 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
2575 DWORD dwFlags, LONG_PTR lParam)
2577 trace("%08x, %s, %s, %08x, %08lx\n",
2578 lgrpid, lpszNum, lpszName, dwFlags, lParam);
2580 ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
2581 "Enumerated grp %d not valid (flags %d)\n", lgrpid, dwFlags);
2583 /* If lParam is one, we are calling with flags defaulted from 0 */
2584 ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
2585 "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %d\n", dwFlags);
2590 static void test_EnumSystemLanguageGroupsA(void)
2594 if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
2596 win_skip("EnumSystemLanguageGroupsA and/or IsValidLanguageGroup are not available\n");
2600 /* No enumeration proc */
2602 ret = pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
2603 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2605 win_skip("EnumSystemLanguageGroupsA is not implemented\n");
2608 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2609 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2613 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
2614 ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2616 /* No flags - defaults to LGRPID_INSTALLED */
2617 SetLastError(0xdeadbeef);
2618 pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
2619 ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
2621 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
2622 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
2625 static BOOL CALLBACK enum_func( LPWSTR name, DWORD flags, LPARAM lparam )
2627 trace( "%s %x\n", wine_dbgstr_w(name), flags );
2631 static void test_EnumSystemLocalesEx(void)
2635 if (!pEnumSystemLocalesEx)
2637 win_skip( "EnumSystemLocalesEx not available\n" );
2640 SetLastError( 0xdeadbeef );
2641 ret = pEnumSystemLocalesEx( enum_func, LOCALE_ALL, 0, (void *)1 );
2642 ok( !ret, "should have failed\n" );
2643 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
2644 SetLastError( 0xdeadbeef );
2645 ret = pEnumSystemLocalesEx( enum_func, 0, 0, NULL );
2646 ok( ret, "failed err %u\n", GetLastError() );
2649 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
2652 trace("%08x, %08x, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
2654 /* invalid locale enumerated on some platforms */
2658 ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
2659 "Enumerated grp %d not valid\n", lgrpid);
2660 ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
2661 "Enumerated grp locale %d not valid\n", lcid);
2665 static void test_EnumLanguageGroupLocalesA(void)
2669 if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
2671 win_skip("EnumLanguageGroupLocalesA and/or IsValidLanguageGroup are not available\n");
2675 /* No enumeration proc */
2677 ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
2678 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2680 win_skip("EnumLanguageGroupLocalesA is not implemented\n");
2683 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2684 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2686 /* lgrpid too small */
2688 ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
2689 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2690 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2692 /* lgrpid too big */
2694 ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
2695 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2696 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2698 /* dwFlags is reserved */
2700 ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
2701 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2702 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2704 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2707 static void test_SetLocaleInfoA(void)
2710 LCID lcid = GetUserDefaultLCID();
2714 bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2715 ok( !bRet && GetLastError() == ERROR_INVALID_PARAMETER,
2716 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2720 bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, "test_SetLocaleInfoA");
2721 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2722 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2726 bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, "test_SetLocaleInfoA");
2727 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2728 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2731 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2733 trace("%s %08lx\n", value, lParam);
2737 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2739 ok(!enumCount, "callback called again unexpected\n");
2744 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2746 ok(0,"callback called unexpected\n");
2750 static void test_EnumUILanguageA(void)
2753 if (!pEnumUILanguagesA) {
2754 win_skip("EnumUILanguagesA is not available on Win9x or NT4\n");
2758 SetLastError(ERROR_SUCCESS);
2759 ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2760 if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2762 win_skip("EnumUILanguagesA is not implemented\n");
2765 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2768 SetLastError(ERROR_SUCCESS);
2769 ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2770 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2772 SetLastError(ERROR_SUCCESS);
2773 ret = pEnumUILanguagesA(NULL, 0, 0);
2774 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2775 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2776 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2778 SetLastError(ERROR_SUCCESS);
2779 ret = pEnumUILanguagesA(luilocale_proc3A, 0x5a5a5a5a, 0);
2780 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2781 ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2783 SetLastError(ERROR_SUCCESS);
2784 ret = pEnumUILanguagesA(NULL, 0x5a5a5a5a, 0);
2785 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2786 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2787 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2790 static char date_fmt_buf[1024];
2792 static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
2794 lstrcatA(date_fmt_buf, fmt);
2795 lstrcatA(date_fmt_buf, "\n");
2799 static void test_EnumDateFormatsA(void)
2803 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2805 trace("EnumDateFormatsA 0\n");
2806 date_fmt_buf[0] = 0;
2807 SetLastError(0xdeadbeef);
2808 ret = EnumDateFormatsA(enum_datetime_procA, lcid, 0);
2809 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2811 win_skip("0 for dwFlags is not supported\n");
2815 ok(ret, "EnumDateFormatsA(0) error %d\n", GetLastError());
2816 trace("%s\n", date_fmt_buf);
2817 /* test the 1st enumerated format */
2818 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2819 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2820 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2821 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2824 trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n");
2825 date_fmt_buf[0] = 0;
2826 SetLastError(0xdeadbeef);
2827 ret = EnumDateFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2828 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2830 win_skip("LOCALE_USE_CP_ACP is not supported\n");
2834 ok(ret, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2835 trace("%s\n", date_fmt_buf);
2836 /* test the 1st enumerated format */
2837 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2838 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2839 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2840 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2843 trace("EnumDateFormatsA DATE_SHORTDATE\n");
2844 date_fmt_buf[0] = 0;
2845 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_SHORTDATE);
2846 ok(ret, "EnumDateFormatsA(DATE_SHORTDATE) error %d\n", GetLastError());
2847 trace("%s\n", date_fmt_buf);
2848 /* test the 1st enumerated format */
2849 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2850 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2851 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2852 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2854 trace("EnumDateFormatsA DATE_LONGDATE\n");
2855 date_fmt_buf[0] = 0;
2856 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_LONGDATE);
2857 ok(ret, "EnumDateFormatsA(DATE_LONGDATE) error %d\n", GetLastError());
2858 trace("%s\n", date_fmt_buf);
2859 /* test the 1st enumerated format */
2860 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2861 ret = GetLocaleInfoA(lcid, LOCALE_SLONGDATE, buf, sizeof(buf));
2862 ok(ret, "GetLocaleInfoA(LOCALE_SLONGDATE) error %d\n", GetLastError());
2863 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2865 trace("EnumDateFormatsA DATE_YEARMONTH\n");
2866 date_fmt_buf[0] = 0;
2867 SetLastError(0xdeadbeef);
2868 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_YEARMONTH);
2869 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2871 skip("DATE_YEARMONTH is only present on W2K and later\n");
2874 ok(ret, "EnumDateFormatsA(DATE_YEARMONTH) error %d\n", GetLastError());
2875 trace("%s\n", date_fmt_buf);
2876 /* test the 1st enumerated format */
2877 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2878 ret = GetLocaleInfoA(lcid, LOCALE_SYEARMONTH, buf, sizeof(buf));
2879 ok(ret, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %d\n", GetLastError());
2880 ok(!lstrcmpA(date_fmt_buf, buf) || broken(!buf[0]) /* win9x */,
2881 "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2884 static void test_EnumTimeFormatsA(void)
2888 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2890 trace("EnumTimeFormatsA 0\n");
2891 date_fmt_buf[0] = 0;
2892 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, 0);
2893 ok(ret, "EnumTimeFormatsA(0) error %d\n", GetLastError());
2894 trace("%s\n", date_fmt_buf);
2895 /* test the 1st enumerated format */
2896 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2897 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2898 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2899 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2901 trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n");
2902 date_fmt_buf[0] = 0;
2903 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2904 ok(ret, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2905 trace("%s\n", date_fmt_buf);
2906 /* test the 1st enumerated format */
2907 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2908 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2909 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2910 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2913 static void test_GetCPInfo(void)
2918 SetLastError(0xdeadbeef);
2919 ret = GetCPInfo(CP_SYMBOL, &cpinfo);
2920 ok(!ret, "GetCPInfo(CP_SYMBOL) should fail\n");
2921 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2922 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2924 SetLastError(0xdeadbeef);
2925 ret = GetCPInfo(CP_UTF7, &cpinfo);
2926 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2928 skip("Codepage CP_UTF7 is not installed/available\n");
2932 ok(ret, "GetCPInfo(CP_UTF7) error %u\n", GetLastError());
2933 ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2934 ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2935 ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2936 ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2937 ok(cpinfo.MaxCharSize == 5, "expected 5, got 0x%x\n", cpinfo.MaxCharSize);
2940 SetLastError(0xdeadbeef);
2941 ret = GetCPInfo(CP_UTF8, &cpinfo);
2942 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2944 skip("Codepage CP_UTF8 is not installed/available\n");
2948 ok(ret, "GetCPInfo(CP_UTF8) error %u\n", GetLastError());
2949 ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2950 ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2951 ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2952 ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2953 ok(cpinfo.MaxCharSize == 4 || broken(cpinfo.MaxCharSize == 3) /* win9x */,
2954 "expected 4, got %u\n", cpinfo.MaxCharSize);
2959 * The CT_TYPE1 has varied over windows version.
2960 * The current target for correct behavior is windows 7.
2961 * There was a big shift between windows 2000 (first introduced) and windows Xp
2962 * Most of the old values below are from windows 2000.
2963 * A smaller subset of changes happened between windows Xp and Window vista/7
2965 static void test_GetStringTypeW(void)
2967 static const WCHAR blanks[] = {0x9, 0x20, 0xa0, 0x3000, 0xfeff};
2968 static const WORD blanks_new[] = {C1_SPACE | C1_CNTRL | C1_BLANK | C1_DEFINED,
2969 C1_SPACE | C1_BLANK | C1_DEFINED,
2970 C1_SPACE | C1_BLANK | C1_DEFINED,
2971 C1_SPACE | C1_BLANK | C1_DEFINED,
2972 C1_CNTRL | C1_BLANK | C1_DEFINED};
2973 static const WORD blanks_old[] ={C1_SPACE | C1_CNTRL | C1_BLANK,
2974 C1_SPACE | C1_BLANK,
2975 C1_SPACE | C1_BLANK,
2976 C1_SPACE | C1_BLANK,
2977 C1_SPACE | C1_BLANK};
2979 static const WCHAR undefined[] = {0x378, 0x379, 0x604, 0xfff8, 0xfffe};
2982 static const WCHAR alpha[] = {0x47, 0x67, 0x1c5};
2983 static const WORD alpha_old[] = {C1_UPPER | C1_ALPHA,
2984 C1_LOWER | C1_ALPHA,
2985 C1_UPPER | C1_LOWER | C1_ALPHA,
2988 /* Sk, Sk, Mn, So, Me */
2989 static const WCHAR oldpunc[] = { 0x2c2, 0x2e5, 0x322, 0x482, 0x6de,
2991 0xffe0, 0xffe9, 0x2153};
2993 /* Lm, Nl, Cf, 0xad(Cf), 0x1f88 (Lt), Lo, Mc */
2994 static const WCHAR changed[] = {0x2b0, 0x2160, 0x600, 0xad, 0x1f88, 0x294, 0x903};
2995 static const WORD changed_old[] = { C1_PUNCT, C1_PUNCT, 0, C1_PUNCT, C1_UPPER | C1_ALPHA, C1_ALPHA, C1_PUNCT };
2996 static const WORD changed_xp[] = {C1_ALPHA | C1_DEFINED,
2997 C1_ALPHA | C1_DEFINED,
2998 C1_CNTRL | C1_DEFINED,
2999 C1_PUNCT | C1_DEFINED,
3000 C1_UPPER | C1_LOWER | C1_ALPHA | C1_DEFINED,
3001 C1_ALPHA | C1_LOWER | C1_DEFINED,
3002 C1_ALPHA | C1_DEFINED };
3003 static const WORD changed_new[] = { C1_ALPHA | C1_DEFINED,
3004 C1_ALPHA | C1_DEFINED,
3005 C1_CNTRL | C1_DEFINED,
3006 C1_PUNCT | C1_CNTRL | C1_DEFINED,
3007 C1_UPPER | C1_LOWER | C1_ALPHA | C1_DEFINED,
3008 C1_ALPHA | C1_DEFINED,
3011 /* Pc, Pd, Ps, Pe, Pi, Pf, Po*/
3012 static const WCHAR punct[] = { 0x5f, 0x2d, 0x28, 0x29, 0xab, 0xbb, 0x21 };
3014 static const WCHAR punct_special[] = {0x24, 0x2b, 0x3c, 0x3e, 0x5e, 0x60,
3015 0x7c, 0x7e, 0xa2, 0xbe, 0xd7, 0xf7};
3016 static const WCHAR digit_special[] = {0xb2, 0xb3, 0xb9};
3017 static const WCHAR lower_special[] = {0x2071, 0x207f};
3018 static const WCHAR cntrl_special[] = {0x070f, 0x200c, 0x200d,
3019 0x200e, 0x200f, 0x202a, 0x202b, 0x202c, 0x202d, 0x202e,
3020 0x206a, 0x206b, 0x206c, 0x206d, 0x206e, 0x206f, 0xfeff,
3021 0xfff9, 0xfffa, 0xfffb};
3022 static const WCHAR space_special[] = {0x09, 0x0d, 0x85};
3027 memset(types,0,sizeof(types));
3028 GetStringTypeW(CT_CTYPE1, blanks, 5, types);
3029 for (i = 0; i < 5; i++)
3030 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]);
3032 memset(types,0,sizeof(types));
3033 GetStringTypeW(CT_CTYPE1, alpha, 3, types);
3034 for (i = 0; i < 3; i++)
3035 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]));
3036 memset(types,0,sizeof(types));
3037 GetStringTypeW(CT_CTYPE1, undefined, 5, types);
3038 for (i = 0; i < 5; i++)
3039 ok(types[i] == 0, "incorrect types returned for %x -> (%x != 0)\n",undefined[i], types[i]);
3041 memset(types,0,sizeof(types));
3042 GetStringTypeW(CT_CTYPE1, oldpunc, 8, types);
3043 for (i = 0; i < 8; i++)
3044 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);
3046 memset(types,0,sizeof(types));
3047 GetStringTypeW(CT_CTYPE1, changed, 7, types);
3048 for (i = 0; i < 7; i++)
3049 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]);
3051 memset(types,0,sizeof(types));
3052 GetStringTypeW(CT_CTYPE1, punct, 7, types);
3053 for (i = 0; i < 7; i++)
3054 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));
3057 memset(types,0,sizeof(types));
3058 GetStringTypeW(CT_CTYPE1, punct_special, 12, types);
3059 for (i = 0; i < 12; i++)
3060 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);
3062 memset(types,0,sizeof(types));
3063 GetStringTypeW(CT_CTYPE1, digit_special, 3, types);
3064 for (i = 0; i < 3; i++)
3065 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);
3067 memset(types,0,sizeof(types));
3068 GetStringTypeW(CT_CTYPE1, lower_special, 2, types);
3069 for (i = 0; i < 2; i++)
3070 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);
3072 memset(types,0,sizeof(types));
3073 GetStringTypeW(CT_CTYPE1, cntrl_special, 20, types);
3074 for (i = 0; i < 20; i++)
3075 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);
3077 memset(types,0,sizeof(types));
3078 GetStringTypeW(CT_CTYPE1, space_special, 3, types);
3079 for (i = 0; i < 3; i++)
3080 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 );
3083 static void test_IdnToNameprepUnicode(void)
3089 const WCHAR out[64];
3095 5, {'t','e','s','t',0},
3096 5, {'t','e','s','t',0},
3100 3, {'a',0xe111,'b'},
3102 0, ERROR_INVALID_NAME
3107 0, ERROR_INVALID_NAME
3117 0, ERROR_INVALID_NAME
3120 6, {' ','-','/','[',']',0},
3121 6, {' ','-','/','[',']',0},
3127 IDN_USE_STD3_ASCII_RULES, 0xdeadbeef
3132 IDN_USE_STD3_ASCII_RULES, ERROR_INVALID_NAME
3134 { /* FoldString is not working as expected when MAP_FOLDCZONE is specified (composition+compatibility) */
3135 10, {'T',0xdf,0x130,0x143,0x37a,0x6a,0x30c,' ',0xaa,0},
3136 12, {'t','s','s','i',0x307,0x144,' ',0x3b9,0x1f0,' ','a',0},
3140 11, {'t',0xad,0x34f,0x1806,0x180b,0x180c,0x180d,0x200b,0x200c,0x200d,0},
3144 { /* Another example of incorrectly working FoldString (composition) */
3152 0, ERROR_NO_UNICODE_TRANSLATION
3157 IDN_ALLOW_UNASSIGNED, 0xdeadbeef
3160 5, {'a','.','.','a',0},
3162 0, ERROR_INVALID_NAME
3174 if (!pIdnToNameprepUnicode)
3176 win_skip("IdnToNameprepUnicode is not available\n");
3180 ret = pIdnToNameprepUnicode(0, test_data[0].in,
3181 test_data[0].in_len, NULL, 0);
3182 ok(ret == test_data[0].ret, "ret = %d\n", ret);
3184 SetLastError(0xdeadbeef);
3185 ret = pIdnToNameprepUnicode(0, test_data[1].in,
3186 test_data[1].in_len, NULL, 0);
3187 err = GetLastError();
3188 ok(ret == test_data[1].ret, "ret = %d\n", ret);
3189 ok(err == test_data[1].err, "err = %d\n", err);
3191 SetLastError(0xdeadbeef);
3192 ret = pIdnToNameprepUnicode(0, test_data[0].in, -1,
3193 buf, sizeof(buf)/sizeof(WCHAR));
3194 err = GetLastError();
3195 ok(ret == test_data[0].ret, "ret = %d\n", ret);
3196 ok(err == 0xdeadbeef, "err = %d\n", err);
3198 SetLastError(0xdeadbeef);
3199 ret = pIdnToNameprepUnicode(0, test_data[0].in, -2,
3200 buf, sizeof(buf)/sizeof(WCHAR));
3201 err = GetLastError();
3202 ok(ret == 0, "ret = %d\n", ret);
3203 ok(err == ERROR_INVALID_PARAMETER, "err = %d\n", err);
3205 SetLastError(0xdeadbeef);
3206 ret = pIdnToNameprepUnicode(0, test_data[0].in, 0,
3207 buf, sizeof(buf)/sizeof(WCHAR));
3208 err = GetLastError();
3209 ok(ret == 0, "ret = %d\n", ret);
3210 ok(err == ERROR_INVALID_NAME, "err = %d\n", err);
3212 ret = pIdnToNameprepUnicode(IDN_ALLOW_UNASSIGNED|IDN_USE_STD3_ASCII_RULES,
3213 test_data[0].in, -1, buf, sizeof(buf)/sizeof(WCHAR));
3214 ok(ret == test_data[0].ret, "ret = %d\n", ret);
3216 SetLastError(0xdeadbeef);
3217 ret = pIdnToNameprepUnicode(0, NULL, 0, NULL, 0);
3218 err = GetLastError();
3219 ok(ret == 0, "ret = %d\n", ret);
3220 ok(err == ERROR_INVALID_PARAMETER, "err = %d\n", err);
3222 SetLastError(0xdeadbeef);
3223 ret = pIdnToNameprepUnicode(4, NULL, 0, NULL, 0);
3224 err = GetLastError();
3225 ok(ret == 0, "ret = %d\n", ret);
3226 ok(err == ERROR_INVALID_FLAGS, "err = %d\n", err);
3228 for (i=0; i<sizeof(test_data)/sizeof(*test_data); i++)
3230 SetLastError(0xdeadbeef);
3231 ret = pIdnToNameprepUnicode(test_data[i].flags, test_data[i].in,
3232 test_data[i].in_len, buf, sizeof(buf)/sizeof(WCHAR));
3233 err = GetLastError();
3234 if(!test_data[i].todo) {
3235 ok(ret == test_data[i].ret, "%d) ret = %d\n", i, ret);
3236 ok(err == test_data[i].err, "%d) err = %d\n", i, err);
3237 ok(!memcmp(test_data[i].out, buf, ret*sizeof(WCHAR)),
3238 "%d) buf = %s\n", i, wine_dbgstr_wn(buf, ret));
3240 todo_wine ok(!memcmp(test_data[i].out, buf, ret*sizeof(WCHAR)),
3241 "%d) buf = %s\n", i, wine_dbgstr_wn(buf, ret));
3246 static void test_IdnToAscii(void)
3252 const WCHAR out[64];
3257 5, {'T','e','s','t',0},
3258 5, {'T','e','s','t',0},
3262 5, {'T','e',0x017c,'s','t',0},
3263 12, {'x','n','-','-','t','e','s','t','-','c','b','b',0},
3267 12, {'t','e',0x0105,'s','t','.','t','e',0x017c,'s','t',0},
3268 26, {'x','n','-','-','t','e','s','t','-','c','t','a','.','x','n','-','-','t','e','s','t','-','c','b','b',0},
3273 9, {'x','n','-','-','2','d','a','.',0},
3277 10, {'h','t','t','p',':','/','/','t',0x0106,0},
3278 17, {'x','n','-','-','h','t','t','p',':','/','/','t','-','7','8','a',0},
3282 10, {0x4e3a,0x8bf4,0x4e0d,0x4ed6,0x5011,0x10d,0x11b,0x305c,0x306a,0},
3283 35, {'x','n','-','-','b','e','a','2','a','1','6','3','1','a','v','b','a',
3284 'v','4','4','t','y','h','a','3','2','b','9','1','e','g','s','2','t',0},
3289 8, {'x','n','-','-','6','l','a',0},
3290 IDN_ALLOW_UNASSIGNED, 0xdeadbeef
3299 win_skip("IdnToAscii is not available\n");
3303 for (i=0; i<sizeof(test_data)/sizeof(*test_data); i++)
3305 SetLastError(0xdeadbeef);
3306 ret = pIdnToAscii(test_data[i].flags, test_data[i].in,
3307 test_data[i].in_len, buf, sizeof(buf));
3308 err = GetLastError();
3309 ok(ret == test_data[i].ret, "%d) ret = %d\n", i, ret);
3310 ok(err == test_data[i].err, "%d) err = %d\n", i, err);
3311 ok(!memcmp(test_data[i].out, buf, ret*sizeof(WCHAR)),
3312 "%d) buf = %s\n", i, wine_dbgstr_wn(buf, ret));
3316 static void test_IdnToUnicode(void)
3322 const WCHAR out[64];
3327 5, {'T','e','s','.',0},
3328 5, {'T','e','s','.',0},
3334 0, ERROR_INVALID_NAME
3337 33, {'x','n','-','-','4','d','b','c','a','g','d','a','h','y','m','b',
3338 'x','e','k','h','e','h','6','e','0','a','7','f','e','i','0','b',0},
3339 23, {0x05dc,0x05de,0x05d4,0x05d4,0x05dd,0x05e4,0x05e9,0x05d5,0x05d8,
3340 0x05dc,0x05d0,0x05de,0x05d3,0x05d1,0x05e8,0x05d9,0x05dd,0x05e2,
3341 0x05d1,0x05e8,0x05d9,0x05ea,0},
3345 34, {'t','e','s','t','.','x','n','-','-','k','d','a','9','a','g','5','e',
3346 '9','j','n','f','s','j','.','x','n','-','-','p','d','-','f','n','a'},
3347 16, {'t','e','s','t','.',0x0105,0x0119,0x015b,0x0107,
3348 0x0142,0x00f3,0x017c,'.','p',0x0119,'d'},
3352 64, {'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
3353 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
3354 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
3355 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a'},
3357 0, ERROR_INVALID_NAME
3360 8, {'x','n','-','-','6','l','a',0},
3362 IDN_ALLOW_UNASSIGNED, 0xdeadbeef
3371 win_skip("IdnToUnicode is not available\n");
3375 for (i=0; i<sizeof(test_data)/sizeof(*test_data); i++)
3377 SetLastError(0xdeadbeef);
3378 ret = pIdnToUnicode(test_data[i].flags, test_data[i].in,
3379 test_data[i].in_len, buf, sizeof(buf));
3380 err = GetLastError();
3381 ok(ret == test_data[i].ret, "%d) ret = %d\n", i, ret);
3382 ok(err == test_data[i].err, "%d) err = %d\n", i, err);
3383 ok(!memcmp(test_data[i].out, buf, ret*sizeof(WCHAR)),
3384 "%d) buf = %s\n", i, wine_dbgstr_wn(buf, ret));
3388 static void test_GetLocaleInfoEx(void)
3390 static const WCHAR enW[] = {'e','n',0};
3394 if (!pGetLocaleInfoEx)
3396 win_skip("GetLocaleInfoEx not supported\n");
3400 ret = pGetLocaleInfoEx(enW, LOCALE_SNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3401 ok(ret || broken(ret == 0) /* Vista */, "got %d\n", ret);
3404 static const WCHAR statesW[] = {'U','n','i','t','e','d',' ','S','t','a','t','e','s',0};
3405 static const WCHAR dummyW[] = {'d','u','m','m','y',0};
3406 static const WCHAR enusW[] = {'e','n','-','U','S',0};
3407 static const WCHAR usaW[] = {'U','S','A',0};
3408 static const WCHAR enuW[] = {'E','N','U',0};
3409 const struct neutralsublang_name_t *ptr = neutralsublang_names;
3412 ok(ret == lstrlenW(bufferW)+1, "got %d\n", ret);
3413 ok(!lstrcmpW(bufferW, enW), "got %s\n", wine_dbgstr_w(bufferW));
3415 SetLastError(0xdeadbeef);
3416 ret = pGetLocaleInfoEx(enW, LOCALE_SNAME, bufferW, 2);
3417 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d, %d\n", ret, GetLastError());
3419 SetLastError(0xdeadbeef);
3420 ret = pGetLocaleInfoEx(enW, LOCALE_SNAME, NULL, 0);
3421 ok(ret == 3 && GetLastError() == 0xdeadbeef, "got %d, %d\n", ret, GetLastError());
3423 ret = pGetLocaleInfoEx(enusW, LOCALE_SNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3424 ok(ret == lstrlenW(bufferW)+1, "got %d\n", ret);
3425 ok(!lstrcmpW(bufferW, enusW), "got %s\n", wine_dbgstr_w(bufferW));
3427 ret = pGetLocaleInfoEx(enW, LOCALE_SABBREVCTRYNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3428 ok(ret == lstrlenW(bufferW)+1, "got %d\n", ret);
3429 ok(!lstrcmpW(bufferW, usaW), "got %s\n", wine_dbgstr_w(bufferW));
3431 ret = pGetLocaleInfoEx(enW, LOCALE_SABBREVLANGNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3432 ok(ret == lstrlenW(bufferW)+1, "got %d\n", ret);
3433 ok(!lstrcmpW(bufferW, enuW), "got %s\n", wine_dbgstr_w(bufferW));
3435 ret = pGetLocaleInfoEx(enW, LOCALE_SCOUNTRY, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3436 ok(ret == lstrlenW(bufferW)+1, "got %d\n", ret);
3437 ok(!lstrcmpW(bufferW, statesW), "got %s\n", wine_dbgstr_w(bufferW));
3440 SetLastError(0xdeadbeef);
3441 ret = pGetLocaleInfoEx(dummyW, LOCALE_SNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3442 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError());
3447 pGetLocaleInfoEx(ptr->name, LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER, (WCHAR*)&val, sizeof(val)/sizeof(WCHAR));
3450 ok(val == ptr->lcid, "%s: got wrong lcid 0x%04x, expected 0x%04x\n", wine_dbgstr_w(ptr->name), val, ptr->lcid);
3452 ok(val == ptr->lcid, "%s: got wrong lcid 0x%04x, expected 0x%04x\n", wine_dbgstr_w(ptr->name), val, ptr->lcid);
3454 ret = pGetLocaleInfoEx(ptr->name, LOCALE_SNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3455 ok(ret == lstrlenW(bufferW)+1, "%s: got ret value %d\n", wine_dbgstr_w(ptr->name), ret);
3456 ok(!lstrcmpW(bufferW, ptr->name), "%s: got wrong LOCALE_SNAME %s\n", wine_dbgstr_w(ptr->name), wine_dbgstr_w(bufferW));
3462 static void test_IsValidLocaleName(void)
3464 static const WCHAR enusW[] = {'e','n','-','U','S',0};
3465 static const WCHAR zzW[] = {'z','z',0};
3466 static const WCHAR zzzzW[] = {'z','z','-','Z','Z',0};
3469 if (!pIsValidLocaleName)
3471 win_skip("IsValidLocaleName not supported\n");
3475 ret = pIsValidLocaleName(enusW);
3476 ok(ret, "IsValidLocaleName failed\n");
3477 ret = pIsValidLocaleName(zzW);
3478 ok(!ret, "IsValidLocaleName should have failed\n");
3479 ret = pIsValidLocaleName(zzzzW);
3480 ok(!ret, "IsValidLocaleName should have failed\n");
3483 static void test_CompareStringOrdinal(void)
3486 WCHAR test1[] = { 't','e','s','t',0 };
3487 WCHAR test2[] = { 'T','e','S','t',0 };
3488 WCHAR test3[] = { 't','e','s','t','3',0 };
3489 WCHAR null1[] = { 'a',0,'a',0 };
3490 WCHAR null2[] = { 'a',0,'b',0 };
3491 WCHAR bills1[] = { 'b','i','l','l','\'','s',0 };
3492 WCHAR bills2[] = { 'b','i','l','l','s',0 };
3493 WCHAR coop1[] = { 'c','o','-','o','p',0 };
3494 WCHAR coop2[] = { 'c','o','o','p',0 };
3495 WCHAR nonascii1[] = { 0x0102,0 };
3496 WCHAR nonascii2[] = { 0x0201,0 };
3498 if (!pCompareStringOrdinal)
3500 win_skip("CompareStringOrdinal not supported\n");
3505 SetLastError(0xdeadbeef);
3506 ret = pCompareStringOrdinal(NULL, 0, NULL, 0, FALSE);
3507 ok(!ret, "Got %u, expected 0\n", ret);
3508 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got %x, expected %x\n", GetLastError(), ERROR_INVALID_PARAMETER);
3509 SetLastError(0xdeadbeef);
3510 ret = pCompareStringOrdinal(test1, -1, NULL, 0, FALSE);
3511 ok(!ret, "Got %u, expected 0\n", ret);
3512 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got %x, expected %x\n", GetLastError(), ERROR_INVALID_PARAMETER);
3513 SetLastError(0xdeadbeef);
3514 ret = pCompareStringOrdinal(NULL, 0, test1, -1, FALSE);
3515 ok(!ret, "Got %u, expected 0\n", ret);
3516 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got %x, expected %x\n", GetLastError(), ERROR_INVALID_PARAMETER);
3519 ret = pCompareStringOrdinal(test1, -1, test1, -1, FALSE);
3520 ok(ret == CSTR_EQUAL, "Got %u, expected %u\n", ret, CSTR_EQUAL);
3521 ret = pCompareStringOrdinal(test1, -1, test2, -1, FALSE);
3522 ok(ret == CSTR_GREATER_THAN, "Got %u, expected %u\n", ret, CSTR_GREATER_THAN);
3523 ret = pCompareStringOrdinal(test2, -1, test1, -1, FALSE);
3524 ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
3525 ret = pCompareStringOrdinal(test1, -1, test2, -1, TRUE);
3526 ok(ret == CSTR_EQUAL, "Got %u, expected %u\n", ret, CSTR_EQUAL);
3528 /* Check different sizes */
3529 ret = pCompareStringOrdinal(test1, 3, test2, -1, TRUE);
3530 ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
3531 ret = pCompareStringOrdinal(test1, -1, test2, 3, TRUE);
3532 ok(ret == CSTR_GREATER_THAN, "Got %u, expected %u\n", ret, CSTR_GREATER_THAN);
3534 /* Check null character */
3535 ret = pCompareStringOrdinal(null1, 3, null2, 3, FALSE);
3536 ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
3537 ret = pCompareStringOrdinal(null1, 3, null2, 3, TRUE);
3538 ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
3539 ret = pCompareStringOrdinal(test1, 5, test3, 5, FALSE);
3540 ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
3541 ret = pCompareStringOrdinal(test1, 4, test1, 5, FALSE);
3542 ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
3544 /* Check ordinal behaviour */
3545 ret = pCompareStringOrdinal(bills1, -1, bills2, -1, FALSE);
3546 ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
3547 ret = pCompareStringOrdinal(coop2, -1, coop1, -1, FALSE);
3548 ok(ret == CSTR_GREATER_THAN, "Got %u, expected %u\n", ret, CSTR_GREATER_THAN);
3549 ret = pCompareStringOrdinal(nonascii1, -1, nonascii2, -1, FALSE);
3550 ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
3551 ret = pCompareStringOrdinal(nonascii1, -1, nonascii2, -1, TRUE);
3552 ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
3557 InitFunctionPointers();
3559 test_EnumTimeFormatsA();
3560 test_EnumDateFormatsA();
3561 test_GetLocaleInfoA();
3562 test_GetLocaleInfoW();
3563 test_GetLocaleInfoEx();
3564 test_GetTimeFormatA();
3565 test_GetDateFormatA();
3566 test_GetDateFormatW();
3567 test_GetCurrencyFormatA(); /* Also tests the W version */
3568 test_GetNumberFormatA(); /* Also tests the W version */
3569 test_CompareStringA();
3570 test_LCMapStringA();
3571 test_LCMapStringW();
3572 test_LCMapStringEx();
3573 test_LocaleNameToLCID();
3576 test_ConvertDefaultLocale();
3577 test_EnumSystemLanguageGroupsA();
3578 test_EnumSystemLocalesEx();
3579 test_EnumLanguageGroupLocalesA();
3580 test_SetLocaleInfoA();
3581 test_EnumUILanguageA();
3583 test_GetStringTypeW();
3584 test_IdnToNameprepUnicode();
3586 test_IdnToUnicode();
3587 test_IsValidLocaleName();
3588 test_CompareStringOrdinal();
3589 /* this requires collation table patch to make it MS compatible */
3590 if (0) test_sorting();