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