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