2 * Unit tests for locale functions
4 * Copyright 2002 YASAR Mehmet
5 * Copyright 2003 Dmitry Timoshkov
6 * Copyright 2003 Jon Griffiths
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 * We must pass LOCALE_NOUSEROVERRIDE (NUO) to formatting functions so that
24 * even when the user has overridden their default i8n settings (e.g. in
25 * the control panel i8n page), we will still get the expected results.
32 #include "wine/test.h"
38 static inline unsigned int strlenW( const WCHAR *str )
45 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
48 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
52 static inline WCHAR *strchrW( const WCHAR *str, WCHAR ch )
54 do { if (*str == ch) return (WCHAR *)str; } while (*str++);
58 static inline int isdigitW( WCHAR wc )
61 GetStringTypeW( CT_CTYPE1, &wc, 1, &type );
62 return type & C1_DIGIT;
65 /* Some functions are only in later versions of kernel32.dll */
66 static HMODULE hKernel32;
67 static WORD enumCount;
69 typedef BOOL (WINAPI *EnumSystemLanguageGroupsAFn)(LANGUAGEGROUP_ENUMPROC,
71 static EnumSystemLanguageGroupsAFn pEnumSystemLanguageGroupsA;
72 typedef BOOL (WINAPI *EnumLanguageGroupLocalesAFn)(LANGGROUPLOCALE_ENUMPROC,
73 LGRPID, DWORD, LONG_PTR);
74 static EnumLanguageGroupLocalesAFn pEnumLanguageGroupLocalesA;
75 typedef BOOL (WINAPI *EnumUILanguagesAFn)(UILANGUAGE_ENUMPROC,
77 static EnumUILanguagesAFn pEnumUILanguagesA;
79 typedef INT (WINAPI *FoldStringAFn)(DWORD, LPCSTR, INT, LPSTR, INT);
80 static FoldStringAFn pFoldStringA;
81 typedef INT (WINAPI *FoldStringWFn)(DWORD, LPCWSTR, INT, LPWSTR, INT);
82 static FoldStringWFn pFoldStringW;
84 typedef BOOL (WINAPI *IsValidLanguageGroupFn)(LGRPID, DWORD);
85 static IsValidLanguageGroupFn pIsValidLanguageGroup;
87 static void InitFunctionPointers(void)
89 hKernel32 = GetModuleHandleA("kernel32");
90 pEnumSystemLanguageGroupsA = (void*)GetProcAddress(hKernel32, "EnumSystemLanguageGroupsA");
91 pEnumLanguageGroupLocalesA = (void*)GetProcAddress(hKernel32, "EnumLanguageGroupLocalesA");
92 pFoldStringA = (void*)GetProcAddress(hKernel32, "FoldStringA");
93 pFoldStringW = (void*)GetProcAddress(hKernel32, "FoldStringW");
94 pIsValidLanguageGroup = (void*)GetProcAddress(hKernel32, "IsValidLanguageGroup");
95 pEnumUILanguagesA = (void*)GetProcAddress(hKernel32, "EnumUILanguagesA");
98 #define eq(received, expected, label, type) \
99 ok((received) == (expected), "%s: got " type " instead of " type "\n", \
100 (label), (received), (expected))
102 #define BUFFER_SIZE 128
103 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
105 #define STRINGSA(x,y) strcpy(input, x); strcpy(Expected, y); SetLastError(0xdeadbeef); buffer[0] = '\0'
106 #define EXPECT_LENA ok(ret == lstrlen(Expected)+1, "Expected Len %d, got %d\n", lstrlen(Expected)+1, ret)
107 #define EXPECT_EQA ok(strncmp(buffer, Expected, strlen(Expected)) == 0, \
108 "Expected '%s', got '%s'\n", Expected, buffer)
110 #define STRINGSW(x,y) MultiByteToWideChar(CP_ACP,0,x,-1,input,COUNTOF(input)); \
111 MultiByteToWideChar(CP_ACP,0,y,-1,Expected,COUNTOF(Expected)); \
112 SetLastError(0xdeadbeef); buffer[0] = '\0'
113 #define EXPECT_LENW ok(ret == lstrlenW(Expected)+1, "Expected Len %d, got %d\n", lstrlenW(Expected)+1, ret)
114 #define EXPECT_EQW ok(strncmpW(buffer, Expected, strlenW(Expected)) == 0, "Bad conversion\n")
116 #define NUO LOCALE_NOUSEROVERRIDE
118 static void test_GetLocaleInfoA(void)
121 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
122 char buffer[BUFFER_SIZE];
123 const char * expected;
125 ok(lcid == 0x409, "wrong LCID calculated - %d\n", lcid);
127 /* en, ar and zh use SUBLANG_NEUTRAL, but GetLocaleInfo assume SUBLANG_DEFAULT */
128 SetLastError(0xdeadbeef);
129 memset(buffer, 0, COUNTOF(buffer));
130 ret = GetLocaleInfoA(LANG_ENGLISH, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
131 expected = "English (United States)";
132 ok((ret == (lstrlenA(expected)+1)) && !lstrcmpA(buffer, expected),
133 "got %d with '%s' (expected %d with '%s')\n",
134 ret, buffer, lstrlenA(expected)+1, expected);
136 SetLastError(0xdeadbeef);
137 memset(buffer, 0, COUNTOF(buffer));
138 ret = GetLocaleInfoA(LANG_ARABIC, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
139 expected = "Arabic (Saudi Arabia)";
140 ok((ret == (lstrlenA(expected)+1)) && !lstrcmpA(buffer, expected),
141 "got %d with '%s' (expected %d with '%s')\n",
142 ret, buffer, lstrlenA(expected)+1, expected);
144 SetLastError(0xdeadbeef);
145 memset(buffer, 0, COUNTOF(buffer));
146 ret = GetLocaleInfoA(LANG_CHINESE, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
147 expected = "Chinese (Taiwan)";
148 ok((ret == (lstrlenA(expected)+1)) && !lstrcmpA(buffer, expected),
149 "got %d with '%s' (expected %d with '%s')\n",
150 ret, buffer, lstrlenA(expected)+1, expected);
152 /* SUBLANG_DEFAULT is not required for GetLocaleInfo */
153 SetLastError(0xdeadbeef);
154 memset(buffer, 0, COUNTOF(buffer));
155 ret = GetLocaleInfoA(LANG_GERMAN, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
156 expected = "German (Germany)";
157 ok((ret == (lstrlenA(expected)+1)) && !lstrcmpA(buffer, expected),
158 "got %d with '%s' (expected %d with '%s')\n",
159 ret, buffer, lstrlenA(expected)+1, expected);
161 /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
162 * partially fill the buffer even if it is too short. See bug 637.
164 SetLastError(0xdeadbeef);
165 memset(buffer, 0, COUNTOF(buffer));
166 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 0);
167 ok(ret == 7 && !buffer[0], "Expected len=7, got %d\n", ret);
169 SetLastError(0xdeadbeef);
170 memset(buffer, 0, COUNTOF(buffer));
171 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 3);
172 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
173 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
174 ok(!strcmp(buffer, "Mon"), "Expected 'Mon', got '%s'\n", buffer);
176 SetLastError(0xdeadbeef);
177 memset(buffer, 0, COUNTOF(buffer));
178 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 10);
179 ok(ret == 7, "Expected ret == 7, got %d, error %d\n", ret, GetLastError());
180 ok(!strcmp(buffer, "Monday"), "Expected 'Monday', got '%s'\n", buffer);
183 static void test_GetTimeFormatA(void)
187 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
188 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
190 memset(&curtime, 2, sizeof(SYSTEMTIME));
191 STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
192 SetLastError(0xdeadbeef);
193 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
194 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
195 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
198 curtime.wMinute = 56;
199 curtime.wSecond = 13;
200 curtime.wMilliseconds = 22;
201 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
202 SetLastError(0xdeadbeef);
203 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
204 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
205 EXPECT_LENA; EXPECT_EQA;
207 /* MSDN: LOCALE_NOUSEROVERRIDE can't be specified with a format string */
208 SetLastError(0xdeadbeef);
209 ret = GetTimeFormatA(lcid, NUO|TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
210 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
211 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
213 STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficient buffer */
214 SetLastError(0xdeadbeef);
215 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, 2);
216 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
217 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
219 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
220 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, NULL, 0);
221 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
224 STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
225 ret = GetTimeFormatA(lcid, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
226 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
227 EXPECT_LENA; EXPECT_EQA;
229 STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
230 ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
231 ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
232 ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "4" )), /* win9x */
233 "Expected '', got '%s'\n", buffer );
235 STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
236 ret = GetTimeFormatA(lcid, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
237 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
238 EXPECT_LENA; EXPECT_EQA;
240 STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
241 strcpy(Expected, "8:56 AM");
242 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
243 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
244 EXPECT_LENA; EXPECT_EQA;
246 STRINGSA("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
247 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
248 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
249 ok( !strcmp( buffer, "8.@:56AM" ) || broken( !strcmp( buffer, "8.@:56.@:AM" )) /* win9x */,
250 "Expected '8.@:56AM', got '%s'\n", buffer );
252 STRINGSA("s1s2s3", ""); /* Duplicate tokens */
253 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
254 ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
255 ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "3" )), /* win9x */
256 "Expected '', got '%s'\n", buffer );
258 STRINGSA("t/tt", "A/AM"); /* AM time marker */
259 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
260 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
261 EXPECT_LENA; EXPECT_EQA;
264 STRINGSA("t/tt", "P/PM"); /* PM time marker */
265 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
266 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
267 EXPECT_LENA; EXPECT_EQA;
269 STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
270 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
271 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
272 EXPECT_LENA; EXPECT_EQA;
274 STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
275 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
276 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
277 EXPECT_LENA; EXPECT_EQA;
279 STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
280 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
281 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
282 EXPECT_LENA; EXPECT_EQA;
284 curtime.wHour = 14; /* change this to 14 or 2pm */
287 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 */
288 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
289 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
290 EXPECT_LENA; EXPECT_EQA;
293 STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
294 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
295 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
296 EXPECT_LENA; EXPECT_EQA;
298 STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
299 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
300 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
301 EXPECT_LENA; EXPECT_EQA;
303 /* try to convert formatting strings with more than two letters
304 * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
305 * NOTE: We expect any letter for which there is an upper case value
306 * we should see a replacement. For letters that DO NOT have
307 * upper case values we should see NO REPLACEMENT.
310 curtime.wMinute = 56;
311 curtime.wSecond = 13;
312 curtime.wMilliseconds = 22;
313 STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
314 "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
315 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
316 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
317 EXPECT_LENA; EXPECT_EQA;
319 STRINGSA("h", "text"); /* Don't write to buffer if len is 0 */
320 strcpy(buffer, "text");
321 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, 0);
322 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
325 STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
326 "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
327 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
328 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
329 EXPECT_LENA; EXPECT_EQA;
331 STRINGSA("'''", "'"); /* invalid quoted string */
332 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
333 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
334 EXPECT_LENA; EXPECT_EQA;
336 /* test that msdn suggested single quotation usage works as expected */
337 STRINGSA("''''", "'"); /* single quote mark */
338 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
339 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
340 EXPECT_LENA; EXPECT_EQA;
342 STRINGSA("''HHHHHH", "08"); /* Normal use */
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 /* and test for normal use of the single quotation mark */
348 STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
349 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
350 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
351 EXPECT_LENA; EXPECT_EQA;
353 STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
354 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
355 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
356 EXPECT_LENA; EXPECT_EQA;
358 STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
359 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
360 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
361 EXPECT_LENA; EXPECT_EQA;
364 STRINGSA("'123'tt", ""); /* Invalid time */
365 SetLastError(0xdeadbeef);
366 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
367 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
368 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
371 curtime.wMonth = 60; /* Invalid */
372 STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
373 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
374 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
375 EXPECT_LENA; EXPECT_EQA;
378 static void test_GetDateFormatA(void)
382 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
383 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
385 memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
386 STRINGSA("ddd',' MMM dd yy","");
387 SetLastError(0xdeadbeef);
388 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
389 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
390 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
392 curtime.wYear = 2002;
395 curtime.wDayOfWeek = 3;
396 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
397 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
398 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
399 EXPECT_LENA; EXPECT_EQA;
401 /* Same as above but with LOCALE_NOUSEROVERRIDE */
402 STRINGSA("ddd',' MMM dd yy",""); /* Simple case */
403 SetLastError(0xdeadbeef);
404 ret = GetDateFormatA(lcid, NUO, &curtime, input, buffer, COUNTOF(buffer));
405 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
406 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
409 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
410 ret = GetDateFormatA(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 curtime.wHour = 36; /* Invalid */
415 STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
416 ret = GetDateFormatA(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("ddd',' MMM dd ''''yy",""); /* Get size only */
421 ret = GetDateFormatA(lcid, 0, &curtime, input, NULL, 0);
422 ok(ret == 16, "Expected ret == 16, got %d, error %d\n", ret, GetLastError());
425 STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
426 SetLastError(0xdeadbeef);
427 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, 2);
428 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
429 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
431 STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
432 ret = GetDateFormat(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
433 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
434 if (strncmp(buffer, Expected, strlen(Expected)) && strncmp(buffer, "5/4/02", strlen(Expected)) != 0)
435 ok (0, "Expected '%s' or '5/4/02', got '%s'\n", Expected, buffer);
437 STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
438 ret = GetDateFormat(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
439 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
440 EXPECT_LENA; EXPECT_EQA;
442 /* test for expected DATE_YEARMONTH behavior with null format */
443 /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
444 STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
445 SetLastError(0xdeadbeef);
446 ret = GetDateFormat(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
447 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
448 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
451 /* Test that using invalid DATE_* flags results in the correct error */
452 /* and return values */
453 STRINGSA("m/d/y", ""); /* Invalid flags */
454 SetLastError(0xdeadbeef);
455 ret = GetDateFormat(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
456 &curtime, input, buffer, COUNTOF(buffer));
457 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
458 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
462 static void test_GetDateFormatW(void)
466 WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
467 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
469 STRINGSW("",""); /* If flags is not zero then format must be NULL */
470 ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL,
471 input, buffer, COUNTOF(buffer));
472 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
474 win_skip("GetDateFormatW is not implemented\n");
477 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
478 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
481 STRINGSW("",""); /* NULL buffer, len > 0 */
482 SetLastError(0xdeadbeef);
483 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
484 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
485 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
487 STRINGSW("",""); /* NULL buffer, len == 0 */
488 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
489 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
490 EXPECT_LENW; EXPECT_EQW;
492 curtime.wYear = 2002;
495 curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
496 curtime.wHour = 65432; /* Invalid */
497 curtime.wMinute = 34512; /* Invalid */
498 curtime.wSecond = 65535; /* Invalid */
499 curtime.wMilliseconds = 12345;
500 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
501 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
502 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
503 EXPECT_LENW; EXPECT_EQW;
507 curtime.wYear = 1601;
510 curtime.wDayOfWeek = 0; /* Irrelevant */
514 curtime.wMilliseconds = 0;
515 STRINGSW("dddd d MMMM yyyy","Monday 1 January 1601");
516 SetLastError(0xdeadbeef);
517 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
518 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
519 EXPECT_LENW; EXPECT_EQW;
521 curtime.wYear = 1600;
524 curtime.wDayOfWeek = 0; /* Irrelevant */
526 curtime.wMinute = 59;
527 curtime.wSecond = 59;
528 curtime.wMilliseconds = 999;
529 STRINGSW("dddd d MMMM yyyy","Friday 31 December 1600");
530 SetLastError(0xdeadbeef);
531 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
532 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
533 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
537 #define CY_POS_LEFT 0
538 #define CY_POS_RIGHT 1
539 #define CY_POS_LEFT_SPACE 2
540 #define CY_POS_RIGHT_SPACE 3
542 static void test_GetCurrencyFormatA(void)
544 static char szDot[] = { '.', '\0' };
545 static char szComma[] = { ',', '\0' };
546 static char szDollar[] = { '$', '\0' };
548 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
549 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
552 memset(&format, 0, sizeof(format));
554 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
555 SetLastError(0xdeadbeef);
556 ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
557 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
558 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
560 STRINGSA("23,53",""); /* Invalid character --> Error */
561 SetLastError(0xdeadbeef);
562 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
563 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
564 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
566 STRINGSA("--",""); /* Double '-' --> Error */
567 SetLastError(0xdeadbeef);
568 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
569 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
570 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
572 STRINGSA("0-",""); /* Trailing '-' --> Error */
573 SetLastError(0xdeadbeef);
574 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
575 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
576 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
578 STRINGSA("0..",""); /* Double '.' --> Error */
579 SetLastError(0xdeadbeef);
580 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
581 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
582 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
584 STRINGSA(" 0.1",""); /* Leading space --> Error */
585 SetLastError(0xdeadbeef);
586 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
587 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
588 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
590 STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
591 SetLastError(0xdeadbeef);
592 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, 2);
593 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
594 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
596 STRINGSA("2353",""); /* Format and flags given --> Error */
597 SetLastError(0xdeadbeef);
598 ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
599 ok( !ret, "Expected ret == 0, got %d\n", ret);
600 ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
601 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
603 STRINGSA("2353",""); /* Invalid format --> Error */
604 SetLastError(0xdeadbeef);
605 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
606 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
607 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
609 STRINGSA("2353","$2,353.00"); /* Valid number */
610 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
611 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
612 EXPECT_LENA; EXPECT_EQA;
614 STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
615 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
616 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
617 EXPECT_LENA; EXPECT_EQA;
619 STRINGSA("2353.1","$2,353.10"); /* Valid real number */
620 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
621 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
622 EXPECT_LENA; EXPECT_EQA;
624 STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
625 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
626 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
627 EXPECT_LENA; EXPECT_EQA;
629 STRINGSA("2353.119","$2,353.12"); /* Too many DP --> Rounded */
630 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
631 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
632 EXPECT_LENA; EXPECT_EQA;
634 format.NumDigits = 0; /* No decimal separator */
635 format.LeadingZero = 0;
636 format.Grouping = 0; /* No grouping char */
637 format.NegativeOrder = 0;
638 format.PositiveOrder = CY_POS_LEFT;
639 format.lpDecimalSep = szDot;
640 format.lpThousandSep = szComma;
641 format.lpCurrencySymbol = szDollar;
643 STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
644 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
645 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
646 EXPECT_LENA; EXPECT_EQA;
648 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
649 STRINGSA("2353","$2353.0");
650 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
651 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
652 EXPECT_LENA; EXPECT_EQA;
654 format.Grouping = 2; /* Group by 100's */
655 STRINGSA("2353","$23,53.0");
656 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
657 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
658 EXPECT_LENA; EXPECT_EQA;
660 format.LeadingZero = 1; /* Always provide leading zero */
661 STRINGSA(".5","$0.5");
662 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
663 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
664 EXPECT_LENA; EXPECT_EQA;
666 format.PositiveOrder = CY_POS_RIGHT;
667 STRINGSA("1","1.0$");
668 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
669 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
670 EXPECT_LENA; EXPECT_EQA;
672 format.PositiveOrder = CY_POS_LEFT_SPACE;
673 STRINGSA("1","$ 1.0");
674 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
675 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
676 EXPECT_LENA; EXPECT_EQA;
678 format.PositiveOrder = CY_POS_RIGHT_SPACE;
679 STRINGSA("1","1.0 $");
680 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
681 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
682 EXPECT_LENA; EXPECT_EQA;
684 format.NegativeOrder = 0;
685 STRINGSA("-1","($1.0)");
686 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
687 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
688 EXPECT_LENA; EXPECT_EQA;
690 format.NegativeOrder = 1;
691 STRINGSA("-1","-$1.0");
692 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
693 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
694 EXPECT_LENA; EXPECT_EQA;
696 format.NegativeOrder = 2;
697 STRINGSA("-1","$-1.0");
698 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
699 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
700 EXPECT_LENA; EXPECT_EQA;
702 format.NegativeOrder = 3;
703 STRINGSA("-1","$1.0-");
704 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
705 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
706 EXPECT_LENA; EXPECT_EQA;
708 format.NegativeOrder = 4;
709 STRINGSA("-1","(1.0$)");
710 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
711 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
712 EXPECT_LENA; EXPECT_EQA;
714 format.NegativeOrder = 5;
715 STRINGSA("-1","-1.0$");
716 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
717 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
718 EXPECT_LENA; EXPECT_EQA;
720 format.NegativeOrder = 6;
721 STRINGSA("-1","1.0-$");
722 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
723 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
724 EXPECT_LENA; EXPECT_EQA;
726 format.NegativeOrder = 7;
727 STRINGSA("-1","1.0$-");
728 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
729 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
730 EXPECT_LENA; EXPECT_EQA;
732 format.NegativeOrder = 8;
733 STRINGSA("-1","-1.0 $");
734 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
735 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
736 EXPECT_LENA; EXPECT_EQA;
738 format.NegativeOrder = 9;
739 STRINGSA("-1","-$ 1.0");
740 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
741 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
742 EXPECT_LENA; EXPECT_EQA;
744 format.NegativeOrder = 10;
745 STRINGSA("-1","1.0 $-");
746 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
747 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
748 EXPECT_LENA; EXPECT_EQA;
750 format.NegativeOrder = 11;
751 STRINGSA("-1","$ 1.0-");
752 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
753 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
754 EXPECT_LENA; EXPECT_EQA;
756 format.NegativeOrder = 12;
757 STRINGSA("-1","$ -1.0");
758 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
759 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
760 EXPECT_LENA; EXPECT_EQA;
762 format.NegativeOrder = 13;
763 STRINGSA("-1","1.0- $");
764 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
765 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
766 EXPECT_LENA; EXPECT_EQA;
768 format.NegativeOrder = 14;
769 STRINGSA("-1","($ 1.0)");
770 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
771 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
772 EXPECT_LENA; EXPECT_EQA;
774 format.NegativeOrder = 15;
775 STRINGSA("-1","(1.0 $)");
776 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
777 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
778 EXPECT_LENA; EXPECT_EQA;
781 #define NEG_PARENS 0 /* "(1.1)" */
782 #define NEG_LEFT 1 /* "-1.1" */
783 #define NEG_LEFT_SPACE 2 /* "- 1.1" */
784 #define NEG_RIGHT 3 /* "1.1-" */
785 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
787 static void test_GetNumberFormatA(void)
789 static char szDot[] = { '.', '\0' };
790 static char szComma[] = { ',', '\0' };
792 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
793 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
796 memset(&format, 0, sizeof(format));
798 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
799 SetLastError(0xdeadbeef);
800 ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
801 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
802 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
804 STRINGSA("23,53",""); /* Invalid character --> Error */
805 SetLastError(0xdeadbeef);
806 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
807 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
808 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
810 STRINGSA("--",""); /* Double '-' --> Error */
811 SetLastError(0xdeadbeef);
812 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
813 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
814 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
816 STRINGSA("0-",""); /* Trailing '-' --> Error */
817 SetLastError(0xdeadbeef);
818 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
819 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
820 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
822 STRINGSA("0..",""); /* Double '.' --> Error */
823 SetLastError(0xdeadbeef);
824 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
825 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
826 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
828 STRINGSA(" 0.1",""); /* Leading space --> Error */
829 SetLastError(0xdeadbeef);
830 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
831 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
832 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
834 STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
835 SetLastError(0xdeadbeef);
836 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, 2);
837 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
838 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
840 STRINGSA("2353",""); /* Format and flags given --> Error */
841 SetLastError(0xdeadbeef);
842 ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
843 ok( !ret, "Expected ret == 0, got %d\n", ret);
844 ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
845 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
847 STRINGSA("2353",""); /* Invalid format --> Error */
848 SetLastError(0xdeadbeef);
849 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
850 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
851 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
853 STRINGSA("2353","2,353.00"); /* Valid number */
854 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
855 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
856 EXPECT_LENA; EXPECT_EQA;
858 STRINGSA("-2353","-2,353.00"); /* Valid negative number */
859 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
860 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
861 EXPECT_LENA; EXPECT_EQA;
863 STRINGSA("-353","-353.00"); /* test for off by one error in grouping */
864 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
865 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
866 EXPECT_LENA; EXPECT_EQA;
868 STRINGSA("2353.1","2,353.10"); /* Valid real number */
869 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
870 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
871 EXPECT_LENA; EXPECT_EQA;
873 STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
874 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
875 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
876 EXPECT_LENA; EXPECT_EQA;
878 STRINGSA("2353.119","2,353.12"); /* Too many DP --> Rounded */
879 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
880 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
881 EXPECT_LENA; EXPECT_EQA;
883 format.NumDigits = 0; /* No decimal separator */
884 format.LeadingZero = 0;
885 format.Grouping = 0; /* No grouping char */
886 format.NegativeOrder = 0;
887 format.lpDecimalSep = szDot;
888 format.lpThousandSep = szComma;
890 STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
891 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
892 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
893 EXPECT_LENA; EXPECT_EQA;
895 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
896 STRINGSA("2353","2353.0");
897 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
898 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
899 EXPECT_LENA; EXPECT_EQA;
901 format.Grouping = 2; /* Group by 100's */
902 STRINGSA("2353","23,53.0");
903 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
904 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
905 EXPECT_LENA; EXPECT_EQA;
907 format.LeadingZero = 1; /* Always provide leading zero */
908 STRINGSA(".5","0.5");
909 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
910 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
911 EXPECT_LENA; EXPECT_EQA;
913 format.NegativeOrder = NEG_PARENS;
914 STRINGSA("-1","(1.0)");
915 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
916 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
917 EXPECT_LENA; EXPECT_EQA;
919 format.NegativeOrder = NEG_LEFT;
920 STRINGSA("-1","-1.0");
921 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
922 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
923 EXPECT_LENA; EXPECT_EQA;
925 format.NegativeOrder = NEG_LEFT_SPACE;
926 STRINGSA("-1","- 1.0");
927 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
928 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
929 EXPECT_LENA; EXPECT_EQA;
931 format.NegativeOrder = NEG_RIGHT;
932 STRINGSA("-1","1.0-");
933 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
934 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
935 EXPECT_LENA; EXPECT_EQA;
937 format.NegativeOrder = NEG_RIGHT_SPACE;
938 STRINGSA("-1","1.0 -");
939 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
940 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
941 EXPECT_LENA; EXPECT_EQA;
943 lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
945 if (IsValidLocale(lcid, 0))
947 STRINGSA("-12345","-12 345,00"); /* Try French formatting */
948 Expected[3] = 160; /* Non breaking space */
949 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
950 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
951 EXPECT_LENA; EXPECT_EQA;
956 static void test_CompareStringA(void)
959 LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
961 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
962 ok (ret== 1, "(Salut/Salute) Expected 1, got %d\n", ret);
964 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
965 ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
967 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
968 ok (ret== 3, "(Salut/hola) Expected 3, got %d\n", ret);
970 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
971 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
973 lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
975 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
976 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
978 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
979 ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
981 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
982 ok (ret == 2, "(Salut/saLuT) Expected 2, got %d\n", ret);
984 /* test for CompareStringA flags */
985 SetLastError(0xdeadbeef);
986 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0x8, "NULL", -1, "NULL", -1);
987 ok(GetLastError() == ERROR_INVALID_FLAGS,
988 "unexpected error code %d\n", GetLastError());
989 ok(!ret, "CompareStringA must fail with invalid flag\n");
991 SetLastError(0xdeadbeef);
992 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, LOCALE_USE_CP_ACP, "NULL", -1, "NULL", -1);
993 ok(GetLastError() == 0xdeadbeef, "unexpected error code %d\n", GetLastError());
994 ok(ret == CSTR_EQUAL, "CompareStringA error: %d != CSTR_EQUAL\n", ret);
995 /* end of test for CompareStringA flags */
997 ret = lstrcmpA("", "");
998 ok (ret == 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret);
1000 ret = lstrcmpA(NULL, NULL);
1001 ok (ret == 0 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, NULL) should return 0, got %d\n", ret);
1003 ret = lstrcmpA("", NULL);
1004 ok (ret == 1 || broken(ret == -2) /* win9x */, "lstrcmpA(\"\", NULL) should return 1, got %d\n", ret);
1006 ret = lstrcmpA(NULL, "");
1007 ok (ret == -1 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret);
1009 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"EndDialog",-1,"_Property",-1);
1010 ok( ret == 3, "EndDialog vs _Property ... expected 3, got %d\n", ret);
1012 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0070",-1,"_IEWWBrowserComp",-1);
1013 ok( ret == 3, "osp_vba.sreg0070 vs _IEWWBrowserComp ... expected 3, got %d\n", ret);
1015 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"r",-1,"\\",-1);
1016 ok( ret == 3, "r vs \\ ... expected 3, got %d\n", ret);
1018 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0031", -1, "OriginalDatabase", -1 );
1019 ok( ret == 3, "osp_vba.sreg0031 vs OriginalDatabase ... expected 3, got %d\n", ret);
1021 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1 );
1022 ok( ret == 3, "AAA vs aaa expected 3, got %d\n", ret);
1024 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1 );
1025 ok( ret == 1, "AAA vs aab expected 1, got %d\n", ret);
1027 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1 );
1028 ok( ret == 1, "AAA vs Aab expected 1, got %d\n", ret);
1030 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1 );
1031 ok( ret == 1, ".AAA vs Aab expected 1, got %d\n", ret);
1033 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1 );
1034 ok( ret == 1, ".AAA vs A.ab expected 1, got %d\n", ret);
1036 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1 );
1037 ok( ret == 1, "aa vs AB expected 1, got %d\n", ret);
1039 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1 );
1040 ok( ret == 1, "aa vs Aab expected 1, got %d\n", ret);
1042 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1 );
1043 ok( ret == 3, "aB vs Aab expected 3, got %d\n", ret);
1045 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1 );
1046 ok( ret == 1, "Ba vs bab expected 1, got %d\n", ret);
1048 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1 );
1049 ok( ret == 1, "{100}{83}{71}{71}{71} vs Global_DataAccess_JRO expected 1, got %d\n", ret);
1051 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1 );
1052 ok( ret == 3, "a vs { expected 3, got %d\n", ret);
1054 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1 );
1055 ok( ret == 3, "A vs { expected 3, got %d\n", ret);
1057 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1 );
1058 ok(ret == 1, "3.5/0 vs 4.0/-1 expected 1, got %d\n", ret);
1060 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1 );
1061 ok(ret == 1, "3.5 vs 4.0 expected 1, got %d\n", ret);
1063 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1 );
1064 ok(ret == 1, "3.520.4403.2 vs 4.0.2927.10 expected 1, got %d\n", ret);
1066 /* hyphen and apostrophe are treated differently depending on
1067 * whether SORT_STRINGSORT specified or not
1069 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1 );
1070 ok(ret == 3, "-o vs /m expected 3, got %d\n", ret);
1072 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1 );
1073 ok(ret == 1, "/m vs -o expected 1, got %d\n", ret);
1075 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1 );
1076 ok(ret == 1, "-o vs /m expected 1, got %d\n", ret);
1078 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1 );
1079 ok(ret == 3, "/m vs -o expected 3, got %d\n", ret);
1081 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1 );
1082 ok(ret == 3, "'o vs /m expected 3, got %d\n", ret);
1084 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1 );
1085 ok(ret == 1, "/m vs 'o expected 1, got %d\n", ret);
1087 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1 );
1088 ok(ret == 1, "'o vs /m expected 1, got %d\n", ret);
1090 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1 );
1091 ok(ret == 3, "/m vs 'o expected 3, got %d\n", ret);
1093 if (0) { /* this requires collation table patch to make it MS compatible */
1094 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
1095 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
1097 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
1098 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
1100 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
1101 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
1103 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
1104 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
1106 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
1107 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
1109 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
1110 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
1112 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
1113 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
1115 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
1116 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
1118 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
1119 ok(ret == 1, "`o vs -m expected 1, got %d\n", ret);
1121 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
1122 ok(ret == 3, "-m vs `o expected 3, got %d\n", ret);
1124 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
1125 ok(ret == 3, "`o vs -m expected 3, got %d\n", ret);
1127 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
1128 ok(ret == 1, "-m vs `o expected 1, got %d\n", ret);
1131 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9);
1132 ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0 expected 2, got %d\n", ret);
1134 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10);
1135 ok(ret == 1, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1, got %d\n", ret);
1137 /* WinXP handles embedded NULLs differently than earlier versions */
1138 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
1139 ok(ret == 1 || ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1 or 2, got %d\n", ret);
1141 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
1142 ok(ret == 1 || ret == 2, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected 1 or 2, got %d\n", ret);
1144 ret = CompareStringA(lcid, 0, "a\0b", -1, "a", -1);
1145 ok(ret == 2, "a vs a expected 2, got %d\n", ret);
1147 ret = CompareStringA(lcid, 0, "a\0b", 4, "a", 2);
1148 ok(ret == CSTR_EQUAL || /* win2k */
1149 ret == CSTR_GREATER_THAN,
1150 "a\\0b vs a expected CSTR_EQUAL or CSTR_GREATER_THAN, got %d\n", ret);
1152 ret = CompareStringA(lcid, 0, "\2", 2, "\1", 2);
1153 todo_wine ok(ret != 2, "\\2 vs \\1 expected unequal\n");
1155 ret = CompareStringA(lcid, NORM_IGNORECASE | LOCALE_USE_CP_ACP, "#", -1, ".", -1);
1156 todo_wine ok(ret == CSTR_LESS_THAN, "\"#\" vs \".\" expected CSTR_LESS_THAN, got %d\n", ret);
1158 ret = lstrcmpi("#", ".");
1159 todo_wine ok(ret == -1, "\"#\" vs \".\" expected -1, got %d\n", ret);
1162 static void test_LCMapStringA(void)
1165 char buf[256], buf2[256];
1166 static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
1167 static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
1168 static const char symbols_stripped[] = "justateststring1";
1170 SetLastError(0xdeadbeef);
1171 ret = LCMapStringA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP | LCMAP_LOWERCASE,
1172 lower_case, -1, buf, sizeof(buf));
1173 ok(ret == lstrlenA(lower_case) + 1,
1174 "ret %d, error %d, expected value %d\n",
1175 ret, GetLastError(), lstrlenA(lower_case) + 1);
1176 ok(!memcmp(buf, lower_case, ret), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1178 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1179 upper_case, -1, buf, sizeof(buf));
1180 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1181 ok(GetLastError() == ERROR_INVALID_FLAGS,
1182 "unexpected error code %d\n", GetLastError());
1184 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1185 upper_case, -1, buf, sizeof(buf));
1186 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1187 ok(GetLastError() == ERROR_INVALID_FLAGS,
1188 "unexpected error code %d\n", GetLastError());
1190 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1191 upper_case, -1, buf, sizeof(buf));
1192 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1193 ok(GetLastError() == ERROR_INVALID_FLAGS,
1194 "unexpected error code %d\n", GetLastError());
1196 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1197 upper_case, -1, buf, sizeof(buf));
1198 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1199 ok(GetLastError() == ERROR_INVALID_FLAGS,
1200 "unexpected error code %d\n", GetLastError());
1202 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1203 SetLastError(0xdeadbeef);
1204 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1205 upper_case, -1, buf, sizeof(buf));
1206 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1207 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1209 /* test LCMAP_LOWERCASE */
1210 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1211 upper_case, -1, buf, sizeof(buf));
1212 ok(ret == lstrlenA(upper_case) + 1,
1213 "ret %d, error %d, expected value %d\n",
1214 ret, GetLastError(), lstrlenA(upper_case) + 1);
1215 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1217 /* test LCMAP_UPPERCASE */
1218 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1219 lower_case, -1, buf, sizeof(buf));
1220 ok(ret == lstrlenA(lower_case) + 1,
1221 "ret %d, error %d, expected value %d\n",
1222 ret, GetLastError(), lstrlenA(lower_case) + 1);
1223 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1225 /* test buffer overflow */
1226 SetLastError(0xdeadbeef);
1227 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1228 lower_case, -1, buf, 4);
1229 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1230 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1232 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1233 lstrcpyA(buf, lower_case);
1234 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1235 buf, -1, buf, sizeof(buf));
1236 if (!ret) /* Win9x */
1237 trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1240 ok(ret == lstrlenA(lower_case) + 1,
1241 "ret %d, error %d, expected value %d\n",
1242 ret, GetLastError(), lstrlenA(lower_case) + 1);
1243 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1245 lstrcpyA(buf, upper_case);
1246 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1247 buf, -1, buf, sizeof(buf));
1248 if (!ret) /* Win9x */
1249 trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1252 ok(ret == lstrlenA(upper_case) + 1,
1253 "ret %d, error %d, expected value %d\n",
1254 ret, GetLastError(), lstrlenA(lower_case) + 1);
1255 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1258 /* otherwise src == dst should fail */
1259 SetLastError(0xdeadbeef);
1260 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1261 buf, 10, buf, sizeof(buf));
1262 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1263 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1264 "unexpected error code %d\n", GetLastError());
1265 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1267 /* test whether '\0' is always appended */
1268 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1269 upper_case, -1, buf, sizeof(buf));
1270 ok(ret, "LCMapStringA must succeed\n");
1271 ok(buf[ret-1] == 0, "LCMapStringA not null-terminated\n");
1272 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1273 upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1274 ok(ret2, "LCMapStringA must succeed\n");
1275 ok(buf2[ret2-1] == 0, "LCMapStringA not null-terminated\n" );
1276 ok(ret == ret2, "lengths of sort keys must be equal\n");
1277 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1279 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1280 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1281 upper_case, -1, buf, sizeof(buf));
1282 ok(ret, "LCMapStringA must succeed\n");
1283 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1284 lower_case, -1, buf2, sizeof(buf2));
1285 ok(ret2, "LCMapStringA must succeed\n");
1286 ok(ret == ret2, "lengths of sort keys must be equal\n");
1287 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1289 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1290 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1291 lower_case, -1, buf, sizeof(buf));
1292 ok(ret, "LCMapStringA must succeed\n");
1293 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1294 lower_case, -1, buf2, sizeof(buf2));
1295 ok(ret2, "LCMapStringA must succeed\n");
1296 ok(ret == ret2, "lengths of sort keys must be equal\n");
1297 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1299 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1300 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1301 lower_case, -1, buf, sizeof(buf));
1302 ok(ret, "LCMapStringA must succeed\n");
1303 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1304 symbols_stripped, -1, buf2, sizeof(buf2));
1305 ok(ret2, "LCMapStringA must succeed\n");
1306 ok(ret == ret2, "lengths of sort keys must be equal\n");
1307 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1309 /* test NORM_IGNORENONSPACE */
1310 lstrcpyA(buf, "foo");
1311 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1312 lower_case, -1, buf, sizeof(buf));
1313 ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1314 lstrlenA(lower_case) + 1, ret);
1315 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1317 /* test NORM_IGNORESYMBOLS */
1318 lstrcpyA(buf, "foo");
1319 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1320 lower_case, -1, buf, sizeof(buf));
1321 ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1322 lstrlenA(symbols_stripped) + 1, ret);
1323 ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1325 /* test srclen = 0 */
1326 SetLastError(0xdeadbeef);
1327 ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1328 ok(!ret, "LCMapStringA should fail with srclen = 0\n");
1329 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1330 "unexpected error code %d\n", GetLastError());
1333 static void test_LCMapStringW(void)
1336 WCHAR buf[256], buf2[256];
1337 char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1338 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};
1339 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};
1340 static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
1341 static const WCHAR fooW[] = {'f','o','o',0};
1343 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1344 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1345 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1347 win_skip("LCMapStringW is not implemented\n");
1350 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1351 ok(GetLastError() == ERROR_INVALID_FLAGS,
1352 "unexpected error code %d\n", GetLastError());
1354 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1355 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1356 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1357 ok(GetLastError() == ERROR_INVALID_FLAGS,
1358 "unexpected error code %d\n", GetLastError());
1360 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1361 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1362 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1363 ok(GetLastError() == ERROR_INVALID_FLAGS,
1364 "unexpected error code %d\n", GetLastError());
1366 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1367 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1368 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1369 ok(GetLastError() == ERROR_INVALID_FLAGS,
1370 "unexpected error code %d\n", GetLastError());
1372 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1373 SetLastError(0xdeadbeef);
1374 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1375 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1376 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1377 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1379 /* test LCMAP_LOWERCASE */
1380 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1381 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1382 ok(ret == lstrlenW(upper_case) + 1,
1383 "ret %d, error %d, expected value %d\n",
1384 ret, GetLastError(), lstrlenW(upper_case) + 1);
1385 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1387 /* test LCMAP_UPPERCASE */
1388 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1389 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1390 ok(ret == lstrlenW(lower_case) + 1,
1391 "ret %d, error %d, expected value %d\n",
1392 ret, GetLastError(), lstrlenW(lower_case) + 1);
1393 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1395 /* test buffer overflow */
1396 SetLastError(0xdeadbeef);
1397 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1398 lower_case, -1, buf, 4);
1399 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1400 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1402 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1403 lstrcpyW(buf, lower_case);
1404 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1405 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1406 ok(ret == lstrlenW(lower_case) + 1,
1407 "ret %d, error %d, expected value %d\n",
1408 ret, GetLastError(), lstrlenW(lower_case) + 1);
1409 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1411 lstrcpyW(buf, upper_case);
1412 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1413 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1414 ok(ret == lstrlenW(upper_case) + 1,
1415 "ret %d, error %d, expected value %d\n",
1416 ret, GetLastError(), lstrlenW(lower_case) + 1);
1417 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1419 /* otherwise src == dst should fail */
1420 SetLastError(0xdeadbeef);
1421 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1422 buf, 10, buf, sizeof(buf));
1423 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1424 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1425 "unexpected error code %d\n", GetLastError());
1426 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1428 /* test whether '\0' is always appended */
1429 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1430 upper_case, -1, buf, sizeof(buf));
1431 ok(ret, "LCMapStringW must succeed\n");
1432 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1433 upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1434 ok(ret, "LCMapStringW must succeed\n");
1435 ok(ret == ret2, "lengths of sort keys must be equal\n");
1436 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1438 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1439 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1440 upper_case, -1, buf, sizeof(buf));
1441 ok(ret, "LCMapStringW must succeed\n");
1442 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1443 lower_case, -1, buf2, sizeof(buf2));
1444 ok(ret2, "LCMapStringW must succeed\n");
1445 ok(ret == ret2, "lengths of sort keys must be equal\n");
1446 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1448 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1449 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1450 lower_case, -1, buf, sizeof(buf));
1451 ok(ret, "LCMapStringW must succeed\n");
1452 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1453 lower_case, -1, buf2, sizeof(buf2));
1454 ok(ret2, "LCMapStringW must succeed\n");
1455 ok(ret == ret2, "lengths of sort keys must be equal\n");
1456 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1458 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1459 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1460 lower_case, -1, buf, sizeof(buf));
1461 ok(ret, "LCMapStringW must succeed\n");
1462 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1463 symbols_stripped, -1, buf2, sizeof(buf2));
1464 ok(ret2, "LCMapStringW must succeed\n");
1465 ok(ret == ret2, "lengths of sort keys must be equal\n");
1466 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1468 /* test NORM_IGNORENONSPACE */
1469 lstrcpyW(buf, fooW);
1470 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1471 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1472 ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1473 lstrlenW(lower_case) + 1, ret);
1474 ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1476 /* test NORM_IGNORESYMBOLS */
1477 lstrcpyW(buf, fooW);
1478 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1479 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1480 ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1481 lstrlenW(symbols_stripped) + 1, ret);
1482 ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1484 /* test srclen = 0 */
1485 SetLastError(0xdeadbeef);
1486 ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf)/sizeof(WCHAR));
1487 ok(!ret, "LCMapStringW should fail with srclen = 0\n");
1488 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1489 "unexpected error code %d\n", GetLastError());
1492 /* this requires collation table patch to make it MS compatible */
1493 static const char * const strings_sorted[] =
1525 static const char * const strings[] =
1557 static int compare_string1(const void *e1, const void *e2)
1559 const char *s1 = *(const char *const *)e1;
1560 const char *s2 = *(const char *const *)e2;
1562 return lstrcmpA(s1, s2);
1565 static int compare_string2(const void *e1, const void *e2)
1567 const char *s1 = *(const char *const *)e1;
1568 const char *s2 = *(const char *const *)e2;
1570 return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1573 static int compare_string3(const void *e1, const void *e2)
1575 const char *s1 = *(const char *const *)e1;
1576 const char *s2 = *(const char *const *)e2;
1577 char key1[256], key2[256];
1579 LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
1580 LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
1581 return strcmp(key1, key2);
1584 static void test_sorting(void)
1587 char **str_buf = (char **)buf;
1590 assert(sizeof(buf) >= sizeof(strings));
1592 /* 1. sort using lstrcmpA */
1593 memcpy(buf, strings, sizeof(strings));
1594 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
1595 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1597 ok(!strcmp(strings_sorted[i], str_buf[i]),
1598 "qsort using lstrcmpA failed for element %d\n", i);
1600 /* 2. sort using CompareStringA */
1601 memcpy(buf, strings, sizeof(strings));
1602 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
1603 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1605 ok(!strcmp(strings_sorted[i], str_buf[i]),
1606 "qsort using CompareStringA failed for element %d\n", i);
1608 /* 3. sort using sort keys */
1609 memcpy(buf, strings, sizeof(strings));
1610 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
1611 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1613 ok(!strcmp(strings_sorted[i], str_buf[i]),
1614 "qsort using sort keys failed for element %d\n", i);
1618 static void test_FoldStringA(void)
1621 char src[256], dst[256];
1622 static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0' };
1623 static const char digits_dst[] = { '1','2','3','\0' };
1624 static const char composite_src[] =
1626 0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
1627 0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
1628 0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
1629 0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
1630 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
1631 0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
1632 0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
1633 0xfb,0xfc,0xfd,0xff,'\0'
1635 static const char composite_dst[] =
1637 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1638 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1639 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1640 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1641 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1642 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1643 0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
1644 0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
1645 0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
1646 0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
1647 0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
1648 0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
1649 0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
1650 0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
1651 0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1653 static const char ligatures_src[] =
1655 0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1657 static const char ligatures_dst[] =
1659 'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1663 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1665 /* these tests are locale specific */
1666 if (GetACP() != 1252)
1668 trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1672 /* MAP_FOLDDIGITS */
1674 ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
1675 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1677 win_skip("FoldStringA is not implemented\n");
1680 ok(ret == 4, "Expected ret == 4, got %d, error %d\n", ret, GetLastError());
1681 ok(strcmp(dst, digits_dst) == 0,
1682 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
1683 for (i = 1; i < 256; i++)
1685 if (!strchr(digits_src, i))
1690 ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
1691 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1692 ok(dst[0] == src[0],
1693 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
1697 /* MAP_EXPAND_LIGATURES */
1699 ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1700 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1701 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1702 ok(ret == sizeof(ligatures_dst), "Got %d, error %d\n", ret, GetLastError());
1703 ok(strcmp(dst, ligatures_dst) == 0,
1704 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
1705 for (i = 1; i < 256; i++)
1707 if (!strchr(ligatures_src, i))
1712 ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1713 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1714 ok(dst[0] == src[0],
1715 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
1722 ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
1723 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1726 /* Wine gets close, but doesn't produce quite the same result as native */
1727 ok(ret == 121, "Expected 121, got %d\n", ret);
1728 ok(strcmp(dst, composite_dst) == 0,
1729 "MAP_COMPOSITE: Expected '%s', got '%s'\n", composite_dst, dst);
1732 for (i = 1; i < 256; i++)
1734 if (!strchr(composite_src, i))
1739 ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
1740 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1741 ok(dst[0] == src[0],
1742 "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
1743 (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
1748 for (i = 1; i < 256; i++)
1753 ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
1754 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1755 ok(src[0] == dst[0],
1756 "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
1757 (unsigned char)src[0], (unsigned char)dst[0]);
1760 /* MAP_PRECOMPOSED */
1761 for (i = 1; i < 256; i++)
1766 ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
1767 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1768 ok(src[0] == dst[0],
1769 "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
1770 (unsigned char)src[0], (unsigned char)dst[0]);
1774 static void test_FoldStringW(void)
1777 unsigned int i, j, failures;
1778 WCHAR src[256], dst[256], ch, prev_ch = 1;
1779 static const DWORD badFlags[] =
1782 MAP_PRECOMPOSED|MAP_COMPOSITE,
1783 MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
1784 MAP_COMPOSITE|MAP_EXPAND_LIGATURES
1786 /* Ranges of digits 0-9 : Must be sorted! */
1787 static const WCHAR digitRanges[] =
1789 0x0030, /* '0'-'9' */
1790 0x0660, /* Eastern Arabic */
1791 0x06F0, /* Arabic - Hindu */
1792 0x0966, /* Devengari */
1793 0x09E6, /* Bengalii */
1794 0x0A66, /* Gurmukhi */
1795 0x0AE6, /* Gujarati */
1797 0x0BE6, /* Tamil - No 0 */
1798 0x0C66, /* Telugu */
1799 0x0CE6, /* Kannada */
1800 0x0D66, /* Maylayalam */
1803 0x2070, /* Superscript - 1, 2, 3 are out of sequence */
1804 0x2080, /* Subscript */
1805 0x245F, /* Circled - 0 is out of sequence */
1806 0x2473, /* Bracketed */
1807 0x2487, /* Full stop */
1808 0x2775, /* Inverted circled - No 0 */
1809 0x277F, /* Patterned circled - No 0 */
1810 0x2789, /* Inverted Patterned circled - No 0 */
1811 0xff10, /* Pliene chasse (?) */
1812 0xffff /* Terminator */
1814 /* Digits which are represented, but out of sequence */
1815 static const WCHAR outOfSequenceDigits[] =
1817 0xB9, /* Superscript 1 */
1818 0xB2, /* Superscript 2 */
1819 0xB3, /* Superscript 3 */
1820 0x24EA, /* Circled 0 */
1821 '\0' /* Terminator */
1823 /* Digits in digitRanges for which no representation is available */
1824 static const WCHAR noDigitAvailable[] =
1826 0x0BE6, /* No Tamil 0 */
1827 0x2473, /* No Bracketed 0 */
1828 0x2487, /* No 0 Full stop */
1829 0x2775, /* No inverted circled 0 */
1830 0x277F, /* No patterned circled */
1831 0x2789, /* No inverted Patterned circled */
1832 '\0' /* Terminator */
1834 /* Compatibility conversion results */
1835 static const WCHAR compat_F900_FA2F[256+48] =
1837 0x8c48, 0x66f4, 0x8eca, 0x8cc8, 0x6ed1, 0x4e32, 0x53e5, 0x9f9c,
1838 0x9f9c, 0x5951, 0x91d1, 0x5587, 0x5948, 0x61f6, 0x7669, 0x7f85,
1839 0x863f, 0x87ba, 0x88f8, 0x908f, 0x6a02, 0x6d1b, 0x70d9, 0x73de,
1840 0x843d, 0x916a, 0x99f1, 0x4e82, 0x5375, 0x6b04, 0x721b, 0x862d,
1841 0x9e1e, 0x5d50, 0x6feb, 0x85cd, 0x8964, 0x62c9, 0x81d8, 0x881f,
1842 0x5eca, 0x6717, 0x6d6a, 0x72fc, 0x0000, 0x4f86, 0x51b7, 0x52de,
1843 0x64c4, 0x6ad3, 0x7210, 0x76e7, 0x8001, 0x8606, 0x865c, 0x8def,
1844 0x9732, 0x9b6f, 0x9dfa, 0x788c, 0x797f, 0x7da0, 0x83c9, 0x9304,
1845 0x9e7f, 0x8ad6, 0x58df, 0x5f04, 0x7c60, 0x807e, 0x7262, 0x78ca,
1846 0x8cc2, 0x96f7, 0x58d8, 0x5c62, 0x6a13, 0x6dda, 0x6f0f, 0x7d2f,
1847 0x7e37, 0x964b, 0x52d2, 0x808b, 0x51dc, 0x51cc, 0x7a1c, 0x7dbe,
1848 0x83f1, 0x9675, 0x8b80, 0x62cf, 0x6a02, 0x8afe, 0x4e39, 0x5be7,
1849 0x6012, 0x7387, 0x7570, 0x5317, 0x78fb, 0x4fbf, 0x5fa9, 0x4e0d,
1850 0x6ccc, 0x6578, 0x7d22, 0x53c3, 0x585e, 0x7701, 0x8449, 0x8aaa,
1851 0x6bba, 0x8fb0, 0x6c88, 0x62fe, 0x82e5, 0x63a0, 0x7565, 0x4eae,
1852 0x5169, 0x0000, 0x6881, 0x7ce7, 0x826f, 0x8ad2, 0x91cf, 0x52f5,
1853 0x5442, 0x5973, 0x5eec, 0x65c5, 0x6ffe, 0x792a, 0x95ad, 0x9a6a,
1854 0x9e97, 0x9ece, 0x529b, 0x66c6, 0x6b77, 0x8f62, 0x5e74, 0x6190,
1855 0x6200, 0x649a, 0x6f23, 0x7149, 0x7489, 0x0000, 0x7df4, 0x806f,
1856 0x8f26, 0x84ee, 0x9023, 0x934a, 0x5217, 0x52a3, 0x54bd, 0x70c8,
1857 0x88c2, 0x8aaa, 0x5ec9, 0x5ff5, 0x637b, 0x6bae, 0x7c3e, 0x7375,
1858 0x4ee4, 0x56f9, 0x5be7, 0x5dba, 0x601c, 0x73b2, 0x7469, 0x7f9a,
1859 0x8046, 0x9234, 0x96f6, 0x9748, 0x9818, 0x4f8b, 0x79ae, 0x91b4,
1860 0x96b8, 0x60e1, 0x4e86, 0x50da, 0x5bee, 0x5c3f, 0x6599, 0x6a02,
1861 0x71ce, 0x7642, 0x84fc, 0x907c, 0x9f8d, 0x6688, 0x962e, 0x5289,
1862 0x677b, 0x67f3, 0x6d41, 0x6e9c, 0x7409, 0x7559, 0x786b, 0x7d10,
1863 0x985e, 0x516d, 0x622e, 0x9678, 0x502b, 0x5d19, 0x6dea, 0x8f2a,
1864 0x5f8b, 0x6144, 0x6817, 0x7387, 0x9686, 0x5229, 0x540f, 0x5c65,
1865 0x6613, 0x674e, 0x68a8, 0x6ce5, 0x7406, 0x75e2, 0x7f79, 0x0000,
1866 0x88e1, 0x91cc, 0x96e2, 0x533f, 0x6eba, 0x541d, 0x71d0, 0x7498,
1867 0x85fa, 0x0000, 0x9c57, 0x9e9f, 0x6797, 0x6dcb, 0x81e8, 0x7acb,
1868 0x7b20, 0x7c92, 0x72c0, 0x7099, 0x8b58, 0x4ec0, 0x8336, 0x523a,
1869 0x5207, 0x5ea6, 0x62d3, 0x7cd6, 0x5b85, 0x6d1e, 0x66b4, 0x8f3b,
1870 0x884c, 0x964d, 0x898b, 0x5ed3, 0x0000, 0x0000, 0x0000, 0x0000,
1871 0x585a, 0x0000, 0x6674, 0x0000, 0x0000, 0x51de, 0x8c6c, 0x76ca,
1872 0x0000, 0x795e, 0x7965, 0x798f, 0x9756, 0x7cbe, 0x7fbd, 0x0000,
1873 0x0000, 0x0000, 0x8af8, 0x0000, 0x0000, 0x9038, 0x90fd, 0x0000,
1874 0x0000, 0x0000, 0x98ef, 0x98fc, 0x9928, 0x9db4, 0x0000, 0x0000
1876 static const WCHAR compat_FE30_FEF7[200] =
1878 0x2025, 0x2014, 0x2013, 0x005f, 0x005f, 0x0028, 0x0029, 0x007b,
1879 0x007d, 0x3014, 0x3015, 0x3010, 0x3011, 0x300a, 0x300b, 0x3008,
1880 0x3009, 0x300c, 0x300d, 0x300e, 0x300f, 0x0000, 0x0000, 0x0000,
1881 0x0000, 0x203e, 0x203e, 0x203e, 0x203e, 0x005f, 0x005f, 0x005f,
1882 0x002c, 0x3001, 0x002e, 0x0000, 0x003b, 0x003a, 0x003f, 0x0021,
1883 0x2014, 0x0028, 0x0029, 0x007b, 0x007d, 0x3014, 0x3015, 0x0023,
1884 0x0026, 0x002a, 0x002b, 0x002d, 0x003c, 0x003e, 0x003d, 0x0000,
1885 0x0000, 0x0024, 0x0025, 0x0040, 0x0000, 0x0000, 0x0000, 0x0000,
1886 0x064b, 0x064b, 0x064c, 0x0000, 0x064d, 0x0000, 0x064e, 0x064e,
1887 0x064f, 0x064f, 0x0650, 0x0650, 0x0651, 0x0651, 0x0652, 0x0652,
1888 0x0621, 0x0622, 0x0622, 0x0623, 0x0623, 0x0624, 0x0624, 0x0625,
1889 0x0625, 0x0626, 0x0626, 0x0626, 0x0626, 0x0627, 0x0627, 0x0628,
1890 0x0628, 0x0628, 0x0628, 0x0629, 0x0629, 0x062a, 0x062a, 0x062a,
1891 0x062a, 0x062b, 0x062b, 0x062b, 0x062b, 0x062c, 0x062c, 0x062c,
1892 0x062c, 0x062d, 0x062d, 0x062d, 0x062d, 0x062e, 0x062e, 0x062e,
1893 0x062e, 0x062f, 0x062f, 0x0630, 0x0630, 0x0631, 0x0631, 0x0632,
1894 0x0632, 0x0633, 0x0633, 0x0633, 0x0633, 0x0634, 0x0634, 0x0634,
1895 0x0634, 0x0635, 0x0635, 0x0635, 0x0635, 0x0636, 0x0636, 0x0636,
1896 0x0636, 0x0637, 0x0637, 0x0637, 0x0637, 0x0638, 0x0638, 0x0638,
1897 0x0638, 0x0639, 0x0639, 0x0639, 0x0639, 0x063a, 0x063a, 0x063a,
1898 0x063a, 0x0641, 0x0641, 0x0641, 0x0641, 0x0642, 0x0642, 0x0642,
1899 0x0642, 0x0643, 0x0643, 0x0643, 0x0643, 0x0644, 0x0644, 0x0644,
1900 0x0644, 0x0645, 0x0645, 0x0645, 0x0645, 0x0646, 0x0646, 0x0646,
1901 0x0646, 0x0647, 0x0647, 0x0647, 0x0647, 0x0648, 0x0648, 0x0649,
1902 0x0649, 0x064a, 0x064a, 0x064a, 0x064a, 0x0000, 0x0000, 0x0000
1904 static const WCHAR compat_FF00_FFEF[240] =
1906 0x0000, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
1907 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
1908 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
1909 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
1910 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
1911 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
1912 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
1913 0x0058, 0x0059, 0x005a, 0x005b, 0x0000, 0x005d, 0x005e, 0x005f,
1914 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
1915 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
1916 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
1917 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000,
1918 0x0000, 0x3002, 0x300c, 0x300d, 0x3001, 0x30fb, 0x30f2, 0x30a1,
1919 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, 0x30c3,
1920 0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, 0x30ab, 0x30ad,
1921 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, 0x30b9, 0x30bb, 0x30bd,
1922 0x30bf, 0x30c1, 0x30c4, 0x30c6, 0x30c8, 0x30ca, 0x30cb, 0x30cc,
1923 0x30cd, 0x30ce, 0x30cf, 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de,
1924 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9,
1925 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c,
1926 0x3164, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137,
1927 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f,
1928 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147,
1929 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x0000,
1930 0x0000, 0x0000, 0x314f, 0x3150, 0x3151, 0x3152, 0x3153, 0x3154,
1931 0x0000, 0x0000, 0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315a,
1932 0x0000, 0x0000, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, 0x3160,
1933 0x0000, 0x0000, 0x3161, 0x3162, 0x3163, 0x0000, 0x0000, 0x0000,
1934 0x00a2, 0x00a3, 0x00ac, 0x00af, 0x00a6, 0x00a5, 0x20a9, 0x0000,
1935 0x2502, 0x2190, 0x2191, 0x2192, 0x2193, 0x25a0, 0x25cb, 0x0000
1937 static const WCHAR ligatures_src[] =
1939 0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
1940 0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
1941 0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
1942 0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
1943 0xfb04, 0xfb05, 0xfb06, '\0'
1945 static const WCHAR ligatures_dst[] =
1947 'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
1948 'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
1949 'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
1950 0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
1951 'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
1956 win_skip("FoldStringW is not available\n");
1957 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1960 /* Invalid flag combinations */
1961 for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
1963 src[0] = dst[0] = '\0';
1965 ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
1966 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1968 win_skip("FoldStringW is not implemented\n");
1971 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
1972 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1975 /* src & dst cannot be the same */
1977 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
1978 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1979 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1981 /* src can't be NULL */
1983 ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
1984 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1985 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1987 /* srclen can't be 0 */
1989 ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
1990 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1991 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1993 /* dstlen can't be < 0 */
1995 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
1996 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1997 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1999 /* Ret includes terminating NUL which is appended if srclen = -1 */
2004 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
2005 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2006 ok(dst[0] == 'A' && dst[1] == '\0',
2007 "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%d\n",
2008 'A', '\0', ret, dst[0], dst[1], GetLastError());
2010 /* If size is given, result is not NUL terminated */
2016 ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
2017 ok(ret == 1, "Expected ret == 1, got %d, error %d\n", ret, GetLastError());
2018 ok(dst[0] == 'A' && dst[1] == 'X',
2019 "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%d\n",
2020 'A','X', ret, dst[0], dst[1], GetLastError());
2022 /* MAP_FOLDDIGITS */
2023 for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
2025 /* Check everything before this range */
2026 for (ch = prev_ch; ch < digitRanges[j]; ch++)
2030 src[1] = dst[0] = '\0';
2031 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2032 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2034 ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
2035 /* Wine (correctly) maps all Unicode 4.0+ digits */
2036 isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF ||
2037 (ch >= 0x1369 && ch <= 0x1371),
2038 "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
2041 if (digitRanges[j] == 0xffff)
2042 break; /* Finished the whole code point space */
2044 for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
2048 /* Map out of sequence characters */
2049 if (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
2050 else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
2051 else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
2052 else if (ch == 0x245F) c = 0x24EA; /* Circled 0 */
2056 src[1] = dst[0] = '\0';
2057 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2058 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2060 ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
2061 broken( dst[0] == ch ) || /* old Windows versions don't have all mappings */
2062 strchrW(noDigitAvailable, c),
2063 "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
2064 ch, '0' + digitRanges[j] - ch, dst[0]);
2070 for (ch = 1, failures = 0; ch <0xffff; ch++)
2074 if (ch >= 0xF900 && ch <= 0xFA2F)
2075 expected = compat_F900_FA2F[ch - 0xF900];
2076 else if (ch >= 0xFE30 && ch <= 0xFEF7)
2077 expected = compat_FE30_FEF7[ch - 0xFE30];
2078 else if (ch >= 0xFF00 && ch <= 0xFFEF)
2079 expected = compat_FF00_FFEF[ch - 0xFF00];
2086 src[1] = dst[0] = '\0';
2087 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
2088 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2089 ok(dst[0] == expected ||
2090 broken( dst[0] == ch ) || /* old Windows versions don't have all mappings */
2091 /* Wine (correctly) uses updated mappings for some Unicode 4.0 chars */
2092 /* FIXME: But they should be re-checked */
2093 ch == 0xf92c || ch == 0xf979 || ch == 0xf995 || ch == 0xf9e7 ||
2095 (0xfa0c <= ch && ch <= 0xfa6a) ||
2096 (0xfa70 <= ch && ch <= 0xfad9) ||
2097 ch == 0xfe47 || ch == 0xfe48 || ch == 0xfe68 ||
2098 (0xfe70 <= ch && ch <= 0xfe7f) ||
2099 ch == 0xff3c || ch == 0xff5f || ch == 0xff60 ||
2100 ch == 0xff9e || ch == 0xff9f,
2101 "MAP_FOLDCZONE: ch %d 0x%04x Expected 0x%04x got 0x%04x\n",
2102 ch, ch, expected, dst[0]);
2103 if (dst[0] != expected && ch < 0xf000 && ++failures > 50)
2105 trace( "MAP_FOLDCZONE: Too many failures, giving up\n" );
2110 /* MAP_EXPAND_LIGATURES */
2112 ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
2113 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
2114 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
2115 ok(ret == sizeof(ligatures_dst)/sizeof(ligatures_dst[0]),
2116 "Got %d, error %d\n", ret, GetLastError());
2117 ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
2118 "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
2119 for (i = 1, failures = 0; i <= 0xffff; i++)
2121 if (!strchrW(ligatures_src, i))
2126 ret = pFoldStringW(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
2127 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2129 ok(0, "MAP_EXPAND_LIGATURES: %04x : Expected %04x, got %04x %04x\n",
2130 i, src[0], dst[0], dst[1]);
2132 ok(dst[0] == src[0],
2133 "MAP_EXPAND_LIGATURES: %04x : Expected %04x, got %04x\n",
2135 if (dst[0] != src[0] && ++failures > 50)
2137 trace( "MAP_EXPAND_LIGATURES: Too many failures, giving up\n" );
2144 /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
2149 #define LCID_OK(l) \
2150 ok(lcid == l, "Expected lcid = %08x, got %08x\n", l, lcid)
2151 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
2152 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
2153 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
2154 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
2156 static void test_ConvertDefaultLocale(void)
2160 /* Doesn't change lcid, even if non default sublang/sort used */
2161 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_US, SORT_DEFAULT);
2162 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_UK, SORT_DEFAULT);
2163 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT);
2164 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE);
2166 /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
2167 LCID_RES(MKLCID(LANG_ENGLISH, SUBLANG_NEUTRAL, SORT_DEFAULT),
2168 MKLCID(LANG_ENGLISH, SUBLANG_DEFAULT, SORT_DEFAULT));
2169 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
2170 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
2171 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_JAPANESE_UNICODE),
2172 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE));
2174 /* Invariant language is not treated specially */
2175 TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
2176 LCID_RES(MKLCID(LANG_INVARIANT, SUBLANG_NEUTRAL, SORT_DEFAULT),
2177 MKLCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT));
2179 /* User/system default languages alone are not mapped */
2180 TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
2181 TEST_LCIDLANG(LANG_USER_DEFAULT, SORT_JAPANESE_UNICODE);
2184 LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
2185 LCID_RES(LOCALE_USER_DEFAULT, GetUserDefaultLCID());
2186 LCID_RES(LOCALE_NEUTRAL, GetUserDefaultLCID());
2189 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
2190 DWORD dwFlags, LONG_PTR lParam)
2192 trace("%08x, %s, %s, %08x, %08lx\n",
2193 lgrpid, lpszNum, lpszName, dwFlags, lParam);
2195 ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
2196 "Enumerated grp %d not valid (flags %d)\n", lgrpid, dwFlags);
2198 /* If lParam is one, we are calling with flags defaulted from 0 */
2199 ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
2200 "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %d\n", dwFlags);
2205 static void test_EnumSystemLanguageGroupsA(void)
2209 if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
2211 win_skip("EnumSystemLanguageGroupsA and/or IsValidLanguageGroup are not available\n");
2215 /* No enumeration proc */
2217 ret = pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
2218 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2220 win_skip("EnumSystemLanguageGroupsA is not implemented\n");
2223 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2224 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2228 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
2229 ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2231 /* No flags - defaults to LGRPID_INSTALLED */
2232 SetLastError(0xdeadbeef);
2233 pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
2234 ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
2236 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
2237 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
2241 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
2244 trace("%08x, %08x, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
2246 /* invalid locale enumerated on some platforms */
2250 ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
2251 "Enumerated grp %d not valid\n", lgrpid);
2252 ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
2253 "Enumerated grp locale %d not valid\n", lcid);
2257 static void test_EnumLanguageGroupLocalesA(void)
2261 if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
2263 win_skip("EnumLanguageGroupLocalesA and/or IsValidLanguageGroup are not available\n");
2267 /* No enumeration proc */
2269 ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
2270 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2272 win_skip("EnumLanguageGroupLocalesA is not implemented\n");
2275 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2276 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2278 /* lgrpid too small */
2280 ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
2281 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2282 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2284 /* lgrpid too big */
2286 ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
2287 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2288 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2290 /* dwFlags is reserved */
2292 ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
2293 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2294 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2296 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2299 static void test_SetLocaleInfoA(void)
2302 LCID lcid = GetUserDefaultLCID();
2306 bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2307 ok( !bRet && GetLastError() == ERROR_INVALID_PARAMETER,
2308 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2312 bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
2313 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2314 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2318 bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
2319 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2320 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2323 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2325 trace("%s %08lx\n", value, lParam);
2329 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2331 ok(!enumCount, "callback called again unexpected\n");
2336 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2338 ok(0,"callback called unexpected\n");
2342 static void test_EnumUILanguageA(void)
2345 if (!pEnumUILanguagesA) {
2346 win_skip("EnumUILanguagesA is not available on Win9x or NT4\n");
2350 SetLastError(ERROR_SUCCESS);
2351 ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2352 if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2354 win_skip("EnumUILanguagesA is not implemented\n");
2357 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2360 SetLastError(ERROR_SUCCESS);
2361 ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2362 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2364 SetLastError(ERROR_SUCCESS);
2365 ret = pEnumUILanguagesA(NULL, 0, 0);
2366 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2367 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2368 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2370 SetLastError(ERROR_SUCCESS);
2371 ret = pEnumUILanguagesA(luilocale_proc3A, 0x5a5a5a5a, 0);
2372 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2373 ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2375 SetLastError(ERROR_SUCCESS);
2376 ret = pEnumUILanguagesA(NULL, 0x5a5a5a5a, 0);
2377 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2378 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2379 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2382 static char date_fmt_buf[1024];
2384 static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
2386 lstrcatA(date_fmt_buf, fmt);
2387 lstrcatA(date_fmt_buf, "\n");
2391 static void test_EnumDateFormatsA(void)
2395 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2397 trace("EnumDateFormatsA 0\n");
2398 date_fmt_buf[0] = 0;
2399 SetLastError(0xdeadbeef);
2400 ret = EnumDateFormatsA(enum_datetime_procA, lcid, 0);
2401 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2403 win_skip("0 for dwFlags is not supported\n");
2407 ok(ret, "EnumDateFormatsA(0) error %d\n", GetLastError());
2408 trace("%s\n", date_fmt_buf);
2409 /* test the 1st enumerated format */
2410 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2411 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2412 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2413 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2416 trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n");
2417 date_fmt_buf[0] = 0;
2418 SetLastError(0xdeadbeef);
2419 ret = EnumDateFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2420 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2422 win_skip("LOCALE_USE_CP_ACP is not supported\n");
2426 ok(ret, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2427 trace("%s\n", date_fmt_buf);
2428 /* test the 1st enumerated format */
2429 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2430 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2431 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2432 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2435 trace("EnumDateFormatsA DATE_SHORTDATE\n");
2436 date_fmt_buf[0] = 0;
2437 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_SHORTDATE);
2438 ok(ret, "EnumDateFormatsA(DATE_SHORTDATE) error %d\n", GetLastError());
2439 trace("%s\n", date_fmt_buf);
2440 /* test the 1st enumerated format */
2441 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2442 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2443 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2444 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2446 trace("EnumDateFormatsA DATE_LONGDATE\n");
2447 date_fmt_buf[0] = 0;
2448 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_LONGDATE);
2449 ok(ret, "EnumDateFormatsA(DATE_LONGDATE) error %d\n", GetLastError());
2450 trace("%s\n", date_fmt_buf);
2451 /* test the 1st enumerated format */
2452 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2453 ret = GetLocaleInfoA(lcid, LOCALE_SLONGDATE, buf, sizeof(buf));
2454 ok(ret, "GetLocaleInfoA(LOCALE_SLONGDATE) error %d\n", GetLastError());
2455 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2457 trace("EnumDateFormatsA DATE_YEARMONTH\n");
2458 date_fmt_buf[0] = 0;
2459 SetLastError(0xdeadbeef);
2460 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_YEARMONTH);
2461 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2463 skip("DATE_YEARMONTH is only present on W2K and later\n");
2466 ok(ret, "EnumDateFormatsA(DATE_YEARMONTH) error %d\n", GetLastError());
2467 trace("%s\n", date_fmt_buf);
2468 /* test the 1st enumerated format */
2469 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2470 ret = GetLocaleInfoA(lcid, LOCALE_SYEARMONTH, buf, sizeof(buf));
2471 ok(ret, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %d\n", GetLastError());
2472 ok(!lstrcmpA(date_fmt_buf, buf) || broken(!buf[0]) /* win9x */,
2473 "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2476 static void test_EnumTimeFormatsA(void)
2480 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2482 trace("EnumTimeFormatsA 0\n");
2483 date_fmt_buf[0] = 0;
2484 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, 0);
2485 ok(ret, "EnumTimeFormatsA(0) error %d\n", GetLastError());
2486 trace("%s\n", date_fmt_buf);
2487 /* test the 1st enumerated format */
2488 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2489 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2490 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2491 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2493 trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n");
2494 date_fmt_buf[0] = 0;
2495 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2496 ok(ret, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2497 trace("%s\n", date_fmt_buf);
2498 /* test the 1st enumerated format */
2499 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2500 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2501 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2502 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2505 static void test_GetCPInfo(void)
2510 SetLastError(0xdeadbeef);
2511 ret = GetCPInfo(CP_SYMBOL, &cpinfo);
2512 ok(!ret, "GetCPInfo(CP_SYMBOL) should fail\n");
2513 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2514 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2516 SetLastError(0xdeadbeef);
2517 ret = GetCPInfo(CP_UTF7, &cpinfo);
2518 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2520 skip("Codepage CP_UTF7 is not installed/available\n");
2524 ok(ret, "GetCPInfo(CP_UTF7) error %u\n", GetLastError());
2525 ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2526 ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2527 ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2528 ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2529 ok(cpinfo.MaxCharSize == 5, "expected 5, got 0x%x\n", cpinfo.MaxCharSize);
2532 SetLastError(0xdeadbeef);
2533 ret = GetCPInfo(CP_UTF8, &cpinfo);
2534 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2536 skip("Codepage CP_UTF8 is not installed/available\n");
2540 ok(ret, "GetCPInfo(CP_UTF8) error %u\n", GetLastError());
2541 ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2542 ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2543 ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2544 ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2545 ok(cpinfo.MaxCharSize == 4 || broken(cpinfo.MaxCharSize == 3) /* win9x */,
2546 "expected 4, got %u\n", cpinfo.MaxCharSize);
2552 InitFunctionPointers();
2554 test_EnumTimeFormatsA();
2555 test_EnumDateFormatsA();
2556 test_GetLocaleInfoA();
2557 test_GetTimeFormatA();
2558 test_GetDateFormatA();
2559 test_GetDateFormatW();
2560 test_GetCurrencyFormatA(); /* Also tests the W version */
2561 test_GetNumberFormatA(); /* Also tests the W version */
2562 test_CompareStringA();
2563 test_LCMapStringA();
2564 test_LCMapStringW();
2567 test_ConvertDefaultLocale();
2568 test_EnumSystemLanguageGroupsA();
2569 test_EnumLanguageGroupLocalesA();
2570 test_SetLocaleInfoA();
2571 test_EnumUILanguageA();
2573 /* this requires collation table patch to make it MS compatible */
2574 if (0) test_sorting();