2 * Unit tests for locale functions
4 * Copyright 2002 YASAR Mehmet
5 * Copyright 2003 Dmitry Timoshkov
6 * Copyright 2003 Jon Griffiths
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 * We must pass LOCALE_NOUSEROVERRIDE (NUO) to formatting functions so that
24 * even when the user has overridden their default i8n settings (e.g. in
25 * the control panel i8n page), we will still get the expected results.
32 #include "wine/test.h"
38 static inline unsigned int strlenW( const WCHAR *str )
45 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
48 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
52 static inline WCHAR *strchrW( const WCHAR *str, WCHAR ch )
54 do { if (*str == ch) return (WCHAR *)str; } while (*str++);
58 static inline int isdigitW( WCHAR wc )
61 GetStringTypeW( CT_CTYPE1, &wc, 1, &type );
62 return type & C1_DIGIT;
65 /* Some functions are only in later versions of kernel32.dll */
66 static HMODULE hKernel32;
67 static WORD enumCount;
69 typedef BOOL (WINAPI *EnumSystemLanguageGroupsAFn)(LANGUAGEGROUP_ENUMPROC,
71 static EnumSystemLanguageGroupsAFn pEnumSystemLanguageGroupsA;
72 typedef BOOL (WINAPI *EnumLanguageGroupLocalesAFn)(LANGGROUPLOCALE_ENUMPROC,
73 LGRPID, DWORD, LONG_PTR);
74 static EnumLanguageGroupLocalesAFn pEnumLanguageGroupLocalesA;
75 typedef BOOL (WINAPI *EnumUILanguagesAFn)(UILANGUAGE_ENUMPROC,
77 static EnumUILanguagesAFn pEnumUILanguagesA;
79 typedef INT (WINAPI *FoldStringAFn)(DWORD, LPCSTR, INT, LPSTR, INT);
80 static FoldStringAFn pFoldStringA;
81 typedef INT (WINAPI *FoldStringWFn)(DWORD, LPCWSTR, INT, LPWSTR, INT);
82 static FoldStringWFn pFoldStringW;
84 typedef BOOL (WINAPI *IsValidLanguageGroupFn)(LGRPID, DWORD);
85 static IsValidLanguageGroupFn pIsValidLanguageGroup;
87 static void InitFunctionPointers(void)
89 hKernel32 = GetModuleHandleA("kernel32");
90 pEnumSystemLanguageGroupsA = (void*)GetProcAddress(hKernel32, "EnumSystemLanguageGroupsA");
91 pEnumLanguageGroupLocalesA = (void*)GetProcAddress(hKernel32, "EnumLanguageGroupLocalesA");
92 pFoldStringA = (void*)GetProcAddress(hKernel32, "FoldStringA");
93 pFoldStringW = (void*)GetProcAddress(hKernel32, "FoldStringW");
94 pIsValidLanguageGroup = (void*)GetProcAddress(hKernel32, "IsValidLanguageGroup");
95 pEnumUILanguagesA = (void*)GetProcAddress(hKernel32, "EnumUILanguagesA");
98 #define eq(received, expected, label, type) \
99 ok((received) == (expected), "%s: got " type " instead of " type "\n", \
100 (label), (received), (expected))
102 #define BUFFER_SIZE 128
103 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
105 #define EXPECT_LEN(len) ok(ret == (len), "Expected Len %d, got %d\n", (int)(len), ret)
106 #define EXPECT_INVALID ok(GetLastError() == ERROR_INVALID_PARAMETER, \
107 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError())
108 #define EXPECT_BUFFER ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, \
109 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError())
110 #define EXPECT_FLAGS ok(GetLastError() == ERROR_INVALID_FLAGS, \
111 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError())
112 #define EXPECT_INVALIDFLAGS ok(GetLastError() == ERROR_INVALID_FLAGS || \
113 GetLastError() == ERROR_INVALID_PARAMETER, \
114 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError())
115 #define EXPECT_LASTERROR_0 ok(GetLastError() == 0, \
116 "Expected GetLastError() == 0, got %d\n", GetLastError())
117 #define EXPECT_VALID ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError())
119 #define STRINGSA(x,y) strcpy(input, x); strcpy(Expected, y); SetLastError(0); buffer[0] = '\0'
120 #define EXPECT_LENA EXPECT_LEN((int)strlen(Expected)+1)
121 #define EXPECT_EQA ok(strncmp(buffer, Expected, strlen(Expected)) == 0, \
122 "Expected '%s', got '%s'\n", Expected, buffer)
124 #define STRINGSW(x,y) MultiByteToWideChar(CP_ACP,0,x,-1,input,COUNTOF(input)); \
125 MultiByteToWideChar(CP_ACP,0,y,-1,Expected,COUNTOF(Expected)); \
126 SetLastError(0); buffer[0] = '\0'
127 #define EXPECT_LENW EXPECT_LEN((int)strlenW(Expected)+1)
128 #define EXPECT_EQW ok(strncmpW(buffer, Expected, strlenW(Expected)) == 0, "Bad conversion\n")
129 #define EXPECT_FALSE ok(FALSE == ret, "Expected return value FALSE, got TRUE\n")
130 #define EXPECT_TRUE ok(FALSE != ret, "Expected return value TRUE, got FALSE\n")
132 #define NUO LOCALE_NOUSEROVERRIDE
134 static void test_GetLocaleInfoA(void)
137 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
138 char buffer[BUFFER_SIZE];
140 ok(lcid == 0x409, "wrong LCID calculated - %d\n", lcid);
142 /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
143 * partially fill the buffer even if it is too short. See bug 637.
145 SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
146 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 0);
147 ok(ret == 7 && !buffer[0], "Expected len=7, got %d\n", ret);
149 SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
150 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 3);
151 EXPECT_BUFFER; EXPECT_LEN(0);
152 ok(!strcmp(buffer, "Mon"), "Expected 'Mon', got '%s'\n", buffer);
154 SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
155 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 10);
156 EXPECT_VALID; EXPECT_LEN(7);
157 ok(!strcmp(buffer, "Monday"), "Expected 'Monday', got '%s'\n", buffer);
160 static void test_GetTimeFormatA(void)
164 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
165 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
167 memset(&curtime, 2, sizeof(SYSTEMTIME));
168 STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
169 SetLastError(0xdeadbeef);
170 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
171 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
174 curtime.wMinute = 56;
175 curtime.wSecond = 13;
176 curtime.wMilliseconds = 22;
177 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
178 SetLastError(0xdeadbeef);
179 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
180 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
182 /* MSDN: LOCALE_NOUSEROVERRIDE can't be specified with a format string */
183 SetLastError(0xdeadbeef);
184 ret = GetTimeFormatA(lcid, NUO|TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
185 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
187 STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficent buffer */
188 SetLastError(0xdeadbeef);
189 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, 2);
190 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
192 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
193 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, NULL, 0);
194 EXPECT_VALID; EXPECT_LENA;
196 STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
197 ret = GetTimeFormatA(lcid, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
198 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
200 STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
201 ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
202 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
204 STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
205 ret = GetTimeFormatA(lcid, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
206 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
208 STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
209 strcpy(Expected, "8:56 AM");
210 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
211 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
213 STRINGSA("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
214 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
215 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
217 STRINGSA("s1s2s3", ""); /* Duplicate tokens */
218 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
219 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
221 STRINGSA("t/tt", "A/AM"); /* AM time marker */
222 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
223 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
226 STRINGSA("t/tt", "P/PM"); /* PM time marker */
227 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
228 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
230 STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
231 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
232 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
234 STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
235 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
236 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
238 STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
239 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
240 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
242 curtime.wHour = 14; /* change this to 14 or 2pm */
245 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 */
246 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
247 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
250 STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
251 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
252 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
254 STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
255 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
256 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
258 /* try to convert formatting strings with more than two letters
259 * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
260 * NOTE: We expect any letter for which there is an upper case value
261 * we should see a replacement. For letters that DO NOT have
262 * upper case values we should see NO REPLACEMENT.
265 curtime.wMinute = 56;
266 curtime.wSecond = 13;
267 curtime.wMilliseconds = 22;
268 STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
269 "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
270 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
271 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
273 STRINGSA("h", "text"); /* Don't write to buffer if len is 0 */
274 strcpy(buffer, "text");
275 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, 0);
276 EXPECT_VALID; EXPECT_LEN(2); EXPECT_EQA;
278 STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
279 "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
280 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
281 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
283 STRINGSA("'''", "'"); /* invalid quoted string */
284 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
285 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
287 /* test that msdn suggested single quotation usage works as expected */
288 STRINGSA("''''", "'"); /* single quote mark */
289 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
290 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
292 STRINGSA("''HHHHHH", "08"); /* Normal use */
293 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
294 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
296 /* and test for normal use of the single quotation mark */
297 STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
298 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
299 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
301 STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
302 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
303 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
305 STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
306 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
307 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
310 STRINGSA("'123'tt", ""); /* Invalid time */
311 SetLastError(0xdeadbeef);
312 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
313 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
316 curtime.wMonth = 60; /* Invalid */
317 STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
318 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
319 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
322 static void test_GetDateFormatA(void)
326 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
327 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
329 memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
330 STRINGSA("ddd',' MMM dd yy","");
331 SetLastError(0xdeadbeef);
332 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
333 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
335 curtime.wYear = 2002;
338 curtime.wDayOfWeek = 3;
339 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
340 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
341 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
343 /* Same as above but with LOCALE_NOUSEROVERRIDE */
344 STRINGSA("ddd',' MMM dd yy",""); /* Simple case */
345 SetLastError(0xdeadbeef);
346 ret = GetDateFormatA(lcid, NUO, &curtime, input, buffer, COUNTOF(buffer));
347 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
349 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
350 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
351 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
353 curtime.wHour = 36; /* Invalid */
354 STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
355 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
356 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
358 STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
359 ret = GetDateFormatA(lcid, 0, &curtime, input, NULL, 0);
360 EXPECT_VALID; EXPECT_LEN(16); EXPECT_EQA;
362 STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
363 SetLastError(0xdeadbeef);
364 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, 2);
365 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
367 STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
368 ret = GetDateFormat(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
369 EXPECT_VALID; EXPECT_LENA;
370 if (strncmp(buffer, Expected, strlen(Expected)) && strncmp(buffer, "5/4/02", strlen(Expected)) != 0)
371 ok (0, "Expected '%s' or '5/4/02', got '%s'\n", Expected, buffer);
373 STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
374 ret = GetDateFormat(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
375 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
377 /* test for expected DATE_YEARMONTH behavior with null format */
378 /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
379 STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
380 SetLastError(0xdeadbeef);
381 ret = GetDateFormat(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
382 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
384 /* Test that using invalid DATE_* flags results in the correct error */
385 /* and return values */
386 STRINGSA("m/d/y", ""); /* Invalid flags */
387 SetLastError(0xdeadbeef);
388 ret = GetDateFormat(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
389 &curtime, input, buffer, COUNTOF(buffer));
390 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
393 static void test_GetDateFormatW(void)
397 WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
398 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
400 STRINGSW("",""); /* If flags is not zero then format must be NULL */
401 ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL,
402 input, buffer, COUNTOF(buffer));
403 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
405 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQW;
407 STRINGSW("",""); /* NULL buffer, len > 0 */
408 SetLastError(0xdeadbeef);
409 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
410 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQW;
412 STRINGSW("",""); /* NULL buffer, len == 0 */
413 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
414 EXPECT_VALID; EXPECT_LENW; EXPECT_EQW;
416 curtime.wYear = 2002;
419 curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
420 curtime.wHour = 65432; /* Invalid */
421 curtime.wMinute = 34512; /* Invalid */
422 curtime.wSecond = 65535; /* Invalid */
423 curtime.wMilliseconds = 12345;
424 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
425 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
426 EXPECT_VALID; EXPECT_LENW; EXPECT_EQW;
430 #define CY_POS_LEFT 0
431 #define CY_POS_RIGHT 1
432 #define CY_POS_LEFT_SPACE 2
433 #define CY_POS_RIGHT_SPACE 3
435 static void test_GetCurrencyFormatA(void)
437 static char szDot[] = { '.', '\0' };
438 static char szComma[] = { ',', '\0' };
439 static char szDollar[] = { '$', '\0' };
441 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
442 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
445 memset(&format, 0, sizeof(format));
447 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
448 SetLastError(0xdeadbeef);
449 ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
450 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
452 STRINGSA("23,53",""); /* Invalid character --> Error */
453 SetLastError(0xdeadbeef);
454 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
455 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
457 STRINGSA("--",""); /* Double '-' --> Error */
458 SetLastError(0xdeadbeef);
459 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
460 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
462 STRINGSA("0-",""); /* Trailing '-' --> Error */
463 SetLastError(0xdeadbeef);
464 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
465 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
467 STRINGSA("0..",""); /* Double '.' --> Error */
468 SetLastError(0xdeadbeef);
469 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
470 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
472 STRINGSA(" 0.1",""); /* Leading space --> Error */
473 SetLastError(0xdeadbeef);
474 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
475 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
477 STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
478 SetLastError(0xdeadbeef);
479 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, 2);
480 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
482 STRINGSA("2353",""); /* Format and flags given --> Error */
483 SetLastError(0xdeadbeef);
484 ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
485 EXPECT_INVALIDFLAGS; EXPECT_LEN(0); EXPECT_EQA;
487 STRINGSA("2353",""); /* Invalid format --> Error */
488 SetLastError(0xdeadbeef);
489 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
490 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
492 STRINGSA("2353","$2,353.00"); /* Valid number */
493 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
494 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
496 STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
497 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
498 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
500 STRINGSA("2353.1","$2,353.10"); /* Valid real number */
501 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
502 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
504 STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
505 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
506 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
508 STRINGSA("2353.119","$2,353.12"); /* Too many DP --> Rounded */
509 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
510 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
512 format.NumDigits = 0; /* No decimal separator */
513 format.LeadingZero = 0;
514 format.Grouping = 0; /* No grouping char */
515 format.NegativeOrder = 0;
516 format.PositiveOrder = CY_POS_LEFT;
517 format.lpDecimalSep = szDot;
518 format.lpThousandSep = szComma;
519 format.lpCurrencySymbol = szDollar;
521 STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
522 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
523 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
525 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
526 STRINGSA("2353","$2353.0");
527 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
528 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
530 format.Grouping = 2; /* Group by 100's */
531 STRINGSA("2353","$23,53.0");
532 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
533 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
535 format.LeadingZero = 1; /* Always provide leading zero */
536 STRINGSA(".5","$0.5");
537 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
538 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
540 format.PositiveOrder = CY_POS_RIGHT;
541 STRINGSA("1","1.0$");
542 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
543 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
545 format.PositiveOrder = CY_POS_LEFT_SPACE;
546 STRINGSA("1","$ 1.0");
547 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
548 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
550 format.PositiveOrder = CY_POS_RIGHT_SPACE;
551 STRINGSA("1","1.0 $");
552 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
553 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
555 format.NegativeOrder = 0;
556 STRINGSA("-1","($1.0)");
557 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
558 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
560 format.NegativeOrder = 1;
561 STRINGSA("-1","-$1.0");
562 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
563 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
565 format.NegativeOrder = 2;
566 STRINGSA("-1","$-1.0");
567 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
568 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
570 format.NegativeOrder = 3;
571 STRINGSA("-1","$1.0-");
572 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
573 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
575 format.NegativeOrder = 4;
576 STRINGSA("-1","(1.0$)");
577 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
578 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
580 format.NegativeOrder = 5;
581 STRINGSA("-1","-1.0$");
582 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
583 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
585 format.NegativeOrder = 6;
586 STRINGSA("-1","1.0-$");
587 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
588 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
590 format.NegativeOrder = 7;
591 STRINGSA("-1","1.0$-");
592 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
593 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
595 format.NegativeOrder = 8;
596 STRINGSA("-1","-1.0 $");
597 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
598 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
600 format.NegativeOrder = 9;
601 STRINGSA("-1","-$ 1.0");
602 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
603 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
605 format.NegativeOrder = 10;
606 STRINGSA("-1","1.0 $-");
607 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
608 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
610 format.NegativeOrder = 11;
611 STRINGSA("-1","$ 1.0-");
612 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
613 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
615 format.NegativeOrder = 12;
616 STRINGSA("-1","$ -1.0");
617 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
618 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
620 format.NegativeOrder = 13;
621 STRINGSA("-1","1.0- $");
622 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
623 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
625 format.NegativeOrder = 14;
626 STRINGSA("-1","($ 1.0)");
627 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
628 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
630 format.NegativeOrder = 15;
631 STRINGSA("-1","(1.0 $)");
632 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
633 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
636 #define NEG_PARENS 0 /* "(1.1)" */
637 #define NEG_LEFT 1 /* "-1.1" */
638 #define NEG_LEFT_SPACE 2 /* "- 1.1" */
639 #define NEG_RIGHT 3 /* "1.1-" */
640 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
642 static void test_GetNumberFormatA(void)
644 static char szDot[] = { '.', '\0' };
645 static char szComma[] = { ',', '\0' };
647 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
648 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
651 memset(&format, 0, sizeof(format));
653 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
654 SetLastError(0xdeadbeef);
655 ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
656 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
658 STRINGSA("23,53",""); /* Invalid character --> Error */
659 SetLastError(0xdeadbeef);
660 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
661 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
663 STRINGSA("--",""); /* Double '-' --> Error */
664 SetLastError(0xdeadbeef);
665 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
666 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
668 STRINGSA("0-",""); /* Trailing '-' --> Error */
669 SetLastError(0xdeadbeef);
670 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
671 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
673 STRINGSA("0..",""); /* Double '.' --> Error */
674 SetLastError(0xdeadbeef);
675 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
676 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
678 STRINGSA(" 0.1",""); /* Leading space --> Error */
679 SetLastError(0xdeadbeef);
680 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
681 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
683 STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
684 SetLastError(0xdeadbeef);
685 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, 2);
686 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
688 STRINGSA("2353",""); /* Format and flags given --> Error */
689 SetLastError(0xdeadbeef);
690 ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
691 EXPECT_INVALIDFLAGS; EXPECT_LEN(0); EXPECT_EQA;
693 STRINGSA("2353",""); /* Invalid format --> Error */
694 SetLastError(0xdeadbeef);
695 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
696 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
698 STRINGSA("2353","2,353.00"); /* Valid number */
699 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
700 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
702 STRINGSA("-2353","-2,353.00"); /* Valid negative number */
703 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
704 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
706 STRINGSA("-353","-353.00"); /* test for off by one error in grouping */
707 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
708 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
710 STRINGSA("2353.1","2,353.10"); /* Valid real number */
711 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
712 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
714 STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
715 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
716 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
718 STRINGSA("2353.119","2,353.12"); /* Too many DP --> Rounded */
719 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
720 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
722 format.NumDigits = 0; /* No decimal separator */
723 format.LeadingZero = 0;
724 format.Grouping = 0; /* No grouping char */
725 format.NegativeOrder = 0;
726 format.lpDecimalSep = szDot;
727 format.lpThousandSep = szComma;
729 STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
730 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
731 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
733 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
734 STRINGSA("2353","2353.0");
735 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
736 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
738 format.Grouping = 2; /* Group by 100's */
739 STRINGSA("2353","23,53.0");
740 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
741 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
743 format.LeadingZero = 1; /* Always provide leading zero */
744 STRINGSA(".5","0.5");
745 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
746 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
748 format.NegativeOrder = NEG_PARENS;
749 STRINGSA("-1","(1.0)");
750 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
751 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
753 format.NegativeOrder = NEG_LEFT;
754 STRINGSA("-1","-1.0");
755 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
756 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
758 format.NegativeOrder = NEG_LEFT_SPACE;
759 STRINGSA("-1","- 1.0");
760 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
761 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
763 format.NegativeOrder = NEG_RIGHT;
764 STRINGSA("-1","1.0-");
765 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
766 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
768 format.NegativeOrder = NEG_RIGHT_SPACE;
769 STRINGSA("-1","1.0 -");
770 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
771 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
773 lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
775 if (IsValidLocale(lcid, 0))
777 STRINGSA("-12345","-12 345,00"); /* Try French formatting */
778 Expected[3] = 160; /* Non breaking space */
779 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
780 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
785 static void test_CompareStringA(void)
788 LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
790 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
791 ok (ret== 1, "(Salut/Salute) Expected 1, got %d\n", ret);
793 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
794 ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
796 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
797 ok (ret== 3, "(Salut/hola) Expected 3, got %d\n", ret);
799 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
800 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
802 lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
804 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
805 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
807 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
808 ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
810 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
811 ok (ret == 2, "(Salut/saLuT) Expected 2, got %d\n", ret);
813 /* test for CompareStringA flags */
814 SetLastError(0xdeadbeef);
815 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0x10, "NULL", -1, "NULL", -1);
816 ok(GetLastError() == ERROR_INVALID_FLAGS,
817 "unexpected error code %d\n", GetLastError());
818 ok(!ret, "CompareStringA must fail with invalid flag\n");
820 SetLastError(0xdeadbeef);
821 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, LOCALE_USE_CP_ACP, "NULL", -1, "NULL", -1);
822 ok(GetLastError() == 0xdeadbeef, "unexpected error code %d\n", GetLastError());
823 ok(ret == CSTR_EQUAL, "CompareStringA error: %d != CSTR_EQUAL\n", ret);
824 /* end of test for CompareStringA flags */
826 ret = lstrcmpA("", "");
827 ok (ret == 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret);
829 ret = lstrcmpA(NULL, NULL);
830 ok (ret == 0, "lstrcmpA(NULL, NULL) should return 0, got %d\n", ret);
832 ret = lstrcmpA("", NULL);
833 ok (ret == 1, "lstrcmpA(\"\", NULL) should return 1, got %d\n", ret);
835 ret = lstrcmpA(NULL, "");
836 ok (ret == -1, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret);
838 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"EndDialog",-1,"_Property",-1);
839 ok( ret == 3, "EndDialog vs _Property ... expected 3, got %d\n", ret);
841 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0070",-1,"_IEWWBrowserComp",-1);
842 ok( ret == 3, "osp_vba.sreg0070 vs _IEWWBrowserComp ... expected 3, got %d\n", ret);
844 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"r",-1,"\\",-1);
845 ok( ret == 3, "r vs \\ ... expected 3, got %d\n", ret);
847 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0031", -1, "OriginalDatabase", -1 );
848 ok( ret == 3, "osp_vba.sreg0031 vs OriginalDatabase ... expected 3, got %d\n", ret);
850 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1 );
851 ok( ret == 3, "AAA vs aaa expected 3, got %d\n", ret);
853 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1 );
854 ok( ret == 1, "AAA vs aab expected 1, got %d\n", ret);
856 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1 );
857 ok( ret == 1, "AAA vs Aab expected 1, got %d\n", ret);
859 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1 );
860 ok( ret == 1, ".AAA vs Aab expected 1, got %d\n", ret);
862 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1 );
863 ok( ret == 1, ".AAA vs A.ab expected 1, got %d\n", ret);
865 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1 );
866 ok( ret == 1, "aa vs AB expected 1, got %d\n", ret);
868 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1 );
869 ok( ret == 1, "aa vs Aab expected 1, got %d\n", ret);
871 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1 );
872 ok( ret == 3, "aB vs Aab expected 3, got %d\n", ret);
874 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1 );
875 ok( ret == 1, "Ba vs bab expected 1, got %d\n", ret);
877 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1 );
878 ok( ret == 1, "{100}{83}{71}{71}{71} vs Global_DataAccess_JRO expected 1, got %d\n", ret);
880 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1 );
881 ok( ret == 3, "a vs { expected 3, got %d\n", ret);
883 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1 );
884 ok( ret == 3, "A vs { expected 3, got %d\n", ret);
886 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1 );
887 ok(ret == 1, "3.5/0 vs 4.0/-1 expected 1, got %d\n", ret);
889 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1 );
890 ok(ret == 1, "3.5 vs 4.0 expected 1, got %d\n", ret);
892 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1 );
893 ok(ret == 1, "3.520.4403.2 vs 4.0.2927.10 expected 1, got %d\n", ret);
895 /* hyphen and apostrophe are treated differently depending on
896 * whether SORT_STRINGSORT specified or not
898 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1 );
899 ok(ret == 3, "-o vs /m expected 3, got %d\n", ret);
901 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1 );
902 ok(ret == 1, "/m vs -o expected 1, got %d\n", ret);
904 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1 );
905 ok(ret == 1, "-o vs /m expected 1, got %d\n", ret);
907 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1 );
908 ok(ret == 3, "/m vs -o expected 3, got %d\n", ret);
910 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1 );
911 ok(ret == 3, "'o vs /m expected 3, got %d\n", ret);
913 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1 );
914 ok(ret == 1, "/m vs 'o expected 1, got %d\n", ret);
916 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1 );
917 ok(ret == 1, "'o vs /m expected 1, got %d\n", ret);
919 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1 );
920 ok(ret == 3, "/m vs 'o expected 3, got %d\n", ret);
922 if (0) { /* this requires collation table patch to make it MS compatible */
923 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
924 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
926 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
927 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
929 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
930 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
932 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
933 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
935 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
936 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
938 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
939 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
941 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
942 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
944 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
945 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
947 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
948 ok(ret == 1, "`o vs -m expected 1, got %d\n", ret);
950 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
951 ok(ret == 3, "-m vs `o expected 3, got %d\n", ret);
953 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
954 ok(ret == 3, "`o vs -m expected 3, got %d\n", ret);
956 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
957 ok(ret == 1, "-m vs `o expected 1, got %d\n", ret);
960 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9);
961 ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0 expected 2, got %d\n", ret);
963 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10);
964 ok(ret == 1, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1, got %d\n", ret);
966 /* WinXP handles embedded NULLs differently than earlier versions */
967 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
968 ok(ret == 1 || ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1 or 2, got %d\n", ret);
970 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
971 ok(ret == 1 || ret == 2, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected 1 or 2, got %d\n", ret);
973 ret = CompareStringA(lcid, 0, "a\0b", -1, "a", -1);
974 ok(ret == 2, "a vs a expected 2, got %d\n", ret);
976 ret = CompareStringA(lcid, 0, "a\0b", 4, "a", 2);
977 ok(ret == 3, "a\\0b vs a expected 3, got %d\n", ret);
979 ret = CompareStringA(lcid, 0, "\2", 2, "\1", 2);
980 todo_wine ok(ret != 2, "\\2 vs \\1 expected unequal\n");
983 static void test_LCMapStringA(void)
986 char buf[256], buf2[256];
987 static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
988 static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
989 static const char symbols_stripped[] = "justateststring1";
991 SetLastError(0xdeadbeef);
992 ret = LCMapStringA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP | LCMAP_LOWERCASE,
993 lower_case, -1, buf, sizeof(buf));
994 ok(ret == lstrlenA(lower_case) + 1,
995 "ret %d, error %d, expected value %d\n",
996 ret, GetLastError(), lstrlenA(lower_case) + 1);
997 ok(!memcmp(buf, lower_case, ret), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
999 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1000 upper_case, -1, buf, sizeof(buf));
1001 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1002 ok(GetLastError() == ERROR_INVALID_FLAGS,
1003 "unexpected error code %d\n", GetLastError());
1005 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1006 upper_case, -1, buf, sizeof(buf));
1007 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1008 ok(GetLastError() == ERROR_INVALID_FLAGS,
1009 "unexpected error code %d\n", GetLastError());
1011 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1012 upper_case, -1, buf, sizeof(buf));
1013 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1014 ok(GetLastError() == ERROR_INVALID_FLAGS,
1015 "unexpected error code %d\n", GetLastError());
1017 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1018 upper_case, -1, buf, sizeof(buf));
1019 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1020 ok(GetLastError() == ERROR_INVALID_FLAGS,
1021 "unexpected error code %d\n", GetLastError());
1023 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1024 SetLastError(0xdeadbeef);
1025 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1026 upper_case, -1, buf, sizeof(buf));
1027 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1028 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1030 /* test LCMAP_LOWERCASE */
1031 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1032 upper_case, -1, buf, sizeof(buf));
1033 ok(ret == lstrlenA(upper_case) + 1,
1034 "ret %d, error %d, expected value %d\n",
1035 ret, GetLastError(), lstrlenA(upper_case) + 1);
1036 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1038 /* test LCMAP_UPPERCASE */
1039 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1040 lower_case, -1, buf, sizeof(buf));
1041 ok(ret == lstrlenA(lower_case) + 1,
1042 "ret %d, error %d, expected value %d\n",
1043 ret, GetLastError(), lstrlenA(lower_case) + 1);
1044 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1046 /* test buffer overflow */
1047 SetLastError(0xdeadbeef);
1048 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1049 lower_case, -1, buf, 4);
1050 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1051 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1053 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1054 lstrcpyA(buf, lower_case);
1055 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1056 buf, -1, buf, sizeof(buf));
1057 if (!ret) /* Win9x */
1058 trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1061 ok(ret == lstrlenA(lower_case) + 1,
1062 "ret %d, error %d, expected value %d\n",
1063 ret, GetLastError(), lstrlenA(lower_case) + 1);
1064 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1066 lstrcpyA(buf, upper_case);
1067 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1068 buf, -1, buf, sizeof(buf));
1069 if (!ret) /* Win9x */
1070 trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1073 ok(ret == lstrlenA(upper_case) + 1,
1074 "ret %d, error %d, expected value %d\n",
1075 ret, GetLastError(), lstrlenA(lower_case) + 1);
1076 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1079 /* otherwise src == dst should fail */
1080 SetLastError(0xdeadbeef);
1081 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1082 buf, 10, buf, sizeof(buf));
1083 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1084 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1085 "unexpected error code %d\n", GetLastError());
1086 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1088 /* test whether '\0' is always appended */
1089 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1090 upper_case, -1, buf, sizeof(buf));
1091 ok(ret, "LCMapStringA must succeed\n");
1092 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1093 upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1094 ok(ret, "LCMapStringA must succeed\n");
1095 ok(ret == ret2, "lengths of sort keys must be equal\n");
1096 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1098 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1099 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1100 upper_case, -1, buf, sizeof(buf));
1101 ok(ret, "LCMapStringA must succeed\n");
1102 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1103 lower_case, -1, buf2, sizeof(buf2));
1104 ok(ret2, "LCMapStringA must succeed\n");
1105 ok(ret == ret2, "lengths of sort keys must be equal\n");
1106 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1108 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1109 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1110 lower_case, -1, buf, sizeof(buf));
1111 ok(ret, "LCMapStringA must succeed\n");
1112 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1113 lower_case, -1, buf2, sizeof(buf2));
1114 ok(ret2, "LCMapStringA must succeed\n");
1115 ok(ret == ret2, "lengths of sort keys must be equal\n");
1116 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1118 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1119 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1120 lower_case, -1, buf, sizeof(buf));
1121 ok(ret, "LCMapStringA must succeed\n");
1122 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1123 symbols_stripped, -1, buf2, sizeof(buf2));
1124 ok(ret2, "LCMapStringA must succeed\n");
1125 ok(ret == ret2, "lengths of sort keys must be equal\n");
1126 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1128 /* test NORM_IGNORENONSPACE */
1129 lstrcpyA(buf, "foo");
1130 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1131 lower_case, -1, buf, sizeof(buf));
1132 ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1133 lstrlenA(lower_case) + 1, ret);
1134 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1136 /* test NORM_IGNORESYMBOLS */
1137 lstrcpyA(buf, "foo");
1138 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1139 lower_case, -1, buf, sizeof(buf));
1140 ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1141 lstrlenA(symbols_stripped) + 1, ret);
1142 ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1144 /* test srclen = 0 */
1145 SetLastError(0xdeadbeef);
1146 ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1147 ok(!ret, "LCMapStringA should fail with srclen = 0\n");
1148 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1149 "unexpected error code %d\n", GetLastError());
1152 static void test_LCMapStringW(void)
1155 WCHAR buf[256], buf2[256];
1156 char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1157 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};
1158 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};
1159 static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
1160 static const WCHAR fooW[] = {'f','o','o',0};
1162 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1163 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1164 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1166 trace("Skipping LCMapStringW tests on Win9x\n");
1169 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1170 ok(GetLastError() == ERROR_INVALID_FLAGS,
1171 "unexpected error code %d\n", GetLastError());
1173 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1174 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1175 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1176 ok(GetLastError() == ERROR_INVALID_FLAGS,
1177 "unexpected error code %d\n", GetLastError());
1179 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1180 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1181 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1182 ok(GetLastError() == ERROR_INVALID_FLAGS,
1183 "unexpected error code %d\n", GetLastError());
1185 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1186 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1187 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1188 ok(GetLastError() == ERROR_INVALID_FLAGS,
1189 "unexpected error code %d\n", GetLastError());
1191 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1192 SetLastError(0xdeadbeef);
1193 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1194 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1195 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1196 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1198 /* test LCMAP_LOWERCASE */
1199 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1200 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1201 ok(ret == lstrlenW(upper_case) + 1,
1202 "ret %d, error %d, expected value %d\n",
1203 ret, GetLastError(), lstrlenW(upper_case) + 1);
1204 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1206 /* test LCMAP_UPPERCASE */
1207 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1208 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1209 ok(ret == lstrlenW(lower_case) + 1,
1210 "ret %d, error %d, expected value %d\n",
1211 ret, GetLastError(), lstrlenW(lower_case) + 1);
1212 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1214 /* test buffer overflow */
1215 SetLastError(0xdeadbeef);
1216 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1217 lower_case, -1, buf, 4);
1218 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1219 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1221 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1222 lstrcpyW(buf, lower_case);
1223 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1224 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1225 ok(ret == lstrlenW(lower_case) + 1,
1226 "ret %d, error %d, expected value %d\n",
1227 ret, GetLastError(), lstrlenW(lower_case) + 1);
1228 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1230 lstrcpyW(buf, upper_case);
1231 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1232 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1233 ok(ret == lstrlenW(upper_case) + 1,
1234 "ret %d, error %d, expected value %d\n",
1235 ret, GetLastError(), lstrlenW(lower_case) + 1);
1236 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1238 /* otherwise src == dst should fail */
1239 SetLastError(0xdeadbeef);
1240 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1241 buf, 10, buf, sizeof(buf));
1242 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1243 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1244 "unexpected error code %d\n", GetLastError());
1245 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1247 /* test whether '\0' is always appended */
1248 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1249 upper_case, -1, buf, sizeof(buf));
1250 ok(ret, "LCMapStringW must succeed\n");
1251 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1252 upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1253 ok(ret, "LCMapStringW must succeed\n");
1254 ok(ret == ret2, "lengths of sort keys must be equal\n");
1255 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1257 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1258 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1259 upper_case, -1, buf, sizeof(buf));
1260 ok(ret, "LCMapStringW must succeed\n");
1261 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1262 lower_case, -1, buf2, sizeof(buf2));
1263 ok(ret2, "LCMapStringW must succeed\n");
1264 ok(ret == ret2, "lengths of sort keys must be equal\n");
1265 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1267 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1268 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1269 lower_case, -1, buf, sizeof(buf));
1270 ok(ret, "LCMapStringW must succeed\n");
1271 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1272 lower_case, -1, buf2, sizeof(buf2));
1273 ok(ret2, "LCMapStringW must succeed\n");
1274 ok(ret == ret2, "lengths of sort keys must be equal\n");
1275 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1277 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1278 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1279 lower_case, -1, buf, sizeof(buf));
1280 ok(ret, "LCMapStringW must succeed\n");
1281 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1282 symbols_stripped, -1, buf2, sizeof(buf2));
1283 ok(ret2, "LCMapStringW must succeed\n");
1284 ok(ret == ret2, "lengths of sort keys must be equal\n");
1285 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1287 /* test NORM_IGNORENONSPACE */
1288 lstrcpyW(buf, fooW);
1289 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1290 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1291 ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1292 lstrlenW(lower_case) + 1, ret);
1293 ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1295 /* test NORM_IGNORESYMBOLS */
1296 lstrcpyW(buf, fooW);
1297 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1298 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1299 ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1300 lstrlenW(symbols_stripped) + 1, ret);
1301 ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1303 /* test srclen = 0 */
1304 SetLastError(0xdeadbeef);
1305 ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1306 ok(!ret, "LCMapStringW should fail with srclen = 0\n");
1307 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1308 "unexpected error code %d\n", GetLastError());
1311 /* this requires collation table patch to make it MS compatible */
1312 const char *strings_sorted[] =
1344 const char *strings[] =
1376 static int compare_string1(const void *e1, const void *e2)
1378 const char *s1 = *(const char *const *)e1;
1379 const char *s2 = *(const char *const *)e2;
1381 return lstrcmpA(s1, s2);
1384 static int compare_string2(const void *e1, const void *e2)
1386 const char *s1 = *(const char *const *)e1;
1387 const char *s2 = *(const char *const *)e2;
1389 return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1392 static int compare_string3(const void *e1, const void *e2)
1394 const char *s1 = *(const char *const *)e1;
1395 const char *s2 = *(const char *const *)e2;
1396 char key1[256], key2[256];
1398 LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
1399 LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
1400 return strcmp(key1, key2);
1403 static void test_sorting(void)
1406 char **str_buf = (char **)buf;
1409 assert(sizeof(buf) >= sizeof(strings));
1411 /* 1. sort using lstrcmpA */
1412 memcpy(buf, strings, sizeof(strings));
1413 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
1414 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1416 ok(!strcmp(strings_sorted[i], str_buf[i]),
1417 "qsort using lstrcmpA failed for element %d\n", i);
1419 /* 2. sort using CompareStringA */
1420 memcpy(buf, strings, sizeof(strings));
1421 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
1422 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1424 ok(!strcmp(strings_sorted[i], str_buf[i]),
1425 "qsort using CompareStringA failed for element %d\n", i);
1427 /* 3. sort using sort keys */
1428 memcpy(buf, strings, sizeof(strings));
1429 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
1430 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1432 ok(!strcmp(strings_sorted[i], str_buf[i]),
1433 "qsort using sort keys failed for element %d\n", i);
1437 static void test_FoldStringA(void)
1440 char src[256], dst[256];
1441 static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0' };
1442 static const char digits_dst[] = { '1','2','3','\0' };
1443 static const char composite_src[] =
1445 0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
1446 0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
1447 0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
1448 0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
1449 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
1450 0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
1451 0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
1452 0xfb,0xfc,0xfd,0xff,'\0'
1454 static const char composite_dst[] =
1456 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1457 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1458 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1459 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1460 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1461 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1462 0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
1463 0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
1464 0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
1465 0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
1466 0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
1467 0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
1468 0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
1469 0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
1470 0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1472 static const char ligatures_src[] =
1474 0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1476 static const char ligatures_dst[] =
1478 'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1482 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1484 /* these tests are locale specific */
1485 if (GetACP() != 1252)
1487 trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1491 /* MAP_FOLDDIGITS */
1493 ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
1494 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1496 EXPECT_LEN(4); EXPECT_VALID;
1497 ok(strcmp(dst, digits_dst) == 0,
1498 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
1499 for (i = 1; i < 256; i++)
1501 if (!strchr(digits_src, i))
1506 ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
1507 EXPECT_LEN(2); EXPECT_VALID;
1508 ok(dst[0] == src[0],
1509 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
1513 /* MAP_EXPAND_LIGATURES */
1515 ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1516 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1517 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1518 EXPECT_LEN(sizeof(ligatures_dst)); EXPECT_VALID;
1519 ok(strcmp(dst, ligatures_dst) == 0,
1520 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
1521 for (i = 1; i < 256; i++)
1523 if (!strchr(ligatures_src, i))
1528 ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1529 EXPECT_LEN(2); EXPECT_VALID;
1530 ok(dst[0] == src[0],
1531 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
1538 ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
1542 /* Wine gets close, but doesn't produce quite the same result as native */
1544 ok(strcmp(dst, composite_dst) == 0,
1545 "MAP_COMPOSITE: Expected '%s', got '%s'\n", composite_dst, dst);
1548 for (i = 1; i < 256; i++)
1550 if (!strchr(composite_src, i))
1555 ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
1556 EXPECT_LEN(2); EXPECT_VALID;
1557 ok(dst[0] == src[0],
1558 "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
1559 (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
1564 for (i = 1; i < 256; i++)
1569 ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
1570 EXPECT_LEN(2); EXPECT_VALID;
1571 ok(src[0] == dst[0],
1572 "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
1573 (unsigned char)src[0], (unsigned char)dst[0]);
1576 /* MAP_PRECOMPOSED */
1577 for (i = 1; i < 256; i++)
1582 ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
1583 EXPECT_LEN(2); EXPECT_VALID;
1584 ok(src[0] == dst[0],
1585 "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
1586 (unsigned char)src[0], (unsigned char)dst[0]);
1590 static void test_FoldStringW(void)
1594 WCHAR src[256], dst[256], ch, prev_ch = 1;
1595 static const DWORD badFlags[] =
1598 MAP_PRECOMPOSED|MAP_COMPOSITE,
1599 MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
1600 MAP_COMPOSITE|MAP_EXPAND_LIGATURES
1602 /* Ranges of digits 0-9 : Must be sorted! */
1603 static const WCHAR digitRanges[] =
1605 0x0030, /* '0'-'9' */
1606 0x0660, /* Eastern Arabic */
1607 0x06F0, /* Arabic - Hindu */
1608 0x0966, /* Devengari */
1609 0x09E6, /* Bengalii */
1610 0x0A66, /* Gurmukhi */
1611 0x0AE6, /* Gujarati */
1613 0x0BE6, /* Tamil - No 0 */
1614 0x0C66, /* Telugu */
1615 0x0CE6, /* Kannada */
1616 0x0D66, /* Maylayalam */
1619 0x2070, /* Superscript - 1, 2, 3 are out of sequence */
1620 0x2080, /* Subscript */
1621 0x245F, /* Circled - 0 is out of sequence */
1622 0x2473, /* Bracketed */
1623 0x2487, /* Full stop */
1624 0x2775, /* Inverted circled - No 0 */
1625 0x277F, /* Patterned circled - No 0 */
1626 0x2789, /* Inverted Patterned circled - No 0 */
1627 0xff10, /* Pliene chasse (?) */
1628 0xffff /* Terminator */
1630 /* Digits which are represented, but out of sequence */
1631 static const WCHAR outOfSequenceDigits[] =
1633 0xB9, /* Superscript 1 */
1634 0xB2, /* Superscript 2 */
1635 0xB3, /* Superscript 3 */
1636 0x24EA, /* Circled 0 */
1637 '\0' /* Terminator */
1639 /* Digits in digitRanges for which no representation is available */
1640 static const WCHAR noDigitAvailable[] =
1642 0x0BE6, /* No Tamil 0 */
1643 0x2473, /* No Bracketed 0 */
1644 0x2487, /* No 0 Full stop */
1645 0x2775, /* No inverted circled 0 */
1646 0x277F, /* No patterned circled */
1647 0x2789, /* No inverted Patterned circled */
1648 '\0' /* Terminator */
1650 /* Compatibility conversion results */
1651 static const WCHAR compat_F900_FA2F[256+48] =
1653 0x8c48, 0x66f4, 0x8eca, 0x8cc8, 0x6ed1, 0x4e32, 0x53e5, 0x9f9c,
1654 0x9f9c, 0x5951, 0x91d1, 0x5587, 0x5948, 0x61f6, 0x7669, 0x7f85,
1655 0x863f, 0x87ba, 0x88f8, 0x908f, 0x6a02, 0x6d1b, 0x70d9, 0x73de,
1656 0x843d, 0x916a, 0x99f1, 0x4e82, 0x5375, 0x6b04, 0x721b, 0x862d,
1657 0x9e1e, 0x5d50, 0x6feb, 0x85cd, 0x8964, 0x62c9, 0x81d8, 0x881f,
1658 0x5eca, 0x6717, 0x6d6a, 0x72fc, 0x0000, 0x4f86, 0x51b7, 0x52de,
1659 0x64c4, 0x6ad3, 0x7210, 0x76e7, 0x8001, 0x8606, 0x865c, 0x8def,
1660 0x9732, 0x9b6f, 0x9dfa, 0x788c, 0x797f, 0x7da0, 0x83c9, 0x9304,
1661 0x9e7f, 0x8ad6, 0x58df, 0x5f04, 0x7c60, 0x807e, 0x7262, 0x78ca,
1662 0x8cc2, 0x96f7, 0x58d8, 0x5c62, 0x6a13, 0x6dda, 0x6f0f, 0x7d2f,
1663 0x7e37, 0x964b, 0x52d2, 0x808b, 0x51dc, 0x51cc, 0x7a1c, 0x7dbe,
1664 0x83f1, 0x9675, 0x8b80, 0x62cf, 0x6a02, 0x8afe, 0x4e39, 0x5be7,
1665 0x6012, 0x7387, 0x7570, 0x5317, 0x78fb, 0x4fbf, 0x5fa9, 0x4e0d,
1666 0x6ccc, 0x6578, 0x7d22, 0x53c3, 0x585e, 0x7701, 0x8449, 0x8aaa,
1667 0x6bba, 0x8fb0, 0x6c88, 0x62fe, 0x82e5, 0x63a0, 0x7565, 0x4eae,
1668 0x5169, 0x0000, 0x6881, 0x7ce7, 0x826f, 0x8ad2, 0x91cf, 0x52f5,
1669 0x5442, 0x5973, 0x5eec, 0x65c5, 0x6ffe, 0x792a, 0x95ad, 0x9a6a,
1670 0x9e97, 0x9ece, 0x529b, 0x66c6, 0x6b77, 0x8f62, 0x5e74, 0x6190,
1671 0x6200, 0x649a, 0x6f23, 0x7149, 0x7489, 0x0000, 0x7df4, 0x806f,
1672 0x8f26, 0x84ee, 0x9023, 0x934a, 0x5217, 0x52a3, 0x54bd, 0x70c8,
1673 0x88c2, 0x8aaa, 0x5ec9, 0x5ff5, 0x637b, 0x6bae, 0x7c3e, 0x7375,
1674 0x4ee4, 0x56f9, 0x5be7, 0x5dba, 0x601c, 0x73b2, 0x7469, 0x7f9a,
1675 0x8046, 0x9234, 0x96f6, 0x9748, 0x9818, 0x4f8b, 0x79ae, 0x91b4,
1676 0x96b8, 0x60e1, 0x4e86, 0x50da, 0x5bee, 0x5c3f, 0x6599, 0x6a02,
1677 0x71ce, 0x7642, 0x84fc, 0x907c, 0x9f8d, 0x6688, 0x962e, 0x5289,
1678 0x677b, 0x67f3, 0x6d41, 0x6e9c, 0x7409, 0x7559, 0x786b, 0x7d10,
1679 0x985e, 0x516d, 0x622e, 0x9678, 0x502b, 0x5d19, 0x6dea, 0x8f2a,
1680 0x5f8b, 0x6144, 0x6817, 0x7387, 0x9686, 0x5229, 0x540f, 0x5c65,
1681 0x6613, 0x674e, 0x68a8, 0x6ce5, 0x7406, 0x75e2, 0x7f79, 0x0000,
1682 0x88e1, 0x91cc, 0x96e2, 0x533f, 0x6eba, 0x541d, 0x71d0, 0x7498,
1683 0x85fa, 0x0000, 0x9c57, 0x9e9f, 0x6797, 0x6dcb, 0x81e8, 0x7acb,
1684 0x7b20, 0x7c92, 0x72c0, 0x7099, 0x8b58, 0x4ec0, 0x8336, 0x523a,
1685 0x5207, 0x5ea6, 0x62d3, 0x7cd6, 0x5b85, 0x6d1e, 0x66b4, 0x8f3b,
1686 0x884c, 0x964d, 0x898b, 0x5ed3, 0x0000, 0x0000, 0x0000, 0x0000,
1687 0x585a, 0x0000, 0x6674, 0x0000, 0x0000, 0x51de, 0x8c6c, 0x76ca,
1688 0x0000, 0x795e, 0x7965, 0x798f, 0x9756, 0x7cbe, 0x7fbd, 0x0000,
1689 0x0000, 0x0000, 0x8af8, 0x0000, 0x0000, 0x9038, 0x90fd, 0x0000,
1690 0x0000, 0x0000, 0x98ef, 0x98fc, 0x9928, 0x9db4, 0x0000, 0x0000
1692 static const WCHAR compat_FE30_FEF7[200] =
1694 0x2025, 0x2014, 0x2013, 0x005f, 0x005f, 0x0028, 0x0029, 0x007b,
1695 0x007d, 0x3014, 0x3015, 0x3010, 0x3011, 0x300a, 0x300b, 0x3008,
1696 0x3009, 0x300c, 0x300d, 0x300e, 0x300f, 0x0000, 0x0000, 0x0000,
1697 0x0000, 0x203e, 0x203e, 0x203e, 0x203e, 0x005f, 0x005f, 0x005f,
1698 0x002c, 0x3001, 0x002e, 0x0000, 0x003b, 0x003a, 0x003f, 0x0021,
1699 0x2014, 0x0028, 0x0029, 0x007b, 0x007d, 0x3014, 0x3015, 0x0023,
1700 0x0026, 0x002a, 0x002b, 0x002d, 0x003c, 0x003e, 0x003d, 0x0000,
1701 0x0000, 0x0024, 0x0025, 0x0040, 0x0000, 0x0000, 0x0000, 0x0000,
1702 0x064b, 0x064b, 0x064c, 0x0000, 0x064d, 0x0000, 0x064e, 0x064e,
1703 0x064f, 0x064f, 0x0650, 0x0650, 0x0651, 0x0651, 0x0652, 0x0652,
1704 0x0621, 0x0622, 0x0622, 0x0623, 0x0623, 0x0624, 0x0624, 0x0625,
1705 0x0625, 0x0626, 0x0626, 0x0626, 0x0626, 0x0627, 0x0627, 0x0628,
1706 0x0628, 0x0628, 0x0628, 0x0629, 0x0629, 0x062a, 0x062a, 0x062a,
1707 0x062a, 0x062b, 0x062b, 0x062b, 0x062b, 0x062c, 0x062c, 0x062c,
1708 0x062c, 0x062d, 0x062d, 0x062d, 0x062d, 0x062e, 0x062e, 0x062e,
1709 0x062e, 0x062f, 0x062f, 0x0630, 0x0630, 0x0631, 0x0631, 0x0632,
1710 0x0632, 0x0633, 0x0633, 0x0633, 0x0633, 0x0634, 0x0634, 0x0634,
1711 0x0634, 0x0635, 0x0635, 0x0635, 0x0635, 0x0636, 0x0636, 0x0636,
1712 0x0636, 0x0637, 0x0637, 0x0637, 0x0637, 0x0638, 0x0638, 0x0638,
1713 0x0638, 0x0639, 0x0639, 0x0639, 0x0639, 0x063a, 0x063a, 0x063a,
1714 0x063a, 0x0641, 0x0641, 0x0641, 0x0641, 0x0642, 0x0642, 0x0642,
1715 0x0642, 0x0643, 0x0643, 0x0643, 0x0643, 0x0644, 0x0644, 0x0644,
1716 0x0644, 0x0645, 0x0645, 0x0645, 0x0645, 0x0646, 0x0646, 0x0646,
1717 0x0646, 0x0647, 0x0647, 0x0647, 0x0647, 0x0648, 0x0648, 0x0649,
1718 0x0649, 0x064a, 0x064a, 0x064a, 0x064a, 0x0000, 0x0000, 0x0000
1720 static const WCHAR compat_FF00_FFEF[240] =
1722 0x0000, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
1723 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
1724 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
1725 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
1726 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
1727 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
1728 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
1729 0x0058, 0x0059, 0x005a, 0x005b, 0x0000, 0x005d, 0x005e, 0x005f,
1730 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
1731 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
1732 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
1733 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000,
1734 0x0000, 0x3002, 0x300c, 0x300d, 0x3001, 0x30fb, 0x30f2, 0x30a1,
1735 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, 0x30c3,
1736 0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, 0x30ab, 0x30ad,
1737 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, 0x30b9, 0x30bb, 0x30bd,
1738 0x30bf, 0x30c1, 0x30c4, 0x30c6, 0x30c8, 0x30ca, 0x30cb, 0x30cc,
1739 0x30cd, 0x30ce, 0x30cf, 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de,
1740 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9,
1741 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c,
1742 0x3164, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137,
1743 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f,
1744 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147,
1745 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x0000,
1746 0x0000, 0x0000, 0x314f, 0x3150, 0x3151, 0x3152, 0x3153, 0x3154,
1747 0x0000, 0x0000, 0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315a,
1748 0x0000, 0x0000, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, 0x3160,
1749 0x0000, 0x0000, 0x3161, 0x3162, 0x3163, 0x0000, 0x0000, 0x0000,
1750 0x00a2, 0x00a3, 0x00ac, 0x00af, 0x00a6, 0x00a5, 0x20a9, 0x0000,
1751 0x2502, 0x2190, 0x2191, 0x2192, 0x2193, 0x25a0, 0x25cb, 0x0000
1753 static const WCHAR ligatures_src[] =
1755 0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
1756 0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
1757 0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
1758 0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
1759 0xfb04, 0xfb05, 0xfb06, '\0'
1761 static const WCHAR ligatures_dst[] =
1763 'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
1764 'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
1765 'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
1766 0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
1767 'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
1771 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1773 /* Invalid flag combinations */
1774 for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
1776 src[0] = dst[0] = '\0';
1778 ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
1779 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1781 EXPECT_LEN(0); EXPECT_FLAGS;
1784 /* src & dst cannot be the same */
1786 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
1787 EXPECT_LEN(0); EXPECT_INVALID;
1789 /* src can't be NULL */
1791 ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
1792 EXPECT_LEN(0); EXPECT_INVALID;
1794 /* srclen can't be 0 */
1796 ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
1797 EXPECT_LEN(0); EXPECT_INVALID;
1799 /* dstlen can't be < 0 */
1801 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
1802 EXPECT_LEN(0); EXPECT_INVALID;
1804 /* Ret includes terminating NUL which is appended if srclen = -1 */
1809 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
1810 EXPECT_LEN(2); EXPECT_VALID;
1811 ok(dst[0] == 'A' && dst[1] == '\0',
1812 "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%d\n",
1813 'A', '\0', ret, dst[0], dst[1], GetLastError());
1815 /* If size is given, result is not NUL terminated */
1821 ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
1822 EXPECT_LEN(1); EXPECT_VALID;
1823 ok(dst[0] == 'A' && dst[1] == 'X',
1824 "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%d\n",
1825 'A','X', ret, dst[0], dst[1], GetLastError());
1827 /* MAP_FOLDDIGITS */
1828 for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
1830 /* Check everything before this range */
1831 for (ch = prev_ch; ch < digitRanges[j]; ch++)
1835 src[1] = dst[0] = '\0';
1836 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
1837 EXPECT_LEN(2); EXPECT_VALID;
1839 ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
1840 /* Wine (correctly) maps all Unicode 4.0+ digits */
1841 isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF ||
1842 (ch >= 0x1369 && ch <= 0x1371),
1843 "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
1846 if (digitRanges[j] == 0xffff)
1847 break; /* Finished the whole code point space */
1849 for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
1853 /* Map out of sequence characters */
1854 if (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
1855 else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
1856 else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
1857 else if (ch == 0x245F) c = 0x24EA; /* Circled 0 */
1861 src[1] = dst[0] = '\0';
1862 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
1863 EXPECT_LEN(2); EXPECT_VALID;
1865 ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
1866 strchrW(noDigitAvailable, c),
1867 "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
1868 ch, '0' + digitRanges[j] - ch, dst[0]);
1874 for (ch = 1; ch <0xffff; ch++)
1878 if (ch >= 0xF900 && ch <= 0xFA2F)
1879 expected = compat_F900_FA2F[ch - 0xF900];
1880 else if (ch >= 0xFE30 && ch <= 0xFEF7)
1881 expected = compat_FE30_FEF7[ch - 0xFE30];
1882 else if (ch >= 0xFF00 && ch <= 0xFFEF)
1883 expected = compat_FF00_FFEF[ch - 0xFF00];
1890 src[1] = dst[0] = '\0';
1891 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
1892 EXPECT_LEN(2); EXPECT_VALID;
1893 ok(dst[0] == expected ||
1894 /* Wine (correctly) uses updated mappings for some Unicode 4.0 chars */
1895 /* FIXME: But they should be re-checked */
1896 ch == 0xf92c || ch == 0xf979 || ch == 0xf995 || ch == 0xf9e7 ||
1898 (0xfa0c <= ch && ch <= 0xfa6a) ||
1899 (0xfa70 <= ch && ch <= 0xfad9) ||
1900 ch == 0xfe47 || ch == 0xfe48 || ch == 0xfe68 ||
1901 (0xfe70 <= ch && ch <= 0xfe7f) ||
1902 ch == 0xff3c || ch == 0xff5f || ch == 0xff60 ||
1903 ch == 0xff9e || ch == 0xff9f,
1904 "MAP_FOLDCZONE: ch %d 0x%04x Expected 0x%04x got 0x%04x\n",
1905 ch, ch, expected, dst[0]);
1908 /* MAP_EXPAND_LIGATURES */
1910 ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1911 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1912 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1913 EXPECT_LEN(sizeof(ligatures_dst)/sizeof(ligatures_dst[0])); EXPECT_VALID;
1914 ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
1915 "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
1916 for (i = 1; i <= 0xffff; i++)
1918 if (!strchrW(ligatures_src, i))
1923 ret = pFoldStringW(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1924 EXPECT_LEN(2); EXPECT_VALID;
1925 ok(dst[0] == src[0],
1926 "MAP_EXPAND_LIGATURES: 0x%02x : Expected 0x%02x, got 0x%02x\n",
1932 /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
1937 #define LCID_OK(l) \
1938 ok(lcid == l, "Expected lcid = %08x, got %08x\n", l, lcid)
1939 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
1940 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
1941 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
1942 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
1944 static void test_ConvertDefaultLocale(void)
1948 /* Doesn't change lcid, even if non default sublang/sort used */
1949 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_US, SORT_DEFAULT);
1950 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_UK, SORT_DEFAULT);
1951 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT);
1952 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE);
1954 /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
1955 LCID_RES(MKLCID(LANG_ENGLISH, SUBLANG_NEUTRAL, SORT_DEFAULT),
1956 MKLCID(LANG_ENGLISH, SUBLANG_DEFAULT, SORT_DEFAULT));
1957 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
1958 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
1959 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_JAPANESE_UNICODE),
1960 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE));
1962 /* Invariant language is not treated specially */
1963 TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
1964 LCID_RES(MKLCID(LANG_INVARIANT, SUBLANG_NEUTRAL, SORT_DEFAULT),
1965 MKLCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT));
1967 /* User/system default languages alone are not mapped */
1968 TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
1969 TEST_LCIDLANG(LANG_USER_DEFAULT, SORT_JAPANESE_UNICODE);
1972 LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
1973 LCID_RES(LOCALE_USER_DEFAULT, GetUserDefaultLCID());
1974 LCID_RES(LOCALE_NEUTRAL, GetUserDefaultLCID());
1977 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
1978 DWORD dwFlags, LONG_PTR lParam)
1980 trace("%08x, %s, %s, %08x, %08lx\n",
1981 lgrpid, lpszNum, lpszName, dwFlags, lParam);
1983 ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
1984 "Enumerated grp %d not valid (flags %d)\n", lgrpid, dwFlags);
1986 /* If lParam is one, we are calling with flags defaulted from 0 */
1987 ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
1988 "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %d\n", dwFlags);
1993 static void test_EnumSystemLanguageGroupsA(void)
1995 if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
1998 /* No enumeration proc */
2000 pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
2005 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
2008 /* No flags - defaults to LGRPID_INSTALLED */
2010 pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
2013 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
2014 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
2018 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
2021 trace("%08x, %08x, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
2023 ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
2024 "Enumerated grp %d not valid\n", lgrpid);
2025 ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
2026 "Enumerated grp locale %d not valid\n", lcid);
2030 static void test_EnumLanguageGroupLocalesA(void)
2032 if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
2035 /* No enumeration proc */
2037 pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
2040 /* lgrpid too small */
2042 pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
2045 /* lgrpid too big */
2047 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
2050 /* dwFlags is reserved */
2052 pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
2055 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2058 static void test_SetLocaleInfoA(void)
2061 LCID lcid = GetUserDefaultLCID();
2065 bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2070 bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
2075 bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
2079 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2081 trace("%s %08lx\n", value, lParam);
2085 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2087 ok(!enumCount, "callback called again unexpected\n");
2092 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2094 ok(0,"callback called unexpected\n");
2098 static void test_EnumUILanguageA(void)
2101 if (!pEnumUILanguagesA) {
2102 trace("EnumUILanguagesA is not available on Win9x\n");
2106 SetLastError(ERROR_SUCCESS);
2107 ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2108 EXPECT_TRUE; EXPECT_VALID;
2111 SetLastError(ERROR_SUCCESS);
2112 ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2113 EXPECT_TRUE; EXPECT_VALID;
2115 SetLastError(ERROR_SUCCESS);
2116 ret = pEnumUILanguagesA(NULL, 0, 0);
2117 EXPECT_FALSE; EXPECT_INVALID;
2119 SetLastError(ERROR_SUCCESS);
2120 ret = pEnumUILanguagesA(luilocale_proc3A, 0x5a5a5a5a, 0);
2121 EXPECT_FALSE; EXPECT_FLAGS;
2123 SetLastError(ERROR_SUCCESS);
2124 ret = pEnumUILanguagesA(NULL, 0x5a5a5a5a, 0);
2125 EXPECT_FALSE; EXPECT_INVALID;
2128 static char date_fmt_buf[1024];
2130 static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
2132 lstrcatA(date_fmt_buf, fmt);
2133 lstrcatA(date_fmt_buf, "\n");
2137 static void test_EnumDateFormatsA(void)
2141 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2143 trace("EnumDateFormatsA 0\n");
2144 date_fmt_buf[0] = 0;
2145 ret = EnumDateFormatsA(enum_datetime_procA, lcid, 0);
2146 ok(ret, "EnumDateFormatsA(0) error %d\n", GetLastError());
2147 trace("%s\n", date_fmt_buf);
2148 /* test the 1st enumerated format */
2149 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2150 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2151 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2152 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2154 trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n");
2155 date_fmt_buf[0] = 0;
2156 ret = EnumDateFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2157 ok(ret, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2158 trace("%s\n", date_fmt_buf);
2159 /* test the 1st enumerated format */
2160 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2161 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2162 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2163 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2165 trace("EnumDateFormatsA DATE_SHORTDATE\n");
2166 date_fmt_buf[0] = 0;
2167 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_SHORTDATE);
2168 ok(ret, "EnumDateFormatsA(DATE_SHORTDATE) error %d\n", GetLastError());
2169 trace("%s\n", date_fmt_buf);
2170 /* test the 1st enumerated format */
2171 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2172 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2173 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2174 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2176 trace("EnumDateFormatsA DATE_LONGDATE\n");
2177 date_fmt_buf[0] = 0;
2178 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_LONGDATE);
2179 ok(ret, "EnumDateFormatsA(DATE_LONGDATE) error %d\n", GetLastError());
2180 trace("%s\n", date_fmt_buf);
2181 /* test the 1st enumerated format */
2182 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2183 ret = GetLocaleInfoA(lcid, LOCALE_SLONGDATE, buf, sizeof(buf));
2184 ok(ret, "GetLocaleInfoA(LOCALE_SLONGDATE) error %d\n", GetLastError());
2185 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2187 trace("EnumDateFormatsA DATE_YEARMONTH\n");
2188 date_fmt_buf[0] = 0;
2189 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_YEARMONTH);
2190 ok(ret, "EnumDateFormatsA(DATE_YEARMONTH) error %d\n", GetLastError());
2191 trace("%s\n", date_fmt_buf);
2192 /* test the 1st enumerated format */
2193 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2194 ret = GetLocaleInfoA(lcid, LOCALE_SYEARMONTH, buf, sizeof(buf));
2195 ok(ret, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %d\n", GetLastError());
2196 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2199 static void test_EnumTimeFormatsA(void)
2203 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2205 trace("EnumTimeFormatsA 0\n");
2206 date_fmt_buf[0] = 0;
2207 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, 0);
2208 ok(ret, "EnumTimeFormatsA(0) error %d\n", GetLastError());
2209 trace("%s\n", date_fmt_buf);
2210 /* test the 1st enumerated format */
2211 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2212 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2213 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2214 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2216 trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n");
2217 date_fmt_buf[0] = 0;
2218 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2219 ok(ret, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2220 trace("%s\n", date_fmt_buf);
2221 /* test the 1st enumerated format */
2222 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2223 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2224 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2225 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2228 static void test_GetCPInfo(void)
2233 SetLastError(0xdeadbeef);
2234 ret = GetCPInfo(CP_SYMBOL, &cpinfo);
2235 ok(!ret, "GetCPInfo(CP_SYMBOL) should fail\n");
2236 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2237 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2239 SetLastError(0xdeadbeef);
2240 ret = GetCPInfo(CP_UTF7, &cpinfo);
2241 ok(ret, "GetCPInfo(CP_UTF7) error %u\n", GetLastError());
2242 ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2243 ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2244 ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2245 ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2246 ok(cpinfo.MaxCharSize == 5, "expected 5, got 0x%x\n", cpinfo.MaxCharSize);
2248 SetLastError(0xdeadbeef);
2249 ret = GetCPInfo(CP_UTF8, &cpinfo);
2250 ok(ret, "GetCPInfo(CP_UTF8) error %u\n", GetLastError());
2251 ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2252 ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2253 ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2254 ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2255 ok(cpinfo.MaxCharSize == 4, "expected 5, got 0x%x\n", cpinfo.MaxCharSize);
2260 InitFunctionPointers();
2262 test_EnumTimeFormatsA();
2263 test_EnumDateFormatsA();
2264 test_GetLocaleInfoA();
2265 test_GetTimeFormatA();
2266 test_GetDateFormatA();
2267 test_GetDateFormatW();
2268 test_GetCurrencyFormatA(); /* Also tests the W version */
2269 test_GetNumberFormatA(); /* Also tests the W version */
2270 test_CompareStringA();
2271 test_LCMapStringA();
2272 test_LCMapStringW();
2275 test_ConvertDefaultLocale();
2276 test_EnumSystemLanguageGroupsA();
2277 test_EnumLanguageGroupLocalesA();
2278 test_SetLocaleInfoA();
2279 test_EnumUILanguageA();
2281 /* this requires collation table patch to make it MS compatible */
2282 if (0) test_sorting();