oledlg: Update Portuguese (Brazilian) translation.
[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 #include <stdio.h>
32
33 #include "wine/test.h"
34 #include "windef.h"
35 #include "winbase.h"
36 #include "winerror.h"
37 #include "winnls.h"
38
39 static inline unsigned int strlenW( const WCHAR *str )
40 {
41     const WCHAR *s = str;
42     while (*s) s++;
43     return s - str;
44 }
45
46 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
47 {
48     if (n <= 0) return 0;
49     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
50     return *str1 - *str2;
51 }
52
53 static inline WCHAR *strchrW( const WCHAR *str, WCHAR ch )
54 {
55     do { if (*str == ch) return (WCHAR *)str; } while (*str++);
56     return NULL;
57 }
58
59 static inline int isdigitW( WCHAR wc )
60 {
61     WORD type;
62     GetStringTypeW( CT_CTYPE1, &wc, 1, &type );
63     return type & C1_DIGIT;
64 }
65
66 /* Some functions are only in later versions of kernel32.dll */
67 static HMODULE hKernel32;
68 static WORD enumCount;
69
70 typedef BOOL (WINAPI *EnumSystemLanguageGroupsAFn)(LANGUAGEGROUP_ENUMPROC,
71                                                    DWORD, LONG_PTR);
72 static EnumSystemLanguageGroupsAFn pEnumSystemLanguageGroupsA;
73 typedef BOOL (WINAPI *EnumLanguageGroupLocalesAFn)(LANGGROUPLOCALE_ENUMPROC,
74                                                    LGRPID, DWORD, LONG_PTR);
75 static EnumLanguageGroupLocalesAFn pEnumLanguageGroupLocalesA;
76 typedef BOOL (WINAPI *EnumUILanguagesAFn)(UILANGUAGE_ENUMPROC,
77                                                    DWORD, LONG_PTR);
78 static EnumUILanguagesAFn pEnumUILanguagesA;
79
80 typedef INT (WINAPI *FoldStringAFn)(DWORD, LPCSTR, INT, LPSTR, INT);
81 static FoldStringAFn pFoldStringA;
82 typedef INT (WINAPI *FoldStringWFn)(DWORD, LPCWSTR, INT, LPWSTR, INT);
83 static FoldStringWFn pFoldStringW;
84
85 typedef BOOL (WINAPI *IsValidLanguageGroupFn)(LGRPID, DWORD);
86 static IsValidLanguageGroupFn pIsValidLanguageGroup;
87
88 static void InitFunctionPointers(void)
89 {
90   hKernel32 = GetModuleHandleA("kernel32");
91   pEnumSystemLanguageGroupsA = (void*)GetProcAddress(hKernel32, "EnumSystemLanguageGroupsA");
92   pEnumLanguageGroupLocalesA = (void*)GetProcAddress(hKernel32, "EnumLanguageGroupLocalesA");
93   pFoldStringA = (void*)GetProcAddress(hKernel32, "FoldStringA");
94   pFoldStringW = (void*)GetProcAddress(hKernel32, "FoldStringW");
95   pIsValidLanguageGroup = (void*)GetProcAddress(hKernel32, "IsValidLanguageGroup");
96   pEnumUILanguagesA = (void*)GetProcAddress(hKernel32, "EnumUILanguagesA");
97 }
98
99 #define eq(received, expected, label, type) \
100         ok((received) == (expected), "%s: got " type " instead of " type "\n", \
101            (label), (received), (expected))
102
103 #define BUFFER_SIZE    128
104 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
105
106 #define STRINGSA(x,y) strcpy(input, x); strcpy(Expected, y); SetLastError(0xdeadbeef); buffer[0] = '\0'
107 #define EXPECT_LENA ok(ret == lstrlen(Expected)+1, "Expected Len %d, got %d\n", lstrlen(Expected)+1, ret)
108 #define EXPECT_EQA ok(strncmp(buffer, Expected, strlen(Expected)) == 0, \
109   "Expected '%s', got '%s'\n", Expected, buffer)
110
111 #define STRINGSW(x,y) MultiByteToWideChar(CP_ACP,0,x,-1,input,COUNTOF(input)); \
112    MultiByteToWideChar(CP_ACP,0,y,-1,Expected,COUNTOF(Expected)); \
113    SetLastError(0xdeadbeef); buffer[0] = '\0'
114 #define EXPECT_LENW ok(ret == lstrlenW(Expected)+1, "Expected Len %d, got %d\n", lstrlenW(Expected)+1, ret)
115 #define EXPECT_EQW  ok(strncmpW(buffer, Expected, strlenW(Expected)) == 0, "Bad conversion\n")
116
117 #define NUO LOCALE_NOUSEROVERRIDE
118
119 static void test_GetLocaleInfoA(void)
120 {
121   int ret;
122   int len;
123   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
124   char buffer[BUFFER_SIZE];
125   char expected[BUFFER_SIZE];
126
127   ok(lcid == 0x409, "wrong LCID calculated - %d\n", lcid);
128
129   /* en and ar use SUBLANG_NEUTRAL, but GetLocaleInfo assume SUBLANG_DEFAULT
130      Same is true for zh on pre-Vista, but on Vista and higher GetLocaleInfo
131      assumes SUBLANG_NEUTRAL for zh */
132   memset(expected, 0, COUNTOF(expected));
133   len = GetLocaleInfoA(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
134   SetLastError(0xdeadbeef);
135   memset(buffer, 0, COUNTOF(buffer));
136   ret = GetLocaleInfoA(LANG_ENGLISH, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
137   ok((ret == len) && !lstrcmpA(buffer, expected),
138       "got %d with '%s' (expected %d with '%s')\n",
139       ret, buffer, len, expected);
140
141   memset(expected, 0, COUNTOF(expected));
142   len = GetLocaleInfoA(MAKELANGID(LANG_ARABIC, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
143   if (len) {
144       SetLastError(0xdeadbeef);
145       memset(buffer, 0, COUNTOF(buffer));
146       ret = GetLocaleInfoA(LANG_ARABIC, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
147       ok((ret == len) && !lstrcmpA(buffer, expected),
148           "got %d with '%s' (expected %d with '%s')\n",
149           ret, buffer, len, expected);
150   }
151   else
152       win_skip("LANG_ARABIC not installed\n");
153
154   /* SUBLANG_DEFAULT is required for mlang.dll, but optional for GetLocaleInfo */
155   memset(expected, 0, COUNTOF(expected));
156   len = GetLocaleInfoA(MAKELANGID(LANG_GERMAN, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
157   SetLastError(0xdeadbeef);
158   memset(buffer, 0, COUNTOF(buffer));
159   ret = GetLocaleInfoA(LANG_GERMAN, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
160   ok((ret == len) && !lstrcmpA(buffer, expected),
161       "got %d with '%s' (expected %d with '%s')\n",
162       ret, buffer, len, expected);
163
164
165   /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
166    * partially fill the buffer even if it is too short. See bug 637.
167    */
168   SetLastError(0xdeadbeef);
169   memset(buffer, 0, COUNTOF(buffer));
170   ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 0);
171   ok(ret == 7 && !buffer[0], "Expected len=7, got %d\n", ret);
172
173   SetLastError(0xdeadbeef);
174   memset(buffer, 0, COUNTOF(buffer));
175   ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 3);
176   ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
177       "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
178   ok(!strcmp(buffer, "Mon"), "Expected 'Mon', got '%s'\n", buffer);
179
180   SetLastError(0xdeadbeef);
181   memset(buffer, 0, COUNTOF(buffer));
182   ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 10);
183   ok(ret == 7, "Expected ret == 7, got %d, error %d\n", ret, GetLastError());
184   ok(!strcmp(buffer, "Monday"), "Expected 'Monday', got '%s'\n", buffer);
185 }
186
187 static void test_GetLocaleInfoW(void)
188 {
189   LCID lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
190   LCID lcid_ru = MAKELCID(MAKELANGID(LANG_RUSSIAN, SUBLANG_NEUTRAL), SORT_DEFAULT);
191   WCHAR bufferW[80], buffer2W[80];
192   CHAR bufferA[80];
193   DWORD ret;
194   INT i;
195
196   ret = GetLocaleInfoW(lcid_en, LOCALE_SMONTHNAME1, bufferW, COUNTOF(bufferW));
197   if (!ret) {
198       win_skip("GetLocaleInfoW() isn't implemented\n");
199       return;
200   }
201   ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1, bufferW, COUNTOF(bufferW));
202   if (!ret) {
203       win_skip("LANG_RUSSIAN locale data unavailable\n");
204       return;
205   }
206   ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1|LOCALE_RETURN_GENITIVE_NAMES,
207                        bufferW, COUNTOF(bufferW));
208   if (!ret) {
209       win_skip("LOCALE_RETURN_GENITIVE_NAMES isn't supported\n");
210       return;
211   }
212
213   /* LOCALE_RETURN_GENITIVE_NAMES isn't supported for GetLocaleInfoA */
214   bufferA[0] = 'a';
215   SetLastError(0xdeadbeef);
216   ret = GetLocaleInfoA(lcid_ru, LOCALE_SMONTHNAME1|LOCALE_RETURN_GENITIVE_NAMES,
217                        bufferA, COUNTOF(bufferA));
218   ok(ret == 0, "LOCALE_RETURN_GENITIVE_NAMES should fail with GetLocaleInfoA\n");
219   ok(bufferA[0] == 'a', "Expected buffer to be untouched\n");
220   ok(GetLastError() == ERROR_INVALID_FLAGS,
221      "Expected ERROR_INVALID_FLAGS, got %x\n", GetLastError());
222
223   bufferW[0] = 'a';
224   SetLastError(0xdeadbeef);
225   ret = GetLocaleInfoW(lcid_ru, LOCALE_RETURN_GENITIVE_NAMES,
226                        bufferW, COUNTOF(bufferW));
227   ok(ret == 0,
228      "LOCALE_RETURN_GENITIVE_NAMES itself doesn't return anything, got %d\n", ret);
229   ok(bufferW[0] == 'a', "Expected buffer to be untouched\n");
230   ok(GetLastError() == ERROR_INVALID_FLAGS,
231      "Expected ERROR_INVALID_FLAGS, got %x\n", GetLastError());
232
233   /* yes, test empty 13 month entry too */
234   for (i = 0; i < 12; i++) {
235       bufferW[0] = 0;
236       ret = GetLocaleInfoW(lcid_ru, (LOCALE_SMONTHNAME1+i)|LOCALE_RETURN_GENITIVE_NAMES,
237                            bufferW, COUNTOF(bufferW));
238       ok(ret, "Expected non zero result\n");
239       ok(ret == lstrlenW(bufferW)+1, "Expected actual length, got %d, length %d\n",
240                                     ret, lstrlenW(bufferW));
241       buffer2W[0] = 0;
242       ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1+i,
243                            buffer2W, COUNTOF(buffer2W));
244       ok(ret, "Expected non zero result\n");
245       ok(ret == lstrlenW(buffer2W)+1, "Expected actual length, got %d, length %d\n",
246                                     ret, lstrlenW(buffer2W));
247
248       ok(lstrcmpW(bufferW, buffer2W) != 0,
249            "Expected genitive name to differ, got the same for month %d\n", i+1);
250
251       /* for locale without genitive names nominative returned in both cases */
252       bufferW[0] = 0;
253       ret = GetLocaleInfoW(lcid_en, (LOCALE_SMONTHNAME1+i)|LOCALE_RETURN_GENITIVE_NAMES,
254                            bufferW, COUNTOF(bufferW));
255       ok(ret, "Expected non zero result\n");
256       ok(ret == lstrlenW(bufferW)+1, "Expected actual length, got %d, length %d\n",
257                                     ret, lstrlenW(bufferW));
258       buffer2W[0] = 0;
259       ret = GetLocaleInfoW(lcid_en, LOCALE_SMONTHNAME1+i,
260                            buffer2W, COUNTOF(buffer2W));
261       ok(ret, "Expected non zero result\n");
262       ok(ret == lstrlenW(buffer2W)+1, "Expected actual length, got %d, length %d\n",
263                                     ret, lstrlenW(buffer2W));
264
265       ok(lstrcmpW(bufferW, buffer2W) == 0,
266          "Expected same names, got different for month %d\n", i+1);
267   }
268 }
269
270 static void test_GetTimeFormatA(void)
271 {
272   int ret;
273   SYSTEMTIME  curtime;
274   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
275   char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
276
277   memset(&curtime, 2, sizeof(SYSTEMTIME));
278   STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
279   SetLastError(0xdeadbeef);
280   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
281   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
282       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
283
284   curtime.wHour = 8;
285   curtime.wMinute = 56;
286   curtime.wSecond = 13;
287   curtime.wMilliseconds = 22;
288   STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
289   SetLastError(0xdeadbeef);
290   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
291   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
292   EXPECT_LENA; EXPECT_EQA;
293
294   /* MSDN: LOCALE_NOUSEROVERRIDE can't be specified with a format string */
295   SetLastError(0xdeadbeef);
296   ret = GetTimeFormatA(lcid, NUO|TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
297   ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
298      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
299
300   STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficient buffer */
301   SetLastError(0xdeadbeef);
302   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, 2);
303   ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
304       "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
305
306   STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
307   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, NULL, 0);
308   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
309   EXPECT_LENA;
310
311   STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
312   ret = GetTimeFormatA(lcid, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
313   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
314   EXPECT_LENA; EXPECT_EQA;
315
316   STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
317   ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
318   ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
319   ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "4" )), /* win9x */
320       "Expected '', got '%s'\n", buffer );
321
322   STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
323   ret = GetTimeFormatA(lcid, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
324   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
325   EXPECT_LENA; EXPECT_EQA;
326
327   STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
328   strcpy(Expected, "8:56 AM");
329   ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
330   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
331   EXPECT_LENA; EXPECT_EQA;
332
333   STRINGSA("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
334   ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
335   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
336   ok( !strcmp( buffer, "8.@:56AM" ) || broken( !strcmp( buffer, "8.@:56.@:AM" )) /* win9x */,
337       "Expected '8.@:56AM', got '%s'\n", buffer );
338
339   STRINGSA("s1s2s3", ""); /* Duplicate tokens */
340   ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
341   ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
342   ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "3" )), /* win9x */
343       "Expected '', got '%s'\n", buffer );
344
345   STRINGSA("t/tt", "A/AM"); /* AM time marker */
346   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
347   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
348   EXPECT_LENA; EXPECT_EQA;
349
350   curtime.wHour = 13;
351   STRINGSA("t/tt", "P/PM"); /* PM time marker */
352   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
353   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
354   EXPECT_LENA; EXPECT_EQA;
355
356   STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
357   ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
358   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
359   EXPECT_LENA; EXPECT_EQA;
360
361   STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
362   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
363   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
364   EXPECT_LENA; EXPECT_EQA;
365
366   STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
367   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
368   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
369   EXPECT_LENA; EXPECT_EQA;
370
371   curtime.wHour = 14; /* change this to 14 or 2pm */
372   curtime.wMinute = 5;
373   curtime.wSecond = 3;
374   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 */
375   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
376   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
377   EXPECT_LENA; EXPECT_EQA;
378
379   curtime.wHour = 0;
380   STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
381   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
382   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
383   EXPECT_LENA; EXPECT_EQA;
384
385   STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
386   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
387   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
388   EXPECT_LENA; EXPECT_EQA;
389
390   /* try to convert formatting strings with more than two letters
391    * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
392    * NOTE: We expect any letter for which there is an upper case value
393    *       we should see a replacement.  For letters that DO NOT have
394    *       upper case values we should see NO REPLACEMENT.
395    */
396   curtime.wHour = 8;
397   curtime.wMinute = 56;
398   curtime.wSecond = 13;
399   curtime.wMilliseconds = 22;
400   STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
401            "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
402   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
403   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
404   EXPECT_LENA; EXPECT_EQA;
405
406   STRINGSA("h", "text"); /* Don't write to buffer if len is 0 */
407   strcpy(buffer, "text");
408   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, 0);
409   ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
410   EXPECT_EQA;
411
412   STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
413            "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
414   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
415   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
416   EXPECT_LENA; EXPECT_EQA;
417
418   STRINGSA("'''", "'"); /* invalid quoted string */
419   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
420   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
421   EXPECT_LENA; EXPECT_EQA;
422
423   /* test that msdn suggested single quotation usage works as expected */
424   STRINGSA("''''", "'"); /* single quote mark */
425   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
426   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
427   EXPECT_LENA; EXPECT_EQA;
428
429   STRINGSA("''HHHHHH", "08"); /* Normal use */
430   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
431   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
432   EXPECT_LENA; EXPECT_EQA;
433
434   /* and test for normal use of the single quotation mark */
435   STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
436   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
437   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
438   EXPECT_LENA; EXPECT_EQA;
439
440   STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
441   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
442   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
443   EXPECT_LENA; EXPECT_EQA;
444
445   STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
446   ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
447   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
448   EXPECT_LENA; EXPECT_EQA;
449
450   curtime.wHour = 25;
451   STRINGSA("'123'tt", ""); /* Invalid time */
452   SetLastError(0xdeadbeef);
453   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
454   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
455       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
456
457   curtime.wHour = 12;
458   curtime.wMonth = 60; /* Invalid */
459   STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
460   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
461   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
462   EXPECT_LENA; EXPECT_EQA;
463 }
464
465 static void test_GetDateFormatA(void)
466 {
467   int ret;
468   SYSTEMTIME  curtime;
469   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
470   LCID lcid_ru = MAKELCID(MAKELANGID(LANG_RUSSIAN, SUBLANG_NEUTRAL), SORT_DEFAULT);
471   char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
472   char Broken[BUFFER_SIZE];
473   char short_day[10], month[10], genitive_month[10];
474
475   memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
476   STRINGSA("ddd',' MMM dd yy","");
477   SetLastError(0xdeadbeef);
478   ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
479   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
480       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
481
482   curtime.wYear = 2002;
483   curtime.wMonth = 5;
484   curtime.wDay = 4;
485   curtime.wDayOfWeek = 3;
486   STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
487   ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
488   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
489   EXPECT_LENA; EXPECT_EQA;
490
491   /* Same as above but with LOCALE_NOUSEROVERRIDE */
492   STRINGSA("ddd',' MMM dd yy",""); /* Simple case */
493   SetLastError(0xdeadbeef);
494   ret = GetDateFormatA(lcid, NUO, &curtime, input, buffer, COUNTOF(buffer));
495   ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
496      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
497   EXPECT_EQA;
498
499   STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
500   ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
501   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
502   EXPECT_LENA; EXPECT_EQA;
503
504   curtime.wHour = 36; /* Invalid */
505   STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
506   ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
507   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
508   EXPECT_LENA; EXPECT_EQA;
509
510   STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
511   ret = GetDateFormatA(lcid, 0, &curtime, input, NULL, 0);
512   ok(ret == 16, "Expected ret == 16, got %d, error %d\n", ret, GetLastError());
513   EXPECT_EQA;
514
515   STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
516   SetLastError(0xdeadbeef);
517   ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, 2);
518   ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
519       "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
520
521   STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
522   ret = GetDateFormat(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
523   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
524   if (strncmp(buffer, Expected, strlen(Expected)) && strncmp(buffer, "5/4/02", strlen(Expected)) != 0)
525           ok (0, "Expected '%s' or '5/4/02', got '%s'\n", Expected, buffer);
526
527   STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
528   ret = GetDateFormat(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
529   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
530   EXPECT_LENA; EXPECT_EQA;
531
532   /* test for expected DATE_YEARMONTH behavior with null format */
533   /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
534   STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
535   SetLastError(0xdeadbeef);
536   ret = GetDateFormat(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
537   ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
538      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
539   EXPECT_EQA;
540
541   /* Test that using invalid DATE_* flags results in the correct error */
542   /* and return values */
543   STRINGSA("m/d/y", ""); /* Invalid flags */
544   SetLastError(0xdeadbeef);
545   ret = GetDateFormat(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
546                       &curtime, input, buffer, COUNTOF(buffer));
547   ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
548      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
549
550   ret = GetDateFormat(lcid_ru, 0, &curtime, "ddMMMM", buffer, COUNTOF(buffer));
551   if (!ret)
552   {
553     win_skip("LANG_RUSSIAN locale data unavailable\n");
554     return;
555   }
556
557   /* month part should be in genitive form */
558   strcpy(genitive_month, buffer + 2);
559   ret = GetDateFormat(lcid_ru, 0, &curtime, "MMMM", buffer, COUNTOF(buffer));
560   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
561   strcpy(month, buffer);
562   ok(strcmp(genitive_month, month) != 0, "Expected different month forms\n");
563
564   ret = GetDateFormat(lcid_ru, 0, &curtime, "ddd", buffer, COUNTOF(buffer));
565   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
566   strcpy(short_day, buffer);
567
568   STRINGSA("dd MMMMddd dd", "");
569   sprintf(Expected, "04 %s%s 04", genitive_month, short_day);
570   ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
571   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
572   EXPECT_EQA;
573
574   STRINGSA("MMMMddd dd", "");
575   sprintf(Expected, "%s%s 04", month, short_day);
576   ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
577   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
578   EXPECT_EQA;
579
580   STRINGSA("MMMMddd", "");
581   sprintf(Expected, "%s%s", month, short_day);
582   ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
583   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
584   EXPECT_EQA;
585
586   STRINGSA("MMMMdd", "");
587   sprintf(Expected, "%s04", genitive_month);
588   sprintf(Broken, "%s04", month);
589   ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
590   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
591   ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
592      broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
593      "Expected '%s', got '%s'\n", Expected, buffer);
594
595   STRINGSA("MMMMdd ddd", "");
596   sprintf(Expected, "%s04 %s", genitive_month, short_day);
597   sprintf(Broken, "%s04 %s", month, short_day);
598   ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
599   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
600   ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
601      broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
602      "Expected '%s', got '%s'\n", Expected, buffer);
603
604   STRINGSA("dd dddMMMM", "");
605   sprintf(Expected, "04 %s%s", short_day, month);
606   ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
607   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
608   EXPECT_EQA;
609
610   STRINGSA("dd dddMMMM ddd MMMMdd", "");
611   sprintf(Expected, "04 %s%s %s %s04", short_day, month, short_day, genitive_month);
612   sprintf(Broken, "04 %s%s %s %s04", short_day, month, short_day, month);
613   ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
614   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
615   ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
616      broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
617      "Expected '%s', got '%s'\n", Expected, buffer);
618
619   /* with literal part */
620   STRINGSA("ddd',' MMMM dd", "");
621   sprintf(Expected, "%s, %s 04", short_day, genitive_month);
622   sprintf(Broken, "%s, %s 04", short_day, month);
623   ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
624   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
625   ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
626      broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
627      "Expected '%s', got '%s'\n", Expected, buffer);
628 }
629
630 static void test_GetDateFormatW(void)
631 {
632   int ret;
633   SYSTEMTIME  curtime;
634   WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
635   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
636
637   STRINGSW("",""); /* If flags is not zero then format must be NULL */
638   ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL,
639                        input, buffer, COUNTOF(buffer));
640   if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
641   {
642     win_skip("GetDateFormatW is not implemented\n");
643     return;
644   }
645   ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
646      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
647   EXPECT_EQW;
648
649   STRINGSW("",""); /* NULL buffer, len > 0 */
650   SetLastError(0xdeadbeef);
651   ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
652   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
653       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
654
655   STRINGSW("",""); /* NULL buffer, len == 0 */
656   ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
657   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
658   EXPECT_LENW; EXPECT_EQW;
659
660   curtime.wYear = 2002;
661   curtime.wMonth = 10;
662   curtime.wDay = 23;
663   curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
664   curtime.wHour = 65432; /* Invalid */
665   curtime.wMinute = 34512; /* Invalid */
666   curtime.wSecond = 65535; /* Invalid */
667   curtime.wMilliseconds = 12345;
668   STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
669   ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
670   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
671   EXPECT_LENW; EXPECT_EQW;
672
673   /* Limit tests */
674
675   curtime.wYear = 1601;
676   curtime.wMonth = 1;
677   curtime.wDay = 1;
678   curtime.wDayOfWeek = 0; /* Irrelevant */
679   curtime.wHour = 0;
680   curtime.wMinute = 0;
681   curtime.wSecond = 0;
682   curtime.wMilliseconds = 0;
683   STRINGSW("dddd d MMMM yyyy","Monday 1 January 1601");
684   SetLastError(0xdeadbeef);
685   ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
686   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
687   EXPECT_LENW; EXPECT_EQW;
688
689   curtime.wYear = 1600;
690   curtime.wMonth = 12;
691   curtime.wDay = 31;
692   curtime.wDayOfWeek = 0; /* Irrelevant */
693   curtime.wHour = 23;
694   curtime.wMinute = 59;
695   curtime.wSecond = 59;
696   curtime.wMilliseconds = 999;
697   STRINGSW("dddd d MMMM yyyy","Friday 31 December 1600");
698   SetLastError(0xdeadbeef);
699   ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
700   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
701       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
702 }
703
704
705 #define CY_POS_LEFT  0
706 #define CY_POS_RIGHT 1
707 #define CY_POS_LEFT_SPACE  2
708 #define CY_POS_RIGHT_SPACE 3
709
710 static void test_GetCurrencyFormatA(void)
711 {
712   static char szDot[] = { '.', '\0' };
713   static char szComma[] = { ',', '\0' };
714   static char szDollar[] = { '$', '\0' };
715   int ret;
716   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
717   char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
718   CURRENCYFMTA format;
719
720   memset(&format, 0, sizeof(format));
721
722   STRINGSA("23",""); /* NULL output, length > 0 --> Error */
723   SetLastError(0xdeadbeef);
724   ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
725   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
726       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
727
728   STRINGSA("23,53",""); /* Invalid character --> Error */
729   SetLastError(0xdeadbeef);
730   ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
731   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
732       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
733
734   STRINGSA("--",""); /* Double '-' --> Error */
735   SetLastError(0xdeadbeef);
736   ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
737   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
738       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
739
740   STRINGSA("0-",""); /* Trailing '-' --> Error */
741   SetLastError(0xdeadbeef);
742   ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
743   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
744       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
745
746   STRINGSA("0..",""); /* Double '.' --> Error */
747   SetLastError(0xdeadbeef);
748   ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
749   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
750       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
751
752   STRINGSA(" 0.1",""); /* Leading space --> Error */
753   SetLastError(0xdeadbeef);
754   ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
755   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
756       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
757
758   STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
759   SetLastError(0xdeadbeef);
760   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, 2);
761   ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
762       "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
763
764   STRINGSA("2353",""); /* Format and flags given --> Error */
765   SetLastError(0xdeadbeef);
766   ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
767   ok( !ret, "Expected ret == 0, got %d\n", ret);
768   ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
769       "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
770
771   STRINGSA("2353",""); /* Invalid format --> Error */
772   SetLastError(0xdeadbeef);
773   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
774   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
775       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
776
777   STRINGSA("2353","$2,353.00"); /* Valid number */
778   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
779   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
780   EXPECT_LENA; EXPECT_EQA;
781
782   STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
783   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
784   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
785   EXPECT_LENA; EXPECT_EQA;
786
787   STRINGSA("2353.1","$2,353.10"); /* Valid real number */
788   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
789   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
790   EXPECT_LENA; EXPECT_EQA;
791
792   STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
793   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
794   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
795   EXPECT_LENA; EXPECT_EQA;
796
797   STRINGSA("2353.119","$2,353.12");  /* Too many DP --> Rounded */
798   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
799   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
800   EXPECT_LENA; EXPECT_EQA;
801
802   format.NumDigits = 0; /* No decimal separator */
803   format.LeadingZero = 0;
804   format.Grouping = 0;  /* No grouping char */
805   format.NegativeOrder = 0;
806   format.PositiveOrder = CY_POS_LEFT;
807   format.lpDecimalSep = szDot;
808   format.lpThousandSep = szComma;
809   format.lpCurrencySymbol = szDollar;
810
811   STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
812   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
813   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
814   EXPECT_LENA; EXPECT_EQA;
815
816   format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
817   STRINGSA("2353","$2353.0");
818   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
819   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
820   EXPECT_LENA; EXPECT_EQA;
821
822   format.Grouping = 2; /* Group by 100's */
823   STRINGSA("2353","$23,53.0");
824   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
825   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
826   EXPECT_LENA; EXPECT_EQA;
827
828   STRINGSA("235","$235.0"); /* Grouping of a positive number */
829   format.Grouping = 3;
830   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
831   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
832   EXPECT_LENA; EXPECT_EQA;
833
834   STRINGSA("-235","$-235.0"); /* Grouping of a negative number */
835   format.NegativeOrder = 2;
836   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
837   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
838   EXPECT_LENA; EXPECT_EQA;
839
840   format.LeadingZero = 1; /* Always provide leading zero */
841   STRINGSA(".5","$0.5");
842   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
843   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
844   EXPECT_LENA; EXPECT_EQA;
845
846   format.PositiveOrder = CY_POS_RIGHT;
847   STRINGSA("1","1.0$");
848   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
849   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
850   EXPECT_LENA; EXPECT_EQA;
851
852   format.PositiveOrder = CY_POS_LEFT_SPACE;
853   STRINGSA("1","$ 1.0");
854   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
855   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
856   EXPECT_LENA; EXPECT_EQA;
857
858   format.PositiveOrder = CY_POS_RIGHT_SPACE;
859   STRINGSA("1","1.0 $");
860   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
861   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
862   EXPECT_LENA; EXPECT_EQA;
863
864   format.NegativeOrder = 0;
865   STRINGSA("-1","($1.0)");
866   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
867   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
868   EXPECT_LENA; EXPECT_EQA;
869
870   format.NegativeOrder = 1;
871   STRINGSA("-1","-$1.0");
872   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
873   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
874   EXPECT_LENA; EXPECT_EQA;
875
876   format.NegativeOrder = 2;
877   STRINGSA("-1","$-1.0");
878   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
879   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
880   EXPECT_LENA; EXPECT_EQA;
881
882   format.NegativeOrder = 3;
883   STRINGSA("-1","$1.0-");
884   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
885   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
886   EXPECT_LENA; EXPECT_EQA;
887
888   format.NegativeOrder = 4;
889   STRINGSA("-1","(1.0$)");
890   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
891   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
892   EXPECT_LENA; EXPECT_EQA;
893
894   format.NegativeOrder = 5;
895   STRINGSA("-1","-1.0$");
896   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
897   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
898   EXPECT_LENA; EXPECT_EQA;
899
900   format.NegativeOrder = 6;
901   STRINGSA("-1","1.0-$");
902   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
903   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
904   EXPECT_LENA; EXPECT_EQA;
905
906   format.NegativeOrder = 7;
907   STRINGSA("-1","1.0$-");
908   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
909   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
910   EXPECT_LENA; EXPECT_EQA;
911
912   format.NegativeOrder = 8;
913   STRINGSA("-1","-1.0 $");
914   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
915   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
916   EXPECT_LENA; EXPECT_EQA;
917
918   format.NegativeOrder = 9;
919   STRINGSA("-1","-$ 1.0");
920   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
921   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
922   EXPECT_LENA; EXPECT_EQA;
923
924   format.NegativeOrder = 10;
925   STRINGSA("-1","1.0 $-");
926   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
927   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
928   EXPECT_LENA; EXPECT_EQA;
929
930   format.NegativeOrder = 11;
931   STRINGSA("-1","$ 1.0-");
932   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
933   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
934   EXPECT_LENA; EXPECT_EQA;
935
936   format.NegativeOrder = 12;
937   STRINGSA("-1","$ -1.0");
938   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
939   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
940   EXPECT_LENA; EXPECT_EQA;
941
942   format.NegativeOrder = 13;
943   STRINGSA("-1","1.0- $");
944   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
945   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
946   EXPECT_LENA; EXPECT_EQA;
947
948   format.NegativeOrder = 14;
949   STRINGSA("-1","($ 1.0)");
950   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
951   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
952   EXPECT_LENA; EXPECT_EQA;
953
954   format.NegativeOrder = 15;
955   STRINGSA("-1","(1.0 $)");
956   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
957   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
958   EXPECT_LENA; EXPECT_EQA;
959 }
960
961 #define NEG_PARENS      0 /* "(1.1)" */
962 #define NEG_LEFT        1 /* "-1.1"  */
963 #define NEG_LEFT_SPACE  2 /* "- 1.1" */
964 #define NEG_RIGHT       3 /* "1.1-"  */
965 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
966
967 static void test_GetNumberFormatA(void)
968 {
969   static char szDot[] = { '.', '\0' };
970   static char szComma[] = { ',', '\0' };
971   int ret;
972   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
973   char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
974   NUMBERFMTA format;
975
976   memset(&format, 0, sizeof(format));
977
978   STRINGSA("23",""); /* NULL output, length > 0 --> Error */
979   SetLastError(0xdeadbeef);
980   ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
981   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
982       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
983
984   STRINGSA("23,53",""); /* Invalid character --> Error */
985   SetLastError(0xdeadbeef);
986   ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
987   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
988       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
989
990   STRINGSA("--",""); /* Double '-' --> Error */
991   SetLastError(0xdeadbeef);
992   ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
993   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
994       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
995
996   STRINGSA("0-",""); /* Trailing '-' --> Error */
997   SetLastError(0xdeadbeef);
998   ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
999   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1000       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1001
1002   STRINGSA("0..",""); /* Double '.' --> Error */
1003   SetLastError(0xdeadbeef);
1004   ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1005   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1006       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1007
1008   STRINGSA(" 0.1",""); /* Leading space --> Error */
1009   SetLastError(0xdeadbeef);
1010   ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1011   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1012       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1013
1014   STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
1015   SetLastError(0xdeadbeef);
1016   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, 2);
1017   ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1018       "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1019
1020   STRINGSA("2353",""); /* Format and flags given --> Error */
1021   SetLastError(0xdeadbeef);
1022   ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
1023   ok( !ret, "Expected ret == 0, got %d\n", ret);
1024   ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
1025       "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1026
1027   STRINGSA("2353",""); /* Invalid format --> Error */
1028   SetLastError(0xdeadbeef);
1029   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1030   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1031       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1032
1033   STRINGSA("2353","2,353.00"); /* Valid number */
1034   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1035   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1036   EXPECT_LENA; EXPECT_EQA;
1037
1038   STRINGSA("-2353","-2,353.00"); /* Valid negative number */
1039   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1040   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1041   EXPECT_LENA; EXPECT_EQA;
1042
1043   STRINGSA("-353","-353.00"); /* test for off by one error in grouping */
1044   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1045   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1046   EXPECT_LENA; EXPECT_EQA;
1047
1048   STRINGSA("2353.1","2,353.10"); /* Valid real number */
1049   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1050   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1051   EXPECT_LENA; EXPECT_EQA;
1052
1053   STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
1054   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1055   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1056   EXPECT_LENA; EXPECT_EQA;
1057
1058   STRINGSA("2353.119","2,353.12");  /* Too many DP --> Rounded */
1059   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1060   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1061   EXPECT_LENA; EXPECT_EQA;
1062
1063   format.NumDigits = 0; /* No decimal separator */
1064   format.LeadingZero = 0;
1065   format.Grouping = 0;  /* No grouping char */
1066   format.NegativeOrder = 0;
1067   format.lpDecimalSep = szDot;
1068   format.lpThousandSep = szComma;
1069
1070   STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
1071   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1072   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1073   EXPECT_LENA; EXPECT_EQA;
1074
1075   format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
1076   STRINGSA("2353","2353.0");
1077   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1078   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1079   EXPECT_LENA; EXPECT_EQA;
1080
1081   format.Grouping = 2; /* Group by 100's */
1082   STRINGSA("2353","23,53.0");
1083   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1084   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1085   EXPECT_LENA; EXPECT_EQA;
1086
1087   STRINGSA("235","235.0"); /* Grouping of a positive number */
1088   format.Grouping = 3;
1089   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1090   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1091   EXPECT_LENA; EXPECT_EQA;
1092
1093   STRINGSA("-235","-235.0"); /* Grouping of a negative number */
1094   format.NegativeOrder = NEG_LEFT;
1095   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1096   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1097   EXPECT_LENA; EXPECT_EQA;
1098
1099   format.LeadingZero = 1; /* Always provide leading zero */
1100   STRINGSA(".5","0.5");
1101   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1102   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1103   EXPECT_LENA; EXPECT_EQA;
1104
1105   format.NegativeOrder = NEG_PARENS;
1106   STRINGSA("-1","(1.0)");
1107   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1108   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1109   EXPECT_LENA; EXPECT_EQA;
1110
1111   format.NegativeOrder = NEG_LEFT;
1112   STRINGSA("-1","-1.0");
1113   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1114   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1115   EXPECT_LENA; EXPECT_EQA;
1116
1117   format.NegativeOrder = NEG_LEFT_SPACE;
1118   STRINGSA("-1","- 1.0");
1119   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1120   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1121   EXPECT_LENA; EXPECT_EQA;
1122
1123   format.NegativeOrder = NEG_RIGHT;
1124   STRINGSA("-1","1.0-");
1125   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1126   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1127   EXPECT_LENA; EXPECT_EQA;
1128
1129   format.NegativeOrder = NEG_RIGHT_SPACE;
1130   STRINGSA("-1","1.0 -");
1131   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1132   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1133   EXPECT_LENA; EXPECT_EQA;
1134
1135   lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
1136
1137   if (IsValidLocale(lcid, 0))
1138   {
1139     STRINGSA("-12345","-12 345,00"); /* Try French formatting */
1140     Expected[3] = 160; /* Non breaking space */
1141     ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1142     ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1143     EXPECT_LENA; EXPECT_EQA;
1144   }
1145 }
1146
1147
1148 static void test_CompareStringA(void)
1149 {
1150   int ret;
1151   LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
1152
1153   ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
1154   ok (ret== 1, "(Salut/Salute) Expected 1, got %d\n", ret);
1155
1156   ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
1157   ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
1158
1159   ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
1160   ok (ret== 3, "(Salut/hola) Expected 3, got %d\n", ret);
1161
1162   ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
1163   ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
1164
1165   lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
1166
1167   ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
1168   ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
1169
1170   ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
1171   ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
1172
1173     ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
1174     ok (ret == 2, "(Salut/saLuT) Expected 2, got %d\n", ret);
1175
1176     /* test for CompareStringA flags */
1177     SetLastError(0xdeadbeef);
1178     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0x8, "NULL", -1, "NULL", -1);
1179     ok(GetLastError() == ERROR_INVALID_FLAGS,
1180         "unexpected error code %d\n", GetLastError());
1181     ok(!ret, "CompareStringA must fail with invalid flag\n");
1182
1183     SetLastError(0xdeadbeef);
1184     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, LOCALE_USE_CP_ACP, "NULL", -1, "NULL", -1);
1185     ok(GetLastError() == 0xdeadbeef, "unexpected error code %d\n", GetLastError());
1186     ok(ret == CSTR_EQUAL, "CompareStringA error: %d != CSTR_EQUAL\n", ret);
1187     /* end of test for CompareStringA flags */
1188
1189     ret = lstrcmpA("", "");
1190     ok (ret == 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret);
1191
1192     ret = lstrcmpA(NULL, NULL);
1193     ok (ret == 0 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, NULL) should return 0, got %d\n", ret);
1194
1195     ret = lstrcmpA("", NULL);
1196     ok (ret == 1 || broken(ret == -2) /* win9x */, "lstrcmpA(\"\", NULL) should return 1, got %d\n", ret);
1197
1198     ret = lstrcmpA(NULL, "");
1199     ok (ret == -1 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret);
1200  
1201     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"EndDialog",-1,"_Property",-1);
1202     ok( ret == 3, "EndDialog vs _Property ... expected 3, got %d\n", ret);
1203
1204     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0070",-1,"_IEWWBrowserComp",-1);
1205     ok( ret == 3, "osp_vba.sreg0070 vs _IEWWBrowserComp ... expected 3, got %d\n", ret);
1206
1207     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"r",-1,"\\",-1); 
1208     ok( ret == 3, "r vs \\ ... expected 3, got %d\n", ret);
1209
1210     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0031", -1, "OriginalDatabase", -1 );
1211     ok( ret == 3, "osp_vba.sreg0031 vs OriginalDatabase ... expected 3, got %d\n", ret);
1212
1213     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1 );
1214     ok( ret == 3, "AAA vs aaa expected 3, got %d\n", ret);
1215
1216     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1 );
1217     ok( ret == 1, "AAA vs aab expected 1, got %d\n", ret);
1218
1219     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1 );
1220     ok( ret == 1, "AAA vs Aab expected 1, got %d\n", ret);
1221
1222     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1 );
1223     ok( ret == 1, ".AAA vs Aab expected 1, got %d\n", ret);
1224
1225     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1 );
1226     ok( ret == 1, ".AAA vs A.ab expected 1, got %d\n", ret);
1227
1228     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1 );
1229     ok( ret == 1, "aa vs AB expected 1, got %d\n", ret);
1230
1231     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1 );
1232     ok( ret == 1, "aa vs Aab expected 1, got %d\n", ret);
1233
1234     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1 );
1235     ok( ret == 3, "aB vs Aab expected 3, got %d\n", ret);
1236
1237     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1 );
1238     ok( ret == 1, "Ba vs bab expected 1, got %d\n", ret);
1239
1240     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1 );
1241     ok( ret == 1, "{100}{83}{71}{71}{71} vs Global_DataAccess_JRO expected 1, got %d\n", ret);
1242
1243     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1 );
1244     ok( ret == 3, "a vs { expected 3, got %d\n", ret);
1245
1246     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1 );
1247     ok( ret == 3, "A vs { expected 3, got %d\n", ret);
1248
1249     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1 );
1250     ok(ret == 1, "3.5/0 vs 4.0/-1 expected 1, got %d\n", ret);
1251
1252     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1 );
1253     ok(ret == 1, "3.5 vs 4.0 expected 1, got %d\n", ret);
1254
1255     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1 );
1256     ok(ret == 1, "3.520.4403.2 vs 4.0.2927.10 expected 1, got %d\n", ret);
1257
1258    /* hyphen and apostrophe are treated differently depending on
1259     * whether SORT_STRINGSORT specified or not
1260     */
1261     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1 );
1262     ok(ret == 3, "-o vs /m expected 3, got %d\n", ret);
1263
1264     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1 );
1265     ok(ret == 1, "/m vs -o expected 1, got %d\n", ret);
1266
1267     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1 );
1268     ok(ret == 1, "-o vs /m expected 1, got %d\n", ret);
1269
1270     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1 );
1271     ok(ret == 3, "/m vs -o expected 3, got %d\n", ret);
1272
1273     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1 );
1274     ok(ret == 3, "'o vs /m expected 3, got %d\n", ret);
1275
1276     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1 );
1277     ok(ret == 1, "/m vs 'o expected 1, got %d\n", ret);
1278
1279     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1 );
1280     ok(ret == 1, "'o vs /m expected 1, got %d\n", ret);
1281
1282     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1 );
1283     ok(ret == 3, "/m vs 'o expected 3, got %d\n", ret);
1284
1285     if (0) { /* this requires collation table patch to make it MS compatible */
1286     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
1287     ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
1288
1289     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
1290     ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
1291
1292     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
1293     ok(ret == 1, "' vs - expected 1, got %d\n", ret);
1294
1295     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
1296     ok(ret == 1, "' vs - expected 1, got %d\n", ret);
1297
1298     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
1299     ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
1300
1301     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
1302     ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
1303
1304     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
1305     ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
1306
1307     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
1308     ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
1309
1310     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
1311     ok(ret == 1, "`o vs -m expected 1, got %d\n", ret);
1312
1313     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
1314     ok(ret == 3, "-m vs `o expected 3, got %d\n", ret);
1315
1316     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
1317     ok(ret == 3, "`o vs -m expected 3, got %d\n", ret);
1318
1319     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
1320     ok(ret == 1, "-m vs `o expected 1, got %d\n", ret);
1321     }
1322
1323     ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9);
1324     ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0 expected 2, got %d\n", ret);
1325
1326     ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10);
1327     ok(ret == 1, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1, got %d\n", ret);
1328
1329     /* WinXP handles embedded NULLs differently than earlier versions */
1330     ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
1331     ok(ret == 1 || ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1 or 2, got %d\n", ret);
1332
1333     ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
1334     ok(ret == 1 || ret == 2, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected 1 or 2, got %d\n", ret);
1335
1336     ret = CompareStringA(lcid, 0, "a\0b", -1, "a", -1);
1337     ok(ret == 2, "a vs a expected 2, got %d\n", ret);
1338
1339     ret = CompareStringA(lcid, 0, "a\0b", 4, "a", 2);
1340     ok(ret == CSTR_EQUAL || /* win2k */
1341        ret == CSTR_GREATER_THAN,
1342        "a\\0b vs a expected CSTR_EQUAL or CSTR_GREATER_THAN, got %d\n", ret);
1343
1344     ret = CompareStringA(lcid, 0, "\2", 2, "\1", 2);
1345     todo_wine ok(ret != 2, "\\2 vs \\1 expected unequal\n");
1346
1347     ret = CompareStringA(lcid, NORM_IGNORECASE | LOCALE_USE_CP_ACP, "#", -1, ".", -1);
1348     todo_wine ok(ret == CSTR_LESS_THAN, "\"#\" vs \".\" expected CSTR_LESS_THAN, got %d\n", ret);
1349
1350     ret = CompareStringA(lcid, NORM_IGNORECASE, "_", -1, ".", -1);
1351     todo_wine ok(ret == CSTR_GREATER_THAN, "\"_\" vs \".\" expected CSTR_GREATER_THAN, got %d\n", ret);
1352
1353     ret = lstrcmpi("#", ".");
1354     todo_wine ok(ret == -1, "\"#\" vs \".\" expected -1, got %d\n", ret);
1355 }
1356
1357 static void test_LCMapStringA(void)
1358 {
1359     int ret, ret2;
1360     char buf[256], buf2[256];
1361     static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
1362     static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
1363     static const char symbols_stripped[] = "justateststring1";
1364
1365     SetLastError(0xdeadbeef);
1366     ret = LCMapStringA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP | LCMAP_LOWERCASE,
1367                        lower_case, -1, buf, sizeof(buf));
1368     ok(ret == lstrlenA(lower_case) + 1,
1369        "ret %d, error %d, expected value %d\n",
1370        ret, GetLastError(), lstrlenA(lower_case) + 1);
1371     ok(!memcmp(buf, lower_case, ret), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1372
1373     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1374                        upper_case, -1, buf, sizeof(buf));
1375     ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1376     ok(GetLastError() == ERROR_INVALID_FLAGS,
1377        "unexpected error code %d\n", GetLastError());
1378
1379     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1380                        upper_case, -1, buf, sizeof(buf));
1381     ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1382     ok(GetLastError() == ERROR_INVALID_FLAGS,
1383        "unexpected error code %d\n", GetLastError());
1384
1385     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1386                        upper_case, -1, buf, sizeof(buf));
1387     ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1388     ok(GetLastError() == ERROR_INVALID_FLAGS,
1389        "unexpected error code %d\n", GetLastError());
1390
1391     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1392                        upper_case, -1, buf, sizeof(buf));
1393     ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1394     ok(GetLastError() == ERROR_INVALID_FLAGS,
1395        "unexpected error code %d\n", GetLastError());
1396
1397     /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1398     SetLastError(0xdeadbeef);
1399     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1400                        upper_case, -1, buf, sizeof(buf));
1401     ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1402     ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1403
1404     /* test LCMAP_LOWERCASE */
1405     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1406                        upper_case, -1, buf, sizeof(buf));
1407     ok(ret == lstrlenA(upper_case) + 1,
1408        "ret %d, error %d, expected value %d\n",
1409        ret, GetLastError(), lstrlenA(upper_case) + 1);
1410     ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1411
1412     /* test LCMAP_UPPERCASE */
1413     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1414                        lower_case, -1, buf, sizeof(buf));
1415     ok(ret == lstrlenA(lower_case) + 1,
1416        "ret %d, error %d, expected value %d\n",
1417        ret, GetLastError(), lstrlenA(lower_case) + 1);
1418     ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1419
1420     /* test buffer overflow */
1421     SetLastError(0xdeadbeef);
1422     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1423                        lower_case, -1, buf, 4);
1424     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1425        "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1426
1427     /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1428     lstrcpyA(buf, lower_case);
1429     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1430                        buf, -1, buf, sizeof(buf));
1431     if (!ret) /* Win9x */
1432         trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1433     else
1434     {
1435         ok(ret == lstrlenA(lower_case) + 1,
1436            "ret %d, error %d, expected value %d\n",
1437            ret, GetLastError(), lstrlenA(lower_case) + 1);
1438         ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1439     }
1440     lstrcpyA(buf, upper_case);
1441     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1442                        buf, -1, buf, sizeof(buf));
1443     if (!ret) /* Win9x */
1444         trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1445     else
1446     {
1447         ok(ret == lstrlenA(upper_case) + 1,
1448            "ret %d, error %d, expected value %d\n",
1449            ret, GetLastError(), lstrlenA(lower_case) + 1);
1450         ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1451     }
1452
1453     /* otherwise src == dst should fail */
1454     SetLastError(0xdeadbeef);
1455     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1456                        buf, 10, buf, sizeof(buf));
1457     ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1458        GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1459        "unexpected error code %d\n", GetLastError());
1460     ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1461
1462     /* test whether '\0' is always appended */
1463     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1464                        upper_case, -1, buf, sizeof(buf));
1465     ok(ret, "LCMapStringA must succeed\n");
1466     ok(buf[ret-1] == 0, "LCMapStringA not null-terminated\n");
1467     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1468                        upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1469     ok(ret2, "LCMapStringA must succeed\n");
1470     ok(buf2[ret2-1] == 0, "LCMapStringA not null-terminated\n" );
1471     ok(ret == ret2, "lengths of sort keys must be equal\n");
1472     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1473
1474     /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1475     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1476                        upper_case, -1, buf, sizeof(buf));
1477     ok(ret, "LCMapStringA must succeed\n");
1478     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1479                        lower_case, -1, buf2, sizeof(buf2));
1480     ok(ret2, "LCMapStringA must succeed\n");
1481     ok(ret == ret2, "lengths of sort keys must be equal\n");
1482     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1483
1484     /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1485        results from plain LCMAP_SORTKEY on Vista */
1486
1487     /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1488     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1489                        lower_case, -1, buf, sizeof(buf));
1490     ok(ret, "LCMapStringA must succeed\n");
1491     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1492                        symbols_stripped, -1, buf2, sizeof(buf2));
1493     ok(ret2, "LCMapStringA must succeed\n");
1494     ok(ret == ret2, "lengths of sort keys must be equal\n");
1495     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1496
1497     /* test NORM_IGNORENONSPACE */
1498     lstrcpyA(buf, "foo");
1499     ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1500                        lower_case, -1, buf, sizeof(buf));
1501     ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1502         lstrlenA(lower_case) + 1, ret);
1503     ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1504
1505     /* test NORM_IGNORESYMBOLS */
1506     lstrcpyA(buf, "foo");
1507     ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1508                        lower_case, -1, buf, sizeof(buf));
1509     ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1510         lstrlenA(symbols_stripped) + 1, ret);
1511     ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1512
1513     /* test srclen = 0 */
1514     SetLastError(0xdeadbeef);
1515     ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1516     ok(!ret, "LCMapStringA should fail with srclen = 0\n");
1517     ok(GetLastError() == ERROR_INVALID_PARAMETER,
1518        "unexpected error code %d\n", GetLastError());
1519 }
1520
1521 static void test_LCMapStringW(void)
1522 {
1523     int ret, ret2;
1524     WCHAR buf[256], buf2[256];
1525     char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1526     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};
1527     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};
1528     static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
1529     static const WCHAR fooW[] = {'f','o','o',0};
1530
1531     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1532                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1533     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1534     {
1535         win_skip("LCMapStringW is not implemented\n");
1536         return;
1537     }
1538     if (broken(ret))
1539         ok(lstrcmpW(buf, upper_case) == 0, "Expected upper case string\n");
1540     else
1541     {
1542         ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1543         ok(GetLastError() == ERROR_INVALID_FLAGS,
1544            "unexpected error code %d\n", GetLastError());
1545     }
1546
1547     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1548                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1549     ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1550     ok(GetLastError() == ERROR_INVALID_FLAGS,
1551        "unexpected error code %d\n", GetLastError());
1552
1553     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1554                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1555     ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1556     ok(GetLastError() == ERROR_INVALID_FLAGS,
1557        "unexpected error code %d\n", GetLastError());
1558
1559     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1560                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1561     ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1562     ok(GetLastError() == ERROR_INVALID_FLAGS,
1563        "unexpected error code %d\n", GetLastError());
1564
1565     /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1566     SetLastError(0xdeadbeef);
1567     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1568                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1569     ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1570     ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1571
1572     /* test LCMAP_LOWERCASE */
1573     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1574                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1575     ok(ret == lstrlenW(upper_case) + 1,
1576        "ret %d, error %d, expected value %d\n",
1577        ret, GetLastError(), lstrlenW(upper_case) + 1);
1578     ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1579
1580     /* test LCMAP_UPPERCASE */
1581     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1582                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1583     ok(ret == lstrlenW(lower_case) + 1,
1584        "ret %d, error %d, expected value %d\n",
1585        ret, GetLastError(), lstrlenW(lower_case) + 1);
1586     ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1587
1588     /* test buffer overflow */
1589     SetLastError(0xdeadbeef);
1590     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1591                        lower_case, -1, buf, 4);
1592     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1593        "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1594
1595     /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1596     lstrcpyW(buf, lower_case);
1597     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1598                        buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1599     ok(ret == lstrlenW(lower_case) + 1,
1600        "ret %d, error %d, expected value %d\n",
1601        ret, GetLastError(), lstrlenW(lower_case) + 1);
1602     ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1603
1604     lstrcpyW(buf, upper_case);
1605     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1606                        buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1607     ok(ret == lstrlenW(upper_case) + 1,
1608        "ret %d, error %d, expected value %d\n",
1609        ret, GetLastError(), lstrlenW(lower_case) + 1);
1610     ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1611
1612     /* otherwise src == dst should fail */
1613     SetLastError(0xdeadbeef);
1614     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1615                        buf, 10, buf, sizeof(buf));
1616     ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1617        GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1618        "unexpected error code %d\n", GetLastError());
1619     ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1620
1621     /* test whether '\0' is always appended */
1622     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1623                        upper_case, -1, buf, sizeof(buf));
1624     ok(ret, "LCMapStringW must succeed\n");
1625     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1626                        upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1627     ok(ret, "LCMapStringW must succeed\n");
1628     ok(ret == ret2, "lengths of sort keys must be equal\n");
1629     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1630
1631     /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1632     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1633                        upper_case, -1, buf, sizeof(buf));
1634     ok(ret, "LCMapStringW must succeed\n");
1635     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1636                        lower_case, -1, buf2, sizeof(buf2));
1637     ok(ret2, "LCMapStringW must succeed\n");
1638     ok(ret == ret2, "lengths of sort keys must be equal\n");
1639     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1640
1641     /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1642        results from plain LCMAP_SORTKEY on Vista */
1643
1644     /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1645     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1646                        lower_case, -1, buf, sizeof(buf));
1647     ok(ret, "LCMapStringW must succeed\n");
1648     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1649                        symbols_stripped, -1, buf2, sizeof(buf2));
1650     ok(ret2, "LCMapStringW must succeed\n");
1651     ok(ret == ret2, "lengths of sort keys must be equal\n");
1652     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1653
1654     /* test NORM_IGNORENONSPACE */
1655     lstrcpyW(buf, fooW);
1656     ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1657                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1658     ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1659         lstrlenW(lower_case) + 1, ret);
1660     ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1661
1662     /* test NORM_IGNORESYMBOLS */
1663     lstrcpyW(buf, fooW);
1664     ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1665                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1666     ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1667         lstrlenW(symbols_stripped) + 1, ret);
1668     ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1669
1670     /* test srclen = 0 */
1671     SetLastError(0xdeadbeef);
1672     ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf)/sizeof(WCHAR));
1673     ok(!ret, "LCMapStringW should fail with srclen = 0\n");
1674     ok(GetLastError() == ERROR_INVALID_PARAMETER,
1675        "unexpected error code %d\n", GetLastError());
1676 }
1677
1678 /* this requires collation table patch to make it MS compatible */
1679 static const char * const strings_sorted[] =
1680 {
1681 "'",
1682 "-",
1683 "!",
1684 "\"",
1685 ".",
1686 ":",
1687 "\\",
1688 "_",
1689 "`",
1690 "{",
1691 "}",
1692 "+",
1693 "0",
1694 "1",
1695 "2",
1696 "3",
1697 "4",
1698 "5",
1699 "6",
1700 "7",
1701 "8",
1702 "9",
1703 "a",
1704 "A",
1705 "b",
1706 "B",
1707 "c",
1708 "C"
1709 };
1710
1711 static const char * const strings[] =
1712 {
1713 "C",
1714 "\"",
1715 "9",
1716 "'",
1717 "}",
1718 "-",
1719 "7",
1720 "+",
1721 "`",
1722 "1",
1723 "a",
1724 "5",
1725 "\\",
1726 "8",
1727 "B",
1728 "3",
1729 "_",
1730 "6",
1731 "{",
1732 "2",
1733 "c",
1734 "4",
1735 "!",
1736 "0",
1737 "A",
1738 ":",
1739 "b",
1740 "."
1741 };
1742
1743 static int compare_string1(const void *e1, const void *e2)
1744 {
1745     const char *s1 = *(const char *const *)e1;
1746     const char *s2 = *(const char *const *)e2;
1747
1748     return lstrcmpA(s1, s2);
1749 }
1750
1751 static int compare_string2(const void *e1, const void *e2)
1752 {
1753     const char *s1 = *(const char *const *)e1;
1754     const char *s2 = *(const char *const *)e2;
1755
1756     return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1757 }
1758
1759 static int compare_string3(const void *e1, const void *e2)
1760 {
1761     const char *s1 = *(const char *const *)e1;
1762     const char *s2 = *(const char *const *)e2;
1763     char key1[256], key2[256];
1764
1765     LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
1766     LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
1767     return strcmp(key1, key2);
1768 }
1769
1770 static void test_sorting(void)
1771 {
1772     char buf[256];
1773     char **str_buf = (char **)buf;
1774     int i;
1775
1776     assert(sizeof(buf) >= sizeof(strings));
1777
1778     /* 1. sort using lstrcmpA */
1779     memcpy(buf, strings, sizeof(strings));
1780     qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
1781     for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1782     {
1783         ok(!strcmp(strings_sorted[i], str_buf[i]),
1784            "qsort using lstrcmpA failed for element %d\n", i);
1785     }
1786     /* 2. sort using CompareStringA */
1787     memcpy(buf, strings, sizeof(strings));
1788     qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
1789     for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1790     {
1791         ok(!strcmp(strings_sorted[i], str_buf[i]),
1792            "qsort using CompareStringA failed for element %d\n", i);
1793     }
1794     /* 3. sort using sort keys */
1795     memcpy(buf, strings, sizeof(strings));
1796     qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
1797     for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1798     {
1799         ok(!strcmp(strings_sorted[i], str_buf[i]),
1800            "qsort using sort keys failed for element %d\n", i);
1801     }
1802 }
1803
1804 static void test_FoldStringA(void)
1805 {
1806   int ret, i, j;
1807   BOOL is_special;
1808   char src[256], dst[256];
1809   static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0'  };
1810   static const char digits_dst[] = { '1','2','3','\0'  };
1811   static const char composite_src[] =
1812   {
1813     0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
1814     0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
1815     0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
1816     0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
1817     0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
1818     0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
1819     0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
1820     0xfb,0xfc,0xfd,0xff,'\0'
1821   };
1822   static const char composite_dst[] =
1823   {
1824     0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1825     0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1826     0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1827     0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1828     0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1829     0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1830     0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
1831     0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
1832     0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
1833     0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
1834     0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
1835     0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
1836     0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
1837     0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
1838     0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1839   };
1840   static const char composite_dst_alt[] =
1841   {
1842     0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1843     0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1844     0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1845     0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1846     0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1847     0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1848     0x4f,0x7e,0x4f,0xa8,0xd8,0x55,0x60,0x55,
1849     0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,0x61,
1850     0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,0x61,
1851     0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,0x65,
1852     0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,0x69,
1853     0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,0x6f,
1854     0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,0x6f,
1855     0xa8,0xf8,0x75,0x60,0x75,0xb4,0x75,0x5e,
1856     0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1857   };
1858   static const char ligatures_src[] =
1859   {
1860     0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1861   };
1862   static const char ligatures_dst[] =
1863   {
1864     'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1865   };
1866   static const struct special
1867   {
1868     char src;
1869     char dst[4];
1870   }  foldczone_special[] =
1871   {
1872     /* src   dst                   */
1873     { 0x85, { 0x2e, 0x2e, 0x2e, 0x00 } },
1874     { 0x98, { 0x20, 0x7e, 0x00 } },
1875     { 0x99, { 0x54, 0x4d, 0x00 } },
1876     { 0xa0, { 0x20, 0x00 } },
1877     { 0xa8, { 0x20, 0xa8, 0x00 } },
1878     { 0xaa, { 0x61, 0x00 } },
1879     { 0xaf, { 0x20, 0xaf, 0x00 } },
1880     { 0xb2, { 0x32, 0x00 } },
1881     { 0xb3, { 0x33, 0x00 } },
1882     { 0xb4, { 0x20, 0xb4, 0x00 } },
1883     { 0xb8, { 0x20, 0xb8, 0x00 } },
1884     { 0xb9, { 0x31, 0x00 } },
1885     { 0xba, { 0x6f, 0x00 } },
1886     { 0xbc, { 0x31, 0x2f, 0x34, 0x00 } },
1887     { 0xbd, { 0x31, 0x2f, 0x32, 0x00 } },
1888     { 0xbe, { 0x33, 0x2f, 0x34, 0x00 } },
1889     { 0x00 }
1890   };
1891
1892   if (!pFoldStringA)
1893     return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1894
1895   /* these tests are locale specific */
1896   if (GetACP() != 1252)
1897   {
1898       trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1899       return;
1900   }
1901
1902   /* MAP_FOLDDIGITS */
1903   SetLastError(0);
1904   ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
1905   if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1906   {
1907     win_skip("FoldStringA is not implemented\n");
1908     return;
1909   }
1910   ok(ret == 4, "Expected ret == 4, got %d, error %d\n", ret, GetLastError());
1911   ok(strcmp(dst, digits_dst) == 0,
1912      "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
1913   for (i = 1; i < 256; i++)
1914   {
1915     if (!strchr(digits_src, i))
1916     {
1917       src[0] = i;
1918       src[1] = '\0';
1919       SetLastError(0);
1920       ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
1921       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1922       ok(dst[0] == src[0],
1923          "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
1924     }
1925   }
1926
1927   /* MAP_EXPAND_LIGATURES */
1928   SetLastError(0);
1929   ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1930   /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1931   if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1932     ok(ret == sizeof(ligatures_dst), "Got %d, error %d\n", ret, GetLastError());
1933     ok(strcmp(dst, ligatures_dst) == 0,
1934        "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
1935     for (i = 1; i < 256; i++)
1936     {
1937       if (!strchr(ligatures_src, i))
1938       {
1939         src[0] = i;
1940         src[1] = '\0';
1941         SetLastError(0);
1942         ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1943         if (ret == 3)
1944         {
1945           /* Vista */
1946           ok((i == 0xDC && lstrcmpA(dst, "UE") == 0) ||
1947              (i == 0xFC && lstrcmpA(dst, "ue") == 0),
1948              "Got %s for %d\n", dst, i);
1949         }
1950         else
1951         {
1952           ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1953           ok(dst[0] == src[0],
1954              "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
1955         }
1956       }
1957     }
1958   }
1959
1960   /* MAP_COMPOSITE */
1961   SetLastError(0);
1962   ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
1963   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1964   ok(ret == 121 || ret == 119, "Expected 121 or 119, got %d\n", ret);
1965   ok(strcmp(dst, composite_dst) == 0 || strcmp(dst, composite_dst_alt) == 0,
1966      "MAP_COMPOSITE: Mismatch, got '%s'\n", dst);
1967
1968   for (i = 1; i < 256; i++)
1969   {
1970     if (!strchr(composite_src, i))
1971     {
1972       src[0] = i;
1973       src[1] = '\0';
1974       SetLastError(0);
1975       ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
1976       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1977       ok(dst[0] == src[0],
1978          "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
1979          (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
1980     }
1981   }
1982
1983   /* MAP_FOLDCZONE */
1984   for (i = 1; i < 256; i++)
1985   {
1986     src[0] = i;
1987     src[1] = '\0';
1988     SetLastError(0);
1989     ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
1990     is_special = FALSE;
1991     for (j = 0; foldczone_special[j].src != 0 && ! is_special; j++)
1992     {
1993       if (foldczone_special[j].src == src[0])
1994       {
1995         ok(ret == 2 || ret == lstrlenA(foldczone_special[j].dst) + 1,
1996            "Expected ret == 2 or %d, got %d, error %d\n",
1997            lstrlenA(foldczone_special[j].dst) + 1, ret, GetLastError());
1998         ok(src[0] == dst[0] || lstrcmpA(foldczone_special[j].dst, dst) == 0,
1999            "MAP_FOLDCZONE: string mismatch for 0x%02x\n",
2000            (unsigned char)src[0]);
2001         is_special = TRUE;
2002       }
2003     }
2004     if (! is_special)
2005     {
2006       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2007       ok(src[0] == dst[0],
2008          "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
2009          (unsigned char)src[0], (unsigned char)dst[0]);
2010     }
2011   }
2012
2013   /* MAP_PRECOMPOSED */
2014   for (i = 1; i < 256; i++)
2015   {
2016     src[0] = i;
2017     src[1] = '\0';
2018     SetLastError(0);
2019     ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
2020     ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2021     ok(src[0] == dst[0],
2022        "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
2023        (unsigned char)src[0], (unsigned char)dst[0]);
2024   }
2025 }
2026
2027 static void test_FoldStringW(void)
2028 {
2029   int ret;
2030   unsigned int i, j;
2031   WCHAR src[256], dst[256], ch, prev_ch = 1;
2032   static const DWORD badFlags[] =
2033   {
2034     0,
2035     MAP_PRECOMPOSED|MAP_COMPOSITE,
2036     MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
2037     MAP_COMPOSITE|MAP_EXPAND_LIGATURES
2038   };
2039   /* Ranges of digits 0-9 : Must be sorted! */
2040   static const WCHAR digitRanges[] =
2041   {
2042     0x0030, /* '0'-'9' */
2043     0x0660, /* Eastern Arabic */
2044     0x06F0, /* Arabic - Hindu */
2045     0x0966, /* Devengari */
2046     0x09E6, /* Bengalii */
2047     0x0A66, /* Gurmukhi */
2048     0x0AE6, /* Gujarati */
2049     0x0B66, /* Oriya */
2050     0x0BE6, /* Tamil - No 0 */
2051     0x0C66, /* Telugu */
2052     0x0CE6, /* Kannada */
2053     0x0D66, /* Maylayalam */
2054     0x0E50, /* Thai */
2055     0x0ED0, /* Laos */
2056     0x0F29, /* Tibet - 0 is out of sequence */
2057     0x2070, /* Superscript - 1, 2, 3 are out of sequence */
2058     0x2080, /* Subscript */
2059     0x245F, /* Circled - 0 is out of sequence */
2060     0x2473, /* Bracketed */
2061     0x2487, /* Full stop */
2062     0x2775, /* Inverted circled - No 0 */
2063     0x277F, /* Patterned circled - No 0 */
2064     0x2789, /* Inverted Patterned circled - No 0 */
2065     0x3020, /* Hangzhou */
2066     0xff10, /* Pliene chasse (?) */
2067     0xffff  /* Terminator */
2068   };
2069   /* Digits which are represented, but out of sequence */
2070   static const WCHAR outOfSequenceDigits[] =
2071   {
2072       0xB9,   /* Superscript 1 */
2073       0xB2,   /* Superscript 2 */
2074       0xB3,   /* Superscript 3 */
2075       0x0F33, /* Tibetan half zero */
2076       0x24EA, /* Circled 0 */
2077       0x3007, /* Ideographic number zero */
2078       '\0'    /* Terminator */
2079   };
2080   /* Digits in digitRanges for which no representation is available */
2081   static const WCHAR noDigitAvailable[] =
2082   {
2083       0x0BE6, /* No Tamil 0 */
2084       0x0F29, /* No Tibetan half zero (out of sequence) */
2085       0x2473, /* No Bracketed 0 */
2086       0x2487, /* No 0 Full stop */
2087       0x2775, /* No inverted circled 0 */
2088       0x277F, /* No patterned circled */
2089       0x2789, /* No inverted Patterned circled */
2090       0x3020, /* No Hangzhou 0 */
2091       '\0'    /* Terminator */
2092   };
2093   static const WCHAR foldczone_src[] =
2094   {
2095     'W',    'i',    'n',    'e',    0x0348, 0x0551, 0x1323, 0x280d,
2096     0xff37, 0xff49, 0xff4e, 0xff45, '\0'
2097   };
2098   static const WCHAR foldczone_dst[] =
2099   {
2100     'W','i','n','e',0x0348,0x0551,0x1323,0x280d,'W','i','n','e','\0'
2101   };
2102   static const WCHAR ligatures_src[] =
2103   {
2104     'W',    'i',    'n',    'e',    0x03a6, 0x03b9, 0x03bd, 0x03b5,
2105     0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
2106     0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
2107     0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
2108     0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
2109     0xfb04, 0xfb05, 0xfb06, '\0'
2110   };
2111   static const WCHAR ligatures_dst[] =
2112   {
2113     'W','i','n','e',0x03a6,0x03b9,0x03bd,0x03b5,
2114     'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
2115     'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
2116     'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
2117     0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
2118     'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
2119   };
2120
2121   if (!pFoldStringW)
2122   {
2123     win_skip("FoldStringW is not available\n");
2124     return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
2125   }
2126
2127   /* Invalid flag combinations */
2128   for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
2129   {
2130     src[0] = dst[0] = '\0';
2131     SetLastError(0);
2132     ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
2133     if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
2134     {
2135       win_skip("FoldStringW is not implemented\n");
2136       return;
2137     }
2138     ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
2139        "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2140   }
2141
2142   /* src & dst cannot be the same */
2143   SetLastError(0);
2144   ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
2145   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2146       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2147
2148   /* src can't be NULL */
2149   SetLastError(0);
2150   ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
2151   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2152       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2153
2154   /* srclen can't be 0 */
2155   SetLastError(0);
2156   ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
2157   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2158       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2159
2160   /* dstlen can't be < 0 */
2161   SetLastError(0);
2162   ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
2163   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2164       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2165
2166   /* Ret includes terminating NUL which is appended if srclen = -1 */
2167   SetLastError(0);
2168   src[0] = 'A';
2169   src[1] = '\0';
2170   dst[0] = '\0';
2171   ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
2172   ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2173   ok(dst[0] == 'A' && dst[1] == '\0',
2174      "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%d\n",
2175      'A', '\0', ret, dst[0], dst[1], GetLastError());
2176
2177   /* If size is given, result is not NUL terminated */
2178   SetLastError(0);
2179   src[0] = 'A';
2180   src[1] = 'A';
2181   dst[0] = 'X';
2182   dst[1] = 'X';
2183   ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
2184   ok(ret == 1, "Expected ret == 1, got %d, error %d\n", ret, GetLastError());
2185   ok(dst[0] == 'A' && dst[1] == 'X',
2186      "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%d\n",
2187      'A','X', ret, dst[0], dst[1], GetLastError());
2188
2189   /* MAP_FOLDDIGITS */
2190   for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
2191   {
2192     /* Check everything before this range */
2193     for (ch = prev_ch; ch < digitRanges[j]; ch++)
2194     {
2195       SetLastError(0);
2196       src[0] = ch;
2197       src[1] = dst[0] = '\0';
2198       ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2199       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2200
2201       ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
2202          /* Wine (correctly) maps all Unicode 4.0+ digits */
2203          isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF ||
2204          (ch >= 0x1369 && ch <= 0x1371),
2205          "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
2206     }
2207
2208     if (digitRanges[j] == 0xffff)
2209       break; /* Finished the whole code point space */
2210
2211     for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
2212     {
2213       WCHAR c;
2214
2215       /* Map out of sequence characters */
2216       if      (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
2217       else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
2218       else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
2219       else if (ch == 0x245F) c = 0x24EA; /* Circled 0     */
2220       else                   c = ch;
2221       SetLastError(0);
2222       src[0] = c;
2223       src[1] = dst[0] = '\0';
2224       ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2225       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2226
2227       ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
2228          broken( dst[0] == ch ) ||  /* old Windows versions don't have all mappings */
2229          (digitRanges[j] == 0x3020 && dst[0] == ch) || /* Hangzhou not present in all Windows versions */
2230          (digitRanges[j] == 0x0F29 && dst[0] == ch) || /* Tibetan not present in all Windows versions */
2231          strchrW(noDigitAvailable, c),
2232          "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
2233          ch, '0' + digitRanges[j] - ch, dst[0]);
2234     }
2235     prev_ch = ch;
2236   }
2237
2238   /* MAP_FOLDCZONE */
2239   SetLastError(0);
2240   ret = pFoldStringW(MAP_FOLDCZONE, foldczone_src, -1, dst, 256);
2241   ok(ret == sizeof(foldczone_dst)/sizeof(foldczone_dst[0]),
2242      "Got %d, error %d\n", ret, GetLastError());
2243   ok(!memcmp(dst, foldczone_dst, sizeof(foldczone_dst)),
2244      "MAP_FOLDCZONE: Expanded incorrectly\n");
2245
2246   /* MAP_EXPAND_LIGATURES */
2247   SetLastError(0);
2248   ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
2249   /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
2250   if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
2251     ok(ret == sizeof(ligatures_dst)/sizeof(ligatures_dst[0]),
2252        "Got %d, error %d\n", ret, GetLastError());
2253     ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
2254        "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
2255   }
2256
2257   /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
2258 }
2259
2260
2261
2262 #define LCID_OK(l) \
2263   ok(lcid == l, "Expected lcid = %08x, got %08x\n", l, lcid)
2264 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
2265 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
2266 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
2267 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
2268
2269 static void test_ConvertDefaultLocale(void)
2270 {
2271   LCID lcid;
2272
2273   /* Doesn't change lcid, even if non default sublang/sort used */
2274   TEST_LCID(LANG_ENGLISH,  SUBLANG_ENGLISH_US, SORT_DEFAULT);
2275   TEST_LCID(LANG_ENGLISH,  SUBLANG_ENGLISH_UK, SORT_DEFAULT);
2276   TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT,    SORT_DEFAULT);
2277   TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT,    SORT_JAPANESE_UNICODE);
2278
2279   /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
2280   LCID_RES(MKLCID(LANG_ENGLISH,  SUBLANG_NEUTRAL, SORT_DEFAULT),
2281            MKLCID(LANG_ENGLISH,  SUBLANG_DEFAULT, SORT_DEFAULT));
2282   LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
2283            MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
2284
2285   /* Invariant language is not treated specially */
2286   TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
2287
2288   /* User/system default languages alone are not mapped */
2289   TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
2290   TEST_LCIDLANG(LANG_USER_DEFAULT,   SORT_JAPANESE_UNICODE);
2291
2292   /* Default lcids */
2293   LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
2294   LCID_RES(LOCALE_USER_DEFAULT,   GetUserDefaultLCID());
2295   LCID_RES(LOCALE_NEUTRAL,        GetUserDefaultLCID());
2296 }
2297
2298 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
2299                                     DWORD dwFlags, LONG_PTR lParam)
2300 {
2301   trace("%08x, %s, %s, %08x, %08lx\n",
2302         lgrpid, lpszNum, lpszName, dwFlags, lParam);
2303
2304   ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
2305      "Enumerated grp %d not valid (flags %d)\n", lgrpid, dwFlags);
2306
2307   /* If lParam is one, we are calling with flags defaulted from 0 */
2308   ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
2309          "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %d\n", dwFlags);
2310
2311   return TRUE;
2312 }
2313
2314 static void test_EnumSystemLanguageGroupsA(void)
2315 {
2316   BOOL ret;
2317
2318   if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
2319   {
2320     win_skip("EnumSystemLanguageGroupsA and/or IsValidLanguageGroup are not available\n");
2321     return;
2322   }
2323
2324   /* No enumeration proc */
2325   SetLastError(0);
2326   ret = pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
2327   if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2328   {
2329     win_skip("EnumSystemLanguageGroupsA is not implemented\n");
2330     return;
2331   }
2332   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2333       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2334
2335   /* Invalid flags */
2336   SetLastError(0);
2337   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
2338   ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2339
2340   /* No flags - defaults to LGRPID_INSTALLED */
2341   SetLastError(0xdeadbeef);
2342   pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
2343   ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
2344
2345   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
2346   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
2347 }
2348
2349
2350 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
2351                                       LONG_PTR lParam)
2352 {
2353   trace("%08x, %08x, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
2354
2355   /* invalid locale enumerated on some platforms */
2356   if (lcid == 0)
2357       return TRUE;
2358
2359   ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
2360      "Enumerated grp %d not valid\n", lgrpid);
2361   ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
2362      "Enumerated grp locale %d not valid\n", lcid);
2363   return TRUE;
2364 }
2365
2366 static void test_EnumLanguageGroupLocalesA(void)
2367 {
2368   BOOL ret;
2369
2370   if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
2371   {
2372     win_skip("EnumLanguageGroupLocalesA and/or IsValidLanguageGroup are not available\n");
2373     return;
2374   }
2375
2376   /* No enumeration proc */
2377   SetLastError(0);
2378   ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
2379   if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2380   {
2381     win_skip("EnumLanguageGroupLocalesA is not implemented\n");
2382     return;
2383   }
2384   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2385       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2386
2387   /* lgrpid too small */
2388   SetLastError(0);
2389   ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
2390   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2391       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2392
2393   /* lgrpid too big */
2394   SetLastError(0);
2395   ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
2396   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2397       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2398
2399   /* dwFlags is reserved */
2400   SetLastError(0);
2401   ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
2402   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2403       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2404
2405   pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2406 }
2407
2408 static void test_SetLocaleInfoA(void)
2409 {
2410   BOOL bRet;
2411   LCID lcid = GetUserDefaultLCID();
2412
2413   /* Null data */
2414   SetLastError(0);
2415   bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2416   ok( !bRet && GetLastError() == ERROR_INVALID_PARAMETER,
2417       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2418
2419   /* IDATE */
2420   SetLastError(0);
2421   bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
2422   ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2423      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2424
2425   /* ILDATE */
2426   SetLastError(0);
2427   bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
2428   ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2429      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2430 }
2431
2432 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2433 {
2434   trace("%s %08lx\n", value, lParam);
2435   return(TRUE);
2436 }
2437
2438 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2439 {
2440   ok(!enumCount, "callback called again unexpected\n");
2441   enumCount++;
2442   return(FALSE);
2443 }
2444
2445 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2446 {
2447   ok(0,"callback called unexpected\n");
2448   return(FALSE);
2449 }
2450
2451 static void test_EnumUILanguageA(void)
2452 {
2453   BOOL ret;
2454   if (!pEnumUILanguagesA) {
2455     win_skip("EnumUILanguagesA is not available on Win9x or NT4\n");
2456     return;
2457   }
2458
2459   SetLastError(ERROR_SUCCESS);
2460   ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2461   if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2462   {
2463     win_skip("EnumUILanguagesA is not implemented\n");
2464     return;
2465   }
2466   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2467
2468   enumCount = 0;
2469   SetLastError(ERROR_SUCCESS);
2470   ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2471   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2472
2473   SetLastError(ERROR_SUCCESS);
2474   ret = pEnumUILanguagesA(NULL, 0, 0);
2475   ok(!ret, "Expected return value FALSE, got %u\n", ret);
2476   ok(GetLastError() == ERROR_INVALID_PARAMETER,
2477       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2478
2479   SetLastError(ERROR_SUCCESS);
2480   ret = pEnumUILanguagesA(luilocale_proc3A, 0x5a5a5a5a, 0);
2481   ok(!ret, "Expected return value FALSE, got %u\n", ret);
2482   ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2483
2484   SetLastError(ERROR_SUCCESS);
2485   ret = pEnumUILanguagesA(NULL, 0x5a5a5a5a, 0);
2486   ok(!ret, "Expected return value FALSE, got %u\n", ret);
2487   ok(GetLastError() == ERROR_INVALID_PARAMETER,
2488       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2489 }
2490
2491 static char date_fmt_buf[1024];
2492
2493 static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
2494 {
2495     lstrcatA(date_fmt_buf, fmt);
2496     lstrcatA(date_fmt_buf, "\n");
2497     return TRUE;
2498 }
2499
2500 static void test_EnumDateFormatsA(void)
2501 {
2502     char *p, buf[256];
2503     BOOL ret;
2504     LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2505
2506     trace("EnumDateFormatsA 0\n");
2507     date_fmt_buf[0] = 0;
2508     SetLastError(0xdeadbeef);
2509     ret = EnumDateFormatsA(enum_datetime_procA, lcid, 0);
2510     if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2511     {
2512         win_skip("0 for dwFlags is not supported\n");
2513     }
2514     else
2515     {
2516         ok(ret, "EnumDateFormatsA(0) error %d\n", GetLastError());
2517         trace("%s\n", date_fmt_buf);
2518         /* test the 1st enumerated format */
2519         if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2520         ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2521         ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2522         ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2523     }
2524
2525     trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n");
2526     date_fmt_buf[0] = 0;
2527     SetLastError(0xdeadbeef);
2528     ret = EnumDateFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2529     if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2530     {
2531         win_skip("LOCALE_USE_CP_ACP is not supported\n");
2532     }
2533     else
2534     {
2535         ok(ret, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2536         trace("%s\n", date_fmt_buf);
2537         /* test the 1st enumerated format */
2538         if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2539         ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2540         ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2541         ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2542     }
2543
2544     trace("EnumDateFormatsA DATE_SHORTDATE\n");
2545     date_fmt_buf[0] = 0;
2546     ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_SHORTDATE);
2547     ok(ret, "EnumDateFormatsA(DATE_SHORTDATE) error %d\n", GetLastError());
2548     trace("%s\n", date_fmt_buf);
2549     /* test the 1st enumerated format */
2550     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2551     ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2552     ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2553     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2554
2555     trace("EnumDateFormatsA DATE_LONGDATE\n");
2556     date_fmt_buf[0] = 0;
2557     ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_LONGDATE);
2558     ok(ret, "EnumDateFormatsA(DATE_LONGDATE) error %d\n", GetLastError());
2559     trace("%s\n", date_fmt_buf);
2560     /* test the 1st enumerated format */
2561     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2562     ret = GetLocaleInfoA(lcid, LOCALE_SLONGDATE, buf, sizeof(buf));
2563     ok(ret, "GetLocaleInfoA(LOCALE_SLONGDATE) error %d\n", GetLastError());
2564     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2565
2566     trace("EnumDateFormatsA DATE_YEARMONTH\n");
2567     date_fmt_buf[0] = 0;
2568     SetLastError(0xdeadbeef);
2569     ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_YEARMONTH);
2570     if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2571     {
2572         skip("DATE_YEARMONTH is only present on W2K and later\n");
2573         return;
2574     }
2575     ok(ret, "EnumDateFormatsA(DATE_YEARMONTH) error %d\n", GetLastError());
2576     trace("%s\n", date_fmt_buf);
2577     /* test the 1st enumerated format */
2578     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2579     ret = GetLocaleInfoA(lcid, LOCALE_SYEARMONTH, buf, sizeof(buf));
2580     ok(ret, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %d\n", GetLastError());
2581     ok(!lstrcmpA(date_fmt_buf, buf) || broken(!buf[0]) /* win9x */,
2582        "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2583 }
2584
2585 static void test_EnumTimeFormatsA(void)
2586 {
2587     char *p, buf[256];
2588     BOOL ret;
2589     LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2590
2591     trace("EnumTimeFormatsA 0\n");
2592     date_fmt_buf[0] = 0;
2593     ret = EnumTimeFormatsA(enum_datetime_procA, lcid, 0);
2594     ok(ret, "EnumTimeFormatsA(0) error %d\n", GetLastError());
2595     trace("%s\n", date_fmt_buf);
2596     /* test the 1st enumerated format */
2597     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2598     ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2599     ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2600     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2601
2602     trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n");
2603     date_fmt_buf[0] = 0;
2604     ret = EnumTimeFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2605     ok(ret, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2606     trace("%s\n", date_fmt_buf);
2607     /* test the 1st enumerated format */
2608     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2609     ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2610     ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2611     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2612 }
2613
2614 static void test_GetCPInfo(void)
2615 {
2616     BOOL ret;
2617     CPINFO cpinfo;
2618
2619     SetLastError(0xdeadbeef);
2620     ret = GetCPInfo(CP_SYMBOL, &cpinfo);
2621     ok(!ret, "GetCPInfo(CP_SYMBOL) should fail\n");
2622     ok(GetLastError() == ERROR_INVALID_PARAMETER,
2623        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2624
2625     SetLastError(0xdeadbeef);
2626     ret = GetCPInfo(CP_UTF7, &cpinfo);
2627     if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2628     {
2629         skip("Codepage CP_UTF7 is not installed/available\n");
2630     }
2631     else
2632     {
2633         ok(ret, "GetCPInfo(CP_UTF7) error %u\n", GetLastError());
2634         ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2635         ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2636         ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2637         ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2638         ok(cpinfo.MaxCharSize == 5, "expected 5, got 0x%x\n", cpinfo.MaxCharSize);
2639     }
2640
2641     SetLastError(0xdeadbeef);
2642     ret = GetCPInfo(CP_UTF8, &cpinfo);
2643     if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2644     {
2645         skip("Codepage CP_UTF8 is not installed/available\n");
2646     }
2647     else
2648     {
2649         ok(ret, "GetCPInfo(CP_UTF8) error %u\n", GetLastError());
2650         ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2651         ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2652         ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2653         ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2654         ok(cpinfo.MaxCharSize == 4 || broken(cpinfo.MaxCharSize == 3) /* win9x */,
2655            "expected 4, got %u\n", cpinfo.MaxCharSize);
2656     }
2657 }
2658
2659 START_TEST(locale)
2660 {
2661   InitFunctionPointers();
2662
2663   test_EnumTimeFormatsA();
2664   test_EnumDateFormatsA();
2665   test_GetLocaleInfoA();
2666   test_GetLocaleInfoW();
2667   test_GetTimeFormatA();
2668   test_GetDateFormatA();
2669   test_GetDateFormatW();
2670   test_GetCurrencyFormatA(); /* Also tests the W version */
2671   test_GetNumberFormatA();   /* Also tests the W version */
2672   test_CompareStringA();
2673   test_LCMapStringA();
2674   test_LCMapStringW();
2675   test_FoldStringA();
2676   test_FoldStringW();
2677   test_ConvertDefaultLocale();
2678   test_EnumSystemLanguageGroupsA();
2679   test_EnumLanguageGroupLocalesA();
2680   test_SetLocaleInfoA();
2681   test_EnumUILanguageA();
2682   test_GetCPInfo();
2683   /* this requires collation table patch to make it MS compatible */
2684   if (0) test_sorting();
2685 }