More locale tests.
[wine/hacks.git] / dlls / kernel / tests / locale.c
blobe71219a16b3265532cc9fc78e3f46a1c6fc76b5f
1 /*
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * NOTES
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.
27 #include <stdarg.h>
29 #include "wine/test.h"
30 #include "windef.h"
31 #include "wine/unicode.h"
32 #include "winbase.h"
33 #include "winerror.h"
34 #include "winnls.h"
36 /* Some functions are only in later versions of kernel32.dll */
37 static HMODULE hKernel32;
39 typedef BOOL (WINAPI *EnumSystemLanguageGroupsAFn)(LANGUAGEGROUP_ENUMPROC,
40 DWORD, LONG_PTR);
41 static EnumSystemLanguageGroupsAFn pEnumSystemLanguageGroupsA;
42 typedef BOOL (WINAPI *EnumLanguageGroupLocalesAFn)(LANGGROUPLOCALE_ENUMPROC,
43 LGRPID, DWORD, LONG_PTR);
44 static EnumLanguageGroupLocalesAFn pEnumLanguageGroupLocalesA;
47 static void InitFunctionPointers(void)
49 hKernel32 = GetModuleHandleA("kernel32");
51 if (hKernel32)
53 pEnumSystemLanguageGroupsA = (void*)GetProcAddress(hKernel32, "EnumSystemLanguageGroupsA");
54 pEnumLanguageGroupLocalesA = (void*)GetProcAddress(hKernel32, "EnumLanguageGroupLocalesA");
58 #define eq(received, expected, label, type) \
59 ok((received) == (expected), "%s: got " type " instead of " type "\n", \
60 (label), (received), (expected))
62 #define BUFFER_SIZE 128
63 char GlobalBuffer[BUFFER_SIZE]; /* Buffer used by callback function */
64 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
66 #define EXPECT_LEN(len) ok(ret == len, "Expected Len %d, got %d\n", len, ret)
67 #define EXPECT_INVALID ok(GetLastError() == ERROR_INVALID_PARAMETER, \
68 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError())
69 #define EXPECT_BUFFER ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, \
70 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError())
71 #define EXPECT_FLAGS ok(GetLastError() == ERROR_INVALID_FLAGS, \
72 "Expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError())
73 #define EXPECT_INVALIDFLAGS ok(GetLastError() == ERROR_INVALID_FLAGS || \
74 GetLastError() == ERROR_INVALID_PARAMETER, \
75 "Expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError())
76 #define EXPECT_VALID ok(GetLastError() == 0, \
77 "Expected GetLastError() == 0, got %ld\n", GetLastError())
79 #define STRINGSA(x,y) strcpy(input, x); strcpy(Expected, y); SetLastError(0); buffer[0] = '\0'
80 #define EXPECT_LENA EXPECT_LEN(strlen(Expected)+1)
81 #define EXPECT_EQA ok(strncmp(buffer, Expected, strlen(Expected)) == 0, \
82 "Expected '%s', got '%s'", Expected, buffer)
84 #define STRINGSW(x,y) MultiByteToWideChar(CP_ACP,0,x,-1,input,COUNTOF(input)); \
85 MultiByteToWideChar(CP_ACP,0,y,-1,Expected,COUNTOF(Expected)); \
86 SetLastError(0); buffer[0] = '\0'
87 #define EXPECT_LENW EXPECT_LEN(strlenW(Expected)+1)
88 #define EXPECT_EQW ok(strncmpW(buffer, Expected, strlenW(Expected)) == 0, "Bad conversion\n")
90 #define NUO LOCALE_NOUSEROVERRIDE
92 static void test_GetLocaleInfoA()
94 int ret;
95 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
96 char buffer[BUFFER_SIZE];
98 ok(lcid == 0x409, "wrong LCID calculated - %ld\n", lcid);
100 /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
101 * partially fill the buffer even if it is too short. See bug 637.
103 SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
104 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 0);
105 ok(ret == 7 && !buffer[0], "Expected len=7, got %d\n", ret);
107 SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
108 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 3);
109 EXPECT_BUFFER; EXPECT_LEN(0);
110 ok(!strcmp(buffer, "Mon"), "Expected 'Mon', got '%s'\n", buffer);
112 SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
113 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 10);
114 EXPECT_VALID; EXPECT_LEN(7);
115 ok(!strcmp(buffer, "Monday"), "Expected 'Monday', got '%s'\n", buffer);
118 static void test_GetTimeFormatA()
120 int ret;
121 SYSTEMTIME curtime;
122 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
123 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
125 memset(&curtime, 2, sizeof(SYSTEMTIME));
126 STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
127 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
128 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
130 curtime.wHour = 8;
131 curtime.wMinute = 56;
132 curtime.wSecond = 13;
133 curtime.wMilliseconds = 22;
134 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
135 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
136 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
138 STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficent buffer */
139 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, 2);
140 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
142 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
143 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, NULL, 0);
144 EXPECT_VALID; EXPECT_LENA;
146 STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
147 ret = GetTimeFormatA(lcid, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
148 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
150 STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
151 ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
152 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
154 STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
155 ret = GetTimeFormatA(lcid, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
156 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
158 STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
159 strcpy(Expected, "8:56 AM");
160 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
161 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
163 STRINGSA("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
164 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
165 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
167 STRINGSA("s1s2s3", ""); /* Duplicate tokens */
168 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
169 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
171 STRINGSA("t/tt", "A/AM"); /* AM time marker */
172 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
173 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
175 curtime.wHour = 13;
176 STRINGSA("t/tt", "P/PM"); /* PM time marker */
177 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
178 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
180 STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
181 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
182 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
184 STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
185 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
186 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
188 STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
189 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
190 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
192 curtime.wHour = 14; /* change this to 14 or 2pm */
193 curtime.wMinute = 5;
194 curtime.wSecond = 3;
195 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 */
196 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
197 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
199 curtime.wHour = 0;
200 STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
201 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
202 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
204 STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
205 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
206 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
208 /* try to convert formatting strings with more than two letters
209 * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
210 * NOTE: We expect any letter for which there is an upper case value
211 * we should see a replacement. For letters that DO NOT have
212 * upper case values we should see NO REPLACEMENT.
214 curtime.wHour = 8;
215 curtime.wMinute = 56;
216 curtime.wSecond = 13;
217 curtime.wMilliseconds = 22;
218 STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
219 "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
220 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
221 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
223 STRINGSA("h", "text"); /* Dont write to buffer if len is 0*/
224 strcpy(buffer, "text");
225 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, 0);
226 EXPECT_VALID; EXPECT_LEN(2); EXPECT_EQA;
228 STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
229 "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
230 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
231 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
233 STRINGSA("'''", "'"); /* invalid quoted string */
234 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
235 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
237 /* test that msdn suggested single quotation usage works as expected */
238 STRINGSA("''''", "'"); /* single quote mark */
239 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
240 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
242 STRINGSA("''HHHHHH", "08"); /* Normal use */
243 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
244 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
246 /* and test for normal use of the single quotation mark */
247 STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
248 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
249 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
251 STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
252 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
253 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
255 STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
256 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
257 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
259 curtime.wHour = 25;
260 STRINGSA("'123'tt", ""); /* Invalid time */
261 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
262 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
264 curtime.wHour = 12;
265 curtime.wMonth = 60; /* Invalid */
266 STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
267 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
268 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
271 static void test_GetDateFormatA()
273 int ret;
274 SYSTEMTIME curtime;
275 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
276 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
278 memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
279 STRINGSA("ddd',' MMM dd yy","");
280 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
281 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
283 curtime.wYear = 2002;
284 curtime.wMonth = 5;
285 curtime.wDay = 4;
286 curtime.wDayOfWeek = 3;
287 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
288 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
289 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
291 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
292 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
293 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
295 curtime.wHour = 36; /* Invalid */
296 STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
297 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
298 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
300 STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
301 ret = GetDateFormatA(lcid, 0, &curtime, input, NULL, 0);
302 EXPECT_VALID; EXPECT_LEN(16); EXPECT_EQA;
304 STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
305 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, 2);
306 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
308 STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
309 ret = GetDateFormat(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
310 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
312 STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
313 ret = GetDateFormat(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
314 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
316 /* test for expected DATE_YEARMONTH behavior with null format */
317 /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
318 STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
319 ret = GetDateFormat(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
320 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
322 /* Test that using invalid DATE_* flags results in the correct error */
323 /* and return values */
324 STRINGSA("m/d/y", ""); /* Invalid flags */
325 ret = GetDateFormat(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
326 &curtime, input, buffer, COUNTOF(buffer));
327 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
330 static void test_GetDateFormatW()
332 int ret;
333 SYSTEMTIME curtime;
334 WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
335 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
337 STRINGSW("",""); /* If flags is not zero then format must be NULL */
338 ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL,
339 input, buffer, COUNTOF(buffer));
340 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
341 return;
342 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQW;
344 STRINGSW("",""); /* NULL buffer, len > 0 */
345 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
346 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQW;
348 STRINGSW("",""); /* NULL buffer, len == 0 */
349 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
350 EXPECT_VALID; EXPECT_LENW; EXPECT_EQW;
352 curtime.wYear = 2002;
353 curtime.wMonth = 10;
354 curtime.wDay = 23;
355 curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
356 curtime.wHour = 65432; /* Invalid */
357 curtime.wMinute = 34512; /* Invalid */
358 curtime.wSecond = 65535; /* Invalid */
359 curtime.wMilliseconds = 12345;
360 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
361 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
362 EXPECT_VALID; EXPECT_LENW; EXPECT_EQW;
366 #define CY_POS_LEFT 0
367 #define CY_POS_RIGHT 1
368 #define CY_POS_LEFT_SPACE 2
369 #define CY_POS_RIGHT_SPACE 3
371 static void test_GetCurrencyFormatA()
373 static char szDot[] = { '.', '\0' };
374 static char szComma[] = { ',', '\0' };
375 static char szDollar[] = { '$', '\0' };
376 int ret;
377 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
378 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
379 CURRENCYFMTA format;
381 memset(&format, 0, sizeof(format));
383 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
384 ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
385 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
387 STRINGSA("23,53",""); /* Invalid character --> Error */
388 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
389 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
391 STRINGSA("--",""); /* Double '-' --> Error */
392 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
393 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
395 STRINGSA("0-",""); /* Trailing '-' --> Error */
396 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
397 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
399 STRINGSA("0..",""); /* Double '.' --> Error */
400 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
401 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
403 STRINGSA(" 0.1",""); /* Leading space --> Error */
404 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
405 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
407 STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
408 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, 2);
409 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
411 STRINGSA("2353",""); /* Format and flags given --> Error */
412 ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
413 EXPECT_INVALIDFLAGS; EXPECT_LEN(0); EXPECT_EQA;
415 STRINGSA("2353",""); /* Invalid format --> Error */
416 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
417 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
419 STRINGSA("2353","$2,353.00"); /* Valid number */
420 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
421 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
423 STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
424 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
425 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
427 STRINGSA("2353.1","$2,353.10"); /* Valid real number */
428 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
429 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
431 STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
432 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
433 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
435 STRINGSA("2353.119","$2,353.12"); /* Too many DP --> Rounded */
436 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
437 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
439 format.NumDigits = 0; /* No decimal seperator */
440 format.LeadingZero = 0;
441 format.Grouping = 0; /* No grouping char */
442 format.NegativeOrder = 0;
443 format.PositiveOrder = CY_POS_LEFT;
444 format.lpDecimalSep = szDot;
445 format.lpThousandSep = szComma;
446 format.lpCurrencySymbol = szDollar;
448 STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
449 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
450 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
452 format.NumDigits = 1; /* 1 DP --> Expect decimal seperator */
453 STRINGSA("2353","$2353.0");
454 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
455 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
457 format.Grouping = 2; /* Group by 100's */
458 STRINGSA("2353","$23,53.0");
459 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
460 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
462 format.LeadingZero = 1; /* Always provide leading zero */
463 STRINGSA(".5","$0.5");
464 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
465 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
467 format.PositiveOrder = CY_POS_RIGHT;
468 STRINGSA("1","1.0$");
469 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
470 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
472 format.PositiveOrder = CY_POS_LEFT_SPACE;
473 STRINGSA("1","$ 1.0");
474 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
475 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
477 format.PositiveOrder = CY_POS_RIGHT_SPACE;
478 STRINGSA("1","1.0 $");
479 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
480 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
482 format.NegativeOrder = 0;
483 STRINGSA("-1","($1.0)");
484 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
485 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
487 format.NegativeOrder = 1;
488 STRINGSA("-1","-$1.0");
489 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
490 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
492 format.NegativeOrder = 2;
493 STRINGSA("-1","$-1.0");
494 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
495 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
497 format.NegativeOrder = 3;
498 STRINGSA("-1","$1.0-");
499 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
500 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
502 format.NegativeOrder = 4;
503 STRINGSA("-1","(1.0$)");
504 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
505 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
507 format.NegativeOrder = 5;
508 STRINGSA("-1","-1.0$");
509 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
510 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
512 format.NegativeOrder = 6;
513 STRINGSA("-1","1.0-$");
514 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
515 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
517 format.NegativeOrder = 7;
518 STRINGSA("-1","1.0$-");
519 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
520 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
522 format.NegativeOrder = 8;
523 STRINGSA("-1","-1.0 $");
524 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
525 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
527 format.NegativeOrder = 9;
528 STRINGSA("-1","-$ 1.0");
529 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
530 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
532 format.NegativeOrder = 10;
533 STRINGSA("-1","1.0 $-");
534 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
535 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
537 format.NegativeOrder = 11;
538 STRINGSA("-1","$ 1.0-");
539 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
540 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
542 format.NegativeOrder = 12;
543 STRINGSA("-1","$ -1.0");
544 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
545 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
547 format.NegativeOrder = 13;
548 STRINGSA("-1","1.0- $");
549 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
550 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
552 format.NegativeOrder = 14;
553 STRINGSA("-1","($ 1.0)");
554 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
555 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
557 format.NegativeOrder = 15;
558 STRINGSA("-1","(1.0 $)");
559 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
560 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
563 #define NEG_PARENS 0 /* "(1.1)" */
564 #define NEG_LEFT 1 /* "-1.1" */
565 #define NEG_LEFT_SPACE 2 /* "- 1.1" */
566 #define NEG_RIGHT 3 /* "1.1-" */
567 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
569 static void test_GetNumberFormatA()
571 static char szDot[] = { '.', '\0' };
572 static char szComma[] = { ',', '\0' };
573 int ret;
574 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
575 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
576 NUMBERFMTA format;
578 memset(&format, 0, sizeof(format));
580 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
581 ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
582 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
584 STRINGSA("23,53",""); /* Invalid character --> Error */
585 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
586 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
588 STRINGSA("--",""); /* Double '-' --> Error */
589 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
590 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
592 STRINGSA("0-",""); /* Trailing '-' --> Error */
593 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
594 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
596 STRINGSA("0..",""); /* Double '.' --> Error */
597 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
598 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
600 STRINGSA(" 0.1",""); /* Leading space --> Error */
601 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
602 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
604 STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
605 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, 2);
606 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
608 STRINGSA("2353",""); /* Format and flags given --> Error */
609 ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
610 EXPECT_INVALIDFLAGS; EXPECT_LEN(0); EXPECT_EQA;
612 STRINGSA("2353",""); /* Invalid format --> Error */
613 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
614 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
616 STRINGSA("2353","2,353.00"); /* Valid number */
617 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
618 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
620 STRINGSA("-2353","-2,353.00"); /* Valid negative number */
621 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
622 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
624 STRINGSA("2353.1","2,353.10"); /* Valid real number */
625 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
626 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
628 STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
629 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
630 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
632 STRINGSA("2353.119","2,353.12"); /* Too many DP --> Rounded */
633 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
634 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
636 format.NumDigits = 0; /* No decimal seperator */
637 format.LeadingZero = 0;
638 format.Grouping = 0; /* No grouping char */
639 format.NegativeOrder = 0;
640 format.lpDecimalSep = szDot;
641 format.lpThousandSep = szComma;
643 STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
644 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
645 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
647 format.NumDigits = 1; /* 1 DP --> Expect decimal seperator */
648 STRINGSA("2353","2353.0");
649 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
650 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
652 format.Grouping = 2; /* Group by 100's */
653 STRINGSA("2353","23,53.0");
654 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
655 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
657 format.LeadingZero = 1; /* Always provide leading zero */
658 STRINGSA(".5","0.5");
659 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
660 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
662 format.NegativeOrder = NEG_PARENS;
663 STRINGSA("-1","(1.0)");
664 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
665 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
667 format.NegativeOrder = NEG_LEFT;
668 STRINGSA("-1","-1.0");
669 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
670 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
672 format.NegativeOrder = NEG_LEFT_SPACE;
673 STRINGSA("-1","- 1.0");
674 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
675 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
677 format.NegativeOrder = NEG_RIGHT;
678 STRINGSA("-1","1.0-");
679 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
680 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
682 format.NegativeOrder = NEG_RIGHT_SPACE;
683 STRINGSA("-1","1.0 -");
684 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
685 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
687 lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
689 if (IsValidLocale(lcid, 0))
691 STRINGSA("-12345","-12 345,00"); /* Try French formatting */
692 Expected[3] = 160; /* Non breaking space */
693 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
694 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
699 /* Callback function used by TestEnumTimeFormats */
700 static BOOL CALLBACK EnumTimeFormatsProc(char * lpTimeFormatString)
702 trace("%s\n", lpTimeFormatString);
703 strcpy(GlobalBuffer, lpTimeFormatString);
704 #if 0
705 return TRUE;
706 #endif
707 return FALSE;
710 void test_EnumTimeFormats()
712 int ret;
713 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
715 GlobalBuffer[0] = '\0';
716 ret = EnumTimeFormatsA(EnumTimeFormatsProc, lcid, 0);
717 ok (ret == 1 && !strcmp(GlobalBuffer,"h:mm:ss tt"), "Expected %d '%s'\n", ret, GlobalBuffer);
720 static void test_CompareStringA()
722 int ret;
723 LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
725 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
726 ok (ret== 1, "(Salut/Salute) Expected 1, got %d\n", ret);
728 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
729 ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
731 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
732 ok (ret== 3, "(Salut/hola) Expected 3, got %d\n", ret);
734 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
735 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
737 lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
739 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
740 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
742 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
743 ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
745 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "SaLuT", -1);
746 ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
749 void test_LCMapStringA(void)
751 int ret, ret2;
752 char buf[256], buf2[256];
753 static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
754 static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
755 static const char symbols_stripped[] = "justateststring1";
757 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
758 upper_case, -1, buf, sizeof(buf));
759 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
760 ok(GetLastError() == ERROR_INVALID_FLAGS,
761 "unexpected error code %ld\n", GetLastError());
763 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
764 upper_case, -1, buf, sizeof(buf));
765 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
766 ok(GetLastError() == ERROR_INVALID_FLAGS,
767 "unexpected error code %ld\n", GetLastError());
769 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
771 upper_case, -1, buf, sizeof(buf));
772 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
773 ok(GetLastError() == ERROR_INVALID_FLAGS,
774 "unexpected error code %ld\n", GetLastError());
776 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
777 upper_case, -1, buf, sizeof(buf));
778 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
779 ok(GetLastError() == ERROR_INVALID_FLAGS,
780 "unexpected error code %ld\n", GetLastError());
782 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
783 SetLastError(0xdeadbeef);
784 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
785 upper_case, -1, buf, sizeof(buf));
786 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError());
787 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
789 /* test LCMAP_LOWERCASE */
790 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
791 upper_case, -1, buf, sizeof(buf));
792 ok(ret == lstrlenA(upper_case) + 1,
793 "ret %d, error %ld, expected value %d\n",
794 ret, GetLastError(), lstrlenA(upper_case) + 1);
795 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
797 /* test LCMAP_UPPERCASE */
798 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
799 lower_case, -1, buf, sizeof(buf));
800 ok(ret == lstrlenA(lower_case) + 1,
801 "ret %d, error %ld, expected value %d\n",
802 ret, GetLastError(), lstrlenA(lower_case) + 1);
803 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
805 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
806 lstrcpyA(buf, lower_case);
807 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
808 buf, -1, buf, sizeof(buf));
809 if (!ret) /* Win9x */
810 trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
811 else
813 ok(ret == lstrlenA(lower_case) + 1,
814 "ret %d, error %ld, expected value %d\n",
815 ret, GetLastError(), lstrlenA(lower_case) + 1);
816 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
818 lstrcpyA(buf, upper_case);
819 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
820 buf, -1, buf, sizeof(buf));
821 if (!ret) /* Win9x */
822 trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
823 else
825 ok(ret == lstrlenA(upper_case) + 1,
826 "ret %d, error %ld, expected value %d\n",
827 ret, GetLastError(), lstrlenA(lower_case) + 1);
828 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
831 /* otherwise src == dst should fail */
832 SetLastError(0xdeadbeef);
833 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
834 buf, 10, buf, sizeof(buf));
835 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
836 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
837 "unexpected error code %ld\n", GetLastError());
838 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
840 /* test whether '\0' is always appended */
841 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
842 upper_case, -1, buf, sizeof(buf));
843 ok(ret, "LCMapStringA must succeed\n");
844 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
845 upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
846 ok(ret, "LCMapStringA must succeed\n");
847 ok(ret == ret2, "lengths of sort keys must be equal\n");
848 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
850 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
851 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
852 upper_case, -1, buf, sizeof(buf));
853 ok(ret, "LCMapStringA must succeed\n");
854 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
855 lower_case, -1, buf2, sizeof(buf2));
856 ok(ret2, "LCMapStringA must succeed\n");
857 ok(ret == ret2, "lengths of sort keys must be equal\n");
858 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
860 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
861 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
862 lower_case, -1, buf, sizeof(buf));
863 ok(ret, "LCMapStringA must succeed\n");
864 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
865 lower_case, -1, buf2, sizeof(buf2));
866 ok(ret2, "LCMapStringA must succeed\n");
867 ok(ret == ret2, "lengths of sort keys must be equal\n");
868 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
870 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
871 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
872 lower_case, -1, buf, sizeof(buf));
873 ok(ret, "LCMapStringA must succeed\n");
874 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
875 symbols_stripped, -1, buf2, sizeof(buf2));
876 ok(ret2, "LCMapStringA must succeed\n");
877 ok(ret == ret2, "lengths of sort keys must be equal\n");
878 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
880 /* test NORM_IGNORENONSPACE */
881 lstrcpyA(buf, "foo");
882 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
883 lower_case, -1, buf, sizeof(buf));
884 ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
885 lstrlenA(lower_case) + 1, ret);
886 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
888 /* test NORM_IGNORESYMBOLS */
889 lstrcpyA(buf, "foo");
890 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
891 lower_case, -1, buf, sizeof(buf));
892 ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
893 lstrlenA(symbols_stripped) + 1, ret);
894 ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
897 void test_LCMapStringW(void)
899 int ret, ret2;
900 WCHAR buf[256], buf2[256];
901 char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
902 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};
903 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};
904 static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
905 static const WCHAR fooW[] = {'f','o','o',0};
907 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
908 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
909 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
911 trace("Skipping LCMapStringW tests on Win9x\n");
912 return;
914 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
915 ok(GetLastError() == ERROR_INVALID_FLAGS,
916 "unexpected error code %ld\n", GetLastError());
918 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
919 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
920 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
921 ok(GetLastError() == ERROR_INVALID_FLAGS,
922 "unexpected error code %ld\n", GetLastError());
924 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
925 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
926 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
927 ok(GetLastError() == ERROR_INVALID_FLAGS,
928 "unexpected error code %ld\n", GetLastError());
930 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
931 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
932 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
933 ok(GetLastError() == ERROR_INVALID_FLAGS,
934 "unexpected error code %ld\n", GetLastError());
936 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
937 SetLastError(0xdeadbeef);
938 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
939 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
940 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError());
941 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
943 /* test LCMAP_LOWERCASE */
944 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
945 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
946 ok(ret == lstrlenW(upper_case) + 1,
947 "ret %d, error %ld, expected value %d\n",
948 ret, GetLastError(), lstrlenW(upper_case) + 1);
949 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
951 /* test LCMAP_UPPERCASE */
952 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
953 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
954 ok(ret == lstrlenW(lower_case) + 1,
955 "ret %d, error %ld, expected value %d\n",
956 ret, GetLastError(), lstrlenW(lower_case) + 1);
957 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
959 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
960 lstrcpyW(buf, lower_case);
961 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
962 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
963 ok(ret == lstrlenW(lower_case) + 1,
964 "ret %d, error %ld, expected value %d\n",
965 ret, GetLastError(), lstrlenW(lower_case) + 1);
966 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
968 lstrcpyW(buf, upper_case);
969 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
970 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
971 ok(ret == lstrlenW(upper_case) + 1,
972 "ret %d, error %ld, expected value %d\n",
973 ret, GetLastError(), lstrlenW(lower_case) + 1);
974 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
976 /* otherwise src == dst should fail */
977 SetLastError(0xdeadbeef);
978 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
979 buf, 10, buf, sizeof(buf));
980 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
981 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
982 "unexpected error code %ld\n", GetLastError());
983 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
985 /* test whether '\0' is always appended */
986 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
987 upper_case, -1, buf, sizeof(buf));
988 ok(ret, "LCMapStringW must succeed\n");
989 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
990 upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
991 ok(ret, "LCMapStringW must succeed\n");
992 ok(ret == ret2, "lengths of sort keys must be equal\n");
993 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
995 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
996 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
997 upper_case, -1, buf, sizeof(buf));
998 ok(ret, "LCMapStringW must succeed\n");
999 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1000 lower_case, -1, buf2, sizeof(buf2));
1001 ok(ret2, "LCMapStringW must succeed\n");
1002 ok(ret == ret2, "lengths of sort keys must be equal\n");
1003 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1005 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1006 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1007 lower_case, -1, buf, sizeof(buf));
1008 ok(ret, "LCMapStringW must succeed\n");
1009 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1010 lower_case, -1, buf2, sizeof(buf2));
1011 ok(ret2, "LCMapStringW must succeed\n");
1012 ok(ret == ret2, "lengths of sort keys must be equal\n");
1013 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1015 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1016 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1017 lower_case, -1, buf, sizeof(buf));
1018 ok(ret, "LCMapStringW must succeed\n");
1019 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1020 symbols_stripped, -1, buf2, sizeof(buf2));
1021 ok(ret2, "LCMapStringW must succeed\n");
1022 ok(ret == ret2, "lengths of sort keys must be equal\n");
1023 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1025 /* test NORM_IGNORENONSPACE */
1026 lstrcpyW(buf, fooW);
1027 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1028 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1029 ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1030 lstrlenW(lower_case) + 1, ret);
1031 ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1033 /* test NORM_IGNORESYMBOLS */
1034 lstrcpyW(buf, fooW);
1035 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1036 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1037 ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1038 lstrlenW(symbols_stripped) + 1, ret);
1039 ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1042 #define LCID_OK(l) \
1043 ok(lcid == l, "Expected lcid = %08lx, got %08lx\n", l, lcid)
1044 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
1045 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
1046 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
1047 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
1049 static void test_ConvertDefaultLocale(void)
1051 LCID lcid;
1053 /* Doesn't change lcid, even if non default sublang/sort used */
1054 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_US, SORT_DEFAULT);
1055 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_UK, SORT_DEFAULT);
1056 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT);
1057 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE);
1059 /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
1060 LCID_RES(MKLCID(LANG_ENGLISH, SUBLANG_NEUTRAL, SORT_DEFAULT),
1061 MKLCID(LANG_ENGLISH, SUBLANG_DEFAULT, SORT_DEFAULT));
1062 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
1063 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
1064 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_JAPANESE_UNICODE),
1065 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE));
1067 /* Invariant language is not treated specially */
1068 TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
1069 LCID_RES(MKLCID(LANG_INVARIANT, SUBLANG_NEUTRAL, SORT_DEFAULT),
1070 MKLCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT));
1072 /* User/system default languages alone are not mapped */
1073 TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
1074 TEST_LCIDLANG(LANG_USER_DEFAULT, SORT_JAPANESE_UNICODE);
1076 /* Default lcids */
1077 LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
1078 LCID_RES(LOCALE_USER_DEFAULT, GetUserDefaultLCID());
1079 LCID_RES(LOCALE_NEUTRAL, GetUserDefaultLCID());
1082 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
1083 DWORD dwFlags, LONG_PTR lParam)
1085 trace("%08lx, %s, %s, %08lx, %08lx\n",
1086 lgrpid, lpszNum, lpszName, dwFlags, lParam);
1088 ok(IsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
1089 "Enumerated grp %ld not valid (flags %ld)\n", lgrpid, dwFlags);
1091 /* If lParam is one, we are calling with flags defaulted from 0 */
1092 ok(!lParam || dwFlags == LGRPID_INSTALLED,
1093 "Expected dwFlags == LGRPID_INSTALLED, got %ld\n", dwFlags);
1095 return TRUE;
1098 static void test_EnumSystemLanguageGroupsA(void)
1100 if (!pEnumSystemLanguageGroupsA)
1101 return;
1103 /* No enumeration proc */
1104 SetLastError(0);
1105 pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
1106 EXPECT_INVALID;
1108 /* Invalid flags */
1109 SetLastError(0);
1110 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
1111 EXPECT_FLAGS;
1113 /* No flags - defaults to LGRPID_INSTALLED */
1114 SetLastError(0);
1115 pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
1116 EXPECT_VALID;
1118 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
1119 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
1123 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
1124 LONG_PTR lParam)
1126 trace("%08lx, %08lx, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
1128 ok(IsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
1129 "Enumerated grp %ld not valid\n", lgrpid);
1130 ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
1131 "Enumerated grp locale %ld not valid\n", lcid);
1132 return TRUE;
1135 static void test_EnumLanguageGroupLocalesA(void)
1137 if (!pEnumLanguageGroupLocalesA)
1138 return;
1140 /* No enumeration proc */
1141 SetLastError(0);
1142 pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
1143 EXPECT_INVALID;
1145 /* lgrpid too small */
1146 SetLastError(0);
1147 pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
1148 EXPECT_INVALID;
1150 /* lgrpid too big */
1151 SetLastError(0);
1152 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
1153 EXPECT_INVALID;
1155 /* dwFlags is reserved */
1156 SetLastError(0);
1157 pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
1158 EXPECT_INVALID;
1160 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
1163 static void test_SetLocaleInfoA(void)
1165 BOOL bRet;
1166 LCID lcid = GetUserDefaultLCID();
1168 /* Null data */
1169 SetLastError(0);
1170 bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
1171 EXPECT_INVALID;
1173 /* IDATE */
1174 SetLastError(0);
1175 bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
1176 EXPECT_FLAGS;
1178 /* ILDATE */
1179 SetLastError(0);
1180 bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
1181 EXPECT_FLAGS;
1184 START_TEST(locale)
1186 InitFunctionPointers();
1188 #if 0
1189 test_EnumTimeFormats();
1190 #endif
1191 test_GetLocaleInfoA();
1192 test_GetTimeFormatA();
1193 test_GetDateFormatA();
1194 test_GetDateFormatW();
1195 test_GetCurrencyFormatA(); /* Also tests the W version */
1196 test_GetNumberFormatA(); /* Also tests the W version */
1197 test_CompareStringA();
1198 test_LCMapStringA();
1199 test_LCMapStringW();
1200 test_ConvertDefaultLocale();
1201 test_EnumSystemLanguageGroupsA();
1202 test_EnumLanguageGroupLocalesA();
1203 test_SetLocaleInfoA();