Correct the calculation of the year for the 31'st of December of 2000
[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   /* 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 START_TEST(locale)
2027 {
2028   InitFunctionPointers();
2029
2030 #if 0
2031   test_EnumTimeFormats();
2032 #endif
2033   test_GetLocaleInfoA();
2034   test_GetTimeFormatA();
2035   test_GetDateFormatA();
2036   test_GetDateFormatW();
2037   test_GetCurrencyFormatA(); /* Also tests the W version */
2038   test_GetNumberFormatA();   /* Also tests the W version */
2039   test_CompareStringA();
2040   test_LCMapStringA();
2041   test_LCMapStringW();
2042   test_FoldStringA();
2043   test_FoldStringW();
2044   test_ConvertDefaultLocale();
2045   test_EnumSystemLanguageGroupsA();
2046   test_EnumLanguageGroupLocalesA();
2047   test_SetLocaleInfoA();
2048 #if 0 /* this requires collation table patch to make it MS compatible */
2049   test_sorting();
2050 #endif
2051 }