wbemprox: Support overriding the CIM to VARIANT type mapping for method parameters.
[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
1922             *buffer = 0;
1923             ret = pLCIDToLocaleName(lcid, buffer, sizeof(buffer)/sizeof(WCHAR), 0);
1924             ok(ret > 0, "%s: got %d\n", wine_dbgstr_w(ptr->name), ret);
1925             ok(lstrcmpW(ptr->name, buffer), "%s: got wrong locale name %s\n",
1926                 wine_dbgstr_w(ptr->name), wine_dbgstr_w(buffer));
1927
1928             ptr++;
1929         }
1930     }
1931 }
1932
1933 /* this requires collation table patch to make it MS compatible */
1934 static const char * const strings_sorted[] =
1935 {
1936 "'",
1937 "-",
1938 "!",
1939 "\"",
1940 ".",
1941 ":",
1942 "\\",
1943 "_",
1944 "`",
1945 "{",
1946 "}",
1947 "+",
1948 "0",
1949 "1",
1950 "2",
1951 "3",
1952 "4",
1953 "5",
1954 "6",
1955 "7",
1956 "8",
1957 "9",
1958 "a",
1959 "A",
1960 "b",
1961 "B",
1962 "c",
1963 "C"
1964 };
1965
1966 static const char * const strings[] =
1967 {
1968 "C",
1969 "\"",
1970 "9",
1971 "'",
1972 "}",
1973 "-",
1974 "7",
1975 "+",
1976 "`",
1977 "1",
1978 "a",
1979 "5",
1980 "\\",
1981 "8",
1982 "B",
1983 "3",
1984 "_",
1985 "6",
1986 "{",
1987 "2",
1988 "c",
1989 "4",
1990 "!",
1991 "0",
1992 "A",
1993 ":",
1994 "b",
1995 "."
1996 };
1997
1998 static int compare_string1(const void *e1, const void *e2)
1999 {
2000     const char *s1 = *(const char *const *)e1;
2001     const char *s2 = *(const char *const *)e2;
2002
2003     return lstrcmpA(s1, s2);
2004 }
2005
2006 static int compare_string2(const void *e1, const void *e2)
2007 {
2008     const char *s1 = *(const char *const *)e1;
2009     const char *s2 = *(const char *const *)e2;
2010
2011     return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
2012 }
2013
2014 static int compare_string3(const void *e1, const void *e2)
2015 {
2016     const char *s1 = *(const char *const *)e1;
2017     const char *s2 = *(const char *const *)e2;
2018     char key1[256], key2[256];
2019
2020     LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
2021     LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
2022     return strcmp(key1, key2);
2023 }
2024
2025 static void test_sorting(void)
2026 {
2027     char buf[256];
2028     char **str_buf = (char **)buf;
2029     int i;
2030
2031     assert(sizeof(buf) >= sizeof(strings));
2032
2033     /* 1. sort using lstrcmpA */
2034     memcpy(buf, strings, sizeof(strings));
2035     qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
2036     for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
2037     {
2038         ok(!strcmp(strings_sorted[i], str_buf[i]),
2039            "qsort using lstrcmpA failed for element %d\n", i);
2040     }
2041     /* 2. sort using CompareStringA */
2042     memcpy(buf, strings, sizeof(strings));
2043     qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
2044     for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
2045     {
2046         ok(!strcmp(strings_sorted[i], str_buf[i]),
2047            "qsort using CompareStringA failed for element %d\n", i);
2048     }
2049     /* 3. sort using sort keys */
2050     memcpy(buf, strings, sizeof(strings));
2051     qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
2052     for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
2053     {
2054         ok(!strcmp(strings_sorted[i], str_buf[i]),
2055            "qsort using sort keys failed for element %d\n", i);
2056     }
2057 }
2058
2059 static void test_FoldStringA(void)
2060 {
2061   int ret, i, j;
2062   BOOL is_special;
2063   char src[256], dst[256];
2064   static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0'  };
2065   static const char digits_dst[] = { '1','2','3','\0'  };
2066   static const char composite_src[] =
2067   {
2068     0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
2069     0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
2070     0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
2071     0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
2072     0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
2073     0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
2074     0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
2075     0xfb,0xfc,0xfd,0xff,'\0'
2076   };
2077   static const char composite_dst[] =
2078   {
2079     0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
2080     0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
2081     0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
2082     0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
2083     0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
2084     0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
2085     0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
2086     0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
2087     0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
2088     0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
2089     0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
2090     0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
2091     0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
2092     0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
2093     0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
2094   };
2095   static const char composite_dst_alt[] =
2096   {
2097     0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
2098     0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
2099     0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
2100     0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
2101     0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
2102     0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
2103     0x4f,0x7e,0x4f,0xa8,0xd8,0x55,0x60,0x55,
2104     0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,0x61,
2105     0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,0x61,
2106     0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,0x65,
2107     0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,0x69,
2108     0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,0x6f,
2109     0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,0x6f,
2110     0xa8,0xf8,0x75,0x60,0x75,0xb4,0x75,0x5e,
2111     0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
2112   };
2113   static const char ligatures_src[] =
2114   {
2115     0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
2116   };
2117   static const char ligatures_dst[] =
2118   {
2119     'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
2120   };
2121   static const struct special
2122   {
2123     char src;
2124     char dst[4];
2125   }  foldczone_special[] =
2126   {
2127     /* src   dst                   */
2128     { 0x85, { 0x2e, 0x2e, 0x2e, 0x00 } },
2129     { 0x98, { 0x20, 0x7e, 0x00 } },
2130     { 0x99, { 0x54, 0x4d, 0x00 } },
2131     { 0xa0, { 0x20, 0x00 } },
2132     { 0xa8, { 0x20, 0xa8, 0x00 } },
2133     { 0xaa, { 0x61, 0x00 } },
2134     { 0xaf, { 0x20, 0xaf, 0x00 } },
2135     { 0xb2, { 0x32, 0x00 } },
2136     { 0xb3, { 0x33, 0x00 } },
2137     { 0xb4, { 0x20, 0xb4, 0x00 } },
2138     { 0xb8, { 0x20, 0xb8, 0x00 } },
2139     { 0xb9, { 0x31, 0x00 } },
2140     { 0xba, { 0x6f, 0x00 } },
2141     { 0xbc, { 0x31, 0x2f, 0x34, 0x00 } },
2142     { 0xbd, { 0x31, 0x2f, 0x32, 0x00 } },
2143     { 0xbe, { 0x33, 0x2f, 0x34, 0x00 } },
2144     { 0x00 }
2145   };
2146
2147   if (!pFoldStringA)
2148     return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
2149
2150   /* these tests are locale specific */
2151   if (GetACP() != 1252)
2152   {
2153       trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
2154       return;
2155   }
2156
2157   /* MAP_FOLDDIGITS */
2158   SetLastError(0);
2159   ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
2160   if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2161   {
2162     win_skip("FoldStringA is not implemented\n");
2163     return;
2164   }
2165   ok(ret == 4, "Expected ret == 4, got %d, error %d\n", ret, GetLastError());
2166   ok(strcmp(dst, digits_dst) == 0,
2167      "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
2168   for (i = 1; i < 256; i++)
2169   {
2170     if (!strchr(digits_src, i))
2171     {
2172       src[0] = i;
2173       src[1] = '\0';
2174       SetLastError(0);
2175       ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
2176       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2177       ok(dst[0] == src[0],
2178          "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
2179     }
2180   }
2181
2182   /* MAP_EXPAND_LIGATURES */
2183   SetLastError(0);
2184   ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
2185   /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
2186   if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
2187     ok(ret == sizeof(ligatures_dst), "Got %d, error %d\n", ret, GetLastError());
2188     ok(strcmp(dst, ligatures_dst) == 0,
2189        "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
2190     for (i = 1; i < 256; i++)
2191     {
2192       if (!strchr(ligatures_src, i))
2193       {
2194         src[0] = i;
2195         src[1] = '\0';
2196         SetLastError(0);
2197         ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
2198         if (ret == 3)
2199         {
2200           /* Vista */
2201           ok((i == 0xDC && lstrcmpA(dst, "UE") == 0) ||
2202              (i == 0xFC && lstrcmpA(dst, "ue") == 0),
2203              "Got %s for %d\n", dst, i);
2204         }
2205         else
2206         {
2207           ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2208           ok(dst[0] == src[0],
2209              "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
2210         }
2211       }
2212     }
2213   }
2214
2215   /* MAP_COMPOSITE */
2216   SetLastError(0);
2217   ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
2218   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2219   ok(ret == 121 || ret == 119, "Expected 121 or 119, got %d\n", ret);
2220   ok(strcmp(dst, composite_dst) == 0 || strcmp(dst, composite_dst_alt) == 0,
2221      "MAP_COMPOSITE: Mismatch, got '%s'\n", dst);
2222
2223   for (i = 1; i < 256; i++)
2224   {
2225     if (!strchr(composite_src, i))
2226     {
2227       src[0] = i;
2228       src[1] = '\0';
2229       SetLastError(0);
2230       ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
2231       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2232       ok(dst[0] == src[0],
2233          "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
2234          (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
2235     }
2236   }
2237
2238   /* MAP_FOLDCZONE */
2239   for (i = 1; i < 256; i++)
2240   {
2241     src[0] = i;
2242     src[1] = '\0';
2243     SetLastError(0);
2244     ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
2245     is_special = FALSE;
2246     for (j = 0; foldczone_special[j].src != 0 && ! is_special; j++)
2247     {
2248       if (foldczone_special[j].src == src[0])
2249       {
2250         ok(ret == 2 || ret == lstrlenA(foldczone_special[j].dst) + 1,
2251            "Expected ret == 2 or %d, got %d, error %d\n",
2252            lstrlenA(foldczone_special[j].dst) + 1, ret, GetLastError());
2253         ok(src[0] == dst[0] || lstrcmpA(foldczone_special[j].dst, dst) == 0,
2254            "MAP_FOLDCZONE: string mismatch for 0x%02x\n",
2255            (unsigned char)src[0]);
2256         is_special = TRUE;
2257       }
2258     }
2259     if (! is_special)
2260     {
2261       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2262       ok(src[0] == dst[0],
2263          "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
2264          (unsigned char)src[0], (unsigned char)dst[0]);
2265     }
2266   }
2267
2268   /* MAP_PRECOMPOSED */
2269   for (i = 1; i < 256; i++)
2270   {
2271     src[0] = i;
2272     src[1] = '\0';
2273     SetLastError(0);
2274     ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
2275     ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2276     ok(src[0] == dst[0],
2277        "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
2278        (unsigned char)src[0], (unsigned char)dst[0]);
2279   }
2280 }
2281
2282 static void test_FoldStringW(void)
2283 {
2284   int ret;
2285   unsigned int i, j;
2286   WCHAR src[256], dst[256], ch, prev_ch = 1;
2287   static const DWORD badFlags[] =
2288   {
2289     0,
2290     MAP_PRECOMPOSED|MAP_COMPOSITE,
2291     MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
2292     MAP_COMPOSITE|MAP_EXPAND_LIGATURES
2293   };
2294   /* Ranges of digits 0-9 : Must be sorted! */
2295   static const WCHAR digitRanges[] =
2296   {
2297     0x0030, /* '0'-'9' */
2298     0x0660, /* Eastern Arabic */
2299     0x06F0, /* Arabic - Hindu */
2300     0x0966, /* Devengari */
2301     0x09E6, /* Bengalii */
2302     0x0A66, /* Gurmukhi */
2303     0x0AE6, /* Gujarati */
2304     0x0B66, /* Oriya */
2305     0x0BE6, /* Tamil - No 0 */
2306     0x0C66, /* Telugu */
2307     0x0CE6, /* Kannada */
2308     0x0D66, /* Maylayalam */
2309     0x0E50, /* Thai */
2310     0x0ED0, /* Laos */
2311     0x0F29, /* Tibet - 0 is out of sequence */
2312     0x2070, /* Superscript - 1, 2, 3 are out of sequence */
2313     0x2080, /* Subscript */
2314     0x245F, /* Circled - 0 is out of sequence */
2315     0x2473, /* Bracketed */
2316     0x2487, /* Full stop */
2317     0x2775, /* Inverted circled - No 0 */
2318     0x277F, /* Patterned circled - No 0 */
2319     0x2789, /* Inverted Patterned circled - No 0 */
2320     0x3020, /* Hangzhou */
2321     0xff10, /* Pliene chasse (?) */
2322     0xffff  /* Terminator */
2323   };
2324   /* Digits which are represented, but out of sequence */
2325   static const WCHAR outOfSequenceDigits[] =
2326   {
2327       0xB9,   /* Superscript 1 */
2328       0xB2,   /* Superscript 2 */
2329       0xB3,   /* Superscript 3 */
2330       0x0F33, /* Tibetan half zero */
2331       0x24EA, /* Circled 0 */
2332       0x3007, /* Ideographic number zero */
2333       '\0'    /* Terminator */
2334   };
2335   /* Digits in digitRanges for which no representation is available */
2336   static const WCHAR noDigitAvailable[] =
2337   {
2338       0x0BE6, /* No Tamil 0 */
2339       0x0F29, /* No Tibetan half zero (out of sequence) */
2340       0x2473, /* No Bracketed 0 */
2341       0x2487, /* No 0 Full stop */
2342       0x2775, /* No inverted circled 0 */
2343       0x277F, /* No patterned circled */
2344       0x2789, /* No inverted Patterned circled */
2345       0x3020, /* No Hangzhou 0 */
2346       '\0'    /* Terminator */
2347   };
2348   static const WCHAR foldczone_src[] =
2349   {
2350     'W',    'i',    'n',    'e',    0x0348, 0x0551, 0x1323, 0x280d,
2351     0xff37, 0xff49, 0xff4e, 0xff45, '\0'
2352   };
2353   static const WCHAR foldczone_dst[] =
2354   {
2355     'W','i','n','e',0x0348,0x0551,0x1323,0x280d,'W','i','n','e','\0'
2356   };
2357   static const WCHAR foldczone_todo_src[] =
2358   {
2359       0x3c5,0x308,0x6a,0x30c,0xa0,0xaa,0
2360   };
2361   static const WCHAR foldczone_todo_dst[] =
2362   {
2363       0x3cb,0x1f0,' ','a',0
2364   };
2365   static const WCHAR foldczone_todo_broken_dst[] =
2366   {
2367       0x3cb,0x1f0,0xa0,0xaa,0
2368   };
2369   static const WCHAR ligatures_src[] =
2370   {
2371     'W',    'i',    'n',    'e',    0x03a6, 0x03b9, 0x03bd, 0x03b5,
2372     0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
2373     0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
2374     0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
2375     0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
2376     0xfb04, 0xfb05, 0xfb06, '\0'
2377   };
2378   static const WCHAR ligatures_dst[] =
2379   {
2380     'W','i','n','e',0x03a6,0x03b9,0x03bd,0x03b5,
2381     'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
2382     'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
2383     'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
2384     0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
2385     'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
2386   };
2387
2388   if (!pFoldStringW)
2389   {
2390     win_skip("FoldStringW is not available\n");
2391     return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
2392   }
2393
2394   /* Invalid flag combinations */
2395   for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
2396   {
2397     src[0] = dst[0] = '\0';
2398     SetLastError(0);
2399     ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
2400     if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
2401     {
2402       win_skip("FoldStringW is not implemented\n");
2403       return;
2404     }
2405     ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
2406        "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2407   }
2408
2409   /* src & dst cannot be the same */
2410   SetLastError(0);
2411   ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
2412   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2413       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2414
2415   /* src can't be NULL */
2416   SetLastError(0);
2417   ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
2418   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2419       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2420
2421   /* srclen can't be 0 */
2422   SetLastError(0);
2423   ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
2424   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2425       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2426
2427   /* dstlen can't be < 0 */
2428   SetLastError(0);
2429   ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
2430   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2431       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2432
2433   /* Ret includes terminating NUL which is appended if srclen = -1 */
2434   SetLastError(0);
2435   src[0] = 'A';
2436   src[1] = '\0';
2437   dst[0] = '\0';
2438   ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
2439   ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2440   ok(dst[0] == 'A' && dst[1] == '\0',
2441      "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%d\n",
2442      'A', '\0', ret, dst[0], dst[1], GetLastError());
2443
2444   /* If size is given, result is not NUL terminated */
2445   SetLastError(0);
2446   src[0] = 'A';
2447   src[1] = 'A';
2448   dst[0] = 'X';
2449   dst[1] = 'X';
2450   ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
2451   ok(ret == 1, "Expected ret == 1, got %d, error %d\n", ret, GetLastError());
2452   ok(dst[0] == 'A' && dst[1] == 'X',
2453      "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%d\n",
2454      'A','X', ret, dst[0], dst[1], GetLastError());
2455
2456   /* MAP_FOLDDIGITS */
2457   for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
2458   {
2459     /* Check everything before this range */
2460     for (ch = prev_ch; ch < digitRanges[j]; ch++)
2461     {
2462       SetLastError(0);
2463       src[0] = ch;
2464       src[1] = dst[0] = '\0';
2465       ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2466       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2467
2468       ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
2469          /* Wine (correctly) maps all Unicode 4.0+ digits */
2470          isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF || ch == 0x19da ||
2471          (ch >= 0x1369 && ch <= 0x1371),
2472          "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
2473     }
2474
2475     if (digitRanges[j] == 0xffff)
2476       break; /* Finished the whole code point space */
2477
2478     for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
2479     {
2480       WCHAR c;
2481
2482       /* Map out of sequence characters */
2483       if      (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
2484       else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
2485       else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
2486       else if (ch == 0x245F) c = 0x24EA; /* Circled 0     */
2487       else                   c = ch;
2488       SetLastError(0);
2489       src[0] = c;
2490       src[1] = dst[0] = '\0';
2491       ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
2492       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
2493
2494       ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
2495          broken( dst[0] == ch ) ||  /* old Windows versions don't have all mappings */
2496          (digitRanges[j] == 0x3020 && dst[0] == ch) || /* Hangzhou not present in all Windows versions */
2497          (digitRanges[j] == 0x0F29 && dst[0] == ch) || /* Tibetan not present in all Windows versions */
2498          strchrW(noDigitAvailable, c),
2499          "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
2500          ch, '0' + digitRanges[j] - ch, dst[0]);
2501     }
2502     prev_ch = ch;
2503   }
2504
2505   /* MAP_FOLDCZONE */
2506   SetLastError(0);
2507   ret = pFoldStringW(MAP_FOLDCZONE, foldczone_src, -1, dst, 256);
2508   ok(ret == sizeof(foldczone_dst)/sizeof(foldczone_dst[0]),
2509      "Got %d, error %d\n", ret, GetLastError());
2510   ok(!memcmp(dst, foldczone_dst, sizeof(foldczone_dst)),
2511      "MAP_FOLDCZONE: Expanded incorrectly\n");
2512
2513   ret = pFoldStringW(MAP_FOLDCZONE|MAP_PRECOMPOSED, foldczone_todo_src, -1, dst, 256);
2514   todo_wine ok(ret == sizeof(foldczone_todo_dst)/sizeof(foldczone_todo_dst[0]),
2515           "Got %d, error %d\n", ret, GetLastError());
2516   todo_wine ok(!memcmp(dst, foldczone_todo_dst, sizeof(foldczone_todo_dst))
2517           || broken(!memcmp(dst, foldczone_todo_broken_dst, sizeof(foldczone_todo_broken_dst))),
2518           "MAP_FOLDCZONE: Expanded incorrectly (%s)\n", wine_dbgstr_w(dst));
2519
2520   /* MAP_EXPAND_LIGATURES */
2521   SetLastError(0);
2522   ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
2523   /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
2524   if (!(ret == 0 && GetLastError() == ERROR_INVALID_FLAGS)) {
2525     ok(ret == sizeof(ligatures_dst)/sizeof(ligatures_dst[0]),
2526        "Got %d, error %d\n", ret, GetLastError());
2527     ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
2528        "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
2529   }
2530
2531   /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
2532 }
2533
2534
2535
2536 #define LCID_OK(l) \
2537   ok(lcid == l, "Expected lcid = %08x, got %08x\n", l, lcid)
2538 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
2539 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
2540 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
2541 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
2542
2543 static void test_ConvertDefaultLocale(void)
2544 {
2545   LCID lcid;
2546
2547   /* Doesn't change lcid, even if non default sublang/sort used */
2548   TEST_LCID(LANG_ENGLISH,  SUBLANG_ENGLISH_US, SORT_DEFAULT);
2549   TEST_LCID(LANG_ENGLISH,  SUBLANG_ENGLISH_UK, SORT_DEFAULT);
2550   TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT,    SORT_DEFAULT);
2551   TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT,    SORT_JAPANESE_UNICODE);
2552
2553   /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
2554   LCID_RES(MKLCID(LANG_ENGLISH,  SUBLANG_NEUTRAL, SORT_DEFAULT),
2555            MKLCID(LANG_ENGLISH,  SUBLANG_DEFAULT, SORT_DEFAULT));
2556   LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
2557            MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
2558
2559   /* Invariant language is not treated specially */
2560   TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
2561
2562   /* User/system default languages alone are not mapped */
2563   TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
2564   TEST_LCIDLANG(LANG_USER_DEFAULT,   SORT_JAPANESE_UNICODE);
2565
2566   /* Default lcids */
2567   LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
2568   LCID_RES(LOCALE_USER_DEFAULT,   GetUserDefaultLCID());
2569   LCID_RES(LOCALE_NEUTRAL,        GetUserDefaultLCID());
2570 }
2571
2572 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
2573                                     DWORD dwFlags, LONG_PTR lParam)
2574 {
2575   trace("%08x, %s, %s, %08x, %08lx\n",
2576         lgrpid, lpszNum, lpszName, dwFlags, lParam);
2577
2578   ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
2579      "Enumerated grp %d not valid (flags %d)\n", lgrpid, dwFlags);
2580
2581   /* If lParam is one, we are calling with flags defaulted from 0 */
2582   ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
2583          "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %d\n", dwFlags);
2584
2585   return TRUE;
2586 }
2587
2588 static void test_EnumSystemLanguageGroupsA(void)
2589 {
2590   BOOL ret;
2591
2592   if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
2593   {
2594     win_skip("EnumSystemLanguageGroupsA and/or IsValidLanguageGroup are not available\n");
2595     return;
2596   }
2597
2598   /* No enumeration proc */
2599   SetLastError(0);
2600   ret = pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
2601   if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2602   {
2603     win_skip("EnumSystemLanguageGroupsA is not implemented\n");
2604     return;
2605   }
2606   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2607       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2608
2609   /* Invalid flags */
2610   SetLastError(0);
2611   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
2612   ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2613
2614   /* No flags - defaults to LGRPID_INSTALLED */
2615   SetLastError(0xdeadbeef);
2616   pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
2617   ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
2618
2619   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
2620   pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
2621 }
2622
2623 static BOOL CALLBACK enum_func( LPWSTR name, DWORD flags, LPARAM lparam )
2624 {
2625     trace( "%s %x\n", wine_dbgstr_w(name), flags );
2626     return TRUE;
2627 }
2628
2629 static void test_EnumSystemLocalesEx(void)
2630 {
2631     BOOL ret;
2632
2633     if (!pEnumSystemLocalesEx)
2634     {
2635         win_skip( "EnumSystemLocalesEx not available\n" );
2636         return;
2637     }
2638     SetLastError( 0xdeadbeef );
2639     ret = pEnumSystemLocalesEx( enum_func, LOCALE_ALL, 0, (void *)1 );
2640     ok( !ret, "should have failed\n" );
2641     ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
2642     SetLastError( 0xdeadbeef );
2643     ret = pEnumSystemLocalesEx( enum_func, 0, 0, NULL );
2644     ok( ret, "failed err %u\n", GetLastError() );
2645 }
2646
2647 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
2648                                       LONG_PTR lParam)
2649 {
2650   trace("%08x, %08x, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
2651
2652   /* invalid locale enumerated on some platforms */
2653   if (lcid == 0)
2654       return TRUE;
2655
2656   ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
2657      "Enumerated grp %d not valid\n", lgrpid);
2658   ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
2659      "Enumerated grp locale %d not valid\n", lcid);
2660   return TRUE;
2661 }
2662
2663 static void test_EnumLanguageGroupLocalesA(void)
2664 {
2665   BOOL ret;
2666
2667   if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
2668   {
2669     win_skip("EnumLanguageGroupLocalesA and/or IsValidLanguageGroup are not available\n");
2670     return;
2671   }
2672
2673   /* No enumeration proc */
2674   SetLastError(0);
2675   ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
2676   if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2677   {
2678     win_skip("EnumLanguageGroupLocalesA is not implemented\n");
2679     return;
2680   }
2681   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2682       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2683
2684   /* lgrpid too small */
2685   SetLastError(0);
2686   ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
2687   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2688       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2689
2690   /* lgrpid too big */
2691   SetLastError(0);
2692   ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
2693   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2694       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2695
2696   /* dwFlags is reserved */
2697   SetLastError(0);
2698   ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
2699   ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2700       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2701
2702   pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2703 }
2704
2705 static void test_SetLocaleInfoA(void)
2706 {
2707   BOOL bRet;
2708   LCID lcid = GetUserDefaultLCID();
2709
2710   /* Null data */
2711   SetLastError(0);
2712   bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2713   ok( !bRet && GetLastError() == ERROR_INVALID_PARAMETER,
2714       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2715
2716   /* IDATE */
2717   SetLastError(0);
2718   bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, "test_SetLocaleInfoA");
2719   ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2720      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2721
2722   /* ILDATE */
2723   SetLastError(0);
2724   bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, "test_SetLocaleInfoA");
2725   ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2726      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2727 }
2728
2729 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2730 {
2731   trace("%s %08lx\n", value, lParam);
2732   return(TRUE);
2733 }
2734
2735 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2736 {
2737   ok(!enumCount, "callback called again unexpected\n");
2738   enumCount++;
2739   return(FALSE);
2740 }
2741
2742 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2743 {
2744   ok(0,"callback called unexpected\n");
2745   return(FALSE);
2746 }
2747
2748 static void test_EnumUILanguageA(void)
2749 {
2750   BOOL ret;
2751   if (!pEnumUILanguagesA) {
2752     win_skip("EnumUILanguagesA is not available on Win9x or NT4\n");
2753     return;
2754   }
2755
2756   SetLastError(ERROR_SUCCESS);
2757   ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2758   if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2759   {
2760     win_skip("EnumUILanguagesA is not implemented\n");
2761     return;
2762   }
2763   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2764
2765   enumCount = 0;
2766   SetLastError(ERROR_SUCCESS);
2767   ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2768   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2769
2770   SetLastError(ERROR_SUCCESS);
2771   ret = pEnumUILanguagesA(NULL, 0, 0);
2772   ok(!ret, "Expected return value FALSE, got %u\n", ret);
2773   ok(GetLastError() == ERROR_INVALID_PARAMETER,
2774       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2775
2776   SetLastError(ERROR_SUCCESS);
2777   ret = pEnumUILanguagesA(luilocale_proc3A, 0x5a5a5a5a, 0);
2778   ok(!ret, "Expected return value FALSE, got %u\n", ret);
2779   ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2780
2781   SetLastError(ERROR_SUCCESS);
2782   ret = pEnumUILanguagesA(NULL, 0x5a5a5a5a, 0);
2783   ok(!ret, "Expected return value FALSE, got %u\n", ret);
2784   ok(GetLastError() == ERROR_INVALID_PARAMETER,
2785       "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2786 }
2787
2788 static char date_fmt_buf[1024];
2789
2790 static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
2791 {
2792     lstrcatA(date_fmt_buf, fmt);
2793     lstrcatA(date_fmt_buf, "\n");
2794     return TRUE;
2795 }
2796
2797 static void test_EnumDateFormatsA(void)
2798 {
2799     char *p, buf[256];
2800     BOOL ret;
2801     LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2802
2803     trace("EnumDateFormatsA 0\n");
2804     date_fmt_buf[0] = 0;
2805     SetLastError(0xdeadbeef);
2806     ret = EnumDateFormatsA(enum_datetime_procA, lcid, 0);
2807     if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2808     {
2809         win_skip("0 for dwFlags is not supported\n");
2810     }
2811     else
2812     {
2813         ok(ret, "EnumDateFormatsA(0) error %d\n", GetLastError());
2814         trace("%s\n", date_fmt_buf);
2815         /* test the 1st enumerated format */
2816         if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2817         ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2818         ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2819         ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2820     }
2821
2822     trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n");
2823     date_fmt_buf[0] = 0;
2824     SetLastError(0xdeadbeef);
2825     ret = EnumDateFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2826     if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2827     {
2828         win_skip("LOCALE_USE_CP_ACP is not supported\n");
2829     }
2830     else
2831     {
2832         ok(ret, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2833         trace("%s\n", date_fmt_buf);
2834         /* test the 1st enumerated format */
2835         if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2836         ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2837         ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2838         ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2839     }
2840
2841     trace("EnumDateFormatsA DATE_SHORTDATE\n");
2842     date_fmt_buf[0] = 0;
2843     ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_SHORTDATE);
2844     ok(ret, "EnumDateFormatsA(DATE_SHORTDATE) error %d\n", GetLastError());
2845     trace("%s\n", date_fmt_buf);
2846     /* test the 1st enumerated format */
2847     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2848     ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf));
2849     ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2850     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2851
2852     trace("EnumDateFormatsA DATE_LONGDATE\n");
2853     date_fmt_buf[0] = 0;
2854     ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_LONGDATE);
2855     ok(ret, "EnumDateFormatsA(DATE_LONGDATE) error %d\n", GetLastError());
2856     trace("%s\n", date_fmt_buf);
2857     /* test the 1st enumerated format */
2858     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2859     ret = GetLocaleInfoA(lcid, LOCALE_SLONGDATE, buf, sizeof(buf));
2860     ok(ret, "GetLocaleInfoA(LOCALE_SLONGDATE) error %d\n", GetLastError());
2861     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2862
2863     trace("EnumDateFormatsA DATE_YEARMONTH\n");
2864     date_fmt_buf[0] = 0;
2865     SetLastError(0xdeadbeef);
2866     ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_YEARMONTH);
2867     if (!ret && (GetLastError() == ERROR_INVALID_FLAGS))
2868     {
2869         skip("DATE_YEARMONTH is only present on W2K and later\n");
2870         return;
2871     }
2872     ok(ret, "EnumDateFormatsA(DATE_YEARMONTH) error %d\n", GetLastError());
2873     trace("%s\n", date_fmt_buf);
2874     /* test the 1st enumerated format */
2875     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2876     ret = GetLocaleInfoA(lcid, LOCALE_SYEARMONTH, buf, sizeof(buf));
2877     ok(ret, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %d\n", GetLastError());
2878     ok(!lstrcmpA(date_fmt_buf, buf) || broken(!buf[0]) /* win9x */,
2879        "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2880 }
2881
2882 static void test_EnumTimeFormatsA(void)
2883 {
2884     char *p, buf[256];
2885     BOOL ret;
2886     LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
2887
2888     trace("EnumTimeFormatsA 0\n");
2889     date_fmt_buf[0] = 0;
2890     ret = EnumTimeFormatsA(enum_datetime_procA, lcid, 0);
2891     ok(ret, "EnumTimeFormatsA(0) error %d\n", GetLastError());
2892     trace("%s\n", date_fmt_buf);
2893     /* test the 1st enumerated format */
2894     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2895     ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2896     ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2897     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2898
2899     trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n");
2900     date_fmt_buf[0] = 0;
2901     ret = EnumTimeFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP);
2902     ok(ret, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2903     trace("%s\n", date_fmt_buf);
2904     /* test the 1st enumerated format */
2905     if ((p = strchr(date_fmt_buf, '\n'))) *p = 0;
2906     ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf));
2907     ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2908     ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
2909 }
2910
2911 static void test_GetCPInfo(void)
2912 {
2913     BOOL ret;
2914     CPINFO cpinfo;
2915
2916     SetLastError(0xdeadbeef);
2917     ret = GetCPInfo(CP_SYMBOL, &cpinfo);
2918     ok(!ret, "GetCPInfo(CP_SYMBOL) should fail\n");
2919     ok(GetLastError() == ERROR_INVALID_PARAMETER,
2920        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2921
2922     SetLastError(0xdeadbeef);
2923     ret = GetCPInfo(CP_UTF7, &cpinfo);
2924     if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2925     {
2926         skip("Codepage CP_UTF7 is not installed/available\n");
2927     }
2928     else
2929     {
2930         ok(ret, "GetCPInfo(CP_UTF7) error %u\n", GetLastError());
2931         ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2932         ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2933         ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2934         ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2935         ok(cpinfo.MaxCharSize == 5, "expected 5, got 0x%x\n", cpinfo.MaxCharSize);
2936     }
2937
2938     SetLastError(0xdeadbeef);
2939     ret = GetCPInfo(CP_UTF8, &cpinfo);
2940     if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2941     {
2942         skip("Codepage CP_UTF8 is not installed/available\n");
2943     }
2944     else
2945     {
2946         ok(ret, "GetCPInfo(CP_UTF8) error %u\n", GetLastError());
2947         ok(cpinfo.DefaultChar[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo.DefaultChar[0]);
2948         ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]);
2949         ok(cpinfo.LeadByte[0] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[0]);
2950         ok(cpinfo.LeadByte[1] == 0, "expected 0, got 0x%x\n", cpinfo.LeadByte[1]);
2951         ok(cpinfo.MaxCharSize == 4 || broken(cpinfo.MaxCharSize == 3) /* win9x */,
2952            "expected 4, got %u\n", cpinfo.MaxCharSize);
2953     }
2954 }
2955
2956 /*
2957  * The CT_TYPE1 has varied over windows version.
2958  * The current target for correct behavior is windows 7.
2959  * There was a big shift between windows 2000 (first introduced) and windows Xp
2960  * Most of the old values below are from windows 2000.
2961  * A smaller subset of changes happened between windows Xp and Window vista/7
2962  */
2963 static void test_GetStringTypeW(void)
2964 {
2965     static const WCHAR blanks[] = {0x9, 0x20, 0xa0, 0x3000, 0xfeff};
2966     static const WORD blanks_new[] = {C1_SPACE | C1_CNTRL | C1_BLANK | C1_DEFINED,
2967                                  C1_SPACE | C1_BLANK | C1_DEFINED,
2968                                  C1_SPACE | C1_BLANK | C1_DEFINED,
2969                                  C1_SPACE | C1_BLANK | C1_DEFINED,
2970                                  C1_CNTRL | C1_BLANK | C1_DEFINED};
2971     static const WORD blanks_old[] ={C1_SPACE | C1_CNTRL | C1_BLANK,
2972                                     C1_SPACE | C1_BLANK,
2973                                     C1_SPACE | C1_BLANK,
2974                                     C1_SPACE | C1_BLANK,
2975                                     C1_SPACE | C1_BLANK};
2976
2977     static const WCHAR undefined[] = {0x378, 0x379, 0x604, 0xfff8, 0xfffe};
2978
2979                                   /* Lu, Ll, Lt */
2980     static const WCHAR alpha[] = {0x47, 0x67, 0x1c5};
2981     static const WORD alpha_old[] = {C1_UPPER | C1_ALPHA,
2982                                      C1_LOWER | C1_ALPHA,
2983                                      C1_UPPER | C1_LOWER | C1_ALPHA,
2984                                      C1_ALPHA};
2985
2986                                   /* Sk, Sk, Mn, So, Me */
2987     static const WCHAR oldpunc[] = { 0x2c2, 0x2e5, 0x322, 0x482, 0x6de,
2988                                  /* Sc, Sm, No,*/
2989                                      0xffe0, 0xffe9, 0x2153};
2990
2991                                 /* Lm, Nl, Cf, 0xad(Cf), 0x1f88 (Lt), Lo, Mc */
2992     static const WCHAR changed[] = {0x2b0, 0x2160, 0x600, 0xad, 0x1f88, 0x294, 0x903};
2993     static const WORD changed_old[] = { C1_PUNCT, C1_PUNCT, 0, C1_PUNCT, C1_UPPER | C1_ALPHA, C1_ALPHA, C1_PUNCT };
2994     static const WORD changed_xp[] = {C1_ALPHA | C1_DEFINED,
2995                                       C1_ALPHA | C1_DEFINED,
2996                                       C1_CNTRL | C1_DEFINED,
2997                                       C1_PUNCT | C1_DEFINED,
2998                                       C1_UPPER | C1_LOWER | C1_ALPHA | C1_DEFINED,
2999                                       C1_ALPHA | C1_LOWER | C1_DEFINED,
3000                                       C1_ALPHA | C1_DEFINED };
3001     static const WORD changed_new[] = { C1_ALPHA | C1_DEFINED,
3002                                       C1_ALPHA | C1_DEFINED,
3003                                       C1_CNTRL | C1_DEFINED,
3004                                       C1_PUNCT | C1_CNTRL | C1_DEFINED,
3005                                       C1_UPPER | C1_LOWER | C1_ALPHA | C1_DEFINED,
3006                                       C1_ALPHA | C1_DEFINED,
3007                                       C1_DEFINED
3008  };
3009                                 /* Pc,  Pd, Ps, Pe, Pi, Pf, Po*/
3010     static const WCHAR punct[] = { 0x5f, 0x2d, 0x28, 0x29, 0xab, 0xbb, 0x21 };
3011
3012     static const WCHAR punct_special[] = {0x24, 0x2b, 0x3c, 0x3e, 0x5e, 0x60,
3013                                           0x7c, 0x7e, 0xa2, 0xbe, 0xd7, 0xf7};
3014     static const WCHAR digit_special[] = {0xb2, 0xb3, 0xb9};
3015     static const WCHAR lower_special[] = {0x2071, 0x207f};
3016     static const WCHAR cntrl_special[] = {0x070f, 0x200c, 0x200d,
3017                   0x200e, 0x200f, 0x202a, 0x202b, 0x202c, 0x202d, 0x202e,
3018                   0x206a, 0x206b, 0x206c, 0x206d, 0x206e, 0x206f, 0xfeff,
3019                   0xfff9, 0xfffa, 0xfffb};
3020     static const WCHAR space_special[] = {0x09, 0x0d, 0x85};
3021
3022     WORD types[20];
3023     int i;
3024
3025     memset(types,0,sizeof(types));
3026     GetStringTypeW(CT_CTYPE1, blanks, 5, types);
3027     for (i = 0; i < 5; i++)
3028         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]);
3029
3030     memset(types,0,sizeof(types));
3031     GetStringTypeW(CT_CTYPE1, alpha, 3, types);
3032     for (i = 0; i < 3; i++)
3033         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]));
3034     memset(types,0,sizeof(types));
3035     GetStringTypeW(CT_CTYPE1, undefined, 5, types);
3036     for (i = 0; i < 5; i++)
3037         ok(types[i] == 0, "incorrect types returned for %x -> (%x != 0)\n",undefined[i], types[i]);
3038
3039     memset(types,0,sizeof(types));
3040     GetStringTypeW(CT_CTYPE1, oldpunc, 8, types);
3041     for (i = 0; i < 8; i++)
3042         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);
3043
3044     memset(types,0,sizeof(types));
3045     GetStringTypeW(CT_CTYPE1, changed, 7, types);
3046     for (i = 0; i < 7; i++)
3047         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]);
3048
3049     memset(types,0,sizeof(types));
3050     GetStringTypeW(CT_CTYPE1, punct, 7, types);
3051     for (i = 0; i < 7; i++)
3052         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));
3053
3054
3055     memset(types,0,sizeof(types));
3056     GetStringTypeW(CT_CTYPE1, punct_special, 12, types);
3057     for (i = 0; i < 12; i++)
3058         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);
3059
3060     memset(types,0,sizeof(types));
3061     GetStringTypeW(CT_CTYPE1, digit_special, 3, types);
3062     for (i = 0; i < 3; i++)
3063         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);
3064
3065     memset(types,0,sizeof(types));
3066     GetStringTypeW(CT_CTYPE1, lower_special, 2, types);
3067     for (i = 0; i < 2; i++)
3068         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);
3069
3070     memset(types,0,sizeof(types));
3071     GetStringTypeW(CT_CTYPE1, cntrl_special, 20, types);
3072     for (i = 0; i < 20; i++)
3073         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);
3074
3075     memset(types,0,sizeof(types));
3076     GetStringTypeW(CT_CTYPE1, space_special, 3, types);
3077     for (i = 0; i < 3; i++)
3078         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 );
3079 }
3080
3081 static void test_IdnToNameprepUnicode(void)
3082 {
3083     struct {
3084         DWORD in_len;
3085         const WCHAR in[64];
3086         DWORD ret;
3087         const WCHAR out[64];
3088         DWORD flags;
3089         DWORD err;
3090         DWORD todo;
3091     } test_data[] = {
3092         {
3093             5, {'t','e','s','t',0},
3094             5, {'t','e','s','t',0},
3095             0, 0xdeadbeef
3096         },
3097         {
3098             3, {'a',0xe111,'b'},
3099             0, {0},
3100             0, ERROR_INVALID_NAME
3101         },
3102         {
3103             4, {'t',0,'e',0},
3104             0, {0},
3105             0, ERROR_INVALID_NAME
3106         },
3107         {
3108             1, {'T',0},
3109             1, {'T',0},
3110             0, 0xdeadbeef
3111         },
3112         {
3113             1, {0},
3114             0, {0},
3115             0, ERROR_INVALID_NAME
3116         },
3117         {
3118             6, {' ','-','/','[',']',0},
3119             6, {' ','-','/','[',']',0},
3120             0, 0xdeadbeef
3121         },
3122         {
3123             3, {'a','-','a'},
3124             3, {'a','-','a'},
3125             IDN_USE_STD3_ASCII_RULES, 0xdeadbeef
3126         },
3127         {
3128             3, {'a','a','-'},
3129             0, {0},
3130             IDN_USE_STD3_ASCII_RULES, ERROR_INVALID_NAME
3131         },
3132         { /* FoldString is not working as expected when MAP_FOLDCZONE is specified (composition+compatibility) */
3133             10, {'T',0xdf,0x130,0x143,0x37a,0x6a,0x30c,' ',0xaa,0},
3134             12, {'t','s','s','i',0x307,0x144,' ',0x3b9,0x1f0,' ','a',0},
3135             0, 0xdeadbeef, TRUE
3136         },
3137         {
3138             11, {'t',0xad,0x34f,0x1806,0x180b,0x180c,0x180d,0x200b,0x200c,0x200d,0},
3139             2, {'t',0},
3140             0, 0xdeadbeef
3141         },
3142         { /* Another example of incorrectly working FoldString (composition) */
3143             2, {0x3b0, 0},
3144             2, {0x3b0, 0},
3145             0, 0xdeadbeef, TRUE
3146         },
3147         {
3148             2, {0x221, 0},
3149             0, {0},
3150             0, ERROR_NO_UNICODE_TRANSLATION
3151         },
3152         {
3153             2, {0x221, 0},
3154             2, {0x221, 0},
3155             IDN_ALLOW_UNASSIGNED, 0xdeadbeef
3156         },
3157         {
3158             5, {'a','.','.','a',0},
3159             0, {0},
3160             0, ERROR_INVALID_NAME
3161         },
3162         {
3163             3, {'a','.',0},
3164             3, {'a','.',0},
3165             0, 0xdeadbeef
3166         },
3167     };
3168
3169     WCHAR buf[1024];
3170     DWORD i, ret, err;
3171
3172     if (!pIdnToNameprepUnicode)
3173     {
3174         win_skip("IdnToNameprepUnicode is not available\n");
3175         return;
3176     }
3177
3178     ret = pIdnToNameprepUnicode(0, test_data[0].in,
3179             test_data[0].in_len, NULL, 0);
3180     ok(ret == test_data[0].ret, "ret = %d\n", ret);
3181
3182     SetLastError(0xdeadbeef);
3183     ret = pIdnToNameprepUnicode(0, test_data[1].in,
3184             test_data[1].in_len, NULL, 0);
3185     err = GetLastError();
3186     ok(ret == test_data[1].ret, "ret = %d\n", ret);
3187     ok(err == test_data[1].err, "err = %d\n", err);
3188
3189     SetLastError(0xdeadbeef);
3190     ret = pIdnToNameprepUnicode(0, test_data[0].in, -1,
3191             buf, sizeof(buf)/sizeof(WCHAR));
3192     err = GetLastError();
3193     ok(ret == test_data[0].ret, "ret = %d\n", ret);
3194     ok(err == 0xdeadbeef, "err = %d\n", err);
3195
3196     SetLastError(0xdeadbeef);
3197     ret = pIdnToNameprepUnicode(0, test_data[0].in, -2,
3198             buf, sizeof(buf)/sizeof(WCHAR));
3199     err = GetLastError();
3200     ok(ret == 0, "ret = %d\n", ret);
3201     ok(err == ERROR_INVALID_PARAMETER, "err = %d\n", err);
3202
3203     SetLastError(0xdeadbeef);
3204     ret = pIdnToNameprepUnicode(0, test_data[0].in, 0,
3205             buf, sizeof(buf)/sizeof(WCHAR));
3206     err = GetLastError();
3207     ok(ret == 0, "ret = %d\n", ret);
3208     ok(err == ERROR_INVALID_NAME, "err = %d\n", err);
3209
3210     ret = pIdnToNameprepUnicode(IDN_ALLOW_UNASSIGNED|IDN_USE_STD3_ASCII_RULES,
3211             test_data[0].in, -1, buf, sizeof(buf)/sizeof(WCHAR));
3212     ok(ret == test_data[0].ret, "ret = %d\n", ret);
3213
3214     SetLastError(0xdeadbeef);
3215     ret = pIdnToNameprepUnicode(0, NULL, 0, NULL, 0);
3216     err = GetLastError();
3217     ok(ret == 0, "ret = %d\n", ret);
3218     ok(err == ERROR_INVALID_PARAMETER, "err = %d\n", err);
3219
3220     SetLastError(0xdeadbeef);
3221     ret = pIdnToNameprepUnicode(4, NULL, 0, NULL, 0);
3222     err = GetLastError();
3223     ok(ret == 0, "ret = %d\n", ret);
3224     ok(err == ERROR_INVALID_FLAGS, "err = %d\n", err);
3225
3226     for (i=0; i<sizeof(test_data)/sizeof(*test_data); i++)
3227     {
3228         SetLastError(0xdeadbeef);
3229         ret = pIdnToNameprepUnicode(test_data[i].flags, test_data[i].in,
3230                 test_data[i].in_len, buf, sizeof(buf)/sizeof(WCHAR));
3231         err = GetLastError();
3232         if(!test_data[i].todo) {
3233             ok(ret == test_data[i].ret, "%d) ret = %d\n", i, ret);
3234             ok(err == test_data[i].err, "%d) err = %d\n", i, err);
3235             ok(!memcmp(test_data[i].out, buf, ret*sizeof(WCHAR)),
3236                     "%d) buf = %s\n", i, wine_dbgstr_wn(buf, ret));
3237         }else {
3238             todo_wine ok(!memcmp(test_data[i].out, buf, ret*sizeof(WCHAR)),
3239                     "%d) buf = %s\n", i, wine_dbgstr_wn(buf, ret));
3240         }
3241     }
3242 }
3243
3244 static void test_IdnToAscii(void)
3245 {
3246     struct {
3247         DWORD in_len;
3248         const WCHAR in[64];
3249         DWORD ret;
3250         const WCHAR out[64];
3251         DWORD flags;
3252         DWORD err;
3253     } test_data[] = {
3254         {
3255             5, {'T','e','s','t',0},
3256             5, {'T','e','s','t',0},
3257             0, 0xdeadbeef
3258         },
3259         {
3260             5, {'T','e',0x017c,'s','t',0},
3261             12, {'x','n','-','-','t','e','s','t','-','c','b','b',0},
3262             0, 0xdeadbeef
3263         },
3264         {
3265             12, {'t','e',0x0105,'s','t','.','t','e',0x017c,'s','t',0},
3266             26, {'x','n','-','-','t','e','s','t','-','c','t','a','.','x','n','-','-','t','e','s','t','-','c','b','b',0},
3267             0, 0xdeadbeef
3268         },
3269         {
3270             3, {0x0105,'.',0},
3271             9, {'x','n','-','-','2','d','a','.',0},
3272             0, 0xdeadbeef
3273         },
3274         {
3275             10, {'h','t','t','p',':','/','/','t',0x0106,0},
3276             17, {'x','n','-','-','h','t','t','p',':','/','/','t','-','7','8','a',0},
3277             0, 0xdeadbeef
3278         },
3279         {
3280             10, {0x4e3a,0x8bf4,0x4e0d,0x4ed6,0x5011,0x10d,0x11b,0x305c,0x306a,0},
3281             35, {'x','n','-','-','b','e','a','2','a','1','6','3','1','a','v','b','a',
3282                 'v','4','4','t','y','h','a','3','2','b','9','1','e','g','s','2','t',0},
3283             0, 0xdeadbeef
3284         },
3285         {
3286             2, {0x221,0},
3287             8, {'x','n','-','-','6','l','a',0},
3288             IDN_ALLOW_UNASSIGNED, 0xdeadbeef
3289         },
3290     };
3291
3292     WCHAR buf[1024];
3293     DWORD i, ret, err;
3294
3295     if (!pIdnToAscii)
3296     {
3297         win_skip("IdnToAscii is not available\n");
3298         return;
3299     }
3300
3301     for (i=0; i<sizeof(test_data)/sizeof(*test_data); i++)
3302     {
3303         SetLastError(0xdeadbeef);
3304         ret = pIdnToAscii(test_data[i].flags, test_data[i].in,
3305                 test_data[i].in_len, buf, sizeof(buf));
3306         err = GetLastError();
3307         ok(ret == test_data[i].ret, "%d) ret = %d\n", i, ret);
3308         ok(err == test_data[i].err, "%d) err = %d\n", i, err);
3309         ok(!memcmp(test_data[i].out, buf, ret*sizeof(WCHAR)),
3310                 "%d) buf = %s\n", i, wine_dbgstr_wn(buf, ret));
3311     }
3312 }
3313
3314 static void test_IdnToUnicode(void)
3315 {
3316     struct {
3317         DWORD in_len;
3318         const WCHAR in[64];
3319         DWORD ret;
3320         const WCHAR out[64];
3321         DWORD flags;
3322         DWORD err;
3323     } test_data[] = {
3324         {
3325             5, {'T','e','s','.',0},
3326             5, {'T','e','s','.',0},
3327             0, 0xdeadbeef
3328         },
3329         {
3330             2, {0x105,0},
3331             0, {0},
3332             0, ERROR_INVALID_NAME
3333         },
3334         {
3335             33, {'x','n','-','-','4','d','b','c','a','g','d','a','h','y','m','b',
3336                 'x','e','k','h','e','h','6','e','0','a','7','f','e','i','0','b',0},
3337             23, {0x05dc,0x05de,0x05d4,0x05d4,0x05dd,0x05e4,0x05e9,0x05d5,0x05d8,
3338                 0x05dc,0x05d0,0x05de,0x05d3,0x05d1,0x05e8,0x05d9,0x05dd,0x05e2,
3339                 0x05d1,0x05e8,0x05d9,0x05ea,0},
3340             0, 0xdeadbeef
3341         },
3342         {
3343             34, {'t','e','s','t','.','x','n','-','-','k','d','a','9','a','g','5','e',
3344                 '9','j','n','f','s','j','.','x','n','-','-','p','d','-','f','n','a'},
3345             16, {'t','e','s','t','.',0x0105,0x0119,0x015b,0x0107,
3346                 0x0142,0x00f3,0x017c,'.','p',0x0119,'d'},
3347             0, 0xdeadbeef
3348         },
3349         {
3350             64, {'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
3351                 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
3352                 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
3353                 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a'},
3354             0, {0},
3355             0, ERROR_INVALID_NAME
3356         },
3357         {
3358             8, {'x','n','-','-','6','l','a',0},
3359             2, {0x221,0},
3360             IDN_ALLOW_UNASSIGNED, 0xdeadbeef
3361         },
3362     };
3363
3364     WCHAR buf[1024];
3365     DWORD i, ret, err;
3366
3367     if (!pIdnToUnicode)
3368     {
3369         win_skip("IdnToUnicode is not available\n");
3370         return;
3371     }
3372
3373     for (i=0; i<sizeof(test_data)/sizeof(*test_data); i++)
3374     {
3375         SetLastError(0xdeadbeef);
3376         ret = pIdnToUnicode(test_data[i].flags, test_data[i].in,
3377                 test_data[i].in_len, buf, sizeof(buf));
3378         err = GetLastError();
3379         ok(ret == test_data[i].ret, "%d) ret = %d\n", i, ret);
3380         ok(err == test_data[i].err, "%d) err = %d\n", i, err);
3381         ok(!memcmp(test_data[i].out, buf, ret*sizeof(WCHAR)),
3382                 "%d) buf = %s\n", i, wine_dbgstr_wn(buf, ret));
3383     }
3384 }
3385
3386 static void test_GetLocaleInfoEx(void)
3387 {
3388     static const WCHAR enW[] = {'e','n',0};
3389     WCHAR bufferW[80];
3390     INT ret;
3391
3392     if (!pGetLocaleInfoEx)
3393     {
3394         win_skip("GetLocaleInfoEx not supported\n");
3395         return;
3396     }
3397
3398     ret = pGetLocaleInfoEx(enW, LOCALE_SNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3399     ok(ret || broken(ret == 0) /* Vista */, "got %d\n", ret);
3400     if (ret)
3401     {
3402         static const WCHAR statesW[] = {'U','n','i','t','e','d',' ','S','t','a','t','e','s',0};
3403         static const WCHAR dummyW[] = {'d','u','m','m','y',0};
3404         static const WCHAR enusW[] = {'e','n','-','U','S',0};
3405         static const WCHAR usaW[] = {'U','S','A',0};
3406         static const WCHAR enuW[] = {'E','N','U',0};
3407         const struct neutralsublang_name_t *ptr = neutralsublang_names;
3408         DWORD val;
3409
3410         ok(ret == lstrlenW(bufferW)+1, "got %d\n", ret);
3411         ok(!lstrcmpW(bufferW, enW), "got %s\n", wine_dbgstr_w(bufferW));
3412
3413         SetLastError(0xdeadbeef);
3414         ret = pGetLocaleInfoEx(enW, LOCALE_SNAME, bufferW, 2);
3415         ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d, %d\n", ret, GetLastError());
3416
3417         SetLastError(0xdeadbeef);
3418         ret = pGetLocaleInfoEx(enW, LOCALE_SNAME, NULL, 0);
3419         ok(ret == 3 && GetLastError() == 0xdeadbeef, "got %d, %d\n", ret, GetLastError());
3420
3421         ret = pGetLocaleInfoEx(enusW, LOCALE_SNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3422         ok(ret == lstrlenW(bufferW)+1, "got %d\n", ret);
3423         ok(!lstrcmpW(bufferW, enusW), "got %s\n", wine_dbgstr_w(bufferW));
3424
3425         ret = pGetLocaleInfoEx(enW, LOCALE_SABBREVCTRYNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3426         ok(ret == lstrlenW(bufferW)+1, "got %d\n", ret);
3427         ok(!lstrcmpW(bufferW, usaW), "got %s\n", wine_dbgstr_w(bufferW));
3428
3429         ret = pGetLocaleInfoEx(enW, LOCALE_SABBREVLANGNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3430         ok(ret == lstrlenW(bufferW)+1, "got %d\n", ret);
3431         ok(!lstrcmpW(bufferW, enuW), "got %s\n", wine_dbgstr_w(bufferW));
3432
3433         ret = pGetLocaleInfoEx(enW, LOCALE_SCOUNTRY, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3434         ok(ret == lstrlenW(bufferW)+1, "got %d\n", ret);
3435         ok(!lstrcmpW(bufferW, statesW), "got %s\n", wine_dbgstr_w(bufferW));
3436
3437         bufferW[0] = 0;
3438         SetLastError(0xdeadbeef);
3439         ret = pGetLocaleInfoEx(dummyW, LOCALE_SNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3440         ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError());
3441
3442         while (*ptr->name)
3443         {
3444             val = 0;
3445             pGetLocaleInfoEx(ptr->name, LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER, (WCHAR*)&val, sizeof(val)/sizeof(WCHAR));
3446             if (ptr->todo)
3447             todo_wine
3448                 ok(val == ptr->lcid, "%s: got wrong lcid 0x%04x, expected 0x%04x\n", wine_dbgstr_w(ptr->name), val, ptr->lcid);
3449             else
3450                 ok(val == ptr->lcid, "%s: got wrong lcid 0x%04x, expected 0x%04x\n", wine_dbgstr_w(ptr->name), val, ptr->lcid);
3451             bufferW[0] = 0;
3452             ret = pGetLocaleInfoEx(ptr->name, LOCALE_SNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
3453             ok(ret == lstrlenW(bufferW)+1, "%s: got ret value %d\n", wine_dbgstr_w(ptr->name), ret);
3454             ok(!lstrcmpW(bufferW, ptr->name), "%s: got wrong LOCALE_SNAME %s\n", wine_dbgstr_w(ptr->name), wine_dbgstr_w(bufferW));
3455             ptr++;
3456         }
3457     }
3458 }
3459
3460 static void test_IsValidLocaleName(void)
3461 {
3462     static const WCHAR enusW[] = {'e','n','-','U','S',0};
3463     static const WCHAR zzW[] = {'z','z',0};
3464     static const WCHAR zzzzW[] = {'z','z','-','Z','Z',0};
3465     BOOL ret;
3466
3467     if (!pIsValidLocaleName)
3468     {
3469         win_skip("IsValidLocaleName not supported\n");
3470         return;
3471     }
3472
3473     ret = pIsValidLocaleName(enusW);
3474     ok(ret, "IsValidLocaleName failed\n");
3475     ret = pIsValidLocaleName(zzW);
3476     ok(!ret, "IsValidLocaleName should have failed\n");
3477     ret = pIsValidLocaleName(zzzzW);
3478     ok(!ret, "IsValidLocaleName should have failed\n");
3479 }
3480
3481 START_TEST(locale)
3482 {
3483   InitFunctionPointers();
3484
3485
3486   test_EnumTimeFormatsA();
3487   test_EnumDateFormatsA();
3488   test_GetLocaleInfoA();
3489   test_GetLocaleInfoW();
3490   test_GetLocaleInfoEx();
3491   test_GetTimeFormatA();
3492   test_GetDateFormatA();
3493   test_GetDateFormatW();
3494   test_GetCurrencyFormatA(); /* Also tests the W version */
3495   test_GetNumberFormatA();   /* Also tests the W version */
3496   test_CompareStringA();
3497   test_LCMapStringA();
3498   test_LCMapStringW();
3499   test_LCMapStringEx();
3500   test_LocaleNameToLCID();
3501   test_FoldStringA();
3502   test_FoldStringW();
3503   test_ConvertDefaultLocale();
3504   test_EnumSystemLanguageGroupsA();
3505   test_EnumSystemLocalesEx();
3506   test_EnumLanguageGroupLocalesA();
3507   test_SetLocaleInfoA();
3508   test_EnumUILanguageA();
3509   test_GetCPInfo();
3510   test_GetStringTypeW();
3511   test_IdnToNameprepUnicode();
3512   test_IdnToAscii();
3513   test_IdnToUnicode();
3514   test_IsValidLocaleName();
3515   /* this requires collation table patch to make it MS compatible */
3516   if (0) test_sorting();
3517 }