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