wordpad: Remove untranslated resources from the Turkish translation.
[wine/testsucceed.git] / dlls / kernel32 / tests / locale.c
blobf37d503da6399f67300386e0ebbceedfae396833
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 Broken[BUFFER_SIZE];
473 char short_day[10], month[10], genitive_month[10];
475 memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
476 STRINGSA("ddd',' MMM dd yy","");
477 SetLastError(0xdeadbeef);
478 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
479 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
480 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
482 curtime.wYear = 2002;
483 curtime.wMonth = 5;
484 curtime.wDay = 4;
485 curtime.wDayOfWeek = 3;
486 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
487 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
488 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
489 EXPECT_LENA; EXPECT_EQA;
491 /* Same as above but with LOCALE_NOUSEROVERRIDE */
492 STRINGSA("ddd',' MMM dd yy",""); /* Simple case */
493 SetLastError(0xdeadbeef);
494 ret = GetDateFormatA(lcid, NUO, &curtime, input, buffer, COUNTOF(buffer));
495 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
496 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
497 EXPECT_EQA;
499 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
500 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
501 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
502 EXPECT_LENA; EXPECT_EQA;
504 curtime.wHour = 36; /* Invalid */
505 STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
506 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
507 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
508 EXPECT_LENA; EXPECT_EQA;
510 STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
511 ret = GetDateFormatA(lcid, 0, &curtime, input, NULL, 0);
512 ok(ret == 16, "Expected ret == 16, got %d, error %d\n", ret, GetLastError());
513 EXPECT_EQA;
515 STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
516 SetLastError(0xdeadbeef);
517 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, 2);
518 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
519 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
521 STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
522 ret = GetDateFormat(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
523 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
524 if (strncmp(buffer, Expected, strlen(Expected)) && strncmp(buffer, "5/4/02", strlen(Expected)) != 0)
525 ok (0, "Expected '%s' or '5/4/02', got '%s'\n", Expected, buffer);
527 STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
528 ret = GetDateFormat(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
529 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
530 EXPECT_LENA; EXPECT_EQA;
532 /* test for expected DATE_YEARMONTH behavior with null format */
533 /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
534 STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
535 SetLastError(0xdeadbeef);
536 ret = GetDateFormat(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
537 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
538 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
539 EXPECT_EQA;
541 /* Test that using invalid DATE_* flags results in the correct error */
542 /* and return values */
543 STRINGSA("m/d/y", ""); /* Invalid flags */
544 SetLastError(0xdeadbeef);
545 ret = GetDateFormat(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
546 &curtime, input, buffer, COUNTOF(buffer));
547 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
548 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
550 ret = GetDateFormat(lcid_ru, 0, &curtime, "ddMMMM", buffer, COUNTOF(buffer));
551 if (!ret)
553 win_skip("LANG_RUSSIAN locale data unavailable\n");
554 return;
557 /* month part should be in genitive form */
558 strcpy(genitive_month, buffer + 2);
559 ret = GetDateFormat(lcid_ru, 0, &curtime, "MMMM", buffer, COUNTOF(buffer));
560 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
561 strcpy(month, buffer);
562 ok(strcmp(genitive_month, month) != 0, "Expected different month forms\n");
564 ret = GetDateFormat(lcid_ru, 0, &curtime, "ddd", buffer, COUNTOF(buffer));
565 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
566 strcpy(short_day, buffer);
568 STRINGSA("dd MMMMddd dd", "");
569 sprintf(Expected, "04 %s%s 04", genitive_month, short_day);
570 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
571 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
572 EXPECT_EQA;
574 STRINGSA("MMMMddd dd", "");
575 sprintf(Expected, "%s%s 04", month, short_day);
576 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
577 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
578 EXPECT_EQA;
580 STRINGSA("MMMMddd", "");
581 sprintf(Expected, "%s%s", month, short_day);
582 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
583 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
584 EXPECT_EQA;
586 STRINGSA("MMMMdd", "");
587 sprintf(Expected, "%s04", genitive_month);
588 sprintf(Broken, "%s04", month);
589 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
590 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
591 ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
592 broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
593 "Expected '%s', got '%s'\n", Expected, buffer);
595 STRINGSA("MMMMdd ddd", "");
596 sprintf(Expected, "%s04 %s", genitive_month, short_day);
597 sprintf(Broken, "%s04 %s", month, short_day);
598 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
599 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
600 ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
601 broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
602 "Expected '%s', got '%s'\n", Expected, buffer);
604 STRINGSA("dd dddMMMM", "");
605 sprintf(Expected, "04 %s%s", short_day, month);
606 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
607 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
608 EXPECT_EQA;
610 STRINGSA("dd dddMMMM ddd MMMMdd", "");
611 sprintf(Expected, "04 %s%s %s %s04", short_day, month, short_day, genitive_month);
612 sprintf(Broken, "04 %s%s %s %s04", short_day, month, short_day, month);
613 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
614 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
615 ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
616 broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
617 "Expected '%s', got '%s'\n", Expected, buffer);
619 /* with literal part */
620 STRINGSA("ddd',' MMMM dd", "");
621 sprintf(Expected, "%s, %s 04", short_day, genitive_month);
622 sprintf(Broken, "%s, %s 04", short_day, month);
623 ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
624 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
625 ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
626 broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
627 "Expected '%s', got '%s'\n", Expected, buffer);
630 static void test_GetDateFormatW(void)
632 int ret;
633 SYSTEMTIME curtime;
634 WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
635 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
637 STRINGSW("",""); /* If flags is not zero then format must be NULL */
638 ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL,
639 input, buffer, COUNTOF(buffer));
640 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
642 win_skip("GetDateFormatW is not implemented\n");
643 return;
645 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
646 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
647 EXPECT_EQW;
649 STRINGSW("",""); /* NULL buffer, len > 0 */
650 SetLastError(0xdeadbeef);
651 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
652 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
653 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
655 STRINGSW("",""); /* NULL buffer, len == 0 */
656 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
657 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
658 EXPECT_LENW; EXPECT_EQW;
660 curtime.wYear = 2002;
661 curtime.wMonth = 10;
662 curtime.wDay = 23;
663 curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
664 curtime.wHour = 65432; /* Invalid */
665 curtime.wMinute = 34512; /* Invalid */
666 curtime.wSecond = 65535; /* Invalid */
667 curtime.wMilliseconds = 12345;
668 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
669 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
670 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
671 EXPECT_LENW; EXPECT_EQW;
673 /* Limit tests */
675 curtime.wYear = 1601;
676 curtime.wMonth = 1;
677 curtime.wDay = 1;
678 curtime.wDayOfWeek = 0; /* Irrelevant */
679 curtime.wHour = 0;
680 curtime.wMinute = 0;
681 curtime.wSecond = 0;
682 curtime.wMilliseconds = 0;
683 STRINGSW("dddd d MMMM yyyy","Monday 1 January 1601");
684 SetLastError(0xdeadbeef);
685 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
686 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
687 EXPECT_LENW; EXPECT_EQW;
689 curtime.wYear = 1600;
690 curtime.wMonth = 12;
691 curtime.wDay = 31;
692 curtime.wDayOfWeek = 0; /* Irrelevant */
693 curtime.wHour = 23;
694 curtime.wMinute = 59;
695 curtime.wSecond = 59;
696 curtime.wMilliseconds = 999;
697 STRINGSW("dddd d MMMM yyyy","Friday 31 December 1600");
698 SetLastError(0xdeadbeef);
699 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
700 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
701 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
705 #define CY_POS_LEFT 0
706 #define CY_POS_RIGHT 1
707 #define CY_POS_LEFT_SPACE 2
708 #define CY_POS_RIGHT_SPACE 3
710 static void test_GetCurrencyFormatA(void)
712 static char szDot[] = { '.', '\0' };
713 static char szComma[] = { ',', '\0' };
714 static char szDollar[] = { '$', '\0' };
715 int ret;
716 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
717 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
718 CURRENCYFMTA format;
720 memset(&format, 0, sizeof(format));
722 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
723 SetLastError(0xdeadbeef);
724 ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
725 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
726 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
728 STRINGSA("23,53",""); /* Invalid character --> Error */
729 SetLastError(0xdeadbeef);
730 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
731 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
732 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
734 STRINGSA("--",""); /* Double '-' --> Error */
735 SetLastError(0xdeadbeef);
736 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
737 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
738 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
740 STRINGSA("0-",""); /* Trailing '-' --> Error */
741 SetLastError(0xdeadbeef);
742 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
743 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
744 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
746 STRINGSA("0..",""); /* Double '.' --> Error */
747 SetLastError(0xdeadbeef);
748 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
749 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
750 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
752 STRINGSA(" 0.1",""); /* Leading space --> Error */
753 SetLastError(0xdeadbeef);
754 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
755 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
756 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
758 STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
759 SetLastError(0xdeadbeef);
760 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, 2);
761 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
762 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
764 STRINGSA("2353",""); /* Format and flags given --> Error */
765 SetLastError(0xdeadbeef);
766 ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
767 ok( !ret, "Expected ret == 0, got %d\n", ret);
768 ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
769 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
771 STRINGSA("2353",""); /* Invalid format --> Error */
772 SetLastError(0xdeadbeef);
773 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
774 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
775 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
777 STRINGSA("2353","$2,353.00"); /* Valid number */
778 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
779 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
780 EXPECT_LENA; EXPECT_EQA;
782 STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
783 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
784 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
785 EXPECT_LENA; EXPECT_EQA;
787 STRINGSA("2353.1","$2,353.10"); /* Valid real number */
788 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
789 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
790 EXPECT_LENA; EXPECT_EQA;
792 STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
793 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
794 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
795 EXPECT_LENA; EXPECT_EQA;
797 STRINGSA("2353.119","$2,353.12"); /* Too many DP --> Rounded */
798 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
799 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
800 EXPECT_LENA; EXPECT_EQA;
802 format.NumDigits = 0; /* No decimal separator */
803 format.LeadingZero = 0;
804 format.Grouping = 0; /* No grouping char */
805 format.NegativeOrder = 0;
806 format.PositiveOrder = CY_POS_LEFT;
807 format.lpDecimalSep = szDot;
808 format.lpThousandSep = szComma;
809 format.lpCurrencySymbol = szDollar;
811 STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
812 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
813 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
814 EXPECT_LENA; EXPECT_EQA;
816 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
817 STRINGSA("2353","$2353.0");
818 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
819 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
820 EXPECT_LENA; EXPECT_EQA;
822 format.Grouping = 2; /* Group by 100's */
823 STRINGSA("2353","$23,53.0");
824 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
825 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
826 EXPECT_LENA; EXPECT_EQA;
828 STRINGSA("235","$235.0"); /* Grouping of a positive number */
829 format.Grouping = 3;
830 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
831 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
832 EXPECT_LENA; EXPECT_EQA;
834 STRINGSA("-235","$-235.0"); /* Grouping of a negative number */
835 format.NegativeOrder = 2;
836 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
837 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
838 EXPECT_LENA; EXPECT_EQA;
840 format.LeadingZero = 1; /* Always provide leading zero */
841 STRINGSA(".5","$0.5");
842 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
843 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
844 EXPECT_LENA; EXPECT_EQA;
846 format.PositiveOrder = CY_POS_RIGHT;
847 STRINGSA("1","1.0$");
848 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
849 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
850 EXPECT_LENA; EXPECT_EQA;
852 format.PositiveOrder = CY_POS_LEFT_SPACE;
853 STRINGSA("1","$ 1.0");
854 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
855 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
856 EXPECT_LENA; EXPECT_EQA;
858 format.PositiveOrder = CY_POS_RIGHT_SPACE;
859 STRINGSA("1","1.0 $");
860 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
861 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
862 EXPECT_LENA; EXPECT_EQA;
864 format.NegativeOrder = 0;
865 STRINGSA("-1","($1.0)");
866 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
867 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
868 EXPECT_LENA; EXPECT_EQA;
870 format.NegativeOrder = 1;
871 STRINGSA("-1","-$1.0");
872 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
873 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
874 EXPECT_LENA; EXPECT_EQA;
876 format.NegativeOrder = 2;
877 STRINGSA("-1","$-1.0");
878 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
879 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
880 EXPECT_LENA; EXPECT_EQA;
882 format.NegativeOrder = 3;
883 STRINGSA("-1","$1.0-");
884 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
885 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
886 EXPECT_LENA; EXPECT_EQA;
888 format.NegativeOrder = 4;
889 STRINGSA("-1","(1.0$)");
890 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
891 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
892 EXPECT_LENA; EXPECT_EQA;
894 format.NegativeOrder = 5;
895 STRINGSA("-1","-1.0$");
896 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
897 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
898 EXPECT_LENA; EXPECT_EQA;
900 format.NegativeOrder = 6;
901 STRINGSA("-1","1.0-$");
902 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
903 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
904 EXPECT_LENA; EXPECT_EQA;
906 format.NegativeOrder = 7;
907 STRINGSA("-1","1.0$-");
908 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
909 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
910 EXPECT_LENA; EXPECT_EQA;
912 format.NegativeOrder = 8;
913 STRINGSA("-1","-1.0 $");
914 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
915 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
916 EXPECT_LENA; EXPECT_EQA;
918 format.NegativeOrder = 9;
919 STRINGSA("-1","-$ 1.0");
920 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
921 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
922 EXPECT_LENA; EXPECT_EQA;
924 format.NegativeOrder = 10;
925 STRINGSA("-1","1.0 $-");
926 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
927 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
928 EXPECT_LENA; EXPECT_EQA;
930 format.NegativeOrder = 11;
931 STRINGSA("-1","$ 1.0-");
932 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
933 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
934 EXPECT_LENA; EXPECT_EQA;
936 format.NegativeOrder = 12;
937 STRINGSA("-1","$ -1.0");
938 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
939 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
940 EXPECT_LENA; EXPECT_EQA;
942 format.NegativeOrder = 13;
943 STRINGSA("-1","1.0- $");
944 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
945 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
946 EXPECT_LENA; EXPECT_EQA;
948 format.NegativeOrder = 14;
949 STRINGSA("-1","($ 1.0)");
950 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
951 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
952 EXPECT_LENA; EXPECT_EQA;
954 format.NegativeOrder = 15;
955 STRINGSA("-1","(1.0 $)");
956 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
957 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
958 EXPECT_LENA; EXPECT_EQA;
961 #define NEG_PARENS 0 /* "(1.1)" */
962 #define NEG_LEFT 1 /* "-1.1" */
963 #define NEG_LEFT_SPACE 2 /* "- 1.1" */
964 #define NEG_RIGHT 3 /* "1.1-" */
965 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
967 static void test_GetNumberFormatA(void)
969 static char szDot[] = { '.', '\0' };
970 static char szComma[] = { ',', '\0' };
971 int ret;
972 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
973 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
974 NUMBERFMTA format;
976 memset(&format, 0, sizeof(format));
978 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
979 SetLastError(0xdeadbeef);
980 ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
981 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
982 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
984 STRINGSA("23,53",""); /* Invalid character --> Error */
985 SetLastError(0xdeadbeef);
986 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
987 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
988 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
990 STRINGSA("--",""); /* Double '-' --> Error */
991 SetLastError(0xdeadbeef);
992 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
993 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
994 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
996 STRINGSA("0-",""); /* Trailing '-' --> Error */
997 SetLastError(0xdeadbeef);
998 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
999 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1000 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1002 STRINGSA("0..",""); /* Double '.' --> Error */
1003 SetLastError(0xdeadbeef);
1004 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1005 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1006 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1008 STRINGSA(" 0.1",""); /* Leading space --> Error */
1009 SetLastError(0xdeadbeef);
1010 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1011 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1012 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1014 STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
1015 SetLastError(0xdeadbeef);
1016 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, 2);
1017 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1018 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1020 STRINGSA("2353",""); /* Format and flags given --> Error */
1021 SetLastError(0xdeadbeef);
1022 ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
1023 ok( !ret, "Expected ret == 0, got %d\n", ret);
1024 ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
1025 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1027 STRINGSA("2353",""); /* Invalid format --> Error */
1028 SetLastError(0xdeadbeef);
1029 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1030 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1031 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1033 STRINGSA("2353","2,353.00"); /* Valid number */
1034 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1035 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1036 EXPECT_LENA; EXPECT_EQA;
1038 STRINGSA("-2353","-2,353.00"); /* Valid negative number */
1039 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1040 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1041 EXPECT_LENA; EXPECT_EQA;
1043 STRINGSA("-353","-353.00"); /* test for off by one error in grouping */
1044 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1045 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1046 EXPECT_LENA; EXPECT_EQA;
1048 STRINGSA("2353.1","2,353.10"); /* Valid real number */
1049 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1050 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1051 EXPECT_LENA; EXPECT_EQA;
1053 STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
1054 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1055 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1056 EXPECT_LENA; EXPECT_EQA;
1058 STRINGSA("2353.119","2,353.12"); /* Too many DP --> Rounded */
1059 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1060 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1061 EXPECT_LENA; EXPECT_EQA;
1063 format.NumDigits = 0; /* No decimal separator */
1064 format.LeadingZero = 0;
1065 format.Grouping = 0; /* No grouping char */
1066 format.NegativeOrder = 0;
1067 format.lpDecimalSep = szDot;
1068 format.lpThousandSep = szComma;
1070 STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
1071 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1072 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1073 EXPECT_LENA; EXPECT_EQA;
1075 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
1076 STRINGSA("2353","2353.0");
1077 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1078 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1079 EXPECT_LENA; EXPECT_EQA;
1081 format.Grouping = 2; /* Group by 100's */
1082 STRINGSA("2353","23,53.0");
1083 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1084 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1085 EXPECT_LENA; EXPECT_EQA;
1087 STRINGSA("235","235.0"); /* Grouping of a positive number */
1088 format.Grouping = 3;
1089 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1090 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1091 EXPECT_LENA; EXPECT_EQA;
1093 STRINGSA("-235","-235.0"); /* Grouping of a negative number */
1094 format.NegativeOrder = NEG_LEFT;
1095 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1096 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1097 EXPECT_LENA; EXPECT_EQA;
1099 format.LeadingZero = 1; /* Always provide leading zero */
1100 STRINGSA(".5","0.5");
1101 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1102 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1103 EXPECT_LENA; EXPECT_EQA;
1105 format.NegativeOrder = NEG_PARENS;
1106 STRINGSA("-1","(1.0)");
1107 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1108 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1109 EXPECT_LENA; EXPECT_EQA;
1111 format.NegativeOrder = NEG_LEFT;
1112 STRINGSA("-1","-1.0");
1113 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1114 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1115 EXPECT_LENA; EXPECT_EQA;
1117 format.NegativeOrder = NEG_LEFT_SPACE;
1118 STRINGSA("-1","- 1.0");
1119 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1120 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1121 EXPECT_LENA; EXPECT_EQA;
1123 format.NegativeOrder = NEG_RIGHT;
1124 STRINGSA("-1","1.0-");
1125 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1126 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1127 EXPECT_LENA; EXPECT_EQA;
1129 format.NegativeOrder = NEG_RIGHT_SPACE;
1130 STRINGSA("-1","1.0 -");
1131 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1132 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1133 EXPECT_LENA; EXPECT_EQA;
1135 lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
1137 if (IsValidLocale(lcid, 0))
1139 STRINGSA("-12345","-12 345,00"); /* Try French formatting */
1140 Expected[3] = 160; /* Non breaking space */
1141 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1142 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1143 EXPECT_LENA; EXPECT_EQA;
1148 static void test_CompareStringA(void)
1150 int ret;
1151 LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
1153 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
1154 ok (ret== 1, "(Salut/Salute) Expected 1, got %d\n", ret);
1156 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
1157 ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
1159 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
1160 ok (ret== 3, "(Salut/hola) Expected 3, got %d\n", ret);
1162 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
1163 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
1165 lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
1167 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
1168 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
1170 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
1171 ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
1173 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
1174 ok (ret == 2, "(Salut/saLuT) Expected 2, got %d\n", ret);
1176 /* test for CompareStringA flags */
1177 SetLastError(0xdeadbeef);
1178 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0x8, "NULL", -1, "NULL", -1);
1179 ok(GetLastError() == ERROR_INVALID_FLAGS,
1180 "unexpected error code %d\n", GetLastError());
1181 ok(!ret, "CompareStringA must fail with invalid flag\n");
1183 SetLastError(0xdeadbeef);
1184 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, LOCALE_USE_CP_ACP, "NULL", -1, "NULL", -1);
1185 ok(GetLastError() == 0xdeadbeef, "unexpected error code %d\n", GetLastError());
1186 ok(ret == CSTR_EQUAL, "CompareStringA error: %d != CSTR_EQUAL\n", ret);
1187 /* end of test for CompareStringA flags */
1189 ret = lstrcmpA("", "");
1190 ok (ret == 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret);
1192 ret = lstrcmpA(NULL, NULL);
1193 ok (ret == 0 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, NULL) should return 0, got %d\n", ret);
1195 ret = lstrcmpA("", NULL);
1196 ok (ret == 1 || broken(ret == -2) /* win9x */, "lstrcmpA(\"\", NULL) should return 1, got %d\n", ret);
1198 ret = lstrcmpA(NULL, "");
1199 ok (ret == -1 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret);
1201 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"EndDialog",-1,"_Property",-1);
1202 ok( ret == 3, "EndDialog vs _Property ... expected 3, got %d\n", ret);
1204 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0070",-1,"_IEWWBrowserComp",-1);
1205 ok( ret == 3, "osp_vba.sreg0070 vs _IEWWBrowserComp ... expected 3, got %d\n", ret);
1207 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"r",-1,"\\",-1);
1208 ok( ret == 3, "r vs \\ ... expected 3, got %d\n", ret);
1210 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0031", -1, "OriginalDatabase", -1 );
1211 ok( ret == 3, "osp_vba.sreg0031 vs OriginalDatabase ... expected 3, got %d\n", ret);
1213 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1 );
1214 ok( ret == 3, "AAA vs aaa expected 3, got %d\n", ret);
1216 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1 );
1217 ok( ret == 1, "AAA vs aab expected 1, got %d\n", ret);
1219 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1 );
1220 ok( ret == 1, "AAA vs Aab expected 1, got %d\n", ret);
1222 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1 );
1223 ok( ret == 1, ".AAA vs Aab expected 1, got %d\n", ret);
1225 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1 );
1226 ok( ret == 1, ".AAA vs A.ab expected 1, got %d\n", ret);
1228 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1 );
1229 ok( ret == 1, "aa vs AB expected 1, got %d\n", ret);
1231 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1 );
1232 ok( ret == 1, "aa vs Aab expected 1, got %d\n", ret);
1234 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1 );
1235 ok( ret == 3, "aB vs Aab expected 3, got %d\n", ret);
1237 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1 );
1238 ok( ret == 1, "Ba vs bab expected 1, got %d\n", ret);
1240 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1 );
1241 ok( ret == 1, "{100}{83}{71}{71}{71} vs Global_DataAccess_JRO expected 1, got %d\n", ret);
1243 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1 );
1244 ok( ret == 3, "a vs { expected 3, got %d\n", ret);
1246 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1 );
1247 ok( ret == 3, "A vs { expected 3, got %d\n", ret);
1249 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1 );
1250 ok(ret == 1, "3.5/0 vs 4.0/-1 expected 1, got %d\n", ret);
1252 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1 );
1253 ok(ret == 1, "3.5 vs 4.0 expected 1, got %d\n", ret);
1255 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1 );
1256 ok(ret == 1, "3.520.4403.2 vs 4.0.2927.10 expected 1, got %d\n", ret);
1258 /* hyphen and apostrophe are treated differently depending on
1259 * whether SORT_STRINGSORT specified or not
1261 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1 );
1262 ok(ret == 3, "-o vs /m expected 3, got %d\n", ret);
1264 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1 );
1265 ok(ret == 1, "/m vs -o expected 1, got %d\n", ret);
1267 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1 );
1268 ok(ret == 1, "-o vs /m expected 1, got %d\n", ret);
1270 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1 );
1271 ok(ret == 3, "/m vs -o expected 3, got %d\n", ret);
1273 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1 );
1274 ok(ret == 3, "'o vs /m expected 3, got %d\n", ret);
1276 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1 );
1277 ok(ret == 1, "/m vs 'o expected 1, got %d\n", ret);
1279 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1 );
1280 ok(ret == 1, "'o vs /m expected 1, got %d\n", ret);
1282 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1 );
1283 ok(ret == 3, "/m vs 'o expected 3, got %d\n", ret);
1285 if (0) { /* this requires collation table patch to make it MS compatible */
1286 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
1287 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
1289 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
1290 ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
1292 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
1293 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
1295 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
1296 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
1298 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
1299 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
1301 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
1302 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
1304 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
1305 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
1307 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
1308 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
1310 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
1311 ok(ret == 1, "`o vs -m expected 1, got %d\n", ret);
1313 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
1314 ok(ret == 3, "-m vs `o expected 3, got %d\n", ret);
1316 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
1317 ok(ret == 3, "`o vs -m expected 3, got %d\n", ret);
1319 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
1320 ok(ret == 1, "-m vs `o expected 1, got %d\n", ret);
1323 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9);
1324 ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0 expected 2, got %d\n", ret);
1326 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10);
1327 ok(ret == 1, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1, got %d\n", ret);
1329 /* WinXP handles embedded NULLs differently than earlier versions */
1330 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
1331 ok(ret == 1 || ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1 or 2, got %d\n", ret);
1333 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
1334 ok(ret == 1 || ret == 2, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected 1 or 2, got %d\n", ret);
1336 ret = CompareStringA(lcid, 0, "a\0b", -1, "a", -1);
1337 ok(ret == 2, "a vs a expected 2, got %d\n", ret);
1339 ret = CompareStringA(lcid, 0, "a\0b", 4, "a", 2);
1340 ok(ret == CSTR_EQUAL || /* win2k */
1341 ret == CSTR_GREATER_THAN,
1342 "a\\0b vs a expected CSTR_EQUAL or CSTR_GREATER_THAN, got %d\n", ret);
1344 ret = CompareStringA(lcid, 0, "\2", 2, "\1", 2);
1345 todo_wine ok(ret != 2, "\\2 vs \\1 expected unequal\n");
1347 ret = CompareStringA(lcid, NORM_IGNORECASE | LOCALE_USE_CP_ACP, "#", -1, ".", -1);
1348 todo_wine ok(ret == CSTR_LESS_THAN, "\"#\" vs \".\" expected CSTR_LESS_THAN, got %d\n", ret);
1350 ret = CompareStringA(lcid, NORM_IGNORECASE, "_", -1, ".", -1);
1351 todo_wine ok(ret == CSTR_GREATER_THAN, "\"_\" vs \".\" expected CSTR_GREATER_THAN, got %d\n", ret);
1353 ret = lstrcmpi("#", ".");
1354 todo_wine ok(ret == -1, "\"#\" vs \".\" expected -1, got %d\n", ret);
1357 static void test_LCMapStringA(void)
1359 int ret, ret2;
1360 char buf[256], buf2[256];
1361 static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
1362 static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
1363 static const char symbols_stripped[] = "justateststring1";
1365 SetLastError(0xdeadbeef);
1366 ret = LCMapStringA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP | LCMAP_LOWERCASE,
1367 lower_case, -1, buf, sizeof(buf));
1368 ok(ret == lstrlenA(lower_case) + 1,
1369 "ret %d, error %d, expected value %d\n",
1370 ret, GetLastError(), lstrlenA(lower_case) + 1);
1371 ok(!memcmp(buf, lower_case, ret), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1373 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1374 upper_case, -1, buf, sizeof(buf));
1375 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1376 ok(GetLastError() == ERROR_INVALID_FLAGS,
1377 "unexpected error code %d\n", GetLastError());
1379 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1380 upper_case, -1, buf, sizeof(buf));
1381 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1382 ok(GetLastError() == ERROR_INVALID_FLAGS,
1383 "unexpected error code %d\n", GetLastError());
1385 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1386 upper_case, -1, buf, sizeof(buf));
1387 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1388 ok(GetLastError() == ERROR_INVALID_FLAGS,
1389 "unexpected error code %d\n", GetLastError());
1391 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1392 upper_case, -1, buf, sizeof(buf));
1393 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1394 ok(GetLastError() == ERROR_INVALID_FLAGS,
1395 "unexpected error code %d\n", GetLastError());
1397 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1398 SetLastError(0xdeadbeef);
1399 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1400 upper_case, -1, buf, sizeof(buf));
1401 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1402 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1404 /* test LCMAP_LOWERCASE */
1405 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1406 upper_case, -1, buf, sizeof(buf));
1407 ok(ret == lstrlenA(upper_case) + 1,
1408 "ret %d, error %d, expected value %d\n",
1409 ret, GetLastError(), lstrlenA(upper_case) + 1);
1410 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1412 /* test LCMAP_UPPERCASE */
1413 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1414 lower_case, -1, buf, sizeof(buf));
1415 ok(ret == lstrlenA(lower_case) + 1,
1416 "ret %d, error %d, expected value %d\n",
1417 ret, GetLastError(), lstrlenA(lower_case) + 1);
1418 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1420 /* test buffer overflow */
1421 SetLastError(0xdeadbeef);
1422 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1423 lower_case, -1, buf, 4);
1424 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1425 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1427 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1428 lstrcpyA(buf, lower_case);
1429 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1430 buf, -1, buf, sizeof(buf));
1431 if (!ret) /* Win9x */
1432 trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1433 else
1435 ok(ret == lstrlenA(lower_case) + 1,
1436 "ret %d, error %d, expected value %d\n",
1437 ret, GetLastError(), lstrlenA(lower_case) + 1);
1438 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1440 lstrcpyA(buf, upper_case);
1441 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1442 buf, -1, buf, sizeof(buf));
1443 if (!ret) /* Win9x */
1444 trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1445 else
1447 ok(ret == lstrlenA(upper_case) + 1,
1448 "ret %d, error %d, expected value %d\n",
1449 ret, GetLastError(), lstrlenA(lower_case) + 1);
1450 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1453 /* otherwise src == dst should fail */
1454 SetLastError(0xdeadbeef);
1455 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1456 buf, 10, buf, sizeof(buf));
1457 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1458 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1459 "unexpected error code %d\n", GetLastError());
1460 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1462 /* test whether '\0' is always appended */
1463 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1464 upper_case, -1, buf, sizeof(buf));
1465 ok(ret, "LCMapStringA must succeed\n");
1466 ok(buf[ret-1] == 0, "LCMapStringA not null-terminated\n");
1467 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1468 upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1469 ok(ret2, "LCMapStringA must succeed\n");
1470 ok(buf2[ret2-1] == 0, "LCMapStringA not null-terminated\n" );
1471 ok(ret == ret2, "lengths of sort keys must be equal\n");
1472 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1474 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1475 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1476 upper_case, -1, buf, sizeof(buf));
1477 ok(ret, "LCMapStringA must succeed\n");
1478 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1479 lower_case, -1, buf2, sizeof(buf2));
1480 ok(ret2, "LCMapStringA must succeed\n");
1481 ok(ret == ret2, "lengths of sort keys must be equal\n");
1482 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1484 /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1485 results from plain LCMAP_SORTKEY on Vista */
1487 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1488 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1489 lower_case, -1, buf, sizeof(buf));
1490 ok(ret, "LCMapStringA must succeed\n");
1491 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1492 symbols_stripped, -1, buf2, sizeof(buf2));
1493 ok(ret2, "LCMapStringA must succeed\n");
1494 ok(ret == ret2, "lengths of sort keys must be equal\n");
1495 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1497 /* test NORM_IGNORENONSPACE */
1498 lstrcpyA(buf, "foo");
1499 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1500 lower_case, -1, buf, sizeof(buf));
1501 ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1502 lstrlenA(lower_case) + 1, ret);
1503 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1505 /* test NORM_IGNORESYMBOLS */
1506 lstrcpyA(buf, "foo");
1507 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1508 lower_case, -1, buf, sizeof(buf));
1509 ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1510 lstrlenA(symbols_stripped) + 1, ret);
1511 ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1513 /* test srclen = 0 */
1514 SetLastError(0xdeadbeef);
1515 ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1516 ok(!ret, "LCMapStringA should fail with srclen = 0\n");
1517 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1518 "unexpected error code %d\n", GetLastError());
1521 static void test_LCMapStringW(void)
1523 int ret, ret2;
1524 WCHAR buf[256], buf2[256];
1525 char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1526 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};
1527 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};
1528 static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
1529 static const WCHAR fooW[] = {'f','o','o',0};
1531 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1532 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1533 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1535 win_skip("LCMapStringW is not implemented\n");
1536 return;
1538 if (broken(ret))
1539 ok(lstrcmpW(buf, upper_case) == 0, "Expected upper case string\n");
1540 else
1542 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1543 ok(GetLastError() == ERROR_INVALID_FLAGS,
1544 "unexpected error code %d\n", GetLastError());
1547 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1548 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1549 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1550 ok(GetLastError() == ERROR_INVALID_FLAGS,
1551 "unexpected error code %d\n", GetLastError());
1553 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1554 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1555 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1556 ok(GetLastError() == ERROR_INVALID_FLAGS,
1557 "unexpected error code %d\n", GetLastError());
1559 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1560 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1561 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1562 ok(GetLastError() == ERROR_INVALID_FLAGS,
1563 "unexpected error code %d\n", GetLastError());
1565 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1566 SetLastError(0xdeadbeef);
1567 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1568 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1569 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1570 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1572 /* test LCMAP_LOWERCASE */
1573 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1574 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1575 ok(ret == lstrlenW(upper_case) + 1,
1576 "ret %d, error %d, expected value %d\n",
1577 ret, GetLastError(), lstrlenW(upper_case) + 1);
1578 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1580 /* test LCMAP_UPPERCASE */
1581 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1582 lower_case, -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 /* test buffer overflow */
1589 SetLastError(0xdeadbeef);
1590 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1591 lower_case, -1, buf, 4);
1592 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1593 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1595 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1596 lstrcpyW(buf, lower_case);
1597 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1598 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1599 ok(ret == lstrlenW(lower_case) + 1,
1600 "ret %d, error %d, expected value %d\n",
1601 ret, GetLastError(), lstrlenW(lower_case) + 1);
1602 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1604 lstrcpyW(buf, upper_case);
1605 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1606 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1607 ok(ret == lstrlenW(upper_case) + 1,
1608 "ret %d, error %d, expected value %d\n",
1609 ret, GetLastError(), lstrlenW(lower_case) + 1);
1610 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1612 /* otherwise src == dst should fail */
1613 SetLastError(0xdeadbeef);
1614 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1615 buf, 10, buf, sizeof(buf));
1616 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1617 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1618 "unexpected error code %d\n", GetLastError());
1619 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1621 /* test whether '\0' is always appended */
1622 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1623 upper_case, -1, buf, sizeof(buf));
1624 ok(ret, "LCMapStringW must succeed\n");
1625 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1626 upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1627 ok(ret, "LCMapStringW must succeed\n");
1628 ok(ret == ret2, "lengths of sort keys must be equal\n");
1629 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1631 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1632 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1633 upper_case, -1, buf, sizeof(buf));
1634 ok(ret, "LCMapStringW must succeed\n");
1635 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1636 lower_case, -1, buf2, sizeof(buf2));
1637 ok(ret2, "LCMapStringW must succeed\n");
1638 ok(ret == ret2, "lengths of sort keys must be equal\n");
1639 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1641 /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1642 results from plain LCMAP_SORTKEY on Vista */
1644 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1645 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1646 lower_case, -1, buf, sizeof(buf));
1647 ok(ret, "LCMapStringW must succeed\n");
1648 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1649 symbols_stripped, -1, buf2, sizeof(buf2));
1650 ok(ret2, "LCMapStringW must succeed\n");
1651 ok(ret == ret2, "lengths of sort keys must be equal\n");
1652 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1654 /* test NORM_IGNORENONSPACE */
1655 lstrcpyW(buf, fooW);
1656 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1657 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1658 ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1659 lstrlenW(lower_case) + 1, ret);
1660 ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1662 /* test NORM_IGNORESYMBOLS */
1663 lstrcpyW(buf, fooW);
1664 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1665 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1666 ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1667 lstrlenW(symbols_stripped) + 1, ret);
1668 ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1670 /* test srclen = 0 */
1671 SetLastError(0xdeadbeef);
1672 ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf)/sizeof(WCHAR));
1673 ok(!ret, "LCMapStringW should fail with srclen = 0\n");
1674 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1675 "unexpected error code %d\n", GetLastError());
1678 /* this requires collation table patch to make it MS compatible */
1679 static const char * const strings_sorted[] =
1681 "'",
1682 "-",
1683 "!",
1684 "\"",
1685 ".",
1686 ":",
1687 "\\",
1688 "_",
1689 "`",
1690 "{",
1691 "}",
1692 "+",
1693 "0",
1694 "1",
1695 "2",
1696 "3",
1697 "4",
1698 "5",
1699 "6",
1700 "7",
1701 "8",
1702 "9",
1703 "a",
1704 "A",
1705 "b",
1706 "B",
1707 "c",
1711 static const char * const strings[] =
1713 "C",
1714 "\"",
1715 "9",
1716 "'",
1717 "}",
1718 "-",
1719 "7",
1720 "+",
1721 "`",
1722 "1",
1723 "a",
1724 "5",
1725 "\\",
1726 "8",
1727 "B",
1728 "3",
1729 "_",
1730 "6",
1731 "{",
1732 "2",
1733 "c",
1734 "4",
1735 "!",
1736 "0",
1737 "A",
1738 ":",
1739 "b",
1743 static int compare_string1(const void *e1, const void *e2)
1745 const char *s1 = *(const char *const *)e1;
1746 const char *s2 = *(const char *const *)e2;
1748 return lstrcmpA(s1, s2);
1751 static int compare_string2(const void *e1, const void *e2)
1753 const char *s1 = *(const char *const *)e1;
1754 const char *s2 = *(const char *const *)e2;
1756 return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1759 static int compare_string3(const void *e1, const void *e2)
1761 const char *s1 = *(const char *const *)e1;
1762 const char *s2 = *(const char *const *)e2;
1763 char key1[256], key2[256];
1765 LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
1766 LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
1767 return strcmp(key1, key2);
1770 static void test_sorting(void)
1772 char buf[256];
1773 char **str_buf = (char **)buf;
1774 int i;
1776 assert(sizeof(buf) >= sizeof(strings));
1778 /* 1. sort using lstrcmpA */
1779 memcpy(buf, strings, sizeof(strings));
1780 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
1781 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1783 ok(!strcmp(strings_sorted[i], str_buf[i]),
1784 "qsort using lstrcmpA failed for element %d\n", i);
1786 /* 2. sort using CompareStringA */
1787 memcpy(buf, strings, sizeof(strings));
1788 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
1789 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1791 ok(!strcmp(strings_sorted[i], str_buf[i]),
1792 "qsort using CompareStringA failed for element %d\n", i);
1794 /* 3. sort using sort keys */
1795 memcpy(buf, strings, sizeof(strings));
1796 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
1797 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1799 ok(!strcmp(strings_sorted[i], str_buf[i]),
1800 "qsort using sort keys failed for element %d\n", i);
1804 static void test_FoldStringA(void)
1806 int ret, i, j;
1807 BOOL is_special;
1808 char src[256], dst[256];
1809 static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0' };
1810 static const char digits_dst[] = { '1','2','3','\0' };
1811 static const char composite_src[] =
1813 0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
1814 0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
1815 0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
1816 0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
1817 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
1818 0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
1819 0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
1820 0xfb,0xfc,0xfd,0xff,'\0'
1822 static const char composite_dst[] =
1824 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1825 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1826 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1827 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1828 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1829 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1830 0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
1831 0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
1832 0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
1833 0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
1834 0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
1835 0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
1836 0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
1837 0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
1838 0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1840 static const char composite_dst_alt[] =
1842 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1843 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1844 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1845 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1846 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1847 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1848 0x4f,0x7e,0x4f,0xa8,0xd8,0x55,0x60,0x55,
1849 0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,0x61,
1850 0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,0x61,
1851 0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,0x65,
1852 0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,0x69,
1853 0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,0x6f,
1854 0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,0x6f,
1855 0xa8,0xf8,0x75,0x60,0x75,0xb4,0x75,0x5e,
1856 0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1858 static const char ligatures_src[] =
1860 0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1862 static const char ligatures_dst[] =
1864 'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1866 static const struct special
1868 char src;
1869 char dst[4];
1870 } foldczone_special[] =
1872 /* src dst */
1873 { 0x85, { 0x2e, 0x2e, 0x2e, 0x00 } },
1874 { 0x98, { 0x20, 0x7e, 0x00 } },
1875 { 0x99, { 0x54, 0x4d, 0x00 } },
1876 { 0xa0, { 0x20, 0x00 } },
1877 { 0xa8, { 0x20, 0xa8, 0x00 } },
1878 { 0xaa, { 0x61, 0x00 } },
1879 { 0xaf, { 0x20, 0xaf, 0x00 } },
1880 { 0xb2, { 0x32, 0x00 } },
1881 { 0xb3, { 0x33, 0x00 } },
1882 { 0xb4, { 0x20, 0xb4, 0x00 } },
1883 { 0xb8, { 0x20, 0xb8, 0x00 } },
1884 { 0xb9, { 0x31, 0x00 } },
1885 { 0xba, { 0x6f, 0x00 } },
1886 { 0xbc, { 0x31, 0x2f, 0x34, 0x00 } },
1887 { 0xbd, { 0x31, 0x2f, 0x32, 0x00 } },
1888 { 0xbe, { 0x33, 0x2f, 0x34, 0x00 } },
1889 { 0x00 }
1892 if (!pFoldStringA)
1893 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1895 /* these tests are locale specific */
1896 if (GetACP() != 1252)
1898 trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1899 return;
1902 /* MAP_FOLDDIGITS */
1903 SetLastError(0);
1904 ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
1905 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1907 win_skip("FoldStringA is not implemented\n");
1908 return;
1910 ok(ret == 4, "Expected ret == 4, got %d, error %d\n", ret, GetLastError());
1911 ok(strcmp(dst, digits_dst) == 0,
1912 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
1913 for (i = 1; i < 256; i++)
1915 if (!strchr(digits_src, i))
1917 src[0] = i;
1918 src[1] = '\0';
1919 SetLastError(0);
1920 ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
1921 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1922 ok(dst[0] == src[0],
1923 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
1927 /* MAP_EXPAND_LIGATURES */
1928 SetLastError(0);
1929 ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1930 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1931 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1932 ok(ret == sizeof(ligatures_dst), "Got %d, error %d\n", ret, GetLastError());
1933 ok(strcmp(dst, ligatures_dst) == 0,
1934 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
1935 for (i = 1; i < 256; i++)
1937 if (!strchr(ligatures_src, i))
1939 src[0] = i;
1940 src[1] = '\0';
1941 SetLastError(0);
1942 ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1943 if (ret == 3)
1945 /* Vista */
1946 ok((i == 0xDC && lstrcmpA(dst, "UE") == 0) ||
1947 (i == 0xFC && lstrcmpA(dst, "ue") == 0),
1948 "Got %s for %d\n", dst, i);
1950 else
1952 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1953 ok(dst[0] == src[0],
1954 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
1960 /* MAP_COMPOSITE */
1961 SetLastError(0);
1962 ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
1963 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1964 ok(ret == 121 || ret == 119, "Expected 121 or 119, got %d\n", ret);
1965 ok(strcmp(dst, composite_dst) == 0 || strcmp(dst, composite_dst_alt) == 0,
1966 "MAP_COMPOSITE: Mismatch, got '%s'\n", dst);
1968 for (i = 1; i < 256; i++)
1970 if (!strchr(composite_src, i))
1972 src[0] = i;
1973 src[1] = '\0';
1974 SetLastError(0);
1975 ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
1976 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1977 ok(dst[0] == src[0],
1978 "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
1979 (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
1983 /* MAP_FOLDCZONE */
1984 for (i = 1; i < 256; i++)
1986 src[0] = i;
1987 src[1] = '\0';
1988 SetLastError(0);
1989 ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
1990 is_special = FALSE;
1991 for (j = 0; foldczone_special[j].src != 0 && ! is_special; j++)
1993 if (foldczone_special[j].src == src[0])
1995 ok(ret == 2 || ret == lstrlenA(foldczone_special[j].dst) + 1,
1996 "Expected ret == 2 or %d, got %d, error %d\n",
1997 lstrlenA(foldczone_special[j].dst) + 1, ret, GetLastError());
1998 ok(src[0] == dst[0] || lstrcmpA(foldczone_special[j].dst, dst) == 0,
1999 "MAP_FOLDCZONE: string mismatch for 0x%02x\n",
2000 (unsigned char)src[0]);
2001 is_special = TRUE;
2004 if (! is_special)
2006 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2007 ok(src[0] == dst[0],
2008 "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
2009 (unsigned char)src[0], (unsigned char)dst[0]);
2013 /* MAP_PRECOMPOSED */
2014 for (i = 1; i < 256; i++)
2016 src[0] = i;
2017 src[1] = '\0';
2018 SetLastError(0);
2019 ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
2020 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2021 ok(src[0] == dst[0],
2022 "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
2023 (unsigned char)src[0], (unsigned char)dst[0]);
2027 static void test_FoldStringW(void)
2029 int ret;
2030 unsigned int i, j;
2031 WCHAR src[256], dst[256], ch, prev_ch = 1;
2032 static const DWORD badFlags[] =
2035 MAP_PRECOMPOSED|MAP_COMPOSITE,
2036 MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
2037 MAP_COMPOSITE|MAP_EXPAND_LIGATURES
2039 /* Ranges of digits 0-9 : Must be sorted! */
2040 static const WCHAR digitRanges[] =
2042 0x0030, /* '0'-'9' */
2043 0x0660, /* Eastern Arabic */
2044 0x06F0, /* Arabic - Hindu */
2045 0x0966, /* Devengari */
2046 0x09E6, /* Bengalii */
2047 0x0A66, /* Gurmukhi */
2048 0x0AE6, /* Gujarati */
2049 0x0B66, /* Oriya */
2050 0x0BE6, /* Tamil - No 0 */
2051 0x0C66, /* Telugu */
2052 0x0CE6, /* Kannada */
2053 0x0D66, /* Maylayalam */
2054 0x0E50, /* Thai */
2055 0x0ED0, /* Laos */
2056 0x0F29, /* Tibet - 0 is out of sequence */
2057 0x2070, /* Superscript - 1, 2, 3 are out of sequence */
2058 0x2080, /* Subscript */
2059 0x245F, /* Circled - 0 is out of sequence */
2060 0x2473, /* Bracketed */
2061 0x2487, /* Full stop */
2062 0x2775, /* Inverted circled - No 0 */
2063 0x277F, /* Patterned circled - No 0 */
2064 0x2789, /* Inverted Patterned circled - No 0 */
2065 0x3020, /* Hangzhou */
2066 0xff10, /* Pliene chasse (?) */
2067 0xffff /* Terminator */
2069 /* Digits which are represented, but out of sequence */
2070 static const WCHAR outOfSequenceDigits[] =
2072 0xB9, /* Superscript 1 */
2073 0xB2, /* Superscript 2 */
2074 0xB3, /* Superscript 3 */
2075 0x0F33, /* Tibetan half zero */
2076 0x24EA, /* Circled 0 */
2077 0x3007, /* Ideographic number zero */
2078 '\0' /* Terminator */
2080 /* Digits in digitRanges for which no representation is available */
2081 static const WCHAR noDigitAvailable[] =
2083 0x0BE6, /* No Tamil 0 */
2084 0x0F29, /* No Tibetan half zero (out of sequence) */
2085 0x2473, /* No Bracketed 0 */
2086 0x2487, /* No 0 Full stop */
2087 0x2775, /* No inverted circled 0 */
2088 0x277F, /* No patterned circled */
2089 0x2789, /* No inverted Patterned circled */
2090 0x3020, /* No Hangzhou 0 */
2091 '\0' /* Terminator */
2093 static const WCHAR foldczone_src[] =
2095 'W', 'i', 'n', 'e', 0x0348, 0x0551, 0x1323, 0x280d,
2096 0xff37, 0xff49, 0xff4e, 0xff45, '\0'
2098 static const WCHAR foldczone_dst[] =
2100 'W','i','n','e',0x0348,0x0551,0x1323,0x280d,'W','i','n','e','\0'
2102 static const WCHAR ligatures_src[] =
2104 'W', 'i', 'n', 'e', 0x03a6, 0x03b9, 0x03bd, 0x03b5,
2105 0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
2106 0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
2107 0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
2108 0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
2109 0xfb04, 0xfb05, 0xfb06, '\0'
2111 static const WCHAR ligatures_dst[] =
2113 'W','i','n','e',0x03a6,0x03b9,0x03bd,0x03b5,
2114 'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
2115 'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
2116 'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
2117 0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
2118 'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
2121 if (!pFoldStringW)
2123 win_skip("FoldStringW is not available\n");
2124 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
2127 /* Invalid flag combinations */
2128 for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
2130 src[0] = dst[0] = '\0';
2131 SetLastError(0);
2132 ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
2133 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
2135 win_skip("FoldStringW is not implemented\n");
2136 return;
2138 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
2139 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2142 /* src & dst cannot be the same */
2143 SetLastError(0);
2144 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
2145 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2146 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2148 /* src can't be NULL */
2149 SetLastError(0);
2150 ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
2151 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2152 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2154 /* srclen can't be 0 */
2155 SetLastError(0);
2156 ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
2157 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2158 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2160 /* dstlen can't be < 0 */
2161 SetLastError(0);
2162 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
2163 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2164 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2166 /* Ret includes terminating NUL which is appended if srclen = -1 */
2167 SetLastError(0);
2168 src[0] = 'A';
2169 src[1] = '\0';
2170 dst[0] = '\0';
2171 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
2172 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2173 ok(dst[0] == 'A' && dst[1] == '\0',
2174 "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%d\n",
2175 'A', '\0', ret, dst[0], dst[1], GetLastError());
2177 /* If size is given, result is not NUL terminated */
2178 SetLastError(0);
2179 src[0] = 'A';
2180 src[1] = 'A';
2181 dst[0] = 'X';
2182 dst[1] = 'X';
2183 ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
2184 ok(ret == 1, "Expected ret == 1, got %d, error %d\n", ret, GetLastError());
2185 ok(dst[0] == 'A' && dst[1] == 'X',
2186 "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%d\n",
2187 'A','X', ret, dst[0], dst[1], GetLastError());
2189 /* MAP_FOLDDIGITS */
2190 for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
2192 /* Check everything before this range */
2193 for (ch = prev_ch; ch < digitRanges[j]; ch++)
2195 SetLastError(0);
2196 src[0] = ch;
2197 src[1] = dst[0] = '\0';
2198 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2199 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2201 ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
2202 /* Wine (correctly) maps all Unicode 4.0+ digits */
2203 isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF ||
2204 (ch >= 0x1369 && ch <= 0x1371),
2205 "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
2208 if (digitRanges[j] == 0xffff)
2209 break; /* Finished the whole code point space */
2211 for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
2213 WCHAR c;
2215 /* Map out of sequence characters */
2216 if (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
2217 else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
2218 else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
2219 else if (ch == 0x245F) c = 0x24EA; /* Circled 0 */
2220 else c = ch;
2221 SetLastError(0);
2222 src[0] = c;
2223 src[1] = dst[0] = '\0';
2224 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2225 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2227 ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
2228 broken( dst[0] == ch ) || /* old Windows versions don't have all mappings */
2229 (digitRanges[j] == 0x3020 && dst[0] == ch) || /* Hangzhou not present in all Windows versions */
2230 (digitRanges[j] == 0x0F29 && dst[0] == ch) || /* Tibetan not present in all Windows versions */
2231 strchrW(noDigitAvailable, c),
2232 "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
2233 ch, '0' + digitRanges[j] - ch, dst[0]);
2235 prev_ch = ch;
2238 /* MAP_FOLDCZONE */
2239 SetLastError(0);
2240 ret = pFoldStringW(MAP_FOLDCZONE, foldczone_src, -1, dst, 256);
2241 ok(ret == sizeof(foldczone_dst)/sizeof(foldczone_dst[0]),
2242 "Got %d, error %d\n", ret, GetLastError());
2243 ok(!memcmp(dst, foldczone_dst, sizeof(foldczone_dst)),
2244 "MAP_FOLDCZONE: Expanded incorrectly\n");
2246 /* MAP_EXPAND_LIGATURES */
2247 SetLastError(0);
2248 ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
2249 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
2250 if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
2251 ok(ret == sizeof(ligatures_dst)/sizeof(ligatures_dst[0]),
2252 "Got %d, error %d\n", ret, GetLastError());
2253 ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
2254 "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
2257 /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
2262 #define LCID_OK(l) \
2263 ok(lcid == l, "Expected lcid = %08x, got %08x\n", l, lcid)
2264 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
2265 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
2266 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
2267 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
2269 static void test_ConvertDefaultLocale(void)
2271 LCID lcid;
2273 /* Doesn't change lcid, even if non default sublang/sort used */
2274 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_US, SORT_DEFAULT);
2275 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_UK, SORT_DEFAULT);
2276 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT);
2277 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE);
2279 /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
2280 LCID_RES(MKLCID(LANG_ENGLISH, SUBLANG_NEUTRAL, SORT_DEFAULT),
2281 MKLCID(LANG_ENGLISH, SUBLANG_DEFAULT, SORT_DEFAULT));
2282 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
2283 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
2285 /* Invariant language is not treated specially */
2286 TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
2288 /* User/system default languages alone are not mapped */
2289 TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
2290 TEST_LCIDLANG(LANG_USER_DEFAULT, SORT_JAPANESE_UNICODE);
2292 /* Default lcids */
2293 LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
2294 LCID_RES(LOCALE_USER_DEFAULT, GetUserDefaultLCID());
2295 LCID_RES(LOCALE_NEUTRAL, GetUserDefaultLCID());
2298 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
2299 DWORD dwFlags, LONG_PTR lParam)
2301 trace("%08x, %s, %s, %08x, %08lx\n",
2302 lgrpid, lpszNum, lpszName, dwFlags, lParam);
2304 ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
2305 "Enumerated grp %d not valid (flags %d)\n", lgrpid, dwFlags);
2307 /* If lParam is one, we are calling with flags defaulted from 0 */
2308 ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
2309 "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %d\n", dwFlags);
2311 return TRUE;
2314 static void test_EnumSystemLanguageGroupsA(void)
2316 BOOL ret;
2318 if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
2320 win_skip("EnumSystemLanguageGroupsA and/or IsValidLanguageGroup are not available\n");
2321 return;
2324 /* No enumeration proc */
2325 SetLastError(0);
2326 ret = pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
2327 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2329 win_skip("EnumSystemLanguageGroupsA is not implemented\n");
2330 return;
2332 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2333 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2335 /* Invalid flags */
2336 SetLastError(0);
2337 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
2338 ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2340 /* No flags - defaults to LGRPID_INSTALLED */
2341 SetLastError(0xdeadbeef);
2342 pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
2343 ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
2345 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
2346 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
2350 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
2351 LONG_PTR lParam)
2353 trace("%08x, %08x, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
2355 /* invalid locale enumerated on some platforms */
2356 if (lcid == 0)
2357 return TRUE;
2359 ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
2360 "Enumerated grp %d not valid\n", lgrpid);
2361 ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
2362 "Enumerated grp locale %d not valid\n", lcid);
2363 return TRUE;
2366 static void test_EnumLanguageGroupLocalesA(void)
2368 BOOL ret;
2370 if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
2372 win_skip("EnumLanguageGroupLocalesA and/or IsValidLanguageGroup are not available\n");
2373 return;
2376 /* No enumeration proc */
2377 SetLastError(0);
2378 ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
2379 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2381 win_skip("EnumLanguageGroupLocalesA is not implemented\n");
2382 return;
2384 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2385 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2387 /* lgrpid too small */
2388 SetLastError(0);
2389 ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
2390 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2391 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2393 /* lgrpid too big */
2394 SetLastError(0);
2395 ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
2396 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2397 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2399 /* dwFlags is reserved */
2400 SetLastError(0);
2401 ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
2402 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2403 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2405 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2408 static void test_SetLocaleInfoA(void)
2410 BOOL bRet;
2411 LCID lcid = GetUserDefaultLCID();
2413 /* Null data */
2414 SetLastError(0);
2415 bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2416 ok( !bRet && GetLastError() == ERROR_INVALID_PARAMETER,
2417 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2419 /* IDATE */
2420 SetLastError(0);
2421 bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
2422 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2423 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2425 /* ILDATE */
2426 SetLastError(0);
2427 bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
2428 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2429 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2432 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2434 trace("%s %08lx\n", value, lParam);
2435 return(TRUE);
2438 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2440 ok(!enumCount, "callback called again unexpected\n");
2441 enumCount++;
2442 return(FALSE);
2445 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2447 ok(0,"callback called unexpected\n");
2448 return(FALSE);
2451 static void test_EnumUILanguageA(void)
2453 BOOL ret;
2454 if (!pEnumUILanguagesA) {
2455 win_skip("EnumUILanguagesA is not available on Win9x or NT4\n");
2456 return;
2459 SetLastError(ERROR_SUCCESS);
2460 ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2461 if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2463 win_skip("EnumUILanguagesA is not implemented\n");
2464 return;
2466 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2468 enumCount = 0;
2469 SetLastError(ERROR_SUCCESS);
2470 ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2471 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2473 SetLastError(ERROR_SUCCESS);
2474 ret = pEnumUILanguagesA(NULL, 0, 0);
2475 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2476 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2477 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2479 SetLastError(ERROR_SUCCESS);
2480 ret = pEnumUILanguagesA(luilocale_proc3A, 0x5a5a5a5a, 0);
2481 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2482 ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2484 SetLastError(ERROR_SUCCESS);
2485 ret = pEnumUILanguagesA(NULL, 0x5a5a5a5a, 0);
2486 ok(!ret, "Expected return value FALSE, got %u\n", ret);
2487 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2488 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2491 static char date_fmt_buf[1024];
2493 static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
2495 lstrcatA(date_fmt_buf, fmt);
2496 lstrcatA(date_fmt_buf, "\n");
2497 return TRUE;
2500 static void test_EnumDateFormatsA(void)
2502 char *p, buf[256];
2503 BOOL ret;
2504 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2506 trace("EnumDateFormatsA 0\n");
2507 date_fmt_buf[0] = 0;
2508 SetLastError(0xdeadbeef);
2509 ret = EnumDateFormatsA(enum_datetime_procA, lcid, 0);
2510 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2512 win_skip("0 for dwFlags is not supported\n");
2514 else
2516 ok(ret, "EnumDateFormatsA(0) error %d\n", GetLastError());
2517 trace("%s\n", date_fmt_buf);
2518 /* test the 1st enumerated format */
2519 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2520 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2521 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2522 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2525 trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n");
2526 date_fmt_buf[0] = 0;
2527 SetLastError(0xdeadbeef);
2528 ret = EnumDateFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2529 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2531 win_skip("LOCALE_USE_CP_ACP is not supported\n");
2533 else
2535 ok(ret, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2536 trace("%s\n", date_fmt_buf);
2537 /* test the 1st enumerated format */
2538 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2539 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2540 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2541 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2544 trace("EnumDateFormatsA DATE_SHORTDATE\n");
2545 date_fmt_buf[0] = 0;
2546 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_SHORTDATE);
2547 ok(ret, "EnumDateFormatsA(DATE_SHORTDATE) error %d\n", GetLastError());
2548 trace("%s\n", date_fmt_buf);
2549 /* test the 1st enumerated format */
2550 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2551 ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2552 ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2553 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2555 trace("EnumDateFormatsA DATE_LONGDATE\n");
2556 date_fmt_buf[0] = 0;
2557 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_LONGDATE);
2558 ok(ret, "EnumDateFormatsA(DATE_LONGDATE) error %d\n", GetLastError());
2559 trace("%s\n", date_fmt_buf);
2560 /* test the 1st enumerated format */
2561 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2562 ret = GetLocaleInfoA(lcid, LOCALE_SLONGDATE, buf, sizeof(buf));
2563 ok(ret, "GetLocaleInfoA(LOCALE_SLONGDATE) error %d\n", GetLastError());
2564 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2566 trace("EnumDateFormatsA DATE_YEARMONTH\n");
2567 date_fmt_buf[0] = 0;
2568 SetLastError(0xdeadbeef);
2569 ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_YEARMONTH);
2570 if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2572 skip("DATE_YEARMONTH is only present on W2K and later\n");
2573 return;
2575 ok(ret, "EnumDateFormatsA(DATE_YEARMONTH) error %d\n", GetLastError());
2576 trace("%s\n", date_fmt_buf);
2577 /* test the 1st enumerated format */
2578 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2579 ret = GetLocaleInfoA(lcid, LOCALE_SYEARMONTH, buf, sizeof(buf));
2580 ok(ret, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %d\n", GetLastError());
2581 ok(!lstrcmpA(date_fmt_buf, buf) || broken(!buf[0]) /* win9x */,
2582 "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2585 static void test_EnumTimeFormatsA(void)
2587 char *p, buf[256];
2588 BOOL ret;
2589 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2591 trace("EnumTimeFormatsA 0\n");
2592 date_fmt_buf[0] = 0;
2593 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, 0);
2594 ok(ret, "EnumTimeFormatsA(0) error %d\n", GetLastError());
2595 trace("%s\n", date_fmt_buf);
2596 /* test the 1st enumerated format */
2597 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2598 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2599 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2600 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2602 trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n");
2603 date_fmt_buf[0] = 0;
2604 ret = EnumTimeFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2605 ok(ret, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2606 trace("%s\n", date_fmt_buf);
2607 /* test the 1st enumerated format */
2608 if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2609 ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2610 ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2611 ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2614 static void test_GetCPInfo(void)
2616 BOOL ret;
2617 CPINFO cpinfo;
2619 SetLastError(0xdeadbeef);
2620 ret = GetCPInfo(CP_SYMBOL, &cpinfo);
2621 ok(!ret, "GetCPInfo(CP_SYMBOL) should fail\n");
2622 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2623 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2625 SetLastError(0xdeadbeef);
2626 ret = GetCPInfo(CP_UTF7, &cpinfo);
2627 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2629 skip("Codepage CP_UTF7 is not installed/available\n");
2631 else
2633 ok(ret, "GetCPInfo(CP_UTF7) 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 == 5, "expected 5, got 0x%x\n", cpinfo.MaxCharSize);
2641 SetLastError(0xdeadbeef);
2642 ret = GetCPInfo(CP_UTF8, &cpinfo);
2643 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2645 skip("Codepage CP_UTF8 is not installed/available\n");
2647 else
2649 ok(ret, "GetCPInfo(CP_UTF8) error %u\n", GetLastError());
2650 ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2651 ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2652 ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2653 ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2654 ok(cpinfo.MaxCharSize == 4 || broken(cpinfo.MaxCharSize == 3) /* win9x */,
2655 "expected 4, got %u\n", cpinfo.MaxCharSize);
2659 START_TEST(locale)
2661 InitFunctionPointers();
2663 test_EnumTimeFormatsA();
2664 test_EnumDateFormatsA();
2665 test_GetLocaleInfoA();
2666 test_GetLocaleInfoW();
2667 test_GetTimeFormatA();
2668 test_GetDateFormatA();
2669 test_GetDateFormatW();
2670 test_GetCurrencyFormatA(); /* Also tests the W version */
2671 test_GetNumberFormatA(); /* Also tests the W version */
2672 test_CompareStringA();
2673 test_LCMapStringA();
2674 test_LCMapStringW();
2675 test_FoldStringA();
2676 test_FoldStringW();
2677 test_ConvertDefaultLocale();
2678 test_EnumSystemLanguageGroupsA();
2679 test_EnumLanguageGroupLocalesA();
2680 test_SetLocaleInfoA();
2681 test_EnumUILanguageA();
2682 test_GetCPInfo();
2683 /* this requires collation table patch to make it MS compatible */
2684 if (0) test_sorting();