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