winapi: Generate the 64-bit variant of structure size/alignment tests.
[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 = lstrcmpi("#", ".");
1351     todo_wine ok(ret == -1, "\"#\" vs \".\" expected -1, got %d\n", ret);
1352 }
1353
1354 static void test_LCMapStringA(void)
1355 {
1356     int ret, ret2;
1357     char buf[256], buf2[256];
1358     static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
1359     static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
1360     static const char symbols_stripped[] = "justateststring1";
1361
1362     SetLastError(0xdeadbeef);
1363     ret = LCMapStringA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP | LCMAP_LOWERCASE,
1364                        lower_case, -1, buf, sizeof(buf));
1365     ok(ret == lstrlenA(lower_case) + 1,
1366        "ret %d, error %d, expected value %d\n",
1367        ret, GetLastError(), lstrlenA(lower_case) + 1);
1368     ok(!memcmp(buf, lower_case, ret), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1369
1370     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1371                        upper_case, -1, buf, sizeof(buf));
1372     ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1373     ok(GetLastError() == ERROR_INVALID_FLAGS,
1374        "unexpected error code %d\n", GetLastError());
1375
1376     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1377                        upper_case, -1, buf, sizeof(buf));
1378     ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1379     ok(GetLastError() == ERROR_INVALID_FLAGS,
1380        "unexpected error code %d\n", GetLastError());
1381
1382     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1383                        upper_case, -1, buf, sizeof(buf));
1384     ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1385     ok(GetLastError() == ERROR_INVALID_FLAGS,
1386        "unexpected error code %d\n", GetLastError());
1387
1388     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1389                        upper_case, -1, buf, sizeof(buf));
1390     ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1391     ok(GetLastError() == ERROR_INVALID_FLAGS,
1392        "unexpected error code %d\n", GetLastError());
1393
1394     /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1395     SetLastError(0xdeadbeef);
1396     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1397                        upper_case, -1, buf, sizeof(buf));
1398     ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1399     ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1400
1401     /* test LCMAP_LOWERCASE */
1402     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1403                        upper_case, -1, buf, sizeof(buf));
1404     ok(ret == lstrlenA(upper_case) + 1,
1405        "ret %d, error %d, expected value %d\n",
1406        ret, GetLastError(), lstrlenA(upper_case) + 1);
1407     ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1408
1409     /* test LCMAP_UPPERCASE */
1410     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1411                        lower_case, -1, buf, sizeof(buf));
1412     ok(ret == lstrlenA(lower_case) + 1,
1413        "ret %d, error %d, expected value %d\n",
1414        ret, GetLastError(), lstrlenA(lower_case) + 1);
1415     ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1416
1417     /* test buffer overflow */
1418     SetLastError(0xdeadbeef);
1419     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1420                        lower_case, -1, buf, 4);
1421     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1422        "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1423
1424     /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1425     lstrcpyA(buf, lower_case);
1426     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1427                        buf, -1, buf, sizeof(buf));
1428     if (!ret) /* Win9x */
1429         trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1430     else
1431     {
1432         ok(ret == lstrlenA(lower_case) + 1,
1433            "ret %d, error %d, expected value %d\n",
1434            ret, GetLastError(), lstrlenA(lower_case) + 1);
1435         ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1436     }
1437     lstrcpyA(buf, upper_case);
1438     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1439                        buf, -1, buf, sizeof(buf));
1440     if (!ret) /* Win9x */
1441         trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1442     else
1443     {
1444         ok(ret == lstrlenA(upper_case) + 1,
1445            "ret %d, error %d, expected value %d\n",
1446            ret, GetLastError(), lstrlenA(lower_case) + 1);
1447         ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1448     }
1449
1450     /* otherwise src == dst should fail */
1451     SetLastError(0xdeadbeef);
1452     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1453                        buf, 10, buf, sizeof(buf));
1454     ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1455        GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1456        "unexpected error code %d\n", GetLastError());
1457     ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1458
1459     /* test whether '\0' is always appended */
1460     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1461                        upper_case, -1, buf, sizeof(buf));
1462     ok(ret, "LCMapStringA must succeed\n");
1463     ok(buf[ret-1] == 0, "LCMapStringA not null-terminated\n");
1464     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1465                        upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1466     ok(ret2, "LCMapStringA must succeed\n");
1467     ok(buf2[ret2-1] == 0, "LCMapStringA not null-terminated\n" );
1468     ok(ret == ret2, "lengths of sort keys must be equal\n");
1469     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1470
1471     /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1472     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1473                        upper_case, -1, buf, sizeof(buf));
1474     ok(ret, "LCMapStringA must succeed\n");
1475     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1476                        lower_case, -1, buf2, sizeof(buf2));
1477     ok(ret2, "LCMapStringA must succeed\n");
1478     ok(ret == ret2, "lengths of sort keys must be equal\n");
1479     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1480
1481     /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1482        results from plain LCMAP_SORTKEY on Vista */
1483
1484     /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1485     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1486                        lower_case, -1, buf, sizeof(buf));
1487     ok(ret, "LCMapStringA must succeed\n");
1488     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1489                        symbols_stripped, -1, buf2, sizeof(buf2));
1490     ok(ret2, "LCMapStringA must succeed\n");
1491     ok(ret == ret2, "lengths of sort keys must be equal\n");
1492     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1493
1494     /* test NORM_IGNORENONSPACE */
1495     lstrcpyA(buf, "foo");
1496     ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1497                        lower_case, -1, buf, sizeof(buf));
1498     ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1499         lstrlenA(lower_case) + 1, ret);
1500     ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1501
1502     /* test NORM_IGNORESYMBOLS */
1503     lstrcpyA(buf, "foo");
1504     ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1505                        lower_case, -1, buf, sizeof(buf));
1506     ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1507         lstrlenA(symbols_stripped) + 1, ret);
1508     ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1509
1510     /* test srclen = 0 */
1511     SetLastError(0xdeadbeef);
1512     ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1513     ok(!ret, "LCMapStringA should fail with srclen = 0\n");
1514     ok(GetLastError() == ERROR_INVALID_PARAMETER,
1515        "unexpected error code %d\n", GetLastError());
1516 }
1517
1518 static void test_LCMapStringW(void)
1519 {
1520     int ret, ret2;
1521     WCHAR buf[256], buf2[256];
1522     char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1523     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};
1524     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};
1525     static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
1526     static const WCHAR fooW[] = {'f','o','o',0};
1527
1528     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1529                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1530     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1531     {
1532         win_skip("LCMapStringW is not implemented\n");
1533         return;
1534     }
1535     if (broken(ret))
1536         ok(lstrcmpW(buf, upper_case) == 0, "Expected upper case string\n");
1537     else
1538     {
1539         ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1540         ok(GetLastError() == ERROR_INVALID_FLAGS,
1541            "unexpected error code %d\n", GetLastError());
1542     }
1543
1544     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1545                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1546     ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1547     ok(GetLastError() == ERROR_INVALID_FLAGS,
1548        "unexpected error code %d\n", GetLastError());
1549
1550     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1551                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1552     ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1553     ok(GetLastError() == ERROR_INVALID_FLAGS,
1554        "unexpected error code %d\n", GetLastError());
1555
1556     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1557                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1558     ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1559     ok(GetLastError() == ERROR_INVALID_FLAGS,
1560        "unexpected error code %d\n", GetLastError());
1561
1562     /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1563     SetLastError(0xdeadbeef);
1564     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1565                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1566     ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1567     ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1568
1569     /* test LCMAP_LOWERCASE */
1570     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1571                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1572     ok(ret == lstrlenW(upper_case) + 1,
1573        "ret %d, error %d, expected value %d\n",
1574        ret, GetLastError(), lstrlenW(upper_case) + 1);
1575     ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1576
1577     /* test LCMAP_UPPERCASE */
1578     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1579                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1580     ok(ret == lstrlenW(lower_case) + 1,
1581        "ret %d, error %d, expected value %d\n",
1582        ret, GetLastError(), lstrlenW(lower_case) + 1);
1583     ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1584
1585     /* test buffer overflow */
1586     SetLastError(0xdeadbeef);
1587     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1588                        lower_case, -1, buf, 4);
1589     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1590        "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1591
1592     /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1593     lstrcpyW(buf, lower_case);
1594     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1595                        buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1596     ok(ret == lstrlenW(lower_case) + 1,
1597        "ret %d, error %d, expected value %d\n",
1598        ret, GetLastError(), lstrlenW(lower_case) + 1);
1599     ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1600
1601     lstrcpyW(buf, upper_case);
1602     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1603                        buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1604     ok(ret == lstrlenW(upper_case) + 1,
1605        "ret %d, error %d, expected value %d\n",
1606        ret, GetLastError(), lstrlenW(lower_case) + 1);
1607     ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1608
1609     /* otherwise src == dst should fail */
1610     SetLastError(0xdeadbeef);
1611     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1612                        buf, 10, buf, sizeof(buf));
1613     ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1614        GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1615        "unexpected error code %d\n", GetLastError());
1616     ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1617
1618     /* test whether '\0' is always appended */
1619     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1620                        upper_case, -1, buf, sizeof(buf));
1621     ok(ret, "LCMapStringW must succeed\n");
1622     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1623                        upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1624     ok(ret, "LCMapStringW must succeed\n");
1625     ok(ret == ret2, "lengths of sort keys must be equal\n");
1626     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1627
1628     /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1629     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1630                        upper_case, -1, buf, sizeof(buf));
1631     ok(ret, "LCMapStringW must succeed\n");
1632     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1633                        lower_case, -1, buf2, sizeof(buf2));
1634     ok(ret2, "LCMapStringW must succeed\n");
1635     ok(ret == ret2, "lengths of sort keys must be equal\n");
1636     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1637
1638     /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1639        results from plain LCMAP_SORTKEY on Vista */
1640
1641     /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1642     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1643                        lower_case, -1, buf, sizeof(buf));
1644     ok(ret, "LCMapStringW must succeed\n");
1645     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1646                        symbols_stripped, -1, buf2, sizeof(buf2));
1647     ok(ret2, "LCMapStringW must succeed\n");
1648     ok(ret == ret2, "lengths of sort keys must be equal\n");
1649     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1650
1651     /* test NORM_IGNORENONSPACE */
1652     lstrcpyW(buf, fooW);
1653     ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1654                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1655     ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1656         lstrlenW(lower_case) + 1, ret);
1657     ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1658
1659     /* test NORM_IGNORESYMBOLS */
1660     lstrcpyW(buf, fooW);
1661     ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1662                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1663     ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1664         lstrlenW(symbols_stripped) + 1, ret);
1665     ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1666
1667     /* test srclen = 0 */
1668     SetLastError(0xdeadbeef);
1669     ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf)/sizeof(WCHAR));
1670     ok(!ret, "LCMapStringW should fail with srclen = 0\n");
1671     ok(GetLastError() == ERROR_INVALID_PARAMETER,
1672        "unexpected error code %d\n", GetLastError());
1673 }
1674
1675 /* this requires collation table patch to make it MS compatible */
1676 static const char * const strings_sorted[] =
1677 {
1678 "'",
1679 "-",
1680 "!",
1681 "\"",
1682 ".",
1683 ":",
1684 "\\",
1685 "_",
1686 "`",
1687 "{",
1688 "}",
1689 "+",
1690 "0",
1691 "1",
1692 "2",
1693 "3",
1694 "4",
1695 "5",
1696 "6",
1697 "7",
1698 "8",
1699 "9",
1700 "a",
1701 "A",
1702 "b",
1703 "B",
1704 "c",
1705 "C"
1706 };
1707
1708 static const char * const strings[] =
1709 {
1710 "C",
1711 "\"",
1712 "9",
1713 "'",
1714 "}",
1715 "-",
1716 "7",
1717 "+",
1718 "`",
1719 "1",
1720 "a",
1721 "5",
1722 "\\",
1723 "8",
1724 "B",
1725 "3",
1726 "_",
1727 "6",
1728 "{",
1729 "2",
1730 "c",
1731 "4",
1732 "!",
1733 "0",
1734 "A",
1735 ":",
1736 "b",
1737 "."
1738 };
1739
1740 static int compare_string1(const void *e1, const void *e2)
1741 {
1742     const char *s1 = *(const char *const *)e1;
1743     const char *s2 = *(const char *const *)e2;
1744
1745     return lstrcmpA(s1, s2);
1746 }
1747
1748 static int compare_string2(const void *e1, const void *e2)
1749 {
1750     const char *s1 = *(const char *const *)e1;
1751     const char *s2 = *(const char *const *)e2;
1752
1753     return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1754 }
1755
1756 static int compare_string3(const void *e1, const void *e2)
1757 {
1758     const char *s1 = *(const char *const *)e1;
1759     const char *s2 = *(const char *const *)e2;
1760     char key1[256], key2[256];
1761
1762     LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
1763     LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
1764     return strcmp(key1, key2);
1765 }
1766
1767 static void test_sorting(void)
1768 {
1769     char buf[256];
1770     char **str_buf = (char **)buf;
1771     int i;
1772
1773     assert(sizeof(buf) >= sizeof(strings));
1774
1775     /* 1. sort using lstrcmpA */
1776     memcpy(buf, strings, sizeof(strings));
1777     qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
1778     for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1779     {
1780         ok(!strcmp(strings_sorted[i], str_buf[i]),
1781            "qsort using lstrcmpA failed for element %d\n", i);
1782     }
1783     /* 2. sort using CompareStringA */
1784     memcpy(buf, strings, sizeof(strings));
1785     qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
1786     for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1787     {
1788         ok(!strcmp(strings_sorted[i], str_buf[i]),
1789            "qsort using CompareStringA failed for element %d\n", i);
1790     }
1791     /* 3. sort using sort keys */
1792     memcpy(buf, strings, sizeof(strings));
1793     qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
1794     for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1795     {
1796         ok(!strcmp(strings_sorted[i], str_buf[i]),
1797            "qsort using sort keys failed for element %d\n", i);
1798     }
1799 }
1800
1801 static void test_FoldStringA(void)
1802 {
1803   int ret, i, j;
1804   BOOL is_special;
1805   char src[256], dst[256];
1806   static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0'  };
1807   static const char digits_dst[] = { '1','2','3','\0'  };
1808   static const char composite_src[] =
1809   {
1810     0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
1811     0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
1812     0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
1813     0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
1814     0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
1815     0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
1816     0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
1817     0xfb,0xfc,0xfd,0xff,'\0'
1818   };
1819   static const char composite_dst[] =
1820   {
1821     0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1822     0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1823     0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1824     0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1825     0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1826     0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1827     0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
1828     0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
1829     0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
1830     0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
1831     0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
1832     0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
1833     0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
1834     0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
1835     0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1836   };
1837   static const char composite_dst_alt[] =
1838   {
1839     0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1840     0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1841     0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1842     0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1843     0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1844     0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1845     0x4f,0x7e,0x4f,0xa8,0xd8,0x55,0x60,0x55,
1846     0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,0x61,
1847     0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,0x61,
1848     0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,0x65,
1849     0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,0x69,
1850     0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,0x6f,
1851     0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,0x6f,
1852     0xa8,0xf8,0x75,0x60,0x75,0xb4,0x75,0x5e,
1853     0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1854   };
1855   static const char ligatures_src[] =
1856   {
1857     0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1858   };
1859   static const char ligatures_dst[] =
1860   {
1861     'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1862   };
1863   static const struct special
1864   {
1865     char src;
1866     char dst[4];
1867   }  foldczone_special[] =
1868   {
1869     /* src   dst                   */
1870     { 0x85, { 0x2e, 0x2e, 0x2e, 0x00 } },
1871     { 0x98, { 0x20, 0x7e, 0x00 } },
1872     { 0x99, { 0x54, 0x4d, 0x00 } },
1873     { 0xa0, { 0x20, 0x00 } },
1874     { 0xa8, { 0x20, 0xa8, 0x00 } },
1875     { 0xaa, { 0x61, 0x00 } },
1876     { 0xaf, { 0x20, 0xaf, 0x00 } },
1877     { 0xb2, { 0x32, 0x00 } },
1878     { 0xb3, { 0x33, 0x00 } },
1879     { 0xb4, { 0x20, 0xb4, 0x00 } },
1880     { 0xb8, { 0x20, 0xb8, 0x00 } },
1881     { 0xb9, { 0x31, 0x00 } },
1882     { 0xba, { 0x6f, 0x00 } },
1883     { 0xbc, { 0x31, 0x2f, 0x34, 0x00 } },
1884     { 0xbd, { 0x31, 0x2f, 0x32, 0x00 } },
1885     { 0xbe, { 0x33, 0x2f, 0x34, 0x00 } },
1886     { 0x00 }
1887   };
1888
1889   if (!pFoldStringA)
1890     return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1891
1892   /* these tests are locale specific */
1893   if (GetACP() != 1252)
1894   {
1895       trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1896       return;
1897   }
1898
1899   /* MAP_FOLDDIGITS */
1900   SetLastError(0);
1901   ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
1902   if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1903   {
1904     win_skip("FoldStringA is not implemented\n");
1905     return;
1906   }
1907   ok(ret == 4, "Expected ret == 4, got %d, error %d\n", ret, GetLastError());
1908   ok(strcmp(dst, digits_dst) == 0,
1909      "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
1910   for (i = 1; i < 256; i++)
1911   {
1912     if (!strchr(digits_src, i))
1913     {
1914       src[0] = i;
1915       src[1] = '\0';
1916       SetLastError(0);
1917       ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
1918       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1919       ok(dst[0] == src[0],
1920          "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
1921     }
1922   }
1923
1924   /* MAP_EXPAND_LIGATURES */
1925   SetLastError(0);
1926   ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1927   /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1928   if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
1929     ok(ret == sizeof(ligatures_dst), "Got %d, error %d\n", ret, GetLastError());
1930     ok(strcmp(dst, ligatures_dst) == 0,
1931        "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
1932     for (i = 1; i < 256; i++)
1933     {
1934       if (!strchr(ligatures_src, i))
1935       {
1936         src[0] = i;
1937         src[1] = '\0';
1938         SetLastError(0);
1939         ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1940         if (ret == 3)
1941         {
1942           /* Vista */
1943           ok((i == 0xDC && lstrcmpA(dst, "UE") == 0) ||
1944              (i == 0xFC && lstrcmpA(dst, "ue") == 0),
1945              "Got %s for %d\n", dst, i);
1946         }
1947         else
1948         {
1949           ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1950           ok(dst[0] == src[0],
1951              "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
1952         }
1953       }
1954     }
1955   }
1956
1957   /* MAP_COMPOSITE */
1958   SetLastError(0);
1959   ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
1960   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1961   ok(ret == 121 || ret == 119, "Expected 121 or 119, got %d\n", ret);
1962   ok(strcmp(dst, composite_dst) == 0 || strcmp(dst, composite_dst_alt) == 0,
1963      "MAP_COMPOSITE: Mismatch, got '%s'\n", dst);
1964
1965   for (i = 1; i < 256; i++)
1966   {
1967     if (!strchr(composite_src, i))
1968     {
1969       src[0] = i;
1970       src[1] = '\0';
1971       SetLastError(0);
1972       ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
1973       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
1974       ok(dst[0] == src[0],
1975          "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
1976          (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
1977     }
1978   }
1979
1980   /* MAP_FOLDCZONE */
1981   for (i = 1; i < 256; i++)
1982   {
1983     src[0] = i;
1984     src[1] = '\0';
1985     SetLastError(0);
1986     ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
1987     is_special = FALSE;
1988     for (j = 0; foldczone_special[j].src != 0 && ! is_special; j++)
1989     {
1990       if (foldczone_special[j].src == src[0])
1991       {
1992         ok(ret == 2 || ret == lstrlenA(foldczone_special[j].dst) + 1,
1993            "Expected ret == 2 or %d, got %d, error %d\n",
1994            lstrlenA(foldczone_special[j].dst) + 1, ret, GetLastError());
1995         ok(src[0] == dst[0] || lstrcmpA(foldczone_special[j].dst, dst) == 0,
1996            "MAP_FOLDCZONE: string mismatch for 0x%02x\n",
1997            (unsigned char)src[0]);
1998         is_special = TRUE;
1999       }
2000     }
2001     if (! is_special)
2002     {
2003       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2004       ok(src[0] == dst[0],
2005          "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
2006          (unsigned char)src[0], (unsigned char)dst[0]);
2007     }
2008   }
2009
2010   /* MAP_PRECOMPOSED */
2011   for (i = 1; i < 256; i++)
2012   {
2013     src[0] = i;
2014     src[1] = '\0';
2015     SetLastError(0);
2016     ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
2017     ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2018     ok(src[0] == dst[0],
2019        "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
2020        (unsigned char)src[0], (unsigned char)dst[0]);
2021   }
2022 }
2023
2024 static void test_FoldStringW(void)
2025 {
2026   int ret;
2027   unsigned int i, j;
2028   WCHAR src[256], dst[256], ch, prev_ch = 1;
2029   static const DWORD badFlags[] =
2030   {
2031     0,
2032     MAP_PRECOMPOSED|MAP_COMPOSITE,
2033     MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
2034     MAP_COMPOSITE|MAP_EXPAND_LIGATURES
2035   };
2036   /* Ranges of digits 0-9 : Must be sorted! */
2037   static const WCHAR digitRanges[] =
2038   {
2039     0x0030, /* '0'-'9' */
2040     0x0660, /* Eastern Arabic */
2041     0x06F0, /* Arabic - Hindu */
2042     0x0966, /* Devengari */
2043     0x09E6, /* Bengalii */
2044     0x0A66, /* Gurmukhi */
2045     0x0AE6, /* Gujarati */
2046     0x0B66, /* Oriya */
2047     0x0BE6, /* Tamil - No 0 */
2048     0x0C66, /* Telugu */
2049     0x0CE6, /* Kannada */
2050     0x0D66, /* Maylayalam */
2051     0x0E50, /* Thai */
2052     0x0ED0, /* Laos */
2053     0x0F29, /* Tibet - 0 is out of sequence */
2054     0x2070, /* Superscript - 1, 2, 3 are out of sequence */
2055     0x2080, /* Subscript */
2056     0x245F, /* Circled - 0 is out of sequence */
2057     0x2473, /* Bracketed */
2058     0x2487, /* Full stop */
2059     0x2775, /* Inverted circled - No 0 */
2060     0x277F, /* Patterned circled - No 0 */
2061     0x2789, /* Inverted Patterned circled - No 0 */
2062     0x3020, /* Hangzhou */
2063     0xff10, /* Pliene chasse (?) */
2064     0xffff  /* Terminator */
2065   };
2066   /* Digits which are represented, but out of sequence */
2067   static const WCHAR outOfSequenceDigits[] =
2068   {
2069       0xB9,   /* Superscript 1 */
2070       0xB2,   /* Superscript 2 */
2071       0xB3,   /* Superscript 3 */
2072       0x0F33, /* Tibetan half zero */
2073       0x24EA, /* Circled 0 */
2074       0x3007, /* Ideographic number zero */
2075       '\0'    /* Terminator */
2076   };
2077   /* Digits in digitRanges for which no representation is available */
2078   static const WCHAR noDigitAvailable[] =
2079   {
2080       0x0BE6, /* No Tamil 0 */
2081       0x0F29, /* No Tibetan half zero (out of sequence) */
2082       0x2473, /* No Bracketed 0 */
2083       0x2487, /* No 0 Full stop */
2084       0x2775, /* No inverted circled 0 */
2085       0x277F, /* No patterned circled */
2086       0x2789, /* No inverted Patterned circled */
2087       0x3020, /* No Hangzhou 0 */
2088       '\0'    /* Terminator */
2089   };
2090   static const WCHAR foldczone_src[] =
2091   {
2092     'W',    'i',    'n',    'e',    0x0348, 0x0551, 0x1323, 0x280d,
2093     0xff37, 0xff49, 0xff4e, 0xff45, '\0'
2094   };
2095   static const WCHAR foldczone_dst[] =
2096   {
2097     'W','i','n','e',0x0348,0x0551,0x1323,0x280d,'W','i','n','e','\0'
2098   };
2099   static const WCHAR ligatures_src[] =
2100   {
2101     'W',    'i',    'n',    'e',    0x03a6, 0x03b9, 0x03bd, 0x03b5,
2102     0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
2103     0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
2104     0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
2105     0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
2106     0xfb04, 0xfb05, 0xfb06, '\0'
2107   };
2108   static const WCHAR ligatures_dst[] =
2109   {
2110     'W','i','n','e',0x03a6,0x03b9,0x03bd,0x03b5,
2111     'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
2112     'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
2113     'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
2114     0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
2115     'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
2116   };
2117
2118   if (!pFoldStringW)
2119   {
2120     win_skip("FoldStringW is not available\n");
2121     return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
2122   }
2123
2124   /* Invalid flag combinations */
2125   for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
2126   {
2127     src[0] = dst[0] = '\0';
2128     SetLastError(0);
2129     ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
2130     if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
2131     {
2132       win_skip("FoldStringW is not implemented\n");
2133       return;
2134     }
2135     ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
2136        "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2137   }
2138
2139   /* src & dst cannot be the same */
2140   SetLastError(0);
2141   ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
2142   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2143       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2144
2145   /* src can't be NULL */
2146   SetLastError(0);
2147   ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
2148   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2149       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2150
2151   /* srclen can't be 0 */
2152   SetLastError(0);
2153   ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
2154   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2155       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2156
2157   /* dstlen can't be < 0 */
2158   SetLastError(0);
2159   ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
2160   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2161       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2162
2163   /* Ret includes terminating NUL which is appended if srclen = -1 */
2164   SetLastError(0);
2165   src[0] = 'A';
2166   src[1] = '\0';
2167   dst[0] = '\0';
2168   ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
2169   ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2170   ok(dst[0] == 'A' && dst[1] == '\0',
2171      "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%d\n",
2172      'A', '\0', ret, dst[0], dst[1], GetLastError());
2173
2174   /* If size is given, result is not NUL terminated */
2175   SetLastError(0);
2176   src[0] = 'A';
2177   src[1] = 'A';
2178   dst[0] = 'X';
2179   dst[1] = 'X';
2180   ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
2181   ok(ret == 1, "Expected ret == 1, got %d, error %d\n", ret, GetLastError());
2182   ok(dst[0] == 'A' && dst[1] == 'X',
2183      "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%d\n",
2184      'A','X', ret, dst[0], dst[1], GetLastError());
2185
2186   /* MAP_FOLDDIGITS */
2187   for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
2188   {
2189     /* Check everything before this range */
2190     for (ch = prev_ch; ch < digitRanges[j]; ch++)
2191     {
2192       SetLastError(0);
2193       src[0] = ch;
2194       src[1] = dst[0] = '\0';
2195       ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2196       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2197
2198       ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
2199          /* Wine (correctly) maps all Unicode 4.0+ digits */
2200          isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF ||
2201          (ch >= 0x1369 && ch <= 0x1371),
2202          "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
2203     }
2204
2205     if (digitRanges[j] == 0xffff)
2206       break; /* Finished the whole code point space */
2207
2208     for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
2209     {
2210       WCHAR c;
2211
2212       /* Map out of sequence characters */
2213       if      (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
2214       else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
2215       else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
2216       else if (ch == 0x245F) c = 0x24EA; /* Circled 0     */
2217       else                   c = ch;
2218       SetLastError(0);
2219       src[0] = c;
2220       src[1] = dst[0] = '\0';
2221       ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2222       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2223
2224       ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
2225          broken( dst[0] == ch ) ||  /* old Windows versions don't have all mappings */
2226          (digitRanges[j] == 0x3020 && dst[0] == ch) || /* Hangzhou not present in all Windows versions */
2227          (digitRanges[j] == 0x0F29 && dst[0] == ch) || /* Tibetan not present in all Windows versions */
2228          strchrW(noDigitAvailable, c),
2229          "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
2230          ch, '0' + digitRanges[j] - ch, dst[0]);
2231     }
2232     prev_ch = ch;
2233   }
2234
2235   /* MAP_FOLDCZONE */
2236   SetLastError(0);
2237   ret = pFoldStringW(MAP_FOLDCZONE, foldczone_src, -1, dst, 256);
2238   ok(ret == sizeof(foldczone_dst)/sizeof(foldczone_dst[0]),
2239      "Got %d, error %d\n", ret, GetLastError());
2240   ok(!memcmp(dst, foldczone_dst, sizeof(foldczone_dst)),
2241      "MAP_FOLDCZONE: Expanded incorrectly\n");
2242
2243   /* MAP_EXPAND_LIGATURES */
2244   SetLastError(0);
2245   ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
2246   /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
2247   if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
2248     ok(ret == sizeof(ligatures_dst)/sizeof(ligatures_dst[0]),
2249        "Got %d, error %d\n", ret, GetLastError());
2250     ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
2251        "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
2252   }
2253
2254   /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
2255 }
2256
2257
2258
2259 #define LCID_OK(l) \
2260   ok(lcid == l, "Expected lcid = %08x, got %08x\n", l, lcid)
2261 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
2262 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
2263 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
2264 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
2265
2266 static void test_ConvertDefaultLocale(void)
2267 {
2268   LCID lcid;
2269
2270   /* Doesn't change lcid, even if non default sublang/sort used */
2271   TEST_LCID(LANG_ENGLISH,  SUBLANG_ENGLISH_US, SORT_DEFAULT);
2272   TEST_LCID(LANG_ENGLISH,  SUBLANG_ENGLISH_UK, SORT_DEFAULT);
2273   TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT,    SORT_DEFAULT);
2274   TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT,    SORT_JAPANESE_UNICODE);
2275
2276   /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
2277   LCID_RES(MKLCID(LANG_ENGLISH,  SUBLANG_NEUTRAL, SORT_DEFAULT),
2278            MKLCID(LANG_ENGLISH,  SUBLANG_DEFAULT, SORT_DEFAULT));
2279   LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
2280            MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
2281
2282   /* Invariant language is not treated specially */
2283   TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
2284
2285   /* User/system default languages alone are not mapped */
2286   TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
2287   TEST_LCIDLANG(LANG_USER_DEFAULT,   SORT_JAPANESE_UNICODE);
2288
2289   /* Default lcids */
2290   LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
2291   LCID_RES(LOCALE_USER_DEFAULT,   GetUserDefaultLCID());
2292   LCID_RES(LOCALE_NEUTRAL,        GetUserDefaultLCID());
2293 }
2294
2295 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
2296                                     DWORD dwFlags, LONG_PTR lParam)
2297 {
2298   trace("%08x, %s, %s, %08x, %08lx\n",
2299         lgrpid, lpszNum, lpszName, dwFlags, lParam);
2300
2301   ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
2302      "Enumerated grp %d not valid (flags %d)\n", lgrpid, dwFlags);
2303
2304   /* If lParam is one, we are calling with flags defaulted from 0 */
2305   ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
2306          "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %d\n", dwFlags);
2307
2308   return TRUE;
2309 }
2310
2311 static void test_EnumSystemLanguageGroupsA(void)
2312 {
2313   BOOL ret;
2314
2315   if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
2316   {
2317     win_skip("EnumSystemLanguageGroupsA and/or IsValidLanguageGroup are not available\n");
2318     return;
2319   }
2320
2321   /* No enumeration proc */
2322   SetLastError(0);
2323   ret = pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
2324   if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2325   {
2326     win_skip("EnumSystemLanguageGroupsA is not implemented\n");
2327     return;
2328   }
2329   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2330       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2331
2332   /* Invalid flags */
2333   SetLastError(0);
2334   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
2335   ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2336
2337   /* No flags - defaults to LGRPID_INSTALLED */
2338   SetLastError(0xdeadbeef);
2339   pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
2340   ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
2341
2342   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
2343   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
2344 }
2345
2346
2347 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
2348                                       LONG_PTR lParam)
2349 {
2350   trace("%08x, %08x, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
2351
2352   /* invalid locale enumerated on some platforms */
2353   if (lcid == 0)
2354       return TRUE;
2355
2356   ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
2357      "Enumerated grp %d not valid\n", lgrpid);
2358   ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
2359      "Enumerated grp locale %d not valid\n", lcid);
2360   return TRUE;
2361 }
2362
2363 static void test_EnumLanguageGroupLocalesA(void)
2364 {
2365   BOOL ret;
2366
2367   if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
2368   {
2369     win_skip("EnumLanguageGroupLocalesA and/or IsValidLanguageGroup are not available\n");
2370     return;
2371   }
2372
2373   /* No enumeration proc */
2374   SetLastError(0);
2375   ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
2376   if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2377   {
2378     win_skip("EnumLanguageGroupLocalesA is not implemented\n");
2379     return;
2380   }
2381   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2382       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2383
2384   /* lgrpid too small */
2385   SetLastError(0);
2386   ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
2387   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2388       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2389
2390   /* lgrpid too big */
2391   SetLastError(0);
2392   ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
2393   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2394       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2395
2396   /* dwFlags is reserved */
2397   SetLastError(0);
2398   ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
2399   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2400       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2401
2402   pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2403 }
2404
2405 static void test_SetLocaleInfoA(void)
2406 {
2407   BOOL bRet;
2408   LCID lcid = GetUserDefaultLCID();
2409
2410   /* Null data */
2411   SetLastError(0);
2412   bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2413   ok( !bRet && GetLastError() == ERROR_INVALID_PARAMETER,
2414       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2415
2416   /* IDATE */
2417   SetLastError(0);
2418   bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
2419   ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2420      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2421
2422   /* ILDATE */
2423   SetLastError(0);
2424   bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
2425   ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2426      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2427 }
2428
2429 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2430 {
2431   trace("%s %08lx\n", value, lParam);
2432   return(TRUE);
2433 }
2434
2435 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2436 {
2437   ok(!enumCount, "callback called again unexpected\n");
2438   enumCount++;
2439   return(FALSE);
2440 }
2441
2442 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2443 {
2444   ok(0,"callback called unexpected\n");
2445   return(FALSE);
2446 }
2447
2448 static void test_EnumUILanguageA(void)
2449 {
2450   BOOL ret;
2451   if (!pEnumUILanguagesA) {
2452     win_skip("EnumUILanguagesA is not available on Win9x or NT4\n");
2453     return;
2454   }
2455
2456   SetLastError(ERROR_SUCCESS);
2457   ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2458   if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2459   {
2460     win_skip("EnumUILanguagesA is not implemented\n");
2461     return;
2462   }
2463   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2464
2465   enumCount = 0;
2466   SetLastError(ERROR_SUCCESS);
2467   ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2468   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2469
2470   SetLastError(ERROR_SUCCESS);
2471   ret = pEnumUILanguagesA(NULL, 0, 0);
2472   ok(!ret, "Expected return value FALSE, got %u\n", ret);
2473   ok(GetLastError() == ERROR_INVALID_PARAMETER,
2474       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2475
2476   SetLastError(ERROR_SUCCESS);
2477   ret = pEnumUILanguagesA(luilocale_proc3A, 0x5a5a5a5a, 0);
2478   ok(!ret, "Expected return value FALSE, got %u\n", ret);
2479   ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2480
2481   SetLastError(ERROR_SUCCESS);
2482   ret = pEnumUILanguagesA(NULL, 0x5a5a5a5a, 0);
2483   ok(!ret, "Expected return value FALSE, got %u\n", ret);
2484   ok(GetLastError() == ERROR_INVALID_PARAMETER,
2485       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2486 }
2487
2488 static char date_fmt_buf[1024];
2489
2490 static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
2491 {
2492     lstrcatA(date_fmt_buf, fmt);
2493     lstrcatA(date_fmt_buf, "\n");
2494     return TRUE;
2495 }
2496
2497 static void test_EnumDateFormatsA(void)
2498 {
2499     char *p, buf[256];
2500     BOOL ret;
2501     LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2502
2503     trace("EnumDateFormatsA 0\n");
2504     date_fmt_buf[0] = 0;
2505     SetLastError(0xdeadbeef);
2506     ret = EnumDateFormatsA(enum_datetime_procA, lcid, 0);
2507     if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2508     {
2509         win_skip("0 for dwFlags is not supported\n");
2510     }
2511     else
2512     {
2513         ok(ret, "EnumDateFormatsA(0) error %d\n", GetLastError());
2514         trace("%s\n", date_fmt_buf);
2515         /* test the 1st enumerated format */
2516         if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2517         ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2518         ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2519         ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2520     }
2521
2522     trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n");
2523     date_fmt_buf[0] = 0;
2524     SetLastError(0xdeadbeef);
2525     ret = EnumDateFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2526     if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2527     {
2528         win_skip("LOCALE_USE_CP_ACP is not supported\n");
2529     }
2530     else
2531     {
2532         ok(ret, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2533         trace("%s\n", date_fmt_buf);
2534         /* test the 1st enumerated format */
2535         if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2536         ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2537         ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2538         ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2539     }
2540
2541     trace("EnumDateFormatsA DATE_SHORTDATE\n");
2542     date_fmt_buf[0] = 0;
2543     ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_SHORTDATE);
2544     ok(ret, "EnumDateFormatsA(DATE_SHORTDATE) error %d\n", GetLastError());
2545     trace("%s\n", date_fmt_buf);
2546     /* test the 1st enumerated format */
2547     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2548     ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2549     ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2550     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2551
2552     trace("EnumDateFormatsA DATE_LONGDATE\n");
2553     date_fmt_buf[0] = 0;
2554     ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_LONGDATE);
2555     ok(ret, "EnumDateFormatsA(DATE_LONGDATE) error %d\n", GetLastError());
2556     trace("%s\n", date_fmt_buf);
2557     /* test the 1st enumerated format */
2558     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2559     ret = GetLocaleInfoA(lcid, LOCALE_SLONGDATE, buf, sizeof(buf));
2560     ok(ret, "GetLocaleInfoA(LOCALE_SLONGDATE) error %d\n", GetLastError());
2561     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2562
2563     trace("EnumDateFormatsA DATE_YEARMONTH\n");
2564     date_fmt_buf[0] = 0;
2565     SetLastError(0xdeadbeef);
2566     ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_YEARMONTH);
2567     if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2568     {
2569         skip("DATE_YEARMONTH is only present on W2K and later\n");
2570         return;
2571     }
2572     ok(ret, "EnumDateFormatsA(DATE_YEARMONTH) error %d\n", GetLastError());
2573     trace("%s\n", date_fmt_buf);
2574     /* test the 1st enumerated format */
2575     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2576     ret = GetLocaleInfoA(lcid, LOCALE_SYEARMONTH, buf, sizeof(buf));
2577     ok(ret, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %d\n", GetLastError());
2578     ok(!lstrcmpA(date_fmt_buf, buf) || broken(!buf[0]) /* win9x */,
2579        "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2580 }
2581
2582 static void test_EnumTimeFormatsA(void)
2583 {
2584     char *p, buf[256];
2585     BOOL ret;
2586     LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2587
2588     trace("EnumTimeFormatsA 0\n");
2589     date_fmt_buf[0] = 0;
2590     ret = EnumTimeFormatsA(enum_datetime_procA, lcid, 0);
2591     ok(ret, "EnumTimeFormatsA(0) error %d\n", GetLastError());
2592     trace("%s\n", date_fmt_buf);
2593     /* test the 1st enumerated format */
2594     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2595     ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2596     ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2597     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2598
2599     trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n");
2600     date_fmt_buf[0] = 0;
2601     ret = EnumTimeFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2602     ok(ret, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2603     trace("%s\n", date_fmt_buf);
2604     /* test the 1st enumerated format */
2605     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2606     ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2607     ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2608     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2609 }
2610
2611 static void test_GetCPInfo(void)
2612 {
2613     BOOL ret;
2614     CPINFO cpinfo;
2615
2616     SetLastError(0xdeadbeef);
2617     ret = GetCPInfo(CP_SYMBOL, &cpinfo);
2618     ok(!ret, "GetCPInfo(CP_SYMBOL) should fail\n");
2619     ok(GetLastError() == ERROR_INVALID_PARAMETER,
2620        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2621
2622     SetLastError(0xdeadbeef);
2623     ret = GetCPInfo(CP_UTF7, &cpinfo);
2624     if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2625     {
2626         skip("Codepage CP_UTF7 is not installed/available\n");
2627     }
2628     else
2629     {
2630         ok(ret, "GetCPInfo(CP_UTF7) error %u\n", GetLastError());
2631         ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2632         ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2633         ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2634         ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2635         ok(cpinfo.MaxCharSize == 5, "expected 5, got 0x%x\n", cpinfo.MaxCharSize);
2636     }
2637
2638     SetLastError(0xdeadbeef);
2639     ret = GetCPInfo(CP_UTF8, &cpinfo);
2640     if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2641     {
2642         skip("Codepage CP_UTF8 is not installed/available\n");
2643     }
2644     else
2645     {
2646         ok(ret, "GetCPInfo(CP_UTF8) error %u\n", GetLastError());
2647         ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2648         ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2649         ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2650         ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2651         ok(cpinfo.MaxCharSize == 4 || broken(cpinfo.MaxCharSize == 3) /* win9x */,
2652            "expected 4, got %u\n", cpinfo.MaxCharSize);
2653     }
2654 }
2655
2656 START_TEST(locale)
2657 {
2658   InitFunctionPointers();
2659
2660   test_EnumTimeFormatsA();
2661   test_EnumDateFormatsA();
2662   test_GetLocaleInfoA();
2663   test_GetLocaleInfoW();
2664   test_GetTimeFormatA();
2665   test_GetDateFormatA();
2666   test_GetDateFormatW();
2667   test_GetCurrencyFormatA(); /* Also tests the W version */
2668   test_GetNumberFormatA();   /* Also tests the W version */
2669   test_CompareStringA();
2670   test_LCMapStringA();
2671   test_LCMapStringW();
2672   test_FoldStringA();
2673   test_FoldStringW();
2674   test_ConvertDefaultLocale();
2675   test_EnumSystemLanguageGroupsA();
2676   test_EnumLanguageGroupLocalesA();
2677   test_SetLocaleInfoA();
2678   test_EnumUILanguageA();
2679   test_GetCPInfo();
2680   /* this requires collation table patch to make it MS compatible */
2681   if (0) test_sorting();
2682 }