wined3d: Recognize Nvidia GT520 cards.
[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 const WCHAR upper_case[] = {'\t','J','U','S','T','!',' ','A',',',' ','T','E','S','T',';',' ','S','T','R','I','N','G',' ','1','/','*','+','-','.','\r','\n',0};
40 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};
41 static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
42 static const WCHAR fooW[] = {'f','o','o',0};
43
44 static inline unsigned int strlenW( const WCHAR *str )
45 {
46     const WCHAR *s = str;
47     while (*s) s++;
48     return s - str;
49 }
50
51 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
52 {
53     if (n <= 0) return 0;
54     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
55     return *str1 - *str2;
56 }
57
58 static inline WCHAR *strchrW( const WCHAR *str, WCHAR ch )
59 {
60     do { if (*str == ch) return (WCHAR *)str; } while (*str++);
61     return NULL;
62 }
63
64 static inline int isdigitW( WCHAR wc )
65 {
66     WORD type;
67     GetStringTypeW( CT_CTYPE1, &wc, 1, &type );
68     return type & C1_DIGIT;
69 }
70
71 /* Some functions are only in later versions of kernel32.dll */
72 static HMODULE hKernel32;
73 static WORD enumCount;
74
75 static BOOL (WINAPI *pEnumSystemLanguageGroupsA)(LANGUAGEGROUP_ENUMPROC, DWORD, LONG_PTR);
76 static BOOL (WINAPI *pEnumLanguageGroupLocalesA)(LANGGROUPLOCALE_ENUMPROC, LGRPID, DWORD, LONG_PTR);
77 static BOOL (WINAPI *pEnumUILanguagesA)(UILANGUAGE_ENUMPROC, DWORD, LONG_PTR);
78 static BOOL (WINAPI *pEnumSystemLocalesEx)(LOCALE_ENUMPROCEX, DWORD, LPARAM, LPVOID);
79 static INT (WINAPI *pLCMapStringEx)(LPCWSTR, DWORD, LPCWSTR, INT, LPWSTR, INT, LPNLSVERSIONINFO, LPVOID, LPARAM);
80 static LCID (WINAPI *pLocaleNameToLCID)(LPCWSTR, DWORD);
81 static INT  (WINAPI *pLCIDToLocaleName)(LCID, LPWSTR, INT, DWORD);
82 static INT (WINAPI *pFoldStringA)(DWORD, LPCSTR, INT, LPSTR, INT);
83 static INT (WINAPI *pFoldStringW)(DWORD, LPCWSTR, INT, LPWSTR, INT);
84 static BOOL (WINAPI *pIsValidLanguageGroup)(LGRPID, DWORD);
85 static INT (WINAPI *pIdnToNameprepUnicode)(DWORD, LPCWSTR, INT, LPWSTR, INT);
86 static INT (WINAPI *pIdnToAscii)(DWORD, LPCWSTR, INT, LPWSTR, INT);
87 static INT (WINAPI *pIdnToUnicode)(DWORD, LPCWSTR, INT, LPWSTR, INT);
88 static INT (WINAPI *pGetLocaleInfoEx)(LPCWSTR, LCTYPE, LPWSTR, INT);
89 static BOOL (WINAPI *pIsValidLocaleName)(LPCWSTR);
90 static INT (WINAPI *pCompareStringOrdinal)(const WCHAR *, INT, const WCHAR *, INT, BOOL);
91
92 static void InitFunctionPointers(void)
93 {
94   hKernel32 = GetModuleHandleA("kernel32");
95   pEnumSystemLanguageGroupsA = (void*)GetProcAddress(hKernel32, "EnumSystemLanguageGroupsA");
96   pEnumLanguageGroupLocalesA = (void*)GetProcAddress(hKernel32, "EnumLanguageGroupLocalesA");
97   pLocaleNameToLCID = (void*)GetProcAddress(hKernel32, "LocaleNameToLCID");
98   pLCIDToLocaleName = (void*)GetProcAddress(hKernel32, "LCIDToLocaleName");
99   pLCMapStringEx = (void*)GetProcAddress(hKernel32, "LCMapStringEx");
100   pFoldStringA = (void*)GetProcAddress(hKernel32, "FoldStringA");
101   pFoldStringW = (void*)GetProcAddress(hKernel32, "FoldStringW");
102   pIsValidLanguageGroup = (void*)GetProcAddress(hKernel32, "IsValidLanguageGroup");
103   pEnumUILanguagesA = (void*)GetProcAddress(hKernel32, "EnumUILanguagesA");
104   pEnumSystemLocalesEx = (void*)GetProcAddress(hKernel32, "EnumSystemLocalesEx");
105   pIdnToNameprepUnicode = (void*)GetProcAddress(hKernel32, "IdnToNameprepUnicode");
106   pIdnToAscii = (void*)GetProcAddress(hKernel32, "IdnToAscii");
107   pIdnToUnicode = (void*)GetProcAddress(hKernel32, "IdnToUnicode");
108   pGetLocaleInfoEx = (void*)GetProcAddress(hKernel32, "GetLocaleInfoEx");
109   pIsValidLocaleName = (void*)GetProcAddress(hKernel32, "IsValidLocaleName");
110   pCompareStringOrdinal = (void*)GetProcAddress(hKernel32, "CompareStringOrdinal");
111 }
112
113 #define eq(received, expected, label, type) \
114         ok((received) == (expected), "%s: got " type " instead of " type "\n", \
115            (label), (received), (expected))
116
117 #define BUFFER_SIZE    128
118 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
119
120 #define STRINGSA(x,y) strcpy(input, x); strcpy(Expected, y); SetLastError(0xdeadbeef); buffer[0] = '\0'
121 #define EXPECT_LENA ok(ret == lstrlen(Expected)+1, "Expected Len %d, got %d\n", lstrlen(Expected)+1, ret)
122 #define EXPECT_EQA ok(strncmp(buffer, Expected, strlen(Expected)) == 0, \
123   "Expected '%s', got '%s'\n", Expected, buffer)
124
125 #define STRINGSW(x,y) MultiByteToWideChar(CP_ACP,0,x,-1,input,COUNTOF(input)); \
126    MultiByteToWideChar(CP_ACP,0,y,-1,Expected,COUNTOF(Expected)); \
127    SetLastError(0xdeadbeef); buffer[0] = '\0'
128 #define EXPECT_LENW ok(ret == lstrlenW(Expected)+1, "Expected Len %d, got %d\n", lstrlenW(Expected)+1, ret)
129 #define EXPECT_EQW  ok(strncmpW(buffer, Expected, strlenW(Expected)) == 0, "Bad conversion\n")
130
131 #define NUO LOCALE_NOUSEROVERRIDE
132
133 static void test_GetLocaleInfoA(void)
134 {
135   int ret;
136   int len;
137   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
138   char buffer[BUFFER_SIZE];
139   char expected[BUFFER_SIZE];
140   DWORD val;
141
142   ok(lcid == 0x409, "wrong LCID calculated - %d\n", lcid);
143
144   ret = GetLocaleInfoA(lcid, LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER, (char*)&val, sizeof(val));
145   ok(ret, "got %d\n", ret);
146   ok(val == lcid, "got 0x%08x\n", val);
147
148   /* en and ar use SUBLANG_NEUTRAL, but GetLocaleInfo assume SUBLANG_DEFAULT
149      Same is true for zh on pre-Vista, but on Vista and higher GetLocaleInfo
150      assumes SUBLANG_NEUTRAL for zh */
151   memset(expected, 0, COUNTOF(expected));
152   len = GetLocaleInfoA(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
153   SetLastError(0xdeadbeef);
154   memset(buffer, 0, COUNTOF(buffer));
155   ret = GetLocaleInfoA(LANG_ENGLISH, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
156   ok((ret == len) && !lstrcmpA(buffer, expected),
157       "got %d with '%s' (expected %d with '%s')\n",
158       ret, buffer, len, expected);
159
160   memset(expected, 0, COUNTOF(expected));
161   len = GetLocaleInfoA(MAKELANGID(LANG_ARABIC, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
162   if (len) {
163       SetLastError(0xdeadbeef);
164       memset(buffer, 0, COUNTOF(buffer));
165       ret = GetLocaleInfoA(LANG_ARABIC, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
166       ok((ret == len) && !lstrcmpA(buffer, expected),
167           "got %d with '%s' (expected %d with '%s')\n",
168           ret, buffer, len, expected);
169   }
170   else
171       win_skip("LANG_ARABIC not installed\n");
172
173   /* SUBLANG_DEFAULT is required for mlang.dll, but optional for GetLocaleInfo */
174   memset(expected, 0, COUNTOF(expected));
175   len = GetLocaleInfoA(MAKELANGID(LANG_GERMAN, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
176   SetLastError(0xdeadbeef);
177   memset(buffer, 0, COUNTOF(buffer));
178   ret = GetLocaleInfoA(LANG_GERMAN, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
179   ok((ret == len) && !lstrcmpA(buffer, expected),
180       "got %d with '%s' (expected %d with '%s')\n",
181       ret, buffer, len, expected);
182
183
184   /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
185    * partially fill the buffer even if it is too short. See bug 637.
186    */
187   SetLastError(0xdeadbeef);
188   memset(buffer, 0, COUNTOF(buffer));
189   ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 0);
190   ok(ret == 7 && !buffer[0], "Expected len=7, got %d\n", ret);
191
192   SetLastError(0xdeadbeef);
193   memset(buffer, 0, COUNTOF(buffer));
194   ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 3);
195   ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
196       "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
197   ok(!strcmp(buffer, "Mon"), "Expected 'Mon', got '%s'\n", buffer);
198
199   SetLastError(0xdeadbeef);
200   memset(buffer, 0, COUNTOF(buffer));
201   ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 10);
202   ok(ret == 7, "Expected ret == 7, got %d, error %d\n", ret, GetLastError());
203   ok(!strcmp(buffer, "Monday"), "Expected 'Monday', got '%s'\n", buffer);
204 }
205
206 struct neutralsublang_name2_t {
207     WCHAR name[3];
208     WCHAR sname[15];
209     LCID lcid;
210     LCID lcid_broken;
211     WCHAR sname_broken[15];
212     int todo;
213 };
214
215 static const struct neutralsublang_name2_t neutralsublang_names2[] = {
216     { {'a','r',0}, {'a','r','-','S','A',0},
217       MAKELCID(MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA), SORT_DEFAULT) },
218     { {'a','z',0}, {'a','z','-','L','a','t','n','-','A','Z',0},
219       MAKELCID(MAKELANGID(LANG_AZERI, SUBLANG_AZERI_LATIN), SORT_DEFAULT) },
220     { {'d','e',0}, {'d','e','-','D','E',0},
221       MAKELCID(MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN), SORT_DEFAULT) },
222     { {'e','n',0}, {'e','n','-','U','S',0},
223       MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT) },
224     { {'e','s',0}, {'e','s','-','E','S',0},
225       MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN), SORT_DEFAULT),
226       MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH), SORT_DEFAULT) /* vista */,
227       {'e','s','-','E','S','_','t','r','a','d','n','l',0}, 0x1 },
228     { {'g','a',0}, {'g','a','-','I','E',0},
229       MAKELCID(MAKELANGID(LANG_IRISH, SUBLANG_IRISH_IRELAND), SORT_DEFAULT), 0, {0}, 0x3 },
230     { {'i','t',0}, {'i','t','-','I','T',0},
231       MAKELCID(MAKELANGID(LANG_ITALIAN, SUBLANG_ITALIAN), SORT_DEFAULT) },
232     { {'m','s',0}, {'m','s','-','M','Y',0},
233       MAKELCID(MAKELANGID(LANG_MALAY, SUBLANG_MALAY_MALAYSIA), SORT_DEFAULT) },
234     { {'n','l',0}, {'n','l','-','N','L',0},
235       MAKELCID(MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH), SORT_DEFAULT) },
236     { {'p','t',0}, {'p','t','-','B','R',0},
237       MAKELCID(MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN), SORT_DEFAULT) },
238     { {'s','r',0}, {'h','r','-','H','R',0},
239       MAKELCID(MAKELANGID(LANG_SERBIAN, SUBLANG_SERBIAN_CROATIA), SORT_DEFAULT) },
240     { {'s','v',0}, {'s','v','-','S','E',0},
241       MAKELCID(MAKELANGID(LANG_SWEDISH, SUBLANG_SWEDISH), SORT_DEFAULT) },
242     { {'u','z',0}, {'u','z','-','L','a','t','n','-','U','Z',0},
243       MAKELCID(MAKELANGID(LANG_UZBEK, SUBLANG_UZBEK_LATIN), SORT_DEFAULT) },
244     { {'z','h',0}, {'z','h','-','C','N',0},
245       MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT), 0, {0}, 0x3 },
246     { {0} }
247 };
248
249 static void test_GetLocaleInfoW(void)
250 {
251   LCID lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
252   LCID lcid_ru = MAKELCID(MAKELANGID(LANG_RUSSIAN, SUBLANG_NEUTRAL), SORT_DEFAULT);
253   LCID lcid_en_neut = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL), SORT_DEFAULT);
254   WCHAR bufferW[80], buffer2W[80];
255   CHAR bufferA[80];
256   DWORD val;
257   DWORD ret;
258   INT i;
259
260   ret = GetLocaleInfoW(lcid_en, LOCALE_SMONTHNAME1, bufferW, COUNTOF(bufferW));
261   if (!ret) {
262       win_skip("GetLocaleInfoW() isn't implemented\n");
263       return;
264   }
265
266   ret = GetLocaleInfoW(lcid_en, LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER, (WCHAR*)&val, sizeof(val)/sizeof(WCHAR));
267   ok(ret, "got %d\n", ret);
268   ok(val == lcid_en, "got 0x%08x\n", val);
269
270   ret = GetLocaleInfoW(lcid_en_neut, LOCALE_SNAME, bufferW, COUNTOF(bufferW));
271   if (ret)
272   {
273       static const WCHAR slangW[] = {'E','n','g','l','i','s','h',' ','(','U','n','i','t','e','d',' ',
274                                                                      'S','t','a','t','e','s',')',0};
275       static const WCHAR statesW[] = {'U','n','i','t','e','d',' ','S','t','a','t','e','s',0};
276       static const WCHAR enW[] = {'e','n','-','U','S',0};
277       const struct neutralsublang_name2_t *ptr = neutralsublang_names2;
278
279       ok(!lstrcmpW(bufferW, enW), "got wrong name %s\n", wine_dbgstr_w(bufferW));
280
281       ret = GetLocaleInfoW(lcid_en_neut, LOCALE_SCOUNTRY, bufferW, COUNTOF(bufferW));
282       ok(ret, "got %d\n", ret);
283       ok(!lstrcmpW(statesW, bufferW), "got wrong name %s\n", wine_dbgstr_w(bufferW));
284
285       ret = GetLocaleInfoW(lcid_en_neut, LOCALE_SLANGUAGE, bufferW, COUNTOF(bufferW));
286       ok(ret, "got %d\n", ret);
287       ok(!lstrcmpW(slangW, bufferW), "got wrong name %s\n", wine_dbgstr_w(bufferW));
288
289       while (*ptr->name)
290       {
291           LANGID langid;
292           LCID lcid;
293
294           /* make neutral lcid */
295           langid = MAKELANGID(PRIMARYLANGID(LANGIDFROMLCID(ptr->lcid)), SUBLANG_NEUTRAL);
296           lcid = MAKELCID(langid, SORT_DEFAULT);
297
298           val = 0;
299           GetLocaleInfoW(lcid, LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER, (WCHAR*)&val, sizeof(val)/sizeof(WCHAR));
300           if (ptr->todo & 0x1)
301           {
302           todo_wine
303               ok(val == ptr->lcid || (val && broken(val == ptr->lcid_broken)), "%s: got wrong lcid 0x%04x, expected 0x%04x\n",
304                   wine_dbgstr_w(ptr->name), val, ptr->lcid);
305           }
306           else
307               ok(val == ptr->lcid || (val && broken(val == ptr->lcid_broken)), "%s: got wrong lcid 0x%04x, expected 0x%04x\n",
308                   wine_dbgstr_w(ptr->name), val, ptr->lcid);
309
310           /* now check LOCALE_SNAME */
311           GetLocaleInfoW(lcid, LOCALE_SNAME, bufferW, COUNTOF(bufferW));
312           if (ptr->todo & 0x2)
313           todo_wine
314               ok(!lstrcmpW(bufferW, ptr->sname) ||
315                  (*ptr->sname_broken && broken(!lstrcmpW(bufferW, ptr->sname_broken))),
316                   "%s: got %s\n", wine_dbgstr_w(ptr->name), wine_dbgstr_w(bufferW));
317           else
318               ok(!lstrcmpW(bufferW, ptr->sname) ||
319                  (*ptr->sname_broken && broken(!lstrcmpW(bufferW, ptr->sname_broken))),
320                   "%s: got %s\n", wine_dbgstr_w(ptr->name), wine_dbgstr_w(bufferW));
321           ptr++;
322       }
323   }
324   else
325       win_skip("English neutral locale not supported\n");
326
327   ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1, bufferW, COUNTOF(bufferW));
328   if (!ret) {
329       win_skip("LANG_RUSSIAN locale data unavailable\n");
330       return;
331   }
332   ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1|LOCALE_RETURN_GENITIVE_NAMES,
333                        bufferW, COUNTOF(bufferW));
334   if (!ret) {
335       win_skip("LOCALE_RETURN_GENITIVE_NAMES isn't supported\n");
336       return;
337   }
338
339   /* LOCALE_RETURN_GENITIVE_NAMES isn't supported for GetLocaleInfoA */
340   bufferA[0] = 'a';
341   SetLastError(0xdeadbeef);
342   ret = GetLocaleInfoA(lcid_ru, LOCALE_SMONTHNAME1|LOCALE_RETURN_GENITIVE_NAMES,
343                        bufferA, COUNTOF(bufferA));
344   ok(ret == 0, "LOCALE_RETURN_GENITIVE_NAMES should fail with GetLocaleInfoA\n");
345   ok(bufferA[0] == 'a', "Expected buffer to be untouched\n");
346   ok(GetLastError() == ERROR_INVALID_FLAGS,
347      "Expected ERROR_INVALID_FLAGS, got %x\n", GetLastError());
348
349   bufferW[0] = 'a';
350   SetLastError(0xdeadbeef);
351   ret = GetLocaleInfoW(lcid_ru, LOCALE_RETURN_GENITIVE_NAMES,
352                        bufferW, COUNTOF(bufferW));
353   ok(ret == 0,
354      "LOCALE_RETURN_GENITIVE_NAMES itself doesn't return anything, got %d\n", ret);
355   ok(bufferW[0] == 'a', "Expected buffer to be untouched\n");
356   ok(GetLastError() == ERROR_INVALID_FLAGS,
357      "Expected ERROR_INVALID_FLAGS, got %x\n", GetLastError());
358
359   /* yes, test empty 13 month entry too */
360   for (i = 0; i < 12; i++) {
361       bufferW[0] = 0;
362       ret = GetLocaleInfoW(lcid_ru, (LOCALE_SMONTHNAME1+i)|LOCALE_RETURN_GENITIVE_NAMES,
363                            bufferW, COUNTOF(bufferW));
364       ok(ret, "Expected non zero result\n");
365       ok(ret == lstrlenW(bufferW)+1, "Expected actual length, got %d, length %d\n",
366                                     ret, lstrlenW(bufferW));
367       buffer2W[0] = 0;
368       ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1+i,
369                            buffer2W, COUNTOF(buffer2W));
370       ok(ret, "Expected non zero result\n");
371       ok(ret == lstrlenW(buffer2W)+1, "Expected actual length, got %d, length %d\n",
372                                     ret, lstrlenW(buffer2W));
373
374       ok(lstrcmpW(bufferW, buffer2W) != 0,
375            "Expected genitive name to differ, got the same for month %d\n", i+1);
376
377       /* for locale without genitive names nominative returned in both cases */
378       bufferW[0] = 0;
379       ret = GetLocaleInfoW(lcid_en, (LOCALE_SMONTHNAME1+i)|LOCALE_RETURN_GENITIVE_NAMES,
380                            bufferW, COUNTOF(bufferW));
381       ok(ret, "Expected non zero result\n");
382       ok(ret == lstrlenW(bufferW)+1, "Expected actual length, got %d, length %d\n",
383                                     ret, lstrlenW(bufferW));
384       buffer2W[0] = 0;
385       ret = GetLocaleInfoW(lcid_en, LOCALE_SMONTHNAME1+i,
386                            buffer2W, COUNTOF(buffer2W));
387       ok(ret, "Expected non zero result\n");
388       ok(ret == lstrlenW(buffer2W)+1, "Expected actual length, got %d, length %d\n",
389                                     ret, lstrlenW(buffer2W));
390
391       ok(lstrcmpW(bufferW, buffer2W) == 0,
392          "Expected same names, got different for month %d\n", i+1);
393   }
394 }
395
396 static void test_GetTimeFormatA(void)
397 {
398   int ret;
399   SYSTEMTIME  curtime;
400   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
401   char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
402
403   memset(&curtime, 2, sizeof(SYSTEMTIME));
404   STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
405   SetLastError(0xdeadbeef);
406   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
407   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
408       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
409
410   curtime.wHour = 8;
411   curtime.wMinute = 56;
412   curtime.wSecond = 13;
413   curtime.wMilliseconds = 22;
414   STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
415   SetLastError(0xdeadbeef);
416   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
417   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
418   EXPECT_LENA; EXPECT_EQA;
419
420   /* MSDN: LOCALE_NOUSEROVERRIDE can't be specified with a format string */
421   SetLastError(0xdeadbeef);
422   ret = GetTimeFormatA(lcid, NUO|TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
423   ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
424      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
425
426   STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficient buffer */
427   SetLastError(0xdeadbeef);
428   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, 2);
429   ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
430       "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
431
432   STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
433   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, NULL, 0);
434   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
435   EXPECT_LENA;
436
437   STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
438   ret = GetTimeFormatA(lcid, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
439   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
440   EXPECT_LENA; EXPECT_EQA;
441
442   STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
443   ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
444   ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
445   ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "4" )), /* win9x */
446       "Expected '', got '%s'\n", buffer );
447
448   STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
449   ret = GetTimeFormatA(lcid, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
450   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
451   EXPECT_LENA; EXPECT_EQA;
452
453   STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
454   strcpy(Expected, "8:56 AM");
455   ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &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   STRINGSA("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
460   ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
461   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
462   ok( !strcmp( buffer, "8.@:56AM" ) || broken( !strcmp( buffer, "8.@:56.@:AM" )) /* win9x */,
463       "Expected '8.@:56AM', got '%s'\n", buffer );
464
465   STRINGSA("s1s2s3", ""); /* Duplicate tokens */
466   ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
467   ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
468   ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "3" )), /* win9x */
469       "Expected '', got '%s'\n", buffer );
470
471   STRINGSA("t/tt", "A/AM"); /* AM time marker */
472   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
473   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
474   EXPECT_LENA; EXPECT_EQA;
475
476   curtime.wHour = 13;
477   STRINGSA("t/tt", "P/PM"); /* PM time marker */
478   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
479   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
480   EXPECT_LENA; EXPECT_EQA;
481
482   STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
483   ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
484   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
485   EXPECT_LENA; EXPECT_EQA;
486
487   STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
488   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
489   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
490   EXPECT_LENA; EXPECT_EQA;
491
492   STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
493   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
494   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
495   EXPECT_LENA; EXPECT_EQA;
496
497   curtime.wHour = 14; /* change this to 14 or 2pm */
498   curtime.wMinute = 5;
499   curtime.wSecond = 3;
500   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 */
501   ret = GetTimeFormatA(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   curtime.wHour = 0;
506   STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
507   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
508   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
509   EXPECT_LENA; EXPECT_EQA;
510
511   STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
512   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
513   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
514   EXPECT_LENA; EXPECT_EQA;
515
516   /* try to convert formatting strings with more than two letters
517    * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
518    * NOTE: We expect any letter for which there is an upper case value
519    *       we should see a replacement.  For letters that DO NOT have
520    *       upper case values we should see NO REPLACEMENT.
521    */
522   curtime.wHour = 8;
523   curtime.wMinute = 56;
524   curtime.wSecond = 13;
525   curtime.wMilliseconds = 22;
526   STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
527            "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
528   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
529   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
530   EXPECT_LENA; EXPECT_EQA;
531
532   STRINGSA("h", "text"); /* Don't write to buffer if len is 0 */
533   strcpy(buffer, "text");
534   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, 0);
535   ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
536   EXPECT_EQA;
537
538   STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
539            "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
540   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
541   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
542   EXPECT_LENA; EXPECT_EQA;
543
544   STRINGSA("'''", "'"); /* invalid quoted string */
545   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
546   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
547   EXPECT_LENA; EXPECT_EQA;
548
549   /* test that msdn suggested single quotation usage works as expected */
550   STRINGSA("''''", "'"); /* single quote mark */
551   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
552   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
553   EXPECT_LENA; EXPECT_EQA;
554
555   STRINGSA("''HHHHHH", "08"); /* Normal use */
556   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
557   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
558   EXPECT_LENA; EXPECT_EQA;
559
560   /* and test for normal use of the single quotation mark */
561   STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
562   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
563   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
564   EXPECT_LENA; EXPECT_EQA;
565
566   STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
567   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
568   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
569   EXPECT_LENA; EXPECT_EQA;
570
571   STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
572   ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
573   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
574   EXPECT_LENA; EXPECT_EQA;
575
576   curtime.wHour = 25;
577   STRINGSA("'123'tt", ""); /* Invalid time */
578   SetLastError(0xdeadbeef);
579   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
580   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
581       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
582
583   curtime.wHour = 12;
584   curtime.wMonth = 60; /* Invalid */
585   STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
586   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
587   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
588   EXPECT_LENA; EXPECT_EQA;
589 }
590
591 static void test_GetDateFormatA(void)
592 {
593   int ret;
594   SYSTEMTIME  curtime;
595   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
596   LCID lcid_ru = MAKELCID(MAKELANGID(LANG_RUSSIAN, SUBLANG_NEUTRAL), SORT_DEFAULT);
597   char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
598   char Broken[BUFFER_SIZE];
599   char short_day[10], month[10], genitive_month[10];
600
601   memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
602   STRINGSA("ddd',' MMM dd yy","");
603   SetLastError(0xdeadbeef);
604   ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
605   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
606       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
607
608   curtime.wYear = 2002;
609   curtime.wMonth = 5;
610   curtime.wDay = 4;
611   curtime.wDayOfWeek = 3;
612   STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
613   ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
614   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
615   EXPECT_LENA; EXPECT_EQA;
616
617   /* Same as above but with LOCALE_NOUSEROVERRIDE */
618   STRINGSA("ddd',' MMM dd yy",""); /* Simple case */
619   SetLastError(0xdeadbeef);
620   ret = GetDateFormatA(lcid, NUO, &curtime, input, buffer, COUNTOF(buffer));
621   ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
622      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
623   EXPECT_EQA;
624
625   STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
626   ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
627   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
628   EXPECT_LENA; EXPECT_EQA;
629
630   curtime.wHour = 36; /* Invalid */
631   STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
632   ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
633   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
634   EXPECT_LENA; EXPECT_EQA;
635
636   STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
637   ret = GetDateFormatA(lcid, 0, &curtime, input, NULL, 0);
638   ok(ret == 16, "Expected ret == 16, got %d, error %d\n", ret, GetLastError());
639   EXPECT_EQA;
640
641   STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
642   SetLastError(0xdeadbeef);
643   ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, 2);
644   ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
645       "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
646
647   STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
648   ret = GetDateFormat(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
649   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
650   if (strncmp(buffer, Expected, strlen(Expected)) && strncmp(buffer, "5/4/02", strlen(Expected)) != 0)
651           ok (0, "Expected '%s' or '5/4/02', got '%s'\n", Expected, buffer);
652
653   STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
654   ret = GetDateFormat(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
655   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
656   EXPECT_LENA; EXPECT_EQA;
657
658   /* test for expected DATE_YEARMONTH behavior with null format */
659   /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
660   STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
661   SetLastError(0xdeadbeef);
662   ret = GetDateFormat(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
663   ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
664      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
665   EXPECT_EQA;
666
667   /* Test that using invalid DATE_* flags results in the correct error */
668   /* and return values */
669   STRINGSA("m/d/y", ""); /* Invalid flags */
670   SetLastError(0xdeadbeef);
671   ret = GetDateFormat(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
672                       &curtime, input, buffer, COUNTOF(buffer));
673   ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
674      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
675
676   ret = GetDateFormat(lcid_ru, 0, &curtime, "ddMMMM", buffer, COUNTOF(buffer));
677   if (!ret)
678   {
679     win_skip("LANG_RUSSIAN locale data unavailable\n");
680     return;
681   }
682
683   /* month part should be in genitive form */
684   strcpy(genitive_month, buffer + 2);
685   ret = GetDateFormat(lcid_ru, 0, &curtime, "MMMM", buffer, COUNTOF(buffer));
686   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
687   strcpy(month, buffer);
688   ok(strcmp(genitive_month, month) != 0, "Expected different month forms\n");
689
690   ret = GetDateFormat(lcid_ru, 0, &curtime, "ddd", buffer, COUNTOF(buffer));
691   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
692   strcpy(short_day, buffer);
693
694   STRINGSA("dd MMMMddd dd", "");
695   sprintf(Expected, "04 %s%s 04", genitive_month, short_day);
696   ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
697   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
698   EXPECT_EQA;
699
700   STRINGSA("MMMMddd dd", "");
701   sprintf(Expected, "%s%s 04", month, short_day);
702   ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
703   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
704   EXPECT_EQA;
705
706   STRINGSA("MMMMddd", "");
707   sprintf(Expected, "%s%s", month, short_day);
708   ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
709   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
710   EXPECT_EQA;
711
712   STRINGSA("MMMMdd", "");
713   sprintf(Expected, "%s04", genitive_month);
714   sprintf(Broken, "%s04", month);
715   ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
716   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
717   ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
718      broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
719      "Expected '%s', got '%s'\n", Expected, buffer);
720
721   STRINGSA("MMMMdd ddd", "");
722   sprintf(Expected, "%s04 %s", genitive_month, short_day);
723   sprintf(Broken, "%s04 %s", month, short_day);
724   ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
725   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
726   ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
727      broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
728      "Expected '%s', got '%s'\n", Expected, buffer);
729
730   STRINGSA("dd dddMMMM", "");
731   sprintf(Expected, "04 %s%s", short_day, month);
732   ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
733   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
734   EXPECT_EQA;
735
736   STRINGSA("dd dddMMMM ddd MMMMdd", "");
737   sprintf(Expected, "04 %s%s %s %s04", short_day, month, short_day, genitive_month);
738   sprintf(Broken, "04 %s%s %s %s04", short_day, month, short_day, month);
739   ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
740   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
741   ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
742      broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
743      "Expected '%s', got '%s'\n", Expected, buffer);
744
745   /* with literal part */
746   STRINGSA("ddd',' MMMM dd", "");
747   sprintf(Expected, "%s, %s 04", short_day, genitive_month);
748   sprintf(Broken, "%s, %s 04", short_day, month);
749   ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
750   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
751   ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
752      broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
753      "Expected '%s', got '%s'\n", Expected, buffer);
754 }
755
756 static void test_GetDateFormatW(void)
757 {
758   int ret;
759   SYSTEMTIME  curtime;
760   WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
761   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
762
763   STRINGSW("",""); /* If flags is not zero then format must be NULL */
764   ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL,
765                        input, buffer, COUNTOF(buffer));
766   if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
767   {
768     win_skip("GetDateFormatW is not implemented\n");
769     return;
770   }
771   ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
772      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
773   EXPECT_EQW;
774
775   STRINGSW("",""); /* NULL buffer, len > 0 */
776   SetLastError(0xdeadbeef);
777   ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
778   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
779       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
780
781   STRINGSW("",""); /* NULL buffer, len == 0 */
782   ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
783   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
784   EXPECT_LENW; EXPECT_EQW;
785
786   curtime.wYear = 2002;
787   curtime.wMonth = 10;
788   curtime.wDay = 23;
789   curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
790   curtime.wHour = 65432; /* Invalid */
791   curtime.wMinute = 34512; /* Invalid */
792   curtime.wSecond = 65535; /* Invalid */
793   curtime.wMilliseconds = 12345;
794   STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
795   ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
796   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
797   EXPECT_LENW; EXPECT_EQW;
798
799   /* Limit tests */
800
801   curtime.wYear = 1601;
802   curtime.wMonth = 1;
803   curtime.wDay = 1;
804   curtime.wDayOfWeek = 0; /* Irrelevant */
805   curtime.wHour = 0;
806   curtime.wMinute = 0;
807   curtime.wSecond = 0;
808   curtime.wMilliseconds = 0;
809   STRINGSW("dddd d MMMM yyyy","Monday 1 January 1601");
810   SetLastError(0xdeadbeef);
811   ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
812   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
813   EXPECT_LENW; EXPECT_EQW;
814
815   curtime.wYear = 1600;
816   curtime.wMonth = 12;
817   curtime.wDay = 31;
818   curtime.wDayOfWeek = 0; /* Irrelevant */
819   curtime.wHour = 23;
820   curtime.wMinute = 59;
821   curtime.wSecond = 59;
822   curtime.wMilliseconds = 999;
823   STRINGSW("dddd d MMMM yyyy","Friday 31 December 1600");
824   SetLastError(0xdeadbeef);
825   ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
826   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
827       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
828 }
829
830
831 #define CY_POS_LEFT  0
832 #define CY_POS_RIGHT 1
833 #define CY_POS_LEFT_SPACE  2
834 #define CY_POS_RIGHT_SPACE 3
835
836 static void test_GetCurrencyFormatA(void)
837 {
838   static char szDot[] = { '.', '\0' };
839   static char szComma[] = { ',', '\0' };
840   static char szDollar[] = { '$', '\0' };
841   int ret;
842   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
843   char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
844   CURRENCYFMTA format;
845
846   memset(&format, 0, sizeof(format));
847
848   STRINGSA("23",""); /* NULL output, length > 0 --> Error */
849   SetLastError(0xdeadbeef);
850   ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
851   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
852       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
853
854   STRINGSA("23,53",""); /* Invalid character --> Error */
855   SetLastError(0xdeadbeef);
856   ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
857   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
858       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
859
860   STRINGSA("--",""); /* Double '-' --> Error */
861   SetLastError(0xdeadbeef);
862   ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
863   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
864       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
865
866   STRINGSA("0-",""); /* Trailing '-' --> Error */
867   SetLastError(0xdeadbeef);
868   ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
869   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
870       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
871
872   STRINGSA("0..",""); /* Double '.' --> Error */
873   SetLastError(0xdeadbeef);
874   ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
875   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
876       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
877
878   STRINGSA(" 0.1",""); /* Leading space --> Error */
879   SetLastError(0xdeadbeef);
880   ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
881   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
882       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
883
884   STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
885   SetLastError(0xdeadbeef);
886   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, 2);
887   ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
888       "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
889
890   STRINGSA("2353",""); /* Format and flags given --> Error */
891   SetLastError(0xdeadbeef);
892   ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
893   ok( !ret, "Expected ret == 0, got %d\n", ret);
894   ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
895       "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
896
897   STRINGSA("2353",""); /* Invalid format --> Error */
898   SetLastError(0xdeadbeef);
899   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
900   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
901       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
902
903   STRINGSA("2353","$2,353.00"); /* Valid number */
904   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
905   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
906   EXPECT_LENA; EXPECT_EQA;
907
908   STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
909   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
910   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
911   EXPECT_LENA; EXPECT_EQA;
912
913   STRINGSA("2353.1","$2,353.10"); /* Valid real number */
914   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
915   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
916   EXPECT_LENA; EXPECT_EQA;
917
918   STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
919   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
920   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
921   EXPECT_LENA; EXPECT_EQA;
922
923   STRINGSA("2353.119","$2,353.12");  /* Too many DP --> Rounded */
924   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
925   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
926   EXPECT_LENA; EXPECT_EQA;
927
928   format.NumDigits = 0; /* No decimal separator */
929   format.LeadingZero = 0;
930   format.Grouping = 0;  /* No grouping char */
931   format.NegativeOrder = 0;
932   format.PositiveOrder = CY_POS_LEFT;
933   format.lpDecimalSep = szDot;
934   format.lpThousandSep = szComma;
935   format.lpCurrencySymbol = szDollar;
936
937   STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
938   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
939   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
940   EXPECT_LENA; EXPECT_EQA;
941
942   format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
943   STRINGSA("2353","$2353.0");
944   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
945   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
946   EXPECT_LENA; EXPECT_EQA;
947
948   format.Grouping = 2; /* Group by 100's */
949   STRINGSA("2353","$23,53.0");
950   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
951   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
952   EXPECT_LENA; EXPECT_EQA;
953
954   STRINGSA("235","$235.0"); /* Grouping of a positive number */
955   format.Grouping = 3;
956   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
957   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
958   EXPECT_LENA; EXPECT_EQA;
959
960   STRINGSA("-235","$-235.0"); /* Grouping of a negative number */
961   format.NegativeOrder = 2;
962   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
963   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
964   EXPECT_LENA; EXPECT_EQA;
965
966   format.LeadingZero = 1; /* Always provide leading zero */
967   STRINGSA(".5","$0.5");
968   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
969   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
970   EXPECT_LENA; EXPECT_EQA;
971
972   format.PositiveOrder = CY_POS_RIGHT;
973   STRINGSA("1","1.0$");
974   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
975   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
976   EXPECT_LENA; EXPECT_EQA;
977
978   format.PositiveOrder = CY_POS_LEFT_SPACE;
979   STRINGSA("1","$ 1.0");
980   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
981   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
982   EXPECT_LENA; EXPECT_EQA;
983
984   format.PositiveOrder = CY_POS_RIGHT_SPACE;
985   STRINGSA("1","1.0 $");
986   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
987   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
988   EXPECT_LENA; EXPECT_EQA;
989
990   format.NegativeOrder = 0;
991   STRINGSA("-1","($1.0)");
992   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
993   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
994   EXPECT_LENA; EXPECT_EQA;
995
996   format.NegativeOrder = 1;
997   STRINGSA("-1","-$1.0");
998   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
999   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1000   EXPECT_LENA; EXPECT_EQA;
1001
1002   format.NegativeOrder = 2;
1003   STRINGSA("-1","$-1.0");
1004   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1005   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1006   EXPECT_LENA; EXPECT_EQA;
1007
1008   format.NegativeOrder = 3;
1009   STRINGSA("-1","$1.0-");
1010   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1011   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1012   EXPECT_LENA; EXPECT_EQA;
1013
1014   format.NegativeOrder = 4;
1015   STRINGSA("-1","(1.0$)");
1016   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1017   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1018   EXPECT_LENA; EXPECT_EQA;
1019
1020   format.NegativeOrder = 5;
1021   STRINGSA("-1","-1.0$");
1022   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1023   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1024   EXPECT_LENA; EXPECT_EQA;
1025
1026   format.NegativeOrder = 6;
1027   STRINGSA("-1","1.0-$");
1028   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1029   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1030   EXPECT_LENA; EXPECT_EQA;
1031
1032   format.NegativeOrder = 7;
1033   STRINGSA("-1","1.0$-");
1034   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1035   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1036   EXPECT_LENA; EXPECT_EQA;
1037
1038   format.NegativeOrder = 8;
1039   STRINGSA("-1","-1.0 $");
1040   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1041   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1042   EXPECT_LENA; EXPECT_EQA;
1043
1044   format.NegativeOrder = 9;
1045   STRINGSA("-1","-$ 1.0");
1046   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1047   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1048   EXPECT_LENA; EXPECT_EQA;
1049
1050   format.NegativeOrder = 10;
1051   STRINGSA("-1","1.0 $-");
1052   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1053   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1054   EXPECT_LENA; EXPECT_EQA;
1055
1056   format.NegativeOrder = 11;
1057   STRINGSA("-1","$ 1.0-");
1058   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1059   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1060   EXPECT_LENA; EXPECT_EQA;
1061
1062   format.NegativeOrder = 12;
1063   STRINGSA("-1","$ -1.0");
1064   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1065   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1066   EXPECT_LENA; EXPECT_EQA;
1067
1068   format.NegativeOrder = 13;
1069   STRINGSA("-1","1.0- $");
1070   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1071   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1072   EXPECT_LENA; EXPECT_EQA;
1073
1074   format.NegativeOrder = 14;
1075   STRINGSA("-1","($ 1.0)");
1076   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1077   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1078   EXPECT_LENA; EXPECT_EQA;
1079
1080   format.NegativeOrder = 15;
1081   STRINGSA("-1","(1.0 $)");
1082   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1083   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1084   EXPECT_LENA; EXPECT_EQA;
1085 }
1086
1087 #define NEG_PARENS      0 /* "(1.1)" */
1088 #define NEG_LEFT        1 /* "-1.1"  */
1089 #define NEG_LEFT_SPACE  2 /* "- 1.1" */
1090 #define NEG_RIGHT       3 /* "1.1-"  */
1091 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
1092
1093 static void test_GetNumberFormatA(void)
1094 {
1095   static char szDot[] = { '.', '\0' };
1096   static char szComma[] = { ',', '\0' };
1097   int ret;
1098   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
1099   char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
1100   NUMBERFMTA format;
1101
1102   memset(&format, 0, sizeof(format));
1103
1104   STRINGSA("23",""); /* NULL output, length > 0 --> Error */
1105   SetLastError(0xdeadbeef);
1106   ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
1107   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1108       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1109
1110   STRINGSA("23,53",""); /* Invalid character --> Error */
1111   SetLastError(0xdeadbeef);
1112   ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1113   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1114       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1115
1116   STRINGSA("--",""); /* Double '-' --> Error */
1117   SetLastError(0xdeadbeef);
1118   ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1119   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1120       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1121
1122   STRINGSA("0-",""); /* Trailing '-' --> Error */
1123   SetLastError(0xdeadbeef);
1124   ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1125   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1126       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1127
1128   STRINGSA("0..",""); /* Double '.' --> Error */
1129   SetLastError(0xdeadbeef);
1130   ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1131   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1132       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1133
1134   STRINGSA(" 0.1",""); /* Leading space --> Error */
1135   SetLastError(0xdeadbeef);
1136   ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1137   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1138       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1139
1140   STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
1141   SetLastError(0xdeadbeef);
1142   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, 2);
1143   ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1144       "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1145
1146   STRINGSA("2353",""); /* Format and flags given --> Error */
1147   SetLastError(0xdeadbeef);
1148   ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
1149   ok( !ret, "Expected ret == 0, got %d\n", ret);
1150   ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
1151       "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1152
1153   STRINGSA("2353",""); /* Invalid format --> Error */
1154   SetLastError(0xdeadbeef);
1155   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1156   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1157       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1158
1159   STRINGSA("2353","2,353.00"); /* Valid number */
1160   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1161   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1162   EXPECT_LENA; EXPECT_EQA;
1163
1164   STRINGSA("-2353","-2,353.00"); /* Valid negative number */
1165   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1166   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1167   EXPECT_LENA; EXPECT_EQA;
1168
1169   STRINGSA("-353","-353.00"); /* test for off by one error in grouping */
1170   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1171   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1172   EXPECT_LENA; EXPECT_EQA;
1173
1174   STRINGSA("2353.1","2,353.10"); /* Valid real number */
1175   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1176   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1177   EXPECT_LENA; EXPECT_EQA;
1178
1179   STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
1180   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1181   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1182   EXPECT_LENA; EXPECT_EQA;
1183
1184   STRINGSA("2353.119","2,353.12");  /* Too many DP --> Rounded */
1185   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1186   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1187   EXPECT_LENA; EXPECT_EQA;
1188
1189   format.NumDigits = 0; /* No decimal separator */
1190   format.LeadingZero = 0;
1191   format.Grouping = 0;  /* No grouping char */
1192   format.NegativeOrder = 0;
1193   format.lpDecimalSep = szDot;
1194   format.lpThousandSep = szComma;
1195
1196   STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
1197   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1198   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1199   EXPECT_LENA; EXPECT_EQA;
1200
1201   format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
1202   STRINGSA("2353","2353.0");
1203   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1204   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1205   EXPECT_LENA; EXPECT_EQA;
1206
1207   format.Grouping = 2; /* Group by 100's */
1208   STRINGSA("2353","23,53.0");
1209   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1210   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1211   EXPECT_LENA; EXPECT_EQA;
1212
1213   STRINGSA("235","235.0"); /* Grouping of a positive number */
1214   format.Grouping = 3;
1215   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1216   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1217   EXPECT_LENA; EXPECT_EQA;
1218
1219   STRINGSA("-235","-235.0"); /* Grouping of a negative number */
1220   format.NegativeOrder = NEG_LEFT;
1221   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1222   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1223   EXPECT_LENA; EXPECT_EQA;
1224
1225   format.LeadingZero = 1; /* Always provide leading zero */
1226   STRINGSA(".5","0.5");
1227   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1228   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1229   EXPECT_LENA; EXPECT_EQA;
1230
1231   format.NegativeOrder = NEG_PARENS;
1232   STRINGSA("-1","(1.0)");
1233   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1234   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1235   EXPECT_LENA; EXPECT_EQA;
1236
1237   format.NegativeOrder = NEG_LEFT;
1238   STRINGSA("-1","-1.0");
1239   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1240   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1241   EXPECT_LENA; EXPECT_EQA;
1242
1243   format.NegativeOrder = NEG_LEFT_SPACE;
1244   STRINGSA("-1","- 1.0");
1245   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1246   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1247   EXPECT_LENA; EXPECT_EQA;
1248
1249   format.NegativeOrder = NEG_RIGHT;
1250   STRINGSA("-1","1.0-");
1251   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1252   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1253   EXPECT_LENA; EXPECT_EQA;
1254
1255   format.NegativeOrder = NEG_RIGHT_SPACE;
1256   STRINGSA("-1","1.0 -");
1257   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1258   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1259   EXPECT_LENA; EXPECT_EQA;
1260
1261   lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
1262
1263   if (IsValidLocale(lcid, 0))
1264   {
1265     STRINGSA("-12345","-12 345,00"); /* Try French formatting */
1266     Expected[3] = 160; /* Non breaking space */
1267     ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1268     ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1269     EXPECT_LENA; EXPECT_EQA;
1270   }
1271 }
1272
1273 struct comparestringa_entry {
1274   LCID lcid;
1275   DWORD flags;
1276   const char *first;
1277   int first_len;
1278   const char *second;
1279   int second_len;
1280   int ret;
1281 };
1282
1283 static const struct comparestringa_entry comparestringa_data[] = {
1284   { LOCALE_SYSTEM_DEFAULT, 0, "EndDialog", -1, "_Property", -1, CSTR_GREATER_THAN },
1285   { LOCALE_SYSTEM_DEFAULT, 0, "osp_vba.sreg0070", -1, "_IEWWBrowserComp", -1, CSTR_GREATER_THAN },
1286   { LOCALE_SYSTEM_DEFAULT, 0, "r", -1, "\\", -1, CSTR_GREATER_THAN },
1287   { LOCALE_SYSTEM_DEFAULT, 0, "osp_vba.sreg0031", -1, "OriginalDatabase", -1, CSTR_GREATER_THAN },
1288   { LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1, CSTR_GREATER_THAN },
1289   { LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1, CSTR_LESS_THAN },
1290   { LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1, CSTR_LESS_THAN },
1291   { LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1, CSTR_LESS_THAN },
1292   { LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1, CSTR_LESS_THAN },
1293   { LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1, CSTR_LESS_THAN },
1294   { LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1, CSTR_LESS_THAN },
1295   { LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1, CSTR_GREATER_THAN },
1296   { LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1, CSTR_LESS_THAN },
1297   { LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1, CSTR_LESS_THAN },
1298   { LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1, CSTR_GREATER_THAN },
1299   { LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1, CSTR_GREATER_THAN },
1300   { LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1, CSTR_LESS_THAN },
1301   { LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1, CSTR_LESS_THAN },
1302   { LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1, CSTR_LESS_THAN },
1303   /* hyphen and apostrophe are treated differently depending on whether SORT_STRINGSORT specified or not */
1304   { LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1, CSTR_GREATER_THAN },
1305   { LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1, CSTR_LESS_THAN },
1306   { LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1, CSTR_LESS_THAN },
1307   { LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1, CSTR_GREATER_THAN },
1308   { LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1, CSTR_GREATER_THAN },
1309   { LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1, CSTR_LESS_THAN },
1310   { LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1, CSTR_LESS_THAN },
1311   { LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1, CSTR_GREATER_THAN },
1312   { LOCALE_SYSTEM_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9, CSTR_EQUAL },
1313   { LOCALE_SYSTEM_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10, CSTR_LESS_THAN }
1314 };
1315
1316 static void test_CompareStringA(void)
1317 {
1318   int ret, i;
1319   LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
1320
1321   for (i = 0; i < sizeof(comparestringa_data)/sizeof(struct comparestringa_entry); i++)
1322   {
1323       const struct comparestringa_entry *entry = &comparestringa_data[i];
1324
1325       ret = CompareStringA(entry->lcid, entry->flags, entry->first, entry->first_len,
1326           entry->second, entry->second_len);
1327       ok(ret == entry->ret, "%d: got %d, expected %d\n", i, ret, entry->ret);
1328   }
1329
1330   ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
1331   ok (ret == CSTR_LESS_THAN, "(Salut/Salute) Expected CSTR_LESS_THAN, got %d\n", ret);
1332
1333   ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
1334   ok (ret == CSTR_EQUAL, "(Salut/SaLuT) Expected CSTR_EQUAL, got %d\n", ret);
1335
1336   ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
1337   ok (ret == CSTR_GREATER_THAN, "(Salut/hola) Expected CSTR_GREATER_THAN, got %d\n", ret);
1338
1339   ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
1340   ok (ret == CSTR_LESS_THAN, "(haha/hoho) Expected CSTR_LESS_THAN, got %d\n", ret);
1341
1342   lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
1343
1344   ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
1345   ok (ret == CSTR_LESS_THAN, "(haha/hoho) Expected CSTR_LESS_THAN, got %d\n", ret);
1346
1347   ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
1348   ok (ret == CSTR_GREATER_THAN, "(haha/hoho) Expected CSTR_GREATER_THAN, got %d\n", ret);
1349
1350     ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
1351     ok (ret == CSTR_EQUAL, "(Salut/saLuT) Expected CSTR_EQUAL, got %d\n", ret);
1352
1353     /* test for CompareStringA flags */
1354     SetLastError(0xdeadbeef);
1355     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0x8, "NULL", -1, "NULL", -1);
1356     ok(GetLastError() == ERROR_INVALID_FLAGS,
1357         "unexpected error code %d\n", GetLastError());
1358     ok(!ret, "CompareStringA must fail with invalid flag\n");
1359
1360     SetLastError(0xdeadbeef);
1361     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, LOCALE_USE_CP_ACP, "NULL", -1, "NULL", -1);
1362     ok(GetLastError() == 0xdeadbeef, "unexpected error code %d\n", GetLastError());
1363     ok(ret == CSTR_EQUAL, "CompareStringA error: %d != CSTR_EQUAL\n", ret);
1364     /* end of test for CompareStringA flags */
1365
1366     ret = lstrcmpA("", "");
1367     ok (ret == 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret);
1368
1369     ret = lstrcmpA(NULL, NULL);
1370     ok (ret == 0 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, NULL) should return 0, got %d\n", ret);
1371
1372     ret = lstrcmpA("", NULL);
1373     ok (ret == 1 || broken(ret == -2) /* win9x */, "lstrcmpA(\"\", NULL) should return 1, got %d\n", ret);
1374
1375     ret = lstrcmpA(NULL, "");
1376     ok (ret == -1 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret);
1377  
1378
1379     if (0) { /* this requires collation table patch to make it MS compatible */
1380     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
1381     ok(ret == CSTR_LESS_THAN, "'o vs -o expected CSTR_LESS_THAN, got %d\n", ret);
1382
1383     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
1384     ok(ret == CSTR_LESS_THAN, "'o vs -o expected CSTR_LESS_THAN, got %d\n", ret);
1385
1386     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
1387     ok(ret == CSTR_LESS_THAN, "' vs - expected CSTR_LESS_THAN, got %d\n", ret);
1388
1389     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
1390     ok(ret == CSTR_LESS_THAN, "' vs - expected CSTR_LESS_THAN, got %d\n", ret);
1391
1392     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
1393     ok(ret == CSTR_GREATER_THAN, "`o vs /m CSTR_GREATER_THAN got %d\n", ret);
1394
1395     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
1396     ok(ret == CSTR_LESS_THAN, "/m vs `o expected CSTR_LESS_THAN, got %d\n", ret);
1397
1398     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
1399     ok(ret == CSTR_GREATER_THAN, "`o vs /m CSTR_GREATER_THAN got %d\n", ret);
1400
1401     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
1402     ok(ret == CSTR_LESS_THAN, "/m vs `o expected CSTR_LESS_THAN, got %d\n", ret);
1403
1404     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
1405     ok(ret == CSTR_LESS_THAN, "`o vs -m expected CSTR_LESS_THAN, got %d\n", ret);
1406
1407     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
1408     ok(ret == CSTR_GREATER_THAN, "-m vs `o CSTR_GREATER_THAN got %d\n", ret);
1409
1410     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
1411     ok(ret == CSTR_GREATER_THAN, "`o vs -m CSTR_GREATER_THAN got %d\n", ret);
1412
1413     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
1414     ok(ret == CSTR_LESS_THAN, "-m vs `o expected CSTR_LESS_THAN, got %d\n", ret);
1415     }
1416
1417
1418     /* WinXP handles embedded NULLs differently than earlier versions */
1419     ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
1420     ok(ret == CSTR_LESS_THAN || ret == CSTR_EQUAL, "aLuZkUtZ vs aLuZkUtZ\\0A expected CSTR_LESS_THAN or CSTR_EQUAL, got %d\n", ret);
1421
1422     ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
1423     ok(ret == CSTR_LESS_THAN || ret == CSTR_EQUAL, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected CSTR_LESS_THAN or CSTR_EQUAL, got %d\n", ret);
1424
1425     ret = CompareStringA(lcid, 0, "a\0b", -1, "a", -1);
1426     ok(ret == CSTR_EQUAL, "a vs a expected CSTR_EQUAL, got %d\n", ret);
1427
1428     ret = CompareStringA(lcid, 0, "a\0b", 4, "a", 2);
1429     ok(ret == CSTR_EQUAL || /* win2k */
1430        ret == CSTR_GREATER_THAN,
1431        "a\\0b vs a expected CSTR_EQUAL or CSTR_GREATER_THAN, got %d\n", ret);
1432
1433     ret = CompareStringA(lcid, 0, "\2", 2, "\1", 2);
1434     todo_wine ok(ret != CSTR_EQUAL, "\\2 vs \\1 expected unequal\n");
1435
1436     ret = CompareStringA(lcid, NORM_IGNORECASE | LOCALE_USE_CP_ACP, "#", -1, ".", -1);
1437     todo_wine ok(ret == CSTR_LESS_THAN, "\"#\" vs \".\" expected CSTR_LESS_THAN, got %d\n", ret);
1438
1439     ret = CompareStringA(lcid, NORM_IGNORECASE, "_", -1, ".", -1);
1440     todo_wine ok(ret == CSTR_GREATER_THAN, "\"_\" vs \".\" expected CSTR_GREATER_THAN, got %d\n", ret);
1441
1442     ret = lstrcmpi("#", ".");
1443     todo_wine ok(ret == -1, "\"#\" vs \".\" expected -1, got %d\n", ret);
1444
1445     lcid = MAKELCID(MAKELANGID(LANG_POLISH, SUBLANG_DEFAULT), SORT_DEFAULT);
1446
1447     /* \xB9 character lies between a and b */
1448     ret = CompareStringA(lcid, 0, "a", 1, "\xB9", 1);
1449     todo_wine ok(ret == CSTR_LESS_THAN, "\'\\xB9\' character should be greater than \'a\'\n");
1450     ret = CompareStringA(lcid, 0, "\xB9", 1, "b", 1);
1451     ok(ret == CSTR_LESS_THAN, "\'\\xB9\' character should be smaller than \'b\'\n");
1452 }
1453
1454 static void test_LCMapStringA(void)
1455 {
1456     int ret, ret2;
1457     char buf[256], buf2[256];
1458     static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
1459     static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
1460     static const char symbols_stripped[] = "justateststring1";
1461
1462     SetLastError(0xdeadbeef);
1463     ret = LCMapStringA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP | LCMAP_LOWERCASE,
1464                        lower_case, -1, buf, sizeof(buf));
1465     ok(ret == lstrlenA(lower_case) + 1,
1466        "ret %d, error %d, expected value %d\n",
1467        ret, GetLastError(), lstrlenA(lower_case) + 1);
1468     ok(!memcmp(buf, lower_case, ret), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1469
1470     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1471                        upper_case, -1, buf, sizeof(buf));
1472     ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1473     ok(GetLastError() == ERROR_INVALID_FLAGS,
1474        "unexpected error code %d\n", GetLastError());
1475
1476     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1477                        upper_case, -1, buf, sizeof(buf));
1478     ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1479     ok(GetLastError() == ERROR_INVALID_FLAGS,
1480        "unexpected error code %d\n", GetLastError());
1481
1482     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1483                        upper_case, -1, buf, sizeof(buf));
1484     ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1485     ok(GetLastError() == ERROR_INVALID_FLAGS,
1486        "unexpected error code %d\n", GetLastError());
1487
1488     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1489                        upper_case, -1, buf, sizeof(buf));
1490     ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1491     ok(GetLastError() == ERROR_INVALID_FLAGS,
1492        "unexpected error code %d\n", GetLastError());
1493
1494     /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1495     SetLastError(0xdeadbeef);
1496     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1497                        upper_case, -1, buf, sizeof(buf));
1498     ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1499     ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1500
1501     /* test LCMAP_LOWERCASE */
1502     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1503                        upper_case, -1, buf, sizeof(buf));
1504     ok(ret == lstrlenA(upper_case) + 1,
1505        "ret %d, error %d, expected value %d\n",
1506        ret, GetLastError(), lstrlenA(upper_case) + 1);
1507     ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1508
1509     /* test LCMAP_UPPERCASE */
1510     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1511                        lower_case, -1, buf, sizeof(buf));
1512     ok(ret == lstrlenA(lower_case) + 1,
1513        "ret %d, error %d, expected value %d\n",
1514        ret, GetLastError(), lstrlenA(lower_case) + 1);
1515     ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1516
1517     /* test buffer overflow */
1518     SetLastError(0xdeadbeef);
1519     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1520                        lower_case, -1, buf, 4);
1521     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1522        "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1523
1524     /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1525     lstrcpyA(buf, lower_case);
1526     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1527                        buf, -1, buf, sizeof(buf));
1528     if (!ret) /* Win9x */
1529         trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1530     else
1531     {
1532         ok(ret == lstrlenA(lower_case) + 1,
1533            "ret %d, error %d, expected value %d\n",
1534            ret, GetLastError(), lstrlenA(lower_case) + 1);
1535         ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1536     }
1537     lstrcpyA(buf, upper_case);
1538     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1539                        buf, -1, buf, sizeof(buf));
1540     if (!ret) /* Win9x */
1541         trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1542     else
1543     {
1544         ok(ret == lstrlenA(upper_case) + 1,
1545            "ret %d, error %d, expected value %d\n",
1546            ret, GetLastError(), lstrlenA(lower_case) + 1);
1547         ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1548     }
1549
1550     /* otherwise src == dst should fail */
1551     SetLastError(0xdeadbeef);
1552     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1553                        buf, 10, buf, sizeof(buf));
1554     ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1555        GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1556        "unexpected error code %d\n", GetLastError());
1557     ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1558
1559     /* test whether '\0' is always appended */
1560     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1561                        upper_case, -1, buf, sizeof(buf));
1562     ok(ret, "LCMapStringA must succeed\n");
1563     ok(buf[ret-1] == 0, "LCMapStringA not null-terminated\n");
1564     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1565                        upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1566     ok(ret2, "LCMapStringA must succeed\n");
1567     ok(buf2[ret2-1] == 0, "LCMapStringA not null-terminated\n" );
1568     ok(ret == ret2, "lengths of sort keys must be equal\n");
1569     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1570
1571     /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1572     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1573                        upper_case, -1, buf, sizeof(buf));
1574     ok(ret, "LCMapStringA must succeed\n");
1575     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1576                        lower_case, -1, buf2, sizeof(buf2));
1577     ok(ret2, "LCMapStringA must succeed\n");
1578     ok(ret == ret2, "lengths of sort keys must be equal\n");
1579     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1580
1581     /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1582        results from plain LCMAP_SORTKEY on Vista */
1583
1584     /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1585     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1586                        lower_case, -1, buf, sizeof(buf));
1587     ok(ret, "LCMapStringA must succeed\n");
1588     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1589                        symbols_stripped, -1, buf2, sizeof(buf2));
1590     ok(ret2, "LCMapStringA must succeed\n");
1591     ok(ret == ret2, "lengths of sort keys must be equal\n");
1592     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1593
1594     /* test NORM_IGNORENONSPACE */
1595     lstrcpyA(buf, "foo");
1596     ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1597                        lower_case, -1, buf, sizeof(buf));
1598     ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1599         lstrlenA(lower_case) + 1, ret);
1600     ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1601
1602     /* test NORM_IGNORESYMBOLS */
1603     lstrcpyA(buf, "foo");
1604     ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1605                        lower_case, -1, buf, sizeof(buf));
1606     ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1607         lstrlenA(symbols_stripped) + 1, ret);
1608     ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1609
1610     /* test srclen = 0 */
1611     SetLastError(0xdeadbeef);
1612     ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1613     ok(!ret, "LCMapStringA should fail with srclen = 0\n");
1614     ok(GetLastError() == ERROR_INVALID_PARAMETER,
1615        "unexpected error code %d\n", GetLastError());
1616 }
1617
1618 typedef INT (*lcmapstring_wrapper)(DWORD, LPCWSTR, INT, LPWSTR, INT);
1619
1620 static void test_lcmapstring_unicode(lcmapstring_wrapper func_ptr, const char *func_name)
1621 {
1622     int ret, ret2;
1623     WCHAR buf[256], buf2[256];
1624     char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1625
1626     ret = func_ptr(LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1627                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1628     if (broken(ret))
1629         ok(lstrcmpW(buf, upper_case) == 0, "Expected upper case string\n");
1630     else
1631     {
1632         ok(!ret, "%s LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n", func_name);
1633         ok(GetLastError() == ERROR_INVALID_FLAGS, "%s unexpected error code %d\n",
1634            func_name, GetLastError());
1635     }
1636
1637     ret = func_ptr(LCMAP_HIRAGANA | LCMAP_KATAKANA,
1638                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1639     ok(!ret, "%s LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n", func_name);
1640     ok(GetLastError() == ERROR_INVALID_FLAGS, "%s unexpected error code %d\n",
1641        func_name, GetLastError());
1642
1643     ret = func_ptr(LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1644                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1645     ok(!ret, "%s LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n", func_name);
1646     ok(GetLastError() == ERROR_INVALID_FLAGS, "%s unexpected error code %d\n",
1647        func_name, GetLastError());
1648
1649     ret = func_ptr(LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1650                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1651     ok(!ret, "%s LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n",
1652        func_name);
1653     ok(GetLastError() == ERROR_INVALID_FLAGS, "%s unexpected error code %d\n",
1654        func_name, GetLastError());
1655
1656     /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1657     SetLastError(0xdeadbeef);
1658     ret = func_ptr(LCMAP_LOWERCASE | SORT_STRINGSORT,
1659                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1660     ok(GetLastError() == ERROR_INVALID_FLAGS, "%s expected ERROR_INVALID_FLAGS, got %d\n",
1661        func_name, GetLastError());
1662     ok(!ret, "%s SORT_STRINGSORT without LCMAP_SORTKEY must fail\n", func_name);
1663
1664     /* test LCMAP_LOWERCASE */
1665     ret = func_ptr(LCMAP_LOWERCASE,
1666                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1667     ok(ret == lstrlenW(upper_case) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
1668        ret, GetLastError(), lstrlenW(upper_case) + 1);
1669     ok(!lstrcmpW(buf, lower_case), "%s string compare mismatch\n", func_name);
1670
1671     /* test LCMAP_UPPERCASE */
1672     ret = func_ptr(LCMAP_UPPERCASE,
1673                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1674     ok(ret == lstrlenW(lower_case) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
1675        ret, GetLastError(), lstrlenW(lower_case) + 1);
1676     ok(!lstrcmpW(buf, upper_case), "%s string compare mismatch\n", func_name);
1677
1678     /* test buffer overflow */
1679     SetLastError(0xdeadbeef);
1680     ret = func_ptr(LCMAP_UPPERCASE,
1681                        lower_case, -1, buf, 4);
1682     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1683        "%s should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", func_name, ret);
1684
1685     /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1686     lstrcpyW(buf, lower_case);
1687     ret = func_ptr(LCMAP_UPPERCASE,
1688                        buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1689     ok(ret == lstrlenW(lower_case) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
1690        ret, GetLastError(), lstrlenW(lower_case) + 1);
1691     ok(!lstrcmpW(buf, upper_case), "%s string compare mismatch\n", func_name);
1692
1693     lstrcpyW(buf, upper_case);
1694     ret = func_ptr(LCMAP_LOWERCASE,
1695                        buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1696     ok(ret == lstrlenW(upper_case) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
1697        ret, GetLastError(), lstrlenW(lower_case) + 1);
1698     ok(!lstrcmpW(buf, lower_case), "%s string compare mismatch\n", func_name);
1699
1700     /* otherwise src == dst should fail */
1701     SetLastError(0xdeadbeef);
1702     ret = func_ptr(LCMAP_SORTKEY | LCMAP_UPPERCASE,
1703                        buf, 10, buf, sizeof(buf));
1704     ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1705        GetLastError() == ERROR_INVALID_PARAMETER /* Win7+ */,
1706        "%s unexpected error code %d\n", func_name, GetLastError());
1707     ok(!ret, "%s src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n", func_name);
1708
1709     /* test whether '\0' is always appended */
1710     ret = func_ptr(LCMAP_SORTKEY,
1711                        upper_case, -1, buf, sizeof(buf));
1712     ok(ret, "%s func_ptr must succeed\n", func_name);
1713     ret2 = func_ptr(LCMAP_SORTKEY,
1714                        upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1715     ok(ret, "%s func_ptr must succeed\n", func_name);
1716     ok(ret == ret2, "%s lengths of sort keys must be equal\n", func_name);
1717     ok(!lstrcmpA(p_buf, p_buf2), "%s sort keys must be equal\n", func_name);
1718
1719     /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1720     ret = func_ptr(LCMAP_SORTKEY | NORM_IGNORECASE,
1721                        upper_case, -1, buf, sizeof(buf));
1722     ok(ret, "%s func_ptr must succeed\n", func_name);
1723     ret2 = func_ptr(LCMAP_SORTKEY,
1724                        lower_case, -1, buf2, sizeof(buf2));
1725     ok(ret2, "%s func_ptr must succeed\n", func_name);
1726     ok(ret == ret2, "%s lengths of sort keys must be equal\n", func_name);
1727     ok(!lstrcmpA(p_buf, p_buf2), "%s sort keys must be equal\n", func_name);
1728
1729     /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1730        results from plain LCMAP_SORTKEY on Vista */
1731
1732     /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1733     ret = func_ptr(LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1734                        lower_case, -1, buf, sizeof(buf));
1735     ok(ret, "%s func_ptr must succeed\n", func_name);
1736     ret2 = func_ptr(LCMAP_SORTKEY,
1737                        symbols_stripped, -1, buf2, sizeof(buf2));
1738     ok(ret2, "%s func_ptr must succeed\n", func_name);
1739     ok(ret == ret2, "%s lengths of sort keys must be equal\n", func_name);
1740     ok(!lstrcmpA(p_buf, p_buf2), "%s sort keys must be equal\n", func_name);
1741
1742     /* test NORM_IGNORENONSPACE */
1743     lstrcpyW(buf, fooW);
1744     ret = func_ptr(NORM_IGNORENONSPACE,
1745                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1746     ok(ret == lstrlenW(lower_case) + 1, "%s func_ptr should return %d, ret = %d\n", func_name,
1747     lstrlenW(lower_case) + 1, ret);
1748     ok(!lstrcmpW(buf, lower_case), "%s string comparison mismatch\n", func_name);
1749
1750     /* test NORM_IGNORESYMBOLS */
1751     lstrcpyW(buf, fooW);
1752     ret = func_ptr(NORM_IGNORESYMBOLS,
1753                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1754     ok(ret == lstrlenW(symbols_stripped) + 1, "%s func_ptr should return %d, ret = %d\n", func_name,
1755     lstrlenW(symbols_stripped) + 1, ret);
1756     ok(!lstrcmpW(buf, symbols_stripped), "%s string comparison mismatch\n", func_name);
1757
1758     /* test srclen = 0 */
1759     SetLastError(0xdeadbeef);
1760     ret = func_ptr(0, upper_case, 0, buf, sizeof(buf)/sizeof(WCHAR));
1761     ok(!ret, "%s func_ptr should fail with srclen = 0\n", func_name);
1762     ok(GetLastError() == ERROR_INVALID_PARAMETER,
1763        "%s unexpected error code %d\n", func_name, GetLastError());
1764 }
1765
1766 static INT LCMapStringW_wrapper(DWORD flags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen)
1767 {
1768     return LCMapStringW(LOCALE_USER_DEFAULT, flags, src, srclen, dst, dstlen);
1769 }
1770
1771 static void test_LCMapStringW(void)
1772 {
1773     int ret;
1774     WCHAR buf[256];
1775
1776     trace("testing LCMapStringW\n");
1777
1778     SetLastError(0xdeadbeef);
1779     ret = LCMapStringW((LCID)-1, LCMAP_LOWERCASE, upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1780     todo_wine {
1781     ok(!ret, "LCMapStringW should fail with bad lcid\n");
1782     ok(GetLastError() == ERROR_INVALID_PARAMETER, "unexpected error code %d\n", GetLastError());
1783     }
1784
1785     test_lcmapstring_unicode(LCMapStringW_wrapper, "LCMapStringW:");
1786 }
1787
1788 static INT LCMapStringEx_wrapper(DWORD flags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen)
1789 {
1790     return pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, flags, src, srclen, dst, dstlen, NULL, NULL, 0);
1791 }
1792
1793 static void test_LCMapStringEx(void)
1794 {
1795     int ret;
1796     WCHAR buf[256];
1797
1798     if (!pLCMapStringEx)
1799     {
1800         win_skip( "LCMapStringEx not available\n" );
1801         return;
1802     }
1803
1804     trace("testing LCMapStringEx\n");
1805
1806     SetLastError(0xdeadbeef);
1807     ret = pLCMapStringEx(fooW, LCMAP_LOWERCASE,
1808                          upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), NULL, NULL, 0);
1809     todo_wine {
1810     ok(!ret, "LCMapStringEx should fail with bad locale name\n");
1811     ok(GetLastError() == ERROR_INVALID_PARAMETER, "unexpected error code %d\n", GetLastError());
1812     }
1813
1814     /* test reserved parameters */
1815     ret = pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_LOWERCASE,
1816                          upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), NULL, NULL, 1);
1817     ok(ret == lstrlenW(upper_case) + 1, "ret %d, error %d, expected value %d\n",
1818        ret, GetLastError(), lstrlenW(upper_case) + 1);
1819     ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1820
1821     ret = pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_LOWERCASE,
1822                          upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), NULL, (void*)1, 0);
1823     ok(ret == lstrlenW(upper_case) + 1, "ret %d, error %d, expected value %d\n",
1824        ret, GetLastError(), lstrlenW(upper_case) + 1);
1825     ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1826
1827     /* crashes on native */
1828     if(0)
1829         ret = pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_LOWERCASE,
1830                              upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), (void*)1, NULL, 0);
1831
1832     test_lcmapstring_unicode(LCMapStringEx_wrapper, "LCMapStringEx:");
1833 }
1834
1835 struct neutralsublang_name_t {
1836     WCHAR name[3];
1837     LCID lcid;
1838     int todo;
1839 };
1840
1841 static const struct neutralsublang_name_t neutralsublang_names[] = {
1842     { {'a','r',0}, MAKELCID(MAKELANGID(LANG_ARABIC,     SUBLANG_ARABIC_SAUDI_ARABIA), SORT_DEFAULT) },
1843     { {'a','z',0}, MAKELCID(MAKELANGID(LANG_AZERI,      SUBLANG_AZERI_LATIN), SORT_DEFAULT) },
1844     { {'d','e',0}, MAKELCID(MAKELANGID(LANG_GERMAN,     SUBLANG_GERMAN), SORT_DEFAULT) },
1845     { {'e','n',0}, MAKELCID(MAKELANGID(LANG_ENGLISH,    SUBLANG_ENGLISH_US), SORT_DEFAULT) },
1846     { {'e','s',0}, MAKELCID(MAKELANGID(LANG_SPANISH,    SUBLANG_SPANISH_MODERN), SORT_DEFAULT), 1 },
1847     { {'g','a',0}, MAKELCID(MAKELANGID(LANG_IRISH,      SUBLANG_IRISH_IRELAND), SORT_DEFAULT), 1 },
1848     { {'i','t',0}, MAKELCID(MAKELANGID(LANG_ITALIAN,    SUBLANG_ITALIAN), SORT_DEFAULT) },
1849     { {'m','s',0}, MAKELCID(MAKELANGID(LANG_MALAY,      SUBLANG_MALAY_MALAYSIA), SORT_DEFAULT) },
1850     { {'n','l',0}, MAKELCID(MAKELANGID(LANG_DUTCH,      SUBLANG_DUTCH), SORT_DEFAULT) },
1851     { {'p','t',0}, MAKELCID(MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN), SORT_DEFAULT) },
1852     { {'s','r',0}, MAKELCID(MAKELANGID(LANG_SERBIAN,    SUBLANG_SERBIAN_SERBIA_LATIN), SORT_DEFAULT), 1 },
1853     { {'s','v',0}, MAKELCID(MAKELANGID(LANG_SWEDISH,    SUBLANG_SWEDISH), SORT_DEFAULT) },
1854     { {'u','z',0}, MAKELCID(MAKELANGID(LANG_UZBEK,      SUBLANG_UZBEK_LATIN), SORT_DEFAULT) },
1855     { {'z','h',0}, MAKELCID(MAKELANGID(LANG_CHINESE,    SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT), 1 },
1856     { {0} }
1857 };
1858
1859 static void test_LocaleNameToLCID(void)
1860 {
1861     LCID lcid;
1862     INT ret;
1863     WCHAR buffer[LOCALE_NAME_MAX_LENGTH];
1864     static const WCHAR enW[] = {'e','n',0};
1865
1866     if (!pLocaleNameToLCID)
1867     {
1868         win_skip( "LocaleNameToLCID not available\n" );
1869         return;
1870     }
1871
1872     /* special cases */
1873     buffer[0] = 0;
1874     SetLastError(0xdeadbeef);
1875     lcid = pLocaleNameToLCID(LOCALE_NAME_USER_DEFAULT, 0);
1876     ok(lcid == GetUserDefaultLCID() || broken(GetLastError() == ERROR_INVALID_PARAMETER /* Vista */),
1877        "Expected lcid == %08x, got %08x, error %d\n", GetUserDefaultLCID(), lcid, GetLastError());
1878     ret = pLCIDToLocaleName(lcid, buffer, LOCALE_NAME_MAX_LENGTH, 0);
1879     ok(ret > 0, "Expected ret > 0, got %d, error %d\n", ret, GetLastError());
1880     trace("%08x, %s\n", lcid, wine_dbgstr_w(buffer));
1881
1882     buffer[0] = 0;
1883     SetLastError(0xdeadbeef);
1884     lcid = pLocaleNameToLCID(LOCALE_NAME_SYSTEM_DEFAULT, 0);
1885     ok(!lcid && GetLastError() == ERROR_INVALID_PARAMETER,
1886        "Expected lcid == 0, got %08x, error %d\n", lcid, GetLastError());
1887     ret = pLCIDToLocaleName(lcid, buffer, LOCALE_NAME_MAX_LENGTH, 0);
1888     ok(ret > 0, "Expected ret > 0, got %d, error %d\n", ret, GetLastError());
1889     trace("%08x, %s\n", lcid, wine_dbgstr_w(buffer));
1890
1891     buffer[0] = 0;
1892     SetLastError(0xdeadbeef);
1893     lcid = pLocaleNameToLCID(LOCALE_NAME_INVARIANT, 0);
1894     todo_wine ok(lcid == 0x7F, "Expected lcid = 0x7F, got %08x, error %d\n", lcid, GetLastError());
1895     ret = pLCIDToLocaleName(lcid, buffer, LOCALE_NAME_MAX_LENGTH, 0);
1896     ok(ret > 0, "Expected ret > 0, got %d, error %d\n", ret, GetLastError());
1897     trace("%08x, %s\n", lcid, wine_dbgstr_w(buffer));
1898
1899     /* bad name */
1900     SetLastError(0xdeadbeef);
1901     lcid = pLocaleNameToLCID(fooW, 0);
1902     ok(!lcid && GetLastError() == ERROR_INVALID_PARAMETER,
1903        "Expected lcid == 0, got got %08x, error %d\n", lcid, GetLastError());
1904
1905     /* english neutral name */
1906     lcid = pLocaleNameToLCID(enW, 0);
1907     ok(lcid == MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT) ||
1908        broken(lcid == 0) /* Vista */, "got 0x%04x\n", lcid);
1909     if (lcid)
1910     {
1911         const struct neutralsublang_name_t *ptr = neutralsublang_names;
1912
1913         while (*ptr->name)
1914         {
1915             lcid = pLocaleNameToLCID(ptr->name, 0);
1916             if (ptr->todo)
1917             todo_wine
1918                 ok(lcid == ptr->lcid, "%s: got wrong lcid 0x%04x, expected 0x%04x\n",
1919                     wine_dbgstr_w(ptr->name), lcid, ptr->lcid);
1920             else
1921                 ok(lcid == ptr->lcid, "%s: got wrong lcid 0x%04x, expected 0x%04x\n",
1922                     wine_dbgstr_w(ptr->name), lcid, ptr->lcid);
1923
1924             *buffer = 0;
1925             ret = pLCIDToLocaleName(lcid, buffer, sizeof(buffer)/sizeof(WCHAR), 0);
1926             ok(ret > 0, "%s: got %d\n", wine_dbgstr_w(ptr->name), ret);
1927             ok(lstrcmpW(ptr->name, buffer), "%s: got wrong locale name %s\n",
1928                 wine_dbgstr_w(ptr->name), wine_dbgstr_w(buffer));
1929
1930             ptr++;
1931         }
1932     }
1933 }
1934
1935 /* this requires collation table patch to make it MS compatible */
1936 static const char * const strings_sorted[] =
1937 {
1938 "'",
1939 "-",
1940 "!",
1941 "\"",
1942 ".",
1943 ":",
1944 "\\",
1945 "_",
1946 "`",
1947 "{",
1948 "}",
1949 "+",
1950 "0",
1951 "1",
1952 "2",
1953 "3",
1954 "4",
1955 "5",
1956 "6",
1957 "7",
1958 "8",
1959 "9",
1960 "a",
1961 "A",
1962 "b",
1963 "B",
1964 "c",
1965 "C"
1966 };
1967
1968 static const char * const strings[] =
1969 {
1970 "C",
1971 "\"",
1972 "9",
1973 "'",
1974 "}",
1975 "-",
1976 "7",
1977 "+",
1978 "`",
1979 "1",
1980 "a",
1981 "5",
1982 "\\",
1983 "8",
1984 "B",
1985 "3",
1986 "_",
1987 "6",
1988 "{",
1989 "2",
1990 "c",
1991 "4",
1992 "!",
1993 "0",
1994 "A",
1995 ":",
1996 "b",
1997 "."
1998 };
1999
2000 static int compare_string1(const void *e1, const void *e2)
2001 {
2002     const char *s1 = *(const char *const *)e1;
2003     const char *s2 = *(const char *const *)e2;
2004
2005     return lstrcmpA(s1, s2);
2006 }
2007
2008 static int compare_string2(const void *e1, const void *e2)
2009 {
2010     const char *s1 = *(const char *const *)e1;
2011     const char *s2 = *(const char *const *)e2;
2012
2013     return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
2014 }
2015
2016 static int compare_string3(const void *e1, const void *e2)
2017 {
2018     const char *s1 = *(const char *const *)e1;
2019     const char *s2 = *(const char *const *)e2;
2020     char key1[256], key2[256];
2021
2022     LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
2023     LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
2024     return strcmp(key1, key2);
2025 }
2026
2027 static void test_sorting(void)
2028 {
2029     char buf[256];
2030     char **str_buf = (char **)buf;
2031     int i;
2032
2033     assert(sizeof(buf) >= sizeof(strings));
2034
2035     /* 1. sort using lstrcmpA */
2036     memcpy(buf, strings, sizeof(strings));
2037     qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
2038     for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
2039     {
2040         ok(!strcmp(strings_sorted[i], str_buf[i]),
2041            "qsort using lstrcmpA failed for element %d\n", i);
2042     }
2043     /* 2. sort using CompareStringA */
2044     memcpy(buf, strings, sizeof(strings));
2045     qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
2046     for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
2047     {
2048         ok(!strcmp(strings_sorted[i], str_buf[i]),
2049            "qsort using CompareStringA failed for element %d\n", i);
2050     }
2051     /* 3. sort using sort keys */
2052     memcpy(buf, strings, sizeof(strings));
2053     qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
2054     for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
2055     {
2056         ok(!strcmp(strings_sorted[i], str_buf[i]),
2057            "qsort using sort keys failed for element %d\n", i);
2058     }
2059 }
2060
2061 static void test_FoldStringA(void)
2062 {
2063   int ret, i, j;
2064   BOOL is_special;
2065   char src[256], dst[256];
2066   static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0'  };
2067   static const char digits_dst[] = { '1','2','3','\0'  };
2068   static const char composite_src[] =
2069   {
2070     0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
2071     0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
2072     0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
2073     0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
2074     0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
2075     0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
2076     0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
2077     0xfb,0xfc,0xfd,0xff,'\0'
2078   };
2079   static const char composite_dst[] =
2080   {
2081     0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
2082     0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
2083     0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
2084     0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
2085     0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
2086     0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
2087     0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
2088     0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
2089     0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
2090     0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
2091     0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
2092     0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
2093     0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
2094     0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
2095     0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
2096   };
2097   static const char composite_dst_alt[] =
2098   {
2099     0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
2100     0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
2101     0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
2102     0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
2103     0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
2104     0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
2105     0x4f,0x7e,0x4f,0xa8,0xd8,0x55,0x60,0x55,
2106     0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,0x61,
2107     0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,0x61,
2108     0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,0x65,
2109     0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,0x69,
2110     0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,0x6f,
2111     0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,0x6f,
2112     0xa8,0xf8,0x75,0x60,0x75,0xb4,0x75,0x5e,
2113     0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
2114   };
2115   static const char ligatures_src[] =
2116   {
2117     0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
2118   };
2119   static const char ligatures_dst[] =
2120   {
2121     'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
2122   };
2123   static const struct special
2124   {
2125     char src;
2126     char dst[4];
2127   }  foldczone_special[] =
2128   {
2129     /* src   dst                   */
2130     { 0x85, { 0x2e, 0x2e, 0x2e, 0x00 } },
2131     { 0x98, { 0x20, 0x7e, 0x00 } },
2132     { 0x99, { 0x54, 0x4d, 0x00 } },
2133     { 0xa0, { 0x20, 0x00 } },
2134     { 0xa8, { 0x20, 0xa8, 0x00 } },
2135     { 0xaa, { 0x61, 0x00 } },
2136     { 0xaf, { 0x20, 0xaf, 0x00 } },
2137     { 0xb2, { 0x32, 0x00 } },
2138     { 0xb3, { 0x33, 0x00 } },
2139     { 0xb4, { 0x20, 0xb4, 0x00 } },
2140     { 0xb8, { 0x20, 0xb8, 0x00 } },
2141     { 0xb9, { 0x31, 0x00 } },
2142     { 0xba, { 0x6f, 0x00 } },
2143     { 0xbc, { 0x31, 0x2f, 0x34, 0x00 } },
2144     { 0xbd, { 0x31, 0x2f, 0x32, 0x00 } },
2145     { 0xbe, { 0x33, 0x2f, 0x34, 0x00 } },
2146     { 0x00 }
2147   };
2148
2149   if (!pFoldStringA)
2150     return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
2151
2152   /* these tests are locale specific */
2153   if (GetACP() != 1252)
2154   {
2155       trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
2156       return;
2157   }
2158
2159   /* MAP_FOLDDIGITS */
2160   SetLastError(0);
2161   ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
2162   if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2163   {
2164     win_skip("FoldStringA is not implemented\n");
2165     return;
2166   }
2167   ok(ret == 4, "Expected ret == 4, got %d, error %d\n", ret, GetLastError());
2168   ok(strcmp(dst, digits_dst) == 0,
2169      "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
2170   for (i = 1; i < 256; i++)
2171   {
2172     if (!strchr(digits_src, i))
2173     {
2174       src[0] = i;
2175       src[1] = '\0';
2176       SetLastError(0);
2177       ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
2178       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2179       ok(dst[0] == src[0],
2180          "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
2181     }
2182   }
2183
2184   /* MAP_EXPAND_LIGATURES */
2185   SetLastError(0);
2186   ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
2187   /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
2188   if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
2189     ok(ret == sizeof(ligatures_dst), "Got %d, error %d\n", ret, GetLastError());
2190     ok(strcmp(dst, ligatures_dst) == 0,
2191        "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
2192     for (i = 1; i < 256; i++)
2193     {
2194       if (!strchr(ligatures_src, i))
2195       {
2196         src[0] = i;
2197         src[1] = '\0';
2198         SetLastError(0);
2199         ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
2200         if (ret == 3)
2201         {
2202           /* Vista */
2203           ok((i == 0xDC && lstrcmpA(dst, "UE") == 0) ||
2204              (i == 0xFC && lstrcmpA(dst, "ue") == 0),
2205              "Got %s for %d\n", dst, i);
2206         }
2207         else
2208         {
2209           ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2210           ok(dst[0] == src[0],
2211              "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
2212         }
2213       }
2214     }
2215   }
2216
2217   /* MAP_COMPOSITE */
2218   SetLastError(0);
2219   ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
2220   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2221   ok(ret == 121 || ret == 119, "Expected 121 or 119, got %d\n", ret);
2222   ok(strcmp(dst, composite_dst) == 0 || strcmp(dst, composite_dst_alt) == 0,
2223      "MAP_COMPOSITE: Mismatch, got '%s'\n", dst);
2224
2225   for (i = 1; i < 256; i++)
2226   {
2227     if (!strchr(composite_src, i))
2228     {
2229       src[0] = i;
2230       src[1] = '\0';
2231       SetLastError(0);
2232       ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
2233       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2234       ok(dst[0] == src[0],
2235          "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
2236          (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
2237     }
2238   }
2239
2240   /* MAP_FOLDCZONE */
2241   for (i = 1; i < 256; i++)
2242   {
2243     src[0] = i;
2244     src[1] = '\0';
2245     SetLastError(0);
2246     ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
2247     is_special = FALSE;
2248     for (j = 0; foldczone_special[j].src != 0 && ! is_special; j++)
2249     {
2250       if (foldczone_special[j].src == src[0])
2251       {
2252         ok(ret == 2 || ret == lstrlenA(foldczone_special[j].dst) + 1,
2253            "Expected ret == 2 or %d, got %d, error %d\n",
2254            lstrlenA(foldczone_special[j].dst) + 1, ret, GetLastError());
2255         ok(src[0] == dst[0] || lstrcmpA(foldczone_special[j].dst, dst) == 0,
2256            "MAP_FOLDCZONE: string mismatch for 0x%02x\n",
2257            (unsigned char)src[0]);
2258         is_special = TRUE;
2259       }
2260     }
2261     if (! is_special)
2262     {
2263       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2264       ok(src[0] == dst[0],
2265          "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
2266          (unsigned char)src[0], (unsigned char)dst[0]);
2267     }
2268   }
2269
2270   /* MAP_PRECOMPOSED */
2271   for (i = 1; i < 256; i++)
2272   {
2273     src[0] = i;
2274     src[1] = '\0';
2275     SetLastError(0);
2276     ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
2277     ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2278     ok(src[0] == dst[0],
2279        "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
2280        (unsigned char)src[0], (unsigned char)dst[0]);
2281   }
2282 }
2283
2284 static void test_FoldStringW(void)
2285 {
2286   int ret;
2287   unsigned int i, j;
2288   WCHAR src[256], dst[256], ch, prev_ch = 1;
2289   static const DWORD badFlags[] =
2290   {
2291     0,
2292     MAP_PRECOMPOSED|MAP_COMPOSITE,
2293     MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
2294     MAP_COMPOSITE|MAP_EXPAND_LIGATURES
2295   };
2296   /* Ranges of digits 0-9 : Must be sorted! */
2297   static const WCHAR digitRanges[] =
2298   {
2299     0x0030, /* '0'-'9' */
2300     0x0660, /* Eastern Arabic */
2301     0x06F0, /* Arabic - Hindu */
2302     0x0966, /* Devengari */
2303     0x09E6, /* Bengalii */
2304     0x0A66, /* Gurmukhi */
2305     0x0AE6, /* Gujarati */
2306     0x0B66, /* Oriya */
2307     0x0BE6, /* Tamil - No 0 */
2308     0x0C66, /* Telugu */
2309     0x0CE6, /* Kannada */
2310     0x0D66, /* Maylayalam */
2311     0x0E50, /* Thai */
2312     0x0ED0, /* Laos */
2313     0x0F29, /* Tibet - 0 is out of sequence */
2314     0x2070, /* Superscript - 1, 2, 3 are out of sequence */
2315     0x2080, /* Subscript */
2316     0x245F, /* Circled - 0 is out of sequence */
2317     0x2473, /* Bracketed */
2318     0x2487, /* Full stop */
2319     0x2775, /* Inverted circled - No 0 */
2320     0x277F, /* Patterned circled - No 0 */
2321     0x2789, /* Inverted Patterned circled - No 0 */
2322     0x3020, /* Hangzhou */
2323     0xff10, /* Pliene chasse (?) */
2324     0xffff  /* Terminator */
2325   };
2326   /* Digits which are represented, but out of sequence */
2327   static const WCHAR outOfSequenceDigits[] =
2328   {
2329       0xB9,   /* Superscript 1 */
2330       0xB2,   /* Superscript 2 */
2331       0xB3,   /* Superscript 3 */
2332       0x0F33, /* Tibetan half zero */
2333       0x24EA, /* Circled 0 */
2334       0x3007, /* Ideographic number zero */
2335       '\0'    /* Terminator */
2336   };
2337   /* Digits in digitRanges for which no representation is available */
2338   static const WCHAR noDigitAvailable[] =
2339   {
2340       0x0BE6, /* No Tamil 0 */
2341       0x0F29, /* No Tibetan half zero (out of sequence) */
2342       0x2473, /* No Bracketed 0 */
2343       0x2487, /* No 0 Full stop */
2344       0x2775, /* No inverted circled 0 */
2345       0x277F, /* No patterned circled */
2346       0x2789, /* No inverted Patterned circled */
2347       0x3020, /* No Hangzhou 0 */
2348       '\0'    /* Terminator */
2349   };
2350   static const WCHAR foldczone_src[] =
2351   {
2352     'W',    'i',    'n',    'e',    0x0348, 0x0551, 0x1323, 0x280d,
2353     0xff37, 0xff49, 0xff4e, 0xff45, '\0'
2354   };
2355   static const WCHAR foldczone_dst[] =
2356   {
2357     'W','i','n','e',0x0348,0x0551,0x1323,0x280d,'W','i','n','e','\0'
2358   };
2359   static const WCHAR foldczone_todo_src[] =
2360   {
2361       0x3c5,0x308,0x6a,0x30c,0xa0,0xaa,0
2362   };
2363   static const WCHAR foldczone_todo_dst[] =
2364   {
2365       0x3cb,0x1f0,' ','a',0
2366   };
2367   static const WCHAR foldczone_todo_broken_dst[] =
2368   {
2369       0x3cb,0x1f0,0xa0,0xaa,0
2370   };
2371   static const WCHAR ligatures_src[] =
2372   {
2373     'W',    'i',    'n',    'e',    0x03a6, 0x03b9, 0x03bd, 0x03b5,
2374     0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
2375     0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
2376     0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
2377     0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
2378     0xfb04, 0xfb05, 0xfb06, '\0'
2379   };
2380   static const WCHAR ligatures_dst[] =
2381   {
2382     'W','i','n','e',0x03a6,0x03b9,0x03bd,0x03b5,
2383     'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
2384     'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
2385     'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
2386     0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
2387     'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
2388   };
2389
2390   if (!pFoldStringW)
2391   {
2392     win_skip("FoldStringW is not available\n");
2393     return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
2394   }
2395
2396   /* Invalid flag combinations */
2397   for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
2398   {
2399     src[0] = dst[0] = '\0';
2400     SetLastError(0);
2401     ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
2402     if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
2403     {
2404       win_skip("FoldStringW is not implemented\n");
2405       return;
2406     }
2407     ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
2408        "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2409   }
2410
2411   /* src & dst cannot be the same */
2412   SetLastError(0);
2413   ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
2414   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2415       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2416
2417   /* src can't be NULL */
2418   SetLastError(0);
2419   ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
2420   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2421       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2422
2423   /* srclen can't be 0 */
2424   SetLastError(0);
2425   ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
2426   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2427       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2428
2429   /* dstlen can't be < 0 */
2430   SetLastError(0);
2431   ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
2432   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2433       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2434
2435   /* Ret includes terminating NUL which is appended if srclen = -1 */
2436   SetLastError(0);
2437   src[0] = 'A';
2438   src[1] = '\0';
2439   dst[0] = '\0';
2440   ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
2441   ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2442   ok(dst[0] == 'A' && dst[1] == '\0',
2443      "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%d\n",
2444      'A', '\0', ret, dst[0], dst[1], GetLastError());
2445
2446   /* If size is given, result is not NUL terminated */
2447   SetLastError(0);
2448   src[0] = 'A';
2449   src[1] = 'A';
2450   dst[0] = 'X';
2451   dst[1] = 'X';
2452   ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
2453   ok(ret == 1, "Expected ret == 1, got %d, error %d\n", ret, GetLastError());
2454   ok(dst[0] == 'A' && dst[1] == 'X',
2455      "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%d\n",
2456      'A','X', ret, dst[0], dst[1], GetLastError());
2457
2458   /* MAP_FOLDDIGITS */
2459   for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
2460   {
2461     /* Check everything before this range */
2462     for (ch = prev_ch; ch < digitRanges[j]; ch++)
2463     {
2464       SetLastError(0);
2465       src[0] = ch;
2466       src[1] = dst[0] = '\0';
2467       ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2468       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2469
2470       ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
2471          /* Wine (correctly) maps all Unicode 4.0+ digits */
2472          isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF || ch == 0x19da ||
2473          (ch >= 0x1369 && ch <= 0x1371),
2474          "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
2475     }
2476
2477     if (digitRanges[j] == 0xffff)
2478       break; /* Finished the whole code point space */
2479
2480     for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
2481     {
2482       WCHAR c;
2483
2484       /* Map out of sequence characters */
2485       if      (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
2486       else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
2487       else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
2488       else if (ch == 0x245F) c = 0x24EA; /* Circled 0     */
2489       else                   c = ch;
2490       SetLastError(0);
2491       src[0] = c;
2492       src[1] = dst[0] = '\0';
2493       ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2494       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2495
2496       ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
2497          broken( dst[0] == ch ) ||  /* old Windows versions don't have all mappings */
2498          (digitRanges[j] == 0x3020 && dst[0] == ch) || /* Hangzhou not present in all Windows versions */
2499          (digitRanges[j] == 0x0F29 && dst[0] == ch) || /* Tibetan not present in all Windows versions */
2500          strchrW(noDigitAvailable, c),
2501          "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
2502          ch, '0' + digitRanges[j] - ch, dst[0]);
2503     }
2504     prev_ch = ch;
2505   }
2506
2507   /* MAP_FOLDCZONE */
2508   SetLastError(0);
2509   ret = pFoldStringW(MAP_FOLDCZONE, foldczone_src, -1, dst, 256);
2510   ok(ret == sizeof(foldczone_dst)/sizeof(foldczone_dst[0]),
2511      "Got %d, error %d\n", ret, GetLastError());
2512   ok(!memcmp(dst, foldczone_dst, sizeof(foldczone_dst)),
2513      "MAP_FOLDCZONE: Expanded incorrectly\n");
2514
2515   ret = pFoldStringW(MAP_FOLDCZONE|MAP_PRECOMPOSED, foldczone_todo_src, -1, dst, 256);
2516   todo_wine ok(ret == sizeof(foldczone_todo_dst)/sizeof(foldczone_todo_dst[0]),
2517           "Got %d, error %d\n", ret, GetLastError());
2518   todo_wine ok(!memcmp(dst, foldczone_todo_dst, sizeof(foldczone_todo_dst))
2519           || broken(!memcmp(dst, foldczone_todo_broken_dst, sizeof(foldczone_todo_broken_dst))),
2520           "MAP_FOLDCZONE: Expanded incorrectly (%s)\n", wine_dbgstr_w(dst));
2521
2522   /* MAP_EXPAND_LIGATURES */
2523   SetLastError(0);
2524   ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
2525   /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
2526   if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
2527     ok(ret == sizeof(ligatures_dst)/sizeof(ligatures_dst[0]),
2528        "Got %d, error %d\n", ret, GetLastError());
2529     ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
2530        "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
2531   }
2532
2533   /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
2534 }
2535
2536
2537
2538 #define LCID_OK(l) \
2539   ok(lcid == l, "Expected lcid = %08x, got %08x\n", l, lcid)
2540 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
2541 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
2542 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
2543 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
2544
2545 static void test_ConvertDefaultLocale(void)
2546 {
2547   LCID lcid;
2548
2549   /* Doesn't change lcid, even if non default sublang/sort used */
2550   TEST_LCID(LANG_ENGLISH,  SUBLANG_ENGLISH_US, SORT_DEFAULT);
2551   TEST_LCID(LANG_ENGLISH,  SUBLANG_ENGLISH_UK, SORT_DEFAULT);
2552   TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT,    SORT_DEFAULT);
2553   TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT,    SORT_JAPANESE_UNICODE);
2554
2555   /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
2556   LCID_RES(MKLCID(LANG_ENGLISH,  SUBLANG_NEUTRAL, SORT_DEFAULT),
2557            MKLCID(LANG_ENGLISH,  SUBLANG_DEFAULT, SORT_DEFAULT));
2558   LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
2559            MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
2560
2561   /* Invariant language is not treated specially */
2562   TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
2563
2564   /* User/system default languages alone are not mapped */
2565   TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
2566   TEST_LCIDLANG(LANG_USER_DEFAULT,   SORT_JAPANESE_UNICODE);
2567
2568   /* Default lcids */
2569   LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
2570   LCID_RES(LOCALE_USER_DEFAULT,   GetUserDefaultLCID());
2571   LCID_RES(LOCALE_NEUTRAL,        GetUserDefaultLCID());
2572 }
2573
2574 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
2575                                     DWORD dwFlags, LONG_PTR lParam)
2576 {
2577   trace("%08x, %s, %s, %08x, %08lx\n",
2578         lgrpid, lpszNum, lpszName, dwFlags, lParam);
2579
2580   ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
2581      "Enumerated grp %d not valid (flags %d)\n", lgrpid, dwFlags);
2582
2583   /* If lParam is one, we are calling with flags defaulted from 0 */
2584   ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
2585          "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %d\n", dwFlags);
2586
2587   return TRUE;
2588 }
2589
2590 static void test_EnumSystemLanguageGroupsA(void)
2591 {
2592   BOOL ret;
2593
2594   if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
2595   {
2596     win_skip("EnumSystemLanguageGroupsA and/or IsValidLanguageGroup are not available\n");
2597     return;
2598   }
2599
2600   /* No enumeration proc */
2601   SetLastError(0);
2602   ret = pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
2603   if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2604   {
2605     win_skip("EnumSystemLanguageGroupsA is not implemented\n");
2606     return;
2607   }
2608   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2609       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2610
2611   /* Invalid flags */
2612   SetLastError(0);
2613   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
2614   ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2615
2616   /* No flags - defaults to LGRPID_INSTALLED */
2617   SetLastError(0xdeadbeef);
2618   pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
2619   ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
2620
2621   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
2622   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
2623 }
2624
2625 static BOOL CALLBACK enum_func( LPWSTR name, DWORD flags, LPARAM lparam )
2626 {
2627     trace( "%s %x\n", wine_dbgstr_w(name), flags );
2628     return TRUE;
2629 }
2630
2631 static void test_EnumSystemLocalesEx(void)
2632 {
2633     BOOL ret;
2634
2635     if (!pEnumSystemLocalesEx)
2636     {
2637         win_skip( "EnumSystemLocalesEx not available\n" );
2638         return;
2639     }
2640     SetLastError( 0xdeadbeef );
2641     ret = pEnumSystemLocalesEx( enum_func, LOCALE_ALL, 0, (void *)1 );
2642     ok( !ret, "should have failed\n" );
2643     ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
2644     SetLastError( 0xdeadbeef );
2645     ret = pEnumSystemLocalesEx( enum_func, 0, 0, NULL );
2646     ok( ret, "failed err %u\n", GetLastError() );
2647 }
2648
2649 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
2650                                       LONG_PTR lParam)
2651 {
2652   trace("%08x, %08x, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
2653
2654   /* invalid locale enumerated on some platforms */
2655   if (lcid == 0)
2656       return TRUE;
2657
2658   ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
2659      "Enumerated grp %d not valid\n", lgrpid);
2660   ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
2661      "Enumerated grp locale %d not valid\n", lcid);
2662   return TRUE;
2663 }
2664
2665 static void test_EnumLanguageGroupLocalesA(void)
2666 {
2667   BOOL ret;
2668
2669   if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
2670   {
2671     win_skip("EnumLanguageGroupLocalesA and/or IsValidLanguageGroup are not available\n");
2672     return;
2673   }
2674
2675   /* No enumeration proc */
2676   SetLastError(0);
2677   ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
2678   if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2679   {
2680     win_skip("EnumLanguageGroupLocalesA is not implemented\n");
2681     return;
2682   }
2683   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2684       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2685
2686   /* lgrpid too small */
2687   SetLastError(0);
2688   ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
2689   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2690       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2691
2692   /* lgrpid too big */
2693   SetLastError(0);
2694   ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
2695   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2696       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2697
2698   /* dwFlags is reserved */
2699   SetLastError(0);
2700   ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
2701   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2702       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2703
2704   pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2705 }
2706
2707 static void test_SetLocaleInfoA(void)
2708 {
2709   BOOL bRet;
2710   LCID lcid = GetUserDefaultLCID();
2711
2712   /* Null data */
2713   SetLastError(0);
2714   bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2715   ok( !bRet && GetLastError() == ERROR_INVALID_PARAMETER,
2716       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2717
2718   /* IDATE */
2719   SetLastError(0);
2720   bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, "test_SetLocaleInfoA");
2721   ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2722      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2723
2724   /* ILDATE */
2725   SetLastError(0);
2726   bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, "test_SetLocaleInfoA");
2727   ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2728      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2729 }
2730
2731 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2732 {
2733   trace("%s %08lx\n", value, lParam);
2734   return(TRUE);
2735 }
2736
2737 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2738 {
2739   ok(!enumCount, "callback called again unexpected\n");
2740   enumCount++;
2741   return(FALSE);
2742 }
2743
2744 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2745 {
2746   ok(0,"callback called unexpected\n");
2747   return(FALSE);
2748 }
2749
2750 static void test_EnumUILanguageA(void)
2751 {
2752   BOOL ret;
2753   if (!pEnumUILanguagesA) {
2754     win_skip("EnumUILanguagesA is not available on Win9x or NT4\n");
2755     return;
2756   }
2757
2758   SetLastError(ERROR_SUCCESS);
2759   ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2760   if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2761   {
2762     win_skip("EnumUILanguagesA is not implemented\n");
2763     return;
2764   }
2765   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2766
2767   enumCount = 0;
2768   SetLastError(ERROR_SUCCESS);
2769   ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2770   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2771
2772   SetLastError(ERROR_SUCCESS);
2773   ret = pEnumUILanguagesA(NULL, 0, 0);
2774   ok(!ret, "Expected return value FALSE, got %u\n", ret);
2775   ok(GetLastError() == ERROR_INVALID_PARAMETER,
2776       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2777
2778   SetLastError(ERROR_SUCCESS);
2779   ret = pEnumUILanguagesA(luilocale_proc3A, 0x5a5a5a5a, 0);
2780   ok(!ret, "Expected return value FALSE, got %u\n", ret);
2781   ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2782
2783   SetLastError(ERROR_SUCCESS);
2784   ret = pEnumUILanguagesA(NULL, 0x5a5a5a5a, 0);
2785   ok(!ret, "Expected return value FALSE, got %u\n", ret);
2786   ok(GetLastError() == ERROR_INVALID_PARAMETER,
2787       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2788 }
2789
2790 static char date_fmt_buf[1024];
2791
2792 static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
2793 {
2794     lstrcatA(date_fmt_buf, fmt);
2795     lstrcatA(date_fmt_buf, "\n");
2796     return TRUE;
2797 }
2798
2799 static void test_EnumDateFormatsA(void)
2800 {
2801     char *p, buf[256];
2802     BOOL ret;
2803     LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2804
2805     trace("EnumDateFormatsA 0\n");
2806     date_fmt_buf[0] = 0;
2807     SetLastError(0xdeadbeef);
2808     ret = EnumDateFormatsA(enum_datetime_procA, lcid, 0);
2809     if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2810     {
2811         win_skip("0 for dwFlags is not supported\n");
2812     }
2813     else
2814     {
2815         ok(ret, "EnumDateFormatsA(0) error %d\n", GetLastError());
2816         trace("%s\n", date_fmt_buf);
2817         /* test the 1st enumerated format */
2818         if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2819         ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2820         ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2821         ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2822     }
2823
2824     trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n");
2825     date_fmt_buf[0] = 0;
2826     SetLastError(0xdeadbeef);
2827     ret = EnumDateFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2828     if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2829     {
2830         win_skip("LOCALE_USE_CP_ACP is not supported\n");
2831     }
2832     else
2833     {
2834         ok(ret, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2835         trace("%s\n", date_fmt_buf);
2836         /* test the 1st enumerated format */
2837         if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2838         ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2839         ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2840         ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2841     }
2842
2843     trace("EnumDateFormatsA DATE_SHORTDATE\n");
2844     date_fmt_buf[0] = 0;
2845     ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_SHORTDATE);
2846     ok(ret, "EnumDateFormatsA(DATE_SHORTDATE) error %d\n", GetLastError());
2847     trace("%s\n", date_fmt_buf);
2848     /* test the 1st enumerated format */
2849     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2850     ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2851     ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2852     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2853
2854     trace("EnumDateFormatsA DATE_LONGDATE\n");
2855     date_fmt_buf[0] = 0;
2856     ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_LONGDATE);
2857     ok(ret, "EnumDateFormatsA(DATE_LONGDATE) error %d\n", GetLastError());
2858     trace("%s\n", date_fmt_buf);
2859     /* test the 1st enumerated format */
2860     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2861     ret = GetLocaleInfoA(lcid, LOCALE_SLONGDATE, buf, sizeof(buf));
2862     ok(ret, "GetLocaleInfoA(LOCALE_SLONGDATE) error %d\n", GetLastError());
2863     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2864
2865     trace("EnumDateFormatsA DATE_YEARMONTH\n");
2866     date_fmt_buf[0] = 0;
2867     SetLastError(0xdeadbeef);
2868     ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_YEARMONTH);
2869     if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2870     {
2871         skip("DATE_YEARMONTH is only present on W2K and later\n");
2872         return;
2873     }
2874     ok(ret, "EnumDateFormatsA(DATE_YEARMONTH) error %d\n", GetLastError());
2875     trace("%s\n", date_fmt_buf);
2876     /* test the 1st enumerated format */
2877     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2878     ret = GetLocaleInfoA(lcid, LOCALE_SYEARMONTH, buf, sizeof(buf));
2879     ok(ret, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %d\n", GetLastError());
2880     ok(!lstrcmpA(date_fmt_buf, buf) || broken(!buf[0]) /* win9x */,
2881        "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2882 }
2883
2884 static void test_EnumTimeFormatsA(void)
2885 {
2886     char *p, buf[256];
2887     BOOL ret;
2888     LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2889
2890     trace("EnumTimeFormatsA 0\n");
2891     date_fmt_buf[0] = 0;
2892     ret = EnumTimeFormatsA(enum_datetime_procA, lcid, 0);
2893     ok(ret, "EnumTimeFormatsA(0) error %d\n", GetLastError());
2894     trace("%s\n", date_fmt_buf);
2895     /* test the 1st enumerated format */
2896     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2897     ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2898     ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2899     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2900
2901     trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n");
2902     date_fmt_buf[0] = 0;
2903     ret = EnumTimeFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2904     ok(ret, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2905     trace("%s\n", date_fmt_buf);
2906     /* test the 1st enumerated format */
2907     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2908     ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2909     ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2910     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2911 }
2912
2913 static void test_GetCPInfo(void)
2914 {
2915     BOOL ret;
2916     CPINFO cpinfo;
2917
2918     SetLastError(0xdeadbeef);
2919     ret = GetCPInfo(CP_SYMBOL, &cpinfo);
2920     ok(!ret, "GetCPInfo(CP_SYMBOL) should fail\n");
2921     ok(GetLastError() == ERROR_INVALID_PARAMETER,
2922        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2923
2924     SetLastError(0xdeadbeef);
2925     ret = GetCPInfo(CP_UTF7, &cpinfo);
2926     if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2927     {
2928         skip("Codepage CP_UTF7 is not installed/available\n");
2929     }
2930     else
2931     {
2932         ok(ret, "GetCPInfo(CP_UTF7) error %u\n", GetLastError());
2933         ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2934         ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2935         ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2936         ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2937         ok(cpinfo.MaxCharSize == 5, "expected 5, got 0x%x\n", cpinfo.MaxCharSize);
2938     }
2939
2940     SetLastError(0xdeadbeef);
2941     ret = GetCPInfo(CP_UTF8, &cpinfo);
2942     if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2943     {
2944         skip("Codepage CP_UTF8 is not installed/available\n");
2945     }
2946     else
2947     {
2948         ok(ret, "GetCPInfo(CP_UTF8) error %u\n", GetLastError());
2949         ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2950         ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2951         ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2952         ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2953         ok(cpinfo.MaxCharSize == 4 || broken(cpinfo.MaxCharSize == 3) /* win9x */,
2954            "expected 4, got %u\n", cpinfo.MaxCharSize);
2955     }
2956 }
2957
2958 /*
2959  * The CT_TYPE1 has varied over windows version.
2960  * The current target for correct behavior is windows 7.
2961  * There was a big shift between windows 2000 (first introduced) and windows Xp
2962  * Most of the old values below are from windows 2000.
2963  * A smaller subset of changes happened between windows Xp and Window vista/7
2964  */
2965 static void test_GetStringTypeW(void)
2966 {
2967     static const WCHAR blanks[] = {0x9, 0x20, 0xa0, 0x3000, 0xfeff};
2968     static const WORD blanks_new[] = {C1_SPACE | C1_CNTRL | C1_BLANK | C1_DEFINED,
2969                                  C1_SPACE | C1_BLANK | C1_DEFINED,
2970                                  C1_SPACE | C1_BLANK | C1_DEFINED,
2971                                  C1_SPACE | C1_BLANK | C1_DEFINED,
2972                                  C1_CNTRL | C1_BLANK | C1_DEFINED};
2973     static const WORD blanks_old[] ={C1_SPACE | C1_CNTRL | C1_BLANK,
2974                                     C1_SPACE | C1_BLANK,
2975                                     C1_SPACE | C1_BLANK,
2976                                     C1_SPACE | C1_BLANK,
2977                                     C1_SPACE | C1_BLANK};
2978
2979     static const WCHAR undefined[] = {0x378, 0x379, 0x604, 0xfff8, 0xfffe};
2980
2981                                   /* Lu, Ll, Lt */
2982     static const WCHAR alpha[] = {0x47, 0x67, 0x1c5};
2983     static const WORD alpha_old[] = {C1_UPPER | C1_ALPHA,
2984                                      C1_LOWER | C1_ALPHA,
2985                                      C1_UPPER | C1_LOWER | C1_ALPHA,
2986                                      C1_ALPHA};
2987
2988                                   /* Sk, Sk, Mn, So, Me */
2989     static const WCHAR oldpunc[] = { 0x2c2, 0x2e5, 0x322, 0x482, 0x6de,
2990                                  /* Sc, Sm, No,*/
2991                                      0xffe0, 0xffe9, 0x2153};
2992
2993                                 /* Lm, Nl, Cf, 0xad(Cf), 0x1f88 (Lt), Lo, Mc */
2994     static const WCHAR changed[] = {0x2b0, 0x2160, 0x600, 0xad, 0x1f88, 0x294, 0x903};
2995     static const WORD changed_old[] = { C1_PUNCT, C1_PUNCT, 0, C1_PUNCT, C1_UPPER | C1_ALPHA, C1_ALPHA, C1_PUNCT };
2996     static const WORD changed_xp[] = {C1_ALPHA | C1_DEFINED,
2997                                       C1_ALPHA | C1_DEFINED,
2998                                       C1_CNTRL | C1_DEFINED,
2999                                       C1_PUNCT | C1_DEFINED,
3000                                       C1_UPPER | C1_LOWER | C1_ALPHA | C1_DEFINED,
3001                                       C1_ALPHA | C1_LOWER | C1_DEFINED,
3002                                       C1_ALPHA | C1_DEFINED };
3003     static const WORD changed_new[] = { C1_ALPHA | C1_DEFINED,
3004                                       C1_ALPHA | C1_DEFINED,
3005                                       C1_CNTRL | C1_DEFINED,
3006                                       C1_PUNCT | C1_CNTRL | C1_DEFINED,
3007                                       C1_UPPER | C1_LOWER | C1_ALPHA | C1_DEFINED,
3008                                       C1_ALPHA | C1_DEFINED,
3009                                       C1_DEFINED
3010  };
3011                                 /* Pc,  Pd, Ps, Pe, Pi, Pf, Po*/
3012     static const WCHAR punct[] = { 0x5f, 0x2d, 0x28, 0x29, 0xab, 0xbb, 0x21 };
3013
3014     static const WCHAR punct_special[] = {0x24, 0x2b, 0x3c, 0x3e, 0x5e, 0x60,
3015                                           0x7c, 0x7e, 0xa2, 0xbe, 0xd7, 0xf7};
3016     static const WCHAR digit_special[] = {0xb2, 0xb3, 0xb9};
3017     static const WCHAR lower_special[] = {0x2071, 0x207f};
3018     static const WCHAR cntrl_special[] = {0x070f, 0x200c, 0x200d,
3019                   0x200e, 0x200f, 0x202a, 0x202b, 0x202c, 0x202d, 0x202e,
3020                   0x206a, 0x206b, 0x206c, 0x206d, 0x206e, 0x206f, 0xfeff,
3021                   0xfff9, 0xfffa, 0xfffb};
3022     static const WCHAR space_special[] = {0x09, 0x0d, 0x85};
3023
3024     WORD types[20];
3025     int i;
3026
3027     memset(types,0,sizeof(types));
3028     GetStringTypeW(CT_CTYPE1, blanks, 5, types);
3029     for (i = 0; i < 5; i++)
3030         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]);
3031
3032     memset(types,0,sizeof(types));
3033     GetStringTypeW(CT_CTYPE1, alpha, 3, types);
3034     for (i = 0; i < 3; i++)
3035         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]));
3036     memset(types,0,sizeof(types));
3037     GetStringTypeW(CT_CTYPE1, undefined, 5, types);
3038     for (i = 0; i < 5; i++)
3039         ok(types[i] == 0, "incorrect types returned for %x -> (%x != 0)\n",undefined[i], types[i]);
3040
3041     memset(types,0,sizeof(types));
3042     GetStringTypeW(CT_CTYPE1, oldpunc, 8, types);
3043     for (i = 0; i < 8; i++)
3044         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);
3045
3046     memset(types,0,sizeof(types));
3047     GetStringTypeW(CT_CTYPE1, changed, 7, types);
3048     for (i = 0; i < 7; i++)
3049         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]);
3050
3051     memset(types,0,sizeof(types));
3052     GetStringTypeW(CT_CTYPE1, punct, 7, types);
3053     for (i = 0; i < 7; i++)
3054         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));
3055
3056
3057     memset(types,0,sizeof(types));
3058     GetStringTypeW(CT_CTYPE1, punct_special, 12, types);
3059     for (i = 0; i < 12; i++)
3060         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);
3061
3062     memset(types,0,sizeof(types));
3063     GetStringTypeW(CT_CTYPE1, digit_special, 3, types);
3064     for (i = 0; i < 3; i++)
3065         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);
3066
3067     memset(types,0,sizeof(types));
3068     GetStringTypeW(CT_CTYPE1, lower_special, 2, types);
3069     for (i = 0; i < 2; i++)
3070         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);
3071
3072     memset(types,0,sizeof(types));
3073     GetStringTypeW(CT_CTYPE1, cntrl_special, 20, types);
3074     for (i = 0; i < 20; i++)
3075         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);
3076
3077     memset(types,0,sizeof(types));
3078     GetStringTypeW(CT_CTYPE1, space_special, 3, types);
3079     for (i = 0; i < 3; i++)
3080         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 );
3081 }
3082
3083 static void test_IdnToNameprepUnicode(void)
3084 {
3085     struct {
3086         DWORD in_len;
3087         const WCHAR in[64];
3088         DWORD ret;
3089         const WCHAR out[64];
3090         DWORD flags;
3091         DWORD err;
3092         DWORD todo;
3093     } test_data[] = {
3094         {
3095             5, {'t','e','s','t',0},
3096             5, {'t','e','s','t',0},
3097             0, 0xdeadbeef
3098         },
3099         {
3100             3, {'a',0xe111,'b'},
3101             0, {0},
3102             0, ERROR_INVALID_NAME
3103         },
3104         {
3105             4, {'t',0,'e',0},
3106             0, {0},
3107             0, ERROR_INVALID_NAME
3108         },
3109         {
3110             1, {'T',0},
3111             1, {'T',0},
3112             0, 0xdeadbeef
3113         },
3114         {
3115             1, {0},
3116             0, {0},
3117             0, ERROR_INVALID_NAME
3118         },
3119         {
3120             6, {' ','-','/','[',']',0},
3121             6, {' ','-','/','[',']',0},
3122             0, 0xdeadbeef
3123         },
3124         {
3125             3, {'a','-','a'},
3126             3, {'a','-','a'},
3127             IDN_USE_STD3_ASCII_RULES, 0xdeadbeef
3128         },
3129         {
3130             3, {'a','a','-'},
3131             0, {0},
3132             IDN_USE_STD3_ASCII_RULES, ERROR_INVALID_NAME
3133         },
3134         { /* FoldString is not working as expected when MAP_FOLDCZONE is specified (composition+compatibility) */
3135             10, {'T',0xdf,0x130,0x143,0x37a,0x6a,0x30c,' ',0xaa,0},
3136             12, {'t','s','s','i',0x307,0x144,' ',0x3b9,0x1f0,' ','a',0},
3137             0, 0xdeadbeef, TRUE
3138         },
3139         {
3140             11, {'t',0xad,0x34f,0x1806,0x180b,0x180c,0x180d,0x200b,0x200c,0x200d,0},
3141             2, {'t',0},
3142             0, 0xdeadbeef
3143         },
3144         { /* Another example of incorrectly working FoldString (composition) */
3145             2, {0x3b0, 0},
3146             2, {0x3b0, 0},
3147             0, 0xdeadbeef, TRUE
3148         },
3149         {
3150             2, {0x221, 0},
3151             0, {0},
3152             0, ERROR_NO_UNICODE_TRANSLATION
3153         },
3154         {
3155             2, {0x221, 0},
3156             2, {0x221, 0},
3157             IDN_ALLOW_UNASSIGNED, 0xdeadbeef
3158         },
3159         {
3160             5, {'a','.','.','a',0},
3161             0, {0},
3162             0, ERROR_INVALID_NAME
3163         },
3164         {
3165             3, {'a','.',0},
3166             3, {'a','.',0},
3167             0, 0xdeadbeef
3168         },
3169     };
3170
3171     WCHAR buf[1024];
3172     DWORD i, ret, err;
3173
3174     if (!pIdnToNameprepUnicode)
3175     {
3176         win_skip("IdnToNameprepUnicode is not available\n");
3177         return;
3178     }
3179
3180     ret = pIdnToNameprepUnicode(0, test_data[0].in,
3181             test_data[0].in_len, NULL, 0);
3182     ok(ret == test_data[0].ret, "ret = %d\n", ret);
3183
3184     SetLastError(0xdeadbeef);
3185     ret = pIdnToNameprepUnicode(0, test_data[1].in,
3186             test_data[1].in_len, NULL, 0);
3187     err = GetLastError();
3188     ok(ret == test_data[1].ret, "ret = %d\n", ret);
3189     ok(err == test_data[1].err, "err = %d\n", err);
3190
3191     SetLastError(0xdeadbeef);
3192     ret = pIdnToNameprepUnicode(0, test_data[0].in, -1,
3193             buf, sizeof(buf)/sizeof(WCHAR));
3194     err = GetLastError();
3195     ok(ret == test_data[0].ret, "ret = %d\n", ret);
3196     ok(err == 0xdeadbeef, "err = %d\n", err);
3197
3198     SetLastError(0xdeadbeef);
3199     ret = pIdnToNameprepUnicode(0, test_data[0].in, -2,
3200             buf, sizeof(buf)/sizeof(WCHAR));
3201     err = GetLastError();
3202     ok(ret == 0, "ret = %d\n", ret);
3203     ok(err == ERROR_INVALID_PARAMETER, "err = %d\n", err);
3204
3205     SetLastError(0xdeadbeef);
3206     ret = pIdnToNameprepUnicode(0, test_data[0].in, 0,
3207             buf, sizeof(buf)/sizeof(WCHAR));
3208     err = GetLastError();
3209     ok(ret == 0, "ret = %d\n", ret);
3210     ok(err == ERROR_INVALID_NAME, "err = %d\n", err);
3211
3212     ret = pIdnToNameprepUnicode(IDN_ALLOW_UNASSIGNED|IDN_USE_STD3_ASCII_RULES,
3213             test_data[0].in, -1, buf, sizeof(buf)/sizeof(WCHAR));
3214     ok(ret == test_data[0].ret, "ret = %d\n", ret);
3215
3216     SetLastError(0xdeadbeef);
3217     ret = pIdnToNameprepUnicode(0, NULL, 0, NULL, 0);
3218     err = GetLastError();
3219     ok(ret == 0, "ret = %d\n", ret);
3220     ok(err == ERROR_INVALID_PARAMETER, "err = %d\n", err);
3221
3222     SetLastError(0xdeadbeef);
3223     ret = pIdnToNameprepUnicode(4, NULL, 0, NULL, 0);
3224     err = GetLastError();
3225     ok(ret == 0, "ret = %d\n", ret);
3226     ok(err == ERROR_INVALID_FLAGS, "err = %d\n", err);
3227
3228     for (i=0; i<sizeof(test_data)/sizeof(*test_data); i++)
3229     {
3230         SetLastError(0xdeadbeef);
3231         ret = pIdnToNameprepUnicode(test_data[i].flags, test_data[i].in,
3232                 test_data[i].in_len, buf, sizeof(buf)/sizeof(WCHAR));
3233         err = GetLastError();
3234         if(!test_data[i].todo) {
3235             ok(ret == test_data[i].ret, "%d) ret = %d\n", i, ret);
3236             ok(err == test_data[i].err, "%d) err = %d\n", i, err);
3237             ok(!memcmp(test_data[i].out, buf, ret*sizeof(WCHAR)),
3238                     "%d) buf = %s\n", i, wine_dbgstr_wn(buf, ret));
3239         }else {
3240             todo_wine ok(!memcmp(test_data[i].out, buf, ret*sizeof(WCHAR)),
3241                     "%d) buf = %s\n", i, wine_dbgstr_wn(buf, ret));
3242         }
3243     }
3244 }
3245
3246 static void test_IdnToAscii(void)
3247 {
3248     struct {
3249         DWORD in_len;
3250         const WCHAR in[64];
3251         DWORD ret;
3252         const WCHAR out[64];
3253         DWORD flags;
3254         DWORD err;
3255     } test_data[] = {
3256         {
3257             5, {'T','e','s','t',0},
3258             5, {'T','e','s','t',0},
3259             0, 0xdeadbeef
3260         },
3261         {
3262             5, {'T','e',0x017c,'s','t',0},
3263             12, {'x','n','-','-','t','e','s','t','-','c','b','b',0},
3264             0, 0xdeadbeef
3265         },
3266         {
3267             12, {'t','e',0x0105,'s','t','.','t','e',0x017c,'s','t',0},
3268             26, {'x','n','-','-','t','e','s','t','-','c','t','a','.','x','n','-','-','t','e','s','t','-','c','b','b',0},
3269             0, 0xdeadbeef
3270         },
3271         {
3272             3, {0x0105,'.',0},
3273             9, {'x','n','-','-','2','d','a','.',0},
3274             0, 0xdeadbeef
3275         },
3276         {
3277             10, {'h','t','t','p',':','/','/','t',0x0106,0},
3278             17, {'x','n','-','-','h','t','t','p',':','/','/','t','-','7','8','a',0},
3279             0, 0xdeadbeef
3280         },
3281         {
3282             10, {0x4e3a,0x8bf4,0x4e0d,0x4ed6,0x5011,0x10d,0x11b,0x305c,0x306a,0},
3283             35, {'x','n','-','-','b','e','a','2','a','1','6','3','1','a','v','b','a',
3284                 'v','4','4','t','y','h','a','3','2','b','9','1','e','g','s','2','t',0},
3285             0, 0xdeadbeef
3286         },
3287         {
3288             2, {0x221,0},
3289             8, {'x','n','-','-','6','l','a',0},
3290             IDN_ALLOW_UNASSIGNED, 0xdeadbeef
3291         },
3292     };
3293
3294     WCHAR buf[1024];
3295     DWORD i, ret, err;
3296
3297     if (!pIdnToAscii)
3298     {
3299         win_skip("IdnToAscii is not available\n");
3300         return;
3301     }
3302
3303     for (i=0; i<sizeof(test_data)/sizeof(*test_data); i++)
3304     {
3305         SetLastError(0xdeadbeef);
3306         ret = pIdnToAscii(test_data[i].flags, test_data[i].in,
3307                 test_data[i].in_len, buf, sizeof(buf));
3308         err = GetLastError();
3309         ok(ret == test_data[i].ret, "%d) ret = %d\n", i, ret);
3310         ok(err == test_data[i].err, "%d) err = %d\n", i, err);
3311         ok(!memcmp(test_data[i].out, buf, ret*sizeof(WCHAR)),
3312                 "%d) buf = %s\n", i, wine_dbgstr_wn(buf, ret));
3313     }
3314 }
3315
3316 static void test_IdnToUnicode(void)
3317 {
3318     struct {
3319         DWORD in_len;
3320         const WCHAR in[64];
3321         DWORD ret;
3322         const WCHAR out[64];
3323         DWORD flags;
3324         DWORD err;
3325     } test_data[] = {
3326         {
3327             5, {'T','e','s','.',0},
3328             5, {'T','e','s','.',0},
3329             0, 0xdeadbeef
3330         },
3331         {
3332             2, {0x105,0},
3333             0, {0},
3334             0, ERROR_INVALID_NAME
3335         },
3336         {
3337             33, {'x','n','-','-','4','d','b','c','a','g','d','a','h','y','m','b',
3338                 'x','e','k','h','e','h','6','e','0','a','7','f','e','i','0','b',0},
3339             23, {0x05dc,0x05de,0x05d4,0x05d4,0x05dd,0x05e4,0x05e9,0x05d5,0x05d8,
3340                 0x05dc,0x05d0,0x05de,0x05d3,0x05d1,0x05e8,0x05d9,0x05dd,0x05e2,
3341                 0x05d1,0x05e8,0x05d9,0x05ea,0},
3342             0, 0xdeadbeef
3343         },
3344         {
3345             34, {'t','e','s','t','.','x','n','-','-','k','d','a','9','a','g','5','e',
3346                 '9','j','n','f','s','j','.','x','n','-','-','p','d','-','f','n','a'},
3347             16, {'t','e','s','t','.',0x0105,0x0119,0x015b,0x0107,
3348                 0x0142,0x00f3,0x017c,'.','p',0x0119,'d'},
3349             0, 0xdeadbeef
3350         },
3351         {
3352             64, {'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
3353                 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
3354                 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
3355                 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a'},
3356             0, {0},
3357             0, ERROR_INVALID_NAME
3358         },
3359         {
3360             8, {'x','n','-','-','6','l','a',0},
3361             2, {0x221,0},
3362             IDN_ALLOW_UNASSIGNED, 0xdeadbeef
3363         },
3364     };
3365
3366     WCHAR buf[1024];
3367     DWORD i, ret, err;
3368
3369     if (!pIdnToUnicode)
3370     {
3371         win_skip("IdnToUnicode is not available\n");
3372         return;
3373     }
3374
3375     for (i=0; i<sizeof(test_data)/sizeof(*test_data); i++)
3376     {
3377         SetLastError(0xdeadbeef);
3378         ret = pIdnToUnicode(test_data[i].flags, test_data[i].in,
3379                 test_data[i].in_len, buf, sizeof(buf));
3380         err = GetLastError();
3381         ok(ret == test_data[i].ret, "%d) ret = %d\n", i, ret);
3382         ok(err == test_data[i].err, "%d) err = %d\n", i, err);
3383         ok(!memcmp(test_data[i].out, buf, ret*sizeof(WCHAR)),
3384                 "%d) buf = %s\n", i, wine_dbgstr_wn(buf, ret));
3385     }
3386 }
3387
3388 static void test_GetLocaleInfoEx(void)
3389 {
3390     static const WCHAR enW[] = {'e','n',0};
3391     WCHAR bufferW[80];
3392     INT ret;
3393
3394     if (!pGetLocaleInfoEx)
3395     {
3396         win_skip("GetLocaleInfoEx not supported\n");
3397         return;
3398     }
3399
3400     ret = pGetLocaleInfoEx(enW, LOCALE_SNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3401     ok(ret || broken(ret == 0) /* Vista */, "got %d\n", ret);
3402     if (ret)
3403     {
3404         static const WCHAR statesW[] = {'U','n','i','t','e','d',' ','S','t','a','t','e','s',0};
3405         static const WCHAR dummyW[] = {'d','u','m','m','y',0};
3406         static const WCHAR enusW[] = {'e','n','-','U','S',0};
3407         static const WCHAR usaW[] = {'U','S','A',0};
3408         static const WCHAR enuW[] = {'E','N','U',0};
3409         const struct neutralsublang_name_t *ptr = neutralsublang_names;
3410         DWORD val;
3411
3412         ok(ret == lstrlenW(bufferW)+1, "got %d\n", ret);
3413         ok(!lstrcmpW(bufferW, enW), "got %s\n", wine_dbgstr_w(bufferW));
3414
3415         SetLastError(0xdeadbeef);
3416         ret = pGetLocaleInfoEx(enW, LOCALE_SNAME, bufferW, 2);
3417         ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d, %d\n", ret, GetLastError());
3418
3419         SetLastError(0xdeadbeef);
3420         ret = pGetLocaleInfoEx(enW, LOCALE_SNAME, NULL, 0);
3421         ok(ret == 3 && GetLastError() == 0xdeadbeef, "got %d, %d\n", ret, GetLastError());
3422
3423         ret = pGetLocaleInfoEx(enusW, LOCALE_SNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3424         ok(ret == lstrlenW(bufferW)+1, "got %d\n", ret);
3425         ok(!lstrcmpW(bufferW, enusW), "got %s\n", wine_dbgstr_w(bufferW));
3426
3427         ret = pGetLocaleInfoEx(enW, LOCALE_SABBREVCTRYNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3428         ok(ret == lstrlenW(bufferW)+1, "got %d\n", ret);
3429         ok(!lstrcmpW(bufferW, usaW), "got %s\n", wine_dbgstr_w(bufferW));
3430
3431         ret = pGetLocaleInfoEx(enW, LOCALE_SABBREVLANGNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3432         ok(ret == lstrlenW(bufferW)+1, "got %d\n", ret);
3433         ok(!lstrcmpW(bufferW, enuW), "got %s\n", wine_dbgstr_w(bufferW));
3434
3435         ret = pGetLocaleInfoEx(enW, LOCALE_SCOUNTRY, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3436         ok(ret == lstrlenW(bufferW)+1, "got %d\n", ret);
3437         ok(!lstrcmpW(bufferW, statesW), "got %s\n", wine_dbgstr_w(bufferW));
3438
3439         bufferW[0] = 0;
3440         SetLastError(0xdeadbeef);
3441         ret = pGetLocaleInfoEx(dummyW, LOCALE_SNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3442         ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError());
3443
3444         while (*ptr->name)
3445         {
3446             val = 0;
3447             pGetLocaleInfoEx(ptr->name, LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER, (WCHAR*)&val, sizeof(val)/sizeof(WCHAR));
3448             if (ptr->todo)
3449             todo_wine
3450                 ok(val == ptr->lcid, "%s: got wrong lcid 0x%04x, expected 0x%04x\n", wine_dbgstr_w(ptr->name), val, ptr->lcid);
3451             else
3452                 ok(val == ptr->lcid, "%s: got wrong lcid 0x%04x, expected 0x%04x\n", wine_dbgstr_w(ptr->name), val, ptr->lcid);
3453             bufferW[0] = 0;
3454             ret = pGetLocaleInfoEx(ptr->name, LOCALE_SNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3455             ok(ret == lstrlenW(bufferW)+1, "%s: got ret value %d\n", wine_dbgstr_w(ptr->name), ret);
3456             ok(!lstrcmpW(bufferW, ptr->name), "%s: got wrong LOCALE_SNAME %s\n", wine_dbgstr_w(ptr->name), wine_dbgstr_w(bufferW));
3457             ptr++;
3458         }
3459     }
3460 }
3461
3462 static void test_IsValidLocaleName(void)
3463 {
3464     static const WCHAR enusW[] = {'e','n','-','U','S',0};
3465     static const WCHAR zzW[] = {'z','z',0};
3466     static const WCHAR zzzzW[] = {'z','z','-','Z','Z',0};
3467     BOOL ret;
3468
3469     if (!pIsValidLocaleName)
3470     {
3471         win_skip("IsValidLocaleName not supported\n");
3472         return;
3473     }
3474
3475     ret = pIsValidLocaleName(enusW);
3476     ok(ret, "IsValidLocaleName failed\n");
3477     ret = pIsValidLocaleName(zzW);
3478     ok(!ret, "IsValidLocaleName should have failed\n");
3479     ret = pIsValidLocaleName(zzzzW);
3480     ok(!ret, "IsValidLocaleName should have failed\n");
3481 }
3482
3483 static void test_CompareStringOrdinal(void)
3484 {
3485     INT ret;
3486     WCHAR test1[] = { 't','e','s','t',0 };
3487     WCHAR test2[] = { 'T','e','S','t',0 };
3488     WCHAR test3[] = { 't','e','s','t','3',0 };
3489     WCHAR null1[] = { 'a',0,'a',0 };
3490     WCHAR null2[] = { 'a',0,'b',0 };
3491     WCHAR bills1[] = { 'b','i','l','l','\'','s',0 };
3492     WCHAR bills2[] = { 'b','i','l','l','s',0 };
3493     WCHAR coop1[] = { 'c','o','-','o','p',0 };
3494     WCHAR coop2[] = { 'c','o','o','p',0 };
3495     WCHAR nonascii1[] = { 0x0102,0 };
3496     WCHAR nonascii2[] = { 0x0201,0 };
3497
3498     if (!pCompareStringOrdinal)
3499     {
3500         win_skip("CompareStringOrdinal not supported\n");
3501         return;
3502     }
3503
3504     /* Check errors */
3505     SetLastError(0xdeadbeef);
3506     ret = pCompareStringOrdinal(NULL, 0, NULL, 0, FALSE);
3507     ok(!ret, "Got %u, expected 0\n", ret);
3508     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got %x, expected %x\n", GetLastError(), ERROR_INVALID_PARAMETER);
3509     SetLastError(0xdeadbeef);
3510     ret = pCompareStringOrdinal(test1, -1, NULL, 0, FALSE);
3511     ok(!ret, "Got %u, expected 0\n", ret);
3512     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got %x, expected %x\n", GetLastError(), ERROR_INVALID_PARAMETER);
3513     SetLastError(0xdeadbeef);
3514     ret = pCompareStringOrdinal(NULL, 0, test1, -1, FALSE);
3515     ok(!ret, "Got %u, expected 0\n", ret);
3516     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got %x, expected %x\n", GetLastError(), ERROR_INVALID_PARAMETER);
3517
3518     /* Check case */
3519     ret = pCompareStringOrdinal(test1, -1, test1, -1, FALSE);
3520     ok(ret == CSTR_EQUAL, "Got %u, expected %u\n", ret, CSTR_EQUAL);
3521     ret = pCompareStringOrdinal(test1, -1, test2, -1, FALSE);
3522     ok(ret == CSTR_GREATER_THAN, "Got %u, expected %u\n", ret, CSTR_GREATER_THAN);
3523     ret = pCompareStringOrdinal(test2, -1, test1, -1, FALSE);
3524     ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
3525     ret = pCompareStringOrdinal(test1, -1, test2, -1, TRUE);
3526     ok(ret == CSTR_EQUAL, "Got %u, expected %u\n", ret, CSTR_EQUAL);
3527
3528     /* Check different sizes */
3529     ret = pCompareStringOrdinal(test1, 3, test2, -1, TRUE);
3530     ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
3531     ret = pCompareStringOrdinal(test1, -1, test2, 3, TRUE);
3532     ok(ret == CSTR_GREATER_THAN, "Got %u, expected %u\n", ret, CSTR_GREATER_THAN);
3533
3534     /* Check null character */
3535     ret = pCompareStringOrdinal(null1, 3, null2, 3, FALSE);
3536     ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
3537     ret = pCompareStringOrdinal(null1, 3, null2, 3, TRUE);
3538     ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
3539     ret = pCompareStringOrdinal(test1, 5, test3, 5, FALSE);
3540     ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
3541     ret = pCompareStringOrdinal(test1, 4, test1, 5, FALSE);
3542     ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
3543
3544     /* Check ordinal behaviour */
3545     ret = pCompareStringOrdinal(bills1, -1, bills2, -1, FALSE);
3546     ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
3547     ret = pCompareStringOrdinal(coop2, -1, coop1, -1, FALSE);
3548     ok(ret == CSTR_GREATER_THAN, "Got %u, expected %u\n", ret, CSTR_GREATER_THAN);
3549     ret = pCompareStringOrdinal(nonascii1, -1, nonascii2, -1, FALSE);
3550     ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
3551     ret = pCompareStringOrdinal(nonascii1, -1, nonascii2, -1, TRUE);
3552     ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
3553 }
3554
3555 START_TEST(locale)
3556 {
3557   InitFunctionPointers();
3558
3559   test_EnumTimeFormatsA();
3560   test_EnumDateFormatsA();
3561   test_GetLocaleInfoA();
3562   test_GetLocaleInfoW();
3563   test_GetLocaleInfoEx();
3564   test_GetTimeFormatA();
3565   test_GetDateFormatA();
3566   test_GetDateFormatW();
3567   test_GetCurrencyFormatA(); /* Also tests the W version */
3568   test_GetNumberFormatA();   /* Also tests the W version */
3569   test_CompareStringA();
3570   test_LCMapStringA();
3571   test_LCMapStringW();
3572   test_LCMapStringEx();
3573   test_LocaleNameToLCID();
3574   test_FoldStringA();
3575   test_FoldStringW();
3576   test_ConvertDefaultLocale();
3577   test_EnumSystemLanguageGroupsA();
3578   test_EnumSystemLocalesEx();
3579   test_EnumLanguageGroupLocalesA();
3580   test_SetLocaleInfoA();
3581   test_EnumUILanguageA();
3582   test_GetCPInfo();
3583   test_GetStringTypeW();
3584   test_IdnToNameprepUnicode();
3585   test_IdnToAscii();
3586   test_IdnToUnicode();
3587   test_IsValidLocaleName();
3588   test_CompareStringOrdinal();
3589   /* this requires collation table patch to make it MS compatible */
3590   if (0) test_sorting();
3591 }