2 * Unit tests for locale functions
4 * Copyright 2002 YASAR Mehmet
5 * Copyright 2003 Dmitry Timoshkov
6 * Copyright 2003 Jon Griffiths
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 * We must pass LOCALE_NOUSEROVERRIDE (NUO) to formatting functions so that
24 * even when the user has overridden their default i8n settings (e.g. in
25 * the control panel i8n page), we will still get the expected results.
33 #include "wine/test.h"
39 static inline unsigned int strlenW( const WCHAR *str )
46 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
49 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
53 static inline WCHAR *strchrW( const WCHAR *str, WCHAR ch )
55 do { if (*str == ch) return (WCHAR *)str; } while (*str++);
59 static inline int isdigitW( WCHAR wc )
62 GetStringTypeW( CT_CTYPE1, &wc, 1, &type );
63 return type & C1_DIGIT;
66 /* Some functions are only in later versions of kernel32.dll */
67 static HMODULE hKernel32;
68 static WORD enumCount;
70 static BOOL (WINAPI *pEnumSystemLanguageGroupsA)(LANGUAGEGROUP_ENUMPROC, DWORD, LONG_PTR);
71 static BOOL (WINAPI *pEnumLanguageGroupLocalesA)(LANGGROUPLOCALE_ENUMPROC, LGRPID, DWORD, LONG_PTR);
72 static BOOL (WINAPI *pEnumUILanguagesA)(UILANGUAGE_ENUMPROC, DWORD, LONG_PTR);
73 static BOOL (WINAPI *pEnumSystemLocalesEx)(LOCALE_ENUMPROCEX, DWORD, LPARAM, LPVOID);
74 static INT (WINAPI *pFoldStringA)(DWORD, LPCSTR, INT, LPSTR, INT);
75 static INT (WINAPI *pFoldStringW)(DWORD, LPCWSTR, INT, LPWSTR, INT);
76 static BOOL (WINAPI *pIsValidLanguageGroup)(LGRPID, DWORD);
78 static void InitFunctionPointers(void)
80 hKernel32 = GetModuleHandleA("kernel32");
81 pEnumSystemLanguageGroupsA = (void*)GetProcAddress(hKernel32, "EnumSystemLanguageGroupsA");
82 pEnumLanguageGroupLocalesA = (void*)GetProcAddress(hKernel32, "EnumLanguageGroupLocalesA");
83 pFoldStringA = (void*)GetProcAddress(hKernel32, "FoldStringA");
84 pFoldStringW = (void*)GetProcAddress(hKernel32, "FoldStringW");
85 pIsValidLanguageGroup = (void*)GetProcAddress(hKernel32, "IsValidLanguageGroup");
86 pEnumUILanguagesA = (void*)GetProcAddress(hKernel32, "EnumUILanguagesA");
87 pEnumSystemLocalesEx = (void*)GetProcAddress(hKernel32, "EnumSystemLocalesEx");
90 #define eq(received, expected, label, type) \
91 ok((received) == (expected), "%s: got " type " instead of " type "\n", \
92 (label), (received), (expected))
94 #define BUFFER_SIZE 128
95 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
97 #define STRINGSA(x,y) strcpy(input, x); strcpy(Expected, y); SetLastError(0xdeadbeef); buffer[0] = '\0'
98 #define EXPECT_LENA ok(ret == lstrlen(Expected)+1, "Expected Len %d, got %d\n", lstrlen(Expected)+1, ret)
99 #define EXPECT_EQA ok(strncmp(buffer, Expected, strlen(Expected)) == 0, \
100 "Expected '%s', got '%s'\n", Expected, buffer)
102 #define STRINGSW(x,y) MultiByteToWideChar(CP_ACP,0,x,-1,input,COUNTOF(input)); \
103 MultiByteToWideChar(CP_ACP,0,y,-1,Expected,COUNTOF(Expected)); \
104 SetLastError(0xdeadbeef); buffer[0] = '\0'
105 #define EXPECT_LENW ok(ret == lstrlenW(Expected)+1, "Expected Len %d, got %d\n", lstrlenW(Expected)+1, ret)
106 #define EXPECT_EQW ok(strncmpW(buffer, Expected, strlenW(Expected)) == 0, "Bad conversion\n")
108 #define NUO LOCALE_NOUSEROVERRIDE
110 static void test_GetLocaleInfoA(void)
114 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
115 char buffer[BUFFER_SIZE];
116 char expected[BUFFER_SIZE];
118 ok(lcid == 0x409, "wrong LCID calculated - %d\n", lcid);
120 /* en and ar use SUBLANG_NEUTRAL, but GetLocaleInfo assume SUBLANG_DEFAULT
121 Same is true for zh on pre-Vista, but on Vista and higher GetLocaleInfo
122 assumes SUBLANG_NEUTRAL for zh */
123 memset(expected, 0, COUNTOF(expected));
124 len = GetLocaleInfoA(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
125 SetLastError(0xdeadbeef);
126 memset(buffer, 0, COUNTOF(buffer));
127 ret = GetLocaleInfoA(LANG_ENGLISH, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
128 ok((ret == len) && !lstrcmpA(buffer, expected),
129 "got %d with '%s' (expected %d with '%s')\n",
130 ret, buffer, len, expected);
132 memset(expected, 0, COUNTOF(expected));
133 len = GetLocaleInfoA(MAKELANGID(LANG_ARABIC, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
135 SetLastError(0xdeadbeef);
136 memset(buffer, 0, COUNTOF(buffer));
137 ret = GetLocaleInfoA(LANG_ARABIC, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
138 ok((ret == len) && !lstrcmpA(buffer, expected),
139 "got %d with '%s' (expected %d with '%s')\n",
140 ret, buffer, len, expected);
143 win_skip("LANG_ARABIC not installed\n");
145 /* SUBLANG_DEFAULT is required for mlang.dll, but optional for GetLocaleInfo */
146 memset(expected, 0, COUNTOF(expected));
147 len = GetLocaleInfoA(MAKELANGID(LANG_GERMAN, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
148 SetLastError(0xdeadbeef);
149 memset(buffer, 0, COUNTOF(buffer));
150 ret = GetLocaleInfoA(LANG_GERMAN, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
151 ok((ret == len) && !lstrcmpA(buffer, expected),
152 "got %d with '%s' (expected %d with '%s')\n",
153 ret, buffer, len, expected);
156 /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
157 * partially fill the buffer even if it is too short. See bug 637.
159 SetLastError(0xdeadbeef);
160 memset(buffer, 0, COUNTOF(buffer));
161 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 0);
162 ok(ret == 7 && !buffer[0], "Expected len=7, got %d\n", ret);
164 SetLastError(0xdeadbeef);
165 memset(buffer, 0, COUNTOF(buffer));
166 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 3);
167 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
168 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
169 ok(!strcmp(buffer, "Mon"), "Expected 'Mon', got '%s'\n", buffer);
171 SetLastError(0xdeadbeef);
172 memset(buffer, 0, COUNTOF(buffer));
173 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 10);
174 ok(ret == 7, "Expected ret == 7, got %d, error %d\n", ret, GetLastError());
175 ok(!strcmp(buffer, "Monday"), "Expected 'Monday', got '%s'\n", buffer);
178 static void test_GetLocaleInfoW(void)
180 LCID lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
181 LCID lcid_ru = MAKELCID(MAKELANGID(LANG_RUSSIAN, SUBLANG_NEUTRAL), SORT_DEFAULT);
182 WCHAR bufferW[80], buffer2W[80];
187 ret = GetLocaleInfoW(lcid_en, LOCALE_SMONTHNAME1, bufferW, COUNTOF(bufferW));
189 win_skip("GetLocaleInfoW() isn't implemented\n");
192 ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1, bufferW, COUNTOF(bufferW));
194 win_skip("LANG_RUSSIAN locale data unavailable\n");
197 ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1|LOCALE_RETURN_GENITIVE_NAMES,
198 bufferW, COUNTOF(bufferW));
200 win_skip("LOCALE_RETURN_GENITIVE_NAMES isn't supported\n");
204 /* LOCALE_RETURN_GENITIVE_NAMES isn't supported for GetLocaleInfoA */
206 SetLastError(0xdeadbeef);
207 ret = GetLocaleInfoA(lcid_ru, LOCALE_SMONTHNAME1|LOCALE_RETURN_GENITIVE_NAMES,
208 bufferA, COUNTOF(bufferA));
209 ok(ret == 0, "LOCALE_RETURN_GENITIVE_NAMES should fail with GetLocaleInfoA\n");
210 ok(bufferA[0] == 'a', "Expected buffer to be untouched\n");
211 ok(GetLastError() == ERROR_INVALID_FLAGS,
212 "Expected ERROR_INVALID_FLAGS, got %x\n", GetLastError());
215 SetLastError(0xdeadbeef);
216 ret = GetLocaleInfoW(lcid_ru, LOCALE_RETURN_GENITIVE_NAMES,
217 bufferW, COUNTOF(bufferW));
219 "LOCALE_RETURN_GENITIVE_NAMES itself doesn't return anything, got %d\n", ret);
220 ok(bufferW[0] == 'a', "Expected buffer to be untouched\n");
221 ok(GetLastError() == ERROR_INVALID_FLAGS,
222 "Expected ERROR_INVALID_FLAGS, got %x\n", GetLastError());
224 /* yes, test empty 13 month entry too */
225 for (i = 0; i < 12; i++) {
227 ret = GetLocaleInfoW(lcid_ru, (LOCALE_SMONTHNAME1+i)|LOCALE_RETURN_GENITIVE_NAMES,
228 bufferW, COUNTOF(bufferW));
229 ok(ret, "Expected non zero result\n");
230 ok(ret == lstrlenW(bufferW)+1, "Expected actual length, got %d, length %d\n",
231 ret, lstrlenW(bufferW));
233 ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1+i,
234 buffer2W, COUNTOF(buffer2W));
235 ok(ret, "Expected non zero result\n");
236 ok(ret == lstrlenW(buffer2W)+1, "Expected actual length, got %d, length %d\n",
237 ret, lstrlenW(buffer2W));
239 ok(lstrcmpW(bufferW, buffer2W) != 0,
240 "Expected genitive name to differ, got the same for month %d\n", i+1);
242 /* for locale without genitive names nominative returned in both cases */
244 ret = GetLocaleInfoW(lcid_en, (LOCALE_SMONTHNAME1+i)|LOCALE_RETURN_GENITIVE_NAMES,
245 bufferW, COUNTOF(bufferW));
246 ok(ret, "Expected non zero result\n");
247 ok(ret == lstrlenW(bufferW)+1, "Expected actual length, got %d, length %d\n",
248 ret, lstrlenW(bufferW));
250 ret = GetLocaleInfoW(lcid_en, LOCALE_SMONTHNAME1+i,
251 buffer2W, COUNTOF(buffer2W));
252 ok(ret, "Expected non zero result\n");
253 ok(ret == lstrlenW(buffer2W)+1, "Expected actual length, got %d, length %d\n",
254 ret, lstrlenW(buffer2W));
256 ok(lstrcmpW(bufferW, buffer2W) == 0,
257 "Expected same names, got different for month %d\n", i+1);
261 static void test_GetTimeFormatA(void)
265 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
266 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
268 memset(&curtime, 2, sizeof(SYSTEMTIME));
269 STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
270 SetLastError(0xdeadbeef);
271 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
272 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
273 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
276 curtime.wMinute = 56;
277 curtime.wSecond = 13;
278 curtime.wMilliseconds = 22;
279 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
280 SetLastError(0xdeadbeef);
281 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
282 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
283 EXPECT_LENA; EXPECT_EQA;
285 /* MSDN: LOCALE_NOUSEROVERRIDE can't be specified with a format string */
286 SetLastError(0xdeadbeef);
287 ret = GetTimeFormatA(lcid, NUO|TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
288 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
289 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
291 STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficient buffer */
292 SetLastError(0xdeadbeef);
293 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, 2);
294 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
295 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
297 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
298 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, NULL, 0);
299 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
302 STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
303 ret = GetTimeFormatA(lcid, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
304 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
305 EXPECT_LENA; EXPECT_EQA;
307 STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
308 ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
309 ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
310 ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "4" )), /* win9x */
311 "Expected '', got '%s'\n", buffer );
313 STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
314 ret = GetTimeFormatA(lcid, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
315 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
316 EXPECT_LENA; EXPECT_EQA;
318 STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
319 strcpy(Expected, "8:56 AM");
320 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
321 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
322 EXPECT_LENA; EXPECT_EQA;
324 STRINGSA("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
325 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
326 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
327 ok( !strcmp( buffer, "8.@:56AM" ) || broken( !strcmp( buffer, "8.@:56.@:AM" )) /* win9x */,
328 "Expected '8.@:56AM', got '%s'\n", buffer );
330 STRINGSA("s1s2s3", ""); /* Duplicate tokens */
331 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
332 ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
333 ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "3" )), /* win9x */
334 "Expected '', got '%s'\n", buffer );
336 STRINGSA("t/tt", "A/AM"); /* AM time marker */
337 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
338 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
339 EXPECT_LENA; EXPECT_EQA;
342 STRINGSA("t/tt", "P/PM"); /* PM time marker */
343 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
344 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
345 EXPECT_LENA; EXPECT_EQA;
347 STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
348 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
349 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
350 EXPECT_LENA; EXPECT_EQA;
352 STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
353 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
354 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
355 EXPECT_LENA; EXPECT_EQA;
357 STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
358 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
359 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
360 EXPECT_LENA; EXPECT_EQA;
362 curtime.wHour = 14; /* change this to 14 or 2pm */
365 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 */
366 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
367 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
368 EXPECT_LENA; EXPECT_EQA;
371 STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
372 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
373 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
374 EXPECT_LENA; EXPECT_EQA;
376 STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
377 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
378 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
379 EXPECT_LENA; EXPECT_EQA;
381 /* try to convert formatting strings with more than two letters
382 * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
383 * NOTE: We expect any letter for which there is an upper case value
384 * we should see a replacement. For letters that DO NOT have
385 * upper case values we should see NO REPLACEMENT.
388 curtime.wMinute = 56;
389 curtime.wSecond = 13;
390 curtime.wMilliseconds = 22;
391 STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
392 "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
393 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
394 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
395 EXPECT_LENA; EXPECT_EQA;
397 STRINGSA("h", "text"); /* Don't write to buffer if len is 0 */
398 strcpy(buffer, "text");
399 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, 0);
400 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
403 STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
404 "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
405 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
406 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
407 EXPECT_LENA; EXPECT_EQA;
409 STRINGSA("'''", "'"); /* invalid quoted string */
410 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
411 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
412 EXPECT_LENA; EXPECT_EQA;
414 /* test that msdn suggested single quotation usage works as expected */
415 STRINGSA("''''", "'"); /* single quote mark */
416 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
417 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
418 EXPECT_LENA; EXPECT_EQA;
420 STRINGSA("''HHHHHH", "08"); /* Normal use */
421 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
422 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
423 EXPECT_LENA; EXPECT_EQA;
425 /* and test for normal use of the single quotation mark */
426 STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
427 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
428 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
429 EXPECT_LENA; EXPECT_EQA;
431 STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
432 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
433 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
434 EXPECT_LENA; EXPECT_EQA;
436 STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
437 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
438 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
439 EXPECT_LENA; EXPECT_EQA;
442 STRINGSA("'123'tt", ""); /* Invalid time */
443 SetLastError(0xdeadbeef);
444 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
445 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
446 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
449 curtime.wMonth = 60; /* Invalid */
450 STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
451 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
452 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
453 EXPECT_LENA; EXPECT_EQA;
456 static void test_GetDateFormatA(void)
460 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
461 LCID lcid_ru = MAKELCID(MAKELANGID(LANG_RUSSIAN, SUBLANG_NEUTRAL), SORT_DEFAULT);
462 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
463 char Broken[BUFFER_SIZE];
464 char short_day[10], month[10], genitive_month[10];
466 memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
467 STRINGSA("ddd',' MMM dd yy","");
468 SetLastError(0xdeadbeef);
469 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
470 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
471 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
473 curtime.wYear = 2002;
476 curtime.wDayOfWeek = 3;
477 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
478 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
479 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
480 EXPECT_LENA; EXPECT_EQA;
482 /* Same as above but with LOCALE_NOUSEROVERRIDE */
483 STRINGSA("ddd',' MMM dd yy",""); /* Simple case */
484 SetLastError(0xdeadbeef);
485 ret = GetDateFormatA(lcid, NUO, &curtime, input, buffer, COUNTOF(buffer));
486 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
487 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
490 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
491 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
492 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
493 EXPECT_LENA; EXPECT_EQA;
495 curtime.wHour = 36; /* Invalid */
496 STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
497 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
498 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
499 EXPECT_LENA; EXPECT_EQA;
501 STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
502 ret = GetDateFormatA(lcid, 0, &curtime, input, NULL, 0);
503 ok(ret == 16, "Expected ret == 16, got %d, error %d\n", ret, GetLastError());
506 STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
507 SetLastError(0xdeadbeef);
508 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, 2);
509 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
510 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
512 STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
513 ret = GetDateFormat(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
514 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
515 if (strncmp(buffer, Expected, strlen(Expected)) && strncmp(buffer, "5/4/02", strlen(Expected)) != 0)
516 ok (0, "Expected '%s' or '5/4/02', got '%s'\n", Expected, buffer);
518 STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
519 ret = GetDateFormat(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
520 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
521 EXPECT_LENA; EXPECT_EQA;
523 /* test for expected DATE_YEARMONTH behavior with null format */
524 /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
525 STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
526 SetLastError(0xdeadbeef);
527 ret = GetDateFormat(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
528 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
529 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
532 /* Test that using invalid DATE_* flags results in the correct error */
533 /* and return values */
534 STRINGSA("m/d/y", ""); /* Invalid flags */
535 SetLastError(0xdeadbeef);
536 ret = GetDateFormat(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
537 &curtime, input, buffer, COUNTOF(buffer));
538 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
539 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
541 ret = GetDateFormat(lcid_ru, 0, &curtime, "ddMMMM", buffer, COUNTOF(buffer));
544 win_skip("LANG_RUSSIAN locale data unavailable\n");
548 /* month part should be in genitive form */
549 strcpy(genitive_month, buffer + 2);
550 ret = GetDateFormat(lcid_ru, 0, &curtime, "MMMM", buffer, COUNTOF(buffer));
551 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
552 strcpy(month, buffer);
553 ok(strcmp(genitive_month, month) != 0, "Expected different month forms\n");
555 ret = GetDateFormat(lcid_ru, 0, &curtime, "ddd", buffer, COUNTOF(buffer));
556 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
557 strcpy(short_day, buffer);
559 STRINGSA("dd MMMMddd dd", "");
560 sprintf(Expected, "04 %s%s 04", genitive_month, short_day);
561 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
562 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
565 STRINGSA("MMMMddd dd", "");
566 sprintf(Expected, "%s%s 04", month, short_day);
567 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
568 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
571 STRINGSA("MMMMddd", "");
572 sprintf(Expected, "%s%s", month, short_day);
573 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
574 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
577 STRINGSA("MMMMdd", "");
578 sprintf(Expected, "%s04", genitive_month);
579 sprintf(Broken, "%s04", month);
580 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
581 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
582 ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
583 broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
584 "Expected '%s', got '%s'\n", Expected, buffer);
586 STRINGSA("MMMMdd ddd", "");
587 sprintf(Expected, "%s04 %s", genitive_month, short_day);
588 sprintf(Broken, "%s04 %s", month, short_day);
589 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
590 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
591 ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
592 broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
593 "Expected '%s', got '%s'\n", Expected, buffer);
595 STRINGSA("dd dddMMMM", "");
596 sprintf(Expected, "04 %s%s", short_day, month);
597 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
598 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
601 STRINGSA("dd dddMMMM ddd MMMMdd", "");
602 sprintf(Expected, "04 %s%s %s %s04", short_day, month, short_day, genitive_month);
603 sprintf(Broken, "04 %s%s %s %s04", short_day, month, short_day, month);
604 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
605 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
606 ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
607 broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
608 "Expected '%s', got '%s'\n", Expected, buffer);
610 /* with literal part */
611 STRINGSA("ddd',' MMMM dd", "");
612 sprintf(Expected, "%s, %s 04", short_day, genitive_month);
613 sprintf(Broken, "%s, %s 04", short_day, month);
614 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
615 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
616 ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
617 broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
618 "Expected '%s', got '%s'\n", Expected, buffer);
621 static void test_GetDateFormatW(void)
625 WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
626 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
628 STRINGSW("",""); /* If flags is not zero then format must be NULL */
629 ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL,
630 input, buffer, COUNTOF(buffer));
631 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
633 win_skip("GetDateFormatW is not implemented\n");
636 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
637 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
640 STRINGSW("",""); /* NULL buffer, len > 0 */
641 SetLastError(0xdeadbeef);
642 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
643 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
644 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
646 STRINGSW("",""); /* NULL buffer, len == 0 */
647 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
648 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
649 EXPECT_LENW; EXPECT_EQW;
651 curtime.wYear = 2002;
654 curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
655 curtime.wHour = 65432; /* Invalid */
656 curtime.wMinute = 34512; /* Invalid */
657 curtime.wSecond = 65535; /* Invalid */
658 curtime.wMilliseconds = 12345;
659 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
660 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
661 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
662 EXPECT_LENW; EXPECT_EQW;
666 curtime.wYear = 1601;
669 curtime.wDayOfWeek = 0; /* Irrelevant */
673 curtime.wMilliseconds = 0;
674 STRINGSW("dddd d MMMM yyyy","Monday 1 January 1601");
675 SetLastError(0xdeadbeef);
676 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
677 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
678 EXPECT_LENW; EXPECT_EQW;
680 curtime.wYear = 1600;
683 curtime.wDayOfWeek = 0; /* Irrelevant */
685 curtime.wMinute = 59;
686 curtime.wSecond = 59;
687 curtime.wMilliseconds = 999;
688 STRINGSW("dddd d MMMM yyyy","Friday 31 December 1600");
689 SetLastError(0xdeadbeef);
690 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
691 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
692 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
696 #define CY_POS_LEFT 0
697 #define CY_POS_RIGHT 1
698 #define CY_POS_LEFT_SPACE 2
699 #define CY_POS_RIGHT_SPACE 3
701 static void test_GetCurrencyFormatA(void)
703 static char szDot[] = { '.', '\0' };
704 static char szComma[] = { ',', '\0' };
705 static char szDollar[] = { '$', '\0' };
707 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
708 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
711 memset(&format, 0, sizeof(format));
713 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
714 SetLastError(0xdeadbeef);
715 ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
716 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
717 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
719 STRINGSA("23,53",""); /* Invalid character --> Error */
720 SetLastError(0xdeadbeef);
721 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
722 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
723 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
725 STRINGSA("--",""); /* Double '-' --> Error */
726 SetLastError(0xdeadbeef);
727 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
728 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
729 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
731 STRINGSA("0-",""); /* Trailing '-' --> Error */
732 SetLastError(0xdeadbeef);
733 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
734 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
735 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
737 STRINGSA("0..",""); /* Double '.' --> Error */
738 SetLastError(0xdeadbeef);
739 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
740 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
741 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
743 STRINGSA(" 0.1",""); /* Leading space --> Error */
744 SetLastError(0xdeadbeef);
745 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
746 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
747 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
749 STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
750 SetLastError(0xdeadbeef);
751 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, 2);
752 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
753 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
755 STRINGSA("2353",""); /* Format and flags given --> Error */
756 SetLastError(0xdeadbeef);
757 ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
758 ok( !ret, "Expected ret == 0, got %d\n", ret);
759 ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
760 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
762 STRINGSA("2353",""); /* Invalid format --> Error */
763 SetLastError(0xdeadbeef);
764 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
765 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
766 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
768 STRINGSA("2353","$2,353.00"); /* Valid number */
769 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
770 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
771 EXPECT_LENA; EXPECT_EQA;
773 STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
774 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
775 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
776 EXPECT_LENA; EXPECT_EQA;
778 STRINGSA("2353.1","$2,353.10"); /* Valid real number */
779 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
780 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
781 EXPECT_LENA; EXPECT_EQA;
783 STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
784 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
785 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
786 EXPECT_LENA; EXPECT_EQA;
788 STRINGSA("2353.119","$2,353.12"); /* Too many DP --> Rounded */
789 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
790 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
791 EXPECT_LENA; EXPECT_EQA;
793 format.NumDigits = 0; /* No decimal separator */
794 format.LeadingZero = 0;
795 format.Grouping = 0; /* No grouping char */
796 format.NegativeOrder = 0;
797 format.PositiveOrder = CY_POS_LEFT;
798 format.lpDecimalSep = szDot;
799 format.lpThousandSep = szComma;
800 format.lpCurrencySymbol = szDollar;
802 STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
803 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
804 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
805 EXPECT_LENA; EXPECT_EQA;
807 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
808 STRINGSA("2353","$2353.0");
809 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
810 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
811 EXPECT_LENA; EXPECT_EQA;
813 format.Grouping = 2; /* Group by 100's */
814 STRINGSA("2353","$23,53.0");
815 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
816 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
817 EXPECT_LENA; EXPECT_EQA;
819 STRINGSA("235","$235.0"); /* Grouping of a positive number */
821 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
822 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
823 EXPECT_LENA; EXPECT_EQA;
825 STRINGSA("-235","$-235.0"); /* Grouping of a negative number */
826 format.NegativeOrder = 2;
827 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
828 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
829 EXPECT_LENA; EXPECT_EQA;
831 format.LeadingZero = 1; /* Always provide leading zero */
832 STRINGSA(".5","$0.5");
833 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
834 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
835 EXPECT_LENA; EXPECT_EQA;
837 format.PositiveOrder = CY_POS_RIGHT;
838 STRINGSA("1","1.0$");
839 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
840 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
841 EXPECT_LENA; EXPECT_EQA;
843 format.PositiveOrder = CY_POS_LEFT_SPACE;
844 STRINGSA("1","$ 1.0");
845 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
846 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
847 EXPECT_LENA; EXPECT_EQA;
849 format.PositiveOrder = CY_POS_RIGHT_SPACE;
850 STRINGSA("1","1.0 $");
851 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
852 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
853 EXPECT_LENA; EXPECT_EQA;
855 format.NegativeOrder = 0;
856 STRINGSA("-1","($1.0)");
857 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
858 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
859 EXPECT_LENA; EXPECT_EQA;
861 format.NegativeOrder = 1;
862 STRINGSA("-1","-$1.0");
863 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
864 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
865 EXPECT_LENA; EXPECT_EQA;
867 format.NegativeOrder = 2;
868 STRINGSA("-1","$-1.0");
869 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
870 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
871 EXPECT_LENA; EXPECT_EQA;
873 format.NegativeOrder = 3;
874 STRINGSA("-1","$1.0-");
875 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
876 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
877 EXPECT_LENA; EXPECT_EQA;
879 format.NegativeOrder = 4;
880 STRINGSA("-1","(1.0$)");
881 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
882 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
883 EXPECT_LENA; EXPECT_EQA;
885 format.NegativeOrder = 5;
886 STRINGSA("-1","-1.0$");
887 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
888 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
889 EXPECT_LENA; EXPECT_EQA;
891 format.NegativeOrder = 6;
892 STRINGSA("-1","1.0-$");
893 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
894 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
895 EXPECT_LENA; EXPECT_EQA;
897 format.NegativeOrder = 7;
898 STRINGSA("-1","1.0$-");
899 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
900 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
901 EXPECT_LENA; EXPECT_EQA;
903 format.NegativeOrder = 8;
904 STRINGSA("-1","-1.0 $");
905 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
906 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
907 EXPECT_LENA; EXPECT_EQA;
909 format.NegativeOrder = 9;
910 STRINGSA("-1","-$ 1.0");
911 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
912 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
913 EXPECT_LENA; EXPECT_EQA;
915 format.NegativeOrder = 10;
916 STRINGSA("-1","1.0 $-");
917 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
918 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
919 EXPECT_LENA; EXPECT_EQA;
921 format.NegativeOrder = 11;
922 STRINGSA("-1","$ 1.0-");
923 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
924 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
925 EXPECT_LENA; EXPECT_EQA;
927 format.NegativeOrder = 12;
928 STRINGSA("-1","$ -1.0");
929 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
930 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
931 EXPECT_LENA; EXPECT_EQA;
933 format.NegativeOrder = 13;
934 STRINGSA("-1","1.0- $");
935 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
936 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
937 EXPECT_LENA; EXPECT_EQA;
939 format.NegativeOrder = 14;
940 STRINGSA("-1","($ 1.0)");
941 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
942 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
943 EXPECT_LENA; EXPECT_EQA;
945 format.NegativeOrder = 15;
946 STRINGSA("-1","(1.0 $)");
947 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
948 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
949 EXPECT_LENA; EXPECT_EQA;
952 #define NEG_PARENS 0 /* "(1.1)" */
953 #define NEG_LEFT 1 /* "-1.1" */
954 #define NEG_LEFT_SPACE 2 /* "- 1.1" */
955 #define NEG_RIGHT 3 /* "1.1-" */
956 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
958 static void test_GetNumberFormatA(void)
960 static char szDot[] = { '.', '\0' };
961 static char szComma[] = { ',', '\0' };
963 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
964 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
967 memset(&format, 0, sizeof(format));
969 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
970 SetLastError(0xdeadbeef);
971 ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
972 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
973 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
975 STRINGSA("23,53",""); /* Invalid character --> Error */
976 SetLastError(0xdeadbeef);
977 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
978 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
979 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
981 STRINGSA("--",""); /* Double '-' --> Error */
982 SetLastError(0xdeadbeef);
983 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
984 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
985 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
987 STRINGSA("0-",""); /* Trailing '-' --> Error */
988 SetLastError(0xdeadbeef);
989 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
990 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
991 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
993 STRINGSA("0..",""); /* Double '.' --> Error */
994 SetLastError(0xdeadbeef);
995 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
996 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
997 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
999 STRINGSA(" 0.1",""); /* Leading space --> Error */
1000 SetLastError(0xdeadbeef);
1001 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1002 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1003 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1005 STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
1006 SetLastError(0xdeadbeef);
1007 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, 2);
1008 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1009 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1011 STRINGSA("2353",""); /* Format and flags given --> Error */
1012 SetLastError(0xdeadbeef);
1013 ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
1014 ok( !ret, "Expected ret == 0, got %d\n", ret);
1015 ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
1016 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1018 STRINGSA("2353",""); /* Invalid format --> Error */
1019 SetLastError(0xdeadbeef);
1020 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1021 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1022 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1024 STRINGSA("2353","2,353.00"); /* Valid number */
1025 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1026 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1027 EXPECT_LENA; EXPECT_EQA;
1029 STRINGSA("-2353","-2,353.00"); /* Valid negative number */
1030 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1031 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1032 EXPECT_LENA; EXPECT_EQA;
1034 STRINGSA("-353","-353.00"); /* test for off by one error in grouping */
1035 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1036 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1037 EXPECT_LENA; EXPECT_EQA;
1039 STRINGSA("2353.1","2,353.10"); /* Valid real number */
1040 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1041 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1042 EXPECT_LENA; EXPECT_EQA;
1044 STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
1045 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1046 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1047 EXPECT_LENA; EXPECT_EQA;
1049 STRINGSA("2353.119","2,353.12"); /* Too many DP --> Rounded */
1050 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1051 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1052 EXPECT_LENA; EXPECT_EQA;
1054 format.NumDigits = 0; /* No decimal separator */
1055 format.LeadingZero = 0;
1056 format.Grouping = 0; /* No grouping char */
1057 format.NegativeOrder = 0;
1058 format.lpDecimalSep = szDot;
1059 format.lpThousandSep = szComma;
1061 STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
1062 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1063 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1064 EXPECT_LENA; EXPECT_EQA;
1066 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
1067 STRINGSA("2353","2353.0");
1068 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1069 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1070 EXPECT_LENA; EXPECT_EQA;
1072 format.Grouping = 2; /* Group by 100's */
1073 STRINGSA("2353","23,53.0");
1074 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1075 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1076 EXPECT_LENA; EXPECT_EQA;
1078 STRINGSA("235","235.0"); /* Grouping of a positive number */
1079 format.Grouping = 3;
1080 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1081 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1082 EXPECT_LENA; EXPECT_EQA;
1084 STRINGSA("-235","-235.0"); /* Grouping of a negative number */
1085 format.NegativeOrder = NEG_LEFT;
1086 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1087 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1088 EXPECT_LENA; EXPECT_EQA;
1090 format.LeadingZero = 1; /* Always provide leading zero */
1091 STRINGSA(".5","0.5");
1092 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1093 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1094 EXPECT_LENA; EXPECT_EQA;
1096 format.NegativeOrder = NEG_PARENS;
1097 STRINGSA("-1","(1.0)");
1098 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1099 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1100 EXPECT_LENA; EXPECT_EQA;
1102 format.NegativeOrder = NEG_LEFT;
1103 STRINGSA("-1","-1.0");
1104 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1105 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1106 EXPECT_LENA; EXPECT_EQA;
1108 format.NegativeOrder = NEG_LEFT_SPACE;
1109 STRINGSA("-1","- 1.0");
1110 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1111 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1112 EXPECT_LENA; EXPECT_EQA;
1114 format.NegativeOrder = NEG_RIGHT;
1115 STRINGSA("-1","1.0-");
1116 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1117 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1118 EXPECT_LENA; EXPECT_EQA;
1120 format.NegativeOrder = NEG_RIGHT_SPACE;
1121 STRINGSA("-1","1.0 -");
1122 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1123 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1124 EXPECT_LENA; EXPECT_EQA;
1126 lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
1128 if (IsValidLocale(lcid, 0))
1130 STRINGSA("-12345","-12 345,00"); /* Try French formatting */
1131 Expected[3] = 160; /* Non breaking space */
1132 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1133 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1134 EXPECT_LENA; EXPECT_EQA;
1139 static void test_CompareStringA(void)
1142 LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
1144 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
1145 ok (ret== 1, "(Salut/Salute) Expected 1, got %d\n", ret);
1147 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
1148 ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
1150 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
1151 ok (ret== 3, "(Salut/hola) Expected 3, got %d\n", ret);
1153 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
1154 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
1156 lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
1158 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
1159 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
1161 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
1162 ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
1164 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
1165 ok (ret == 2, "(Salut/saLuT) Expected 2, got %d\n", ret);
1167 /* test for CompareStringA flags */
1168 SetLastError(0xdeadbeef);
1169 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0x8, "NULL", -1, "NULL", -1);
1170 ok(GetLastError() == ERROR_INVALID_FLAGS,
1171 "unexpected error code %d\n", GetLastError());
1172 ok(!ret, "CompareStringA must fail with invalid flag\n");
1174 SetLastError(0xdeadbeef);
1175 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, LOCALE_USE_CP_ACP, "NULL", -1, "NULL", -1);
1176 ok(GetLastError() == 0xdeadbeef, "unexpected error code %d\n", GetLastError());
1177 ok(ret == CSTR_EQUAL, "CompareStringA error: %d != CSTR_EQUAL\n", ret);
1178 /* end of test for CompareStringA flags */
1180 ret = lstrcmpA("", "");
1181 ok (ret == 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret);
1183 ret = lstrcmpA(NULL, NULL);
1184 ok (ret == 0 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, NULL) should return 0, got %d\n", ret);
1186 ret = lstrcmpA("", NULL);
1187 ok (ret == 1 || broken(ret == -2) /* win9x */, "lstrcmpA(\"\", NULL) should return 1, got %d\n", ret);
1189 ret = lstrcmpA(NULL, "");
1190 ok (ret == -1 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret);
1192 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"EndDialog",-1,"_Property",-1);
1193 ok( ret == 3, "EndDialog vs _Property ... expected 3, got %d\n", ret);
1195 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0070",-1,"_IEWWBrowserComp",-1);
1196 ok( ret == 3, "osp_vba.sreg0070 vs _IEWWBrowserComp ... expected 3, got %d\n", ret);
1198 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"r",-1,"\\",-1);
1199 ok( ret == 3, "r vs \\ ... expected 3, got %d\n", ret);
1201 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0031", -1, "OriginalDatabase", -1 );
1202 ok( ret == 3, "osp_vba.sreg0031 vs OriginalDatabase ... expected 3, got %d\n", ret);
1204 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1 );
1205 ok( ret == 3, "AAA vs aaa expected 3, got %d\n", ret);
1207 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1 );
1208 ok( ret == 1, "AAA vs aab expected 1, got %d\n", ret);
1210 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1 );
1211 ok( ret == 1, "AAA vs Aab expected 1, got %d\n", ret);
1213 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1 );
1214 ok( ret == 1, ".AAA vs Aab expected 1, got %d\n", ret);
1216 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1 );
1217 ok( ret == 1, ".AAA vs A.ab expected 1, got %d\n", ret);
1219 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1 );
1220 ok( ret == 1, "aa vs AB expected 1, got %d\n", ret);
1222 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1 );
1223 ok( ret == 1, "aa vs Aab expected 1, got %d\n", ret);
1225 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1 );
1226 ok( ret == 3, "aB vs Aab expected 3, got %d\n", ret);
1228 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1 );
1229 ok( ret == 1, "Ba vs bab expected 1, got %d\n", ret);
1231 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1 );
1232 ok( ret == 1, "{100}{83}{71}{71}{71} vs Global_DataAccess_JRO expected 1, got %d\n", ret);
1234 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1 );
1235 ok( ret == 3, "a vs { expected 3, got %d\n", ret);
1237 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1 );
1238 ok( ret == 3, "A vs { expected 3, got %d\n", ret);
1240 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1 );
1241 ok(ret == 1, "3.5/0 vs 4.0/-1 expected 1, got %d\n", ret);
1243 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1 );
1244 ok(ret == 1, "3.5 vs 4.0 expected 1, got %d\n", ret);
1246 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1 );
1247 ok(ret == 1, "3.520.4403.2 vs 4.0.2927.10 expected 1, got %d\n", ret);
1249 /* hyphen and apostrophe are treated differently depending on
1250 * whether SORT_STRINGSORT specified or not
1252 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1 );
1253 ok(ret == 3, "-o vs /m expected 3, got %d\n", ret);
1255 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1 );
1256 ok(ret == 1, "/m vs -o expected 1, got %d\n", ret);
1258 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1 );
1259 ok(ret == 1, "-o vs /m expected 1, got %d\n", ret);
1261 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1 );
1262 ok(ret == 3, "/m vs -o expected 3, got %d\n", ret);
1264 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1 );
1265 ok(ret == 3, "'o vs /m expected 3, got %d\n", ret);
1267 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1 );
1268 ok(ret == 1, "/m vs 'o expected 1, got %d\n", ret);
1270 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1 );
1271 ok(ret == 1, "'o vs /m expected 1, got %d\n", ret);
1273 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1 );
1274 ok(ret == 3, "/m vs 'o expected 3, got %d\n", ret);
1276 if (0) { /* this requires collation table patch to make it MS compatible */
1277 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
1278 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
1280 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
1281 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
1283 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
1284 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
1286 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
1287 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
1289 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
1290 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
1292 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
1293 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
1295 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
1296 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
1298 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
1299 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
1301 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
1302 ok(ret == 1, "`o vs -m expected 1, got %d\n", ret);
1304 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
1305 ok(ret == 3, "-m vs `o expected 3, got %d\n", ret);
1307 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
1308 ok(ret == 3, "`o vs -m expected 3, got %d\n", ret);
1310 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
1311 ok(ret == 1, "-m vs `o expected 1, got %d\n", ret);
1314 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9);
1315 ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0 expected 2, got %d\n", ret);
1317 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10);
1318 ok(ret == 1, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1, got %d\n", ret);
1320 /* WinXP handles embedded NULLs differently than earlier versions */
1321 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
1322 ok(ret == 1 || ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1 or 2, got %d\n", ret);
1324 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
1325 ok(ret == 1 || ret == 2, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected 1 or 2, got %d\n", ret);
1327 ret = CompareStringA(lcid, 0, "a\0b", -1, "a", -1);
1328 ok(ret == 2, "a vs a expected 2, got %d\n", ret);
1330 ret = CompareStringA(lcid, 0, "a\0b", 4, "a", 2);
1331 ok(ret == CSTR_EQUAL || /* win2k */
1332 ret == CSTR_GREATER_THAN,
1333 "a\\0b vs a expected CSTR_EQUAL or CSTR_GREATER_THAN, got %d\n", ret);
1335 ret = CompareStringA(lcid, 0, "\2", 2, "\1", 2);
1336 todo_wine ok(ret != 2, "\\2 vs \\1 expected unequal\n");
1338 ret = CompareStringA(lcid, NORM_IGNORECASE | LOCALE_USE_CP_ACP, "#", -1, ".", -1);
1339 todo_wine ok(ret == CSTR_LESS_THAN, "\"#\" vs \".\" expected CSTR_LESS_THAN, got %d\n", ret);
1341 ret = CompareStringA(lcid, NORM_IGNORECASE, "_", -1, ".", -1);
1342 todo_wine ok(ret == CSTR_GREATER_THAN, "\"_\" vs \".\" expected CSTR_GREATER_THAN, got %d\n", ret);
1344 ret = lstrcmpi("#", ".");
1345 todo_wine ok(ret == -1, "\"#\" vs \".\" expected -1, got %d\n", ret);
1348 static void test_LCMapStringA(void)
1351 char buf[256], buf2[256];
1352 static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
1353 static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
1354 static const char symbols_stripped[] = "justateststring1";
1356 SetLastError(0xdeadbeef);
1357 ret = LCMapStringA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP | LCMAP_LOWERCASE,
1358 lower_case, -1, buf, sizeof(buf));
1359 ok(ret == lstrlenA(lower_case) + 1,
1360 "ret %d, error %d, expected value %d\n",
1361 ret, GetLastError(), lstrlenA(lower_case) + 1);
1362 ok(!memcmp(buf, lower_case, ret), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1364 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1365 upper_case, -1, buf, sizeof(buf));
1366 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1367 ok(GetLastError() == ERROR_INVALID_FLAGS,
1368 "unexpected error code %d\n", GetLastError());
1370 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1371 upper_case, -1, buf, sizeof(buf));
1372 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1373 ok(GetLastError() == ERROR_INVALID_FLAGS,
1374 "unexpected error code %d\n", GetLastError());
1376 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1377 upper_case, -1, buf, sizeof(buf));
1378 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1379 ok(GetLastError() == ERROR_INVALID_FLAGS,
1380 "unexpected error code %d\n", GetLastError());
1382 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1383 upper_case, -1, buf, sizeof(buf));
1384 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1385 ok(GetLastError() == ERROR_INVALID_FLAGS,
1386 "unexpected error code %d\n", GetLastError());
1388 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1389 SetLastError(0xdeadbeef);
1390 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1391 upper_case, -1, buf, sizeof(buf));
1392 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1393 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1395 /* test LCMAP_LOWERCASE */
1396 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1397 upper_case, -1, buf, sizeof(buf));
1398 ok(ret == lstrlenA(upper_case) + 1,
1399 "ret %d, error %d, expected value %d\n",
1400 ret, GetLastError(), lstrlenA(upper_case) + 1);
1401 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1403 /* test LCMAP_UPPERCASE */
1404 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1405 lower_case, -1, buf, sizeof(buf));
1406 ok(ret == lstrlenA(lower_case) + 1,
1407 "ret %d, error %d, expected value %d\n",
1408 ret, GetLastError(), lstrlenA(lower_case) + 1);
1409 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1411 /* test buffer overflow */
1412 SetLastError(0xdeadbeef);
1413 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1414 lower_case, -1, buf, 4);
1415 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1416 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1418 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1419 lstrcpyA(buf, lower_case);
1420 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1421 buf, -1, buf, sizeof(buf));
1422 if (!ret) /* Win9x */
1423 trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1426 ok(ret == lstrlenA(lower_case) + 1,
1427 "ret %d, error %d, expected value %d\n",
1428 ret, GetLastError(), lstrlenA(lower_case) + 1);
1429 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1431 lstrcpyA(buf, upper_case);
1432 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1433 buf, -1, buf, sizeof(buf));
1434 if (!ret) /* Win9x */
1435 trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1438 ok(ret == lstrlenA(upper_case) + 1,
1439 "ret %d, error %d, expected value %d\n",
1440 ret, GetLastError(), lstrlenA(lower_case) + 1);
1441 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1444 /* otherwise src == dst should fail */
1445 SetLastError(0xdeadbeef);
1446 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1447 buf, 10, buf, sizeof(buf));
1448 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1449 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1450 "unexpected error code %d\n", GetLastError());
1451 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1453 /* test whether '\0' is always appended */
1454 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1455 upper_case, -1, buf, sizeof(buf));
1456 ok(ret, "LCMapStringA must succeed\n");
1457 ok(buf[ret-1] == 0, "LCMapStringA not null-terminated\n");
1458 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1459 upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1460 ok(ret2, "LCMapStringA must succeed\n");
1461 ok(buf2[ret2-1] == 0, "LCMapStringA not null-terminated\n" );
1462 ok(ret == ret2, "lengths of sort keys must be equal\n");
1463 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1465 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1466 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1467 upper_case, -1, buf, sizeof(buf));
1468 ok(ret, "LCMapStringA must succeed\n");
1469 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1470 lower_case, -1, buf2, sizeof(buf2));
1471 ok(ret2, "LCMapStringA must succeed\n");
1472 ok(ret == ret2, "lengths of sort keys must be equal\n");
1473 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1475 /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1476 results from plain LCMAP_SORTKEY on Vista */
1478 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1479 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1480 lower_case, -1, buf, sizeof(buf));
1481 ok(ret, "LCMapStringA must succeed\n");
1482 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1483 symbols_stripped, -1, buf2, sizeof(buf2));
1484 ok(ret2, "LCMapStringA must succeed\n");
1485 ok(ret == ret2, "lengths of sort keys must be equal\n");
1486 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1488 /* test NORM_IGNORENONSPACE */
1489 lstrcpyA(buf, "foo");
1490 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1491 lower_case, -1, buf, sizeof(buf));
1492 ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1493 lstrlenA(lower_case) + 1, ret);
1494 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1496 /* test NORM_IGNORESYMBOLS */
1497 lstrcpyA(buf, "foo");
1498 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1499 lower_case, -1, buf, sizeof(buf));
1500 ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1501 lstrlenA(symbols_stripped) + 1, ret);
1502 ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1504 /* test srclen = 0 */
1505 SetLastError(0xdeadbeef);
1506 ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1507 ok(!ret, "LCMapStringA should fail with srclen = 0\n");
1508 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1509 "unexpected error code %d\n", GetLastError());
1512 static void test_LCMapStringW(void)
1515 WCHAR buf[256], buf2[256];
1516 char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1517 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};
1518 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};
1519 static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
1520 static const WCHAR fooW[] = {'f','o','o',0};
1522 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1523 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1524 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1526 win_skip("LCMapStringW is not implemented\n");
1530 ok(lstrcmpW(buf, upper_case) == 0, "Expected upper case string\n");
1533 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1534 ok(GetLastError() == ERROR_INVALID_FLAGS,
1535 "unexpected error code %d\n", GetLastError());
1538 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1539 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1540 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1541 ok(GetLastError() == ERROR_INVALID_FLAGS,
1542 "unexpected error code %d\n", GetLastError());
1544 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1545 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1546 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1547 ok(GetLastError() == ERROR_INVALID_FLAGS,
1548 "unexpected error code %d\n", GetLastError());
1550 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1551 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1552 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1553 ok(GetLastError() == ERROR_INVALID_FLAGS,
1554 "unexpected error code %d\n", GetLastError());
1556 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1557 SetLastError(0xdeadbeef);
1558 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1559 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1560 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1561 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1563 /* test LCMAP_LOWERCASE */
1564 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1565 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1566 ok(ret == lstrlenW(upper_case) + 1,
1567 "ret %d, error %d, expected value %d\n",
1568 ret, GetLastError(), lstrlenW(upper_case) + 1);
1569 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1571 /* test LCMAP_UPPERCASE */
1572 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1573 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1574 ok(ret == lstrlenW(lower_case) + 1,
1575 "ret %d, error %d, expected value %d\n",
1576 ret, GetLastError(), lstrlenW(lower_case) + 1);
1577 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1579 /* test buffer overflow */
1580 SetLastError(0xdeadbeef);
1581 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1582 lower_case, -1, buf, 4);
1583 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1584 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1586 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1587 lstrcpyW(buf, lower_case);
1588 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1589 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1590 ok(ret == lstrlenW(lower_case) + 1,
1591 "ret %d, error %d, expected value %d\n",
1592 ret, GetLastError(), lstrlenW(lower_case) + 1);
1593 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1595 lstrcpyW(buf, upper_case);
1596 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1597 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1598 ok(ret == lstrlenW(upper_case) + 1,
1599 "ret %d, error %d, expected value %d\n",
1600 ret, GetLastError(), lstrlenW(lower_case) + 1);
1601 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1603 /* otherwise src == dst should fail */
1604 SetLastError(0xdeadbeef);
1605 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1606 buf, 10, buf, sizeof(buf));
1607 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1608 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1609 "unexpected error code %d\n", GetLastError());
1610 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1612 /* test whether '\0' is always appended */
1613 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1614 upper_case, -1, buf, sizeof(buf));
1615 ok(ret, "LCMapStringW must succeed\n");
1616 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1617 upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1618 ok(ret, "LCMapStringW must succeed\n");
1619 ok(ret == ret2, "lengths of sort keys must be equal\n");
1620 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1622 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1623 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1624 upper_case, -1, buf, sizeof(buf));
1625 ok(ret, "LCMapStringW must succeed\n");
1626 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1627 lower_case, -1, buf2, sizeof(buf2));
1628 ok(ret2, "LCMapStringW must succeed\n");
1629 ok(ret == ret2, "lengths of sort keys must be equal\n");
1630 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1632 /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1633 results from plain LCMAP_SORTKEY on Vista */
1635 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1636 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1637 lower_case, -1, buf, sizeof(buf));
1638 ok(ret, "LCMapStringW must succeed\n");
1639 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1640 symbols_stripped, -1, buf2, sizeof(buf2));
1641 ok(ret2, "LCMapStringW must succeed\n");
1642 ok(ret == ret2, "lengths of sort keys must be equal\n");
1643 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1645 /* test NORM_IGNORENONSPACE */
1646 lstrcpyW(buf, fooW);
1647 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1648 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1649 ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1650 lstrlenW(lower_case) + 1, ret);
1651 ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1653 /* test NORM_IGNORESYMBOLS */
1654 lstrcpyW(buf, fooW);
1655 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1656 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1657 ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1658 lstrlenW(symbols_stripped) + 1, ret);
1659 ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1661 /* test srclen = 0 */
1662 SetLastError(0xdeadbeef);
1663 ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf)/sizeof(WCHAR));
1664 ok(!ret, "LCMapStringW should fail with srclen = 0\n");
1665 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1666 "unexpected error code %d\n", GetLastError());
1669 /* this requires collation table patch to make it MS compatible */
1670 static const char * const strings_sorted[] =
1702 static const char * const strings[] =
1734 static int compare_string1(const void *e1, const void *e2)
1736 const char *s1 = *(const char *const *)e1;
1737 const char *s2 = *(const char *const *)e2;
1739 return lstrcmpA(s1, s2);
1742 static int compare_string2(const void *e1, const void *e2)
1744 const char *s1 = *(const char *const *)e1;
1745 const char *s2 = *(const char *const *)e2;
1747 return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1750 static int compare_string3(const void *e1, const void *e2)
1752 const char *s1 = *(const char *const *)e1;
1753 const char *s2 = *(const char *const *)e2;
1754 char key1[256], key2[256];
1756 LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
1757 LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
1758 return strcmp(key1, key2);
1761 static void test_sorting(void)
1764 char **str_buf = (char **)buf;
1767 assert(sizeof(buf) >= sizeof(strings));
1769 /* 1. sort using lstrcmpA */
1770 memcpy(buf, strings, sizeof(strings));
1771 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
1772 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1774 ok(!strcmp(strings_sorted[i], str_buf[i]),
1775 "qsort using lstrcmpA failed for element %d\n", i);
1777 /* 2. sort using CompareStringA */
1778 memcpy(buf, strings, sizeof(strings));
1779 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
1780 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1782 ok(!strcmp(strings_sorted[i], str_buf[i]),
1783 "qsort using CompareStringA failed for element %d\n", i);
1785 /* 3. sort using sort keys */
1786 memcpy(buf, strings, sizeof(strings));
1787 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
1788 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1790 ok(!strcmp(strings_sorted[i], str_buf[i]),
1791 "qsort using sort keys failed for element %d\n", i);
1795 static void test_FoldStringA(void)
1799 char src[256], dst[256];
1800 static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0' };
1801 static const char digits_dst[] = { '1','2','3','\0' };
1802 static const char composite_src[] =
1804 0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
1805 0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
1806 0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
1807 0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
1808 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
1809 0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
1810 0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
1811 0xfb,0xfc,0xfd,0xff,'\0'
1813 static const char composite_dst[] =
1815 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1816 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1817 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1818 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1819 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1820 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1821 0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
1822 0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
1823 0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
1824 0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
1825 0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
1826 0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
1827 0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
1828 0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
1829 0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1831 static const char composite_dst_alt[] =
1833 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1834 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1835 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1836 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1837 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1838 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1839 0x4f,0x7e,0x4f,0xa8,0xd8,0x55,0x60,0x55,
1840 0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,0x61,
1841 0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,0x61,
1842 0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,0x65,
1843 0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,0x69,
1844 0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,0x6f,
1845 0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,0x6f,
1846 0xa8,0xf8,0x75,0x60,0x75,0xb4,0x75,0x5e,
1847 0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1849 static const char ligatures_src[] =
1851 0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1853 static const char ligatures_dst[] =
1855 'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1857 static const struct special
1861 } foldczone_special[] =
1864 { 0x85, { 0x2e, 0x2e, 0x2e, 0x00 } },
1865 { 0x98, { 0x20, 0x7e, 0x00 } },
1866 { 0x99, { 0x54, 0x4d, 0x00 } },
1867 { 0xa0, { 0x20, 0x00 } },
1868 { 0xa8, { 0x20, 0xa8, 0x00 } },
1869 { 0xaa, { 0x61, 0x00 } },
1870 { 0xaf, { 0x20, 0xaf, 0x00 } },
1871 { 0xb2, { 0x32, 0x00 } },
1872 { 0xb3, { 0x33, 0x00 } },
1873 { 0xb4, { 0x20, 0xb4, 0x00 } },
1874 { 0xb8, { 0x20, 0xb8, 0x00 } },
1875 { 0xb9, { 0x31, 0x00 } },
1876 { 0xba, { 0x6f, 0x00 } },
1877 { 0xbc, { 0x31, 0x2f, 0x34, 0x00 } },
1878 { 0xbd, { 0x31, 0x2f, 0x32, 0x00 } },
1879 { 0xbe, { 0x33, 0x2f, 0x34, 0x00 } },
1884 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1886 /* these tests are locale specific */
1887 if (GetACP() != 1252)
1889 trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1893 /* MAP_FOLDDIGITS */
1895 ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
1896 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1898 win_skip("FoldStringA is not implemented\n");
1901 ok(ret == 4, "Expected ret == 4, got %d, error %d\n", ret, GetLastError());
1902 ok(strcmp(dst, digits_dst) == 0,
1903 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
1904 for (i = 1; i < 256; i++)
1906 if (!strchr(digits_src, i))
1911 ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
1912 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1913 ok(dst[0] == src[0],
1914 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
1918 /* MAP_EXPAND_LIGATURES */
1920 ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1921 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1922 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1923 ok(ret == sizeof(ligatures_dst), "Got %d, error %d\n", ret, GetLastError());
1924 ok(strcmp(dst, ligatures_dst) == 0,
1925 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
1926 for (i = 1; i < 256; i++)
1928 if (!strchr(ligatures_src, i))
1933 ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1937 ok((i == 0xDC && lstrcmpA(dst, "UE") == 0) ||
1938 (i == 0xFC && lstrcmpA(dst, "ue") == 0),
1939 "Got %s for %d\n", dst, i);
1943 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1944 ok(dst[0] == src[0],
1945 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
1953 ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
1954 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1955 ok(ret == 121 || ret == 119, "Expected 121 or 119, got %d\n", ret);
1956 ok(strcmp(dst, composite_dst) == 0 || strcmp(dst, composite_dst_alt) == 0,
1957 "MAP_COMPOSITE: Mismatch, got '%s'\n", dst);
1959 for (i = 1; i < 256; i++)
1961 if (!strchr(composite_src, i))
1966 ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
1967 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1968 ok(dst[0] == src[0],
1969 "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
1970 (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
1975 for (i = 1; i < 256; i++)
1980 ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
1982 for (j = 0; foldczone_special[j].src != 0 && ! is_special; j++)
1984 if (foldczone_special[j].src == src[0])
1986 ok(ret == 2 || ret == lstrlenA(foldczone_special[j].dst) + 1,
1987 "Expected ret == 2 or %d, got %d, error %d\n",
1988 lstrlenA(foldczone_special[j].dst) + 1, ret, GetLastError());
1989 ok(src[0] == dst[0] || lstrcmpA(foldczone_special[j].dst, dst) == 0,
1990 "MAP_FOLDCZONE: string mismatch for 0x%02x\n",
1991 (unsigned char)src[0]);
1997 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1998 ok(src[0] == dst[0],
1999 "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
2000 (unsigned char)src[0], (unsigned char)dst[0]);
2004 /* MAP_PRECOMPOSED */
2005 for (i = 1; i < 256; i++)
2010 ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
2011 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2012 ok(src[0] == dst[0],
2013 "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
2014 (unsigned char)src[0], (unsigned char)dst[0]);
2018 static void test_FoldStringW(void)
2022 WCHAR src[256], dst[256], ch, prev_ch = 1;
2023 static const DWORD badFlags[] =
2026 MAP_PRECOMPOSED|MAP_COMPOSITE,
2027 MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
2028 MAP_COMPOSITE|MAP_EXPAND_LIGATURES
2030 /* Ranges of digits 0-9 : Must be sorted! */
2031 static const WCHAR digitRanges[] =
2033 0x0030, /* '0'-'9' */
2034 0x0660, /* Eastern Arabic */
2035 0x06F0, /* Arabic - Hindu */
2036 0x0966, /* Devengari */
2037 0x09E6, /* Bengalii */
2038 0x0A66, /* Gurmukhi */
2039 0x0AE6, /* Gujarati */
2041 0x0BE6, /* Tamil - No 0 */
2042 0x0C66, /* Telugu */
2043 0x0CE6, /* Kannada */
2044 0x0D66, /* Maylayalam */
2047 0x0F29, /* Tibet - 0 is out of sequence */
2048 0x2070, /* Superscript - 1, 2, 3 are out of sequence */
2049 0x2080, /* Subscript */
2050 0x245F, /* Circled - 0 is out of sequence */
2051 0x2473, /* Bracketed */
2052 0x2487, /* Full stop */
2053 0x2775, /* Inverted circled - No 0 */
2054 0x277F, /* Patterned circled - No 0 */
2055 0x2789, /* Inverted Patterned circled - No 0 */
2056 0x3020, /* Hangzhou */
2057 0xff10, /* Pliene chasse (?) */
2058 0xffff /* Terminator */
2060 /* Digits which are represented, but out of sequence */
2061 static const WCHAR outOfSequenceDigits[] =
2063 0xB9, /* Superscript 1 */
2064 0xB2, /* Superscript 2 */
2065 0xB3, /* Superscript 3 */
2066 0x0F33, /* Tibetan half zero */
2067 0x24EA, /* Circled 0 */
2068 0x3007, /* Ideographic number zero */
2069 '\0' /* Terminator */
2071 /* Digits in digitRanges for which no representation is available */
2072 static const WCHAR noDigitAvailable[] =
2074 0x0BE6, /* No Tamil 0 */
2075 0x0F29, /* No Tibetan half zero (out of sequence) */
2076 0x2473, /* No Bracketed 0 */
2077 0x2487, /* No 0 Full stop */
2078 0x2775, /* No inverted circled 0 */
2079 0x277F, /* No patterned circled */
2080 0x2789, /* No inverted Patterned circled */
2081 0x3020, /* No Hangzhou 0 */
2082 '\0' /* Terminator */
2084 static const WCHAR foldczone_src[] =
2086 'W', 'i', 'n', 'e', 0x0348, 0x0551, 0x1323, 0x280d,
2087 0xff37, 0xff49, 0xff4e, 0xff45, '\0'
2089 static const WCHAR foldczone_dst[] =
2091 'W','i','n','e',0x0348,0x0551,0x1323,0x280d,'W','i','n','e','\0'
2093 static const WCHAR ligatures_src[] =
2095 'W', 'i', 'n', 'e', 0x03a6, 0x03b9, 0x03bd, 0x03b5,
2096 0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
2097 0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
2098 0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
2099 0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
2100 0xfb04, 0xfb05, 0xfb06, '\0'
2102 static const WCHAR ligatures_dst[] =
2104 'W','i','n','e',0x03a6,0x03b9,0x03bd,0x03b5,
2105 'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
2106 'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
2107 'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
2108 0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
2109 'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
2114 win_skip("FoldStringW is not available\n");
2115 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
2118 /* Invalid flag combinations */
2119 for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
2121 src[0] = dst[0] = '\0';
2123 ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
2124 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
2126 win_skip("FoldStringW is not implemented\n");
2129 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
2130 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2133 /* src & dst cannot be the same */
2135 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
2136 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2137 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2139 /* src can't be NULL */
2141 ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
2142 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2143 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2145 /* srclen can't be 0 */
2147 ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
2148 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2149 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2151 /* dstlen can't be < 0 */
2153 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
2154 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2155 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2157 /* Ret includes terminating NUL which is appended if srclen = -1 */
2162 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
2163 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2164 ok(dst[0] == 'A' && dst[1] == '\0',
2165 "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%d\n",
2166 'A', '\0', ret, dst[0], dst[1], GetLastError());
2168 /* If size is given, result is not NUL terminated */
2174 ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
2175 ok(ret == 1, "Expected ret == 1, got %d, error %d\n", ret, GetLastError());
2176 ok(dst[0] == 'A' && dst[1] == 'X',
2177 "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%d\n",
2178 'A','X', ret, dst[0], dst[1], GetLastError());
2180 /* MAP_FOLDDIGITS */
2181 for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
2183 /* Check everything before this range */
2184 for (ch = prev_ch; ch < digitRanges[j]; ch++)
2188 src[1] = dst[0] = '\0';
2189 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2190 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2192 ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
2193 /* Wine (correctly) maps all Unicode 4.0+ digits */
2194 isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF || ch == 0x19da ||
2195 (ch >= 0x1369 && ch <= 0x1371),
2196 "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
2199 if (digitRanges[j] == 0xffff)
2200 break; /* Finished the whole code point space */
2202 for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
2206 /* Map out of sequence characters */
2207 if (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
2208 else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
2209 else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
2210 else if (ch == 0x245F) c = 0x24EA; /* Circled 0 */
2214 src[1] = dst[0] = '\0';
2215 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2216 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2218 ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
2219 broken( dst[0] == ch ) || /* old Windows versions don't have all mappings */
2220 (digitRanges[j] == 0x3020 && dst[0] == ch) || /* Hangzhou not present in all Windows versions */
2221 (digitRanges[j] == 0x0F29 && dst[0] == ch) || /* Tibetan not present in all Windows versions */
2222 strchrW(noDigitAvailable, c),
2223 "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
2224 ch, '0' + digitRanges[j] - ch, dst[0]);
2231 ret = pFoldStringW(MAP_FOLDCZONE, foldczone_src, -1, dst, 256);
2232 ok(ret == sizeof(foldczone_dst)/sizeof(foldczone_dst[0]),
2233 "Got %d, error %d\n", ret, GetLastError());
2234 ok(!memcmp(dst, foldczone_dst, sizeof(foldczone_dst)),
2235 "MAP_FOLDCZONE: Expanded incorrectly\n");
2237 /* MAP_EXPAND_LIGATURES */
2239 ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
2240 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
2241 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
2242 ok(ret == sizeof(ligatures_dst)/sizeof(ligatures_dst[0]),
2243 "Got %d, error %d\n", ret, GetLastError());
2244 ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
2245 "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
2248 /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
2253 #define LCID_OK(l) \
2254 ok(lcid == l, "Expected lcid = %08x, got %08x\n", l, lcid)
2255 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
2256 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
2257 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
2258 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
2260 static void test_ConvertDefaultLocale(void)
2264 /* Doesn't change lcid, even if non default sublang/sort used */
2265 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_US, SORT_DEFAULT);
2266 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_UK, SORT_DEFAULT);
2267 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT);
2268 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE);
2270 /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
2271 LCID_RES(MKLCID(LANG_ENGLISH, SUBLANG_NEUTRAL, SORT_DEFAULT),
2272 MKLCID(LANG_ENGLISH, SUBLANG_DEFAULT, SORT_DEFAULT));
2273 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
2274 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
2276 /* Invariant language is not treated specially */
2277 TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
2279 /* User/system default languages alone are not mapped */
2280 TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
2281 TEST_LCIDLANG(LANG_USER_DEFAULT, SORT_JAPANESE_UNICODE);
2284 LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
2285 LCID_RES(LOCALE_USER_DEFAULT, GetUserDefaultLCID());
2286 LCID_RES(LOCALE_NEUTRAL, GetUserDefaultLCID());
2289 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
2290 DWORD dwFlags, LONG_PTR lParam)
2292 trace("%08x, %s, %s, %08x, %08lx\n",
2293 lgrpid, lpszNum, lpszName, dwFlags, lParam);
2295 ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
2296 "Enumerated grp %d not valid (flags %d)\n", lgrpid, dwFlags);
2298 /* If lParam is one, we are calling with flags defaulted from 0 */
2299 ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
2300 "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %d\n", dwFlags);
2305 static void test_EnumSystemLanguageGroupsA(void)
2309 if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
2311 win_skip("EnumSystemLanguageGroupsA and/or IsValidLanguageGroup are not available\n");
2315 /* No enumeration proc */
2317 ret = pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
2318 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2320 win_skip("EnumSystemLanguageGroupsA is not implemented\n");
2323 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2324 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2328 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
2329 ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2331 /* No flags - defaults to LGRPID_INSTALLED */
2332 SetLastError(0xdeadbeef);
2333 pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
2334 ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
2336 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
2337 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
2340 static BOOL CALLBACK enum_func( LPWSTR name, DWORD flags, LPARAM lparam )
2342 trace( "%s %x\n", wine_dbgstr_w(name), flags );
2346 static void test_EnumSystemLocalesEx(void)
2350 if (!pEnumSystemLocalesEx)
2352 win_skip( "EnumSystemLocalesEx not available\n" );
2355 SetLastError( 0xdeadbeef );
2356 ret = pEnumSystemLocalesEx( enum_func, LOCALE_ALL, 0, (void *)1 );
2357 ok( !ret, "should have failed\n" );
2358 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
2359 SetLastError( 0xdeadbeef );
2360 ret = pEnumSystemLocalesEx( enum_func, 0, 0, NULL );
2361 ok( ret, "failed err %u\n", GetLastError() );
2364 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
2367 trace("%08x, %08x, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
2369 /* invalid locale enumerated on some platforms */
2373 ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
2374 "Enumerated grp %d not valid\n", lgrpid);
2375 ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
2376 "Enumerated grp locale %d not valid\n", lcid);
2380 static void test_EnumLanguageGroupLocalesA(void)
2384 if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
2386 win_skip("EnumLanguageGroupLocalesA and/or IsValidLanguageGroup are not available\n");
2390 /* No enumeration proc */
2392 ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
2393 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2395 win_skip("EnumLanguageGroupLocalesA is not implemented\n");
2398 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2399 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2401 /* lgrpid too small */
2403 ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
2404 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2405 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2407 /* lgrpid too big */
2409 ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
2410 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2411 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2413 /* dwFlags is reserved */
2415 ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
2416 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2417 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2419 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2422 static void test_SetLocaleInfoA(void)
2425 LCID lcid = GetUserDefaultLCID();
2429 bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2430 ok( !bRet && GetLastError() == ERROR_INVALID_PARAMETER,
2431 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2435 bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
2436 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2437 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2441 bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
2442 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2443 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2446 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2448 trace("%s %08lx\n", value, lParam);
2452 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2454 ok(!enumCount, "callback called again unexpected\n");
2459 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2461 ok(0,"callback called unexpected\n");
2465 static void test_EnumUILanguageA(void)
2468 if (!pEnumUILanguagesA) {
2469 win_skip("EnumUILanguagesA is not available on Win9x or NT4\n");
2473 SetLastError(ERROR_SUCCESS);
2474 ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2475 if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2477 win_skip("EnumUILanguagesA is not implemented\n");
2480 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2483 SetLastError(ERROR_SUCCESS);
2484 ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2485 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2487 SetLastError(ERROR_SUCCESS);
2488 ret = pEnumUILanguagesA(NULL, 0, 0);
2489 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2490 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2491 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2493 SetLastError(ERROR_SUCCESS);
2494 ret = pEnumUILanguagesA(luilocale_proc3A, 0x5a5a5a5a, 0);
2495 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2496 ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2498 SetLastError(ERROR_SUCCESS);
2499 ret = pEnumUILanguagesA(NULL, 0x5a5a5a5a, 0);
2500 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2501 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2502 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2505 static char date_fmt_buf[1024];
2507 static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
2509 lstrcatA(date_fmt_buf, fmt);
2510 lstrcatA(date_fmt_buf, "\n");
2514 static void test_EnumDateFormatsA(void)
2518 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2520 trace("EnumDateFormatsA 0\n");
2521 date_fmt_buf[0] = 0;
2522 SetLastError(0xdeadbeef);
2523 ret = EnumDateFormatsA(enum_datetime_procA, lcid, 0);
2524 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2526 win_skip("0 for dwFlags is not supported\n");
2530 ok(ret, "EnumDateFormatsA(0) error %d\n", GetLastError());
2531 trace("%s\n", date_fmt_buf);
2532 /* test the 1st enumerated format */
2533 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2534 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2535 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2536 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2539 trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n");
2540 date_fmt_buf[0] = 0;
2541 SetLastError(0xdeadbeef);
2542 ret = EnumDateFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2543 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2545 win_skip("LOCALE_USE_CP_ACP is not supported\n");
2549 ok(ret, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2550 trace("%s\n", date_fmt_buf);
2551 /* test the 1st enumerated format */
2552 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2553 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2554 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2555 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2558 trace("EnumDateFormatsA DATE_SHORTDATE\n");
2559 date_fmt_buf[0] = 0;
2560 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_SHORTDATE);
2561 ok(ret, "EnumDateFormatsA(DATE_SHORTDATE) error %d\n", GetLastError());
2562 trace("%s\n", date_fmt_buf);
2563 /* test the 1st enumerated format */
2564 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2565 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2566 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2567 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2569 trace("EnumDateFormatsA DATE_LONGDATE\n");
2570 date_fmt_buf[0] = 0;
2571 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_LONGDATE);
2572 ok(ret, "EnumDateFormatsA(DATE_LONGDATE) error %d\n", GetLastError());
2573 trace("%s\n", date_fmt_buf);
2574 /* test the 1st enumerated format */
2575 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2576 ret = GetLocaleInfoA(lcid, LOCALE_SLONGDATE, buf, sizeof(buf));
2577 ok(ret, "GetLocaleInfoA(LOCALE_SLONGDATE) error %d\n", GetLastError());
2578 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2580 trace("EnumDateFormatsA DATE_YEARMONTH\n");
2581 date_fmt_buf[0] = 0;
2582 SetLastError(0xdeadbeef);
2583 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_YEARMONTH);
2584 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2586 skip("DATE_YEARMONTH is only present on W2K and later\n");
2589 ok(ret, "EnumDateFormatsA(DATE_YEARMONTH) error %d\n", GetLastError());
2590 trace("%s\n", date_fmt_buf);
2591 /* test the 1st enumerated format */
2592 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2593 ret = GetLocaleInfoA(lcid, LOCALE_SYEARMONTH, buf, sizeof(buf));
2594 ok(ret, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %d\n", GetLastError());
2595 ok(!lstrcmpA(date_fmt_buf, buf) || broken(!buf[0]) /* win9x */,
2596 "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2599 static void test_EnumTimeFormatsA(void)
2603 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2605 trace("EnumTimeFormatsA 0\n");
2606 date_fmt_buf[0] = 0;
2607 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, 0);
2608 ok(ret, "EnumTimeFormatsA(0) error %d\n", GetLastError());
2609 trace("%s\n", date_fmt_buf);
2610 /* test the 1st enumerated format */
2611 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2612 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2613 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2614 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2616 trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n");
2617 date_fmt_buf[0] = 0;
2618 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2619 ok(ret, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2620 trace("%s\n", date_fmt_buf);
2621 /* test the 1st enumerated format */
2622 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2623 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2624 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2625 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2628 static void test_GetCPInfo(void)
2633 SetLastError(0xdeadbeef);
2634 ret = GetCPInfo(CP_SYMBOL, &cpinfo);
2635 ok(!ret, "GetCPInfo(CP_SYMBOL) should fail\n");
2636 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2637 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2639 SetLastError(0xdeadbeef);
2640 ret = GetCPInfo(CP_UTF7, &cpinfo);
2641 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2643 skip("Codepage CP_UTF7 is not installed/available\n");
2647 ok(ret, "GetCPInfo(CP_UTF7) error %u\n", GetLastError());
2648 ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2649 ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2650 ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2651 ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2652 ok(cpinfo.MaxCharSize == 5, "expected 5, got 0x%x\n", cpinfo.MaxCharSize);
2655 SetLastError(0xdeadbeef);
2656 ret = GetCPInfo(CP_UTF8, &cpinfo);
2657 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2659 skip("Codepage CP_UTF8 is not installed/available\n");
2663 ok(ret, "GetCPInfo(CP_UTF8) error %u\n", GetLastError());
2664 ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2665 ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2666 ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2667 ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2668 ok(cpinfo.MaxCharSize == 4 || broken(cpinfo.MaxCharSize == 3) /* win9x */,
2669 "expected 4, got %u\n", cpinfo.MaxCharSize);
2674 * The CT_TYPE1 has varied over windows version.
2675 * The current target for correct behavior is windows 7.
2676 * There was a big shift between windows 2000 (first introduced) and windows Xp
2677 * Most of the old values below are from windows 2000.
2678 * A smaller subset of changes happened between windows Xp and Window vista/7
2680 static void test_GetStringTypeW(void)
2682 static const WCHAR blanks[] = {0x9, 0x20, 0xa0, 0x3000, 0xfeff};
2683 static const WORD blanks_new[] = {C1_SPACE | C1_CNTRL | C1_BLANK | C1_DEFINED,
2684 C1_SPACE | C1_BLANK | C1_DEFINED,
2685 C1_SPACE | C1_BLANK | C1_DEFINED,
2686 C1_SPACE | C1_BLANK | C1_DEFINED,
2687 C1_CNTRL | C1_BLANK | C1_DEFINED};
2688 static const WORD blanks_old[] ={C1_SPACE | C1_CNTRL | C1_BLANK,
2689 C1_SPACE | C1_BLANK,
2690 C1_SPACE | C1_BLANK,
2691 C1_SPACE | C1_BLANK,
2692 C1_SPACE | C1_BLANK};
2694 static const WCHAR undefined[] = {0x378, 0x379, 0x604, 0xfff8, 0xfffe};
2697 static const WCHAR alpha[] = {0x47, 0x67, 0x1c5};
2698 static const WORD alpha_old[] = {C1_UPPER | C1_ALPHA,
2699 C1_LOWER | C1_ALPHA,
2700 C1_UPPER | C1_LOWER | C1_ALPHA,
2703 /* Sk, Sk, Mn, So, Me */
2704 static const WCHAR oldpunc[] = { 0x2c2, 0x2e5, 0x322, 0x482, 0x6de,
2706 0xffe0, 0xffe9, 0x2153};
2708 /* Lm, Nl, Cf, 0xad(Cf), 0x1f88 (Lt), Lo, Mc */
2709 static const WCHAR changed[] = {0x2b0, 0x2160, 0x600, 0xad, 0x1f88, 0x294, 0x903};
2710 static const WORD changed_old[] = { C1_PUNCT, C1_PUNCT, 0, C1_PUNCT, C1_UPPER | C1_ALPHA, C1_ALPHA, C1_PUNCT };
2711 static const WORD changed_xp[] = {C1_ALPHA | C1_DEFINED,
2712 C1_ALPHA | C1_DEFINED,
2713 C1_CNTRL | C1_DEFINED,
2714 C1_PUNCT | C1_DEFINED,
2715 C1_UPPER | C1_LOWER | C1_ALPHA | C1_DEFINED,
2716 C1_ALPHA | C1_LOWER | C1_DEFINED,
2717 C1_ALPHA | C1_DEFINED };
2718 static const WORD changed_new[] = { C1_ALPHA | C1_DEFINED,
2719 C1_ALPHA | C1_DEFINED,
2720 C1_CNTRL | C1_DEFINED,
2721 C1_PUNCT | C1_CNTRL | C1_DEFINED,
2722 C1_UPPER | C1_LOWER | C1_ALPHA | C1_DEFINED,
2723 C1_ALPHA | C1_DEFINED,
2726 /* Pc, Pd, Ps, Pe, Pi, Pf, Po*/
2727 static const WCHAR punct[] = { 0x5f, 0x2d, 0x28, 0x29, 0xab, 0xbb, 0x21 };
2729 static const WCHAR punct_special[] = {0x24, 0x2b, 0x3c, 0x3e, 0x5e, 0x60,
2730 0x7c, 0x7e, 0xa2, 0xbe, 0xd7, 0xf7};
2731 static const WCHAR digit_special[] = {0xb2, 0xb3, 0xb9};
2732 static const WCHAR lower_special[] = {0x2071, 0x207f};
2733 static const WCHAR cntrl_special[] = {0x070f, 0x200c, 0x200d,
2734 0x200e, 0x200f, 0x202a, 0x202b, 0x202c, 0x202d, 0x202e,
2735 0x206a, 0x206b, 0x206c, 0x206d, 0x206e, 0x206f, 0xfeff,
2736 0xfff9, 0xfffa, 0xfffb};
2737 static const WCHAR space_special[] = {0x09, 0x0d, 0x85};
2742 memset(types,0,sizeof(types));
2743 GetStringTypeW(CT_CTYPE1, blanks, 5, types);
2744 for (i = 0; i < 5; i++)
2745 ok(types[i] == blanks_new[i] || broken(types[i] == blanks_old[i] || broken(types[i] == 0)), "incorrect type1 returned for %x -> (%x != %x)\n",blanks[i],types[i],blanks_new[i]);
2747 memset(types,0,sizeof(types));
2748 GetStringTypeW(CT_CTYPE1, alpha, 3, types);
2749 for (i = 0; i < 3; i++)
2750 ok(types[i] == (C1_DEFINED | alpha_old[i]) || broken(types[i] == alpha_old[i]) || broken(types[i] == 0), "incorrect types returned for %x -> (%x != %x)\n",alpha[i], types[i],(C1_DEFINED | alpha_old[i]));
2751 memset(types,0,sizeof(types));
2752 GetStringTypeW(CT_CTYPE1, undefined, 5, types);
2753 for (i = 0; i < 5; i++)
2754 ok(types[i] == 0, "incorrect types returned for %x -> (%x != 0)\n",undefined[i], types[i]);
2756 memset(types,0,sizeof(types));
2757 GetStringTypeW(CT_CTYPE1, oldpunc, 8, types);
2758 for (i = 0; i < 8; i++)
2759 ok(types[i] == C1_DEFINED || broken(types[i] == C1_PUNCT) || broken(types[i] == 0), "incorrect types returned for %x -> (%x != %x)\n",oldpunc[i], types[i], C1_DEFINED);
2761 memset(types,0,sizeof(types));
2762 GetStringTypeW(CT_CTYPE1, changed, 7, types);
2763 for (i = 0; i < 7; i++)
2764 ok(types[i] == changed_new[i] || broken(types[i] == changed_old[i]) || broken(types[i] == changed_xp[i]) || broken(types[i] == 0), "incorrect types returned for %x -> (%x != %x)\n",changed[i], types[i], changed_new[i]);
2766 memset(types,0,sizeof(types));
2767 GetStringTypeW(CT_CTYPE1, punct, 7, types);
2768 for (i = 0; i < 7; i++)
2769 ok(types[i] == (C1_PUNCT | C1_DEFINED) || broken(types[i] == C1_PUNCT) || broken(types[i] == 0), "incorrect types returned for %x -> (%x != %x)\n",punct[i], types[i], (C1_PUNCT | C1_DEFINED));
2772 memset(types,0,sizeof(types));
2773 GetStringTypeW(CT_CTYPE1, punct_special, 12, types);
2774 for (i = 0; i < 12; i++)
2775 ok(types[i] & C1_PUNCT || broken(types[i] == 0), "incorrect types returned for %x -> (%x doest not have %x)\n",punct_special[i], types[i], C1_PUNCT);
2777 memset(types,0,sizeof(types));
2778 GetStringTypeW(CT_CTYPE1, digit_special, 3, types);
2779 for (i = 0; i < 3; i++)
2780 ok(types[i] & C1_DIGIT || broken(types[i] == 0), "incorrect types returned for %x -> (%x doest not have = %x)\n",digit_special[i], types[i], C1_DIGIT);
2782 memset(types,0,sizeof(types));
2783 GetStringTypeW(CT_CTYPE1, lower_special, 2, types);
2784 for (i = 0; i < 2; i++)
2785 ok(types[i] & C1_LOWER || broken(types[i] == C1_PUNCT) || broken(types[i] == 0), "incorrect types returned for %x -> (%x does not have %x)\n",lower_special[i], types[i], C1_LOWER);
2787 memset(types,0,sizeof(types));
2788 GetStringTypeW(CT_CTYPE1, cntrl_special, 20, types);
2789 for (i = 0; i < 20; i++)
2790 ok(types[i] & C1_CNTRL || broken(types[i] == (C1_BLANK|C1_SPACE)) || broken(types[i] == C1_PUNCT) || broken(types[i] == 0), "incorrect types returned for %x -> (%x does not have %x)\n",cntrl_special[i], types[i], C1_CNTRL);
2792 memset(types,0,sizeof(types));
2793 GetStringTypeW(CT_CTYPE1, space_special, 3, types);
2794 for (i = 0; i < 3; i++)
2795 ok(types[i] & C1_SPACE || broken(types[i] == C1_CNTRL) || broken(types[i] == 0), "incorrect types returned for %x -> (%x does not have %x)\n",space_special[i], types[i], C1_SPACE );
2800 InitFunctionPointers();
2802 test_EnumTimeFormatsA();
2803 test_EnumDateFormatsA();
2804 test_GetLocaleInfoA();
2805 test_GetLocaleInfoW();
2806 test_GetTimeFormatA();
2807 test_GetDateFormatA();
2808 test_GetDateFormatW();
2809 test_GetCurrencyFormatA(); /* Also tests the W version */
2810 test_GetNumberFormatA(); /* Also tests the W version */
2811 test_CompareStringA();
2812 test_LCMapStringA();
2813 test_LCMapStringW();
2816 test_ConvertDefaultLocale();
2817 test_EnumSystemLanguageGroupsA();
2818 test_EnumSystemLocalesEx();
2819 test_EnumLanguageGroupLocalesA();
2820 test_SetLocaleInfoA();
2821 test_EnumUILanguageA();
2823 test_GetStringTypeW();
2824 /* this requires collation table patch to make it MS compatible */
2825 if (0) test_sorting();