2 * Unit tests for locale functions
4 * Copyright 2002 YASAR Mehmet
5 * Copyright 2003 Dmitry Timoshkov
6 * Copyright 2003 Jon Griffiths
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 * We must pass LOCALE_NOUSEROVERRIDE (NUO) to formatting functions so that
24 * even when the user has overridden their default i8n settings (e.g. in
25 * the control panel i8n page), we will still get the expected results.
32 #include "wine/test.h"
38 static inline unsigned int strlenW( const WCHAR *str )
45 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
48 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
52 static inline WCHAR *strchrW( const WCHAR *str, WCHAR ch )
54 do { if (*str == ch) return (WCHAR *)str; } while (*str++);
58 static inline int isdigitW( WCHAR wc )
61 GetStringTypeW( CT_CTYPE1, &wc, 1, &type );
62 return type & C1_DIGIT;
65 /* Some functions are only in later versions of kernel32.dll */
66 static HMODULE hKernel32;
67 static WORD enumCount;
69 typedef BOOL (WINAPI *EnumSystemLanguageGroupsAFn)(LANGUAGEGROUP_ENUMPROC,
71 static EnumSystemLanguageGroupsAFn pEnumSystemLanguageGroupsA;
72 typedef BOOL (WINAPI *EnumLanguageGroupLocalesAFn)(LANGGROUPLOCALE_ENUMPROC,
73 LGRPID, DWORD, LONG_PTR);
74 static EnumLanguageGroupLocalesAFn pEnumLanguageGroupLocalesA;
75 typedef BOOL (WINAPI *EnumUILanguagesAFn)(UILANGUAGE_ENUMPROC,
77 static EnumUILanguagesAFn pEnumUILanguagesA;
79 typedef INT (WINAPI *FoldStringAFn)(DWORD, LPCSTR, INT, LPSTR, INT);
80 static FoldStringAFn pFoldStringA;
81 typedef INT (WINAPI *FoldStringWFn)(DWORD, LPCWSTR, INT, LPWSTR, INT);
82 static FoldStringWFn pFoldStringW;
84 typedef BOOL (WINAPI *IsValidLanguageGroupFn)(LGRPID, DWORD);
85 static IsValidLanguageGroupFn pIsValidLanguageGroup;
87 static void InitFunctionPointers(void)
89 hKernel32 = GetModuleHandleA("kernel32");
90 pEnumSystemLanguageGroupsA = (void*)GetProcAddress(hKernel32, "EnumSystemLanguageGroupsA");
91 pEnumLanguageGroupLocalesA = (void*)GetProcAddress(hKernel32, "EnumLanguageGroupLocalesA");
92 pFoldStringA = (void*)GetProcAddress(hKernel32, "FoldStringA");
93 pFoldStringW = (void*)GetProcAddress(hKernel32, "FoldStringW");
94 pIsValidLanguageGroup = (void*)GetProcAddress(hKernel32, "IsValidLanguageGroup");
95 pEnumUILanguagesA = (void*)GetProcAddress(hKernel32, "EnumUILanguagesA");
98 #define eq(received, expected, label, type) \
99 ok((received) == (expected), "%s: got " type " instead of " type "\n", \
100 (label), (received), (expected))
102 #define BUFFER_SIZE 128
103 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
105 #define STRINGSA(x,y) strcpy(input, x); strcpy(Expected, y); SetLastError(0xdeadbeef); buffer[0] = '\0'
106 #define EXPECT_LENA ok(ret == lstrlen(Expected)+1, "Expected Len %d, got %d\n", lstrlen(Expected)+1, ret)
107 #define EXPECT_EQA ok(strncmp(buffer, Expected, strlen(Expected)) == 0, \
108 "Expected '%s', got '%s'\n", Expected, buffer)
110 #define STRINGSW(x,y) MultiByteToWideChar(CP_ACP,0,x,-1,input,COUNTOF(input)); \
111 MultiByteToWideChar(CP_ACP,0,y,-1,Expected,COUNTOF(Expected)); \
112 SetLastError(0xdeadbeef); buffer[0] = '\0'
113 #define EXPECT_LENW ok(ret == lstrlenW(Expected)+1, "Expected Len %d, got %d\n", lstrlenW(Expected)+1, ret)
114 #define EXPECT_EQW ok(strncmpW(buffer, Expected, strlenW(Expected)) == 0, "Bad conversion\n")
116 #define NUO LOCALE_NOUSEROVERRIDE
118 static void test_GetLocaleInfoA(void)
122 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
123 char buffer[BUFFER_SIZE];
124 char expected[BUFFER_SIZE];
126 ok(lcid == 0x409, "wrong LCID calculated - %d\n", lcid);
128 /* en and ar use SUBLANG_NEUTRAL, but GetLocaleInfo assume SUBLANG_DEFAULT
129 Same is true for zh on pre-Vista, but on Vista and higher GetLocaleInfo
130 assumes SUBLANG_NEUTRAL for zh */
131 memset(expected, 0, COUNTOF(expected));
132 len = GetLocaleInfoA(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
133 SetLastError(0xdeadbeef);
134 memset(buffer, 0, COUNTOF(buffer));
135 ret = GetLocaleInfoA(LANG_ENGLISH, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
136 ok((ret == len) && !lstrcmpA(buffer, expected),
137 "got %d with '%s' (expected %d with '%s')\n",
138 ret, buffer, len, expected);
140 memset(expected, 0, COUNTOF(expected));
141 len = GetLocaleInfoA(MAKELANGID(LANG_ARABIC, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
143 SetLastError(0xdeadbeef);
144 memset(buffer, 0, COUNTOF(buffer));
145 ret = GetLocaleInfoA(LANG_ARABIC, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
146 ok((ret == len) && !lstrcmpA(buffer, expected),
147 "got %d with '%s' (expected %d with '%s')\n",
148 ret, buffer, len, expected);
151 win_skip("LANG_ARABIC not installed\n");
153 /* SUBLANG_DEFAULT is required for mlang.dll, but optional for GetLocaleInfo */
154 memset(expected, 0, COUNTOF(expected));
155 len = GetLocaleInfoA(MAKELANGID(LANG_GERMAN, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
156 SetLastError(0xdeadbeef);
157 memset(buffer, 0, COUNTOF(buffer));
158 ret = GetLocaleInfoA(LANG_GERMAN, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
159 ok((ret == len) && !lstrcmpA(buffer, expected),
160 "got %d with '%s' (expected %d with '%s')\n",
161 ret, buffer, len, expected);
164 /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
165 * partially fill the buffer even if it is too short. See bug 637.
167 SetLastError(0xdeadbeef);
168 memset(buffer, 0, COUNTOF(buffer));
169 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 0);
170 ok(ret == 7 && !buffer[0], "Expected len=7, got %d\n", ret);
172 SetLastError(0xdeadbeef);
173 memset(buffer, 0, COUNTOF(buffer));
174 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 3);
175 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
176 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
177 ok(!strcmp(buffer, "Mon"), "Expected 'Mon', got '%s'\n", buffer);
179 SetLastError(0xdeadbeef);
180 memset(buffer, 0, COUNTOF(buffer));
181 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 10);
182 ok(ret == 7, "Expected ret == 7, got %d, error %d\n", ret, GetLastError());
183 ok(!strcmp(buffer, "Monday"), "Expected 'Monday', got '%s'\n", buffer);
186 static void test_GetTimeFormatA(void)
190 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
191 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
193 memset(&curtime, 2, sizeof(SYSTEMTIME));
194 STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
195 SetLastError(0xdeadbeef);
196 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
197 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
198 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
201 curtime.wMinute = 56;
202 curtime.wSecond = 13;
203 curtime.wMilliseconds = 22;
204 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
205 SetLastError(0xdeadbeef);
206 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
207 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
208 EXPECT_LENA; EXPECT_EQA;
210 /* MSDN: LOCALE_NOUSEROVERRIDE can't be specified with a format string */
211 SetLastError(0xdeadbeef);
212 ret = GetTimeFormatA(lcid, NUO|TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
213 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
214 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
216 STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficient buffer */
217 SetLastError(0xdeadbeef);
218 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, 2);
219 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
220 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
222 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
223 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, NULL, 0);
224 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
227 STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
228 ret = GetTimeFormatA(lcid, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
229 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
230 EXPECT_LENA; EXPECT_EQA;
232 STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
233 ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
234 ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
235 ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "4" )), /* win9x */
236 "Expected '', got '%s'\n", buffer );
238 STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
239 ret = GetTimeFormatA(lcid, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
240 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
241 EXPECT_LENA; EXPECT_EQA;
243 STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
244 strcpy(Expected, "8:56 AM");
245 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
246 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
247 EXPECT_LENA; EXPECT_EQA;
249 STRINGSA("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
250 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
251 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
252 ok( !strcmp( buffer, "8.@:56AM" ) || broken( !strcmp( buffer, "8.@:56.@:AM" )) /* win9x */,
253 "Expected '8.@:56AM', got '%s'\n", buffer );
255 STRINGSA("s1s2s3", ""); /* Duplicate tokens */
256 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
257 ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
258 ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "3" )), /* win9x */
259 "Expected '', got '%s'\n", buffer );
261 STRINGSA("t/tt", "A/AM"); /* AM time marker */
262 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
263 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
264 EXPECT_LENA; EXPECT_EQA;
267 STRINGSA("t/tt", "P/PM"); /* PM time marker */
268 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
269 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
270 EXPECT_LENA; EXPECT_EQA;
272 STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
273 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
274 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
275 EXPECT_LENA; EXPECT_EQA;
277 STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
278 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
279 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
280 EXPECT_LENA; EXPECT_EQA;
282 STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
283 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
284 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
285 EXPECT_LENA; EXPECT_EQA;
287 curtime.wHour = 14; /* change this to 14 or 2pm */
290 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 */
291 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
292 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
293 EXPECT_LENA; EXPECT_EQA;
296 STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
297 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
298 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
299 EXPECT_LENA; EXPECT_EQA;
301 STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
302 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
303 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
304 EXPECT_LENA; EXPECT_EQA;
306 /* try to convert formatting strings with more than two letters
307 * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
308 * NOTE: We expect any letter for which there is an upper case value
309 * we should see a replacement. For letters that DO NOT have
310 * upper case values we should see NO REPLACEMENT.
313 curtime.wMinute = 56;
314 curtime.wSecond = 13;
315 curtime.wMilliseconds = 22;
316 STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
317 "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
318 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
319 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
320 EXPECT_LENA; EXPECT_EQA;
322 STRINGSA("h", "text"); /* Don't write to buffer if len is 0 */
323 strcpy(buffer, "text");
324 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, 0);
325 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
328 STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
329 "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
330 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
331 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
332 EXPECT_LENA; EXPECT_EQA;
334 STRINGSA("'''", "'"); /* invalid quoted string */
335 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
336 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
337 EXPECT_LENA; EXPECT_EQA;
339 /* test that msdn suggested single quotation usage works as expected */
340 STRINGSA("''''", "'"); /* single quote mark */
341 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
342 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
343 EXPECT_LENA; EXPECT_EQA;
345 STRINGSA("''HHHHHH", "08"); /* Normal use */
346 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
347 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
348 EXPECT_LENA; EXPECT_EQA;
350 /* and test for normal use of the single quotation mark */
351 STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
352 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
353 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
354 EXPECT_LENA; EXPECT_EQA;
356 STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
357 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
358 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
359 EXPECT_LENA; EXPECT_EQA;
361 STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
362 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
363 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
364 EXPECT_LENA; EXPECT_EQA;
367 STRINGSA("'123'tt", ""); /* Invalid time */
368 SetLastError(0xdeadbeef);
369 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
370 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
371 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
374 curtime.wMonth = 60; /* Invalid */
375 STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
376 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
377 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
378 EXPECT_LENA; EXPECT_EQA;
381 static void test_GetDateFormatA(void)
385 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
386 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
388 memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
389 STRINGSA("ddd',' MMM dd yy","");
390 SetLastError(0xdeadbeef);
391 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
392 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
393 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
395 curtime.wYear = 2002;
398 curtime.wDayOfWeek = 3;
399 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
400 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
401 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
402 EXPECT_LENA; EXPECT_EQA;
404 /* Same as above but with LOCALE_NOUSEROVERRIDE */
405 STRINGSA("ddd',' MMM dd yy",""); /* Simple case */
406 SetLastError(0xdeadbeef);
407 ret = GetDateFormatA(lcid, NUO, &curtime, input, buffer, COUNTOF(buffer));
408 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
409 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
412 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
413 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
414 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
415 EXPECT_LENA; EXPECT_EQA;
417 curtime.wHour = 36; /* Invalid */
418 STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
419 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
420 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
421 EXPECT_LENA; EXPECT_EQA;
423 STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
424 ret = GetDateFormatA(lcid, 0, &curtime, input, NULL, 0);
425 ok(ret == 16, "Expected ret == 16, got %d, error %d\n", ret, GetLastError());
428 STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
429 SetLastError(0xdeadbeef);
430 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, 2);
431 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
432 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
434 STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
435 ret = GetDateFormat(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
436 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
437 if (strncmp(buffer, Expected, strlen(Expected)) && strncmp(buffer, "5/4/02", strlen(Expected)) != 0)
438 ok (0, "Expected '%s' or '5/4/02', got '%s'\n", Expected, buffer);
440 STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
441 ret = GetDateFormat(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
442 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
443 EXPECT_LENA; EXPECT_EQA;
445 /* test for expected DATE_YEARMONTH behavior with null format */
446 /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
447 STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
448 SetLastError(0xdeadbeef);
449 ret = GetDateFormat(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
450 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
451 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
454 /* Test that using invalid DATE_* flags results in the correct error */
455 /* and return values */
456 STRINGSA("m/d/y", ""); /* Invalid flags */
457 SetLastError(0xdeadbeef);
458 ret = GetDateFormat(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
459 &curtime, input, buffer, COUNTOF(buffer));
460 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
461 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
465 static void test_GetDateFormatW(void)
469 WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
470 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
472 STRINGSW("",""); /* If flags is not zero then format must be NULL */
473 ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL,
474 input, buffer, COUNTOF(buffer));
475 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
477 win_skip("GetDateFormatW is not implemented\n");
480 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
481 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
484 STRINGSW("",""); /* NULL buffer, len > 0 */
485 SetLastError(0xdeadbeef);
486 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
487 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
488 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
490 STRINGSW("",""); /* NULL buffer, len == 0 */
491 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
492 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
493 EXPECT_LENW; EXPECT_EQW;
495 curtime.wYear = 2002;
498 curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
499 curtime.wHour = 65432; /* Invalid */
500 curtime.wMinute = 34512; /* Invalid */
501 curtime.wSecond = 65535; /* Invalid */
502 curtime.wMilliseconds = 12345;
503 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
504 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
505 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
506 EXPECT_LENW; EXPECT_EQW;
510 curtime.wYear = 1601;
513 curtime.wDayOfWeek = 0; /* Irrelevant */
517 curtime.wMilliseconds = 0;
518 STRINGSW("dddd d MMMM yyyy","Monday 1 January 1601");
519 SetLastError(0xdeadbeef);
520 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
521 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
522 EXPECT_LENW; EXPECT_EQW;
524 curtime.wYear = 1600;
527 curtime.wDayOfWeek = 0; /* Irrelevant */
529 curtime.wMinute = 59;
530 curtime.wSecond = 59;
531 curtime.wMilliseconds = 999;
532 STRINGSW("dddd d MMMM yyyy","Friday 31 December 1600");
533 SetLastError(0xdeadbeef);
534 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
535 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
536 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
540 #define CY_POS_LEFT 0
541 #define CY_POS_RIGHT 1
542 #define CY_POS_LEFT_SPACE 2
543 #define CY_POS_RIGHT_SPACE 3
545 static void test_GetCurrencyFormatA(void)
547 static char szDot[] = { '.', '\0' };
548 static char szComma[] = { ',', '\0' };
549 static char szDollar[] = { '$', '\0' };
551 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
552 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
555 memset(&format, 0, sizeof(format));
557 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
558 SetLastError(0xdeadbeef);
559 ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
560 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
561 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
563 STRINGSA("23,53",""); /* Invalid character --> Error */
564 SetLastError(0xdeadbeef);
565 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
566 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
567 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
569 STRINGSA("--",""); /* Double '-' --> Error */
570 SetLastError(0xdeadbeef);
571 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
572 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
573 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
575 STRINGSA("0-",""); /* Trailing '-' --> Error */
576 SetLastError(0xdeadbeef);
577 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
578 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
579 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
581 STRINGSA("0..",""); /* Double '.' --> Error */
582 SetLastError(0xdeadbeef);
583 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
584 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
585 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
587 STRINGSA(" 0.1",""); /* Leading space --> Error */
588 SetLastError(0xdeadbeef);
589 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
590 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
591 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
593 STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
594 SetLastError(0xdeadbeef);
595 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, 2);
596 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
597 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
599 STRINGSA("2353",""); /* Format and flags given --> Error */
600 SetLastError(0xdeadbeef);
601 ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
602 ok( !ret, "Expected ret == 0, got %d\n", ret);
603 ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
604 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
606 STRINGSA("2353",""); /* Invalid format --> Error */
607 SetLastError(0xdeadbeef);
608 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
609 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
610 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
612 STRINGSA("2353","$2,353.00"); /* Valid number */
613 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
614 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
615 EXPECT_LENA; EXPECT_EQA;
617 STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
618 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
619 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
620 EXPECT_LENA; EXPECT_EQA;
622 STRINGSA("2353.1","$2,353.10"); /* Valid real number */
623 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
624 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
625 EXPECT_LENA; EXPECT_EQA;
627 STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
628 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
629 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
630 EXPECT_LENA; EXPECT_EQA;
632 STRINGSA("2353.119","$2,353.12"); /* Too many DP --> Rounded */
633 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
634 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
635 EXPECT_LENA; EXPECT_EQA;
637 format.NumDigits = 0; /* No decimal separator */
638 format.LeadingZero = 0;
639 format.Grouping = 0; /* No grouping char */
640 format.NegativeOrder = 0;
641 format.PositiveOrder = CY_POS_LEFT;
642 format.lpDecimalSep = szDot;
643 format.lpThousandSep = szComma;
644 format.lpCurrencySymbol = szDollar;
646 STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
647 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
648 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
649 EXPECT_LENA; EXPECT_EQA;
651 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
652 STRINGSA("2353","$2353.0");
653 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
654 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
655 EXPECT_LENA; EXPECT_EQA;
657 format.Grouping = 2; /* Group by 100's */
658 STRINGSA("2353","$23,53.0");
659 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
660 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
661 EXPECT_LENA; EXPECT_EQA;
663 format.LeadingZero = 1; /* Always provide leading zero */
664 STRINGSA(".5","$0.5");
665 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
666 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
667 EXPECT_LENA; EXPECT_EQA;
669 format.PositiveOrder = CY_POS_RIGHT;
670 STRINGSA("1","1.0$");
671 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
672 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
673 EXPECT_LENA; EXPECT_EQA;
675 format.PositiveOrder = CY_POS_LEFT_SPACE;
676 STRINGSA("1","$ 1.0");
677 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
678 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
679 EXPECT_LENA; EXPECT_EQA;
681 format.PositiveOrder = CY_POS_RIGHT_SPACE;
682 STRINGSA("1","1.0 $");
683 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
684 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
685 EXPECT_LENA; EXPECT_EQA;
687 format.NegativeOrder = 0;
688 STRINGSA("-1","($1.0)");
689 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
690 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
691 EXPECT_LENA; EXPECT_EQA;
693 format.NegativeOrder = 1;
694 STRINGSA("-1","-$1.0");
695 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
696 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
697 EXPECT_LENA; EXPECT_EQA;
699 format.NegativeOrder = 2;
700 STRINGSA("-1","$-1.0");
701 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
702 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
703 EXPECT_LENA; EXPECT_EQA;
705 format.NegativeOrder = 3;
706 STRINGSA("-1","$1.0-");
707 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
708 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
709 EXPECT_LENA; EXPECT_EQA;
711 format.NegativeOrder = 4;
712 STRINGSA("-1","(1.0$)");
713 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
714 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
715 EXPECT_LENA; EXPECT_EQA;
717 format.NegativeOrder = 5;
718 STRINGSA("-1","-1.0$");
719 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
720 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
721 EXPECT_LENA; EXPECT_EQA;
723 format.NegativeOrder = 6;
724 STRINGSA("-1","1.0-$");
725 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
726 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
727 EXPECT_LENA; EXPECT_EQA;
729 format.NegativeOrder = 7;
730 STRINGSA("-1","1.0$-");
731 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
732 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
733 EXPECT_LENA; EXPECT_EQA;
735 format.NegativeOrder = 8;
736 STRINGSA("-1","-1.0 $");
737 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
738 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
739 EXPECT_LENA; EXPECT_EQA;
741 format.NegativeOrder = 9;
742 STRINGSA("-1","-$ 1.0");
743 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
744 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
745 EXPECT_LENA; EXPECT_EQA;
747 format.NegativeOrder = 10;
748 STRINGSA("-1","1.0 $-");
749 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
750 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
751 EXPECT_LENA; EXPECT_EQA;
753 format.NegativeOrder = 11;
754 STRINGSA("-1","$ 1.0-");
755 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
756 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
757 EXPECT_LENA; EXPECT_EQA;
759 format.NegativeOrder = 12;
760 STRINGSA("-1","$ -1.0");
761 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
762 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
763 EXPECT_LENA; EXPECT_EQA;
765 format.NegativeOrder = 13;
766 STRINGSA("-1","1.0- $");
767 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
768 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
769 EXPECT_LENA; EXPECT_EQA;
771 format.NegativeOrder = 14;
772 STRINGSA("-1","($ 1.0)");
773 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
774 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
775 EXPECT_LENA; EXPECT_EQA;
777 format.NegativeOrder = 15;
778 STRINGSA("-1","(1.0 $)");
779 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
780 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
781 EXPECT_LENA; EXPECT_EQA;
784 #define NEG_PARENS 0 /* "(1.1)" */
785 #define NEG_LEFT 1 /* "-1.1" */
786 #define NEG_LEFT_SPACE 2 /* "- 1.1" */
787 #define NEG_RIGHT 3 /* "1.1-" */
788 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
790 static void test_GetNumberFormatA(void)
792 static char szDot[] = { '.', '\0' };
793 static char szComma[] = { ',', '\0' };
795 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
796 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
799 memset(&format, 0, sizeof(format));
801 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
802 SetLastError(0xdeadbeef);
803 ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
804 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
805 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
807 STRINGSA("23,53",""); /* Invalid character --> Error */
808 SetLastError(0xdeadbeef);
809 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
810 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
811 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
813 STRINGSA("--",""); /* Double '-' --> Error */
814 SetLastError(0xdeadbeef);
815 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
816 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
817 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
819 STRINGSA("0-",""); /* Trailing '-' --> Error */
820 SetLastError(0xdeadbeef);
821 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
822 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
823 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
825 STRINGSA("0..",""); /* Double '.' --> Error */
826 SetLastError(0xdeadbeef);
827 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
828 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
829 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
831 STRINGSA(" 0.1",""); /* Leading space --> Error */
832 SetLastError(0xdeadbeef);
833 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
834 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
835 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
837 STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
838 SetLastError(0xdeadbeef);
839 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, 2);
840 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
841 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
843 STRINGSA("2353",""); /* Format and flags given --> Error */
844 SetLastError(0xdeadbeef);
845 ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
846 ok( !ret, "Expected ret == 0, got %d\n", ret);
847 ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
848 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
850 STRINGSA("2353",""); /* Invalid format --> Error */
851 SetLastError(0xdeadbeef);
852 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
853 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
854 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
856 STRINGSA("2353","2,353.00"); /* Valid number */
857 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
858 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
859 EXPECT_LENA; EXPECT_EQA;
861 STRINGSA("-2353","-2,353.00"); /* Valid negative number */
862 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
863 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
864 EXPECT_LENA; EXPECT_EQA;
866 STRINGSA("-353","-353.00"); /* test for off by one error in grouping */
867 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
868 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
869 EXPECT_LENA; EXPECT_EQA;
871 STRINGSA("2353.1","2,353.10"); /* Valid real number */
872 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
873 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
874 EXPECT_LENA; EXPECT_EQA;
876 STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
877 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
878 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
879 EXPECT_LENA; EXPECT_EQA;
881 STRINGSA("2353.119","2,353.12"); /* Too many DP --> Rounded */
882 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
883 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
884 EXPECT_LENA; EXPECT_EQA;
886 format.NumDigits = 0; /* No decimal separator */
887 format.LeadingZero = 0;
888 format.Grouping = 0; /* No grouping char */
889 format.NegativeOrder = 0;
890 format.lpDecimalSep = szDot;
891 format.lpThousandSep = szComma;
893 STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
894 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
895 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
896 EXPECT_LENA; EXPECT_EQA;
898 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
899 STRINGSA("2353","2353.0");
900 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
901 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
902 EXPECT_LENA; EXPECT_EQA;
904 format.Grouping = 2; /* Group by 100's */
905 STRINGSA("2353","23,53.0");
906 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
907 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
908 EXPECT_LENA; EXPECT_EQA;
910 format.LeadingZero = 1; /* Always provide leading zero */
911 STRINGSA(".5","0.5");
912 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
913 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
914 EXPECT_LENA; EXPECT_EQA;
916 format.NegativeOrder = NEG_PARENS;
917 STRINGSA("-1","(1.0)");
918 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
919 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
920 EXPECT_LENA; EXPECT_EQA;
922 format.NegativeOrder = NEG_LEFT;
923 STRINGSA("-1","-1.0");
924 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
925 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
926 EXPECT_LENA; EXPECT_EQA;
928 format.NegativeOrder = NEG_LEFT_SPACE;
929 STRINGSA("-1","- 1.0");
930 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
931 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
932 EXPECT_LENA; EXPECT_EQA;
934 format.NegativeOrder = NEG_RIGHT;
935 STRINGSA("-1","1.0-");
936 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
937 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
938 EXPECT_LENA; EXPECT_EQA;
940 format.NegativeOrder = NEG_RIGHT_SPACE;
941 STRINGSA("-1","1.0 -");
942 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
943 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
944 EXPECT_LENA; EXPECT_EQA;
946 lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
948 if (IsValidLocale(lcid, 0))
950 STRINGSA("-12345","-12 345,00"); /* Try French formatting */
951 Expected[3] = 160; /* Non breaking space */
952 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
953 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
954 EXPECT_LENA; EXPECT_EQA;
959 static void test_CompareStringA(void)
962 LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
964 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
965 ok (ret== 1, "(Salut/Salute) Expected 1, got %d\n", ret);
967 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
968 ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
970 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
971 ok (ret== 3, "(Salut/hola) Expected 3, got %d\n", ret);
973 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
974 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
976 lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
978 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
979 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
981 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
982 ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
984 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
985 ok (ret == 2, "(Salut/saLuT) Expected 2, got %d\n", ret);
987 /* test for CompareStringA flags */
988 SetLastError(0xdeadbeef);
989 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0x8, "NULL", -1, "NULL", -1);
990 ok(GetLastError() == ERROR_INVALID_FLAGS,
991 "unexpected error code %d\n", GetLastError());
992 ok(!ret, "CompareStringA must fail with invalid flag\n");
994 SetLastError(0xdeadbeef);
995 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, LOCALE_USE_CP_ACP, "NULL", -1, "NULL", -1);
996 ok(GetLastError() == 0xdeadbeef, "unexpected error code %d\n", GetLastError());
997 ok(ret == CSTR_EQUAL, "CompareStringA error: %d != CSTR_EQUAL\n", ret);
998 /* end of test for CompareStringA flags */
1000 ret = lstrcmpA("", "");
1001 ok (ret == 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret);
1003 ret = lstrcmpA(NULL, NULL);
1004 ok (ret == 0 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, NULL) should return 0, 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 = lstrcmpA(NULL, "");
1010 ok (ret == -1 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret);
1012 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"EndDialog",-1,"_Property",-1);
1013 ok( ret == 3, "EndDialog vs _Property ... expected 3, got %d\n", ret);
1015 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0070",-1,"_IEWWBrowserComp",-1);
1016 ok( ret == 3, "osp_vba.sreg0070 vs _IEWWBrowserComp ... expected 3, got %d\n", ret);
1018 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"r",-1,"\\",-1);
1019 ok( ret == 3, "r vs \\ ... expected 3, got %d\n", ret);
1021 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0031", -1, "OriginalDatabase", -1 );
1022 ok( ret == 3, "osp_vba.sreg0031 vs OriginalDatabase ... expected 3, got %d\n", ret);
1024 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1 );
1025 ok( ret == 3, "AAA vs aaa expected 3, 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, "Aab", -1 );
1034 ok( ret == 1, ".AAA vs Aab expected 1, got %d\n", ret);
1036 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1 );
1037 ok( ret == 1, ".AAA vs A.ab expected 1, got %d\n", ret);
1039 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1 );
1040 ok( ret == 1, "aa vs AB expected 1, got %d\n", ret);
1042 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1 );
1043 ok( ret == 1, "aa vs Aab expected 1, got %d\n", ret);
1045 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1 );
1046 ok( ret == 3, "aB vs Aab expected 3, got %d\n", ret);
1048 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1 );
1049 ok( ret == 1, "Ba vs bab expected 1, got %d\n", ret);
1051 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1 );
1052 ok( ret == 1, "{100}{83}{71}{71}{71} vs Global_DataAccess_JRO expected 1, 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, "A", -1, "{", -1 );
1058 ok( ret == 3, "A vs { expected 3, got %d\n", ret);
1060 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1 );
1061 ok(ret == 1, "3.5/0 vs 4.0/-1 expected 1, got %d\n", ret);
1063 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1 );
1064 ok(ret == 1, "3.5 vs 4.0 expected 1, got %d\n", ret);
1066 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1 );
1067 ok(ret == 1, "3.520.4403.2 vs 4.0.2927.10 expected 1, got %d\n", ret);
1069 /* hyphen and apostrophe are treated differently depending on
1070 * whether SORT_STRINGSORT specified or not
1072 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1 );
1073 ok(ret == 3, "-o vs /m expected 3, got %d\n", ret);
1075 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1 );
1076 ok(ret == 1, "/m vs -o expected 1, got %d\n", ret);
1078 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1 );
1079 ok(ret == 1, "-o vs /m expected 1, got %d\n", ret);
1081 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1 );
1082 ok(ret == 3, "/m vs -o expected 3, got %d\n", ret);
1084 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1 );
1085 ok(ret == 3, "'o vs /m expected 3, got %d\n", ret);
1087 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1 );
1088 ok(ret == 1, "/m vs 'o expected 1, got %d\n", ret);
1090 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1 );
1091 ok(ret == 1, "'o vs /m expected 1, got %d\n", ret);
1093 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1 );
1094 ok(ret == 3, "/m vs 'o expected 3, got %d\n", ret);
1096 if (0) { /* this requires collation table patch to make it MS compatible */
1097 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
1098 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
1100 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
1101 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
1103 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
1104 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
1106 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
1107 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
1109 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
1110 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
1112 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
1113 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
1115 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
1116 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
1118 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
1119 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
1121 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
1122 ok(ret == 1, "`o vs -m expected 1, got %d\n", ret);
1124 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
1125 ok(ret == 3, "-m vs `o expected 3, got %d\n", ret);
1127 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
1128 ok(ret == 3, "`o vs -m expected 3, got %d\n", ret);
1130 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
1131 ok(ret == 1, "-m vs `o expected 1, got %d\n", ret);
1134 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9);
1135 ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0 expected 2, got %d\n", ret);
1137 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10);
1138 ok(ret == 1, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1, got %d\n", ret);
1140 /* WinXP handles embedded NULLs differently than earlier versions */
1141 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
1142 ok(ret == 1 || ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1 or 2, got %d\n", ret);
1144 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
1145 ok(ret == 1 || ret == 2, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected 1 or 2, got %d\n", ret);
1147 ret = CompareStringA(lcid, 0, "a\0b", -1, "a", -1);
1148 ok(ret == 2, "a vs a expected 2, got %d\n", ret);
1150 ret = CompareStringA(lcid, 0, "a\0b", 4, "a", 2);
1151 ok(ret == CSTR_EQUAL || /* win2k */
1152 ret == CSTR_GREATER_THAN,
1153 "a\\0b vs a expected CSTR_EQUAL or CSTR_GREATER_THAN, got %d\n", ret);
1155 ret = CompareStringA(lcid, 0, "\2", 2, "\1", 2);
1156 todo_wine ok(ret != 2, "\\2 vs \\1 expected unequal\n");
1158 ret = CompareStringA(lcid, NORM_IGNORECASE | LOCALE_USE_CP_ACP, "#", -1, ".", -1);
1159 todo_wine ok(ret == CSTR_LESS_THAN, "\"#\" vs \".\" expected CSTR_LESS_THAN, got %d\n", ret);
1161 ret = lstrcmpi("#", ".");
1162 todo_wine ok(ret == -1, "\"#\" vs \".\" expected -1, got %d\n", ret);
1165 static void test_LCMapStringA(void)
1168 char buf[256], buf2[256];
1169 static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
1170 static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
1171 static const char symbols_stripped[] = "justateststring1";
1173 SetLastError(0xdeadbeef);
1174 ret = LCMapStringA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP | LCMAP_LOWERCASE,
1175 lower_case, -1, buf, sizeof(buf));
1176 ok(ret == lstrlenA(lower_case) + 1,
1177 "ret %d, error %d, expected value %d\n",
1178 ret, GetLastError(), lstrlenA(lower_case) + 1);
1179 ok(!memcmp(buf, lower_case, ret), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1181 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1182 upper_case, -1, buf, sizeof(buf));
1183 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1184 ok(GetLastError() == ERROR_INVALID_FLAGS,
1185 "unexpected error code %d\n", GetLastError());
1187 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1188 upper_case, -1, buf, sizeof(buf));
1189 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1190 ok(GetLastError() == ERROR_INVALID_FLAGS,
1191 "unexpected error code %d\n", GetLastError());
1193 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1194 upper_case, -1, buf, sizeof(buf));
1195 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1196 ok(GetLastError() == ERROR_INVALID_FLAGS,
1197 "unexpected error code %d\n", GetLastError());
1199 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1200 upper_case, -1, buf, sizeof(buf));
1201 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1202 ok(GetLastError() == ERROR_INVALID_FLAGS,
1203 "unexpected error code %d\n", GetLastError());
1205 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1206 SetLastError(0xdeadbeef);
1207 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1208 upper_case, -1, buf, sizeof(buf));
1209 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1210 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1212 /* test LCMAP_LOWERCASE */
1213 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1214 upper_case, -1, buf, sizeof(buf));
1215 ok(ret == lstrlenA(upper_case) + 1,
1216 "ret %d, error %d, expected value %d\n",
1217 ret, GetLastError(), lstrlenA(upper_case) + 1);
1218 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1220 /* test LCMAP_UPPERCASE */
1221 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1222 lower_case, -1, buf, sizeof(buf));
1223 ok(ret == lstrlenA(lower_case) + 1,
1224 "ret %d, error %d, expected value %d\n",
1225 ret, GetLastError(), lstrlenA(lower_case) + 1);
1226 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1228 /* test buffer overflow */
1229 SetLastError(0xdeadbeef);
1230 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1231 lower_case, -1, buf, 4);
1232 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1233 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1235 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1236 lstrcpyA(buf, lower_case);
1237 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1238 buf, -1, buf, sizeof(buf));
1239 if (!ret) /* Win9x */
1240 trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1243 ok(ret == lstrlenA(lower_case) + 1,
1244 "ret %d, error %d, expected value %d\n",
1245 ret, GetLastError(), lstrlenA(lower_case) + 1);
1246 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1248 lstrcpyA(buf, upper_case);
1249 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1250 buf, -1, buf, sizeof(buf));
1251 if (!ret) /* Win9x */
1252 trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1255 ok(ret == lstrlenA(upper_case) + 1,
1256 "ret %d, error %d, expected value %d\n",
1257 ret, GetLastError(), lstrlenA(lower_case) + 1);
1258 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1261 /* otherwise src == dst should fail */
1262 SetLastError(0xdeadbeef);
1263 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1264 buf, 10, buf, sizeof(buf));
1265 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1266 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1267 "unexpected error code %d\n", GetLastError());
1268 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1270 /* test whether '\0' is always appended */
1271 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1272 upper_case, -1, buf, sizeof(buf));
1273 ok(ret, "LCMapStringA must succeed\n");
1274 ok(buf[ret-1] == 0, "LCMapStringA not null-terminated\n");
1275 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1276 upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1277 ok(ret2, "LCMapStringA must succeed\n");
1278 ok(buf2[ret2-1] == 0, "LCMapStringA not null-terminated\n" );
1279 ok(ret == ret2, "lengths of sort keys must be equal\n");
1280 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1282 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1283 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1284 upper_case, -1, buf, sizeof(buf));
1285 ok(ret, "LCMapStringA must succeed\n");
1286 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1287 lower_case, -1, buf2, sizeof(buf2));
1288 ok(ret2, "LCMapStringA must succeed\n");
1289 ok(ret == ret2, "lengths of sort keys must be equal\n");
1290 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1292 /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1293 results from plain LCMAP_SORTKEY on Vista */
1295 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1296 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1297 lower_case, -1, buf, sizeof(buf));
1298 ok(ret, "LCMapStringA must succeed\n");
1299 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1300 symbols_stripped, -1, buf2, sizeof(buf2));
1301 ok(ret2, "LCMapStringA must succeed\n");
1302 ok(ret == ret2, "lengths of sort keys must be equal\n");
1303 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1305 /* test NORM_IGNORENONSPACE */
1306 lstrcpyA(buf, "foo");
1307 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1308 lower_case, -1, buf, sizeof(buf));
1309 ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1310 lstrlenA(lower_case) + 1, ret);
1311 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1313 /* test NORM_IGNORESYMBOLS */
1314 lstrcpyA(buf, "foo");
1315 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1316 lower_case, -1, buf, sizeof(buf));
1317 ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1318 lstrlenA(symbols_stripped) + 1, ret);
1319 ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1321 /* test srclen = 0 */
1322 SetLastError(0xdeadbeef);
1323 ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1324 ok(!ret, "LCMapStringA should fail with srclen = 0\n");
1325 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1326 "unexpected error code %d\n", GetLastError());
1329 static void test_LCMapStringW(void)
1332 WCHAR buf[256], buf2[256];
1333 char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1334 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};
1335 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};
1336 static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
1337 static const WCHAR fooW[] = {'f','o','o',0};
1339 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1340 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1341 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1343 win_skip("LCMapStringW is not implemented\n");
1347 ok(lstrcmpW(buf, upper_case) == 0, "Expected upper case string\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());
1355 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1356 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1357 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1358 ok(GetLastError() == ERROR_INVALID_FLAGS,
1359 "unexpected error code %d\n", GetLastError());
1361 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1362 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1363 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1364 ok(GetLastError() == ERROR_INVALID_FLAGS,
1365 "unexpected error code %d\n", GetLastError());
1367 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1368 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1369 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1370 ok(GetLastError() == ERROR_INVALID_FLAGS,
1371 "unexpected error code %d\n", GetLastError());
1373 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1374 SetLastError(0xdeadbeef);
1375 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1376 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1377 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1378 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1380 /* test LCMAP_LOWERCASE */
1381 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1382 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1383 ok(ret == lstrlenW(upper_case) + 1,
1384 "ret %d, error %d, expected value %d\n",
1385 ret, GetLastError(), lstrlenW(upper_case) + 1);
1386 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1388 /* test LCMAP_UPPERCASE */
1389 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1390 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1391 ok(ret == lstrlenW(lower_case) + 1,
1392 "ret %d, error %d, expected value %d\n",
1393 ret, GetLastError(), lstrlenW(lower_case) + 1);
1394 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1396 /* test buffer overflow */
1397 SetLastError(0xdeadbeef);
1398 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1399 lower_case, -1, buf, 4);
1400 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1401 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1403 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1404 lstrcpyW(buf, lower_case);
1405 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1406 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1407 ok(ret == lstrlenW(lower_case) + 1,
1408 "ret %d, error %d, expected value %d\n",
1409 ret, GetLastError(), lstrlenW(lower_case) + 1);
1410 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1412 lstrcpyW(buf, upper_case);
1413 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1414 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1415 ok(ret == lstrlenW(upper_case) + 1,
1416 "ret %d, error %d, expected value %d\n",
1417 ret, GetLastError(), lstrlenW(lower_case) + 1);
1418 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1420 /* otherwise src == dst should fail */
1421 SetLastError(0xdeadbeef);
1422 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1423 buf, 10, buf, sizeof(buf));
1424 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1425 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1426 "unexpected error code %d\n", GetLastError());
1427 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1429 /* test whether '\0' is always appended */
1430 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1431 upper_case, -1, buf, sizeof(buf));
1432 ok(ret, "LCMapStringW must succeed\n");
1433 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1434 upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1435 ok(ret, "LCMapStringW must succeed\n");
1436 ok(ret == ret2, "lengths of sort keys must be equal\n");
1437 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1439 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1440 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1441 upper_case, -1, buf, sizeof(buf));
1442 ok(ret, "LCMapStringW must succeed\n");
1443 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1444 lower_case, -1, buf2, sizeof(buf2));
1445 ok(ret2, "LCMapStringW must succeed\n");
1446 ok(ret == ret2, "lengths of sort keys must be equal\n");
1447 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1449 /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1450 results from plain LCMAP_SORTKEY on Vista */
1452 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1453 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1454 lower_case, -1, buf, sizeof(buf));
1455 ok(ret, "LCMapStringW must succeed\n");
1456 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1457 symbols_stripped, -1, buf2, sizeof(buf2));
1458 ok(ret2, "LCMapStringW must succeed\n");
1459 ok(ret == ret2, "lengths of sort keys must be equal\n");
1460 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1462 /* test NORM_IGNORENONSPACE */
1463 lstrcpyW(buf, fooW);
1464 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1465 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1466 ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1467 lstrlenW(lower_case) + 1, ret);
1468 ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1470 /* test NORM_IGNORESYMBOLS */
1471 lstrcpyW(buf, fooW);
1472 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1473 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1474 ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1475 lstrlenW(symbols_stripped) + 1, ret);
1476 ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1478 /* test srclen = 0 */
1479 SetLastError(0xdeadbeef);
1480 ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf)/sizeof(WCHAR));
1481 ok(!ret, "LCMapStringW should fail with srclen = 0\n");
1482 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1483 "unexpected error code %d\n", GetLastError());
1486 /* this requires collation table patch to make it MS compatible */
1487 static const char * const strings_sorted[] =
1519 static const char * const strings[] =
1551 static int compare_string1(const void *e1, const void *e2)
1553 const char *s1 = *(const char *const *)e1;
1554 const char *s2 = *(const char *const *)e2;
1556 return lstrcmpA(s1, s2);
1559 static int compare_string2(const void *e1, const void *e2)
1561 const char *s1 = *(const char *const *)e1;
1562 const char *s2 = *(const char *const *)e2;
1564 return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1567 static int compare_string3(const void *e1, const void *e2)
1569 const char *s1 = *(const char *const *)e1;
1570 const char *s2 = *(const char *const *)e2;
1571 char key1[256], key2[256];
1573 LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
1574 LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
1575 return strcmp(key1, key2);
1578 static void test_sorting(void)
1581 char **str_buf = (char **)buf;
1584 assert(sizeof(buf) >= sizeof(strings));
1586 /* 1. sort using lstrcmpA */
1587 memcpy(buf, strings, sizeof(strings));
1588 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
1589 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1591 ok(!strcmp(strings_sorted[i], str_buf[i]),
1592 "qsort using lstrcmpA failed for element %d\n", i);
1594 /* 2. sort using CompareStringA */
1595 memcpy(buf, strings, sizeof(strings));
1596 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
1597 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1599 ok(!strcmp(strings_sorted[i], str_buf[i]),
1600 "qsort using CompareStringA failed for element %d\n", i);
1602 /* 3. sort using sort keys */
1603 memcpy(buf, strings, sizeof(strings));
1604 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
1605 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1607 ok(!strcmp(strings_sorted[i], str_buf[i]),
1608 "qsort using sort keys failed for element %d\n", i);
1612 static void test_FoldStringA(void)
1616 char src[256], dst[256];
1617 static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0' };
1618 static const char digits_dst[] = { '1','2','3','\0' };
1619 static const char composite_src[] =
1621 0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
1622 0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
1623 0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
1624 0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
1625 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
1626 0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
1627 0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
1628 0xfb,0xfc,0xfd,0xff,'\0'
1630 static const char composite_dst[] =
1632 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1633 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1634 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1635 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1636 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1637 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1638 0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
1639 0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
1640 0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
1641 0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
1642 0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
1643 0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
1644 0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
1645 0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
1646 0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1648 static const char composite_dst_alt[] =
1650 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1651 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1652 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1653 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1654 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1655 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1656 0x4f,0x7e,0x4f,0xa8,0xd8,0x55,0x60,0x55,
1657 0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,0x61,
1658 0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,0x61,
1659 0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,0x65,
1660 0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,0x69,
1661 0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,0x6f,
1662 0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,0x6f,
1663 0xa8,0xf8,0x75,0x60,0x75,0xb4,0x75,0x5e,
1664 0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1666 static const char ligatures_src[] =
1668 0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1670 static const char ligatures_dst[] =
1672 'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1674 static const struct special
1678 } foldczone_special[] =
1681 { 0x85, { 0x2e, 0x2e, 0x2e, 0x00 } },
1682 { 0x98, { 0x20, 0x7e, 0x00 } },
1683 { 0x99, { 0x54, 0x4d, 0x00 } },
1684 { 0xa0, { 0x20, 0x00 } },
1685 { 0xa8, { 0x20, 0xa8, 0x00 } },
1686 { 0xaa, { 0x61, 0x00 } },
1687 { 0xaf, { 0x20, 0xaf, 0x00 } },
1688 { 0xb2, { 0x32, 0x00 } },
1689 { 0xb3, { 0x33, 0x00 } },
1690 { 0xb4, { 0x20, 0xb4, 0x00 } },
1691 { 0xb8, { 0x20, 0xb8, 0x00 } },
1692 { 0xb9, { 0x31, 0x00 } },
1693 { 0xba, { 0x6f, 0x00 } },
1694 { 0xbc, { 0x31, 0x2f, 0x34, 0x00 } },
1695 { 0xbd, { 0x31, 0x2f, 0x32, 0x00 } },
1696 { 0xbe, { 0x33, 0x2f, 0x34, 0x00 } },
1701 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1703 /* these tests are locale specific */
1704 if (GetACP() != 1252)
1706 trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1710 /* MAP_FOLDDIGITS */
1712 ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
1713 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1715 win_skip("FoldStringA is not implemented\n");
1718 ok(ret == 4, "Expected ret == 4, got %d, error %d\n", ret, GetLastError());
1719 ok(strcmp(dst, digits_dst) == 0,
1720 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
1721 for (i = 1; i < 256; i++)
1723 if (!strchr(digits_src, i))
1728 ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
1729 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1730 ok(dst[0] == src[0],
1731 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
1735 /* MAP_EXPAND_LIGATURES */
1737 ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1738 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1739 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1740 ok(ret == sizeof(ligatures_dst), "Got %d, error %d\n", ret, GetLastError());
1741 ok(strcmp(dst, ligatures_dst) == 0,
1742 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
1743 for (i = 1; i < 256; i++)
1745 if (!strchr(ligatures_src, i))
1750 ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1754 ok((i == 0xDC && lstrcmpA(dst, "UE") == 0) ||
1755 (i == 0xFC && lstrcmpA(dst, "ue") == 0),
1756 "Got %s for %d\n", dst, i);
1760 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1761 ok(dst[0] == src[0],
1762 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
1770 ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
1771 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1772 ok(ret == 121 || ret == 119, "Expected 121 or 119, got %d\n", ret);
1773 ok(strcmp(dst, composite_dst) == 0 || strcmp(dst, composite_dst_alt) == 0,
1774 "MAP_COMPOSITE: Mismatch, got '%s'\n", dst);
1776 for (i = 1; i < 256; i++)
1778 if (!strchr(composite_src, i))
1783 ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
1784 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1785 ok(dst[0] == src[0],
1786 "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
1787 (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
1792 for (i = 1; i < 256; i++)
1797 ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
1799 for (j = 0; foldczone_special[j].src != 0 && ! is_special; j++)
1801 if (foldczone_special[j].src == src[0])
1803 ok(ret == 2 || ret == lstrlenA(foldczone_special[j].dst) + 1,
1804 "Expected ret == 2 or %d, got %d, error %d\n",
1805 lstrlenA(foldczone_special[j].dst) + 1, ret, GetLastError());
1806 ok(src[0] == dst[0] || lstrcmpA(foldczone_special[j].dst, dst) == 0,
1807 "MAP_FOLDCZONE: string mismatch for 0x%02x\n",
1808 (unsigned char)src[0]);
1814 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1815 ok(src[0] == dst[0],
1816 "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
1817 (unsigned char)src[0], (unsigned char)dst[0]);
1821 /* MAP_PRECOMPOSED */
1822 for (i = 1; i < 256; i++)
1827 ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
1828 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1829 ok(src[0] == dst[0],
1830 "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
1831 (unsigned char)src[0], (unsigned char)dst[0]);
1835 static void test_FoldStringW(void)
1839 WCHAR src[256], dst[256], ch, prev_ch = 1;
1840 static const DWORD badFlags[] =
1843 MAP_PRECOMPOSED|MAP_COMPOSITE,
1844 MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
1845 MAP_COMPOSITE|MAP_EXPAND_LIGATURES
1847 /* Ranges of digits 0-9 : Must be sorted! */
1848 static const WCHAR digitRanges[] =
1850 0x0030, /* '0'-'9' */
1851 0x0660, /* Eastern Arabic */
1852 0x06F0, /* Arabic - Hindu */
1853 0x0966, /* Devengari */
1854 0x09E6, /* Bengalii */
1855 0x0A66, /* Gurmukhi */
1856 0x0AE6, /* Gujarati */
1858 0x0BE6, /* Tamil - No 0 */
1859 0x0C66, /* Telugu */
1860 0x0CE6, /* Kannada */
1861 0x0D66, /* Maylayalam */
1864 0x0F29, /* Tibet - 0 is out of sequence */
1865 0x2070, /* Superscript - 1, 2, 3 are out of sequence */
1866 0x2080, /* Subscript */
1867 0x245F, /* Circled - 0 is out of sequence */
1868 0x2473, /* Bracketed */
1869 0x2487, /* Full stop */
1870 0x2775, /* Inverted circled - No 0 */
1871 0x277F, /* Patterned circled - No 0 */
1872 0x2789, /* Inverted Patterned circled - No 0 */
1873 0x3020, /* Hangzhou */
1874 0xff10, /* Pliene chasse (?) */
1875 0xffff /* Terminator */
1877 /* Digits which are represented, but out of sequence */
1878 static const WCHAR outOfSequenceDigits[] =
1880 0xB9, /* Superscript 1 */
1881 0xB2, /* Superscript 2 */
1882 0xB3, /* Superscript 3 */
1883 0x0F33, /* Tibetan half zero */
1884 0x24EA, /* Circled 0 */
1885 0x3007, /* Ideographic number zero */
1886 '\0' /* Terminator */
1888 /* Digits in digitRanges for which no representation is available */
1889 static const WCHAR noDigitAvailable[] =
1891 0x0BE6, /* No Tamil 0 */
1892 0x0F29, /* No Tibetan half zero (out of sequence) */
1893 0x2473, /* No Bracketed 0 */
1894 0x2487, /* No 0 Full stop */
1895 0x2775, /* No inverted circled 0 */
1896 0x277F, /* No patterned circled */
1897 0x2789, /* No inverted Patterned circled */
1898 0x3020, /* No Hangzhou 0 */
1899 '\0' /* Terminator */
1901 static const WCHAR foldczone_src[] =
1903 'W', 'i', 'n', 'e', 0x0348, 0x0551, 0x1323, 0x280d,
1904 0xff37, 0xff49, 0xff4e, 0xff45, '\0'
1906 static const WCHAR foldczone_dst[] =
1908 'W','i','n','e',0x0348,0x0551,0x1323,0x280d,'W','i','n','e','\0'
1910 static const WCHAR ligatures_src[] =
1912 'W', 'i', 'n', 'e', 0x03a6, 0x03b9, 0x03bd, 0x03b5,
1913 0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
1914 0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
1915 0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
1916 0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
1917 0xfb04, 0xfb05, 0xfb06, '\0'
1919 static const WCHAR ligatures_dst[] =
1921 'W','i','n','e',0x03a6,0x03b9,0x03bd,0x03b5,
1922 'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
1923 'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
1924 'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
1925 0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
1926 'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
1931 win_skip("FoldStringW is not available\n");
1932 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1935 /* Invalid flag combinations */
1936 for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
1938 src[0] = dst[0] = '\0';
1940 ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
1941 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1943 win_skip("FoldStringW is not implemented\n");
1946 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
1947 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1950 /* src & dst cannot be the same */
1952 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
1953 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1954 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1956 /* src can't be NULL */
1958 ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
1959 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1960 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1962 /* srclen can't be 0 */
1964 ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
1965 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1966 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1968 /* dstlen can't be < 0 */
1970 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
1971 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1972 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1974 /* Ret includes terminating NUL which is appended if srclen = -1 */
1979 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
1980 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1981 ok(dst[0] == 'A' && dst[1] == '\0',
1982 "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%d\n",
1983 'A', '\0', ret, dst[0], dst[1], GetLastError());
1985 /* If size is given, result is not NUL terminated */
1991 ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
1992 ok(ret == 1, "Expected ret == 1, got %d, error %d\n", ret, GetLastError());
1993 ok(dst[0] == 'A' && dst[1] == 'X',
1994 "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%d\n",
1995 'A','X', ret, dst[0], dst[1], GetLastError());
1997 /* MAP_FOLDDIGITS */
1998 for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
2000 /* Check everything before this range */
2001 for (ch = prev_ch; ch < digitRanges[j]; ch++)
2005 src[1] = dst[0] = '\0';
2006 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2007 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2009 ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
2010 /* Wine (correctly) maps all Unicode 4.0+ digits */
2011 isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF ||
2012 (ch >= 0x1369 && ch <= 0x1371),
2013 "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
2016 if (digitRanges[j] == 0xffff)
2017 break; /* Finished the whole code point space */
2019 for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
2023 /* Map out of sequence characters */
2024 if (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
2025 else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
2026 else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
2027 else if (ch == 0x245F) c = 0x24EA; /* Circled 0 */
2031 src[1] = dst[0] = '\0';
2032 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2033 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2035 ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
2036 broken( dst[0] == ch ) || /* old Windows versions don't have all mappings */
2037 (digitRanges[j] == 0x3020 && dst[0] == ch) || /* Hangzhou not present in all Windows versions */
2038 (digitRanges[j] == 0x0F29 && dst[0] == ch) || /* Tibetan not present in all Windows versions */
2039 strchrW(noDigitAvailable, c),
2040 "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
2041 ch, '0' + digitRanges[j] - ch, dst[0]);
2048 ret = pFoldStringW(MAP_FOLDCZONE, foldczone_src, -1, dst, 256);
2049 ok(ret == sizeof(foldczone_dst)/sizeof(foldczone_dst[0]),
2050 "Got %d, error %d\n", ret, GetLastError());
2051 ok(!memcmp(dst, foldczone_dst, sizeof(foldczone_dst)),
2052 "MAP_FOLDCZONE: Expanded incorrectly\n");
2054 /* MAP_EXPAND_LIGATURES */
2056 ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
2057 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
2058 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
2059 ok(ret == sizeof(ligatures_dst)/sizeof(ligatures_dst[0]),
2060 "Got %d, error %d\n", ret, GetLastError());
2061 ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
2062 "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
2065 /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
2070 #define LCID_OK(l) \
2071 ok(lcid == l, "Expected lcid = %08x, got %08x\n", l, lcid)
2072 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
2073 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
2074 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
2075 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
2077 static void test_ConvertDefaultLocale(void)
2081 /* Doesn't change lcid, even if non default sublang/sort used */
2082 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_US, SORT_DEFAULT);
2083 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_UK, SORT_DEFAULT);
2084 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT);
2085 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE);
2087 /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
2088 LCID_RES(MKLCID(LANG_ENGLISH, SUBLANG_NEUTRAL, SORT_DEFAULT),
2089 MKLCID(LANG_ENGLISH, SUBLANG_DEFAULT, SORT_DEFAULT));
2090 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
2091 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
2093 /* Invariant language is not treated specially */
2094 TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
2096 /* User/system default languages alone are not mapped */
2097 TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
2098 TEST_LCIDLANG(LANG_USER_DEFAULT, SORT_JAPANESE_UNICODE);
2101 LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
2102 LCID_RES(LOCALE_USER_DEFAULT, GetUserDefaultLCID());
2103 LCID_RES(LOCALE_NEUTRAL, GetUserDefaultLCID());
2106 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
2107 DWORD dwFlags, LONG_PTR lParam)
2109 trace("%08x, %s, %s, %08x, %08lx\n",
2110 lgrpid, lpszNum, lpszName, dwFlags, lParam);
2112 ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
2113 "Enumerated grp %d not valid (flags %d)\n", lgrpid, dwFlags);
2115 /* If lParam is one, we are calling with flags defaulted from 0 */
2116 ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
2117 "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %d\n", dwFlags);
2122 static void test_EnumSystemLanguageGroupsA(void)
2126 if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
2128 win_skip("EnumSystemLanguageGroupsA and/or IsValidLanguageGroup are not available\n");
2132 /* No enumeration proc */
2134 ret = pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
2135 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2137 win_skip("EnumSystemLanguageGroupsA is not implemented\n");
2140 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2141 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2145 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
2146 ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2148 /* No flags - defaults to LGRPID_INSTALLED */
2149 SetLastError(0xdeadbeef);
2150 pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
2151 ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
2153 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
2154 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
2158 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
2161 trace("%08x, %08x, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
2163 /* invalid locale enumerated on some platforms */
2167 ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
2168 "Enumerated grp %d not valid\n", lgrpid);
2169 ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
2170 "Enumerated grp locale %d not valid\n", lcid);
2174 static void test_EnumLanguageGroupLocalesA(void)
2178 if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
2180 win_skip("EnumLanguageGroupLocalesA and/or IsValidLanguageGroup are not available\n");
2184 /* No enumeration proc */
2186 ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
2187 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2189 win_skip("EnumLanguageGroupLocalesA is not implemented\n");
2192 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2193 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2195 /* lgrpid too small */
2197 ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
2198 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2199 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2201 /* lgrpid too big */
2203 ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
2204 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2205 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2207 /* dwFlags is reserved */
2209 ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
2210 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2211 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2213 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2216 static void test_SetLocaleInfoA(void)
2219 LCID lcid = GetUserDefaultLCID();
2223 bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2224 ok( !bRet && GetLastError() == ERROR_INVALID_PARAMETER,
2225 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2229 bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
2230 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2231 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2235 bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
2236 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2237 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2240 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2242 trace("%s %08lx\n", value, lParam);
2246 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2248 ok(!enumCount, "callback called again unexpected\n");
2253 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2255 ok(0,"callback called unexpected\n");
2259 static void test_EnumUILanguageA(void)
2262 if (!pEnumUILanguagesA) {
2263 win_skip("EnumUILanguagesA is not available on Win9x or NT4\n");
2267 SetLastError(ERROR_SUCCESS);
2268 ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2269 if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2271 win_skip("EnumUILanguagesA is not implemented\n");
2274 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2277 SetLastError(ERROR_SUCCESS);
2278 ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2279 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2281 SetLastError(ERROR_SUCCESS);
2282 ret = pEnumUILanguagesA(NULL, 0, 0);
2283 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2284 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2285 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2287 SetLastError(ERROR_SUCCESS);
2288 ret = pEnumUILanguagesA(luilocale_proc3A, 0x5a5a5a5a, 0);
2289 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2290 ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2292 SetLastError(ERROR_SUCCESS);
2293 ret = pEnumUILanguagesA(NULL, 0x5a5a5a5a, 0);
2294 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2295 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2296 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2299 static char date_fmt_buf[1024];
2301 static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
2303 lstrcatA(date_fmt_buf, fmt);
2304 lstrcatA(date_fmt_buf, "\n");
2308 static void test_EnumDateFormatsA(void)
2312 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2314 trace("EnumDateFormatsA 0\n");
2315 date_fmt_buf[0] = 0;
2316 SetLastError(0xdeadbeef);
2317 ret = EnumDateFormatsA(enum_datetime_procA, lcid, 0);
2318 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2320 win_skip("0 for dwFlags is not supported\n");
2324 ok(ret, "EnumDateFormatsA(0) error %d\n", GetLastError());
2325 trace("%s\n", date_fmt_buf);
2326 /* test the 1st enumerated format */
2327 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2328 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2329 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2330 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2333 trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n");
2334 date_fmt_buf[0] = 0;
2335 SetLastError(0xdeadbeef);
2336 ret = EnumDateFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2337 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2339 win_skip("LOCALE_USE_CP_ACP is not supported\n");
2343 ok(ret, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2344 trace("%s\n", date_fmt_buf);
2345 /* test the 1st enumerated format */
2346 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2347 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2348 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2349 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2352 trace("EnumDateFormatsA DATE_SHORTDATE\n");
2353 date_fmt_buf[0] = 0;
2354 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_SHORTDATE);
2355 ok(ret, "EnumDateFormatsA(DATE_SHORTDATE) error %d\n", GetLastError());
2356 trace("%s\n", date_fmt_buf);
2357 /* test the 1st enumerated format */
2358 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2359 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2360 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2361 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2363 trace("EnumDateFormatsA DATE_LONGDATE\n");
2364 date_fmt_buf[0] = 0;
2365 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_LONGDATE);
2366 ok(ret, "EnumDateFormatsA(DATE_LONGDATE) error %d\n", GetLastError());
2367 trace("%s\n", date_fmt_buf);
2368 /* test the 1st enumerated format */
2369 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2370 ret = GetLocaleInfoA(lcid, LOCALE_SLONGDATE, buf, sizeof(buf));
2371 ok(ret, "GetLocaleInfoA(LOCALE_SLONGDATE) error %d\n", GetLastError());
2372 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2374 trace("EnumDateFormatsA DATE_YEARMONTH\n");
2375 date_fmt_buf[0] = 0;
2376 SetLastError(0xdeadbeef);
2377 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_YEARMONTH);
2378 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2380 skip("DATE_YEARMONTH is only present on W2K and later\n");
2383 ok(ret, "EnumDateFormatsA(DATE_YEARMONTH) error %d\n", GetLastError());
2384 trace("%s\n", date_fmt_buf);
2385 /* test the 1st enumerated format */
2386 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2387 ret = GetLocaleInfoA(lcid, LOCALE_SYEARMONTH, buf, sizeof(buf));
2388 ok(ret, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %d\n", GetLastError());
2389 ok(!lstrcmpA(date_fmt_buf, buf) || broken(!buf[0]) /* win9x */,
2390 "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2393 static void test_EnumTimeFormatsA(void)
2397 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2399 trace("EnumTimeFormatsA 0\n");
2400 date_fmt_buf[0] = 0;
2401 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, 0);
2402 ok(ret, "EnumTimeFormatsA(0) error %d\n", GetLastError());
2403 trace("%s\n", date_fmt_buf);
2404 /* test the 1st enumerated format */
2405 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2406 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2407 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2408 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2410 trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n");
2411 date_fmt_buf[0] = 0;
2412 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2413 ok(ret, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2414 trace("%s\n", date_fmt_buf);
2415 /* test the 1st enumerated format */
2416 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2417 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2418 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2419 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2422 static void test_GetCPInfo(void)
2427 SetLastError(0xdeadbeef);
2428 ret = GetCPInfo(CP_SYMBOL, &cpinfo);
2429 ok(!ret, "GetCPInfo(CP_SYMBOL) should fail\n");
2430 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2431 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2433 SetLastError(0xdeadbeef);
2434 ret = GetCPInfo(CP_UTF7, &cpinfo);
2435 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2437 skip("Codepage CP_UTF7 is not installed/available\n");
2441 ok(ret, "GetCPInfo(CP_UTF7) error %u\n", GetLastError());
2442 ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2443 ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2444 ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2445 ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2446 ok(cpinfo.MaxCharSize == 5, "expected 5, got 0x%x\n", cpinfo.MaxCharSize);
2449 SetLastError(0xdeadbeef);
2450 ret = GetCPInfo(CP_UTF8, &cpinfo);
2451 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2453 skip("Codepage CP_UTF8 is not installed/available\n");
2457 ok(ret, "GetCPInfo(CP_UTF8) error %u\n", GetLastError());
2458 ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2459 ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2460 ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2461 ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2462 ok(cpinfo.MaxCharSize == 4 || broken(cpinfo.MaxCharSize == 3) /* win9x */,
2463 "expected 4, got %u\n", cpinfo.MaxCharSize);
2469 InitFunctionPointers();
2471 test_EnumTimeFormatsA();
2472 test_EnumDateFormatsA();
2473 test_GetLocaleInfoA();
2474 test_GetTimeFormatA();
2475 test_GetDateFormatA();
2476 test_GetDateFormatW();
2477 test_GetCurrencyFormatA(); /* Also tests the W version */
2478 test_GetNumberFormatA(); /* Also tests the W version */
2479 test_CompareStringA();
2480 test_LCMapStringA();
2481 test_LCMapStringW();
2484 test_ConvertDefaultLocale();
2485 test_EnumSystemLanguageGroupsA();
2486 test_EnumLanguageGroupLocalesA();
2487 test_SetLocaleInfoA();
2488 test_EnumUILanguageA();
2490 /* this requires collation table patch to make it MS compatible */
2491 if (0) test_sorting();