2 * Unit tests for locale functions
4 * Copyright 2002 YASAR Mehmet
5 * Copyright 2003 Dmitry Timoshkov
6 * Copyright 2003 Jon Griffiths
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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 for ( ; *str; str++) if (*str == ch) return (WCHAR *)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 static char GlobalBuffer[BUFFER_SIZE]; /* Buffer used by callback function */
108 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
110 #define EXPECT_LEN(len) ok(ret == (len), "Expected Len %d, got %d\n", (len), ret)
111 #define EXPECT_INVALID ok(GetLastError() == ERROR_INVALID_PARAMETER, \
112 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError())
113 #define EXPECT_BUFFER ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, \
114 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError())
115 #define EXPECT_FLAGS ok(GetLastError() == ERROR_INVALID_FLAGS, \
116 "Expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError())
117 #define EXPECT_INVALIDFLAGS ok(GetLastError() == ERROR_INVALID_FLAGS || \
118 GetLastError() == ERROR_INVALID_PARAMETER, \
119 "Expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError())
120 #define EXPECT_VALID ok(GetLastError() == 0, \
121 "Expected GetLastError() == 0, got %ld\n", 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 - %ld\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 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
174 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
177 curtime.wMinute = 56;
178 curtime.wSecond = 13;
179 curtime.wMilliseconds = 22;
180 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
181 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
182 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
184 STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficent buffer */
185 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, 2);
186 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
188 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
189 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, NULL, 0);
190 EXPECT_VALID; EXPECT_LENA;
192 STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
193 ret = GetTimeFormatA(lcid, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
194 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
196 STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
197 ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
198 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
200 STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
201 ret = GetTimeFormatA(lcid, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
202 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
204 STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
205 strcpy(Expected, "8:56 AM");
206 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
207 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
209 STRINGSA("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
210 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
211 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
213 STRINGSA("s1s2s3", ""); /* Duplicate tokens */
214 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
215 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
217 STRINGSA("t/tt", "A/AM"); /* AM time marker */
218 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
219 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
222 STRINGSA("t/tt", "P/PM"); /* PM time marker */
223 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
224 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
226 STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
227 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
228 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
230 STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
231 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
232 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
234 STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
235 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
236 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
238 curtime.wHour = 14; /* change this to 14 or 2pm */
241 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 */
242 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
243 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
246 STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
247 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
248 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
250 STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
251 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
252 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
254 /* try to convert formatting strings with more than two letters
255 * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
256 * NOTE: We expect any letter for which there is an upper case value
257 * we should see a replacement. For letters that DO NOT have
258 * upper case values we should see NO REPLACEMENT.
261 curtime.wMinute = 56;
262 curtime.wSecond = 13;
263 curtime.wMilliseconds = 22;
264 STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
265 "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
266 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
267 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
269 STRINGSA("h", "text"); /* Don't write to buffer if len is 0 */
270 strcpy(buffer, "text");
271 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, 0);
272 EXPECT_VALID; EXPECT_LEN(2); EXPECT_EQA;
274 STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
275 "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
276 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
277 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
279 STRINGSA("'''", "'"); /* invalid quoted string */
280 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
281 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
283 /* test that msdn suggested single quotation usage works as expected */
284 STRINGSA("''''", "'"); /* single quote mark */
285 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
286 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
288 STRINGSA("''HHHHHH", "08"); /* Normal use */
289 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
290 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
292 /* and test for normal use of the single quotation mark */
293 STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
294 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
295 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
297 STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
298 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
299 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
301 STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
302 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
303 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
306 STRINGSA("'123'tt", ""); /* Invalid time */
307 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
308 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
311 curtime.wMonth = 60; /* Invalid */
312 STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
313 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
314 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
317 static void test_GetDateFormatA(void)
321 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
322 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
324 memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
325 STRINGSA("ddd',' MMM dd yy","");
326 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
327 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
329 curtime.wYear = 2002;
332 curtime.wDayOfWeek = 3;
333 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
334 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
335 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
337 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
338 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
339 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
341 curtime.wHour = 36; /* Invalid */
342 STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
343 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
344 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
346 STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
347 ret = GetDateFormatA(lcid, 0, &curtime, input, NULL, 0);
348 EXPECT_VALID; EXPECT_LEN(16); EXPECT_EQA;
350 STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
351 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, 2);
352 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
354 STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
355 ret = GetDateFormat(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
356 EXPECT_VALID; EXPECT_LENA;
357 if (strncmp(buffer, Expected, strlen(Expected)) && strncmp(buffer, "5/4/02", strlen(Expected)) != 0)
358 ok (0, "Expected '%s' or '5/4/02', got '%s'\n", Expected, buffer);
360 STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
361 ret = GetDateFormat(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
362 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
364 /* test for expected DATE_YEARMONTH behavior with null format */
365 /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
366 STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
367 ret = GetDateFormat(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
368 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
370 /* Test that using invalid DATE_* flags results in the correct error */
371 /* and return values */
372 STRINGSA("m/d/y", ""); /* Invalid flags */
373 ret = GetDateFormat(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
374 &curtime, input, buffer, COUNTOF(buffer));
375 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
378 static void test_GetDateFormatW(void)
382 WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
383 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
385 STRINGSW("",""); /* If flags is not zero then format must be NULL */
386 ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL,
387 input, buffer, COUNTOF(buffer));
388 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
390 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQW;
392 STRINGSW("",""); /* NULL buffer, len > 0 */
393 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
394 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQW;
396 STRINGSW("",""); /* NULL buffer, len == 0 */
397 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
398 EXPECT_VALID; EXPECT_LENW; EXPECT_EQW;
400 curtime.wYear = 2002;
403 curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
404 curtime.wHour = 65432; /* Invalid */
405 curtime.wMinute = 34512; /* Invalid */
406 curtime.wSecond = 65535; /* Invalid */
407 curtime.wMilliseconds = 12345;
408 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
409 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
410 EXPECT_VALID; EXPECT_LENW; EXPECT_EQW;
414 #define CY_POS_LEFT 0
415 #define CY_POS_RIGHT 1
416 #define CY_POS_LEFT_SPACE 2
417 #define CY_POS_RIGHT_SPACE 3
419 static void test_GetCurrencyFormatA(void)
421 static char szDot[] = { '.', '\0' };
422 static char szComma[] = { ',', '\0' };
423 static char szDollar[] = { '$', '\0' };
425 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
426 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
429 memset(&format, 0, sizeof(format));
431 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
432 ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
433 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
435 STRINGSA("23,53",""); /* Invalid character --> Error */
436 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
437 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
439 STRINGSA("--",""); /* Double '-' --> Error */
440 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
441 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
443 STRINGSA("0-",""); /* Trailing '-' --> Error */
444 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
445 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
447 STRINGSA("0..",""); /* Double '.' --> Error */
448 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
449 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
451 STRINGSA(" 0.1",""); /* Leading space --> Error */
452 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
453 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
455 STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
456 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, 2);
457 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
459 STRINGSA("2353",""); /* Format and flags given --> Error */
460 ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
461 EXPECT_INVALIDFLAGS; EXPECT_LEN(0); EXPECT_EQA;
463 STRINGSA("2353",""); /* Invalid format --> Error */
464 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
465 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
467 STRINGSA("2353","$2,353.00"); /* Valid number */
468 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
469 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
471 STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
472 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
473 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
475 STRINGSA("2353.1","$2,353.10"); /* Valid real number */
476 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
477 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
479 STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
480 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
481 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
483 STRINGSA("2353.119","$2,353.12"); /* Too many DP --> Rounded */
484 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
485 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
487 format.NumDigits = 0; /* No decimal separator */
488 format.LeadingZero = 0;
489 format.Grouping = 0; /* No grouping char */
490 format.NegativeOrder = 0;
491 format.PositiveOrder = CY_POS_LEFT;
492 format.lpDecimalSep = szDot;
493 format.lpThousandSep = szComma;
494 format.lpCurrencySymbol = szDollar;
496 STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
497 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
498 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
500 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
501 STRINGSA("2353","$2353.0");
502 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
503 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
505 format.Grouping = 2; /* Group by 100's */
506 STRINGSA("2353","$23,53.0");
507 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
508 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
510 format.LeadingZero = 1; /* Always provide leading zero */
511 STRINGSA(".5","$0.5");
512 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
513 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
515 format.PositiveOrder = CY_POS_RIGHT;
516 STRINGSA("1","1.0$");
517 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
518 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
520 format.PositiveOrder = CY_POS_LEFT_SPACE;
521 STRINGSA("1","$ 1.0");
522 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
523 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
525 format.PositiveOrder = CY_POS_RIGHT_SPACE;
526 STRINGSA("1","1.0 $");
527 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
528 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
530 format.NegativeOrder = 0;
531 STRINGSA("-1","($1.0)");
532 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
533 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
535 format.NegativeOrder = 1;
536 STRINGSA("-1","-$1.0");
537 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
538 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
540 format.NegativeOrder = 2;
541 STRINGSA("-1","$-1.0");
542 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
543 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
545 format.NegativeOrder = 3;
546 STRINGSA("-1","$1.0-");
547 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
548 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
550 format.NegativeOrder = 4;
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 = 5;
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 = 6;
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 = 7;
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 = 8;
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 = 9;
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 = 10;
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 = 11;
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 = 12;
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 = 13;
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 = 14;
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 = 15;
606 STRINGSA("-1","(1.0 $)");
607 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
608 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
611 #define NEG_PARENS 0 /* "(1.1)" */
612 #define NEG_LEFT 1 /* "-1.1" */
613 #define NEG_LEFT_SPACE 2 /* "- 1.1" */
614 #define NEG_RIGHT 3 /* "1.1-" */
615 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
617 static void test_GetNumberFormatA(void)
619 static char szDot[] = { '.', '\0' };
620 static char szComma[] = { ',', '\0' };
622 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
623 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
626 memset(&format, 0, sizeof(format));
628 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
629 ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
630 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
632 STRINGSA("23,53",""); /* Invalid character --> Error */
633 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
634 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
636 STRINGSA("--",""); /* Double '-' --> Error */
637 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
638 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
640 STRINGSA("0-",""); /* Trailing '-' --> Error */
641 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
642 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
644 STRINGSA("0..",""); /* Double '.' --> Error */
645 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
646 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
648 STRINGSA(" 0.1",""); /* Leading space --> Error */
649 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
650 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
652 STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
653 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, 2);
654 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
656 STRINGSA("2353",""); /* Format and flags given --> Error */
657 ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
658 EXPECT_INVALIDFLAGS; EXPECT_LEN(0); EXPECT_EQA;
660 STRINGSA("2353",""); /* Invalid format --> Error */
661 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
662 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
664 STRINGSA("2353","2,353.00"); /* Valid number */
665 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
666 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
668 STRINGSA("-2353","-2,353.00"); /* Valid negative number */
669 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
670 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
672 STRINGSA("-353","-353.00"); /* test for off by one error in grouping */
673 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
674 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
676 STRINGSA("2353.1","2,353.10"); /* Valid real number */
677 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
678 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
680 STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
681 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
682 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
684 STRINGSA("2353.119","2,353.12"); /* Too many DP --> Rounded */
685 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
686 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
688 format.NumDigits = 0; /* No decimal separator */
689 format.LeadingZero = 0;
690 format.Grouping = 0; /* No grouping char */
691 format.NegativeOrder = 0;
692 format.lpDecimalSep = szDot;
693 format.lpThousandSep = szComma;
695 STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
696 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
697 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
699 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
700 STRINGSA("2353","2353.0");
701 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
702 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
704 format.Grouping = 2; /* Group by 100's */
705 STRINGSA("2353","23,53.0");
706 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
707 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
709 format.LeadingZero = 1; /* Always provide leading zero */
710 STRINGSA(".5","0.5");
711 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
712 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
714 format.NegativeOrder = NEG_PARENS;
715 STRINGSA("-1","(1.0)");
716 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
717 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
719 format.NegativeOrder = NEG_LEFT;
720 STRINGSA("-1","-1.0");
721 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
722 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
724 format.NegativeOrder = NEG_LEFT_SPACE;
725 STRINGSA("-1","- 1.0");
726 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
727 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
729 format.NegativeOrder = NEG_RIGHT;
730 STRINGSA("-1","1.0-");
731 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
732 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
734 format.NegativeOrder = NEG_RIGHT_SPACE;
735 STRINGSA("-1","1.0 -");
736 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
737 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
739 lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
741 if (IsValidLocale(lcid, 0))
743 STRINGSA("-12345","-12 345,00"); /* Try French formatting */
744 Expected[3] = 160; /* Non breaking space */
745 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
746 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
751 /* Callback function used by TestEnumTimeFormats */
752 static BOOL CALLBACK EnumTimeFormatsProc(char * lpTimeFormatString)
754 trace("%s\n", lpTimeFormatString);
755 strcpy(GlobalBuffer, lpTimeFormatString);
762 static void test_EnumTimeFormats(void)
765 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
767 GlobalBuffer[0] = '\0';
768 ret = EnumTimeFormatsA(EnumTimeFormatsProc, lcid, 0);
769 ok (ret == 1 && !strcmp(GlobalBuffer,"h:mm:ss tt"), "Expected %d '%s'\n", ret, GlobalBuffer);
772 static void test_CompareStringA(void)
775 LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
777 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
778 ok (ret== 1, "(Salut/Salute) Expected 1, got %d\n", ret);
780 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
781 ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
783 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
784 ok (ret== 3, "(Salut/hola) Expected 3, got %d\n", ret);
786 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
787 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
789 lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
791 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
792 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
794 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
795 ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
797 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
798 ok (ret == 2, "(Salut/saLuT) Expected 2, got %d\n", ret);
800 /* test for CompareStringA flags */
801 SetLastError(0xdeadbeef);
802 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0x10, "NULL", -1, "NULL", -1);
803 ok(GetLastError() == ERROR_INVALID_FLAGS,
804 "unexpected error code %ld\n", GetLastError());
805 ok(!ret, "CompareStringA must fail with invalid flag\n");
807 SetLastError(0xdeadbeef);
808 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, LOCALE_USE_CP_ACP, "NULL", -1, "NULL", -1);
809 ok(GetLastError() == 0xdeadbeef, "unexpected error code %ld\n", GetLastError());
810 ok(ret == CSTR_EQUAL, "CompareStringA error: %d != CSTR_EQUAL\n", ret);
811 /* end of test for CompareStringA flags */
813 ret = lstrcmpA("", "");
814 ok (ret == 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret);
816 ret = lstrcmpA(NULL, NULL);
817 ok (ret == 0, "lstrcmpA(NULL, NULL) should return 0, got %d\n", ret);
819 ret = lstrcmpA("", NULL);
820 ok (ret == 1, "lstrcmpA(\"\", NULL) should return 1, got %d\n", ret);
822 ret = lstrcmpA(NULL, "");
823 ok (ret == -1, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret);
825 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"EndDialog",-1,"_Property",-1);
826 ok( ret == 3, "EndDialog vs _Property ... expected 3, got %d\n", ret);
828 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0070",-1,"_IEWWBrowserComp",-1);
829 ok( ret == 3, "osp_vba.sreg0070 vs _IEWWBrowserComp ... expected 3, got %d\n", ret);
831 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"r",-1,"\\",-1);
832 ok( ret == 3, "r vs \\ ... expected 3, got %d\n", ret);
834 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0031", -1, "OriginalDatabase", -1 );
835 ok( ret == 3, "osp_vba.sreg0031 vs OriginalDatabase ... expected 3, got %d\n", ret);
837 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1 );
838 ok( ret == 3, "AAA vs aaa expected 3, got %d\n", ret);
840 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1 );
841 ok( ret == 1, "AAA vs aab expected 1, got %d\n", ret);
843 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1 );
844 ok( ret == 1, "AAA vs Aab expected 1, got %d\n", ret);
846 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1 );
847 ok( ret == 1, ".AAA vs Aab expected 1, got %d\n", ret);
849 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1 );
850 ok( ret == 1, ".AAA vs A.ab expected 1, got %d\n", ret);
852 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1 );
853 ok( ret == 1, "aa vs AB expected 1, got %d\n", ret);
855 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1 );
856 ok( ret == 1, "aa vs Aab expected 1, got %d\n", ret);
858 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1 );
859 ok( ret == 3, "aB vs Aab expected 3, got %d\n", ret);
861 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1 );
862 ok( ret == 1, "Ba vs bab expected 1, got %d\n", ret);
864 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1 );
865 ok( ret == 1, "{100}{83}{71}{71}{71} vs Global_DataAccess_JRO expected 1, got %d\n", ret);
867 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1 );
868 ok( ret == 3, "a vs { expected 3, got %d\n", ret);
870 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1 );
871 ok( ret == 3, "A vs { expected 3, got %d\n", ret);
873 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1 );
874 ok(ret == 1, "3.5/0 vs 4.0/-1 expected 1, got %d\n", ret);
876 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1 );
877 ok(ret == 1, "3.5 vs 4.0 expected 1, got %d\n", ret);
879 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1 );
880 ok(ret == 1, "3.520.4403.2 vs 4.0.2927.10 expected 1, got %d\n", ret);
882 /* hyphen and apostrophe are treated differently depending on
883 * whether SORT_STRINGSORT specified or not
885 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1 );
886 ok(ret == 3, "-o vs /m expected 3, got %d\n", ret);
888 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1 );
889 ok(ret == 1, "/m vs -o expected 1, got %d\n", ret);
891 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1 );
892 ok(ret == 1, "-o vs /m expected 1, got %d\n", ret);
894 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1 );
895 ok(ret == 3, "/m vs -o expected 3, got %d\n", ret);
897 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1 );
898 ok(ret == 3, "'o vs /m expected 3, got %d\n", ret);
900 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1 );
901 ok(ret == 1, "/m vs 'o expected 1, got %d\n", ret);
903 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1 );
904 ok(ret == 1, "'o vs /m expected 1, got %d\n", ret);
906 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1 );
907 ok(ret == 3, "/m vs 'o expected 3, got %d\n", ret);
909 if (0) { /* this requires collation table patch to make it MS compatible */
910 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
911 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
913 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
914 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
916 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
917 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
919 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
920 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
922 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
923 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
925 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
926 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
928 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
929 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
931 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
932 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
934 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
935 ok(ret == 1, "`o vs -m expected 1, got %d\n", ret);
937 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
938 ok(ret == 3, "-m vs `o expected 3, got %d\n", ret);
940 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
941 ok(ret == 3, "`o vs -m expected 3, got %d\n", ret);
943 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
944 ok(ret == 1, "-m vs `o expected 1, got %d\n", ret);
947 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9);
948 ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0 expected 2, got %d\n", ret);
950 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10);
951 ok(ret == 1, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1, got %d\n", ret);
953 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
954 ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0A expected 2, got %d\n", ret);
956 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
957 ok(ret == 2, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected 2, got %d\n", ret);
960 static void test_LCMapStringA(void)
963 char buf[256], buf2[256];
964 static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
965 static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
966 static const char symbols_stripped[] = "justateststring1";
968 SetLastError(0xdeadbeef);
969 ret = LCMapStringA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP | LCMAP_LOWERCASE,
970 lower_case, -1, buf, sizeof(buf));
971 ok(ret == lstrlenA(lower_case) + 1,
972 "ret %d, error %ld, expected value %d\n",
973 ret, GetLastError(), lstrlenA(lower_case) + 1);
974 ok(!memcmp(buf, lower_case, ret), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
976 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
977 upper_case, -1, buf, sizeof(buf));
978 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
979 ok(GetLastError() == ERROR_INVALID_FLAGS,
980 "unexpected error code %ld\n", GetLastError());
982 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
983 upper_case, -1, buf, sizeof(buf));
984 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
985 ok(GetLastError() == ERROR_INVALID_FLAGS,
986 "unexpected error code %ld\n", GetLastError());
988 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
989 upper_case, -1, buf, sizeof(buf));
990 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
991 ok(GetLastError() == ERROR_INVALID_FLAGS,
992 "unexpected error code %ld\n", GetLastError());
994 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
995 upper_case, -1, buf, sizeof(buf));
996 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
997 ok(GetLastError() == ERROR_INVALID_FLAGS,
998 "unexpected error code %ld\n", GetLastError());
1000 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1001 SetLastError(0xdeadbeef);
1002 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1003 upper_case, -1, buf, sizeof(buf));
1004 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError());
1005 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1007 /* test LCMAP_LOWERCASE */
1008 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1009 upper_case, -1, buf, sizeof(buf));
1010 ok(ret == lstrlenA(upper_case) + 1,
1011 "ret %d, error %ld, expected value %d\n",
1012 ret, GetLastError(), lstrlenA(upper_case) + 1);
1013 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1015 /* test LCMAP_UPPERCASE */
1016 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1017 lower_case, -1, buf, sizeof(buf));
1018 ok(ret == lstrlenA(lower_case) + 1,
1019 "ret %d, error %ld, expected value %d\n",
1020 ret, GetLastError(), lstrlenA(lower_case) + 1);
1021 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1023 /* test buffer overflow */
1024 SetLastError(0xdeadbeef);
1025 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1026 lower_case, -1, buf, 4);
1027 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1028 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1030 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1031 lstrcpyA(buf, lower_case);
1032 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1033 buf, -1, buf, sizeof(buf));
1034 if (!ret) /* Win9x */
1035 trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1038 ok(ret == lstrlenA(lower_case) + 1,
1039 "ret %d, error %ld, expected value %d\n",
1040 ret, GetLastError(), lstrlenA(lower_case) + 1);
1041 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1043 lstrcpyA(buf, upper_case);
1044 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1045 buf, -1, buf, sizeof(buf));
1046 if (!ret) /* Win9x */
1047 trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1050 ok(ret == lstrlenA(upper_case) + 1,
1051 "ret %d, error %ld, expected value %d\n",
1052 ret, GetLastError(), lstrlenA(lower_case) + 1);
1053 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1056 /* otherwise src == dst should fail */
1057 SetLastError(0xdeadbeef);
1058 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1059 buf, 10, buf, sizeof(buf));
1060 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1061 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1062 "unexpected error code %ld\n", GetLastError());
1063 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1065 /* test whether '\0' is always appended */
1066 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1067 upper_case, -1, buf, sizeof(buf));
1068 ok(ret, "LCMapStringA must succeed\n");
1069 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1070 upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1071 ok(ret, "LCMapStringA must succeed\n");
1072 ok(ret == ret2, "lengths of sort keys must be equal\n");
1073 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1075 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1076 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1077 upper_case, -1, buf, sizeof(buf));
1078 ok(ret, "LCMapStringA must succeed\n");
1079 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1080 lower_case, -1, buf2, sizeof(buf2));
1081 ok(ret2, "LCMapStringA must succeed\n");
1082 ok(ret == ret2, "lengths of sort keys must be equal\n");
1083 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1085 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1086 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1087 lower_case, -1, buf, sizeof(buf));
1088 ok(ret, "LCMapStringA must succeed\n");
1089 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1090 lower_case, -1, buf2, sizeof(buf2));
1091 ok(ret2, "LCMapStringA must succeed\n");
1092 ok(ret == ret2, "lengths of sort keys must be equal\n");
1093 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1095 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1096 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1097 lower_case, -1, buf, sizeof(buf));
1098 ok(ret, "LCMapStringA must succeed\n");
1099 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1100 symbols_stripped, -1, buf2, sizeof(buf2));
1101 ok(ret2, "LCMapStringA must succeed\n");
1102 ok(ret == ret2, "lengths of sort keys must be equal\n");
1103 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1105 /* test NORM_IGNORENONSPACE */
1106 lstrcpyA(buf, "foo");
1107 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1108 lower_case, -1, buf, sizeof(buf));
1109 ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1110 lstrlenA(lower_case) + 1, ret);
1111 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1113 /* test NORM_IGNORESYMBOLS */
1114 lstrcpyA(buf, "foo");
1115 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1116 lower_case, -1, buf, sizeof(buf));
1117 ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1118 lstrlenA(symbols_stripped) + 1, ret);
1119 ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1121 /* test srclen = 0 */
1122 SetLastError(0xdeadbeef);
1123 ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1124 ok(!ret, "LCMapStringA should fail with srclen = 0\n");
1125 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1126 "unexpected error code %ld\n", GetLastError());
1129 static void test_LCMapStringW(void)
1132 WCHAR buf[256], buf2[256];
1133 char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1134 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};
1135 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};
1136 static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
1137 static const WCHAR fooW[] = {'f','o','o',0};
1139 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1140 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1141 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1143 trace("Skipping LCMapStringW tests on Win9x\n");
1146 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1147 ok(GetLastError() == ERROR_INVALID_FLAGS,
1148 "unexpected error code %ld\n", GetLastError());
1150 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1151 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1152 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1153 ok(GetLastError() == ERROR_INVALID_FLAGS,
1154 "unexpected error code %ld\n", GetLastError());
1156 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1157 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1158 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1159 ok(GetLastError() == ERROR_INVALID_FLAGS,
1160 "unexpected error code %ld\n", GetLastError());
1162 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1163 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1164 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1165 ok(GetLastError() == ERROR_INVALID_FLAGS,
1166 "unexpected error code %ld\n", GetLastError());
1168 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1169 SetLastError(0xdeadbeef);
1170 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1171 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1172 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError());
1173 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1175 /* test LCMAP_LOWERCASE */
1176 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1177 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1178 ok(ret == lstrlenW(upper_case) + 1,
1179 "ret %d, error %ld, expected value %d\n",
1180 ret, GetLastError(), lstrlenW(upper_case) + 1);
1181 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1183 /* test LCMAP_UPPERCASE */
1184 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1185 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1186 ok(ret == lstrlenW(lower_case) + 1,
1187 "ret %d, error %ld, expected value %d\n",
1188 ret, GetLastError(), lstrlenW(lower_case) + 1);
1189 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1191 /* test buffer overflow */
1192 SetLastError(0xdeadbeef);
1193 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1194 lower_case, -1, buf, 4);
1195 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1196 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1198 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1199 lstrcpyW(buf, lower_case);
1200 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1201 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1202 ok(ret == lstrlenW(lower_case) + 1,
1203 "ret %d, error %ld, expected value %d\n",
1204 ret, GetLastError(), lstrlenW(lower_case) + 1);
1205 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1207 lstrcpyW(buf, upper_case);
1208 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1209 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1210 ok(ret == lstrlenW(upper_case) + 1,
1211 "ret %d, error %ld, expected value %d\n",
1212 ret, GetLastError(), lstrlenW(lower_case) + 1);
1213 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1215 /* otherwise src == dst should fail */
1216 SetLastError(0xdeadbeef);
1217 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1218 buf, 10, buf, sizeof(buf));
1219 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1220 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1221 "unexpected error code %ld\n", GetLastError());
1222 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1224 /* test whether '\0' is always appended */
1225 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1226 upper_case, -1, buf, sizeof(buf));
1227 ok(ret, "LCMapStringW must succeed\n");
1228 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1229 upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1230 ok(ret, "LCMapStringW must succeed\n");
1231 ok(ret == ret2, "lengths of sort keys must be equal\n");
1232 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1234 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1235 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1236 upper_case, -1, buf, sizeof(buf));
1237 ok(ret, "LCMapStringW must succeed\n");
1238 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1239 lower_case, -1, buf2, sizeof(buf2));
1240 ok(ret2, "LCMapStringW must succeed\n");
1241 ok(ret == ret2, "lengths of sort keys must be equal\n");
1242 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1244 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1245 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1246 lower_case, -1, buf, sizeof(buf));
1247 ok(ret, "LCMapStringW must succeed\n");
1248 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1249 lower_case, -1, buf2, sizeof(buf2));
1250 ok(ret2, "LCMapStringW must succeed\n");
1251 ok(ret == ret2, "lengths of sort keys must be equal\n");
1252 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1254 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1255 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1256 lower_case, -1, buf, sizeof(buf));
1257 ok(ret, "LCMapStringW must succeed\n");
1258 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1259 symbols_stripped, -1, buf2, sizeof(buf2));
1260 ok(ret2, "LCMapStringW must succeed\n");
1261 ok(ret == ret2, "lengths of sort keys must be equal\n");
1262 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1264 /* test NORM_IGNORENONSPACE */
1265 lstrcpyW(buf, fooW);
1266 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1267 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1268 ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1269 lstrlenW(lower_case) + 1, ret);
1270 ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1272 /* test NORM_IGNORESYMBOLS */
1273 lstrcpyW(buf, fooW);
1274 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1275 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1276 ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1277 lstrlenW(symbols_stripped) + 1, ret);
1278 ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1280 /* test srclen = 0 */
1281 SetLastError(0xdeadbeef);
1282 ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1283 ok(!ret, "LCMapStringW should fail with srclen = 0\n");
1284 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1285 "unexpected error code %ld\n", GetLastError());
1288 /* this requires collation table patch to make it MS compatible */
1289 const char *strings_sorted[] =
1321 const char *strings[] =
1353 static int compare_string1(const void *e1, const void *e2)
1355 const char *s1 = *(const char **)e1;
1356 const char *s2 = *(const char **)e2;
1358 return lstrcmpA(s1, s2);
1361 static int compare_string2(const void *e1, const void *e2)
1363 const char *s1 = *(const char **)e1;
1364 const char *s2 = *(const char **)e2;
1366 return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1369 static int compare_string3(const void *e1, const void *e2)
1371 const char *s1 = *(const char **)e1;
1372 const char *s2 = *(const char **)e2;
1373 char key1[256], key2[256];
1375 LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
1376 LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
1377 return strcmp(key1, key2);
1380 static void test_sorting(void)
1383 char **str_buf = (char **)buf;
1386 assert(sizeof(buf) >= sizeof(strings));
1388 /* 1. sort using lstrcmpA */
1389 memcpy(buf, strings, sizeof(strings));
1390 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
1391 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1393 ok(!strcmp(strings_sorted[i], str_buf[i]),
1394 "qsort using lstrcmpA failed for element %d\n", i);
1396 /* 2. sort using CompareStringA */
1397 memcpy(buf, strings, sizeof(strings));
1398 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
1399 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1401 ok(!strcmp(strings_sorted[i], str_buf[i]),
1402 "qsort using CompareStringA failed for element %d\n", i);
1404 /* 3. sort using sort keys */
1405 memcpy(buf, strings, sizeof(strings));
1406 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
1407 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1409 ok(!strcmp(strings_sorted[i], str_buf[i]),
1410 "qsort using sort keys failed for element %d\n", i);
1414 static void test_FoldStringA(void)
1417 char src[256], dst[256];
1418 static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0' };
1419 static const char digits_dst[] = { '1','2','3','\0' };
1420 static const char composite_src[] =
1422 0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
1423 0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
1424 0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
1425 0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
1426 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
1427 0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
1428 0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
1429 0xfb,0xfc,0xfd,0xff,'\0'
1431 static const char composite_dst[] =
1433 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1434 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1435 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1436 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1437 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1438 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1439 0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
1440 0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
1441 0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
1442 0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
1443 0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
1444 0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
1445 0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
1446 0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
1447 0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1449 static const char ligatures_src[] =
1451 0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1453 static const char ligatures_dst[] =
1455 'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1459 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1461 /* these tests are locale specific */
1462 if (GetACP() != 1252)
1464 trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1468 /* MAP_FOLDDIGITS */
1470 ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
1471 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1473 EXPECT_LEN(4); EXPECT_VALID;
1474 ok(strcmp(dst, digits_dst) == 0,
1475 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
1476 for (i = 1; i < 256; i++)
1478 if (!strchr(digits_src, i))
1483 ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
1484 EXPECT_LEN(2); EXPECT_VALID;
1485 ok(dst[0] == src[0],
1486 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
1490 /* MAP_EXPAND_LIGATURES */
1492 ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1493 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1494 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1495 EXPECT_LEN(sizeof(ligatures_dst)); EXPECT_VALID;
1496 ok(strcmp(dst, ligatures_dst) == 0,
1497 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
1498 for (i = 1; i < 256; i++)
1500 if (!strchr(ligatures_src, i))
1505 ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1506 EXPECT_LEN(2); EXPECT_VALID;
1507 ok(dst[0] == src[0],
1508 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
1515 ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
1519 /* Wine gets close, but doesn't produce quite the same result as native */
1521 ok(strcmp(dst, composite_dst) == 0,
1522 "MAP_COMPOSITE: Expected '%s', got '%s'\n", composite_dst, dst);
1525 for (i = 1; i < 256; i++)
1527 if (!strchr(composite_src, i))
1532 ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
1533 EXPECT_LEN(2); EXPECT_VALID;
1534 ok(dst[0] == src[0],
1535 "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
1536 (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
1541 for (i = 1; i < 256; i++)
1546 ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
1547 EXPECT_LEN(2); EXPECT_VALID;
1548 ok(src[0] == dst[0],
1549 "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
1550 (unsigned char)src[0], (unsigned char)dst[0]);
1553 /* MAP_PRECOMPOSED */
1554 for (i = 1; i < 256; i++)
1559 ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
1560 EXPECT_LEN(2); EXPECT_VALID;
1561 ok(src[0] == dst[0],
1562 "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
1563 (unsigned char)src[0], (unsigned char)dst[0]);
1567 static void test_FoldStringW(void)
1571 WCHAR src[256], dst[256], ch, prev_ch = 1;
1572 static const DWORD badFlags[] =
1575 MAP_PRECOMPOSED|MAP_COMPOSITE,
1576 MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
1577 MAP_COMPOSITE|MAP_EXPAND_LIGATURES
1579 /* Ranges of digits 0-9 : Must be sorted! */
1580 static const WCHAR digitRanges[] =
1582 0x0030, /* '0'-'9' */
1583 0x0660, /* Eastern Arabic */
1584 0x06F0, /* Arabic - Hindu */
1585 0x0966, /* Devengari */
1586 0x09E6, /* Bengalii */
1587 0x0A66, /* Gurmukhi */
1588 0x0AE6, /* Gujarati */
1590 0x0BE6, /* Tamil - No 0 */
1591 0x0C66, /* Telugu */
1592 0x0CE6, /* Kannada */
1593 0x0D66, /* Maylayalam */
1596 0x2070, /* Superscript - 1, 2, 3 are out of sequence */
1597 0x2080, /* Subscript */
1598 0x245F, /* Circled - 0 is out of sequence */
1599 0x2473, /* Bracketed */
1600 0x2487, /* Full stop */
1601 0x2775, /* Inverted circled - No 0 */
1602 0x277F, /* Patterned circled - No 0 */
1603 0x2789, /* Inverted Patterned circled - No 0 */
1604 0xff10, /* Pliene chasse (?) */
1605 0xffff /* Terminator */
1607 /* Digits which are represented, but out of sequence */
1608 static const WCHAR outOfSequenceDigits[] =
1610 0xB9, /* Superscript 1 */
1611 0xB2, /* Superscript 2 */
1612 0xB3, /* Superscript 3 */
1613 0x24EA, /* Circled 0 */
1614 '\0' /* Terminator */
1616 /* Digits in digitRanges for which no representation is available */
1617 static const WCHAR noDigitAvailable[] =
1619 0x0BE6, /* No Tamil 0 */
1620 0x2473, /* No Bracketed 0 */
1621 0x2487, /* No 0 Full stop */
1622 0x2775, /* No inverted circled 0 */
1623 0x277F, /* No patterned circled */
1624 0x2789, /* No inverted Patterned circled */
1625 '\0' /* Terminator */
1627 /* Compatibility conversion results */
1628 static const WCHAR compat_F900_FA2F[256+48] =
1630 0x8c48, 0x66f4, 0x8eca, 0x8cc8, 0x6ed1, 0x4e32, 0x53e5, 0x9f9c,
1631 0x9f9c, 0x5951, 0x91d1, 0x5587, 0x5948, 0x61f6, 0x7669, 0x7f85,
1632 0x863f, 0x87ba, 0x88f8, 0x908f, 0x6a02, 0x6d1b, 0x70d9, 0x73de,
1633 0x843d, 0x916a, 0x99f1, 0x4e82, 0x5375, 0x6b04, 0x721b, 0x862d,
1634 0x9e1e, 0x5d50, 0x6feb, 0x85cd, 0x8964, 0x62c9, 0x81d8, 0x881f,
1635 0x5eca, 0x6717, 0x6d6a, 0x72fc, 0x0000, 0x4f86, 0x51b7, 0x52de,
1636 0x64c4, 0x6ad3, 0x7210, 0x76e7, 0x8001, 0x8606, 0x865c, 0x8def,
1637 0x9732, 0x9b6f, 0x9dfa, 0x788c, 0x797f, 0x7da0, 0x83c9, 0x9304,
1638 0x9e7f, 0x8ad6, 0x58df, 0x5f04, 0x7c60, 0x807e, 0x7262, 0x78ca,
1639 0x8cc2, 0x96f7, 0x58d8, 0x5c62, 0x6a13, 0x6dda, 0x6f0f, 0x7d2f,
1640 0x7e37, 0x964b, 0x52d2, 0x808b, 0x51dc, 0x51cc, 0x7a1c, 0x7dbe,
1641 0x83f1, 0x9675, 0x8b80, 0x62cf, 0x6a02, 0x8afe, 0x4e39, 0x5be7,
1642 0x6012, 0x7387, 0x7570, 0x5317, 0x78fb, 0x4fbf, 0x5fa9, 0x4e0d,
1643 0x6ccc, 0x6578, 0x7d22, 0x53c3, 0x585e, 0x7701, 0x8449, 0x8aaa,
1644 0x6bba, 0x8fb0, 0x6c88, 0x62fe, 0x82e5, 0x63a0, 0x7565, 0x4eae,
1645 0x5169, 0x0000, 0x6881, 0x7ce7, 0x826f, 0x8ad2, 0x91cf, 0x52f5,
1646 0x5442, 0x5973, 0x5eec, 0x65c5, 0x6ffe, 0x792a, 0x95ad, 0x9a6a,
1647 0x9e97, 0x9ece, 0x529b, 0x66c6, 0x6b77, 0x8f62, 0x5e74, 0x6190,
1648 0x6200, 0x649a, 0x6f23, 0x7149, 0x7489, 0x0000, 0x7df4, 0x806f,
1649 0x8f26, 0x84ee, 0x9023, 0x934a, 0x5217, 0x52a3, 0x54bd, 0x70c8,
1650 0x88c2, 0x8aaa, 0x5ec9, 0x5ff5, 0x637b, 0x6bae, 0x7c3e, 0x7375,
1651 0x4ee4, 0x56f9, 0x5be7, 0x5dba, 0x601c, 0x73b2, 0x7469, 0x7f9a,
1652 0x8046, 0x9234, 0x96f6, 0x9748, 0x9818, 0x4f8b, 0x79ae, 0x91b4,
1653 0x96b8, 0x60e1, 0x4e86, 0x50da, 0x5bee, 0x5c3f, 0x6599, 0x6a02,
1654 0x71ce, 0x7642, 0x84fc, 0x907c, 0x9f8d, 0x6688, 0x962e, 0x5289,
1655 0x677b, 0x67f3, 0x6d41, 0x6e9c, 0x7409, 0x7559, 0x786b, 0x7d10,
1656 0x985e, 0x516d, 0x622e, 0x9678, 0x502b, 0x5d19, 0x6dea, 0x8f2a,
1657 0x5f8b, 0x6144, 0x6817, 0x7387, 0x9686, 0x5229, 0x540f, 0x5c65,
1658 0x6613, 0x674e, 0x68a8, 0x6ce5, 0x7406, 0x75e2, 0x7f79, 0x0000,
1659 0x88e1, 0x91cc, 0x96e2, 0x533f, 0x6eba, 0x541d, 0x71d0, 0x7498,
1660 0x85fa, 0x0000, 0x9c57, 0x9e9f, 0x6797, 0x6dcb, 0x81e8, 0x7acb,
1661 0x7b20, 0x7c92, 0x72c0, 0x7099, 0x8b58, 0x4ec0, 0x8336, 0x523a,
1662 0x5207, 0x5ea6, 0x62d3, 0x7cd6, 0x5b85, 0x6d1e, 0x66b4, 0x8f3b,
1663 0x884c, 0x964d, 0x898b, 0x5ed3, 0x0000, 0x0000, 0x0000, 0x0000,
1664 0x585a, 0x0000, 0x6674, 0x0000, 0x0000, 0x51de, 0x8c6c, 0x76ca,
1665 0x0000, 0x795e, 0x7965, 0x798f, 0x9756, 0x7cbe, 0x7fbd, 0x0000,
1666 0x0000, 0x0000, 0x8af8, 0x0000, 0x0000, 0x9038, 0x90fd, 0x0000,
1667 0x0000, 0x0000, 0x98ef, 0x98fc, 0x9928, 0x9db4, 0x0000, 0x0000
1669 static const WCHAR compat_FE30_FEF7[200] =
1671 0x2025, 0x2014, 0x2013, 0x005f, 0x005f, 0x0028, 0x0029, 0x007b,
1672 0x007d, 0x3014, 0x3015, 0x3010, 0x3011, 0x300a, 0x300b, 0x3008,
1673 0x3009, 0x300c, 0x300d, 0x300e, 0x300f, 0x0000, 0x0000, 0x0000,
1674 0x0000, 0x203e, 0x203e, 0x203e, 0x203e, 0x005f, 0x005f, 0x005f,
1675 0x002c, 0x3001, 0x002e, 0x0000, 0x003b, 0x003a, 0x003f, 0x0021,
1676 0x2014, 0x0028, 0x0029, 0x007b, 0x007d, 0x3014, 0x3015, 0x0023,
1677 0x0026, 0x002a, 0x002b, 0x002d, 0x003c, 0x003e, 0x003d, 0x0000,
1678 0x0000, 0x0024, 0x0025, 0x0040, 0x0000, 0x0000, 0x0000, 0x0000,
1679 0x064b, 0x064b, 0x064c, 0x0000, 0x064d, 0x0000, 0x064e, 0x064e,
1680 0x064f, 0x064f, 0x0650, 0x0650, 0x0651, 0x0651, 0x0652, 0x0652,
1681 0x0621, 0x0622, 0x0622, 0x0623, 0x0623, 0x0624, 0x0624, 0x0625,
1682 0x0625, 0x0626, 0x0626, 0x0626, 0x0626, 0x0627, 0x0627, 0x0628,
1683 0x0628, 0x0628, 0x0628, 0x0629, 0x0629, 0x062a, 0x062a, 0x062a,
1684 0x062a, 0x062b, 0x062b, 0x062b, 0x062b, 0x062c, 0x062c, 0x062c,
1685 0x062c, 0x062d, 0x062d, 0x062d, 0x062d, 0x062e, 0x062e, 0x062e,
1686 0x062e, 0x062f, 0x062f, 0x0630, 0x0630, 0x0631, 0x0631, 0x0632,
1687 0x0632, 0x0633, 0x0633, 0x0633, 0x0633, 0x0634, 0x0634, 0x0634,
1688 0x0634, 0x0635, 0x0635, 0x0635, 0x0635, 0x0636, 0x0636, 0x0636,
1689 0x0636, 0x0637, 0x0637, 0x0637, 0x0637, 0x0638, 0x0638, 0x0638,
1690 0x0638, 0x0639, 0x0639, 0x0639, 0x0639, 0x063a, 0x063a, 0x063a,
1691 0x063a, 0x0641, 0x0641, 0x0641, 0x0641, 0x0642, 0x0642, 0x0642,
1692 0x0642, 0x0643, 0x0643, 0x0643, 0x0643, 0x0644, 0x0644, 0x0644,
1693 0x0644, 0x0645, 0x0645, 0x0645, 0x0645, 0x0646, 0x0646, 0x0646,
1694 0x0646, 0x0647, 0x0647, 0x0647, 0x0647, 0x0648, 0x0648, 0x0649,
1695 0x0649, 0x064a, 0x064a, 0x064a, 0x064a, 0x0000, 0x0000, 0x0000
1697 static const WCHAR compat_FF00_FFEF[240] =
1699 0x0000, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
1700 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
1701 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
1702 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
1703 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
1704 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
1705 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
1706 0x0058, 0x0059, 0x005a, 0x005b, 0x0000, 0x005d, 0x005e, 0x005f,
1707 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
1708 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
1709 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
1710 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000,
1711 0x0000, 0x3002, 0x300c, 0x300d, 0x3001, 0x30fb, 0x30f2, 0x30a1,
1712 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, 0x30c3,
1713 0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, 0x30ab, 0x30ad,
1714 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, 0x30b9, 0x30bb, 0x30bd,
1715 0x30bf, 0x30c1, 0x30c4, 0x30c6, 0x30c8, 0x30ca, 0x30cb, 0x30cc,
1716 0x30cd, 0x30ce, 0x30cf, 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de,
1717 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9,
1718 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c,
1719 0x3164, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137,
1720 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f,
1721 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147,
1722 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x0000,
1723 0x0000, 0x0000, 0x314f, 0x3150, 0x3151, 0x3152, 0x3153, 0x3154,
1724 0x0000, 0x0000, 0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315a,
1725 0x0000, 0x0000, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, 0x3160,
1726 0x0000, 0x0000, 0x3161, 0x3162, 0x3163, 0x0000, 0x0000, 0x0000,
1727 0x00a2, 0x00a3, 0x00ac, 0x00af, 0x00a6, 0x00a5, 0x20a9, 0x0000,
1728 0x2502, 0x2190, 0x2191, 0x2192, 0x2193, 0x25a0, 0x25cb, 0x0000
1730 static const WCHAR ligatures_src[] =
1732 0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
1733 0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
1734 0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
1735 0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
1736 0xfb04, 0xfb05, 0xfb06, '\0'
1738 static const WCHAR ligatures_dst[] =
1740 'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
1741 'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
1742 'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
1743 0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
1744 'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
1748 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1750 /* Invalid flag combinations */
1751 for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
1753 src[0] = dst[0] = '\0';
1755 ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
1756 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1758 EXPECT_LEN(0); EXPECT_FLAGS;
1761 /* src & dst cannot be the same */
1763 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
1764 EXPECT_LEN(0); EXPECT_INVALID;
1766 /* src can't be NULL */
1768 ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
1769 EXPECT_LEN(0); EXPECT_INVALID;
1771 /* srclen can't be 0 */
1773 ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
1774 EXPECT_LEN(0); EXPECT_INVALID;
1776 /* dstlen can't be < 0 */
1778 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
1779 EXPECT_LEN(0); EXPECT_INVALID;
1781 /* Ret includes terminating NUL which is appended if srclen = -1 */
1786 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
1787 EXPECT_LEN(2); EXPECT_VALID;
1788 ok(dst[0] == 'A' && dst[1] == '\0',
1789 "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%ld\n",
1790 'A', '\0', ret, dst[0], dst[1], GetLastError());
1792 /* If size is given, result is not NUL terminated */
1798 ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
1799 EXPECT_LEN(1); EXPECT_VALID;
1800 ok(dst[0] == 'A' && dst[1] == 'X',
1801 "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%ld\n",
1802 'A','X', ret, dst[0], dst[1], GetLastError());
1804 /* MAP_FOLDDIGITS */
1805 for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
1807 /* Check everything before this range */
1808 for (ch = prev_ch; ch < digitRanges[j]; ch++)
1812 src[1] = dst[0] = '\0';
1813 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
1814 EXPECT_LEN(2); EXPECT_VALID;
1816 ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
1817 /* Wine (correctly) maps all Unicode 4.0+ digits */
1818 isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF,
1819 "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
1822 if (digitRanges[j] == 0xffff)
1823 break; /* Finished the whole code point space */
1825 for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
1829 /* Map out of sequence characters */
1830 if (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
1831 else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
1832 else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
1833 else if (ch == 0x245F) c = 0x24EA; /* Circled 0 */
1837 src[1] = dst[0] = '\0';
1838 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
1839 EXPECT_LEN(2); EXPECT_VALID;
1841 ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
1842 strchrW(noDigitAvailable, c),
1843 "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
1844 ch, '0' + digitRanges[j] - ch, dst[0]);
1850 for (ch = 1; ch <0xffff; ch++)
1854 if (ch >= 0xF900 && ch <= 0xFA2F)
1855 expected = compat_F900_FA2F[ch - 0xF900];
1856 else if (ch >= 0xFE30 && ch <= 0xFEF7)
1857 expected = compat_FE30_FEF7[ch - 0xFE30];
1858 else if (ch >= 0xFF00 && ch <= 0xFFEF)
1859 expected = compat_FF00_FFEF[ch - 0xFF00];
1866 src[1] = dst[0] = '\0';
1867 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
1868 EXPECT_LEN(2); EXPECT_VALID;
1869 ok(dst[0] == expected ||
1870 /* Wine (correctly) uses updated mappings for some Unicode 4.0 chars */
1871 (ch >= 0xFA0D && ch <= 0xFA47) ||
1872 0xf92c || ch == 0xf979 || ch == 0xf995 || ch == 0xf9e7 || ch == 0xf9f1,
1873 "MAP_FOLDCZONE: ch %d 0x%04x Expected 0x%04x got 0x%04x\n",
1874 ch, ch, expected, dst[0]);
1877 /* MAP_EXPAND_LIGATURES */
1879 ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1880 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1881 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1882 EXPECT_LEN(sizeof(ligatures_dst)/sizeof(ligatures_dst[0])); EXPECT_VALID;
1883 ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
1884 "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
1885 for (i = 1; i <= 0xffff; i++)
1887 if (!strchrW(ligatures_src, i))
1892 ret = pFoldStringW(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1893 EXPECT_LEN(2); EXPECT_VALID;
1894 ok(dst[0] == src[0],
1895 "MAP_EXPAND_LIGATURES: 0x%02x : Expected 0x%02x, got 0x%02x\n",
1901 /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
1906 #define LCID_OK(l) \
1907 ok(lcid == l, "Expected lcid = %08lx, got %08lx\n", l, lcid)
1908 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
1909 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
1910 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
1911 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
1913 static void test_ConvertDefaultLocale(void)
1917 /* Doesn't change lcid, even if non default sublang/sort used */
1918 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_US, SORT_DEFAULT);
1919 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_UK, SORT_DEFAULT);
1920 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT);
1921 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE);
1923 /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
1924 LCID_RES(MKLCID(LANG_ENGLISH, SUBLANG_NEUTRAL, SORT_DEFAULT),
1925 MKLCID(LANG_ENGLISH, SUBLANG_DEFAULT, SORT_DEFAULT));
1926 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
1927 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
1928 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_JAPANESE_UNICODE),
1929 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE));
1931 /* Invariant language is not treated specially */
1932 TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
1933 LCID_RES(MKLCID(LANG_INVARIANT, SUBLANG_NEUTRAL, SORT_DEFAULT),
1934 MKLCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT));
1936 /* User/system default languages alone are not mapped */
1937 TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
1938 TEST_LCIDLANG(LANG_USER_DEFAULT, SORT_JAPANESE_UNICODE);
1941 LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
1942 LCID_RES(LOCALE_USER_DEFAULT, GetUserDefaultLCID());
1943 LCID_RES(LOCALE_NEUTRAL, GetUserDefaultLCID());
1946 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
1947 DWORD dwFlags, LONG_PTR lParam)
1949 trace("%08lx, %s, %s, %08lx, %08lx\n",
1950 lgrpid, lpszNum, lpszName, dwFlags, lParam);
1952 ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
1953 "Enumerated grp %ld not valid (flags %ld)\n", lgrpid, dwFlags);
1955 /* If lParam is one, we are calling with flags defaulted from 0 */
1956 ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
1957 "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %ld\n", dwFlags);
1962 static void test_EnumSystemLanguageGroupsA(void)
1964 if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
1967 /* No enumeration proc */
1969 pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
1974 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
1977 /* No flags - defaults to LGRPID_INSTALLED */
1979 pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
1982 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
1983 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
1987 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
1990 trace("%08lx, %08lx, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
1992 ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
1993 "Enumerated grp %ld not valid\n", lgrpid);
1994 ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
1995 "Enumerated grp locale %ld not valid\n", lcid);
1999 static void test_EnumLanguageGroupLocalesA(void)
2001 if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
2004 /* No enumeration proc */
2006 pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
2009 /* lgrpid too small */
2011 pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
2014 /* lgrpid too big */
2016 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
2019 /* dwFlags is reserved */
2021 pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
2024 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2027 static void test_SetLocaleInfoA(void)
2030 LCID lcid = GetUserDefaultLCID();
2034 bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2039 bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
2044 bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
2048 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2050 trace("%s %08lx\n", value, lParam);
2054 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2056 ok(!enumCount, "callback called again unexpected\n");
2061 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2063 ok(0,"callback called unexpected\n");
2067 static void test_EnumUILanguageA(void)
2070 if (!pEnumUILanguagesA) {
2071 trace("EnumUILanguagesA is not available on Win9x\n");
2075 SetLastError(ERROR_SUCCESS);
2076 ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2077 EXPECT_TRUE; EXPECT_VALID;
2080 SetLastError(ERROR_SUCCESS);
2081 ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2082 EXPECT_TRUE; EXPECT_VALID;
2084 SetLastError(ERROR_SUCCESS);
2085 ret = pEnumUILanguagesA(NULL, 0, 0);
2086 EXPECT_FALSE; EXPECT_INVALID;
2088 SetLastError(ERROR_SUCCESS);
2089 ret = pEnumUILanguagesA(luilocale_proc3A, 0x5a5a5a5a, 0);
2090 EXPECT_FALSE; EXPECT_FLAGS;
2092 SetLastError(ERROR_SUCCESS);
2093 ret = pEnumUILanguagesA(NULL, 0x5a5a5a5a, 0);
2094 EXPECT_FALSE; EXPECT_INVALID;
2099 InitFunctionPointers();
2101 if (0) test_EnumTimeFormats();
2103 test_GetLocaleInfoA();
2104 test_GetTimeFormatA();
2105 test_GetDateFormatA();
2106 test_GetDateFormatW();
2107 test_GetCurrencyFormatA(); /* Also tests the W version */
2108 test_GetNumberFormatA(); /* Also tests the W version */
2109 test_CompareStringA();
2110 test_LCMapStringA();
2111 test_LCMapStringW();
2114 test_ConvertDefaultLocale();
2115 test_EnumSystemLanguageGroupsA();
2116 test_EnumLanguageGroupLocalesA();
2117 test_SetLocaleInfoA();
2118 test_EnumUILanguageA();
2120 /* this requires collation table patch to make it MS compatible */
2121 if (0) test_sorting();