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