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