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