kernel32: "base" is a pointer in 16-bit global heap.
[wine/multimedia.git] / dlls / kernel / tests / locale.c
blobc09993054cabaa3138b5063bea2f8d711cf00108
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 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
932 ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0A expected 2, got %d\n", ret);
934 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
935 ok(ret == 2, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected 2, got %d\n", ret);
938 static void test_LCMapStringA(void)
940 int ret, ret2;
941 char buf[256], buf2[256];
942 static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
943 static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
944 static const char symbols_stripped[] = "justateststring1";
946 SetLastError(0xdeadbeef);
947 ret = LCMapStringA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP | LCMAP_LOWERCASE,
948 lower_case, -1, buf, sizeof(buf));
949 ok(ret == lstrlenA(lower_case) + 1,
950 "ret %d, error %ld, expected value %d\n",
951 ret, GetLastError(), lstrlenA(lower_case) + 1);
952 ok(!memcmp(buf, lower_case, ret), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
954 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
955 upper_case, -1, buf, sizeof(buf));
956 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
957 ok(GetLastError() == ERROR_INVALID_FLAGS,
958 "unexpected error code %ld\n", GetLastError());
960 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
961 upper_case, -1, buf, sizeof(buf));
962 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
963 ok(GetLastError() == ERROR_INVALID_FLAGS,
964 "unexpected error code %ld\n", GetLastError());
966 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
967 upper_case, -1, buf, sizeof(buf));
968 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
969 ok(GetLastError() == ERROR_INVALID_FLAGS,
970 "unexpected error code %ld\n", GetLastError());
972 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
973 upper_case, -1, buf, sizeof(buf));
974 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
975 ok(GetLastError() == ERROR_INVALID_FLAGS,
976 "unexpected error code %ld\n", GetLastError());
978 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
979 SetLastError(0xdeadbeef);
980 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
981 upper_case, -1, buf, sizeof(buf));
982 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError());
983 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
985 /* test LCMAP_LOWERCASE */
986 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
987 upper_case, -1, buf, sizeof(buf));
988 ok(ret == lstrlenA(upper_case) + 1,
989 "ret %d, error %ld, expected value %d\n",
990 ret, GetLastError(), lstrlenA(upper_case) + 1);
991 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
993 /* test LCMAP_UPPERCASE */
994 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
995 lower_case, -1, buf, sizeof(buf));
996 ok(ret == lstrlenA(lower_case) + 1,
997 "ret %d, error %ld, expected value %d\n",
998 ret, GetLastError(), lstrlenA(lower_case) + 1);
999 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1001 /* test buffer overflow */
1002 SetLastError(0xdeadbeef);
1003 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1004 lower_case, -1, buf, 4);
1005 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1006 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1008 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1009 lstrcpyA(buf, lower_case);
1010 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1011 buf, -1, buf, sizeof(buf));
1012 if (!ret) /* Win9x */
1013 trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1014 else
1016 ok(ret == lstrlenA(lower_case) + 1,
1017 "ret %d, error %ld, expected value %d\n",
1018 ret, GetLastError(), lstrlenA(lower_case) + 1);
1019 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1021 lstrcpyA(buf, upper_case);
1022 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1023 buf, -1, buf, sizeof(buf));
1024 if (!ret) /* Win9x */
1025 trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1026 else
1028 ok(ret == lstrlenA(upper_case) + 1,
1029 "ret %d, error %ld, expected value %d\n",
1030 ret, GetLastError(), lstrlenA(lower_case) + 1);
1031 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1034 /* otherwise src == dst should fail */
1035 SetLastError(0xdeadbeef);
1036 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1037 buf, 10, buf, sizeof(buf));
1038 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1039 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1040 "unexpected error code %ld\n", GetLastError());
1041 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1043 /* test whether '\0' is always appended */
1044 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1045 upper_case, -1, buf, sizeof(buf));
1046 ok(ret, "LCMapStringA must succeed\n");
1047 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1048 upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1049 ok(ret, "LCMapStringA must succeed\n");
1050 ok(ret == ret2, "lengths of sort keys must be equal\n");
1051 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1053 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1054 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1055 upper_case, -1, buf, sizeof(buf));
1056 ok(ret, "LCMapStringA must succeed\n");
1057 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1058 lower_case, -1, buf2, sizeof(buf2));
1059 ok(ret2, "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_IGNORENONSPACE */
1064 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1065 lower_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_IGNORESYMBOLS */
1074 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1075 lower_case, -1, buf, sizeof(buf));
1076 ok(ret, "LCMapStringA must succeed\n");
1077 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1078 symbols_stripped, -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 NORM_IGNORENONSPACE */
1084 lstrcpyA(buf, "foo");
1085 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1086 lower_case, -1, buf, sizeof(buf));
1087 ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1088 lstrlenA(lower_case) + 1, ret);
1089 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1091 /* test NORM_IGNORESYMBOLS */
1092 lstrcpyA(buf, "foo");
1093 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1094 lower_case, -1, buf, sizeof(buf));
1095 ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1096 lstrlenA(symbols_stripped) + 1, ret);
1097 ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1099 /* test srclen = 0 */
1100 SetLastError(0xdeadbeef);
1101 ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1102 ok(!ret, "LCMapStringA should fail with srclen = 0\n");
1103 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1104 "unexpected error code %ld\n", GetLastError());
1107 static void test_LCMapStringW(void)
1109 int ret, ret2;
1110 WCHAR buf[256], buf2[256];
1111 char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1112 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};
1113 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};
1114 static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
1115 static const WCHAR fooW[] = {'f','o','o',0};
1117 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1118 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1119 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1121 trace("Skipping LCMapStringW tests on Win9x\n");
1122 return;
1124 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1125 ok(GetLastError() == ERROR_INVALID_FLAGS,
1126 "unexpected error code %ld\n", GetLastError());
1128 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1129 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1130 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1131 ok(GetLastError() == ERROR_INVALID_FLAGS,
1132 "unexpected error code %ld\n", GetLastError());
1134 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1135 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1136 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1137 ok(GetLastError() == ERROR_INVALID_FLAGS,
1138 "unexpected error code %ld\n", GetLastError());
1140 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1141 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1142 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1143 ok(GetLastError() == ERROR_INVALID_FLAGS,
1144 "unexpected error code %ld\n", GetLastError());
1146 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1147 SetLastError(0xdeadbeef);
1148 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1149 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1150 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError());
1151 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1153 /* test LCMAP_LOWERCASE */
1154 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1155 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1156 ok(ret == lstrlenW(upper_case) + 1,
1157 "ret %d, error %ld, expected value %d\n",
1158 ret, GetLastError(), lstrlenW(upper_case) + 1);
1159 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1161 /* test LCMAP_UPPERCASE */
1162 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1163 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1164 ok(ret == lstrlenW(lower_case) + 1,
1165 "ret %d, error %ld, expected value %d\n",
1166 ret, GetLastError(), lstrlenW(lower_case) + 1);
1167 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1169 /* test buffer overflow */
1170 SetLastError(0xdeadbeef);
1171 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1172 lower_case, -1, buf, 4);
1173 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1174 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1176 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1177 lstrcpyW(buf, lower_case);
1178 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1179 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1180 ok(ret == lstrlenW(lower_case) + 1,
1181 "ret %d, error %ld, expected value %d\n",
1182 ret, GetLastError(), lstrlenW(lower_case) + 1);
1183 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1185 lstrcpyW(buf, upper_case);
1186 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1187 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1188 ok(ret == lstrlenW(upper_case) + 1,
1189 "ret %d, error %ld, expected value %d\n",
1190 ret, GetLastError(), lstrlenW(lower_case) + 1);
1191 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1193 /* otherwise src == dst should fail */
1194 SetLastError(0xdeadbeef);
1195 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1196 buf, 10, buf, sizeof(buf));
1197 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1198 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1199 "unexpected error code %ld\n", GetLastError());
1200 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1202 /* test whether '\0' is always appended */
1203 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1204 upper_case, -1, buf, sizeof(buf));
1205 ok(ret, "LCMapStringW must succeed\n");
1206 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1207 upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1208 ok(ret, "LCMapStringW must succeed\n");
1209 ok(ret == ret2, "lengths of sort keys must be equal\n");
1210 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1212 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1213 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1214 upper_case, -1, buf, sizeof(buf));
1215 ok(ret, "LCMapStringW must succeed\n");
1216 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1217 lower_case, -1, buf2, sizeof(buf2));
1218 ok(ret2, "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_IGNORENONSPACE */
1223 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1224 lower_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_IGNORESYMBOLS */
1233 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1234 lower_case, -1, buf, sizeof(buf));
1235 ok(ret, "LCMapStringW must succeed\n");
1236 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1237 symbols_stripped, -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 NORM_IGNORENONSPACE */
1243 lstrcpyW(buf, fooW);
1244 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1245 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1246 ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1247 lstrlenW(lower_case) + 1, ret);
1248 ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1250 /* test NORM_IGNORESYMBOLS */
1251 lstrcpyW(buf, fooW);
1252 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1253 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1254 ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1255 lstrlenW(symbols_stripped) + 1, ret);
1256 ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1258 /* test srclen = 0 */
1259 SetLastError(0xdeadbeef);
1260 ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1261 ok(!ret, "LCMapStringW should fail with srclen = 0\n");
1262 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1263 "unexpected error code %ld\n", GetLastError());
1266 /* this requires collation table patch to make it MS compatible */
1267 const char *strings_sorted[] =
1269 "'",
1270 "-",
1271 "!",
1272 "\"",
1273 ".",
1274 ":",
1275 "\\",
1276 "_",
1277 "`",
1278 "{",
1279 "}",
1280 "+",
1281 "0",
1282 "1",
1283 "2",
1284 "3",
1285 "4",
1286 "5",
1287 "6",
1288 "7",
1289 "8",
1290 "9",
1291 "a",
1292 "A",
1293 "b",
1294 "B",
1295 "c",
1299 const char *strings[] =
1301 "C",
1302 "\"",
1303 "9",
1304 "'",
1305 "}",
1306 "-",
1307 "7",
1308 "+",
1309 "`",
1310 "1",
1311 "a",
1312 "5",
1313 "\\",
1314 "8",
1315 "B",
1316 "3",
1317 "_",
1318 "6",
1319 "{",
1320 "2",
1321 "c",
1322 "4",
1323 "!",
1324 "0",
1325 "A",
1326 ":",
1327 "b",
1331 static int compare_string1(const void *e1, const void *e2)
1333 const char *s1 = *(const char **)e1;
1334 const char *s2 = *(const char **)e2;
1336 return lstrcmpA(s1, s2);
1339 static int compare_string2(const void *e1, const void *e2)
1341 const char *s1 = *(const char **)e1;
1342 const char *s2 = *(const char **)e2;
1344 return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1347 static int compare_string3(const void *e1, const void *e2)
1349 const char *s1 = *(const char **)e1;
1350 const char *s2 = *(const char **)e2;
1351 char key1[256], key2[256];
1353 LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
1354 LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
1355 return strcmp(key1, key2);
1358 static void test_sorting(void)
1360 char buf[256];
1361 char **str_buf = (char **)buf;
1362 int i;
1364 assert(sizeof(buf) >= sizeof(strings));
1366 /* 1. sort using lstrcmpA */
1367 memcpy(buf, strings, sizeof(strings));
1368 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
1369 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1371 ok(!strcmp(strings_sorted[i], str_buf[i]),
1372 "qsort using lstrcmpA failed for element %d\n", i);
1374 /* 2. sort using CompareStringA */
1375 memcpy(buf, strings, sizeof(strings));
1376 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
1377 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1379 ok(!strcmp(strings_sorted[i], str_buf[i]),
1380 "qsort using CompareStringA failed for element %d\n", i);
1382 /* 3. sort using sort keys */
1383 memcpy(buf, strings, sizeof(strings));
1384 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
1385 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1387 ok(!strcmp(strings_sorted[i], str_buf[i]),
1388 "qsort using sort keys failed for element %d\n", i);
1392 static void test_FoldStringA(void)
1394 int ret, i;
1395 char src[256], dst[256];
1396 static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0' };
1397 static const char digits_dst[] = { '1','2','3','\0' };
1398 static const char composite_src[] =
1400 0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
1401 0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
1402 0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
1403 0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
1404 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
1405 0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
1406 0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
1407 0xfb,0xfc,0xfd,0xff,'\0'
1409 static const char composite_dst[] =
1411 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1412 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1413 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1414 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1415 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1416 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1417 0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
1418 0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
1419 0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
1420 0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
1421 0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
1422 0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
1423 0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
1424 0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
1425 0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1427 static const char ligatures_src[] =
1429 0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1431 static const char ligatures_dst[] =
1433 'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1436 if (!pFoldStringA)
1437 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1439 /* these tests are locale specific */
1440 if (GetACP() != 1252)
1442 trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1443 return;
1446 /* MAP_FOLDDIGITS */
1447 SetLastError(0);
1448 ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
1449 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1450 return;
1451 EXPECT_LEN(4); EXPECT_VALID;
1452 ok(strcmp(dst, digits_dst) == 0,
1453 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
1454 for (i = 1; i < 256; i++)
1456 if (!strchr(digits_src, i))
1458 src[0] = i;
1459 src[1] = '\0';
1460 SetLastError(0);
1461 ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
1462 EXPECT_LEN(2); EXPECT_VALID;
1463 ok(dst[0] == src[0],
1464 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
1468 /* MAP_EXPAND_LIGATURES */
1469 SetLastError(0);
1470 ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1471 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1472 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1473 EXPECT_LEN(sizeof(ligatures_dst)); EXPECT_VALID;
1474 ok(strcmp(dst, ligatures_dst) == 0,
1475 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
1476 for (i = 1; i < 256; i++)
1478 if (!strchr(ligatures_src, i))
1480 src[0] = i;
1481 src[1] = '\0';
1482 SetLastError(0);
1483 ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1484 EXPECT_LEN(2); EXPECT_VALID;
1485 ok(dst[0] == src[0],
1486 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
1491 /* MAP_COMPOSITE */
1492 SetLastError(0);
1493 ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
1494 EXPECT_VALID;
1495 todo_wine
1497 /* Wine gets close, but doesn't produce quite the same result as native */
1498 EXPECT_LEN(121);
1499 ok(strcmp(dst, composite_dst) == 0,
1500 "MAP_COMPOSITE: Expected '%s', got '%s'\n", composite_dst, dst);
1503 for (i = 1; i < 256; i++)
1505 if (!strchr(composite_src, i))
1507 src[0] = i;
1508 src[1] = '\0';
1509 SetLastError(0);
1510 ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
1511 EXPECT_LEN(2); EXPECT_VALID;
1512 ok(dst[0] == src[0],
1513 "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
1514 (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
1518 /* MAP_FOLDCZONE */
1519 for (i = 1; i < 256; i++)
1521 src[0] = i;
1522 src[1] = '\0';
1523 SetLastError(0);
1524 ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
1525 EXPECT_LEN(2); EXPECT_VALID;
1526 ok(src[0] == dst[0],
1527 "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
1528 (unsigned char)src[0], (unsigned char)dst[0]);
1531 /* MAP_PRECOMPOSED */
1532 for (i = 1; i < 256; i++)
1534 src[0] = i;
1535 src[1] = '\0';
1536 SetLastError(0);
1537 ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
1538 EXPECT_LEN(2); EXPECT_VALID;
1539 ok(src[0] == dst[0],
1540 "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
1541 (unsigned char)src[0], (unsigned char)dst[0]);
1545 static void test_FoldStringW(void)
1547 int ret;
1548 unsigned int i, j;
1549 WCHAR src[256], dst[256], ch, prev_ch = 1;
1550 static const DWORD badFlags[] =
1553 MAP_PRECOMPOSED|MAP_COMPOSITE,
1554 MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
1555 MAP_COMPOSITE|MAP_EXPAND_LIGATURES
1557 /* Ranges of digits 0-9 : Must be sorted! */
1558 static const WCHAR digitRanges[] =
1560 0x0030, /* '0'-'9' */
1561 0x0660, /* Eastern Arabic */
1562 0x06F0, /* Arabic - Hindu */
1563 0x0966, /* Devengari */
1564 0x09E6, /* Bengalii */
1565 0x0A66, /* Gurmukhi */
1566 0x0AE6, /* Gujarati */
1567 0x0B66, /* Oriya */
1568 0x0BE6, /* Tamil - No 0 */
1569 0x0C66, /* Telugu */
1570 0x0CE6, /* Kannada */
1571 0x0D66, /* Maylayalam */
1572 0x0E50, /* Thai */
1573 0x0ED0, /* Laos */
1574 0x2070, /* Superscript - 1, 2, 3 are out of sequence */
1575 0x2080, /* Subscript */
1576 0x245F, /* Circled - 0 is out of sequence */
1577 0x2473, /* Bracketed */
1578 0x2487, /* Full stop */
1579 0x2775, /* Inverted circled - No 0 */
1580 0x277F, /* Patterned circled - No 0 */
1581 0x2789, /* Inverted Patterned circled - No 0 */
1582 0xff10, /* Pliene chasse (?) */
1583 0xffff /* Terminator */
1585 /* Digits which are represented, but out of sequence */
1586 static const WCHAR outOfSequenceDigits[] =
1588 0xB9, /* Superscript 1 */
1589 0xB2, /* Superscript 2 */
1590 0xB3, /* Superscript 3 */
1591 0x24EA, /* Circled 0 */
1592 '\0' /* Terminator */
1594 /* Digits in digitRanges for which no representation is available */
1595 static const WCHAR noDigitAvailable[] =
1597 0x0BE6, /* No Tamil 0 */
1598 0x2473, /* No Bracketed 0 */
1599 0x2487, /* No 0 Full stop */
1600 0x2775, /* No inverted circled 0 */
1601 0x277F, /* No patterned circled */
1602 0x2789, /* No inverted Patterned circled */
1603 '\0' /* Terminator */
1605 /* Compatibility conversion results */
1606 static const WCHAR compat_F900_FA2F[256+48] =
1608 0x8c48, 0x66f4, 0x8eca, 0x8cc8, 0x6ed1, 0x4e32, 0x53e5, 0x9f9c,
1609 0x9f9c, 0x5951, 0x91d1, 0x5587, 0x5948, 0x61f6, 0x7669, 0x7f85,
1610 0x863f, 0x87ba, 0x88f8, 0x908f, 0x6a02, 0x6d1b, 0x70d9, 0x73de,
1611 0x843d, 0x916a, 0x99f1, 0x4e82, 0x5375, 0x6b04, 0x721b, 0x862d,
1612 0x9e1e, 0x5d50, 0x6feb, 0x85cd, 0x8964, 0x62c9, 0x81d8, 0x881f,
1613 0x5eca, 0x6717, 0x6d6a, 0x72fc, 0x0000, 0x4f86, 0x51b7, 0x52de,
1614 0x64c4, 0x6ad3, 0x7210, 0x76e7, 0x8001, 0x8606, 0x865c, 0x8def,
1615 0x9732, 0x9b6f, 0x9dfa, 0x788c, 0x797f, 0x7da0, 0x83c9, 0x9304,
1616 0x9e7f, 0x8ad6, 0x58df, 0x5f04, 0x7c60, 0x807e, 0x7262, 0x78ca,
1617 0x8cc2, 0x96f7, 0x58d8, 0x5c62, 0x6a13, 0x6dda, 0x6f0f, 0x7d2f,
1618 0x7e37, 0x964b, 0x52d2, 0x808b, 0x51dc, 0x51cc, 0x7a1c, 0x7dbe,
1619 0x83f1, 0x9675, 0x8b80, 0x62cf, 0x6a02, 0x8afe, 0x4e39, 0x5be7,
1620 0x6012, 0x7387, 0x7570, 0x5317, 0x78fb, 0x4fbf, 0x5fa9, 0x4e0d,
1621 0x6ccc, 0x6578, 0x7d22, 0x53c3, 0x585e, 0x7701, 0x8449, 0x8aaa,
1622 0x6bba, 0x8fb0, 0x6c88, 0x62fe, 0x82e5, 0x63a0, 0x7565, 0x4eae,
1623 0x5169, 0x0000, 0x6881, 0x7ce7, 0x826f, 0x8ad2, 0x91cf, 0x52f5,
1624 0x5442, 0x5973, 0x5eec, 0x65c5, 0x6ffe, 0x792a, 0x95ad, 0x9a6a,
1625 0x9e97, 0x9ece, 0x529b, 0x66c6, 0x6b77, 0x8f62, 0x5e74, 0x6190,
1626 0x6200, 0x649a, 0x6f23, 0x7149, 0x7489, 0x0000, 0x7df4, 0x806f,
1627 0x8f26, 0x84ee, 0x9023, 0x934a, 0x5217, 0x52a3, 0x54bd, 0x70c8,
1628 0x88c2, 0x8aaa, 0x5ec9, 0x5ff5, 0x637b, 0x6bae, 0x7c3e, 0x7375,
1629 0x4ee4, 0x56f9, 0x5be7, 0x5dba, 0x601c, 0x73b2, 0x7469, 0x7f9a,
1630 0x8046, 0x9234, 0x96f6, 0x9748, 0x9818, 0x4f8b, 0x79ae, 0x91b4,
1631 0x96b8, 0x60e1, 0x4e86, 0x50da, 0x5bee, 0x5c3f, 0x6599, 0x6a02,
1632 0x71ce, 0x7642, 0x84fc, 0x907c, 0x9f8d, 0x6688, 0x962e, 0x5289,
1633 0x677b, 0x67f3, 0x6d41, 0x6e9c, 0x7409, 0x7559, 0x786b, 0x7d10,
1634 0x985e, 0x516d, 0x622e, 0x9678, 0x502b, 0x5d19, 0x6dea, 0x8f2a,
1635 0x5f8b, 0x6144, 0x6817, 0x7387, 0x9686, 0x5229, 0x540f, 0x5c65,
1636 0x6613, 0x674e, 0x68a8, 0x6ce5, 0x7406, 0x75e2, 0x7f79, 0x0000,
1637 0x88e1, 0x91cc, 0x96e2, 0x533f, 0x6eba, 0x541d, 0x71d0, 0x7498,
1638 0x85fa, 0x0000, 0x9c57, 0x9e9f, 0x6797, 0x6dcb, 0x81e8, 0x7acb,
1639 0x7b20, 0x7c92, 0x72c0, 0x7099, 0x8b58, 0x4ec0, 0x8336, 0x523a,
1640 0x5207, 0x5ea6, 0x62d3, 0x7cd6, 0x5b85, 0x6d1e, 0x66b4, 0x8f3b,
1641 0x884c, 0x964d, 0x898b, 0x5ed3, 0x0000, 0x0000, 0x0000, 0x0000,
1642 0x585a, 0x0000, 0x6674, 0x0000, 0x0000, 0x51de, 0x8c6c, 0x76ca,
1643 0x0000, 0x795e, 0x7965, 0x798f, 0x9756, 0x7cbe, 0x7fbd, 0x0000,
1644 0x0000, 0x0000, 0x8af8, 0x0000, 0x0000, 0x9038, 0x90fd, 0x0000,
1645 0x0000, 0x0000, 0x98ef, 0x98fc, 0x9928, 0x9db4, 0x0000, 0x0000
1647 static const WCHAR compat_FE30_FEF7[200] =
1649 0x2025, 0x2014, 0x2013, 0x005f, 0x005f, 0x0028, 0x0029, 0x007b,
1650 0x007d, 0x3014, 0x3015, 0x3010, 0x3011, 0x300a, 0x300b, 0x3008,
1651 0x3009, 0x300c, 0x300d, 0x300e, 0x300f, 0x0000, 0x0000, 0x0000,
1652 0x0000, 0x203e, 0x203e, 0x203e, 0x203e, 0x005f, 0x005f, 0x005f,
1653 0x002c, 0x3001, 0x002e, 0x0000, 0x003b, 0x003a, 0x003f, 0x0021,
1654 0x2014, 0x0028, 0x0029, 0x007b, 0x007d, 0x3014, 0x3015, 0x0023,
1655 0x0026, 0x002a, 0x002b, 0x002d, 0x003c, 0x003e, 0x003d, 0x0000,
1656 0x0000, 0x0024, 0x0025, 0x0040, 0x0000, 0x0000, 0x0000, 0x0000,
1657 0x064b, 0x064b, 0x064c, 0x0000, 0x064d, 0x0000, 0x064e, 0x064e,
1658 0x064f, 0x064f, 0x0650, 0x0650, 0x0651, 0x0651, 0x0652, 0x0652,
1659 0x0621, 0x0622, 0x0622, 0x0623, 0x0623, 0x0624, 0x0624, 0x0625,
1660 0x0625, 0x0626, 0x0626, 0x0626, 0x0626, 0x0627, 0x0627, 0x0628,
1661 0x0628, 0x0628, 0x0628, 0x0629, 0x0629, 0x062a, 0x062a, 0x062a,
1662 0x062a, 0x062b, 0x062b, 0x062b, 0x062b, 0x062c, 0x062c, 0x062c,
1663 0x062c, 0x062d, 0x062d, 0x062d, 0x062d, 0x062e, 0x062e, 0x062e,
1664 0x062e, 0x062f, 0x062f, 0x0630, 0x0630, 0x0631, 0x0631, 0x0632,
1665 0x0632, 0x0633, 0x0633, 0x0633, 0x0633, 0x0634, 0x0634, 0x0634,
1666 0x0634, 0x0635, 0x0635, 0x0635, 0x0635, 0x0636, 0x0636, 0x0636,
1667 0x0636, 0x0637, 0x0637, 0x0637, 0x0637, 0x0638, 0x0638, 0x0638,
1668 0x0638, 0x0639, 0x0639, 0x0639, 0x0639, 0x063a, 0x063a, 0x063a,
1669 0x063a, 0x0641, 0x0641, 0x0641, 0x0641, 0x0642, 0x0642, 0x0642,
1670 0x0642, 0x0643, 0x0643, 0x0643, 0x0643, 0x0644, 0x0644, 0x0644,
1671 0x0644, 0x0645, 0x0645, 0x0645, 0x0645, 0x0646, 0x0646, 0x0646,
1672 0x0646, 0x0647, 0x0647, 0x0647, 0x0647, 0x0648, 0x0648, 0x0649,
1673 0x0649, 0x064a, 0x064a, 0x064a, 0x064a, 0x0000, 0x0000, 0x0000
1675 static const WCHAR compat_FF00_FFEF[240] =
1677 0x0000, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
1678 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
1679 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
1680 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
1681 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
1682 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
1683 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
1684 0x0058, 0x0059, 0x005a, 0x005b, 0x0000, 0x005d, 0x005e, 0x005f,
1685 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
1686 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
1687 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
1688 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000,
1689 0x0000, 0x3002, 0x300c, 0x300d, 0x3001, 0x30fb, 0x30f2, 0x30a1,
1690 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, 0x30c3,
1691 0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, 0x30ab, 0x30ad,
1692 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, 0x30b9, 0x30bb, 0x30bd,
1693 0x30bf, 0x30c1, 0x30c4, 0x30c6, 0x30c8, 0x30ca, 0x30cb, 0x30cc,
1694 0x30cd, 0x30ce, 0x30cf, 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de,
1695 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9,
1696 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c,
1697 0x3164, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137,
1698 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f,
1699 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147,
1700 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x0000,
1701 0x0000, 0x0000, 0x314f, 0x3150, 0x3151, 0x3152, 0x3153, 0x3154,
1702 0x0000, 0x0000, 0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315a,
1703 0x0000, 0x0000, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, 0x3160,
1704 0x0000, 0x0000, 0x3161, 0x3162, 0x3163, 0x0000, 0x0000, 0x0000,
1705 0x00a2, 0x00a3, 0x00ac, 0x00af, 0x00a6, 0x00a5, 0x20a9, 0x0000,
1706 0x2502, 0x2190, 0x2191, 0x2192, 0x2193, 0x25a0, 0x25cb, 0x0000
1708 static const WCHAR ligatures_src[] =
1710 0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
1711 0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
1712 0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
1713 0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
1714 0xfb04, 0xfb05, 0xfb06, '\0'
1716 static const WCHAR ligatures_dst[] =
1718 'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
1719 'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
1720 'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
1721 0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
1722 'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
1725 if (!pFoldStringW)
1726 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1728 /* Invalid flag combinations */
1729 for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
1731 src[0] = dst[0] = '\0';
1732 SetLastError(0);
1733 ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
1734 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1735 return;
1736 EXPECT_LEN(0); EXPECT_FLAGS;
1739 /* src & dst cannot be the same */
1740 SetLastError(0);
1741 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
1742 EXPECT_LEN(0); EXPECT_INVALID;
1744 /* src can't be NULL */
1745 SetLastError(0);
1746 ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
1747 EXPECT_LEN(0); EXPECT_INVALID;
1749 /* srclen can't be 0 */
1750 SetLastError(0);
1751 ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
1752 EXPECT_LEN(0); EXPECT_INVALID;
1754 /* dstlen can't be < 0 */
1755 SetLastError(0);
1756 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
1757 EXPECT_LEN(0); EXPECT_INVALID;
1759 /* Ret includes terminating NUL which is appended if srclen = -1 */
1760 SetLastError(0);
1761 src[0] = 'A';
1762 src[1] = '\0';
1763 dst[0] = '\0';
1764 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
1765 EXPECT_LEN(2); EXPECT_VALID;
1766 ok(dst[0] == 'A' && dst[1] == '\0',
1767 "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%ld\n",
1768 'A', '\0', ret, dst[0], dst[1], GetLastError());
1770 /* If size is given, result is not NUL terminated */
1771 SetLastError(0);
1772 src[0] = 'A';
1773 src[1] = 'A';
1774 dst[0] = 'X';
1775 dst[1] = 'X';
1776 ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
1777 EXPECT_LEN(1); EXPECT_VALID;
1778 ok(dst[0] == 'A' && dst[1] == 'X',
1779 "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%ld\n",
1780 'A','X', ret, dst[0], dst[1], GetLastError());
1782 /* MAP_FOLDDIGITS */
1783 for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
1785 /* Check everything before this range */
1786 for (ch = prev_ch; ch < digitRanges[j]; ch++)
1788 SetLastError(0);
1789 src[0] = ch;
1790 src[1] = dst[0] = '\0';
1791 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
1792 EXPECT_LEN(2); EXPECT_VALID;
1794 ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
1795 /* Wine (correctly) maps all Unicode 4.0+ digits */
1796 isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF ||
1797 (ch >= 0x1369 && ch <= 0x1371),
1798 "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
1801 if (digitRanges[j] == 0xffff)
1802 break; /* Finished the whole code point space */
1804 for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
1806 WCHAR c;
1808 /* Map out of sequence characters */
1809 if (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
1810 else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
1811 else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
1812 else if (ch == 0x245F) c = 0x24EA; /* Circled 0 */
1813 else c = ch;
1814 SetLastError(0);
1815 src[0] = c;
1816 src[1] = dst[0] = '\0';
1817 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
1818 EXPECT_LEN(2); EXPECT_VALID;
1820 ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
1821 strchrW(noDigitAvailable, c),
1822 "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
1823 ch, '0' + digitRanges[j] - ch, dst[0]);
1825 prev_ch = ch;
1828 /* MAP_FOLDCZONE */
1829 for (ch = 1; ch <0xffff; ch++)
1831 WCHAR expected = 0;
1833 if (ch >= 0xF900 && ch <= 0xFA2F)
1834 expected = compat_F900_FA2F[ch - 0xF900];
1835 else if (ch >= 0xFE30 && ch <= 0xFEF7)
1836 expected = compat_FE30_FEF7[ch - 0xFE30];
1837 else if (ch >= 0xFF00 && ch <= 0xFFEF)
1838 expected = compat_FF00_FFEF[ch - 0xFF00];
1840 if (!expected)
1841 expected = ch;
1843 SetLastError(0);
1844 src[0] = ch;
1845 src[1] = dst[0] = '\0';
1846 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
1847 EXPECT_LEN(2); EXPECT_VALID;
1848 ok(dst[0] == expected ||
1849 /* Wine (correctly) uses updated mappings for some Unicode 4.0 chars */
1850 (ch >= 0xFA0D && ch <= 0xFA47) ||
1851 0xf92c || ch == 0xf979 || ch == 0xf995 || ch == 0xf9e7 || ch == 0xf9f1,
1852 "MAP_FOLDCZONE: ch %d 0x%04x Expected 0x%04x got 0x%04x\n",
1853 ch, ch, expected, dst[0]);
1856 /* MAP_EXPAND_LIGATURES */
1857 SetLastError(0);
1858 ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1859 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1860 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1861 EXPECT_LEN(sizeof(ligatures_dst)/sizeof(ligatures_dst[0])); EXPECT_VALID;
1862 ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
1863 "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
1864 for (i = 1; i <= 0xffff; i++)
1866 if (!strchrW(ligatures_src, i))
1868 src[0] = i;
1869 src[1] = '\0';
1870 SetLastError(0);
1871 ret = pFoldStringW(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1872 EXPECT_LEN(2); EXPECT_VALID;
1873 ok(dst[0] == src[0],
1874 "MAP_EXPAND_LIGATURES: 0x%02x : Expected 0x%02x, got 0x%02x\n",
1875 i, src[0], dst[0]);
1880 /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
1885 #define LCID_OK(l) \
1886 ok(lcid == l, "Expected lcid = %08lx, got %08lx\n", l, lcid)
1887 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
1888 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
1889 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
1890 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
1892 static void test_ConvertDefaultLocale(void)
1894 LCID lcid;
1896 /* Doesn't change lcid, even if non default sublang/sort used */
1897 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_US, SORT_DEFAULT);
1898 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_UK, SORT_DEFAULT);
1899 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT);
1900 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE);
1902 /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
1903 LCID_RES(MKLCID(LANG_ENGLISH, SUBLANG_NEUTRAL, SORT_DEFAULT),
1904 MKLCID(LANG_ENGLISH, SUBLANG_DEFAULT, SORT_DEFAULT));
1905 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
1906 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
1907 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_JAPANESE_UNICODE),
1908 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE));
1910 /* Invariant language is not treated specially */
1911 TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
1912 LCID_RES(MKLCID(LANG_INVARIANT, SUBLANG_NEUTRAL, SORT_DEFAULT),
1913 MKLCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT));
1915 /* User/system default languages alone are not mapped */
1916 TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
1917 TEST_LCIDLANG(LANG_USER_DEFAULT, SORT_JAPANESE_UNICODE);
1919 /* Default lcids */
1920 LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
1921 LCID_RES(LOCALE_USER_DEFAULT, GetUserDefaultLCID());
1922 LCID_RES(LOCALE_NEUTRAL, GetUserDefaultLCID());
1925 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
1926 DWORD dwFlags, LONG_PTR lParam)
1928 trace("%08lx, %s, %s, %08lx, %08lx\n",
1929 lgrpid, lpszNum, lpszName, dwFlags, lParam);
1931 ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
1932 "Enumerated grp %ld not valid (flags %ld)\n", lgrpid, dwFlags);
1934 /* If lParam is one, we are calling with flags defaulted from 0 */
1935 ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
1936 "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %ld\n", dwFlags);
1938 return TRUE;
1941 static void test_EnumSystemLanguageGroupsA(void)
1943 if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
1944 return;
1946 /* No enumeration proc */
1947 SetLastError(0);
1948 pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
1949 EXPECT_INVALID;
1951 /* Invalid flags */
1952 SetLastError(0);
1953 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
1954 EXPECT_FLAGS;
1956 /* No flags - defaults to LGRPID_INSTALLED */
1957 SetLastError(0);
1958 pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
1959 EXPECT_VALID;
1961 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
1962 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
1966 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
1967 LONG_PTR lParam)
1969 trace("%08lx, %08lx, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
1971 ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
1972 "Enumerated grp %ld not valid\n", lgrpid);
1973 ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
1974 "Enumerated grp locale %ld not valid\n", lcid);
1975 return TRUE;
1978 static void test_EnumLanguageGroupLocalesA(void)
1980 if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
1981 return;
1983 /* No enumeration proc */
1984 SetLastError(0);
1985 pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
1986 EXPECT_INVALID;
1988 /* lgrpid too small */
1989 SetLastError(0);
1990 pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
1991 EXPECT_INVALID;
1993 /* lgrpid too big */
1994 SetLastError(0);
1995 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
1996 EXPECT_INVALID;
1998 /* dwFlags is reserved */
1999 SetLastError(0);
2000 pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
2001 EXPECT_INVALID;
2003 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2006 static void test_SetLocaleInfoA(void)
2008 BOOL bRet;
2009 LCID lcid = GetUserDefaultLCID();
2011 /* Null data */
2012 SetLastError(0);
2013 bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2014 EXPECT_INVALID;
2016 /* IDATE */
2017 SetLastError(0);
2018 bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
2019 EXPECT_FLAGS;
2021 /* ILDATE */
2022 SetLastError(0);
2023 bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
2024 EXPECT_FLAGS;
2027 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2029 trace("%s %08lx\n", value, lParam);
2030 return(TRUE);
2033 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2035 ok(!enumCount, "callback called again unexpected\n");
2036 enumCount++;
2037 return(FALSE);
2040 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2042 ok(0,"callback called unexpected\n");
2043 return(FALSE);
2046 static void test_EnumUILanguageA(void)
2048 BOOL ret;
2049 if (!pEnumUILanguagesA) {
2050 trace("EnumUILanguagesA is not available on Win9x\n");
2051 return;
2054 SetLastError(ERROR_SUCCESS);
2055 ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2056 EXPECT_TRUE; EXPECT_VALID;
2058 enumCount = 0;
2059 SetLastError(ERROR_SUCCESS);
2060 ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2061 EXPECT_TRUE; EXPECT_VALID;
2063 SetLastError(ERROR_SUCCESS);
2064 ret = pEnumUILanguagesA(NULL, 0, 0);
2065 EXPECT_FALSE; EXPECT_INVALID;
2067 SetLastError(ERROR_SUCCESS);
2068 ret = pEnumUILanguagesA(luilocale_proc3A, 0x5a5a5a5a, 0);
2069 EXPECT_FALSE; EXPECT_FLAGS;
2071 SetLastError(ERROR_SUCCESS);
2072 ret = pEnumUILanguagesA(NULL, 0x5a5a5a5a, 0);
2073 EXPECT_FALSE; EXPECT_INVALID;
2076 static char date_fmt_buf[1024];
2078 static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
2080 lstrcatA(date_fmt_buf, fmt);
2081 lstrcatA(date_fmt_buf, "\n");
2082 return TRUE;
2085 static void test_EnumDateFormatsA(void)
2087 char *p, buf[256];
2088 BOOL ret;
2089 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2091 trace("EnumDateFormatsA 0\n");
2092 date_fmt_buf[0] = 0;
2093 ret = EnumDateFormatsA(enum_datetime_procA, lcid, 0);
2094 ok(ret, "EnumDateFormatsA(0) error %ld\n", GetLastError());
2095 trace("%s\n", date_fmt_buf);
2096 /* test the 1st enumerated format */
2097 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2098 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2099 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %ld\n", GetLastError());
2100 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2102 trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n");
2103 date_fmt_buf[0] = 0;
2104 ret = EnumDateFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2105 ok(ret, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %ld\n", GetLastError());
2106 trace("%s\n", date_fmt_buf);
2107 /* test the 1st enumerated format */
2108 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2109 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2110 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %ld\n", GetLastError());
2111 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2113 trace("EnumDateFormatsA DATE_SHORTDATE\n");
2114 date_fmt_buf[0] = 0;
2115 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_SHORTDATE);
2116 ok(ret, "EnumDateFormatsA(DATE_SHORTDATE) error %ld\n", GetLastError());
2117 trace("%s\n", date_fmt_buf);
2118 /* test the 1st enumerated format */
2119 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2120 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2121 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %ld\n", GetLastError());
2122 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2124 trace("EnumDateFormatsA DATE_LONGDATE\n");
2125 date_fmt_buf[0] = 0;
2126 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_LONGDATE);
2127 ok(ret, "EnumDateFormatsA(DATE_LONGDATE) error %ld\n", GetLastError());
2128 trace("%s\n", date_fmt_buf);
2129 /* test the 1st enumerated format */
2130 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2131 ret = GetLocaleInfoA(lcid, LOCALE_SLONGDATE, buf, sizeof(buf));
2132 ok(ret, "GetLocaleInfoA(LOCALE_SLONGDATE) error %ld\n", GetLastError());
2133 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2135 trace("EnumDateFormatsA DATE_YEARMONTH\n");
2136 date_fmt_buf[0] = 0;
2137 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_YEARMONTH);
2138 ok(ret, "EnumDateFormatsA(DATE_YEARMONTH) error %ld\n", GetLastError());
2139 trace("%s\n", date_fmt_buf);
2140 /* test the 1st enumerated format */
2141 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2142 ret = GetLocaleInfoA(lcid, LOCALE_SYEARMONTH, buf, sizeof(buf));
2143 ok(ret, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %ld\n", GetLastError());
2144 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2147 static void test_EnumTimeFormatsA(void)
2149 char *p, buf[256];
2150 BOOL ret;
2151 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2153 trace("EnumTimeFormatsA 0\n");
2154 date_fmt_buf[0] = 0;
2155 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, 0);
2156 ok(ret, "EnumTimeFormatsA(0) error %ld\n", GetLastError());
2157 trace("%s\n", date_fmt_buf);
2158 /* test the 1st enumerated format */
2159 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2160 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2161 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %ld\n", GetLastError());
2162 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2164 trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n");
2165 date_fmt_buf[0] = 0;
2166 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2167 ok(ret, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %ld\n", GetLastError());
2168 trace("%s\n", date_fmt_buf);
2169 /* test the 1st enumerated format */
2170 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2171 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2172 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %ld\n", GetLastError());
2173 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2176 START_TEST(locale)
2178 InitFunctionPointers();
2180 test_EnumTimeFormatsA();
2181 test_EnumDateFormatsA();
2183 test_GetLocaleInfoA();
2184 test_GetTimeFormatA();
2185 test_GetDateFormatA();
2186 test_GetDateFormatW();
2187 test_GetCurrencyFormatA(); /* Also tests the W version */
2188 test_GetNumberFormatA(); /* Also tests the W version */
2189 test_CompareStringA();
2190 test_LCMapStringA();
2191 test_LCMapStringW();
2192 test_FoldStringA();
2193 test_FoldStringW();
2194 test_ConvertDefaultLocale();
2195 test_EnumSystemLanguageGroupsA();
2196 test_EnumLanguageGroupLocalesA();
2197 test_SetLocaleInfoA();
2198 test_EnumUILanguageA();
2200 /* this requires collation table patch to make it MS compatible */
2201 if (0) test_sorting();