kernel32: Renamed the kernel directory to kernel32.
[wine/multimedia.git] / dlls / kernel32 / tests / locale.c
blob565f9980aedb6538a62c52d08f3c4ad377b5b288
1 /*
2 * Unit tests for locale functions
4 * Copyright 2002 YASAR Mehmet
5 * Copyright 2003 Dmitry Timoshkov
6 * Copyright 2003 Jon Griffiths
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 * NOTES
23 * We must pass LOCALE_NOUSEROVERRIDE (NUO) to formatting functions so that
24 * even when the user has overridden their default i8n settings (e.g. in
25 * the control panel i8n page), we will still get the expected results.
28 #include <assert.h>
29 #include <stdlib.h>
30 #include <stdarg.h>
32 #include "wine/test.h"
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winerror.h"
36 #include "winnls.h"
38 static inline unsigned int strlenW( const WCHAR *str )
40 const WCHAR *s = str;
41 while (*s) s++;
42 return s - str;
45 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
47 if (n <= 0) return 0;
48 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
49 return *str1 - *str2;
52 static inline WCHAR *strchrW( const WCHAR *str, WCHAR ch )
54 do { if (*str == ch) return (WCHAR *)str; } while (*str++);
55 return NULL;
58 inline static int isdigitW( WCHAR wc )
60 WORD type;
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,
70 DWORD, LONG_PTR);
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,
76 DWORD, LONG_PTR);
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");
91 if (hKernel32)
93 pEnumSystemLanguageGroupsA = (void*)GetProcAddress(hKernel32, "EnumSystemLanguageGroupsA");
94 pEnumLanguageGroupLocalesA = (void*)GetProcAddress(hKernel32, "EnumLanguageGroupLocalesA");
95 pFoldStringA = (void*)GetProcAddress(hKernel32, "FoldStringA");
96 pFoldStringW = (void*)GetProcAddress(hKernel32, "FoldStringW");
97 pIsValidLanguageGroup = (void*)GetProcAddress(hKernel32, "IsValidLanguageGroup");
98 pEnumUILanguagesA = (void*)GetProcAddress(hKernel32, "EnumUILanguagesA");
102 #define eq(received, expected, label, type) \
103 ok((received) == (expected), "%s: got " type " instead of " type "\n", \
104 (label), (received), (expected))
106 #define BUFFER_SIZE 128
107 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
109 #define EXPECT_LEN(len) ok(ret == (len), "Expected Len %d, got %d\n", (int)(len), ret)
110 #define EXPECT_INVALID ok(GetLastError() == ERROR_INVALID_PARAMETER, \
111 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError())
112 #define EXPECT_BUFFER ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, \
113 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError())
114 #define EXPECT_FLAGS ok(GetLastError() == ERROR_INVALID_FLAGS, \
115 "Expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError())
116 #define EXPECT_INVALIDFLAGS ok(GetLastError() == ERROR_INVALID_FLAGS || \
117 GetLastError() == ERROR_INVALID_PARAMETER, \
118 "Expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError())
119 #define EXPECT_VALID ok(GetLastError() == 0, \
120 "Expected GetLastError() == 0, got %ld\n", GetLastError())
122 #define STRINGSA(x,y) strcpy(input, x); strcpy(Expected, y); SetLastError(0); buffer[0] = '\0'
123 #define EXPECT_LENA EXPECT_LEN((int)strlen(Expected)+1)
124 #define EXPECT_EQA ok(strncmp(buffer, Expected, strlen(Expected)) == 0, \
125 "Expected '%s', got '%s'\n", Expected, buffer)
127 #define STRINGSW(x,y) MultiByteToWideChar(CP_ACP,0,x,-1,input,COUNTOF(input)); \
128 MultiByteToWideChar(CP_ACP,0,y,-1,Expected,COUNTOF(Expected)); \
129 SetLastError(0); buffer[0] = '\0'
130 #define EXPECT_LENW EXPECT_LEN((int)strlenW(Expected)+1)
131 #define EXPECT_EQW ok(strncmpW(buffer, Expected, strlenW(Expected)) == 0, "Bad conversion\n")
132 #define EXPECT_FALSE ok(FALSE == ret, "Expected return value FALSE, got TRUE\n")
133 #define EXPECT_TRUE ok(FALSE != ret, "Expected return value TRUE, got FALSE\n")
135 #define NUO LOCALE_NOUSEROVERRIDE
137 static void test_GetLocaleInfoA(void)
139 int ret;
140 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
141 char buffer[BUFFER_SIZE];
143 ok(lcid == 0x409, "wrong LCID calculated - %ld\n", lcid);
145 /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
146 * partially fill the buffer even if it is too short. See bug 637.
148 SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
149 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 0);
150 ok(ret == 7 && !buffer[0], "Expected len=7, got %d\n", ret);
152 SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
153 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 3);
154 EXPECT_BUFFER; EXPECT_LEN(0);
155 ok(!strcmp(buffer, "Mon"), "Expected 'Mon', got '%s'\n", buffer);
157 SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
158 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 10);
159 EXPECT_VALID; EXPECT_LEN(7);
160 ok(!strcmp(buffer, "Monday"), "Expected 'Monday', got '%s'\n", buffer);
163 static void test_GetTimeFormatA(void)
165 int ret;
166 SYSTEMTIME curtime;
167 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
168 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
170 memset(&curtime, 2, sizeof(SYSTEMTIME));
171 STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
172 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
173 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
175 curtime.wHour = 8;
176 curtime.wMinute = 56;
177 curtime.wSecond = 13;
178 curtime.wMilliseconds = 22;
179 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
180 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
181 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
183 STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficent buffer */
184 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, 2);
185 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
187 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
188 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, NULL, 0);
189 EXPECT_VALID; EXPECT_LENA;
191 STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
192 ret = GetTimeFormatA(lcid, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
193 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
195 STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
196 ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
197 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
199 STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
200 ret = GetTimeFormatA(lcid, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
201 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
203 STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
204 strcpy(Expected, "8:56 AM");
205 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
206 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
208 STRINGSA("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
209 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
210 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
212 STRINGSA("s1s2s3", ""); /* Duplicate tokens */
213 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
214 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
216 STRINGSA("t/tt", "A/AM"); /* AM time marker */
217 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
218 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
220 curtime.wHour = 13;
221 STRINGSA("t/tt", "P/PM"); /* PM time marker */
222 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
223 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
225 STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
226 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
227 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
229 STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
230 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
231 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
233 STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
234 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
235 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
237 curtime.wHour = 14; /* change this to 14 or 2pm */
238 curtime.wMinute = 5;
239 curtime.wSecond = 3;
240 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 */
241 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
242 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
244 curtime.wHour = 0;
245 STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
246 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
247 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
249 STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
250 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
251 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
253 /* try to convert formatting strings with more than two letters
254 * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
255 * NOTE: We expect any letter for which there is an upper case value
256 * we should see a replacement. For letters that DO NOT have
257 * upper case values we should see NO REPLACEMENT.
259 curtime.wHour = 8;
260 curtime.wMinute = 56;
261 curtime.wSecond = 13;
262 curtime.wMilliseconds = 22;
263 STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
264 "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
265 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
266 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
268 STRINGSA("h", "text"); /* Don't write to buffer if len is 0 */
269 strcpy(buffer, "text");
270 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, 0);
271 EXPECT_VALID; EXPECT_LEN(2); EXPECT_EQA;
273 STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
274 "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
275 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
276 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
278 STRINGSA("'''", "'"); /* invalid quoted string */
279 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
280 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
282 /* test that msdn suggested single quotation usage works as expected */
283 STRINGSA("''''", "'"); /* single quote mark */
284 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
285 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
287 STRINGSA("''HHHHHH", "08"); /* Normal use */
288 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
289 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
291 /* and test for normal use of the single quotation mark */
292 STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
293 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
294 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
296 STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
297 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
298 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
300 STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
301 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
302 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
304 curtime.wHour = 25;
305 STRINGSA("'123'tt", ""); /* Invalid time */
306 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
307 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
309 curtime.wHour = 12;
310 curtime.wMonth = 60; /* Invalid */
311 STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
312 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
313 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
316 static void test_GetDateFormatA(void)
318 int ret;
319 SYSTEMTIME curtime;
320 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
321 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
323 memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
324 STRINGSA("ddd',' MMM dd yy","");
325 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
326 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
328 curtime.wYear = 2002;
329 curtime.wMonth = 5;
330 curtime.wDay = 4;
331 curtime.wDayOfWeek = 3;
332 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
333 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
334 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
336 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
337 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
338 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
340 curtime.wHour = 36; /* Invalid */
341 STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
342 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
343 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
345 STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
346 ret = GetDateFormatA(lcid, 0, &curtime, input, NULL, 0);
347 EXPECT_VALID; EXPECT_LEN(16); EXPECT_EQA;
349 STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
350 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, 2);
351 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
353 STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
354 ret = GetDateFormat(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
355 EXPECT_VALID; EXPECT_LENA;
356 if (strncmp(buffer, Expected, strlen(Expected)) && strncmp(buffer, "5/4/02", strlen(Expected)) != 0)
357 ok (0, "Expected '%s' or '5/4/02', got '%s'\n", Expected, buffer);
359 STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
360 ret = GetDateFormat(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
361 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
363 /* test for expected DATE_YEARMONTH behavior with null format */
364 /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
365 STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
366 ret = GetDateFormat(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
367 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
369 /* Test that using invalid DATE_* flags results in the correct error */
370 /* and return values */
371 STRINGSA("m/d/y", ""); /* Invalid flags */
372 ret = GetDateFormat(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
373 &curtime, input, buffer, COUNTOF(buffer));
374 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
377 static void test_GetDateFormatW(void)
379 int ret;
380 SYSTEMTIME curtime;
381 WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
382 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
384 STRINGSW("",""); /* If flags is not zero then format must be NULL */
385 ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL,
386 input, buffer, COUNTOF(buffer));
387 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
388 return;
389 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQW;
391 STRINGSW("",""); /* NULL buffer, len > 0 */
392 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
393 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQW;
395 STRINGSW("",""); /* NULL buffer, len == 0 */
396 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
397 EXPECT_VALID; EXPECT_LENW; EXPECT_EQW;
399 curtime.wYear = 2002;
400 curtime.wMonth = 10;
401 curtime.wDay = 23;
402 curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
403 curtime.wHour = 65432; /* Invalid */
404 curtime.wMinute = 34512; /* Invalid */
405 curtime.wSecond = 65535; /* Invalid */
406 curtime.wMilliseconds = 12345;
407 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
408 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
409 EXPECT_VALID; EXPECT_LENW; EXPECT_EQW;
413 #define CY_POS_LEFT 0
414 #define CY_POS_RIGHT 1
415 #define CY_POS_LEFT_SPACE 2
416 #define CY_POS_RIGHT_SPACE 3
418 static void test_GetCurrencyFormatA(void)
420 static char szDot[] = { '.', '\0' };
421 static char szComma[] = { ',', '\0' };
422 static char szDollar[] = { '$', '\0' };
423 int ret;
424 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
425 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
426 CURRENCYFMTA format;
428 memset(&format, 0, sizeof(format));
430 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
431 ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
432 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
434 STRINGSA("23,53",""); /* Invalid character --> Error */
435 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
436 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
438 STRINGSA("--",""); /* Double '-' --> Error */
439 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
440 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
442 STRINGSA("0-",""); /* Trailing '-' --> Error */
443 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
444 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
446 STRINGSA("0..",""); /* Double '.' --> Error */
447 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
448 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
450 STRINGSA(" 0.1",""); /* Leading space --> Error */
451 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
452 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
454 STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
455 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, 2);
456 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
458 STRINGSA("2353",""); /* Format and flags given --> Error */
459 ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
460 EXPECT_INVALIDFLAGS; EXPECT_LEN(0); EXPECT_EQA;
462 STRINGSA("2353",""); /* Invalid format --> Error */
463 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
464 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
466 STRINGSA("2353","$2,353.00"); /* Valid number */
467 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
468 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
470 STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
471 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
472 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
474 STRINGSA("2353.1","$2,353.10"); /* Valid real number */
475 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
476 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
478 STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
479 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
480 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
482 STRINGSA("2353.119","$2,353.12"); /* Too many DP --> Rounded */
483 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
484 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
486 format.NumDigits = 0; /* No decimal separator */
487 format.LeadingZero = 0;
488 format.Grouping = 0; /* No grouping char */
489 format.NegativeOrder = 0;
490 format.PositiveOrder = CY_POS_LEFT;
491 format.lpDecimalSep = szDot;
492 format.lpThousandSep = szComma;
493 format.lpCurrencySymbol = szDollar;
495 STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
496 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
497 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
499 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
500 STRINGSA("2353","$2353.0");
501 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
502 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
504 format.Grouping = 2; /* Group by 100's */
505 STRINGSA("2353","$23,53.0");
506 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
507 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
509 format.LeadingZero = 1; /* Always provide leading zero */
510 STRINGSA(".5","$0.5");
511 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
512 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
514 format.PositiveOrder = CY_POS_RIGHT;
515 STRINGSA("1","1.0$");
516 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
517 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
519 format.PositiveOrder = CY_POS_LEFT_SPACE;
520 STRINGSA("1","$ 1.0");
521 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
522 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
524 format.PositiveOrder = CY_POS_RIGHT_SPACE;
525 STRINGSA("1","1.0 $");
526 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
527 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
529 format.NegativeOrder = 0;
530 STRINGSA("-1","($1.0)");
531 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
532 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
534 format.NegativeOrder = 1;
535 STRINGSA("-1","-$1.0");
536 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
537 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
539 format.NegativeOrder = 2;
540 STRINGSA("-1","$-1.0");
541 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
542 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
544 format.NegativeOrder = 3;
545 STRINGSA("-1","$1.0-");
546 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
547 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
549 format.NegativeOrder = 4;
550 STRINGSA("-1","(1.0$)");
551 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
552 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
554 format.NegativeOrder = 5;
555 STRINGSA("-1","-1.0$");
556 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
557 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
559 format.NegativeOrder = 6;
560 STRINGSA("-1","1.0-$");
561 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
562 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
564 format.NegativeOrder = 7;
565 STRINGSA("-1","1.0$-");
566 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
567 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
569 format.NegativeOrder = 8;
570 STRINGSA("-1","-1.0 $");
571 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
572 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
574 format.NegativeOrder = 9;
575 STRINGSA("-1","-$ 1.0");
576 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
577 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
579 format.NegativeOrder = 10;
580 STRINGSA("-1","1.0 $-");
581 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
582 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
584 format.NegativeOrder = 11;
585 STRINGSA("-1","$ 1.0-");
586 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
587 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
589 format.NegativeOrder = 12;
590 STRINGSA("-1","$ -1.0");
591 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
592 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
594 format.NegativeOrder = 13;
595 STRINGSA("-1","1.0- $");
596 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
597 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
599 format.NegativeOrder = 14;
600 STRINGSA("-1","($ 1.0)");
601 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
602 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
604 format.NegativeOrder = 15;
605 STRINGSA("-1","(1.0 $)");
606 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
607 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
610 #define NEG_PARENS 0 /* "(1.1)" */
611 #define NEG_LEFT 1 /* "-1.1" */
612 #define NEG_LEFT_SPACE 2 /* "- 1.1" */
613 #define NEG_RIGHT 3 /* "1.1-" */
614 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
616 static void test_GetNumberFormatA(void)
618 static char szDot[] = { '.', '\0' };
619 static char szComma[] = { ',', '\0' };
620 int ret;
621 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
622 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
623 NUMBERFMTA format;
625 memset(&format, 0, sizeof(format));
627 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
628 ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
629 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
631 STRINGSA("23,53",""); /* Invalid character --> Error */
632 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
633 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
635 STRINGSA("--",""); /* Double '-' --> Error */
636 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
637 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
639 STRINGSA("0-",""); /* Trailing '-' --> Error */
640 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
641 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
643 STRINGSA("0..",""); /* Double '.' --> Error */
644 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
645 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
647 STRINGSA(" 0.1",""); /* Leading space --> Error */
648 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
649 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
651 STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
652 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, 2);
653 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
655 STRINGSA("2353",""); /* Format and flags given --> Error */
656 ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
657 EXPECT_INVALIDFLAGS; EXPECT_LEN(0); EXPECT_EQA;
659 STRINGSA("2353",""); /* Invalid format --> Error */
660 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
661 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
663 STRINGSA("2353","2,353.00"); /* Valid number */
664 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
665 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
667 STRINGSA("-2353","-2,353.00"); /* Valid negative number */
668 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
669 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
671 STRINGSA("-353","-353.00"); /* test for off by one error in grouping */
672 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
673 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
675 STRINGSA("2353.1","2,353.10"); /* Valid real number */
676 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
677 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
679 STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
680 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
681 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
683 STRINGSA("2353.119","2,353.12"); /* Too many DP --> Rounded */
684 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
685 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
687 format.NumDigits = 0; /* No decimal separator */
688 format.LeadingZero = 0;
689 format.Grouping = 0; /* No grouping char */
690 format.NegativeOrder = 0;
691 format.lpDecimalSep = szDot;
692 format.lpThousandSep = szComma;
694 STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
695 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
696 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
698 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
699 STRINGSA("2353","2353.0");
700 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
701 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
703 format.Grouping = 2; /* Group by 100's */
704 STRINGSA("2353","23,53.0");
705 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
706 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
708 format.LeadingZero = 1; /* Always provide leading zero */
709 STRINGSA(".5","0.5");
710 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
711 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
713 format.NegativeOrder = NEG_PARENS;
714 STRINGSA("-1","(1.0)");
715 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
716 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
718 format.NegativeOrder = NEG_LEFT;
719 STRINGSA("-1","-1.0");
720 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
721 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
723 format.NegativeOrder = NEG_LEFT_SPACE;
724 STRINGSA("-1","- 1.0");
725 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
726 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
728 format.NegativeOrder = NEG_RIGHT;
729 STRINGSA("-1","1.0-");
730 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
731 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
733 format.NegativeOrder = NEG_RIGHT_SPACE;
734 STRINGSA("-1","1.0 -");
735 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
736 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
738 lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
740 if (IsValidLocale(lcid, 0))
742 STRINGSA("-12345","-12 345,00"); /* Try French formatting */
743 Expected[3] = 160; /* Non breaking space */
744 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
745 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
750 static void test_CompareStringA(void)
752 int ret;
753 LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
755 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
756 ok (ret== 1, "(Salut/Salute) Expected 1, got %d\n", ret);
758 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
759 ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
761 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
762 ok (ret== 3, "(Salut/hola) Expected 3, got %d\n", ret);
764 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
765 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
767 lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
769 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
770 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
772 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
773 ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
775 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
776 ok (ret == 2, "(Salut/saLuT) Expected 2, got %d\n", ret);
778 /* test for CompareStringA flags */
779 SetLastError(0xdeadbeef);
780 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0x10, "NULL", -1, "NULL", -1);
781 ok(GetLastError() == ERROR_INVALID_FLAGS,
782 "unexpected error code %ld\n", GetLastError());
783 ok(!ret, "CompareStringA must fail with invalid flag\n");
785 SetLastError(0xdeadbeef);
786 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, LOCALE_USE_CP_ACP, "NULL", -1, "NULL", -1);
787 ok(GetLastError() == 0xdeadbeef, "unexpected error code %ld\n", GetLastError());
788 ok(ret == CSTR_EQUAL, "CompareStringA error: %d != CSTR_EQUAL\n", ret);
789 /* end of test for CompareStringA flags */
791 ret = lstrcmpA("", "");
792 ok (ret == 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret);
794 ret = lstrcmpA(NULL, NULL);
795 ok (ret == 0, "lstrcmpA(NULL, NULL) should return 0, got %d\n", ret);
797 ret = lstrcmpA("", NULL);
798 ok (ret == 1, "lstrcmpA(\"\", NULL) should return 1, got %d\n", ret);
800 ret = lstrcmpA(NULL, "");
801 ok (ret == -1, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret);
803 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"EndDialog",-1,"_Property",-1);
804 ok( ret == 3, "EndDialog vs _Property ... expected 3, got %d\n", ret);
806 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0070",-1,"_IEWWBrowserComp",-1);
807 ok( ret == 3, "osp_vba.sreg0070 vs _IEWWBrowserComp ... expected 3, got %d\n", ret);
809 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"r",-1,"\\",-1);
810 ok( ret == 3, "r vs \\ ... expected 3, got %d\n", ret);
812 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0031", -1, "OriginalDatabase", -1 );
813 ok( ret == 3, "osp_vba.sreg0031 vs OriginalDatabase ... expected 3, got %d\n", ret);
815 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1 );
816 ok( ret == 3, "AAA vs aaa expected 3, got %d\n", ret);
818 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1 );
819 ok( ret == 1, "AAA vs aab expected 1, got %d\n", ret);
821 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1 );
822 ok( ret == 1, "AAA vs Aab expected 1, got %d\n", ret);
824 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1 );
825 ok( ret == 1, ".AAA vs Aab expected 1, got %d\n", ret);
827 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1 );
828 ok( ret == 1, ".AAA vs A.ab expected 1, got %d\n", ret);
830 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1 );
831 ok( ret == 1, "aa vs AB expected 1, got %d\n", ret);
833 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1 );
834 ok( ret == 1, "aa vs Aab expected 1, got %d\n", ret);
836 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1 );
837 ok( ret == 3, "aB vs Aab expected 3, got %d\n", ret);
839 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1 );
840 ok( ret == 1, "Ba vs bab expected 1, got %d\n", ret);
842 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1 );
843 ok( ret == 1, "{100}{83}{71}{71}{71} vs Global_DataAccess_JRO expected 1, got %d\n", ret);
845 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1 );
846 ok( ret == 3, "a vs { expected 3, got %d\n", ret);
848 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1 );
849 ok( ret == 3, "A vs { expected 3, got %d\n", ret);
851 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1 );
852 ok(ret == 1, "3.5/0 vs 4.0/-1 expected 1, got %d\n", ret);
854 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1 );
855 ok(ret == 1, "3.5 vs 4.0 expected 1, got %d\n", ret);
857 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1 );
858 ok(ret == 1, "3.520.4403.2 vs 4.0.2927.10 expected 1, got %d\n", ret);
860 /* hyphen and apostrophe are treated differently depending on
861 * whether SORT_STRINGSORT specified or not
863 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1 );
864 ok(ret == 3, "-o vs /m expected 3, got %d\n", ret);
866 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1 );
867 ok(ret == 1, "/m vs -o expected 1, got %d\n", ret);
869 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1 );
870 ok(ret == 1, "-o vs /m expected 1, got %d\n", ret);
872 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1 );
873 ok(ret == 3, "/m vs -o expected 3, got %d\n", ret);
875 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1 );
876 ok(ret == 3, "'o vs /m expected 3, got %d\n", ret);
878 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1 );
879 ok(ret == 1, "/m vs 'o expected 1, got %d\n", ret);
881 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1 );
882 ok(ret == 1, "'o vs /m expected 1, got %d\n", ret);
884 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1 );
885 ok(ret == 3, "/m vs 'o expected 3, got %d\n", ret);
887 if (0) { /* this requires collation table patch to make it MS compatible */
888 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
889 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
891 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
892 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
894 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
895 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
897 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
898 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
900 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
901 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
903 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
904 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
906 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
907 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
909 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
910 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
912 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
913 ok(ret == 1, "`o vs -m expected 1, got %d\n", ret);
915 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
916 ok(ret == 3, "-m vs `o expected 3, got %d\n", ret);
918 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
919 ok(ret == 3, "`o vs -m expected 3, got %d\n", ret);
921 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
922 ok(ret == 1, "-m vs `o expected 1, got %d\n", ret);
925 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9);
926 ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0 expected 2, got %d\n", ret);
928 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10);
929 ok(ret == 1, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1, got %d\n", ret);
931 /* WinXP handles embedded NULLs differently than earlier versions */
932 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
933 ok(ret == 1 || ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1 or 2, got %d\n", ret);
935 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
936 ok(ret == 1 || ret == 2, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected 1 or 2, got %d\n", ret);
938 ret = CompareStringA(lcid, 0, "a\0b", -1, "a", -1);
939 ok(ret == 2, "a vs a expected 2, got %d\n", ret);
941 ret = CompareStringA(lcid, 0, "a\0b", 4, "a", 2);
942 ok(ret == 3, "a\\0b vs a expected 3, got %d\n", ret);
944 ret = CompareStringA(lcid, 0, "\2", 2, "\1", 2);
945 todo_wine ok(ret != 2, "\\2 vs \\1 expected unequal\n");
948 static void test_LCMapStringA(void)
950 int ret, ret2;
951 char buf[256], buf2[256];
952 static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
953 static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
954 static const char symbols_stripped[] = "justateststring1";
956 SetLastError(0xdeadbeef);
957 ret = LCMapStringA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP | LCMAP_LOWERCASE,
958 lower_case, -1, buf, sizeof(buf));
959 ok(ret == lstrlenA(lower_case) + 1,
960 "ret %d, error %ld, expected value %d\n",
961 ret, GetLastError(), lstrlenA(lower_case) + 1);
962 ok(!memcmp(buf, lower_case, ret), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
964 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
965 upper_case, -1, buf, sizeof(buf));
966 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
967 ok(GetLastError() == ERROR_INVALID_FLAGS,
968 "unexpected error code %ld\n", GetLastError());
970 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
971 upper_case, -1, buf, sizeof(buf));
972 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
973 ok(GetLastError() == ERROR_INVALID_FLAGS,
974 "unexpected error code %ld\n", GetLastError());
976 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
977 upper_case, -1, buf, sizeof(buf));
978 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
979 ok(GetLastError() == ERROR_INVALID_FLAGS,
980 "unexpected error code %ld\n", GetLastError());
982 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
983 upper_case, -1, buf, sizeof(buf));
984 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
985 ok(GetLastError() == ERROR_INVALID_FLAGS,
986 "unexpected error code %ld\n", GetLastError());
988 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
989 SetLastError(0xdeadbeef);
990 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
991 upper_case, -1, buf, sizeof(buf));
992 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError());
993 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
995 /* test LCMAP_LOWERCASE */
996 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
997 upper_case, -1, buf, sizeof(buf));
998 ok(ret == lstrlenA(upper_case) + 1,
999 "ret %d, error %ld, expected value %d\n",
1000 ret, GetLastError(), lstrlenA(upper_case) + 1);
1001 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1003 /* test LCMAP_UPPERCASE */
1004 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1005 lower_case, -1, buf, sizeof(buf));
1006 ok(ret == lstrlenA(lower_case) + 1,
1007 "ret %d, error %ld, expected value %d\n",
1008 ret, GetLastError(), lstrlenA(lower_case) + 1);
1009 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1011 /* test buffer overflow */
1012 SetLastError(0xdeadbeef);
1013 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1014 lower_case, -1, buf, 4);
1015 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1016 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1018 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1019 lstrcpyA(buf, lower_case);
1020 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1021 buf, -1, buf, sizeof(buf));
1022 if (!ret) /* Win9x */
1023 trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1024 else
1026 ok(ret == lstrlenA(lower_case) + 1,
1027 "ret %d, error %ld, expected value %d\n",
1028 ret, GetLastError(), lstrlenA(lower_case) + 1);
1029 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1031 lstrcpyA(buf, upper_case);
1032 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1033 buf, -1, buf, sizeof(buf));
1034 if (!ret) /* Win9x */
1035 trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1036 else
1038 ok(ret == lstrlenA(upper_case) + 1,
1039 "ret %d, error %ld, expected value %d\n",
1040 ret, GetLastError(), lstrlenA(lower_case) + 1);
1041 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1044 /* otherwise src == dst should fail */
1045 SetLastError(0xdeadbeef);
1046 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1047 buf, 10, buf, sizeof(buf));
1048 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1049 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1050 "unexpected error code %ld\n", GetLastError());
1051 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1053 /* test whether '\0' is always appended */
1054 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1055 upper_case, -1, buf, sizeof(buf));
1056 ok(ret, "LCMapStringA must succeed\n");
1057 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1058 upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1059 ok(ret, "LCMapStringA must succeed\n");
1060 ok(ret == ret2, "lengths of sort keys must be equal\n");
1061 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1063 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1064 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1065 upper_case, -1, buf, sizeof(buf));
1066 ok(ret, "LCMapStringA must succeed\n");
1067 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1068 lower_case, -1, buf2, sizeof(buf2));
1069 ok(ret2, "LCMapStringA must succeed\n");
1070 ok(ret == ret2, "lengths of sort keys must be equal\n");
1071 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1073 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1074 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1075 lower_case, -1, buf, sizeof(buf));
1076 ok(ret, "LCMapStringA must succeed\n");
1077 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1078 lower_case, -1, buf2, sizeof(buf2));
1079 ok(ret2, "LCMapStringA must succeed\n");
1080 ok(ret == ret2, "lengths of sort keys must be equal\n");
1081 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1083 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1084 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1085 lower_case, -1, buf, sizeof(buf));
1086 ok(ret, "LCMapStringA must succeed\n");
1087 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1088 symbols_stripped, -1, buf2, sizeof(buf2));
1089 ok(ret2, "LCMapStringA must succeed\n");
1090 ok(ret == ret2, "lengths of sort keys must be equal\n");
1091 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1093 /* test NORM_IGNORENONSPACE */
1094 lstrcpyA(buf, "foo");
1095 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1096 lower_case, -1, buf, sizeof(buf));
1097 ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1098 lstrlenA(lower_case) + 1, ret);
1099 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1101 /* test NORM_IGNORESYMBOLS */
1102 lstrcpyA(buf, "foo");
1103 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1104 lower_case, -1, buf, sizeof(buf));
1105 ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1106 lstrlenA(symbols_stripped) + 1, ret);
1107 ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1109 /* test srclen = 0 */
1110 SetLastError(0xdeadbeef);
1111 ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1112 ok(!ret, "LCMapStringA should fail with srclen = 0\n");
1113 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1114 "unexpected error code %ld\n", GetLastError());
1117 static void test_LCMapStringW(void)
1119 int ret, ret2;
1120 WCHAR buf[256], buf2[256];
1121 char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1122 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};
1123 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};
1124 static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
1125 static const WCHAR fooW[] = {'f','o','o',0};
1127 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1128 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1129 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1131 trace("Skipping LCMapStringW tests on Win9x\n");
1132 return;
1134 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1135 ok(GetLastError() == ERROR_INVALID_FLAGS,
1136 "unexpected error code %ld\n", GetLastError());
1138 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1139 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1140 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1141 ok(GetLastError() == ERROR_INVALID_FLAGS,
1142 "unexpected error code %ld\n", GetLastError());
1144 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1145 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1146 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1147 ok(GetLastError() == ERROR_INVALID_FLAGS,
1148 "unexpected error code %ld\n", GetLastError());
1150 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1151 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1152 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1153 ok(GetLastError() == ERROR_INVALID_FLAGS,
1154 "unexpected error code %ld\n", GetLastError());
1156 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1157 SetLastError(0xdeadbeef);
1158 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1159 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1160 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError());
1161 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1163 /* test LCMAP_LOWERCASE */
1164 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1165 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1166 ok(ret == lstrlenW(upper_case) + 1,
1167 "ret %d, error %ld, expected value %d\n",
1168 ret, GetLastError(), lstrlenW(upper_case) + 1);
1169 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1171 /* test LCMAP_UPPERCASE */
1172 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1173 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1174 ok(ret == lstrlenW(lower_case) + 1,
1175 "ret %d, error %ld, expected value %d\n",
1176 ret, GetLastError(), lstrlenW(lower_case) + 1);
1177 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1179 /* test buffer overflow */
1180 SetLastError(0xdeadbeef);
1181 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1182 lower_case, -1, buf, 4);
1183 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1184 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1186 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1187 lstrcpyW(buf, lower_case);
1188 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1189 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1190 ok(ret == lstrlenW(lower_case) + 1,
1191 "ret %d, error %ld, expected value %d\n",
1192 ret, GetLastError(), lstrlenW(lower_case) + 1);
1193 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1195 lstrcpyW(buf, upper_case);
1196 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1197 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1198 ok(ret == lstrlenW(upper_case) + 1,
1199 "ret %d, error %ld, expected value %d\n",
1200 ret, GetLastError(), lstrlenW(lower_case) + 1);
1201 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1203 /* otherwise src == dst should fail */
1204 SetLastError(0xdeadbeef);
1205 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1206 buf, 10, buf, sizeof(buf));
1207 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1208 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1209 "unexpected error code %ld\n", GetLastError());
1210 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1212 /* test whether '\0' is always appended */
1213 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1214 upper_case, -1, buf, sizeof(buf));
1215 ok(ret, "LCMapStringW must succeed\n");
1216 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1217 upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1218 ok(ret, "LCMapStringW must succeed\n");
1219 ok(ret == ret2, "lengths of sort keys must be equal\n");
1220 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1222 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1223 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1224 upper_case, -1, buf, sizeof(buf));
1225 ok(ret, "LCMapStringW must succeed\n");
1226 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1227 lower_case, -1, buf2, sizeof(buf2));
1228 ok(ret2, "LCMapStringW must succeed\n");
1229 ok(ret == ret2, "lengths of sort keys must be equal\n");
1230 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1232 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1233 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1234 lower_case, -1, buf, sizeof(buf));
1235 ok(ret, "LCMapStringW must succeed\n");
1236 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1237 lower_case, -1, buf2, sizeof(buf2));
1238 ok(ret2, "LCMapStringW must succeed\n");
1239 ok(ret == ret2, "lengths of sort keys must be equal\n");
1240 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1242 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1243 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1244 lower_case, -1, buf, sizeof(buf));
1245 ok(ret, "LCMapStringW must succeed\n");
1246 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1247 symbols_stripped, -1, buf2, sizeof(buf2));
1248 ok(ret2, "LCMapStringW must succeed\n");
1249 ok(ret == ret2, "lengths of sort keys must be equal\n");
1250 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1252 /* test NORM_IGNORENONSPACE */
1253 lstrcpyW(buf, fooW);
1254 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1255 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1256 ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1257 lstrlenW(lower_case) + 1, ret);
1258 ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1260 /* test NORM_IGNORESYMBOLS */
1261 lstrcpyW(buf, fooW);
1262 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1263 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1264 ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1265 lstrlenW(symbols_stripped) + 1, ret);
1266 ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1268 /* test srclen = 0 */
1269 SetLastError(0xdeadbeef);
1270 ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1271 ok(!ret, "LCMapStringW should fail with srclen = 0\n");
1272 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1273 "unexpected error code %ld\n", GetLastError());
1276 /* this requires collation table patch to make it MS compatible */
1277 const char *strings_sorted[] =
1279 "'",
1280 "-",
1281 "!",
1282 "\"",
1283 ".",
1284 ":",
1285 "\\",
1286 "_",
1287 "`",
1288 "{",
1289 "}",
1290 "+",
1291 "0",
1292 "1",
1293 "2",
1294 "3",
1295 "4",
1296 "5",
1297 "6",
1298 "7",
1299 "8",
1300 "9",
1301 "a",
1302 "A",
1303 "b",
1304 "B",
1305 "c",
1309 const char *strings[] =
1311 "C",
1312 "\"",
1313 "9",
1314 "'",
1315 "}",
1316 "-",
1317 "7",
1318 "+",
1319 "`",
1320 "1",
1321 "a",
1322 "5",
1323 "\\",
1324 "8",
1325 "B",
1326 "3",
1327 "_",
1328 "6",
1329 "{",
1330 "2",
1331 "c",
1332 "4",
1333 "!",
1334 "0",
1335 "A",
1336 ":",
1337 "b",
1341 static int compare_string1(const void *e1, const void *e2)
1343 const char *s1 = *(const char **)e1;
1344 const char *s2 = *(const char **)e2;
1346 return lstrcmpA(s1, s2);
1349 static int compare_string2(const void *e1, const void *e2)
1351 const char *s1 = *(const char **)e1;
1352 const char *s2 = *(const char **)e2;
1354 return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1357 static int compare_string3(const void *e1, const void *e2)
1359 const char *s1 = *(const char **)e1;
1360 const char *s2 = *(const char **)e2;
1361 char key1[256], key2[256];
1363 LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
1364 LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
1365 return strcmp(key1, key2);
1368 static void test_sorting(void)
1370 char buf[256];
1371 char **str_buf = (char **)buf;
1372 int i;
1374 assert(sizeof(buf) >= sizeof(strings));
1376 /* 1. sort using lstrcmpA */
1377 memcpy(buf, strings, sizeof(strings));
1378 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
1379 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1381 ok(!strcmp(strings_sorted[i], str_buf[i]),
1382 "qsort using lstrcmpA failed for element %d\n", i);
1384 /* 2. sort using CompareStringA */
1385 memcpy(buf, strings, sizeof(strings));
1386 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
1387 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1389 ok(!strcmp(strings_sorted[i], str_buf[i]),
1390 "qsort using CompareStringA failed for element %d\n", i);
1392 /* 3. sort using sort keys */
1393 memcpy(buf, strings, sizeof(strings));
1394 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
1395 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1397 ok(!strcmp(strings_sorted[i], str_buf[i]),
1398 "qsort using sort keys failed for element %d\n", i);
1402 static void test_FoldStringA(void)
1404 int ret, i;
1405 char src[256], dst[256];
1406 static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0' };
1407 static const char digits_dst[] = { '1','2','3','\0' };
1408 static const char composite_src[] =
1410 0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
1411 0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
1412 0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
1413 0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
1414 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
1415 0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
1416 0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
1417 0xfb,0xfc,0xfd,0xff,'\0'
1419 static const char composite_dst[] =
1421 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1422 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1423 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1424 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1425 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1426 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1427 0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
1428 0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
1429 0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
1430 0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
1431 0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
1432 0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
1433 0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
1434 0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
1435 0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1437 static const char ligatures_src[] =
1439 0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1441 static const char ligatures_dst[] =
1443 'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1446 if (!pFoldStringA)
1447 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1449 /* these tests are locale specific */
1450 if (GetACP() != 1252)
1452 trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1453 return;
1456 /* MAP_FOLDDIGITS */
1457 SetLastError(0);
1458 ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
1459 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1460 return;
1461 EXPECT_LEN(4); EXPECT_VALID;
1462 ok(strcmp(dst, digits_dst) == 0,
1463 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
1464 for (i = 1; i < 256; i++)
1466 if (!strchr(digits_src, i))
1468 src[0] = i;
1469 src[1] = '\0';
1470 SetLastError(0);
1471 ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
1472 EXPECT_LEN(2); EXPECT_VALID;
1473 ok(dst[0] == src[0],
1474 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
1478 /* MAP_EXPAND_LIGATURES */
1479 SetLastError(0);
1480 ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1481 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1482 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1483 EXPECT_LEN(sizeof(ligatures_dst)); EXPECT_VALID;
1484 ok(strcmp(dst, ligatures_dst) == 0,
1485 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
1486 for (i = 1; i < 256; i++)
1488 if (!strchr(ligatures_src, i))
1490 src[0] = i;
1491 src[1] = '\0';
1492 SetLastError(0);
1493 ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1494 EXPECT_LEN(2); EXPECT_VALID;
1495 ok(dst[0] == src[0],
1496 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
1501 /* MAP_COMPOSITE */
1502 SetLastError(0);
1503 ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
1504 EXPECT_VALID;
1505 todo_wine
1507 /* Wine gets close, but doesn't produce quite the same result as native */
1508 EXPECT_LEN(121);
1509 ok(strcmp(dst, composite_dst) == 0,
1510 "MAP_COMPOSITE: Expected '%s', got '%s'\n", composite_dst, dst);
1513 for (i = 1; i < 256; i++)
1515 if (!strchr(composite_src, i))
1517 src[0] = i;
1518 src[1] = '\0';
1519 SetLastError(0);
1520 ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
1521 EXPECT_LEN(2); EXPECT_VALID;
1522 ok(dst[0] == src[0],
1523 "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
1524 (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
1528 /* MAP_FOLDCZONE */
1529 for (i = 1; i < 256; i++)
1531 src[0] = i;
1532 src[1] = '\0';
1533 SetLastError(0);
1534 ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
1535 EXPECT_LEN(2); EXPECT_VALID;
1536 ok(src[0] == dst[0],
1537 "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
1538 (unsigned char)src[0], (unsigned char)dst[0]);
1541 /* MAP_PRECOMPOSED */
1542 for (i = 1; i < 256; i++)
1544 src[0] = i;
1545 src[1] = '\0';
1546 SetLastError(0);
1547 ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
1548 EXPECT_LEN(2); EXPECT_VALID;
1549 ok(src[0] == dst[0],
1550 "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
1551 (unsigned char)src[0], (unsigned char)dst[0]);
1555 static void test_FoldStringW(void)
1557 int ret;
1558 unsigned int i, j;
1559 WCHAR src[256], dst[256], ch, prev_ch = 1;
1560 static const DWORD badFlags[] =
1563 MAP_PRECOMPOSED|MAP_COMPOSITE,
1564 MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
1565 MAP_COMPOSITE|MAP_EXPAND_LIGATURES
1567 /* Ranges of digits 0-9 : Must be sorted! */
1568 static const WCHAR digitRanges[] =
1570 0x0030, /* '0'-'9' */
1571 0x0660, /* Eastern Arabic */
1572 0x06F0, /* Arabic - Hindu */
1573 0x0966, /* Devengari */
1574 0x09E6, /* Bengalii */
1575 0x0A66, /* Gurmukhi */
1576 0x0AE6, /* Gujarati */
1577 0x0B66, /* Oriya */
1578 0x0BE6, /* Tamil - No 0 */
1579 0x0C66, /* Telugu */
1580 0x0CE6, /* Kannada */
1581 0x0D66, /* Maylayalam */
1582 0x0E50, /* Thai */
1583 0x0ED0, /* Laos */
1584 0x2070, /* Superscript - 1, 2, 3 are out of sequence */
1585 0x2080, /* Subscript */
1586 0x245F, /* Circled - 0 is out of sequence */
1587 0x2473, /* Bracketed */
1588 0x2487, /* Full stop */
1589 0x2775, /* Inverted circled - No 0 */
1590 0x277F, /* Patterned circled - No 0 */
1591 0x2789, /* Inverted Patterned circled - No 0 */
1592 0xff10, /* Pliene chasse (?) */
1593 0xffff /* Terminator */
1595 /* Digits which are represented, but out of sequence */
1596 static const WCHAR outOfSequenceDigits[] =
1598 0xB9, /* Superscript 1 */
1599 0xB2, /* Superscript 2 */
1600 0xB3, /* Superscript 3 */
1601 0x24EA, /* Circled 0 */
1602 '\0' /* Terminator */
1604 /* Digits in digitRanges for which no representation is available */
1605 static const WCHAR noDigitAvailable[] =
1607 0x0BE6, /* No Tamil 0 */
1608 0x2473, /* No Bracketed 0 */
1609 0x2487, /* No 0 Full stop */
1610 0x2775, /* No inverted circled 0 */
1611 0x277F, /* No patterned circled */
1612 0x2789, /* No inverted Patterned circled */
1613 '\0' /* Terminator */
1615 /* Compatibility conversion results */
1616 static const WCHAR compat_F900_FA2F[256+48] =
1618 0x8c48, 0x66f4, 0x8eca, 0x8cc8, 0x6ed1, 0x4e32, 0x53e5, 0x9f9c,
1619 0x9f9c, 0x5951, 0x91d1, 0x5587, 0x5948, 0x61f6, 0x7669, 0x7f85,
1620 0x863f, 0x87ba, 0x88f8, 0x908f, 0x6a02, 0x6d1b, 0x70d9, 0x73de,
1621 0x843d, 0x916a, 0x99f1, 0x4e82, 0x5375, 0x6b04, 0x721b, 0x862d,
1622 0x9e1e, 0x5d50, 0x6feb, 0x85cd, 0x8964, 0x62c9, 0x81d8, 0x881f,
1623 0x5eca, 0x6717, 0x6d6a, 0x72fc, 0x0000, 0x4f86, 0x51b7, 0x52de,
1624 0x64c4, 0x6ad3, 0x7210, 0x76e7, 0x8001, 0x8606, 0x865c, 0x8def,
1625 0x9732, 0x9b6f, 0x9dfa, 0x788c, 0x797f, 0x7da0, 0x83c9, 0x9304,
1626 0x9e7f, 0x8ad6, 0x58df, 0x5f04, 0x7c60, 0x807e, 0x7262, 0x78ca,
1627 0x8cc2, 0x96f7, 0x58d8, 0x5c62, 0x6a13, 0x6dda, 0x6f0f, 0x7d2f,
1628 0x7e37, 0x964b, 0x52d2, 0x808b, 0x51dc, 0x51cc, 0x7a1c, 0x7dbe,
1629 0x83f1, 0x9675, 0x8b80, 0x62cf, 0x6a02, 0x8afe, 0x4e39, 0x5be7,
1630 0x6012, 0x7387, 0x7570, 0x5317, 0x78fb, 0x4fbf, 0x5fa9, 0x4e0d,
1631 0x6ccc, 0x6578, 0x7d22, 0x53c3, 0x585e, 0x7701, 0x8449, 0x8aaa,
1632 0x6bba, 0x8fb0, 0x6c88, 0x62fe, 0x82e5, 0x63a0, 0x7565, 0x4eae,
1633 0x5169, 0x0000, 0x6881, 0x7ce7, 0x826f, 0x8ad2, 0x91cf, 0x52f5,
1634 0x5442, 0x5973, 0x5eec, 0x65c5, 0x6ffe, 0x792a, 0x95ad, 0x9a6a,
1635 0x9e97, 0x9ece, 0x529b, 0x66c6, 0x6b77, 0x8f62, 0x5e74, 0x6190,
1636 0x6200, 0x649a, 0x6f23, 0x7149, 0x7489, 0x0000, 0x7df4, 0x806f,
1637 0x8f26, 0x84ee, 0x9023, 0x934a, 0x5217, 0x52a3, 0x54bd, 0x70c8,
1638 0x88c2, 0x8aaa, 0x5ec9, 0x5ff5, 0x637b, 0x6bae, 0x7c3e, 0x7375,
1639 0x4ee4, 0x56f9, 0x5be7, 0x5dba, 0x601c, 0x73b2, 0x7469, 0x7f9a,
1640 0x8046, 0x9234, 0x96f6, 0x9748, 0x9818, 0x4f8b, 0x79ae, 0x91b4,
1641 0x96b8, 0x60e1, 0x4e86, 0x50da, 0x5bee, 0x5c3f, 0x6599, 0x6a02,
1642 0x71ce, 0x7642, 0x84fc, 0x907c, 0x9f8d, 0x6688, 0x962e, 0x5289,
1643 0x677b, 0x67f3, 0x6d41, 0x6e9c, 0x7409, 0x7559, 0x786b, 0x7d10,
1644 0x985e, 0x516d, 0x622e, 0x9678, 0x502b, 0x5d19, 0x6dea, 0x8f2a,
1645 0x5f8b, 0x6144, 0x6817, 0x7387, 0x9686, 0x5229, 0x540f, 0x5c65,
1646 0x6613, 0x674e, 0x68a8, 0x6ce5, 0x7406, 0x75e2, 0x7f79, 0x0000,
1647 0x88e1, 0x91cc, 0x96e2, 0x533f, 0x6eba, 0x541d, 0x71d0, 0x7498,
1648 0x85fa, 0x0000, 0x9c57, 0x9e9f, 0x6797, 0x6dcb, 0x81e8, 0x7acb,
1649 0x7b20, 0x7c92, 0x72c0, 0x7099, 0x8b58, 0x4ec0, 0x8336, 0x523a,
1650 0x5207, 0x5ea6, 0x62d3, 0x7cd6, 0x5b85, 0x6d1e, 0x66b4, 0x8f3b,
1651 0x884c, 0x964d, 0x898b, 0x5ed3, 0x0000, 0x0000, 0x0000, 0x0000,
1652 0x585a, 0x0000, 0x6674, 0x0000, 0x0000, 0x51de, 0x8c6c, 0x76ca,
1653 0x0000, 0x795e, 0x7965, 0x798f, 0x9756, 0x7cbe, 0x7fbd, 0x0000,
1654 0x0000, 0x0000, 0x8af8, 0x0000, 0x0000, 0x9038, 0x90fd, 0x0000,
1655 0x0000, 0x0000, 0x98ef, 0x98fc, 0x9928, 0x9db4, 0x0000, 0x0000
1657 static const WCHAR compat_FE30_FEF7[200] =
1659 0x2025, 0x2014, 0x2013, 0x005f, 0x005f, 0x0028, 0x0029, 0x007b,
1660 0x007d, 0x3014, 0x3015, 0x3010, 0x3011, 0x300a, 0x300b, 0x3008,
1661 0x3009, 0x300c, 0x300d, 0x300e, 0x300f, 0x0000, 0x0000, 0x0000,
1662 0x0000, 0x203e, 0x203e, 0x203e, 0x203e, 0x005f, 0x005f, 0x005f,
1663 0x002c, 0x3001, 0x002e, 0x0000, 0x003b, 0x003a, 0x003f, 0x0021,
1664 0x2014, 0x0028, 0x0029, 0x007b, 0x007d, 0x3014, 0x3015, 0x0023,
1665 0x0026, 0x002a, 0x002b, 0x002d, 0x003c, 0x003e, 0x003d, 0x0000,
1666 0x0000, 0x0024, 0x0025, 0x0040, 0x0000, 0x0000, 0x0000, 0x0000,
1667 0x064b, 0x064b, 0x064c, 0x0000, 0x064d, 0x0000, 0x064e, 0x064e,
1668 0x064f, 0x064f, 0x0650, 0x0650, 0x0651, 0x0651, 0x0652, 0x0652,
1669 0x0621, 0x0622, 0x0622, 0x0623, 0x0623, 0x0624, 0x0624, 0x0625,
1670 0x0625, 0x0626, 0x0626, 0x0626, 0x0626, 0x0627, 0x0627, 0x0628,
1671 0x0628, 0x0628, 0x0628, 0x0629, 0x0629, 0x062a, 0x062a, 0x062a,
1672 0x062a, 0x062b, 0x062b, 0x062b, 0x062b, 0x062c, 0x062c, 0x062c,
1673 0x062c, 0x062d, 0x062d, 0x062d, 0x062d, 0x062e, 0x062e, 0x062e,
1674 0x062e, 0x062f, 0x062f, 0x0630, 0x0630, 0x0631, 0x0631, 0x0632,
1675 0x0632, 0x0633, 0x0633, 0x0633, 0x0633, 0x0634, 0x0634, 0x0634,
1676 0x0634, 0x0635, 0x0635, 0x0635, 0x0635, 0x0636, 0x0636, 0x0636,
1677 0x0636, 0x0637, 0x0637, 0x0637, 0x0637, 0x0638, 0x0638, 0x0638,
1678 0x0638, 0x0639, 0x0639, 0x0639, 0x0639, 0x063a, 0x063a, 0x063a,
1679 0x063a, 0x0641, 0x0641, 0x0641, 0x0641, 0x0642, 0x0642, 0x0642,
1680 0x0642, 0x0643, 0x0643, 0x0643, 0x0643, 0x0644, 0x0644, 0x0644,
1681 0x0644, 0x0645, 0x0645, 0x0645, 0x0645, 0x0646, 0x0646, 0x0646,
1682 0x0646, 0x0647, 0x0647, 0x0647, 0x0647, 0x0648, 0x0648, 0x0649,
1683 0x0649, 0x064a, 0x064a, 0x064a, 0x064a, 0x0000, 0x0000, 0x0000
1685 static const WCHAR compat_FF00_FFEF[240] =
1687 0x0000, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
1688 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
1689 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
1690 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
1691 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
1692 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
1693 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
1694 0x0058, 0x0059, 0x005a, 0x005b, 0x0000, 0x005d, 0x005e, 0x005f,
1695 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
1696 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
1697 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
1698 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000,
1699 0x0000, 0x3002, 0x300c, 0x300d, 0x3001, 0x30fb, 0x30f2, 0x30a1,
1700 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, 0x30c3,
1701 0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, 0x30ab, 0x30ad,
1702 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, 0x30b9, 0x30bb, 0x30bd,
1703 0x30bf, 0x30c1, 0x30c4, 0x30c6, 0x30c8, 0x30ca, 0x30cb, 0x30cc,
1704 0x30cd, 0x30ce, 0x30cf, 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de,
1705 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9,
1706 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c,
1707 0x3164, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137,
1708 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f,
1709 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147,
1710 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x0000,
1711 0x0000, 0x0000, 0x314f, 0x3150, 0x3151, 0x3152, 0x3153, 0x3154,
1712 0x0000, 0x0000, 0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315a,
1713 0x0000, 0x0000, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, 0x3160,
1714 0x0000, 0x0000, 0x3161, 0x3162, 0x3163, 0x0000, 0x0000, 0x0000,
1715 0x00a2, 0x00a3, 0x00ac, 0x00af, 0x00a6, 0x00a5, 0x20a9, 0x0000,
1716 0x2502, 0x2190, 0x2191, 0x2192, 0x2193, 0x25a0, 0x25cb, 0x0000
1718 static const WCHAR ligatures_src[] =
1720 0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
1721 0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
1722 0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
1723 0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
1724 0xfb04, 0xfb05, 0xfb06, '\0'
1726 static const WCHAR ligatures_dst[] =
1728 'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
1729 'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
1730 'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
1731 0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
1732 'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
1735 if (!pFoldStringW)
1736 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1738 /* Invalid flag combinations */
1739 for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
1741 src[0] = dst[0] = '\0';
1742 SetLastError(0);
1743 ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
1744 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1745 return;
1746 EXPECT_LEN(0); EXPECT_FLAGS;
1749 /* src & dst cannot be the same */
1750 SetLastError(0);
1751 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
1752 EXPECT_LEN(0); EXPECT_INVALID;
1754 /* src can't be NULL */
1755 SetLastError(0);
1756 ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
1757 EXPECT_LEN(0); EXPECT_INVALID;
1759 /* srclen can't be 0 */
1760 SetLastError(0);
1761 ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
1762 EXPECT_LEN(0); EXPECT_INVALID;
1764 /* dstlen can't be < 0 */
1765 SetLastError(0);
1766 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
1767 EXPECT_LEN(0); EXPECT_INVALID;
1769 /* Ret includes terminating NUL which is appended if srclen = -1 */
1770 SetLastError(0);
1771 src[0] = 'A';
1772 src[1] = '\0';
1773 dst[0] = '\0';
1774 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
1775 EXPECT_LEN(2); EXPECT_VALID;
1776 ok(dst[0] == 'A' && dst[1] == '\0',
1777 "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%ld\n",
1778 'A', '\0', ret, dst[0], dst[1], GetLastError());
1780 /* If size is given, result is not NUL terminated */
1781 SetLastError(0);
1782 src[0] = 'A';
1783 src[1] = 'A';
1784 dst[0] = 'X';
1785 dst[1] = 'X';
1786 ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
1787 EXPECT_LEN(1); EXPECT_VALID;
1788 ok(dst[0] == 'A' && dst[1] == 'X',
1789 "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%ld\n",
1790 'A','X', ret, dst[0], dst[1], GetLastError());
1792 /* MAP_FOLDDIGITS */
1793 for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
1795 /* Check everything before this range */
1796 for (ch = prev_ch; ch < digitRanges[j]; ch++)
1798 SetLastError(0);
1799 src[0] = ch;
1800 src[1] = dst[0] = '\0';
1801 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
1802 EXPECT_LEN(2); EXPECT_VALID;
1804 ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
1805 /* Wine (correctly) maps all Unicode 4.0+ digits */
1806 isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF ||
1807 (ch >= 0x1369 && ch <= 0x1371),
1808 "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
1811 if (digitRanges[j] == 0xffff)
1812 break; /* Finished the whole code point space */
1814 for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
1816 WCHAR c;
1818 /* Map out of sequence characters */
1819 if (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
1820 else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
1821 else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
1822 else if (ch == 0x245F) c = 0x24EA; /* Circled 0 */
1823 else c = ch;
1824 SetLastError(0);
1825 src[0] = c;
1826 src[1] = dst[0] = '\0';
1827 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
1828 EXPECT_LEN(2); EXPECT_VALID;
1830 ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
1831 strchrW(noDigitAvailable, c),
1832 "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
1833 ch, '0' + digitRanges[j] - ch, dst[0]);
1835 prev_ch = ch;
1838 /* MAP_FOLDCZONE */
1839 for (ch = 1; ch <0xffff; ch++)
1841 WCHAR expected = 0;
1843 if (ch >= 0xF900 && ch <= 0xFA2F)
1844 expected = compat_F900_FA2F[ch - 0xF900];
1845 else if (ch >= 0xFE30 && ch <= 0xFEF7)
1846 expected = compat_FE30_FEF7[ch - 0xFE30];
1847 else if (ch >= 0xFF00 && ch <= 0xFFEF)
1848 expected = compat_FF00_FFEF[ch - 0xFF00];
1850 if (!expected)
1851 expected = ch;
1853 SetLastError(0);
1854 src[0] = ch;
1855 src[1] = dst[0] = '\0';
1856 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
1857 EXPECT_LEN(2); EXPECT_VALID;
1858 ok(dst[0] == expected ||
1859 /* Wine (correctly) uses updated mappings for some Unicode 4.0 chars */
1860 (ch >= 0xFA0D && ch <= 0xFA47) ||
1861 0xf92c || ch == 0xf979 || ch == 0xf995 || ch == 0xf9e7 || ch == 0xf9f1,
1862 "MAP_FOLDCZONE: ch %d 0x%04x Expected 0x%04x got 0x%04x\n",
1863 ch, ch, expected, dst[0]);
1866 /* MAP_EXPAND_LIGATURES */
1867 SetLastError(0);
1868 ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1869 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1870 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1871 EXPECT_LEN(sizeof(ligatures_dst)/sizeof(ligatures_dst[0])); EXPECT_VALID;
1872 ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
1873 "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
1874 for (i = 1; i <= 0xffff; i++)
1876 if (!strchrW(ligatures_src, i))
1878 src[0] = i;
1879 src[1] = '\0';
1880 SetLastError(0);
1881 ret = pFoldStringW(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1882 EXPECT_LEN(2); EXPECT_VALID;
1883 ok(dst[0] == src[0],
1884 "MAP_EXPAND_LIGATURES: 0x%02x : Expected 0x%02x, got 0x%02x\n",
1885 i, src[0], dst[0]);
1890 /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
1895 #define LCID_OK(l) \
1896 ok(lcid == l, "Expected lcid = %08lx, got %08lx\n", l, lcid)
1897 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
1898 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
1899 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
1900 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
1902 static void test_ConvertDefaultLocale(void)
1904 LCID lcid;
1906 /* Doesn't change lcid, even if non default sublang/sort used */
1907 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_US, SORT_DEFAULT);
1908 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_UK, SORT_DEFAULT);
1909 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT);
1910 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE);
1912 /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
1913 LCID_RES(MKLCID(LANG_ENGLISH, SUBLANG_NEUTRAL, SORT_DEFAULT),
1914 MKLCID(LANG_ENGLISH, SUBLANG_DEFAULT, SORT_DEFAULT));
1915 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
1916 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
1917 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_JAPANESE_UNICODE),
1918 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE));
1920 /* Invariant language is not treated specially */
1921 TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
1922 LCID_RES(MKLCID(LANG_INVARIANT, SUBLANG_NEUTRAL, SORT_DEFAULT),
1923 MKLCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT));
1925 /* User/system default languages alone are not mapped */
1926 TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
1927 TEST_LCIDLANG(LANG_USER_DEFAULT, SORT_JAPANESE_UNICODE);
1929 /* Default lcids */
1930 LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
1931 LCID_RES(LOCALE_USER_DEFAULT, GetUserDefaultLCID());
1932 LCID_RES(LOCALE_NEUTRAL, GetUserDefaultLCID());
1935 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
1936 DWORD dwFlags, LONG_PTR lParam)
1938 trace("%08lx, %s, %s, %08lx, %08lx\n",
1939 lgrpid, lpszNum, lpszName, dwFlags, lParam);
1941 ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
1942 "Enumerated grp %ld not valid (flags %ld)\n", lgrpid, dwFlags);
1944 /* If lParam is one, we are calling with flags defaulted from 0 */
1945 ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
1946 "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %ld\n", dwFlags);
1948 return TRUE;
1951 static void test_EnumSystemLanguageGroupsA(void)
1953 if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
1954 return;
1956 /* No enumeration proc */
1957 SetLastError(0);
1958 pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
1959 EXPECT_INVALID;
1961 /* Invalid flags */
1962 SetLastError(0);
1963 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
1964 EXPECT_FLAGS;
1966 /* No flags - defaults to LGRPID_INSTALLED */
1967 SetLastError(0);
1968 pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
1969 EXPECT_VALID;
1971 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
1972 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
1976 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
1977 LONG_PTR lParam)
1979 trace("%08lx, %08lx, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
1981 ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
1982 "Enumerated grp %ld not valid\n", lgrpid);
1983 ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
1984 "Enumerated grp locale %ld not valid\n", lcid);
1985 return TRUE;
1988 static void test_EnumLanguageGroupLocalesA(void)
1990 if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
1991 return;
1993 /* No enumeration proc */
1994 SetLastError(0);
1995 pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
1996 EXPECT_INVALID;
1998 /* lgrpid too small */
1999 SetLastError(0);
2000 pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
2001 EXPECT_INVALID;
2003 /* lgrpid too big */
2004 SetLastError(0);
2005 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
2006 EXPECT_INVALID;
2008 /* dwFlags is reserved */
2009 SetLastError(0);
2010 pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
2011 EXPECT_INVALID;
2013 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2016 static void test_SetLocaleInfoA(void)
2018 BOOL bRet;
2019 LCID lcid = GetUserDefaultLCID();
2021 /* Null data */
2022 SetLastError(0);
2023 bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2024 EXPECT_INVALID;
2026 /* IDATE */
2027 SetLastError(0);
2028 bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
2029 EXPECT_FLAGS;
2031 /* ILDATE */
2032 SetLastError(0);
2033 bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
2034 EXPECT_FLAGS;
2037 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2039 trace("%s %08lx\n", value, lParam);
2040 return(TRUE);
2043 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2045 ok(!enumCount, "callback called again unexpected\n");
2046 enumCount++;
2047 return(FALSE);
2050 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2052 ok(0,"callback called unexpected\n");
2053 return(FALSE);
2056 static void test_EnumUILanguageA(void)
2058 BOOL ret;
2059 if (!pEnumUILanguagesA) {
2060 trace("EnumUILanguagesA is not available on Win9x\n");
2061 return;
2064 SetLastError(ERROR_SUCCESS);
2065 ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2066 EXPECT_TRUE; EXPECT_VALID;
2068 enumCount = 0;
2069 SetLastError(ERROR_SUCCESS);
2070 ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2071 EXPECT_TRUE; EXPECT_VALID;
2073 SetLastError(ERROR_SUCCESS);
2074 ret = pEnumUILanguagesA(NULL, 0, 0);
2075 EXPECT_FALSE; EXPECT_INVALID;
2077 SetLastError(ERROR_SUCCESS);
2078 ret = pEnumUILanguagesA(luilocale_proc3A, 0x5a5a5a5a, 0);
2079 EXPECT_FALSE; EXPECT_FLAGS;
2081 SetLastError(ERROR_SUCCESS);
2082 ret = pEnumUILanguagesA(NULL, 0x5a5a5a5a, 0);
2083 EXPECT_FALSE; EXPECT_INVALID;
2086 static char date_fmt_buf[1024];
2088 static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
2090 lstrcatA(date_fmt_buf, fmt);
2091 lstrcatA(date_fmt_buf, "\n");
2092 return TRUE;
2095 static void test_EnumDateFormatsA(void)
2097 char *p, buf[256];
2098 BOOL ret;
2099 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2101 trace("EnumDateFormatsA 0\n");
2102 date_fmt_buf[0] = 0;
2103 ret = EnumDateFormatsA(enum_datetime_procA, lcid, 0);
2104 ok(ret, "EnumDateFormatsA(0) error %ld\n", GetLastError());
2105 trace("%s\n", date_fmt_buf);
2106 /* test the 1st enumerated format */
2107 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2108 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2109 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %ld\n", GetLastError());
2110 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2112 trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n");
2113 date_fmt_buf[0] = 0;
2114 ret = EnumDateFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2115 ok(ret, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %ld\n", GetLastError());
2116 trace("%s\n", date_fmt_buf);
2117 /* test the 1st enumerated format */
2118 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2119 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2120 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %ld\n", GetLastError());
2121 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2123 trace("EnumDateFormatsA DATE_SHORTDATE\n");
2124 date_fmt_buf[0] = 0;
2125 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_SHORTDATE);
2126 ok(ret, "EnumDateFormatsA(DATE_SHORTDATE) error %ld\n", GetLastError());
2127 trace("%s\n", date_fmt_buf);
2128 /* test the 1st enumerated format */
2129 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2130 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2131 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %ld\n", GetLastError());
2132 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2134 trace("EnumDateFormatsA DATE_LONGDATE\n");
2135 date_fmt_buf[0] = 0;
2136 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_LONGDATE);
2137 ok(ret, "EnumDateFormatsA(DATE_LONGDATE) error %ld\n", GetLastError());
2138 trace("%s\n", date_fmt_buf);
2139 /* test the 1st enumerated format */
2140 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2141 ret = GetLocaleInfoA(lcid, LOCALE_SLONGDATE, buf, sizeof(buf));
2142 ok(ret, "GetLocaleInfoA(LOCALE_SLONGDATE) error %ld\n", GetLastError());
2143 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2145 trace("EnumDateFormatsA DATE_YEARMONTH\n");
2146 date_fmt_buf[0] = 0;
2147 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_YEARMONTH);
2148 ok(ret, "EnumDateFormatsA(DATE_YEARMONTH) error %ld\n", GetLastError());
2149 trace("%s\n", date_fmt_buf);
2150 /* test the 1st enumerated format */
2151 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2152 ret = GetLocaleInfoA(lcid, LOCALE_SYEARMONTH, buf, sizeof(buf));
2153 ok(ret, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %ld\n", GetLastError());
2154 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2157 static void test_EnumTimeFormatsA(void)
2159 char *p, buf[256];
2160 BOOL ret;
2161 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2163 trace("EnumTimeFormatsA 0\n");
2164 date_fmt_buf[0] = 0;
2165 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, 0);
2166 ok(ret, "EnumTimeFormatsA(0) error %ld\n", GetLastError());
2167 trace("%s\n", date_fmt_buf);
2168 /* test the 1st enumerated format */
2169 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2170 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2171 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %ld\n", GetLastError());
2172 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2174 trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n");
2175 date_fmt_buf[0] = 0;
2176 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2177 ok(ret, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %ld\n", GetLastError());
2178 trace("%s\n", date_fmt_buf);
2179 /* test the 1st enumerated format */
2180 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2181 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2182 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %ld\n", GetLastError());
2183 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2186 START_TEST(locale)
2188 InitFunctionPointers();
2190 test_EnumTimeFormatsA();
2191 test_EnumDateFormatsA();
2193 test_GetLocaleInfoA();
2194 test_GetTimeFormatA();
2195 test_GetDateFormatA();
2196 test_GetDateFormatW();
2197 test_GetCurrencyFormatA(); /* Also tests the W version */
2198 test_GetNumberFormatA(); /* Also tests the W version */
2199 test_CompareStringA();
2200 test_LCMapStringA();
2201 test_LCMapStringW();
2202 test_FoldStringA();
2203 test_FoldStringW();
2204 test_ConvertDefaultLocale();
2205 test_EnumSystemLanguageGroupsA();
2206 test_EnumLanguageGroupLocalesA();
2207 test_SetLocaleInfoA();
2208 test_EnumUILanguageA();
2210 /* this requires collation table patch to make it MS compatible */
2211 if (0) test_sorting();