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