wininet/tests: Test for handling of blank headers in HttpAddRequestHeaders.
[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     ret = CompareStringA(lcid, NORM_IGNORECASE | LOCALE_USE_CP_ACP, "#", -1, ".", -1);
1115     todo_wine ok(ret == CSTR_LESS_THAN, "\"#\" vs \".\" expected CSTR_LESS_THAN, got %d\n", ret);
1116
1117     ret = lstrcmpi("#", ".");
1118     todo_wine ok(ret == -1, "\"#\" vs \".\" expected -1, got %d\n", ret);
1119 }
1120
1121 static void test_LCMapStringA(void)
1122 {
1123     int ret, ret2;
1124     char buf[256], buf2[256];
1125     static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
1126     static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
1127     static const char symbols_stripped[] = "justateststring1";
1128
1129     SetLastError(0xdeadbeef);
1130     ret = LCMapStringA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP | LCMAP_LOWERCASE,
1131                        lower_case, -1, buf, sizeof(buf));
1132     ok(ret == lstrlenA(lower_case) + 1,
1133        "ret %d, error %d, expected value %d\n",
1134        ret, GetLastError(), lstrlenA(lower_case) + 1);
1135     ok(!memcmp(buf, lower_case, ret), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1136
1137     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1138                        upper_case, -1, buf, sizeof(buf));
1139     ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE 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_HIRAGANA | LCMAP_KATAKANA,
1144                        upper_case, -1, buf, sizeof(buf));
1145     ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA 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_HALFWIDTH | LCMAP_FULLWIDTH,
1150                        upper_case, -1, buf, sizeof(buf));
1151     ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1152     ok(GetLastError() == ERROR_INVALID_FLAGS,
1153        "unexpected error code %d\n", GetLastError());
1154
1155     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1156                        upper_case, -1, buf, sizeof(buf));
1157     ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1158     ok(GetLastError() == ERROR_INVALID_FLAGS,
1159        "unexpected error code %d\n", GetLastError());
1160
1161     /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1162     SetLastError(0xdeadbeef);
1163     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1164                        upper_case, -1, buf, sizeof(buf));
1165     ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1166     ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1167
1168     /* test LCMAP_LOWERCASE */
1169     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1170                        upper_case, -1, buf, sizeof(buf));
1171     ok(ret == lstrlenA(upper_case) + 1,
1172        "ret %d, error %d, expected value %d\n",
1173        ret, GetLastError(), lstrlenA(upper_case) + 1);
1174     ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1175
1176     /* test LCMAP_UPPERCASE */
1177     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1178                        lower_case, -1, buf, sizeof(buf));
1179     ok(ret == lstrlenA(lower_case) + 1,
1180        "ret %d, error %d, expected value %d\n",
1181        ret, GetLastError(), lstrlenA(lower_case) + 1);
1182     ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1183
1184     /* test buffer overflow */
1185     SetLastError(0xdeadbeef);
1186     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1187                        lower_case, -1, buf, 4);
1188     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1189        "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1190
1191     /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1192     lstrcpyA(buf, lower_case);
1193     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1194                        buf, -1, buf, sizeof(buf));
1195     if (!ret) /* Win9x */
1196         trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1197     else
1198     {
1199         ok(ret == lstrlenA(lower_case) + 1,
1200            "ret %d, error %d, expected value %d\n",
1201            ret, GetLastError(), lstrlenA(lower_case) + 1);
1202         ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1203     }
1204     lstrcpyA(buf, upper_case);
1205     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1206                        buf, -1, buf, sizeof(buf));
1207     if (!ret) /* Win9x */
1208         trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1209     else
1210     {
1211         ok(ret == lstrlenA(upper_case) + 1,
1212            "ret %d, error %d, expected value %d\n",
1213            ret, GetLastError(), lstrlenA(lower_case) + 1);
1214         ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1215     }
1216
1217     /* otherwise src == dst should fail */
1218     SetLastError(0xdeadbeef);
1219     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1220                        buf, 10, buf, sizeof(buf));
1221     ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1222        GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1223        "unexpected error code %d\n", GetLastError());
1224     ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1225
1226     /* test whether '\0' is always appended */
1227     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1228                        upper_case, -1, buf, sizeof(buf));
1229     ok(ret, "LCMapStringA must succeed\n");
1230     ok(buf[ret-1] == 0, "LCMapStringA not null-terminated\n");
1231     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1232                        upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1233     ok(ret2, "LCMapStringA must succeed\n");
1234     ok(buf2[ret2-1] == 0, "LCMapStringA not null-terminated\n" );
1235     ok(ret == ret2, "lengths of sort keys must be equal\n");
1236     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1237
1238     /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1239     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1240                        upper_case, -1, buf, sizeof(buf));
1241     ok(ret, "LCMapStringA must succeed\n");
1242     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1243                        lower_case, -1, buf2, sizeof(buf2));
1244     ok(ret2, "LCMapStringA must succeed\n");
1245     ok(ret == ret2, "lengths of sort keys must be equal\n");
1246     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1247
1248     /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1249     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1250                        lower_case, -1, buf, sizeof(buf));
1251     ok(ret, "LCMapStringA must succeed\n");
1252     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1253                        lower_case, -1, buf2, sizeof(buf2));
1254     ok(ret2, "LCMapStringA must succeed\n");
1255     ok(ret == ret2, "lengths of sort keys must be equal\n");
1256     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1257
1258     /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1259     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1260                        lower_case, -1, buf, sizeof(buf));
1261     ok(ret, "LCMapStringA must succeed\n");
1262     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1263                        symbols_stripped, -1, buf2, sizeof(buf2));
1264     ok(ret2, "LCMapStringA must succeed\n");
1265     ok(ret == ret2, "lengths of sort keys must be equal\n");
1266     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1267
1268     /* test NORM_IGNORENONSPACE */
1269     lstrcpyA(buf, "foo");
1270     ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1271                        lower_case, -1, buf, sizeof(buf));
1272     ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1273         lstrlenA(lower_case) + 1, ret);
1274     ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1275
1276     /* test NORM_IGNORESYMBOLS */
1277     lstrcpyA(buf, "foo");
1278     ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1279                        lower_case, -1, buf, sizeof(buf));
1280     ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1281         lstrlenA(symbols_stripped) + 1, ret);
1282     ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1283
1284     /* test srclen = 0 */
1285     SetLastError(0xdeadbeef);
1286     ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1287     ok(!ret, "LCMapStringA should fail with srclen = 0\n");
1288     ok(GetLastError() == ERROR_INVALID_PARAMETER,
1289        "unexpected error code %d\n", GetLastError());
1290 }
1291
1292 static void test_LCMapStringW(void)
1293 {
1294     int ret, ret2;
1295     WCHAR buf[256], buf2[256];
1296     char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1297     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};
1298     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};
1299     static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
1300     static const WCHAR fooW[] = {'f','o','o',0};
1301
1302     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1303                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1304     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1305     {
1306         win_skip("LCMapStringW is not implemented\n");
1307         return;
1308     }
1309     ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1310     ok(GetLastError() == ERROR_INVALID_FLAGS,
1311        "unexpected error code %d\n", GetLastError());
1312
1313     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1314                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1315     ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1316     ok(GetLastError() == ERROR_INVALID_FLAGS,
1317        "unexpected error code %d\n", GetLastError());
1318
1319     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1320                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1321     ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1322     ok(GetLastError() == ERROR_INVALID_FLAGS,
1323        "unexpected error code %d\n", GetLastError());
1324
1325     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1326                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1327     ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1328     ok(GetLastError() == ERROR_INVALID_FLAGS,
1329        "unexpected error code %d\n", GetLastError());
1330
1331     /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1332     SetLastError(0xdeadbeef);
1333     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1334                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1335     ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1336     ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1337
1338     /* test LCMAP_LOWERCASE */
1339     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1340                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1341     ok(ret == lstrlenW(upper_case) + 1,
1342        "ret %d, error %d, expected value %d\n",
1343        ret, GetLastError(), lstrlenW(upper_case) + 1);
1344     ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1345
1346     /* test LCMAP_UPPERCASE */
1347     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1348                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1349     ok(ret == lstrlenW(lower_case) + 1,
1350        "ret %d, error %d, expected value %d\n",
1351        ret, GetLastError(), lstrlenW(lower_case) + 1);
1352     ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1353
1354     /* test buffer overflow */
1355     SetLastError(0xdeadbeef);
1356     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1357                        lower_case, -1, buf, 4);
1358     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1359        "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1360
1361     /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1362     lstrcpyW(buf, lower_case);
1363     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1364                        buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1365     ok(ret == lstrlenW(lower_case) + 1,
1366        "ret %d, error %d, expected value %d\n",
1367        ret, GetLastError(), lstrlenW(lower_case) + 1);
1368     ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1369
1370     lstrcpyW(buf, upper_case);
1371     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1372                        buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1373     ok(ret == lstrlenW(upper_case) + 1,
1374        "ret %d, error %d, expected value %d\n",
1375        ret, GetLastError(), lstrlenW(lower_case) + 1);
1376     ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1377
1378     /* otherwise src == dst should fail */
1379     SetLastError(0xdeadbeef);
1380     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1381                        buf, 10, buf, sizeof(buf));
1382     ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1383        GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1384        "unexpected error code %d\n", GetLastError());
1385     ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1386
1387     /* test whether '\0' is always appended */
1388     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1389                        upper_case, -1, buf, sizeof(buf));
1390     ok(ret, "LCMapStringW must succeed\n");
1391     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1392                        upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1393     ok(ret, "LCMapStringW must succeed\n");
1394     ok(ret == ret2, "lengths of sort keys must be equal\n");
1395     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1396
1397     /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1398     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1399                        upper_case, -1, buf, sizeof(buf));
1400     ok(ret, "LCMapStringW must succeed\n");
1401     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1402                        lower_case, -1, buf2, sizeof(buf2));
1403     ok(ret2, "LCMapStringW must succeed\n");
1404     ok(ret == ret2, "lengths of sort keys must be equal\n");
1405     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1406
1407     /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1408     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1409                        lower_case, -1, buf, sizeof(buf));
1410     ok(ret, "LCMapStringW must succeed\n");
1411     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1412                        lower_case, -1, buf2, sizeof(buf2));
1413     ok(ret2, "LCMapStringW must succeed\n");
1414     ok(ret == ret2, "lengths of sort keys must be equal\n");
1415     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1416
1417     /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1418     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1419                        lower_case, -1, buf, sizeof(buf));
1420     ok(ret, "LCMapStringW must succeed\n");
1421     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1422                        symbols_stripped, -1, buf2, sizeof(buf2));
1423     ok(ret2, "LCMapStringW must succeed\n");
1424     ok(ret == ret2, "lengths of sort keys must be equal\n");
1425     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1426
1427     /* test NORM_IGNORENONSPACE */
1428     lstrcpyW(buf, fooW);
1429     ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1430                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1431     ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1432         lstrlenW(lower_case) + 1, ret);
1433     ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1434
1435     /* test NORM_IGNORESYMBOLS */
1436     lstrcpyW(buf, fooW);
1437     ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1438                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1439     ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1440         lstrlenW(symbols_stripped) + 1, ret);
1441     ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1442
1443     /* test srclen = 0 */
1444     SetLastError(0xdeadbeef);
1445     ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf)/sizeof(WCHAR));
1446     ok(!ret, "LCMapStringW should fail with srclen = 0\n");
1447     ok(GetLastError() == ERROR_INVALID_PARAMETER,
1448        "unexpected error code %d\n", GetLastError());
1449 }
1450
1451 /* this requires collation table patch to make it MS compatible */
1452 static const char * const strings_sorted[] =
1453 {
1454 "'",
1455 "-",
1456 "!",
1457 "\"",
1458 ".",
1459 ":",
1460 "\\",
1461 "_",
1462 "`",
1463 "{",
1464 "}",
1465 "+",
1466 "0",
1467 "1",
1468 "2",
1469 "3",
1470 "4",
1471 "5",
1472 "6",
1473 "7",
1474 "8",
1475 "9",
1476 "a",
1477 "A",
1478 "b",
1479 "B",
1480 "c",
1481 "C"
1482 };
1483
1484 static const char * const strings[] =
1485 {
1486 "C",
1487 "\"",
1488 "9",
1489 "'",
1490 "}",
1491 "-",
1492 "7",
1493 "+",
1494 "`",
1495 "1",
1496 "a",
1497 "5",
1498 "\\",
1499 "8",
1500 "B",
1501 "3",
1502 "_",
1503 "6",
1504 "{",
1505 "2",
1506 "c",
1507 "4",
1508 "!",
1509 "0",
1510 "A",
1511 ":",
1512 "b",
1513 "."
1514 };
1515
1516 static int compare_string1(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 lstrcmpA(s1, s2);
1522 }
1523
1524 static int compare_string2(const void *e1, const void *e2)
1525 {
1526     const char *s1 = *(const char *const *)e1;
1527     const char *s2 = *(const char *const *)e2;
1528
1529     return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1530 }
1531
1532 static int compare_string3(const void *e1, const void *e2)
1533 {
1534     const char *s1 = *(const char *const *)e1;
1535     const char *s2 = *(const char *const *)e2;
1536     char key1[256], key2[256];
1537
1538     LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
1539     LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
1540     return strcmp(key1, key2);
1541 }
1542
1543 static void test_sorting(void)
1544 {
1545     char buf[256];
1546     char **str_buf = (char **)buf;
1547     int i;
1548
1549     assert(sizeof(buf) >= sizeof(strings));
1550
1551     /* 1. sort using lstrcmpA */
1552     memcpy(buf, strings, sizeof(strings));
1553     qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
1554     for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1555     {
1556         ok(!strcmp(strings_sorted[i], str_buf[i]),
1557            "qsort using lstrcmpA failed for element %d\n", i);
1558     }
1559     /* 2. sort using CompareStringA */
1560     memcpy(buf, strings, sizeof(strings));
1561     qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
1562     for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1563     {
1564         ok(!strcmp(strings_sorted[i], str_buf[i]),
1565            "qsort using CompareStringA failed for element %d\n", i);
1566     }
1567     /* 3. sort using sort keys */
1568     memcpy(buf, strings, sizeof(strings));
1569     qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
1570     for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1571     {
1572         ok(!strcmp(strings_sorted[i], str_buf[i]),
1573            "qsort using sort keys failed for element %d\n", i);
1574     }
1575 }
1576
1577 static void test_FoldStringA(void)
1578 {
1579   int ret, i;
1580   char src[256], dst[256];
1581   static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0'  };
1582   static const char digits_dst[] = { '1','2','3','\0'  };
1583   static const char composite_src[] =
1584   {
1585     0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
1586     0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
1587     0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
1588     0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
1589     0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
1590     0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
1591     0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
1592     0xfb,0xfc,0xfd,0xff,'\0'
1593   };
1594   static const char composite_dst[] =
1595   {
1596     0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1597     0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1598     0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1599     0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1600     0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1601     0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1602     0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
1603     0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
1604     0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
1605     0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
1606     0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
1607     0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
1608     0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
1609     0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
1610     0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1611   };
1612   static const char ligatures_src[] =
1613   {
1614     0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1615   };
1616   static const char ligatures_dst[] =
1617   {
1618     'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1619   };
1620
1621   if (!pFoldStringA)
1622     return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1623
1624   /* these tests are locale specific */
1625   if (GetACP() != 1252)
1626   {
1627       trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1628       return;
1629   }
1630
1631   /* MAP_FOLDDIGITS */
1632   SetLastError(0);
1633   ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
1634   if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1635     return;
1636   ok(ret == 4, "Expected ret == 4, got %d, error %d\n", ret, GetLastError());
1637   ok(strcmp(dst, digits_dst) == 0,
1638      "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
1639   for (i = 1; i < 256; i++)
1640   {
1641     if (!strchr(digits_src, i))
1642     {
1643       src[0] = i;
1644       src[1] = '\0';
1645       SetLastError(0);
1646       ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
1647       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1648       ok(dst[0] == src[0],
1649          "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
1650     }
1651   }
1652
1653   /* MAP_EXPAND_LIGATURES */
1654   SetLastError(0);
1655   ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1656   /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1657   if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1658     ok(ret == sizeof(ligatures_dst), "Got %d, error %d\n", ret, GetLastError());
1659     ok(strcmp(dst, ligatures_dst) == 0,
1660        "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
1661     for (i = 1; i < 256; i++)
1662     {
1663       if (!strchr(ligatures_src, i))
1664       {
1665         src[0] = i;
1666         src[1] = '\0';
1667         SetLastError(0);
1668         ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1669         ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1670         ok(dst[0] == src[0],
1671            "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
1672       }
1673     }
1674   }
1675
1676   /* MAP_COMPOSITE */
1677   SetLastError(0);
1678   ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
1679   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1680   todo_wine
1681   {
1682     /* Wine gets close, but doesn't produce quite the same result as native */
1683     ok(ret == 121, "Expected 121, got %d\n", ret);
1684     ok(strcmp(dst, composite_dst) == 0,
1685        "MAP_COMPOSITE: Expected '%s', got '%s'\n", composite_dst, dst);
1686   }
1687
1688   for (i = 1; i < 256; i++)
1689   {
1690     if (!strchr(composite_src, i))
1691     {
1692       src[0] = i;
1693       src[1] = '\0';
1694       SetLastError(0);
1695       ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
1696       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1697       ok(dst[0] == src[0],
1698          "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
1699          (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
1700     }
1701   }
1702
1703   /* MAP_FOLDCZONE */
1704   for (i = 1; i < 256; i++)
1705   {
1706     src[0] = i;
1707     src[1] = '\0';
1708     SetLastError(0);
1709     ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
1710     ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1711     ok(src[0] == dst[0],
1712        "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
1713        (unsigned char)src[0], (unsigned char)dst[0]);
1714   }
1715
1716   /* MAP_PRECOMPOSED */
1717   for (i = 1; i < 256; i++)
1718   {
1719     src[0] = i;
1720     src[1] = '\0';
1721     SetLastError(0);
1722     ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
1723     ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1724     ok(src[0] == dst[0],
1725        "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
1726        (unsigned char)src[0], (unsigned char)dst[0]);
1727   }
1728 }
1729
1730 static void test_FoldStringW(void)
1731 {
1732   int ret;
1733   unsigned int i, j, failures;
1734   WCHAR src[256], dst[256], ch, prev_ch = 1;
1735   static const DWORD badFlags[] =
1736   {
1737     0,
1738     MAP_PRECOMPOSED|MAP_COMPOSITE,
1739     MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
1740     MAP_COMPOSITE|MAP_EXPAND_LIGATURES
1741   };
1742   /* Ranges of digits 0-9 : Must be sorted! */
1743   static const WCHAR digitRanges[] =
1744   {
1745     0x0030, /* '0'-'9' */
1746     0x0660, /* Eastern Arabic */
1747     0x06F0, /* Arabic - Hindu */
1748     0x0966, /* Devengari */
1749     0x09E6, /* Bengalii */
1750     0x0A66, /* Gurmukhi */
1751     0x0AE6, /* Gujarati */
1752     0x0B66, /* Oriya */
1753     0x0BE6, /* Tamil - No 0 */
1754     0x0C66, /* Telugu */
1755     0x0CE6, /* Kannada */
1756     0x0D66, /* Maylayalam */
1757     0x0E50, /* Thai */
1758     0x0ED0, /* Laos */
1759     0x2070, /* Superscript - 1, 2, 3 are out of sequence */
1760     0x2080, /* Subscript */
1761     0x245F, /* Circled - 0 is out of sequence */
1762     0x2473, /* Bracketed */
1763     0x2487, /* Full stop */
1764     0x2775, /* Inverted circled - No 0 */
1765     0x277F, /* Patterned circled - No 0 */
1766     0x2789, /* Inverted Patterned circled - No 0 */
1767     0xff10, /* Pliene chasse (?) */
1768     0xffff  /* Terminator */
1769   };
1770   /* Digits which are represented, but out of sequence */
1771   static const WCHAR outOfSequenceDigits[] =
1772   {
1773       0xB9,   /* Superscript 1 */
1774       0xB2,   /* Superscript 2 */
1775       0xB3,   /* Superscript 3 */
1776       0x24EA, /* Circled 0 */
1777       '\0'    /* Terminator */
1778   };
1779   /* Digits in digitRanges for which no representation is available */
1780   static const WCHAR noDigitAvailable[] =
1781   {
1782       0x0BE6, /* No Tamil 0 */
1783       0x2473, /* No Bracketed 0 */
1784       0x2487, /* No 0 Full stop */
1785       0x2775, /* No inverted circled 0 */
1786       0x277F, /* No patterned circled */
1787       0x2789, /* No inverted Patterned circled */
1788       '\0'    /* Terminator */
1789   };
1790   /* Compatibility conversion results */
1791   static const WCHAR compat_F900_FA2F[256+48] =
1792   {
1793       0x8c48, 0x66f4, 0x8eca, 0x8cc8, 0x6ed1, 0x4e32, 0x53e5, 0x9f9c,
1794       0x9f9c, 0x5951, 0x91d1, 0x5587, 0x5948, 0x61f6, 0x7669, 0x7f85,
1795       0x863f, 0x87ba, 0x88f8, 0x908f, 0x6a02, 0x6d1b, 0x70d9, 0x73de,
1796       0x843d, 0x916a, 0x99f1, 0x4e82, 0x5375, 0x6b04, 0x721b, 0x862d,
1797       0x9e1e, 0x5d50, 0x6feb, 0x85cd, 0x8964, 0x62c9, 0x81d8, 0x881f,
1798       0x5eca, 0x6717, 0x6d6a, 0x72fc, 0x0000, 0x4f86, 0x51b7, 0x52de,
1799       0x64c4, 0x6ad3, 0x7210, 0x76e7, 0x8001, 0x8606, 0x865c, 0x8def,
1800       0x9732, 0x9b6f, 0x9dfa, 0x788c, 0x797f, 0x7da0, 0x83c9, 0x9304,
1801       0x9e7f, 0x8ad6, 0x58df, 0x5f04, 0x7c60, 0x807e, 0x7262, 0x78ca,
1802       0x8cc2, 0x96f7, 0x58d8, 0x5c62, 0x6a13, 0x6dda, 0x6f0f, 0x7d2f,
1803       0x7e37, 0x964b, 0x52d2, 0x808b, 0x51dc, 0x51cc, 0x7a1c, 0x7dbe,
1804       0x83f1, 0x9675, 0x8b80, 0x62cf, 0x6a02, 0x8afe, 0x4e39, 0x5be7,
1805       0x6012, 0x7387, 0x7570, 0x5317, 0x78fb, 0x4fbf, 0x5fa9, 0x4e0d,
1806       0x6ccc, 0x6578, 0x7d22, 0x53c3, 0x585e, 0x7701, 0x8449, 0x8aaa,
1807       0x6bba, 0x8fb0, 0x6c88, 0x62fe, 0x82e5, 0x63a0, 0x7565, 0x4eae,
1808       0x5169, 0x0000, 0x6881, 0x7ce7, 0x826f, 0x8ad2, 0x91cf, 0x52f5,
1809       0x5442, 0x5973, 0x5eec, 0x65c5, 0x6ffe, 0x792a, 0x95ad, 0x9a6a,
1810       0x9e97, 0x9ece, 0x529b, 0x66c6, 0x6b77, 0x8f62, 0x5e74, 0x6190,
1811       0x6200, 0x649a, 0x6f23, 0x7149, 0x7489, 0x0000, 0x7df4, 0x806f,
1812       0x8f26, 0x84ee, 0x9023, 0x934a, 0x5217, 0x52a3, 0x54bd, 0x70c8,
1813       0x88c2, 0x8aaa, 0x5ec9, 0x5ff5, 0x637b, 0x6bae, 0x7c3e, 0x7375,
1814       0x4ee4, 0x56f9, 0x5be7, 0x5dba, 0x601c, 0x73b2, 0x7469, 0x7f9a,
1815       0x8046, 0x9234, 0x96f6, 0x9748, 0x9818, 0x4f8b, 0x79ae, 0x91b4,
1816       0x96b8, 0x60e1, 0x4e86, 0x50da, 0x5bee, 0x5c3f, 0x6599, 0x6a02,
1817       0x71ce, 0x7642, 0x84fc, 0x907c, 0x9f8d, 0x6688, 0x962e, 0x5289,
1818       0x677b, 0x67f3, 0x6d41, 0x6e9c, 0x7409, 0x7559, 0x786b, 0x7d10,
1819       0x985e, 0x516d, 0x622e, 0x9678, 0x502b, 0x5d19, 0x6dea, 0x8f2a,
1820       0x5f8b, 0x6144, 0x6817, 0x7387, 0x9686, 0x5229, 0x540f, 0x5c65,
1821       0x6613, 0x674e, 0x68a8, 0x6ce5, 0x7406, 0x75e2, 0x7f79, 0x0000,
1822       0x88e1, 0x91cc, 0x96e2, 0x533f, 0x6eba, 0x541d, 0x71d0, 0x7498,
1823       0x85fa, 0x0000, 0x9c57, 0x9e9f, 0x6797, 0x6dcb, 0x81e8, 0x7acb,
1824       0x7b20, 0x7c92, 0x72c0, 0x7099, 0x8b58, 0x4ec0, 0x8336, 0x523a,
1825       0x5207, 0x5ea6, 0x62d3, 0x7cd6, 0x5b85, 0x6d1e, 0x66b4, 0x8f3b,
1826       0x884c, 0x964d, 0x898b, 0x5ed3, 0x0000, 0x0000, 0x0000, 0x0000,
1827       0x585a, 0x0000, 0x6674, 0x0000, 0x0000, 0x51de, 0x8c6c, 0x76ca,
1828       0x0000, 0x795e, 0x7965, 0x798f, 0x9756, 0x7cbe, 0x7fbd, 0x0000,
1829       0x0000, 0x0000, 0x8af8, 0x0000, 0x0000, 0x9038, 0x90fd, 0x0000,
1830       0x0000, 0x0000, 0x98ef, 0x98fc, 0x9928, 0x9db4, 0x0000, 0x0000
1831   };
1832   static const WCHAR compat_FE30_FEF7[200] =
1833   {
1834       0x2025, 0x2014, 0x2013, 0x005f, 0x005f, 0x0028, 0x0029, 0x007b,
1835       0x007d, 0x3014, 0x3015, 0x3010, 0x3011, 0x300a, 0x300b, 0x3008,
1836       0x3009, 0x300c, 0x300d, 0x300e, 0x300f, 0x0000, 0x0000, 0x0000,
1837       0x0000, 0x203e, 0x203e, 0x203e, 0x203e, 0x005f, 0x005f, 0x005f,
1838       0x002c, 0x3001, 0x002e, 0x0000, 0x003b, 0x003a, 0x003f, 0x0021,
1839       0x2014, 0x0028, 0x0029, 0x007b, 0x007d, 0x3014, 0x3015, 0x0023,
1840       0x0026, 0x002a, 0x002b, 0x002d, 0x003c, 0x003e, 0x003d, 0x0000,
1841       0x0000, 0x0024, 0x0025, 0x0040, 0x0000, 0x0000, 0x0000, 0x0000,
1842       0x064b, 0x064b, 0x064c, 0x0000, 0x064d, 0x0000, 0x064e, 0x064e,
1843       0x064f, 0x064f, 0x0650, 0x0650, 0x0651, 0x0651, 0x0652, 0x0652,
1844       0x0621, 0x0622, 0x0622, 0x0623, 0x0623, 0x0624, 0x0624, 0x0625,
1845       0x0625, 0x0626, 0x0626, 0x0626, 0x0626, 0x0627, 0x0627, 0x0628,
1846       0x0628, 0x0628, 0x0628, 0x0629, 0x0629, 0x062a, 0x062a, 0x062a,
1847       0x062a, 0x062b, 0x062b, 0x062b, 0x062b, 0x062c, 0x062c, 0x062c,
1848       0x062c, 0x062d, 0x062d, 0x062d, 0x062d, 0x062e, 0x062e, 0x062e,
1849       0x062e, 0x062f, 0x062f, 0x0630, 0x0630, 0x0631, 0x0631, 0x0632,
1850       0x0632, 0x0633, 0x0633, 0x0633, 0x0633, 0x0634, 0x0634, 0x0634,
1851       0x0634, 0x0635, 0x0635, 0x0635, 0x0635, 0x0636, 0x0636, 0x0636,
1852       0x0636, 0x0637, 0x0637, 0x0637, 0x0637, 0x0638, 0x0638, 0x0638,
1853       0x0638, 0x0639, 0x0639, 0x0639, 0x0639, 0x063a, 0x063a, 0x063a,
1854       0x063a, 0x0641, 0x0641, 0x0641, 0x0641, 0x0642, 0x0642, 0x0642,
1855       0x0642, 0x0643, 0x0643, 0x0643, 0x0643, 0x0644, 0x0644, 0x0644,
1856       0x0644, 0x0645, 0x0645, 0x0645, 0x0645, 0x0646, 0x0646, 0x0646,
1857       0x0646, 0x0647, 0x0647, 0x0647, 0x0647, 0x0648, 0x0648, 0x0649,
1858       0x0649, 0x064a, 0x064a, 0x064a, 0x064a, 0x0000, 0x0000, 0x0000
1859   };
1860   static const WCHAR compat_FF00_FFEF[240] =
1861   {
1862       0x0000, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
1863       0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
1864       0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
1865       0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
1866       0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
1867       0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
1868       0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
1869       0x0058, 0x0059, 0x005a, 0x005b, 0x0000, 0x005d, 0x005e, 0x005f,
1870       0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
1871       0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
1872       0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
1873       0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000,
1874       0x0000, 0x3002, 0x300c, 0x300d, 0x3001, 0x30fb, 0x30f2, 0x30a1,
1875       0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, 0x30c3,
1876       0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, 0x30ab, 0x30ad,
1877       0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, 0x30b9, 0x30bb, 0x30bd,
1878       0x30bf, 0x30c1, 0x30c4, 0x30c6, 0x30c8, 0x30ca, 0x30cb, 0x30cc,
1879       0x30cd, 0x30ce, 0x30cf, 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de,
1880       0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9,
1881       0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c,
1882       0x3164, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137,
1883       0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f,
1884       0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147,
1885       0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x0000,
1886       0x0000, 0x0000, 0x314f, 0x3150, 0x3151, 0x3152, 0x3153, 0x3154,
1887       0x0000, 0x0000, 0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315a,
1888       0x0000, 0x0000, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, 0x3160,
1889       0x0000, 0x0000, 0x3161, 0x3162, 0x3163, 0x0000, 0x0000, 0x0000,
1890       0x00a2, 0x00a3, 0x00ac, 0x00af, 0x00a6, 0x00a5, 0x20a9, 0x0000,
1891       0x2502, 0x2190, 0x2191, 0x2192, 0x2193, 0x25a0, 0x25cb, 0x0000
1892   };
1893   static const WCHAR ligatures_src[] =
1894   {
1895     0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
1896     0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
1897     0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
1898     0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
1899     0xfb04, 0xfb05, 0xfb06, '\0'
1900   };
1901   static const WCHAR ligatures_dst[] =
1902   {
1903     'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
1904     'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
1905     'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
1906     0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
1907     'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
1908   };
1909
1910   if (!pFoldStringW)
1911   {
1912     win_skip("FoldStringW is not available\n");
1913     return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1914   }
1915
1916   /* Invalid flag combinations */
1917   for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
1918   {
1919     src[0] = dst[0] = '\0';
1920     SetLastError(0);
1921     ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
1922     if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1923     {
1924       win_skip("FoldStringW is not implemented\n");
1925       return;
1926     }
1927     ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
1928        "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1929   }
1930
1931   /* src & dst cannot be the same */
1932   SetLastError(0);
1933   ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
1934   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1935       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1936
1937   /* src can't be NULL */
1938   SetLastError(0);
1939   ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
1940   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1941       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1942
1943   /* srclen can't be 0 */
1944   SetLastError(0);
1945   ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
1946   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1947       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1948
1949   /* dstlen can't be < 0 */
1950   SetLastError(0);
1951   ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
1952   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1953       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1954
1955   /* Ret includes terminating NUL which is appended if srclen = -1 */
1956   SetLastError(0);
1957   src[0] = 'A';
1958   src[1] = '\0';
1959   dst[0] = '\0';
1960   ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
1961   ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1962   ok(dst[0] == 'A' && dst[1] == '\0',
1963      "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%d\n",
1964      'A', '\0', ret, dst[0], dst[1], GetLastError());
1965
1966   /* If size is given, result is not NUL terminated */
1967   SetLastError(0);
1968   src[0] = 'A';
1969   src[1] = 'A';
1970   dst[0] = 'X';
1971   dst[1] = 'X';
1972   ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
1973   ok(ret == 1, "Expected ret == 1, got %d, error %d\n", ret, GetLastError());
1974   ok(dst[0] == 'A' && dst[1] == 'X',
1975      "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%d\n",
1976      'A','X', ret, dst[0], dst[1], GetLastError());
1977
1978   /* MAP_FOLDDIGITS */
1979   for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
1980   {
1981     /* Check everything before this range */
1982     for (ch = prev_ch; ch < digitRanges[j]; ch++)
1983     {
1984       SetLastError(0);
1985       src[0] = ch;
1986       src[1] = dst[0] = '\0';
1987       ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
1988       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1989
1990       ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
1991          /* Wine (correctly) maps all Unicode 4.0+ digits */
1992          isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF ||
1993          (ch >= 0x1369 && ch <= 0x1371),
1994          "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
1995     }
1996
1997     if (digitRanges[j] == 0xffff)
1998       break; /* Finished the whole code point space */
1999
2000     for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
2001     {
2002       WCHAR c;
2003
2004       /* Map out of sequence characters */
2005       if      (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
2006       else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
2007       else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
2008       else if (ch == 0x245F) c = 0x24EA; /* Circled 0     */
2009       else                   c = ch;
2010       SetLastError(0);
2011       src[0] = c;
2012       src[1] = dst[0] = '\0';
2013       ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2014       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2015
2016       ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
2017          broken( dst[0] == ch ) ||  /* old Windows versions don't have all mappings */
2018          strchrW(noDigitAvailable, c),
2019          "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
2020          ch, '0' + digitRanges[j] - ch, dst[0]);
2021     }
2022     prev_ch = ch;
2023   }
2024
2025   /* MAP_FOLDCZONE */
2026   for (ch = 1, failures = 0; ch <0xffff; ch++)
2027   {
2028     WCHAR expected = 0;
2029
2030     if (ch >= 0xF900 && ch <= 0xFA2F)
2031       expected = compat_F900_FA2F[ch - 0xF900];
2032     else if (ch >= 0xFE30 && ch <= 0xFEF7)
2033       expected = compat_FE30_FEF7[ch - 0xFE30];
2034     else if (ch >= 0xFF00 && ch <= 0xFFEF)
2035       expected = compat_FF00_FFEF[ch - 0xFF00];
2036
2037     if (!expected)
2038       expected = ch;
2039
2040     SetLastError(0);
2041     src[0] = ch;
2042     src[1] = dst[0] = '\0';
2043     ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
2044     ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2045     ok(dst[0] == expected ||
2046        broken( dst[0] == ch ) ||  /* old Windows versions don't have all mappings */
2047        /* Wine (correctly) uses updated mappings for some Unicode 4.0 chars */
2048        /* FIXME: But they should be re-checked */
2049        ch == 0xf92c || ch == 0xf979 || ch == 0xf995 || ch == 0xf9e7 ||
2050        ch == 0xf9f1 ||
2051        (0xfa0c <= ch && ch <= 0xfa6a) ||
2052        (0xfa70 <= ch && ch <= 0xfad9) ||
2053        ch == 0xfe47 || ch == 0xfe48 || ch == 0xfe68 ||
2054        (0xfe70 <= ch && ch <= 0xfe7f) ||
2055        ch == 0xff3c || ch == 0xff5f || ch == 0xff60 ||
2056        ch == 0xff9e || ch == 0xff9f,
2057        "MAP_FOLDCZONE: ch %d 0x%04x Expected 0x%04x got 0x%04x\n",
2058        ch, ch, expected, dst[0]);
2059     if (dst[0] != expected && ch < 0xf000 && ++failures > 50)
2060     {
2061         trace( "MAP_FOLDCZONE: Too many failures, giving up\n" );
2062         break;
2063     }
2064   }
2065
2066   /* MAP_EXPAND_LIGATURES */
2067   SetLastError(0);
2068   ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
2069   /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
2070   if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
2071     ok(ret == sizeof(ligatures_dst)/sizeof(ligatures_dst[0]),
2072        "Got %d, error %d\n", ret, GetLastError());
2073     ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
2074        "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
2075     for (i = 1, failures = 0; i <= 0xffff; i++)
2076     {
2077       if (!strchrW(ligatures_src, i))
2078       {
2079         src[0] = i;
2080         src[1] = '\0';
2081         SetLastError(0);
2082         ret = pFoldStringW(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
2083         ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2084         if (ret == 3)
2085             ok(0, "MAP_EXPAND_LIGATURES: %04x : Expected %04x, got %04x %04x\n",
2086                i, src[0], dst[0], dst[1]);
2087         else
2088             ok(dst[0] == src[0],
2089                "MAP_EXPAND_LIGATURES: %04x : Expected %04x, got %04x\n",
2090                i, src[0], dst[0]);
2091         if (dst[0] != src[0] && ++failures > 50)
2092         {
2093             trace( "MAP_EXPAND_LIGATURES: Too many failures, giving up\n" );
2094             break;
2095         }
2096       }
2097     }
2098   }
2099
2100   /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
2101 }
2102
2103
2104
2105 #define LCID_OK(l) \
2106   ok(lcid == l, "Expected lcid = %08x, got %08x\n", l, lcid)
2107 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
2108 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
2109 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
2110 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
2111
2112 static void test_ConvertDefaultLocale(void)
2113 {
2114   LCID lcid;
2115
2116   /* Doesn't change lcid, even if non default sublang/sort used */
2117   TEST_LCID(LANG_ENGLISH,  SUBLANG_ENGLISH_US, SORT_DEFAULT);
2118   TEST_LCID(LANG_ENGLISH,  SUBLANG_ENGLISH_UK, SORT_DEFAULT);
2119   TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT,    SORT_DEFAULT);
2120   TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT,    SORT_JAPANESE_UNICODE);
2121
2122   /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
2123   LCID_RES(MKLCID(LANG_ENGLISH,  SUBLANG_NEUTRAL, SORT_DEFAULT),
2124            MKLCID(LANG_ENGLISH,  SUBLANG_DEFAULT, SORT_DEFAULT));
2125   LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
2126            MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
2127   LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_JAPANESE_UNICODE),
2128            MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE));
2129
2130   /* Invariant language is not treated specially */
2131   TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
2132   LCID_RES(MKLCID(LANG_INVARIANT, SUBLANG_NEUTRAL, SORT_DEFAULT),
2133            MKLCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT));
2134
2135   /* User/system default languages alone are not mapped */
2136   TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
2137   TEST_LCIDLANG(LANG_USER_DEFAULT,   SORT_JAPANESE_UNICODE);
2138
2139   /* Default lcids */
2140   LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
2141   LCID_RES(LOCALE_USER_DEFAULT,   GetUserDefaultLCID());
2142   LCID_RES(LOCALE_NEUTRAL,        GetUserDefaultLCID());
2143 }
2144
2145 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
2146                                     DWORD dwFlags, LONG_PTR lParam)
2147 {
2148   trace("%08x, %s, %s, %08x, %08lx\n",
2149         lgrpid, lpszNum, lpszName, dwFlags, lParam);
2150
2151   ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
2152      "Enumerated grp %d not valid (flags %d)\n", lgrpid, dwFlags);
2153
2154   /* If lParam is one, we are calling with flags defaulted from 0 */
2155   ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
2156          "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %d\n", dwFlags);
2157
2158   return TRUE;
2159 }
2160
2161 static void test_EnumSystemLanguageGroupsA(void)
2162 {
2163   BOOL ret;
2164
2165   if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
2166   {
2167     win_skip("EnumSystemLanguageGroupsA and/or IsValidLanguageGroup are not available\n");
2168     return;
2169   }
2170
2171   /* No enumeration proc */
2172   SetLastError(0);
2173   ret = pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
2174   if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2175   {
2176     win_skip("EnumSystemLanguageGroupsA is not implemented\n");
2177     return;
2178   }
2179   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2180       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2181
2182   /* Invalid flags */
2183   SetLastError(0);
2184   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
2185   ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2186
2187   /* No flags - defaults to LGRPID_INSTALLED */
2188   SetLastError(0xdeadbeef);
2189   pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
2190   ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
2191
2192   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
2193   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
2194 }
2195
2196
2197 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
2198                                       LONG_PTR lParam)
2199 {
2200   trace("%08x, %08x, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
2201
2202   /* invalid locale enumerated on some platforms */
2203   if (lcid == 0)
2204       return TRUE;
2205
2206   ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
2207      "Enumerated grp %d not valid\n", lgrpid);
2208   ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
2209      "Enumerated grp locale %d not valid\n", lcid);
2210   return TRUE;
2211 }
2212
2213 static void test_EnumLanguageGroupLocalesA(void)
2214 {
2215   BOOL ret;
2216
2217   if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
2218   {
2219     win_skip("EnumLanguageGroupLocalesA and/or IsValidLanguageGroup are not available\n");
2220     return;
2221   }
2222
2223   /* No enumeration proc */
2224   SetLastError(0);
2225   ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
2226   if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2227   {
2228     win_skip("EnumLanguageGroupLocalesA is not implemented\n");
2229     return;
2230   }
2231   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2232       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2233
2234   /* lgrpid too small */
2235   SetLastError(0);
2236   ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
2237   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2238       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2239
2240   /* lgrpid too big */
2241   SetLastError(0);
2242   ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
2243   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2244       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2245
2246   /* dwFlags is reserved */
2247   SetLastError(0);
2248   ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
2249   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2250       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2251
2252   pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2253 }
2254
2255 static void test_SetLocaleInfoA(void)
2256 {
2257   BOOL bRet;
2258   LCID lcid = GetUserDefaultLCID();
2259
2260   /* Null data */
2261   SetLastError(0);
2262   bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2263   ok( !bRet && GetLastError() == ERROR_INVALID_PARAMETER,
2264       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2265
2266   /* IDATE */
2267   SetLastError(0);
2268   bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
2269   ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2270      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2271
2272   /* ILDATE */
2273   SetLastError(0);
2274   bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
2275   ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2276      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2277 }
2278
2279 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2280 {
2281   trace("%s %08lx\n", value, lParam);
2282   return(TRUE);
2283 }
2284
2285 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2286 {
2287   ok(!enumCount, "callback called again unexpected\n");
2288   enumCount++;
2289   return(FALSE);
2290 }
2291
2292 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2293 {
2294   ok(0,"callback called unexpected\n");
2295   return(FALSE);
2296 }
2297
2298 static void test_EnumUILanguageA(void)
2299 {
2300   BOOL ret;
2301   if (!pEnumUILanguagesA) {
2302     win_skip("EnumUILanguagesA is not available on Win9x or NT4\n");
2303     return;
2304   }
2305
2306   SetLastError(ERROR_SUCCESS);
2307   ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2308   if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2309   {
2310     win_skip("EnumUILanguagesA is not implemented\n");
2311     return;
2312   }
2313   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2314
2315   enumCount = 0;
2316   SetLastError(ERROR_SUCCESS);
2317   ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2318   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2319
2320   SetLastError(ERROR_SUCCESS);
2321   ret = pEnumUILanguagesA(NULL, 0, 0);
2322   ok(!ret, "Expected return value FALSE, got %u\n", ret);
2323   ok(GetLastError() == ERROR_INVALID_PARAMETER,
2324       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2325
2326   SetLastError(ERROR_SUCCESS);
2327   ret = pEnumUILanguagesA(luilocale_proc3A, 0x5a5a5a5a, 0);
2328   ok(!ret, "Expected return value FALSE, got %u\n", ret);
2329   ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2330
2331   SetLastError(ERROR_SUCCESS);
2332   ret = pEnumUILanguagesA(NULL, 0x5a5a5a5a, 0);
2333   ok(!ret, "Expected return value FALSE, got %u\n", ret);
2334   ok(GetLastError() == ERROR_INVALID_PARAMETER,
2335       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2336 }
2337
2338 static char date_fmt_buf[1024];
2339
2340 static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
2341 {
2342     lstrcatA(date_fmt_buf, fmt);
2343     lstrcatA(date_fmt_buf, "\n");
2344     return TRUE;
2345 }
2346
2347 static void test_EnumDateFormatsA(void)
2348 {
2349     char *p, buf[256];
2350     BOOL ret;
2351     LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2352
2353     trace("EnumDateFormatsA 0\n");
2354     date_fmt_buf[0] = 0;
2355     SetLastError(0xdeadbeef);
2356     ret = EnumDateFormatsA(enum_datetime_procA, lcid, 0);
2357     if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2358     {
2359         win_skip("0 for dwFlags is not supported\n");
2360     }
2361     else
2362     {
2363         ok(ret, "EnumDateFormatsA(0) error %d\n", GetLastError());
2364         trace("%s\n", date_fmt_buf);
2365         /* test the 1st enumerated format */
2366         if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2367         ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2368         ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2369         ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2370     }
2371
2372     trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n");
2373     date_fmt_buf[0] = 0;
2374     SetLastError(0xdeadbeef);
2375     ret = EnumDateFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2376     if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2377     {
2378         win_skip("LOCALE_USE_CP_ACP is not supported\n");
2379     }
2380     else
2381     {
2382         ok(ret, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2383         trace("%s\n", date_fmt_buf);
2384         /* test the 1st enumerated format */
2385         if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2386         ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2387         ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2388         ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2389     }
2390
2391     trace("EnumDateFormatsA DATE_SHORTDATE\n");
2392     date_fmt_buf[0] = 0;
2393     ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_SHORTDATE);
2394     ok(ret, "EnumDateFormatsA(DATE_SHORTDATE) error %d\n", GetLastError());
2395     trace("%s\n", date_fmt_buf);
2396     /* test the 1st enumerated format */
2397     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2398     ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2399     ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2400     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2401
2402     trace("EnumDateFormatsA DATE_LONGDATE\n");
2403     date_fmt_buf[0] = 0;
2404     ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_LONGDATE);
2405     ok(ret, "EnumDateFormatsA(DATE_LONGDATE) error %d\n", GetLastError());
2406     trace("%s\n", date_fmt_buf);
2407     /* test the 1st enumerated format */
2408     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2409     ret = GetLocaleInfoA(lcid, LOCALE_SLONGDATE, buf, sizeof(buf));
2410     ok(ret, "GetLocaleInfoA(LOCALE_SLONGDATE) error %d\n", GetLastError());
2411     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2412
2413     trace("EnumDateFormatsA DATE_YEARMONTH\n");
2414     date_fmt_buf[0] = 0;
2415     SetLastError(0xdeadbeef);
2416     ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_YEARMONTH);
2417     if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2418     {
2419         skip("DATE_YEARMONTH is only present on W2K and later\n");
2420         return;
2421     }
2422     ok(ret, "EnumDateFormatsA(DATE_YEARMONTH) error %d\n", GetLastError());
2423     trace("%s\n", date_fmt_buf);
2424     /* test the 1st enumerated format */
2425     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2426     ret = GetLocaleInfoA(lcid, LOCALE_SYEARMONTH, buf, sizeof(buf));
2427     ok(ret, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %d\n", GetLastError());
2428     ok(!lstrcmpA(date_fmt_buf, buf) || broken(!buf[0]) /* win9x */,
2429        "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2430 }
2431
2432 static void test_EnumTimeFormatsA(void)
2433 {
2434     char *p, buf[256];
2435     BOOL ret;
2436     LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2437
2438     trace("EnumTimeFormatsA 0\n");
2439     date_fmt_buf[0] = 0;
2440     ret = EnumTimeFormatsA(enum_datetime_procA, lcid, 0);
2441     ok(ret, "EnumTimeFormatsA(0) error %d\n", GetLastError());
2442     trace("%s\n", date_fmt_buf);
2443     /* test the 1st enumerated format */
2444     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2445     ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2446     ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2447     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2448
2449     trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n");
2450     date_fmt_buf[0] = 0;
2451     ret = EnumTimeFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2452     ok(ret, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2453     trace("%s\n", date_fmt_buf);
2454     /* test the 1st enumerated format */
2455     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2456     ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2457     ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2458     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2459 }
2460
2461 static void test_GetCPInfo(void)
2462 {
2463     BOOL ret;
2464     CPINFO cpinfo;
2465
2466     SetLastError(0xdeadbeef);
2467     ret = GetCPInfo(CP_SYMBOL, &cpinfo);
2468     ok(!ret, "GetCPInfo(CP_SYMBOL) should fail\n");
2469     ok(GetLastError() == ERROR_INVALID_PARAMETER,
2470        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2471
2472     SetLastError(0xdeadbeef);
2473     ret = GetCPInfo(CP_UTF7, &cpinfo);
2474     if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2475     {
2476         skip("Codepage CP_UTF7 is not installed/available\n");
2477     }
2478     else
2479     {
2480         ok(ret, "GetCPInfo(CP_UTF7) error %u\n", GetLastError());
2481         ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2482         ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2483         ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2484         ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2485         ok(cpinfo.MaxCharSize == 5, "expected 5, got 0x%x\n", cpinfo.MaxCharSize);
2486     }
2487
2488     SetLastError(0xdeadbeef);
2489     ret = GetCPInfo(CP_UTF8, &cpinfo);
2490     if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2491     {
2492         skip("Codepage CP_UTF8 is not installed/available\n");
2493     }
2494     else
2495     {
2496         ok(ret, "GetCPInfo(CP_UTF8) error %u\n", GetLastError());
2497         ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2498         ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2499         ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2500         ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2501         ok(cpinfo.MaxCharSize == 4 || broken(cpinfo.MaxCharSize == 3) /* win9x */,
2502            "expected 4, got %u\n", cpinfo.MaxCharSize);
2503     }
2504 }
2505
2506 START_TEST(locale)
2507 {
2508   InitFunctionPointers();
2509
2510   test_EnumTimeFormatsA();
2511   test_EnumDateFormatsA();
2512   test_GetLocaleInfoA();
2513   test_GetTimeFormatA();
2514   test_GetDateFormatA();
2515   test_GetDateFormatW();
2516   test_GetCurrencyFormatA(); /* Also tests the W version */
2517   test_GetNumberFormatA();   /* Also tests the W version */
2518   test_CompareStringA();
2519   test_LCMapStringA();
2520   test_LCMapStringW();
2521   test_FoldStringA();
2522   test_FoldStringW();
2523   test_ConvertDefaultLocale();
2524   test_EnumSystemLanguageGroupsA();
2525   test_EnumLanguageGroupLocalesA();
2526   test_SetLocaleInfoA();
2527   test_EnumUILanguageA();
2528   test_GetCPInfo();
2529   /* this requires collation table patch to make it MS compatible */
2530   if (0) test_sorting();
2531 }