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