rsaenh: Fix padding bytes check for 0-byte payload.
[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   STRINGSA("235","$235.0"); /* Grouping of a positive number */
747   format.Grouping = 3;
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   STRINGSA("-235","$-235.0"); /* Grouping of a negative number */
753   format.NegativeOrder = 2;
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.LeadingZero = 1; /* Always provide leading zero */
759   STRINGSA(".5","$0.5");
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;
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.PositiveOrder = CY_POS_LEFT_SPACE;
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.PositiveOrder = CY_POS_RIGHT_SPACE;
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 = 0;
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 = 1;
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 = 2;
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 = 3;
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 = 4;
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 = 5;
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 = 6;
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 = 7;
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 = 8;
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 = 9;
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 = 10;
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 = 11;
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 = 12;
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 = 13;
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   format.NegativeOrder = 14;
867   STRINGSA("-1","($ 1.0)");
868   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
869   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
870   EXPECT_LENA; EXPECT_EQA;
871
872   format.NegativeOrder = 15;
873   STRINGSA("-1","(1.0 $)");
874   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
875   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
876   EXPECT_LENA; EXPECT_EQA;
877 }
878
879 #define NEG_PARENS      0 /* "(1.1)" */
880 #define NEG_LEFT        1 /* "-1.1"  */
881 #define NEG_LEFT_SPACE  2 /* "- 1.1" */
882 #define NEG_RIGHT       3 /* "1.1-"  */
883 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
884
885 static void test_GetNumberFormatA(void)
886 {
887   static char szDot[] = { '.', '\0' };
888   static char szComma[] = { ',', '\0' };
889   int ret;
890   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
891   char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
892   NUMBERFMTA format;
893
894   memset(&format, 0, sizeof(format));
895
896   STRINGSA("23",""); /* NULL output, length > 0 --> Error */
897   SetLastError(0xdeadbeef);
898   ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
899   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
900       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
901
902   STRINGSA("23,53",""); /* Invalid character --> 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("--",""); /* 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-",""); /* Trailing '-' --> 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("0..",""); /* Double '.' --> Error */
921   SetLastError(0xdeadbeef);
922   ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
923   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
924       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
925
926   STRINGSA(" 0.1",""); /* Leading space --> Error */
927   SetLastError(0xdeadbeef);
928   ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
929   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
930       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
931
932   STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
933   SetLastError(0xdeadbeef);
934   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, 2);
935   ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
936       "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
937
938   STRINGSA("2353",""); /* Format and flags given --> Error */
939   SetLastError(0xdeadbeef);
940   ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
941   ok( !ret, "Expected ret == 0, got %d\n", ret);
942   ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
943       "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
944
945   STRINGSA("2353",""); /* Invalid format --> Error */
946   SetLastError(0xdeadbeef);
947   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
948   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
949       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
950
951   STRINGSA("2353","2,353.00"); /* Valid number */
952   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
953   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
954   EXPECT_LENA; EXPECT_EQA;
955
956   STRINGSA("-2353","-2,353.00"); /* Valid negative number */
957   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
958   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
959   EXPECT_LENA; EXPECT_EQA;
960
961   STRINGSA("-353","-353.00"); /* test for off by one error in grouping */
962   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
963   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
964   EXPECT_LENA; EXPECT_EQA;
965
966   STRINGSA("2353.1","2,353.10"); /* Valid real number */
967   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
968   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
969   EXPECT_LENA; EXPECT_EQA;
970
971   STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
972   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
973   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
974   EXPECT_LENA; EXPECT_EQA;
975
976   STRINGSA("2353.119","2,353.12");  /* Too many DP --> Rounded */
977   ret = GetNumberFormatA(lcid, NUO, input, NULL, 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 = 0; /* No decimal separator */
982   format.LeadingZero = 0;
983   format.Grouping = 0;  /* No grouping char */
984   format.NegativeOrder = 0;
985   format.lpDecimalSep = szDot;
986   format.lpThousandSep = szComma;
987
988   STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
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.NumDigits = 1; /* 1 DP --> Expect decimal separator */
994   STRINGSA("2353","2353.0");
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.Grouping = 2; /* Group by 100's */
1000   STRINGSA("2353","23,53.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   STRINGSA("235","235.0"); /* Grouping of a positive number */
1006   format.Grouping = 3;
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   STRINGSA("-235","-235.0"); /* Grouping of a negative number */
1012   format.NegativeOrder = NEG_LEFT;
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.LeadingZero = 1; /* Always provide leading zero */
1018   STRINGSA(".5","0.5");
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_PARENS;
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   format.NegativeOrder = NEG_LEFT;
1030   STRINGSA("-1","-1.0");
1031   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1032   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1033   EXPECT_LENA; EXPECT_EQA;
1034
1035   format.NegativeOrder = NEG_LEFT_SPACE;
1036   STRINGSA("-1","- 1.0");
1037   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1038   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1039   EXPECT_LENA; EXPECT_EQA;
1040
1041   format.NegativeOrder = NEG_RIGHT;
1042   STRINGSA("-1","1.0-");
1043   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1044   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1045   EXPECT_LENA; EXPECT_EQA;
1046
1047   format.NegativeOrder = NEG_RIGHT_SPACE;
1048   STRINGSA("-1","1.0 -");
1049   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1050   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1051   EXPECT_LENA; EXPECT_EQA;
1052
1053   lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
1054
1055   if (IsValidLocale(lcid, 0))
1056   {
1057     STRINGSA("-12345","-12 345,00"); /* Try French formatting */
1058     Expected[3] = 160; /* Non breaking space */
1059     ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1060     ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1061     EXPECT_LENA; EXPECT_EQA;
1062   }
1063 }
1064
1065
1066 static void test_CompareStringA(void)
1067 {
1068   int ret;
1069   LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
1070
1071   ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
1072   ok (ret== 1, "(Salut/Salute) Expected 1, got %d\n", ret);
1073
1074   ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
1075   ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
1076
1077   ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
1078   ok (ret== 3, "(Salut/hola) Expected 3, got %d\n", ret);
1079
1080   ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
1081   ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
1082
1083   lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
1084
1085   ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
1086   ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
1087
1088   ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
1089   ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
1090
1091     ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
1092     ok (ret == 2, "(Salut/saLuT) Expected 2, got %d\n", ret);
1093
1094     /* test for CompareStringA flags */
1095     SetLastError(0xdeadbeef);
1096     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0x8, "NULL", -1, "NULL", -1);
1097     ok(GetLastError() == ERROR_INVALID_FLAGS,
1098         "unexpected error code %d\n", GetLastError());
1099     ok(!ret, "CompareStringA must fail with invalid flag\n");
1100
1101     SetLastError(0xdeadbeef);
1102     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, LOCALE_USE_CP_ACP, "NULL", -1, "NULL", -1);
1103     ok(GetLastError() == 0xdeadbeef, "unexpected error code %d\n", GetLastError());
1104     ok(ret == CSTR_EQUAL, "CompareStringA error: %d != CSTR_EQUAL\n", ret);
1105     /* end of test for CompareStringA flags */
1106
1107     ret = lstrcmpA("", "");
1108     ok (ret == 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret);
1109
1110     ret = lstrcmpA(NULL, NULL);
1111     ok (ret == 0 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, NULL) should return 0, got %d\n", ret);
1112
1113     ret = lstrcmpA("", NULL);
1114     ok (ret == 1 || broken(ret == -2) /* win9x */, "lstrcmpA(\"\", NULL) should return 1, got %d\n", ret);
1115
1116     ret = lstrcmpA(NULL, "");
1117     ok (ret == -1 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret);
1118  
1119     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"EndDialog",-1,"_Property",-1);
1120     ok( ret == 3, "EndDialog vs _Property ... expected 3, got %d\n", ret);
1121
1122     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0070",-1,"_IEWWBrowserComp",-1);
1123     ok( ret == 3, "osp_vba.sreg0070 vs _IEWWBrowserComp ... expected 3, got %d\n", ret);
1124
1125     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"r",-1,"\\",-1); 
1126     ok( ret == 3, "r vs \\ ... expected 3, got %d\n", ret);
1127
1128     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0031", -1, "OriginalDatabase", -1 );
1129     ok( ret == 3, "osp_vba.sreg0031 vs OriginalDatabase ... expected 3, got %d\n", ret);
1130
1131     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1 );
1132     ok( ret == 3, "AAA vs aaa expected 3, got %d\n", ret);
1133
1134     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1 );
1135     ok( ret == 1, "AAA vs aab expected 1, got %d\n", ret);
1136
1137     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1 );
1138     ok( ret == 1, "AAA vs Aab expected 1, got %d\n", ret);
1139
1140     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1 );
1141     ok( ret == 1, ".AAA vs Aab expected 1, got %d\n", ret);
1142
1143     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1 );
1144     ok( ret == 1, ".AAA vs A.ab expected 1, got %d\n", ret);
1145
1146     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1 );
1147     ok( ret == 1, "aa vs AB expected 1, got %d\n", ret);
1148
1149     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1 );
1150     ok( ret == 1, "aa vs Aab expected 1, got %d\n", ret);
1151
1152     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1 );
1153     ok( ret == 3, "aB vs Aab expected 3, got %d\n", ret);
1154
1155     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1 );
1156     ok( ret == 1, "Ba vs bab expected 1, got %d\n", ret);
1157
1158     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1 );
1159     ok( ret == 1, "{100}{83}{71}{71}{71} vs Global_DataAccess_JRO expected 1, got %d\n", ret);
1160
1161     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1 );
1162     ok( ret == 3, "a vs { expected 3, got %d\n", ret);
1163
1164     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1 );
1165     ok( ret == 3, "A vs { expected 3, got %d\n", ret);
1166
1167     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1 );
1168     ok(ret == 1, "3.5/0 vs 4.0/-1 expected 1, got %d\n", ret);
1169
1170     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1 );
1171     ok(ret == 1, "3.5 vs 4.0 expected 1, got %d\n", ret);
1172
1173     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1 );
1174     ok(ret == 1, "3.520.4403.2 vs 4.0.2927.10 expected 1, got %d\n", ret);
1175
1176    /* hyphen and apostrophe are treated differently depending on
1177     * whether SORT_STRINGSORT specified or not
1178     */
1179     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1 );
1180     ok(ret == 3, "-o vs /m expected 3, got %d\n", ret);
1181
1182     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1 );
1183     ok(ret == 1, "/m vs -o expected 1, got %d\n", ret);
1184
1185     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1 );
1186     ok(ret == 1, "-o vs /m expected 1, got %d\n", ret);
1187
1188     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1 );
1189     ok(ret == 3, "/m vs -o expected 3, got %d\n", ret);
1190
1191     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1 );
1192     ok(ret == 3, "'o vs /m expected 3, got %d\n", ret);
1193
1194     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1 );
1195     ok(ret == 1, "/m vs 'o expected 1, got %d\n", ret);
1196
1197     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1 );
1198     ok(ret == 1, "'o vs /m expected 1, got %d\n", ret);
1199
1200     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1 );
1201     ok(ret == 3, "/m vs 'o expected 3, got %d\n", ret);
1202
1203     if (0) { /* this requires collation table patch to make it MS compatible */
1204     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
1205     ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
1206
1207     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
1208     ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
1209
1210     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
1211     ok(ret == 1, "' vs - expected 1, got %d\n", ret);
1212
1213     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
1214     ok(ret == 1, "' vs - expected 1, got %d\n", ret);
1215
1216     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
1217     ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
1218
1219     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
1220     ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
1221
1222     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
1223     ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
1224
1225     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
1226     ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
1227
1228     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
1229     ok(ret == 1, "`o vs -m expected 1, got %d\n", ret);
1230
1231     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
1232     ok(ret == 3, "-m vs `o expected 3, got %d\n", ret);
1233
1234     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
1235     ok(ret == 3, "`o vs -m expected 3, got %d\n", ret);
1236
1237     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
1238     ok(ret == 1, "-m vs `o expected 1, got %d\n", ret);
1239     }
1240
1241     ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9);
1242     ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0 expected 2, got %d\n", ret);
1243
1244     ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10);
1245     ok(ret == 1, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1, got %d\n", ret);
1246
1247     /* WinXP handles embedded NULLs differently than earlier versions */
1248     ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
1249     ok(ret == 1 || ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1 or 2, got %d\n", ret);
1250
1251     ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
1252     ok(ret == 1 || ret == 2, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected 1 or 2, got %d\n", ret);
1253
1254     ret = CompareStringA(lcid, 0, "a\0b", -1, "a", -1);
1255     ok(ret == 2, "a vs a expected 2, got %d\n", ret);
1256
1257     ret = CompareStringA(lcid, 0, "a\0b", 4, "a", 2);
1258     ok(ret == CSTR_EQUAL || /* win2k */
1259        ret == CSTR_GREATER_THAN,
1260        "a\\0b vs a expected CSTR_EQUAL or CSTR_GREATER_THAN, got %d\n", ret);
1261
1262     ret = CompareStringA(lcid, 0, "\2", 2, "\1", 2);
1263     todo_wine ok(ret != 2, "\\2 vs \\1 expected unequal\n");
1264
1265     ret = CompareStringA(lcid, NORM_IGNORECASE | LOCALE_USE_CP_ACP, "#", -1, ".", -1);
1266     todo_wine ok(ret == CSTR_LESS_THAN, "\"#\" vs \".\" expected CSTR_LESS_THAN, got %d\n", ret);
1267
1268     ret = lstrcmpi("#", ".");
1269     todo_wine ok(ret == -1, "\"#\" vs \".\" expected -1, got %d\n", ret);
1270 }
1271
1272 static void test_LCMapStringA(void)
1273 {
1274     int ret, ret2;
1275     char buf[256], buf2[256];
1276     static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
1277     static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
1278     static const char symbols_stripped[] = "justateststring1";
1279
1280     SetLastError(0xdeadbeef);
1281     ret = LCMapStringA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP | LCMAP_LOWERCASE,
1282                        lower_case, -1, buf, sizeof(buf));
1283     ok(ret == lstrlenA(lower_case) + 1,
1284        "ret %d, error %d, expected value %d\n",
1285        ret, GetLastError(), lstrlenA(lower_case) + 1);
1286     ok(!memcmp(buf, lower_case, ret), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1287
1288     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1289                        upper_case, -1, buf, sizeof(buf));
1290     ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1291     ok(GetLastError() == ERROR_INVALID_FLAGS,
1292        "unexpected error code %d\n", GetLastError());
1293
1294     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1295                        upper_case, -1, buf, sizeof(buf));
1296     ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1297     ok(GetLastError() == ERROR_INVALID_FLAGS,
1298        "unexpected error code %d\n", GetLastError());
1299
1300     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1301                        upper_case, -1, buf, sizeof(buf));
1302     ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1303     ok(GetLastError() == ERROR_INVALID_FLAGS,
1304        "unexpected error code %d\n", GetLastError());
1305
1306     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1307                        upper_case, -1, buf, sizeof(buf));
1308     ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1309     ok(GetLastError() == ERROR_INVALID_FLAGS,
1310        "unexpected error code %d\n", GetLastError());
1311
1312     /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1313     SetLastError(0xdeadbeef);
1314     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1315                        upper_case, -1, buf, sizeof(buf));
1316     ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1317     ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1318
1319     /* test LCMAP_LOWERCASE */
1320     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1321                        upper_case, -1, buf, sizeof(buf));
1322     ok(ret == lstrlenA(upper_case) + 1,
1323        "ret %d, error %d, expected value %d\n",
1324        ret, GetLastError(), lstrlenA(upper_case) + 1);
1325     ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1326
1327     /* test LCMAP_UPPERCASE */
1328     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1329                        lower_case, -1, buf, sizeof(buf));
1330     ok(ret == lstrlenA(lower_case) + 1,
1331        "ret %d, error %d, expected value %d\n",
1332        ret, GetLastError(), lstrlenA(lower_case) + 1);
1333     ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1334
1335     /* test buffer overflow */
1336     SetLastError(0xdeadbeef);
1337     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1338                        lower_case, -1, buf, 4);
1339     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1340        "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1341
1342     /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1343     lstrcpyA(buf, lower_case);
1344     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1345                        buf, -1, buf, sizeof(buf));
1346     if (!ret) /* Win9x */
1347         trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1348     else
1349     {
1350         ok(ret == lstrlenA(lower_case) + 1,
1351            "ret %d, error %d, expected value %d\n",
1352            ret, GetLastError(), lstrlenA(lower_case) + 1);
1353         ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1354     }
1355     lstrcpyA(buf, upper_case);
1356     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1357                        buf, -1, buf, sizeof(buf));
1358     if (!ret) /* Win9x */
1359         trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1360     else
1361     {
1362         ok(ret == lstrlenA(upper_case) + 1,
1363            "ret %d, error %d, expected value %d\n",
1364            ret, GetLastError(), lstrlenA(lower_case) + 1);
1365         ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1366     }
1367
1368     /* otherwise src == dst should fail */
1369     SetLastError(0xdeadbeef);
1370     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1371                        buf, 10, buf, sizeof(buf));
1372     ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1373        GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1374        "unexpected error code %d\n", GetLastError());
1375     ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1376
1377     /* test whether '\0' is always appended */
1378     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1379                        upper_case, -1, buf, sizeof(buf));
1380     ok(ret, "LCMapStringA must succeed\n");
1381     ok(buf[ret-1] == 0, "LCMapStringA not null-terminated\n");
1382     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1383                        upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1384     ok(ret2, "LCMapStringA must succeed\n");
1385     ok(buf2[ret2-1] == 0, "LCMapStringA not null-terminated\n" );
1386     ok(ret == ret2, "lengths of sort keys must be equal\n");
1387     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1388
1389     /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1390     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1391                        upper_case, -1, buf, sizeof(buf));
1392     ok(ret, "LCMapStringA must succeed\n");
1393     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1394                        lower_case, -1, buf2, sizeof(buf2));
1395     ok(ret2, "LCMapStringA must succeed\n");
1396     ok(ret == ret2, "lengths of sort keys must be equal\n");
1397     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1398
1399     /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1400        results from plain LCMAP_SORTKEY on Vista */
1401
1402     /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1403     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1404                        lower_case, -1, buf, sizeof(buf));
1405     ok(ret, "LCMapStringA must succeed\n");
1406     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1407                        symbols_stripped, -1, buf2, sizeof(buf2));
1408     ok(ret2, "LCMapStringA must succeed\n");
1409     ok(ret == ret2, "lengths of sort keys must be equal\n");
1410     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1411
1412     /* test NORM_IGNORENONSPACE */
1413     lstrcpyA(buf, "foo");
1414     ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1415                        lower_case, -1, buf, sizeof(buf));
1416     ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1417         lstrlenA(lower_case) + 1, ret);
1418     ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1419
1420     /* test NORM_IGNORESYMBOLS */
1421     lstrcpyA(buf, "foo");
1422     ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1423                        lower_case, -1, buf, sizeof(buf));
1424     ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1425         lstrlenA(symbols_stripped) + 1, ret);
1426     ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1427
1428     /* test srclen = 0 */
1429     SetLastError(0xdeadbeef);
1430     ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1431     ok(!ret, "LCMapStringA should fail with srclen = 0\n");
1432     ok(GetLastError() == ERROR_INVALID_PARAMETER,
1433        "unexpected error code %d\n", GetLastError());
1434 }
1435
1436 static void test_LCMapStringW(void)
1437 {
1438     int ret, ret2;
1439     WCHAR buf[256], buf2[256];
1440     char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1441     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};
1442     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};
1443     static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
1444     static const WCHAR fooW[] = {'f','o','o',0};
1445
1446     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1447                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1448     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1449     {
1450         win_skip("LCMapStringW is not implemented\n");
1451         return;
1452     }
1453     if (broken(ret))
1454         ok(lstrcmpW(buf, upper_case) == 0, "Expected upper case string\n");
1455     else
1456     {
1457         ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1458         ok(GetLastError() == ERROR_INVALID_FLAGS,
1459            "unexpected error code %d\n", GetLastError());
1460     }
1461
1462     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1463                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1464     ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1465     ok(GetLastError() == ERROR_INVALID_FLAGS,
1466        "unexpected error code %d\n", GetLastError());
1467
1468     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1469                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1470     ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1471     ok(GetLastError() == ERROR_INVALID_FLAGS,
1472        "unexpected error code %d\n", GetLastError());
1473
1474     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1475                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1476     ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1477     ok(GetLastError() == ERROR_INVALID_FLAGS,
1478        "unexpected error code %d\n", GetLastError());
1479
1480     /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1481     SetLastError(0xdeadbeef);
1482     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1483                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1484     ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1485     ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1486
1487     /* test LCMAP_LOWERCASE */
1488     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1489                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1490     ok(ret == lstrlenW(upper_case) + 1,
1491        "ret %d, error %d, expected value %d\n",
1492        ret, GetLastError(), lstrlenW(upper_case) + 1);
1493     ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1494
1495     /* test LCMAP_UPPERCASE */
1496     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1497                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1498     ok(ret == lstrlenW(lower_case) + 1,
1499        "ret %d, error %d, expected value %d\n",
1500        ret, GetLastError(), lstrlenW(lower_case) + 1);
1501     ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1502
1503     /* test buffer overflow */
1504     SetLastError(0xdeadbeef);
1505     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1506                        lower_case, -1, buf, 4);
1507     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1508        "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1509
1510     /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1511     lstrcpyW(buf, lower_case);
1512     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1513                        buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1514     ok(ret == lstrlenW(lower_case) + 1,
1515        "ret %d, error %d, expected value %d\n",
1516        ret, GetLastError(), lstrlenW(lower_case) + 1);
1517     ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1518
1519     lstrcpyW(buf, upper_case);
1520     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1521                        buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1522     ok(ret == lstrlenW(upper_case) + 1,
1523        "ret %d, error %d, expected value %d\n",
1524        ret, GetLastError(), lstrlenW(lower_case) + 1);
1525     ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1526
1527     /* otherwise src == dst should fail */
1528     SetLastError(0xdeadbeef);
1529     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1530                        buf, 10, buf, sizeof(buf));
1531     ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1532        GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1533        "unexpected error code %d\n", GetLastError());
1534     ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1535
1536     /* test whether '\0' is always appended */
1537     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1538                        upper_case, -1, buf, sizeof(buf));
1539     ok(ret, "LCMapStringW must succeed\n");
1540     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1541                        upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1542     ok(ret, "LCMapStringW must succeed\n");
1543     ok(ret == ret2, "lengths of sort keys must be equal\n");
1544     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1545
1546     /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1547     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1548                        upper_case, -1, buf, sizeof(buf));
1549     ok(ret, "LCMapStringW must succeed\n");
1550     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1551                        lower_case, -1, buf2, sizeof(buf2));
1552     ok(ret2, "LCMapStringW must succeed\n");
1553     ok(ret == ret2, "lengths of sort keys must be equal\n");
1554     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1555
1556     /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1557        results from plain LCMAP_SORTKEY on Vista */
1558
1559     /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1560     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1561                        lower_case, -1, buf, sizeof(buf));
1562     ok(ret, "LCMapStringW must succeed\n");
1563     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1564                        symbols_stripped, -1, buf2, sizeof(buf2));
1565     ok(ret2, "LCMapStringW must succeed\n");
1566     ok(ret == ret2, "lengths of sort keys must be equal\n");
1567     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1568
1569     /* test NORM_IGNORENONSPACE */
1570     lstrcpyW(buf, fooW);
1571     ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1572                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1573     ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1574         lstrlenW(lower_case) + 1, ret);
1575     ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1576
1577     /* test NORM_IGNORESYMBOLS */
1578     lstrcpyW(buf, fooW);
1579     ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1580                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1581     ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1582         lstrlenW(symbols_stripped) + 1, ret);
1583     ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1584
1585     /* test srclen = 0 */
1586     SetLastError(0xdeadbeef);
1587     ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf)/sizeof(WCHAR));
1588     ok(!ret, "LCMapStringW should fail with srclen = 0\n");
1589     ok(GetLastError() == ERROR_INVALID_PARAMETER,
1590        "unexpected error code %d\n", GetLastError());
1591 }
1592
1593 /* this requires collation table patch to make it MS compatible */
1594 static const char * const strings_sorted[] =
1595 {
1596 "'",
1597 "-",
1598 "!",
1599 "\"",
1600 ".",
1601 ":",
1602 "\\",
1603 "_",
1604 "`",
1605 "{",
1606 "}",
1607 "+",
1608 "0",
1609 "1",
1610 "2",
1611 "3",
1612 "4",
1613 "5",
1614 "6",
1615 "7",
1616 "8",
1617 "9",
1618 "a",
1619 "A",
1620 "b",
1621 "B",
1622 "c",
1623 "C"
1624 };
1625
1626 static const char * const strings[] =
1627 {
1628 "C",
1629 "\"",
1630 "9",
1631 "'",
1632 "}",
1633 "-",
1634 "7",
1635 "+",
1636 "`",
1637 "1",
1638 "a",
1639 "5",
1640 "\\",
1641 "8",
1642 "B",
1643 "3",
1644 "_",
1645 "6",
1646 "{",
1647 "2",
1648 "c",
1649 "4",
1650 "!",
1651 "0",
1652 "A",
1653 ":",
1654 "b",
1655 "."
1656 };
1657
1658 static int compare_string1(const void *e1, const void *e2)
1659 {
1660     const char *s1 = *(const char *const *)e1;
1661     const char *s2 = *(const char *const *)e2;
1662
1663     return lstrcmpA(s1, s2);
1664 }
1665
1666 static int compare_string2(const void *e1, const void *e2)
1667 {
1668     const char *s1 = *(const char *const *)e1;
1669     const char *s2 = *(const char *const *)e2;
1670
1671     return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1672 }
1673
1674 static int compare_string3(const void *e1, const void *e2)
1675 {
1676     const char *s1 = *(const char *const *)e1;
1677     const char *s2 = *(const char *const *)e2;
1678     char key1[256], key2[256];
1679
1680     LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
1681     LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
1682     return strcmp(key1, key2);
1683 }
1684
1685 static void test_sorting(void)
1686 {
1687     char buf[256];
1688     char **str_buf = (char **)buf;
1689     int i;
1690
1691     assert(sizeof(buf) >= sizeof(strings));
1692
1693     /* 1. sort using lstrcmpA */
1694     memcpy(buf, strings, sizeof(strings));
1695     qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
1696     for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1697     {
1698         ok(!strcmp(strings_sorted[i], str_buf[i]),
1699            "qsort using lstrcmpA failed for element %d\n", i);
1700     }
1701     /* 2. sort using CompareStringA */
1702     memcpy(buf, strings, sizeof(strings));
1703     qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
1704     for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1705     {
1706         ok(!strcmp(strings_sorted[i], str_buf[i]),
1707            "qsort using CompareStringA failed for element %d\n", i);
1708     }
1709     /* 3. sort using sort keys */
1710     memcpy(buf, strings, sizeof(strings));
1711     qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
1712     for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1713     {
1714         ok(!strcmp(strings_sorted[i], str_buf[i]),
1715            "qsort using sort keys failed for element %d\n", i);
1716     }
1717 }
1718
1719 static void test_FoldStringA(void)
1720 {
1721   int ret, i, j;
1722   BOOL is_special;
1723   char src[256], dst[256];
1724   static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0'  };
1725   static const char digits_dst[] = { '1','2','3','\0'  };
1726   static const char composite_src[] =
1727   {
1728     0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
1729     0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
1730     0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
1731     0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
1732     0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
1733     0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
1734     0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
1735     0xfb,0xfc,0xfd,0xff,'\0'
1736   };
1737   static const char composite_dst[] =
1738   {
1739     0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1740     0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1741     0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1742     0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1743     0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1744     0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1745     0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
1746     0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
1747     0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
1748     0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
1749     0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
1750     0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
1751     0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
1752     0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
1753     0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1754   };
1755   static const char composite_dst_alt[] =
1756   {
1757     0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1758     0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1759     0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1760     0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1761     0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1762     0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1763     0x4f,0x7e,0x4f,0xa8,0xd8,0x55,0x60,0x55,
1764     0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,0x61,
1765     0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,0x61,
1766     0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,0x65,
1767     0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,0x69,
1768     0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,0x6f,
1769     0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,0x6f,
1770     0xa8,0xf8,0x75,0x60,0x75,0xb4,0x75,0x5e,
1771     0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1772   };
1773   static const char ligatures_src[] =
1774   {
1775     0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1776   };
1777   static const char ligatures_dst[] =
1778   {
1779     'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1780   };
1781   static const struct special
1782   {
1783     char src;
1784     char dst[4];
1785   }  foldczone_special[] =
1786   {
1787     /* src   dst                   */
1788     { 0x85, { 0x2e, 0x2e, 0x2e, 0x00 } },
1789     { 0x98, { 0x20, 0x7e, 0x00 } },
1790     { 0x99, { 0x54, 0x4d, 0x00 } },
1791     { 0xa0, { 0x20, 0x00 } },
1792     { 0xa8, { 0x20, 0xa8, 0x00 } },
1793     { 0xaa, { 0x61, 0x00 } },
1794     { 0xaf, { 0x20, 0xaf, 0x00 } },
1795     { 0xb2, { 0x32, 0x00 } },
1796     { 0xb3, { 0x33, 0x00 } },
1797     { 0xb4, { 0x20, 0xb4, 0x00 } },
1798     { 0xb8, { 0x20, 0xb8, 0x00 } },
1799     { 0xb9, { 0x31, 0x00 } },
1800     { 0xba, { 0x6f, 0x00 } },
1801     { 0xbc, { 0x31, 0x2f, 0x34, 0x00 } },
1802     { 0xbd, { 0x31, 0x2f, 0x32, 0x00 } },
1803     { 0xbe, { 0x33, 0x2f, 0x34, 0x00 } },
1804     { 0x00 }
1805   };
1806
1807   if (!pFoldStringA)
1808     return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1809
1810   /* these tests are locale specific */
1811   if (GetACP() != 1252)
1812   {
1813       trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1814       return;
1815   }
1816
1817   /* MAP_FOLDDIGITS */
1818   SetLastError(0);
1819   ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
1820   if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1821   {
1822     win_skip("FoldStringA is not implemented\n");
1823     return;
1824   }
1825   ok(ret == 4, "Expected ret == 4, got %d, error %d\n", ret, GetLastError());
1826   ok(strcmp(dst, digits_dst) == 0,
1827      "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
1828   for (i = 1; i < 256; i++)
1829   {
1830     if (!strchr(digits_src, i))
1831     {
1832       src[0] = i;
1833       src[1] = '\0';
1834       SetLastError(0);
1835       ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
1836       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1837       ok(dst[0] == src[0],
1838          "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
1839     }
1840   }
1841
1842   /* MAP_EXPAND_LIGATURES */
1843   SetLastError(0);
1844   ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1845   /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1846   if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1847     ok(ret == sizeof(ligatures_dst), "Got %d, error %d\n", ret, GetLastError());
1848     ok(strcmp(dst, ligatures_dst) == 0,
1849        "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
1850     for (i = 1; i < 256; i++)
1851     {
1852       if (!strchr(ligatures_src, i))
1853       {
1854         src[0] = i;
1855         src[1] = '\0';
1856         SetLastError(0);
1857         ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1858         if (ret == 3)
1859         {
1860           /* Vista */
1861           ok((i == 0xDC && lstrcmpA(dst, "UE") == 0) ||
1862              (i == 0xFC && lstrcmpA(dst, "ue") == 0),
1863              "Got %s for %d\n", dst, i);
1864         }
1865         else
1866         {
1867           ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1868           ok(dst[0] == src[0],
1869              "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
1870         }
1871       }
1872     }
1873   }
1874
1875   /* MAP_COMPOSITE */
1876   SetLastError(0);
1877   ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
1878   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1879   ok(ret == 121 || ret == 119, "Expected 121 or 119, got %d\n", ret);
1880   ok(strcmp(dst, composite_dst) == 0 || strcmp(dst, composite_dst_alt) == 0,
1881      "MAP_COMPOSITE: Mismatch, got '%s'\n", dst);
1882
1883   for (i = 1; i < 256; i++)
1884   {
1885     if (!strchr(composite_src, i))
1886     {
1887       src[0] = i;
1888       src[1] = '\0';
1889       SetLastError(0);
1890       ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
1891       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1892       ok(dst[0] == src[0],
1893          "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
1894          (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
1895     }
1896   }
1897
1898   /* MAP_FOLDCZONE */
1899   for (i = 1; i < 256; i++)
1900   {
1901     src[0] = i;
1902     src[1] = '\0';
1903     SetLastError(0);
1904     ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
1905     is_special = FALSE;
1906     for (j = 0; foldczone_special[j].src != 0 && ! is_special; j++)
1907     {
1908       if (foldczone_special[j].src == src[0])
1909       {
1910         ok(ret == 2 || ret == lstrlenA(foldczone_special[j].dst) + 1,
1911            "Expected ret == 2 or %d, got %d, error %d\n",
1912            lstrlenA(foldczone_special[j].dst) + 1, ret, GetLastError());
1913         ok(src[0] == dst[0] || lstrcmpA(foldczone_special[j].dst, dst) == 0,
1914            "MAP_FOLDCZONE: string mismatch for 0x%02x\n",
1915            (unsigned char)src[0]);
1916         is_special = TRUE;
1917       }
1918     }
1919     if (! is_special)
1920     {
1921       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1922       ok(src[0] == dst[0],
1923          "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
1924          (unsigned char)src[0], (unsigned char)dst[0]);
1925     }
1926   }
1927
1928   /* MAP_PRECOMPOSED */
1929   for (i = 1; i < 256; i++)
1930   {
1931     src[0] = i;
1932     src[1] = '\0';
1933     SetLastError(0);
1934     ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
1935     ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1936     ok(src[0] == dst[0],
1937        "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
1938        (unsigned char)src[0], (unsigned char)dst[0]);
1939   }
1940 }
1941
1942 static void test_FoldStringW(void)
1943 {
1944   int ret;
1945   unsigned int i, j;
1946   WCHAR src[256], dst[256], ch, prev_ch = 1;
1947   static const DWORD badFlags[] =
1948   {
1949     0,
1950     MAP_PRECOMPOSED|MAP_COMPOSITE,
1951     MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
1952     MAP_COMPOSITE|MAP_EXPAND_LIGATURES
1953   };
1954   /* Ranges of digits 0-9 : Must be sorted! */
1955   static const WCHAR digitRanges[] =
1956   {
1957     0x0030, /* '0'-'9' */
1958     0x0660, /* Eastern Arabic */
1959     0x06F0, /* Arabic - Hindu */
1960     0x0966, /* Devengari */
1961     0x09E6, /* Bengalii */
1962     0x0A66, /* Gurmukhi */
1963     0x0AE6, /* Gujarati */
1964     0x0B66, /* Oriya */
1965     0x0BE6, /* Tamil - No 0 */
1966     0x0C66, /* Telugu */
1967     0x0CE6, /* Kannada */
1968     0x0D66, /* Maylayalam */
1969     0x0E50, /* Thai */
1970     0x0ED0, /* Laos */
1971     0x0F29, /* Tibet - 0 is out of sequence */
1972     0x2070, /* Superscript - 1, 2, 3 are out of sequence */
1973     0x2080, /* Subscript */
1974     0x245F, /* Circled - 0 is out of sequence */
1975     0x2473, /* Bracketed */
1976     0x2487, /* Full stop */
1977     0x2775, /* Inverted circled - No 0 */
1978     0x277F, /* Patterned circled - No 0 */
1979     0x2789, /* Inverted Patterned circled - No 0 */
1980     0x3020, /* Hangzhou */
1981     0xff10, /* Pliene chasse (?) */
1982     0xffff  /* Terminator */
1983   };
1984   /* Digits which are represented, but out of sequence */
1985   static const WCHAR outOfSequenceDigits[] =
1986   {
1987       0xB9,   /* Superscript 1 */
1988       0xB2,   /* Superscript 2 */
1989       0xB3,   /* Superscript 3 */
1990       0x0F33, /* Tibetan half zero */
1991       0x24EA, /* Circled 0 */
1992       0x3007, /* Ideographic number zero */
1993       '\0'    /* Terminator */
1994   };
1995   /* Digits in digitRanges for which no representation is available */
1996   static const WCHAR noDigitAvailable[] =
1997   {
1998       0x0BE6, /* No Tamil 0 */
1999       0x0F29, /* No Tibetan half zero (out of sequence) */
2000       0x2473, /* No Bracketed 0 */
2001       0x2487, /* No 0 Full stop */
2002       0x2775, /* No inverted circled 0 */
2003       0x277F, /* No patterned circled */
2004       0x2789, /* No inverted Patterned circled */
2005       0x3020, /* No Hangzhou 0 */
2006       '\0'    /* Terminator */
2007   };
2008   static const WCHAR foldczone_src[] =
2009   {
2010     'W',    'i',    'n',    'e',    0x0348, 0x0551, 0x1323, 0x280d,
2011     0xff37, 0xff49, 0xff4e, 0xff45, '\0'
2012   };
2013   static const WCHAR foldczone_dst[] =
2014   {
2015     'W','i','n','e',0x0348,0x0551,0x1323,0x280d,'W','i','n','e','\0'
2016   };
2017   static const WCHAR ligatures_src[] =
2018   {
2019     'W',    'i',    'n',    'e',    0x03a6, 0x03b9, 0x03bd, 0x03b5,
2020     0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
2021     0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
2022     0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
2023     0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
2024     0xfb04, 0xfb05, 0xfb06, '\0'
2025   };
2026   static const WCHAR ligatures_dst[] =
2027   {
2028     'W','i','n','e',0x03a6,0x03b9,0x03bd,0x03b5,
2029     'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
2030     'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
2031     'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
2032     0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
2033     'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
2034   };
2035
2036   if (!pFoldStringW)
2037   {
2038     win_skip("FoldStringW is not available\n");
2039     return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
2040   }
2041
2042   /* Invalid flag combinations */
2043   for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
2044   {
2045     src[0] = dst[0] = '\0';
2046     SetLastError(0);
2047     ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
2048     if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
2049     {
2050       win_skip("FoldStringW is not implemented\n");
2051       return;
2052     }
2053     ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
2054        "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2055   }
2056
2057   /* src & dst cannot be the same */
2058   SetLastError(0);
2059   ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
2060   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2061       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2062
2063   /* src can't be NULL */
2064   SetLastError(0);
2065   ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
2066   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2067       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2068
2069   /* srclen can't be 0 */
2070   SetLastError(0);
2071   ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
2072   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2073       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2074
2075   /* dstlen can't be < 0 */
2076   SetLastError(0);
2077   ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
2078   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2079       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2080
2081   /* Ret includes terminating NUL which is appended if srclen = -1 */
2082   SetLastError(0);
2083   src[0] = 'A';
2084   src[1] = '\0';
2085   dst[0] = '\0';
2086   ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
2087   ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2088   ok(dst[0] == 'A' && dst[1] == '\0',
2089      "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%d\n",
2090      'A', '\0', ret, dst[0], dst[1], GetLastError());
2091
2092   /* If size is given, result is not NUL terminated */
2093   SetLastError(0);
2094   src[0] = 'A';
2095   src[1] = 'A';
2096   dst[0] = 'X';
2097   dst[1] = 'X';
2098   ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
2099   ok(ret == 1, "Expected ret == 1, got %d, error %d\n", ret, GetLastError());
2100   ok(dst[0] == 'A' && dst[1] == 'X',
2101      "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%d\n",
2102      'A','X', ret, dst[0], dst[1], GetLastError());
2103
2104   /* MAP_FOLDDIGITS */
2105   for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
2106   {
2107     /* Check everything before this range */
2108     for (ch = prev_ch; ch < digitRanges[j]; ch++)
2109     {
2110       SetLastError(0);
2111       src[0] = ch;
2112       src[1] = dst[0] = '\0';
2113       ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2114       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2115
2116       ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
2117          /* Wine (correctly) maps all Unicode 4.0+ digits */
2118          isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF ||
2119          (ch >= 0x1369 && ch <= 0x1371),
2120          "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
2121     }
2122
2123     if (digitRanges[j] == 0xffff)
2124       break; /* Finished the whole code point space */
2125
2126     for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
2127     {
2128       WCHAR c;
2129
2130       /* Map out of sequence characters */
2131       if      (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
2132       else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
2133       else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
2134       else if (ch == 0x245F) c = 0x24EA; /* Circled 0     */
2135       else                   c = ch;
2136       SetLastError(0);
2137       src[0] = c;
2138       src[1] = dst[0] = '\0';
2139       ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2140       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2141
2142       ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
2143          broken( dst[0] == ch ) ||  /* old Windows versions don't have all mappings */
2144          (digitRanges[j] == 0x3020 && dst[0] == ch) || /* Hangzhou not present in all Windows versions */
2145          (digitRanges[j] == 0x0F29 && dst[0] == ch) || /* Tibetan not present in all Windows versions */
2146          strchrW(noDigitAvailable, c),
2147          "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
2148          ch, '0' + digitRanges[j] - ch, dst[0]);
2149     }
2150     prev_ch = ch;
2151   }
2152
2153   /* MAP_FOLDCZONE */
2154   SetLastError(0);
2155   ret = pFoldStringW(MAP_FOLDCZONE, foldczone_src, -1, dst, 256);
2156   ok(ret == sizeof(foldczone_dst)/sizeof(foldczone_dst[0]),
2157      "Got %d, error %d\n", ret, GetLastError());
2158   ok(!memcmp(dst, foldczone_dst, sizeof(foldczone_dst)),
2159      "MAP_FOLDCZONE: Expanded incorrectly\n");
2160
2161   /* MAP_EXPAND_LIGATURES */
2162   SetLastError(0);
2163   ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
2164   /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
2165   if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
2166     ok(ret == sizeof(ligatures_dst)/sizeof(ligatures_dst[0]),
2167        "Got %d, error %d\n", ret, GetLastError());
2168     ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
2169        "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
2170   }
2171
2172   /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
2173 }
2174
2175
2176
2177 #define LCID_OK(l) \
2178   ok(lcid == l, "Expected lcid = %08x, got %08x\n", l, lcid)
2179 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
2180 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
2181 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
2182 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
2183
2184 static void test_ConvertDefaultLocale(void)
2185 {
2186   LCID lcid;
2187
2188   /* Doesn't change lcid, even if non default sublang/sort used */
2189   TEST_LCID(LANG_ENGLISH,  SUBLANG_ENGLISH_US, SORT_DEFAULT);
2190   TEST_LCID(LANG_ENGLISH,  SUBLANG_ENGLISH_UK, SORT_DEFAULT);
2191   TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT,    SORT_DEFAULT);
2192   TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT,    SORT_JAPANESE_UNICODE);
2193
2194   /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
2195   LCID_RES(MKLCID(LANG_ENGLISH,  SUBLANG_NEUTRAL, SORT_DEFAULT),
2196            MKLCID(LANG_ENGLISH,  SUBLANG_DEFAULT, SORT_DEFAULT));
2197   LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
2198            MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
2199
2200   /* Invariant language is not treated specially */
2201   TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
2202
2203   /* User/system default languages alone are not mapped */
2204   TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
2205   TEST_LCIDLANG(LANG_USER_DEFAULT,   SORT_JAPANESE_UNICODE);
2206
2207   /* Default lcids */
2208   LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
2209   LCID_RES(LOCALE_USER_DEFAULT,   GetUserDefaultLCID());
2210   LCID_RES(LOCALE_NEUTRAL,        GetUserDefaultLCID());
2211 }
2212
2213 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
2214                                     DWORD dwFlags, LONG_PTR lParam)
2215 {
2216   trace("%08x, %s, %s, %08x, %08lx\n",
2217         lgrpid, lpszNum, lpszName, dwFlags, lParam);
2218
2219   ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
2220      "Enumerated grp %d not valid (flags %d)\n", lgrpid, dwFlags);
2221
2222   /* If lParam is one, we are calling with flags defaulted from 0 */
2223   ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
2224          "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %d\n", dwFlags);
2225
2226   return TRUE;
2227 }
2228
2229 static void test_EnumSystemLanguageGroupsA(void)
2230 {
2231   BOOL ret;
2232
2233   if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
2234   {
2235     win_skip("EnumSystemLanguageGroupsA and/or IsValidLanguageGroup are not available\n");
2236     return;
2237   }
2238
2239   /* No enumeration proc */
2240   SetLastError(0);
2241   ret = pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
2242   if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2243   {
2244     win_skip("EnumSystemLanguageGroupsA is not implemented\n");
2245     return;
2246   }
2247   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2248       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2249
2250   /* Invalid flags */
2251   SetLastError(0);
2252   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
2253   ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2254
2255   /* No flags - defaults to LGRPID_INSTALLED */
2256   SetLastError(0xdeadbeef);
2257   pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
2258   ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
2259
2260   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
2261   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
2262 }
2263
2264
2265 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
2266                                       LONG_PTR lParam)
2267 {
2268   trace("%08x, %08x, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
2269
2270   /* invalid locale enumerated on some platforms */
2271   if (lcid == 0)
2272       return TRUE;
2273
2274   ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
2275      "Enumerated grp %d not valid\n", lgrpid);
2276   ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
2277      "Enumerated grp locale %d not valid\n", lcid);
2278   return TRUE;
2279 }
2280
2281 static void test_EnumLanguageGroupLocalesA(void)
2282 {
2283   BOOL ret;
2284
2285   if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
2286   {
2287     win_skip("EnumLanguageGroupLocalesA and/or IsValidLanguageGroup are not available\n");
2288     return;
2289   }
2290
2291   /* No enumeration proc */
2292   SetLastError(0);
2293   ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
2294   if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2295   {
2296     win_skip("EnumLanguageGroupLocalesA is not implemented\n");
2297     return;
2298   }
2299   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2300       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2301
2302   /* lgrpid too small */
2303   SetLastError(0);
2304   ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
2305   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2306       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2307
2308   /* lgrpid too big */
2309   SetLastError(0);
2310   ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
2311   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2312       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2313
2314   /* dwFlags is reserved */
2315   SetLastError(0);
2316   ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
2317   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2318       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2319
2320   pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2321 }
2322
2323 static void test_SetLocaleInfoA(void)
2324 {
2325   BOOL bRet;
2326   LCID lcid = GetUserDefaultLCID();
2327
2328   /* Null data */
2329   SetLastError(0);
2330   bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2331   ok( !bRet && GetLastError() == ERROR_INVALID_PARAMETER,
2332       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2333
2334   /* IDATE */
2335   SetLastError(0);
2336   bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
2337   ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2338      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2339
2340   /* ILDATE */
2341   SetLastError(0);
2342   bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
2343   ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2344      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2345 }
2346
2347 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2348 {
2349   trace("%s %08lx\n", value, lParam);
2350   return(TRUE);
2351 }
2352
2353 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2354 {
2355   ok(!enumCount, "callback called again unexpected\n");
2356   enumCount++;
2357   return(FALSE);
2358 }
2359
2360 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2361 {
2362   ok(0,"callback called unexpected\n");
2363   return(FALSE);
2364 }
2365
2366 static void test_EnumUILanguageA(void)
2367 {
2368   BOOL ret;
2369   if (!pEnumUILanguagesA) {
2370     win_skip("EnumUILanguagesA is not available on Win9x or NT4\n");
2371     return;
2372   }
2373
2374   SetLastError(ERROR_SUCCESS);
2375   ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2376   if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2377   {
2378     win_skip("EnumUILanguagesA is not implemented\n");
2379     return;
2380   }
2381   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2382
2383   enumCount = 0;
2384   SetLastError(ERROR_SUCCESS);
2385   ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2386   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2387
2388   SetLastError(ERROR_SUCCESS);
2389   ret = pEnumUILanguagesA(NULL, 0, 0);
2390   ok(!ret, "Expected return value FALSE, got %u\n", ret);
2391   ok(GetLastError() == ERROR_INVALID_PARAMETER,
2392       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2393
2394   SetLastError(ERROR_SUCCESS);
2395   ret = pEnumUILanguagesA(luilocale_proc3A, 0x5a5a5a5a, 0);
2396   ok(!ret, "Expected return value FALSE, got %u\n", ret);
2397   ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2398
2399   SetLastError(ERROR_SUCCESS);
2400   ret = pEnumUILanguagesA(NULL, 0x5a5a5a5a, 0);
2401   ok(!ret, "Expected return value FALSE, got %u\n", ret);
2402   ok(GetLastError() == ERROR_INVALID_PARAMETER,
2403       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2404 }
2405
2406 static char date_fmt_buf[1024];
2407
2408 static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
2409 {
2410     lstrcatA(date_fmt_buf, fmt);
2411     lstrcatA(date_fmt_buf, "\n");
2412     return TRUE;
2413 }
2414
2415 static void test_EnumDateFormatsA(void)
2416 {
2417     char *p, buf[256];
2418     BOOL ret;
2419     LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2420
2421     trace("EnumDateFormatsA 0\n");
2422     date_fmt_buf[0] = 0;
2423     SetLastError(0xdeadbeef);
2424     ret = EnumDateFormatsA(enum_datetime_procA, lcid, 0);
2425     if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2426     {
2427         win_skip("0 for dwFlags is not supported\n");
2428     }
2429     else
2430     {
2431         ok(ret, "EnumDateFormatsA(0) error %d\n", GetLastError());
2432         trace("%s\n", date_fmt_buf);
2433         /* test the 1st enumerated format */
2434         if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2435         ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2436         ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2437         ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2438     }
2439
2440     trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n");
2441     date_fmt_buf[0] = 0;
2442     SetLastError(0xdeadbeef);
2443     ret = EnumDateFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2444     if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2445     {
2446         win_skip("LOCALE_USE_CP_ACP is not supported\n");
2447     }
2448     else
2449     {
2450         ok(ret, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2451         trace("%s\n", date_fmt_buf);
2452         /* test the 1st enumerated format */
2453         if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2454         ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2455         ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2456         ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2457     }
2458
2459     trace("EnumDateFormatsA DATE_SHORTDATE\n");
2460     date_fmt_buf[0] = 0;
2461     ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_SHORTDATE);
2462     ok(ret, "EnumDateFormatsA(DATE_SHORTDATE) error %d\n", GetLastError());
2463     trace("%s\n", date_fmt_buf);
2464     /* test the 1st enumerated format */
2465     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2466     ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2467     ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2468     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2469
2470     trace("EnumDateFormatsA DATE_LONGDATE\n");
2471     date_fmt_buf[0] = 0;
2472     ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_LONGDATE);
2473     ok(ret, "EnumDateFormatsA(DATE_LONGDATE) error %d\n", GetLastError());
2474     trace("%s\n", date_fmt_buf);
2475     /* test the 1st enumerated format */
2476     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2477     ret = GetLocaleInfoA(lcid, LOCALE_SLONGDATE, buf, sizeof(buf));
2478     ok(ret, "GetLocaleInfoA(LOCALE_SLONGDATE) error %d\n", GetLastError());
2479     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2480
2481     trace("EnumDateFormatsA DATE_YEARMONTH\n");
2482     date_fmt_buf[0] = 0;
2483     SetLastError(0xdeadbeef);
2484     ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_YEARMONTH);
2485     if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2486     {
2487         skip("DATE_YEARMONTH is only present on W2K and later\n");
2488         return;
2489     }
2490     ok(ret, "EnumDateFormatsA(DATE_YEARMONTH) error %d\n", GetLastError());
2491     trace("%s\n", date_fmt_buf);
2492     /* test the 1st enumerated format */
2493     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2494     ret = GetLocaleInfoA(lcid, LOCALE_SYEARMONTH, buf, sizeof(buf));
2495     ok(ret, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %d\n", GetLastError());
2496     ok(!lstrcmpA(date_fmt_buf, buf) || broken(!buf[0]) /* win9x */,
2497        "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2498 }
2499
2500 static void test_EnumTimeFormatsA(void)
2501 {
2502     char *p, buf[256];
2503     BOOL ret;
2504     LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2505
2506     trace("EnumTimeFormatsA 0\n");
2507     date_fmt_buf[0] = 0;
2508     ret = EnumTimeFormatsA(enum_datetime_procA, lcid, 0);
2509     ok(ret, "EnumTimeFormatsA(0) error %d\n", GetLastError());
2510     trace("%s\n", date_fmt_buf);
2511     /* test the 1st enumerated format */
2512     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2513     ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2514     ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2515     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2516
2517     trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n");
2518     date_fmt_buf[0] = 0;
2519     ret = EnumTimeFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2520     ok(ret, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2521     trace("%s\n", date_fmt_buf);
2522     /* test the 1st enumerated format */
2523     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2524     ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2525     ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2526     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2527 }
2528
2529 static void test_GetCPInfo(void)
2530 {
2531     BOOL ret;
2532     CPINFO cpinfo;
2533
2534     SetLastError(0xdeadbeef);
2535     ret = GetCPInfo(CP_SYMBOL, &cpinfo);
2536     ok(!ret, "GetCPInfo(CP_SYMBOL) should fail\n");
2537     ok(GetLastError() == ERROR_INVALID_PARAMETER,
2538        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2539
2540     SetLastError(0xdeadbeef);
2541     ret = GetCPInfo(CP_UTF7, &cpinfo);
2542     if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2543     {
2544         skip("Codepage CP_UTF7 is not installed/available\n");
2545     }
2546     else
2547     {
2548         ok(ret, "GetCPInfo(CP_UTF7) error %u\n", GetLastError());
2549         ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2550         ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2551         ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2552         ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2553         ok(cpinfo.MaxCharSize == 5, "expected 5, got 0x%x\n", cpinfo.MaxCharSize);
2554     }
2555
2556     SetLastError(0xdeadbeef);
2557     ret = GetCPInfo(CP_UTF8, &cpinfo);
2558     if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2559     {
2560         skip("Codepage CP_UTF8 is not installed/available\n");
2561     }
2562     else
2563     {
2564         ok(ret, "GetCPInfo(CP_UTF8) error %u\n", GetLastError());
2565         ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2566         ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2567         ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2568         ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2569         ok(cpinfo.MaxCharSize == 4 || broken(cpinfo.MaxCharSize == 3) /* win9x */,
2570            "expected 4, got %u\n", cpinfo.MaxCharSize);
2571     }
2572 }
2573
2574 START_TEST(locale)
2575 {
2576   InitFunctionPointers();
2577
2578   test_EnumTimeFormatsA();
2579   test_EnumDateFormatsA();
2580   test_GetLocaleInfoA();
2581   test_GetLocaleInfoW();
2582   test_GetTimeFormatA();
2583   test_GetDateFormatA();
2584   test_GetDateFormatW();
2585   test_GetCurrencyFormatA(); /* Also tests the W version */
2586   test_GetNumberFormatA();   /* Also tests the W version */
2587   test_CompareStringA();
2588   test_LCMapStringA();
2589   test_LCMapStringW();
2590   test_FoldStringA();
2591   test_FoldStringW();
2592   test_ConvertDefaultLocale();
2593   test_EnumSystemLanguageGroupsA();
2594   test_EnumLanguageGroupLocalesA();
2595   test_SetLocaleInfoA();
2596   test_EnumUILanguageA();
2597   test_GetCPInfo();
2598   /* this requires collation table patch to make it MS compatible */
2599   if (0) test_sorting();
2600 }