push 297972334720102b8c295c34d3cd5b0b9aafc558
[wine/hacks.git] / dlls / kernel32 / tests / locale.c
blobe88e182a37c9dba9e7058dce729e0a3b8384fa29
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 static inline 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");
90 pEnumSystemLanguageGroupsA = (void*)GetProcAddress(hKernel32, "EnumSystemLanguageGroupsA");
91 pEnumLanguageGroupLocalesA = (void*)GetProcAddress(hKernel32, "EnumLanguageGroupLocalesA");
92 pFoldStringA = (void*)GetProcAddress(hKernel32, "FoldStringA");
93 pFoldStringW = (void*)GetProcAddress(hKernel32, "FoldStringW");
94 pIsValidLanguageGroup = (void*)GetProcAddress(hKernel32, "IsValidLanguageGroup");
95 pEnumUILanguagesA = (void*)GetProcAddress(hKernel32, "EnumUILanguagesA");
98 #define eq(received, expected, label, type) \
99 ok((received) == (expected), "%s: got " type " instead of " type "\n", \
100 (label), (received), (expected))
102 #define BUFFER_SIZE 128
103 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
105 #define STRINGSA(x,y) strcpy(input, x); strcpy(Expected, y); SetLastError(0xdeadbeef); buffer[0] = '\0'
106 #define EXPECT_LENA ok(ret == lstrlen(Expected)+1, "Expected Len %d, got %d\n", lstrlen(Expected)+1, ret)
107 #define EXPECT_EQA ok(strncmp(buffer, Expected, strlen(Expected)) == 0, \
108 "Expected '%s', got '%s'\n", Expected, buffer)
110 #define STRINGSW(x,y) MultiByteToWideChar(CP_ACP,0,x,-1,input,COUNTOF(input)); \
111 MultiByteToWideChar(CP_ACP,0,y,-1,Expected,COUNTOF(Expected)); \
112 SetLastError(0xdeadbeef); buffer[0] = '\0'
113 #define EXPECT_LENW ok(ret == lstrlenW(Expected)+1, "Expected Len %d, got %d\n", lstrlenW(Expected)+1, ret)
114 #define EXPECT_EQW ok(strncmpW(buffer, Expected, strlenW(Expected)) == 0, "Bad conversion\n")
116 #define NUO LOCALE_NOUSEROVERRIDE
118 static void test_GetLocaleInfoA(void)
120 int ret;
121 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
122 char buffer[BUFFER_SIZE];
124 ok(lcid == 0x409, "wrong LCID calculated - %d\n", lcid);
126 /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
127 * partially fill the buffer even if it is too short. See bug 637.
129 SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
130 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 0);
131 ok(ret == 7 && !buffer[0], "Expected len=7, got %d\n", ret);
133 SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
134 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 3);
135 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
136 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
137 ok(!strcmp(buffer, "Mon"), "Expected 'Mon', got '%s'\n", buffer);
139 SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
140 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 10);
141 ok(ret == 7, "Expected ret == 7, got %d, error %d\n", ret, GetLastError());
142 ok(!strcmp(buffer, "Monday"), "Expected 'Monday', got '%s'\n", buffer);
145 static void test_GetTimeFormatA(void)
147 int ret;
148 SYSTEMTIME curtime;
149 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
150 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
152 memset(&curtime, 2, sizeof(SYSTEMTIME));
153 STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
154 SetLastError(0xdeadbeef);
155 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
156 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
157 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
159 curtime.wHour = 8;
160 curtime.wMinute = 56;
161 curtime.wSecond = 13;
162 curtime.wMilliseconds = 22;
163 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
164 SetLastError(0xdeadbeef);
165 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
166 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
167 EXPECT_LENA; EXPECT_EQA;
169 /* MSDN: LOCALE_NOUSEROVERRIDE can't be specified with a format string */
170 SetLastError(0xdeadbeef);
171 ret = GetTimeFormatA(lcid, NUO|TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
172 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
173 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
175 STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficient buffer */
176 SetLastError(0xdeadbeef);
177 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, 2);
178 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
179 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
181 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
182 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, NULL, 0);
183 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
184 EXPECT_LENA;
186 STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
187 ret = GetTimeFormatA(lcid, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
188 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
189 EXPECT_LENA; EXPECT_EQA;
191 STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
192 ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
193 ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
194 ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "4" )), /* win9x */
195 "Expected '', got '%s'\n", buffer );
197 STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
198 ret = GetTimeFormatA(lcid, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
199 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
200 EXPECT_LENA; EXPECT_EQA;
202 STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
203 strcpy(Expected, "8:56 AM");
204 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
205 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
206 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 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
211 ok( !strcmp( buffer, "8.@:56AM" ) || broken( !strcmp( buffer, "8.@:56.@:AM" )) /* win9x */,
212 "Expected '8.@:56AM', got '%s'\n", buffer );
214 STRINGSA("s1s2s3", ""); /* Duplicate tokens */
215 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
216 ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
217 ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "3" )), /* win9x */
218 "Expected '', got '%s'\n", buffer );
220 STRINGSA("t/tt", "A/AM"); /* AM time marker */
221 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
222 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
223 EXPECT_LENA; EXPECT_EQA;
225 curtime.wHour = 13;
226 STRINGSA("t/tt", "P/PM"); /* PM time marker */
227 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
228 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
229 EXPECT_LENA; EXPECT_EQA;
231 STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
232 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
233 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
234 EXPECT_LENA; EXPECT_EQA;
236 STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
237 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
238 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
239 EXPECT_LENA; EXPECT_EQA;
241 STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
242 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
243 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
244 EXPECT_LENA; EXPECT_EQA;
246 curtime.wHour = 14; /* change this to 14 or 2pm */
247 curtime.wMinute = 5;
248 curtime.wSecond = 3;
249 STRINGSA("h hh H HH m mm s ss t tt", "2 02 14 14 5 05 3 03 P PM"); /* 24 hrs, leading 0 */
250 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
251 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
252 EXPECT_LENA; EXPECT_EQA;
254 curtime.wHour = 0;
255 STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
256 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
257 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
258 EXPECT_LENA; EXPECT_EQA;
260 STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
261 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
262 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
263 EXPECT_LENA; EXPECT_EQA;
265 /* try to convert formatting strings with more than two letters
266 * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
267 * NOTE: We expect any letter for which there is an upper case value
268 * we should see a replacement. For letters that DO NOT have
269 * upper case values we should see NO REPLACEMENT.
271 curtime.wHour = 8;
272 curtime.wMinute = 56;
273 curtime.wSecond = 13;
274 curtime.wMilliseconds = 22;
275 STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
276 "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
277 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
278 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
279 EXPECT_LENA; EXPECT_EQA;
281 STRINGSA("h", "text"); /* Don't write to buffer if len is 0 */
282 strcpy(buffer, "text");
283 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, 0);
284 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
285 EXPECT_EQA;
287 STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
288 "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
289 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
290 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
291 EXPECT_LENA; EXPECT_EQA;
293 STRINGSA("'''", "'"); /* invalid quoted string */
294 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
295 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
296 EXPECT_LENA; EXPECT_EQA;
298 /* test that msdn suggested single quotation usage works as expected */
299 STRINGSA("''''", "'"); /* single quote mark */
300 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
301 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
302 EXPECT_LENA; EXPECT_EQA;
304 STRINGSA("''HHHHHH", "08"); /* Normal use */
305 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
306 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
307 EXPECT_LENA; EXPECT_EQA;
309 /* and test for normal use of the single quotation mark */
310 STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
311 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
312 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
313 EXPECT_LENA; EXPECT_EQA;
315 STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
316 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
317 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
318 EXPECT_LENA; EXPECT_EQA;
320 STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
321 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
322 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
323 EXPECT_LENA; EXPECT_EQA;
325 curtime.wHour = 25;
326 STRINGSA("'123'tt", ""); /* Invalid time */
327 SetLastError(0xdeadbeef);
328 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
329 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
330 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
332 curtime.wHour = 12;
333 curtime.wMonth = 60; /* Invalid */
334 STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
335 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
336 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
337 EXPECT_LENA; EXPECT_EQA;
340 static void test_GetDateFormatA(void)
342 int ret;
343 SYSTEMTIME curtime;
344 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
345 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
347 memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
348 STRINGSA("ddd',' MMM dd yy","");
349 SetLastError(0xdeadbeef);
350 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
351 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
352 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
354 curtime.wYear = 2002;
355 curtime.wMonth = 5;
356 curtime.wDay = 4;
357 curtime.wDayOfWeek = 3;
358 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
359 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
360 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
361 EXPECT_LENA; EXPECT_EQA;
363 /* Same as above but with LOCALE_NOUSEROVERRIDE */
364 STRINGSA("ddd',' MMM dd yy",""); /* Simple case */
365 SetLastError(0xdeadbeef);
366 ret = GetDateFormatA(lcid, NUO, &curtime, input, buffer, COUNTOF(buffer));
367 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
368 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
369 EXPECT_EQA;
371 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
372 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
373 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
374 EXPECT_LENA; EXPECT_EQA;
376 curtime.wHour = 36; /* Invalid */
377 STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
378 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
379 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
380 EXPECT_LENA; EXPECT_EQA;
382 STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
383 ret = GetDateFormatA(lcid, 0, &curtime, input, NULL, 0);
384 ok(ret == 16, "Expected ret == 16, got %d, error %d\n", ret, GetLastError());
385 EXPECT_EQA;
387 STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
388 SetLastError(0xdeadbeef);
389 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, 2);
390 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
391 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
393 STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
394 ret = GetDateFormat(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
395 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
396 if (strncmp(buffer, Expected, strlen(Expected)) && strncmp(buffer, "5/4/02", strlen(Expected)) != 0)
397 ok (0, "Expected '%s' or '5/4/02', got '%s'\n", Expected, buffer);
399 STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
400 ret = GetDateFormat(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
401 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
402 EXPECT_LENA; EXPECT_EQA;
404 /* test for expected DATE_YEARMONTH behavior with null format */
405 /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
406 STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
407 SetLastError(0xdeadbeef);
408 ret = GetDateFormat(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
409 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
410 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
411 EXPECT_EQA;
413 /* Test that using invalid DATE_* flags results in the correct error */
414 /* and return values */
415 STRINGSA("m/d/y", ""); /* Invalid flags */
416 SetLastError(0xdeadbeef);
417 ret = GetDateFormat(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
418 &curtime, input, buffer, COUNTOF(buffer));
419 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
420 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
421 EXPECT_EQA;
424 static void test_GetDateFormatW(void)
426 int ret;
427 SYSTEMTIME curtime;
428 WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
429 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
431 STRINGSW("",""); /* If flags is not zero then format must be NULL */
432 ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL,
433 input, buffer, COUNTOF(buffer));
434 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
435 return;
436 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
437 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
438 EXPECT_EQW;
440 STRINGSW("",""); /* NULL buffer, len > 0 */
441 SetLastError(0xdeadbeef);
442 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
443 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
444 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
446 STRINGSW("",""); /* NULL buffer, len == 0 */
447 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
448 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
449 EXPECT_LENW; EXPECT_EQW;
451 curtime.wYear = 2002;
452 curtime.wMonth = 10;
453 curtime.wDay = 23;
454 curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
455 curtime.wHour = 65432; /* Invalid */
456 curtime.wMinute = 34512; /* Invalid */
457 curtime.wSecond = 65535; /* Invalid */
458 curtime.wMilliseconds = 12345;
459 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
460 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
461 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
462 EXPECT_LENW; EXPECT_EQW;
464 /* Limit tests */
466 curtime.wYear = 1601;
467 curtime.wMonth = 1;
468 curtime.wDay = 1;
469 curtime.wDayOfWeek = 0; /* Irrelevant */
470 curtime.wHour = 0;
471 curtime.wMinute = 0;
472 curtime.wSecond = 0;
473 curtime.wMilliseconds = 0;
474 STRINGSW("dddd d MMMM yyyy","Monday 1 January 1601");
475 SetLastError(0xdeadbeef);
476 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
477 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
478 EXPECT_LENW; EXPECT_EQW;
480 curtime.wYear = 1600;
481 curtime.wMonth = 12;
482 curtime.wDay = 31;
483 curtime.wDayOfWeek = 0; /* Irrelevant */
484 curtime.wHour = 23;
485 curtime.wMinute = 59;
486 curtime.wSecond = 59;
487 curtime.wMilliseconds = 999;
488 STRINGSW("dddd d MMMM yyyy","Friday 31 December 1600");
489 SetLastError(0xdeadbeef);
490 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
491 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
492 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
496 #define CY_POS_LEFT 0
497 #define CY_POS_RIGHT 1
498 #define CY_POS_LEFT_SPACE 2
499 #define CY_POS_RIGHT_SPACE 3
501 static void test_GetCurrencyFormatA(void)
503 static char szDot[] = { '.', '\0' };
504 static char szComma[] = { ',', '\0' };
505 static char szDollar[] = { '$', '\0' };
506 int ret;
507 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
508 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
509 CURRENCYFMTA format;
511 memset(&format, 0, sizeof(format));
513 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
514 SetLastError(0xdeadbeef);
515 ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
516 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
517 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
519 STRINGSA("23,53",""); /* Invalid character --> Error */
520 SetLastError(0xdeadbeef);
521 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
522 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
523 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
525 STRINGSA("--",""); /* Double '-' --> Error */
526 SetLastError(0xdeadbeef);
527 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
528 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
529 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
531 STRINGSA("0-",""); /* Trailing '-' --> Error */
532 SetLastError(0xdeadbeef);
533 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
534 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
535 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
537 STRINGSA("0..",""); /* Double '.' --> Error */
538 SetLastError(0xdeadbeef);
539 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
540 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
541 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
543 STRINGSA(" 0.1",""); /* Leading space --> Error */
544 SetLastError(0xdeadbeef);
545 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
546 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
547 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
549 STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
550 SetLastError(0xdeadbeef);
551 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, 2);
552 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
553 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
555 STRINGSA("2353",""); /* Format and flags given --> Error */
556 SetLastError(0xdeadbeef);
557 ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
558 ok( !ret, "Expected ret == 0, got %d\n", ret);
559 ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
560 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
562 STRINGSA("2353",""); /* Invalid format --> Error */
563 SetLastError(0xdeadbeef);
564 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
565 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
566 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
568 STRINGSA("2353","$2,353.00"); /* Valid number */
569 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
570 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
571 EXPECT_LENA; EXPECT_EQA;
573 STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
574 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
575 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
576 EXPECT_LENA; EXPECT_EQA;
578 STRINGSA("2353.1","$2,353.10"); /* Valid real number */
579 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
580 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
581 EXPECT_LENA; EXPECT_EQA;
583 STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
584 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
585 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
586 EXPECT_LENA; EXPECT_EQA;
588 STRINGSA("2353.119","$2,353.12"); /* Too many DP --> Rounded */
589 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
590 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
591 EXPECT_LENA; EXPECT_EQA;
593 format.NumDigits = 0; /* No decimal separator */
594 format.LeadingZero = 0;
595 format.Grouping = 0; /* No grouping char */
596 format.NegativeOrder = 0;
597 format.PositiveOrder = CY_POS_LEFT;
598 format.lpDecimalSep = szDot;
599 format.lpThousandSep = szComma;
600 format.lpCurrencySymbol = szDollar;
602 STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
603 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
604 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
605 EXPECT_LENA; EXPECT_EQA;
607 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
608 STRINGSA("2353","$2353.0");
609 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
610 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
611 EXPECT_LENA; EXPECT_EQA;
613 format.Grouping = 2; /* Group by 100's */
614 STRINGSA("2353","$23,53.0");
615 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
616 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
617 EXPECT_LENA; EXPECT_EQA;
619 format.LeadingZero = 1; /* Always provide leading zero */
620 STRINGSA(".5","$0.5");
621 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
622 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
623 EXPECT_LENA; EXPECT_EQA;
625 format.PositiveOrder = CY_POS_RIGHT;
626 STRINGSA("1","1.0$");
627 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
628 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
629 EXPECT_LENA; EXPECT_EQA;
631 format.PositiveOrder = CY_POS_LEFT_SPACE;
632 STRINGSA("1","$ 1.0");
633 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
634 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
635 EXPECT_LENA; EXPECT_EQA;
637 format.PositiveOrder = CY_POS_RIGHT_SPACE;
638 STRINGSA("1","1.0 $");
639 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
640 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
641 EXPECT_LENA; EXPECT_EQA;
643 format.NegativeOrder = 0;
644 STRINGSA("-1","($1.0)");
645 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
646 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
647 EXPECT_LENA; EXPECT_EQA;
649 format.NegativeOrder = 1;
650 STRINGSA("-1","-$1.0");
651 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
652 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
653 EXPECT_LENA; EXPECT_EQA;
655 format.NegativeOrder = 2;
656 STRINGSA("-1","$-1.0");
657 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
658 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
659 EXPECT_LENA; EXPECT_EQA;
661 format.NegativeOrder = 3;
662 STRINGSA("-1","$1.0-");
663 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
664 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
665 EXPECT_LENA; EXPECT_EQA;
667 format.NegativeOrder = 4;
668 STRINGSA("-1","(1.0$)");
669 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
670 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
671 EXPECT_LENA; EXPECT_EQA;
673 format.NegativeOrder = 5;
674 STRINGSA("-1","-1.0$");
675 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
676 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
677 EXPECT_LENA; EXPECT_EQA;
679 format.NegativeOrder = 6;
680 STRINGSA("-1","1.0-$");
681 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
682 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
683 EXPECT_LENA; EXPECT_EQA;
685 format.NegativeOrder = 7;
686 STRINGSA("-1","1.0$-");
687 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
688 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
689 EXPECT_LENA; EXPECT_EQA;
691 format.NegativeOrder = 8;
692 STRINGSA("-1","-1.0 $");
693 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
694 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
695 EXPECT_LENA; EXPECT_EQA;
697 format.NegativeOrder = 9;
698 STRINGSA("-1","-$ 1.0");
699 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
700 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
701 EXPECT_LENA; EXPECT_EQA;
703 format.NegativeOrder = 10;
704 STRINGSA("-1","1.0 $-");
705 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
706 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
707 EXPECT_LENA; EXPECT_EQA;
709 format.NegativeOrder = 11;
710 STRINGSA("-1","$ 1.0-");
711 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
712 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
713 EXPECT_LENA; EXPECT_EQA;
715 format.NegativeOrder = 12;
716 STRINGSA("-1","$ -1.0");
717 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
718 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
719 EXPECT_LENA; EXPECT_EQA;
721 format.NegativeOrder = 13;
722 STRINGSA("-1","1.0- $");
723 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
724 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
725 EXPECT_LENA; EXPECT_EQA;
727 format.NegativeOrder = 14;
728 STRINGSA("-1","($ 1.0)");
729 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
730 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
731 EXPECT_LENA; EXPECT_EQA;
733 format.NegativeOrder = 15;
734 STRINGSA("-1","(1.0 $)");
735 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
736 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
737 EXPECT_LENA; EXPECT_EQA;
740 #define NEG_PARENS 0 /* "(1.1)" */
741 #define NEG_LEFT 1 /* "-1.1" */
742 #define NEG_LEFT_SPACE 2 /* "- 1.1" */
743 #define NEG_RIGHT 3 /* "1.1-" */
744 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
746 static void test_GetNumberFormatA(void)
748 static char szDot[] = { '.', '\0' };
749 static char szComma[] = { ',', '\0' };
750 int ret;
751 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
752 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
753 NUMBERFMTA format;
755 memset(&format, 0, sizeof(format));
757 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
758 SetLastError(0xdeadbeef);
759 ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
760 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
761 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
763 STRINGSA("23,53",""); /* Invalid character --> Error */
764 SetLastError(0xdeadbeef);
765 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
766 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
767 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
769 STRINGSA("--",""); /* Double '-' --> Error */
770 SetLastError(0xdeadbeef);
771 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
772 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
773 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
775 STRINGSA("0-",""); /* Trailing '-' --> Error */
776 SetLastError(0xdeadbeef);
777 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
778 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
779 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
781 STRINGSA("0..",""); /* Double '.' --> Error */
782 SetLastError(0xdeadbeef);
783 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
784 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
785 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
787 STRINGSA(" 0.1",""); /* Leading space --> Error */
788 SetLastError(0xdeadbeef);
789 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
790 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
791 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
793 STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
794 SetLastError(0xdeadbeef);
795 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, 2);
796 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
797 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
799 STRINGSA("2353",""); /* Format and flags given --> Error */
800 SetLastError(0xdeadbeef);
801 ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
802 ok( !ret, "Expected ret == 0, got %d\n", ret);
803 ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
804 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
806 STRINGSA("2353",""); /* Invalid format --> Error */
807 SetLastError(0xdeadbeef);
808 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
809 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
810 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
812 STRINGSA("2353","2,353.00"); /* Valid number */
813 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
814 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
815 EXPECT_LENA; EXPECT_EQA;
817 STRINGSA("-2353","-2,353.00"); /* Valid negative number */
818 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
819 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
820 EXPECT_LENA; EXPECT_EQA;
822 STRINGSA("-353","-353.00"); /* test for off by one error in grouping */
823 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
824 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
825 EXPECT_LENA; EXPECT_EQA;
827 STRINGSA("2353.1","2,353.10"); /* Valid real number */
828 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
829 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
830 EXPECT_LENA; EXPECT_EQA;
832 STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
833 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
834 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
835 EXPECT_LENA; EXPECT_EQA;
837 STRINGSA("2353.119","2,353.12"); /* Too many DP --> Rounded */
838 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
839 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
840 EXPECT_LENA; EXPECT_EQA;
842 format.NumDigits = 0; /* No decimal separator */
843 format.LeadingZero = 0;
844 format.Grouping = 0; /* No grouping char */
845 format.NegativeOrder = 0;
846 format.lpDecimalSep = szDot;
847 format.lpThousandSep = szComma;
849 STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
850 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
851 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
852 EXPECT_LENA; EXPECT_EQA;
854 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
855 STRINGSA("2353","2353.0");
856 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
857 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
858 EXPECT_LENA; EXPECT_EQA;
860 format.Grouping = 2; /* Group by 100's */
861 STRINGSA("2353","23,53.0");
862 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
863 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
864 EXPECT_LENA; EXPECT_EQA;
866 format.LeadingZero = 1; /* Always provide leading zero */
867 STRINGSA(".5","0.5");
868 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
869 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
870 EXPECT_LENA; EXPECT_EQA;
872 format.NegativeOrder = NEG_PARENS;
873 STRINGSA("-1","(1.0)");
874 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
875 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
876 EXPECT_LENA; EXPECT_EQA;
878 format.NegativeOrder = NEG_LEFT;
879 STRINGSA("-1","-1.0");
880 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
881 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
882 EXPECT_LENA; EXPECT_EQA;
884 format.NegativeOrder = NEG_LEFT_SPACE;
885 STRINGSA("-1","- 1.0");
886 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
887 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
888 EXPECT_LENA; EXPECT_EQA;
890 format.NegativeOrder = NEG_RIGHT;
891 STRINGSA("-1","1.0-");
892 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
893 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
894 EXPECT_LENA; EXPECT_EQA;
896 format.NegativeOrder = NEG_RIGHT_SPACE;
897 STRINGSA("-1","1.0 -");
898 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
899 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
900 EXPECT_LENA; EXPECT_EQA;
902 lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
904 if (IsValidLocale(lcid, 0))
906 STRINGSA("-12345","-12 345,00"); /* Try French formatting */
907 Expected[3] = 160; /* Non breaking space */
908 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
909 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
910 EXPECT_LENA; EXPECT_EQA;
915 static void test_CompareStringA(void)
917 int ret;
918 LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
920 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
921 ok (ret== 1, "(Salut/Salute) Expected 1, got %d\n", ret);
923 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
924 ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
926 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
927 ok (ret== 3, "(Salut/hola) Expected 3, got %d\n", ret);
929 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
930 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
932 lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
934 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
935 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
937 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
938 ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
940 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
941 ok (ret == 2, "(Salut/saLuT) Expected 2, got %d\n", ret);
943 /* test for CompareStringA flags */
944 SetLastError(0xdeadbeef);
945 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0x8, "NULL", -1, "NULL", -1);
946 ok(GetLastError() == ERROR_INVALID_FLAGS,
947 "unexpected error code %d\n", GetLastError());
948 ok(!ret, "CompareStringA must fail with invalid flag\n");
950 SetLastError(0xdeadbeef);
951 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, LOCALE_USE_CP_ACP, "NULL", -1, "NULL", -1);
952 ok(GetLastError() == 0xdeadbeef, "unexpected error code %d\n", GetLastError());
953 ok(ret == CSTR_EQUAL, "CompareStringA error: %d != CSTR_EQUAL\n", ret);
954 /* end of test for CompareStringA flags */
956 ret = lstrcmpA("", "");
957 ok (ret == 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret);
959 ret = lstrcmpA(NULL, NULL);
960 ok (ret == 0 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, NULL) should return 0, got %d\n", ret);
962 ret = lstrcmpA("", NULL);
963 ok (ret == 1 || broken(ret == -2) /* win9x */, "lstrcmpA(\"\", NULL) should return 1, got %d\n", ret);
965 ret = lstrcmpA(NULL, "");
966 ok (ret == -1 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret);
968 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"EndDialog",-1,"_Property",-1);
969 ok( ret == 3, "EndDialog vs _Property ... expected 3, got %d\n", ret);
971 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0070",-1,"_IEWWBrowserComp",-1);
972 ok( ret == 3, "osp_vba.sreg0070 vs _IEWWBrowserComp ... expected 3, got %d\n", ret);
974 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"r",-1,"\\",-1);
975 ok( ret == 3, "r vs \\ ... expected 3, got %d\n", ret);
977 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0031", -1, "OriginalDatabase", -1 );
978 ok( ret == 3, "osp_vba.sreg0031 vs OriginalDatabase ... expected 3, got %d\n", ret);
980 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1 );
981 ok( ret == 3, "AAA vs aaa expected 3, got %d\n", ret);
983 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1 );
984 ok( ret == 1, "AAA vs aab expected 1, got %d\n", ret);
986 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1 );
987 ok( ret == 1, "AAA vs Aab expected 1, got %d\n", ret);
989 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1 );
990 ok( ret == 1, ".AAA vs Aab expected 1, got %d\n", ret);
992 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1 );
993 ok( ret == 1, ".AAA vs A.ab expected 1, got %d\n", ret);
995 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1 );
996 ok( ret == 1, "aa vs AB expected 1, got %d\n", ret);
998 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1 );
999 ok( ret == 1, "aa vs Aab expected 1, got %d\n", ret);
1001 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1 );
1002 ok( ret == 3, "aB vs Aab expected 3, got %d\n", ret);
1004 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1 );
1005 ok( ret == 1, "Ba vs bab expected 1, got %d\n", ret);
1007 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1 );
1008 ok( ret == 1, "{100}{83}{71}{71}{71} vs Global_DataAccess_JRO expected 1, got %d\n", ret);
1010 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1 );
1011 ok( ret == 3, "a vs { expected 3, got %d\n", ret);
1013 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1 );
1014 ok( ret == 3, "A vs { expected 3, got %d\n", ret);
1016 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1 );
1017 ok(ret == 1, "3.5/0 vs 4.0/-1 expected 1, got %d\n", ret);
1019 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1 );
1020 ok(ret == 1, "3.5 vs 4.0 expected 1, got %d\n", ret);
1022 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1 );
1023 ok(ret == 1, "3.520.4403.2 vs 4.0.2927.10 expected 1, got %d\n", ret);
1025 /* hyphen and apostrophe are treated differently depending on
1026 * whether SORT_STRINGSORT specified or not
1028 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1 );
1029 ok(ret == 3, "-o vs /m expected 3, got %d\n", ret);
1031 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1 );
1032 ok(ret == 1, "/m vs -o expected 1, got %d\n", ret);
1034 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1 );
1035 ok(ret == 1, "-o vs /m expected 1, got %d\n", ret);
1037 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1 );
1038 ok(ret == 3, "/m vs -o expected 3, got %d\n", ret);
1040 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1 );
1041 ok(ret == 3, "'o vs /m expected 3, got %d\n", ret);
1043 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1 );
1044 ok(ret == 1, "/m vs 'o expected 1, got %d\n", ret);
1046 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1 );
1047 ok(ret == 1, "'o vs /m expected 1, got %d\n", ret);
1049 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1 );
1050 ok(ret == 3, "/m vs 'o expected 3, got %d\n", ret);
1052 if (0) { /* this requires collation table patch to make it MS compatible */
1053 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
1054 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
1056 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
1057 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
1059 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
1060 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
1062 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
1063 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
1065 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
1066 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
1068 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
1069 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
1071 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
1072 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
1074 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
1075 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
1077 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
1078 ok(ret == 1, "`o vs -m expected 1, got %d\n", ret);
1080 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
1081 ok(ret == 3, "-m vs `o expected 3, got %d\n", ret);
1083 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
1084 ok(ret == 3, "`o vs -m expected 3, got %d\n", ret);
1086 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
1087 ok(ret == 1, "-m vs `o expected 1, got %d\n", ret);
1090 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9);
1091 ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0 expected 2, got %d\n", ret);
1093 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10);
1094 ok(ret == 1, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1, got %d\n", ret);
1096 /* WinXP handles embedded NULLs differently than earlier versions */
1097 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
1098 ok(ret == 1 || ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1 or 2, got %d\n", ret);
1100 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
1101 ok(ret == 1 || ret == 2, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected 1 or 2, got %d\n", ret);
1103 ret = CompareStringA(lcid, 0, "a\0b", -1, "a", -1);
1104 ok(ret == 2, "a vs a expected 2, got %d\n", ret);
1106 ret = CompareStringA(lcid, 0, "a\0b", 4, "a", 2);
1107 ok(ret == CSTR_EQUAL || /* win2k */
1108 ret == CSTR_GREATER_THAN,
1109 "a\\0b vs a expected CSTR_EQUAL or CSTR_GREATER_THAN, got %d\n", ret);
1111 ret = CompareStringA(lcid, 0, "\2", 2, "\1", 2);
1112 todo_wine ok(ret != 2, "\\2 vs \\1 expected unequal\n");
1114 ret = CompareStringA(lcid, NORM_IGNORECASE | LOCALE_USE_CP_ACP, "#", -1, ".", -1);
1115 todo_wine ok(ret == CSTR_LESS_THAN, "\"#\" vs \".\" expected CSTR_LESS_THAN, got %d\n", ret);
1117 ret = lstrcmpi("#", ".");
1118 todo_wine ok(ret == -1, "\"#\" vs \".\" expected -1, got %d\n", ret);
1121 static void test_LCMapStringA(void)
1123 int ret, ret2;
1124 char buf[256], buf2[256];
1125 static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
1126 static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
1127 static const char symbols_stripped[] = "justateststring1";
1129 SetLastError(0xdeadbeef);
1130 ret = LCMapStringA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP | LCMAP_LOWERCASE,
1131 lower_case, -1, buf, sizeof(buf));
1132 ok(ret == lstrlenA(lower_case) + 1,
1133 "ret %d, error %d, expected value %d\n",
1134 ret, GetLastError(), lstrlenA(lower_case) + 1);
1135 ok(!memcmp(buf, lower_case, ret), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1137 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1138 upper_case, -1, buf, sizeof(buf));
1139 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1140 ok(GetLastError() == ERROR_INVALID_FLAGS,
1141 "unexpected error code %d\n", GetLastError());
1143 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1144 upper_case, -1, buf, sizeof(buf));
1145 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1146 ok(GetLastError() == ERROR_INVALID_FLAGS,
1147 "unexpected error code %d\n", GetLastError());
1149 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1150 upper_case, -1, buf, sizeof(buf));
1151 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1152 ok(GetLastError() == ERROR_INVALID_FLAGS,
1153 "unexpected error code %d\n", GetLastError());
1155 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1156 upper_case, -1, buf, sizeof(buf));
1157 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1158 ok(GetLastError() == ERROR_INVALID_FLAGS,
1159 "unexpected error code %d\n", GetLastError());
1161 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1162 SetLastError(0xdeadbeef);
1163 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1164 upper_case, -1, buf, sizeof(buf));
1165 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1166 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1168 /* test LCMAP_LOWERCASE */
1169 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1170 upper_case, -1, buf, sizeof(buf));
1171 ok(ret == lstrlenA(upper_case) + 1,
1172 "ret %d, error %d, expected value %d\n",
1173 ret, GetLastError(), lstrlenA(upper_case) + 1);
1174 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1176 /* test LCMAP_UPPERCASE */
1177 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1178 lower_case, -1, buf, sizeof(buf));
1179 ok(ret == lstrlenA(lower_case) + 1,
1180 "ret %d, error %d, expected value %d\n",
1181 ret, GetLastError(), lstrlenA(lower_case) + 1);
1182 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1184 /* test buffer overflow */
1185 SetLastError(0xdeadbeef);
1186 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1187 lower_case, -1, buf, 4);
1188 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1189 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1191 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1192 lstrcpyA(buf, lower_case);
1193 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1194 buf, -1, buf, sizeof(buf));
1195 if (!ret) /* Win9x */
1196 trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1197 else
1199 ok(ret == lstrlenA(lower_case) + 1,
1200 "ret %d, error %d, expected value %d\n",
1201 ret, GetLastError(), lstrlenA(lower_case) + 1);
1202 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1204 lstrcpyA(buf, upper_case);
1205 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1206 buf, -1, buf, sizeof(buf));
1207 if (!ret) /* Win9x */
1208 trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1209 else
1211 ok(ret == lstrlenA(upper_case) + 1,
1212 "ret %d, error %d, expected value %d\n",
1213 ret, GetLastError(), lstrlenA(lower_case) + 1);
1214 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1217 /* otherwise src == dst should fail */
1218 SetLastError(0xdeadbeef);
1219 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1220 buf, 10, buf, sizeof(buf));
1221 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1222 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1223 "unexpected error code %d\n", GetLastError());
1224 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1226 /* test whether '\0' is always appended */
1227 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1228 upper_case, -1, buf, sizeof(buf));
1229 ok(ret, "LCMapStringA must succeed\n");
1230 ok(buf[ret-1] == 0, "LCMapStringA not null-terminated\n");
1231 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1232 upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1233 ok(ret2, "LCMapStringA must succeed\n");
1234 ok(buf2[ret2-1] == 0, "LCMapStringA not null-terminated\n" );
1235 ok(ret == ret2, "lengths of sort keys must be equal\n");
1236 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1238 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1239 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1240 upper_case, -1, buf, sizeof(buf));
1241 ok(ret, "LCMapStringA must succeed\n");
1242 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1243 lower_case, -1, buf2, sizeof(buf2));
1244 ok(ret2, "LCMapStringA must succeed\n");
1245 ok(ret == ret2, "lengths of sort keys must be equal\n");
1246 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1248 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1249 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1250 lower_case, -1, buf, sizeof(buf));
1251 ok(ret, "LCMapStringA must succeed\n");
1252 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1253 lower_case, -1, buf2, sizeof(buf2));
1254 ok(ret2, "LCMapStringA must succeed\n");
1255 ok(ret == ret2, "lengths of sort keys must be equal\n");
1256 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1258 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1259 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1260 lower_case, -1, buf, sizeof(buf));
1261 ok(ret, "LCMapStringA must succeed\n");
1262 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1263 symbols_stripped, -1, buf2, sizeof(buf2));
1264 ok(ret2, "LCMapStringA must succeed\n");
1265 ok(ret == ret2, "lengths of sort keys must be equal\n");
1266 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1268 /* test NORM_IGNORENONSPACE */
1269 lstrcpyA(buf, "foo");
1270 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1271 lower_case, -1, buf, sizeof(buf));
1272 ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1273 lstrlenA(lower_case) + 1, ret);
1274 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1276 /* test NORM_IGNORESYMBOLS */
1277 lstrcpyA(buf, "foo");
1278 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1279 lower_case, -1, buf, sizeof(buf));
1280 ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1281 lstrlenA(symbols_stripped) + 1, ret);
1282 ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1284 /* test srclen = 0 */
1285 SetLastError(0xdeadbeef);
1286 ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1287 ok(!ret, "LCMapStringA should fail with srclen = 0\n");
1288 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1289 "unexpected error code %d\n", GetLastError());
1292 static void test_LCMapStringW(void)
1294 int ret, ret2;
1295 WCHAR buf[256], buf2[256];
1296 char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1297 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};
1298 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};
1299 static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
1300 static const WCHAR fooW[] = {'f','o','o',0};
1302 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1303 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1304 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1306 win_skip("LCMapStringW is not implemented\n");
1307 return;
1309 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1310 ok(GetLastError() == ERROR_INVALID_FLAGS,
1311 "unexpected error code %d\n", GetLastError());
1313 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1314 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1315 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1316 ok(GetLastError() == ERROR_INVALID_FLAGS,
1317 "unexpected error code %d\n", GetLastError());
1319 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1320 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1321 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1322 ok(GetLastError() == ERROR_INVALID_FLAGS,
1323 "unexpected error code %d\n", GetLastError());
1325 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1326 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1327 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1328 ok(GetLastError() == ERROR_INVALID_FLAGS,
1329 "unexpected error code %d\n", GetLastError());
1331 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1332 SetLastError(0xdeadbeef);
1333 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1334 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1335 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1336 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1338 /* test LCMAP_LOWERCASE */
1339 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1340 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1341 ok(ret == lstrlenW(upper_case) + 1,
1342 "ret %d, error %d, expected value %d\n",
1343 ret, GetLastError(), lstrlenW(upper_case) + 1);
1344 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1346 /* test LCMAP_UPPERCASE */
1347 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1348 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1349 ok(ret == lstrlenW(lower_case) + 1,
1350 "ret %d, error %d, expected value %d\n",
1351 ret, GetLastError(), lstrlenW(lower_case) + 1);
1352 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1354 /* test buffer overflow */
1355 SetLastError(0xdeadbeef);
1356 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1357 lower_case, -1, buf, 4);
1358 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1359 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1361 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1362 lstrcpyW(buf, lower_case);
1363 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1364 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1365 ok(ret == lstrlenW(lower_case) + 1,
1366 "ret %d, error %d, expected value %d\n",
1367 ret, GetLastError(), lstrlenW(lower_case) + 1);
1368 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1370 lstrcpyW(buf, upper_case);
1371 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1372 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1373 ok(ret == lstrlenW(upper_case) + 1,
1374 "ret %d, error %d, expected value %d\n",
1375 ret, GetLastError(), lstrlenW(lower_case) + 1);
1376 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1378 /* otherwise src == dst should fail */
1379 SetLastError(0xdeadbeef);
1380 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1381 buf, 10, buf, sizeof(buf));
1382 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1383 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1384 "unexpected error code %d\n", GetLastError());
1385 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1387 /* test whether '\0' is always appended */
1388 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1389 upper_case, -1, buf, sizeof(buf));
1390 ok(ret, "LCMapStringW must succeed\n");
1391 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1392 upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1393 ok(ret, "LCMapStringW must succeed\n");
1394 ok(ret == ret2, "lengths of sort keys must be equal\n");
1395 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1397 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1398 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1399 upper_case, -1, buf, sizeof(buf));
1400 ok(ret, "LCMapStringW must succeed\n");
1401 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1402 lower_case, -1, buf2, sizeof(buf2));
1403 ok(ret2, "LCMapStringW must succeed\n");
1404 ok(ret == ret2, "lengths of sort keys must be equal\n");
1405 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1407 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1408 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1409 lower_case, -1, buf, sizeof(buf));
1410 ok(ret, "LCMapStringW must succeed\n");
1411 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1412 lower_case, -1, buf2, sizeof(buf2));
1413 ok(ret2, "LCMapStringW must succeed\n");
1414 ok(ret == ret2, "lengths of sort keys must be equal\n");
1415 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1417 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1418 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1419 lower_case, -1, buf, sizeof(buf));
1420 ok(ret, "LCMapStringW must succeed\n");
1421 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1422 symbols_stripped, -1, buf2, sizeof(buf2));
1423 ok(ret2, "LCMapStringW must succeed\n");
1424 ok(ret == ret2, "lengths of sort keys must be equal\n");
1425 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1427 /* test NORM_IGNORENONSPACE */
1428 lstrcpyW(buf, fooW);
1429 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1430 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1431 ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1432 lstrlenW(lower_case) + 1, ret);
1433 ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1435 /* test NORM_IGNORESYMBOLS */
1436 lstrcpyW(buf, fooW);
1437 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1438 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1439 ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1440 lstrlenW(symbols_stripped) + 1, ret);
1441 ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1443 /* test srclen = 0 */
1444 SetLastError(0xdeadbeef);
1445 ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf)/sizeof(WCHAR));
1446 ok(!ret, "LCMapStringW should fail with srclen = 0\n");
1447 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1448 "unexpected error code %d\n", GetLastError());
1451 /* this requires collation table patch to make it MS compatible */
1452 static const char * const strings_sorted[] =
1454 "'",
1455 "-",
1456 "!",
1457 "\"",
1458 ".",
1459 ":",
1460 "\\",
1461 "_",
1462 "`",
1463 "{",
1464 "}",
1465 "+",
1466 "0",
1467 "1",
1468 "2",
1469 "3",
1470 "4",
1471 "5",
1472 "6",
1473 "7",
1474 "8",
1475 "9",
1476 "a",
1477 "A",
1478 "b",
1479 "B",
1480 "c",
1484 static const char * const strings[] =
1486 "C",
1487 "\"",
1488 "9",
1489 "'",
1490 "}",
1491 "-",
1492 "7",
1493 "+",
1494 "`",
1495 "1",
1496 "a",
1497 "5",
1498 "\\",
1499 "8",
1500 "B",
1501 "3",
1502 "_",
1503 "6",
1504 "{",
1505 "2",
1506 "c",
1507 "4",
1508 "!",
1509 "0",
1510 "A",
1511 ":",
1512 "b",
1516 static int compare_string1(const void *e1, const void *e2)
1518 const char *s1 = *(const char *const *)e1;
1519 const char *s2 = *(const char *const *)e2;
1521 return lstrcmpA(s1, s2);
1524 static int compare_string2(const void *e1, const void *e2)
1526 const char *s1 = *(const char *const *)e1;
1527 const char *s2 = *(const char *const *)e2;
1529 return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1532 static int compare_string3(const void *e1, const void *e2)
1534 const char *s1 = *(const char *const *)e1;
1535 const char *s2 = *(const char *const *)e2;
1536 char key1[256], key2[256];
1538 LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
1539 LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
1540 return strcmp(key1, key2);
1543 static void test_sorting(void)
1545 char buf[256];
1546 char **str_buf = (char **)buf;
1547 int i;
1549 assert(sizeof(buf) >= sizeof(strings));
1551 /* 1. sort using lstrcmpA */
1552 memcpy(buf, strings, sizeof(strings));
1553 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
1554 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1556 ok(!strcmp(strings_sorted[i], str_buf[i]),
1557 "qsort using lstrcmpA failed for element %d\n", i);
1559 /* 2. sort using CompareStringA */
1560 memcpy(buf, strings, sizeof(strings));
1561 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
1562 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1564 ok(!strcmp(strings_sorted[i], str_buf[i]),
1565 "qsort using CompareStringA failed for element %d\n", i);
1567 /* 3. sort using sort keys */
1568 memcpy(buf, strings, sizeof(strings));
1569 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
1570 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1572 ok(!strcmp(strings_sorted[i], str_buf[i]),
1573 "qsort using sort keys failed for element %d\n", i);
1577 static void test_FoldStringA(void)
1579 int ret, i;
1580 char src[256], dst[256];
1581 static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0' };
1582 static const char digits_dst[] = { '1','2','3','\0' };
1583 static const char composite_src[] =
1585 0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
1586 0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
1587 0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
1588 0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
1589 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
1590 0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
1591 0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
1592 0xfb,0xfc,0xfd,0xff,'\0'
1594 static const char composite_dst[] =
1596 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1597 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1598 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1599 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1600 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1601 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1602 0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
1603 0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
1604 0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
1605 0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
1606 0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
1607 0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
1608 0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
1609 0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
1610 0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1612 static const char ligatures_src[] =
1614 0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1616 static const char ligatures_dst[] =
1618 'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1621 if (!pFoldStringA)
1622 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1624 /* these tests are locale specific */
1625 if (GetACP() != 1252)
1627 trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1628 return;
1631 /* MAP_FOLDDIGITS */
1632 SetLastError(0);
1633 ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
1634 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1635 return;
1636 ok(ret == 4, "Expected ret == 4, got %d, error %d\n", ret, GetLastError());
1637 ok(strcmp(dst, digits_dst) == 0,
1638 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
1639 for (i = 1; i < 256; i++)
1641 if (!strchr(digits_src, i))
1643 src[0] = i;
1644 src[1] = '\0';
1645 SetLastError(0);
1646 ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
1647 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1648 ok(dst[0] == src[0],
1649 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
1653 /* MAP_EXPAND_LIGATURES */
1654 SetLastError(0);
1655 ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1656 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1657 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1658 ok(ret == sizeof(ligatures_dst), "Got %d, error %d\n", ret, GetLastError());
1659 ok(strcmp(dst, ligatures_dst) == 0,
1660 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
1661 for (i = 1; i < 256; i++)
1663 if (!strchr(ligatures_src, i))
1665 src[0] = i;
1666 src[1] = '\0';
1667 SetLastError(0);
1668 ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1669 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1670 ok(dst[0] == src[0],
1671 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
1676 /* MAP_COMPOSITE */
1677 SetLastError(0);
1678 ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
1679 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1680 todo_wine
1682 /* Wine gets close, but doesn't produce quite the same result as native */
1683 ok(ret == 121, "Expected 121, got %d\n", ret);
1684 ok(strcmp(dst, composite_dst) == 0,
1685 "MAP_COMPOSITE: Expected '%s', got '%s'\n", composite_dst, dst);
1688 for (i = 1; i < 256; i++)
1690 if (!strchr(composite_src, i))
1692 src[0] = i;
1693 src[1] = '\0';
1694 SetLastError(0);
1695 ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
1696 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1697 ok(dst[0] == src[0],
1698 "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
1699 (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
1703 /* MAP_FOLDCZONE */
1704 for (i = 1; i < 256; i++)
1706 src[0] = i;
1707 src[1] = '\0';
1708 SetLastError(0);
1709 ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
1710 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1711 ok(src[0] == dst[0],
1712 "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
1713 (unsigned char)src[0], (unsigned char)dst[0]);
1716 /* MAP_PRECOMPOSED */
1717 for (i = 1; i < 256; i++)
1719 src[0] = i;
1720 src[1] = '\0';
1721 SetLastError(0);
1722 ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
1723 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1724 ok(src[0] == dst[0],
1725 "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
1726 (unsigned char)src[0], (unsigned char)dst[0]);
1730 static void test_FoldStringW(void)
1732 int ret;
1733 unsigned int i, j, failures;
1734 WCHAR src[256], dst[256], ch, prev_ch = 1;
1735 static const DWORD badFlags[] =
1738 MAP_PRECOMPOSED|MAP_COMPOSITE,
1739 MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
1740 MAP_COMPOSITE|MAP_EXPAND_LIGATURES
1742 /* Ranges of digits 0-9 : Must be sorted! */
1743 static const WCHAR digitRanges[] =
1745 0x0030, /* '0'-'9' */
1746 0x0660, /* Eastern Arabic */
1747 0x06F0, /* Arabic - Hindu */
1748 0x0966, /* Devengari */
1749 0x09E6, /* Bengalii */
1750 0x0A66, /* Gurmukhi */
1751 0x0AE6, /* Gujarati */
1752 0x0B66, /* Oriya */
1753 0x0BE6, /* Tamil - No 0 */
1754 0x0C66, /* Telugu */
1755 0x0CE6, /* Kannada */
1756 0x0D66, /* Maylayalam */
1757 0x0E50, /* Thai */
1758 0x0ED0, /* Laos */
1759 0x2070, /* Superscript - 1, 2, 3 are out of sequence */
1760 0x2080, /* Subscript */
1761 0x245F, /* Circled - 0 is out of sequence */
1762 0x2473, /* Bracketed */
1763 0x2487, /* Full stop */
1764 0x2775, /* Inverted circled - No 0 */
1765 0x277F, /* Patterned circled - No 0 */
1766 0x2789, /* Inverted Patterned circled - No 0 */
1767 0xff10, /* Pliene chasse (?) */
1768 0xffff /* Terminator */
1770 /* Digits which are represented, but out of sequence */
1771 static const WCHAR outOfSequenceDigits[] =
1773 0xB9, /* Superscript 1 */
1774 0xB2, /* Superscript 2 */
1775 0xB3, /* Superscript 3 */
1776 0x24EA, /* Circled 0 */
1777 '\0' /* Terminator */
1779 /* Digits in digitRanges for which no representation is available */
1780 static const WCHAR noDigitAvailable[] =
1782 0x0BE6, /* No Tamil 0 */
1783 0x2473, /* No Bracketed 0 */
1784 0x2487, /* No 0 Full stop */
1785 0x2775, /* No inverted circled 0 */
1786 0x277F, /* No patterned circled */
1787 0x2789, /* No inverted Patterned circled */
1788 '\0' /* Terminator */
1790 /* Compatibility conversion results */
1791 static const WCHAR compat_F900_FA2F[256+48] =
1793 0x8c48, 0x66f4, 0x8eca, 0x8cc8, 0x6ed1, 0x4e32, 0x53e5, 0x9f9c,
1794 0x9f9c, 0x5951, 0x91d1, 0x5587, 0x5948, 0x61f6, 0x7669, 0x7f85,
1795 0x863f, 0x87ba, 0x88f8, 0x908f, 0x6a02, 0x6d1b, 0x70d9, 0x73de,
1796 0x843d, 0x916a, 0x99f1, 0x4e82, 0x5375, 0x6b04, 0x721b, 0x862d,
1797 0x9e1e, 0x5d50, 0x6feb, 0x85cd, 0x8964, 0x62c9, 0x81d8, 0x881f,
1798 0x5eca, 0x6717, 0x6d6a, 0x72fc, 0x0000, 0x4f86, 0x51b7, 0x52de,
1799 0x64c4, 0x6ad3, 0x7210, 0x76e7, 0x8001, 0x8606, 0x865c, 0x8def,
1800 0x9732, 0x9b6f, 0x9dfa, 0x788c, 0x797f, 0x7da0, 0x83c9, 0x9304,
1801 0x9e7f, 0x8ad6, 0x58df, 0x5f04, 0x7c60, 0x807e, 0x7262, 0x78ca,
1802 0x8cc2, 0x96f7, 0x58d8, 0x5c62, 0x6a13, 0x6dda, 0x6f0f, 0x7d2f,
1803 0x7e37, 0x964b, 0x52d2, 0x808b, 0x51dc, 0x51cc, 0x7a1c, 0x7dbe,
1804 0x83f1, 0x9675, 0x8b80, 0x62cf, 0x6a02, 0x8afe, 0x4e39, 0x5be7,
1805 0x6012, 0x7387, 0x7570, 0x5317, 0x78fb, 0x4fbf, 0x5fa9, 0x4e0d,
1806 0x6ccc, 0x6578, 0x7d22, 0x53c3, 0x585e, 0x7701, 0x8449, 0x8aaa,
1807 0x6bba, 0x8fb0, 0x6c88, 0x62fe, 0x82e5, 0x63a0, 0x7565, 0x4eae,
1808 0x5169, 0x0000, 0x6881, 0x7ce7, 0x826f, 0x8ad2, 0x91cf, 0x52f5,
1809 0x5442, 0x5973, 0x5eec, 0x65c5, 0x6ffe, 0x792a, 0x95ad, 0x9a6a,
1810 0x9e97, 0x9ece, 0x529b, 0x66c6, 0x6b77, 0x8f62, 0x5e74, 0x6190,
1811 0x6200, 0x649a, 0x6f23, 0x7149, 0x7489, 0x0000, 0x7df4, 0x806f,
1812 0x8f26, 0x84ee, 0x9023, 0x934a, 0x5217, 0x52a3, 0x54bd, 0x70c8,
1813 0x88c2, 0x8aaa, 0x5ec9, 0x5ff5, 0x637b, 0x6bae, 0x7c3e, 0x7375,
1814 0x4ee4, 0x56f9, 0x5be7, 0x5dba, 0x601c, 0x73b2, 0x7469, 0x7f9a,
1815 0x8046, 0x9234, 0x96f6, 0x9748, 0x9818, 0x4f8b, 0x79ae, 0x91b4,
1816 0x96b8, 0x60e1, 0x4e86, 0x50da, 0x5bee, 0x5c3f, 0x6599, 0x6a02,
1817 0x71ce, 0x7642, 0x84fc, 0x907c, 0x9f8d, 0x6688, 0x962e, 0x5289,
1818 0x677b, 0x67f3, 0x6d41, 0x6e9c, 0x7409, 0x7559, 0x786b, 0x7d10,
1819 0x985e, 0x516d, 0x622e, 0x9678, 0x502b, 0x5d19, 0x6dea, 0x8f2a,
1820 0x5f8b, 0x6144, 0x6817, 0x7387, 0x9686, 0x5229, 0x540f, 0x5c65,
1821 0x6613, 0x674e, 0x68a8, 0x6ce5, 0x7406, 0x75e2, 0x7f79, 0x0000,
1822 0x88e1, 0x91cc, 0x96e2, 0x533f, 0x6eba, 0x541d, 0x71d0, 0x7498,
1823 0x85fa, 0x0000, 0x9c57, 0x9e9f, 0x6797, 0x6dcb, 0x81e8, 0x7acb,
1824 0x7b20, 0x7c92, 0x72c0, 0x7099, 0x8b58, 0x4ec0, 0x8336, 0x523a,
1825 0x5207, 0x5ea6, 0x62d3, 0x7cd6, 0x5b85, 0x6d1e, 0x66b4, 0x8f3b,
1826 0x884c, 0x964d, 0x898b, 0x5ed3, 0x0000, 0x0000, 0x0000, 0x0000,
1827 0x585a, 0x0000, 0x6674, 0x0000, 0x0000, 0x51de, 0x8c6c, 0x76ca,
1828 0x0000, 0x795e, 0x7965, 0x798f, 0x9756, 0x7cbe, 0x7fbd, 0x0000,
1829 0x0000, 0x0000, 0x8af8, 0x0000, 0x0000, 0x9038, 0x90fd, 0x0000,
1830 0x0000, 0x0000, 0x98ef, 0x98fc, 0x9928, 0x9db4, 0x0000, 0x0000
1832 static const WCHAR compat_FE30_FEF7[200] =
1834 0x2025, 0x2014, 0x2013, 0x005f, 0x005f, 0x0028, 0x0029, 0x007b,
1835 0x007d, 0x3014, 0x3015, 0x3010, 0x3011, 0x300a, 0x300b, 0x3008,
1836 0x3009, 0x300c, 0x300d, 0x300e, 0x300f, 0x0000, 0x0000, 0x0000,
1837 0x0000, 0x203e, 0x203e, 0x203e, 0x203e, 0x005f, 0x005f, 0x005f,
1838 0x002c, 0x3001, 0x002e, 0x0000, 0x003b, 0x003a, 0x003f, 0x0021,
1839 0x2014, 0x0028, 0x0029, 0x007b, 0x007d, 0x3014, 0x3015, 0x0023,
1840 0x0026, 0x002a, 0x002b, 0x002d, 0x003c, 0x003e, 0x003d, 0x0000,
1841 0x0000, 0x0024, 0x0025, 0x0040, 0x0000, 0x0000, 0x0000, 0x0000,
1842 0x064b, 0x064b, 0x064c, 0x0000, 0x064d, 0x0000, 0x064e, 0x064e,
1843 0x064f, 0x064f, 0x0650, 0x0650, 0x0651, 0x0651, 0x0652, 0x0652,
1844 0x0621, 0x0622, 0x0622, 0x0623, 0x0623, 0x0624, 0x0624, 0x0625,
1845 0x0625, 0x0626, 0x0626, 0x0626, 0x0626, 0x0627, 0x0627, 0x0628,
1846 0x0628, 0x0628, 0x0628, 0x0629, 0x0629, 0x062a, 0x062a, 0x062a,
1847 0x062a, 0x062b, 0x062b, 0x062b, 0x062b, 0x062c, 0x062c, 0x062c,
1848 0x062c, 0x062d, 0x062d, 0x062d, 0x062d, 0x062e, 0x062e, 0x062e,
1849 0x062e, 0x062f, 0x062f, 0x0630, 0x0630, 0x0631, 0x0631, 0x0632,
1850 0x0632, 0x0633, 0x0633, 0x0633, 0x0633, 0x0634, 0x0634, 0x0634,
1851 0x0634, 0x0635, 0x0635, 0x0635, 0x0635, 0x0636, 0x0636, 0x0636,
1852 0x0636, 0x0637, 0x0637, 0x0637, 0x0637, 0x0638, 0x0638, 0x0638,
1853 0x0638, 0x0639, 0x0639, 0x0639, 0x0639, 0x063a, 0x063a, 0x063a,
1854 0x063a, 0x0641, 0x0641, 0x0641, 0x0641, 0x0642, 0x0642, 0x0642,
1855 0x0642, 0x0643, 0x0643, 0x0643, 0x0643, 0x0644, 0x0644, 0x0644,
1856 0x0644, 0x0645, 0x0645, 0x0645, 0x0645, 0x0646, 0x0646, 0x0646,
1857 0x0646, 0x0647, 0x0647, 0x0647, 0x0647, 0x0648, 0x0648, 0x0649,
1858 0x0649, 0x064a, 0x064a, 0x064a, 0x064a, 0x0000, 0x0000, 0x0000
1860 static const WCHAR compat_FF00_FFEF[240] =
1862 0x0000, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
1863 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
1864 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
1865 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
1866 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
1867 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
1868 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
1869 0x0058, 0x0059, 0x005a, 0x005b, 0x0000, 0x005d, 0x005e, 0x005f,
1870 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
1871 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
1872 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
1873 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000,
1874 0x0000, 0x3002, 0x300c, 0x300d, 0x3001, 0x30fb, 0x30f2, 0x30a1,
1875 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, 0x30c3,
1876 0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, 0x30ab, 0x30ad,
1877 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, 0x30b9, 0x30bb, 0x30bd,
1878 0x30bf, 0x30c1, 0x30c4, 0x30c6, 0x30c8, 0x30ca, 0x30cb, 0x30cc,
1879 0x30cd, 0x30ce, 0x30cf, 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de,
1880 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9,
1881 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c,
1882 0x3164, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137,
1883 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f,
1884 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147,
1885 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x0000,
1886 0x0000, 0x0000, 0x314f, 0x3150, 0x3151, 0x3152, 0x3153, 0x3154,
1887 0x0000, 0x0000, 0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315a,
1888 0x0000, 0x0000, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, 0x3160,
1889 0x0000, 0x0000, 0x3161, 0x3162, 0x3163, 0x0000, 0x0000, 0x0000,
1890 0x00a2, 0x00a3, 0x00ac, 0x00af, 0x00a6, 0x00a5, 0x20a9, 0x0000,
1891 0x2502, 0x2190, 0x2191, 0x2192, 0x2193, 0x25a0, 0x25cb, 0x0000
1893 static const WCHAR ligatures_src[] =
1895 0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
1896 0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
1897 0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
1898 0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
1899 0xfb04, 0xfb05, 0xfb06, '\0'
1901 static const WCHAR ligatures_dst[] =
1903 'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
1904 'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
1905 'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
1906 0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
1907 'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
1910 if (!pFoldStringW)
1912 win_skip("FoldStringW is not available\n");
1913 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1916 /* Invalid flag combinations */
1917 for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
1919 src[0] = dst[0] = '\0';
1920 SetLastError(0);
1921 ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
1922 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1924 win_skip("FoldStringW is not implemented\n");
1925 return;
1927 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
1928 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1931 /* src & dst cannot be the same */
1932 SetLastError(0);
1933 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
1934 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1935 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1937 /* src can't be NULL */
1938 SetLastError(0);
1939 ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
1940 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1941 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1943 /* srclen can't be 0 */
1944 SetLastError(0);
1945 ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
1946 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1947 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1949 /* dstlen can't be < 0 */
1950 SetLastError(0);
1951 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
1952 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1953 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1955 /* Ret includes terminating NUL which is appended if srclen = -1 */
1956 SetLastError(0);
1957 src[0] = 'A';
1958 src[1] = '\0';
1959 dst[0] = '\0';
1960 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
1961 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1962 ok(dst[0] == 'A' && dst[1] == '\0',
1963 "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%d\n",
1964 'A', '\0', ret, dst[0], dst[1], GetLastError());
1966 /* If size is given, result is not NUL terminated */
1967 SetLastError(0);
1968 src[0] = 'A';
1969 src[1] = 'A';
1970 dst[0] = 'X';
1971 dst[1] = 'X';
1972 ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
1973 ok(ret == 1, "Expected ret == 1, got %d, error %d\n", ret, GetLastError());
1974 ok(dst[0] == 'A' && dst[1] == 'X',
1975 "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%d\n",
1976 'A','X', ret, dst[0], dst[1], GetLastError());
1978 /* MAP_FOLDDIGITS */
1979 for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
1981 /* Check everything before this range */
1982 for (ch = prev_ch; ch < digitRanges[j]; ch++)
1984 SetLastError(0);
1985 src[0] = ch;
1986 src[1] = dst[0] = '\0';
1987 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
1988 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1990 ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
1991 /* Wine (correctly) maps all Unicode 4.0+ digits */
1992 isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF ||
1993 (ch >= 0x1369 && ch <= 0x1371),
1994 "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
1997 if (digitRanges[j] == 0xffff)
1998 break; /* Finished the whole code point space */
2000 for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
2002 WCHAR c;
2004 /* Map out of sequence characters */
2005 if (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
2006 else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
2007 else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
2008 else if (ch == 0x245F) c = 0x24EA; /* Circled 0 */
2009 else c = ch;
2010 SetLastError(0);
2011 src[0] = c;
2012 src[1] = dst[0] = '\0';
2013 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2014 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2016 ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
2017 broken( dst[0] == ch ) || /* old Windows versions don't have all mappings */
2018 strchrW(noDigitAvailable, c),
2019 "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
2020 ch, '0' + digitRanges[j] - ch, dst[0]);
2022 prev_ch = ch;
2025 /* MAP_FOLDCZONE */
2026 for (ch = 1, failures = 0; ch <0xffff; ch++)
2028 WCHAR expected = 0;
2030 if (ch >= 0xF900 && ch <= 0xFA2F)
2031 expected = compat_F900_FA2F[ch - 0xF900];
2032 else if (ch >= 0xFE30 && ch <= 0xFEF7)
2033 expected = compat_FE30_FEF7[ch - 0xFE30];
2034 else if (ch >= 0xFF00 && ch <= 0xFFEF)
2035 expected = compat_FF00_FFEF[ch - 0xFF00];
2037 if (!expected)
2038 expected = ch;
2040 SetLastError(0);
2041 src[0] = ch;
2042 src[1] = dst[0] = '\0';
2043 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
2044 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2045 ok(dst[0] == expected ||
2046 broken( dst[0] == ch ) || /* old Windows versions don't have all mappings */
2047 /* Wine (correctly) uses updated mappings for some Unicode 4.0 chars */
2048 /* FIXME: But they should be re-checked */
2049 ch == 0xf92c || ch == 0xf979 || ch == 0xf995 || ch == 0xf9e7 ||
2050 ch == 0xf9f1 ||
2051 (0xfa0c <= ch && ch <= 0xfa6a) ||
2052 (0xfa70 <= ch && ch <= 0xfad9) ||
2053 ch == 0xfe47 || ch == 0xfe48 || ch == 0xfe68 ||
2054 (0xfe70 <= ch && ch <= 0xfe7f) ||
2055 ch == 0xff3c || ch == 0xff5f || ch == 0xff60 ||
2056 ch == 0xff9e || ch == 0xff9f,
2057 "MAP_FOLDCZONE: ch %d 0x%04x Expected 0x%04x got 0x%04x\n",
2058 ch, ch, expected, dst[0]);
2059 if (dst[0] != expected && ch < 0xf000 && ++failures > 50)
2061 trace( "MAP_FOLDCZONE: Too many failures, giving up\n" );
2062 break;
2066 /* MAP_EXPAND_LIGATURES */
2067 SetLastError(0);
2068 ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
2069 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
2070 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
2071 ok(ret == sizeof(ligatures_dst)/sizeof(ligatures_dst[0]),
2072 "Got %d, error %d\n", ret, GetLastError());
2073 ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
2074 "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
2075 for (i = 1, failures = 0; i <= 0xffff; i++)
2077 if (!strchrW(ligatures_src, i))
2079 src[0] = i;
2080 src[1] = '\0';
2081 SetLastError(0);
2082 ret = pFoldStringW(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
2083 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2084 if (ret == 3)
2085 ok(0, "MAP_EXPAND_LIGATURES: %04x : Expected %04x, got %04x %04x\n",
2086 i, src[0], dst[0], dst[1]);
2087 else
2088 ok(dst[0] == src[0],
2089 "MAP_EXPAND_LIGATURES: %04x : Expected %04x, got %04x\n",
2090 i, src[0], dst[0]);
2091 if (dst[0] != src[0] && ++failures > 50)
2093 trace( "MAP_EXPAND_LIGATURES: Too many failures, giving up\n" );
2094 break;
2100 /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
2105 #define LCID_OK(l) \
2106 ok(lcid == l, "Expected lcid = %08x, got %08x\n", l, lcid)
2107 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
2108 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
2109 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
2110 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
2112 static void test_ConvertDefaultLocale(void)
2114 LCID lcid;
2116 /* Doesn't change lcid, even if non default sublang/sort used */
2117 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_US, SORT_DEFAULT);
2118 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_UK, SORT_DEFAULT);
2119 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT);
2120 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE);
2122 /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
2123 LCID_RES(MKLCID(LANG_ENGLISH, SUBLANG_NEUTRAL, SORT_DEFAULT),
2124 MKLCID(LANG_ENGLISH, SUBLANG_DEFAULT, SORT_DEFAULT));
2125 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
2126 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
2127 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_JAPANESE_UNICODE),
2128 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE));
2130 /* Invariant language is not treated specially */
2131 TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
2132 LCID_RES(MKLCID(LANG_INVARIANT, SUBLANG_NEUTRAL, SORT_DEFAULT),
2133 MKLCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT));
2135 /* User/system default languages alone are not mapped */
2136 TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
2137 TEST_LCIDLANG(LANG_USER_DEFAULT, SORT_JAPANESE_UNICODE);
2139 /* Default lcids */
2140 LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
2141 LCID_RES(LOCALE_USER_DEFAULT, GetUserDefaultLCID());
2142 LCID_RES(LOCALE_NEUTRAL, GetUserDefaultLCID());
2145 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
2146 DWORD dwFlags, LONG_PTR lParam)
2148 trace("%08x, %s, %s, %08x, %08lx\n",
2149 lgrpid, lpszNum, lpszName, dwFlags, lParam);
2151 ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
2152 "Enumerated grp %d not valid (flags %d)\n", lgrpid, dwFlags);
2154 /* If lParam is one, we are calling with flags defaulted from 0 */
2155 ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
2156 "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %d\n", dwFlags);
2158 return TRUE;
2161 static void test_EnumSystemLanguageGroupsA(void)
2163 BOOL ret;
2165 if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
2167 win_skip("EnumSystemLanguageGroupsA and/or IsValidLanguageGroup are not available\n");
2168 return;
2171 /* No enumeration proc */
2172 SetLastError(0);
2173 ret = pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
2174 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2176 win_skip("EnumSystemLanguageGroupsA is not implemented\n");
2177 return;
2179 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2180 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2182 /* Invalid flags */
2183 SetLastError(0);
2184 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
2185 ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2187 /* No flags - defaults to LGRPID_INSTALLED */
2188 SetLastError(0xdeadbeef);
2189 pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
2190 ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
2192 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
2193 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
2197 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
2198 LONG_PTR lParam)
2200 trace("%08x, %08x, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
2202 /* invalid locale enumerated on some platforms */
2203 if (lcid == 0)
2204 return TRUE;
2206 ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
2207 "Enumerated grp %d not valid\n", lgrpid);
2208 ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
2209 "Enumerated grp locale %d not valid\n", lcid);
2210 return TRUE;
2213 static void test_EnumLanguageGroupLocalesA(void)
2215 BOOL ret;
2217 if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
2219 win_skip("EnumLanguageGroupLocalesA and/or IsValidLanguageGroup are not available\n");
2220 return;
2223 /* No enumeration proc */
2224 SetLastError(0);
2225 ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
2226 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2228 win_skip("EnumLanguageGroupLocalesA is not implemented\n");
2229 return;
2231 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2232 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2234 /* lgrpid too small */
2235 SetLastError(0);
2236 ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
2237 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2238 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2240 /* lgrpid too big */
2241 SetLastError(0);
2242 ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
2243 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2244 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2246 /* dwFlags is reserved */
2247 SetLastError(0);
2248 ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
2249 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2250 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2252 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2255 static void test_SetLocaleInfoA(void)
2257 BOOL bRet;
2258 LCID lcid = GetUserDefaultLCID();
2260 /* Null data */
2261 SetLastError(0);
2262 bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2263 ok( !bRet && GetLastError() == ERROR_INVALID_PARAMETER,
2264 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2266 /* IDATE */
2267 SetLastError(0);
2268 bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
2269 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2270 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2272 /* ILDATE */
2273 SetLastError(0);
2274 bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
2275 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2276 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2279 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2281 trace("%s %08lx\n", value, lParam);
2282 return(TRUE);
2285 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2287 ok(!enumCount, "callback called again unexpected\n");
2288 enumCount++;
2289 return(FALSE);
2292 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2294 ok(0,"callback called unexpected\n");
2295 return(FALSE);
2298 static void test_EnumUILanguageA(void)
2300 BOOL ret;
2301 if (!pEnumUILanguagesA) {
2302 win_skip("EnumUILanguagesA is not available on Win9x or NT4\n");
2303 return;
2306 SetLastError(ERROR_SUCCESS);
2307 ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2308 if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2310 win_skip("EnumUILanguagesA is not implemented\n");
2311 return;
2313 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2315 enumCount = 0;
2316 SetLastError(ERROR_SUCCESS);
2317 ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2318 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2320 SetLastError(ERROR_SUCCESS);
2321 ret = pEnumUILanguagesA(NULL, 0, 0);
2322 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2323 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2324 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2326 SetLastError(ERROR_SUCCESS);
2327 ret = pEnumUILanguagesA(luilocale_proc3A, 0x5a5a5a5a, 0);
2328 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2329 ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2331 SetLastError(ERROR_SUCCESS);
2332 ret = pEnumUILanguagesA(NULL, 0x5a5a5a5a, 0);
2333 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2334 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2335 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2338 static char date_fmt_buf[1024];
2340 static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
2342 lstrcatA(date_fmt_buf, fmt);
2343 lstrcatA(date_fmt_buf, "\n");
2344 return TRUE;
2347 static void test_EnumDateFormatsA(void)
2349 char *p, buf[256];
2350 BOOL ret;
2351 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2353 trace("EnumDateFormatsA 0\n");
2354 date_fmt_buf[0] = 0;
2355 SetLastError(0xdeadbeef);
2356 ret = EnumDateFormatsA(enum_datetime_procA, lcid, 0);
2357 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2359 win_skip("0 for dwFlags is not supported\n");
2361 else
2363 ok(ret, "EnumDateFormatsA(0) error %d\n", GetLastError());
2364 trace("%s\n", date_fmt_buf);
2365 /* test the 1st enumerated format */
2366 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2367 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2368 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2369 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2372 trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n");
2373 date_fmt_buf[0] = 0;
2374 SetLastError(0xdeadbeef);
2375 ret = EnumDateFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2376 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2378 win_skip("LOCALE_USE_CP_ACP is not supported\n");
2380 else
2382 ok(ret, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2383 trace("%s\n", date_fmt_buf);
2384 /* test the 1st enumerated format */
2385 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2386 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2387 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2388 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2391 trace("EnumDateFormatsA DATE_SHORTDATE\n");
2392 date_fmt_buf[0] = 0;
2393 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_SHORTDATE);
2394 ok(ret, "EnumDateFormatsA(DATE_SHORTDATE) error %d\n", GetLastError());
2395 trace("%s\n", date_fmt_buf);
2396 /* test the 1st enumerated format */
2397 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2398 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2399 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2400 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2402 trace("EnumDateFormatsA DATE_LONGDATE\n");
2403 date_fmt_buf[0] = 0;
2404 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_LONGDATE);
2405 ok(ret, "EnumDateFormatsA(DATE_LONGDATE) error %d\n", GetLastError());
2406 trace("%s\n", date_fmt_buf);
2407 /* test the 1st enumerated format */
2408 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2409 ret = GetLocaleInfoA(lcid, LOCALE_SLONGDATE, buf, sizeof(buf));
2410 ok(ret, "GetLocaleInfoA(LOCALE_SLONGDATE) error %d\n", GetLastError());
2411 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2413 trace("EnumDateFormatsA DATE_YEARMONTH\n");
2414 date_fmt_buf[0] = 0;
2415 SetLastError(0xdeadbeef);
2416 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_YEARMONTH);
2417 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2419 skip("DATE_YEARMONTH is only present on W2K and later\n");
2420 return;
2422 ok(ret, "EnumDateFormatsA(DATE_YEARMONTH) error %d\n", GetLastError());
2423 trace("%s\n", date_fmt_buf);
2424 /* test the 1st enumerated format */
2425 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2426 ret = GetLocaleInfoA(lcid, LOCALE_SYEARMONTH, buf, sizeof(buf));
2427 ok(ret, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %d\n", GetLastError());
2428 ok(!lstrcmpA(date_fmt_buf, buf) || broken(!buf[0]) /* win9x */,
2429 "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2432 static void test_EnumTimeFormatsA(void)
2434 char *p, buf[256];
2435 BOOL ret;
2436 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2438 trace("EnumTimeFormatsA 0\n");
2439 date_fmt_buf[0] = 0;
2440 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, 0);
2441 ok(ret, "EnumTimeFormatsA(0) error %d\n", GetLastError());
2442 trace("%s\n", date_fmt_buf);
2443 /* test the 1st enumerated format */
2444 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2445 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2446 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2447 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2449 trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n");
2450 date_fmt_buf[0] = 0;
2451 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2452 ok(ret, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2453 trace("%s\n", date_fmt_buf);
2454 /* test the 1st enumerated format */
2455 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2456 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2457 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2458 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2461 static void test_GetCPInfo(void)
2463 BOOL ret;
2464 CPINFO cpinfo;
2466 SetLastError(0xdeadbeef);
2467 ret = GetCPInfo(CP_SYMBOL, &cpinfo);
2468 ok(!ret, "GetCPInfo(CP_SYMBOL) should fail\n");
2469 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2470 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2472 SetLastError(0xdeadbeef);
2473 ret = GetCPInfo(CP_UTF7, &cpinfo);
2474 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2476 skip("Codepage CP_UTF7 is not installed/available\n");
2478 else
2480 ok(ret, "GetCPInfo(CP_UTF7) error %u\n", GetLastError());
2481 ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2482 ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2483 ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2484 ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2485 ok(cpinfo.MaxCharSize == 5, "expected 5, got 0x%x\n", cpinfo.MaxCharSize);
2488 SetLastError(0xdeadbeef);
2489 ret = GetCPInfo(CP_UTF8, &cpinfo);
2490 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2492 skip("Codepage CP_UTF8 is not installed/available\n");
2494 else
2496 ok(ret, "GetCPInfo(CP_UTF8) error %u\n", GetLastError());
2497 ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2498 ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2499 ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2500 ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2501 ok(cpinfo.MaxCharSize == 4 || broken(cpinfo.MaxCharSize == 3) /* win9x */,
2502 "expected 4, got %u\n", cpinfo.MaxCharSize);
2506 START_TEST(locale)
2508 InitFunctionPointers();
2510 test_EnumTimeFormatsA();
2511 test_EnumDateFormatsA();
2512 test_GetLocaleInfoA();
2513 test_GetTimeFormatA();
2514 test_GetDateFormatA();
2515 test_GetDateFormatW();
2516 test_GetCurrencyFormatA(); /* Also tests the W version */
2517 test_GetNumberFormatA(); /* Also tests the W version */
2518 test_CompareStringA();
2519 test_LCMapStringA();
2520 test_LCMapStringW();
2521 test_FoldStringA();
2522 test_FoldStringW();
2523 test_ConvertDefaultLocale();
2524 test_EnumSystemLanguageGroupsA();
2525 test_EnumLanguageGroupLocalesA();
2526 test_SetLocaleInfoA();
2527 test_EnumUILanguageA();
2528 test_GetCPInfo();
2529 /* this requires collation table patch to make it MS compatible */
2530 if (0) test_sorting();