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