wineserver: Don't use O_CREAT and O_EXCL when attempting to open directories.
[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   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
122   char buffer[BUFFER_SIZE];
123
124   ok(lcid == 0x409, "wrong LCID calculated - %d\n", lcid);
125
126   /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
127    * partially fill the buffer even if it is too short. See bug 637.
128    */
129   SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
130   ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 0);
131   ok(ret == 7 && !buffer[0], "Expected len=7, got %d\n", ret);
132
133   SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
134   ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 3);
135   ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
136       "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
137   ok(!strcmp(buffer, "Mon"), "Expected 'Mon', got '%s'\n", buffer);
138
139   SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
140   ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 10);
141   ok(ret == 7, "Expected ret == 7, got %d, error %d\n", ret, GetLastError());
142   ok(!strcmp(buffer, "Monday"), "Expected 'Monday', got '%s'\n", buffer);
143 }
144
145 static void test_GetTimeFormatA(void)
146 {
147   int ret;
148   SYSTEMTIME  curtime;
149   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
150   char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
151
152   memset(&curtime, 2, sizeof(SYSTEMTIME));
153   STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
154   SetLastError(0xdeadbeef);
155   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
156   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
157       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
158
159   curtime.wHour = 8;
160   curtime.wMinute = 56;
161   curtime.wSecond = 13;
162   curtime.wMilliseconds = 22;
163   STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
164   SetLastError(0xdeadbeef);
165   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
166   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
167   EXPECT_LENA; EXPECT_EQA;
168
169   /* MSDN: LOCALE_NOUSEROVERRIDE can't be specified with a format string */
170   SetLastError(0xdeadbeef);
171   ret = GetTimeFormatA(lcid, NUO|TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
172   ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
173      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
174
175   STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficient buffer */
176   SetLastError(0xdeadbeef);
177   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, 2);
178   ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
179       "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
180
181   STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
182   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, NULL, 0);
183   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
184   EXPECT_LENA;
185
186   STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
187   ret = GetTimeFormatA(lcid, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
188   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
189   EXPECT_LENA; EXPECT_EQA;
190
191   STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
192   ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
193   ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
194   ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "4" )), /* win9x */
195       "Expected '', got '%s'\n", buffer );
196
197   STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
198   ret = GetTimeFormatA(lcid, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
199   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
200   EXPECT_LENA; EXPECT_EQA;
201
202   STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
203   strcpy(Expected, "8:56 AM");
204   ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
205   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
206   EXPECT_LENA; EXPECT_EQA;
207
208   STRINGSA("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
209   ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
210   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
211   ok( !strcmp( buffer, "8.@:56AM" ) || broken( !strcmp( buffer, "8.@:56.@:AM" )) /* win9x */,
212       "Expected '8.@:56AM', got '%s'\n", buffer );
213
214   STRINGSA("s1s2s3", ""); /* Duplicate tokens */
215   ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
216   ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
217   ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "3" )), /* win9x */
218       "Expected '', got '%s'\n", buffer );
219
220   STRINGSA("t/tt", "A/AM"); /* AM time marker */
221   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
222   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
223   EXPECT_LENA; EXPECT_EQA;
224
225   curtime.wHour = 13;
226   STRINGSA("t/tt", "P/PM"); /* PM time marker */
227   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
228   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
229   EXPECT_LENA; EXPECT_EQA;
230
231   STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
232   ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
233   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
234   EXPECT_LENA; EXPECT_EQA;
235
236   STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
237   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
238   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
239   EXPECT_LENA; EXPECT_EQA;
240
241   STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
242   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
243   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
244   EXPECT_LENA; EXPECT_EQA;
245
246   curtime.wHour = 14; /* change this to 14 or 2pm */
247   curtime.wMinute = 5;
248   curtime.wSecond = 3;
249   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 */
250   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
251   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
252   EXPECT_LENA; EXPECT_EQA;
253
254   curtime.wHour = 0;
255   STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
256   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
257   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
258   EXPECT_LENA; EXPECT_EQA;
259
260   STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
261   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
262   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
263   EXPECT_LENA; EXPECT_EQA;
264
265   /* try to convert formatting strings with more than two letters
266    * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
267    * NOTE: We expect any letter for which there is an upper case value
268    *       we should see a replacement.  For letters that DO NOT have
269    *       upper case values we should see NO REPLACEMENT.
270    */
271   curtime.wHour = 8;
272   curtime.wMinute = 56;
273   curtime.wSecond = 13;
274   curtime.wMilliseconds = 22;
275   STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
276            "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
277   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
278   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
279   EXPECT_LENA; EXPECT_EQA;
280
281   STRINGSA("h", "text"); /* Don't write to buffer if len is 0 */
282   strcpy(buffer, "text");
283   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, 0);
284   ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
285   EXPECT_EQA;
286
287   STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
288            "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
289   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
290   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
291   EXPECT_LENA; EXPECT_EQA;
292
293   STRINGSA("'''", "'"); /* invalid quoted string */
294   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
295   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
296   EXPECT_LENA; EXPECT_EQA;
297
298   /* test that msdn suggested single quotation usage works as expected */
299   STRINGSA("''''", "'"); /* single quote mark */
300   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
301   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
302   EXPECT_LENA; EXPECT_EQA;
303
304   STRINGSA("''HHHHHH", "08"); /* Normal use */
305   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
306   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
307   EXPECT_LENA; EXPECT_EQA;
308
309   /* and test for normal use of the single quotation mark */
310   STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
311   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
312   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
313   EXPECT_LENA; EXPECT_EQA;
314
315   STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
316   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
317   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
318   EXPECT_LENA; EXPECT_EQA;
319
320   STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
321   ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
322   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
323   EXPECT_LENA; EXPECT_EQA;
324
325   curtime.wHour = 25;
326   STRINGSA("'123'tt", ""); /* Invalid time */
327   SetLastError(0xdeadbeef);
328   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
329   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
330       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
331
332   curtime.wHour = 12;
333   curtime.wMonth = 60; /* Invalid */
334   STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
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
340 static void test_GetDateFormatA(void)
341 {
342   int ret;
343   SYSTEMTIME  curtime;
344   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
345   char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
346
347   memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
348   STRINGSA("ddd',' MMM dd yy","");
349   SetLastError(0xdeadbeef);
350   ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
351   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
352       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
353
354   curtime.wYear = 2002;
355   curtime.wMonth = 5;
356   curtime.wDay = 4;
357   curtime.wDayOfWeek = 3;
358   STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
359   ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
360   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
361   EXPECT_LENA; EXPECT_EQA;
362
363   /* Same as above but with LOCALE_NOUSEROVERRIDE */
364   STRINGSA("ddd',' MMM dd yy",""); /* Simple case */
365   SetLastError(0xdeadbeef);
366   ret = GetDateFormatA(lcid, NUO, &curtime, input, buffer, COUNTOF(buffer));
367   ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
368      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
369   EXPECT_EQA;
370
371   STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
372   ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
373   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
374   EXPECT_LENA; EXPECT_EQA;
375
376   curtime.wHour = 36; /* Invalid */
377   STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
378   ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
379   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
380   EXPECT_LENA; EXPECT_EQA;
381
382   STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
383   ret = GetDateFormatA(lcid, 0, &curtime, input, NULL, 0);
384   ok(ret == 16, "Expected ret == 16, got %d, error %d\n", ret, GetLastError());
385   EXPECT_EQA;
386
387   STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
388   SetLastError(0xdeadbeef);
389   ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, 2);
390   ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
391       "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
392
393   STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
394   ret = GetDateFormat(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
395   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
396   if (strncmp(buffer, Expected, strlen(Expected)) && strncmp(buffer, "5/4/02", strlen(Expected)) != 0)
397           ok (0, "Expected '%s' or '5/4/02', got '%s'\n", Expected, buffer);
398
399   STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
400   ret = GetDateFormat(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
401   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
402   EXPECT_LENA; EXPECT_EQA;
403
404   /* test for expected DATE_YEARMONTH behavior with null format */
405   /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
406   STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
407   SetLastError(0xdeadbeef);
408   ret = GetDateFormat(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
409   ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
410      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
411   EXPECT_EQA;
412
413   /* Test that using invalid DATE_* flags results in the correct error */
414   /* and return values */
415   STRINGSA("m/d/y", ""); /* Invalid flags */
416   SetLastError(0xdeadbeef);
417   ret = GetDateFormat(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
418                       &curtime, input, buffer, COUNTOF(buffer));
419   ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
420      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
421   EXPECT_EQA;
422 }
423
424 static void test_GetDateFormatW(void)
425 {
426   int ret;
427   SYSTEMTIME  curtime;
428   WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
429   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
430
431   STRINGSW("",""); /* If flags is not zero then format must be NULL */
432   ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL,
433                        input, buffer, COUNTOF(buffer));
434   if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
435       return;
436   ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
437      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
438   EXPECT_EQW;
439
440   STRINGSW("",""); /* NULL buffer, len > 0 */
441   SetLastError(0xdeadbeef);
442   ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
443   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
444       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
445
446   STRINGSW("",""); /* NULL buffer, len == 0 */
447   ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
448   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
449   EXPECT_LENW; EXPECT_EQW;
450
451   curtime.wYear = 2002;
452   curtime.wMonth = 10;
453   curtime.wDay = 23;
454   curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
455   curtime.wHour = 65432; /* Invalid */
456   curtime.wMinute = 34512; /* Invalid */
457   curtime.wSecond = 65535; /* Invalid */
458   curtime.wMilliseconds = 12345;
459   STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
460   ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
461   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
462   EXPECT_LENW; EXPECT_EQW;
463
464   /* Limit tests */
465
466   curtime.wYear = 1601;
467   curtime.wMonth = 1;
468   curtime.wDay = 1;
469   curtime.wDayOfWeek = 0; /* Irrelevant */
470   curtime.wHour = 0;
471   curtime.wMinute = 0;
472   curtime.wSecond = 0;
473   curtime.wMilliseconds = 0;
474   STRINGSW("dddd d MMMM yyyy","Monday 1 January 1601");
475   SetLastError(0xdeadbeef);
476   ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
477   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
478   EXPECT_LENW; EXPECT_EQW;
479
480   curtime.wYear = 1600;
481   curtime.wMonth = 12;
482   curtime.wDay = 31;
483   curtime.wDayOfWeek = 0; /* Irrelevant */
484   curtime.wHour = 23;
485   curtime.wMinute = 59;
486   curtime.wSecond = 59;
487   curtime.wMilliseconds = 999;
488   STRINGSW("dddd d MMMM yyyy","Friday 31 December 1600");
489   SetLastError(0xdeadbeef);
490   ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
491   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
492       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
493 }
494
495
496 #define CY_POS_LEFT  0
497 #define CY_POS_RIGHT 1
498 #define CY_POS_LEFT_SPACE  2
499 #define CY_POS_RIGHT_SPACE 3
500
501 static void test_GetCurrencyFormatA(void)
502 {
503   static char szDot[] = { '.', '\0' };
504   static char szComma[] = { ',', '\0' };
505   static char szDollar[] = { '$', '\0' };
506   int ret;
507   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
508   char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
509   CURRENCYFMTA format;
510
511   memset(&format, 0, sizeof(format));
512
513   STRINGSA("23",""); /* NULL output, length > 0 --> Error */
514   SetLastError(0xdeadbeef);
515   ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
516   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
517       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
518
519   STRINGSA("23,53",""); /* Invalid character --> Error */
520   SetLastError(0xdeadbeef);
521   ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
522   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
523       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
524
525   STRINGSA("--",""); /* Double '-' --> Error */
526   SetLastError(0xdeadbeef);
527   ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
528   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
529       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
530
531   STRINGSA("0-",""); /* Trailing '-' --> Error */
532   SetLastError(0xdeadbeef);
533   ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
534   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
535       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
536
537   STRINGSA("0..",""); /* Double '.' --> Error */
538   SetLastError(0xdeadbeef);
539   ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
540   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
541       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
542
543   STRINGSA(" 0.1",""); /* Leading space --> Error */
544   SetLastError(0xdeadbeef);
545   ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
546   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
547       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
548
549   STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
550   SetLastError(0xdeadbeef);
551   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, 2);
552   ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
553       "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
554
555   STRINGSA("2353",""); /* Format and flags given --> Error */
556   SetLastError(0xdeadbeef);
557   ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
558   ok( !ret, "Expected ret == 0, got %d\n", ret);
559   ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
560       "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
561
562   STRINGSA("2353",""); /* Invalid format --> Error */
563   SetLastError(0xdeadbeef);
564   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
565   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
566       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
567
568   STRINGSA("2353","$2,353.00"); /* Valid number */
569   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
570   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
571   EXPECT_LENA; EXPECT_EQA;
572
573   STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
574   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
575   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
576   EXPECT_LENA; EXPECT_EQA;
577
578   STRINGSA("2353.1","$2,353.10"); /* Valid real number */
579   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
580   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
581   EXPECT_LENA; EXPECT_EQA;
582
583   STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
584   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
585   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
586   EXPECT_LENA; EXPECT_EQA;
587
588   STRINGSA("2353.119","$2,353.12");  /* Too many DP --> Rounded */
589   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
590   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
591   EXPECT_LENA; EXPECT_EQA;
592
593   format.NumDigits = 0; /* No decimal separator */
594   format.LeadingZero = 0;
595   format.Grouping = 0;  /* No grouping char */
596   format.NegativeOrder = 0;
597   format.PositiveOrder = CY_POS_LEFT;
598   format.lpDecimalSep = szDot;
599   format.lpThousandSep = szComma;
600   format.lpCurrencySymbol = szDollar;
601
602   STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
603   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
604   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
605   EXPECT_LENA; EXPECT_EQA;
606
607   format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
608   STRINGSA("2353","$2353.0");
609   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
610   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
611   EXPECT_LENA; EXPECT_EQA;
612
613   format.Grouping = 2; /* Group by 100's */
614   STRINGSA("2353","$23,53.0");
615   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
616   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
617   EXPECT_LENA; EXPECT_EQA;
618
619   format.LeadingZero = 1; /* Always provide leading zero */
620   STRINGSA(".5","$0.5");
621   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
622   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
623   EXPECT_LENA; EXPECT_EQA;
624
625   format.PositiveOrder = CY_POS_RIGHT;
626   STRINGSA("1","1.0$");
627   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
628   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
629   EXPECT_LENA; EXPECT_EQA;
630
631   format.PositiveOrder = CY_POS_LEFT_SPACE;
632   STRINGSA("1","$ 1.0");
633   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
634   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
635   EXPECT_LENA; EXPECT_EQA;
636
637   format.PositiveOrder = CY_POS_RIGHT_SPACE;
638   STRINGSA("1","1.0 $");
639   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
640   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
641   EXPECT_LENA; EXPECT_EQA;
642
643   format.NegativeOrder = 0;
644   STRINGSA("-1","($1.0)");
645   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
646   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
647   EXPECT_LENA; EXPECT_EQA;
648
649   format.NegativeOrder = 1;
650   STRINGSA("-1","-$1.0");
651   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
652   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
653   EXPECT_LENA; EXPECT_EQA;
654
655   format.NegativeOrder = 2;
656   STRINGSA("-1","$-1.0");
657   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
658   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
659   EXPECT_LENA; EXPECT_EQA;
660
661   format.NegativeOrder = 3;
662   STRINGSA("-1","$1.0-");
663   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
664   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
665   EXPECT_LENA; EXPECT_EQA;
666
667   format.NegativeOrder = 4;
668   STRINGSA("-1","(1.0$)");
669   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
670   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
671   EXPECT_LENA; EXPECT_EQA;
672
673   format.NegativeOrder = 5;
674   STRINGSA("-1","-1.0$");
675   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
676   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
677   EXPECT_LENA; EXPECT_EQA;
678
679   format.NegativeOrder = 6;
680   STRINGSA("-1","1.0-$");
681   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
682   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
683   EXPECT_LENA; EXPECT_EQA;
684
685   format.NegativeOrder = 7;
686   STRINGSA("-1","1.0$-");
687   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
688   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
689   EXPECT_LENA; EXPECT_EQA;
690
691   format.NegativeOrder = 8;
692   STRINGSA("-1","-1.0 $");
693   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
694   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
695   EXPECT_LENA; EXPECT_EQA;
696
697   format.NegativeOrder = 9;
698   STRINGSA("-1","-$ 1.0");
699   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
700   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
701   EXPECT_LENA; EXPECT_EQA;
702
703   format.NegativeOrder = 10;
704   STRINGSA("-1","1.0 $-");
705   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
706   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
707   EXPECT_LENA; EXPECT_EQA;
708
709   format.NegativeOrder = 11;
710   STRINGSA("-1","$ 1.0-");
711   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
712   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
713   EXPECT_LENA; EXPECT_EQA;
714
715   format.NegativeOrder = 12;
716   STRINGSA("-1","$ -1.0");
717   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
718   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
719   EXPECT_LENA; EXPECT_EQA;
720
721   format.NegativeOrder = 13;
722   STRINGSA("-1","1.0- $");
723   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
724   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
725   EXPECT_LENA; EXPECT_EQA;
726
727   format.NegativeOrder = 14;
728   STRINGSA("-1","($ 1.0)");
729   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
730   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
731   EXPECT_LENA; EXPECT_EQA;
732
733   format.NegativeOrder = 15;
734   STRINGSA("-1","(1.0 $)");
735   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
736   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
737   EXPECT_LENA; EXPECT_EQA;
738 }
739
740 #define NEG_PARENS      0 /* "(1.1)" */
741 #define NEG_LEFT        1 /* "-1.1"  */
742 #define NEG_LEFT_SPACE  2 /* "- 1.1" */
743 #define NEG_RIGHT       3 /* "1.1-"  */
744 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
745
746 static void test_GetNumberFormatA(void)
747 {
748   static char szDot[] = { '.', '\0' };
749   static char szComma[] = { ',', '\0' };
750   int ret;
751   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
752   char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
753   NUMBERFMTA format;
754
755   memset(&format, 0, sizeof(format));
756
757   STRINGSA("23",""); /* NULL output, length > 0 --> Error */
758   SetLastError(0xdeadbeef);
759   ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
760   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
761       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
762
763   STRINGSA("23,53",""); /* Invalid character --> Error */
764   SetLastError(0xdeadbeef);
765   ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
766   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
767       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
768
769   STRINGSA("--",""); /* Double '-' --> Error */
770   SetLastError(0xdeadbeef);
771   ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
772   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
773       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
774
775   STRINGSA("0-",""); /* Trailing '-' --> Error */
776   SetLastError(0xdeadbeef);
777   ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
778   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
779       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
780
781   STRINGSA("0..",""); /* Double '.' --> Error */
782   SetLastError(0xdeadbeef);
783   ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
784   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
785       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
786
787   STRINGSA(" 0.1",""); /* Leading space --> Error */
788   SetLastError(0xdeadbeef);
789   ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
790   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
791       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
792
793   STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
794   SetLastError(0xdeadbeef);
795   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, 2);
796   ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
797       "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
798
799   STRINGSA("2353",""); /* Format and flags given --> Error */
800   SetLastError(0xdeadbeef);
801   ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
802   ok( !ret, "Expected ret == 0, got %d\n", ret);
803   ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
804       "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
805
806   STRINGSA("2353",""); /* Invalid format --> Error */
807   SetLastError(0xdeadbeef);
808   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
809   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
810       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
811
812   STRINGSA("2353","2,353.00"); /* Valid number */
813   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
814   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
815   EXPECT_LENA; EXPECT_EQA;
816
817   STRINGSA("-2353","-2,353.00"); /* Valid negative number */
818   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
819   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
820   EXPECT_LENA; EXPECT_EQA;
821
822   STRINGSA("-353","-353.00"); /* test for off by one error in grouping */
823   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
824   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
825   EXPECT_LENA; EXPECT_EQA;
826
827   STRINGSA("2353.1","2,353.10"); /* Valid real number */
828   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
829   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
830   EXPECT_LENA; EXPECT_EQA;
831
832   STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
833   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
834   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
835   EXPECT_LENA; EXPECT_EQA;
836
837   STRINGSA("2353.119","2,353.12");  /* Too many DP --> Rounded */
838   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
839   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
840   EXPECT_LENA; EXPECT_EQA;
841
842   format.NumDigits = 0; /* No decimal separator */
843   format.LeadingZero = 0;
844   format.Grouping = 0;  /* No grouping char */
845   format.NegativeOrder = 0;
846   format.lpDecimalSep = szDot;
847   format.lpThousandSep = szComma;
848
849   STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
850   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
851   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
852   EXPECT_LENA; EXPECT_EQA;
853
854   format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
855   STRINGSA("2353","2353.0");
856   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
857   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
858   EXPECT_LENA; EXPECT_EQA;
859
860   format.Grouping = 2; /* Group by 100's */
861   STRINGSA("2353","23,53.0");
862   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
863   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
864   EXPECT_LENA; EXPECT_EQA;
865
866   format.LeadingZero = 1; /* Always provide leading zero */
867   STRINGSA(".5","0.5");
868   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
869   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
870   EXPECT_LENA; EXPECT_EQA;
871
872   format.NegativeOrder = NEG_PARENS;
873   STRINGSA("-1","(1.0)");
874   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
875   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
876   EXPECT_LENA; EXPECT_EQA;
877
878   format.NegativeOrder = NEG_LEFT;
879   STRINGSA("-1","-1.0");
880   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
881   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
882   EXPECT_LENA; EXPECT_EQA;
883
884   format.NegativeOrder = NEG_LEFT_SPACE;
885   STRINGSA("-1","- 1.0");
886   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
887   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
888   EXPECT_LENA; EXPECT_EQA;
889
890   format.NegativeOrder = NEG_RIGHT;
891   STRINGSA("-1","1.0-");
892   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
893   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
894   EXPECT_LENA; EXPECT_EQA;
895
896   format.NegativeOrder = NEG_RIGHT_SPACE;
897   STRINGSA("-1","1.0 -");
898   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
899   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
900   EXPECT_LENA; EXPECT_EQA;
901
902   lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
903
904   if (IsValidLocale(lcid, 0))
905   {
906     STRINGSA("-12345","-12 345,00"); /* Try French formatting */
907     Expected[3] = 160; /* Non breaking space */
908     ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
909     ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
910     EXPECT_LENA; EXPECT_EQA;
911   }
912 }
913
914
915 static void test_CompareStringA(void)
916 {
917   int ret;
918   LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
919
920   ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
921   ok (ret== 1, "(Salut/Salute) Expected 1, got %d\n", ret);
922
923   ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
924   ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
925
926   ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
927   ok (ret== 3, "(Salut/hola) Expected 3, got %d\n", ret);
928
929   ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
930   ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
931
932   lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
933
934   ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
935   ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
936
937   ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
938   ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
939
940     ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
941     ok (ret == 2, "(Salut/saLuT) Expected 2, got %d\n", ret);
942
943     /* test for CompareStringA flags */
944     SetLastError(0xdeadbeef);
945     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0x8, "NULL", -1, "NULL", -1);
946     ok(GetLastError() == ERROR_INVALID_FLAGS,
947         "unexpected error code %d\n", GetLastError());
948     ok(!ret, "CompareStringA must fail with invalid flag\n");
949
950     SetLastError(0xdeadbeef);
951     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, LOCALE_USE_CP_ACP, "NULL", -1, "NULL", -1);
952     ok(GetLastError() == 0xdeadbeef, "unexpected error code %d\n", GetLastError());
953     ok(ret == CSTR_EQUAL, "CompareStringA error: %d != CSTR_EQUAL\n", ret);
954     /* end of test for CompareStringA flags */
955
956     ret = lstrcmpA("", "");
957     ok (ret == 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret);
958
959     ret = lstrcmpA(NULL, NULL);
960     ok (ret == 0 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, NULL) should return 0, got %d\n", ret);
961
962     ret = lstrcmpA("", NULL);
963     ok (ret == 1 || broken(ret == -2) /* win9x */, "lstrcmpA(\"\", NULL) should return 1, got %d\n", ret);
964
965     ret = lstrcmpA(NULL, "");
966     ok (ret == -1 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret);
967  
968     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"EndDialog",-1,"_Property",-1);
969     ok( ret == 3, "EndDialog vs _Property ... expected 3, got %d\n", ret);
970
971     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0070",-1,"_IEWWBrowserComp",-1);
972     ok( ret == 3, "osp_vba.sreg0070 vs _IEWWBrowserComp ... expected 3, got %d\n", ret);
973
974     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"r",-1,"\\",-1); 
975     ok( ret == 3, "r vs \\ ... expected 3, got %d\n", ret);
976
977     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0031", -1, "OriginalDatabase", -1 );
978     ok( ret == 3, "osp_vba.sreg0031 vs OriginalDatabase ... expected 3, got %d\n", ret);
979
980     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1 );
981     ok( ret == 3, "AAA vs aaa expected 3, got %d\n", ret);
982
983     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1 );
984     ok( ret == 1, "AAA vs aab expected 1, got %d\n", ret);
985
986     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1 );
987     ok( ret == 1, "AAA vs Aab expected 1, got %d\n", ret);
988
989     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1 );
990     ok( ret == 1, ".AAA vs Aab expected 1, got %d\n", ret);
991
992     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1 );
993     ok( ret == 1, ".AAA vs A.ab expected 1, got %d\n", ret);
994
995     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1 );
996     ok( ret == 1, "aa vs AB expected 1, got %d\n", ret);
997
998     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1 );
999     ok( ret == 1, "aa vs Aab expected 1, got %d\n", ret);
1000
1001     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1 );
1002     ok( ret == 3, "aB vs Aab expected 3, got %d\n", ret);
1003
1004     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1 );
1005     ok( ret == 1, "Ba vs bab expected 1, got %d\n", ret);
1006
1007     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1 );
1008     ok( ret == 1, "{100}{83}{71}{71}{71} vs Global_DataAccess_JRO expected 1, got %d\n", ret);
1009
1010     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1 );
1011     ok( ret == 3, "a vs { expected 3, got %d\n", ret);
1012
1013     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1 );
1014     ok( ret == 3, "A vs { expected 3, got %d\n", ret);
1015
1016     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1 );
1017     ok(ret == 1, "3.5/0 vs 4.0/-1 expected 1, got %d\n", ret);
1018
1019     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1 );
1020     ok(ret == 1, "3.5 vs 4.0 expected 1, got %d\n", ret);
1021
1022     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1 );
1023     ok(ret == 1, "3.520.4403.2 vs 4.0.2927.10 expected 1, got %d\n", ret);
1024
1025    /* hyphen and apostrophe are treated differently depending on
1026     * whether SORT_STRINGSORT specified or not
1027     */
1028     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1 );
1029     ok(ret == 3, "-o vs /m expected 3, got %d\n", ret);
1030
1031     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1 );
1032     ok(ret == 1, "/m vs -o expected 1, got %d\n", ret);
1033
1034     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1 );
1035     ok(ret == 1, "-o vs /m expected 1, got %d\n", ret);
1036
1037     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1 );
1038     ok(ret == 3, "/m vs -o expected 3, got %d\n", ret);
1039
1040     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1 );
1041     ok(ret == 3, "'o vs /m expected 3, got %d\n", ret);
1042
1043     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1 );
1044     ok(ret == 1, "/m vs 'o expected 1, got %d\n", ret);
1045
1046     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1 );
1047     ok(ret == 1, "'o vs /m expected 1, got %d\n", ret);
1048
1049     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1 );
1050     ok(ret == 3, "/m vs 'o expected 3, got %d\n", ret);
1051
1052     if (0) { /* this requires collation table patch to make it MS compatible */
1053     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
1054     ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
1055
1056     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
1057     ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
1058
1059     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
1060     ok(ret == 1, "' vs - expected 1, got %d\n", ret);
1061
1062     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
1063     ok(ret == 1, "' vs - expected 1, got %d\n", ret);
1064
1065     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
1066     ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
1067
1068     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
1069     ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
1070
1071     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
1072     ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
1073
1074     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
1075     ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
1076
1077     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
1078     ok(ret == 1, "`o vs -m expected 1, got %d\n", ret);
1079
1080     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
1081     ok(ret == 3, "-m vs `o expected 3, got %d\n", ret);
1082
1083     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
1084     ok(ret == 3, "`o vs -m expected 3, got %d\n", ret);
1085
1086     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
1087     ok(ret == 1, "-m vs `o expected 1, got %d\n", ret);
1088     }
1089
1090     ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9);
1091     ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0 expected 2, got %d\n", ret);
1092
1093     ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10);
1094     ok(ret == 1, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1, got %d\n", ret);
1095
1096     /* WinXP handles embedded NULLs differently than earlier versions */
1097     ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
1098     ok(ret == 1 || ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1 or 2, got %d\n", ret);
1099
1100     ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
1101     ok(ret == 1 || ret == 2, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected 1 or 2, got %d\n", ret);
1102
1103     ret = CompareStringA(lcid, 0, "a\0b", -1, "a", -1);
1104     ok(ret == 2, "a vs a expected 2, got %d\n", ret);
1105
1106     ret = CompareStringA(lcid, 0, "a\0b", 4, "a", 2);
1107     ok(ret == CSTR_EQUAL || /* win2k */
1108        ret == CSTR_GREATER_THAN,
1109        "a\\0b vs a expected CSTR_EQUAL or CSTR_GREATER_THAN, got %d\n", ret);
1110
1111     ret = CompareStringA(lcid, 0, "\2", 2, "\1", 2);
1112     todo_wine ok(ret != 2, "\\2 vs \\1 expected unequal\n");
1113 }
1114
1115 static void test_LCMapStringA(void)
1116 {
1117     int ret, ret2;
1118     char buf[256], buf2[256];
1119     static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
1120     static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
1121     static const char symbols_stripped[] = "justateststring1";
1122
1123     SetLastError(0xdeadbeef);
1124     ret = LCMapStringA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP | LCMAP_LOWERCASE,
1125                        lower_case, -1, buf, sizeof(buf));
1126     ok(ret == lstrlenA(lower_case) + 1,
1127        "ret %d, error %d, expected value %d\n",
1128        ret, GetLastError(), lstrlenA(lower_case) + 1);
1129     ok(!memcmp(buf, lower_case, ret), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1130
1131     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1132                        upper_case, -1, buf, sizeof(buf));
1133     ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1134     ok(GetLastError() == ERROR_INVALID_FLAGS,
1135        "unexpected error code %d\n", GetLastError());
1136
1137     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1138                        upper_case, -1, buf, sizeof(buf));
1139     ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1140     ok(GetLastError() == ERROR_INVALID_FLAGS,
1141        "unexpected error code %d\n", GetLastError());
1142
1143     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1144                        upper_case, -1, buf, sizeof(buf));
1145     ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1146     ok(GetLastError() == ERROR_INVALID_FLAGS,
1147        "unexpected error code %d\n", GetLastError());
1148
1149     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1150                        upper_case, -1, buf, sizeof(buf));
1151     ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1152     ok(GetLastError() == ERROR_INVALID_FLAGS,
1153        "unexpected error code %d\n", GetLastError());
1154
1155     /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1156     SetLastError(0xdeadbeef);
1157     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1158                        upper_case, -1, buf, sizeof(buf));
1159     ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1160     ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1161
1162     /* test LCMAP_LOWERCASE */
1163     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1164                        upper_case, -1, buf, sizeof(buf));
1165     ok(ret == lstrlenA(upper_case) + 1,
1166        "ret %d, error %d, expected value %d\n",
1167        ret, GetLastError(), lstrlenA(upper_case) + 1);
1168     ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1169
1170     /* test LCMAP_UPPERCASE */
1171     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1172                        lower_case, -1, buf, sizeof(buf));
1173     ok(ret == lstrlenA(lower_case) + 1,
1174        "ret %d, error %d, expected value %d\n",
1175        ret, GetLastError(), lstrlenA(lower_case) + 1);
1176     ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1177
1178     /* test buffer overflow */
1179     SetLastError(0xdeadbeef);
1180     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1181                        lower_case, -1, buf, 4);
1182     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1183        "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1184
1185     /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1186     lstrcpyA(buf, lower_case);
1187     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1188                        buf, -1, buf, sizeof(buf));
1189     if (!ret) /* Win9x */
1190         trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1191     else
1192     {
1193         ok(ret == lstrlenA(lower_case) + 1,
1194            "ret %d, error %d, expected value %d\n",
1195            ret, GetLastError(), lstrlenA(lower_case) + 1);
1196         ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1197     }
1198     lstrcpyA(buf, upper_case);
1199     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1200                        buf, -1, buf, sizeof(buf));
1201     if (!ret) /* Win9x */
1202         trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1203     else
1204     {
1205         ok(ret == lstrlenA(upper_case) + 1,
1206            "ret %d, error %d, expected value %d\n",
1207            ret, GetLastError(), lstrlenA(lower_case) + 1);
1208         ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1209     }
1210
1211     /* otherwise src == dst should fail */
1212     SetLastError(0xdeadbeef);
1213     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1214                        buf, 10, buf, sizeof(buf));
1215     ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1216        GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1217        "unexpected error code %d\n", GetLastError());
1218     ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1219
1220     /* test whether '\0' is always appended */
1221     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1222                        upper_case, -1, buf, sizeof(buf));
1223     ok(ret, "LCMapStringA must succeed\n");
1224     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1225                        upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1226     ok(ret, "LCMapStringA must succeed\n");
1227     ok(ret == ret2, "lengths of sort keys must be equal\n");
1228     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1229
1230     /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1231     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1232                        upper_case, -1, buf, sizeof(buf));
1233     ok(ret, "LCMapStringA must succeed\n");
1234     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1235                        lower_case, -1, buf2, sizeof(buf2));
1236     ok(ret2, "LCMapStringA must succeed\n");
1237     ok(ret == ret2, "lengths of sort keys must be equal\n");
1238     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1239
1240     /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1241     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1242                        lower_case, -1, buf, sizeof(buf));
1243     ok(ret, "LCMapStringA must succeed\n");
1244     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1245                        lower_case, -1, buf2, sizeof(buf2));
1246     ok(ret2, "LCMapStringA must succeed\n");
1247     ok(ret == ret2, "lengths of sort keys must be equal\n");
1248     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1249
1250     /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1251     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1252                        lower_case, -1, buf, sizeof(buf));
1253     ok(ret, "LCMapStringA must succeed\n");
1254     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1255                        symbols_stripped, -1, buf2, sizeof(buf2));
1256     ok(ret2, "LCMapStringA must succeed\n");
1257     ok(ret == ret2, "lengths of sort keys must be equal\n");
1258     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1259
1260     /* test NORM_IGNORENONSPACE */
1261     lstrcpyA(buf, "foo");
1262     ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1263                        lower_case, -1, buf, sizeof(buf));
1264     ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1265         lstrlenA(lower_case) + 1, ret);
1266     ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1267
1268     /* test NORM_IGNORESYMBOLS */
1269     lstrcpyA(buf, "foo");
1270     ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1271                        lower_case, -1, buf, sizeof(buf));
1272     ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1273         lstrlenA(symbols_stripped) + 1, ret);
1274     ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1275
1276     /* test srclen = 0 */
1277     SetLastError(0xdeadbeef);
1278     ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1279     ok(!ret, "LCMapStringA should fail with srclen = 0\n");
1280     ok(GetLastError() == ERROR_INVALID_PARAMETER,
1281        "unexpected error code %d\n", GetLastError());
1282 }
1283
1284 static void test_LCMapStringW(void)
1285 {
1286     int ret, ret2;
1287     WCHAR buf[256], buf2[256];
1288     char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1289     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};
1290     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};
1291     static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
1292     static const WCHAR fooW[] = {'f','o','o',0};
1293
1294     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1295                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1296     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1297     {
1298         win_skip("LCMapStringW is not implemented\n");
1299         return;
1300     }
1301     ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1302     ok(GetLastError() == ERROR_INVALID_FLAGS,
1303        "unexpected error code %d\n", GetLastError());
1304
1305     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1306                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1307     ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1308     ok(GetLastError() == ERROR_INVALID_FLAGS,
1309        "unexpected error code %d\n", GetLastError());
1310
1311     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1312                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1313     ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1314     ok(GetLastError() == ERROR_INVALID_FLAGS,
1315        "unexpected error code %d\n", GetLastError());
1316
1317     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1318                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1319     ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1320     ok(GetLastError() == ERROR_INVALID_FLAGS,
1321        "unexpected error code %d\n", GetLastError());
1322
1323     /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1324     SetLastError(0xdeadbeef);
1325     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1326                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1327     ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1328     ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1329
1330     /* test LCMAP_LOWERCASE */
1331     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1332                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1333     ok(ret == lstrlenW(upper_case) + 1,
1334        "ret %d, error %d, expected value %d\n",
1335        ret, GetLastError(), lstrlenW(upper_case) + 1);
1336     ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1337
1338     /* test LCMAP_UPPERCASE */
1339     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1340                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1341     ok(ret == lstrlenW(lower_case) + 1,
1342        "ret %d, error %d, expected value %d\n",
1343        ret, GetLastError(), lstrlenW(lower_case) + 1);
1344     ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1345
1346     /* test buffer overflow */
1347     SetLastError(0xdeadbeef);
1348     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1349                        lower_case, -1, buf, 4);
1350     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1351        "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1352
1353     /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1354     lstrcpyW(buf, lower_case);
1355     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1356                        buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1357     ok(ret == lstrlenW(lower_case) + 1,
1358        "ret %d, error %d, expected value %d\n",
1359        ret, GetLastError(), lstrlenW(lower_case) + 1);
1360     ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1361
1362     lstrcpyW(buf, upper_case);
1363     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1364                        buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1365     ok(ret == lstrlenW(upper_case) + 1,
1366        "ret %d, error %d, expected value %d\n",
1367        ret, GetLastError(), lstrlenW(lower_case) + 1);
1368     ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1369
1370     /* otherwise src == dst should fail */
1371     SetLastError(0xdeadbeef);
1372     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1373                        buf, 10, buf, sizeof(buf));
1374     ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1375        GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1376        "unexpected error code %d\n", GetLastError());
1377     ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1378
1379     /* test whether '\0' is always appended */
1380     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1381                        upper_case, -1, buf, sizeof(buf));
1382     ok(ret, "LCMapStringW must succeed\n");
1383     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1384                        upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1385     ok(ret, "LCMapStringW must succeed\n");
1386     ok(ret == ret2, "lengths of sort keys must be equal\n");
1387     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1388
1389     /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1390     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1391                        upper_case, -1, buf, sizeof(buf));
1392     ok(ret, "LCMapStringW must succeed\n");
1393     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1394                        lower_case, -1, buf2, sizeof(buf2));
1395     ok(ret2, "LCMapStringW must succeed\n");
1396     ok(ret == ret2, "lengths of sort keys must be equal\n");
1397     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1398
1399     /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1400     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1401                        lower_case, -1, buf, sizeof(buf));
1402     ok(ret, "LCMapStringW must succeed\n");
1403     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1404                        lower_case, -1, buf2, sizeof(buf2));
1405     ok(ret2, "LCMapStringW must succeed\n");
1406     ok(ret == ret2, "lengths of sort keys must be equal\n");
1407     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1408
1409     /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1410     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1411                        lower_case, -1, buf, sizeof(buf));
1412     ok(ret, "LCMapStringW must succeed\n");
1413     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1414                        symbols_stripped, -1, buf2, sizeof(buf2));
1415     ok(ret2, "LCMapStringW must succeed\n");
1416     ok(ret == ret2, "lengths of sort keys must be equal\n");
1417     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1418
1419     /* test NORM_IGNORENONSPACE */
1420     lstrcpyW(buf, fooW);
1421     ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1422                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1423     ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1424         lstrlenW(lower_case) + 1, ret);
1425     ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1426
1427     /* test NORM_IGNORESYMBOLS */
1428     lstrcpyW(buf, fooW);
1429     ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1430                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1431     ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1432         lstrlenW(symbols_stripped) + 1, ret);
1433     ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1434
1435     /* test srclen = 0 */
1436     SetLastError(0xdeadbeef);
1437     ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf)/sizeof(WCHAR));
1438     ok(!ret, "LCMapStringW should fail with srclen = 0\n");
1439     ok(GetLastError() == ERROR_INVALID_PARAMETER,
1440        "unexpected error code %d\n", GetLastError());
1441 }
1442
1443 /* this requires collation table patch to make it MS compatible */
1444 static const char * const strings_sorted[] =
1445 {
1446 "'",
1447 "-",
1448 "!",
1449 "\"",
1450 ".",
1451 ":",
1452 "\\",
1453 "_",
1454 "`",
1455 "{",
1456 "}",
1457 "+",
1458 "0",
1459 "1",
1460 "2",
1461 "3",
1462 "4",
1463 "5",
1464 "6",
1465 "7",
1466 "8",
1467 "9",
1468 "a",
1469 "A",
1470 "b",
1471 "B",
1472 "c",
1473 "C"
1474 };
1475
1476 static const char * const strings[] =
1477 {
1478 "C",
1479 "\"",
1480 "9",
1481 "'",
1482 "}",
1483 "-",
1484 "7",
1485 "+",
1486 "`",
1487 "1",
1488 "a",
1489 "5",
1490 "\\",
1491 "8",
1492 "B",
1493 "3",
1494 "_",
1495 "6",
1496 "{",
1497 "2",
1498 "c",
1499 "4",
1500 "!",
1501 "0",
1502 "A",
1503 ":",
1504 "b",
1505 "."
1506 };
1507
1508 static int compare_string1(const void *e1, const void *e2)
1509 {
1510     const char *s1 = *(const char *const *)e1;
1511     const char *s2 = *(const char *const *)e2;
1512
1513     return lstrcmpA(s1, s2);
1514 }
1515
1516 static int compare_string2(const void *e1, const void *e2)
1517 {
1518     const char *s1 = *(const char *const *)e1;
1519     const char *s2 = *(const char *const *)e2;
1520
1521     return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1522 }
1523
1524 static int compare_string3(const void *e1, const void *e2)
1525 {
1526     const char *s1 = *(const char *const *)e1;
1527     const char *s2 = *(const char *const *)e2;
1528     char key1[256], key2[256];
1529
1530     LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
1531     LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
1532     return strcmp(key1, key2);
1533 }
1534
1535 static void test_sorting(void)
1536 {
1537     char buf[256];
1538     char **str_buf = (char **)buf;
1539     int i;
1540
1541     assert(sizeof(buf) >= sizeof(strings));
1542
1543     /* 1. sort using lstrcmpA */
1544     memcpy(buf, strings, sizeof(strings));
1545     qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
1546     for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1547     {
1548         ok(!strcmp(strings_sorted[i], str_buf[i]),
1549            "qsort using lstrcmpA failed for element %d\n", i);
1550     }
1551     /* 2. sort using CompareStringA */
1552     memcpy(buf, strings, sizeof(strings));
1553     qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
1554     for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1555     {
1556         ok(!strcmp(strings_sorted[i], str_buf[i]),
1557            "qsort using CompareStringA failed for element %d\n", i);
1558     }
1559     /* 3. sort using sort keys */
1560     memcpy(buf, strings, sizeof(strings));
1561     qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
1562     for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1563     {
1564         ok(!strcmp(strings_sorted[i], str_buf[i]),
1565            "qsort using sort keys failed for element %d\n", i);
1566     }
1567 }
1568
1569 static void test_FoldStringA(void)
1570 {
1571   int ret, i;
1572   char src[256], dst[256];
1573   static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0'  };
1574   static const char digits_dst[] = { '1','2','3','\0'  };
1575   static const char composite_src[] =
1576   {
1577     0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
1578     0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
1579     0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
1580     0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
1581     0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
1582     0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
1583     0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
1584     0xfb,0xfc,0xfd,0xff,'\0'
1585   };
1586   static const char composite_dst[] =
1587   {
1588     0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1589     0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1590     0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1591     0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1592     0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1593     0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1594     0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
1595     0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
1596     0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
1597     0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
1598     0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
1599     0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
1600     0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
1601     0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
1602     0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1603   };
1604   static const char ligatures_src[] =
1605   {
1606     0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1607   };
1608   static const char ligatures_dst[] =
1609   {
1610     'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1611   };
1612
1613   if (!pFoldStringA)
1614     return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1615
1616   /* these tests are locale specific */
1617   if (GetACP() != 1252)
1618   {
1619       trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1620       return;
1621   }
1622
1623   /* MAP_FOLDDIGITS */
1624   SetLastError(0);
1625   ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
1626   if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1627     return;
1628   ok(ret == 4, "Expected ret == 4, got %d, error %d\n", ret, GetLastError());
1629   ok(strcmp(dst, digits_dst) == 0,
1630      "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
1631   for (i = 1; i < 256; i++)
1632   {
1633     if (!strchr(digits_src, i))
1634     {
1635       src[0] = i;
1636       src[1] = '\0';
1637       SetLastError(0);
1638       ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
1639       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1640       ok(dst[0] == src[0],
1641          "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
1642     }
1643   }
1644
1645   /* MAP_EXPAND_LIGATURES */
1646   SetLastError(0);
1647   ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1648   /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1649   if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1650     ok(ret == sizeof(ligatures_dst), "Got %d, error %d\n", ret, GetLastError());
1651     ok(strcmp(dst, ligatures_dst) == 0,
1652        "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
1653     for (i = 1; i < 256; i++)
1654     {
1655       if (!strchr(ligatures_src, i))
1656       {
1657         src[0] = i;
1658         src[1] = '\0';
1659         SetLastError(0);
1660         ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1661         ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1662         ok(dst[0] == src[0],
1663            "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
1664       }
1665     }
1666   }
1667
1668   /* MAP_COMPOSITE */
1669   SetLastError(0);
1670   ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
1671   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1672   todo_wine
1673   {
1674     /* Wine gets close, but doesn't produce quite the same result as native */
1675     ok(ret == 121, "Expected 121, got %d\n", ret);
1676     ok(strcmp(dst, composite_dst) == 0,
1677        "MAP_COMPOSITE: Expected '%s', got '%s'\n", composite_dst, dst);
1678   }
1679
1680   for (i = 1; i < 256; i++)
1681   {
1682     if (!strchr(composite_src, i))
1683     {
1684       src[0] = i;
1685       src[1] = '\0';
1686       SetLastError(0);
1687       ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
1688       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1689       ok(dst[0] == src[0],
1690          "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
1691          (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
1692     }
1693   }
1694
1695   /* MAP_FOLDCZONE */
1696   for (i = 1; i < 256; i++)
1697   {
1698     src[0] = i;
1699     src[1] = '\0';
1700     SetLastError(0);
1701     ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
1702     ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1703     ok(src[0] == dst[0],
1704        "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
1705        (unsigned char)src[0], (unsigned char)dst[0]);
1706   }
1707
1708   /* MAP_PRECOMPOSED */
1709   for (i = 1; i < 256; i++)
1710   {
1711     src[0] = i;
1712     src[1] = '\0';
1713     SetLastError(0);
1714     ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
1715     ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1716     ok(src[0] == dst[0],
1717        "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
1718        (unsigned char)src[0], (unsigned char)dst[0]);
1719   }
1720 }
1721
1722 static void test_FoldStringW(void)
1723 {
1724   int ret;
1725   unsigned int i, j, failures;
1726   WCHAR src[256], dst[256], ch, prev_ch = 1;
1727   static const DWORD badFlags[] =
1728   {
1729     0,
1730     MAP_PRECOMPOSED|MAP_COMPOSITE,
1731     MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
1732     MAP_COMPOSITE|MAP_EXPAND_LIGATURES
1733   };
1734   /* Ranges of digits 0-9 : Must be sorted! */
1735   static const WCHAR digitRanges[] =
1736   {
1737     0x0030, /* '0'-'9' */
1738     0x0660, /* Eastern Arabic */
1739     0x06F0, /* Arabic - Hindu */
1740     0x0966, /* Devengari */
1741     0x09E6, /* Bengalii */
1742     0x0A66, /* Gurmukhi */
1743     0x0AE6, /* Gujarati */
1744     0x0B66, /* Oriya */
1745     0x0BE6, /* Tamil - No 0 */
1746     0x0C66, /* Telugu */
1747     0x0CE6, /* Kannada */
1748     0x0D66, /* Maylayalam */
1749     0x0E50, /* Thai */
1750     0x0ED0, /* Laos */
1751     0x2070, /* Superscript - 1, 2, 3 are out of sequence */
1752     0x2080, /* Subscript */
1753     0x245F, /* Circled - 0 is out of sequence */
1754     0x2473, /* Bracketed */
1755     0x2487, /* Full stop */
1756     0x2775, /* Inverted circled - No 0 */
1757     0x277F, /* Patterned circled - No 0 */
1758     0x2789, /* Inverted Patterned circled - No 0 */
1759     0xff10, /* Pliene chasse (?) */
1760     0xffff  /* Terminator */
1761   };
1762   /* Digits which are represented, but out of sequence */
1763   static const WCHAR outOfSequenceDigits[] =
1764   {
1765       0xB9,   /* Superscript 1 */
1766       0xB2,   /* Superscript 2 */
1767       0xB3,   /* Superscript 3 */
1768       0x24EA, /* Circled 0 */
1769       '\0'    /* Terminator */
1770   };
1771   /* Digits in digitRanges for which no representation is available */
1772   static const WCHAR noDigitAvailable[] =
1773   {
1774       0x0BE6, /* No Tamil 0 */
1775       0x2473, /* No Bracketed 0 */
1776       0x2487, /* No 0 Full stop */
1777       0x2775, /* No inverted circled 0 */
1778       0x277F, /* No patterned circled */
1779       0x2789, /* No inverted Patterned circled */
1780       '\0'    /* Terminator */
1781   };
1782   /* Compatibility conversion results */
1783   static const WCHAR compat_F900_FA2F[256+48] =
1784   {
1785       0x8c48, 0x66f4, 0x8eca, 0x8cc8, 0x6ed1, 0x4e32, 0x53e5, 0x9f9c,
1786       0x9f9c, 0x5951, 0x91d1, 0x5587, 0x5948, 0x61f6, 0x7669, 0x7f85,
1787       0x863f, 0x87ba, 0x88f8, 0x908f, 0x6a02, 0x6d1b, 0x70d9, 0x73de,
1788       0x843d, 0x916a, 0x99f1, 0x4e82, 0x5375, 0x6b04, 0x721b, 0x862d,
1789       0x9e1e, 0x5d50, 0x6feb, 0x85cd, 0x8964, 0x62c9, 0x81d8, 0x881f,
1790       0x5eca, 0x6717, 0x6d6a, 0x72fc, 0x0000, 0x4f86, 0x51b7, 0x52de,
1791       0x64c4, 0x6ad3, 0x7210, 0x76e7, 0x8001, 0x8606, 0x865c, 0x8def,
1792       0x9732, 0x9b6f, 0x9dfa, 0x788c, 0x797f, 0x7da0, 0x83c9, 0x9304,
1793       0x9e7f, 0x8ad6, 0x58df, 0x5f04, 0x7c60, 0x807e, 0x7262, 0x78ca,
1794       0x8cc2, 0x96f7, 0x58d8, 0x5c62, 0x6a13, 0x6dda, 0x6f0f, 0x7d2f,
1795       0x7e37, 0x964b, 0x52d2, 0x808b, 0x51dc, 0x51cc, 0x7a1c, 0x7dbe,
1796       0x83f1, 0x9675, 0x8b80, 0x62cf, 0x6a02, 0x8afe, 0x4e39, 0x5be7,
1797       0x6012, 0x7387, 0x7570, 0x5317, 0x78fb, 0x4fbf, 0x5fa9, 0x4e0d,
1798       0x6ccc, 0x6578, 0x7d22, 0x53c3, 0x585e, 0x7701, 0x8449, 0x8aaa,
1799       0x6bba, 0x8fb0, 0x6c88, 0x62fe, 0x82e5, 0x63a0, 0x7565, 0x4eae,
1800       0x5169, 0x0000, 0x6881, 0x7ce7, 0x826f, 0x8ad2, 0x91cf, 0x52f5,
1801       0x5442, 0x5973, 0x5eec, 0x65c5, 0x6ffe, 0x792a, 0x95ad, 0x9a6a,
1802       0x9e97, 0x9ece, 0x529b, 0x66c6, 0x6b77, 0x8f62, 0x5e74, 0x6190,
1803       0x6200, 0x649a, 0x6f23, 0x7149, 0x7489, 0x0000, 0x7df4, 0x806f,
1804       0x8f26, 0x84ee, 0x9023, 0x934a, 0x5217, 0x52a3, 0x54bd, 0x70c8,
1805       0x88c2, 0x8aaa, 0x5ec9, 0x5ff5, 0x637b, 0x6bae, 0x7c3e, 0x7375,
1806       0x4ee4, 0x56f9, 0x5be7, 0x5dba, 0x601c, 0x73b2, 0x7469, 0x7f9a,
1807       0x8046, 0x9234, 0x96f6, 0x9748, 0x9818, 0x4f8b, 0x79ae, 0x91b4,
1808       0x96b8, 0x60e1, 0x4e86, 0x50da, 0x5bee, 0x5c3f, 0x6599, 0x6a02,
1809       0x71ce, 0x7642, 0x84fc, 0x907c, 0x9f8d, 0x6688, 0x962e, 0x5289,
1810       0x677b, 0x67f3, 0x6d41, 0x6e9c, 0x7409, 0x7559, 0x786b, 0x7d10,
1811       0x985e, 0x516d, 0x622e, 0x9678, 0x502b, 0x5d19, 0x6dea, 0x8f2a,
1812       0x5f8b, 0x6144, 0x6817, 0x7387, 0x9686, 0x5229, 0x540f, 0x5c65,
1813       0x6613, 0x674e, 0x68a8, 0x6ce5, 0x7406, 0x75e2, 0x7f79, 0x0000,
1814       0x88e1, 0x91cc, 0x96e2, 0x533f, 0x6eba, 0x541d, 0x71d0, 0x7498,
1815       0x85fa, 0x0000, 0x9c57, 0x9e9f, 0x6797, 0x6dcb, 0x81e8, 0x7acb,
1816       0x7b20, 0x7c92, 0x72c0, 0x7099, 0x8b58, 0x4ec0, 0x8336, 0x523a,
1817       0x5207, 0x5ea6, 0x62d3, 0x7cd6, 0x5b85, 0x6d1e, 0x66b4, 0x8f3b,
1818       0x884c, 0x964d, 0x898b, 0x5ed3, 0x0000, 0x0000, 0x0000, 0x0000,
1819       0x585a, 0x0000, 0x6674, 0x0000, 0x0000, 0x51de, 0x8c6c, 0x76ca,
1820       0x0000, 0x795e, 0x7965, 0x798f, 0x9756, 0x7cbe, 0x7fbd, 0x0000,
1821       0x0000, 0x0000, 0x8af8, 0x0000, 0x0000, 0x9038, 0x90fd, 0x0000,
1822       0x0000, 0x0000, 0x98ef, 0x98fc, 0x9928, 0x9db4, 0x0000, 0x0000
1823   };
1824   static const WCHAR compat_FE30_FEF7[200] =
1825   {
1826       0x2025, 0x2014, 0x2013, 0x005f, 0x005f, 0x0028, 0x0029, 0x007b,
1827       0x007d, 0x3014, 0x3015, 0x3010, 0x3011, 0x300a, 0x300b, 0x3008,
1828       0x3009, 0x300c, 0x300d, 0x300e, 0x300f, 0x0000, 0x0000, 0x0000,
1829       0x0000, 0x203e, 0x203e, 0x203e, 0x203e, 0x005f, 0x005f, 0x005f,
1830       0x002c, 0x3001, 0x002e, 0x0000, 0x003b, 0x003a, 0x003f, 0x0021,
1831       0x2014, 0x0028, 0x0029, 0x007b, 0x007d, 0x3014, 0x3015, 0x0023,
1832       0x0026, 0x002a, 0x002b, 0x002d, 0x003c, 0x003e, 0x003d, 0x0000,
1833       0x0000, 0x0024, 0x0025, 0x0040, 0x0000, 0x0000, 0x0000, 0x0000,
1834       0x064b, 0x064b, 0x064c, 0x0000, 0x064d, 0x0000, 0x064e, 0x064e,
1835       0x064f, 0x064f, 0x0650, 0x0650, 0x0651, 0x0651, 0x0652, 0x0652,
1836       0x0621, 0x0622, 0x0622, 0x0623, 0x0623, 0x0624, 0x0624, 0x0625,
1837       0x0625, 0x0626, 0x0626, 0x0626, 0x0626, 0x0627, 0x0627, 0x0628,
1838       0x0628, 0x0628, 0x0628, 0x0629, 0x0629, 0x062a, 0x062a, 0x062a,
1839       0x062a, 0x062b, 0x062b, 0x062b, 0x062b, 0x062c, 0x062c, 0x062c,
1840       0x062c, 0x062d, 0x062d, 0x062d, 0x062d, 0x062e, 0x062e, 0x062e,
1841       0x062e, 0x062f, 0x062f, 0x0630, 0x0630, 0x0631, 0x0631, 0x0632,
1842       0x0632, 0x0633, 0x0633, 0x0633, 0x0633, 0x0634, 0x0634, 0x0634,
1843       0x0634, 0x0635, 0x0635, 0x0635, 0x0635, 0x0636, 0x0636, 0x0636,
1844       0x0636, 0x0637, 0x0637, 0x0637, 0x0637, 0x0638, 0x0638, 0x0638,
1845       0x0638, 0x0639, 0x0639, 0x0639, 0x0639, 0x063a, 0x063a, 0x063a,
1846       0x063a, 0x0641, 0x0641, 0x0641, 0x0641, 0x0642, 0x0642, 0x0642,
1847       0x0642, 0x0643, 0x0643, 0x0643, 0x0643, 0x0644, 0x0644, 0x0644,
1848       0x0644, 0x0645, 0x0645, 0x0645, 0x0645, 0x0646, 0x0646, 0x0646,
1849       0x0646, 0x0647, 0x0647, 0x0647, 0x0647, 0x0648, 0x0648, 0x0649,
1850       0x0649, 0x064a, 0x064a, 0x064a, 0x064a, 0x0000, 0x0000, 0x0000
1851   };
1852   static const WCHAR compat_FF00_FFEF[240] =
1853   {
1854       0x0000, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
1855       0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
1856       0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
1857       0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
1858       0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
1859       0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
1860       0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
1861       0x0058, 0x0059, 0x005a, 0x005b, 0x0000, 0x005d, 0x005e, 0x005f,
1862       0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
1863       0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
1864       0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
1865       0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000,
1866       0x0000, 0x3002, 0x300c, 0x300d, 0x3001, 0x30fb, 0x30f2, 0x30a1,
1867       0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, 0x30c3,
1868       0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, 0x30ab, 0x30ad,
1869       0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, 0x30b9, 0x30bb, 0x30bd,
1870       0x30bf, 0x30c1, 0x30c4, 0x30c6, 0x30c8, 0x30ca, 0x30cb, 0x30cc,
1871       0x30cd, 0x30ce, 0x30cf, 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de,
1872       0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9,
1873       0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c,
1874       0x3164, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137,
1875       0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f,
1876       0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147,
1877       0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x0000,
1878       0x0000, 0x0000, 0x314f, 0x3150, 0x3151, 0x3152, 0x3153, 0x3154,
1879       0x0000, 0x0000, 0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315a,
1880       0x0000, 0x0000, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, 0x3160,
1881       0x0000, 0x0000, 0x3161, 0x3162, 0x3163, 0x0000, 0x0000, 0x0000,
1882       0x00a2, 0x00a3, 0x00ac, 0x00af, 0x00a6, 0x00a5, 0x20a9, 0x0000,
1883       0x2502, 0x2190, 0x2191, 0x2192, 0x2193, 0x25a0, 0x25cb, 0x0000
1884   };
1885   static const WCHAR ligatures_src[] =
1886   {
1887     0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
1888     0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
1889     0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
1890     0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
1891     0xfb04, 0xfb05, 0xfb06, '\0'
1892   };
1893   static const WCHAR ligatures_dst[] =
1894   {
1895     'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
1896     'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
1897     'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
1898     0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
1899     'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
1900   };
1901
1902   if (!pFoldStringW)
1903   {
1904     skip("FoldStringW is not available\n");
1905     return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1906   }
1907
1908   /* Invalid flag combinations */
1909   for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
1910   {
1911     src[0] = dst[0] = '\0';
1912     SetLastError(0);
1913     ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
1914     if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1915     {
1916       skip("FoldStringW is not implemented\n");
1917       return;
1918     }
1919     ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
1920        "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1921   }
1922
1923   /* src & dst cannot be the same */
1924   SetLastError(0);
1925   ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
1926   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1927       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1928
1929   /* src can't be NULL */
1930   SetLastError(0);
1931   ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
1932   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1933       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1934
1935   /* srclen can't be 0 */
1936   SetLastError(0);
1937   ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
1938   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1939       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1940
1941   /* dstlen can't be < 0 */
1942   SetLastError(0);
1943   ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
1944   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1945       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1946
1947   /* Ret includes terminating NUL which is appended if srclen = -1 */
1948   SetLastError(0);
1949   src[0] = 'A';
1950   src[1] = '\0';
1951   dst[0] = '\0';
1952   ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
1953   ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1954   ok(dst[0] == 'A' && dst[1] == '\0',
1955      "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%d\n",
1956      'A', '\0', ret, dst[0], dst[1], GetLastError());
1957
1958   /* If size is given, result is not NUL terminated */
1959   SetLastError(0);
1960   src[0] = 'A';
1961   src[1] = 'A';
1962   dst[0] = 'X';
1963   dst[1] = 'X';
1964   ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
1965   ok(ret == 1, "Expected ret == 1, got %d, error %d\n", ret, GetLastError());
1966   ok(dst[0] == 'A' && dst[1] == 'X',
1967      "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%d\n",
1968      'A','X', ret, dst[0], dst[1], GetLastError());
1969
1970   /* MAP_FOLDDIGITS */
1971   for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
1972   {
1973     /* Check everything before this range */
1974     for (ch = prev_ch; ch < digitRanges[j]; ch++)
1975     {
1976       SetLastError(0);
1977       src[0] = ch;
1978       src[1] = dst[0] = '\0';
1979       ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
1980       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1981
1982       ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
1983          /* Wine (correctly) maps all Unicode 4.0+ digits */
1984          isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF ||
1985          (ch >= 0x1369 && ch <= 0x1371),
1986          "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
1987     }
1988
1989     if (digitRanges[j] == 0xffff)
1990       break; /* Finished the whole code point space */
1991
1992     for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
1993     {
1994       WCHAR c;
1995
1996       /* Map out of sequence characters */
1997       if      (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
1998       else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
1999       else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
2000       else if (ch == 0x245F) c = 0x24EA; /* Circled 0     */
2001       else                   c = ch;
2002       SetLastError(0);
2003       src[0] = c;
2004       src[1] = dst[0] = '\0';
2005       ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2006       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2007
2008       ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
2009          broken( dst[0] == ch ) ||  /* old Windows versions don't have all mappings */
2010          strchrW(noDigitAvailable, c),
2011          "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
2012          ch, '0' + digitRanges[j] - ch, dst[0]);
2013     }
2014     prev_ch = ch;
2015   }
2016
2017   /* MAP_FOLDCZONE */
2018   for (ch = 1, failures = 0; ch <0xffff; ch++)
2019   {
2020     WCHAR expected = 0;
2021
2022     if (ch >= 0xF900 && ch <= 0xFA2F)
2023       expected = compat_F900_FA2F[ch - 0xF900];
2024     else if (ch >= 0xFE30 && ch <= 0xFEF7)
2025       expected = compat_FE30_FEF7[ch - 0xFE30];
2026     else if (ch >= 0xFF00 && ch <= 0xFFEF)
2027       expected = compat_FF00_FFEF[ch - 0xFF00];
2028
2029     if (!expected)
2030       expected = ch;
2031
2032     SetLastError(0);
2033     src[0] = ch;
2034     src[1] = dst[0] = '\0';
2035     ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
2036     ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2037     ok(dst[0] == expected ||
2038        broken( dst[0] == ch ) ||  /* old Windows versions don't have all mappings */
2039        /* Wine (correctly) uses updated mappings for some Unicode 4.0 chars */
2040        /* FIXME: But they should be re-checked */
2041        ch == 0xf92c || ch == 0xf979 || ch == 0xf995 || ch == 0xf9e7 ||
2042        ch == 0xf9f1 ||
2043        (0xfa0c <= ch && ch <= 0xfa6a) ||
2044        (0xfa70 <= ch && ch <= 0xfad9) ||
2045        ch == 0xfe47 || ch == 0xfe48 || ch == 0xfe68 ||
2046        (0xfe70 <= ch && ch <= 0xfe7f) ||
2047        ch == 0xff3c || ch == 0xff5f || ch == 0xff60 ||
2048        ch == 0xff9e || ch == 0xff9f,
2049        "MAP_FOLDCZONE: ch %d 0x%04x Expected 0x%04x got 0x%04x\n",
2050        ch, ch, expected, dst[0]);
2051     if (dst[0] != expected && ch < 0xf000 && ++failures > 50)
2052     {
2053         trace( "MAP_FOLDCZONE: Too many failures, giving up\n" );
2054         break;
2055     }
2056   }
2057
2058   /* MAP_EXPAND_LIGATURES */
2059   SetLastError(0);
2060   ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
2061   /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
2062   if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
2063     ok(ret == sizeof(ligatures_dst)/sizeof(ligatures_dst[0]),
2064        "Got %d, error %d\n", ret, GetLastError());
2065     ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
2066        "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
2067     for (i = 1, failures = 0; i <= 0xffff; i++)
2068     {
2069       if (!strchrW(ligatures_src, i))
2070       {
2071         src[0] = i;
2072         src[1] = '\0';
2073         SetLastError(0);
2074         ret = pFoldStringW(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
2075         ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2076         if (ret == 3)
2077             ok(0, "MAP_EXPAND_LIGATURES: %04x : Expected %04x, got %04x %04x\n",
2078                i, src[0], dst[0], dst[1]);
2079         else
2080             ok(dst[0] == src[0],
2081                "MAP_EXPAND_LIGATURES: %04x : Expected %04x, got %04x\n",
2082                i, src[0], dst[0]);
2083         if (dst[0] != src[0] && ++failures > 50)
2084         {
2085             trace( "MAP_EXPAND_LIGATURES: Too many failures, giving up\n" );
2086             break;
2087         }
2088       }
2089     }
2090   }
2091
2092   /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
2093 }
2094
2095
2096
2097 #define LCID_OK(l) \
2098   ok(lcid == l, "Expected lcid = %08x, got %08x\n", l, lcid)
2099 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
2100 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
2101 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
2102 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
2103
2104 static void test_ConvertDefaultLocale(void)
2105 {
2106   LCID lcid;
2107
2108   /* Doesn't change lcid, even if non default sublang/sort used */
2109   TEST_LCID(LANG_ENGLISH,  SUBLANG_ENGLISH_US, SORT_DEFAULT);
2110   TEST_LCID(LANG_ENGLISH,  SUBLANG_ENGLISH_UK, SORT_DEFAULT);
2111   TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT,    SORT_DEFAULT);
2112   TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT,    SORT_JAPANESE_UNICODE);
2113
2114   /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
2115   LCID_RES(MKLCID(LANG_ENGLISH,  SUBLANG_NEUTRAL, SORT_DEFAULT),
2116            MKLCID(LANG_ENGLISH,  SUBLANG_DEFAULT, SORT_DEFAULT));
2117   LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
2118            MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
2119   LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_JAPANESE_UNICODE),
2120            MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE));
2121
2122   /* Invariant language is not treated specially */
2123   TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
2124   LCID_RES(MKLCID(LANG_INVARIANT, SUBLANG_NEUTRAL, SORT_DEFAULT),
2125            MKLCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT));
2126
2127   /* User/system default languages alone are not mapped */
2128   TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
2129   TEST_LCIDLANG(LANG_USER_DEFAULT,   SORT_JAPANESE_UNICODE);
2130
2131   /* Default lcids */
2132   LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
2133   LCID_RES(LOCALE_USER_DEFAULT,   GetUserDefaultLCID());
2134   LCID_RES(LOCALE_NEUTRAL,        GetUserDefaultLCID());
2135 }
2136
2137 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
2138                                     DWORD dwFlags, LONG_PTR lParam)
2139 {
2140   trace("%08x, %s, %s, %08x, %08lx\n",
2141         lgrpid, lpszNum, lpszName, dwFlags, lParam);
2142
2143   ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
2144      "Enumerated grp %d not valid (flags %d)\n", lgrpid, dwFlags);
2145
2146   /* If lParam is one, we are calling with flags defaulted from 0 */
2147   ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
2148          "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %d\n", dwFlags);
2149
2150   return TRUE;
2151 }
2152
2153 static void test_EnumSystemLanguageGroupsA(void)
2154 {
2155   BOOL ret;
2156
2157   if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
2158   {
2159     win_skip("EnumSystemLanguageGroupsA and/or IsValidLanguageGroup are not available\n");
2160     return;
2161   }
2162
2163   /* No enumeration proc */
2164   SetLastError(0);
2165   ret = pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
2166   if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2167   {
2168     win_skip("EnumSystemLanguageGroupsA is not implemented\n");
2169     return;
2170   }
2171   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2172       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2173
2174   /* Invalid flags */
2175   SetLastError(0);
2176   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
2177   ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2178
2179   /* No flags - defaults to LGRPID_INSTALLED */
2180   SetLastError(0xdeadbeef);
2181   pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
2182   ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
2183
2184   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
2185   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
2186 }
2187
2188
2189 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
2190                                       LONG_PTR lParam)
2191 {
2192   trace("%08x, %08x, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
2193
2194   /* invalid locale enumerated on some platforms */
2195   if (lcid == 0)
2196       return TRUE;
2197
2198   ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
2199      "Enumerated grp %d not valid\n", lgrpid);
2200   ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
2201      "Enumerated grp locale %d not valid\n", lcid);
2202   return TRUE;
2203 }
2204
2205 static void test_EnumLanguageGroupLocalesA(void)
2206 {
2207   BOOL ret;
2208
2209   if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
2210   {
2211     win_skip("EnumLanguageGroupLocalesA and/or IsValidLanguageGroup are not available\n");
2212     return;
2213   }
2214
2215   /* No enumeration proc */
2216   SetLastError(0);
2217   ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
2218   if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2219   {
2220     win_skip("EnumLanguageGroupLocalesA is not implemented\n");
2221     return;
2222   }
2223   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2224       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2225
2226   /* lgrpid too small */
2227   SetLastError(0);
2228   ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
2229   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2230       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2231
2232   /* lgrpid too big */
2233   SetLastError(0);
2234   ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
2235   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2236       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2237
2238   /* dwFlags is reserved */
2239   SetLastError(0);
2240   ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
2241   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2242       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2243
2244   pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2245 }
2246
2247 static void test_SetLocaleInfoA(void)
2248 {
2249   BOOL bRet;
2250   LCID lcid = GetUserDefaultLCID();
2251
2252   /* Null data */
2253   SetLastError(0);
2254   bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2255   ok( !bRet && GetLastError() == ERROR_INVALID_PARAMETER,
2256       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2257
2258   /* IDATE */
2259   SetLastError(0);
2260   bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
2261   ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2262      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2263
2264   /* ILDATE */
2265   SetLastError(0);
2266   bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
2267   ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2268      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2269 }
2270
2271 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2272 {
2273   trace("%s %08lx\n", value, lParam);
2274   return(TRUE);
2275 }
2276
2277 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2278 {
2279   ok(!enumCount, "callback called again unexpected\n");
2280   enumCount++;
2281   return(FALSE);
2282 }
2283
2284 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2285 {
2286   ok(0,"callback called unexpected\n");
2287   return(FALSE);
2288 }
2289
2290 static void test_EnumUILanguageA(void)
2291 {
2292   BOOL ret;
2293   if (!pEnumUILanguagesA) {
2294     skip("EnumUILanguagesA is not available on Win9x or NT4\n");
2295     return;
2296   }
2297
2298   SetLastError(ERROR_SUCCESS);
2299   ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2300   if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2301   {
2302     win_skip("EnumUILanguagesA is not implemented\n");
2303     return;
2304   }
2305   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2306
2307   enumCount = 0;
2308   SetLastError(ERROR_SUCCESS);
2309   ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2310   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2311
2312   SetLastError(ERROR_SUCCESS);
2313   ret = pEnumUILanguagesA(NULL, 0, 0);
2314   ok(!ret, "Expected return value FALSE, got %u\n", ret);
2315   ok(GetLastError() == ERROR_INVALID_PARAMETER,
2316       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2317
2318   SetLastError(ERROR_SUCCESS);
2319   ret = pEnumUILanguagesA(luilocale_proc3A, 0x5a5a5a5a, 0);
2320   ok(!ret, "Expected return value FALSE, got %u\n", ret);
2321   ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2322
2323   SetLastError(ERROR_SUCCESS);
2324   ret = pEnumUILanguagesA(NULL, 0x5a5a5a5a, 0);
2325   ok(!ret, "Expected return value FALSE, got %u\n", ret);
2326   ok(GetLastError() == ERROR_INVALID_PARAMETER,
2327       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2328 }
2329
2330 static char date_fmt_buf[1024];
2331
2332 static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
2333 {
2334     lstrcatA(date_fmt_buf, fmt);
2335     lstrcatA(date_fmt_buf, "\n");
2336     return TRUE;
2337 }
2338
2339 static void test_EnumDateFormatsA(void)
2340 {
2341     char *p, buf[256];
2342     BOOL ret;
2343     LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2344
2345     trace("EnumDateFormatsA 0\n");
2346     date_fmt_buf[0] = 0;
2347     SetLastError(0xdeadbeef);
2348     ret = EnumDateFormatsA(enum_datetime_procA, lcid, 0);
2349     if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2350     {
2351         win_skip("0 for dwFlags is not supported\n");
2352     }
2353     else
2354     {
2355         ok(ret, "EnumDateFormatsA(0) 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
2364     trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n");
2365     date_fmt_buf[0] = 0;
2366     SetLastError(0xdeadbeef);
2367     ret = EnumDateFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2368     if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2369     {
2370         win_skip("LOCALE_USE_CP_ACP is not supported\n");
2371     }
2372     else
2373     {
2374         ok(ret, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2375         trace("%s\n", date_fmt_buf);
2376         /* test the 1st enumerated format */
2377         if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2378         ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2379         ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2380         ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2381     }
2382
2383     trace("EnumDateFormatsA DATE_SHORTDATE\n");
2384     date_fmt_buf[0] = 0;
2385     ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_SHORTDATE);
2386     ok(ret, "EnumDateFormatsA(DATE_SHORTDATE) error %d\n", GetLastError());
2387     trace("%s\n", date_fmt_buf);
2388     /* test the 1st enumerated format */
2389     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2390     ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2391     ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2392     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2393
2394     trace("EnumDateFormatsA DATE_LONGDATE\n");
2395     date_fmt_buf[0] = 0;
2396     ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_LONGDATE);
2397     ok(ret, "EnumDateFormatsA(DATE_LONGDATE) error %d\n", GetLastError());
2398     trace("%s\n", date_fmt_buf);
2399     /* test the 1st enumerated format */
2400     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2401     ret = GetLocaleInfoA(lcid, LOCALE_SLONGDATE, buf, sizeof(buf));
2402     ok(ret, "GetLocaleInfoA(LOCALE_SLONGDATE) error %d\n", GetLastError());
2403     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2404
2405     trace("EnumDateFormatsA DATE_YEARMONTH\n");
2406     date_fmt_buf[0] = 0;
2407     SetLastError(0xdeadbeef);
2408     ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_YEARMONTH);
2409     if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2410     {
2411         skip("DATE_YEARMONTH is only present on W2K and later\n");
2412         return;
2413     }
2414     ok(ret, "EnumDateFormatsA(DATE_YEARMONTH) error %d\n", GetLastError());
2415     trace("%s\n", date_fmt_buf);
2416     /* test the 1st enumerated format */
2417     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2418     ret = GetLocaleInfoA(lcid, LOCALE_SYEARMONTH, buf, sizeof(buf));
2419     ok(ret, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %d\n", GetLastError());
2420     ok(!lstrcmpA(date_fmt_buf, buf) || broken(!buf[0]) /* win9x */,
2421        "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2422 }
2423
2424 static void test_EnumTimeFormatsA(void)
2425 {
2426     char *p, buf[256];
2427     BOOL ret;
2428     LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2429
2430     trace("EnumTimeFormatsA 0\n");
2431     date_fmt_buf[0] = 0;
2432     ret = EnumTimeFormatsA(enum_datetime_procA, lcid, 0);
2433     ok(ret, "EnumTimeFormatsA(0) error %d\n", GetLastError());
2434     trace("%s\n", date_fmt_buf);
2435     /* test the 1st enumerated format */
2436     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2437     ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2438     ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2439     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2440
2441     trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n");
2442     date_fmt_buf[0] = 0;
2443     ret = EnumTimeFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2444     ok(ret, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2445     trace("%s\n", date_fmt_buf);
2446     /* test the 1st enumerated format */
2447     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2448     ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2449     ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2450     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2451 }
2452
2453 static void test_GetCPInfo(void)
2454 {
2455     BOOL ret;
2456     CPINFO cpinfo;
2457
2458     SetLastError(0xdeadbeef);
2459     ret = GetCPInfo(CP_SYMBOL, &cpinfo);
2460     ok(!ret, "GetCPInfo(CP_SYMBOL) should fail\n");
2461     ok(GetLastError() == ERROR_INVALID_PARAMETER,
2462        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2463
2464     SetLastError(0xdeadbeef);
2465     ret = GetCPInfo(CP_UTF7, &cpinfo);
2466     if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2467     {
2468         skip("Codepage CP_UTF7 is not installed/available\n");
2469     }
2470     else
2471     {
2472         ok(ret, "GetCPInfo(CP_UTF7) error %u\n", GetLastError());
2473         ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2474         ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2475         ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2476         ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2477         ok(cpinfo.MaxCharSize == 5, "expected 5, got 0x%x\n", cpinfo.MaxCharSize);
2478     }
2479
2480     SetLastError(0xdeadbeef);
2481     ret = GetCPInfo(CP_UTF8, &cpinfo);
2482     if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2483     {
2484         skip("Codepage CP_UTF8 is not installed/available\n");
2485     }
2486     else
2487     {
2488         ok(ret, "GetCPInfo(CP_UTF8) error %u\n", GetLastError());
2489         ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2490         ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2491         ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2492         ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2493         ok(cpinfo.MaxCharSize == 4 || broken(cpinfo.MaxCharSize == 3) /* win9x */,
2494            "expected 4, got %u\n", cpinfo.MaxCharSize);
2495     }
2496 }
2497
2498 START_TEST(locale)
2499 {
2500   InitFunctionPointers();
2501
2502   test_EnumTimeFormatsA();
2503   test_EnumDateFormatsA();
2504   test_GetLocaleInfoA();
2505   test_GetTimeFormatA();
2506   test_GetDateFormatA();
2507   test_GetDateFormatW();
2508   test_GetCurrencyFormatA(); /* Also tests the W version */
2509   test_GetNumberFormatA();   /* Also tests the W version */
2510   test_CompareStringA();
2511   test_LCMapStringA();
2512   test_LCMapStringW();
2513   test_FoldStringA();
2514   test_FoldStringW();
2515   test_ConvertDefaultLocale();
2516   test_EnumSystemLanguageGroupsA();
2517   test_EnumLanguageGroupLocalesA();
2518   test_SetLocaleInfoA();
2519   test_EnumUILanguageA();
2520   test_GetCPInfo();
2521   /* this requires collation table patch to make it MS compatible */
2522   if (0) test_sorting();
2523 }