push 149f0a5527ac85057a8ef03858d34d91c36f97e8
[wine/hacks.git] / dlls / kernel32 / tests / locale.c
blob48ab35006355275771663a49eb33be0a2449ec57
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>
31 #include <stdio.h>
33 #include "wine/test.h"
34 #include "windef.h"
35 #include "winbase.h"
36 #include "winerror.h"
37 #include "winnls.h"
39 static inline unsigned int strlenW( const WCHAR *str )
41 const WCHAR *s = str;
42 while (*s) s++;
43 return s - str;
46 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
48 if (n <= 0) return 0;
49 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
50 return *str1 - *str2;
53 static inline WCHAR *strchrW( const WCHAR *str, WCHAR ch )
55 do { if (*str == ch) return (WCHAR *)str; } while (*str++);
56 return NULL;
59 static inline int isdigitW( WCHAR wc )
61 WORD type;
62 GetStringTypeW( CT_CTYPE1, &wc, 1, &type );
63 return type & C1_DIGIT;
66 /* Some functions are only in later versions of kernel32.dll */
67 static HMODULE hKernel32;
68 static WORD enumCount;
70 typedef BOOL (WINAPI *EnumSystemLanguageGroupsAFn)(LANGUAGEGROUP_ENUMPROC,
71 DWORD, LONG_PTR);
72 static EnumSystemLanguageGroupsAFn pEnumSystemLanguageGroupsA;
73 typedef BOOL (WINAPI *EnumLanguageGroupLocalesAFn)(LANGGROUPLOCALE_ENUMPROC,
74 LGRPID, DWORD, LONG_PTR);
75 static EnumLanguageGroupLocalesAFn pEnumLanguageGroupLocalesA;
76 typedef BOOL (WINAPI *EnumUILanguagesAFn)(UILANGUAGE_ENUMPROC,
77 DWORD, LONG_PTR);
78 static EnumUILanguagesAFn pEnumUILanguagesA;
80 typedef INT (WINAPI *FoldStringAFn)(DWORD, LPCSTR, INT, LPSTR, INT);
81 static FoldStringAFn pFoldStringA;
82 typedef INT (WINAPI *FoldStringWFn)(DWORD, LPCWSTR, INT, LPWSTR, INT);
83 static FoldStringWFn pFoldStringW;
85 typedef BOOL (WINAPI *IsValidLanguageGroupFn)(LGRPID, DWORD);
86 static IsValidLanguageGroupFn pIsValidLanguageGroup;
88 static void InitFunctionPointers(void)
90 hKernel32 = GetModuleHandleA("kernel32");
91 pEnumSystemLanguageGroupsA = (void*)GetProcAddress(hKernel32, "EnumSystemLanguageGroupsA");
92 pEnumLanguageGroupLocalesA = (void*)GetProcAddress(hKernel32, "EnumLanguageGroupLocalesA");
93 pFoldStringA = (void*)GetProcAddress(hKernel32, "FoldStringA");
94 pFoldStringW = (void*)GetProcAddress(hKernel32, "FoldStringW");
95 pIsValidLanguageGroup = (void*)GetProcAddress(hKernel32, "IsValidLanguageGroup");
96 pEnumUILanguagesA = (void*)GetProcAddress(hKernel32, "EnumUILanguagesA");
99 #define eq(received, expected, label, type) \
100 ok((received) == (expected), "%s: got " type " instead of " type "\n", \
101 (label), (received), (expected))
103 #define BUFFER_SIZE 128
104 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
106 #define STRINGSA(x,y) strcpy(input, x); strcpy(Expected, y); SetLastError(0xdeadbeef); buffer[0] = '\0'
107 #define EXPECT_LENA ok(ret == lstrlen(Expected)+1, "Expected Len %d, got %d\n", lstrlen(Expected)+1, ret)
108 #define EXPECT_EQA ok(strncmp(buffer, Expected, strlen(Expected)) == 0, \
109 "Expected '%s', got '%s'\n", Expected, buffer)
111 #define STRINGSW(x,y) MultiByteToWideChar(CP_ACP,0,x,-1,input,COUNTOF(input)); \
112 MultiByteToWideChar(CP_ACP,0,y,-1,Expected,COUNTOF(Expected)); \
113 SetLastError(0xdeadbeef); buffer[0] = '\0'
114 #define EXPECT_LENW ok(ret == lstrlenW(Expected)+1, "Expected Len %d, got %d\n", lstrlenW(Expected)+1, ret)
115 #define EXPECT_EQW ok(strncmpW(buffer, Expected, strlenW(Expected)) == 0, "Bad conversion\n")
117 #define NUO LOCALE_NOUSEROVERRIDE
119 static void test_GetLocaleInfoA(void)
121 int ret;
122 int len;
123 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
124 char buffer[BUFFER_SIZE];
125 char expected[BUFFER_SIZE];
127 ok(lcid == 0x409, "wrong LCID calculated - %d\n", lcid);
129 /* en and ar use SUBLANG_NEUTRAL, but GetLocaleInfo assume SUBLANG_DEFAULT
130 Same is true for zh on pre-Vista, but on Vista and higher GetLocaleInfo
131 assumes SUBLANG_NEUTRAL for zh */
132 memset(expected, 0, COUNTOF(expected));
133 len = GetLocaleInfoA(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
134 SetLastError(0xdeadbeef);
135 memset(buffer, 0, COUNTOF(buffer));
136 ret = GetLocaleInfoA(LANG_ENGLISH, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
137 ok((ret == len) && !lstrcmpA(buffer, expected),
138 "got %d with '%s' (expected %d with '%s')\n",
139 ret, buffer, len, expected);
141 memset(expected, 0, COUNTOF(expected));
142 len = GetLocaleInfoA(MAKELANGID(LANG_ARABIC, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
143 if (len) {
144 SetLastError(0xdeadbeef);
145 memset(buffer, 0, COUNTOF(buffer));
146 ret = GetLocaleInfoA(LANG_ARABIC, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
147 ok((ret == len) && !lstrcmpA(buffer, expected),
148 "got %d with '%s' (expected %d with '%s')\n",
149 ret, buffer, len, expected);
151 else
152 win_skip("LANG_ARABIC not installed\n");
154 /* SUBLANG_DEFAULT is required for mlang.dll, but optional for GetLocaleInfo */
155 memset(expected, 0, COUNTOF(expected));
156 len = GetLocaleInfoA(MAKELANGID(LANG_GERMAN, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
157 SetLastError(0xdeadbeef);
158 memset(buffer, 0, COUNTOF(buffer));
159 ret = GetLocaleInfoA(LANG_GERMAN, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
160 ok((ret == len) && !lstrcmpA(buffer, expected),
161 "got %d with '%s' (expected %d with '%s')\n",
162 ret, buffer, len, expected);
165 /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
166 * partially fill the buffer even if it is too short. See bug 637.
168 SetLastError(0xdeadbeef);
169 memset(buffer, 0, COUNTOF(buffer));
170 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 0);
171 ok(ret == 7 && !buffer[0], "Expected len=7, got %d\n", ret);
173 SetLastError(0xdeadbeef);
174 memset(buffer, 0, COUNTOF(buffer));
175 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 3);
176 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
177 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
178 ok(!strcmp(buffer, "Mon"), "Expected 'Mon', got '%s'\n", buffer);
180 SetLastError(0xdeadbeef);
181 memset(buffer, 0, COUNTOF(buffer));
182 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 10);
183 ok(ret == 7, "Expected ret == 7, got %d, error %d\n", ret, GetLastError());
184 ok(!strcmp(buffer, "Monday"), "Expected 'Monday', got '%s'\n", buffer);
187 static void test_GetLocaleInfoW(void)
189 LCID lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
190 LCID lcid_ru = MAKELCID(MAKELANGID(LANG_RUSSIAN, SUBLANG_NEUTRAL), SORT_DEFAULT);
191 WCHAR bufferW[80], buffer2W[80];
192 CHAR bufferA[80];
193 DWORD ret;
194 INT i;
196 ret = GetLocaleInfoW(lcid_en, LOCALE_SMONTHNAME1, bufferW, COUNTOF(bufferW));
197 if (!ret) {
198 win_skip("GetLocaleInfoW() isn't implemented\n");
199 return;
201 ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1, bufferW, COUNTOF(bufferW));
202 if (!ret) {
203 win_skip("LANG_RUSSIAN locale data unavailable\n");
204 return;
206 ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1|LOCALE_RETURN_GENITIVE_NAMES,
207 bufferW, COUNTOF(bufferW));
208 if (!ret) {
209 win_skip("LOCALE_RETURN_GENITIVE_NAMES isn't supported\n");
210 return;
213 /* LOCALE_RETURN_GENITIVE_NAMES isn't supported for GetLocaleInfoA */
214 bufferA[0] = 'a';
215 SetLastError(0xdeadbeef);
216 ret = GetLocaleInfoA(lcid_ru, LOCALE_SMONTHNAME1|LOCALE_RETURN_GENITIVE_NAMES,
217 bufferA, COUNTOF(bufferA));
218 ok(ret == 0, "LOCALE_RETURN_GENITIVE_NAMES should fail with GetLocaleInfoA\n");
219 ok(bufferA[0] == 'a', "Expected buffer to be untouched\n");
220 ok(GetLastError() == ERROR_INVALID_FLAGS,
221 "Expected ERROR_INVALID_FLAGS, got %x\n", GetLastError());
223 bufferW[0] = 'a';
224 SetLastError(0xdeadbeef);
225 ret = GetLocaleInfoW(lcid_ru, LOCALE_RETURN_GENITIVE_NAMES,
226 bufferW, COUNTOF(bufferW));
227 ok(ret == 0,
228 "LOCALE_RETURN_GENITIVE_NAMES itself doesn't return anything, got %d\n", ret);
229 ok(bufferW[0] == 'a', "Expected buffer to be untouched\n");
230 ok(GetLastError() == ERROR_INVALID_FLAGS,
231 "Expected ERROR_INVALID_FLAGS, got %x\n", GetLastError());
233 /* yes, test empty 13 month entry too */
234 for (i = 0; i < 12; i++) {
235 bufferW[0] = 0;
236 ret = GetLocaleInfoW(lcid_ru, (LOCALE_SMONTHNAME1+i)|LOCALE_RETURN_GENITIVE_NAMES,
237 bufferW, COUNTOF(bufferW));
238 ok(ret, "Expected non zero result\n");
239 ok(ret == lstrlenW(bufferW)+1, "Expected actual length, got %d, length %d\n",
240 ret, lstrlenW(bufferW));
241 buffer2W[0] = 0;
242 ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1+i,
243 buffer2W, COUNTOF(buffer2W));
244 ok(ret, "Expected non zero result\n");
245 ok(ret == lstrlenW(buffer2W)+1, "Expected actual length, got %d, length %d\n",
246 ret, lstrlenW(buffer2W));
248 ok(lstrcmpW(bufferW, buffer2W) != 0,
249 "Expected genitive name to differ, got the same for month %d\n", i+1);
251 /* for locale without genitive names nominative returned in both cases */
252 bufferW[0] = 0;
253 ret = GetLocaleInfoW(lcid_en, (LOCALE_SMONTHNAME1+i)|LOCALE_RETURN_GENITIVE_NAMES,
254 bufferW, COUNTOF(bufferW));
255 ok(ret, "Expected non zero result\n");
256 ok(ret == lstrlenW(bufferW)+1, "Expected actual length, got %d, length %d\n",
257 ret, lstrlenW(bufferW));
258 buffer2W[0] = 0;
259 ret = GetLocaleInfoW(lcid_en, LOCALE_SMONTHNAME1+i,
260 buffer2W, COUNTOF(buffer2W));
261 ok(ret, "Expected non zero result\n");
262 ok(ret == lstrlenW(buffer2W)+1, "Expected actual length, got %d, length %d\n",
263 ret, lstrlenW(buffer2W));
265 ok(lstrcmpW(bufferW, buffer2W) == 0,
266 "Expected same names, got different for month %d\n", i+1);
270 static void test_GetTimeFormatA(void)
272 int ret;
273 SYSTEMTIME curtime;
274 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
275 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
277 memset(&curtime, 2, sizeof(SYSTEMTIME));
278 STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
279 SetLastError(0xdeadbeef);
280 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
281 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
282 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
284 curtime.wHour = 8;
285 curtime.wMinute = 56;
286 curtime.wSecond = 13;
287 curtime.wMilliseconds = 22;
288 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
289 SetLastError(0xdeadbeef);
290 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
291 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
292 EXPECT_LENA; EXPECT_EQA;
294 /* MSDN: LOCALE_NOUSEROVERRIDE can't be specified with a format string */
295 SetLastError(0xdeadbeef);
296 ret = GetTimeFormatA(lcid, NUO|TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
297 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
298 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
300 STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficient buffer */
301 SetLastError(0xdeadbeef);
302 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, 2);
303 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
304 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
306 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
307 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, NULL, 0);
308 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
309 EXPECT_LENA;
311 STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
312 ret = GetTimeFormatA(lcid, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
313 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
314 EXPECT_LENA; EXPECT_EQA;
316 STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
317 ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
318 ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
319 ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "4" )), /* win9x */
320 "Expected '', got '%s'\n", buffer );
322 STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
323 ret = GetTimeFormatA(lcid, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
324 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
325 EXPECT_LENA; EXPECT_EQA;
327 STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
328 strcpy(Expected, "8:56 AM");
329 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &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.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
334 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
335 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
336 ok( !strcmp( buffer, "8.@:56AM" ) || broken( !strcmp( buffer, "8.@:56.@:AM" )) /* win9x */,
337 "Expected '8.@:56AM', got '%s'\n", buffer );
339 STRINGSA("s1s2s3", ""); /* Duplicate tokens */
340 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
341 ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
342 ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "3" )), /* win9x */
343 "Expected '', got '%s'\n", buffer );
345 STRINGSA("t/tt", "A/AM"); /* AM time marker */
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 curtime.wHour = 13;
351 STRINGSA("t/tt", "P/PM"); /* PM time marker */
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("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
357 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
358 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
359 EXPECT_LENA; EXPECT_EQA;
361 STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
362 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
363 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
364 EXPECT_LENA; EXPECT_EQA;
366 STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
367 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
368 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
369 EXPECT_LENA; EXPECT_EQA;
371 curtime.wHour = 14; /* change this to 14 or 2pm */
372 curtime.wMinute = 5;
373 curtime.wSecond = 3;
374 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 */
375 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
376 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
377 EXPECT_LENA; EXPECT_EQA;
379 curtime.wHour = 0;
380 STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
381 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
382 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
383 EXPECT_LENA; EXPECT_EQA;
385 STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
386 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
387 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
388 EXPECT_LENA; EXPECT_EQA;
390 /* try to convert formatting strings with more than two letters
391 * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
392 * NOTE: We expect any letter for which there is an upper case value
393 * we should see a replacement. For letters that DO NOT have
394 * upper case values we should see NO REPLACEMENT.
396 curtime.wHour = 8;
397 curtime.wMinute = 56;
398 curtime.wSecond = 13;
399 curtime.wMilliseconds = 22;
400 STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
401 "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
402 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
403 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
404 EXPECT_LENA; EXPECT_EQA;
406 STRINGSA("h", "text"); /* Don't write to buffer if len is 0 */
407 strcpy(buffer, "text");
408 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, 0);
409 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
410 EXPECT_EQA;
412 STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
413 "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
414 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
415 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
416 EXPECT_LENA; EXPECT_EQA;
418 STRINGSA("'''", "'"); /* invalid quoted string */
419 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
420 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
421 EXPECT_LENA; EXPECT_EQA;
423 /* test that msdn suggested single quotation usage works as expected */
424 STRINGSA("''''", "'"); /* single quote mark */
425 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
426 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
427 EXPECT_LENA; EXPECT_EQA;
429 STRINGSA("''HHHHHH", "08"); /* Normal use */
430 ret = GetTimeFormatA(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 /* and test for normal use of the single quotation mark */
435 STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
436 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
437 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
438 EXPECT_LENA; EXPECT_EQA;
440 STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
441 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
442 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
443 EXPECT_LENA; EXPECT_EQA;
445 STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
446 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
447 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
448 EXPECT_LENA; EXPECT_EQA;
450 curtime.wHour = 25;
451 STRINGSA("'123'tt", ""); /* Invalid time */
452 SetLastError(0xdeadbeef);
453 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
454 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
455 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
457 curtime.wHour = 12;
458 curtime.wMonth = 60; /* Invalid */
459 STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
460 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
461 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
462 EXPECT_LENA; EXPECT_EQA;
465 static void test_GetDateFormatA(void)
467 int ret;
468 SYSTEMTIME curtime;
469 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
470 LCID lcid_ru = MAKELCID(MAKELANGID(LANG_RUSSIAN, SUBLANG_NEUTRAL), SORT_DEFAULT);
471 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
472 char short_day[10], month[10], genitive_month[10];
474 memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
475 STRINGSA("ddd',' MMM dd yy","");
476 SetLastError(0xdeadbeef);
477 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
478 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
479 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
481 curtime.wYear = 2002;
482 curtime.wMonth = 5;
483 curtime.wDay = 4;
484 curtime.wDayOfWeek = 3;
485 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
486 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
487 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
488 EXPECT_LENA; EXPECT_EQA;
490 /* Same as above but with LOCALE_NOUSEROVERRIDE */
491 STRINGSA("ddd',' MMM dd yy",""); /* Simple case */
492 SetLastError(0xdeadbeef);
493 ret = GetDateFormatA(lcid, NUO, &curtime, input, buffer, COUNTOF(buffer));
494 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
495 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
496 EXPECT_EQA;
498 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
499 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
500 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
501 EXPECT_LENA; EXPECT_EQA;
503 curtime.wHour = 36; /* Invalid */
504 STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
505 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
506 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
507 EXPECT_LENA; EXPECT_EQA;
509 STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
510 ret = GetDateFormatA(lcid, 0, &curtime, input, NULL, 0);
511 ok(ret == 16, "Expected ret == 16, got %d, error %d\n", ret, GetLastError());
512 EXPECT_EQA;
514 STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
515 SetLastError(0xdeadbeef);
516 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, 2);
517 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
518 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
520 STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
521 ret = GetDateFormat(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
522 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
523 if (strncmp(buffer, Expected, strlen(Expected)) && strncmp(buffer, "5/4/02", strlen(Expected)) != 0)
524 ok (0, "Expected '%s' or '5/4/02', got '%s'\n", Expected, buffer);
526 STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
527 ret = GetDateFormat(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
528 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
529 EXPECT_LENA; EXPECT_EQA;
531 /* test for expected DATE_YEARMONTH behavior with null format */
532 /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
533 STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
534 SetLastError(0xdeadbeef);
535 ret = GetDateFormat(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
536 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
537 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
538 EXPECT_EQA;
540 /* Test that using invalid DATE_* flags results in the correct error */
541 /* and return values */
542 STRINGSA("m/d/y", ""); /* Invalid flags */
543 SetLastError(0xdeadbeef);
544 ret = GetDateFormat(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
545 &curtime, input, buffer, COUNTOF(buffer));
546 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
547 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
549 ret = GetDateFormat(lcid_ru, 0, &curtime, "ddMMMM", buffer, COUNTOF(buffer));
550 if (!ret)
552 win_skip("LANG_RUSSIAN locale data unavailable\n");
553 return;
556 /* month part should be in genitive form */
557 strcpy(genitive_month, buffer + 2);
558 ret = GetDateFormat(lcid_ru, 0, &curtime, "MMMM", buffer, COUNTOF(buffer));
559 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
560 strcpy(month, buffer);
561 ok(strcmp(genitive_month, month) != 0, "Expected different month forms\n");
563 ret = GetDateFormat(lcid_ru, 0, &curtime, "ddd", buffer, COUNTOF(buffer));
564 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
565 strcpy(short_day, buffer);
567 STRINGSA("dd MMMMddd dd", "");
568 sprintf(Expected, "04 %s%s 04", genitive_month, short_day);
569 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
570 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
571 EXPECT_EQA;
573 STRINGSA("MMMMddd dd", "");
574 sprintf(Expected, "%s%s 04", month, short_day);
575 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
576 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
577 EXPECT_EQA;
579 STRINGSA("MMMMddd", "");
580 sprintf(Expected, "%s%s", month, short_day);
581 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
582 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
583 EXPECT_EQA;
585 STRINGSA("MMMMdd", "");
586 sprintf(Expected, "%s04", genitive_month);
587 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
588 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
589 EXPECT_EQA;
591 STRINGSA("MMMMdd ddd", "");
592 sprintf(Expected, "%s04 %s", genitive_month, short_day);
593 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
594 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
595 EXPECT_EQA;
597 STRINGSA("dd dddMMMM", "");
598 sprintf(Expected, "04 %s%s", short_day, month);
599 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
600 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
601 EXPECT_EQA;
603 STRINGSA("dd dddMMMM ddd MMMMdd", "");
604 sprintf(Expected, "04 %s%s %s %s04", short_day, month, short_day, genitive_month);
605 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
606 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
607 EXPECT_EQA;
609 /* with literal part */
610 STRINGSA("ddd',' MMMM dd", "");
611 sprintf(Expected, "%s, %s 04", short_day, genitive_month);
612 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
613 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
614 EXPECT_EQA;
617 static void test_GetDateFormatW(void)
619 int ret;
620 SYSTEMTIME curtime;
621 WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
622 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
624 STRINGSW("",""); /* If flags is not zero then format must be NULL */
625 ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL,
626 input, buffer, COUNTOF(buffer));
627 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
629 win_skip("GetDateFormatW is not implemented\n");
630 return;
632 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
633 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
634 EXPECT_EQW;
636 STRINGSW("",""); /* NULL buffer, len > 0 */
637 SetLastError(0xdeadbeef);
638 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
639 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
640 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
642 STRINGSW("",""); /* NULL buffer, len == 0 */
643 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
644 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
645 EXPECT_LENW; EXPECT_EQW;
647 curtime.wYear = 2002;
648 curtime.wMonth = 10;
649 curtime.wDay = 23;
650 curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
651 curtime.wHour = 65432; /* Invalid */
652 curtime.wMinute = 34512; /* Invalid */
653 curtime.wSecond = 65535; /* Invalid */
654 curtime.wMilliseconds = 12345;
655 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
656 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
657 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
658 EXPECT_LENW; EXPECT_EQW;
660 /* Limit tests */
662 curtime.wYear = 1601;
663 curtime.wMonth = 1;
664 curtime.wDay = 1;
665 curtime.wDayOfWeek = 0; /* Irrelevant */
666 curtime.wHour = 0;
667 curtime.wMinute = 0;
668 curtime.wSecond = 0;
669 curtime.wMilliseconds = 0;
670 STRINGSW("dddd d MMMM yyyy","Monday 1 January 1601");
671 SetLastError(0xdeadbeef);
672 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
673 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
674 EXPECT_LENW; EXPECT_EQW;
676 curtime.wYear = 1600;
677 curtime.wMonth = 12;
678 curtime.wDay = 31;
679 curtime.wDayOfWeek = 0; /* Irrelevant */
680 curtime.wHour = 23;
681 curtime.wMinute = 59;
682 curtime.wSecond = 59;
683 curtime.wMilliseconds = 999;
684 STRINGSW("dddd d MMMM yyyy","Friday 31 December 1600");
685 SetLastError(0xdeadbeef);
686 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
687 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
688 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
692 #define CY_POS_LEFT 0
693 #define CY_POS_RIGHT 1
694 #define CY_POS_LEFT_SPACE 2
695 #define CY_POS_RIGHT_SPACE 3
697 static void test_GetCurrencyFormatA(void)
699 static char szDot[] = { '.', '\0' };
700 static char szComma[] = { ',', '\0' };
701 static char szDollar[] = { '$', '\0' };
702 int ret;
703 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
704 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
705 CURRENCYFMTA format;
707 memset(&format, 0, sizeof(format));
709 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
710 SetLastError(0xdeadbeef);
711 ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
712 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
713 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
715 STRINGSA("23,53",""); /* Invalid character --> Error */
716 SetLastError(0xdeadbeef);
717 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
718 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
719 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
721 STRINGSA("--",""); /* Double '-' --> Error */
722 SetLastError(0xdeadbeef);
723 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
724 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
725 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
727 STRINGSA("0-",""); /* Trailing '-' --> Error */
728 SetLastError(0xdeadbeef);
729 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
730 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
731 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
733 STRINGSA("0..",""); /* Double '.' --> Error */
734 SetLastError(0xdeadbeef);
735 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
736 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
737 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
739 STRINGSA(" 0.1",""); /* Leading space --> Error */
740 SetLastError(0xdeadbeef);
741 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
742 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
743 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
745 STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
746 SetLastError(0xdeadbeef);
747 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, 2);
748 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
749 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
751 STRINGSA("2353",""); /* Format and flags given --> Error */
752 SetLastError(0xdeadbeef);
753 ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
754 ok( !ret, "Expected ret == 0, got %d\n", ret);
755 ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
756 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
758 STRINGSA("2353",""); /* Invalid format --> Error */
759 SetLastError(0xdeadbeef);
760 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
761 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
762 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
764 STRINGSA("2353","$2,353.00"); /* Valid number */
765 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
766 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
767 EXPECT_LENA; EXPECT_EQA;
769 STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
770 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
771 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
772 EXPECT_LENA; EXPECT_EQA;
774 STRINGSA("2353.1","$2,353.10"); /* Valid real number */
775 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
776 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
777 EXPECT_LENA; EXPECT_EQA;
779 STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
780 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
781 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
782 EXPECT_LENA; EXPECT_EQA;
784 STRINGSA("2353.119","$2,353.12"); /* Too many DP --> Rounded */
785 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
786 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
787 EXPECT_LENA; EXPECT_EQA;
789 format.NumDigits = 0; /* No decimal separator */
790 format.LeadingZero = 0;
791 format.Grouping = 0; /* No grouping char */
792 format.NegativeOrder = 0;
793 format.PositiveOrder = CY_POS_LEFT;
794 format.lpDecimalSep = szDot;
795 format.lpThousandSep = szComma;
796 format.lpCurrencySymbol = szDollar;
798 STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
799 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
800 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
801 EXPECT_LENA; EXPECT_EQA;
803 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
804 STRINGSA("2353","$2353.0");
805 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
806 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
807 EXPECT_LENA; EXPECT_EQA;
809 format.Grouping = 2; /* Group by 100's */
810 STRINGSA("2353","$23,53.0");
811 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
812 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
813 EXPECT_LENA; EXPECT_EQA;
815 STRINGSA("235","$235.0"); /* Grouping of a positive number */
816 format.Grouping = 3;
817 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
818 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
819 EXPECT_LENA; EXPECT_EQA;
821 STRINGSA("-235","$-235.0"); /* Grouping of a negative number */
822 format.NegativeOrder = 2;
823 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
824 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
825 EXPECT_LENA; EXPECT_EQA;
827 format.LeadingZero = 1; /* Always provide leading zero */
828 STRINGSA(".5","$0.5");
829 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
830 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
831 EXPECT_LENA; EXPECT_EQA;
833 format.PositiveOrder = CY_POS_RIGHT;
834 STRINGSA("1","1.0$");
835 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
836 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
837 EXPECT_LENA; EXPECT_EQA;
839 format.PositiveOrder = CY_POS_LEFT_SPACE;
840 STRINGSA("1","$ 1.0");
841 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
842 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
843 EXPECT_LENA; EXPECT_EQA;
845 format.PositiveOrder = CY_POS_RIGHT_SPACE;
846 STRINGSA("1","1.0 $");
847 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
848 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
849 EXPECT_LENA; EXPECT_EQA;
851 format.NegativeOrder = 0;
852 STRINGSA("-1","($1.0)");
853 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
854 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
855 EXPECT_LENA; EXPECT_EQA;
857 format.NegativeOrder = 1;
858 STRINGSA("-1","-$1.0");
859 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
860 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
861 EXPECT_LENA; EXPECT_EQA;
863 format.NegativeOrder = 2;
864 STRINGSA("-1","$-1.0");
865 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
866 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
867 EXPECT_LENA; EXPECT_EQA;
869 format.NegativeOrder = 3;
870 STRINGSA("-1","$1.0-");
871 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
872 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
873 EXPECT_LENA; EXPECT_EQA;
875 format.NegativeOrder = 4;
876 STRINGSA("-1","(1.0$)");
877 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
878 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
879 EXPECT_LENA; EXPECT_EQA;
881 format.NegativeOrder = 5;
882 STRINGSA("-1","-1.0$");
883 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
884 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
885 EXPECT_LENA; EXPECT_EQA;
887 format.NegativeOrder = 6;
888 STRINGSA("-1","1.0-$");
889 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
890 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
891 EXPECT_LENA; EXPECT_EQA;
893 format.NegativeOrder = 7;
894 STRINGSA("-1","1.0$-");
895 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
896 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
897 EXPECT_LENA; EXPECT_EQA;
899 format.NegativeOrder = 8;
900 STRINGSA("-1","-1.0 $");
901 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
902 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
903 EXPECT_LENA; EXPECT_EQA;
905 format.NegativeOrder = 9;
906 STRINGSA("-1","-$ 1.0");
907 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
908 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
909 EXPECT_LENA; EXPECT_EQA;
911 format.NegativeOrder = 10;
912 STRINGSA("-1","1.0 $-");
913 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
914 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
915 EXPECT_LENA; EXPECT_EQA;
917 format.NegativeOrder = 11;
918 STRINGSA("-1","$ 1.0-");
919 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
920 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
921 EXPECT_LENA; EXPECT_EQA;
923 format.NegativeOrder = 12;
924 STRINGSA("-1","$ -1.0");
925 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
926 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
927 EXPECT_LENA; EXPECT_EQA;
929 format.NegativeOrder = 13;
930 STRINGSA("-1","1.0- $");
931 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
932 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
933 EXPECT_LENA; EXPECT_EQA;
935 format.NegativeOrder = 14;
936 STRINGSA("-1","($ 1.0)");
937 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
938 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
939 EXPECT_LENA; EXPECT_EQA;
941 format.NegativeOrder = 15;
942 STRINGSA("-1","(1.0 $)");
943 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
944 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
945 EXPECT_LENA; EXPECT_EQA;
948 #define NEG_PARENS 0 /* "(1.1)" */
949 #define NEG_LEFT 1 /* "-1.1" */
950 #define NEG_LEFT_SPACE 2 /* "- 1.1" */
951 #define NEG_RIGHT 3 /* "1.1-" */
952 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
954 static void test_GetNumberFormatA(void)
956 static char szDot[] = { '.', '\0' };
957 static char szComma[] = { ',', '\0' };
958 int ret;
959 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
960 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
961 NUMBERFMTA format;
963 memset(&format, 0, sizeof(format));
965 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
966 SetLastError(0xdeadbeef);
967 ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
968 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
969 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
971 STRINGSA("23,53",""); /* Invalid character --> Error */
972 SetLastError(0xdeadbeef);
973 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
974 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
975 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
977 STRINGSA("--",""); /* Double '-' --> Error */
978 SetLastError(0xdeadbeef);
979 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
980 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
981 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
983 STRINGSA("0-",""); /* Trailing '-' --> Error */
984 SetLastError(0xdeadbeef);
985 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
986 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
987 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
989 STRINGSA("0..",""); /* Double '.' --> Error */
990 SetLastError(0xdeadbeef);
991 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
992 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
993 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
995 STRINGSA(" 0.1",""); /* Leading space --> Error */
996 SetLastError(0xdeadbeef);
997 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
998 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
999 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1001 STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
1002 SetLastError(0xdeadbeef);
1003 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, 2);
1004 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1005 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1007 STRINGSA("2353",""); /* Format and flags given --> Error */
1008 SetLastError(0xdeadbeef);
1009 ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
1010 ok( !ret, "Expected ret == 0, got %d\n", ret);
1011 ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
1012 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1014 STRINGSA("2353",""); /* Invalid format --> Error */
1015 SetLastError(0xdeadbeef);
1016 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1017 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1018 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1020 STRINGSA("2353","2,353.00"); /* Valid number */
1021 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1022 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1023 EXPECT_LENA; EXPECT_EQA;
1025 STRINGSA("-2353","-2,353.00"); /* Valid negative number */
1026 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1027 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1028 EXPECT_LENA; EXPECT_EQA;
1030 STRINGSA("-353","-353.00"); /* test for off by one error in grouping */
1031 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1032 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1033 EXPECT_LENA; EXPECT_EQA;
1035 STRINGSA("2353.1","2,353.10"); /* Valid real number */
1036 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1037 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1038 EXPECT_LENA; EXPECT_EQA;
1040 STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
1041 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1042 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1043 EXPECT_LENA; EXPECT_EQA;
1045 STRINGSA("2353.119","2,353.12"); /* Too many DP --> Rounded */
1046 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1047 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1048 EXPECT_LENA; EXPECT_EQA;
1050 format.NumDigits = 0; /* No decimal separator */
1051 format.LeadingZero = 0;
1052 format.Grouping = 0; /* No grouping char */
1053 format.NegativeOrder = 0;
1054 format.lpDecimalSep = szDot;
1055 format.lpThousandSep = szComma;
1057 STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
1058 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1059 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1060 EXPECT_LENA; EXPECT_EQA;
1062 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
1063 STRINGSA("2353","2353.0");
1064 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1065 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1066 EXPECT_LENA; EXPECT_EQA;
1068 format.Grouping = 2; /* Group by 100's */
1069 STRINGSA("2353","23,53.0");
1070 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1071 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1072 EXPECT_LENA; EXPECT_EQA;
1074 STRINGSA("235","235.0"); /* Grouping of a positive number */
1075 format.Grouping = 3;
1076 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1077 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1078 EXPECT_LENA; EXPECT_EQA;
1080 STRINGSA("-235","-235.0"); /* Grouping of a negative number */
1081 format.NegativeOrder = NEG_LEFT;
1082 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1083 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1084 EXPECT_LENA; EXPECT_EQA;
1086 format.LeadingZero = 1; /* Always provide leading zero */
1087 STRINGSA(".5","0.5");
1088 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1089 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1090 EXPECT_LENA; EXPECT_EQA;
1092 format.NegativeOrder = NEG_PARENS;
1093 STRINGSA("-1","(1.0)");
1094 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1095 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1096 EXPECT_LENA; EXPECT_EQA;
1098 format.NegativeOrder = NEG_LEFT;
1099 STRINGSA("-1","-1.0");
1100 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1101 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1102 EXPECT_LENA; EXPECT_EQA;
1104 format.NegativeOrder = NEG_LEFT_SPACE;
1105 STRINGSA("-1","- 1.0");
1106 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1107 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1108 EXPECT_LENA; EXPECT_EQA;
1110 format.NegativeOrder = NEG_RIGHT;
1111 STRINGSA("-1","1.0-");
1112 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1113 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1114 EXPECT_LENA; EXPECT_EQA;
1116 format.NegativeOrder = NEG_RIGHT_SPACE;
1117 STRINGSA("-1","1.0 -");
1118 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1119 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1120 EXPECT_LENA; EXPECT_EQA;
1122 lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
1124 if (IsValidLocale(lcid, 0))
1126 STRINGSA("-12345","-12 345,00"); /* Try French formatting */
1127 Expected[3] = 160; /* Non breaking space */
1128 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1129 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1130 EXPECT_LENA; EXPECT_EQA;
1135 static void test_CompareStringA(void)
1137 int ret;
1138 LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
1140 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
1141 ok (ret== 1, "(Salut/Salute) Expected 1, got %d\n", ret);
1143 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
1144 ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
1146 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
1147 ok (ret== 3, "(Salut/hola) Expected 3, got %d\n", ret);
1149 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
1150 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
1152 lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
1154 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
1155 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
1157 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
1158 ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
1160 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
1161 ok (ret == 2, "(Salut/saLuT) Expected 2, got %d\n", ret);
1163 /* test for CompareStringA flags */
1164 SetLastError(0xdeadbeef);
1165 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0x8, "NULL", -1, "NULL", -1);
1166 ok(GetLastError() == ERROR_INVALID_FLAGS,
1167 "unexpected error code %d\n", GetLastError());
1168 ok(!ret, "CompareStringA must fail with invalid flag\n");
1170 SetLastError(0xdeadbeef);
1171 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, LOCALE_USE_CP_ACP, "NULL", -1, "NULL", -1);
1172 ok(GetLastError() == 0xdeadbeef, "unexpected error code %d\n", GetLastError());
1173 ok(ret == CSTR_EQUAL, "CompareStringA error: %d != CSTR_EQUAL\n", ret);
1174 /* end of test for CompareStringA flags */
1176 ret = lstrcmpA("", "");
1177 ok (ret == 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret);
1179 ret = lstrcmpA(NULL, NULL);
1180 ok (ret == 0 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, NULL) should return 0, got %d\n", ret);
1182 ret = lstrcmpA("", NULL);
1183 ok (ret == 1 || broken(ret == -2) /* win9x */, "lstrcmpA(\"\", NULL) should return 1, got %d\n", ret);
1185 ret = lstrcmpA(NULL, "");
1186 ok (ret == -1 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret);
1188 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"EndDialog",-1,"_Property",-1);
1189 ok( ret == 3, "EndDialog vs _Property ... expected 3, got %d\n", ret);
1191 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0070",-1,"_IEWWBrowserComp",-1);
1192 ok( ret == 3, "osp_vba.sreg0070 vs _IEWWBrowserComp ... expected 3, got %d\n", ret);
1194 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"r",-1,"\\",-1);
1195 ok( ret == 3, "r vs \\ ... expected 3, got %d\n", ret);
1197 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0031", -1, "OriginalDatabase", -1 );
1198 ok( ret == 3, "osp_vba.sreg0031 vs OriginalDatabase ... expected 3, got %d\n", ret);
1200 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1 );
1201 ok( ret == 3, "AAA vs aaa expected 3, got %d\n", ret);
1203 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1 );
1204 ok( ret == 1, "AAA vs aab expected 1, got %d\n", ret);
1206 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1 );
1207 ok( ret == 1, "AAA vs Aab expected 1, got %d\n", ret);
1209 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1 );
1210 ok( ret == 1, ".AAA vs Aab expected 1, got %d\n", ret);
1212 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1 );
1213 ok( ret == 1, ".AAA vs A.ab expected 1, got %d\n", ret);
1215 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1 );
1216 ok( ret == 1, "aa vs AB expected 1, got %d\n", ret);
1218 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1 );
1219 ok( ret == 1, "aa vs Aab expected 1, got %d\n", ret);
1221 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1 );
1222 ok( ret == 3, "aB vs Aab expected 3, got %d\n", ret);
1224 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1 );
1225 ok( ret == 1, "Ba vs bab expected 1, got %d\n", ret);
1227 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1 );
1228 ok( ret == 1, "{100}{83}{71}{71}{71} vs Global_DataAccess_JRO expected 1, got %d\n", ret);
1230 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1 );
1231 ok( ret == 3, "a vs { expected 3, got %d\n", ret);
1233 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1 );
1234 ok( ret == 3, "A vs { expected 3, got %d\n", ret);
1236 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1 );
1237 ok(ret == 1, "3.5/0 vs 4.0/-1 expected 1, got %d\n", ret);
1239 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1 );
1240 ok(ret == 1, "3.5 vs 4.0 expected 1, got %d\n", ret);
1242 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1 );
1243 ok(ret == 1, "3.520.4403.2 vs 4.0.2927.10 expected 1, got %d\n", ret);
1245 /* hyphen and apostrophe are treated differently depending on
1246 * whether SORT_STRINGSORT specified or not
1248 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1 );
1249 ok(ret == 3, "-o vs /m expected 3, got %d\n", ret);
1251 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1 );
1252 ok(ret == 1, "/m vs -o expected 1, got %d\n", ret);
1254 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1 );
1255 ok(ret == 1, "-o vs /m expected 1, got %d\n", ret);
1257 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1 );
1258 ok(ret == 3, "/m vs -o expected 3, got %d\n", ret);
1260 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1 );
1261 ok(ret == 3, "'o vs /m expected 3, got %d\n", ret);
1263 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1 );
1264 ok(ret == 1, "/m vs 'o expected 1, got %d\n", ret);
1266 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1 );
1267 ok(ret == 1, "'o vs /m expected 1, got %d\n", ret);
1269 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1 );
1270 ok(ret == 3, "/m vs 'o expected 3, got %d\n", ret);
1272 if (0) { /* this requires collation table patch to make it MS compatible */
1273 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
1274 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
1276 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
1277 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
1279 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
1280 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
1282 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
1283 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
1285 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
1286 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
1288 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
1289 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
1291 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
1292 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
1294 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
1295 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
1297 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
1298 ok(ret == 1, "`o vs -m expected 1, got %d\n", ret);
1300 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
1301 ok(ret == 3, "-m vs `o expected 3, got %d\n", ret);
1303 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
1304 ok(ret == 3, "`o vs -m expected 3, got %d\n", ret);
1306 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
1307 ok(ret == 1, "-m vs `o expected 1, got %d\n", ret);
1310 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9);
1311 ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0 expected 2, got %d\n", ret);
1313 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10);
1314 ok(ret == 1, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1, got %d\n", ret);
1316 /* WinXP handles embedded NULLs differently than earlier versions */
1317 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
1318 ok(ret == 1 || ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1 or 2, got %d\n", ret);
1320 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
1321 ok(ret == 1 || ret == 2, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected 1 or 2, got %d\n", ret);
1323 ret = CompareStringA(lcid, 0, "a\0b", -1, "a", -1);
1324 ok(ret == 2, "a vs a expected 2, got %d\n", ret);
1326 ret = CompareStringA(lcid, 0, "a\0b", 4, "a", 2);
1327 ok(ret == CSTR_EQUAL || /* win2k */
1328 ret == CSTR_GREATER_THAN,
1329 "a\\0b vs a expected CSTR_EQUAL or CSTR_GREATER_THAN, got %d\n", ret);
1331 ret = CompareStringA(lcid, 0, "\2", 2, "\1", 2);
1332 todo_wine ok(ret != 2, "\\2 vs \\1 expected unequal\n");
1334 ret = CompareStringA(lcid, NORM_IGNORECASE | LOCALE_USE_CP_ACP, "#", -1, ".", -1);
1335 todo_wine ok(ret == CSTR_LESS_THAN, "\"#\" vs \".\" expected CSTR_LESS_THAN, got %d\n", ret);
1337 ret = lstrcmpi("#", ".");
1338 todo_wine ok(ret == -1, "\"#\" vs \".\" expected -1, got %d\n", ret);
1341 static void test_LCMapStringA(void)
1343 int ret, ret2;
1344 char buf[256], buf2[256];
1345 static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
1346 static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
1347 static const char symbols_stripped[] = "justateststring1";
1349 SetLastError(0xdeadbeef);
1350 ret = LCMapStringA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP | LCMAP_LOWERCASE,
1351 lower_case, -1, buf, sizeof(buf));
1352 ok(ret == lstrlenA(lower_case) + 1,
1353 "ret %d, error %d, expected value %d\n",
1354 ret, GetLastError(), lstrlenA(lower_case) + 1);
1355 ok(!memcmp(buf, lower_case, ret), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1357 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1358 upper_case, -1, buf, sizeof(buf));
1359 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1360 ok(GetLastError() == ERROR_INVALID_FLAGS,
1361 "unexpected error code %d\n", GetLastError());
1363 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1364 upper_case, -1, buf, sizeof(buf));
1365 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1366 ok(GetLastError() == ERROR_INVALID_FLAGS,
1367 "unexpected error code %d\n", GetLastError());
1369 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1370 upper_case, -1, buf, sizeof(buf));
1371 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1372 ok(GetLastError() == ERROR_INVALID_FLAGS,
1373 "unexpected error code %d\n", GetLastError());
1375 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1376 upper_case, -1, buf, sizeof(buf));
1377 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1378 ok(GetLastError() == ERROR_INVALID_FLAGS,
1379 "unexpected error code %d\n", GetLastError());
1381 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1382 SetLastError(0xdeadbeef);
1383 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1384 upper_case, -1, buf, sizeof(buf));
1385 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1386 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1388 /* test LCMAP_LOWERCASE */
1389 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1390 upper_case, -1, buf, sizeof(buf));
1391 ok(ret == lstrlenA(upper_case) + 1,
1392 "ret %d, error %d, expected value %d\n",
1393 ret, GetLastError(), lstrlenA(upper_case) + 1);
1394 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1396 /* test LCMAP_UPPERCASE */
1397 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1398 lower_case, -1, buf, sizeof(buf));
1399 ok(ret == lstrlenA(lower_case) + 1,
1400 "ret %d, error %d, expected value %d\n",
1401 ret, GetLastError(), lstrlenA(lower_case) + 1);
1402 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1404 /* test buffer overflow */
1405 SetLastError(0xdeadbeef);
1406 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1407 lower_case, -1, buf, 4);
1408 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1409 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1411 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1412 lstrcpyA(buf, lower_case);
1413 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1414 buf, -1, buf, sizeof(buf));
1415 if (!ret) /* Win9x */
1416 trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1417 else
1419 ok(ret == lstrlenA(lower_case) + 1,
1420 "ret %d, error %d, expected value %d\n",
1421 ret, GetLastError(), lstrlenA(lower_case) + 1);
1422 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1424 lstrcpyA(buf, upper_case);
1425 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1426 buf, -1, buf, sizeof(buf));
1427 if (!ret) /* Win9x */
1428 trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1429 else
1431 ok(ret == lstrlenA(upper_case) + 1,
1432 "ret %d, error %d, expected value %d\n",
1433 ret, GetLastError(), lstrlenA(lower_case) + 1);
1434 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1437 /* otherwise src == dst should fail */
1438 SetLastError(0xdeadbeef);
1439 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1440 buf, 10, buf, sizeof(buf));
1441 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1442 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1443 "unexpected error code %d\n", GetLastError());
1444 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1446 /* test whether '\0' is always appended */
1447 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1448 upper_case, -1, buf, sizeof(buf));
1449 ok(ret, "LCMapStringA must succeed\n");
1450 ok(buf[ret-1] == 0, "LCMapStringA not null-terminated\n");
1451 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1452 upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1453 ok(ret2, "LCMapStringA must succeed\n");
1454 ok(buf2[ret2-1] == 0, "LCMapStringA not null-terminated\n" );
1455 ok(ret == ret2, "lengths of sort keys must be equal\n");
1456 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1458 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1459 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1460 upper_case, -1, buf, sizeof(buf));
1461 ok(ret, "LCMapStringA must succeed\n");
1462 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1463 lower_case, -1, buf2, sizeof(buf2));
1464 ok(ret2, "LCMapStringA must succeed\n");
1465 ok(ret == ret2, "lengths of sort keys must be equal\n");
1466 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1468 /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1469 results from plain LCMAP_SORTKEY on Vista */
1471 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1472 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1473 lower_case, -1, buf, sizeof(buf));
1474 ok(ret, "LCMapStringA must succeed\n");
1475 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1476 symbols_stripped, -1, buf2, sizeof(buf2));
1477 ok(ret2, "LCMapStringA must succeed\n");
1478 ok(ret == ret2, "lengths of sort keys must be equal\n");
1479 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1481 /* test NORM_IGNORENONSPACE */
1482 lstrcpyA(buf, "foo");
1483 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1484 lower_case, -1, buf, sizeof(buf));
1485 ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1486 lstrlenA(lower_case) + 1, ret);
1487 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1489 /* test NORM_IGNORESYMBOLS */
1490 lstrcpyA(buf, "foo");
1491 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1492 lower_case, -1, buf, sizeof(buf));
1493 ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1494 lstrlenA(symbols_stripped) + 1, ret);
1495 ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1497 /* test srclen = 0 */
1498 SetLastError(0xdeadbeef);
1499 ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1500 ok(!ret, "LCMapStringA should fail with srclen = 0\n");
1501 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1502 "unexpected error code %d\n", GetLastError());
1505 static void test_LCMapStringW(void)
1507 int ret, ret2;
1508 WCHAR buf[256], buf2[256];
1509 char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1510 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};
1511 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};
1512 static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
1513 static const WCHAR fooW[] = {'f','o','o',0};
1515 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1516 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1517 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1519 win_skip("LCMapStringW is not implemented\n");
1520 return;
1522 if (broken(ret))
1523 ok(lstrcmpW(buf, upper_case) == 0, "Expected upper case string\n");
1524 else
1526 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1527 ok(GetLastError() == ERROR_INVALID_FLAGS,
1528 "unexpected error code %d\n", GetLastError());
1531 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1532 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1533 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1534 ok(GetLastError() == ERROR_INVALID_FLAGS,
1535 "unexpected error code %d\n", GetLastError());
1537 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1538 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1539 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1540 ok(GetLastError() == ERROR_INVALID_FLAGS,
1541 "unexpected error code %d\n", GetLastError());
1543 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1544 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1545 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1546 ok(GetLastError() == ERROR_INVALID_FLAGS,
1547 "unexpected error code %d\n", GetLastError());
1549 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1550 SetLastError(0xdeadbeef);
1551 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1552 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1553 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1554 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1556 /* test LCMAP_LOWERCASE */
1557 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1558 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1559 ok(ret == lstrlenW(upper_case) + 1,
1560 "ret %d, error %d, expected value %d\n",
1561 ret, GetLastError(), lstrlenW(upper_case) + 1);
1562 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1564 /* test LCMAP_UPPERCASE */
1565 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1566 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1567 ok(ret == lstrlenW(lower_case) + 1,
1568 "ret %d, error %d, expected value %d\n",
1569 ret, GetLastError(), lstrlenW(lower_case) + 1);
1570 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1572 /* test buffer overflow */
1573 SetLastError(0xdeadbeef);
1574 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1575 lower_case, -1, buf, 4);
1576 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1577 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1579 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1580 lstrcpyW(buf, lower_case);
1581 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1582 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1583 ok(ret == lstrlenW(lower_case) + 1,
1584 "ret %d, error %d, expected value %d\n",
1585 ret, GetLastError(), lstrlenW(lower_case) + 1);
1586 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1588 lstrcpyW(buf, upper_case);
1589 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1590 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1591 ok(ret == lstrlenW(upper_case) + 1,
1592 "ret %d, error %d, expected value %d\n",
1593 ret, GetLastError(), lstrlenW(lower_case) + 1);
1594 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1596 /* otherwise src == dst should fail */
1597 SetLastError(0xdeadbeef);
1598 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1599 buf, 10, buf, sizeof(buf));
1600 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1601 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1602 "unexpected error code %d\n", GetLastError());
1603 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1605 /* test whether '\0' is always appended */
1606 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1607 upper_case, -1, buf, sizeof(buf));
1608 ok(ret, "LCMapStringW must succeed\n");
1609 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1610 upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1611 ok(ret, "LCMapStringW must succeed\n");
1612 ok(ret == ret2, "lengths of sort keys must be equal\n");
1613 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1615 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1616 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1617 upper_case, -1, buf, sizeof(buf));
1618 ok(ret, "LCMapStringW must succeed\n");
1619 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1620 lower_case, -1, buf2, sizeof(buf2));
1621 ok(ret2, "LCMapStringW must succeed\n");
1622 ok(ret == ret2, "lengths of sort keys must be equal\n");
1623 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1625 /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1626 results from plain LCMAP_SORTKEY on Vista */
1628 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1629 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1630 lower_case, -1, buf, sizeof(buf));
1631 ok(ret, "LCMapStringW must succeed\n");
1632 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1633 symbols_stripped, -1, buf2, sizeof(buf2));
1634 ok(ret2, "LCMapStringW must succeed\n");
1635 ok(ret == ret2, "lengths of sort keys must be equal\n");
1636 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1638 /* test NORM_IGNORENONSPACE */
1639 lstrcpyW(buf, fooW);
1640 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1641 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1642 ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1643 lstrlenW(lower_case) + 1, ret);
1644 ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1646 /* test NORM_IGNORESYMBOLS */
1647 lstrcpyW(buf, fooW);
1648 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1649 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1650 ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1651 lstrlenW(symbols_stripped) + 1, ret);
1652 ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1654 /* test srclen = 0 */
1655 SetLastError(0xdeadbeef);
1656 ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf)/sizeof(WCHAR));
1657 ok(!ret, "LCMapStringW should fail with srclen = 0\n");
1658 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1659 "unexpected error code %d\n", GetLastError());
1662 /* this requires collation table patch to make it MS compatible */
1663 static const char * const strings_sorted[] =
1665 "'",
1666 "-",
1667 "!",
1668 "\"",
1669 ".",
1670 ":",
1671 "\\",
1672 "_",
1673 "`",
1674 "{",
1675 "}",
1676 "+",
1677 "0",
1678 "1",
1679 "2",
1680 "3",
1681 "4",
1682 "5",
1683 "6",
1684 "7",
1685 "8",
1686 "9",
1687 "a",
1688 "A",
1689 "b",
1690 "B",
1691 "c",
1695 static const char * const strings[] =
1697 "C",
1698 "\"",
1699 "9",
1700 "'",
1701 "}",
1702 "-",
1703 "7",
1704 "+",
1705 "`",
1706 "1",
1707 "a",
1708 "5",
1709 "\\",
1710 "8",
1711 "B",
1712 "3",
1713 "_",
1714 "6",
1715 "{",
1716 "2",
1717 "c",
1718 "4",
1719 "!",
1720 "0",
1721 "A",
1722 ":",
1723 "b",
1727 static int compare_string1(const void *e1, const void *e2)
1729 const char *s1 = *(const char *const *)e1;
1730 const char *s2 = *(const char *const *)e2;
1732 return lstrcmpA(s1, s2);
1735 static int compare_string2(const void *e1, const void *e2)
1737 const char *s1 = *(const char *const *)e1;
1738 const char *s2 = *(const char *const *)e2;
1740 return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1743 static int compare_string3(const void *e1, const void *e2)
1745 const char *s1 = *(const char *const *)e1;
1746 const char *s2 = *(const char *const *)e2;
1747 char key1[256], key2[256];
1749 LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
1750 LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
1751 return strcmp(key1, key2);
1754 static void test_sorting(void)
1756 char buf[256];
1757 char **str_buf = (char **)buf;
1758 int i;
1760 assert(sizeof(buf) >= sizeof(strings));
1762 /* 1. sort using lstrcmpA */
1763 memcpy(buf, strings, sizeof(strings));
1764 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
1765 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1767 ok(!strcmp(strings_sorted[i], str_buf[i]),
1768 "qsort using lstrcmpA failed for element %d\n", i);
1770 /* 2. sort using CompareStringA */
1771 memcpy(buf, strings, sizeof(strings));
1772 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
1773 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1775 ok(!strcmp(strings_sorted[i], str_buf[i]),
1776 "qsort using CompareStringA failed for element %d\n", i);
1778 /* 3. sort using sort keys */
1779 memcpy(buf, strings, sizeof(strings));
1780 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
1781 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1783 ok(!strcmp(strings_sorted[i], str_buf[i]),
1784 "qsort using sort keys failed for element %d\n", i);
1788 static void test_FoldStringA(void)
1790 int ret, i, j;
1791 BOOL is_special;
1792 char src[256], dst[256];
1793 static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0' };
1794 static const char digits_dst[] = { '1','2','3','\0' };
1795 static const char composite_src[] =
1797 0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
1798 0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
1799 0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
1800 0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
1801 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
1802 0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
1803 0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
1804 0xfb,0xfc,0xfd,0xff,'\0'
1806 static const char composite_dst[] =
1808 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1809 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1810 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1811 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1812 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1813 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1814 0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
1815 0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
1816 0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
1817 0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
1818 0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
1819 0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
1820 0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
1821 0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
1822 0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1824 static const char composite_dst_alt[] =
1826 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1827 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1828 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1829 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1830 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1831 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1832 0x4f,0x7e,0x4f,0xa8,0xd8,0x55,0x60,0x55,
1833 0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,0x61,
1834 0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,0x61,
1835 0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,0x65,
1836 0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,0x69,
1837 0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,0x6f,
1838 0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,0x6f,
1839 0xa8,0xf8,0x75,0x60,0x75,0xb4,0x75,0x5e,
1840 0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1842 static const char ligatures_src[] =
1844 0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1846 static const char ligatures_dst[] =
1848 'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1850 static const struct special
1852 char src;
1853 char dst[4];
1854 } foldczone_special[] =
1856 /* src dst */
1857 { 0x85, { 0x2e, 0x2e, 0x2e, 0x00 } },
1858 { 0x98, { 0x20, 0x7e, 0x00 } },
1859 { 0x99, { 0x54, 0x4d, 0x00 } },
1860 { 0xa0, { 0x20, 0x00 } },
1861 { 0xa8, { 0x20, 0xa8, 0x00 } },
1862 { 0xaa, { 0x61, 0x00 } },
1863 { 0xaf, { 0x20, 0xaf, 0x00 } },
1864 { 0xb2, { 0x32, 0x00 } },
1865 { 0xb3, { 0x33, 0x00 } },
1866 { 0xb4, { 0x20, 0xb4, 0x00 } },
1867 { 0xb8, { 0x20, 0xb8, 0x00 } },
1868 { 0xb9, { 0x31, 0x00 } },
1869 { 0xba, { 0x6f, 0x00 } },
1870 { 0xbc, { 0x31, 0x2f, 0x34, 0x00 } },
1871 { 0xbd, { 0x31, 0x2f, 0x32, 0x00 } },
1872 { 0xbe, { 0x33, 0x2f, 0x34, 0x00 } },
1873 { 0x00 }
1876 if (!pFoldStringA)
1877 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1879 /* these tests are locale specific */
1880 if (GetACP() != 1252)
1882 trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1883 return;
1886 /* MAP_FOLDDIGITS */
1887 SetLastError(0);
1888 ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
1889 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1891 win_skip("FoldStringA is not implemented\n");
1892 return;
1894 ok(ret == 4, "Expected ret == 4, got %d, error %d\n", ret, GetLastError());
1895 ok(strcmp(dst, digits_dst) == 0,
1896 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
1897 for (i = 1; i < 256; i++)
1899 if (!strchr(digits_src, i))
1901 src[0] = i;
1902 src[1] = '\0';
1903 SetLastError(0);
1904 ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
1905 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1906 ok(dst[0] == src[0],
1907 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
1911 /* MAP_EXPAND_LIGATURES */
1912 SetLastError(0);
1913 ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1914 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1915 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1916 ok(ret == sizeof(ligatures_dst), "Got %d, error %d\n", ret, GetLastError());
1917 ok(strcmp(dst, ligatures_dst) == 0,
1918 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
1919 for (i = 1; i < 256; i++)
1921 if (!strchr(ligatures_src, i))
1923 src[0] = i;
1924 src[1] = '\0';
1925 SetLastError(0);
1926 ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1927 if (ret == 3)
1929 /* Vista */
1930 ok((i == 0xDC && lstrcmpA(dst, "UE") == 0) ||
1931 (i == 0xFC && lstrcmpA(dst, "ue") == 0),
1932 "Got %s for %d\n", dst, i);
1934 else
1936 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1937 ok(dst[0] == src[0],
1938 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
1944 /* MAP_COMPOSITE */
1945 SetLastError(0);
1946 ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
1947 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1948 ok(ret == 121 || ret == 119, "Expected 121 or 119, got %d\n", ret);
1949 ok(strcmp(dst, composite_dst) == 0 || strcmp(dst, composite_dst_alt) == 0,
1950 "MAP_COMPOSITE: Mismatch, got '%s'\n", dst);
1952 for (i = 1; i < 256; i++)
1954 if (!strchr(composite_src, i))
1956 src[0] = i;
1957 src[1] = '\0';
1958 SetLastError(0);
1959 ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
1960 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1961 ok(dst[0] == src[0],
1962 "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
1963 (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
1967 /* MAP_FOLDCZONE */
1968 for (i = 1; i < 256; i++)
1970 src[0] = i;
1971 src[1] = '\0';
1972 SetLastError(0);
1973 ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
1974 is_special = FALSE;
1975 for (j = 0; foldczone_special[j].src != 0 && ! is_special; j++)
1977 if (foldczone_special[j].src == src[0])
1979 ok(ret == 2 || ret == lstrlenA(foldczone_special[j].dst) + 1,
1980 "Expected ret == 2 or %d, got %d, error %d\n",
1981 lstrlenA(foldczone_special[j].dst) + 1, ret, GetLastError());
1982 ok(src[0] == dst[0] || lstrcmpA(foldczone_special[j].dst, dst) == 0,
1983 "MAP_FOLDCZONE: string mismatch for 0x%02x\n",
1984 (unsigned char)src[0]);
1985 is_special = TRUE;
1988 if (! is_special)
1990 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1991 ok(src[0] == dst[0],
1992 "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
1993 (unsigned char)src[0], (unsigned char)dst[0]);
1997 /* MAP_PRECOMPOSED */
1998 for (i = 1; i < 256; i++)
2000 src[0] = i;
2001 src[1] = '\0';
2002 SetLastError(0);
2003 ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
2004 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2005 ok(src[0] == dst[0],
2006 "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
2007 (unsigned char)src[0], (unsigned char)dst[0]);
2011 static void test_FoldStringW(void)
2013 int ret;
2014 unsigned int i, j;
2015 WCHAR src[256], dst[256], ch, prev_ch = 1;
2016 static const DWORD badFlags[] =
2019 MAP_PRECOMPOSED|MAP_COMPOSITE,
2020 MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
2021 MAP_COMPOSITE|MAP_EXPAND_LIGATURES
2023 /* Ranges of digits 0-9 : Must be sorted! */
2024 static const WCHAR digitRanges[] =
2026 0x0030, /* '0'-'9' */
2027 0x0660, /* Eastern Arabic */
2028 0x06F0, /* Arabic - Hindu */
2029 0x0966, /* Devengari */
2030 0x09E6, /* Bengalii */
2031 0x0A66, /* Gurmukhi */
2032 0x0AE6, /* Gujarati */
2033 0x0B66, /* Oriya */
2034 0x0BE6, /* Tamil - No 0 */
2035 0x0C66, /* Telugu */
2036 0x0CE6, /* Kannada */
2037 0x0D66, /* Maylayalam */
2038 0x0E50, /* Thai */
2039 0x0ED0, /* Laos */
2040 0x0F29, /* Tibet - 0 is out of sequence */
2041 0x2070, /* Superscript - 1, 2, 3 are out of sequence */
2042 0x2080, /* Subscript */
2043 0x245F, /* Circled - 0 is out of sequence */
2044 0x2473, /* Bracketed */
2045 0x2487, /* Full stop */
2046 0x2775, /* Inverted circled - No 0 */
2047 0x277F, /* Patterned circled - No 0 */
2048 0x2789, /* Inverted Patterned circled - No 0 */
2049 0x3020, /* Hangzhou */
2050 0xff10, /* Pliene chasse (?) */
2051 0xffff /* Terminator */
2053 /* Digits which are represented, but out of sequence */
2054 static const WCHAR outOfSequenceDigits[] =
2056 0xB9, /* Superscript 1 */
2057 0xB2, /* Superscript 2 */
2058 0xB3, /* Superscript 3 */
2059 0x0F33, /* Tibetan half zero */
2060 0x24EA, /* Circled 0 */
2061 0x3007, /* Ideographic number zero */
2062 '\0' /* Terminator */
2064 /* Digits in digitRanges for which no representation is available */
2065 static const WCHAR noDigitAvailable[] =
2067 0x0BE6, /* No Tamil 0 */
2068 0x0F29, /* No Tibetan half zero (out of sequence) */
2069 0x2473, /* No Bracketed 0 */
2070 0x2487, /* No 0 Full stop */
2071 0x2775, /* No inverted circled 0 */
2072 0x277F, /* No patterned circled */
2073 0x2789, /* No inverted Patterned circled */
2074 0x3020, /* No Hangzhou 0 */
2075 '\0' /* Terminator */
2077 static const WCHAR foldczone_src[] =
2079 'W', 'i', 'n', 'e', 0x0348, 0x0551, 0x1323, 0x280d,
2080 0xff37, 0xff49, 0xff4e, 0xff45, '\0'
2082 static const WCHAR foldczone_dst[] =
2084 'W','i','n','e',0x0348,0x0551,0x1323,0x280d,'W','i','n','e','\0'
2086 static const WCHAR ligatures_src[] =
2088 'W', 'i', 'n', 'e', 0x03a6, 0x03b9, 0x03bd, 0x03b5,
2089 0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
2090 0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
2091 0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
2092 0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
2093 0xfb04, 0xfb05, 0xfb06, '\0'
2095 static const WCHAR ligatures_dst[] =
2097 'W','i','n','e',0x03a6,0x03b9,0x03bd,0x03b5,
2098 'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
2099 'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
2100 'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
2101 0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
2102 'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
2105 if (!pFoldStringW)
2107 win_skip("FoldStringW is not available\n");
2108 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
2111 /* Invalid flag combinations */
2112 for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
2114 src[0] = dst[0] = '\0';
2115 SetLastError(0);
2116 ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
2117 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
2119 win_skip("FoldStringW is not implemented\n");
2120 return;
2122 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
2123 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2126 /* src & dst cannot be the same */
2127 SetLastError(0);
2128 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
2129 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2130 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2132 /* src can't be NULL */
2133 SetLastError(0);
2134 ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
2135 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2136 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2138 /* srclen can't be 0 */
2139 SetLastError(0);
2140 ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
2141 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2142 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2144 /* dstlen can't be < 0 */
2145 SetLastError(0);
2146 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
2147 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2148 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2150 /* Ret includes terminating NUL which is appended if srclen = -1 */
2151 SetLastError(0);
2152 src[0] = 'A';
2153 src[1] = '\0';
2154 dst[0] = '\0';
2155 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
2156 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2157 ok(dst[0] == 'A' && dst[1] == '\0',
2158 "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%d\n",
2159 'A', '\0', ret, dst[0], dst[1], GetLastError());
2161 /* If size is given, result is not NUL terminated */
2162 SetLastError(0);
2163 src[0] = 'A';
2164 src[1] = 'A';
2165 dst[0] = 'X';
2166 dst[1] = 'X';
2167 ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
2168 ok(ret == 1, "Expected ret == 1, got %d, error %d\n", ret, GetLastError());
2169 ok(dst[0] == 'A' && dst[1] == 'X',
2170 "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%d\n",
2171 'A','X', ret, dst[0], dst[1], GetLastError());
2173 /* MAP_FOLDDIGITS */
2174 for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
2176 /* Check everything before this range */
2177 for (ch = prev_ch; ch < digitRanges[j]; ch++)
2179 SetLastError(0);
2180 src[0] = ch;
2181 src[1] = dst[0] = '\0';
2182 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2183 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2185 ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
2186 /* Wine (correctly) maps all Unicode 4.0+ digits */
2187 isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF ||
2188 (ch >= 0x1369 && ch <= 0x1371),
2189 "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
2192 if (digitRanges[j] == 0xffff)
2193 break; /* Finished the whole code point space */
2195 for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
2197 WCHAR c;
2199 /* Map out of sequence characters */
2200 if (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
2201 else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
2202 else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
2203 else if (ch == 0x245F) c = 0x24EA; /* Circled 0 */
2204 else c = ch;
2205 SetLastError(0);
2206 src[0] = c;
2207 src[1] = dst[0] = '\0';
2208 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2209 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2211 ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
2212 broken( dst[0] == ch ) || /* old Windows versions don't have all mappings */
2213 (digitRanges[j] == 0x3020 && dst[0] == ch) || /* Hangzhou not present in all Windows versions */
2214 (digitRanges[j] == 0x0F29 && dst[0] == ch) || /* Tibetan not present in all Windows versions */
2215 strchrW(noDigitAvailable, c),
2216 "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
2217 ch, '0' + digitRanges[j] - ch, dst[0]);
2219 prev_ch = ch;
2222 /* MAP_FOLDCZONE */
2223 SetLastError(0);
2224 ret = pFoldStringW(MAP_FOLDCZONE, foldczone_src, -1, dst, 256);
2225 ok(ret == sizeof(foldczone_dst)/sizeof(foldczone_dst[0]),
2226 "Got %d, error %d\n", ret, GetLastError());
2227 ok(!memcmp(dst, foldczone_dst, sizeof(foldczone_dst)),
2228 "MAP_FOLDCZONE: Expanded incorrectly\n");
2230 /* MAP_EXPAND_LIGATURES */
2231 SetLastError(0);
2232 ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
2233 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
2234 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
2235 ok(ret == sizeof(ligatures_dst)/sizeof(ligatures_dst[0]),
2236 "Got %d, error %d\n", ret, GetLastError());
2237 ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
2238 "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
2241 /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
2246 #define LCID_OK(l) \
2247 ok(lcid == l, "Expected lcid = %08x, got %08x\n", l, lcid)
2248 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
2249 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
2250 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
2251 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
2253 static void test_ConvertDefaultLocale(void)
2255 LCID lcid;
2257 /* Doesn't change lcid, even if non default sublang/sort used */
2258 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_US, SORT_DEFAULT);
2259 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_UK, SORT_DEFAULT);
2260 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT);
2261 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE);
2263 /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
2264 LCID_RES(MKLCID(LANG_ENGLISH, SUBLANG_NEUTRAL, SORT_DEFAULT),
2265 MKLCID(LANG_ENGLISH, SUBLANG_DEFAULT, SORT_DEFAULT));
2266 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
2267 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
2269 /* Invariant language is not treated specially */
2270 TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
2272 /* User/system default languages alone are not mapped */
2273 TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
2274 TEST_LCIDLANG(LANG_USER_DEFAULT, SORT_JAPANESE_UNICODE);
2276 /* Default lcids */
2277 LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
2278 LCID_RES(LOCALE_USER_DEFAULT, GetUserDefaultLCID());
2279 LCID_RES(LOCALE_NEUTRAL, GetUserDefaultLCID());
2282 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
2283 DWORD dwFlags, LONG_PTR lParam)
2285 trace("%08x, %s, %s, %08x, %08lx\n",
2286 lgrpid, lpszNum, lpszName, dwFlags, lParam);
2288 ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
2289 "Enumerated grp %d not valid (flags %d)\n", lgrpid, dwFlags);
2291 /* If lParam is one, we are calling with flags defaulted from 0 */
2292 ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
2293 "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %d\n", dwFlags);
2295 return TRUE;
2298 static void test_EnumSystemLanguageGroupsA(void)
2300 BOOL ret;
2302 if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
2304 win_skip("EnumSystemLanguageGroupsA and/or IsValidLanguageGroup are not available\n");
2305 return;
2308 /* No enumeration proc */
2309 SetLastError(0);
2310 ret = pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
2311 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2313 win_skip("EnumSystemLanguageGroupsA is not implemented\n");
2314 return;
2316 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2317 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2319 /* Invalid flags */
2320 SetLastError(0);
2321 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
2322 ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2324 /* No flags - defaults to LGRPID_INSTALLED */
2325 SetLastError(0xdeadbeef);
2326 pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
2327 ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
2329 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
2330 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
2334 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
2335 LONG_PTR lParam)
2337 trace("%08x, %08x, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
2339 /* invalid locale enumerated on some platforms */
2340 if (lcid == 0)
2341 return TRUE;
2343 ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
2344 "Enumerated grp %d not valid\n", lgrpid);
2345 ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
2346 "Enumerated grp locale %d not valid\n", lcid);
2347 return TRUE;
2350 static void test_EnumLanguageGroupLocalesA(void)
2352 BOOL ret;
2354 if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
2356 win_skip("EnumLanguageGroupLocalesA and/or IsValidLanguageGroup are not available\n");
2357 return;
2360 /* No enumeration proc */
2361 SetLastError(0);
2362 ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
2363 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2365 win_skip("EnumLanguageGroupLocalesA is not implemented\n");
2366 return;
2368 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2369 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2371 /* lgrpid too small */
2372 SetLastError(0);
2373 ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
2374 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2375 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2377 /* lgrpid too big */
2378 SetLastError(0);
2379 ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
2380 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2381 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2383 /* dwFlags is reserved */
2384 SetLastError(0);
2385 ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
2386 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2387 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2389 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2392 static void test_SetLocaleInfoA(void)
2394 BOOL bRet;
2395 LCID lcid = GetUserDefaultLCID();
2397 /* Null data */
2398 SetLastError(0);
2399 bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2400 ok( !bRet && GetLastError() == ERROR_INVALID_PARAMETER,
2401 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2403 /* IDATE */
2404 SetLastError(0);
2405 bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
2406 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2407 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2409 /* ILDATE */
2410 SetLastError(0);
2411 bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
2412 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2413 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2416 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2418 trace("%s %08lx\n", value, lParam);
2419 return(TRUE);
2422 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2424 ok(!enumCount, "callback called again unexpected\n");
2425 enumCount++;
2426 return(FALSE);
2429 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2431 ok(0,"callback called unexpected\n");
2432 return(FALSE);
2435 static void test_EnumUILanguageA(void)
2437 BOOL ret;
2438 if (!pEnumUILanguagesA) {
2439 win_skip("EnumUILanguagesA is not available on Win9x or NT4\n");
2440 return;
2443 SetLastError(ERROR_SUCCESS);
2444 ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2445 if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2447 win_skip("EnumUILanguagesA is not implemented\n");
2448 return;
2450 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2452 enumCount = 0;
2453 SetLastError(ERROR_SUCCESS);
2454 ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2455 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2457 SetLastError(ERROR_SUCCESS);
2458 ret = pEnumUILanguagesA(NULL, 0, 0);
2459 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2460 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2461 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2463 SetLastError(ERROR_SUCCESS);
2464 ret = pEnumUILanguagesA(luilocale_proc3A, 0x5a5a5a5a, 0);
2465 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2466 ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2468 SetLastError(ERROR_SUCCESS);
2469 ret = pEnumUILanguagesA(NULL, 0x5a5a5a5a, 0);
2470 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2471 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2472 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2475 static char date_fmt_buf[1024];
2477 static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
2479 lstrcatA(date_fmt_buf, fmt);
2480 lstrcatA(date_fmt_buf, "\n");
2481 return TRUE;
2484 static void test_EnumDateFormatsA(void)
2486 char *p, buf[256];
2487 BOOL ret;
2488 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2490 trace("EnumDateFormatsA 0\n");
2491 date_fmt_buf[0] = 0;
2492 SetLastError(0xdeadbeef);
2493 ret = EnumDateFormatsA(enum_datetime_procA, lcid, 0);
2494 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2496 win_skip("0 for dwFlags is not supported\n");
2498 else
2500 ok(ret, "EnumDateFormatsA(0) error %d\n", GetLastError());
2501 trace("%s\n", date_fmt_buf);
2502 /* test the 1st enumerated format */
2503 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2504 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2505 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2506 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2509 trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n");
2510 date_fmt_buf[0] = 0;
2511 SetLastError(0xdeadbeef);
2512 ret = EnumDateFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2513 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2515 win_skip("LOCALE_USE_CP_ACP is not supported\n");
2517 else
2519 ok(ret, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2520 trace("%s\n", date_fmt_buf);
2521 /* test the 1st enumerated format */
2522 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2523 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2524 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2525 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2528 trace("EnumDateFormatsA DATE_SHORTDATE\n");
2529 date_fmt_buf[0] = 0;
2530 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_SHORTDATE);
2531 ok(ret, "EnumDateFormatsA(DATE_SHORTDATE) error %d\n", GetLastError());
2532 trace("%s\n", date_fmt_buf);
2533 /* test the 1st enumerated format */
2534 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2535 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2536 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2537 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2539 trace("EnumDateFormatsA DATE_LONGDATE\n");
2540 date_fmt_buf[0] = 0;
2541 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_LONGDATE);
2542 ok(ret, "EnumDateFormatsA(DATE_LONGDATE) error %d\n", GetLastError());
2543 trace("%s\n", date_fmt_buf);
2544 /* test the 1st enumerated format */
2545 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2546 ret = GetLocaleInfoA(lcid, LOCALE_SLONGDATE, buf, sizeof(buf));
2547 ok(ret, "GetLocaleInfoA(LOCALE_SLONGDATE) error %d\n", GetLastError());
2548 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2550 trace("EnumDateFormatsA DATE_YEARMONTH\n");
2551 date_fmt_buf[0] = 0;
2552 SetLastError(0xdeadbeef);
2553 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_YEARMONTH);
2554 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2556 skip("DATE_YEARMONTH is only present on W2K and later\n");
2557 return;
2559 ok(ret, "EnumDateFormatsA(DATE_YEARMONTH) error %d\n", GetLastError());
2560 trace("%s\n", date_fmt_buf);
2561 /* test the 1st enumerated format */
2562 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2563 ret = GetLocaleInfoA(lcid, LOCALE_SYEARMONTH, buf, sizeof(buf));
2564 ok(ret, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %d\n", GetLastError());
2565 ok(!lstrcmpA(date_fmt_buf, buf) || broken(!buf[0]) /* win9x */,
2566 "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2569 static void test_EnumTimeFormatsA(void)
2571 char *p, buf[256];
2572 BOOL ret;
2573 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2575 trace("EnumTimeFormatsA 0\n");
2576 date_fmt_buf[0] = 0;
2577 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, 0);
2578 ok(ret, "EnumTimeFormatsA(0) error %d\n", GetLastError());
2579 trace("%s\n", date_fmt_buf);
2580 /* test the 1st enumerated format */
2581 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2582 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2583 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2584 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2586 trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n");
2587 date_fmt_buf[0] = 0;
2588 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2589 ok(ret, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2590 trace("%s\n", date_fmt_buf);
2591 /* test the 1st enumerated format */
2592 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2593 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2594 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2595 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2598 static void test_GetCPInfo(void)
2600 BOOL ret;
2601 CPINFO cpinfo;
2603 SetLastError(0xdeadbeef);
2604 ret = GetCPInfo(CP_SYMBOL, &cpinfo);
2605 ok(!ret, "GetCPInfo(CP_SYMBOL) should fail\n");
2606 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2607 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2609 SetLastError(0xdeadbeef);
2610 ret = GetCPInfo(CP_UTF7, &cpinfo);
2611 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2613 skip("Codepage CP_UTF7 is not installed/available\n");
2615 else
2617 ok(ret, "GetCPInfo(CP_UTF7) error %u\n", GetLastError());
2618 ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2619 ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2620 ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2621 ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2622 ok(cpinfo.MaxCharSize == 5, "expected 5, got 0x%x\n", cpinfo.MaxCharSize);
2625 SetLastError(0xdeadbeef);
2626 ret = GetCPInfo(CP_UTF8, &cpinfo);
2627 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2629 skip("Codepage CP_UTF8 is not installed/available\n");
2631 else
2633 ok(ret, "GetCPInfo(CP_UTF8) error %u\n", GetLastError());
2634 ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2635 ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2636 ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2637 ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2638 ok(cpinfo.MaxCharSize == 4 || broken(cpinfo.MaxCharSize == 3) /* win9x */,
2639 "expected 4, got %u\n", cpinfo.MaxCharSize);
2643 START_TEST(locale)
2645 InitFunctionPointers();
2647 test_EnumTimeFormatsA();
2648 test_EnumDateFormatsA();
2649 test_GetLocaleInfoA();
2650 test_GetLocaleInfoW();
2651 test_GetTimeFormatA();
2652 test_GetDateFormatA();
2653 test_GetDateFormatW();
2654 test_GetCurrencyFormatA(); /* Also tests the W version */
2655 test_GetNumberFormatA(); /* Also tests the W version */
2656 test_CompareStringA();
2657 test_LCMapStringA();
2658 test_LCMapStringW();
2659 test_FoldStringA();
2660 test_FoldStringW();
2661 test_ConvertDefaultLocale();
2662 test_EnumSystemLanguageGroupsA();
2663 test_EnumLanguageGroupLocalesA();
2664 test_SetLocaleInfoA();
2665 test_EnumUILanguageA();
2666 test_GetCPInfo();
2667 /* this requires collation table patch to make it MS compatible */
2668 if (0) test_sorting();