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