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