push e9c4c6cdd0babd7b2cb4288f191bb331b756eaf2
[wine/hacks.git] / dlls / kernel32 / tests / locale.c
blob4f287cfdc161bebeb4dcddfce8fe4c7fd047f0f0
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)
436 win_skip("GetDateFormatW is not implemented\n");
437 return;
439 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
440 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
441 EXPECT_EQW;
443 STRINGSW("",""); /* NULL buffer, len > 0 */
444 SetLastError(0xdeadbeef);
445 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
446 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
447 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
449 STRINGSW("",""); /* NULL buffer, len == 0 */
450 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
451 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
452 EXPECT_LENW; EXPECT_EQW;
454 curtime.wYear = 2002;
455 curtime.wMonth = 10;
456 curtime.wDay = 23;
457 curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
458 curtime.wHour = 65432; /* Invalid */
459 curtime.wMinute = 34512; /* Invalid */
460 curtime.wSecond = 65535; /* Invalid */
461 curtime.wMilliseconds = 12345;
462 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
463 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
464 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
465 EXPECT_LENW; EXPECT_EQW;
467 /* Limit tests */
469 curtime.wYear = 1601;
470 curtime.wMonth = 1;
471 curtime.wDay = 1;
472 curtime.wDayOfWeek = 0; /* Irrelevant */
473 curtime.wHour = 0;
474 curtime.wMinute = 0;
475 curtime.wSecond = 0;
476 curtime.wMilliseconds = 0;
477 STRINGSW("dddd d MMMM yyyy","Monday 1 January 1601");
478 SetLastError(0xdeadbeef);
479 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
480 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
481 EXPECT_LENW; EXPECT_EQW;
483 curtime.wYear = 1600;
484 curtime.wMonth = 12;
485 curtime.wDay = 31;
486 curtime.wDayOfWeek = 0; /* Irrelevant */
487 curtime.wHour = 23;
488 curtime.wMinute = 59;
489 curtime.wSecond = 59;
490 curtime.wMilliseconds = 999;
491 STRINGSW("dddd d MMMM yyyy","Friday 31 December 1600");
492 SetLastError(0xdeadbeef);
493 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
494 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
495 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
499 #define CY_POS_LEFT 0
500 #define CY_POS_RIGHT 1
501 #define CY_POS_LEFT_SPACE 2
502 #define CY_POS_RIGHT_SPACE 3
504 static void test_GetCurrencyFormatA(void)
506 static char szDot[] = { '.', '\0' };
507 static char szComma[] = { ',', '\0' };
508 static char szDollar[] = { '$', '\0' };
509 int ret;
510 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
511 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
512 CURRENCYFMTA format;
514 memset(&format, 0, sizeof(format));
516 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
517 SetLastError(0xdeadbeef);
518 ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
519 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
520 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
522 STRINGSA("23,53",""); /* Invalid character --> Error */
523 SetLastError(0xdeadbeef);
524 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
525 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
526 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
528 STRINGSA("--",""); /* Double '-' --> Error */
529 SetLastError(0xdeadbeef);
530 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
531 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
532 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
534 STRINGSA("0-",""); /* Trailing '-' --> Error */
535 SetLastError(0xdeadbeef);
536 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
537 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
538 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
540 STRINGSA("0..",""); /* Double '.' --> Error */
541 SetLastError(0xdeadbeef);
542 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
543 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
544 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
546 STRINGSA(" 0.1",""); /* Leading space --> Error */
547 SetLastError(0xdeadbeef);
548 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
549 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
550 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
552 STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
553 SetLastError(0xdeadbeef);
554 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, 2);
555 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
556 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
558 STRINGSA("2353",""); /* Format and flags given --> Error */
559 SetLastError(0xdeadbeef);
560 ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
561 ok( !ret, "Expected ret == 0, got %d\n", ret);
562 ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
563 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
565 STRINGSA("2353",""); /* Invalid format --> Error */
566 SetLastError(0xdeadbeef);
567 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
568 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
569 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
571 STRINGSA("2353","$2,353.00"); /* Valid number */
572 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
573 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
574 EXPECT_LENA; EXPECT_EQA;
576 STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
577 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
578 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
579 EXPECT_LENA; EXPECT_EQA;
581 STRINGSA("2353.1","$2,353.10"); /* Valid real number */
582 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
583 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
584 EXPECT_LENA; EXPECT_EQA;
586 STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
587 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
588 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
589 EXPECT_LENA; EXPECT_EQA;
591 STRINGSA("2353.119","$2,353.12"); /* Too many DP --> Rounded */
592 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
593 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
594 EXPECT_LENA; EXPECT_EQA;
596 format.NumDigits = 0; /* No decimal separator */
597 format.LeadingZero = 0;
598 format.Grouping = 0; /* No grouping char */
599 format.NegativeOrder = 0;
600 format.PositiveOrder = CY_POS_LEFT;
601 format.lpDecimalSep = szDot;
602 format.lpThousandSep = szComma;
603 format.lpCurrencySymbol = szDollar;
605 STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
606 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
607 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
608 EXPECT_LENA; EXPECT_EQA;
610 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
611 STRINGSA("2353","$2353.0");
612 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
613 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
614 EXPECT_LENA; EXPECT_EQA;
616 format.Grouping = 2; /* Group by 100's */
617 STRINGSA("2353","$23,53.0");
618 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
619 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
620 EXPECT_LENA; EXPECT_EQA;
622 format.LeadingZero = 1; /* Always provide leading zero */
623 STRINGSA(".5","$0.5");
624 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
625 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
626 EXPECT_LENA; EXPECT_EQA;
628 format.PositiveOrder = CY_POS_RIGHT;
629 STRINGSA("1","1.0$");
630 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
631 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
632 EXPECT_LENA; EXPECT_EQA;
634 format.PositiveOrder = CY_POS_LEFT_SPACE;
635 STRINGSA("1","$ 1.0");
636 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
637 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
638 EXPECT_LENA; EXPECT_EQA;
640 format.PositiveOrder = CY_POS_RIGHT_SPACE;
641 STRINGSA("1","1.0 $");
642 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
643 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
644 EXPECT_LENA; EXPECT_EQA;
646 format.NegativeOrder = 0;
647 STRINGSA("-1","($1.0)");
648 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
649 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
650 EXPECT_LENA; EXPECT_EQA;
652 format.NegativeOrder = 1;
653 STRINGSA("-1","-$1.0");
654 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
655 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
656 EXPECT_LENA; EXPECT_EQA;
658 format.NegativeOrder = 2;
659 STRINGSA("-1","$-1.0");
660 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
661 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
662 EXPECT_LENA; EXPECT_EQA;
664 format.NegativeOrder = 3;
665 STRINGSA("-1","$1.0-");
666 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
667 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
668 EXPECT_LENA; EXPECT_EQA;
670 format.NegativeOrder = 4;
671 STRINGSA("-1","(1.0$)");
672 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
673 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
674 EXPECT_LENA; EXPECT_EQA;
676 format.NegativeOrder = 5;
677 STRINGSA("-1","-1.0$");
678 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
679 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
680 EXPECT_LENA; EXPECT_EQA;
682 format.NegativeOrder = 6;
683 STRINGSA("-1","1.0-$");
684 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
685 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
686 EXPECT_LENA; EXPECT_EQA;
688 format.NegativeOrder = 7;
689 STRINGSA("-1","1.0$-");
690 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
691 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
692 EXPECT_LENA; EXPECT_EQA;
694 format.NegativeOrder = 8;
695 STRINGSA("-1","-1.0 $");
696 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
697 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
698 EXPECT_LENA; EXPECT_EQA;
700 format.NegativeOrder = 9;
701 STRINGSA("-1","-$ 1.0");
702 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
703 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
704 EXPECT_LENA; EXPECT_EQA;
706 format.NegativeOrder = 10;
707 STRINGSA("-1","1.0 $-");
708 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
709 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
710 EXPECT_LENA; EXPECT_EQA;
712 format.NegativeOrder = 11;
713 STRINGSA("-1","$ 1.0-");
714 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
715 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
716 EXPECT_LENA; EXPECT_EQA;
718 format.NegativeOrder = 12;
719 STRINGSA("-1","$ -1.0");
720 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
721 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
722 EXPECT_LENA; EXPECT_EQA;
724 format.NegativeOrder = 13;
725 STRINGSA("-1","1.0- $");
726 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
727 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
728 EXPECT_LENA; EXPECT_EQA;
730 format.NegativeOrder = 14;
731 STRINGSA("-1","($ 1.0)");
732 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
733 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
734 EXPECT_LENA; EXPECT_EQA;
736 format.NegativeOrder = 15;
737 STRINGSA("-1","(1.0 $)");
738 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
739 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
740 EXPECT_LENA; EXPECT_EQA;
743 #define NEG_PARENS 0 /* "(1.1)" */
744 #define NEG_LEFT 1 /* "-1.1" */
745 #define NEG_LEFT_SPACE 2 /* "- 1.1" */
746 #define NEG_RIGHT 3 /* "1.1-" */
747 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
749 static void test_GetNumberFormatA(void)
751 static char szDot[] = { '.', '\0' };
752 static char szComma[] = { ',', '\0' };
753 int ret;
754 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
755 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
756 NUMBERFMTA format;
758 memset(&format, 0, sizeof(format));
760 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
761 SetLastError(0xdeadbeef);
762 ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
763 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
764 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
766 STRINGSA("23,53",""); /* Invalid character --> Error */
767 SetLastError(0xdeadbeef);
768 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
769 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
770 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
772 STRINGSA("--",""); /* Double '-' --> Error */
773 SetLastError(0xdeadbeef);
774 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
775 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
776 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
778 STRINGSA("0-",""); /* Trailing '-' --> Error */
779 SetLastError(0xdeadbeef);
780 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
781 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
782 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
784 STRINGSA("0..",""); /* Double '.' --> Error */
785 SetLastError(0xdeadbeef);
786 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
787 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
788 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
790 STRINGSA(" 0.1",""); /* Leading space --> Error */
791 SetLastError(0xdeadbeef);
792 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
793 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
794 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
796 STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
797 SetLastError(0xdeadbeef);
798 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, 2);
799 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
800 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
802 STRINGSA("2353",""); /* Format and flags given --> Error */
803 SetLastError(0xdeadbeef);
804 ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
805 ok( !ret, "Expected ret == 0, got %d\n", ret);
806 ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
807 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
809 STRINGSA("2353",""); /* Invalid format --> Error */
810 SetLastError(0xdeadbeef);
811 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
812 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
813 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
815 STRINGSA("2353","2,353.00"); /* Valid number */
816 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
817 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
818 EXPECT_LENA; EXPECT_EQA;
820 STRINGSA("-2353","-2,353.00"); /* Valid negative number */
821 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
822 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
823 EXPECT_LENA; EXPECT_EQA;
825 STRINGSA("-353","-353.00"); /* test for off by one error in grouping */
826 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
827 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
828 EXPECT_LENA; EXPECT_EQA;
830 STRINGSA("2353.1","2,353.10"); /* Valid real number */
831 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
832 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
833 EXPECT_LENA; EXPECT_EQA;
835 STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
836 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
837 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
838 EXPECT_LENA; EXPECT_EQA;
840 STRINGSA("2353.119","2,353.12"); /* Too many DP --> Rounded */
841 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
842 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
843 EXPECT_LENA; EXPECT_EQA;
845 format.NumDigits = 0; /* No decimal separator */
846 format.LeadingZero = 0;
847 format.Grouping = 0; /* No grouping char */
848 format.NegativeOrder = 0;
849 format.lpDecimalSep = szDot;
850 format.lpThousandSep = szComma;
852 STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
853 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
854 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
855 EXPECT_LENA; EXPECT_EQA;
857 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
858 STRINGSA("2353","2353.0");
859 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
860 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
861 EXPECT_LENA; EXPECT_EQA;
863 format.Grouping = 2; /* Group by 100's */
864 STRINGSA("2353","23,53.0");
865 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
866 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
867 EXPECT_LENA; EXPECT_EQA;
869 format.LeadingZero = 1; /* Always provide leading zero */
870 STRINGSA(".5","0.5");
871 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
872 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
873 EXPECT_LENA; EXPECT_EQA;
875 format.NegativeOrder = NEG_PARENS;
876 STRINGSA("-1","(1.0)");
877 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
878 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
879 EXPECT_LENA; EXPECT_EQA;
881 format.NegativeOrder = NEG_LEFT;
882 STRINGSA("-1","-1.0");
883 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
884 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
885 EXPECT_LENA; EXPECT_EQA;
887 format.NegativeOrder = NEG_LEFT_SPACE;
888 STRINGSA("-1","- 1.0");
889 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
890 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
891 EXPECT_LENA; EXPECT_EQA;
893 format.NegativeOrder = NEG_RIGHT;
894 STRINGSA("-1","1.0-");
895 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
896 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
897 EXPECT_LENA; EXPECT_EQA;
899 format.NegativeOrder = NEG_RIGHT_SPACE;
900 STRINGSA("-1","1.0 -");
901 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
902 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
903 EXPECT_LENA; EXPECT_EQA;
905 lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
907 if (IsValidLocale(lcid, 0))
909 STRINGSA("-12345","-12 345,00"); /* Try French formatting */
910 Expected[3] = 160; /* Non breaking space */
911 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
912 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
913 EXPECT_LENA; EXPECT_EQA;
918 static void test_CompareStringA(void)
920 int ret;
921 LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
923 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
924 ok (ret== 1, "(Salut/Salute) Expected 1, got %d\n", ret);
926 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
927 ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
929 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
930 ok (ret== 3, "(Salut/hola) Expected 3, got %d\n", ret);
932 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
933 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
935 lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
937 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
938 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
940 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
941 ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
943 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
944 ok (ret == 2, "(Salut/saLuT) Expected 2, got %d\n", ret);
946 /* test for CompareStringA flags */
947 SetLastError(0xdeadbeef);
948 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0x8, "NULL", -1, "NULL", -1);
949 ok(GetLastError() == ERROR_INVALID_FLAGS,
950 "unexpected error code %d\n", GetLastError());
951 ok(!ret, "CompareStringA must fail with invalid flag\n");
953 SetLastError(0xdeadbeef);
954 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, LOCALE_USE_CP_ACP, "NULL", -1, "NULL", -1);
955 ok(GetLastError() == 0xdeadbeef, "unexpected error code %d\n", GetLastError());
956 ok(ret == CSTR_EQUAL, "CompareStringA error: %d != CSTR_EQUAL\n", ret);
957 /* end of test for CompareStringA flags */
959 ret = lstrcmpA("", "");
960 ok (ret == 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret);
962 ret = lstrcmpA(NULL, NULL);
963 ok (ret == 0 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, NULL) should return 0, 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 = lstrcmpA(NULL, "");
969 ok (ret == -1 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret);
971 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"EndDialog",-1,"_Property",-1);
972 ok( ret == 3, "EndDialog vs _Property ... expected 3, got %d\n", ret);
974 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0070",-1,"_IEWWBrowserComp",-1);
975 ok( ret == 3, "osp_vba.sreg0070 vs _IEWWBrowserComp ... expected 3, got %d\n", ret);
977 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"r",-1,"\\",-1);
978 ok( ret == 3, "r vs \\ ... expected 3, got %d\n", ret);
980 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0031", -1, "OriginalDatabase", -1 );
981 ok( ret == 3, "osp_vba.sreg0031 vs OriginalDatabase ... expected 3, got %d\n", ret);
983 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1 );
984 ok( ret == 3, "AAA vs aaa expected 3, 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, "Aab", -1 );
993 ok( ret == 1, ".AAA vs Aab expected 1, got %d\n", ret);
995 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1 );
996 ok( ret == 1, ".AAA vs A.ab expected 1, got %d\n", ret);
998 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1 );
999 ok( ret == 1, "aa vs AB expected 1, got %d\n", ret);
1001 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1 );
1002 ok( ret == 1, "aa vs Aab expected 1, got %d\n", ret);
1004 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1 );
1005 ok( ret == 3, "aB vs Aab expected 3, got %d\n", ret);
1007 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1 );
1008 ok( ret == 1, "Ba vs bab expected 1, got %d\n", ret);
1010 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1 );
1011 ok( ret == 1, "{100}{83}{71}{71}{71} vs Global_DataAccess_JRO expected 1, 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, "A", -1, "{", -1 );
1017 ok( ret == 3, "A vs { expected 3, got %d\n", ret);
1019 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1 );
1020 ok(ret == 1, "3.5/0 vs 4.0/-1 expected 1, got %d\n", ret);
1022 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1 );
1023 ok(ret == 1, "3.5 vs 4.0 expected 1, got %d\n", ret);
1025 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1 );
1026 ok(ret == 1, "3.520.4403.2 vs 4.0.2927.10 expected 1, got %d\n", ret);
1028 /* hyphen and apostrophe are treated differently depending on
1029 * whether SORT_STRINGSORT specified or not
1031 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1 );
1032 ok(ret == 3, "-o vs /m expected 3, got %d\n", ret);
1034 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1 );
1035 ok(ret == 1, "/m vs -o expected 1, got %d\n", ret);
1037 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1 );
1038 ok(ret == 1, "-o vs /m expected 1, got %d\n", ret);
1040 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1 );
1041 ok(ret == 3, "/m vs -o expected 3, got %d\n", ret);
1043 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1 );
1044 ok(ret == 3, "'o vs /m expected 3, got %d\n", ret);
1046 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1 );
1047 ok(ret == 1, "/m vs 'o expected 1, got %d\n", ret);
1049 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1 );
1050 ok(ret == 1, "'o vs /m expected 1, got %d\n", ret);
1052 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1 );
1053 ok(ret == 3, "/m vs 'o expected 3, got %d\n", ret);
1055 if (0) { /* this requires collation table patch to make it MS compatible */
1056 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
1057 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
1059 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
1060 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
1062 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
1063 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
1065 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
1066 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
1068 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
1069 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
1071 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
1072 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
1074 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
1075 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
1077 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
1078 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
1080 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
1081 ok(ret == 1, "`o vs -m expected 1, got %d\n", ret);
1083 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
1084 ok(ret == 3, "-m vs `o expected 3, got %d\n", ret);
1086 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
1087 ok(ret == 3, "`o vs -m expected 3, got %d\n", ret);
1089 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
1090 ok(ret == 1, "-m vs `o expected 1, got %d\n", ret);
1093 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9);
1094 ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0 expected 2, got %d\n", ret);
1096 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10);
1097 ok(ret == 1, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1, got %d\n", ret);
1099 /* WinXP handles embedded NULLs differently than earlier versions */
1100 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
1101 ok(ret == 1 || ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1 or 2, got %d\n", ret);
1103 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
1104 ok(ret == 1 || ret == 2, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected 1 or 2, got %d\n", ret);
1106 ret = CompareStringA(lcid, 0, "a\0b", -1, "a", -1);
1107 ok(ret == 2, "a vs a expected 2, got %d\n", ret);
1109 ret = CompareStringA(lcid, 0, "a\0b", 4, "a", 2);
1110 ok(ret == CSTR_EQUAL || /* win2k */
1111 ret == CSTR_GREATER_THAN,
1112 "a\\0b vs a expected CSTR_EQUAL or CSTR_GREATER_THAN, got %d\n", ret);
1114 ret = CompareStringA(lcid, 0, "\2", 2, "\1", 2);
1115 todo_wine ok(ret != 2, "\\2 vs \\1 expected unequal\n");
1117 ret = CompareStringA(lcid, NORM_IGNORECASE | LOCALE_USE_CP_ACP, "#", -1, ".", -1);
1118 todo_wine ok(ret == CSTR_LESS_THAN, "\"#\" vs \".\" expected CSTR_LESS_THAN, got %d\n", ret);
1120 ret = lstrcmpi("#", ".");
1121 todo_wine ok(ret == -1, "\"#\" vs \".\" expected -1, got %d\n", ret);
1124 static void test_LCMapStringA(void)
1126 int ret, ret2;
1127 char buf[256], buf2[256];
1128 static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
1129 static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
1130 static const char symbols_stripped[] = "justateststring1";
1132 SetLastError(0xdeadbeef);
1133 ret = LCMapStringA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP | LCMAP_LOWERCASE,
1134 lower_case, -1, buf, sizeof(buf));
1135 ok(ret == lstrlenA(lower_case) + 1,
1136 "ret %d, error %d, expected value %d\n",
1137 ret, GetLastError(), lstrlenA(lower_case) + 1);
1138 ok(!memcmp(buf, lower_case, ret), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1140 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1141 upper_case, -1, buf, sizeof(buf));
1142 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1143 ok(GetLastError() == ERROR_INVALID_FLAGS,
1144 "unexpected error code %d\n", GetLastError());
1146 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1147 upper_case, -1, buf, sizeof(buf));
1148 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1149 ok(GetLastError() == ERROR_INVALID_FLAGS,
1150 "unexpected error code %d\n", GetLastError());
1152 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1153 upper_case, -1, buf, sizeof(buf));
1154 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1155 ok(GetLastError() == ERROR_INVALID_FLAGS,
1156 "unexpected error code %d\n", GetLastError());
1158 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1159 upper_case, -1, buf, sizeof(buf));
1160 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1161 ok(GetLastError() == ERROR_INVALID_FLAGS,
1162 "unexpected error code %d\n", GetLastError());
1164 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1165 SetLastError(0xdeadbeef);
1166 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1167 upper_case, -1, buf, sizeof(buf));
1168 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1169 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1171 /* test LCMAP_LOWERCASE */
1172 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1173 upper_case, -1, buf, sizeof(buf));
1174 ok(ret == lstrlenA(upper_case) + 1,
1175 "ret %d, error %d, expected value %d\n",
1176 ret, GetLastError(), lstrlenA(upper_case) + 1);
1177 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1179 /* test LCMAP_UPPERCASE */
1180 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1181 lower_case, -1, buf, sizeof(buf));
1182 ok(ret == lstrlenA(lower_case) + 1,
1183 "ret %d, error %d, expected value %d\n",
1184 ret, GetLastError(), lstrlenA(lower_case) + 1);
1185 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1187 /* test buffer overflow */
1188 SetLastError(0xdeadbeef);
1189 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1190 lower_case, -1, buf, 4);
1191 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1192 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1194 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1195 lstrcpyA(buf, lower_case);
1196 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1197 buf, -1, buf, sizeof(buf));
1198 if (!ret) /* Win9x */
1199 trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1200 else
1202 ok(ret == lstrlenA(lower_case) + 1,
1203 "ret %d, error %d, expected value %d\n",
1204 ret, GetLastError(), lstrlenA(lower_case) + 1);
1205 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1207 lstrcpyA(buf, upper_case);
1208 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1209 buf, -1, buf, sizeof(buf));
1210 if (!ret) /* Win9x */
1211 trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1212 else
1214 ok(ret == lstrlenA(upper_case) + 1,
1215 "ret %d, error %d, expected value %d\n",
1216 ret, GetLastError(), lstrlenA(lower_case) + 1);
1217 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1220 /* otherwise src == dst should fail */
1221 SetLastError(0xdeadbeef);
1222 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1223 buf, 10, buf, sizeof(buf));
1224 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1225 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1226 "unexpected error code %d\n", GetLastError());
1227 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1229 /* test whether '\0' is always appended */
1230 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1231 upper_case, -1, buf, sizeof(buf));
1232 ok(ret, "LCMapStringA must succeed\n");
1233 ok(buf[ret-1] == 0, "LCMapStringA not null-terminated\n");
1234 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1235 upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1236 ok(ret2, "LCMapStringA must succeed\n");
1237 ok(buf2[ret2-1] == 0, "LCMapStringA not null-terminated\n" );
1238 ok(ret == ret2, "lengths of sort keys must be equal\n");
1239 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1241 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1242 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1243 upper_case, -1, buf, sizeof(buf));
1244 ok(ret, "LCMapStringA must succeed\n");
1245 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1246 lower_case, -1, buf2, sizeof(buf2));
1247 ok(ret2, "LCMapStringA must succeed\n");
1248 ok(ret == ret2, "lengths of sort keys must be equal\n");
1249 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1251 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1252 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1253 lower_case, -1, buf, sizeof(buf));
1254 ok(ret, "LCMapStringA must succeed\n");
1255 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1256 lower_case, -1, buf2, sizeof(buf2));
1257 ok(ret2, "LCMapStringA must succeed\n");
1258 ok(ret == ret2, "lengths of sort keys must be equal\n");
1259 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1261 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1262 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1263 lower_case, -1, buf, sizeof(buf));
1264 ok(ret, "LCMapStringA must succeed\n");
1265 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1266 symbols_stripped, -1, buf2, sizeof(buf2));
1267 ok(ret2, "LCMapStringA must succeed\n");
1268 ok(ret == ret2, "lengths of sort keys must be equal\n");
1269 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1271 /* test NORM_IGNORENONSPACE */
1272 lstrcpyA(buf, "foo");
1273 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1274 lower_case, -1, buf, sizeof(buf));
1275 ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1276 lstrlenA(lower_case) + 1, ret);
1277 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1279 /* test NORM_IGNORESYMBOLS */
1280 lstrcpyA(buf, "foo");
1281 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1282 lower_case, -1, buf, sizeof(buf));
1283 ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1284 lstrlenA(symbols_stripped) + 1, ret);
1285 ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1287 /* test srclen = 0 */
1288 SetLastError(0xdeadbeef);
1289 ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1290 ok(!ret, "LCMapStringA should fail with srclen = 0\n");
1291 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1292 "unexpected error code %d\n", GetLastError());
1295 static void test_LCMapStringW(void)
1297 int ret, ret2;
1298 WCHAR buf[256], buf2[256];
1299 char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1300 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};
1301 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};
1302 static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
1303 static const WCHAR fooW[] = {'f','o','o',0};
1305 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1306 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1307 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1309 win_skip("LCMapStringW is not implemented\n");
1310 return;
1312 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1313 ok(GetLastError() == ERROR_INVALID_FLAGS,
1314 "unexpected error code %d\n", GetLastError());
1316 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1317 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1318 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1319 ok(GetLastError() == ERROR_INVALID_FLAGS,
1320 "unexpected error code %d\n", GetLastError());
1322 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1323 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1324 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1325 ok(GetLastError() == ERROR_INVALID_FLAGS,
1326 "unexpected error code %d\n", GetLastError());
1328 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1329 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1330 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1331 ok(GetLastError() == ERROR_INVALID_FLAGS,
1332 "unexpected error code %d\n", GetLastError());
1334 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1335 SetLastError(0xdeadbeef);
1336 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1337 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1338 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1339 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1341 /* test LCMAP_LOWERCASE */
1342 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1343 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1344 ok(ret == lstrlenW(upper_case) + 1,
1345 "ret %d, error %d, expected value %d\n",
1346 ret, GetLastError(), lstrlenW(upper_case) + 1);
1347 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1349 /* test LCMAP_UPPERCASE */
1350 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1351 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1352 ok(ret == lstrlenW(lower_case) + 1,
1353 "ret %d, error %d, expected value %d\n",
1354 ret, GetLastError(), lstrlenW(lower_case) + 1);
1355 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1357 /* test buffer overflow */
1358 SetLastError(0xdeadbeef);
1359 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1360 lower_case, -1, buf, 4);
1361 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1362 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1364 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1365 lstrcpyW(buf, lower_case);
1366 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1367 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1368 ok(ret == lstrlenW(lower_case) + 1,
1369 "ret %d, error %d, expected value %d\n",
1370 ret, GetLastError(), lstrlenW(lower_case) + 1);
1371 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1373 lstrcpyW(buf, upper_case);
1374 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1375 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1376 ok(ret == lstrlenW(upper_case) + 1,
1377 "ret %d, error %d, expected value %d\n",
1378 ret, GetLastError(), lstrlenW(lower_case) + 1);
1379 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1381 /* otherwise src == dst should fail */
1382 SetLastError(0xdeadbeef);
1383 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1384 buf, 10, buf, sizeof(buf));
1385 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1386 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1387 "unexpected error code %d\n", GetLastError());
1388 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1390 /* test whether '\0' is always appended */
1391 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1392 upper_case, -1, buf, sizeof(buf));
1393 ok(ret, "LCMapStringW must succeed\n");
1394 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1395 upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1396 ok(ret, "LCMapStringW must succeed\n");
1397 ok(ret == ret2, "lengths of sort keys must be equal\n");
1398 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1400 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1401 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1402 upper_case, -1, buf, sizeof(buf));
1403 ok(ret, "LCMapStringW must succeed\n");
1404 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1405 lower_case, -1, buf2, sizeof(buf2));
1406 ok(ret2, "LCMapStringW must succeed\n");
1407 ok(ret == ret2, "lengths of sort keys must be equal\n");
1408 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1410 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1411 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1412 lower_case, -1, buf, sizeof(buf));
1413 ok(ret, "LCMapStringW must succeed\n");
1414 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1415 lower_case, -1, buf2, sizeof(buf2));
1416 ok(ret2, "LCMapStringW must succeed\n");
1417 ok(ret == ret2, "lengths of sort keys must be equal\n");
1418 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1420 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1421 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1422 lower_case, -1, buf, sizeof(buf));
1423 ok(ret, "LCMapStringW must succeed\n");
1424 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1425 symbols_stripped, -1, buf2, sizeof(buf2));
1426 ok(ret2, "LCMapStringW must succeed\n");
1427 ok(ret == ret2, "lengths of sort keys must be equal\n");
1428 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1430 /* test NORM_IGNORENONSPACE */
1431 lstrcpyW(buf, fooW);
1432 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1433 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1434 ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1435 lstrlenW(lower_case) + 1, ret);
1436 ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1438 /* test NORM_IGNORESYMBOLS */
1439 lstrcpyW(buf, fooW);
1440 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1441 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1442 ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1443 lstrlenW(symbols_stripped) + 1, ret);
1444 ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1446 /* test srclen = 0 */
1447 SetLastError(0xdeadbeef);
1448 ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf)/sizeof(WCHAR));
1449 ok(!ret, "LCMapStringW should fail with srclen = 0\n");
1450 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1451 "unexpected error code %d\n", GetLastError());
1454 /* this requires collation table patch to make it MS compatible */
1455 static const char * const strings_sorted[] =
1457 "'",
1458 "-",
1459 "!",
1460 "\"",
1461 ".",
1462 ":",
1463 "\\",
1464 "_",
1465 "`",
1466 "{",
1467 "}",
1468 "+",
1469 "0",
1470 "1",
1471 "2",
1472 "3",
1473 "4",
1474 "5",
1475 "6",
1476 "7",
1477 "8",
1478 "9",
1479 "a",
1480 "A",
1481 "b",
1482 "B",
1483 "c",
1487 static const char * const strings[] =
1489 "C",
1490 "\"",
1491 "9",
1492 "'",
1493 "}",
1494 "-",
1495 "7",
1496 "+",
1497 "`",
1498 "1",
1499 "a",
1500 "5",
1501 "\\",
1502 "8",
1503 "B",
1504 "3",
1505 "_",
1506 "6",
1507 "{",
1508 "2",
1509 "c",
1510 "4",
1511 "!",
1512 "0",
1513 "A",
1514 ":",
1515 "b",
1519 static int compare_string1(const void *e1, const void *e2)
1521 const char *s1 = *(const char *const *)e1;
1522 const char *s2 = *(const char *const *)e2;
1524 return lstrcmpA(s1, s2);
1527 static int compare_string2(const void *e1, const void *e2)
1529 const char *s1 = *(const char *const *)e1;
1530 const char *s2 = *(const char *const *)e2;
1532 return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1535 static int compare_string3(const void *e1, const void *e2)
1537 const char *s1 = *(const char *const *)e1;
1538 const char *s2 = *(const char *const *)e2;
1539 char key1[256], key2[256];
1541 LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
1542 LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
1543 return strcmp(key1, key2);
1546 static void test_sorting(void)
1548 char buf[256];
1549 char **str_buf = (char **)buf;
1550 int i;
1552 assert(sizeof(buf) >= sizeof(strings));
1554 /* 1. sort using lstrcmpA */
1555 memcpy(buf, strings, sizeof(strings));
1556 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
1557 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1559 ok(!strcmp(strings_sorted[i], str_buf[i]),
1560 "qsort using lstrcmpA failed for element %d\n", i);
1562 /* 2. sort using CompareStringA */
1563 memcpy(buf, strings, sizeof(strings));
1564 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
1565 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1567 ok(!strcmp(strings_sorted[i], str_buf[i]),
1568 "qsort using CompareStringA failed for element %d\n", i);
1570 /* 3. sort using sort keys */
1571 memcpy(buf, strings, sizeof(strings));
1572 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
1573 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1575 ok(!strcmp(strings_sorted[i], str_buf[i]),
1576 "qsort using sort keys failed for element %d\n", i);
1580 static void test_FoldStringA(void)
1582 int ret, i;
1583 char src[256], dst[256];
1584 static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0' };
1585 static const char digits_dst[] = { '1','2','3','\0' };
1586 static const char composite_src[] =
1588 0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
1589 0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
1590 0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
1591 0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
1592 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
1593 0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
1594 0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
1595 0xfb,0xfc,0xfd,0xff,'\0'
1597 static const char composite_dst[] =
1599 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1600 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1601 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1602 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1603 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1604 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1605 0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
1606 0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
1607 0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
1608 0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
1609 0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
1610 0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
1611 0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
1612 0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
1613 0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1615 static const char ligatures_src[] =
1617 0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1619 static const char ligatures_dst[] =
1621 'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1624 if (!pFoldStringA)
1625 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1627 /* these tests are locale specific */
1628 if (GetACP() != 1252)
1630 trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1631 return;
1634 /* MAP_FOLDDIGITS */
1635 SetLastError(0);
1636 ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
1637 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1639 win_skip("FoldStringA is not implemented\n");
1640 return;
1642 ok(ret == 4, "Expected ret == 4, got %d, error %d\n", ret, GetLastError());
1643 ok(strcmp(dst, digits_dst) == 0,
1644 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
1645 for (i = 1; i < 256; i++)
1647 if (!strchr(digits_src, i))
1649 src[0] = i;
1650 src[1] = '\0';
1651 SetLastError(0);
1652 ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
1653 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1654 ok(dst[0] == src[0],
1655 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
1659 /* MAP_EXPAND_LIGATURES */
1660 SetLastError(0);
1661 ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1662 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1663 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1664 ok(ret == sizeof(ligatures_dst), "Got %d, error %d\n", ret, GetLastError());
1665 ok(strcmp(dst, ligatures_dst) == 0,
1666 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
1667 for (i = 1; i < 256; i++)
1669 if (!strchr(ligatures_src, i))
1671 src[0] = i;
1672 src[1] = '\0';
1673 SetLastError(0);
1674 ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1675 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1676 ok(dst[0] == src[0],
1677 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
1682 /* MAP_COMPOSITE */
1683 SetLastError(0);
1684 ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
1685 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1686 todo_wine
1688 /* Wine gets close, but doesn't produce quite the same result as native */
1689 ok(ret == 121, "Expected 121, got %d\n", ret);
1690 ok(strcmp(dst, composite_dst) == 0,
1691 "MAP_COMPOSITE: Expected '%s', got '%s'\n", composite_dst, dst);
1694 for (i = 1; i < 256; i++)
1696 if (!strchr(composite_src, i))
1698 src[0] = i;
1699 src[1] = '\0';
1700 SetLastError(0);
1701 ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
1702 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1703 ok(dst[0] == src[0],
1704 "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
1705 (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
1709 /* MAP_FOLDCZONE */
1710 for (i = 1; i < 256; i++)
1712 src[0] = i;
1713 src[1] = '\0';
1714 SetLastError(0);
1715 ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
1716 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1717 ok(src[0] == dst[0],
1718 "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
1719 (unsigned char)src[0], (unsigned char)dst[0]);
1722 /* MAP_PRECOMPOSED */
1723 for (i = 1; i < 256; i++)
1725 src[0] = i;
1726 src[1] = '\0';
1727 SetLastError(0);
1728 ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
1729 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1730 ok(src[0] == dst[0],
1731 "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
1732 (unsigned char)src[0], (unsigned char)dst[0]);
1736 static void test_FoldStringW(void)
1738 int ret;
1739 unsigned int i, j, failures;
1740 WCHAR src[256], dst[256], ch, prev_ch = 1;
1741 static const DWORD badFlags[] =
1744 MAP_PRECOMPOSED|MAP_COMPOSITE,
1745 MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
1746 MAP_COMPOSITE|MAP_EXPAND_LIGATURES
1748 /* Ranges of digits 0-9 : Must be sorted! */
1749 static const WCHAR digitRanges[] =
1751 0x0030, /* '0'-'9' */
1752 0x0660, /* Eastern Arabic */
1753 0x06F0, /* Arabic - Hindu */
1754 0x0966, /* Devengari */
1755 0x09E6, /* Bengalii */
1756 0x0A66, /* Gurmukhi */
1757 0x0AE6, /* Gujarati */
1758 0x0B66, /* Oriya */
1759 0x0BE6, /* Tamil - No 0 */
1760 0x0C66, /* Telugu */
1761 0x0CE6, /* Kannada */
1762 0x0D66, /* Maylayalam */
1763 0x0E50, /* Thai */
1764 0x0ED0, /* Laos */
1765 0x2070, /* Superscript - 1, 2, 3 are out of sequence */
1766 0x2080, /* Subscript */
1767 0x245F, /* Circled - 0 is out of sequence */
1768 0x2473, /* Bracketed */
1769 0x2487, /* Full stop */
1770 0x2775, /* Inverted circled - No 0 */
1771 0x277F, /* Patterned circled - No 0 */
1772 0x2789, /* Inverted Patterned circled - No 0 */
1773 0xff10, /* Pliene chasse (?) */
1774 0xffff /* Terminator */
1776 /* Digits which are represented, but out of sequence */
1777 static const WCHAR outOfSequenceDigits[] =
1779 0xB9, /* Superscript 1 */
1780 0xB2, /* Superscript 2 */
1781 0xB3, /* Superscript 3 */
1782 0x24EA, /* Circled 0 */
1783 '\0' /* Terminator */
1785 /* Digits in digitRanges for which no representation is available */
1786 static const WCHAR noDigitAvailable[] =
1788 0x0BE6, /* No Tamil 0 */
1789 0x2473, /* No Bracketed 0 */
1790 0x2487, /* No 0 Full stop */
1791 0x2775, /* No inverted circled 0 */
1792 0x277F, /* No patterned circled */
1793 0x2789, /* No inverted Patterned circled */
1794 '\0' /* Terminator */
1796 /* Compatibility conversion results */
1797 static const WCHAR compat_F900_FA2F[256+48] =
1799 0x8c48, 0x66f4, 0x8eca, 0x8cc8, 0x6ed1, 0x4e32, 0x53e5, 0x9f9c,
1800 0x9f9c, 0x5951, 0x91d1, 0x5587, 0x5948, 0x61f6, 0x7669, 0x7f85,
1801 0x863f, 0x87ba, 0x88f8, 0x908f, 0x6a02, 0x6d1b, 0x70d9, 0x73de,
1802 0x843d, 0x916a, 0x99f1, 0x4e82, 0x5375, 0x6b04, 0x721b, 0x862d,
1803 0x9e1e, 0x5d50, 0x6feb, 0x85cd, 0x8964, 0x62c9, 0x81d8, 0x881f,
1804 0x5eca, 0x6717, 0x6d6a, 0x72fc, 0x0000, 0x4f86, 0x51b7, 0x52de,
1805 0x64c4, 0x6ad3, 0x7210, 0x76e7, 0x8001, 0x8606, 0x865c, 0x8def,
1806 0x9732, 0x9b6f, 0x9dfa, 0x788c, 0x797f, 0x7da0, 0x83c9, 0x9304,
1807 0x9e7f, 0x8ad6, 0x58df, 0x5f04, 0x7c60, 0x807e, 0x7262, 0x78ca,
1808 0x8cc2, 0x96f7, 0x58d8, 0x5c62, 0x6a13, 0x6dda, 0x6f0f, 0x7d2f,
1809 0x7e37, 0x964b, 0x52d2, 0x808b, 0x51dc, 0x51cc, 0x7a1c, 0x7dbe,
1810 0x83f1, 0x9675, 0x8b80, 0x62cf, 0x6a02, 0x8afe, 0x4e39, 0x5be7,
1811 0x6012, 0x7387, 0x7570, 0x5317, 0x78fb, 0x4fbf, 0x5fa9, 0x4e0d,
1812 0x6ccc, 0x6578, 0x7d22, 0x53c3, 0x585e, 0x7701, 0x8449, 0x8aaa,
1813 0x6bba, 0x8fb0, 0x6c88, 0x62fe, 0x82e5, 0x63a0, 0x7565, 0x4eae,
1814 0x5169, 0x0000, 0x6881, 0x7ce7, 0x826f, 0x8ad2, 0x91cf, 0x52f5,
1815 0x5442, 0x5973, 0x5eec, 0x65c5, 0x6ffe, 0x792a, 0x95ad, 0x9a6a,
1816 0x9e97, 0x9ece, 0x529b, 0x66c6, 0x6b77, 0x8f62, 0x5e74, 0x6190,
1817 0x6200, 0x649a, 0x6f23, 0x7149, 0x7489, 0x0000, 0x7df4, 0x806f,
1818 0x8f26, 0x84ee, 0x9023, 0x934a, 0x5217, 0x52a3, 0x54bd, 0x70c8,
1819 0x88c2, 0x8aaa, 0x5ec9, 0x5ff5, 0x637b, 0x6bae, 0x7c3e, 0x7375,
1820 0x4ee4, 0x56f9, 0x5be7, 0x5dba, 0x601c, 0x73b2, 0x7469, 0x7f9a,
1821 0x8046, 0x9234, 0x96f6, 0x9748, 0x9818, 0x4f8b, 0x79ae, 0x91b4,
1822 0x96b8, 0x60e1, 0x4e86, 0x50da, 0x5bee, 0x5c3f, 0x6599, 0x6a02,
1823 0x71ce, 0x7642, 0x84fc, 0x907c, 0x9f8d, 0x6688, 0x962e, 0x5289,
1824 0x677b, 0x67f3, 0x6d41, 0x6e9c, 0x7409, 0x7559, 0x786b, 0x7d10,
1825 0x985e, 0x516d, 0x622e, 0x9678, 0x502b, 0x5d19, 0x6dea, 0x8f2a,
1826 0x5f8b, 0x6144, 0x6817, 0x7387, 0x9686, 0x5229, 0x540f, 0x5c65,
1827 0x6613, 0x674e, 0x68a8, 0x6ce5, 0x7406, 0x75e2, 0x7f79, 0x0000,
1828 0x88e1, 0x91cc, 0x96e2, 0x533f, 0x6eba, 0x541d, 0x71d0, 0x7498,
1829 0x85fa, 0x0000, 0x9c57, 0x9e9f, 0x6797, 0x6dcb, 0x81e8, 0x7acb,
1830 0x7b20, 0x7c92, 0x72c0, 0x7099, 0x8b58, 0x4ec0, 0x8336, 0x523a,
1831 0x5207, 0x5ea6, 0x62d3, 0x7cd6, 0x5b85, 0x6d1e, 0x66b4, 0x8f3b,
1832 0x884c, 0x964d, 0x898b, 0x5ed3, 0x0000, 0x0000, 0x0000, 0x0000,
1833 0x585a, 0x0000, 0x6674, 0x0000, 0x0000, 0x51de, 0x8c6c, 0x76ca,
1834 0x0000, 0x795e, 0x7965, 0x798f, 0x9756, 0x7cbe, 0x7fbd, 0x0000,
1835 0x0000, 0x0000, 0x8af8, 0x0000, 0x0000, 0x9038, 0x90fd, 0x0000,
1836 0x0000, 0x0000, 0x98ef, 0x98fc, 0x9928, 0x9db4, 0x0000, 0x0000
1838 static const WCHAR compat_FE30_FEF7[200] =
1840 0x2025, 0x2014, 0x2013, 0x005f, 0x005f, 0x0028, 0x0029, 0x007b,
1841 0x007d, 0x3014, 0x3015, 0x3010, 0x3011, 0x300a, 0x300b, 0x3008,
1842 0x3009, 0x300c, 0x300d, 0x300e, 0x300f, 0x0000, 0x0000, 0x0000,
1843 0x0000, 0x203e, 0x203e, 0x203e, 0x203e, 0x005f, 0x005f, 0x005f,
1844 0x002c, 0x3001, 0x002e, 0x0000, 0x003b, 0x003a, 0x003f, 0x0021,
1845 0x2014, 0x0028, 0x0029, 0x007b, 0x007d, 0x3014, 0x3015, 0x0023,
1846 0x0026, 0x002a, 0x002b, 0x002d, 0x003c, 0x003e, 0x003d, 0x0000,
1847 0x0000, 0x0024, 0x0025, 0x0040, 0x0000, 0x0000, 0x0000, 0x0000,
1848 0x064b, 0x064b, 0x064c, 0x0000, 0x064d, 0x0000, 0x064e, 0x064e,
1849 0x064f, 0x064f, 0x0650, 0x0650, 0x0651, 0x0651, 0x0652, 0x0652,
1850 0x0621, 0x0622, 0x0622, 0x0623, 0x0623, 0x0624, 0x0624, 0x0625,
1851 0x0625, 0x0626, 0x0626, 0x0626, 0x0626, 0x0627, 0x0627, 0x0628,
1852 0x0628, 0x0628, 0x0628, 0x0629, 0x0629, 0x062a, 0x062a, 0x062a,
1853 0x062a, 0x062b, 0x062b, 0x062b, 0x062b, 0x062c, 0x062c, 0x062c,
1854 0x062c, 0x062d, 0x062d, 0x062d, 0x062d, 0x062e, 0x062e, 0x062e,
1855 0x062e, 0x062f, 0x062f, 0x0630, 0x0630, 0x0631, 0x0631, 0x0632,
1856 0x0632, 0x0633, 0x0633, 0x0633, 0x0633, 0x0634, 0x0634, 0x0634,
1857 0x0634, 0x0635, 0x0635, 0x0635, 0x0635, 0x0636, 0x0636, 0x0636,
1858 0x0636, 0x0637, 0x0637, 0x0637, 0x0637, 0x0638, 0x0638, 0x0638,
1859 0x0638, 0x0639, 0x0639, 0x0639, 0x0639, 0x063a, 0x063a, 0x063a,
1860 0x063a, 0x0641, 0x0641, 0x0641, 0x0641, 0x0642, 0x0642, 0x0642,
1861 0x0642, 0x0643, 0x0643, 0x0643, 0x0643, 0x0644, 0x0644, 0x0644,
1862 0x0644, 0x0645, 0x0645, 0x0645, 0x0645, 0x0646, 0x0646, 0x0646,
1863 0x0646, 0x0647, 0x0647, 0x0647, 0x0647, 0x0648, 0x0648, 0x0649,
1864 0x0649, 0x064a, 0x064a, 0x064a, 0x064a, 0x0000, 0x0000, 0x0000
1866 static const WCHAR compat_FF00_FFEF[240] =
1868 0x0000, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
1869 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
1870 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
1871 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
1872 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
1873 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
1874 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
1875 0x0058, 0x0059, 0x005a, 0x005b, 0x0000, 0x005d, 0x005e, 0x005f,
1876 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
1877 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
1878 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
1879 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000,
1880 0x0000, 0x3002, 0x300c, 0x300d, 0x3001, 0x30fb, 0x30f2, 0x30a1,
1881 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, 0x30c3,
1882 0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, 0x30ab, 0x30ad,
1883 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, 0x30b9, 0x30bb, 0x30bd,
1884 0x30bf, 0x30c1, 0x30c4, 0x30c6, 0x30c8, 0x30ca, 0x30cb, 0x30cc,
1885 0x30cd, 0x30ce, 0x30cf, 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de,
1886 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9,
1887 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c,
1888 0x3164, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137,
1889 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f,
1890 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147,
1891 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x0000,
1892 0x0000, 0x0000, 0x314f, 0x3150, 0x3151, 0x3152, 0x3153, 0x3154,
1893 0x0000, 0x0000, 0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315a,
1894 0x0000, 0x0000, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, 0x3160,
1895 0x0000, 0x0000, 0x3161, 0x3162, 0x3163, 0x0000, 0x0000, 0x0000,
1896 0x00a2, 0x00a3, 0x00ac, 0x00af, 0x00a6, 0x00a5, 0x20a9, 0x0000,
1897 0x2502, 0x2190, 0x2191, 0x2192, 0x2193, 0x25a0, 0x25cb, 0x0000
1899 static const WCHAR ligatures_src[] =
1901 0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
1902 0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
1903 0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
1904 0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
1905 0xfb04, 0xfb05, 0xfb06, '\0'
1907 static const WCHAR ligatures_dst[] =
1909 'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
1910 'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
1911 'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
1912 0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
1913 'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
1916 if (!pFoldStringW)
1918 win_skip("FoldStringW is not available\n");
1919 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1922 /* Invalid flag combinations */
1923 for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
1925 src[0] = dst[0] = '\0';
1926 SetLastError(0);
1927 ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
1928 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1930 win_skip("FoldStringW is not implemented\n");
1931 return;
1933 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
1934 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1937 /* src & dst cannot be the same */
1938 SetLastError(0);
1939 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
1940 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1941 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1943 /* src can't be NULL */
1944 SetLastError(0);
1945 ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
1946 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1947 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1949 /* srclen can't be 0 */
1950 SetLastError(0);
1951 ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
1952 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1953 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1955 /* dstlen can't be < 0 */
1956 SetLastError(0);
1957 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
1958 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1959 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1961 /* Ret includes terminating NUL which is appended if srclen = -1 */
1962 SetLastError(0);
1963 src[0] = 'A';
1964 src[1] = '\0';
1965 dst[0] = '\0';
1966 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
1967 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1968 ok(dst[0] == 'A' && dst[1] == '\0',
1969 "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%d\n",
1970 'A', '\0', ret, dst[0], dst[1], GetLastError());
1972 /* If size is given, result is not NUL terminated */
1973 SetLastError(0);
1974 src[0] = 'A';
1975 src[1] = 'A';
1976 dst[0] = 'X';
1977 dst[1] = 'X';
1978 ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
1979 ok(ret == 1, "Expected ret == 1, got %d, error %d\n", ret, GetLastError());
1980 ok(dst[0] == 'A' && dst[1] == 'X',
1981 "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%d\n",
1982 'A','X', ret, dst[0], dst[1], GetLastError());
1984 /* MAP_FOLDDIGITS */
1985 for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
1987 /* Check everything before this range */
1988 for (ch = prev_ch; ch < digitRanges[j]; ch++)
1990 SetLastError(0);
1991 src[0] = ch;
1992 src[1] = dst[0] = '\0';
1993 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
1994 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1996 ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
1997 /* Wine (correctly) maps all Unicode 4.0+ digits */
1998 isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF ||
1999 (ch >= 0x1369 && ch <= 0x1371),
2000 "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
2003 if (digitRanges[j] == 0xffff)
2004 break; /* Finished the whole code point space */
2006 for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
2008 WCHAR c;
2010 /* Map out of sequence characters */
2011 if (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
2012 else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
2013 else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
2014 else if (ch == 0x245F) c = 0x24EA; /* Circled 0 */
2015 else c = ch;
2016 SetLastError(0);
2017 src[0] = c;
2018 src[1] = dst[0] = '\0';
2019 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2020 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2022 ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
2023 broken( dst[0] == ch ) || /* old Windows versions don't have all mappings */
2024 strchrW(noDigitAvailable, c),
2025 "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
2026 ch, '0' + digitRanges[j] - ch, dst[0]);
2028 prev_ch = ch;
2031 /* MAP_FOLDCZONE */
2032 for (ch = 1, failures = 0; ch <0xffff; ch++)
2034 WCHAR expected = 0;
2036 if (ch >= 0xF900 && ch <= 0xFA2F)
2037 expected = compat_F900_FA2F[ch - 0xF900];
2038 else if (ch >= 0xFE30 && ch <= 0xFEF7)
2039 expected = compat_FE30_FEF7[ch - 0xFE30];
2040 else if (ch >= 0xFF00 && ch <= 0xFFEF)
2041 expected = compat_FF00_FFEF[ch - 0xFF00];
2043 if (!expected)
2044 expected = ch;
2046 SetLastError(0);
2047 src[0] = ch;
2048 src[1] = dst[0] = '\0';
2049 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
2050 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2051 ok(dst[0] == expected ||
2052 broken( dst[0] == ch ) || /* old Windows versions don't have all mappings */
2053 /* Wine (correctly) uses updated mappings for some Unicode 4.0 chars */
2054 /* FIXME: But they should be re-checked */
2055 ch == 0xf92c || ch == 0xf979 || ch == 0xf995 || ch == 0xf9e7 ||
2056 ch == 0xf9f1 ||
2057 (0xfa0c <= ch && ch <= 0xfa6a) ||
2058 (0xfa70 <= ch && ch <= 0xfad9) ||
2059 ch == 0xfe47 || ch == 0xfe48 || ch == 0xfe68 ||
2060 (0xfe70 <= ch && ch <= 0xfe7f) ||
2061 ch == 0xff3c || ch == 0xff5f || ch == 0xff60 ||
2062 ch == 0xff9e || ch == 0xff9f,
2063 "MAP_FOLDCZONE: ch %d 0x%04x Expected 0x%04x got 0x%04x\n",
2064 ch, ch, expected, dst[0]);
2065 if (dst[0] != expected && ch < 0xf000 && ++failures > 50)
2067 trace( "MAP_FOLDCZONE: Too many failures, giving up\n" );
2068 break;
2072 /* MAP_EXPAND_LIGATURES */
2073 SetLastError(0);
2074 ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
2075 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
2076 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
2077 ok(ret == sizeof(ligatures_dst)/sizeof(ligatures_dst[0]),
2078 "Got %d, error %d\n", ret, GetLastError());
2079 ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
2080 "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
2081 for (i = 1, failures = 0; i <= 0xffff; i++)
2083 if (!strchrW(ligatures_src, i))
2085 src[0] = i;
2086 src[1] = '\0';
2087 SetLastError(0);
2088 ret = pFoldStringW(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
2089 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2090 if (ret == 3)
2091 ok(0, "MAP_EXPAND_LIGATURES: %04x : Expected %04x, got %04x %04x\n",
2092 i, src[0], dst[0], dst[1]);
2093 else
2094 ok(dst[0] == src[0],
2095 "MAP_EXPAND_LIGATURES: %04x : Expected %04x, got %04x\n",
2096 i, src[0], dst[0]);
2097 if (dst[0] != src[0] && ++failures > 50)
2099 trace( "MAP_EXPAND_LIGATURES: Too many failures, giving up\n" );
2100 break;
2106 /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
2111 #define LCID_OK(l) \
2112 ok(lcid == l, "Expected lcid = %08x, got %08x\n", l, lcid)
2113 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
2114 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
2115 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
2116 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
2118 static void test_ConvertDefaultLocale(void)
2120 LCID lcid;
2122 /* Doesn't change lcid, even if non default sublang/sort used */
2123 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_US, SORT_DEFAULT);
2124 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_UK, SORT_DEFAULT);
2125 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT);
2126 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE);
2128 /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
2129 LCID_RES(MKLCID(LANG_ENGLISH, SUBLANG_NEUTRAL, SORT_DEFAULT),
2130 MKLCID(LANG_ENGLISH, SUBLANG_DEFAULT, SORT_DEFAULT));
2131 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
2132 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
2133 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_JAPANESE_UNICODE),
2134 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE));
2136 /* Invariant language is not treated specially */
2137 TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
2138 LCID_RES(MKLCID(LANG_INVARIANT, SUBLANG_NEUTRAL, SORT_DEFAULT),
2139 MKLCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT));
2141 /* User/system default languages alone are not mapped */
2142 TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
2143 TEST_LCIDLANG(LANG_USER_DEFAULT, SORT_JAPANESE_UNICODE);
2145 /* Default lcids */
2146 LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
2147 LCID_RES(LOCALE_USER_DEFAULT, GetUserDefaultLCID());
2148 LCID_RES(LOCALE_NEUTRAL, GetUserDefaultLCID());
2151 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
2152 DWORD dwFlags, LONG_PTR lParam)
2154 trace("%08x, %s, %s, %08x, %08lx\n",
2155 lgrpid, lpszNum, lpszName, dwFlags, lParam);
2157 ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
2158 "Enumerated grp %d not valid (flags %d)\n", lgrpid, dwFlags);
2160 /* If lParam is one, we are calling with flags defaulted from 0 */
2161 ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
2162 "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %d\n", dwFlags);
2164 return TRUE;
2167 static void test_EnumSystemLanguageGroupsA(void)
2169 BOOL ret;
2171 if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
2173 win_skip("EnumSystemLanguageGroupsA and/or IsValidLanguageGroup are not available\n");
2174 return;
2177 /* No enumeration proc */
2178 SetLastError(0);
2179 ret = pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
2180 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2182 win_skip("EnumSystemLanguageGroupsA is not implemented\n");
2183 return;
2185 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2186 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2188 /* Invalid flags */
2189 SetLastError(0);
2190 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
2191 ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2193 /* No flags - defaults to LGRPID_INSTALLED */
2194 SetLastError(0xdeadbeef);
2195 pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
2196 ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
2198 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
2199 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
2203 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
2204 LONG_PTR lParam)
2206 trace("%08x, %08x, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
2208 /* invalid locale enumerated on some platforms */
2209 if (lcid == 0)
2210 return TRUE;
2212 ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
2213 "Enumerated grp %d not valid\n", lgrpid);
2214 ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
2215 "Enumerated grp locale %d not valid\n", lcid);
2216 return TRUE;
2219 static void test_EnumLanguageGroupLocalesA(void)
2221 BOOL ret;
2223 if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
2225 win_skip("EnumLanguageGroupLocalesA and/or IsValidLanguageGroup are not available\n");
2226 return;
2229 /* No enumeration proc */
2230 SetLastError(0);
2231 ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
2232 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2234 win_skip("EnumLanguageGroupLocalesA is not implemented\n");
2235 return;
2237 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2238 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2240 /* lgrpid too small */
2241 SetLastError(0);
2242 ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
2243 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2244 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2246 /* lgrpid too big */
2247 SetLastError(0);
2248 ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
2249 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2250 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2252 /* dwFlags is reserved */
2253 SetLastError(0);
2254 ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
2255 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2256 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2258 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2261 static void test_SetLocaleInfoA(void)
2263 BOOL bRet;
2264 LCID lcid = GetUserDefaultLCID();
2266 /* Null data */
2267 SetLastError(0);
2268 bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2269 ok( !bRet && GetLastError() == ERROR_INVALID_PARAMETER,
2270 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2272 /* IDATE */
2273 SetLastError(0);
2274 bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
2275 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2276 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2278 /* ILDATE */
2279 SetLastError(0);
2280 bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
2281 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2282 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2285 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2287 trace("%s %08lx\n", value, lParam);
2288 return(TRUE);
2291 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2293 ok(!enumCount, "callback called again unexpected\n");
2294 enumCount++;
2295 return(FALSE);
2298 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2300 ok(0,"callback called unexpected\n");
2301 return(FALSE);
2304 static void test_EnumUILanguageA(void)
2306 BOOL ret;
2307 if (!pEnumUILanguagesA) {
2308 win_skip("EnumUILanguagesA is not available on Win9x or NT4\n");
2309 return;
2312 SetLastError(ERROR_SUCCESS);
2313 ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2314 if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2316 win_skip("EnumUILanguagesA is not implemented\n");
2317 return;
2319 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2321 enumCount = 0;
2322 SetLastError(ERROR_SUCCESS);
2323 ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2324 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2326 SetLastError(ERROR_SUCCESS);
2327 ret = pEnumUILanguagesA(NULL, 0, 0);
2328 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2329 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2330 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2332 SetLastError(ERROR_SUCCESS);
2333 ret = pEnumUILanguagesA(luilocale_proc3A, 0x5a5a5a5a, 0);
2334 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2335 ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2337 SetLastError(ERROR_SUCCESS);
2338 ret = pEnumUILanguagesA(NULL, 0x5a5a5a5a, 0);
2339 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2340 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2341 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2344 static char date_fmt_buf[1024];
2346 static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
2348 lstrcatA(date_fmt_buf, fmt);
2349 lstrcatA(date_fmt_buf, "\n");
2350 return TRUE;
2353 static void test_EnumDateFormatsA(void)
2355 char *p, buf[256];
2356 BOOL ret;
2357 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2359 trace("EnumDateFormatsA 0\n");
2360 date_fmt_buf[0] = 0;
2361 SetLastError(0xdeadbeef);
2362 ret = EnumDateFormatsA(enum_datetime_procA, lcid, 0);
2363 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2365 win_skip("0 for dwFlags is not supported\n");
2367 else
2369 ok(ret, "EnumDateFormatsA(0) error %d\n", GetLastError());
2370 trace("%s\n", date_fmt_buf);
2371 /* test the 1st enumerated format */
2372 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2373 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2374 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2375 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2378 trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n");
2379 date_fmt_buf[0] = 0;
2380 SetLastError(0xdeadbeef);
2381 ret = EnumDateFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2382 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2384 win_skip("LOCALE_USE_CP_ACP is not supported\n");
2386 else
2388 ok(ret, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2389 trace("%s\n", date_fmt_buf);
2390 /* test the 1st enumerated format */
2391 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2392 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2393 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2394 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2397 trace("EnumDateFormatsA DATE_SHORTDATE\n");
2398 date_fmt_buf[0] = 0;
2399 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_SHORTDATE);
2400 ok(ret, "EnumDateFormatsA(DATE_SHORTDATE) error %d\n", GetLastError());
2401 trace("%s\n", date_fmt_buf);
2402 /* test the 1st enumerated format */
2403 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2404 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2405 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2406 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2408 trace("EnumDateFormatsA DATE_LONGDATE\n");
2409 date_fmt_buf[0] = 0;
2410 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_LONGDATE);
2411 ok(ret, "EnumDateFormatsA(DATE_LONGDATE) error %d\n", GetLastError());
2412 trace("%s\n", date_fmt_buf);
2413 /* test the 1st enumerated format */
2414 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2415 ret = GetLocaleInfoA(lcid, LOCALE_SLONGDATE, buf, sizeof(buf));
2416 ok(ret, "GetLocaleInfoA(LOCALE_SLONGDATE) error %d\n", GetLastError());
2417 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2419 trace("EnumDateFormatsA DATE_YEARMONTH\n");
2420 date_fmt_buf[0] = 0;
2421 SetLastError(0xdeadbeef);
2422 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_YEARMONTH);
2423 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2425 skip("DATE_YEARMONTH is only present on W2K and later\n");
2426 return;
2428 ok(ret, "EnumDateFormatsA(DATE_YEARMONTH) error %d\n", GetLastError());
2429 trace("%s\n", date_fmt_buf);
2430 /* test the 1st enumerated format */
2431 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2432 ret = GetLocaleInfoA(lcid, LOCALE_SYEARMONTH, buf, sizeof(buf));
2433 ok(ret, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %d\n", GetLastError());
2434 ok(!lstrcmpA(date_fmt_buf, buf) || broken(!buf[0]) /* win9x */,
2435 "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2438 static void test_EnumTimeFormatsA(void)
2440 char *p, buf[256];
2441 BOOL ret;
2442 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2444 trace("EnumTimeFormatsA 0\n");
2445 date_fmt_buf[0] = 0;
2446 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, 0);
2447 ok(ret, "EnumTimeFormatsA(0) error %d\n", GetLastError());
2448 trace("%s\n", date_fmt_buf);
2449 /* test the 1st enumerated format */
2450 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2451 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2452 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2453 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2455 trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n");
2456 date_fmt_buf[0] = 0;
2457 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2458 ok(ret, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2459 trace("%s\n", date_fmt_buf);
2460 /* test the 1st enumerated format */
2461 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2462 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2463 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2464 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2467 static void test_GetCPInfo(void)
2469 BOOL ret;
2470 CPINFO cpinfo;
2472 SetLastError(0xdeadbeef);
2473 ret = GetCPInfo(CP_SYMBOL, &cpinfo);
2474 ok(!ret, "GetCPInfo(CP_SYMBOL) should fail\n");
2475 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2476 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2478 SetLastError(0xdeadbeef);
2479 ret = GetCPInfo(CP_UTF7, &cpinfo);
2480 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2482 skip("Codepage CP_UTF7 is not installed/available\n");
2484 else
2486 ok(ret, "GetCPInfo(CP_UTF7) error %u\n", GetLastError());
2487 ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2488 ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2489 ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2490 ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2491 ok(cpinfo.MaxCharSize == 5, "expected 5, got 0x%x\n", cpinfo.MaxCharSize);
2494 SetLastError(0xdeadbeef);
2495 ret = GetCPInfo(CP_UTF8, &cpinfo);
2496 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2498 skip("Codepage CP_UTF8 is not installed/available\n");
2500 else
2502 ok(ret, "GetCPInfo(CP_UTF8) error %u\n", GetLastError());
2503 ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2504 ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2505 ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2506 ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2507 ok(cpinfo.MaxCharSize == 4 || broken(cpinfo.MaxCharSize == 3) /* win9x */,
2508 "expected 4, got %u\n", cpinfo.MaxCharSize);
2512 START_TEST(locale)
2514 InitFunctionPointers();
2516 test_EnumTimeFormatsA();
2517 test_EnumDateFormatsA();
2518 test_GetLocaleInfoA();
2519 test_GetTimeFormatA();
2520 test_GetDateFormatA();
2521 test_GetDateFormatW();
2522 test_GetCurrencyFormatA(); /* Also tests the W version */
2523 test_GetNumberFormatA(); /* Also tests the W version */
2524 test_CompareStringA();
2525 test_LCMapStringA();
2526 test_LCMapStringW();
2527 test_FoldStringA();
2528 test_FoldStringW();
2529 test_ConvertDefaultLocale();
2530 test_EnumSystemLanguageGroupsA();
2531 test_EnumLanguageGroupLocalesA();
2532 test_SetLocaleInfoA();
2533 test_EnumUILanguageA();
2534 test_GetCPInfo();
2535 /* this requires collation table patch to make it MS compatible */
2536 if (0) test_sorting();