Allow the implementation of the VxDCall entry points to be moved to
[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, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret);
799
800     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"EndDialog",-1,"_Property",-1);
801     ok( ret == 3, "EndDialog vs _Property ... expected 3, got %d\n", ret);
802
803     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0070",-1,"_IEWWBrowserComp",-1);
804     ok( ret == 3, "osp_vba.sreg0070 vs _IEWWBrowserComp ... expected 3, got %d\n", ret);
805
806     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"r",-1,"\\",-1); 
807     ok( ret == 3, "r vs \\ ... expected 3, got %d\n", ret);
808
809     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0031", -1, "OriginalDatabase", -1 );
810     ok( ret == 3, "osp_vba.sreg0031 vs OriginalDatabase ... expected 3, got %d\n", ret);
811
812     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1 );
813     ok( ret == 3, "AAA vs aaa expected 3, got %d\n", ret);
814
815     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1 );
816     ok( ret == 1, "AAA vs aab expected 1, got %d\n", ret);
817
818     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1 );
819     ok( ret == 1, "AAA vs Aab expected 1, got %d\n", ret);
820
821     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1 );
822     ok( ret == 1, ".AAA vs Aab expected 1, got %d\n", ret);
823
824     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1 );
825     ok( ret == 1, ".AAA vs A.ab expected 1, got %d\n", ret);
826
827     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1 );
828     ok( ret == 1, "aa vs AB expected 1, got %d\n", ret);
829
830     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1 );
831     ok( ret == 1, "aa vs Aab expected 1, got %d\n", ret);
832
833     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1 );
834     ok( ret == 3, "aB vs Aab expected 3, got %d\n", ret);
835
836     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1 );
837     ok( ret == 1, "Ba vs bab expected 1, got %d\n", ret);
838
839     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1 );
840     ok( ret == 1, "{100}{83}{71}{71}{71} vs Global_DataAccess_JRO expected 1, got %d\n", ret);
841
842     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1 );
843     ok( ret == 3, "a vs { expected 3, got %d\n", ret);
844
845     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1 );
846     ok( ret == 3, "A vs { expected 3, got %d\n", ret);
847
848     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1 );
849     ok(ret == 1, "3.5/0 vs 4.0/-1 expected 1, got %d\n", ret);
850
851     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1 );
852     ok(ret == 1, "3.5 vs 4.0 expected 1, got %d\n", ret);
853
854     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1 );
855     ok(ret == 1, "3.520.4403.2 vs 4.0.2927.10 expected 1, got %d\n", ret);
856
857    /* hyphen and apostrophe are treated differently depending on
858     * whether SORT_STRINGSORT specified or not
859     */
860     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1 );
861     ok(ret == 3, "-o vs /m expected 3, got %d\n", ret);
862
863     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1 );
864     ok(ret == 1, "/m vs -o expected 1, got %d\n", ret);
865
866     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1 );
867     ok(ret == 1, "-o vs /m expected 1, got %d\n", ret);
868
869     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1 );
870     ok(ret == 3, "/m vs -o expected 3, got %d\n", ret);
871
872     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1 );
873     ok(ret == 3, "'o vs /m expected 3, got %d\n", ret);
874
875     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1 );
876     ok(ret == 1, "/m vs 'o expected 1, got %d\n", ret);
877
878     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1 );
879     ok(ret == 1, "'o vs /m expected 1, got %d\n", ret);
880
881     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1 );
882     ok(ret == 3, "/m vs 'o expected 3, got %d\n", ret);
883
884 #if 0 /* this requires collation table patch to make it MS compatible */
885     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
886     ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
887
888     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
889     ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
890
891     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
892     ok(ret == 1, "' vs - expected 1, got %d\n", ret);
893
894     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
895     ok(ret == 1, "' vs - expected 1, got %d\n", ret);
896
897     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
898     ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
899
900     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
901     ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
902
903     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
904     ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
905
906     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
907     ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
908
909     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
910     ok(ret == 1, "`o vs -m expected 1, got %d\n", ret);
911
912     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
913     ok(ret == 3, "-m vs `o expected 3, got %d\n", ret);
914
915     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
916     ok(ret == 3, "`o vs -m expected 3, got %d\n", ret);
917
918     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
919     ok(ret == 1, "-m vs `o expected 1, got %d\n", ret);
920 #endif
921
922     ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9);
923     ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0 expected 2, got %d\n", ret);
924
925     ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10);
926     ok(ret == 1, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1, got %d\n", ret);
927
928     ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
929     ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0A expected 2, got %d\n", ret);
930
931     ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
932     ok(ret == 2, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected 2, got %d\n", ret);
933 }
934
935 void test_LCMapStringA(void)
936 {
937     int ret, ret2;
938     char buf[256], buf2[256];
939     static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
940     static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
941     static const char symbols_stripped[] = "justateststring1";
942
943     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
944                        upper_case, -1, buf, sizeof(buf));
945     ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
946     ok(GetLastError() == ERROR_INVALID_FLAGS,
947        "unexpected error code %ld\n", GetLastError());
948
949     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
950                        upper_case, -1, buf, sizeof(buf));
951     ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
952     ok(GetLastError() == ERROR_INVALID_FLAGS,
953        "unexpected error code %ld\n", GetLastError());
954
955     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
956
957                        upper_case, -1, buf, sizeof(buf));
958     ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
959     ok(GetLastError() == ERROR_INVALID_FLAGS,
960        "unexpected error code %ld\n", GetLastError());
961
962     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
963                        upper_case, -1, buf, sizeof(buf));
964     ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
965     ok(GetLastError() == ERROR_INVALID_FLAGS,
966        "unexpected error code %ld\n", GetLastError());
967
968     /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
969     SetLastError(0xdeadbeef);
970     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
971                        upper_case, -1, buf, sizeof(buf));
972     ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError());
973     ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
974
975     /* test LCMAP_LOWERCASE */
976     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
977                        upper_case, -1, buf, sizeof(buf));
978     ok(ret == lstrlenA(upper_case) + 1,
979        "ret %d, error %ld, expected value %d\n",
980        ret, GetLastError(), lstrlenA(upper_case) + 1);
981     ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
982
983     /* test LCMAP_UPPERCASE */
984     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
985                        lower_case, -1, buf, sizeof(buf));
986     ok(ret == lstrlenA(lower_case) + 1,
987        "ret %d, error %ld, expected value %d\n",
988        ret, GetLastError(), lstrlenA(lower_case) + 1);
989     ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
990
991     /* test buffer overflow */
992     SetLastError(0xdeadbeef);
993     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
994                        lower_case, -1, buf, 4);
995     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
996        "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
997
998     /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
999     lstrcpyA(buf, lower_case);
1000     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1001                        buf, -1, buf, sizeof(buf));
1002     if (!ret) /* Win9x */
1003         trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1004     else
1005     {
1006         ok(ret == lstrlenA(lower_case) + 1,
1007            "ret %d, error %ld, expected value %d\n",
1008            ret, GetLastError(), lstrlenA(lower_case) + 1);
1009         ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1010     }
1011     lstrcpyA(buf, upper_case);
1012     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1013                        buf, -1, buf, sizeof(buf));
1014     if (!ret) /* Win9x */
1015         trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1016     else
1017     {
1018         ok(ret == lstrlenA(upper_case) + 1,
1019            "ret %d, error %ld, expected value %d\n",
1020            ret, GetLastError(), lstrlenA(lower_case) + 1);
1021         ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1022     }
1023
1024     /* otherwise src == dst should fail */
1025     SetLastError(0xdeadbeef);
1026     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1027                        buf, 10, buf, sizeof(buf));
1028     ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1029        GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1030        "unexpected error code %ld\n", GetLastError());
1031     ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1032
1033     /* test whether '\0' is always appended */
1034     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1035                        upper_case, -1, buf, sizeof(buf));
1036     ok(ret, "LCMapStringA must succeed\n");
1037     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1038                        upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1039     ok(ret, "LCMapStringA must succeed\n");
1040     ok(ret == ret2, "lengths of sort keys must be equal\n");
1041     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1042
1043     /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1044     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1045                        upper_case, -1, buf, sizeof(buf));
1046     ok(ret, "LCMapStringA must succeed\n");
1047     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1048                        lower_case, -1, buf2, sizeof(buf2));
1049     ok(ret2, "LCMapStringA must succeed\n");
1050     ok(ret == ret2, "lengths of sort keys must be equal\n");
1051     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1052
1053     /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1054     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1055                        lower_case, -1, buf, sizeof(buf));
1056     ok(ret, "LCMapStringA must succeed\n");
1057     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1058                        lower_case, -1, buf2, sizeof(buf2));
1059     ok(ret2, "LCMapStringA must succeed\n");
1060     ok(ret == ret2, "lengths of sort keys must be equal\n");
1061     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1062
1063     /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1064     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1065                        lower_case, -1, buf, sizeof(buf));
1066     ok(ret, "LCMapStringA must succeed\n");
1067     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1068                        symbols_stripped, -1, buf2, sizeof(buf2));
1069     ok(ret2, "LCMapStringA must succeed\n");
1070     ok(ret == ret2, "lengths of sort keys must be equal\n");
1071     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1072
1073     /* test NORM_IGNORENONSPACE */
1074     lstrcpyA(buf, "foo");
1075     ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1076                        lower_case, -1, buf, sizeof(buf));
1077     ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1078         lstrlenA(lower_case) + 1, ret);
1079     ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1080
1081     /* test NORM_IGNORESYMBOLS */
1082     lstrcpyA(buf, "foo");
1083     ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1084                        lower_case, -1, buf, sizeof(buf));
1085     ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1086         lstrlenA(symbols_stripped) + 1, ret);
1087     ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1088
1089     /* test srclen = 0 */
1090     SetLastError(0xdeadbeef);
1091     ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1092     ok(!ret, "LCMapStringA should fail with srclen = 0\n");
1093     ok(GetLastError() == ERROR_INVALID_PARAMETER,
1094        "unexpected error code %ld\n", GetLastError());
1095 }
1096
1097 void test_LCMapStringW(void)
1098 {
1099     int ret, ret2;
1100     WCHAR buf[256], buf2[256];
1101     char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1102     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};
1103     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};
1104     static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
1105     static const WCHAR fooW[] = {'f','o','o',0};
1106
1107     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1108                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1109     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1110     {
1111         trace("Skipping LCMapStringW tests on Win9x\n");
1112         return;
1113     }
1114     ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1115     ok(GetLastError() == ERROR_INVALID_FLAGS,
1116        "unexpected error code %ld\n", GetLastError());
1117
1118     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1119                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1120     ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1121     ok(GetLastError() == ERROR_INVALID_FLAGS,
1122        "unexpected error code %ld\n", GetLastError());
1123
1124     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1125                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1126     ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1127     ok(GetLastError() == ERROR_INVALID_FLAGS,
1128        "unexpected error code %ld\n", GetLastError());
1129
1130     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1131                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1132     ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1133     ok(GetLastError() == ERROR_INVALID_FLAGS,
1134        "unexpected error code %ld\n", GetLastError());
1135
1136     /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1137     SetLastError(0xdeadbeef);
1138     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1139                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1140     ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError());
1141     ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1142
1143     /* test LCMAP_LOWERCASE */
1144     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1145                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1146     ok(ret == lstrlenW(upper_case) + 1,
1147        "ret %d, error %ld, expected value %d\n",
1148        ret, GetLastError(), lstrlenW(upper_case) + 1);
1149     ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1150
1151     /* test LCMAP_UPPERCASE */
1152     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1153                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1154     ok(ret == lstrlenW(lower_case) + 1,
1155        "ret %d, error %ld, expected value %d\n",
1156        ret, GetLastError(), lstrlenW(lower_case) + 1);
1157     ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1158
1159     /* test buffer overflow */
1160     SetLastError(0xdeadbeef);
1161     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1162                        lower_case, -1, buf, 4);
1163     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1164        "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1165
1166     /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1167     lstrcpyW(buf, lower_case);
1168     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1169                        buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1170     ok(ret == lstrlenW(lower_case) + 1,
1171        "ret %d, error %ld, expected value %d\n",
1172        ret, GetLastError(), lstrlenW(lower_case) + 1);
1173     ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1174
1175     lstrcpyW(buf, upper_case);
1176     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1177                        buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1178     ok(ret == lstrlenW(upper_case) + 1,
1179        "ret %d, error %ld, expected value %d\n",
1180        ret, GetLastError(), lstrlenW(lower_case) + 1);
1181     ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1182
1183     /* otherwise src == dst should fail */
1184     SetLastError(0xdeadbeef);
1185     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1186                        buf, 10, buf, sizeof(buf));
1187     ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1188        GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1189        "unexpected error code %ld\n", GetLastError());
1190     ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1191
1192     /* test whether '\0' is always appended */
1193     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1194                        upper_case, -1, buf, sizeof(buf));
1195     ok(ret, "LCMapStringW must succeed\n");
1196     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1197                        upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1198     ok(ret, "LCMapStringW must succeed\n");
1199     ok(ret == ret2, "lengths of sort keys must be equal\n");
1200     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1201
1202     /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1203     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1204                        upper_case, -1, buf, sizeof(buf));
1205     ok(ret, "LCMapStringW must succeed\n");
1206     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1207                        lower_case, -1, buf2, sizeof(buf2));
1208     ok(ret2, "LCMapStringW must succeed\n");
1209     ok(ret == ret2, "lengths of sort keys must be equal\n");
1210     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1211
1212     /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1213     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1214                        lower_case, -1, buf, sizeof(buf));
1215     ok(ret, "LCMapStringW must succeed\n");
1216     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1217                        lower_case, -1, buf2, sizeof(buf2));
1218     ok(ret2, "LCMapStringW must succeed\n");
1219     ok(ret == ret2, "lengths of sort keys must be equal\n");
1220     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1221
1222     /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1223     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1224                        lower_case, -1, buf, sizeof(buf));
1225     ok(ret, "LCMapStringW must succeed\n");
1226     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1227                        symbols_stripped, -1, buf2, sizeof(buf2));
1228     ok(ret2, "LCMapStringW must succeed\n");
1229     ok(ret == ret2, "lengths of sort keys must be equal\n");
1230     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1231
1232     /* test NORM_IGNORENONSPACE */
1233     lstrcpyW(buf, fooW);
1234     ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1235                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1236     ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1237         lstrlenW(lower_case) + 1, ret);
1238     ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1239
1240     /* test NORM_IGNORESYMBOLS */
1241     lstrcpyW(buf, fooW);
1242     ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1243                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1244     ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1245         lstrlenW(symbols_stripped) + 1, ret);
1246     ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1247
1248     /* test srclen = 0 */
1249     SetLastError(0xdeadbeef);
1250     ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1251     ok(!ret, "LCMapStringW should fail with srclen = 0\n");
1252     ok(GetLastError() == ERROR_INVALID_PARAMETER,
1253        "unexpected error code %ld\n", GetLastError());
1254 }
1255
1256 #if 0 /* this requires collation table patch to make it MS compatible */
1257 const char *strings_sorted[] =
1258 {
1259 "'",
1260 "-",
1261 "!",
1262 "\"",
1263 ".",
1264 ":",
1265 "\\",
1266 "_",
1267 "`",
1268 "{",
1269 "}",
1270 "+",
1271 "0",
1272 "1",
1273 "2",
1274 "3",
1275 "4",
1276 "5",
1277 "6",
1278 "7",
1279 "8",
1280 "9",
1281 "a",
1282 "A",
1283 "b",
1284 "B",
1285 "c",
1286 "C"
1287 };
1288
1289 const char *strings[] =
1290 {
1291 "C",
1292 "\"",
1293 "9",
1294 "'",
1295 "}",
1296 "-",
1297 "7",
1298 "+",
1299 "`",
1300 "1",
1301 "a",
1302 "5",
1303 "\\",
1304 "8",
1305 "B",
1306 "3",
1307 "_",
1308 "6",
1309 "{",
1310 "2",
1311 "c",
1312 "4",
1313 "!",
1314 "0",
1315 "A",
1316 ":",
1317 "b",
1318 "."
1319 };
1320
1321 static int compare_string1(const void *e1, const void *e2)
1322 {
1323     const char *s1 = *(const char **)e1;
1324     const char *s2 = *(const char **)e2;
1325
1326     return lstrcmpA(s1, s2);
1327 }
1328
1329 static int compare_string2(const void *e1, const void *e2)
1330 {
1331     const char *s1 = *(const char **)e1;
1332     const char *s2 = *(const char **)e2;
1333
1334     return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1335 }
1336
1337 static int compare_string3(const void *e1, const void *e2)
1338 {
1339     const char *s1 = *(const char **)e1;
1340     const char *s2 = *(const char **)e2;
1341     char key1[256], key2[256];
1342
1343     LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
1344     LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
1345     return strcmp(key1, key2);
1346 }
1347
1348 static void test_sorting(void)
1349 {
1350     char buf[256];
1351     char **str_buf = (char **)buf;
1352     int i;
1353
1354     assert(sizeof(buf) >= sizeof(strings));
1355
1356     /* 1. sort using lstrcmpA */
1357     memcpy(buf, strings, sizeof(strings));
1358     qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
1359     for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1360     {
1361         ok(!strcmp(strings_sorted[i], str_buf[i]),
1362            "qsort using lstrcmpA failed for element %d\n", i);
1363     }
1364     /* 2. sort using CompareStringA */
1365     memcpy(buf, strings, sizeof(strings));
1366     qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
1367     for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1368     {
1369         ok(!strcmp(strings_sorted[i], str_buf[i]),
1370            "qsort using CompareStringA failed for element %d\n", i);
1371     }
1372     /* 3. sort using sort keys */
1373     memcpy(buf, strings, sizeof(strings));
1374     qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
1375     for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1376     {
1377         ok(!strcmp(strings_sorted[i], str_buf[i]),
1378            "qsort using sort keys failed for element %d\n", i);
1379     }
1380 }
1381 #endif
1382
1383 static void test_FoldStringA(void)
1384 {
1385   int ret, i;
1386   char src[256], dst[256];
1387   static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0'  };
1388   static const char digits_dst[] = { '1','2','3','\0'  };
1389   static const char composite_src[] =
1390   {
1391     0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
1392     0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
1393     0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
1394     0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
1395     0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
1396     0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
1397     0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
1398     0xfb,0xfc,0xfd,0xff,'\0'
1399   };
1400   static const char composite_dst[] =
1401   {
1402     0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1403     0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1404     0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1405     0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1406     0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1407     0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1408     0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
1409     0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
1410     0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
1411     0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
1412     0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
1413     0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
1414     0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
1415     0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
1416     0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1417   };
1418   static const char ligatures_src[] =
1419   {
1420     0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1421   };
1422   static const char ligatures_dst[] =
1423   {
1424     'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1425   };
1426
1427   if (!pFoldStringA)
1428     return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1429
1430   /* these tests are locale specific */
1431   if (GetACP() != 1252)
1432   {
1433       trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1434       return;
1435   }
1436
1437   /* MAP_FOLDDIGITS */
1438   SetLastError(0);
1439   ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
1440   if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1441     return;
1442   EXPECT_LEN(4); EXPECT_VALID;
1443   ok(strcmp(dst, digits_dst) == 0,
1444      "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
1445   for (i = 1; i < 256; i++)
1446   {
1447     if (!strchr(digits_src, i))
1448     {
1449       src[0] = i;
1450       src[1] = '\0';
1451       SetLastError(0);
1452       ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
1453       EXPECT_LEN(2); EXPECT_VALID;
1454       ok(dst[0] == src[0],
1455          "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
1456     }
1457   }
1458
1459   /* MAP_EXPAND_LIGATURES */
1460   SetLastError(0);
1461   ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1462   EXPECT_LEN(sizeof(ligatures_dst)); EXPECT_VALID;
1463   ok(strcmp(dst, ligatures_dst) == 0,
1464      "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
1465   for (i = 1; i < 256; i++)
1466   {
1467     if (!strchr(ligatures_src, i))
1468     {
1469       src[0] = i;
1470       src[1] = '\0';
1471       SetLastError(0);
1472       ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1473       EXPECT_LEN(2); EXPECT_VALID;
1474       ok(dst[0] == src[0],
1475          "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
1476     }
1477   }
1478
1479   /* MAP_COMPOSITE */
1480   SetLastError(0);
1481   ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
1482   EXPECT_VALID;
1483   todo_wine
1484   {
1485     /* Wine gets close, but doesn't produce quite the same result as native */
1486     EXPECT_LEN(121);
1487     ok(strcmp(dst, composite_dst) == 0,
1488        "MAP_COMPOSITE: Expected '%s', got '%s'\n", composite_dst, dst);
1489   }
1490
1491   for (i = 1; i < 256; i++)
1492   {
1493     if (!strchr(composite_src, i))
1494     {
1495       src[0] = i;
1496       src[1] = '\0';
1497       SetLastError(0);
1498       ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
1499       EXPECT_LEN(2); EXPECT_VALID;
1500       ok(dst[0] == src[0],
1501          "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
1502          (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
1503     }
1504   }
1505
1506   /* MAP_FOLDCZONE */
1507   for (i = 1; i < 256; i++)
1508   {
1509     src[0] = i;
1510     src[1] = '\0';
1511     SetLastError(0);
1512     ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
1513     EXPECT_LEN(2); EXPECT_VALID;
1514     ok(src[0] == dst[0],
1515        "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
1516        (unsigned char)src[0], (unsigned char)dst[0]);
1517   }
1518
1519   /* MAP_PRECOMPOSED */
1520   for (i = 1; i < 256; i++)
1521   {
1522     src[0] = i;
1523     src[1] = '\0';
1524     SetLastError(0);
1525     ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
1526     EXPECT_LEN(2); EXPECT_VALID;
1527     ok(src[0] == dst[0],
1528        "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
1529        (unsigned char)src[0], (unsigned char)dst[0]);
1530   }
1531 }
1532
1533 static void test_FoldStringW(void)
1534 {
1535   int ret;
1536   size_t i, j;
1537   WCHAR src[256], dst[256], ch, prev_ch = 1;
1538   static const DWORD badFlags[] =
1539   {
1540     0,
1541     MAP_PRECOMPOSED|MAP_COMPOSITE,
1542     MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
1543     MAP_COMPOSITE|MAP_EXPAND_LIGATURES
1544   };
1545   /* Ranges of digits 0-9 : Must be sorted! */
1546   static const WCHAR digitRanges[] =
1547   {
1548     0x0030, /* '0'-'9' */
1549     0x0660, /* Eastern Arabic */
1550     0x06F0, /* Arabic - Hindu */
1551     0x0966, /* Devengari */
1552     0x09E6, /* Bengalii */
1553     0x0A66, /* Gurmukhi */
1554     0x0AE6, /* Gujarati */
1555     0x0B66, /* Oriya */
1556     0x0BE6, /* Tamil - No 0 */
1557     0x0C66, /* Telugu */
1558     0x0CE6, /* Kannada */
1559     0x0D66, /* Maylayalam */
1560     0x0E50, /* Thai */
1561     0x0ED0, /* Laos */
1562     0x2070, /* Superscript - 1, 2, 3 are out of sequence */
1563     0x2080, /* Subscript */
1564     0x245F, /* Circled - 0 is out of sequence */
1565     0x2473, /* Bracketed */
1566     0x2487, /* Full stop */
1567     0x2775, /* Inverted circled - No 0 */
1568     0x277F, /* Patterned circled - No 0 */
1569     0x2789, /* Inverted Patterned circled - No 0 */
1570     0xff10, /* Pliene chasse (?) */
1571     0xffff  /* Terminator */
1572   };
1573   /* Digits which are represented, but out of sequence */
1574   static const WCHAR outOfSequenceDigits[] =
1575   {
1576       0xB9,   /* Superscript 1 */
1577       0xB2,   /* Superscript 2 */
1578       0xB3,   /* Superscript 3 */
1579       0x24EA, /* Circled 0 */
1580       '\0'    /* Terminator */
1581   };
1582   /* Digits in digitRanges for which no representation is available */
1583   static const WCHAR noDigitAvailable[] =
1584   {
1585       0x0BE6, /* No Tamil 0 */
1586       0x2473, /* No Bracketed 0 */
1587       0x2487, /* No 0 Full stop */
1588       0x2775, /* No inverted circled 0 */
1589       0x277F, /* No patterned circled */
1590       0x2789, /* No inverted Patterned circled */
1591       '\0'    /* Terminator */
1592   };
1593   /* Compatibility conversion results */
1594   static const WCHAR compat_F900_FA2F[256+48] =
1595   {
1596       0x8c48, 0x66f4, 0x8eca, 0x8cc8, 0x6ed1, 0x4e32, 0x53e5, 0x9f9c,
1597       0x9f9c, 0x5951, 0x91d1, 0x5587, 0x5948, 0x61f6, 0x7669, 0x7f85,
1598       0x863f, 0x87ba, 0x88f8, 0x908f, 0x6a02, 0x6d1b, 0x70d9, 0x73de,
1599       0x843d, 0x916a, 0x99f1, 0x4e82, 0x5375, 0x6b04, 0x721b, 0x862d,
1600       0x9e1e, 0x5d50, 0x6feb, 0x85cd, 0x8964, 0x62c9, 0x81d8, 0x881f,
1601       0x5eca, 0x6717, 0x6d6a, 0x72fc, 0x0000, 0x4f86, 0x51b7, 0x52de,
1602       0x64c4, 0x6ad3, 0x7210, 0x76e7, 0x8001, 0x8606, 0x865c, 0x8def,
1603       0x9732, 0x9b6f, 0x9dfa, 0x788c, 0x797f, 0x7da0, 0x83c9, 0x9304,
1604       0x9e7f, 0x8ad6, 0x58df, 0x5f04, 0x7c60, 0x807e, 0x7262, 0x78ca,
1605       0x8cc2, 0x96f7, 0x58d8, 0x5c62, 0x6a13, 0x6dda, 0x6f0f, 0x7d2f,
1606       0x7e37, 0x964b, 0x52d2, 0x808b, 0x51dc, 0x51cc, 0x7a1c, 0x7dbe,
1607       0x83f1, 0x9675, 0x8b80, 0x62cf, 0x6a02, 0x8afe, 0x4e39, 0x5be7,
1608       0x6012, 0x7387, 0x7570, 0x5317, 0x78fb, 0x4fbf, 0x5fa9, 0x4e0d,
1609       0x6ccc, 0x6578, 0x7d22, 0x53c3, 0x585e, 0x7701, 0x8449, 0x8aaa,
1610       0x6bba, 0x8fb0, 0x6c88, 0x62fe, 0x82e5, 0x63a0, 0x7565, 0x4eae,
1611       0x5169, 0x0000, 0x6881, 0x7ce7, 0x826f, 0x8ad2, 0x91cf, 0x52f5,
1612       0x5442, 0x5973, 0x5eec, 0x65c5, 0x6ffe, 0x792a, 0x95ad, 0x9a6a,
1613       0x9e97, 0x9ece, 0x529b, 0x66c6, 0x6b77, 0x8f62, 0x5e74, 0x6190,
1614       0x6200, 0x649a, 0x6f23, 0x7149, 0x7489, 0x0000, 0x7df4, 0x806f,
1615       0x8f26, 0x84ee, 0x9023, 0x934a, 0x5217, 0x52a3, 0x54bd, 0x70c8,
1616       0x88c2, 0x8aaa, 0x5ec9, 0x5ff5, 0x637b, 0x6bae, 0x7c3e, 0x7375,
1617       0x4ee4, 0x56f9, 0x5be7, 0x5dba, 0x601c, 0x73b2, 0x7469, 0x7f9a,
1618       0x8046, 0x9234, 0x96f6, 0x9748, 0x9818, 0x4f8b, 0x79ae, 0x91b4,
1619       0x96b8, 0x60e1, 0x4e86, 0x50da, 0x5bee, 0x5c3f, 0x6599, 0x6a02,
1620       0x71ce, 0x7642, 0x84fc, 0x907c, 0x9f8d, 0x6688, 0x962e, 0x5289,
1621       0x677b, 0x67f3, 0x6d41, 0x6e9c, 0x7409, 0x7559, 0x786b, 0x7d10,
1622       0x985e, 0x516d, 0x622e, 0x9678, 0x502b, 0x5d19, 0x6dea, 0x8f2a,
1623       0x5f8b, 0x6144, 0x6817, 0x7387, 0x9686, 0x5229, 0x540f, 0x5c65,
1624       0x6613, 0x674e, 0x68a8, 0x6ce5, 0x7406, 0x75e2, 0x7f79, 0x0000,
1625       0x88e1, 0x91cc, 0x96e2, 0x533f, 0x6eba, 0x541d, 0x71d0, 0x7498,
1626       0x85fa, 0x0000, 0x9c57, 0x9e9f, 0x6797, 0x6dcb, 0x81e8, 0x7acb,
1627       0x7b20, 0x7c92, 0x72c0, 0x7099, 0x8b58, 0x4ec0, 0x8336, 0x523a,
1628       0x5207, 0x5ea6, 0x62d3, 0x7cd6, 0x5b85, 0x6d1e, 0x66b4, 0x8f3b,
1629       0x884c, 0x964d, 0x898b, 0x5ed3, 0x0000, 0x0000, 0x0000, 0x0000,
1630       0x585a, 0x0000, 0x6674, 0x0000, 0x0000, 0x51de, 0x8c6c, 0x76ca,
1631       0x0000, 0x795e, 0x7965, 0x798f, 0x9756, 0x7cbe, 0x7fbd, 0x0000,
1632       0x0000, 0x0000, 0x8af8, 0x0000, 0x0000, 0x9038, 0x90fd, 0x0000,
1633       0x0000, 0x0000, 0x98ef, 0x98fc, 0x9928, 0x9db4, 0x0000, 0x0000
1634   };
1635   static const WCHAR compat_FE30_FEF7[200] =
1636   {
1637       0x2025, 0x2014, 0x2013, 0x005f, 0x005f, 0x0028, 0x0029, 0x007b,
1638       0x007d, 0x3014, 0x3015, 0x3010, 0x3011, 0x300a, 0x300b, 0x3008,
1639       0x3009, 0x300c, 0x300d, 0x300e, 0x300f, 0x0000, 0x0000, 0x0000,
1640       0x0000, 0x203e, 0x203e, 0x203e, 0x203e, 0x005f, 0x005f, 0x005f,
1641       0x002c, 0x3001, 0x002e, 0x0000, 0x003b, 0x003a, 0x003f, 0x0021,
1642       0x2014, 0x0028, 0x0029, 0x007b, 0x007d, 0x3014, 0x3015, 0x0023,
1643       0x0026, 0x002a, 0x002b, 0x002d, 0x003c, 0x003e, 0x003d, 0x0000,
1644       0x0000, 0x0024, 0x0025, 0x0040, 0x0000, 0x0000, 0x0000, 0x0000,
1645       0x064b, 0x064b, 0x064c, 0x0000, 0x064d, 0x0000, 0x064e, 0x064e,
1646       0x064f, 0x064f, 0x0650, 0x0650, 0x0651, 0x0651, 0x0652, 0x0652,
1647       0x0621, 0x0622, 0x0622, 0x0623, 0x0623, 0x0624, 0x0624, 0x0625,
1648       0x0625, 0x0626, 0x0626, 0x0626, 0x0626, 0x0627, 0x0627, 0x0628,
1649       0x0628, 0x0628, 0x0628, 0x0629, 0x0629, 0x062a, 0x062a, 0x062a,
1650       0x062a, 0x062b, 0x062b, 0x062b, 0x062b, 0x062c, 0x062c, 0x062c,
1651       0x062c, 0x062d, 0x062d, 0x062d, 0x062d, 0x062e, 0x062e, 0x062e,
1652       0x062e, 0x062f, 0x062f, 0x0630, 0x0630, 0x0631, 0x0631, 0x0632,
1653       0x0632, 0x0633, 0x0633, 0x0633, 0x0633, 0x0634, 0x0634, 0x0634,
1654       0x0634, 0x0635, 0x0635, 0x0635, 0x0635, 0x0636, 0x0636, 0x0636,
1655       0x0636, 0x0637, 0x0637, 0x0637, 0x0637, 0x0638, 0x0638, 0x0638,
1656       0x0638, 0x0639, 0x0639, 0x0639, 0x0639, 0x063a, 0x063a, 0x063a,
1657       0x063a, 0x0641, 0x0641, 0x0641, 0x0641, 0x0642, 0x0642, 0x0642,
1658       0x0642, 0x0643, 0x0643, 0x0643, 0x0643, 0x0644, 0x0644, 0x0644,
1659       0x0644, 0x0645, 0x0645, 0x0645, 0x0645, 0x0646, 0x0646, 0x0646,
1660       0x0646, 0x0647, 0x0647, 0x0647, 0x0647, 0x0648, 0x0648, 0x0649,
1661       0x0649, 0x064a, 0x064a, 0x064a, 0x064a, 0x0000, 0x0000, 0x0000
1662   };
1663   static const WCHAR compat_FF00_FFEF[240] =
1664   {
1665       0x0000, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
1666       0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
1667       0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
1668       0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
1669       0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
1670       0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
1671       0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
1672       0x0058, 0x0059, 0x005a, 0x005b, 0x0000, 0x005d, 0x005e, 0x005f,
1673       0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
1674       0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
1675       0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
1676       0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000,
1677       0x0000, 0x3002, 0x300c, 0x300d, 0x3001, 0x30fb, 0x30f2, 0x30a1,
1678       0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, 0x30c3,
1679       0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, 0x30ab, 0x30ad,
1680       0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, 0x30b9, 0x30bb, 0x30bd,
1681       0x30bf, 0x30c1, 0x30c4, 0x30c6, 0x30c8, 0x30ca, 0x30cb, 0x30cc,
1682       0x30cd, 0x30ce, 0x30cf, 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de,
1683       0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9,
1684       0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c,
1685       0x3164, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137,
1686       0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f,
1687       0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147,
1688       0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x0000,
1689       0x0000, 0x0000, 0x314f, 0x3150, 0x3151, 0x3152, 0x3153, 0x3154,
1690       0x0000, 0x0000, 0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315a,
1691       0x0000, 0x0000, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, 0x3160,
1692       0x0000, 0x0000, 0x3161, 0x3162, 0x3163, 0x0000, 0x0000, 0x0000,
1693       0x00a2, 0x00a3, 0x00ac, 0x00af, 0x00a6, 0x00a5, 0x20a9, 0x0000,
1694       0x2502, 0x2190, 0x2191, 0x2192, 0x2193, 0x25a0, 0x25cb, 0x0000
1695   };
1696   static const WCHAR ligatures_src[] =
1697   {
1698     0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
1699     0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
1700     0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
1701     0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
1702     0xfb04, 0xfb05, 0xfb06, '\0'
1703   };
1704   static const WCHAR ligatures_dst[] =
1705   {
1706     'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
1707     'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
1708     'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
1709     0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
1710     'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
1711   };
1712
1713   if (!pFoldStringW)
1714     return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1715
1716   /* Invalid flag combinations */
1717   for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
1718   {
1719     src[0] = dst[0] = '\0';
1720     SetLastError(0);
1721     ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
1722     if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1723       return;
1724     EXPECT_LEN(0); EXPECT_FLAGS;
1725   }
1726
1727   /* src & dst cannot be the same */
1728   SetLastError(0);
1729   ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
1730   EXPECT_LEN(0); EXPECT_INVALID;
1731
1732   /* src can't be NULL */
1733   SetLastError(0);
1734   ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
1735   EXPECT_LEN(0); EXPECT_INVALID;
1736
1737   /* srclen can't be 0 */
1738   SetLastError(0);
1739   ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
1740   EXPECT_LEN(0); EXPECT_INVALID;
1741
1742   /* dstlen can't be < 0 */
1743   SetLastError(0);
1744   ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
1745   EXPECT_LEN(0); EXPECT_INVALID;
1746
1747   /* Ret includes terminating NUL which is appended if srclen = -1 */
1748   SetLastError(0);
1749   src[0] = 'A';
1750   src[1] = '\0';
1751   dst[0] = '\0';
1752   ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
1753   EXPECT_LEN(2); EXPECT_VALID;
1754   ok(dst[0] == 'A' && dst[1] == '\0',
1755      "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%ld\n",
1756      'A', '\0', ret, dst[0], dst[1], GetLastError());
1757
1758   /* If size is given, result is not NUL terminated */
1759   SetLastError(0);
1760   src[0] = 'A';
1761   src[1] = 'A';
1762   dst[0] = 'X';
1763   dst[1] = 'X';
1764   ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
1765   EXPECT_LEN(1); EXPECT_VALID;
1766   ok(dst[0] == 'A' && dst[1] == 'X',
1767      "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%ld\n",
1768      'A','X', ret, dst[0], dst[1], GetLastError());
1769
1770   /* MAP_FOLDDIGITS */
1771   for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
1772   {
1773     /* Check everything before this range */
1774     for (ch = prev_ch; ch < digitRanges[j]; ch++)
1775     {
1776       SetLastError(0);
1777       src[0] = ch;
1778       src[1] = dst[0] = '\0';
1779       ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
1780       EXPECT_LEN(2); EXPECT_VALID;
1781
1782       ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
1783          /* Wine (correctly) maps all Unicode 4.0+ digits */
1784          isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF,
1785          "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
1786     }
1787
1788     if (digitRanges[j] == 0xffff)
1789       break; /* Finished the whole code point space */
1790
1791     for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
1792     {
1793       WCHAR c;
1794
1795       /* Map out of sequence characters */
1796       if      (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
1797       else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
1798       else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
1799       else if (ch == 0x245F) c = 0x24EA; /* Circled 0     */
1800       else                   c = ch;
1801       SetLastError(0);
1802       src[0] = c;
1803       src[1] = dst[0] = '\0';
1804       ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
1805       EXPECT_LEN(2); EXPECT_VALID;
1806
1807       ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
1808          strchrW(noDigitAvailable, c),
1809          "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
1810          ch, '0' + digitRanges[j] - ch, dst[0]);
1811     }
1812     prev_ch = ch;
1813   }
1814
1815   /* MAP_FOLDCZONE */
1816   for (ch = 1; ch <0xffff; ch++)
1817   {
1818     WCHAR expected = 0;
1819
1820     if (ch >= 0xF900 && ch <= 0xFA2F)
1821       expected = compat_F900_FA2F[ch - 0xF900];
1822     else if (ch >= 0xFE30 && ch <= 0xFEF7)
1823       expected = compat_FE30_FEF7[ch - 0xFE30];
1824     else if (ch >= 0xFF00 && ch <= 0xFFEF)
1825       expected = compat_FF00_FFEF[ch - 0xFF00];
1826
1827     if (!expected)
1828       expected = ch;
1829
1830     SetLastError(0);
1831     src[0] = ch;
1832     src[1] = dst[0] = '\0';
1833     ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
1834     EXPECT_LEN(2); EXPECT_VALID;
1835     ok(dst[0] == expected ||
1836        /* Wine (correctly) uses updated mappings for some Unicode 4.0 chars */
1837        (ch >= 0xFA0D && ch <= 0xFA47) ||
1838        0xf92c || ch == 0xf979 || ch == 0xf995 || ch == 0xf9e7 || ch == 0xf9f1,
1839        "MAP_FOLDCZONE: ch %d 0x%04x Expected 0x%04x got 0x%04x\n",
1840        ch, ch, expected, dst[0]);
1841   }
1842
1843   /* MAP_EXPAND_LIGATURES */
1844   SetLastError(0);
1845   ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1846   EXPECT_LEN(sizeof(ligatures_dst)/sizeof(ligatures_dst[0])); EXPECT_VALID;
1847   ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
1848      "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
1849   for (i = 1; i <= 0xffff; i++)
1850   {
1851     if (!strchrW(ligatures_src, i))
1852     {
1853       src[0] = i;
1854       src[1] = '\0';
1855       SetLastError(0);
1856       ret = pFoldStringW(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1857       EXPECT_LEN(2); EXPECT_VALID;
1858       ok(dst[0] == src[0],
1859          "MAP_EXPAND_LIGATURES: 0x%02x : Expected 0x%02x, got 0x%02x\n",
1860          i, src[0], dst[0]);
1861     }
1862   }
1863
1864   /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
1865 }
1866
1867
1868
1869 #define LCID_OK(l) \
1870   ok(lcid == l, "Expected lcid = %08lx, got %08lx\n", l, lcid)
1871 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
1872 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
1873 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
1874 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
1875
1876 static void test_ConvertDefaultLocale(void)
1877 {
1878   LCID lcid;
1879
1880   /* Doesn't change lcid, even if non default sublang/sort used */
1881   TEST_LCID(LANG_ENGLISH,  SUBLANG_ENGLISH_US, SORT_DEFAULT);
1882   TEST_LCID(LANG_ENGLISH,  SUBLANG_ENGLISH_UK, SORT_DEFAULT);
1883   TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT,    SORT_DEFAULT);
1884   TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT,    SORT_JAPANESE_UNICODE);
1885
1886   /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
1887   LCID_RES(MKLCID(LANG_ENGLISH,  SUBLANG_NEUTRAL, SORT_DEFAULT),
1888            MKLCID(LANG_ENGLISH,  SUBLANG_DEFAULT, SORT_DEFAULT));
1889   LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
1890            MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
1891   LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_JAPANESE_UNICODE),
1892            MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE));
1893
1894   /* Invariant language is not treated specially */
1895   TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
1896   LCID_RES(MKLCID(LANG_INVARIANT, SUBLANG_NEUTRAL, SORT_DEFAULT),
1897            MKLCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT));
1898
1899   /* User/system default languages alone are not mapped */
1900   TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
1901   TEST_LCIDLANG(LANG_USER_DEFAULT,   SORT_JAPANESE_UNICODE);
1902
1903   /* Default lcids */
1904   LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
1905   LCID_RES(LOCALE_USER_DEFAULT,   GetUserDefaultLCID());
1906   LCID_RES(LOCALE_NEUTRAL,        GetUserDefaultLCID());
1907 }
1908
1909 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
1910                                     DWORD dwFlags, LONG_PTR lParam)
1911 {
1912   trace("%08lx, %s, %s, %08lx, %08lx\n",
1913         lgrpid, lpszNum, lpszName, dwFlags, lParam);
1914
1915   ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
1916      "Enumerated grp %ld not valid (flags %ld)\n", lgrpid, dwFlags);
1917
1918   /* If lParam is one, we are calling with flags defaulted from 0 */
1919   ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
1920          "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %ld\n", dwFlags);
1921
1922   return TRUE;
1923 }
1924
1925 static void test_EnumSystemLanguageGroupsA(void)
1926 {
1927   if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
1928     return;
1929
1930   /* No enumeration proc */
1931   SetLastError(0);
1932   pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
1933   EXPECT_INVALID;
1934
1935   /* Invalid flags */
1936   SetLastError(0);
1937   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
1938   EXPECT_FLAGS;
1939
1940   /* No flags - defaults to LGRPID_INSTALLED */
1941   SetLastError(0);
1942   pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
1943   EXPECT_VALID;
1944
1945   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
1946   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
1947 }
1948
1949
1950 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
1951                                       LONG_PTR lParam)
1952 {
1953   trace("%08lx, %08lx, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
1954
1955   ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
1956      "Enumerated grp %ld not valid\n", lgrpid);
1957   ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
1958      "Enumerated grp locale %ld not valid\n", lcid);
1959   return TRUE;
1960 }
1961
1962 static void test_EnumLanguageGroupLocalesA(void)
1963 {
1964   if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
1965     return;
1966
1967   /* No enumeration proc */
1968   SetLastError(0);
1969   pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
1970   EXPECT_INVALID;
1971
1972   /* lgrpid too small */
1973   SetLastError(0);
1974   pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
1975   EXPECT_INVALID;
1976
1977   /* lgrpid too big */
1978   SetLastError(0);
1979   pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
1980   EXPECT_INVALID;
1981
1982   /* dwFlags is reserved */
1983   SetLastError(0);
1984   pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
1985   EXPECT_INVALID;
1986
1987   pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
1988 }
1989
1990 static void test_SetLocaleInfoA(void)
1991 {
1992   BOOL bRet;
1993   LCID lcid = GetUserDefaultLCID();
1994
1995   /* Null data */
1996   SetLastError(0);
1997   bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
1998   EXPECT_INVALID;
1999
2000   /* IDATE */
2001   SetLastError(0);
2002   bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
2003   EXPECT_FLAGS;
2004
2005   /* ILDATE */
2006   SetLastError(0);
2007   bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
2008   EXPECT_FLAGS;
2009 }
2010
2011 START_TEST(locale)
2012 {
2013   InitFunctionPointers();
2014
2015 #if 0
2016   test_EnumTimeFormats();
2017 #endif
2018   test_GetLocaleInfoA();
2019   test_GetTimeFormatA();
2020   test_GetDateFormatA();
2021   test_GetDateFormatW();
2022   test_GetCurrencyFormatA(); /* Also tests the W version */
2023   test_GetNumberFormatA();   /* Also tests the W version */
2024   test_CompareStringA();
2025   test_LCMapStringA();
2026   test_LCMapStringW();
2027   test_FoldStringA();
2028   test_FoldStringW();
2029   test_ConvertDefaultLocale();
2030   test_EnumSystemLanguageGroupsA();
2031   test_EnumLanguageGroupLocalesA();
2032   test_SetLocaleInfoA();
2033 #if 0 /* this requires collation table patch to make it MS compatible */
2034   test_sorting();
2035 #endif
2036 }