LoadLibrary should ignore trailing spaces in the library name.
[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          "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
1798     }
1799
1800     if (digitRanges[j] == 0xffff)
1801       break; /* Finished the whole code point space */
1802
1803     for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
1804     {
1805       WCHAR c;
1806
1807       /* Map out of sequence characters */
1808       if      (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
1809       else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
1810       else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
1811       else if (ch == 0x245F) c = 0x24EA; /* Circled 0     */
1812       else                   c = ch;
1813       SetLastError(0);
1814       src[0] = c;
1815       src[1] = dst[0] = '\0';
1816       ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
1817       EXPECT_LEN(2); EXPECT_VALID;
1818
1819       ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
1820          strchrW(noDigitAvailable, c),
1821          "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
1822          ch, '0' + digitRanges[j] - ch, dst[0]);
1823     }
1824     prev_ch = ch;
1825   }
1826
1827   /* MAP_FOLDCZONE */
1828   for (ch = 1; ch <0xffff; ch++)
1829   {
1830     WCHAR expected = 0;
1831
1832     if (ch >= 0xF900 && ch <= 0xFA2F)
1833       expected = compat_F900_FA2F[ch - 0xF900];
1834     else if (ch >= 0xFE30 && ch <= 0xFEF7)
1835       expected = compat_FE30_FEF7[ch - 0xFE30];
1836     else if (ch >= 0xFF00 && ch <= 0xFFEF)
1837       expected = compat_FF00_FFEF[ch - 0xFF00];
1838
1839     if (!expected)
1840       expected = ch;
1841
1842     SetLastError(0);
1843     src[0] = ch;
1844     src[1] = dst[0] = '\0';
1845     ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
1846     EXPECT_LEN(2); EXPECT_VALID;
1847     ok(dst[0] == expected ||
1848        /* Wine (correctly) uses updated mappings for some Unicode 4.0 chars */
1849        (ch >= 0xFA0D && ch <= 0xFA47) ||
1850        0xf92c || ch == 0xf979 || ch == 0xf995 || ch == 0xf9e7 || ch == 0xf9f1,
1851        "MAP_FOLDCZONE: ch %d 0x%04x Expected 0x%04x got 0x%04x\n",
1852        ch, ch, expected, dst[0]);
1853   }
1854
1855   /* MAP_EXPAND_LIGATURES */
1856   SetLastError(0);
1857   ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1858   /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1859   if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1860     EXPECT_LEN(sizeof(ligatures_dst)/sizeof(ligatures_dst[0])); EXPECT_VALID;
1861     ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
1862        "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
1863     for (i = 1; i <= 0xffff; i++)
1864     {
1865       if (!strchrW(ligatures_src, i))
1866       {
1867         src[0] = i;
1868         src[1] = '\0';
1869         SetLastError(0);
1870         ret = pFoldStringW(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1871         EXPECT_LEN(2); EXPECT_VALID;
1872         ok(dst[0] == src[0],
1873            "MAP_EXPAND_LIGATURES: 0x%02x : Expected 0x%02x, got 0x%02x\n",
1874            i, src[0], dst[0]);
1875       }
1876     }
1877   }
1878
1879   /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
1880 }
1881
1882
1883
1884 #define LCID_OK(l) \
1885   ok(lcid == l, "Expected lcid = %08lx, got %08lx\n", l, lcid)
1886 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
1887 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
1888 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
1889 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
1890
1891 static void test_ConvertDefaultLocale(void)
1892 {
1893   LCID lcid;
1894
1895   /* Doesn't change lcid, even if non default sublang/sort used */
1896   TEST_LCID(LANG_ENGLISH,  SUBLANG_ENGLISH_US, SORT_DEFAULT);
1897   TEST_LCID(LANG_ENGLISH,  SUBLANG_ENGLISH_UK, SORT_DEFAULT);
1898   TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT,    SORT_DEFAULT);
1899   TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT,    SORT_JAPANESE_UNICODE);
1900
1901   /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
1902   LCID_RES(MKLCID(LANG_ENGLISH,  SUBLANG_NEUTRAL, SORT_DEFAULT),
1903            MKLCID(LANG_ENGLISH,  SUBLANG_DEFAULT, SORT_DEFAULT));
1904   LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
1905            MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
1906   LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_JAPANESE_UNICODE),
1907            MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE));
1908
1909   /* Invariant language is not treated specially */
1910   TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
1911   LCID_RES(MKLCID(LANG_INVARIANT, SUBLANG_NEUTRAL, SORT_DEFAULT),
1912            MKLCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT));
1913
1914   /* User/system default languages alone are not mapped */
1915   TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
1916   TEST_LCIDLANG(LANG_USER_DEFAULT,   SORT_JAPANESE_UNICODE);
1917
1918   /* Default lcids */
1919   LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
1920   LCID_RES(LOCALE_USER_DEFAULT,   GetUserDefaultLCID());
1921   LCID_RES(LOCALE_NEUTRAL,        GetUserDefaultLCID());
1922 }
1923
1924 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
1925                                     DWORD dwFlags, LONG_PTR lParam)
1926 {
1927   trace("%08lx, %s, %s, %08lx, %08lx\n",
1928         lgrpid, lpszNum, lpszName, dwFlags, lParam);
1929
1930   ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
1931      "Enumerated grp %ld not valid (flags %ld)\n", lgrpid, dwFlags);
1932
1933   /* If lParam is one, we are calling with flags defaulted from 0 */
1934   ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
1935          "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %ld\n", dwFlags);
1936
1937   return TRUE;
1938 }
1939
1940 static void test_EnumSystemLanguageGroupsA(void)
1941 {
1942   if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
1943     return;
1944
1945   /* No enumeration proc */
1946   SetLastError(0);
1947   pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
1948   EXPECT_INVALID;
1949
1950   /* Invalid flags */
1951   SetLastError(0);
1952   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
1953   EXPECT_FLAGS;
1954
1955   /* No flags - defaults to LGRPID_INSTALLED */
1956   SetLastError(0);
1957   pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
1958   EXPECT_VALID;
1959
1960   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
1961   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
1962 }
1963
1964
1965 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
1966                                       LONG_PTR lParam)
1967 {
1968   trace("%08lx, %08lx, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
1969
1970   ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
1971      "Enumerated grp %ld not valid\n", lgrpid);
1972   ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
1973      "Enumerated grp locale %ld not valid\n", lcid);
1974   return TRUE;
1975 }
1976
1977 static void test_EnumLanguageGroupLocalesA(void)
1978 {
1979   if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
1980     return;
1981
1982   /* No enumeration proc */
1983   SetLastError(0);
1984   pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
1985   EXPECT_INVALID;
1986
1987   /* lgrpid too small */
1988   SetLastError(0);
1989   pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
1990   EXPECT_INVALID;
1991
1992   /* lgrpid too big */
1993   SetLastError(0);
1994   pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
1995   EXPECT_INVALID;
1996
1997   /* dwFlags is reserved */
1998   SetLastError(0);
1999   pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
2000   EXPECT_INVALID;
2001
2002   pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2003 }
2004
2005 static void test_SetLocaleInfoA(void)
2006 {
2007   BOOL bRet;
2008   LCID lcid = GetUserDefaultLCID();
2009
2010   /* Null data */
2011   SetLastError(0);
2012   bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2013   EXPECT_INVALID;
2014
2015   /* IDATE */
2016   SetLastError(0);
2017   bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
2018   EXPECT_FLAGS;
2019
2020   /* ILDATE */
2021   SetLastError(0);
2022   bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
2023   EXPECT_FLAGS;
2024 }
2025
2026 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2027 {
2028   trace("%s %08lx\n", value, lParam);
2029   return(TRUE);
2030 }
2031
2032 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2033 {
2034   ok(!enumCount, "callback called again unexpected\n");
2035   enumCount++;
2036   return(FALSE);
2037 }
2038
2039 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2040 {
2041   ok(0,"callback called unexpected\n");
2042   return(FALSE);
2043 }
2044
2045 static void test_EnumUILanguageA(void)
2046 {
2047   BOOL ret;
2048   if (!pEnumUILanguagesA) {
2049     trace("EnumUILanguagesA is not available on Win9x\n");
2050     return;
2051   }
2052
2053   SetLastError(ERROR_SUCCESS);
2054   ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2055   EXPECT_TRUE; EXPECT_VALID;
2056
2057   enumCount = 0;
2058   SetLastError(ERROR_SUCCESS);
2059   ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2060   EXPECT_TRUE; EXPECT_VALID;
2061
2062   SetLastError(ERROR_SUCCESS);
2063   ret = pEnumUILanguagesA(NULL, 0, 0);
2064   EXPECT_FALSE; EXPECT_INVALID;
2065
2066   SetLastError(ERROR_SUCCESS);
2067   ret = pEnumUILanguagesA(luilocale_proc3A, 0x5a5a5a5a, 0);
2068   EXPECT_FALSE; EXPECT_FLAGS;
2069
2070   SetLastError(ERROR_SUCCESS);
2071   ret = pEnumUILanguagesA(NULL, 0x5a5a5a5a, 0);
2072   EXPECT_FALSE; EXPECT_INVALID;
2073 }
2074
2075 static char date_fmt_buf[1024];
2076
2077 static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
2078 {
2079     lstrcatA(date_fmt_buf, fmt);
2080     lstrcatA(date_fmt_buf, "\n");
2081     return TRUE;
2082 }
2083
2084 static void test_EnumDateFormatsA(void)
2085 {
2086     char *p, buf[256];
2087     BOOL ret;
2088     LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2089
2090     trace("EnumDateFormatsA 0\n");
2091     date_fmt_buf[0] = 0;
2092     ret = EnumDateFormatsA(enum_datetime_procA, lcid, 0);
2093     ok(ret, "EnumDateFormatsA(0) error %ld\n", GetLastError());
2094     trace("%s\n", date_fmt_buf);
2095     /* test the 1st enumerated format */
2096     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2097     ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2098     ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %ld\n", GetLastError());
2099     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2100
2101     trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n");
2102     date_fmt_buf[0] = 0;
2103     ret = EnumDateFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2104     ok(ret, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %ld\n", GetLastError());
2105     trace("%s\n", date_fmt_buf);
2106     /* test the 1st enumerated format */
2107     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2108     ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2109     ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %ld\n", GetLastError());
2110     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2111
2112     trace("EnumDateFormatsA DATE_SHORTDATE\n");
2113     date_fmt_buf[0] = 0;
2114     ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_SHORTDATE);
2115     ok(ret, "EnumDateFormatsA(DATE_SHORTDATE) error %ld\n", GetLastError());
2116     trace("%s\n", date_fmt_buf);
2117     /* test the 1st enumerated format */
2118     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2119     ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2120     ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %ld\n", GetLastError());
2121     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2122
2123     trace("EnumDateFormatsA DATE_LONGDATE\n");
2124     date_fmt_buf[0] = 0;
2125     ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_LONGDATE);
2126     ok(ret, "EnumDateFormatsA(DATE_LONGDATE) error %ld\n", GetLastError());
2127     trace("%s\n", date_fmt_buf);
2128     /* test the 1st enumerated format */
2129     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2130     ret = GetLocaleInfoA(lcid, LOCALE_SLONGDATE, buf, sizeof(buf));
2131     ok(ret, "GetLocaleInfoA(LOCALE_SLONGDATE) error %ld\n", GetLastError());
2132     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2133
2134     trace("EnumDateFormatsA DATE_YEARMONTH\n");
2135     date_fmt_buf[0] = 0;
2136     ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_YEARMONTH);
2137     ok(ret, "EnumDateFormatsA(DATE_YEARMONTH) error %ld\n", GetLastError());
2138     trace("%s\n", date_fmt_buf);
2139     /* test the 1st enumerated format */
2140     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2141     ret = GetLocaleInfoA(lcid, LOCALE_SYEARMONTH, buf, sizeof(buf));
2142     ok(ret, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %ld\n", GetLastError());
2143     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2144 }
2145
2146 static void test_EnumTimeFormatsA(void)
2147 {
2148     char *p, buf[256];
2149     BOOL ret;
2150     LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2151
2152     trace("EnumTimeFormatsA 0\n");
2153     date_fmt_buf[0] = 0;
2154     ret = EnumTimeFormatsA(enum_datetime_procA, lcid, 0);
2155     ok(ret, "EnumTimeFormatsA(0) error %ld\n", GetLastError());
2156     trace("%s\n", date_fmt_buf);
2157     /* test the 1st enumerated format */
2158     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2159     ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2160     ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %ld\n", GetLastError());
2161     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2162
2163     trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n");
2164     date_fmt_buf[0] = 0;
2165     ret = EnumTimeFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2166     ok(ret, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %ld\n", GetLastError());
2167     trace("%s\n", date_fmt_buf);
2168     /* test the 1st enumerated format */
2169     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2170     ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2171     ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %ld\n", GetLastError());
2172     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2173 }
2174
2175 START_TEST(locale)
2176 {
2177   InitFunctionPointers();
2178
2179   test_EnumTimeFormatsA();
2180   test_EnumDateFormatsA();
2181
2182   test_GetLocaleInfoA();
2183   test_GetTimeFormatA();
2184   test_GetDateFormatA();
2185   test_GetDateFormatW();
2186   test_GetCurrencyFormatA(); /* Also tests the W version */
2187   test_GetNumberFormatA();   /* Also tests the W version */
2188   test_CompareStringA();
2189   test_LCMapStringA();
2190   test_LCMapStringW();
2191   test_FoldStringA();
2192   test_FoldStringW();
2193   test_ConvertDefaultLocale();
2194   test_EnumSystemLanguageGroupsA();
2195   test_EnumLanguageGroupLocalesA();
2196   test_SetLocaleInfoA();
2197   test_EnumUILanguageA();
2198
2199   /* this requires collation table patch to make it MS compatible */
2200   if (0) test_sorting();
2201 }