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 inline static 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");
93 pEnumSystemLanguageGroupsA = (void*)GetProcAddress(hKernel32, "EnumSystemLanguageGroupsA");
94 pEnumLanguageGroupLocalesA = (void*)GetProcAddress(hKernel32, "EnumLanguageGroupLocalesA");
95 pFoldStringA = (void*)GetProcAddress(hKernel32, "FoldStringA");
96 pFoldStringW = (void*)GetProcAddress(hKernel32, "FoldStringW");
97 pIsValidLanguageGroup = (void*)GetProcAddress(hKernel32, "IsValidLanguageGroup");
98 pEnumUILanguagesA = (void*)GetProcAddress(hKernel32, "EnumUILanguagesA");
102 #define eq(received, expected, label, type) \
103 ok((received) == (expected), "%s: got " type " instead of " type "\n", \
104 (label), (received), (expected))
106 #define BUFFER_SIZE 128
107 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
109 #define EXPECT_LEN(len) ok(ret == (len), "Expected Len %d, got %d\n", (int)(len), ret)
110 #define EXPECT_INVALID ok(GetLastError() == ERROR_INVALID_PARAMETER, \
111 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError())
112 #define EXPECT_BUFFER ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, \
113 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError())
114 #define EXPECT_FLAGS ok(GetLastError() == ERROR_INVALID_FLAGS, \
115 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError())
116 #define EXPECT_INVALIDFLAGS ok(GetLastError() == ERROR_INVALID_FLAGS || \
117 GetLastError() == ERROR_INVALID_PARAMETER, \
118 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError())
119 #define EXPECT_LASTERROR_0 ok(GetLastError() == 0, \
120 "Expected GetLastError() == 0, got %d\n", GetLastError())
121 #define EXPECT_VALID ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError())
123 #define STRINGSA(x,y) strcpy(input, x); strcpy(Expected, y); SetLastError(0); buffer[0] = '\0'
124 #define EXPECT_LENA EXPECT_LEN((int)strlen(Expected)+1)
125 #define EXPECT_EQA ok(strncmp(buffer, Expected, strlen(Expected)) == 0, \
126 "Expected '%s', got '%s'\n", Expected, buffer)
128 #define STRINGSW(x,y) MultiByteToWideChar(CP_ACP,0,x,-1,input,COUNTOF(input)); \
129 MultiByteToWideChar(CP_ACP,0,y,-1,Expected,COUNTOF(Expected)); \
130 SetLastError(0); buffer[0] = '\0'
131 #define EXPECT_LENW EXPECT_LEN((int)strlenW(Expected)+1)
132 #define EXPECT_EQW ok(strncmpW(buffer, Expected, strlenW(Expected)) == 0, "Bad conversion\n")
133 #define EXPECT_FALSE ok(FALSE == ret, "Expected return value FALSE, got TRUE\n")
134 #define EXPECT_TRUE ok(FALSE != ret, "Expected return value TRUE, got FALSE\n")
136 #define NUO LOCALE_NOUSEROVERRIDE
138 static void test_GetLocaleInfoA(void)
141 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
142 char buffer[BUFFER_SIZE];
144 ok(lcid == 0x409, "wrong LCID calculated - %d\n", lcid);
146 /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
147 * partially fill the buffer even if it is too short. See bug 637.
149 SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
150 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 0);
151 ok(ret == 7 && !buffer[0], "Expected len=7, got %d\n", ret);
153 SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
154 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 3);
155 EXPECT_BUFFER; EXPECT_LEN(0);
156 ok(!strcmp(buffer, "Mon"), "Expected 'Mon', got '%s'\n", buffer);
158 SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
159 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 10);
160 EXPECT_VALID; EXPECT_LEN(7);
161 ok(!strcmp(buffer, "Monday"), "Expected 'Monday', got '%s'\n", buffer);
164 static void test_GetTimeFormatA(void)
168 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
169 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
171 memset(&curtime, 2, sizeof(SYSTEMTIME));
172 STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
173 SetLastError(0xdeadbeef);
174 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
175 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
178 curtime.wMinute = 56;
179 curtime.wSecond = 13;
180 curtime.wMilliseconds = 22;
181 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
182 SetLastError(0xdeadbeef);
183 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
184 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
186 /* MSDN: LOCALE_NOUSEROVERRIDE can't be specified with a format string */
187 SetLastError(0xdeadbeef);
188 ret = GetTimeFormatA(lcid, NUO|TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
189 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
191 STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficent buffer */
192 SetLastError(0xdeadbeef);
193 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, 2);
194 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
196 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
197 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, NULL, 0);
198 EXPECT_VALID; EXPECT_LENA;
200 STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
201 ret = GetTimeFormatA(lcid, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
202 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
204 STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
205 ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
206 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
208 STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
209 ret = GetTimeFormatA(lcid, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
210 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
212 STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
213 strcpy(Expected, "8:56 AM");
214 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
215 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
217 STRINGSA("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
218 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
219 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
221 STRINGSA("s1s2s3", ""); /* Duplicate tokens */
222 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
223 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
225 STRINGSA("t/tt", "A/AM"); /* AM time marker */
226 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
227 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
230 STRINGSA("t/tt", "P/PM"); /* PM time marker */
231 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
232 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
234 STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
235 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
236 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
238 STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
239 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
240 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
242 STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
243 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
244 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
246 curtime.wHour = 14; /* change this to 14 or 2pm */
249 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 */
250 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
251 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
254 STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
255 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
256 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
258 STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
259 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
260 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
262 /* try to convert formatting strings with more than two letters
263 * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
264 * NOTE: We expect any letter for which there is an upper case value
265 * we should see a replacement. For letters that DO NOT have
266 * upper case values we should see NO REPLACEMENT.
269 curtime.wMinute = 56;
270 curtime.wSecond = 13;
271 curtime.wMilliseconds = 22;
272 STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
273 "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
274 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
275 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
277 STRINGSA("h", "text"); /* Don't write to buffer if len is 0 */
278 strcpy(buffer, "text");
279 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, 0);
280 EXPECT_VALID; EXPECT_LEN(2); EXPECT_EQA;
282 STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
283 "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
284 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
285 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
287 STRINGSA("'''", "'"); /* invalid quoted string */
288 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
289 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
291 /* test that msdn suggested single quotation usage works as expected */
292 STRINGSA("''''", "'"); /* single quote mark */
293 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
294 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
296 STRINGSA("''HHHHHH", "08"); /* Normal use */
297 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
298 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
300 /* and test for normal use of the single quotation mark */
301 STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
302 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
303 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
305 STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
306 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
307 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
309 STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
310 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
311 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
314 STRINGSA("'123'tt", ""); /* Invalid time */
315 SetLastError(0xdeadbeef);
316 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
317 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
320 curtime.wMonth = 60; /* Invalid */
321 STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
322 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
323 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
326 static void test_GetDateFormatA(void)
330 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
331 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
333 memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
334 STRINGSA("ddd',' MMM dd yy","");
335 SetLastError(0xdeadbeef);
336 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
337 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
339 curtime.wYear = 2002;
342 curtime.wDayOfWeek = 3;
343 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
344 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
345 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
347 /* Same as above but with LOCALE_NOUSEROVERRIDE */
348 STRINGSA("ddd',' MMM dd yy",""); /* Simple case */
349 SetLastError(0xdeadbeef);
350 ret = GetDateFormatA(lcid, NUO, &curtime, input, buffer, COUNTOF(buffer));
351 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
353 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
354 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
355 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
357 curtime.wHour = 36; /* Invalid */
358 STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
359 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
360 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
362 STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
363 ret = GetDateFormatA(lcid, 0, &curtime, input, NULL, 0);
364 EXPECT_VALID; EXPECT_LEN(16); EXPECT_EQA;
366 STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
367 SetLastError(0xdeadbeef);
368 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, 2);
369 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
371 STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
372 ret = GetDateFormat(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
373 EXPECT_VALID; EXPECT_LENA;
374 if (strncmp(buffer, Expected, strlen(Expected)) && strncmp(buffer, "5/4/02", strlen(Expected)) != 0)
375 ok (0, "Expected '%s' or '5/4/02', got '%s'\n", Expected, buffer);
377 STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
378 ret = GetDateFormat(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
379 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
381 /* test for expected DATE_YEARMONTH behavior with null format */
382 /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
383 STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
384 SetLastError(0xdeadbeef);
385 ret = GetDateFormat(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
386 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
388 /* Test that using invalid DATE_* flags results in the correct error */
389 /* and return values */
390 STRINGSA("m/d/y", ""); /* Invalid flags */
391 SetLastError(0xdeadbeef);
392 ret = GetDateFormat(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
393 &curtime, input, buffer, COUNTOF(buffer));
394 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
397 static void test_GetDateFormatW(void)
401 WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
402 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
404 STRINGSW("",""); /* If flags is not zero then format must be NULL */
405 ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL,
406 input, buffer, COUNTOF(buffer));
407 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
409 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQW;
411 STRINGSW("",""); /* NULL buffer, len > 0 */
412 SetLastError(0xdeadbeef);
413 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
414 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQW;
416 STRINGSW("",""); /* NULL buffer, len == 0 */
417 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
418 EXPECT_VALID; EXPECT_LENW; EXPECT_EQW;
420 curtime.wYear = 2002;
423 curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
424 curtime.wHour = 65432; /* Invalid */
425 curtime.wMinute = 34512; /* Invalid */
426 curtime.wSecond = 65535; /* Invalid */
427 curtime.wMilliseconds = 12345;
428 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
429 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
430 EXPECT_VALID; EXPECT_LENW; EXPECT_EQW;
434 #define CY_POS_LEFT 0
435 #define CY_POS_RIGHT 1
436 #define CY_POS_LEFT_SPACE 2
437 #define CY_POS_RIGHT_SPACE 3
439 static void test_GetCurrencyFormatA(void)
441 static char szDot[] = { '.', '\0' };
442 static char szComma[] = { ',', '\0' };
443 static char szDollar[] = { '$', '\0' };
445 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
446 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
449 memset(&format, 0, sizeof(format));
451 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
452 SetLastError(0xdeadbeef);
453 ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
454 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
456 STRINGSA("23,53",""); /* Invalid character --> Error */
457 SetLastError(0xdeadbeef);
458 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
459 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
461 STRINGSA("--",""); /* Double '-' --> Error */
462 SetLastError(0xdeadbeef);
463 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
464 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
466 STRINGSA("0-",""); /* Trailing '-' --> Error */
467 SetLastError(0xdeadbeef);
468 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
469 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
471 STRINGSA("0..",""); /* Double '.' --> Error */
472 SetLastError(0xdeadbeef);
473 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
474 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
476 STRINGSA(" 0.1",""); /* Leading space --> Error */
477 SetLastError(0xdeadbeef);
478 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
479 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
481 STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
482 SetLastError(0xdeadbeef);
483 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, 2);
484 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
486 STRINGSA("2353",""); /* Format and flags given --> Error */
487 SetLastError(0xdeadbeef);
488 ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
489 EXPECT_INVALIDFLAGS; EXPECT_LEN(0); EXPECT_EQA;
491 STRINGSA("2353",""); /* Invalid format --> Error */
492 SetLastError(0xdeadbeef);
493 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
494 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
496 STRINGSA("2353","$2,353.00"); /* Valid number */
497 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
498 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
500 STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
501 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
502 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
504 STRINGSA("2353.1","$2,353.10"); /* Valid real number */
505 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
506 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
508 STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
509 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
510 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
512 STRINGSA("2353.119","$2,353.12"); /* Too many DP --> Rounded */
513 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
514 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
516 format.NumDigits = 0; /* No decimal separator */
517 format.LeadingZero = 0;
518 format.Grouping = 0; /* No grouping char */
519 format.NegativeOrder = 0;
520 format.PositiveOrder = CY_POS_LEFT;
521 format.lpDecimalSep = szDot;
522 format.lpThousandSep = szComma;
523 format.lpCurrencySymbol = szDollar;
525 STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
526 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
527 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
529 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
530 STRINGSA("2353","$2353.0");
531 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
532 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
534 format.Grouping = 2; /* Group by 100's */
535 STRINGSA("2353","$23,53.0");
536 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
537 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
539 format.LeadingZero = 1; /* Always provide leading zero */
540 STRINGSA(".5","$0.5");
541 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
542 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
544 format.PositiveOrder = CY_POS_RIGHT;
545 STRINGSA("1","1.0$");
546 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
547 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
549 format.PositiveOrder = CY_POS_LEFT_SPACE;
550 STRINGSA("1","$ 1.0");
551 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
552 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
554 format.PositiveOrder = CY_POS_RIGHT_SPACE;
555 STRINGSA("1","1.0 $");
556 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
557 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
559 format.NegativeOrder = 0;
560 STRINGSA("-1","($1.0)");
561 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
562 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
564 format.NegativeOrder = 1;
565 STRINGSA("-1","-$1.0");
566 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
567 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
569 format.NegativeOrder = 2;
570 STRINGSA("-1","$-1.0");
571 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
572 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
574 format.NegativeOrder = 3;
575 STRINGSA("-1","$1.0-");
576 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
577 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
579 format.NegativeOrder = 4;
580 STRINGSA("-1","(1.0$)");
581 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
582 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
584 format.NegativeOrder = 5;
585 STRINGSA("-1","-1.0$");
586 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
587 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
589 format.NegativeOrder = 6;
590 STRINGSA("-1","1.0-$");
591 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
592 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
594 format.NegativeOrder = 7;
595 STRINGSA("-1","1.0$-");
596 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
597 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
599 format.NegativeOrder = 8;
600 STRINGSA("-1","-1.0 $");
601 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
602 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
604 format.NegativeOrder = 9;
605 STRINGSA("-1","-$ 1.0");
606 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
607 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
609 format.NegativeOrder = 10;
610 STRINGSA("-1","1.0 $-");
611 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
612 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
614 format.NegativeOrder = 11;
615 STRINGSA("-1","$ 1.0-");
616 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
617 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
619 format.NegativeOrder = 12;
620 STRINGSA("-1","$ -1.0");
621 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
622 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
624 format.NegativeOrder = 13;
625 STRINGSA("-1","1.0- $");
626 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
627 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
629 format.NegativeOrder = 14;
630 STRINGSA("-1","($ 1.0)");
631 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
632 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
634 format.NegativeOrder = 15;
635 STRINGSA("-1","(1.0 $)");
636 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
637 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
640 #define NEG_PARENS 0 /* "(1.1)" */
641 #define NEG_LEFT 1 /* "-1.1" */
642 #define NEG_LEFT_SPACE 2 /* "- 1.1" */
643 #define NEG_RIGHT 3 /* "1.1-" */
644 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
646 static void test_GetNumberFormatA(void)
648 static char szDot[] = { '.', '\0' };
649 static char szComma[] = { ',', '\0' };
651 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
652 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
655 memset(&format, 0, sizeof(format));
657 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
658 SetLastError(0xdeadbeef);
659 ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
660 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
662 STRINGSA("23,53",""); /* Invalid character --> Error */
663 SetLastError(0xdeadbeef);
664 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
665 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
667 STRINGSA("--",""); /* Double '-' --> Error */
668 SetLastError(0xdeadbeef);
669 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
670 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
672 STRINGSA("0-",""); /* Trailing '-' --> Error */
673 SetLastError(0xdeadbeef);
674 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
675 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
677 STRINGSA("0..",""); /* Double '.' --> Error */
678 SetLastError(0xdeadbeef);
679 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
680 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
682 STRINGSA(" 0.1",""); /* Leading space --> Error */
683 SetLastError(0xdeadbeef);
684 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
685 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
687 STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
688 SetLastError(0xdeadbeef);
689 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, 2);
690 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
692 STRINGSA("2353",""); /* Format and flags given --> Error */
693 SetLastError(0xdeadbeef);
694 ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
695 EXPECT_INVALIDFLAGS; EXPECT_LEN(0); EXPECT_EQA;
697 STRINGSA("2353",""); /* Invalid format --> Error */
698 SetLastError(0xdeadbeef);
699 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
700 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
702 STRINGSA("2353","2,353.00"); /* Valid number */
703 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
704 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
706 STRINGSA("-2353","-2,353.00"); /* Valid negative number */
707 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
708 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
710 STRINGSA("-353","-353.00"); /* test for off by one error in grouping */
711 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
712 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
714 STRINGSA("2353.1","2,353.10"); /* Valid real number */
715 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
716 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
718 STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
719 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
720 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
722 STRINGSA("2353.119","2,353.12"); /* Too many DP --> Rounded */
723 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
724 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
726 format.NumDigits = 0; /* No decimal separator */
727 format.LeadingZero = 0;
728 format.Grouping = 0; /* No grouping char */
729 format.NegativeOrder = 0;
730 format.lpDecimalSep = szDot;
731 format.lpThousandSep = szComma;
733 STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
734 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
735 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
737 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
738 STRINGSA("2353","2353.0");
739 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
740 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
742 format.Grouping = 2; /* Group by 100's */
743 STRINGSA("2353","23,53.0");
744 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
745 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
747 format.LeadingZero = 1; /* Always provide leading zero */
748 STRINGSA(".5","0.5");
749 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
750 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
752 format.NegativeOrder = NEG_PARENS;
753 STRINGSA("-1","(1.0)");
754 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
755 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
757 format.NegativeOrder = NEG_LEFT;
758 STRINGSA("-1","-1.0");
759 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
760 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
762 format.NegativeOrder = NEG_LEFT_SPACE;
763 STRINGSA("-1","- 1.0");
764 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
765 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
767 format.NegativeOrder = NEG_RIGHT;
768 STRINGSA("-1","1.0-");
769 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
770 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
772 format.NegativeOrder = NEG_RIGHT_SPACE;
773 STRINGSA("-1","1.0 -");
774 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
775 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
777 lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
779 if (IsValidLocale(lcid, 0))
781 STRINGSA("-12345","-12 345,00"); /* Try French formatting */
782 Expected[3] = 160; /* Non breaking space */
783 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
784 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
789 static void test_CompareStringA(void)
792 LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
794 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
795 ok (ret== 1, "(Salut/Salute) Expected 1, got %d\n", ret);
797 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
798 ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
800 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
801 ok (ret== 3, "(Salut/hola) Expected 3, got %d\n", ret);
803 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
804 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
806 lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
808 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
809 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
811 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
812 ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
814 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
815 ok (ret == 2, "(Salut/saLuT) Expected 2, got %d\n", ret);
817 /* test for CompareStringA flags */
818 SetLastError(0xdeadbeef);
819 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0x10, "NULL", -1, "NULL", -1);
820 ok(GetLastError() == ERROR_INVALID_FLAGS,
821 "unexpected error code %d\n", GetLastError());
822 ok(!ret, "CompareStringA must fail with invalid flag\n");
824 SetLastError(0xdeadbeef);
825 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, LOCALE_USE_CP_ACP, "NULL", -1, "NULL", -1);
826 ok(GetLastError() == 0xdeadbeef, "unexpected error code %d\n", GetLastError());
827 ok(ret == CSTR_EQUAL, "CompareStringA error: %d != CSTR_EQUAL\n", ret);
828 /* end of test for CompareStringA flags */
830 ret = lstrcmpA("", "");
831 ok (ret == 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret);
833 ret = lstrcmpA(NULL, NULL);
834 ok (ret == 0, "lstrcmpA(NULL, NULL) should return 0, got %d\n", ret);
836 ret = lstrcmpA("", NULL);
837 ok (ret == 1, "lstrcmpA(\"\", NULL) should return 1, got %d\n", ret);
839 ret = lstrcmpA(NULL, "");
840 ok (ret == -1, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret);
842 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"EndDialog",-1,"_Property",-1);
843 ok( ret == 3, "EndDialog vs _Property ... expected 3, got %d\n", ret);
845 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0070",-1,"_IEWWBrowserComp",-1);
846 ok( ret == 3, "osp_vba.sreg0070 vs _IEWWBrowserComp ... expected 3, got %d\n", ret);
848 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"r",-1,"\\",-1);
849 ok( ret == 3, "r vs \\ ... expected 3, got %d\n", ret);
851 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0031", -1, "OriginalDatabase", -1 );
852 ok( ret == 3, "osp_vba.sreg0031 vs OriginalDatabase ... expected 3, got %d\n", ret);
854 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1 );
855 ok( ret == 3, "AAA vs aaa expected 3, got %d\n", ret);
857 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1 );
858 ok( ret == 1, "AAA vs aab expected 1, got %d\n", ret);
860 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1 );
861 ok( ret == 1, "AAA vs Aab expected 1, got %d\n", ret);
863 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1 );
864 ok( ret == 1, ".AAA vs Aab expected 1, got %d\n", ret);
866 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1 );
867 ok( ret == 1, ".AAA vs A.ab expected 1, got %d\n", ret);
869 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1 );
870 ok( ret == 1, "aa vs AB expected 1, got %d\n", ret);
872 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1 );
873 ok( ret == 1, "aa vs Aab expected 1, got %d\n", ret);
875 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1 );
876 ok( ret == 3, "aB vs Aab expected 3, got %d\n", ret);
878 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1 );
879 ok( ret == 1, "Ba vs bab expected 1, got %d\n", ret);
881 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1 );
882 ok( ret == 1, "{100}{83}{71}{71}{71} vs Global_DataAccess_JRO expected 1, got %d\n", ret);
884 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1 );
885 ok( ret == 3, "a vs { expected 3, got %d\n", ret);
887 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1 );
888 ok( ret == 3, "A vs { expected 3, got %d\n", ret);
890 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1 );
891 ok(ret == 1, "3.5/0 vs 4.0/-1 expected 1, got %d\n", ret);
893 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1 );
894 ok(ret == 1, "3.5 vs 4.0 expected 1, got %d\n", ret);
896 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1 );
897 ok(ret == 1, "3.520.4403.2 vs 4.0.2927.10 expected 1, got %d\n", ret);
899 /* hyphen and apostrophe are treated differently depending on
900 * whether SORT_STRINGSORT specified or not
902 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1 );
903 ok(ret == 3, "-o vs /m expected 3, got %d\n", ret);
905 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1 );
906 ok(ret == 1, "/m vs -o expected 1, got %d\n", ret);
908 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1 );
909 ok(ret == 1, "-o vs /m expected 1, got %d\n", ret);
911 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1 );
912 ok(ret == 3, "/m vs -o expected 3, got %d\n", ret);
914 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1 );
915 ok(ret == 3, "'o vs /m expected 3, got %d\n", ret);
917 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1 );
918 ok(ret == 1, "/m vs 'o expected 1, got %d\n", ret);
920 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1 );
921 ok(ret == 1, "'o vs /m expected 1, got %d\n", ret);
923 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1 );
924 ok(ret == 3, "/m vs 'o expected 3, got %d\n", ret);
926 if (0) { /* this requires collation table patch to make it MS compatible */
927 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
928 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
930 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
931 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
933 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
934 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
936 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
937 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
939 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
940 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
942 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
943 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
945 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
946 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
948 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
949 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
951 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
952 ok(ret == 1, "`o vs -m expected 1, got %d\n", ret);
954 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
955 ok(ret == 3, "-m vs `o expected 3, got %d\n", ret);
957 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
958 ok(ret == 3, "`o vs -m expected 3, got %d\n", ret);
960 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
961 ok(ret == 1, "-m vs `o expected 1, got %d\n", ret);
964 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9);
965 ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0 expected 2, got %d\n", ret);
967 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10);
968 ok(ret == 1, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1, got %d\n", ret);
970 /* WinXP handles embedded NULLs differently than earlier versions */
971 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
972 ok(ret == 1 || ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1 or 2, got %d\n", ret);
974 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
975 ok(ret == 1 || ret == 2, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected 1 or 2, got %d\n", ret);
977 ret = CompareStringA(lcid, 0, "a\0b", -1, "a", -1);
978 ok(ret == 2, "a vs a expected 2, got %d\n", ret);
980 ret = CompareStringA(lcid, 0, "a\0b", 4, "a", 2);
981 ok(ret == 3, "a\\0b vs a expected 3, got %d\n", ret);
983 ret = CompareStringA(lcid, 0, "\2", 2, "\1", 2);
984 todo_wine ok(ret != 2, "\\2 vs \\1 expected unequal\n");
987 static void test_LCMapStringA(void)
990 char buf[256], buf2[256];
991 static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
992 static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
993 static const char symbols_stripped[] = "justateststring1";
995 SetLastError(0xdeadbeef);
996 ret = LCMapStringA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP | LCMAP_LOWERCASE,
997 lower_case, -1, buf, sizeof(buf));
998 ok(ret == lstrlenA(lower_case) + 1,
999 "ret %d, error %d, expected value %d\n",
1000 ret, GetLastError(), lstrlenA(lower_case) + 1);
1001 ok(!memcmp(buf, lower_case, ret), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1003 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1004 upper_case, -1, buf, sizeof(buf));
1005 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1006 ok(GetLastError() == ERROR_INVALID_FLAGS,
1007 "unexpected error code %d\n", GetLastError());
1009 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1010 upper_case, -1, buf, sizeof(buf));
1011 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1012 ok(GetLastError() == ERROR_INVALID_FLAGS,
1013 "unexpected error code %d\n", GetLastError());
1015 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1016 upper_case, -1, buf, sizeof(buf));
1017 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1018 ok(GetLastError() == ERROR_INVALID_FLAGS,
1019 "unexpected error code %d\n", GetLastError());
1021 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1022 upper_case, -1, buf, sizeof(buf));
1023 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1024 ok(GetLastError() == ERROR_INVALID_FLAGS,
1025 "unexpected error code %d\n", GetLastError());
1027 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1028 SetLastError(0xdeadbeef);
1029 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1030 upper_case, -1, buf, sizeof(buf));
1031 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1032 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1034 /* test LCMAP_LOWERCASE */
1035 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1036 upper_case, -1, buf, sizeof(buf));
1037 ok(ret == lstrlenA(upper_case) + 1,
1038 "ret %d, error %d, expected value %d\n",
1039 ret, GetLastError(), lstrlenA(upper_case) + 1);
1040 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1042 /* test LCMAP_UPPERCASE */
1043 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1044 lower_case, -1, buf, sizeof(buf));
1045 ok(ret == lstrlenA(lower_case) + 1,
1046 "ret %d, error %d, expected value %d\n",
1047 ret, GetLastError(), lstrlenA(lower_case) + 1);
1048 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1050 /* test buffer overflow */
1051 SetLastError(0xdeadbeef);
1052 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1053 lower_case, -1, buf, 4);
1054 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1055 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1057 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1058 lstrcpyA(buf, lower_case);
1059 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1060 buf, -1, buf, sizeof(buf));
1061 if (!ret) /* Win9x */
1062 trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1065 ok(ret == lstrlenA(lower_case) + 1,
1066 "ret %d, error %d, expected value %d\n",
1067 ret, GetLastError(), lstrlenA(lower_case) + 1);
1068 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1070 lstrcpyA(buf, upper_case);
1071 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1072 buf, -1, buf, sizeof(buf));
1073 if (!ret) /* Win9x */
1074 trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1077 ok(ret == lstrlenA(upper_case) + 1,
1078 "ret %d, error %d, expected value %d\n",
1079 ret, GetLastError(), lstrlenA(lower_case) + 1);
1080 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1083 /* otherwise src == dst should fail */
1084 SetLastError(0xdeadbeef);
1085 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1086 buf, 10, buf, sizeof(buf));
1087 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1088 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1089 "unexpected error code %d\n", GetLastError());
1090 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1092 /* test whether '\0' is always appended */
1093 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1094 upper_case, -1, buf, sizeof(buf));
1095 ok(ret, "LCMapStringA must succeed\n");
1096 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1097 upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1098 ok(ret, "LCMapStringA must succeed\n");
1099 ok(ret == ret2, "lengths of sort keys must be equal\n");
1100 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1102 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1103 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1104 upper_case, -1, buf, sizeof(buf));
1105 ok(ret, "LCMapStringA must succeed\n");
1106 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1107 lower_case, -1, buf2, sizeof(buf2));
1108 ok(ret2, "LCMapStringA must succeed\n");
1109 ok(ret == ret2, "lengths of sort keys must be equal\n");
1110 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1112 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1113 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1114 lower_case, -1, buf, sizeof(buf));
1115 ok(ret, "LCMapStringA must succeed\n");
1116 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1117 lower_case, -1, buf2, sizeof(buf2));
1118 ok(ret2, "LCMapStringA must succeed\n");
1119 ok(ret == ret2, "lengths of sort keys must be equal\n");
1120 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1122 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1123 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1124 lower_case, -1, buf, sizeof(buf));
1125 ok(ret, "LCMapStringA must succeed\n");
1126 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1127 symbols_stripped, -1, buf2, sizeof(buf2));
1128 ok(ret2, "LCMapStringA must succeed\n");
1129 ok(ret == ret2, "lengths of sort keys must be equal\n");
1130 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1132 /* test NORM_IGNORENONSPACE */
1133 lstrcpyA(buf, "foo");
1134 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1135 lower_case, -1, buf, sizeof(buf));
1136 ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1137 lstrlenA(lower_case) + 1, ret);
1138 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1140 /* test NORM_IGNORESYMBOLS */
1141 lstrcpyA(buf, "foo");
1142 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1143 lower_case, -1, buf, sizeof(buf));
1144 ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1145 lstrlenA(symbols_stripped) + 1, ret);
1146 ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1148 /* test srclen = 0 */
1149 SetLastError(0xdeadbeef);
1150 ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1151 ok(!ret, "LCMapStringA should fail with srclen = 0\n");
1152 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1153 "unexpected error code %d\n", GetLastError());
1156 static void test_LCMapStringW(void)
1159 WCHAR buf[256], buf2[256];
1160 char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1161 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};
1162 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};
1163 static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
1164 static const WCHAR fooW[] = {'f','o','o',0};
1166 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1167 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1168 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1170 trace("Skipping LCMapStringW tests on Win9x\n");
1173 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1174 ok(GetLastError() == ERROR_INVALID_FLAGS,
1175 "unexpected error code %d\n", GetLastError());
1177 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1178 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1179 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1180 ok(GetLastError() == ERROR_INVALID_FLAGS,
1181 "unexpected error code %d\n", GetLastError());
1183 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1184 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1185 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1186 ok(GetLastError() == ERROR_INVALID_FLAGS,
1187 "unexpected error code %d\n", GetLastError());
1189 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1190 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1191 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1192 ok(GetLastError() == ERROR_INVALID_FLAGS,
1193 "unexpected error code %d\n", GetLastError());
1195 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1196 SetLastError(0xdeadbeef);
1197 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1198 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1199 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1200 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1202 /* test LCMAP_LOWERCASE */
1203 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1204 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1205 ok(ret == lstrlenW(upper_case) + 1,
1206 "ret %d, error %d, expected value %d\n",
1207 ret, GetLastError(), lstrlenW(upper_case) + 1);
1208 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1210 /* test LCMAP_UPPERCASE */
1211 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1212 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1213 ok(ret == lstrlenW(lower_case) + 1,
1214 "ret %d, error %d, expected value %d\n",
1215 ret, GetLastError(), lstrlenW(lower_case) + 1);
1216 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1218 /* test buffer overflow */
1219 SetLastError(0xdeadbeef);
1220 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1221 lower_case, -1, buf, 4);
1222 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1223 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1225 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1226 lstrcpyW(buf, lower_case);
1227 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1228 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1229 ok(ret == lstrlenW(lower_case) + 1,
1230 "ret %d, error %d, expected value %d\n",
1231 ret, GetLastError(), lstrlenW(lower_case) + 1);
1232 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1234 lstrcpyW(buf, upper_case);
1235 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1236 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1237 ok(ret == lstrlenW(upper_case) + 1,
1238 "ret %d, error %d, expected value %d\n",
1239 ret, GetLastError(), lstrlenW(lower_case) + 1);
1240 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1242 /* otherwise src == dst should fail */
1243 SetLastError(0xdeadbeef);
1244 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1245 buf, 10, buf, sizeof(buf));
1246 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1247 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1248 "unexpected error code %d\n", GetLastError());
1249 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1251 /* test whether '\0' is always appended */
1252 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1253 upper_case, -1, buf, sizeof(buf));
1254 ok(ret, "LCMapStringW must succeed\n");
1255 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1256 upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1257 ok(ret, "LCMapStringW must succeed\n");
1258 ok(ret == ret2, "lengths of sort keys must be equal\n");
1259 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1261 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1262 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1263 upper_case, -1, buf, sizeof(buf));
1264 ok(ret, "LCMapStringW must succeed\n");
1265 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1266 lower_case, -1, buf2, sizeof(buf2));
1267 ok(ret2, "LCMapStringW must succeed\n");
1268 ok(ret == ret2, "lengths of sort keys must be equal\n");
1269 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1271 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1272 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1273 lower_case, -1, buf, sizeof(buf));
1274 ok(ret, "LCMapStringW must succeed\n");
1275 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1276 lower_case, -1, buf2, sizeof(buf2));
1277 ok(ret2, "LCMapStringW must succeed\n");
1278 ok(ret == ret2, "lengths of sort keys must be equal\n");
1279 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1281 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1282 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1283 lower_case, -1, buf, sizeof(buf));
1284 ok(ret, "LCMapStringW must succeed\n");
1285 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1286 symbols_stripped, -1, buf2, sizeof(buf2));
1287 ok(ret2, "LCMapStringW must succeed\n");
1288 ok(ret == ret2, "lengths of sort keys must be equal\n");
1289 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1291 /* test NORM_IGNORENONSPACE */
1292 lstrcpyW(buf, fooW);
1293 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1294 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1295 ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1296 lstrlenW(lower_case) + 1, ret);
1297 ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1299 /* test NORM_IGNORESYMBOLS */
1300 lstrcpyW(buf, fooW);
1301 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1302 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1303 ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1304 lstrlenW(symbols_stripped) + 1, ret);
1305 ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1307 /* test srclen = 0 */
1308 SetLastError(0xdeadbeef);
1309 ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1310 ok(!ret, "LCMapStringW should fail with srclen = 0\n");
1311 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1312 "unexpected error code %d\n", GetLastError());
1315 /* this requires collation table patch to make it MS compatible */
1316 const char *strings_sorted[] =
1348 const char *strings[] =
1380 static int compare_string1(const void *e1, const void *e2)
1382 const char *s1 = *(const char *const *)e1;
1383 const char *s2 = *(const char *const *)e2;
1385 return lstrcmpA(s1, s2);
1388 static int compare_string2(const void *e1, const void *e2)
1390 const char *s1 = *(const char *const *)e1;
1391 const char *s2 = *(const char *const *)e2;
1393 return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1396 static int compare_string3(const void *e1, const void *e2)
1398 const char *s1 = *(const char *const *)e1;
1399 const char *s2 = *(const char *const *)e2;
1400 char key1[256], key2[256];
1402 LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
1403 LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
1404 return strcmp(key1, key2);
1407 static void test_sorting(void)
1410 char **str_buf = (char **)buf;
1413 assert(sizeof(buf) >= sizeof(strings));
1415 /* 1. sort using lstrcmpA */
1416 memcpy(buf, strings, sizeof(strings));
1417 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
1418 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1420 ok(!strcmp(strings_sorted[i], str_buf[i]),
1421 "qsort using lstrcmpA failed for element %d\n", i);
1423 /* 2. sort using CompareStringA */
1424 memcpy(buf, strings, sizeof(strings));
1425 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
1426 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1428 ok(!strcmp(strings_sorted[i], str_buf[i]),
1429 "qsort using CompareStringA failed for element %d\n", i);
1431 /* 3. sort using sort keys */
1432 memcpy(buf, strings, sizeof(strings));
1433 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
1434 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1436 ok(!strcmp(strings_sorted[i], str_buf[i]),
1437 "qsort using sort keys failed for element %d\n", i);
1441 static void test_FoldStringA(void)
1444 char src[256], dst[256];
1445 static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0' };
1446 static const char digits_dst[] = { '1','2','3','\0' };
1447 static const char composite_src[] =
1449 0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
1450 0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
1451 0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
1452 0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
1453 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
1454 0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
1455 0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
1456 0xfb,0xfc,0xfd,0xff,'\0'
1458 static const char composite_dst[] =
1460 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1461 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1462 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1463 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1464 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1465 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1466 0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
1467 0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
1468 0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
1469 0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
1470 0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
1471 0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
1472 0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
1473 0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
1474 0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1476 static const char ligatures_src[] =
1478 0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1480 static const char ligatures_dst[] =
1482 'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1486 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1488 /* these tests are locale specific */
1489 if (GetACP() != 1252)
1491 trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1495 /* MAP_FOLDDIGITS */
1497 ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
1498 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1500 EXPECT_LEN(4); EXPECT_VALID;
1501 ok(strcmp(dst, digits_dst) == 0,
1502 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
1503 for (i = 1; i < 256; i++)
1505 if (!strchr(digits_src, i))
1510 ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
1511 EXPECT_LEN(2); EXPECT_VALID;
1512 ok(dst[0] == src[0],
1513 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
1517 /* MAP_EXPAND_LIGATURES */
1519 ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1520 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1521 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1522 EXPECT_LEN(sizeof(ligatures_dst)); EXPECT_VALID;
1523 ok(strcmp(dst, ligatures_dst) == 0,
1524 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
1525 for (i = 1; i < 256; i++)
1527 if (!strchr(ligatures_src, i))
1532 ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1533 EXPECT_LEN(2); EXPECT_VALID;
1534 ok(dst[0] == src[0],
1535 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
1542 ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
1546 /* Wine gets close, but doesn't produce quite the same result as native */
1548 ok(strcmp(dst, composite_dst) == 0,
1549 "MAP_COMPOSITE: Expected '%s', got '%s'\n", composite_dst, dst);
1552 for (i = 1; i < 256; i++)
1554 if (!strchr(composite_src, i))
1559 ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
1560 EXPECT_LEN(2); EXPECT_VALID;
1561 ok(dst[0] == src[0],
1562 "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
1563 (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
1568 for (i = 1; i < 256; i++)
1573 ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
1574 EXPECT_LEN(2); EXPECT_VALID;
1575 ok(src[0] == dst[0],
1576 "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
1577 (unsigned char)src[0], (unsigned char)dst[0]);
1580 /* MAP_PRECOMPOSED */
1581 for (i = 1; i < 256; i++)
1586 ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
1587 EXPECT_LEN(2); EXPECT_VALID;
1588 ok(src[0] == dst[0],
1589 "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
1590 (unsigned char)src[0], (unsigned char)dst[0]);
1594 static void test_FoldStringW(void)
1598 WCHAR src[256], dst[256], ch, prev_ch = 1;
1599 static const DWORD badFlags[] =
1602 MAP_PRECOMPOSED|MAP_COMPOSITE,
1603 MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
1604 MAP_COMPOSITE|MAP_EXPAND_LIGATURES
1606 /* Ranges of digits 0-9 : Must be sorted! */
1607 static const WCHAR digitRanges[] =
1609 0x0030, /* '0'-'9' */
1610 0x0660, /* Eastern Arabic */
1611 0x06F0, /* Arabic - Hindu */
1612 0x0966, /* Devengari */
1613 0x09E6, /* Bengalii */
1614 0x0A66, /* Gurmukhi */
1615 0x0AE6, /* Gujarati */
1617 0x0BE6, /* Tamil - No 0 */
1618 0x0C66, /* Telugu */
1619 0x0CE6, /* Kannada */
1620 0x0D66, /* Maylayalam */
1623 0x2070, /* Superscript - 1, 2, 3 are out of sequence */
1624 0x2080, /* Subscript */
1625 0x245F, /* Circled - 0 is out of sequence */
1626 0x2473, /* Bracketed */
1627 0x2487, /* Full stop */
1628 0x2775, /* Inverted circled - No 0 */
1629 0x277F, /* Patterned circled - No 0 */
1630 0x2789, /* Inverted Patterned circled - No 0 */
1631 0xff10, /* Pliene chasse (?) */
1632 0xffff /* Terminator */
1634 /* Digits which are represented, but out of sequence */
1635 static const WCHAR outOfSequenceDigits[] =
1637 0xB9, /* Superscript 1 */
1638 0xB2, /* Superscript 2 */
1639 0xB3, /* Superscript 3 */
1640 0x24EA, /* Circled 0 */
1641 '\0' /* Terminator */
1643 /* Digits in digitRanges for which no representation is available */
1644 static const WCHAR noDigitAvailable[] =
1646 0x0BE6, /* No Tamil 0 */
1647 0x2473, /* No Bracketed 0 */
1648 0x2487, /* No 0 Full stop */
1649 0x2775, /* No inverted circled 0 */
1650 0x277F, /* No patterned circled */
1651 0x2789, /* No inverted Patterned circled */
1652 '\0' /* Terminator */
1654 /* Compatibility conversion results */
1655 static const WCHAR compat_F900_FA2F[256+48] =
1657 0x8c48, 0x66f4, 0x8eca, 0x8cc8, 0x6ed1, 0x4e32, 0x53e5, 0x9f9c,
1658 0x9f9c, 0x5951, 0x91d1, 0x5587, 0x5948, 0x61f6, 0x7669, 0x7f85,
1659 0x863f, 0x87ba, 0x88f8, 0x908f, 0x6a02, 0x6d1b, 0x70d9, 0x73de,
1660 0x843d, 0x916a, 0x99f1, 0x4e82, 0x5375, 0x6b04, 0x721b, 0x862d,
1661 0x9e1e, 0x5d50, 0x6feb, 0x85cd, 0x8964, 0x62c9, 0x81d8, 0x881f,
1662 0x5eca, 0x6717, 0x6d6a, 0x72fc, 0x0000, 0x4f86, 0x51b7, 0x52de,
1663 0x64c4, 0x6ad3, 0x7210, 0x76e7, 0x8001, 0x8606, 0x865c, 0x8def,
1664 0x9732, 0x9b6f, 0x9dfa, 0x788c, 0x797f, 0x7da0, 0x83c9, 0x9304,
1665 0x9e7f, 0x8ad6, 0x58df, 0x5f04, 0x7c60, 0x807e, 0x7262, 0x78ca,
1666 0x8cc2, 0x96f7, 0x58d8, 0x5c62, 0x6a13, 0x6dda, 0x6f0f, 0x7d2f,
1667 0x7e37, 0x964b, 0x52d2, 0x808b, 0x51dc, 0x51cc, 0x7a1c, 0x7dbe,
1668 0x83f1, 0x9675, 0x8b80, 0x62cf, 0x6a02, 0x8afe, 0x4e39, 0x5be7,
1669 0x6012, 0x7387, 0x7570, 0x5317, 0x78fb, 0x4fbf, 0x5fa9, 0x4e0d,
1670 0x6ccc, 0x6578, 0x7d22, 0x53c3, 0x585e, 0x7701, 0x8449, 0x8aaa,
1671 0x6bba, 0x8fb0, 0x6c88, 0x62fe, 0x82e5, 0x63a0, 0x7565, 0x4eae,
1672 0x5169, 0x0000, 0x6881, 0x7ce7, 0x826f, 0x8ad2, 0x91cf, 0x52f5,
1673 0x5442, 0x5973, 0x5eec, 0x65c5, 0x6ffe, 0x792a, 0x95ad, 0x9a6a,
1674 0x9e97, 0x9ece, 0x529b, 0x66c6, 0x6b77, 0x8f62, 0x5e74, 0x6190,
1675 0x6200, 0x649a, 0x6f23, 0x7149, 0x7489, 0x0000, 0x7df4, 0x806f,
1676 0x8f26, 0x84ee, 0x9023, 0x934a, 0x5217, 0x52a3, 0x54bd, 0x70c8,
1677 0x88c2, 0x8aaa, 0x5ec9, 0x5ff5, 0x637b, 0x6bae, 0x7c3e, 0x7375,
1678 0x4ee4, 0x56f9, 0x5be7, 0x5dba, 0x601c, 0x73b2, 0x7469, 0x7f9a,
1679 0x8046, 0x9234, 0x96f6, 0x9748, 0x9818, 0x4f8b, 0x79ae, 0x91b4,
1680 0x96b8, 0x60e1, 0x4e86, 0x50da, 0x5bee, 0x5c3f, 0x6599, 0x6a02,
1681 0x71ce, 0x7642, 0x84fc, 0x907c, 0x9f8d, 0x6688, 0x962e, 0x5289,
1682 0x677b, 0x67f3, 0x6d41, 0x6e9c, 0x7409, 0x7559, 0x786b, 0x7d10,
1683 0x985e, 0x516d, 0x622e, 0x9678, 0x502b, 0x5d19, 0x6dea, 0x8f2a,
1684 0x5f8b, 0x6144, 0x6817, 0x7387, 0x9686, 0x5229, 0x540f, 0x5c65,
1685 0x6613, 0x674e, 0x68a8, 0x6ce5, 0x7406, 0x75e2, 0x7f79, 0x0000,
1686 0x88e1, 0x91cc, 0x96e2, 0x533f, 0x6eba, 0x541d, 0x71d0, 0x7498,
1687 0x85fa, 0x0000, 0x9c57, 0x9e9f, 0x6797, 0x6dcb, 0x81e8, 0x7acb,
1688 0x7b20, 0x7c92, 0x72c0, 0x7099, 0x8b58, 0x4ec0, 0x8336, 0x523a,
1689 0x5207, 0x5ea6, 0x62d3, 0x7cd6, 0x5b85, 0x6d1e, 0x66b4, 0x8f3b,
1690 0x884c, 0x964d, 0x898b, 0x5ed3, 0x0000, 0x0000, 0x0000, 0x0000,
1691 0x585a, 0x0000, 0x6674, 0x0000, 0x0000, 0x51de, 0x8c6c, 0x76ca,
1692 0x0000, 0x795e, 0x7965, 0x798f, 0x9756, 0x7cbe, 0x7fbd, 0x0000,
1693 0x0000, 0x0000, 0x8af8, 0x0000, 0x0000, 0x9038, 0x90fd, 0x0000,
1694 0x0000, 0x0000, 0x98ef, 0x98fc, 0x9928, 0x9db4, 0x0000, 0x0000
1696 static const WCHAR compat_FE30_FEF7[200] =
1698 0x2025, 0x2014, 0x2013, 0x005f, 0x005f, 0x0028, 0x0029, 0x007b,
1699 0x007d, 0x3014, 0x3015, 0x3010, 0x3011, 0x300a, 0x300b, 0x3008,
1700 0x3009, 0x300c, 0x300d, 0x300e, 0x300f, 0x0000, 0x0000, 0x0000,
1701 0x0000, 0x203e, 0x203e, 0x203e, 0x203e, 0x005f, 0x005f, 0x005f,
1702 0x002c, 0x3001, 0x002e, 0x0000, 0x003b, 0x003a, 0x003f, 0x0021,
1703 0x2014, 0x0028, 0x0029, 0x007b, 0x007d, 0x3014, 0x3015, 0x0023,
1704 0x0026, 0x002a, 0x002b, 0x002d, 0x003c, 0x003e, 0x003d, 0x0000,
1705 0x0000, 0x0024, 0x0025, 0x0040, 0x0000, 0x0000, 0x0000, 0x0000,
1706 0x064b, 0x064b, 0x064c, 0x0000, 0x064d, 0x0000, 0x064e, 0x064e,
1707 0x064f, 0x064f, 0x0650, 0x0650, 0x0651, 0x0651, 0x0652, 0x0652,
1708 0x0621, 0x0622, 0x0622, 0x0623, 0x0623, 0x0624, 0x0624, 0x0625,
1709 0x0625, 0x0626, 0x0626, 0x0626, 0x0626, 0x0627, 0x0627, 0x0628,
1710 0x0628, 0x0628, 0x0628, 0x0629, 0x0629, 0x062a, 0x062a, 0x062a,
1711 0x062a, 0x062b, 0x062b, 0x062b, 0x062b, 0x062c, 0x062c, 0x062c,
1712 0x062c, 0x062d, 0x062d, 0x062d, 0x062d, 0x062e, 0x062e, 0x062e,
1713 0x062e, 0x062f, 0x062f, 0x0630, 0x0630, 0x0631, 0x0631, 0x0632,
1714 0x0632, 0x0633, 0x0633, 0x0633, 0x0633, 0x0634, 0x0634, 0x0634,
1715 0x0634, 0x0635, 0x0635, 0x0635, 0x0635, 0x0636, 0x0636, 0x0636,
1716 0x0636, 0x0637, 0x0637, 0x0637, 0x0637, 0x0638, 0x0638, 0x0638,
1717 0x0638, 0x0639, 0x0639, 0x0639, 0x0639, 0x063a, 0x063a, 0x063a,
1718 0x063a, 0x0641, 0x0641, 0x0641, 0x0641, 0x0642, 0x0642, 0x0642,
1719 0x0642, 0x0643, 0x0643, 0x0643, 0x0643, 0x0644, 0x0644, 0x0644,
1720 0x0644, 0x0645, 0x0645, 0x0645, 0x0645, 0x0646, 0x0646, 0x0646,
1721 0x0646, 0x0647, 0x0647, 0x0647, 0x0647, 0x0648, 0x0648, 0x0649,
1722 0x0649, 0x064a, 0x064a, 0x064a, 0x064a, 0x0000, 0x0000, 0x0000
1724 static const WCHAR compat_FF00_FFEF[240] =
1726 0x0000, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
1727 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
1728 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
1729 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
1730 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
1731 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
1732 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
1733 0x0058, 0x0059, 0x005a, 0x005b, 0x0000, 0x005d, 0x005e, 0x005f,
1734 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
1735 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
1736 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
1737 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000,
1738 0x0000, 0x3002, 0x300c, 0x300d, 0x3001, 0x30fb, 0x30f2, 0x30a1,
1739 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, 0x30c3,
1740 0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, 0x30ab, 0x30ad,
1741 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, 0x30b9, 0x30bb, 0x30bd,
1742 0x30bf, 0x30c1, 0x30c4, 0x30c6, 0x30c8, 0x30ca, 0x30cb, 0x30cc,
1743 0x30cd, 0x30ce, 0x30cf, 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de,
1744 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9,
1745 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c,
1746 0x3164, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137,
1747 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f,
1748 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147,
1749 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x0000,
1750 0x0000, 0x0000, 0x314f, 0x3150, 0x3151, 0x3152, 0x3153, 0x3154,
1751 0x0000, 0x0000, 0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315a,
1752 0x0000, 0x0000, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, 0x3160,
1753 0x0000, 0x0000, 0x3161, 0x3162, 0x3163, 0x0000, 0x0000, 0x0000,
1754 0x00a2, 0x00a3, 0x00ac, 0x00af, 0x00a6, 0x00a5, 0x20a9, 0x0000,
1755 0x2502, 0x2190, 0x2191, 0x2192, 0x2193, 0x25a0, 0x25cb, 0x0000
1757 static const WCHAR ligatures_src[] =
1759 0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
1760 0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
1761 0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
1762 0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
1763 0xfb04, 0xfb05, 0xfb06, '\0'
1765 static const WCHAR ligatures_dst[] =
1767 'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
1768 'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
1769 'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
1770 0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
1771 'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
1775 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1777 /* Invalid flag combinations */
1778 for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
1780 src[0] = dst[0] = '\0';
1782 ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
1783 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1785 EXPECT_LEN(0); EXPECT_FLAGS;
1788 /* src & dst cannot be the same */
1790 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
1791 EXPECT_LEN(0); EXPECT_INVALID;
1793 /* src can't be NULL */
1795 ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
1796 EXPECT_LEN(0); EXPECT_INVALID;
1798 /* srclen can't be 0 */
1800 ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
1801 EXPECT_LEN(0); EXPECT_INVALID;
1803 /* dstlen can't be < 0 */
1805 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
1806 EXPECT_LEN(0); EXPECT_INVALID;
1808 /* Ret includes terminating NUL which is appended if srclen = -1 */
1813 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
1814 EXPECT_LEN(2); EXPECT_VALID;
1815 ok(dst[0] == 'A' && dst[1] == '\0',
1816 "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%d\n",
1817 'A', '\0', ret, dst[0], dst[1], GetLastError());
1819 /* If size is given, result is not NUL terminated */
1825 ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
1826 EXPECT_LEN(1); EXPECT_VALID;
1827 ok(dst[0] == 'A' && dst[1] == 'X',
1828 "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%d\n",
1829 'A','X', ret, dst[0], dst[1], GetLastError());
1831 /* MAP_FOLDDIGITS */
1832 for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
1834 /* Check everything before this range */
1835 for (ch = prev_ch; ch < digitRanges[j]; ch++)
1839 src[1] = dst[0] = '\0';
1840 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
1841 EXPECT_LEN(2); EXPECT_VALID;
1843 ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
1844 /* Wine (correctly) maps all Unicode 4.0+ digits */
1845 isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF ||
1846 (ch >= 0x1369 && ch <= 0x1371),
1847 "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
1850 if (digitRanges[j] == 0xffff)
1851 break; /* Finished the whole code point space */
1853 for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
1857 /* Map out of sequence characters */
1858 if (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
1859 else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
1860 else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
1861 else if (ch == 0x245F) c = 0x24EA; /* Circled 0 */
1865 src[1] = dst[0] = '\0';
1866 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
1867 EXPECT_LEN(2); EXPECT_VALID;
1869 ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
1870 strchrW(noDigitAvailable, c),
1871 "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
1872 ch, '0' + digitRanges[j] - ch, dst[0]);
1878 for (ch = 1; ch <0xffff; ch++)
1882 if (ch >= 0xF900 && ch <= 0xFA2F)
1883 expected = compat_F900_FA2F[ch - 0xF900];
1884 else if (ch >= 0xFE30 && ch <= 0xFEF7)
1885 expected = compat_FE30_FEF7[ch - 0xFE30];
1886 else if (ch >= 0xFF00 && ch <= 0xFFEF)
1887 expected = compat_FF00_FFEF[ch - 0xFF00];
1894 src[1] = dst[0] = '\0';
1895 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
1896 EXPECT_LEN(2); EXPECT_VALID;
1897 ok(dst[0] == expected ||
1898 /* Wine (correctly) uses updated mappings for some Unicode 4.0 chars */
1899 /* FIXME: But they should be re-checked */
1900 ch == 0xf92c || ch == 0xf979 || ch == 0xf995 || ch == 0xf9e7 ||
1902 (0xfa0c <= ch && ch <= 0xfa6a) ||
1903 (0xfa70 <= ch && ch <= 0xfad9) ||
1904 ch == 0xfe47 || ch == 0xfe48 || ch == 0xfe68 ||
1905 (0xfe70 <= ch && ch <= 0xfe7f) ||
1906 ch == 0xff3c || ch == 0xff5f || ch == 0xff60 ||
1907 ch == 0xff9e || ch == 0xff9f,
1908 "MAP_FOLDCZONE: ch %d 0x%04x Expected 0x%04x got 0x%04x\n",
1909 ch, ch, expected, dst[0]);
1912 /* MAP_EXPAND_LIGATURES */
1914 ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1915 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1916 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1917 EXPECT_LEN(sizeof(ligatures_dst)/sizeof(ligatures_dst[0])); EXPECT_VALID;
1918 ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
1919 "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
1920 for (i = 1; i <= 0xffff; i++)
1922 if (!strchrW(ligatures_src, i))
1927 ret = pFoldStringW(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1928 EXPECT_LEN(2); EXPECT_VALID;
1929 ok(dst[0] == src[0],
1930 "MAP_EXPAND_LIGATURES: 0x%02x : Expected 0x%02x, got 0x%02x\n",
1936 /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
1941 #define LCID_OK(l) \
1942 ok(lcid == l, "Expected lcid = %08x, got %08x\n", l, lcid)
1943 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
1944 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
1945 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
1946 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
1948 static void test_ConvertDefaultLocale(void)
1952 /* Doesn't change lcid, even if non default sublang/sort used */
1953 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_US, SORT_DEFAULT);
1954 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_UK, SORT_DEFAULT);
1955 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT);
1956 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE);
1958 /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
1959 LCID_RES(MKLCID(LANG_ENGLISH, SUBLANG_NEUTRAL, SORT_DEFAULT),
1960 MKLCID(LANG_ENGLISH, SUBLANG_DEFAULT, SORT_DEFAULT));
1961 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
1962 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
1963 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_JAPANESE_UNICODE),
1964 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE));
1966 /* Invariant language is not treated specially */
1967 TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
1968 LCID_RES(MKLCID(LANG_INVARIANT, SUBLANG_NEUTRAL, SORT_DEFAULT),
1969 MKLCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT));
1971 /* User/system default languages alone are not mapped */
1972 TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
1973 TEST_LCIDLANG(LANG_USER_DEFAULT, SORT_JAPANESE_UNICODE);
1976 LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
1977 LCID_RES(LOCALE_USER_DEFAULT, GetUserDefaultLCID());
1978 LCID_RES(LOCALE_NEUTRAL, GetUserDefaultLCID());
1981 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
1982 DWORD dwFlags, LONG_PTR lParam)
1984 trace("%08x, %s, %s, %08x, %08lx\n",
1985 lgrpid, lpszNum, lpszName, dwFlags, lParam);
1987 ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
1988 "Enumerated grp %d not valid (flags %d)\n", lgrpid, dwFlags);
1990 /* If lParam is one, we are calling with flags defaulted from 0 */
1991 ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
1992 "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %d\n", dwFlags);
1997 static void test_EnumSystemLanguageGroupsA(void)
1999 if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
2002 /* No enumeration proc */
2004 pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
2009 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
2012 /* No flags - defaults to LGRPID_INSTALLED */
2014 pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
2017 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
2018 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
2022 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
2025 trace("%08x, %08x, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
2027 ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
2028 "Enumerated grp %d not valid\n", lgrpid);
2029 ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
2030 "Enumerated grp locale %d not valid\n", lcid);
2034 static void test_EnumLanguageGroupLocalesA(void)
2036 if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
2039 /* No enumeration proc */
2041 pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
2044 /* lgrpid too small */
2046 pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
2049 /* lgrpid too big */
2051 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
2054 /* dwFlags is reserved */
2056 pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
2059 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2062 static void test_SetLocaleInfoA(void)
2065 LCID lcid = GetUserDefaultLCID();
2069 bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2074 bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
2079 bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
2083 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2085 trace("%s %08lx\n", value, lParam);
2089 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2091 ok(!enumCount, "callback called again unexpected\n");
2096 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2098 ok(0,"callback called unexpected\n");
2102 static void test_EnumUILanguageA(void)
2105 if (!pEnumUILanguagesA) {
2106 trace("EnumUILanguagesA is not available on Win9x\n");
2110 SetLastError(ERROR_SUCCESS);
2111 ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2112 EXPECT_TRUE; EXPECT_VALID;
2115 SetLastError(ERROR_SUCCESS);
2116 ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2117 EXPECT_TRUE; EXPECT_VALID;
2119 SetLastError(ERROR_SUCCESS);
2120 ret = pEnumUILanguagesA(NULL, 0, 0);
2121 EXPECT_FALSE; EXPECT_INVALID;
2123 SetLastError(ERROR_SUCCESS);
2124 ret = pEnumUILanguagesA(luilocale_proc3A, 0x5a5a5a5a, 0);
2125 EXPECT_FALSE; EXPECT_FLAGS;
2127 SetLastError(ERROR_SUCCESS);
2128 ret = pEnumUILanguagesA(NULL, 0x5a5a5a5a, 0);
2129 EXPECT_FALSE; EXPECT_INVALID;
2132 static char date_fmt_buf[1024];
2134 static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
2136 lstrcatA(date_fmt_buf, fmt);
2137 lstrcatA(date_fmt_buf, "\n");
2141 static void test_EnumDateFormatsA(void)
2145 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2147 trace("EnumDateFormatsA 0\n");
2148 date_fmt_buf[0] = 0;
2149 ret = EnumDateFormatsA(enum_datetime_procA, lcid, 0);
2150 ok(ret, "EnumDateFormatsA(0) error %d\n", GetLastError());
2151 trace("%s\n", date_fmt_buf);
2152 /* test the 1st enumerated format */
2153 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2154 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2155 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2156 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2158 trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n");
2159 date_fmt_buf[0] = 0;
2160 ret = EnumDateFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2161 ok(ret, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2162 trace("%s\n", date_fmt_buf);
2163 /* test the 1st enumerated format */
2164 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2165 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2166 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2167 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2169 trace("EnumDateFormatsA DATE_SHORTDATE\n");
2170 date_fmt_buf[0] = 0;
2171 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_SHORTDATE);
2172 ok(ret, "EnumDateFormatsA(DATE_SHORTDATE) error %d\n", GetLastError());
2173 trace("%s\n", date_fmt_buf);
2174 /* test the 1st enumerated format */
2175 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2176 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2177 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2178 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2180 trace("EnumDateFormatsA DATE_LONGDATE\n");
2181 date_fmt_buf[0] = 0;
2182 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_LONGDATE);
2183 ok(ret, "EnumDateFormatsA(DATE_LONGDATE) error %d\n", GetLastError());
2184 trace("%s\n", date_fmt_buf);
2185 /* test the 1st enumerated format */
2186 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2187 ret = GetLocaleInfoA(lcid, LOCALE_SLONGDATE, buf, sizeof(buf));
2188 ok(ret, "GetLocaleInfoA(LOCALE_SLONGDATE) error %d\n", GetLastError());
2189 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2191 trace("EnumDateFormatsA DATE_YEARMONTH\n");
2192 date_fmt_buf[0] = 0;
2193 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_YEARMONTH);
2194 ok(ret, "EnumDateFormatsA(DATE_YEARMONTH) error %d\n", GetLastError());
2195 trace("%s\n", date_fmt_buf);
2196 /* test the 1st enumerated format */
2197 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2198 ret = GetLocaleInfoA(lcid, LOCALE_SYEARMONTH, buf, sizeof(buf));
2199 ok(ret, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %d\n", GetLastError());
2200 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2203 static void test_EnumTimeFormatsA(void)
2207 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2209 trace("EnumTimeFormatsA 0\n");
2210 date_fmt_buf[0] = 0;
2211 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, 0);
2212 ok(ret, "EnumTimeFormatsA(0) error %d\n", GetLastError());
2213 trace("%s\n", date_fmt_buf);
2214 /* test the 1st enumerated format */
2215 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2216 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2217 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2218 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2220 trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n");
2221 date_fmt_buf[0] = 0;
2222 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2223 ok(ret, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2224 trace("%s\n", date_fmt_buf);
2225 /* test the 1st enumerated format */
2226 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2227 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2228 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2229 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2234 InitFunctionPointers();
2236 test_EnumTimeFormatsA();
2237 test_EnumDateFormatsA();
2239 test_GetLocaleInfoA();
2240 test_GetTimeFormatA();
2241 test_GetDateFormatA();
2242 test_GetDateFormatW();
2243 test_GetCurrencyFormatA(); /* Also tests the W version */
2244 test_GetNumberFormatA(); /* Also tests the W version */
2245 test_CompareStringA();
2246 test_LCMapStringA();
2247 test_LCMapStringW();
2250 test_ConvertDefaultLocale();
2251 test_EnumSystemLanguageGroupsA();
2252 test_EnumLanguageGroupLocalesA();
2253 test_SetLocaleInfoA();
2254 test_EnumUILanguageA();
2256 /* this requires collation table patch to make it MS compatible */
2257 if (0) test_sorting();