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