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