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