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.
32 #include "wine/test.h"
38 static inline unsigned int strlenW( const WCHAR *str )
45 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
48 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
52 static inline WCHAR *strchrW( const WCHAR *str, WCHAR ch )
54 do { if (*str == ch) return (WCHAR *)str; } while (*str++);
58 static inline int isdigitW( WCHAR wc )
61 GetStringTypeW( CT_CTYPE1, &wc, 1, &type );
62 return type & C1_DIGIT;
65 /* Some functions are only in later versions of kernel32.dll */
66 static HMODULE hKernel32;
67 static WORD enumCount;
69 typedef BOOL (WINAPI *EnumSystemLanguageGroupsAFn)(LANGUAGEGROUP_ENUMPROC,
71 static EnumSystemLanguageGroupsAFn pEnumSystemLanguageGroupsA;
72 typedef BOOL (WINAPI *EnumLanguageGroupLocalesAFn)(LANGGROUPLOCALE_ENUMPROC,
73 LGRPID, DWORD, LONG_PTR);
74 static EnumLanguageGroupLocalesAFn pEnumLanguageGroupLocalesA;
75 typedef BOOL (WINAPI *EnumUILanguagesAFn)(UILANGUAGE_ENUMPROC,
77 static EnumUILanguagesAFn pEnumUILanguagesA;
79 typedef INT (WINAPI *FoldStringAFn)(DWORD, LPCSTR, INT, LPSTR, INT);
80 static FoldStringAFn pFoldStringA;
81 typedef INT (WINAPI *FoldStringWFn)(DWORD, LPCWSTR, INT, LPWSTR, INT);
82 static FoldStringWFn pFoldStringW;
84 typedef BOOL (WINAPI *IsValidLanguageGroupFn)(LGRPID, DWORD);
85 static IsValidLanguageGroupFn pIsValidLanguageGroup;
87 static void InitFunctionPointers(void)
89 hKernel32 = GetModuleHandleA("kernel32");
90 pEnumSystemLanguageGroupsA = (void*)GetProcAddress(hKernel32, "EnumSystemLanguageGroupsA");
91 pEnumLanguageGroupLocalesA = (void*)GetProcAddress(hKernel32, "EnumLanguageGroupLocalesA");
92 pFoldStringA = (void*)GetProcAddress(hKernel32, "FoldStringA");
93 pFoldStringW = (void*)GetProcAddress(hKernel32, "FoldStringW");
94 pIsValidLanguageGroup = (void*)GetProcAddress(hKernel32, "IsValidLanguageGroup");
95 pEnumUILanguagesA = (void*)GetProcAddress(hKernel32, "EnumUILanguagesA");
98 #define eq(received, expected, label, type) \
99 ok((received) == (expected), "%s: got " type " instead of " type "\n", \
100 (label), (received), (expected))
102 #define BUFFER_SIZE 128
103 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
105 #define STRINGSA(x,y) strcpy(input, x); strcpy(Expected, y); SetLastError(0xdeadbeef); buffer[0] = '\0'
106 #define EXPECT_LENA ok(ret == lstrlen(Expected)+1, "Expected Len %d, got %d\n", lstrlen(Expected)+1, ret)
107 #define EXPECT_EQA ok(strncmp(buffer, Expected, strlen(Expected)) == 0, \
108 "Expected '%s', got '%s'\n", Expected, buffer)
110 #define STRINGSW(x,y) MultiByteToWideChar(CP_ACP,0,x,-1,input,COUNTOF(input)); \
111 MultiByteToWideChar(CP_ACP,0,y,-1,Expected,COUNTOF(Expected)); \
112 SetLastError(0xdeadbeef); buffer[0] = '\0'
113 #define EXPECT_LENW ok(ret == lstrlenW(Expected)+1, "Expected Len %d, got %d\n", lstrlenW(Expected)+1, ret)
114 #define EXPECT_EQW ok(strncmpW(buffer, Expected, strlenW(Expected)) == 0, "Bad conversion\n")
116 #define NUO LOCALE_NOUSEROVERRIDE
118 static void test_GetLocaleInfoA(void)
122 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
123 char buffer[BUFFER_SIZE];
124 char expected[BUFFER_SIZE];
126 ok(lcid == 0x409, "wrong LCID calculated - %d\n", lcid);
128 /* en and ar use SUBLANG_NEUTRAL, but GetLocaleInfo assume SUBLANG_DEFAULT
129 Same is true for zh on pre-Vista, but on Vista and higher GetLocaleInfo
130 assumes SUBLANG_NEUTRAL for zh */
131 memset(expected, 0, COUNTOF(expected));
132 len = GetLocaleInfoA(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
133 SetLastError(0xdeadbeef);
134 memset(buffer, 0, COUNTOF(buffer));
135 ret = GetLocaleInfoA(LANG_ENGLISH, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
136 ok((ret == len) && !lstrcmpA(buffer, expected),
137 "got %d with '%s' (expected %d with '%s')\n",
138 ret, buffer, len, expected);
140 memset(expected, 0, COUNTOF(expected));
141 len = GetLocaleInfoA(MAKELANGID(LANG_ARABIC, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
143 SetLastError(0xdeadbeef);
144 memset(buffer, 0, COUNTOF(buffer));
145 ret = GetLocaleInfoA(LANG_ARABIC, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
146 ok((ret == len) && !lstrcmpA(buffer, expected),
147 "got %d with '%s' (expected %d with '%s')\n",
148 ret, buffer, len, expected);
151 win_skip("LANG_ARABIC not installed\n");
153 /* SUBLANG_DEFAULT is required for mlang.dll, but optional for GetLocaleInfo */
154 memset(expected, 0, COUNTOF(expected));
155 len = GetLocaleInfoA(MAKELANGID(LANG_GERMAN, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
156 SetLastError(0xdeadbeef);
157 memset(buffer, 0, COUNTOF(buffer));
158 ret = GetLocaleInfoA(LANG_GERMAN, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
159 ok((ret == len) && !lstrcmpA(buffer, expected),
160 "got %d with '%s' (expected %d with '%s')\n",
161 ret, buffer, len, expected);
164 /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
165 * partially fill the buffer even if it is too short. See bug 637.
167 SetLastError(0xdeadbeef);
168 memset(buffer, 0, COUNTOF(buffer));
169 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 0);
170 ok(ret == 7 && !buffer[0], "Expected len=7, got %d\n", ret);
172 SetLastError(0xdeadbeef);
173 memset(buffer, 0, COUNTOF(buffer));
174 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 3);
175 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
176 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
177 ok(!strcmp(buffer, "Mon"), "Expected 'Mon', got '%s'\n", buffer);
179 SetLastError(0xdeadbeef);
180 memset(buffer, 0, COUNTOF(buffer));
181 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 10);
182 ok(ret == 7, "Expected ret == 7, got %d, error %d\n", ret, GetLastError());
183 ok(!strcmp(buffer, "Monday"), "Expected 'Monday', got '%s'\n", buffer);
186 static void test_GetLocaleInfoW(void)
188 LCID lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
189 LCID lcid_ru = MAKELCID(MAKELANGID(LANG_RUSSIAN, SUBLANG_NEUTRAL), SORT_DEFAULT);
190 WCHAR bufferW[80], buffer2W[80];
195 ret = GetLocaleInfoW(lcid_en, LOCALE_SMONTHNAME1, bufferW, COUNTOF(bufferW));
197 win_skip("GetLocaleInfoW() isn't implemented\n");
200 ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1, bufferW, COUNTOF(bufferW));
202 win_skip("LANG_RUSSIAN locale data unavailable\n");
205 ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1|LOCALE_RETURN_GENITIVE_NAMES,
206 bufferW, COUNTOF(bufferW));
208 win_skip("LOCALE_RETURN_GENITIVE_NAMES isn't supported\n");
212 /* LOCALE_RETURN_GENITIVE_NAMES isn't supported for GetLocaleInfoA */
214 SetLastError(0xdeadbeef);
215 ret = GetLocaleInfoA(lcid_ru, LOCALE_SMONTHNAME1|LOCALE_RETURN_GENITIVE_NAMES,
216 bufferA, COUNTOF(bufferA));
217 ok(ret == 0, "LOCALE_RETURN_GENITIVE_NAMES should fail with GetLocaleInfoA\n");
218 ok(bufferA[0] == 'a', "Expected buffer to be untouched\n");
219 ok(GetLastError() == ERROR_INVALID_FLAGS,
220 "Expected ERROR_INVALID_FLAGS, got %x\n", GetLastError());
223 SetLastError(0xdeadbeef);
224 ret = GetLocaleInfoW(lcid_ru, LOCALE_RETURN_GENITIVE_NAMES,
225 bufferW, COUNTOF(bufferW));
227 "LOCALE_RETURN_GENITIVE_NAMES itself doesn't return anything, got %d\n", ret);
228 ok(bufferW[0] == 'a', "Expected buffer to be untouched\n");
229 ok(GetLastError() == ERROR_INVALID_FLAGS,
230 "Expected ERROR_INVALID_FLAGS, got %x\n", GetLastError());
232 /* yes, test empty 13 month entry too */
233 for (i = 0; i < 12; i++) {
235 ret = GetLocaleInfoW(lcid_ru, (LOCALE_SMONTHNAME1+i)|LOCALE_RETURN_GENITIVE_NAMES,
236 bufferW, COUNTOF(bufferW));
237 ok(ret, "Expected non zero result\n");
238 ok(ret == lstrlenW(bufferW)+1, "Expected actual length, got %d, length %d\n",
239 ret, lstrlenW(bufferW));
241 ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1+i,
242 buffer2W, COUNTOF(buffer2W));
243 ok(ret, "Expected non zero result\n");
244 ok(ret == lstrlenW(buffer2W)+1, "Expected actual length, got %d, length %d\n",
245 ret, lstrlenW(buffer2W));
247 ok(lstrcmpW(bufferW, buffer2W) != 0,
248 "Expected genitive name to differ, got the same for month %d\n", i+1);
250 /* for locale without genitive names nominative returned in both cases */
252 ret = GetLocaleInfoW(lcid_en, (LOCALE_SMONTHNAME1+i)|LOCALE_RETURN_GENITIVE_NAMES,
253 bufferW, COUNTOF(bufferW));
254 ok(ret, "Expected non zero result\n");
255 ok(ret == lstrlenW(bufferW)+1, "Expected actual length, got %d, length %d\n",
256 ret, lstrlenW(bufferW));
258 ret = GetLocaleInfoW(lcid_en, LOCALE_SMONTHNAME1+i,
259 buffer2W, COUNTOF(buffer2W));
260 ok(ret, "Expected non zero result\n");
261 ok(ret == lstrlenW(buffer2W)+1, "Expected actual length, got %d, length %d\n",
262 ret, lstrlenW(buffer2W));
264 ok(lstrcmpW(bufferW, buffer2W) == 0,
265 "Expected same names, got different for month %d\n", i+1);
269 static void test_GetTimeFormatA(void)
273 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
274 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
276 memset(&curtime, 2, sizeof(SYSTEMTIME));
277 STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
278 SetLastError(0xdeadbeef);
279 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
280 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
281 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
284 curtime.wMinute = 56;
285 curtime.wSecond = 13;
286 curtime.wMilliseconds = 22;
287 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
288 SetLastError(0xdeadbeef);
289 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
290 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
291 EXPECT_LENA; EXPECT_EQA;
293 /* MSDN: LOCALE_NOUSEROVERRIDE can't be specified with a format string */
294 SetLastError(0xdeadbeef);
295 ret = GetTimeFormatA(lcid, NUO|TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
296 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
297 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
299 STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficient buffer */
300 SetLastError(0xdeadbeef);
301 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, 2);
302 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
303 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
305 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
306 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, NULL, 0);
307 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
310 STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
311 ret = GetTimeFormatA(lcid, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
312 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
313 EXPECT_LENA; EXPECT_EQA;
315 STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
316 ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
317 ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
318 ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "4" )), /* win9x */
319 "Expected '', got '%s'\n", buffer );
321 STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
322 ret = GetTimeFormatA(lcid, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
323 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
324 EXPECT_LENA; EXPECT_EQA;
326 STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
327 strcpy(Expected, "8:56 AM");
328 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
329 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
330 EXPECT_LENA; EXPECT_EQA;
332 STRINGSA("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
333 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
334 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
335 ok( !strcmp( buffer, "8.@:56AM" ) || broken( !strcmp( buffer, "8.@:56.@:AM" )) /* win9x */,
336 "Expected '8.@:56AM', got '%s'\n", buffer );
338 STRINGSA("s1s2s3", ""); /* Duplicate tokens */
339 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
340 ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
341 ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "3" )), /* win9x */
342 "Expected '', got '%s'\n", buffer );
344 STRINGSA("t/tt", "A/AM"); /* AM time marker */
345 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
346 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
347 EXPECT_LENA; EXPECT_EQA;
350 STRINGSA("t/tt", "P/PM"); /* PM time marker */
351 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
352 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
353 EXPECT_LENA; EXPECT_EQA;
355 STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
356 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
357 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
358 EXPECT_LENA; EXPECT_EQA;
360 STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
361 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
362 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
363 EXPECT_LENA; EXPECT_EQA;
365 STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
366 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
367 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
368 EXPECT_LENA; EXPECT_EQA;
370 curtime.wHour = 14; /* change this to 14 or 2pm */
373 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 */
374 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
375 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
376 EXPECT_LENA; EXPECT_EQA;
379 STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
380 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
381 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
382 EXPECT_LENA; EXPECT_EQA;
384 STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
385 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
386 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
387 EXPECT_LENA; EXPECT_EQA;
389 /* try to convert formatting strings with more than two letters
390 * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
391 * NOTE: We expect any letter for which there is an upper case value
392 * we should see a replacement. For letters that DO NOT have
393 * upper case values we should see NO REPLACEMENT.
396 curtime.wMinute = 56;
397 curtime.wSecond = 13;
398 curtime.wMilliseconds = 22;
399 STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
400 "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
401 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
402 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
403 EXPECT_LENA; EXPECT_EQA;
405 STRINGSA("h", "text"); /* Don't write to buffer if len is 0 */
406 strcpy(buffer, "text");
407 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, 0);
408 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
411 STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
412 "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
413 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
414 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
415 EXPECT_LENA; EXPECT_EQA;
417 STRINGSA("'''", "'"); /* invalid quoted string */
418 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
419 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
420 EXPECT_LENA; EXPECT_EQA;
422 /* test that msdn suggested single quotation usage works as expected */
423 STRINGSA("''''", "'"); /* single quote mark */
424 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
425 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
426 EXPECT_LENA; EXPECT_EQA;
428 STRINGSA("''HHHHHH", "08"); /* Normal use */
429 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
430 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
431 EXPECT_LENA; EXPECT_EQA;
433 /* and test for normal use of the single quotation mark */
434 STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
435 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
436 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
437 EXPECT_LENA; EXPECT_EQA;
439 STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
440 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
441 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
442 EXPECT_LENA; EXPECT_EQA;
444 STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
445 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
446 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
447 EXPECT_LENA; EXPECT_EQA;
450 STRINGSA("'123'tt", ""); /* Invalid time */
451 SetLastError(0xdeadbeef);
452 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
453 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
454 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
457 curtime.wMonth = 60; /* Invalid */
458 STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
459 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
460 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
461 EXPECT_LENA; EXPECT_EQA;
464 static void test_GetDateFormatA(void)
468 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
469 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
471 memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
472 STRINGSA("ddd',' MMM dd yy","");
473 SetLastError(0xdeadbeef);
474 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
475 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
476 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
478 curtime.wYear = 2002;
481 curtime.wDayOfWeek = 3;
482 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
483 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
484 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
485 EXPECT_LENA; EXPECT_EQA;
487 /* Same as above but with LOCALE_NOUSEROVERRIDE */
488 STRINGSA("ddd',' MMM dd yy",""); /* Simple case */
489 SetLastError(0xdeadbeef);
490 ret = GetDateFormatA(lcid, NUO, &curtime, input, buffer, COUNTOF(buffer));
491 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
492 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
495 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
496 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
497 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
498 EXPECT_LENA; EXPECT_EQA;
500 curtime.wHour = 36; /* Invalid */
501 STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
502 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
503 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
504 EXPECT_LENA; EXPECT_EQA;
506 STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
507 ret = GetDateFormatA(lcid, 0, &curtime, input, NULL, 0);
508 ok(ret == 16, "Expected ret == 16, got %d, error %d\n", ret, GetLastError());
511 STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
512 SetLastError(0xdeadbeef);
513 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, 2);
514 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
515 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
517 STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
518 ret = GetDateFormat(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
519 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
520 if (strncmp(buffer, Expected, strlen(Expected)) && strncmp(buffer, "5/4/02", strlen(Expected)) != 0)
521 ok (0, "Expected '%s' or '5/4/02', got '%s'\n", Expected, buffer);
523 STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
524 ret = GetDateFormat(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
525 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
526 EXPECT_LENA; EXPECT_EQA;
528 /* test for expected DATE_YEARMONTH behavior with null format */
529 /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
530 STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
531 SetLastError(0xdeadbeef);
532 ret = GetDateFormat(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
533 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
534 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
537 /* Test that using invalid DATE_* flags results in the correct error */
538 /* and return values */
539 STRINGSA("m/d/y", ""); /* Invalid flags */
540 SetLastError(0xdeadbeef);
541 ret = GetDateFormat(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
542 &curtime, input, buffer, COUNTOF(buffer));
543 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
544 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
548 static void test_GetDateFormatW(void)
552 WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
553 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
555 STRINGSW("",""); /* If flags is not zero then format must be NULL */
556 ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL,
557 input, buffer, COUNTOF(buffer));
558 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
560 win_skip("GetDateFormatW is not implemented\n");
563 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
564 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
567 STRINGSW("",""); /* NULL buffer, len > 0 */
568 SetLastError(0xdeadbeef);
569 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
570 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
571 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
573 STRINGSW("",""); /* NULL buffer, len == 0 */
574 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
575 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
576 EXPECT_LENW; EXPECT_EQW;
578 curtime.wYear = 2002;
581 curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
582 curtime.wHour = 65432; /* Invalid */
583 curtime.wMinute = 34512; /* Invalid */
584 curtime.wSecond = 65535; /* Invalid */
585 curtime.wMilliseconds = 12345;
586 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
587 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
588 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
589 EXPECT_LENW; EXPECT_EQW;
593 curtime.wYear = 1601;
596 curtime.wDayOfWeek = 0; /* Irrelevant */
600 curtime.wMilliseconds = 0;
601 STRINGSW("dddd d MMMM yyyy","Monday 1 January 1601");
602 SetLastError(0xdeadbeef);
603 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
604 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
605 EXPECT_LENW; EXPECT_EQW;
607 curtime.wYear = 1600;
610 curtime.wDayOfWeek = 0; /* Irrelevant */
612 curtime.wMinute = 59;
613 curtime.wSecond = 59;
614 curtime.wMilliseconds = 999;
615 STRINGSW("dddd d MMMM yyyy","Friday 31 December 1600");
616 SetLastError(0xdeadbeef);
617 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
618 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
619 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
623 #define CY_POS_LEFT 0
624 #define CY_POS_RIGHT 1
625 #define CY_POS_LEFT_SPACE 2
626 #define CY_POS_RIGHT_SPACE 3
628 static void test_GetCurrencyFormatA(void)
630 static char szDot[] = { '.', '\0' };
631 static char szComma[] = { ',', '\0' };
632 static char szDollar[] = { '$', '\0' };
634 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
635 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
638 memset(&format, 0, sizeof(format));
640 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
641 SetLastError(0xdeadbeef);
642 ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
643 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
644 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
646 STRINGSA("23,53",""); /* Invalid character --> Error */
647 SetLastError(0xdeadbeef);
648 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
649 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
650 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
652 STRINGSA("--",""); /* Double '-' --> Error */
653 SetLastError(0xdeadbeef);
654 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
655 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
656 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
658 STRINGSA("0-",""); /* Trailing '-' --> Error */
659 SetLastError(0xdeadbeef);
660 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
661 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
662 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
664 STRINGSA("0..",""); /* Double '.' --> Error */
665 SetLastError(0xdeadbeef);
666 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
667 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
668 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
670 STRINGSA(" 0.1",""); /* Leading space --> Error */
671 SetLastError(0xdeadbeef);
672 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
673 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
674 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
676 STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
677 SetLastError(0xdeadbeef);
678 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, 2);
679 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
680 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
682 STRINGSA("2353",""); /* Format and flags given --> Error */
683 SetLastError(0xdeadbeef);
684 ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
685 ok( !ret, "Expected ret == 0, got %d\n", ret);
686 ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
687 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
689 STRINGSA("2353",""); /* Invalid format --> Error */
690 SetLastError(0xdeadbeef);
691 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
692 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
693 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
695 STRINGSA("2353","$2,353.00"); /* Valid number */
696 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
697 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
698 EXPECT_LENA; EXPECT_EQA;
700 STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
701 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
702 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
703 EXPECT_LENA; EXPECT_EQA;
705 STRINGSA("2353.1","$2,353.10"); /* Valid real number */
706 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
707 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
708 EXPECT_LENA; EXPECT_EQA;
710 STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
711 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
712 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
713 EXPECT_LENA; EXPECT_EQA;
715 STRINGSA("2353.119","$2,353.12"); /* Too many DP --> Rounded */
716 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
717 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
718 EXPECT_LENA; EXPECT_EQA;
720 format.NumDigits = 0; /* No decimal separator */
721 format.LeadingZero = 0;
722 format.Grouping = 0; /* No grouping char */
723 format.NegativeOrder = 0;
724 format.PositiveOrder = CY_POS_LEFT;
725 format.lpDecimalSep = szDot;
726 format.lpThousandSep = szComma;
727 format.lpCurrencySymbol = szDollar;
729 STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
730 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
731 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
732 EXPECT_LENA; EXPECT_EQA;
734 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
735 STRINGSA("2353","$2353.0");
736 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
737 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
738 EXPECT_LENA; EXPECT_EQA;
740 format.Grouping = 2; /* Group by 100's */
741 STRINGSA("2353","$23,53.0");
742 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
743 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
744 EXPECT_LENA; EXPECT_EQA;
746 STRINGSA("235","$235.0"); /* Grouping of a positive number */
748 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
749 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
750 EXPECT_LENA; EXPECT_EQA;
752 STRINGSA("-235","$-235.0"); /* Grouping of a negative number */
753 format.NegativeOrder = 2;
754 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
755 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
756 EXPECT_LENA; EXPECT_EQA;
758 format.LeadingZero = 1; /* Always provide leading zero */
759 STRINGSA(".5","$0.5");
760 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
761 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
762 EXPECT_LENA; EXPECT_EQA;
764 format.PositiveOrder = CY_POS_RIGHT;
765 STRINGSA("1","1.0$");
766 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
767 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
768 EXPECT_LENA; EXPECT_EQA;
770 format.PositiveOrder = CY_POS_LEFT_SPACE;
771 STRINGSA("1","$ 1.0");
772 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
773 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
774 EXPECT_LENA; EXPECT_EQA;
776 format.PositiveOrder = CY_POS_RIGHT_SPACE;
777 STRINGSA("1","1.0 $");
778 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
779 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
780 EXPECT_LENA; EXPECT_EQA;
782 format.NegativeOrder = 0;
783 STRINGSA("-1","($1.0)");
784 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
785 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
786 EXPECT_LENA; EXPECT_EQA;
788 format.NegativeOrder = 1;
789 STRINGSA("-1","-$1.0");
790 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
791 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
792 EXPECT_LENA; EXPECT_EQA;
794 format.NegativeOrder = 2;
795 STRINGSA("-1","$-1.0");
796 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
797 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
798 EXPECT_LENA; EXPECT_EQA;
800 format.NegativeOrder = 3;
801 STRINGSA("-1","$1.0-");
802 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
803 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
804 EXPECT_LENA; EXPECT_EQA;
806 format.NegativeOrder = 4;
807 STRINGSA("-1","(1.0$)");
808 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
809 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
810 EXPECT_LENA; EXPECT_EQA;
812 format.NegativeOrder = 5;
813 STRINGSA("-1","-1.0$");
814 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
815 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
816 EXPECT_LENA; EXPECT_EQA;
818 format.NegativeOrder = 6;
819 STRINGSA("-1","1.0-$");
820 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
821 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
822 EXPECT_LENA; EXPECT_EQA;
824 format.NegativeOrder = 7;
825 STRINGSA("-1","1.0$-");
826 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
827 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
828 EXPECT_LENA; EXPECT_EQA;
830 format.NegativeOrder = 8;
831 STRINGSA("-1","-1.0 $");
832 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
833 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
834 EXPECT_LENA; EXPECT_EQA;
836 format.NegativeOrder = 9;
837 STRINGSA("-1","-$ 1.0");
838 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
839 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
840 EXPECT_LENA; EXPECT_EQA;
842 format.NegativeOrder = 10;
843 STRINGSA("-1","1.0 $-");
844 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
845 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
846 EXPECT_LENA; EXPECT_EQA;
848 format.NegativeOrder = 11;
849 STRINGSA("-1","$ 1.0-");
850 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
851 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
852 EXPECT_LENA; EXPECT_EQA;
854 format.NegativeOrder = 12;
855 STRINGSA("-1","$ -1.0");
856 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
857 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
858 EXPECT_LENA; EXPECT_EQA;
860 format.NegativeOrder = 13;
861 STRINGSA("-1","1.0- $");
862 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
863 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
864 EXPECT_LENA; EXPECT_EQA;
866 format.NegativeOrder = 14;
867 STRINGSA("-1","($ 1.0)");
868 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
869 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
870 EXPECT_LENA; EXPECT_EQA;
872 format.NegativeOrder = 15;
873 STRINGSA("-1","(1.0 $)");
874 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
875 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
876 EXPECT_LENA; EXPECT_EQA;
879 #define NEG_PARENS 0 /* "(1.1)" */
880 #define NEG_LEFT 1 /* "-1.1" */
881 #define NEG_LEFT_SPACE 2 /* "- 1.1" */
882 #define NEG_RIGHT 3 /* "1.1-" */
883 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
885 static void test_GetNumberFormatA(void)
887 static char szDot[] = { '.', '\0' };
888 static char szComma[] = { ',', '\0' };
890 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
891 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
894 memset(&format, 0, sizeof(format));
896 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
897 SetLastError(0xdeadbeef);
898 ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
899 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
900 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
902 STRINGSA("23,53",""); /* Invalid character --> Error */
903 SetLastError(0xdeadbeef);
904 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
905 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
906 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
908 STRINGSA("--",""); /* Double '-' --> Error */
909 SetLastError(0xdeadbeef);
910 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
911 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
912 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
914 STRINGSA("0-",""); /* Trailing '-' --> Error */
915 SetLastError(0xdeadbeef);
916 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
917 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
918 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
920 STRINGSA("0..",""); /* Double '.' --> Error */
921 SetLastError(0xdeadbeef);
922 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
923 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
924 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
926 STRINGSA(" 0.1",""); /* Leading space --> Error */
927 SetLastError(0xdeadbeef);
928 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
929 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
930 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
932 STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
933 SetLastError(0xdeadbeef);
934 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, 2);
935 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
936 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
938 STRINGSA("2353",""); /* Format and flags given --> Error */
939 SetLastError(0xdeadbeef);
940 ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
941 ok( !ret, "Expected ret == 0, got %d\n", ret);
942 ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
943 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
945 STRINGSA("2353",""); /* Invalid format --> Error */
946 SetLastError(0xdeadbeef);
947 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
948 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
949 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
951 STRINGSA("2353","2,353.00"); /* Valid number */
952 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
953 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
954 EXPECT_LENA; EXPECT_EQA;
956 STRINGSA("-2353","-2,353.00"); /* Valid negative number */
957 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
958 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
959 EXPECT_LENA; EXPECT_EQA;
961 STRINGSA("-353","-353.00"); /* test for off by one error in grouping */
962 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
963 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
964 EXPECT_LENA; EXPECT_EQA;
966 STRINGSA("2353.1","2,353.10"); /* Valid real number */
967 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
968 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
969 EXPECT_LENA; EXPECT_EQA;
971 STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
972 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
973 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
974 EXPECT_LENA; EXPECT_EQA;
976 STRINGSA("2353.119","2,353.12"); /* Too many DP --> Rounded */
977 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
978 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
979 EXPECT_LENA; EXPECT_EQA;
981 format.NumDigits = 0; /* No decimal separator */
982 format.LeadingZero = 0;
983 format.Grouping = 0; /* No grouping char */
984 format.NegativeOrder = 0;
985 format.lpDecimalSep = szDot;
986 format.lpThousandSep = szComma;
988 STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
989 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
990 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
991 EXPECT_LENA; EXPECT_EQA;
993 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
994 STRINGSA("2353","2353.0");
995 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
996 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
997 EXPECT_LENA; EXPECT_EQA;
999 format.Grouping = 2; /* Group by 100's */
1000 STRINGSA("2353","23,53.0");
1001 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1002 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1003 EXPECT_LENA; EXPECT_EQA;
1005 STRINGSA("235","235.0"); /* Grouping of a positive number */
1006 format.Grouping = 3;
1007 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1008 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1009 EXPECT_LENA; EXPECT_EQA;
1011 STRINGSA("-235","-235.0"); /* Grouping of a negative number */
1012 format.NegativeOrder = NEG_LEFT;
1013 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1014 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1015 EXPECT_LENA; EXPECT_EQA;
1017 format.LeadingZero = 1; /* Always provide leading zero */
1018 STRINGSA(".5","0.5");
1019 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1020 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1021 EXPECT_LENA; EXPECT_EQA;
1023 format.NegativeOrder = NEG_PARENS;
1024 STRINGSA("-1","(1.0)");
1025 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1026 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1027 EXPECT_LENA; EXPECT_EQA;
1029 format.NegativeOrder = NEG_LEFT;
1030 STRINGSA("-1","-1.0");
1031 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1032 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1033 EXPECT_LENA; EXPECT_EQA;
1035 format.NegativeOrder = NEG_LEFT_SPACE;
1036 STRINGSA("-1","- 1.0");
1037 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1038 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1039 EXPECT_LENA; EXPECT_EQA;
1041 format.NegativeOrder = NEG_RIGHT;
1042 STRINGSA("-1","1.0-");
1043 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1044 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1045 EXPECT_LENA; EXPECT_EQA;
1047 format.NegativeOrder = NEG_RIGHT_SPACE;
1048 STRINGSA("-1","1.0 -");
1049 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1050 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1051 EXPECT_LENA; EXPECT_EQA;
1053 lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
1055 if (IsValidLocale(lcid, 0))
1057 STRINGSA("-12345","-12 345,00"); /* Try French formatting */
1058 Expected[3] = 160; /* Non breaking space */
1059 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1060 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1061 EXPECT_LENA; EXPECT_EQA;
1066 static void test_CompareStringA(void)
1069 LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
1071 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
1072 ok (ret== 1, "(Salut/Salute) Expected 1, got %d\n", ret);
1074 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
1075 ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
1077 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
1078 ok (ret== 3, "(Salut/hola) Expected 3, got %d\n", ret);
1080 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
1081 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
1083 lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
1085 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
1086 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
1088 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
1089 ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
1091 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
1092 ok (ret == 2, "(Salut/saLuT) Expected 2, got %d\n", ret);
1094 /* test for CompareStringA flags */
1095 SetLastError(0xdeadbeef);
1096 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0x8, "NULL", -1, "NULL", -1);
1097 ok(GetLastError() == ERROR_INVALID_FLAGS,
1098 "unexpected error code %d\n", GetLastError());
1099 ok(!ret, "CompareStringA must fail with invalid flag\n");
1101 SetLastError(0xdeadbeef);
1102 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, LOCALE_USE_CP_ACP, "NULL", -1, "NULL", -1);
1103 ok(GetLastError() == 0xdeadbeef, "unexpected error code %d\n", GetLastError());
1104 ok(ret == CSTR_EQUAL, "CompareStringA error: %d != CSTR_EQUAL\n", ret);
1105 /* end of test for CompareStringA flags */
1107 ret = lstrcmpA("", "");
1108 ok (ret == 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret);
1110 ret = lstrcmpA(NULL, NULL);
1111 ok (ret == 0 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, NULL) should return 0, got %d\n", ret);
1113 ret = lstrcmpA("", NULL);
1114 ok (ret == 1 || broken(ret == -2) /* win9x */, "lstrcmpA(\"\", NULL) should return 1, got %d\n", ret);
1116 ret = lstrcmpA(NULL, "");
1117 ok (ret == -1 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret);
1119 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"EndDialog",-1,"_Property",-1);
1120 ok( ret == 3, "EndDialog vs _Property ... expected 3, got %d\n", ret);
1122 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0070",-1,"_IEWWBrowserComp",-1);
1123 ok( ret == 3, "osp_vba.sreg0070 vs _IEWWBrowserComp ... expected 3, got %d\n", ret);
1125 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"r",-1,"\\",-1);
1126 ok( ret == 3, "r vs \\ ... expected 3, got %d\n", ret);
1128 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0031", -1, "OriginalDatabase", -1 );
1129 ok( ret == 3, "osp_vba.sreg0031 vs OriginalDatabase ... expected 3, got %d\n", ret);
1131 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1 );
1132 ok( ret == 3, "AAA vs aaa expected 3, got %d\n", ret);
1134 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1 );
1135 ok( ret == 1, "AAA vs aab expected 1, got %d\n", ret);
1137 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1 );
1138 ok( ret == 1, "AAA vs Aab expected 1, got %d\n", ret);
1140 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1 );
1141 ok( ret == 1, ".AAA vs Aab expected 1, got %d\n", ret);
1143 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1 );
1144 ok( ret == 1, ".AAA vs A.ab expected 1, got %d\n", ret);
1146 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1 );
1147 ok( ret == 1, "aa vs AB expected 1, got %d\n", ret);
1149 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1 );
1150 ok( ret == 1, "aa vs Aab expected 1, got %d\n", ret);
1152 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1 );
1153 ok( ret == 3, "aB vs Aab expected 3, got %d\n", ret);
1155 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1 );
1156 ok( ret == 1, "Ba vs bab expected 1, got %d\n", ret);
1158 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1 );
1159 ok( ret == 1, "{100}{83}{71}{71}{71} vs Global_DataAccess_JRO expected 1, got %d\n", ret);
1161 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1 );
1162 ok( ret == 3, "a vs { expected 3, got %d\n", ret);
1164 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1 );
1165 ok( ret == 3, "A vs { expected 3, got %d\n", ret);
1167 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1 );
1168 ok(ret == 1, "3.5/0 vs 4.0/-1 expected 1, got %d\n", ret);
1170 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1 );
1171 ok(ret == 1, "3.5 vs 4.0 expected 1, got %d\n", ret);
1173 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1 );
1174 ok(ret == 1, "3.520.4403.2 vs 4.0.2927.10 expected 1, got %d\n", ret);
1176 /* hyphen and apostrophe are treated differently depending on
1177 * whether SORT_STRINGSORT specified or not
1179 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1 );
1180 ok(ret == 3, "-o vs /m expected 3, got %d\n", ret);
1182 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1 );
1183 ok(ret == 1, "/m vs -o expected 1, got %d\n", ret);
1185 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1 );
1186 ok(ret == 1, "-o vs /m expected 1, got %d\n", ret);
1188 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1 );
1189 ok(ret == 3, "/m vs -o expected 3, got %d\n", ret);
1191 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1 );
1192 ok(ret == 3, "'o vs /m expected 3, got %d\n", ret);
1194 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1 );
1195 ok(ret == 1, "/m vs 'o expected 1, got %d\n", ret);
1197 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1 );
1198 ok(ret == 1, "'o vs /m expected 1, got %d\n", ret);
1200 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1 );
1201 ok(ret == 3, "/m vs 'o expected 3, got %d\n", ret);
1203 if (0) { /* this requires collation table patch to make it MS compatible */
1204 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
1205 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
1207 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
1208 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
1210 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
1211 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
1213 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
1214 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
1216 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
1217 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
1219 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
1220 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
1222 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
1223 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
1225 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
1226 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
1228 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
1229 ok(ret == 1, "`o vs -m expected 1, got %d\n", ret);
1231 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
1232 ok(ret == 3, "-m vs `o expected 3, got %d\n", ret);
1234 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
1235 ok(ret == 3, "`o vs -m expected 3, got %d\n", ret);
1237 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
1238 ok(ret == 1, "-m vs `o expected 1, got %d\n", ret);
1241 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9);
1242 ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0 expected 2, got %d\n", ret);
1244 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10);
1245 ok(ret == 1, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1, got %d\n", ret);
1247 /* WinXP handles embedded NULLs differently than earlier versions */
1248 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
1249 ok(ret == 1 || ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1 or 2, got %d\n", ret);
1251 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
1252 ok(ret == 1 || ret == 2, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected 1 or 2, got %d\n", ret);
1254 ret = CompareStringA(lcid, 0, "a\0b", -1, "a", -1);
1255 ok(ret == 2, "a vs a expected 2, got %d\n", ret);
1257 ret = CompareStringA(lcid, 0, "a\0b", 4, "a", 2);
1258 ok(ret == CSTR_EQUAL || /* win2k */
1259 ret == CSTR_GREATER_THAN,
1260 "a\\0b vs a expected CSTR_EQUAL or CSTR_GREATER_THAN, got %d\n", ret);
1262 ret = CompareStringA(lcid, 0, "\2", 2, "\1", 2);
1263 todo_wine ok(ret != 2, "\\2 vs \\1 expected unequal\n");
1265 ret = CompareStringA(lcid, NORM_IGNORECASE | LOCALE_USE_CP_ACP, "#", -1, ".", -1);
1266 todo_wine ok(ret == CSTR_LESS_THAN, "\"#\" vs \".\" expected CSTR_LESS_THAN, got %d\n", ret);
1268 ret = lstrcmpi("#", ".");
1269 todo_wine ok(ret == -1, "\"#\" vs \".\" expected -1, got %d\n", ret);
1272 static void test_LCMapStringA(void)
1275 char buf[256], buf2[256];
1276 static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
1277 static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
1278 static const char symbols_stripped[] = "justateststring1";
1280 SetLastError(0xdeadbeef);
1281 ret = LCMapStringA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP | LCMAP_LOWERCASE,
1282 lower_case, -1, buf, sizeof(buf));
1283 ok(ret == lstrlenA(lower_case) + 1,
1284 "ret %d, error %d, expected value %d\n",
1285 ret, GetLastError(), lstrlenA(lower_case) + 1);
1286 ok(!memcmp(buf, lower_case, ret), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1288 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1289 upper_case, -1, buf, sizeof(buf));
1290 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1291 ok(GetLastError() == ERROR_INVALID_FLAGS,
1292 "unexpected error code %d\n", GetLastError());
1294 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1295 upper_case, -1, buf, sizeof(buf));
1296 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1297 ok(GetLastError() == ERROR_INVALID_FLAGS,
1298 "unexpected error code %d\n", GetLastError());
1300 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1301 upper_case, -1, buf, sizeof(buf));
1302 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1303 ok(GetLastError() == ERROR_INVALID_FLAGS,
1304 "unexpected error code %d\n", GetLastError());
1306 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1307 upper_case, -1, buf, sizeof(buf));
1308 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1309 ok(GetLastError() == ERROR_INVALID_FLAGS,
1310 "unexpected error code %d\n", GetLastError());
1312 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1313 SetLastError(0xdeadbeef);
1314 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1315 upper_case, -1, buf, sizeof(buf));
1316 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1317 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1319 /* test LCMAP_LOWERCASE */
1320 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1321 upper_case, -1, buf, sizeof(buf));
1322 ok(ret == lstrlenA(upper_case) + 1,
1323 "ret %d, error %d, expected value %d\n",
1324 ret, GetLastError(), lstrlenA(upper_case) + 1);
1325 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1327 /* test LCMAP_UPPERCASE */
1328 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1329 lower_case, -1, buf, sizeof(buf));
1330 ok(ret == lstrlenA(lower_case) + 1,
1331 "ret %d, error %d, expected value %d\n",
1332 ret, GetLastError(), lstrlenA(lower_case) + 1);
1333 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1335 /* test buffer overflow */
1336 SetLastError(0xdeadbeef);
1337 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1338 lower_case, -1, buf, 4);
1339 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1340 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1342 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1343 lstrcpyA(buf, lower_case);
1344 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1345 buf, -1, buf, sizeof(buf));
1346 if (!ret) /* Win9x */
1347 trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1350 ok(ret == lstrlenA(lower_case) + 1,
1351 "ret %d, error %d, expected value %d\n",
1352 ret, GetLastError(), lstrlenA(lower_case) + 1);
1353 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1355 lstrcpyA(buf, upper_case);
1356 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1357 buf, -1, buf, sizeof(buf));
1358 if (!ret) /* Win9x */
1359 trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1362 ok(ret == lstrlenA(upper_case) + 1,
1363 "ret %d, error %d, expected value %d\n",
1364 ret, GetLastError(), lstrlenA(lower_case) + 1);
1365 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1368 /* otherwise src == dst should fail */
1369 SetLastError(0xdeadbeef);
1370 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1371 buf, 10, buf, sizeof(buf));
1372 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1373 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1374 "unexpected error code %d\n", GetLastError());
1375 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1377 /* test whether '\0' is always appended */
1378 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1379 upper_case, -1, buf, sizeof(buf));
1380 ok(ret, "LCMapStringA must succeed\n");
1381 ok(buf[ret-1] == 0, "LCMapStringA not null-terminated\n");
1382 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1383 upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1384 ok(ret2, "LCMapStringA must succeed\n");
1385 ok(buf2[ret2-1] == 0, "LCMapStringA not null-terminated\n" );
1386 ok(ret == ret2, "lengths of sort keys must be equal\n");
1387 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1389 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1390 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1391 upper_case, -1, buf, sizeof(buf));
1392 ok(ret, "LCMapStringA must succeed\n");
1393 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1394 lower_case, -1, buf2, sizeof(buf2));
1395 ok(ret2, "LCMapStringA must succeed\n");
1396 ok(ret == ret2, "lengths of sort keys must be equal\n");
1397 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1399 /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1400 results from plain LCMAP_SORTKEY on Vista */
1402 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1403 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1404 lower_case, -1, buf, sizeof(buf));
1405 ok(ret, "LCMapStringA must succeed\n");
1406 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1407 symbols_stripped, -1, buf2, sizeof(buf2));
1408 ok(ret2, "LCMapStringA must succeed\n");
1409 ok(ret == ret2, "lengths of sort keys must be equal\n");
1410 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1412 /* test NORM_IGNORENONSPACE */
1413 lstrcpyA(buf, "foo");
1414 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1415 lower_case, -1, buf, sizeof(buf));
1416 ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1417 lstrlenA(lower_case) + 1, ret);
1418 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1420 /* test NORM_IGNORESYMBOLS */
1421 lstrcpyA(buf, "foo");
1422 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1423 lower_case, -1, buf, sizeof(buf));
1424 ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1425 lstrlenA(symbols_stripped) + 1, ret);
1426 ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1428 /* test srclen = 0 */
1429 SetLastError(0xdeadbeef);
1430 ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1431 ok(!ret, "LCMapStringA should fail with srclen = 0\n");
1432 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1433 "unexpected error code %d\n", GetLastError());
1436 static void test_LCMapStringW(void)
1439 WCHAR buf[256], buf2[256];
1440 char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1441 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};
1442 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};
1443 static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
1444 static const WCHAR fooW[] = {'f','o','o',0};
1446 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1447 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1448 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1450 win_skip("LCMapStringW is not implemented\n");
1454 ok(lstrcmpW(buf, upper_case) == 0, "Expected upper case string\n");
1457 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1458 ok(GetLastError() == ERROR_INVALID_FLAGS,
1459 "unexpected error code %d\n", GetLastError());
1462 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1463 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1464 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1465 ok(GetLastError() == ERROR_INVALID_FLAGS,
1466 "unexpected error code %d\n", GetLastError());
1468 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1469 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1470 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1471 ok(GetLastError() == ERROR_INVALID_FLAGS,
1472 "unexpected error code %d\n", GetLastError());
1474 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1475 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1476 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1477 ok(GetLastError() == ERROR_INVALID_FLAGS,
1478 "unexpected error code %d\n", GetLastError());
1480 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1481 SetLastError(0xdeadbeef);
1482 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1483 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1484 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1485 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1487 /* test LCMAP_LOWERCASE */
1488 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1489 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1490 ok(ret == lstrlenW(upper_case) + 1,
1491 "ret %d, error %d, expected value %d\n",
1492 ret, GetLastError(), lstrlenW(upper_case) + 1);
1493 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1495 /* test LCMAP_UPPERCASE */
1496 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1497 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1498 ok(ret == lstrlenW(lower_case) + 1,
1499 "ret %d, error %d, expected value %d\n",
1500 ret, GetLastError(), lstrlenW(lower_case) + 1);
1501 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1503 /* test buffer overflow */
1504 SetLastError(0xdeadbeef);
1505 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1506 lower_case, -1, buf, 4);
1507 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1508 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1510 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1511 lstrcpyW(buf, lower_case);
1512 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1513 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1514 ok(ret == lstrlenW(lower_case) + 1,
1515 "ret %d, error %d, expected value %d\n",
1516 ret, GetLastError(), lstrlenW(lower_case) + 1);
1517 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1519 lstrcpyW(buf, upper_case);
1520 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1521 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1522 ok(ret == lstrlenW(upper_case) + 1,
1523 "ret %d, error %d, expected value %d\n",
1524 ret, GetLastError(), lstrlenW(lower_case) + 1);
1525 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1527 /* otherwise src == dst should fail */
1528 SetLastError(0xdeadbeef);
1529 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1530 buf, 10, buf, sizeof(buf));
1531 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1532 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1533 "unexpected error code %d\n", GetLastError());
1534 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1536 /* test whether '\0' is always appended */
1537 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1538 upper_case, -1, buf, sizeof(buf));
1539 ok(ret, "LCMapStringW must succeed\n");
1540 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1541 upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1542 ok(ret, "LCMapStringW must succeed\n");
1543 ok(ret == ret2, "lengths of sort keys must be equal\n");
1544 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1546 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1547 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1548 upper_case, -1, buf, sizeof(buf));
1549 ok(ret, "LCMapStringW must succeed\n");
1550 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1551 lower_case, -1, buf2, sizeof(buf2));
1552 ok(ret2, "LCMapStringW must succeed\n");
1553 ok(ret == ret2, "lengths of sort keys must be equal\n");
1554 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1556 /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1557 results from plain LCMAP_SORTKEY on Vista */
1559 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1560 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1561 lower_case, -1, buf, sizeof(buf));
1562 ok(ret, "LCMapStringW must succeed\n");
1563 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1564 symbols_stripped, -1, buf2, sizeof(buf2));
1565 ok(ret2, "LCMapStringW must succeed\n");
1566 ok(ret == ret2, "lengths of sort keys must be equal\n");
1567 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1569 /* test NORM_IGNORENONSPACE */
1570 lstrcpyW(buf, fooW);
1571 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1572 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1573 ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1574 lstrlenW(lower_case) + 1, ret);
1575 ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1577 /* test NORM_IGNORESYMBOLS */
1578 lstrcpyW(buf, fooW);
1579 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1580 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1581 ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1582 lstrlenW(symbols_stripped) + 1, ret);
1583 ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1585 /* test srclen = 0 */
1586 SetLastError(0xdeadbeef);
1587 ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf)/sizeof(WCHAR));
1588 ok(!ret, "LCMapStringW should fail with srclen = 0\n");
1589 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1590 "unexpected error code %d\n", GetLastError());
1593 /* this requires collation table patch to make it MS compatible */
1594 static const char * const strings_sorted[] =
1626 static const char * const strings[] =
1658 static int compare_string1(const void *e1, const void *e2)
1660 const char *s1 = *(const char *const *)e1;
1661 const char *s2 = *(const char *const *)e2;
1663 return lstrcmpA(s1, s2);
1666 static int compare_string2(const void *e1, const void *e2)
1668 const char *s1 = *(const char *const *)e1;
1669 const char *s2 = *(const char *const *)e2;
1671 return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1674 static int compare_string3(const void *e1, const void *e2)
1676 const char *s1 = *(const char *const *)e1;
1677 const char *s2 = *(const char *const *)e2;
1678 char key1[256], key2[256];
1680 LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
1681 LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
1682 return strcmp(key1, key2);
1685 static void test_sorting(void)
1688 char **str_buf = (char **)buf;
1691 assert(sizeof(buf) >= sizeof(strings));
1693 /* 1. sort using lstrcmpA */
1694 memcpy(buf, strings, sizeof(strings));
1695 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
1696 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1698 ok(!strcmp(strings_sorted[i], str_buf[i]),
1699 "qsort using lstrcmpA failed for element %d\n", i);
1701 /* 2. sort using CompareStringA */
1702 memcpy(buf, strings, sizeof(strings));
1703 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
1704 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1706 ok(!strcmp(strings_sorted[i], str_buf[i]),
1707 "qsort using CompareStringA failed for element %d\n", i);
1709 /* 3. sort using sort keys */
1710 memcpy(buf, strings, sizeof(strings));
1711 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
1712 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1714 ok(!strcmp(strings_sorted[i], str_buf[i]),
1715 "qsort using sort keys failed for element %d\n", i);
1719 static void test_FoldStringA(void)
1723 char src[256], dst[256];
1724 static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0' };
1725 static const char digits_dst[] = { '1','2','3','\0' };
1726 static const char composite_src[] =
1728 0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
1729 0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
1730 0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
1731 0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
1732 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
1733 0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
1734 0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
1735 0xfb,0xfc,0xfd,0xff,'\0'
1737 static const char composite_dst[] =
1739 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1740 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1741 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1742 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1743 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1744 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1745 0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
1746 0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
1747 0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
1748 0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
1749 0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
1750 0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
1751 0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
1752 0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
1753 0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1755 static const char composite_dst_alt[] =
1757 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1758 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1759 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1760 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1761 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1762 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1763 0x4f,0x7e,0x4f,0xa8,0xd8,0x55,0x60,0x55,
1764 0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,0x61,
1765 0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,0x61,
1766 0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,0x65,
1767 0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,0x69,
1768 0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,0x6f,
1769 0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,0x6f,
1770 0xa8,0xf8,0x75,0x60,0x75,0xb4,0x75,0x5e,
1771 0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1773 static const char ligatures_src[] =
1775 0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1777 static const char ligatures_dst[] =
1779 'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1781 static const struct special
1785 } foldczone_special[] =
1788 { 0x85, { 0x2e, 0x2e, 0x2e, 0x00 } },
1789 { 0x98, { 0x20, 0x7e, 0x00 } },
1790 { 0x99, { 0x54, 0x4d, 0x00 } },
1791 { 0xa0, { 0x20, 0x00 } },
1792 { 0xa8, { 0x20, 0xa8, 0x00 } },
1793 { 0xaa, { 0x61, 0x00 } },
1794 { 0xaf, { 0x20, 0xaf, 0x00 } },
1795 { 0xb2, { 0x32, 0x00 } },
1796 { 0xb3, { 0x33, 0x00 } },
1797 { 0xb4, { 0x20, 0xb4, 0x00 } },
1798 { 0xb8, { 0x20, 0xb8, 0x00 } },
1799 { 0xb9, { 0x31, 0x00 } },
1800 { 0xba, { 0x6f, 0x00 } },
1801 { 0xbc, { 0x31, 0x2f, 0x34, 0x00 } },
1802 { 0xbd, { 0x31, 0x2f, 0x32, 0x00 } },
1803 { 0xbe, { 0x33, 0x2f, 0x34, 0x00 } },
1808 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1810 /* these tests are locale specific */
1811 if (GetACP() != 1252)
1813 trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1817 /* MAP_FOLDDIGITS */
1819 ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
1820 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1822 win_skip("FoldStringA is not implemented\n");
1825 ok(ret == 4, "Expected ret == 4, got %d, error %d\n", ret, GetLastError());
1826 ok(strcmp(dst, digits_dst) == 0,
1827 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
1828 for (i = 1; i < 256; i++)
1830 if (!strchr(digits_src, i))
1835 ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
1836 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1837 ok(dst[0] == src[0],
1838 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
1842 /* MAP_EXPAND_LIGATURES */
1844 ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1845 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1846 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1847 ok(ret == sizeof(ligatures_dst), "Got %d, error %d\n", ret, GetLastError());
1848 ok(strcmp(dst, ligatures_dst) == 0,
1849 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
1850 for (i = 1; i < 256; i++)
1852 if (!strchr(ligatures_src, i))
1857 ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1861 ok((i == 0xDC && lstrcmpA(dst, "UE") == 0) ||
1862 (i == 0xFC && lstrcmpA(dst, "ue") == 0),
1863 "Got %s for %d\n", dst, i);
1867 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1868 ok(dst[0] == src[0],
1869 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
1877 ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
1878 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1879 ok(ret == 121 || ret == 119, "Expected 121 or 119, got %d\n", ret);
1880 ok(strcmp(dst, composite_dst) == 0 || strcmp(dst, composite_dst_alt) == 0,
1881 "MAP_COMPOSITE: Mismatch, got '%s'\n", dst);
1883 for (i = 1; i < 256; i++)
1885 if (!strchr(composite_src, i))
1890 ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
1891 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1892 ok(dst[0] == src[0],
1893 "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
1894 (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
1899 for (i = 1; i < 256; i++)
1904 ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
1906 for (j = 0; foldczone_special[j].src != 0 && ! is_special; j++)
1908 if (foldczone_special[j].src == src[0])
1910 ok(ret == 2 || ret == lstrlenA(foldczone_special[j].dst) + 1,
1911 "Expected ret == 2 or %d, got %d, error %d\n",
1912 lstrlenA(foldczone_special[j].dst) + 1, ret, GetLastError());
1913 ok(src[0] == dst[0] || lstrcmpA(foldczone_special[j].dst, dst) == 0,
1914 "MAP_FOLDCZONE: string mismatch for 0x%02x\n",
1915 (unsigned char)src[0]);
1921 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1922 ok(src[0] == dst[0],
1923 "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
1924 (unsigned char)src[0], (unsigned char)dst[0]);
1928 /* MAP_PRECOMPOSED */
1929 for (i = 1; i < 256; i++)
1934 ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
1935 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1936 ok(src[0] == dst[0],
1937 "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
1938 (unsigned char)src[0], (unsigned char)dst[0]);
1942 static void test_FoldStringW(void)
1946 WCHAR src[256], dst[256], ch, prev_ch = 1;
1947 static const DWORD badFlags[] =
1950 MAP_PRECOMPOSED|MAP_COMPOSITE,
1951 MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
1952 MAP_COMPOSITE|MAP_EXPAND_LIGATURES
1954 /* Ranges of digits 0-9 : Must be sorted! */
1955 static const WCHAR digitRanges[] =
1957 0x0030, /* '0'-'9' */
1958 0x0660, /* Eastern Arabic */
1959 0x06F0, /* Arabic - Hindu */
1960 0x0966, /* Devengari */
1961 0x09E6, /* Bengalii */
1962 0x0A66, /* Gurmukhi */
1963 0x0AE6, /* Gujarati */
1965 0x0BE6, /* Tamil - No 0 */
1966 0x0C66, /* Telugu */
1967 0x0CE6, /* Kannada */
1968 0x0D66, /* Maylayalam */
1971 0x0F29, /* Tibet - 0 is out of sequence */
1972 0x2070, /* Superscript - 1, 2, 3 are out of sequence */
1973 0x2080, /* Subscript */
1974 0x245F, /* Circled - 0 is out of sequence */
1975 0x2473, /* Bracketed */
1976 0x2487, /* Full stop */
1977 0x2775, /* Inverted circled - No 0 */
1978 0x277F, /* Patterned circled - No 0 */
1979 0x2789, /* Inverted Patterned circled - No 0 */
1980 0x3020, /* Hangzhou */
1981 0xff10, /* Pliene chasse (?) */
1982 0xffff /* Terminator */
1984 /* Digits which are represented, but out of sequence */
1985 static const WCHAR outOfSequenceDigits[] =
1987 0xB9, /* Superscript 1 */
1988 0xB2, /* Superscript 2 */
1989 0xB3, /* Superscript 3 */
1990 0x0F33, /* Tibetan half zero */
1991 0x24EA, /* Circled 0 */
1992 0x3007, /* Ideographic number zero */
1993 '\0' /* Terminator */
1995 /* Digits in digitRanges for which no representation is available */
1996 static const WCHAR noDigitAvailable[] =
1998 0x0BE6, /* No Tamil 0 */
1999 0x0F29, /* No Tibetan half zero (out of sequence) */
2000 0x2473, /* No Bracketed 0 */
2001 0x2487, /* No 0 Full stop */
2002 0x2775, /* No inverted circled 0 */
2003 0x277F, /* No patterned circled */
2004 0x2789, /* No inverted Patterned circled */
2005 0x3020, /* No Hangzhou 0 */
2006 '\0' /* Terminator */
2008 static const WCHAR foldczone_src[] =
2010 'W', 'i', 'n', 'e', 0x0348, 0x0551, 0x1323, 0x280d,
2011 0xff37, 0xff49, 0xff4e, 0xff45, '\0'
2013 static const WCHAR foldczone_dst[] =
2015 'W','i','n','e',0x0348,0x0551,0x1323,0x280d,'W','i','n','e','\0'
2017 static const WCHAR ligatures_src[] =
2019 'W', 'i', 'n', 'e', 0x03a6, 0x03b9, 0x03bd, 0x03b5,
2020 0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
2021 0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
2022 0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
2023 0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
2024 0xfb04, 0xfb05, 0xfb06, '\0'
2026 static const WCHAR ligatures_dst[] =
2028 'W','i','n','e',0x03a6,0x03b9,0x03bd,0x03b5,
2029 'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
2030 'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
2031 'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
2032 0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
2033 'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
2038 win_skip("FoldStringW is not available\n");
2039 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
2042 /* Invalid flag combinations */
2043 for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
2045 src[0] = dst[0] = '\0';
2047 ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
2048 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
2050 win_skip("FoldStringW is not implemented\n");
2053 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
2054 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2057 /* src & dst cannot be the same */
2059 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
2060 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2061 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2063 /* src can't be NULL */
2065 ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
2066 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2067 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2069 /* srclen can't be 0 */
2071 ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
2072 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2073 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2075 /* dstlen can't be < 0 */
2077 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
2078 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2079 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2081 /* Ret includes terminating NUL which is appended if srclen = -1 */
2086 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
2087 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2088 ok(dst[0] == 'A' && dst[1] == '\0',
2089 "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%d\n",
2090 'A', '\0', ret, dst[0], dst[1], GetLastError());
2092 /* If size is given, result is not NUL terminated */
2098 ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
2099 ok(ret == 1, "Expected ret == 1, got %d, error %d\n", ret, GetLastError());
2100 ok(dst[0] == 'A' && dst[1] == 'X',
2101 "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%d\n",
2102 'A','X', ret, dst[0], dst[1], GetLastError());
2104 /* MAP_FOLDDIGITS */
2105 for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
2107 /* Check everything before this range */
2108 for (ch = prev_ch; ch < digitRanges[j]; ch++)
2112 src[1] = dst[0] = '\0';
2113 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2114 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2116 ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
2117 /* Wine (correctly) maps all Unicode 4.0+ digits */
2118 isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF ||
2119 (ch >= 0x1369 && ch <= 0x1371),
2120 "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
2123 if (digitRanges[j] == 0xffff)
2124 break; /* Finished the whole code point space */
2126 for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
2130 /* Map out of sequence characters */
2131 if (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
2132 else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
2133 else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
2134 else if (ch == 0x245F) c = 0x24EA; /* Circled 0 */
2138 src[1] = dst[0] = '\0';
2139 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2140 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2142 ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
2143 broken( dst[0] == ch ) || /* old Windows versions don't have all mappings */
2144 (digitRanges[j] == 0x3020 && dst[0] == ch) || /* Hangzhou not present in all Windows versions */
2145 (digitRanges[j] == 0x0F29 && dst[0] == ch) || /* Tibetan not present in all Windows versions */
2146 strchrW(noDigitAvailable, c),
2147 "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
2148 ch, '0' + digitRanges[j] - ch, dst[0]);
2155 ret = pFoldStringW(MAP_FOLDCZONE, foldczone_src, -1, dst, 256);
2156 ok(ret == sizeof(foldczone_dst)/sizeof(foldczone_dst[0]),
2157 "Got %d, error %d\n", ret, GetLastError());
2158 ok(!memcmp(dst, foldczone_dst, sizeof(foldczone_dst)),
2159 "MAP_FOLDCZONE: Expanded incorrectly\n");
2161 /* MAP_EXPAND_LIGATURES */
2163 ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
2164 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
2165 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
2166 ok(ret == sizeof(ligatures_dst)/sizeof(ligatures_dst[0]),
2167 "Got %d, error %d\n", ret, GetLastError());
2168 ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
2169 "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
2172 /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
2177 #define LCID_OK(l) \
2178 ok(lcid == l, "Expected lcid = %08x, got %08x\n", l, lcid)
2179 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
2180 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
2181 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
2182 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
2184 static void test_ConvertDefaultLocale(void)
2188 /* Doesn't change lcid, even if non default sublang/sort used */
2189 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_US, SORT_DEFAULT);
2190 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_UK, SORT_DEFAULT);
2191 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT);
2192 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE);
2194 /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
2195 LCID_RES(MKLCID(LANG_ENGLISH, SUBLANG_NEUTRAL, SORT_DEFAULT),
2196 MKLCID(LANG_ENGLISH, SUBLANG_DEFAULT, SORT_DEFAULT));
2197 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
2198 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
2200 /* Invariant language is not treated specially */
2201 TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
2203 /* User/system default languages alone are not mapped */
2204 TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
2205 TEST_LCIDLANG(LANG_USER_DEFAULT, SORT_JAPANESE_UNICODE);
2208 LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
2209 LCID_RES(LOCALE_USER_DEFAULT, GetUserDefaultLCID());
2210 LCID_RES(LOCALE_NEUTRAL, GetUserDefaultLCID());
2213 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
2214 DWORD dwFlags, LONG_PTR lParam)
2216 trace("%08x, %s, %s, %08x, %08lx\n",
2217 lgrpid, lpszNum, lpszName, dwFlags, lParam);
2219 ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
2220 "Enumerated grp %d not valid (flags %d)\n", lgrpid, dwFlags);
2222 /* If lParam is one, we are calling with flags defaulted from 0 */
2223 ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
2224 "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %d\n", dwFlags);
2229 static void test_EnumSystemLanguageGroupsA(void)
2233 if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
2235 win_skip("EnumSystemLanguageGroupsA and/or IsValidLanguageGroup are not available\n");
2239 /* No enumeration proc */
2241 ret = pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
2242 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2244 win_skip("EnumSystemLanguageGroupsA is not implemented\n");
2247 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2248 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2252 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
2253 ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2255 /* No flags - defaults to LGRPID_INSTALLED */
2256 SetLastError(0xdeadbeef);
2257 pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
2258 ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
2260 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
2261 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
2265 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
2268 trace("%08x, %08x, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
2270 /* invalid locale enumerated on some platforms */
2274 ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
2275 "Enumerated grp %d not valid\n", lgrpid);
2276 ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
2277 "Enumerated grp locale %d not valid\n", lcid);
2281 static void test_EnumLanguageGroupLocalesA(void)
2285 if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
2287 win_skip("EnumLanguageGroupLocalesA and/or IsValidLanguageGroup are not available\n");
2291 /* No enumeration proc */
2293 ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
2294 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2296 win_skip("EnumLanguageGroupLocalesA is not implemented\n");
2299 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2300 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2302 /* lgrpid too small */
2304 ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
2305 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2306 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2308 /* lgrpid too big */
2310 ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
2311 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2312 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2314 /* dwFlags is reserved */
2316 ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
2317 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2318 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2320 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2323 static void test_SetLocaleInfoA(void)
2326 LCID lcid = GetUserDefaultLCID();
2330 bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2331 ok( !bRet && GetLastError() == ERROR_INVALID_PARAMETER,
2332 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2336 bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
2337 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2338 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2342 bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
2343 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2344 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2347 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2349 trace("%s %08lx\n", value, lParam);
2353 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2355 ok(!enumCount, "callback called again unexpected\n");
2360 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2362 ok(0,"callback called unexpected\n");
2366 static void test_EnumUILanguageA(void)
2369 if (!pEnumUILanguagesA) {
2370 win_skip("EnumUILanguagesA is not available on Win9x or NT4\n");
2374 SetLastError(ERROR_SUCCESS);
2375 ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2376 if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2378 win_skip("EnumUILanguagesA is not implemented\n");
2381 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2384 SetLastError(ERROR_SUCCESS);
2385 ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2386 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2388 SetLastError(ERROR_SUCCESS);
2389 ret = pEnumUILanguagesA(NULL, 0, 0);
2390 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2391 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2392 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2394 SetLastError(ERROR_SUCCESS);
2395 ret = pEnumUILanguagesA(luilocale_proc3A, 0x5a5a5a5a, 0);
2396 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2397 ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2399 SetLastError(ERROR_SUCCESS);
2400 ret = pEnumUILanguagesA(NULL, 0x5a5a5a5a, 0);
2401 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2402 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2403 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2406 static char date_fmt_buf[1024];
2408 static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
2410 lstrcatA(date_fmt_buf, fmt);
2411 lstrcatA(date_fmt_buf, "\n");
2415 static void test_EnumDateFormatsA(void)
2419 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2421 trace("EnumDateFormatsA 0\n");
2422 date_fmt_buf[0] = 0;
2423 SetLastError(0xdeadbeef);
2424 ret = EnumDateFormatsA(enum_datetime_procA, lcid, 0);
2425 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2427 win_skip("0 for dwFlags is not supported\n");
2431 ok(ret, "EnumDateFormatsA(0) error %d\n", GetLastError());
2432 trace("%s\n", date_fmt_buf);
2433 /* test the 1st enumerated format */
2434 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2435 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2436 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2437 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2440 trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n");
2441 date_fmt_buf[0] = 0;
2442 SetLastError(0xdeadbeef);
2443 ret = EnumDateFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2444 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2446 win_skip("LOCALE_USE_CP_ACP is not supported\n");
2450 ok(ret, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2451 trace("%s\n", date_fmt_buf);
2452 /* test the 1st enumerated format */
2453 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2454 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2455 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2456 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2459 trace("EnumDateFormatsA DATE_SHORTDATE\n");
2460 date_fmt_buf[0] = 0;
2461 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_SHORTDATE);
2462 ok(ret, "EnumDateFormatsA(DATE_SHORTDATE) error %d\n", GetLastError());
2463 trace("%s\n", date_fmt_buf);
2464 /* test the 1st enumerated format */
2465 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2466 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2467 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2468 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2470 trace("EnumDateFormatsA DATE_LONGDATE\n");
2471 date_fmt_buf[0] = 0;
2472 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_LONGDATE);
2473 ok(ret, "EnumDateFormatsA(DATE_LONGDATE) error %d\n", GetLastError());
2474 trace("%s\n", date_fmt_buf);
2475 /* test the 1st enumerated format */
2476 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2477 ret = GetLocaleInfoA(lcid, LOCALE_SLONGDATE, buf, sizeof(buf));
2478 ok(ret, "GetLocaleInfoA(LOCALE_SLONGDATE) error %d\n", GetLastError());
2479 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2481 trace("EnumDateFormatsA DATE_YEARMONTH\n");
2482 date_fmt_buf[0] = 0;
2483 SetLastError(0xdeadbeef);
2484 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_YEARMONTH);
2485 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2487 skip("DATE_YEARMONTH is only present on W2K and later\n");
2490 ok(ret, "EnumDateFormatsA(DATE_YEARMONTH) error %d\n", GetLastError());
2491 trace("%s\n", date_fmt_buf);
2492 /* test the 1st enumerated format */
2493 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2494 ret = GetLocaleInfoA(lcid, LOCALE_SYEARMONTH, buf, sizeof(buf));
2495 ok(ret, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %d\n", GetLastError());
2496 ok(!lstrcmpA(date_fmt_buf, buf) || broken(!buf[0]) /* win9x */,
2497 "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2500 static void test_EnumTimeFormatsA(void)
2504 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2506 trace("EnumTimeFormatsA 0\n");
2507 date_fmt_buf[0] = 0;
2508 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, 0);
2509 ok(ret, "EnumTimeFormatsA(0) error %d\n", GetLastError());
2510 trace("%s\n", date_fmt_buf);
2511 /* test the 1st enumerated format */
2512 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2513 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2514 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2515 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2517 trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n");
2518 date_fmt_buf[0] = 0;
2519 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2520 ok(ret, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2521 trace("%s\n", date_fmt_buf);
2522 /* test the 1st enumerated format */
2523 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2524 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2525 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2526 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2529 static void test_GetCPInfo(void)
2534 SetLastError(0xdeadbeef);
2535 ret = GetCPInfo(CP_SYMBOL, &cpinfo);
2536 ok(!ret, "GetCPInfo(CP_SYMBOL) should fail\n");
2537 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2538 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2540 SetLastError(0xdeadbeef);
2541 ret = GetCPInfo(CP_UTF7, &cpinfo);
2542 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2544 skip("Codepage CP_UTF7 is not installed/available\n");
2548 ok(ret, "GetCPInfo(CP_UTF7) error %u\n", GetLastError());
2549 ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2550 ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2551 ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2552 ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2553 ok(cpinfo.MaxCharSize == 5, "expected 5, got 0x%x\n", cpinfo.MaxCharSize);
2556 SetLastError(0xdeadbeef);
2557 ret = GetCPInfo(CP_UTF8, &cpinfo);
2558 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2560 skip("Codepage CP_UTF8 is not installed/available\n");
2564 ok(ret, "GetCPInfo(CP_UTF8) error %u\n", GetLastError());
2565 ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2566 ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2567 ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2568 ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2569 ok(cpinfo.MaxCharSize == 4 || broken(cpinfo.MaxCharSize == 3) /* win9x */,
2570 "expected 4, got %u\n", cpinfo.MaxCharSize);
2576 InitFunctionPointers();
2578 test_EnumTimeFormatsA();
2579 test_EnumDateFormatsA();
2580 test_GetLocaleInfoA();
2581 test_GetLocaleInfoW();
2582 test_GetTimeFormatA();
2583 test_GetDateFormatA();
2584 test_GetDateFormatW();
2585 test_GetCurrencyFormatA(); /* Also tests the W version */
2586 test_GetNumberFormatA(); /* Also tests the W version */
2587 test_CompareStringA();
2588 test_LCMapStringA();
2589 test_LCMapStringW();
2592 test_ConvertDefaultLocale();
2593 test_EnumSystemLanguageGroupsA();
2594 test_EnumLanguageGroupLocalesA();
2595 test_SetLocaleInfoA();
2596 test_EnumUILanguageA();
2598 /* this requires collation table patch to make it MS compatible */
2599 if (0) test_sorting();