user32: Fix user_thread_info for 64-bits
[wine/wine64.git] / dlls / kernel32 / tests / locale.c
blob4dce7335e0bc09b659ddbb4f9fda68877ebc7594
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");
1115 static void test_LCMapStringA(void)
1117 int ret, ret2;
1118 char buf[256], buf2[256];
1119 static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
1120 static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
1121 static const char symbols_stripped[] = "justateststring1";
1123 SetLastError(0xdeadbeef);
1124 ret = LCMapStringA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP | LCMAP_LOWERCASE,
1125 lower_case, -1, buf, sizeof(buf));
1126 ok(ret == lstrlenA(lower_case) + 1,
1127 "ret %d, error %d, expected value %d\n",
1128 ret, GetLastError(), lstrlenA(lower_case) + 1);
1129 ok(!memcmp(buf, lower_case, ret), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1131 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1132 upper_case, -1, buf, sizeof(buf));
1133 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1134 ok(GetLastError() == ERROR_INVALID_FLAGS,
1135 "unexpected error code %d\n", GetLastError());
1137 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1138 upper_case, -1, buf, sizeof(buf));
1139 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1140 ok(GetLastError() == ERROR_INVALID_FLAGS,
1141 "unexpected error code %d\n", GetLastError());
1143 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1144 upper_case, -1, buf, sizeof(buf));
1145 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1146 ok(GetLastError() == ERROR_INVALID_FLAGS,
1147 "unexpected error code %d\n", GetLastError());
1149 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1150 upper_case, -1, buf, sizeof(buf));
1151 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1152 ok(GetLastError() == ERROR_INVALID_FLAGS,
1153 "unexpected error code %d\n", GetLastError());
1155 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1156 SetLastError(0xdeadbeef);
1157 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1158 upper_case, -1, buf, sizeof(buf));
1159 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1160 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1162 /* test LCMAP_LOWERCASE */
1163 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1164 upper_case, -1, buf, sizeof(buf));
1165 ok(ret == lstrlenA(upper_case) + 1,
1166 "ret %d, error %d, expected value %d\n",
1167 ret, GetLastError(), lstrlenA(upper_case) + 1);
1168 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1170 /* test LCMAP_UPPERCASE */
1171 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1172 lower_case, -1, buf, sizeof(buf));
1173 ok(ret == lstrlenA(lower_case) + 1,
1174 "ret %d, error %d, expected value %d\n",
1175 ret, GetLastError(), lstrlenA(lower_case) + 1);
1176 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1178 /* test buffer overflow */
1179 SetLastError(0xdeadbeef);
1180 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1181 lower_case, -1, buf, 4);
1182 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1183 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1185 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1186 lstrcpyA(buf, lower_case);
1187 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1188 buf, -1, buf, sizeof(buf));
1189 if (!ret) /* Win9x */
1190 trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1191 else
1193 ok(ret == lstrlenA(lower_case) + 1,
1194 "ret %d, error %d, expected value %d\n",
1195 ret, GetLastError(), lstrlenA(lower_case) + 1);
1196 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1198 lstrcpyA(buf, upper_case);
1199 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1200 buf, -1, buf, sizeof(buf));
1201 if (!ret) /* Win9x */
1202 trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1203 else
1205 ok(ret == lstrlenA(upper_case) + 1,
1206 "ret %d, error %d, expected value %d\n",
1207 ret, GetLastError(), lstrlenA(lower_case) + 1);
1208 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1211 /* otherwise src == dst should fail */
1212 SetLastError(0xdeadbeef);
1213 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1214 buf, 10, buf, sizeof(buf));
1215 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1216 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1217 "unexpected error code %d\n", GetLastError());
1218 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1220 /* test whether '\0' is always appended */
1221 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1222 upper_case, -1, buf, sizeof(buf));
1223 ok(ret, "LCMapStringA must succeed\n");
1224 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1225 upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1226 ok(ret, "LCMapStringA must succeed\n");
1227 ok(ret == ret2, "lengths of sort keys must be equal\n");
1228 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1230 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1231 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1232 upper_case, -1, buf, sizeof(buf));
1233 ok(ret, "LCMapStringA must succeed\n");
1234 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1235 lower_case, -1, buf2, sizeof(buf2));
1236 ok(ret2, "LCMapStringA must succeed\n");
1237 ok(ret == ret2, "lengths of sort keys must be equal\n");
1238 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1240 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1241 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1242 lower_case, -1, buf, sizeof(buf));
1243 ok(ret, "LCMapStringA must succeed\n");
1244 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1245 lower_case, -1, buf2, sizeof(buf2));
1246 ok(ret2, "LCMapStringA must succeed\n");
1247 ok(ret == ret2, "lengths of sort keys must be equal\n");
1248 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1250 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1251 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1252 lower_case, -1, buf, sizeof(buf));
1253 ok(ret, "LCMapStringA must succeed\n");
1254 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1255 symbols_stripped, -1, buf2, sizeof(buf2));
1256 ok(ret2, "LCMapStringA must succeed\n");
1257 ok(ret == ret2, "lengths of sort keys must be equal\n");
1258 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1260 /* test NORM_IGNORENONSPACE */
1261 lstrcpyA(buf, "foo");
1262 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1263 lower_case, -1, buf, sizeof(buf));
1264 ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1265 lstrlenA(lower_case) + 1, ret);
1266 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1268 /* test NORM_IGNORESYMBOLS */
1269 lstrcpyA(buf, "foo");
1270 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1271 lower_case, -1, buf, sizeof(buf));
1272 ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1273 lstrlenA(symbols_stripped) + 1, ret);
1274 ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1276 /* test srclen = 0 */
1277 SetLastError(0xdeadbeef);
1278 ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1279 ok(!ret, "LCMapStringA should fail with srclen = 0\n");
1280 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1281 "unexpected error code %d\n", GetLastError());
1284 static void test_LCMapStringW(void)
1286 int ret, ret2;
1287 WCHAR buf[256], buf2[256];
1288 char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1289 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};
1290 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};
1291 static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
1292 static const WCHAR fooW[] = {'f','o','o',0};
1294 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1295 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1296 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1298 win_skip("LCMapStringW is not implemented\n");
1299 return;
1301 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1302 ok(GetLastError() == ERROR_INVALID_FLAGS,
1303 "unexpected error code %d\n", GetLastError());
1305 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1306 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1307 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1308 ok(GetLastError() == ERROR_INVALID_FLAGS,
1309 "unexpected error code %d\n", GetLastError());
1311 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1312 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1313 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1314 ok(GetLastError() == ERROR_INVALID_FLAGS,
1315 "unexpected error code %d\n", GetLastError());
1317 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1318 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1319 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1320 ok(GetLastError() == ERROR_INVALID_FLAGS,
1321 "unexpected error code %d\n", GetLastError());
1323 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1324 SetLastError(0xdeadbeef);
1325 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1326 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1327 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1328 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1330 /* test LCMAP_LOWERCASE */
1331 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1332 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1333 ok(ret == lstrlenW(upper_case) + 1,
1334 "ret %d, error %d, expected value %d\n",
1335 ret, GetLastError(), lstrlenW(upper_case) + 1);
1336 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1338 /* test LCMAP_UPPERCASE */
1339 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1340 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1341 ok(ret == lstrlenW(lower_case) + 1,
1342 "ret %d, error %d, expected value %d\n",
1343 ret, GetLastError(), lstrlenW(lower_case) + 1);
1344 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1346 /* test buffer overflow */
1347 SetLastError(0xdeadbeef);
1348 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1349 lower_case, -1, buf, 4);
1350 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1351 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1353 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1354 lstrcpyW(buf, lower_case);
1355 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1356 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1357 ok(ret == lstrlenW(lower_case) + 1,
1358 "ret %d, error %d, expected value %d\n",
1359 ret, GetLastError(), lstrlenW(lower_case) + 1);
1360 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1362 lstrcpyW(buf, upper_case);
1363 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1364 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1365 ok(ret == lstrlenW(upper_case) + 1,
1366 "ret %d, error %d, expected value %d\n",
1367 ret, GetLastError(), lstrlenW(lower_case) + 1);
1368 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1370 /* otherwise src == dst should fail */
1371 SetLastError(0xdeadbeef);
1372 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1373 buf, 10, buf, sizeof(buf));
1374 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1375 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1376 "unexpected error code %d\n", GetLastError());
1377 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1379 /* test whether '\0' is always appended */
1380 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1381 upper_case, -1, buf, sizeof(buf));
1382 ok(ret, "LCMapStringW must succeed\n");
1383 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1384 upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1385 ok(ret, "LCMapStringW must succeed\n");
1386 ok(ret == ret2, "lengths of sort keys must be equal\n");
1387 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1389 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1390 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1391 upper_case, -1, buf, sizeof(buf));
1392 ok(ret, "LCMapStringW must succeed\n");
1393 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1394 lower_case, -1, buf2, sizeof(buf2));
1395 ok(ret2, "LCMapStringW must succeed\n");
1396 ok(ret == ret2, "lengths of sort keys must be equal\n");
1397 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1399 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1400 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1401 lower_case, -1, buf, sizeof(buf));
1402 ok(ret, "LCMapStringW must succeed\n");
1403 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1404 lower_case, -1, buf2, sizeof(buf2));
1405 ok(ret2, "LCMapStringW must succeed\n");
1406 ok(ret == ret2, "lengths of sort keys must be equal\n");
1407 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1409 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1410 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1411 lower_case, -1, buf, sizeof(buf));
1412 ok(ret, "LCMapStringW must succeed\n");
1413 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1414 symbols_stripped, -1, buf2, sizeof(buf2));
1415 ok(ret2, "LCMapStringW must succeed\n");
1416 ok(ret == ret2, "lengths of sort keys must be equal\n");
1417 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1419 /* test NORM_IGNORENONSPACE */
1420 lstrcpyW(buf, fooW);
1421 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1422 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1423 ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1424 lstrlenW(lower_case) + 1, ret);
1425 ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1427 /* test NORM_IGNORESYMBOLS */
1428 lstrcpyW(buf, fooW);
1429 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1430 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1431 ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1432 lstrlenW(symbols_stripped) + 1, ret);
1433 ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1435 /* test srclen = 0 */
1436 SetLastError(0xdeadbeef);
1437 ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf)/sizeof(WCHAR));
1438 ok(!ret, "LCMapStringW should fail with srclen = 0\n");
1439 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1440 "unexpected error code %d\n", GetLastError());
1443 /* this requires collation table patch to make it MS compatible */
1444 static const char * const strings_sorted[] =
1446 "'",
1447 "-",
1448 "!",
1449 "\"",
1450 ".",
1451 ":",
1452 "\\",
1453 "_",
1454 "`",
1455 "{",
1456 "}",
1457 "+",
1458 "0",
1459 "1",
1460 "2",
1461 "3",
1462 "4",
1463 "5",
1464 "6",
1465 "7",
1466 "8",
1467 "9",
1468 "a",
1469 "A",
1470 "b",
1471 "B",
1472 "c",
1476 static const char * const strings[] =
1478 "C",
1479 "\"",
1480 "9",
1481 "'",
1482 "}",
1483 "-",
1484 "7",
1485 "+",
1486 "`",
1487 "1",
1488 "a",
1489 "5",
1490 "\\",
1491 "8",
1492 "B",
1493 "3",
1494 "_",
1495 "6",
1496 "{",
1497 "2",
1498 "c",
1499 "4",
1500 "!",
1501 "0",
1502 "A",
1503 ":",
1504 "b",
1508 static int compare_string1(const void *e1, const void *e2)
1510 const char *s1 = *(const char *const *)e1;
1511 const char *s2 = *(const char *const *)e2;
1513 return lstrcmpA(s1, s2);
1516 static int compare_string2(const void *e1, const void *e2)
1518 const char *s1 = *(const char *const *)e1;
1519 const char *s2 = *(const char *const *)e2;
1521 return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1524 static int compare_string3(const void *e1, const void *e2)
1526 const char *s1 = *(const char *const *)e1;
1527 const char *s2 = *(const char *const *)e2;
1528 char key1[256], key2[256];
1530 LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
1531 LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
1532 return strcmp(key1, key2);
1535 static void test_sorting(void)
1537 char buf[256];
1538 char **str_buf = (char **)buf;
1539 int i;
1541 assert(sizeof(buf) >= sizeof(strings));
1543 /* 1. sort using lstrcmpA */
1544 memcpy(buf, strings, sizeof(strings));
1545 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
1546 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1548 ok(!strcmp(strings_sorted[i], str_buf[i]),
1549 "qsort using lstrcmpA failed for element %d\n", i);
1551 /* 2. sort using CompareStringA */
1552 memcpy(buf, strings, sizeof(strings));
1553 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
1554 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1556 ok(!strcmp(strings_sorted[i], str_buf[i]),
1557 "qsort using CompareStringA failed for element %d\n", i);
1559 /* 3. sort using sort keys */
1560 memcpy(buf, strings, sizeof(strings));
1561 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
1562 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1564 ok(!strcmp(strings_sorted[i], str_buf[i]),
1565 "qsort using sort keys failed for element %d\n", i);
1569 static void test_FoldStringA(void)
1571 int ret, i;
1572 char src[256], dst[256];
1573 static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0' };
1574 static const char digits_dst[] = { '1','2','3','\0' };
1575 static const char composite_src[] =
1577 0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
1578 0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
1579 0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
1580 0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
1581 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
1582 0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
1583 0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
1584 0xfb,0xfc,0xfd,0xff,'\0'
1586 static const char composite_dst[] =
1588 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1589 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1590 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1591 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1592 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1593 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1594 0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
1595 0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
1596 0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
1597 0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
1598 0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
1599 0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
1600 0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
1601 0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
1602 0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1604 static const char ligatures_src[] =
1606 0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1608 static const char ligatures_dst[] =
1610 'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1613 if (!pFoldStringA)
1614 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1616 /* these tests are locale specific */
1617 if (GetACP() != 1252)
1619 trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1620 return;
1623 /* MAP_FOLDDIGITS */
1624 SetLastError(0);
1625 ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
1626 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1627 return;
1628 ok(ret == 4, "Expected ret == 4, got %d, error %d\n", ret, GetLastError());
1629 ok(strcmp(dst, digits_dst) == 0,
1630 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
1631 for (i = 1; i < 256; i++)
1633 if (!strchr(digits_src, i))
1635 src[0] = i;
1636 src[1] = '\0';
1637 SetLastError(0);
1638 ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
1639 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1640 ok(dst[0] == src[0],
1641 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
1645 /* MAP_EXPAND_LIGATURES */
1646 SetLastError(0);
1647 ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1648 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1649 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1650 ok(ret == sizeof(ligatures_dst), "Got %d, error %d\n", ret, GetLastError());
1651 ok(strcmp(dst, ligatures_dst) == 0,
1652 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
1653 for (i = 1; i < 256; i++)
1655 if (!strchr(ligatures_src, i))
1657 src[0] = i;
1658 src[1] = '\0';
1659 SetLastError(0);
1660 ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1661 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1662 ok(dst[0] == src[0],
1663 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
1668 /* MAP_COMPOSITE */
1669 SetLastError(0);
1670 ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
1671 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1672 todo_wine
1674 /* Wine gets close, but doesn't produce quite the same result as native */
1675 ok(ret == 121, "Expected 121, got %d\n", ret);
1676 ok(strcmp(dst, composite_dst) == 0,
1677 "MAP_COMPOSITE: Expected '%s', got '%s'\n", composite_dst, dst);
1680 for (i = 1; i < 256; i++)
1682 if (!strchr(composite_src, i))
1684 src[0] = i;
1685 src[1] = '\0';
1686 SetLastError(0);
1687 ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
1688 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1689 ok(dst[0] == src[0],
1690 "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
1691 (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
1695 /* MAP_FOLDCZONE */
1696 for (i = 1; i < 256; i++)
1698 src[0] = i;
1699 src[1] = '\0';
1700 SetLastError(0);
1701 ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
1702 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1703 ok(src[0] == dst[0],
1704 "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
1705 (unsigned char)src[0], (unsigned char)dst[0]);
1708 /* MAP_PRECOMPOSED */
1709 for (i = 1; i < 256; i++)
1711 src[0] = i;
1712 src[1] = '\0';
1713 SetLastError(0);
1714 ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
1715 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1716 ok(src[0] == dst[0],
1717 "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
1718 (unsigned char)src[0], (unsigned char)dst[0]);
1722 static void test_FoldStringW(void)
1724 int ret;
1725 unsigned int i, j, failures;
1726 WCHAR src[256], dst[256], ch, prev_ch = 1;
1727 static const DWORD badFlags[] =
1730 MAP_PRECOMPOSED|MAP_COMPOSITE,
1731 MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
1732 MAP_COMPOSITE|MAP_EXPAND_LIGATURES
1734 /* Ranges of digits 0-9 : Must be sorted! */
1735 static const WCHAR digitRanges[] =
1737 0x0030, /* '0'-'9' */
1738 0x0660, /* Eastern Arabic */
1739 0x06F0, /* Arabic - Hindu */
1740 0x0966, /* Devengari */
1741 0x09E6, /* Bengalii */
1742 0x0A66, /* Gurmukhi */
1743 0x0AE6, /* Gujarati */
1744 0x0B66, /* Oriya */
1745 0x0BE6, /* Tamil - No 0 */
1746 0x0C66, /* Telugu */
1747 0x0CE6, /* Kannada */
1748 0x0D66, /* Maylayalam */
1749 0x0E50, /* Thai */
1750 0x0ED0, /* Laos */
1751 0x2070, /* Superscript - 1, 2, 3 are out of sequence */
1752 0x2080, /* Subscript */
1753 0x245F, /* Circled - 0 is out of sequence */
1754 0x2473, /* Bracketed */
1755 0x2487, /* Full stop */
1756 0x2775, /* Inverted circled - No 0 */
1757 0x277F, /* Patterned circled - No 0 */
1758 0x2789, /* Inverted Patterned circled - No 0 */
1759 0xff10, /* Pliene chasse (?) */
1760 0xffff /* Terminator */
1762 /* Digits which are represented, but out of sequence */
1763 static const WCHAR outOfSequenceDigits[] =
1765 0xB9, /* Superscript 1 */
1766 0xB2, /* Superscript 2 */
1767 0xB3, /* Superscript 3 */
1768 0x24EA, /* Circled 0 */
1769 '\0' /* Terminator */
1771 /* Digits in digitRanges for which no representation is available */
1772 static const WCHAR noDigitAvailable[] =
1774 0x0BE6, /* No Tamil 0 */
1775 0x2473, /* No Bracketed 0 */
1776 0x2487, /* No 0 Full stop */
1777 0x2775, /* No inverted circled 0 */
1778 0x277F, /* No patterned circled */
1779 0x2789, /* No inverted Patterned circled */
1780 '\0' /* Terminator */
1782 /* Compatibility conversion results */
1783 static const WCHAR compat_F900_FA2F[256+48] =
1785 0x8c48, 0x66f4, 0x8eca, 0x8cc8, 0x6ed1, 0x4e32, 0x53e5, 0x9f9c,
1786 0x9f9c, 0x5951, 0x91d1, 0x5587, 0x5948, 0x61f6, 0x7669, 0x7f85,
1787 0x863f, 0x87ba, 0x88f8, 0x908f, 0x6a02, 0x6d1b, 0x70d9, 0x73de,
1788 0x843d, 0x916a, 0x99f1, 0x4e82, 0x5375, 0x6b04, 0x721b, 0x862d,
1789 0x9e1e, 0x5d50, 0x6feb, 0x85cd, 0x8964, 0x62c9, 0x81d8, 0x881f,
1790 0x5eca, 0x6717, 0x6d6a, 0x72fc, 0x0000, 0x4f86, 0x51b7, 0x52de,
1791 0x64c4, 0x6ad3, 0x7210, 0x76e7, 0x8001, 0x8606, 0x865c, 0x8def,
1792 0x9732, 0x9b6f, 0x9dfa, 0x788c, 0x797f, 0x7da0, 0x83c9, 0x9304,
1793 0x9e7f, 0x8ad6, 0x58df, 0x5f04, 0x7c60, 0x807e, 0x7262, 0x78ca,
1794 0x8cc2, 0x96f7, 0x58d8, 0x5c62, 0x6a13, 0x6dda, 0x6f0f, 0x7d2f,
1795 0x7e37, 0x964b, 0x52d2, 0x808b, 0x51dc, 0x51cc, 0x7a1c, 0x7dbe,
1796 0x83f1, 0x9675, 0x8b80, 0x62cf, 0x6a02, 0x8afe, 0x4e39, 0x5be7,
1797 0x6012, 0x7387, 0x7570, 0x5317, 0x78fb, 0x4fbf, 0x5fa9, 0x4e0d,
1798 0x6ccc, 0x6578, 0x7d22, 0x53c3, 0x585e, 0x7701, 0x8449, 0x8aaa,
1799 0x6bba, 0x8fb0, 0x6c88, 0x62fe, 0x82e5, 0x63a0, 0x7565, 0x4eae,
1800 0x5169, 0x0000, 0x6881, 0x7ce7, 0x826f, 0x8ad2, 0x91cf, 0x52f5,
1801 0x5442, 0x5973, 0x5eec, 0x65c5, 0x6ffe, 0x792a, 0x95ad, 0x9a6a,
1802 0x9e97, 0x9ece, 0x529b, 0x66c6, 0x6b77, 0x8f62, 0x5e74, 0x6190,
1803 0x6200, 0x649a, 0x6f23, 0x7149, 0x7489, 0x0000, 0x7df4, 0x806f,
1804 0x8f26, 0x84ee, 0x9023, 0x934a, 0x5217, 0x52a3, 0x54bd, 0x70c8,
1805 0x88c2, 0x8aaa, 0x5ec9, 0x5ff5, 0x637b, 0x6bae, 0x7c3e, 0x7375,
1806 0x4ee4, 0x56f9, 0x5be7, 0x5dba, 0x601c, 0x73b2, 0x7469, 0x7f9a,
1807 0x8046, 0x9234, 0x96f6, 0x9748, 0x9818, 0x4f8b, 0x79ae, 0x91b4,
1808 0x96b8, 0x60e1, 0x4e86, 0x50da, 0x5bee, 0x5c3f, 0x6599, 0x6a02,
1809 0x71ce, 0x7642, 0x84fc, 0x907c, 0x9f8d, 0x6688, 0x962e, 0x5289,
1810 0x677b, 0x67f3, 0x6d41, 0x6e9c, 0x7409, 0x7559, 0x786b, 0x7d10,
1811 0x985e, 0x516d, 0x622e, 0x9678, 0x502b, 0x5d19, 0x6dea, 0x8f2a,
1812 0x5f8b, 0x6144, 0x6817, 0x7387, 0x9686, 0x5229, 0x540f, 0x5c65,
1813 0x6613, 0x674e, 0x68a8, 0x6ce5, 0x7406, 0x75e2, 0x7f79, 0x0000,
1814 0x88e1, 0x91cc, 0x96e2, 0x533f, 0x6eba, 0x541d, 0x71d0, 0x7498,
1815 0x85fa, 0x0000, 0x9c57, 0x9e9f, 0x6797, 0x6dcb, 0x81e8, 0x7acb,
1816 0x7b20, 0x7c92, 0x72c0, 0x7099, 0x8b58, 0x4ec0, 0x8336, 0x523a,
1817 0x5207, 0x5ea6, 0x62d3, 0x7cd6, 0x5b85, 0x6d1e, 0x66b4, 0x8f3b,
1818 0x884c, 0x964d, 0x898b, 0x5ed3, 0x0000, 0x0000, 0x0000, 0x0000,
1819 0x585a, 0x0000, 0x6674, 0x0000, 0x0000, 0x51de, 0x8c6c, 0x76ca,
1820 0x0000, 0x795e, 0x7965, 0x798f, 0x9756, 0x7cbe, 0x7fbd, 0x0000,
1821 0x0000, 0x0000, 0x8af8, 0x0000, 0x0000, 0x9038, 0x90fd, 0x0000,
1822 0x0000, 0x0000, 0x98ef, 0x98fc, 0x9928, 0x9db4, 0x0000, 0x0000
1824 static const WCHAR compat_FE30_FEF7[200] =
1826 0x2025, 0x2014, 0x2013, 0x005f, 0x005f, 0x0028, 0x0029, 0x007b,
1827 0x007d, 0x3014, 0x3015, 0x3010, 0x3011, 0x300a, 0x300b, 0x3008,
1828 0x3009, 0x300c, 0x300d, 0x300e, 0x300f, 0x0000, 0x0000, 0x0000,
1829 0x0000, 0x203e, 0x203e, 0x203e, 0x203e, 0x005f, 0x005f, 0x005f,
1830 0x002c, 0x3001, 0x002e, 0x0000, 0x003b, 0x003a, 0x003f, 0x0021,
1831 0x2014, 0x0028, 0x0029, 0x007b, 0x007d, 0x3014, 0x3015, 0x0023,
1832 0x0026, 0x002a, 0x002b, 0x002d, 0x003c, 0x003e, 0x003d, 0x0000,
1833 0x0000, 0x0024, 0x0025, 0x0040, 0x0000, 0x0000, 0x0000, 0x0000,
1834 0x064b, 0x064b, 0x064c, 0x0000, 0x064d, 0x0000, 0x064e, 0x064e,
1835 0x064f, 0x064f, 0x0650, 0x0650, 0x0651, 0x0651, 0x0652, 0x0652,
1836 0x0621, 0x0622, 0x0622, 0x0623, 0x0623, 0x0624, 0x0624, 0x0625,
1837 0x0625, 0x0626, 0x0626, 0x0626, 0x0626, 0x0627, 0x0627, 0x0628,
1838 0x0628, 0x0628, 0x0628, 0x0629, 0x0629, 0x062a, 0x062a, 0x062a,
1839 0x062a, 0x062b, 0x062b, 0x062b, 0x062b, 0x062c, 0x062c, 0x062c,
1840 0x062c, 0x062d, 0x062d, 0x062d, 0x062d, 0x062e, 0x062e, 0x062e,
1841 0x062e, 0x062f, 0x062f, 0x0630, 0x0630, 0x0631, 0x0631, 0x0632,
1842 0x0632, 0x0633, 0x0633, 0x0633, 0x0633, 0x0634, 0x0634, 0x0634,
1843 0x0634, 0x0635, 0x0635, 0x0635, 0x0635, 0x0636, 0x0636, 0x0636,
1844 0x0636, 0x0637, 0x0637, 0x0637, 0x0637, 0x0638, 0x0638, 0x0638,
1845 0x0638, 0x0639, 0x0639, 0x0639, 0x0639, 0x063a, 0x063a, 0x063a,
1846 0x063a, 0x0641, 0x0641, 0x0641, 0x0641, 0x0642, 0x0642, 0x0642,
1847 0x0642, 0x0643, 0x0643, 0x0643, 0x0643, 0x0644, 0x0644, 0x0644,
1848 0x0644, 0x0645, 0x0645, 0x0645, 0x0645, 0x0646, 0x0646, 0x0646,
1849 0x0646, 0x0647, 0x0647, 0x0647, 0x0647, 0x0648, 0x0648, 0x0649,
1850 0x0649, 0x064a, 0x064a, 0x064a, 0x064a, 0x0000, 0x0000, 0x0000
1852 static const WCHAR compat_FF00_FFEF[240] =
1854 0x0000, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
1855 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
1856 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
1857 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
1858 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
1859 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
1860 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
1861 0x0058, 0x0059, 0x005a, 0x005b, 0x0000, 0x005d, 0x005e, 0x005f,
1862 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
1863 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
1864 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
1865 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000,
1866 0x0000, 0x3002, 0x300c, 0x300d, 0x3001, 0x30fb, 0x30f2, 0x30a1,
1867 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, 0x30c3,
1868 0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, 0x30ab, 0x30ad,
1869 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, 0x30b9, 0x30bb, 0x30bd,
1870 0x30bf, 0x30c1, 0x30c4, 0x30c6, 0x30c8, 0x30ca, 0x30cb, 0x30cc,
1871 0x30cd, 0x30ce, 0x30cf, 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de,
1872 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9,
1873 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c,
1874 0x3164, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137,
1875 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f,
1876 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147,
1877 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x0000,
1878 0x0000, 0x0000, 0x314f, 0x3150, 0x3151, 0x3152, 0x3153, 0x3154,
1879 0x0000, 0x0000, 0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315a,
1880 0x0000, 0x0000, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, 0x3160,
1881 0x0000, 0x0000, 0x3161, 0x3162, 0x3163, 0x0000, 0x0000, 0x0000,
1882 0x00a2, 0x00a3, 0x00ac, 0x00af, 0x00a6, 0x00a5, 0x20a9, 0x0000,
1883 0x2502, 0x2190, 0x2191, 0x2192, 0x2193, 0x25a0, 0x25cb, 0x0000
1885 static const WCHAR ligatures_src[] =
1887 0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
1888 0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
1889 0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
1890 0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
1891 0xfb04, 0xfb05, 0xfb06, '\0'
1893 static const WCHAR ligatures_dst[] =
1895 'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
1896 'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
1897 'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
1898 0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
1899 'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
1902 if (!pFoldStringW)
1904 skip("FoldStringW is not available\n");
1905 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1908 /* Invalid flag combinations */
1909 for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
1911 src[0] = dst[0] = '\0';
1912 SetLastError(0);
1913 ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
1914 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1916 skip("FoldStringW is not implemented\n");
1917 return;
1919 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
1920 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1923 /* src & dst cannot be the same */
1924 SetLastError(0);
1925 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
1926 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1927 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1929 /* src can't be NULL */
1930 SetLastError(0);
1931 ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
1932 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1933 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1935 /* srclen can't be 0 */
1936 SetLastError(0);
1937 ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
1938 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1939 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1941 /* dstlen can't be < 0 */
1942 SetLastError(0);
1943 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
1944 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1945 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1947 /* Ret includes terminating NUL which is appended if srclen = -1 */
1948 SetLastError(0);
1949 src[0] = 'A';
1950 src[1] = '\0';
1951 dst[0] = '\0';
1952 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
1953 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1954 ok(dst[0] == 'A' && dst[1] == '\0',
1955 "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%d\n",
1956 'A', '\0', ret, dst[0], dst[1], GetLastError());
1958 /* If size is given, result is not NUL terminated */
1959 SetLastError(0);
1960 src[0] = 'A';
1961 src[1] = 'A';
1962 dst[0] = 'X';
1963 dst[1] = 'X';
1964 ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
1965 ok(ret == 1, "Expected ret == 1, got %d, error %d\n", ret, GetLastError());
1966 ok(dst[0] == 'A' && dst[1] == 'X',
1967 "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%d\n",
1968 'A','X', ret, dst[0], dst[1], GetLastError());
1970 /* MAP_FOLDDIGITS */
1971 for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
1973 /* Check everything before this range */
1974 for (ch = prev_ch; ch < digitRanges[j]; ch++)
1976 SetLastError(0);
1977 src[0] = ch;
1978 src[1] = dst[0] = '\0';
1979 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
1980 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1982 ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
1983 /* Wine (correctly) maps all Unicode 4.0+ digits */
1984 isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF ||
1985 (ch >= 0x1369 && ch <= 0x1371),
1986 "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
1989 if (digitRanges[j] == 0xffff)
1990 break; /* Finished the whole code point space */
1992 for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
1994 WCHAR c;
1996 /* Map out of sequence characters */
1997 if (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
1998 else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
1999 else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
2000 else if (ch == 0x245F) c = 0x24EA; /* Circled 0 */
2001 else c = ch;
2002 SetLastError(0);
2003 src[0] = c;
2004 src[1] = dst[0] = '\0';
2005 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2006 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2008 ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
2009 broken( dst[0] == ch ) || /* old Windows versions don't have all mappings */
2010 strchrW(noDigitAvailable, c),
2011 "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
2012 ch, '0' + digitRanges[j] - ch, dst[0]);
2014 prev_ch = ch;
2017 /* MAP_FOLDCZONE */
2018 for (ch = 1, failures = 0; ch <0xffff; ch++)
2020 WCHAR expected = 0;
2022 if (ch >= 0xF900 && ch <= 0xFA2F)
2023 expected = compat_F900_FA2F[ch - 0xF900];
2024 else if (ch >= 0xFE30 && ch <= 0xFEF7)
2025 expected = compat_FE30_FEF7[ch - 0xFE30];
2026 else if (ch >= 0xFF00 && ch <= 0xFFEF)
2027 expected = compat_FF00_FFEF[ch - 0xFF00];
2029 if (!expected)
2030 expected = ch;
2032 SetLastError(0);
2033 src[0] = ch;
2034 src[1] = dst[0] = '\0';
2035 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
2036 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2037 ok(dst[0] == expected ||
2038 broken( dst[0] == ch ) || /* old Windows versions don't have all mappings */
2039 /* Wine (correctly) uses updated mappings for some Unicode 4.0 chars */
2040 /* FIXME: But they should be re-checked */
2041 ch == 0xf92c || ch == 0xf979 || ch == 0xf995 || ch == 0xf9e7 ||
2042 ch == 0xf9f1 ||
2043 (0xfa0c <= ch && ch <= 0xfa6a) ||
2044 (0xfa70 <= ch && ch <= 0xfad9) ||
2045 ch == 0xfe47 || ch == 0xfe48 || ch == 0xfe68 ||
2046 (0xfe70 <= ch && ch <= 0xfe7f) ||
2047 ch == 0xff3c || ch == 0xff5f || ch == 0xff60 ||
2048 ch == 0xff9e || ch == 0xff9f,
2049 "MAP_FOLDCZONE: ch %d 0x%04x Expected 0x%04x got 0x%04x\n",
2050 ch, ch, expected, dst[0]);
2051 if (dst[0] != expected && ch < 0xf000 && ++failures > 50)
2053 trace( "MAP_FOLDCZONE: Too many failures, giving up\n" );
2054 break;
2058 /* MAP_EXPAND_LIGATURES */
2059 SetLastError(0);
2060 ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
2061 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
2062 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
2063 ok(ret == sizeof(ligatures_dst)/sizeof(ligatures_dst[0]),
2064 "Got %d, error %d\n", ret, GetLastError());
2065 ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
2066 "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
2067 for (i = 1, failures = 0; i <= 0xffff; i++)
2069 if (!strchrW(ligatures_src, i))
2071 src[0] = i;
2072 src[1] = '\0';
2073 SetLastError(0);
2074 ret = pFoldStringW(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
2075 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2076 if (ret == 3)
2077 ok(0, "MAP_EXPAND_LIGATURES: %04x : Expected %04x, got %04x %04x\n",
2078 i, src[0], dst[0], dst[1]);
2079 else
2080 ok(dst[0] == src[0],
2081 "MAP_EXPAND_LIGATURES: %04x : Expected %04x, got %04x\n",
2082 i, src[0], dst[0]);
2083 if (dst[0] != src[0] && ++failures > 50)
2085 trace( "MAP_EXPAND_LIGATURES: Too many failures, giving up\n" );
2086 break;
2092 /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
2097 #define LCID_OK(l) \
2098 ok(lcid == l, "Expected lcid = %08x, got %08x\n", l, lcid)
2099 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
2100 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
2101 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
2102 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
2104 static void test_ConvertDefaultLocale(void)
2106 LCID lcid;
2108 /* Doesn't change lcid, even if non default sublang/sort used */
2109 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_US, SORT_DEFAULT);
2110 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_UK, SORT_DEFAULT);
2111 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT);
2112 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE);
2114 /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
2115 LCID_RES(MKLCID(LANG_ENGLISH, SUBLANG_NEUTRAL, SORT_DEFAULT),
2116 MKLCID(LANG_ENGLISH, SUBLANG_DEFAULT, SORT_DEFAULT));
2117 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
2118 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
2119 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_JAPANESE_UNICODE),
2120 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE));
2122 /* Invariant language is not treated specially */
2123 TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
2124 LCID_RES(MKLCID(LANG_INVARIANT, SUBLANG_NEUTRAL, SORT_DEFAULT),
2125 MKLCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT));
2127 /* User/system default languages alone are not mapped */
2128 TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
2129 TEST_LCIDLANG(LANG_USER_DEFAULT, SORT_JAPANESE_UNICODE);
2131 /* Default lcids */
2132 LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
2133 LCID_RES(LOCALE_USER_DEFAULT, GetUserDefaultLCID());
2134 LCID_RES(LOCALE_NEUTRAL, GetUserDefaultLCID());
2137 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
2138 DWORD dwFlags, LONG_PTR lParam)
2140 trace("%08x, %s, %s, %08x, %08lx\n",
2141 lgrpid, lpszNum, lpszName, dwFlags, lParam);
2143 ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
2144 "Enumerated grp %d not valid (flags %d)\n", lgrpid, dwFlags);
2146 /* If lParam is one, we are calling with flags defaulted from 0 */
2147 ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
2148 "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %d\n", dwFlags);
2150 return TRUE;
2153 static void test_EnumSystemLanguageGroupsA(void)
2155 BOOL ret;
2157 if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
2159 win_skip("EnumSystemLanguageGroupsA and/or IsValidLanguageGroup are not available\n");
2160 return;
2163 /* No enumeration proc */
2164 SetLastError(0);
2165 ret = pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
2166 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2168 win_skip("EnumSystemLanguageGroupsA is not implemented\n");
2169 return;
2171 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2172 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2174 /* Invalid flags */
2175 SetLastError(0);
2176 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
2177 ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2179 /* No flags - defaults to LGRPID_INSTALLED */
2180 SetLastError(0xdeadbeef);
2181 pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
2182 ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
2184 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
2185 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
2189 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
2190 LONG_PTR lParam)
2192 trace("%08x, %08x, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
2194 /* invalid locale enumerated on some platforms */
2195 if (lcid == 0)
2196 return TRUE;
2198 ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
2199 "Enumerated grp %d not valid\n", lgrpid);
2200 ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
2201 "Enumerated grp locale %d not valid\n", lcid);
2202 return TRUE;
2205 static void test_EnumLanguageGroupLocalesA(void)
2207 BOOL ret;
2209 if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
2211 win_skip("EnumLanguageGroupLocalesA and/or IsValidLanguageGroup are not available\n");
2212 return;
2215 /* No enumeration proc */
2216 SetLastError(0);
2217 ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
2218 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2220 win_skip("EnumLanguageGroupLocalesA is not implemented\n");
2221 return;
2223 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2224 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2226 /* lgrpid too small */
2227 SetLastError(0);
2228 ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
2229 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2230 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2232 /* lgrpid too big */
2233 SetLastError(0);
2234 ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
2235 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2236 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2238 /* dwFlags is reserved */
2239 SetLastError(0);
2240 ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
2241 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2242 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2244 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2247 static void test_SetLocaleInfoA(void)
2249 BOOL bRet;
2250 LCID lcid = GetUserDefaultLCID();
2252 /* Null data */
2253 SetLastError(0);
2254 bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2255 ok( !bRet && GetLastError() == ERROR_INVALID_PARAMETER,
2256 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2258 /* IDATE */
2259 SetLastError(0);
2260 bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
2261 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2262 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2264 /* ILDATE */
2265 SetLastError(0);
2266 bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
2267 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2268 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2271 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2273 trace("%s %08lx\n", value, lParam);
2274 return(TRUE);
2277 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2279 ok(!enumCount, "callback called again unexpected\n");
2280 enumCount++;
2281 return(FALSE);
2284 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2286 ok(0,"callback called unexpected\n");
2287 return(FALSE);
2290 static void test_EnumUILanguageA(void)
2292 BOOL ret;
2293 if (!pEnumUILanguagesA) {
2294 skip("EnumUILanguagesA is not available on Win9x or NT4\n");
2295 return;
2298 SetLastError(ERROR_SUCCESS);
2299 ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2300 if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2302 win_skip("EnumUILanguagesA is not implemented\n");
2303 return;
2305 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2307 enumCount = 0;
2308 SetLastError(ERROR_SUCCESS);
2309 ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2310 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2312 SetLastError(ERROR_SUCCESS);
2313 ret = pEnumUILanguagesA(NULL, 0, 0);
2314 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2315 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2316 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2318 SetLastError(ERROR_SUCCESS);
2319 ret = pEnumUILanguagesA(luilocale_proc3A, 0x5a5a5a5a, 0);
2320 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2321 ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2323 SetLastError(ERROR_SUCCESS);
2324 ret = pEnumUILanguagesA(NULL, 0x5a5a5a5a, 0);
2325 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2326 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2327 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2330 static char date_fmt_buf[1024];
2332 static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
2334 lstrcatA(date_fmt_buf, fmt);
2335 lstrcatA(date_fmt_buf, "\n");
2336 return TRUE;
2339 static void test_EnumDateFormatsA(void)
2341 char *p, buf[256];
2342 BOOL ret;
2343 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2345 trace("EnumDateFormatsA 0\n");
2346 date_fmt_buf[0] = 0;
2347 SetLastError(0xdeadbeef);
2348 ret = EnumDateFormatsA(enum_datetime_procA, lcid, 0);
2349 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2351 win_skip("0 for dwFlags is not supported\n");
2353 else
2355 ok(ret, "EnumDateFormatsA(0) error %d\n", GetLastError());
2356 trace("%s\n", date_fmt_buf);
2357 /* test the 1st enumerated format */
2358 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2359 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2360 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2361 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2364 trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n");
2365 date_fmt_buf[0] = 0;
2366 SetLastError(0xdeadbeef);
2367 ret = EnumDateFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2368 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2370 win_skip("LOCALE_USE_CP_ACP is not supported\n");
2372 else
2374 ok(ret, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2375 trace("%s\n", date_fmt_buf);
2376 /* test the 1st enumerated format */
2377 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2378 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2379 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2380 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2383 trace("EnumDateFormatsA DATE_SHORTDATE\n");
2384 date_fmt_buf[0] = 0;
2385 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_SHORTDATE);
2386 ok(ret, "EnumDateFormatsA(DATE_SHORTDATE) error %d\n", GetLastError());
2387 trace("%s\n", date_fmt_buf);
2388 /* test the 1st enumerated format */
2389 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2390 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2391 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2392 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2394 trace("EnumDateFormatsA DATE_LONGDATE\n");
2395 date_fmt_buf[0] = 0;
2396 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_LONGDATE);
2397 ok(ret, "EnumDateFormatsA(DATE_LONGDATE) error %d\n", GetLastError());
2398 trace("%s\n", date_fmt_buf);
2399 /* test the 1st enumerated format */
2400 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2401 ret = GetLocaleInfoA(lcid, LOCALE_SLONGDATE, buf, sizeof(buf));
2402 ok(ret, "GetLocaleInfoA(LOCALE_SLONGDATE) error %d\n", GetLastError());
2403 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2405 trace("EnumDateFormatsA DATE_YEARMONTH\n");
2406 date_fmt_buf[0] = 0;
2407 SetLastError(0xdeadbeef);
2408 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_YEARMONTH);
2409 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2411 skip("DATE_YEARMONTH is only present on W2K and later\n");
2412 return;
2414 ok(ret, "EnumDateFormatsA(DATE_YEARMONTH) error %d\n", GetLastError());
2415 trace("%s\n", date_fmt_buf);
2416 /* test the 1st enumerated format */
2417 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2418 ret = GetLocaleInfoA(lcid, LOCALE_SYEARMONTH, buf, sizeof(buf));
2419 ok(ret, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %d\n", GetLastError());
2420 ok(!lstrcmpA(date_fmt_buf, buf) || broken(!buf[0]) /* win9x */,
2421 "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2424 static void test_EnumTimeFormatsA(void)
2426 char *p, buf[256];
2427 BOOL ret;
2428 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2430 trace("EnumTimeFormatsA 0\n");
2431 date_fmt_buf[0] = 0;
2432 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, 0);
2433 ok(ret, "EnumTimeFormatsA(0) error %d\n", GetLastError());
2434 trace("%s\n", date_fmt_buf);
2435 /* test the 1st enumerated format */
2436 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2437 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2438 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2439 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2441 trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n");
2442 date_fmt_buf[0] = 0;
2443 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2444 ok(ret, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2445 trace("%s\n", date_fmt_buf);
2446 /* test the 1st enumerated format */
2447 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2448 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2449 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2450 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2453 static void test_GetCPInfo(void)
2455 BOOL ret;
2456 CPINFO cpinfo;
2458 SetLastError(0xdeadbeef);
2459 ret = GetCPInfo(CP_SYMBOL, &cpinfo);
2460 ok(!ret, "GetCPInfo(CP_SYMBOL) should fail\n");
2461 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2462 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2464 SetLastError(0xdeadbeef);
2465 ret = GetCPInfo(CP_UTF7, &cpinfo);
2466 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2468 skip("Codepage CP_UTF7 is not installed/available\n");
2470 else
2472 ok(ret, "GetCPInfo(CP_UTF7) error %u\n", GetLastError());
2473 ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2474 ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2475 ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2476 ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2477 ok(cpinfo.MaxCharSize == 5, "expected 5, got 0x%x\n", cpinfo.MaxCharSize);
2480 SetLastError(0xdeadbeef);
2481 ret = GetCPInfo(CP_UTF8, &cpinfo);
2482 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2484 skip("Codepage CP_UTF8 is not installed/available\n");
2486 else
2488 ok(ret, "GetCPInfo(CP_UTF8) error %u\n", GetLastError());
2489 ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2490 ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2491 ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2492 ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2493 ok(cpinfo.MaxCharSize == 4 || broken(cpinfo.MaxCharSize == 3) /* win9x */,
2494 "expected 4, got %u\n", cpinfo.MaxCharSize);
2498 START_TEST(locale)
2500 InitFunctionPointers();
2502 test_EnumTimeFormatsA();
2503 test_EnumDateFormatsA();
2504 test_GetLocaleInfoA();
2505 test_GetTimeFormatA();
2506 test_GetDateFormatA();
2507 test_GetDateFormatW();
2508 test_GetCurrencyFormatA(); /* Also tests the W version */
2509 test_GetNumberFormatA(); /* Also tests the W version */
2510 test_CompareStringA();
2511 test_LCMapStringA();
2512 test_LCMapStringW();
2513 test_FoldStringA();
2514 test_FoldStringW();
2515 test_ConvertDefaultLocale();
2516 test_EnumSystemLanguageGroupsA();
2517 test_EnumLanguageGroupLocalesA();
2518 test_SetLocaleInfoA();
2519 test_EnumUILanguageA();
2520 test_GetCPInfo();
2521 /* this requires collation table patch to make it MS compatible */
2522 if (0) test_sorting();