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