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