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