2 * Unit tests for locale functions
4 * Copyright 2002 YASAR Mehmet
5 * Copyright 2003 Dmitry Timoshkov
6 * Copyright 2003 Jon Griffiths
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.
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.
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
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.
33 #include "wine/test.h"
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};
44 static inline unsigned int strlenW( const WCHAR *str )
51 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
54 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
58 static inline WCHAR *strchrW( const WCHAR *str, WCHAR ch )
60 do { if (*str == ch) return (WCHAR *)str; } while (*str++);
64 static inline int isdigitW( WCHAR wc )
67 GetStringTypeW( CT_CTYPE1, &wc, 1, &type );
68 return type & C1_DIGIT;
71 /* Some functions are only in later versions of kernel32.dll */
72 static HMODULE hKernel32;
73 static WORD enumCount;
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);
89 static void InitFunctionPointers(void)
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");
107 #define eq(received, expected, label, type) \
108 ok((received) == (expected), "%s: got " type " instead of " type "\n", \
109 (label), (received), (expected))
111 #define BUFFER_SIZE 128
112 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
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)
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")
125 #define NUO LOCALE_NOUSEROVERRIDE
127 static void test_GetLocaleInfoA(void)
131 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
132 char buffer[BUFFER_SIZE];
133 char expected[BUFFER_SIZE];
135 ok(lcid == 0x409, "wrong LCID calculated - %d\n", lcid);
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);
149 memset(expected, 0, COUNTOF(expected));
150 len = GetLocaleInfoA(MAKELANGID(LANG_ARABIC, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
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);
160 win_skip("LANG_ARABIC not installed\n");
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);
173 /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
174 * partially fill the buffer even if it is too short. See bug 637.
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);
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);
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);
195 static void test_GetLocaleInfoW(void)
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];
204 ret = GetLocaleInfoW(lcid_en, LOCALE_SMONTHNAME1, bufferW, COUNTOF(bufferW));
206 win_skip("GetLocaleInfoW() isn't implemented\n");
209 ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1, bufferW, COUNTOF(bufferW));
211 win_skip("LANG_RUSSIAN locale data unavailable\n");
214 ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1|LOCALE_RETURN_GENITIVE_NAMES,
215 bufferW, COUNTOF(bufferW));
217 win_skip("LOCALE_RETURN_GENITIVE_NAMES isn't supported\n");
221 /* LOCALE_RETURN_GENITIVE_NAMES isn't supported for GetLocaleInfoA */
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());
232 SetLastError(0xdeadbeef);
233 ret = GetLocaleInfoW(lcid_ru, LOCALE_RETURN_GENITIVE_NAMES,
234 bufferW, COUNTOF(bufferW));
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());
241 /* yes, test empty 13 month entry too */
242 for (i = 0; i < 12; i++) {
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));
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));
256 ok(lstrcmpW(bufferW, buffer2W) != 0,
257 "Expected genitive name to differ, got the same for month %d\n", i+1);
259 /* for locale without genitive names nominative returned in both cases */
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));
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));
273 ok(lstrcmpW(bufferW, buffer2W) == 0,
274 "Expected same names, got different for month %d\n", i+1);
278 static void test_GetTimeFormatA(void)
282 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
283 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
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());
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;
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());
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());
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());
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;
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 );
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;
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;
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 );
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 );
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;
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;
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;
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;
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;
379 curtime.wHour = 14; /* change this to 14 or 2pm */
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;
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;
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;
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.
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;
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());
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;
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;
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;
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;
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;
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;
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;
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());
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;
473 static void test_GetDateFormatA(void)
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];
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());
490 curtime.wYear = 2002;
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;
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());
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;
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;
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());
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());
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);
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;
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());
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());
558 ret = GetDateFormat(lcid_ru, 0, &curtime, "ddMMMM", buffer, COUNTOF(buffer));
561 win_skip("LANG_RUSSIAN locale data unavailable\n");
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");
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);
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());
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());
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());
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);
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);
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());
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);
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);
638 static void test_GetDateFormatW(void)
642 WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
643 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
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)
650 win_skip("GetDateFormatW is not implemented\n");
653 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
654 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
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());
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;
668 curtime.wYear = 2002;
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;
683 curtime.wYear = 1601;
686 curtime.wDayOfWeek = 0; /* Irrelevant */
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;
697 curtime.wYear = 1600;
700 curtime.wDayOfWeek = 0; /* Irrelevant */
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());
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
718 static void test_GetCurrencyFormatA(void)
720 static char szDot[] = { '.', '\0' };
721 static char szComma[] = { ',', '\0' };
722 static char szDollar[] = { '$', '\0' };
724 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
725 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
728 memset(&format, 0, sizeof(format));
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());
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());
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());
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());
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());
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());
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());
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());
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());
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;
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;
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;
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;
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;
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;
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;
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;
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;
836 STRINGSA("235","$235.0"); /* Grouping of a positive number */
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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 -" */
975 static void test_GetNumberFormatA(void)
977 static char szDot[] = { '.', '\0' };
978 static char szComma[] = { ',', '\0' };
980 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
981 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
984 memset(&format, 0, sizeof(format));
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());
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());
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());
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());
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());
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());
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());
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());
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());
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
1143 lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
1145 if (IsValidLocale(lcid, 0))
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;
1155 struct comparestringa_entry {
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 }
1198 static void test_CompareStringA(void)
1201 LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
1203 for (i = 0; i < sizeof(comparestringa_data)/sizeof(struct comparestringa_entry); i++)
1205 const struct comparestringa_entry *entry = &comparestringa_data[i];
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);
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);
1215 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
1216 ok (ret == CSTR_EQUAL, "(Salut/SaLuT) Expected CSTR_EQUAL, got %d\n", ret);
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);
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);
1224 lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
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);
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);
1232 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
1233 ok (ret == CSTR_EQUAL, "(Salut/saLuT) Expected CSTR_EQUAL, got %d\n", ret);
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");
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 */
1248 ret = lstrcmpA("", "");
1249 ok (ret == 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret);
1251 ret = lstrcmpA(NULL, NULL);
1252 ok (ret == 0 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, NULL) should return 0, got %d\n", ret);
1254 ret = lstrcmpA("", NULL);
1255 ok (ret == 1 || broken(ret == -2) /* win9x */, "lstrcmpA(\"\", NULL) should return 1, got %d\n", ret);
1257 ret = lstrcmpA(NULL, "");
1258 ok (ret == -1 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret);
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);
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);
1268 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
1269 ok(ret == CSTR_LESS_THAN, "' vs - expected CSTR_LESS_THAN, got %d\n", ret);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
1315 ret = CompareStringA(lcid, 0, "\2", 2, "\1", 2);
1316 todo_wine ok(ret != CSTR_EQUAL, "\\2 vs \\1 expected unequal\n");
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);
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);
1324 ret = lstrcmpi("#", ".");
1325 todo_wine ok(ret == -1, "\"#\" vs \".\" expected -1, got %d\n", ret);
1327 lcid = MAKELCID(MAKELANGID(LANG_POLISH, SUBLANG_DEFAULT), SORT_DEFAULT);
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");
1336 static void test_LCMapStringA(void)
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";
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);
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());
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());
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());
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());
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");
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);
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);
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);
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");
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);
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");
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);
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");
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");
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");
1463 /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1464 results from plain LCMAP_SORTKEY on Vista */
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");
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);
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);
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());
1500 typedef INT (*lcmapstring_wrapper)(DWORD, LPCWSTR, INT, LPWSTR, INT);
1502 static void test_lcmapstring_unicode(lcmapstring_wrapper func_ptr, const char *func_name)
1505 WCHAR buf[256], buf2[256];
1506 char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1508 ret = func_ptr(LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1509 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1511 ok(lstrcmpW(buf, upper_case) == 0, "Expected upper case string\n");
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());
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());
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());
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",
1535 ok(GetLastError() == ERROR_INVALID_FLAGS, "%s unexpected error code %d\n",
1536 func_name, GetLastError());
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);
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);
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);
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);
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);
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);
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);
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);
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);
1611 /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1612 results from plain LCMAP_SORTKEY on Vista */
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);
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);
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);
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());
1648 static INT LCMapStringW_wrapper(DWORD flags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen)
1650 return LCMapStringW(LOCALE_USER_DEFAULT, flags, src, srclen, dst, dstlen);
1653 static void test_LCMapStringW(void)
1658 trace("testing LCMapStringW\n");
1660 SetLastError(0xdeadbeef);
1661 ret = LCMapStringW((LCID)-1, LCMAP_LOWERCASE, upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1663 ok(!ret, "LCMapStringW should fail with bad lcid\n");
1664 ok(GetLastError() == ERROR_INVALID_PARAMETER, "unexpected error code %d\n", GetLastError());
1667 test_lcmapstring_unicode(LCMapStringW_wrapper, "LCMapStringW:");
1670 static INT LCMapStringEx_wrapper(DWORD flags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen)
1672 return pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, flags, src, srclen, dst, dstlen, NULL, NULL, 0);
1675 static void test_LCMapStringEx(void)
1678 WCHAR buf[256], badname[] = {'w', 'i', 'n', 'e', 't', 'e', 's', 't', 0};
1680 if (!pLCMapStringEx)
1682 win_skip( "LCMapStringEx not available\n" );
1686 trace("testing LCMapStringEx\n");
1688 SetLastError(0xdeadbeef);
1689 ret = pLCMapStringEx(badname, LCMAP_LOWERCASE,
1690 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), NULL, NULL, 0);
1692 ok(!ret, "LCMapStringEx should fail with bad locale name\n");
1693 ok(GetLastError() == ERROR_INVALID_PARAMETER, "unexpected error code %d\n", GetLastError());
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");
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");
1709 /* crashes on native */
1711 ret = pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_LOWERCASE,
1712 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), (void*)1, NULL, 0);
1714 test_lcmapstring_unicode(LCMapStringEx_wrapper, "LCMapStringEx:");
1717 static void test_LocaleNames(void)
1721 WCHAR buffer[LOCALE_NAME_MAX_LENGTH];
1723 if (!pLocaleNameToLCID)
1725 win_skip( "LocaleNameToLCID not available\n" );
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));
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));
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));
1754 /* this requires collation table patch to make it MS compatible */
1755 static const char * const strings_sorted[] =
1787 static const char * const strings[] =
1819 static int compare_string1(const void *e1, const void *e2)
1821 const char *s1 = *(const char *const *)e1;
1822 const char *s2 = *(const char *const *)e2;
1824 return lstrcmpA(s1, s2);
1827 static int compare_string2(const void *e1, const void *e2)
1829 const char *s1 = *(const char *const *)e1;
1830 const char *s2 = *(const char *const *)e2;
1832 return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1835 static int compare_string3(const void *e1, const void *e2)
1837 const char *s1 = *(const char *const *)e1;
1838 const char *s2 = *(const char *const *)e2;
1839 char key1[256], key2[256];
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);
1846 static void test_sorting(void)
1849 char **str_buf = (char **)buf;
1852 assert(sizeof(buf) >= sizeof(strings));
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++)
1859 ok(!strcmp(strings_sorted[i], str_buf[i]),
1860 "qsort using lstrcmpA failed for element %d\n", i);
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++)
1867 ok(!strcmp(strings_sorted[i], str_buf[i]),
1868 "qsort using CompareStringA failed for element %d\n", i);
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++)
1875 ok(!strcmp(strings_sorted[i], str_buf[i]),
1876 "qsort using sort keys failed for element %d\n", i);
1880 static void test_FoldStringA(void)
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[] =
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'
1898 static const char composite_dst[] =
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'
1916 static const char composite_dst_alt[] =
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'
1934 static const char ligatures_src[] =
1936 0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1938 static const char ligatures_dst[] =
1940 'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1942 static const struct special
1946 } foldczone_special[] =
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 } },
1969 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1971 /* these tests are locale specific */
1972 if (GetACP() != 1252)
1974 trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1978 /* MAP_FOLDDIGITS */
1980 ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
1981 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1983 win_skip("FoldStringA is not implemented\n");
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++)
1991 if (!strchr(digits_src, i))
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);
2003 /* MAP_EXPAND_LIGATURES */
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++)
2013 if (!strchr(ligatures_src, i))
2018 ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
2022 ok((i == 0xDC && lstrcmpA(dst, "UE") == 0) ||
2023 (i == 0xFC && lstrcmpA(dst, "ue") == 0),
2024 "Got %s for %d\n", dst, i);
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);
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);
2044 for (i = 1; i < 256; i++)
2046 if (!strchr(composite_src, i))
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]);
2060 for (i = 1; i < 256; i++)
2065 ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
2067 for (j = 0; foldczone_special[j].src != 0 && ! is_special; j++)
2069 if (foldczone_special[j].src == src[0])
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]);
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]);
2089 /* MAP_PRECOMPOSED */
2090 for (i = 1; i < 256; i++)
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]);
2103 static void test_FoldStringW(void)
2107 WCHAR src[256], dst[256], ch, prev_ch = 1;
2108 static const DWORD badFlags[] =
2111 MAP_PRECOMPOSED|MAP_COMPOSITE,
2112 MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
2113 MAP_COMPOSITE|MAP_EXPAND_LIGATURES
2115 /* Ranges of digits 0-9 : Must be sorted! */
2116 static const WCHAR digitRanges[] =
2118 0x0030, /* '0'-'9' */
2119 0x0660, /* Eastern Arabic */
2120 0x06F0, /* Arabic - Hindu */
2121 0x0966, /* Devengari */
2122 0x09E6, /* Bengalii */
2123 0x0A66, /* Gurmukhi */
2124 0x0AE6, /* Gujarati */
2126 0x0BE6, /* Tamil - No 0 */
2127 0x0C66, /* Telugu */
2128 0x0CE6, /* Kannada */
2129 0x0D66, /* Maylayalam */
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 */
2145 /* Digits which are represented, but out of sequence */
2146 static const WCHAR outOfSequenceDigits[] =
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 */
2156 /* Digits in digitRanges for which no representation is available */
2157 static const WCHAR noDigitAvailable[] =
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 */
2169 static const WCHAR foldczone_src[] =
2171 'W', 'i', 'n', 'e', 0x0348, 0x0551, 0x1323, 0x280d,
2172 0xff37, 0xff49, 0xff4e, 0xff45, '\0'
2174 static const WCHAR foldczone_dst[] =
2176 'W','i','n','e',0x0348,0x0551,0x1323,0x280d,'W','i','n','e','\0'
2178 static const WCHAR foldczone_todo_src[] =
2180 0x3c5,0x308,0x6a,0x30c,0xa0,0xaa,0
2182 static const WCHAR foldczone_todo_dst[] =
2184 0x3cb,0x1f0,' ','a',0
2186 static const WCHAR foldczone_todo_broken_dst[] =
2188 0x3cb,0x1f0,0xa0,0xaa,0
2190 static const WCHAR ligatures_src[] =
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'
2199 static const WCHAR ligatures_dst[] =
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'
2211 win_skip("FoldStringW is not available\n");
2212 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
2215 /* Invalid flag combinations */
2216 for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
2218 src[0] = dst[0] = '\0';
2220 ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
2221 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
2223 win_skip("FoldStringW is not implemented\n");
2226 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
2227 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2230 /* src & dst cannot be the same */
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());
2236 /* src can't be NULL */
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());
2242 /* srclen can't be 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());
2248 /* dstlen can't be < 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());
2254 /* Ret includes terminating NUL which is appended if srclen = -1 */
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());
2265 /* If size is given, result is not NUL terminated */
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());
2277 /* MAP_FOLDDIGITS */
2278 for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
2280 /* Check everything before this range */
2281 for (ch = prev_ch; ch < digitRanges[j]; 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());
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]);
2296 if (digitRanges[j] == 0xffff)
2297 break; /* Finished the whole code point space */
2299 for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
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 */
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());
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]);
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");
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));
2341 /* MAP_EXPAND_LIGATURES */
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");
2352 /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
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))
2364 static void test_ConvertDefaultLocale(void)
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);
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));
2380 /* Invariant language is not treated specially */
2381 TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
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);
2388 LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
2389 LCID_RES(LOCALE_USER_DEFAULT, GetUserDefaultLCID());
2390 LCID_RES(LOCALE_NEUTRAL, GetUserDefaultLCID());
2393 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
2394 DWORD dwFlags, LONG_PTR lParam)
2396 trace("%08x, %s, %s, %08x, %08lx\n",
2397 lgrpid, lpszNum, lpszName, dwFlags, lParam);
2399 ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
2400 "Enumerated grp %d not valid (flags %d)\n", lgrpid, dwFlags);
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);
2409 static void test_EnumSystemLanguageGroupsA(void)
2413 if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
2415 win_skip("EnumSystemLanguageGroupsA and/or IsValidLanguageGroup are not available\n");
2419 /* No enumeration proc */
2421 ret = pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
2422 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2424 win_skip("EnumSystemLanguageGroupsA is not implemented\n");
2427 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2428 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2432 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
2433 ok(GetLastError() == ERROR_INVALID_FLAGS, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
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());
2440 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
2441 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
2444 static BOOL CALLBACK enum_func( LPWSTR name, DWORD flags, LPARAM lparam )
2446 trace( "%s %x\n", wine_dbgstr_w(name), flags );
2450 static void test_EnumSystemLocalesEx(void)
2454 if (!pEnumSystemLocalesEx)
2456 win_skip( "EnumSystemLocalesEx not available\n" );
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() );
2468 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
2471 trace("%08x, %08x, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
2473 /* invalid locale enumerated on some platforms */
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);
2484 static void test_EnumLanguageGroupLocalesA(void)
2488 if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
2490 win_skip("EnumLanguageGroupLocalesA and/or IsValidLanguageGroup are not available\n");
2494 /* No enumeration proc */
2496 ret = pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
2497 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2499 win_skip("EnumLanguageGroupLocalesA is not implemented\n");
2502 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2503 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2505 /* lgrpid too small */
2507 ret = pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
2508 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
2509 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2511 /* lgrpid too big */
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());
2517 /* dwFlags is reserved */
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());
2523 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
2526 static void test_SetLocaleInfoA(void)
2529 LCID lcid = GetUserDefaultLCID();
2533 bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2534 ok( !bRet && GetLastError() == ERROR_INVALID_PARAMETER,
2535 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2539 bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, "test_SetLocaleInfoA");
2540 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2541 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2545 bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, "test_SetLocaleInfoA");
2546 ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
2547 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2550 static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
2552 trace("%s %08lx\n", value, lParam);
2556 static BOOL CALLBACK luilocale_proc2A(LPSTR value, LONG_PTR lParam)
2558 ok(!enumCount, "callback called again unexpected\n");
2563 static BOOL CALLBACK luilocale_proc3A(LPSTR value, LONG_PTR lParam)
2565 ok(0,"callback called unexpected\n");
2569 static void test_EnumUILanguageA(void)
2572 if (!pEnumUILanguagesA) {
2573 win_skip("EnumUILanguagesA is not available on Win9x or NT4\n");
2577 SetLastError(ERROR_SUCCESS);
2578 ret = pEnumUILanguagesA(luilocale_proc1A, 0, 0);
2579 if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2581 win_skip("EnumUILanguagesA is not implemented\n");
2584 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
2587 SetLastError(ERROR_SUCCESS);
2588 ret = pEnumUILanguagesA(luilocale_proc2A, 0, 0);
2589 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
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());
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());
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());
2609 static char date_fmt_buf[1024];
2611 static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
2613 lstrcatA(date_fmt_buf, fmt);
2614 lstrcatA(date_fmt_buf, "\n");
2618 static void test_EnumDateFormatsA(void)
2622 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
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))
2630 win_skip("0 for dwFlags is not supported\n");
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);
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))
2649 win_skip("LOCALE_USE_CP_ACP is not supported\n");
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);
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);
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);
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))
2690 skip("DATE_YEARMONTH is only present on W2K and later\n");
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);
2703 static void test_EnumTimeFormatsA(void)
2707 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
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);
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);
2732 static void test_GetCPInfo(void)
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());
2743 SetLastError(0xdeadbeef);
2744 ret = GetCPInfo(CP_UTF7, &cpinfo);
2745 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2747 skip("Codepage CP_UTF7 is not installed/available\n");
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);
2759 SetLastError(0xdeadbeef);
2760 ret = GetCPInfo(CP_UTF8, &cpinfo);
2761 if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
2763 skip("Codepage CP_UTF8 is not installed/available\n");
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);
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
2784 static void test_GetStringTypeW(void)
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};
2798 static const WCHAR undefined[] = {0x378, 0x379, 0x604, 0xfff8, 0xfffe};
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,
2807 /* Sk, Sk, Mn, So, Me */
2808 static const WCHAR oldpunc[] = { 0x2c2, 0x2e5, 0x322, 0x482, 0x6de,
2810 0xffe0, 0xffe9, 0x2153};
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,
2830 /* Pc, Pd, Ps, Pe, Pi, Pf, Po*/
2831 static const WCHAR punct[] = { 0x5f, 0x2d, 0x28, 0x29, 0xab, 0xbb, 0x21 };
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};
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]);
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]);
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);
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]);
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));
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);
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);
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);
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);
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 );
2902 static void test_IdnToNameprepUnicode(void)
2908 const WCHAR out[64];
2914 5, {'t','e','s','t',0},
2915 5, {'t','e','s','t',0},
2919 3, {'a',0xe111,'b'},
2921 0, ERROR_INVALID_NAME
2926 0, ERROR_INVALID_NAME
2936 0, ERROR_INVALID_NAME
2939 6, {' ','-','/','[',']',0},
2940 6, {' ','-','/','[',']',0},
2946 IDN_USE_STD3_ASCII_RULES, 0xdeadbeef
2951 IDN_USE_STD3_ASCII_RULES, ERROR_INVALID_NAME
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},
2959 11, {'t',0xad,0x34f,0x1806,0x180b,0x180c,0x180d,0x200b,0x200c,0x200d,0},
2963 { /* Another example of incorrectly working FoldString (composition) */
2971 0, ERROR_NO_UNICODE_TRANSLATION
2976 IDN_ALLOW_UNASSIGNED, 0xdeadbeef
2979 5, {'a','.','.','a',0},
2981 0, ERROR_INVALID_NAME
2993 if (!pIdnToNameprepUnicode)
2995 win_skip("IdnToNameprepUnicode is not available\n");
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);
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);
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);
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);
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);
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);
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);
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);
3047 for (i=0; i<sizeof(test_data)/sizeof(*test_data); i++)
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));
3059 todo_wine ok(!memcmp(test_data[i].out, buf, ret*sizeof(WCHAR)),
3060 "%d) buf = %s\n", i, wine_dbgstr_wn(buf, ret));
3065 static void test_IdnToAscii(void)
3071 const WCHAR out[64];
3076 5, {'T','e','s','t',0},
3077 5, {'T','e','s','t',0},
3081 5, {'T','e',0x017c,'s','t',0},
3082 12, {'x','n','-','-','t','e','s','t','-','c','b','b',0},
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},
3092 9, {'x','n','-','-','2','d','a','.',0},
3096 10, {'h','t','t','p',':','/','/','t',0x0106,0},
3097 17, {'x','n','-','-','h','t','t','p',':','/','/','t','-','7','8','a',0},
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},
3108 8, {'x','n','-','-','6','l','a',0},
3109 IDN_ALLOW_UNASSIGNED, 0xdeadbeef
3118 win_skip("IdnToAscii is not available\n");
3122 for (i=0; i<sizeof(test_data)/sizeof(*test_data); i++)
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));
3135 static void test_IdnToUnicode(void)
3141 const WCHAR out[64];
3146 5, {'T','e','s','.',0},
3147 5, {'T','e','s','.',0},
3153 0, ERROR_INVALID_NAME
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},
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'},
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'},
3176 0, ERROR_INVALID_NAME
3179 8, {'x','n','-','-','6','l','a',0},
3181 IDN_ALLOW_UNASSIGNED, 0xdeadbeef
3190 win_skip("IdnToUnicode is not available\n");
3194 for (i=0; i<sizeof(test_data)/sizeof(*test_data); i++)
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));
3209 InitFunctionPointers();
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();
3227 test_ConvertDefaultLocale();
3228 test_EnumSystemLanguageGroupsA();
3229 test_EnumSystemLocalesEx();
3230 test_EnumLanguageGroupLocalesA();
3231 test_SetLocaleInfoA();
3232 test_EnumUILanguageA();
3234 test_GetStringTypeW();
3235 test_IdnToNameprepUnicode();
3237 test_IdnToUnicode();
3238 /* this requires collation table patch to make it MS compatible */
3239 if (0) test_sorting();