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