dplayx: Adjust GetCaps behaviour to documentation
[wine/gsoc_dplay.git] / dlls / kernel32 / tests / locale.c
blob8a561003aeb06cc7f0fdd531238e464504e97926
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 int len;
122 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
123 char buffer[BUFFER_SIZE];
124 char expected[BUFFER_SIZE];
126 ok(lcid == 0x409, "wrong LCID calculated - %d\n", lcid);
128 /* en, ar and zh use SUBLANG_NEUTRAL, but GetLocaleInfo assume SUBLANG_DEFAULT */
129 memset(expected, 0, COUNTOF(expected));
130 len = GetLocaleInfoA(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
131 SetLastError(0xdeadbeef);
132 memset(buffer, 0, COUNTOF(buffer));
133 ret = GetLocaleInfoA(LANG_ENGLISH, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
134 ok((ret == len) && !lstrcmpA(buffer, expected),
135 "got %d with '%s' (expected %d with '%s')\n",
136 ret, buffer, len, expected);
138 memset(expected, 0, COUNTOF(expected));
139 len = GetLocaleInfoA(MAKELANGID(LANG_ARABIC, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
140 if (len) {
141 SetLastError(0xdeadbeef);
142 memset(buffer, 0, COUNTOF(buffer));
143 ret = GetLocaleInfoA(LANG_ARABIC, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
144 ok((ret == len) && !lstrcmpA(buffer, expected),
145 "got %d with '%s' (expected %d with '%s')\n",
146 ret, buffer, len, expected);
148 else
149 win_skip("LANG_ARABIC not installed\n");
151 memset(expected, 0, COUNTOF(expected));
152 len = GetLocaleInfoA(MAKELANGID(LANG_CHINESE, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
153 if (len) {
154 SetLastError(0xdeadbeef);
155 memset(buffer, 0, COUNTOF(buffer));
156 ret = GetLocaleInfoA(LANG_CHINESE, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
157 ok((ret == len) && !lstrcmpA(buffer, expected),
158 "got %d with '%s' (expected %d with '%s')\n",
159 ret, buffer, len, expected);
161 else
162 win_skip("LANG_CHINESE not installed\n");
164 /* SUBLANG_DEFAULT is required for mlang.dll, but optional for GetLocaleInfo */
165 memset(expected, 0, COUNTOF(expected));
166 len = GetLocaleInfoA(MAKELANGID(LANG_GERMAN, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
167 SetLastError(0xdeadbeef);
168 memset(buffer, 0, COUNTOF(buffer));
169 ret = GetLocaleInfoA(LANG_GERMAN, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
170 ok((ret == len) && !lstrcmpA(buffer, expected),
171 "got %d with '%s' (expected %d with '%s')\n",
172 ret, buffer, len, expected);
175 /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
176 * partially fill the buffer even if it is too short. See bug 637.
178 SetLastError(0xdeadbeef);
179 memset(buffer, 0, COUNTOF(buffer));
180 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 0);
181 ok(ret == 7 && !buffer[0], "Expected len=7, got %d\n", ret);
183 SetLastError(0xdeadbeef);
184 memset(buffer, 0, COUNTOF(buffer));
185 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 3);
186 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
187 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
188 ok(!strcmp(buffer, "Mon"), "Expected 'Mon', got '%s'\n", buffer);
190 SetLastError(0xdeadbeef);
191 memset(buffer, 0, COUNTOF(buffer));
192 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 10);
193 ok(ret == 7, "Expected ret == 7, got %d, error %d\n", ret, GetLastError());
194 ok(!strcmp(buffer, "Monday"), "Expected 'Monday', got '%s'\n", buffer);
197 static void test_GetTimeFormatA(void)
199 int ret;
200 SYSTEMTIME curtime;
201 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
202 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
204 memset(&curtime, 2, sizeof(SYSTEMTIME));
205 STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
206 SetLastError(0xdeadbeef);
207 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
208 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
209 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
211 curtime.wHour = 8;
212 curtime.wMinute = 56;
213 curtime.wSecond = 13;
214 curtime.wMilliseconds = 22;
215 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
216 SetLastError(0xdeadbeef);
217 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
218 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
219 EXPECT_LENA; EXPECT_EQA;
221 /* MSDN: LOCALE_NOUSEROVERRIDE can't be specified with a format string */
222 SetLastError(0xdeadbeef);
223 ret = GetTimeFormatA(lcid, NUO|TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
224 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
225 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
227 STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficient buffer */
228 SetLastError(0xdeadbeef);
229 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, 2);
230 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
231 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
233 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
234 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, NULL, 0);
235 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
236 EXPECT_LENA;
238 STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
239 ret = GetTimeFormatA(lcid, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
240 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
241 EXPECT_LENA; EXPECT_EQA;
243 STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
244 ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
245 ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
246 ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "4" )), /* win9x */
247 "Expected '', got '%s'\n", buffer );
249 STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
250 ret = GetTimeFormatA(lcid, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
251 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
252 EXPECT_LENA; EXPECT_EQA;
254 STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
255 strcpy(Expected, "8:56 AM");
256 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &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", "8.@:56AM"); /* Multiple delimiters */
261 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
262 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
263 ok( !strcmp( buffer, "8.@:56AM" ) || broken( !strcmp( buffer, "8.@:56.@:AM" )) /* win9x */,
264 "Expected '8.@:56AM', got '%s'\n", buffer );
266 STRINGSA("s1s2s3", ""); /* Duplicate tokens */
267 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
268 ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
269 ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "3" )), /* win9x */
270 "Expected '', got '%s'\n", buffer );
272 STRINGSA("t/tt", "A/AM"); /* AM time marker */
273 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
274 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
275 EXPECT_LENA; EXPECT_EQA;
277 curtime.wHour = 13;
278 STRINGSA("t/tt", "P/PM"); /* PM time marker */
279 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
280 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
281 EXPECT_LENA; EXPECT_EQA;
283 STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
284 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
285 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
286 EXPECT_LENA; EXPECT_EQA;
288 STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
289 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &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("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
294 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
295 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
296 EXPECT_LENA; EXPECT_EQA;
298 curtime.wHour = 14; /* change this to 14 or 2pm */
299 curtime.wMinute = 5;
300 curtime.wSecond = 3;
301 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 */
302 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
303 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
304 EXPECT_LENA; EXPECT_EQA;
306 curtime.wHour = 0;
307 STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
308 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
309 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
310 EXPECT_LENA; EXPECT_EQA;
312 STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
313 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
314 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
315 EXPECT_LENA; EXPECT_EQA;
317 /* try to convert formatting strings with more than two letters
318 * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
319 * NOTE: We expect any letter for which there is an upper case value
320 * we should see a replacement. For letters that DO NOT have
321 * upper case values we should see NO REPLACEMENT.
323 curtime.wHour = 8;
324 curtime.wMinute = 56;
325 curtime.wSecond = 13;
326 curtime.wMilliseconds = 22;
327 STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
328 "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
329 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
330 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
331 EXPECT_LENA; EXPECT_EQA;
333 STRINGSA("h", "text"); /* Don't write to buffer if len is 0 */
334 strcpy(buffer, "text");
335 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, 0);
336 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
337 EXPECT_EQA;
339 STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
340 "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
341 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
342 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
343 EXPECT_LENA; EXPECT_EQA;
345 STRINGSA("'''", "'"); /* invalid quoted string */
346 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
347 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
348 EXPECT_LENA; EXPECT_EQA;
350 /* test that msdn suggested single quotation usage works as expected */
351 STRINGSA("''''", "'"); /* single quote mark */
352 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
353 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
354 EXPECT_LENA; EXPECT_EQA;
356 STRINGSA("''HHHHHH", "08"); /* Normal use */
357 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
358 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
359 EXPECT_LENA; EXPECT_EQA;
361 /* and test for normal use of the single quotation mark */
362 STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
363 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
364 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
365 EXPECT_LENA; EXPECT_EQA;
367 STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
368 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
369 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
370 EXPECT_LENA; EXPECT_EQA;
372 STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
373 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
374 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
375 EXPECT_LENA; EXPECT_EQA;
377 curtime.wHour = 25;
378 STRINGSA("'123'tt", ""); /* Invalid time */
379 SetLastError(0xdeadbeef);
380 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
381 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
382 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
384 curtime.wHour = 12;
385 curtime.wMonth = 60; /* Invalid */
386 STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
387 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
388 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
389 EXPECT_LENA; EXPECT_EQA;
392 static void test_GetDateFormatA(void)
394 int ret;
395 SYSTEMTIME curtime;
396 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
397 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
399 memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
400 STRINGSA("ddd',' MMM dd yy","");
401 SetLastError(0xdeadbeef);
402 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
403 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
404 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
406 curtime.wYear = 2002;
407 curtime.wMonth = 5;
408 curtime.wDay = 4;
409 curtime.wDayOfWeek = 3;
410 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
411 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
412 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
413 EXPECT_LENA; EXPECT_EQA;
415 /* Same as above but with LOCALE_NOUSEROVERRIDE */
416 STRINGSA("ddd',' MMM dd yy",""); /* Simple case */
417 SetLastError(0xdeadbeef);
418 ret = GetDateFormatA(lcid, NUO, &curtime, input, buffer, COUNTOF(buffer));
419 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
420 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
421 EXPECT_EQA;
423 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
424 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
425 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
426 EXPECT_LENA; EXPECT_EQA;
428 curtime.wHour = 36; /* Invalid */
429 STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
430 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
431 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
432 EXPECT_LENA; EXPECT_EQA;
434 STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
435 ret = GetDateFormatA(lcid, 0, &curtime, input, NULL, 0);
436 ok(ret == 16, "Expected ret == 16, got %d, error %d\n", ret, GetLastError());
437 EXPECT_EQA;
439 STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
440 SetLastError(0xdeadbeef);
441 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, 2);
442 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
443 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
445 STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
446 ret = GetDateFormat(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
447 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
448 if (strncmp(buffer, Expected, strlen(Expected)) && strncmp(buffer, "5/4/02", strlen(Expected)) != 0)
449 ok (0, "Expected '%s' or '5/4/02', got '%s'\n", Expected, buffer);
451 STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
452 ret = GetDateFormat(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
453 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
454 EXPECT_LENA; EXPECT_EQA;
456 /* test for expected DATE_YEARMONTH behavior with null format */
457 /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
458 STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
459 SetLastError(0xdeadbeef);
460 ret = GetDateFormat(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
461 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
462 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
463 EXPECT_EQA;
465 /* Test that using invalid DATE_* flags results in the correct error */
466 /* and return values */
467 STRINGSA("m/d/y", ""); /* Invalid flags */
468 SetLastError(0xdeadbeef);
469 ret = GetDateFormat(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
470 &curtime, input, buffer, COUNTOF(buffer));
471 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
472 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
473 EXPECT_EQA;
476 static void test_GetDateFormatW(void)
478 int ret;
479 SYSTEMTIME curtime;
480 WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
481 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
483 STRINGSW("",""); /* If flags is not zero then format must be NULL */
484 ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL,
485 input, buffer, COUNTOF(buffer));
486 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
488 win_skip("GetDateFormatW is not implemented\n");
489 return;
491 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
492 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
493 EXPECT_EQW;
495 STRINGSW("",""); /* NULL buffer, len > 0 */
496 SetLastError(0xdeadbeef);
497 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
498 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
499 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
501 STRINGSW("",""); /* NULL buffer, len == 0 */
502 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
503 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
504 EXPECT_LENW; EXPECT_EQW;
506 curtime.wYear = 2002;
507 curtime.wMonth = 10;
508 curtime.wDay = 23;
509 curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
510 curtime.wHour = 65432; /* Invalid */
511 curtime.wMinute = 34512; /* Invalid */
512 curtime.wSecond = 65535; /* Invalid */
513 curtime.wMilliseconds = 12345;
514 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
515 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
516 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
517 EXPECT_LENW; EXPECT_EQW;
519 /* Limit tests */
521 curtime.wYear = 1601;
522 curtime.wMonth = 1;
523 curtime.wDay = 1;
524 curtime.wDayOfWeek = 0; /* Irrelevant */
525 curtime.wHour = 0;
526 curtime.wMinute = 0;
527 curtime.wSecond = 0;
528 curtime.wMilliseconds = 0;
529 STRINGSW("dddd d MMMM yyyy","Monday 1 January 1601");
530 SetLastError(0xdeadbeef);
531 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
532 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
533 EXPECT_LENW; EXPECT_EQW;
535 curtime.wYear = 1600;
536 curtime.wMonth = 12;
537 curtime.wDay = 31;
538 curtime.wDayOfWeek = 0; /* Irrelevant */
539 curtime.wHour = 23;
540 curtime.wMinute = 59;
541 curtime.wSecond = 59;
542 curtime.wMilliseconds = 999;
543 STRINGSW("dddd d MMMM yyyy","Friday 31 December 1600");
544 SetLastError(0xdeadbeef);
545 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
546 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
547 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
551 #define CY_POS_LEFT 0
552 #define CY_POS_RIGHT 1
553 #define CY_POS_LEFT_SPACE 2
554 #define CY_POS_RIGHT_SPACE 3
556 static void test_GetCurrencyFormatA(void)
558 static char szDot[] = { '.', '\0' };
559 static char szComma[] = { ',', '\0' };
560 static char szDollar[] = { '$', '\0' };
561 int ret;
562 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
563 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
564 CURRENCYFMTA format;
566 memset(&format, 0, sizeof(format));
568 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
569 SetLastError(0xdeadbeef);
570 ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
571 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
572 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
574 STRINGSA("23,53",""); /* Invalid character --> Error */
575 SetLastError(0xdeadbeef);
576 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
577 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
578 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
580 STRINGSA("--",""); /* Double '-' --> Error */
581 SetLastError(0xdeadbeef);
582 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
583 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
584 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
586 STRINGSA("0-",""); /* Trailing '-' --> Error */
587 SetLastError(0xdeadbeef);
588 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
589 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
590 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
592 STRINGSA("0..",""); /* Double '.' --> Error */
593 SetLastError(0xdeadbeef);
594 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
595 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
596 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
598 STRINGSA(" 0.1",""); /* Leading space --> Error */
599 SetLastError(0xdeadbeef);
600 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
601 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
602 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
604 STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
605 SetLastError(0xdeadbeef);
606 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, 2);
607 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
608 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
610 STRINGSA("2353",""); /* Format and flags given --> Error */
611 SetLastError(0xdeadbeef);
612 ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
613 ok( !ret, "Expected ret == 0, got %d\n", ret);
614 ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
615 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
617 STRINGSA("2353",""); /* Invalid format --> Error */
618 SetLastError(0xdeadbeef);
619 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
620 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
621 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
623 STRINGSA("2353","$2,353.00"); /* Valid number */
624 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
625 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
626 EXPECT_LENA; EXPECT_EQA;
628 STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
629 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
630 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
631 EXPECT_LENA; EXPECT_EQA;
633 STRINGSA("2353.1","$2,353.10"); /* Valid real number */
634 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
635 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
636 EXPECT_LENA; EXPECT_EQA;
638 STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
639 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
640 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
641 EXPECT_LENA; EXPECT_EQA;
643 STRINGSA("2353.119","$2,353.12"); /* Too many DP --> Rounded */
644 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
645 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
646 EXPECT_LENA; EXPECT_EQA;
648 format.NumDigits = 0; /* No decimal separator */
649 format.LeadingZero = 0;
650 format.Grouping = 0; /* No grouping char */
651 format.NegativeOrder = 0;
652 format.PositiveOrder = CY_POS_LEFT;
653 format.lpDecimalSep = szDot;
654 format.lpThousandSep = szComma;
655 format.lpCurrencySymbol = szDollar;
657 STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
658 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
659 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
660 EXPECT_LENA; EXPECT_EQA;
662 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
663 STRINGSA("2353","$2353.0");
664 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
665 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
666 EXPECT_LENA; EXPECT_EQA;
668 format.Grouping = 2; /* Group by 100's */
669 STRINGSA("2353","$23,53.0");
670 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
671 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
672 EXPECT_LENA; EXPECT_EQA;
674 format.LeadingZero = 1; /* Always provide leading zero */
675 STRINGSA(".5","$0.5");
676 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
677 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
678 EXPECT_LENA; EXPECT_EQA;
680 format.PositiveOrder = CY_POS_RIGHT;
681 STRINGSA("1","1.0$");
682 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
683 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
684 EXPECT_LENA; EXPECT_EQA;
686 format.PositiveOrder = CY_POS_LEFT_SPACE;
687 STRINGSA("1","$ 1.0");
688 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
689 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
690 EXPECT_LENA; EXPECT_EQA;
692 format.PositiveOrder = CY_POS_RIGHT_SPACE;
693 STRINGSA("1","1.0 $");
694 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
695 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
696 EXPECT_LENA; EXPECT_EQA;
698 format.NegativeOrder = 0;
699 STRINGSA("-1","($1.0)");
700 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
701 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
702 EXPECT_LENA; EXPECT_EQA;
704 format.NegativeOrder = 1;
705 STRINGSA("-1","-$1.0");
706 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
707 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
708 EXPECT_LENA; EXPECT_EQA;
710 format.NegativeOrder = 2;
711 STRINGSA("-1","$-1.0");
712 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
713 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
714 EXPECT_LENA; EXPECT_EQA;
716 format.NegativeOrder = 3;
717 STRINGSA("-1","$1.0-");
718 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
719 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
720 EXPECT_LENA; EXPECT_EQA;
722 format.NegativeOrder = 4;
723 STRINGSA("-1","(1.0$)");
724 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
725 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
726 EXPECT_LENA; EXPECT_EQA;
728 format.NegativeOrder = 5;
729 STRINGSA("-1","-1.0$");
730 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
731 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
732 EXPECT_LENA; EXPECT_EQA;
734 format.NegativeOrder = 6;
735 STRINGSA("-1","1.0-$");
736 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
737 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
738 EXPECT_LENA; EXPECT_EQA;
740 format.NegativeOrder = 7;
741 STRINGSA("-1","1.0$-");
742 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
743 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
744 EXPECT_LENA; EXPECT_EQA;
746 format.NegativeOrder = 8;
747 STRINGSA("-1","-1.0 $");
748 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
749 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
750 EXPECT_LENA; EXPECT_EQA;
752 format.NegativeOrder = 9;
753 STRINGSA("-1","-$ 1.0");
754 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
755 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
756 EXPECT_LENA; EXPECT_EQA;
758 format.NegativeOrder = 10;
759 STRINGSA("-1","1.0 $-");
760 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
761 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
762 EXPECT_LENA; EXPECT_EQA;
764 format.NegativeOrder = 11;
765 STRINGSA("-1","$ 1.0-");
766 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
767 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
768 EXPECT_LENA; EXPECT_EQA;
770 format.NegativeOrder = 12;
771 STRINGSA("-1","$ -1.0");
772 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
773 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
774 EXPECT_LENA; EXPECT_EQA;
776 format.NegativeOrder = 13;
777 STRINGSA("-1","1.0- $");
778 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
779 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
780 EXPECT_LENA; EXPECT_EQA;
782 format.NegativeOrder = 14;
783 STRINGSA("-1","($ 1.0)");
784 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
785 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
786 EXPECT_LENA; EXPECT_EQA;
788 format.NegativeOrder = 15;
789 STRINGSA("-1","(1.0 $)");
790 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
791 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
792 EXPECT_LENA; EXPECT_EQA;
795 #define NEG_PARENS 0 /* "(1.1)" */
796 #define NEG_LEFT 1 /* "-1.1" */
797 #define NEG_LEFT_SPACE 2 /* "- 1.1" */
798 #define NEG_RIGHT 3 /* "1.1-" */
799 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
801 static void test_GetNumberFormatA(void)
803 static char szDot[] = { '.', '\0' };
804 static char szComma[] = { ',', '\0' };
805 int ret;
806 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
807 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
808 NUMBERFMTA format;
810 memset(&format, 0, sizeof(format));
812 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
813 SetLastError(0xdeadbeef);
814 ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
815 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
816 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
818 STRINGSA("23,53",""); /* Invalid character --> Error */
819 SetLastError(0xdeadbeef);
820 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
821 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
822 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
824 STRINGSA("--",""); /* Double '-' --> Error */
825 SetLastError(0xdeadbeef);
826 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
827 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
828 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
830 STRINGSA("0-",""); /* Trailing '-' --> Error */
831 SetLastError(0xdeadbeef);
832 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
833 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
834 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
836 STRINGSA("0..",""); /* Double '.' --> Error */
837 SetLastError(0xdeadbeef);
838 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
839 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
840 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
842 STRINGSA(" 0.1",""); /* Leading space --> Error */
843 SetLastError(0xdeadbeef);
844 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
845 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
846 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
848 STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
849 SetLastError(0xdeadbeef);
850 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, 2);
851 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
852 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
854 STRINGSA("2353",""); /* Format and flags given --> Error */
855 SetLastError(0xdeadbeef);
856 ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
857 ok( !ret, "Expected ret == 0, got %d\n", ret);
858 ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
859 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
861 STRINGSA("2353",""); /* Invalid format --> Error */
862 SetLastError(0xdeadbeef);
863 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
864 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
865 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
867 STRINGSA("2353","2,353.00"); /* Valid number */
868 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
869 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
870 EXPECT_LENA; EXPECT_EQA;
872 STRINGSA("-2353","-2,353.00"); /* Valid negative number */
873 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
874 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
875 EXPECT_LENA; EXPECT_EQA;
877 STRINGSA("-353","-353.00"); /* test for off by one error in grouping */
878 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
879 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
880 EXPECT_LENA; EXPECT_EQA;
882 STRINGSA("2353.1","2,353.10"); /* Valid real number */
883 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
884 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
885 EXPECT_LENA; EXPECT_EQA;
887 STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
888 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
889 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
890 EXPECT_LENA; EXPECT_EQA;
892 STRINGSA("2353.119","2,353.12"); /* Too many DP --> Rounded */
893 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
894 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
895 EXPECT_LENA; EXPECT_EQA;
897 format.NumDigits = 0; /* No decimal separator */
898 format.LeadingZero = 0;
899 format.Grouping = 0; /* No grouping char */
900 format.NegativeOrder = 0;
901 format.lpDecimalSep = szDot;
902 format.lpThousandSep = szComma;
904 STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
905 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
906 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
907 EXPECT_LENA; EXPECT_EQA;
909 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
910 STRINGSA("2353","2353.0");
911 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
912 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
913 EXPECT_LENA; EXPECT_EQA;
915 format.Grouping = 2; /* Group by 100's */
916 STRINGSA("2353","23,53.0");
917 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
918 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
919 EXPECT_LENA; EXPECT_EQA;
921 format.LeadingZero = 1; /* Always provide leading zero */
922 STRINGSA(".5","0.5");
923 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
924 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
925 EXPECT_LENA; EXPECT_EQA;
927 format.NegativeOrder = NEG_PARENS;
928 STRINGSA("-1","(1.0)");
929 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
930 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
931 EXPECT_LENA; EXPECT_EQA;
933 format.NegativeOrder = NEG_LEFT;
934 STRINGSA("-1","-1.0");
935 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
936 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
937 EXPECT_LENA; EXPECT_EQA;
939 format.NegativeOrder = NEG_LEFT_SPACE;
940 STRINGSA("-1","- 1.0");
941 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
942 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
943 EXPECT_LENA; EXPECT_EQA;
945 format.NegativeOrder = NEG_RIGHT;
946 STRINGSA("-1","1.0-");
947 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
948 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
949 EXPECT_LENA; EXPECT_EQA;
951 format.NegativeOrder = NEG_RIGHT_SPACE;
952 STRINGSA("-1","1.0 -");
953 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
954 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
955 EXPECT_LENA; EXPECT_EQA;
957 lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
959 if (IsValidLocale(lcid, 0))
961 STRINGSA("-12345","-12 345,00"); /* Try French formatting */
962 Expected[3] = 160; /* Non breaking space */
963 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
964 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
965 EXPECT_LENA; EXPECT_EQA;
970 static void test_CompareStringA(void)
972 int ret;
973 LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
975 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
976 ok (ret== 1, "(Salut/Salute) Expected 1, got %d\n", ret);
978 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
979 ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
981 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
982 ok (ret== 3, "(Salut/hola) Expected 3, got %d\n", ret);
984 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
985 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
987 lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
989 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
990 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
992 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
993 ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
995 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
996 ok (ret == 2, "(Salut/saLuT) Expected 2, got %d\n", ret);
998 /* test for CompareStringA flags */
999 SetLastError(0xdeadbeef);
1000 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0x8, "NULL", -1, "NULL", -1);
1001 ok(GetLastError() == ERROR_INVALID_FLAGS,
1002 "unexpected error code %d\n", GetLastError());
1003 ok(!ret, "CompareStringA must fail with invalid flag\n");
1005 SetLastError(0xdeadbeef);
1006 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, LOCALE_USE_CP_ACP, "NULL", -1, "NULL", -1);
1007 ok(GetLastError() == 0xdeadbeef, "unexpected error code %d\n", GetLastError());
1008 ok(ret == CSTR_EQUAL, "CompareStringA error: %d != CSTR_EQUAL\n", ret);
1009 /* end of test for CompareStringA flags */
1011 ret = lstrcmpA("", "");
1012 ok (ret == 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret);
1014 ret = lstrcmpA(NULL, NULL);
1015 ok (ret == 0 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, NULL) should return 0, got %d\n", ret);
1017 ret = lstrcmpA("", NULL);
1018 ok (ret == 1 || broken(ret == -2) /* win9x */, "lstrcmpA(\"\", NULL) should return 1, got %d\n", ret);
1020 ret = lstrcmpA(NULL, "");
1021 ok (ret == -1 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret);
1023 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"EndDialog",-1,"_Property",-1);
1024 ok( ret == 3, "EndDialog vs _Property ... expected 3, got %d\n", ret);
1026 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0070",-1,"_IEWWBrowserComp",-1);
1027 ok( ret == 3, "osp_vba.sreg0070 vs _IEWWBrowserComp ... expected 3, got %d\n", ret);
1029 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"r",-1,"\\",-1);
1030 ok( ret == 3, "r vs \\ ... expected 3, got %d\n", ret);
1032 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0031", -1, "OriginalDatabase", -1 );
1033 ok( ret == 3, "osp_vba.sreg0031 vs OriginalDatabase ... expected 3, got %d\n", ret);
1035 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1 );
1036 ok( ret == 3, "AAA vs aaa expected 3, got %d\n", ret);
1038 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1 );
1039 ok( ret == 1, "AAA vs aab expected 1, got %d\n", ret);
1041 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1 );
1042 ok( ret == 1, "AAA vs Aab expected 1, got %d\n", ret);
1044 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1 );
1045 ok( ret == 1, ".AAA vs Aab expected 1, got %d\n", ret);
1047 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1 );
1048 ok( ret == 1, ".AAA vs A.ab expected 1, got %d\n", ret);
1050 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1 );
1051 ok( ret == 1, "aa vs AB expected 1, got %d\n", ret);
1053 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1 );
1054 ok( ret == 1, "aa vs Aab expected 1, got %d\n", ret);
1056 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1 );
1057 ok( ret == 3, "aB vs Aab expected 3, got %d\n", ret);
1059 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1 );
1060 ok( ret == 1, "Ba vs bab expected 1, got %d\n", ret);
1062 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1 );
1063 ok( ret == 1, "{100}{83}{71}{71}{71} vs Global_DataAccess_JRO expected 1, got %d\n", ret);
1065 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1 );
1066 ok( ret == 3, "a vs { expected 3, got %d\n", ret);
1068 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1 );
1069 ok( ret == 3, "A vs { expected 3, got %d\n", ret);
1071 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1 );
1072 ok(ret == 1, "3.5/0 vs 4.0/-1 expected 1, got %d\n", ret);
1074 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1 );
1075 ok(ret == 1, "3.5 vs 4.0 expected 1, got %d\n", ret);
1077 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1 );
1078 ok(ret == 1, "3.520.4403.2 vs 4.0.2927.10 expected 1, got %d\n", ret);
1080 /* hyphen and apostrophe are treated differently depending on
1081 * whether SORT_STRINGSORT specified or not
1083 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1 );
1084 ok(ret == 3, "-o vs /m expected 3, got %d\n", ret);
1086 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1 );
1087 ok(ret == 1, "/m vs -o expected 1, got %d\n", ret);
1089 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1 );
1090 ok(ret == 1, "-o vs /m expected 1, got %d\n", ret);
1092 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1 );
1093 ok(ret == 3, "/m vs -o expected 3, got %d\n", ret);
1095 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1 );
1096 ok(ret == 3, "'o vs /m expected 3, got %d\n", ret);
1098 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1 );
1099 ok(ret == 1, "/m vs 'o expected 1, got %d\n", ret);
1101 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1 );
1102 ok(ret == 1, "'o vs /m expected 1, got %d\n", ret);
1104 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1 );
1105 ok(ret == 3, "/m vs 'o expected 3, got %d\n", ret);
1107 if (0) { /* this requires collation table patch to make it MS compatible */
1108 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
1109 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
1111 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
1112 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
1114 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
1115 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
1117 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
1118 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
1120 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
1121 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
1123 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
1124 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
1126 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
1127 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
1129 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
1130 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
1132 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
1133 ok(ret == 1, "`o vs -m expected 1, got %d\n", ret);
1135 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
1136 ok(ret == 3, "-m vs `o expected 3, got %d\n", ret);
1138 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
1139 ok(ret == 3, "`o vs -m expected 3, got %d\n", ret);
1141 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
1142 ok(ret == 1, "-m vs `o expected 1, got %d\n", ret);
1145 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9);
1146 ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0 expected 2, got %d\n", ret);
1148 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10);
1149 ok(ret == 1, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1, got %d\n", ret);
1151 /* WinXP handles embedded NULLs differently than earlier versions */
1152 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
1153 ok(ret == 1 || ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1 or 2, got %d\n", ret);
1155 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
1156 ok(ret == 1 || ret == 2, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected 1 or 2, got %d\n", ret);
1158 ret = CompareStringA(lcid, 0, "a\0b", -1, "a", -1);
1159 ok(ret == 2, "a vs a expected 2, got %d\n", ret);
1161 ret = CompareStringA(lcid, 0, "a\0b", 4, "a", 2);
1162 ok(ret == CSTR_EQUAL || /* win2k */
1163 ret == CSTR_GREATER_THAN,
1164 "a\\0b vs a expected CSTR_EQUAL or CSTR_GREATER_THAN, got %d\n", ret);
1166 ret = CompareStringA(lcid, 0, "\2", 2, "\1", 2);
1167 todo_wine ok(ret != 2, "\\2 vs \\1 expected unequal\n");
1169 ret = CompareStringA(lcid, NORM_IGNORECASE | LOCALE_USE_CP_ACP, "#", -1, ".", -1);
1170 todo_wine ok(ret == CSTR_LESS_THAN, "\"#\" vs \".\" expected CSTR_LESS_THAN, got %d\n", ret);
1172 ret = lstrcmpi("#", ".");
1173 todo_wine ok(ret == -1, "\"#\" vs \".\" expected -1, got %d\n", ret);
1176 static void test_LCMapStringA(void)
1178 int ret, ret2;
1179 char buf[256], buf2[256];
1180 static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
1181 static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
1182 static const char symbols_stripped[] = "justateststring1";
1184 SetLastError(0xdeadbeef);
1185 ret = LCMapStringA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP | LCMAP_LOWERCASE,
1186 lower_case, -1, buf, sizeof(buf));
1187 ok(ret == lstrlenA(lower_case) + 1,
1188 "ret %d, error %d, expected value %d\n",
1189 ret, GetLastError(), lstrlenA(lower_case) + 1);
1190 ok(!memcmp(buf, lower_case, ret), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1192 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1193 upper_case, -1, buf, sizeof(buf));
1194 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1195 ok(GetLastError() == ERROR_INVALID_FLAGS,
1196 "unexpected error code %d\n", GetLastError());
1198 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1199 upper_case, -1, buf, sizeof(buf));
1200 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1201 ok(GetLastError() == ERROR_INVALID_FLAGS,
1202 "unexpected error code %d\n", GetLastError());
1204 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1205 upper_case, -1, buf, sizeof(buf));
1206 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1207 ok(GetLastError() == ERROR_INVALID_FLAGS,
1208 "unexpected error code %d\n", GetLastError());
1210 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1211 upper_case, -1, buf, sizeof(buf));
1212 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1213 ok(GetLastError() == ERROR_INVALID_FLAGS,
1214 "unexpected error code %d\n", GetLastError());
1216 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1217 SetLastError(0xdeadbeef);
1218 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1219 upper_case, -1, buf, sizeof(buf));
1220 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1221 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1223 /* test LCMAP_LOWERCASE */
1224 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1225 upper_case, -1, buf, sizeof(buf));
1226 ok(ret == lstrlenA(upper_case) + 1,
1227 "ret %d, error %d, expected value %d\n",
1228 ret, GetLastError(), lstrlenA(upper_case) + 1);
1229 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1231 /* test LCMAP_UPPERCASE */
1232 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1233 lower_case, -1, buf, sizeof(buf));
1234 ok(ret == lstrlenA(lower_case) + 1,
1235 "ret %d, error %d, expected value %d\n",
1236 ret, GetLastError(), lstrlenA(lower_case) + 1);
1237 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1239 /* test buffer overflow */
1240 SetLastError(0xdeadbeef);
1241 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1242 lower_case, -1, buf, 4);
1243 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1244 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1246 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1247 lstrcpyA(buf, lower_case);
1248 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1249 buf, -1, buf, sizeof(buf));
1250 if (!ret) /* Win9x */
1251 trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1252 else
1254 ok(ret == lstrlenA(lower_case) + 1,
1255 "ret %d, error %d, expected value %d\n",
1256 ret, GetLastError(), lstrlenA(lower_case) + 1);
1257 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1259 lstrcpyA(buf, upper_case);
1260 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1261 buf, -1, buf, sizeof(buf));
1262 if (!ret) /* Win9x */
1263 trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1264 else
1266 ok(ret == lstrlenA(upper_case) + 1,
1267 "ret %d, error %d, expected value %d\n",
1268 ret, GetLastError(), lstrlenA(lower_case) + 1);
1269 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1272 /* otherwise src == dst should fail */
1273 SetLastError(0xdeadbeef);
1274 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1275 buf, 10, buf, sizeof(buf));
1276 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1277 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1278 "unexpected error code %d\n", GetLastError());
1279 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1281 /* test whether '\0' is always appended */
1282 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1283 upper_case, -1, buf, sizeof(buf));
1284 ok(ret, "LCMapStringA must succeed\n");
1285 ok(buf[ret-1] == 0, "LCMapStringA not null-terminated\n");
1286 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1287 upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1288 ok(ret2, "LCMapStringA must succeed\n");
1289 ok(buf2[ret2-1] == 0, "LCMapStringA not null-terminated\n" );
1290 ok(ret == ret2, "lengths of sort keys must be equal\n");
1291 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1293 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1294 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1295 upper_case, -1, buf, sizeof(buf));
1296 ok(ret, "LCMapStringA must succeed\n");
1297 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1298 lower_case, -1, buf2, sizeof(buf2));
1299 ok(ret2, "LCMapStringA must succeed\n");
1300 ok(ret == ret2, "lengths of sort keys must be equal\n");
1301 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1303 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1304 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1305 lower_case, -1, buf, sizeof(buf));
1306 ok(ret, "LCMapStringA must succeed\n");
1307 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1308 lower_case, -1, buf2, sizeof(buf2));
1309 ok(ret2, "LCMapStringA must succeed\n");
1310 ok(ret == ret2, "lengths of sort keys must be equal\n");
1311 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1313 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1314 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1315 lower_case, -1, buf, sizeof(buf));
1316 ok(ret, "LCMapStringA must succeed\n");
1317 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1318 symbols_stripped, -1, buf2, sizeof(buf2));
1319 ok(ret2, "LCMapStringA must succeed\n");
1320 ok(ret == ret2, "lengths of sort keys must be equal\n");
1321 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1323 /* test NORM_IGNORENONSPACE */
1324 lstrcpyA(buf, "foo");
1325 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1326 lower_case, -1, buf, sizeof(buf));
1327 ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1328 lstrlenA(lower_case) + 1, ret);
1329 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1331 /* test NORM_IGNORESYMBOLS */
1332 lstrcpyA(buf, "foo");
1333 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1334 lower_case, -1, buf, sizeof(buf));
1335 ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1336 lstrlenA(symbols_stripped) + 1, ret);
1337 ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1339 /* test srclen = 0 */
1340 SetLastError(0xdeadbeef);
1341 ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1342 ok(!ret, "LCMapStringA should fail with srclen = 0\n");
1343 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1344 "unexpected error code %d\n", GetLastError());
1347 static void test_LCMapStringW(void)
1349 int ret, ret2;
1350 WCHAR buf[256], buf2[256];
1351 char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1352 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};
1353 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};
1354 static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
1355 static const WCHAR fooW[] = {'f','o','o',0};
1357 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1358 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1359 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1361 win_skip("LCMapStringW is not implemented\n");
1362 return;
1364 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1365 ok(GetLastError() == ERROR_INVALID_FLAGS,
1366 "unexpected error code %d\n", GetLastError());
1368 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1369 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1370 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1371 ok(GetLastError() == ERROR_INVALID_FLAGS,
1372 "unexpected error code %d\n", GetLastError());
1374 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1375 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1376 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1377 ok(GetLastError() == ERROR_INVALID_FLAGS,
1378 "unexpected error code %d\n", GetLastError());
1380 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1381 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1382 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1383 ok(GetLastError() == ERROR_INVALID_FLAGS,
1384 "unexpected error code %d\n", GetLastError());
1386 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1387 SetLastError(0xdeadbeef);
1388 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1389 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1390 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1391 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1393 /* test LCMAP_LOWERCASE */
1394 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1395 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1396 ok(ret == lstrlenW(upper_case) + 1,
1397 "ret %d, error %d, expected value %d\n",
1398 ret, GetLastError(), lstrlenW(upper_case) + 1);
1399 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1401 /* test LCMAP_UPPERCASE */
1402 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1403 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1404 ok(ret == lstrlenW(lower_case) + 1,
1405 "ret %d, error %d, expected value %d\n",
1406 ret, GetLastError(), lstrlenW(lower_case) + 1);
1407 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1409 /* test buffer overflow */
1410 SetLastError(0xdeadbeef);
1411 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1412 lower_case, -1, buf, 4);
1413 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1414 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1416 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1417 lstrcpyW(buf, lower_case);
1418 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1419 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1420 ok(ret == lstrlenW(lower_case) + 1,
1421 "ret %d, error %d, expected value %d\n",
1422 ret, GetLastError(), lstrlenW(lower_case) + 1);
1423 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1425 lstrcpyW(buf, upper_case);
1426 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1427 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1428 ok(ret == lstrlenW(upper_case) + 1,
1429 "ret %d, error %d, expected value %d\n",
1430 ret, GetLastError(), lstrlenW(lower_case) + 1);
1431 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1433 /* otherwise src == dst should fail */
1434 SetLastError(0xdeadbeef);
1435 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1436 buf, 10, buf, sizeof(buf));
1437 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1438 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1439 "unexpected error code %d\n", GetLastError());
1440 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1442 /* test whether '\0' is always appended */
1443 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1444 upper_case, -1, buf, sizeof(buf));
1445 ok(ret, "LCMapStringW must succeed\n");
1446 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1447 upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1448 ok(ret, "LCMapStringW must succeed\n");
1449 ok(ret == ret2, "lengths of sort keys must be equal\n");
1450 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1452 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1453 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1454 upper_case, -1, buf, sizeof(buf));
1455 ok(ret, "LCMapStringW must succeed\n");
1456 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1457 lower_case, -1, buf2, sizeof(buf2));
1458 ok(ret2, "LCMapStringW must succeed\n");
1459 ok(ret == ret2, "lengths of sort keys must be equal\n");
1460 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1462 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1463 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1464 lower_case, -1, buf, sizeof(buf));
1465 ok(ret, "LCMapStringW must succeed\n");
1466 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1467 lower_case, -1, buf2, sizeof(buf2));
1468 ok(ret2, "LCMapStringW must succeed\n");
1469 ok(ret == ret2, "lengths of sort keys must be equal\n");
1470 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1472 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1473 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1474 lower_case, -1, buf, sizeof(buf));
1475 ok(ret, "LCMapStringW must succeed\n");
1476 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1477 symbols_stripped, -1, buf2, sizeof(buf2));
1478 ok(ret2, "LCMapStringW must succeed\n");
1479 ok(ret == ret2, "lengths of sort keys must be equal\n");
1480 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1482 /* test NORM_IGNORENONSPACE */
1483 lstrcpyW(buf, fooW);
1484 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1485 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1486 ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1487 lstrlenW(lower_case) + 1, ret);
1488 ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1490 /* test NORM_IGNORESYMBOLS */
1491 lstrcpyW(buf, fooW);
1492 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1493 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1494 ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1495 lstrlenW(symbols_stripped) + 1, ret);
1496 ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1498 /* test srclen = 0 */
1499 SetLastError(0xdeadbeef);
1500 ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf)/sizeof(WCHAR));
1501 ok(!ret, "LCMapStringW should fail with srclen = 0\n");
1502 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1503 "unexpected error code %d\n", GetLastError());
1506 /* this requires collation table patch to make it MS compatible */
1507 static const char * const strings_sorted[] =
1509 "'",
1510 "-",
1511 "!",
1512 "\"",
1513 ".",
1514 ":",
1515 "\\",
1516 "_",
1517 "`",
1518 "{",
1519 "}",
1520 "+",
1521 "0",
1522 "1",
1523 "2",
1524 "3",
1525 "4",
1526 "5",
1527 "6",
1528 "7",
1529 "8",
1530 "9",
1531 "a",
1532 "A",
1533 "b",
1534 "B",
1535 "c",
1539 static const char * const strings[] =
1541 "C",
1542 "\"",
1543 "9",
1544 "'",
1545 "}",
1546 "-",
1547 "7",
1548 "+",
1549 "`",
1550 "1",
1551 "a",
1552 "5",
1553 "\\",
1554 "8",
1555 "B",
1556 "3",
1557 "_",
1558 "6",
1559 "{",
1560 "2",
1561 "c",
1562 "4",
1563 "!",
1564 "0",
1565 "A",
1566 ":",
1567 "b",
1571 static int compare_string1(const void *e1, const void *e2)
1573 const char *s1 = *(const char *const *)e1;
1574 const char *s2 = *(const char *const *)e2;
1576 return lstrcmpA(s1, s2);
1579 static int compare_string2(const void *e1, const void *e2)
1581 const char *s1 = *(const char *const *)e1;
1582 const char *s2 = *(const char *const *)e2;
1584 return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1587 static int compare_string3(const void *e1, const void *e2)
1589 const char *s1 = *(const char *const *)e1;
1590 const char *s2 = *(const char *const *)e2;
1591 char key1[256], key2[256];
1593 LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
1594 LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
1595 return strcmp(key1, key2);
1598 static void test_sorting(void)
1600 char buf[256];
1601 char **str_buf = (char **)buf;
1602 int i;
1604 assert(sizeof(buf) >= sizeof(strings));
1606 /* 1. sort using lstrcmpA */
1607 memcpy(buf, strings, sizeof(strings));
1608 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
1609 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1611 ok(!strcmp(strings_sorted[i], str_buf[i]),
1612 "qsort using lstrcmpA failed for element %d\n", i);
1614 /* 2. sort using CompareStringA */
1615 memcpy(buf, strings, sizeof(strings));
1616 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
1617 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1619 ok(!strcmp(strings_sorted[i], str_buf[i]),
1620 "qsort using CompareStringA failed for element %d\n", i);
1622 /* 3. sort using sort keys */
1623 memcpy(buf, strings, sizeof(strings));
1624 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
1625 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1627 ok(!strcmp(strings_sorted[i], str_buf[i]),
1628 "qsort using sort keys failed for element %d\n", i);
1632 static void test_FoldStringA(void)
1634 int ret, i;
1635 char src[256], dst[256];
1636 static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0' };
1637 static const char digits_dst[] = { '1','2','3','\0' };
1638 static const char composite_src[] =
1640 0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
1641 0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
1642 0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
1643 0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
1644 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
1645 0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
1646 0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
1647 0xfb,0xfc,0xfd,0xff,'\0'
1649 static const char composite_dst[] =
1651 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1652 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1653 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1654 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1655 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1656 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1657 0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
1658 0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
1659 0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
1660 0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
1661 0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
1662 0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
1663 0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
1664 0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
1665 0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1667 static const char ligatures_src[] =
1669 0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1671 static const char ligatures_dst[] =
1673 'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1676 if (!pFoldStringA)
1677 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1679 /* these tests are locale specific */
1680 if (GetACP() != 1252)
1682 trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1683 return;
1686 /* MAP_FOLDDIGITS */
1687 SetLastError(0);
1688 ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
1689 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1691 win_skip("FoldStringA is not implemented\n");
1692 return;
1694 ok(ret == 4, "Expected ret == 4, got %d, error %d\n", ret, GetLastError());
1695 ok(strcmp(dst, digits_dst) == 0,
1696 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
1697 for (i = 1; i < 256; i++)
1699 if (!strchr(digits_src, i))
1701 src[0] = i;
1702 src[1] = '\0';
1703 SetLastError(0);
1704 ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
1705 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1706 ok(dst[0] == src[0],
1707 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
1711 /* MAP_EXPAND_LIGATURES */
1712 SetLastError(0);
1713 ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1714 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1715 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1716 ok(ret == sizeof(ligatures_dst), "Got %d, error %d\n", ret, GetLastError());
1717 ok(strcmp(dst, ligatures_dst) == 0,
1718 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
1719 for (i = 1; i < 256; i++)
1721 if (!strchr(ligatures_src, i))
1723 src[0] = i;
1724 src[1] = '\0';
1725 SetLastError(0);
1726 ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1727 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1728 ok(dst[0] == src[0],
1729 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
1734 /* MAP_COMPOSITE */
1735 SetLastError(0);
1736 ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
1737 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1738 todo_wine
1740 /* Wine gets close, but doesn't produce quite the same result as native */
1741 ok(ret == 121, "Expected 121, got %d\n", ret);
1742 ok(strcmp(dst, composite_dst) == 0,
1743 "MAP_COMPOSITE: Expected '%s', got '%s'\n", composite_dst, dst);
1746 for (i = 1; i < 256; i++)
1748 if (!strchr(composite_src, i))
1750 src[0] = i;
1751 src[1] = '\0';
1752 SetLastError(0);
1753 ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
1754 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1755 ok(dst[0] == src[0],
1756 "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
1757 (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
1761 /* MAP_FOLDCZONE */
1762 for (i = 1; i < 256; i++)
1764 src[0] = i;
1765 src[1] = '\0';
1766 SetLastError(0);
1767 ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
1768 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1769 ok(src[0] == dst[0],
1770 "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
1771 (unsigned char)src[0], (unsigned char)dst[0]);
1774 /* MAP_PRECOMPOSED */
1775 for (i = 1; i < 256; i++)
1777 src[0] = i;
1778 src[1] = '\0';
1779 SetLastError(0);
1780 ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
1781 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1782 ok(src[0] == dst[0],
1783 "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
1784 (unsigned char)src[0], (unsigned char)dst[0]);
1788 static void test_FoldStringW(void)
1790 int ret;
1791 unsigned int i, j, failures;
1792 WCHAR src[256], dst[256], ch, prev_ch = 1;
1793 static const DWORD badFlags[] =
1796 MAP_PRECOMPOSED|MAP_COMPOSITE,
1797 MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
1798 MAP_COMPOSITE|MAP_EXPAND_LIGATURES
1800 /* Ranges of digits 0-9 : Must be sorted! */
1801 static const WCHAR digitRanges[] =
1803 0x0030, /* '0'-'9' */
1804 0x0660, /* Eastern Arabic */
1805 0x06F0, /* Arabic - Hindu */
1806 0x0966, /* Devengari */
1807 0x09E6, /* Bengalii */
1808 0x0A66, /* Gurmukhi */
1809 0x0AE6, /* Gujarati */
1810 0x0B66, /* Oriya */
1811 0x0BE6, /* Tamil - No 0 */
1812 0x0C66, /* Telugu */
1813 0x0CE6, /* Kannada */
1814 0x0D66, /* Maylayalam */
1815 0x0E50, /* Thai */
1816 0x0ED0, /* Laos */
1817 0x2070, /* Superscript - 1, 2, 3 are out of sequence */
1818 0x2080, /* Subscript */
1819 0x245F, /* Circled - 0 is out of sequence */
1820 0x2473, /* Bracketed */
1821 0x2487, /* Full stop */
1822 0x2775, /* Inverted circled - No 0 */
1823 0x277F, /* Patterned circled - No 0 */
1824 0x2789, /* Inverted Patterned circled - No 0 */
1825 0xff10, /* Pliene chasse (?) */
1826 0xffff /* Terminator */
1828 /* Digits which are represented, but out of sequence */
1829 static const WCHAR outOfSequenceDigits[] =
1831 0xB9, /* Superscript 1 */
1832 0xB2, /* Superscript 2 */
1833 0xB3, /* Superscript 3 */
1834 0x24EA, /* Circled 0 */
1835 '\0' /* Terminator */
1837 /* Digits in digitRanges for which no representation is available */
1838 static const WCHAR noDigitAvailable[] =
1840 0x0BE6, /* No Tamil 0 */
1841 0x2473, /* No Bracketed 0 */
1842 0x2487, /* No 0 Full stop */
1843 0x2775, /* No inverted circled 0 */
1844 0x277F, /* No patterned circled */
1845 0x2789, /* No inverted Patterned circled */
1846 '\0' /* Terminator */
1848 /* Compatibility conversion results */
1849 static const WCHAR compat_F900_FA2F[256+48] =
1851 0x8c48, 0x66f4, 0x8eca, 0x8cc8, 0x6ed1, 0x4e32, 0x53e5, 0x9f9c,
1852 0x9f9c, 0x5951, 0x91d1, 0x5587, 0x5948, 0x61f6, 0x7669, 0x7f85,
1853 0x863f, 0x87ba, 0x88f8, 0x908f, 0x6a02, 0x6d1b, 0x70d9, 0x73de,
1854 0x843d, 0x916a, 0x99f1, 0x4e82, 0x5375, 0x6b04, 0x721b, 0x862d,
1855 0x9e1e, 0x5d50, 0x6feb, 0x85cd, 0x8964, 0x62c9, 0x81d8, 0x881f,
1856 0x5eca, 0x6717, 0x6d6a, 0x72fc, 0x0000, 0x4f86, 0x51b7, 0x52de,
1857 0x64c4, 0x6ad3, 0x7210, 0x76e7, 0x8001, 0x8606, 0x865c, 0x8def,
1858 0x9732, 0x9b6f, 0x9dfa, 0x788c, 0x797f, 0x7da0, 0x83c9, 0x9304,
1859 0x9e7f, 0x8ad6, 0x58df, 0x5f04, 0x7c60, 0x807e, 0x7262, 0x78ca,
1860 0x8cc2, 0x96f7, 0x58d8, 0x5c62, 0x6a13, 0x6dda, 0x6f0f, 0x7d2f,
1861 0x7e37, 0x964b, 0x52d2, 0x808b, 0x51dc, 0x51cc, 0x7a1c, 0x7dbe,
1862 0x83f1, 0x9675, 0x8b80, 0x62cf, 0x6a02, 0x8afe, 0x4e39, 0x5be7,
1863 0x6012, 0x7387, 0x7570, 0x5317, 0x78fb, 0x4fbf, 0x5fa9, 0x4e0d,
1864 0x6ccc, 0x6578, 0x7d22, 0x53c3, 0x585e, 0x7701, 0x8449, 0x8aaa,
1865 0x6bba, 0x8fb0, 0x6c88, 0x62fe, 0x82e5, 0x63a0, 0x7565, 0x4eae,
1866 0x5169, 0x0000, 0x6881, 0x7ce7, 0x826f, 0x8ad2, 0x91cf, 0x52f5,
1867 0x5442, 0x5973, 0x5eec, 0x65c5, 0x6ffe, 0x792a, 0x95ad, 0x9a6a,
1868 0x9e97, 0x9ece, 0x529b, 0x66c6, 0x6b77, 0x8f62, 0x5e74, 0x6190,
1869 0x6200, 0x649a, 0x6f23, 0x7149, 0x7489, 0x0000, 0x7df4, 0x806f,
1870 0x8f26, 0x84ee, 0x9023, 0x934a, 0x5217, 0x52a3, 0x54bd, 0x70c8,
1871 0x88c2, 0x8aaa, 0x5ec9, 0x5ff5, 0x637b, 0x6bae, 0x7c3e, 0x7375,
1872 0x4ee4, 0x56f9, 0x5be7, 0x5dba, 0x601c, 0x73b2, 0x7469, 0x7f9a,
1873 0x8046, 0x9234, 0x96f6, 0x9748, 0x9818, 0x4f8b, 0x79ae, 0x91b4,
1874 0x96b8, 0x60e1, 0x4e86, 0x50da, 0x5bee, 0x5c3f, 0x6599, 0x6a02,
1875 0x71ce, 0x7642, 0x84fc, 0x907c, 0x9f8d, 0x6688, 0x962e, 0x5289,
1876 0x677b, 0x67f3, 0x6d41, 0x6e9c, 0x7409, 0x7559, 0x786b, 0x7d10,
1877 0x985e, 0x516d, 0x622e, 0x9678, 0x502b, 0x5d19, 0x6dea, 0x8f2a,
1878 0x5f8b, 0x6144, 0x6817, 0x7387, 0x9686, 0x5229, 0x540f, 0x5c65,
1879 0x6613, 0x674e, 0x68a8, 0x6ce5, 0x7406, 0x75e2, 0x7f79, 0x0000,
1880 0x88e1, 0x91cc, 0x96e2, 0x533f, 0x6eba, 0x541d, 0x71d0, 0x7498,
1881 0x85fa, 0x0000, 0x9c57, 0x9e9f, 0x6797, 0x6dcb, 0x81e8, 0x7acb,
1882 0x7b20, 0x7c92, 0x72c0, 0x7099, 0x8b58, 0x4ec0, 0x8336, 0x523a,
1883 0x5207, 0x5ea6, 0x62d3, 0x7cd6, 0x5b85, 0x6d1e, 0x66b4, 0x8f3b,
1884 0x884c, 0x964d, 0x898b, 0x5ed3, 0x0000, 0x0000, 0x0000, 0x0000,
1885 0x585a, 0x0000, 0x6674, 0x0000, 0x0000, 0x51de, 0x8c6c, 0x76ca,
1886 0x0000, 0x795e, 0x7965, 0x798f, 0x9756, 0x7cbe, 0x7fbd, 0x0000,
1887 0x0000, 0x0000, 0x8af8, 0x0000, 0x0000, 0x9038, 0x90fd, 0x0000,
1888 0x0000, 0x0000, 0x98ef, 0x98fc, 0x9928, 0x9db4, 0x0000, 0x0000
1890 static const WCHAR compat_FE30_FEF7[200] =
1892 0x2025, 0x2014, 0x2013, 0x005f, 0x005f, 0x0028, 0x0029, 0x007b,
1893 0x007d, 0x3014, 0x3015, 0x3010, 0x3011, 0x300a, 0x300b, 0x3008,
1894 0x3009, 0x300c, 0x300d, 0x300e, 0x300f, 0x0000, 0x0000, 0x0000,
1895 0x0000, 0x203e, 0x203e, 0x203e, 0x203e, 0x005f, 0x005f, 0x005f,
1896 0x002c, 0x3001, 0x002e, 0x0000, 0x003b, 0x003a, 0x003f, 0x0021,
1897 0x2014, 0x0028, 0x0029, 0x007b, 0x007d, 0x3014, 0x3015, 0x0023,
1898 0x0026, 0x002a, 0x002b, 0x002d, 0x003c, 0x003e, 0x003d, 0x0000,
1899 0x0000, 0x0024, 0x0025, 0x0040, 0x0000, 0x0000, 0x0000, 0x0000,
1900 0x064b, 0x064b, 0x064c, 0x0000, 0x064d, 0x0000, 0x064e, 0x064e,
1901 0x064f, 0x064f, 0x0650, 0x0650, 0x0651, 0x0651, 0x0652, 0x0652,
1902 0x0621, 0x0622, 0x0622, 0x0623, 0x0623, 0x0624, 0x0624, 0x0625,
1903 0x0625, 0x0626, 0x0626, 0x0626, 0x0626, 0x0627, 0x0627, 0x0628,
1904 0x0628, 0x0628, 0x0628, 0x0629, 0x0629, 0x062a, 0x062a, 0x062a,
1905 0x062a, 0x062b, 0x062b, 0x062b, 0x062b, 0x062c, 0x062c, 0x062c,
1906 0x062c, 0x062d, 0x062d, 0x062d, 0x062d, 0x062e, 0x062e, 0x062e,
1907 0x062e, 0x062f, 0x062f, 0x0630, 0x0630, 0x0631, 0x0631, 0x0632,
1908 0x0632, 0x0633, 0x0633, 0x0633, 0x0633, 0x0634, 0x0634, 0x0634,
1909 0x0634, 0x0635, 0x0635, 0x0635, 0x0635, 0x0636, 0x0636, 0x0636,
1910 0x0636, 0x0637, 0x0637, 0x0637, 0x0637, 0x0638, 0x0638, 0x0638,
1911 0x0638, 0x0639, 0x0639, 0x0639, 0x0639, 0x063a, 0x063a, 0x063a,
1912 0x063a, 0x0641, 0x0641, 0x0641, 0x0641, 0x0642, 0x0642, 0x0642,
1913 0x0642, 0x0643, 0x0643, 0x0643, 0x0643, 0x0644, 0x0644, 0x0644,
1914 0x0644, 0x0645, 0x0645, 0x0645, 0x0645, 0x0646, 0x0646, 0x0646,
1915 0x0646, 0x0647, 0x0647, 0x0647, 0x0647, 0x0648, 0x0648, 0x0649,
1916 0x0649, 0x064a, 0x064a, 0x064a, 0x064a, 0x0000, 0x0000, 0x0000
1918 static const WCHAR compat_FF00_FFEF[240] =
1920 0x0000, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
1921 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
1922 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
1923 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
1924 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
1925 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
1926 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
1927 0x0058, 0x0059, 0x005a, 0x005b, 0x0000, 0x005d, 0x005e, 0x005f,
1928 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
1929 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
1930 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
1931 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000,
1932 0x0000, 0x3002, 0x300c, 0x300d, 0x3001, 0x30fb, 0x30f2, 0x30a1,
1933 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, 0x30c3,
1934 0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, 0x30ab, 0x30ad,
1935 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, 0x30b9, 0x30bb, 0x30bd,
1936 0x30bf, 0x30c1, 0x30c4, 0x30c6, 0x30c8, 0x30ca, 0x30cb, 0x30cc,
1937 0x30cd, 0x30ce, 0x30cf, 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de,
1938 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9,
1939 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c,
1940 0x3164, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137,
1941 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f,
1942 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147,
1943 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x0000,
1944 0x0000, 0x0000, 0x314f, 0x3150, 0x3151, 0x3152, 0x3153, 0x3154,
1945 0x0000, 0x0000, 0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315a,
1946 0x0000, 0x0000, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, 0x3160,
1947 0x0000, 0x0000, 0x3161, 0x3162, 0x3163, 0x0000, 0x0000, 0x0000,
1948 0x00a2, 0x00a3, 0x00ac, 0x00af, 0x00a6, 0x00a5, 0x20a9, 0x0000,
1949 0x2502, 0x2190, 0x2191, 0x2192, 0x2193, 0x25a0, 0x25cb, 0x0000
1951 static const WCHAR ligatures_src[] =
1953 0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
1954 0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
1955 0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
1956 0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
1957 0xfb04, 0xfb05, 0xfb06, '\0'
1959 static const WCHAR ligatures_dst[] =
1961 'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
1962 'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
1963 'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
1964 0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
1965 'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
1968 if (!pFoldStringW)
1970 win_skip("FoldStringW is not available\n");
1971 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1974 /* Invalid flag combinations */
1975 for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
1977 src[0] = dst[0] = '\0';
1978 SetLastError(0);
1979 ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
1980 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1982 win_skip("FoldStringW is not implemented\n");
1983 return;
1985 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
1986 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1989 /* src & dst cannot be the same */
1990 SetLastError(0);
1991 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
1992 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1993 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1995 /* src can't be NULL */
1996 SetLastError(0);
1997 ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
1998 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1999 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2001 /* srclen can't be 0 */
2002 SetLastError(0);
2003 ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
2004 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2005 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2007 /* dstlen can't be < 0 */
2008 SetLastError(0);
2009 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
2010 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2011 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2013 /* Ret includes terminating NUL which is appended if srclen = -1 */
2014 SetLastError(0);
2015 src[0] = 'A';
2016 src[1] = '\0';
2017 dst[0] = '\0';
2018 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
2019 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2020 ok(dst[0] == 'A' && dst[1] == '\0',
2021 "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%d\n",
2022 'A', '\0', ret, dst[0], dst[1], GetLastError());
2024 /* If size is given, result is not NUL terminated */
2025 SetLastError(0);
2026 src[0] = 'A';
2027 src[1] = 'A';
2028 dst[0] = 'X';
2029 dst[1] = 'X';
2030 ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
2031 ok(ret == 1, "Expected ret == 1, got %d, error %d\n", ret, GetLastError());
2032 ok(dst[0] == 'A' && dst[1] == 'X',
2033 "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%d\n",
2034 'A','X', ret, dst[0], dst[1], GetLastError());
2036 /* MAP_FOLDDIGITS */
2037 for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
2039 /* Check everything before this range */
2040 for (ch = prev_ch; ch < digitRanges[j]; ch++)
2042 SetLastError(0);
2043 src[0] = ch;
2044 src[1] = dst[0] = '\0';
2045 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2046 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2048 ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
2049 /* Wine (correctly) maps all Unicode 4.0+ digits */
2050 isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF ||
2051 (ch >= 0x1369 && ch <= 0x1371),
2052 "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
2055 if (digitRanges[j] == 0xffff)
2056 break; /* Finished the whole code point space */
2058 for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
2060 WCHAR c;
2062 /* Map out of sequence characters */
2063 if (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
2064 else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
2065 else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
2066 else if (ch == 0x245F) c = 0x24EA; /* Circled 0 */
2067 else c = ch;
2068 SetLastError(0);
2069 src[0] = c;
2070 src[1] = dst[0] = '\0';
2071 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2072 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2074 ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
2075 broken( dst[0] == ch ) || /* old Windows versions don't have all mappings */
2076 strchrW(noDigitAvailable, c),
2077 "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
2078 ch, '0' + digitRanges[j] - ch, dst[0]);
2080 prev_ch = ch;
2083 /* MAP_FOLDCZONE */
2084 for (ch = 1, failures = 0; ch <0xffff; ch++)
2086 WCHAR expected = 0;
2088 if (ch >= 0xF900 && ch <= 0xFA2F)
2089 expected = compat_F900_FA2F[ch - 0xF900];
2090 else if (ch >= 0xFE30 && ch <= 0xFEF7)
2091 expected = compat_FE30_FEF7[ch - 0xFE30];
2092 else if (ch >= 0xFF00 && ch <= 0xFFEF)
2093 expected = compat_FF00_FFEF[ch - 0xFF00];
2095 if (!expected)
2096 expected = ch;
2098 SetLastError(0);
2099 src[0] = ch;
2100 src[1] = dst[0] = '\0';
2101 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
2102 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2103 ok(dst[0] == expected ||
2104 broken( dst[0] == ch ) || /* old Windows versions don't have all mappings */
2105 /* Wine (correctly) uses updated mappings for some Unicode 4.0 chars */
2106 /* FIXME: But they should be re-checked */
2107 ch == 0xf92c || ch == 0xf979 || ch == 0xf995 || ch == 0xf9e7 ||
2108 ch == 0xf9f1 ||
2109 (0xfa0c <= ch && ch <= 0xfa6a) ||
2110 (0xfa70 <= ch && ch <= 0xfad9) ||
2111 ch == 0xfe47 || ch == 0xfe48 || ch == 0xfe68 ||
2112 (0xfe70 <= ch && ch <= 0xfe7f) ||
2113 ch == 0xff3c || ch == 0xff5f || ch == 0xff60 ||
2114 ch == 0xff9e || ch == 0xff9f,
2115 "MAP_FOLDCZONE: ch %d 0x%04x Expected 0x%04x got 0x%04x\n",
2116 ch, ch, expected, dst[0]);
2117 if (dst[0] != expected && ch < 0xf000 && ++failures > 50)
2119 trace( "MAP_FOLDCZONE: Too many failures, giving up\n" );
2120 break;
2124 /* MAP_EXPAND_LIGATURES */
2125 SetLastError(0);
2126 ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
2127 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
2128 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
2129 ok(ret == sizeof(ligatures_dst)/sizeof(ligatures_dst[0]),
2130 "Got %d, error %d\n", ret, GetLastError());
2131 ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
2132 "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
2133 for (i = 1, failures = 0; i <= 0xffff; i++)
2135 if (!strchrW(ligatures_src, i))
2137 src[0] = i;
2138 src[1] = '\0';
2139 SetLastError(0);
2140 ret = pFoldStringW(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
2141 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2142 if (ret == 3)
2143 ok(0, "MAP_EXPAND_LIGATURES: %04x : Expected %04x, got %04x %04x\n",
2144 i, src[0], dst[0], dst[1]);
2145 else
2146 ok(dst[0] == src[0],
2147 "MAP_EXPAND_LIGATURES: %04x : Expected %04x, got %04x\n",
2148 i, src[0], dst[0]);
2149 if (dst[0] != src[0] && ++failures > 50)
2151 trace( "MAP_EXPAND_LIGATURES: Too many failures, giving up\n" );
2152 break;
2158 /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
2163 #define LCID_OK(l) \
2164 ok(lcid == l, "Expected lcid = %08x, got %08x\n", l, lcid)
2165 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
2166 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
2167 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
2168 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
2170 static void test_ConvertDefaultLocale(void)
2172 LCID lcid;
2174 /* Doesn't change lcid, even if non default sublang/sort used */
2175 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_US, SORT_DEFAULT);
2176 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_UK, SORT_DEFAULT);
2177 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT);
2178 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE);
2180 /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
2181 LCID_RES(MKLCID(LANG_ENGLISH, SUBLANG_NEUTRAL, SORT_DEFAULT),
2182 MKLCID(LANG_ENGLISH, SUBLANG_DEFAULT, SORT_DEFAULT));
2183 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
2184 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
2185 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_JAPANESE_UNICODE),
2186 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE));
2188 /* Invariant language is not treated specially */
2189 TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
2190 LCID_RES(MKLCID(LANG_INVARIANT, SUBLANG_NEUTRAL, SORT_DEFAULT),
2191 MKLCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT));
2193 /* User/system default languages alone are not mapped */
2194 TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
2195 TEST_LCIDLANG(LANG_USER_DEFAULT, SORT_JAPANESE_UNICODE);
2197 /* Default lcids */
2198 LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
2199 LCID_RES(LOCALE_USER_DEFAULT, GetUserDefaultLCID());
2200 LCID_RES(LOCALE_NEUTRAL, GetUserDefaultLCID());
2203 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
2204 DWORD dwFlags, LONG_PTR lParam)
2206 trace("%08x, %s, %s, %08x, %08lx\n",
2207 lgrpid, lpszNum, lpszName, dwFlags, lParam);
2209 ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
2210 "Enumerated grp %d not valid (flags %d)\n", lgrpid, dwFlags);
2212 /* If lParam is one, we are calling with flags defaulted from 0 */
2213 ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
2214 "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %d\n", dwFlags);
2216 return TRUE;
2219 static void test_EnumSystemLanguageGroupsA(void)
2221 BOOL ret;
2223 if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
2225 win_skip("EnumSystemLanguageGroupsA and/or IsValidLanguageGroup are not available\n");
2226 return;
2229 /* No enumeration proc */
2230 SetLastError(0);
2231 ret = pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
2232 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2234 win_skip("EnumSystemLanguageGroupsA is not implemented\n");
2235 return;
2237 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2238 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2240 /* Invalid flags */
2241 SetLastError(0);
2242 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
2243 ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2245 /* No flags - defaults to LGRPID_INSTALLED */
2246 SetLastError(0xdeadbeef);
2247 pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
2248 ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
2250 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
2251 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
2255 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
2256 LONG_PTR lParam)
2258 trace("%08x, %08x, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
2260 /* invalid locale enumerated on some platforms */
2261 if (lcid == 0)
2262 return TRUE;
2264 ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
2265 "Enumerated grp %d not valid\n", lgrpid);
2266 ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
2267 "Enumerated grp locale %d not valid\n", lcid);
2268 return TRUE;
2271 static void test_EnumLanguageGroupLocalesA(void)
2273 BOOL ret;
2275 if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
2277 win_skip("EnumLanguageGroupLocalesA and/or IsValidLanguageGroup are not available\n");
2278 return;
2281 /* No enumeration proc */
2282 SetLastError(0);
2283 ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
2284 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2286 win_skip("EnumLanguageGroupLocalesA is not implemented\n");
2287 return;
2289 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2290 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2292 /* lgrpid too small */
2293 SetLastError(0);
2294 ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
2295 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2296 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2298 /* lgrpid too big */
2299 SetLastError(0);
2300 ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
2301 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2302 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2304 /* dwFlags is reserved */
2305 SetLastError(0);
2306 ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
2307 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2308 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2310 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2313 static void test_SetLocaleInfoA(void)
2315 BOOL bRet;
2316 LCID lcid = GetUserDefaultLCID();
2318 /* Null data */
2319 SetLastError(0);
2320 bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2321 ok( !bRet && GetLastError() == ERROR_INVALID_PARAMETER,
2322 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2324 /* IDATE */
2325 SetLastError(0);
2326 bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
2327 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2328 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2330 /* ILDATE */
2331 SetLastError(0);
2332 bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
2333 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2334 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2337 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2339 trace("%s %08lx\n", value, lParam);
2340 return(TRUE);
2343 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2345 ok(!enumCount, "callback called again unexpected\n");
2346 enumCount++;
2347 return(FALSE);
2350 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2352 ok(0,"callback called unexpected\n");
2353 return(FALSE);
2356 static void test_EnumUILanguageA(void)
2358 BOOL ret;
2359 if (!pEnumUILanguagesA) {
2360 win_skip("EnumUILanguagesA is not available on Win9x or NT4\n");
2361 return;
2364 SetLastError(ERROR_SUCCESS);
2365 ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2366 if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2368 win_skip("EnumUILanguagesA is not implemented\n");
2369 return;
2371 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2373 enumCount = 0;
2374 SetLastError(ERROR_SUCCESS);
2375 ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2376 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2378 SetLastError(ERROR_SUCCESS);
2379 ret = pEnumUILanguagesA(NULL, 0, 0);
2380 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2381 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2382 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2384 SetLastError(ERROR_SUCCESS);
2385 ret = pEnumUILanguagesA(luilocale_proc3A, 0x5a5a5a5a, 0);
2386 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2387 ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2389 SetLastError(ERROR_SUCCESS);
2390 ret = pEnumUILanguagesA(NULL, 0x5a5a5a5a, 0);
2391 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2392 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2393 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2396 static char date_fmt_buf[1024];
2398 static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
2400 lstrcatA(date_fmt_buf, fmt);
2401 lstrcatA(date_fmt_buf, "\n");
2402 return TRUE;
2405 static void test_EnumDateFormatsA(void)
2407 char *p, buf[256];
2408 BOOL ret;
2409 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2411 trace("EnumDateFormatsA 0\n");
2412 date_fmt_buf[0] = 0;
2413 SetLastError(0xdeadbeef);
2414 ret = EnumDateFormatsA(enum_datetime_procA, lcid, 0);
2415 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2417 win_skip("0 for dwFlags is not supported\n");
2419 else
2421 ok(ret, "EnumDateFormatsA(0) error %d\n", GetLastError());
2422 trace("%s\n", date_fmt_buf);
2423 /* test the 1st enumerated format */
2424 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2425 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2426 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2427 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2430 trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n");
2431 date_fmt_buf[0] = 0;
2432 SetLastError(0xdeadbeef);
2433 ret = EnumDateFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2434 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2436 win_skip("LOCALE_USE_CP_ACP is not supported\n");
2438 else
2440 ok(ret, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2441 trace("%s\n", date_fmt_buf);
2442 /* test the 1st enumerated format */
2443 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2444 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2445 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2446 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2449 trace("EnumDateFormatsA DATE_SHORTDATE\n");
2450 date_fmt_buf[0] = 0;
2451 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_SHORTDATE);
2452 ok(ret, "EnumDateFormatsA(DATE_SHORTDATE) error %d\n", GetLastError());
2453 trace("%s\n", date_fmt_buf);
2454 /* test the 1st enumerated format */
2455 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2456 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2457 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2458 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2460 trace("EnumDateFormatsA DATE_LONGDATE\n");
2461 date_fmt_buf[0] = 0;
2462 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_LONGDATE);
2463 ok(ret, "EnumDateFormatsA(DATE_LONGDATE) error %d\n", GetLastError());
2464 trace("%s\n", date_fmt_buf);
2465 /* test the 1st enumerated format */
2466 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2467 ret = GetLocaleInfoA(lcid, LOCALE_SLONGDATE, buf, sizeof(buf));
2468 ok(ret, "GetLocaleInfoA(LOCALE_SLONGDATE) error %d\n", GetLastError());
2469 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2471 trace("EnumDateFormatsA DATE_YEARMONTH\n");
2472 date_fmt_buf[0] = 0;
2473 SetLastError(0xdeadbeef);
2474 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_YEARMONTH);
2475 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2477 skip("DATE_YEARMONTH is only present on W2K and later\n");
2478 return;
2480 ok(ret, "EnumDateFormatsA(DATE_YEARMONTH) error %d\n", GetLastError());
2481 trace("%s\n", date_fmt_buf);
2482 /* test the 1st enumerated format */
2483 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2484 ret = GetLocaleInfoA(lcid, LOCALE_SYEARMONTH, buf, sizeof(buf));
2485 ok(ret, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %d\n", GetLastError());
2486 ok(!lstrcmpA(date_fmt_buf, buf) || broken(!buf[0]) /* win9x */,
2487 "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2490 static void test_EnumTimeFormatsA(void)
2492 char *p, buf[256];
2493 BOOL ret;
2494 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2496 trace("EnumTimeFormatsA 0\n");
2497 date_fmt_buf[0] = 0;
2498 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, 0);
2499 ok(ret, "EnumTimeFormatsA(0) error %d\n", GetLastError());
2500 trace("%s\n", date_fmt_buf);
2501 /* test the 1st enumerated format */
2502 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2503 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2504 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2505 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2507 trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n");
2508 date_fmt_buf[0] = 0;
2509 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2510 ok(ret, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2511 trace("%s\n", date_fmt_buf);
2512 /* test the 1st enumerated format */
2513 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2514 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2515 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2516 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2519 static void test_GetCPInfo(void)
2521 BOOL ret;
2522 CPINFO cpinfo;
2524 SetLastError(0xdeadbeef);
2525 ret = GetCPInfo(CP_SYMBOL, &cpinfo);
2526 ok(!ret, "GetCPInfo(CP_SYMBOL) should fail\n");
2527 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2528 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2530 SetLastError(0xdeadbeef);
2531 ret = GetCPInfo(CP_UTF7, &cpinfo);
2532 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2534 skip("Codepage CP_UTF7 is not installed/available\n");
2536 else
2538 ok(ret, "GetCPInfo(CP_UTF7) error %u\n", GetLastError());
2539 ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2540 ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2541 ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2542 ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2543 ok(cpinfo.MaxCharSize == 5, "expected 5, got 0x%x\n", cpinfo.MaxCharSize);
2546 SetLastError(0xdeadbeef);
2547 ret = GetCPInfo(CP_UTF8, &cpinfo);
2548 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2550 skip("Codepage CP_UTF8 is not installed/available\n");
2552 else
2554 ok(ret, "GetCPInfo(CP_UTF8) error %u\n", GetLastError());
2555 ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2556 ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2557 ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2558 ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2559 ok(cpinfo.MaxCharSize == 4 || broken(cpinfo.MaxCharSize == 3) /* win9x */,
2560 "expected 4, got %u\n", cpinfo.MaxCharSize);
2564 START_TEST(locale)
2566 InitFunctionPointers();
2568 test_EnumTimeFormatsA();
2569 test_EnumDateFormatsA();
2570 test_GetLocaleInfoA();
2571 test_GetTimeFormatA();
2572 test_GetDateFormatA();
2573 test_GetDateFormatW();
2574 test_GetCurrencyFormatA(); /* Also tests the W version */
2575 test_GetNumberFormatA(); /* Also tests the W version */
2576 test_CompareStringA();
2577 test_LCMapStringA();
2578 test_LCMapStringW();
2579 test_FoldStringA();
2580 test_FoldStringW();
2581 test_ConvertDefaultLocale();
2582 test_EnumSystemLanguageGroupsA();
2583 test_EnumLanguageGroupLocalesA();
2584 test_SetLocaleInfoA();
2585 test_EnumUILanguageA();
2586 test_GetCPInfo();
2587 /* this requires collation table patch to make it MS compatible */
2588 if (0) test_sorting();