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