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