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