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