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