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.
36 #include "wine/test.h"
42 static inline unsigned int strlenW( const WCHAR
*str
)
49 static inline int strncmpW( const WCHAR
*str1
, const WCHAR
*str2
, int n
)
52 while ((--n
> 0) && *str1
&& (*str1
== *str2
)) { str1
++; str2
++; }
56 static inline WCHAR
*strchrW( const WCHAR
*str
, WCHAR ch
)
58 do { if (*str
== ch
) return (WCHAR
*)str
; } while (*str
++);
62 static inline int isdigitW( WCHAR wc
)
65 GetStringTypeW( CT_CTYPE1
, &wc
, 1, &type
);
66 return type
& C1_DIGIT
;
69 /* Some functions are only in later versions of kernel32.dll */
70 static HMODULE hKernel32
;
71 static WORD enumCount
;
73 static BOOL (WINAPI
*pEnumSystemLanguageGroupsA
)(LANGUAGEGROUP_ENUMPROC
, DWORD
, LONG_PTR
);
74 static BOOL (WINAPI
*pEnumLanguageGroupLocalesA
)(LANGGROUPLOCALE_ENUMPROC
, LGRPID
, DWORD
, LONG_PTR
);
75 static BOOL (WINAPI
*pEnumUILanguagesA
)(UILANGUAGE_ENUMPROC
, DWORD
, LONG_PTR
);
76 static BOOL (WINAPI
*pEnumSystemLocalesEx
)(LOCALE_ENUMPROCEX
, DWORD
, LPARAM
, LPVOID
);
77 static LCID (WINAPI
*pLocaleNameToLCID
)(LPCWSTR
, DWORD
);
78 static INT (WINAPI
*pLCIDToLocaleName
)(LCID
, LPWSTR
, INT
, DWORD
);
79 static INT (WINAPI
*pFoldStringA
)(DWORD
, LPCSTR
, INT
, LPSTR
, INT
);
80 static INT (WINAPI
*pFoldStringW
)(DWORD
, LPCWSTR
, INT
, LPWSTR
, INT
);
81 static BOOL (WINAPI
*pIsValidLanguageGroup
)(LGRPID
, DWORD
);
82 static INT (WINAPI
*pIdnToNameprepUnicode
)(DWORD
, LPCWSTR
, INT
, LPWSTR
, INT
);
83 static INT (WINAPI
*pIdnToAscii
)(DWORD
, LPCWSTR
, INT
, LPWSTR
, INT
);
84 static INT (WINAPI
*pIdnToUnicode
)(DWORD
, LPCWSTR
, INT
, LPWSTR
, INT
);
86 static void InitFunctionPointers(void)
88 hKernel32
= GetModuleHandleA("kernel32");
89 pEnumSystemLanguageGroupsA
= (void*)GetProcAddress(hKernel32
, "EnumSystemLanguageGroupsA");
90 pEnumLanguageGroupLocalesA
= (void*)GetProcAddress(hKernel32
, "EnumLanguageGroupLocalesA");
91 pLocaleNameToLCID
= (void*)GetProcAddress(hKernel32
, "LocaleNameToLCID");
92 pLCIDToLocaleName
= (void*)GetProcAddress(hKernel32
, "LCIDToLocaleName");
93 pFoldStringA
= (void*)GetProcAddress(hKernel32
, "FoldStringA");
94 pFoldStringW
= (void*)GetProcAddress(hKernel32
, "FoldStringW");
95 pIsValidLanguageGroup
= (void*)GetProcAddress(hKernel32
, "IsValidLanguageGroup");
96 pEnumUILanguagesA
= (void*)GetProcAddress(hKernel32
, "EnumUILanguagesA");
97 pEnumSystemLocalesEx
= (void*)GetProcAddress(hKernel32
, "EnumSystemLocalesEx");
98 pIdnToNameprepUnicode
= (void*)GetProcAddress(hKernel32
, "IdnToNameprepUnicode");
99 pIdnToAscii
= (void*)GetProcAddress(hKernel32
, "IdnToAscii");
100 pIdnToUnicode
= (void*)GetProcAddress(hKernel32
, "IdnToUnicode");
103 #define eq(received, expected, label, type) \
104 ok((received) == (expected), "%s: got " type " instead of " type "\n", \
105 (label), (received), (expected))
107 #define BUFFER_SIZE 128
108 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
110 #define STRINGSA(x,y) strcpy(input, x); strcpy(Expected, y); SetLastError(0xdeadbeef); buffer[0] = '\0'
111 #define EXPECT_LENA ok(ret == lstrlen(Expected)+1, "Expected Len %d, got %d\n", lstrlen(Expected)+1, ret)
112 #define EXPECT_EQA ok(strncmp(buffer, Expected, strlen(Expected)) == 0, \
113 "Expected '%s', got '%s'\n", Expected, buffer)
115 #define STRINGSW(x,y) MultiByteToWideChar(CP_ACP,0,x,-1,input,COUNTOF(input)); \
116 MultiByteToWideChar(CP_ACP,0,y,-1,Expected,COUNTOF(Expected)); \
117 SetLastError(0xdeadbeef); buffer[0] = '\0'
118 #define EXPECT_LENW ok(ret == lstrlenW(Expected)+1, "Expected Len %d, got %d\n", lstrlenW(Expected)+1, ret)
119 #define EXPECT_EQW ok(strncmpW(buffer, Expected, strlenW(Expected)) == 0, "Bad conversion\n")
121 #define NUO LOCALE_NOUSEROVERRIDE
123 static void test_GetLocaleInfoA(void)
127 LCID lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
128 char buffer
[BUFFER_SIZE
];
129 char expected
[BUFFER_SIZE
];
131 ok(lcid
== 0x409, "wrong LCID calculated - %d\n", lcid
);
133 /* en and ar use SUBLANG_NEUTRAL, but GetLocaleInfo assume SUBLANG_DEFAULT
134 Same is true for zh on pre-Vista, but on Vista and higher GetLocaleInfo
135 assumes SUBLANG_NEUTRAL for zh */
136 memset(expected
, 0, COUNTOF(expected
));
137 len
= GetLocaleInfoA(MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
), LOCALE_SLANGUAGE
, expected
, COUNTOF(expected
));
138 SetLastError(0xdeadbeef);
139 memset(buffer
, 0, COUNTOF(buffer
));
140 ret
= GetLocaleInfoA(LANG_ENGLISH
, LOCALE_SLANGUAGE
, buffer
, COUNTOF(buffer
));
141 ok((ret
== len
) && !lstrcmpA(buffer
, expected
),
142 "got %d with '%s' (expected %d with '%s')\n",
143 ret
, buffer
, len
, expected
);
145 memset(expected
, 0, COUNTOF(expected
));
146 len
= GetLocaleInfoA(MAKELANGID(LANG_ARABIC
, SUBLANG_DEFAULT
), LOCALE_SLANGUAGE
, expected
, COUNTOF(expected
));
148 SetLastError(0xdeadbeef);
149 memset(buffer
, 0, COUNTOF(buffer
));
150 ret
= GetLocaleInfoA(LANG_ARABIC
, LOCALE_SLANGUAGE
, buffer
, COUNTOF(buffer
));
151 ok((ret
== len
) && !lstrcmpA(buffer
, expected
),
152 "got %d with '%s' (expected %d with '%s')\n",
153 ret
, buffer
, len
, expected
);
156 win_skip("LANG_ARABIC not installed\n");
158 /* SUBLANG_DEFAULT is required for mlang.dll, but optional for GetLocaleInfo */
159 memset(expected
, 0, COUNTOF(expected
));
160 len
= GetLocaleInfoA(MAKELANGID(LANG_GERMAN
, SUBLANG_DEFAULT
), LOCALE_SLANGUAGE
, expected
, COUNTOF(expected
));
161 SetLastError(0xdeadbeef);
162 memset(buffer
, 0, COUNTOF(buffer
));
163 ret
= GetLocaleInfoA(LANG_GERMAN
, LOCALE_SLANGUAGE
, buffer
, COUNTOF(buffer
));
164 ok((ret
== len
) && !lstrcmpA(buffer
, expected
),
165 "got %d with '%s' (expected %d with '%s')\n",
166 ret
, buffer
, len
, expected
);
169 /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
170 * partially fill the buffer even if it is too short. See bug 637.
172 SetLastError(0xdeadbeef);
173 memset(buffer
, 0, COUNTOF(buffer
));
174 ret
= GetLocaleInfoA(lcid
, NUO
|LOCALE_SDAYNAME1
, buffer
, 0);
175 ok(ret
== 7 && !buffer
[0], "Expected len=7, got %d\n", ret
);
177 SetLastError(0xdeadbeef);
178 memset(buffer
, 0, COUNTOF(buffer
));
179 ret
= GetLocaleInfoA(lcid
, NUO
|LOCALE_SDAYNAME1
, buffer
, 3);
180 ok( !ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
181 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
182 ok(!strcmp(buffer
, "Mon"), "Expected 'Mon', got '%s'\n", buffer
);
184 SetLastError(0xdeadbeef);
185 memset(buffer
, 0, COUNTOF(buffer
));
186 ret
= GetLocaleInfoA(lcid
, NUO
|LOCALE_SDAYNAME1
, buffer
, 10);
187 ok(ret
== 7, "Expected ret == 7, got %d, error %d\n", ret
, GetLastError());
188 ok(!strcmp(buffer
, "Monday"), "Expected 'Monday', got '%s'\n", buffer
);
191 static void test_GetLocaleInfoW(void)
193 LCID lcid_en
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
194 LCID lcid_ru
= MAKELCID(MAKELANGID(LANG_RUSSIAN
, SUBLANG_NEUTRAL
), SORT_DEFAULT
);
195 WCHAR bufferW
[80], buffer2W
[80];
200 ret
= GetLocaleInfoW(lcid_en
, LOCALE_SMONTHNAME1
, bufferW
, COUNTOF(bufferW
));
202 win_skip("GetLocaleInfoW() isn't implemented\n");
205 ret
= GetLocaleInfoW(lcid_ru
, LOCALE_SMONTHNAME1
, bufferW
, COUNTOF(bufferW
));
207 win_skip("LANG_RUSSIAN locale data unavailable\n");
210 ret
= GetLocaleInfoW(lcid_ru
, LOCALE_SMONTHNAME1
|LOCALE_RETURN_GENITIVE_NAMES
,
211 bufferW
, COUNTOF(bufferW
));
213 win_skip("LOCALE_RETURN_GENITIVE_NAMES isn't supported\n");
217 /* LOCALE_RETURN_GENITIVE_NAMES isn't supported for GetLocaleInfoA */
219 SetLastError(0xdeadbeef);
220 ret
= GetLocaleInfoA(lcid_ru
, LOCALE_SMONTHNAME1
|LOCALE_RETURN_GENITIVE_NAMES
,
221 bufferA
, COUNTOF(bufferA
));
222 ok(ret
== 0, "LOCALE_RETURN_GENITIVE_NAMES should fail with GetLocaleInfoA\n");
223 ok(bufferA
[0] == 'a', "Expected buffer to be untouched\n");
224 ok(GetLastError() == ERROR_INVALID_FLAGS
,
225 "Expected ERROR_INVALID_FLAGS, got %x\n", GetLastError());
228 SetLastError(0xdeadbeef);
229 ret
= GetLocaleInfoW(lcid_ru
, LOCALE_RETURN_GENITIVE_NAMES
,
230 bufferW
, COUNTOF(bufferW
));
232 "LOCALE_RETURN_GENITIVE_NAMES itself doesn't return anything, got %d\n", ret
);
233 ok(bufferW
[0] == 'a', "Expected buffer to be untouched\n");
234 ok(GetLastError() == ERROR_INVALID_FLAGS
,
235 "Expected ERROR_INVALID_FLAGS, got %x\n", GetLastError());
237 /* yes, test empty 13 month entry too */
238 for (i
= 0; i
< 12; i
++) {
240 ret
= GetLocaleInfoW(lcid_ru
, (LOCALE_SMONTHNAME1
+i
)|LOCALE_RETURN_GENITIVE_NAMES
,
241 bufferW
, COUNTOF(bufferW
));
242 ok(ret
, "Expected non zero result\n");
243 ok(ret
== lstrlenW(bufferW
)+1, "Expected actual length, got %d, length %d\n",
244 ret
, lstrlenW(bufferW
));
246 ret
= GetLocaleInfoW(lcid_ru
, LOCALE_SMONTHNAME1
+i
,
247 buffer2W
, COUNTOF(buffer2W
));
248 ok(ret
, "Expected non zero result\n");
249 ok(ret
== lstrlenW(buffer2W
)+1, "Expected actual length, got %d, length %d\n",
250 ret
, lstrlenW(buffer2W
));
252 ok(lstrcmpW(bufferW
, buffer2W
) != 0,
253 "Expected genitive name to differ, got the same for month %d\n", i
+1);
255 /* for locale without genitive names nominative returned in both cases */
257 ret
= GetLocaleInfoW(lcid_en
, (LOCALE_SMONTHNAME1
+i
)|LOCALE_RETURN_GENITIVE_NAMES
,
258 bufferW
, COUNTOF(bufferW
));
259 ok(ret
, "Expected non zero result\n");
260 ok(ret
== lstrlenW(bufferW
)+1, "Expected actual length, got %d, length %d\n",
261 ret
, lstrlenW(bufferW
));
263 ret
= GetLocaleInfoW(lcid_en
, LOCALE_SMONTHNAME1
+i
,
264 buffer2W
, COUNTOF(buffer2W
));
265 ok(ret
, "Expected non zero result\n");
266 ok(ret
== lstrlenW(buffer2W
)+1, "Expected actual length, got %d, length %d\n",
267 ret
, lstrlenW(buffer2W
));
269 ok(lstrcmpW(bufferW
, buffer2W
) == 0,
270 "Expected same names, got different for month %d\n", i
+1);
274 static void test_GetTimeFormatA(void)
278 LCID lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
279 char buffer
[BUFFER_SIZE
], input
[BUFFER_SIZE
], Expected
[BUFFER_SIZE
];
281 memset(&curtime
, 2, sizeof(SYSTEMTIME
));
282 STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
283 SetLastError(0xdeadbeef);
284 ret
= GetTimeFormatA(lcid
, TIME_FORCE24HOURFORMAT
, &curtime
, input
, buffer
, COUNTOF(buffer
));
285 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
286 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
289 curtime
.wMinute
= 56;
290 curtime
.wSecond
= 13;
291 curtime
.wMilliseconds
= 22;
292 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
293 SetLastError(0xdeadbeef);
294 ret
= GetTimeFormatA(lcid
, TIME_FORCE24HOURFORMAT
, &curtime
, input
, buffer
, COUNTOF(buffer
));
295 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
296 EXPECT_LENA
; EXPECT_EQA
;
298 /* MSDN: LOCALE_NOUSEROVERRIDE can't be specified with a format string */
299 SetLastError(0xdeadbeef);
300 ret
= GetTimeFormatA(lcid
, NUO
|TIME_FORCE24HOURFORMAT
, &curtime
, input
, buffer
, COUNTOF(buffer
));
301 ok(!ret
&& GetLastError() == ERROR_INVALID_FLAGS
,
302 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
304 STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficient buffer */
305 SetLastError(0xdeadbeef);
306 ret
= GetTimeFormatA(lcid
, TIME_FORCE24HOURFORMAT
, &curtime
, input
, buffer
, 2);
307 ok( !ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
308 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
310 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
311 ret
= GetTimeFormatA(lcid
, TIME_FORCE24HOURFORMAT
, &curtime
, input
, NULL
, 0);
312 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
315 STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
316 ret
= GetTimeFormatA(lcid
, NUO
|TIME_NOMINUTESORSECONDS
, &curtime
, NULL
, buffer
, COUNTOF(buffer
));
317 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
318 EXPECT_LENA
; EXPECT_EQA
;
320 STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
321 ret
= GetTimeFormatA(lcid
, TIME_NOMINUTESORSECONDS
, &curtime
, input
, buffer
, COUNTOF(buffer
));
322 ok(ret
== strlen(buffer
)+1, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
323 ok( !strcmp( buffer
, "" ) || broken( !strcmp( buffer
, "4" )), /* win9x */
324 "Expected '', got '%s'\n", buffer
);
326 STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
327 ret
= GetTimeFormatA(lcid
, NUO
|TIME_NOSECONDS
, &curtime
, NULL
, buffer
, COUNTOF(buffer
));
328 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
329 EXPECT_LENA
; EXPECT_EQA
;
331 STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
332 strcpy(Expected
, "8:56 AM");
333 ret
= GetTimeFormatA(lcid
, TIME_NOSECONDS
, &curtime
, input
, buffer
, COUNTOF(buffer
));
334 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
335 EXPECT_LENA
; EXPECT_EQA
;
337 STRINGSA("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
338 ret
= GetTimeFormatA(lcid
, TIME_NOSECONDS
, &curtime
, input
, buffer
, COUNTOF(buffer
));
339 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
340 ok( !strcmp( buffer
, "8.@:56AM" ) || broken( !strcmp( buffer
, "8.@:56.@:AM" )) /* win9x */,
341 "Expected '8.@:56AM', got '%s'\n", buffer
);
343 STRINGSA("s1s2s3", ""); /* Duplicate tokens */
344 ret
= GetTimeFormatA(lcid
, TIME_NOSECONDS
, &curtime
, input
, buffer
, COUNTOF(buffer
));
345 ok(ret
== strlen(buffer
)+1, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
346 ok( !strcmp( buffer
, "" ) || broken( !strcmp( buffer
, "3" )), /* win9x */
347 "Expected '', got '%s'\n", buffer
);
349 STRINGSA("t/tt", "A/AM"); /* AM time marker */
350 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
351 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
352 EXPECT_LENA
; EXPECT_EQA
;
355 STRINGSA("t/tt", "P/PM"); /* PM time marker */
356 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
357 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
358 EXPECT_LENA
; EXPECT_EQA
;
360 STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
361 ret
= GetTimeFormatA(lcid
, TIME_NOTIMEMARKER
, &curtime
, input
, buffer
, COUNTOF(buffer
));
362 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
363 EXPECT_LENA
; EXPECT_EQA
;
365 STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
366 ret
= GetTimeFormatA(lcid
, TIME_FORCE24HOURFORMAT
, &curtime
, input
, buffer
, COUNTOF(buffer
));
367 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
368 EXPECT_LENA
; EXPECT_EQA
;
370 STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
371 ret
= GetTimeFormatA(lcid
, TIME_FORCE24HOURFORMAT
, &curtime
, input
, buffer
, COUNTOF(buffer
));
372 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
373 EXPECT_LENA
; EXPECT_EQA
;
375 curtime
.wHour
= 14; /* change this to 14 or 2pm */
378 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 */
379 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
380 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
381 EXPECT_LENA
; EXPECT_EQA
;
384 STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
385 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
386 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
387 EXPECT_LENA
; EXPECT_EQA
;
389 STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
390 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
391 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
392 EXPECT_LENA
; EXPECT_EQA
;
394 /* try to convert formatting strings with more than two letters
395 * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
396 * NOTE: We expect any letter for which there is an upper case value
397 * we should see a replacement. For letters that DO NOT have
398 * upper case values we should see NO REPLACEMENT.
401 curtime
.wMinute
= 56;
402 curtime
.wSecond
= 13;
403 curtime
.wMilliseconds
= 22;
404 STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
405 "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
406 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
407 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
408 EXPECT_LENA
; EXPECT_EQA
;
410 STRINGSA("h", "text"); /* Don't write to buffer if len is 0 */
411 strcpy(buffer
, "text");
412 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, 0);
413 ok(ret
== 2, "Expected ret == 2, got %d, error %d\n", ret
, GetLastError());
416 STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
417 "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
418 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
419 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
420 EXPECT_LENA
; EXPECT_EQA
;
422 STRINGSA("'''", "'"); /* invalid quoted string */
423 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
424 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
425 EXPECT_LENA
; EXPECT_EQA
;
427 /* test that msdn suggested single quotation usage works as expected */
428 STRINGSA("''''", "'"); /* single quote mark */
429 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
430 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
431 EXPECT_LENA
; EXPECT_EQA
;
433 STRINGSA("''HHHHHH", "08"); /* Normal use */
434 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
435 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
436 EXPECT_LENA
; EXPECT_EQA
;
438 /* and test for normal use of the single quotation mark */
439 STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
440 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
441 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
442 EXPECT_LENA
; EXPECT_EQA
;
444 STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
445 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
446 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
447 EXPECT_LENA
; EXPECT_EQA
;
449 STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
450 ret
= GetTimeFormatA(lcid
, TIME_NOTIMEMARKER
, &curtime
, input
, buffer
, COUNTOF(buffer
));
451 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
452 EXPECT_LENA
; EXPECT_EQA
;
455 STRINGSA("'123'tt", ""); /* Invalid time */
456 SetLastError(0xdeadbeef);
457 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
458 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
459 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
462 curtime
.wMonth
= 60; /* Invalid */
463 STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
464 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
465 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
466 EXPECT_LENA
; EXPECT_EQA
;
469 static void test_GetDateFormatA(void)
473 LCID lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
474 LCID lcid_ru
= MAKELCID(MAKELANGID(LANG_RUSSIAN
, SUBLANG_NEUTRAL
), SORT_DEFAULT
);
475 char buffer
[BUFFER_SIZE
], input
[BUFFER_SIZE
], Expected
[BUFFER_SIZE
];
476 char Broken
[BUFFER_SIZE
];
477 char short_day
[10], month
[10], genitive_month
[10];
479 memset(&curtime
, 2, sizeof(SYSTEMTIME
)); /* Invalid time */
480 STRINGSA("ddd',' MMM dd yy","");
481 SetLastError(0xdeadbeef);
482 ret
= GetDateFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
483 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
484 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
486 curtime
.wYear
= 2002;
489 curtime
.wDayOfWeek
= 3;
490 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
491 ret
= GetDateFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
492 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
493 EXPECT_LENA
; EXPECT_EQA
;
495 /* Same as above but with LOCALE_NOUSEROVERRIDE */
496 STRINGSA("ddd',' MMM dd yy",""); /* Simple case */
497 SetLastError(0xdeadbeef);
498 ret
= GetDateFormatA(lcid
, NUO
, &curtime
, input
, buffer
, COUNTOF(buffer
));
499 ok(!ret
&& GetLastError() == ERROR_INVALID_FLAGS
,
500 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
503 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
504 ret
= GetDateFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
505 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
506 EXPECT_LENA
; EXPECT_EQA
;
508 curtime
.wHour
= 36; /* Invalid */
509 STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
510 ret
= GetDateFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
511 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
512 EXPECT_LENA
; EXPECT_EQA
;
514 STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
515 ret
= GetDateFormatA(lcid
, 0, &curtime
, input
, NULL
, 0);
516 ok(ret
== 16, "Expected ret == 16, got %d, error %d\n", ret
, GetLastError());
519 STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
520 SetLastError(0xdeadbeef);
521 ret
= GetDateFormatA(lcid
, 0, &curtime
, input
, buffer
, 2);
522 ok( !ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
523 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
525 STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
526 ret
= GetDateFormat(lcid
, NUO
, &curtime
, NULL
, buffer
, COUNTOF(buffer
));
527 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
528 if (strncmp(buffer
, Expected
, strlen(Expected
)) && strncmp(buffer
, "5/4/02", strlen(Expected
)) != 0)
529 ok (0, "Expected '%s' or '5/4/02', got '%s'\n", Expected
, buffer
);
531 STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
532 ret
= GetDateFormat(lcid
, NUO
|DATE_LONGDATE
, &curtime
, NULL
, buffer
, COUNTOF(buffer
));
533 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
534 EXPECT_LENA
; EXPECT_EQA
;
536 /* test for expected DATE_YEARMONTH behavior with null format */
537 /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
538 STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
539 SetLastError(0xdeadbeef);
540 ret
= GetDateFormat(lcid
, NUO
|DATE_YEARMONTH
, &curtime
, input
, buffer
, COUNTOF(buffer
));
541 ok(!ret
&& GetLastError() == ERROR_INVALID_FLAGS
,
542 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
545 /* Test that using invalid DATE_* flags results in the correct error */
546 /* and return values */
547 STRINGSA("m/d/y", ""); /* Invalid flags */
548 SetLastError(0xdeadbeef);
549 ret
= GetDateFormat(lcid
, DATE_YEARMONTH
|DATE_SHORTDATE
|DATE_LONGDATE
,
550 &curtime
, input
, buffer
, COUNTOF(buffer
));
551 ok(!ret
&& GetLastError() == ERROR_INVALID_FLAGS
,
552 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
554 ret
= GetDateFormat(lcid_ru
, 0, &curtime
, "ddMMMM", buffer
, COUNTOF(buffer
));
557 win_skip("LANG_RUSSIAN locale data unavailable\n");
561 /* month part should be in genitive form */
562 strcpy(genitive_month
, buffer
+ 2);
563 ret
= GetDateFormat(lcid_ru
, 0, &curtime
, "MMMM", buffer
, COUNTOF(buffer
));
564 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
565 strcpy(month
, buffer
);
566 ok(strcmp(genitive_month
, month
) != 0, "Expected different month forms\n");
568 ret
= GetDateFormat(lcid_ru
, 0, &curtime
, "ddd", buffer
, COUNTOF(buffer
));
569 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
570 strcpy(short_day
, buffer
);
572 STRINGSA("dd MMMMddd dd", "");
573 sprintf(Expected
, "04 %s%s 04", genitive_month
, short_day
);
574 ret
= GetDateFormat(lcid_ru
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
575 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
578 STRINGSA("MMMMddd dd", "");
579 sprintf(Expected
, "%s%s 04", month
, short_day
);
580 ret
= GetDateFormat(lcid_ru
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
581 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
584 STRINGSA("MMMMddd", "");
585 sprintf(Expected
, "%s%s", month
, short_day
);
586 ret
= GetDateFormat(lcid_ru
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
587 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
590 STRINGSA("MMMMdd", "");
591 sprintf(Expected
, "%s04", genitive_month
);
592 sprintf(Broken
, "%s04", month
);
593 ret
= GetDateFormat(lcid_ru
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
594 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
595 ok(strncmp(buffer
, Expected
, strlen(Expected
)) == 0 ||
596 broken(strncmp(buffer
, Broken
, strlen(Broken
)) == 0) /* nt4 */,
597 "Expected '%s', got '%s'\n", Expected
, buffer
);
599 STRINGSA("MMMMdd ddd", "");
600 sprintf(Expected
, "%s04 %s", genitive_month
, short_day
);
601 sprintf(Broken
, "%s04 %s", month
, short_day
);
602 ret
= GetDateFormat(lcid_ru
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
603 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
604 ok(strncmp(buffer
, Expected
, strlen(Expected
)) == 0 ||
605 broken(strncmp(buffer
, Broken
, strlen(Broken
)) == 0) /* nt4 */,
606 "Expected '%s', got '%s'\n", Expected
, buffer
);
608 STRINGSA("dd dddMMMM", "");
609 sprintf(Expected
, "04 %s%s", short_day
, month
);
610 ret
= GetDateFormat(lcid_ru
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
611 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
614 STRINGSA("dd dddMMMM ddd MMMMdd", "");
615 sprintf(Expected
, "04 %s%s %s %s04", short_day
, month
, short_day
, genitive_month
);
616 sprintf(Broken
, "04 %s%s %s %s04", short_day
, month
, short_day
, month
);
617 ret
= GetDateFormat(lcid_ru
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
618 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
619 ok(strncmp(buffer
, Expected
, strlen(Expected
)) == 0 ||
620 broken(strncmp(buffer
, Broken
, strlen(Broken
)) == 0) /* nt4 */,
621 "Expected '%s', got '%s'\n", Expected
, buffer
);
623 /* with literal part */
624 STRINGSA("ddd',' MMMM dd", "");
625 sprintf(Expected
, "%s, %s 04", short_day
, genitive_month
);
626 sprintf(Broken
, "%s, %s 04", short_day
, month
);
627 ret
= GetDateFormat(lcid_ru
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
628 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
629 ok(strncmp(buffer
, Expected
, strlen(Expected
)) == 0 ||
630 broken(strncmp(buffer
, Broken
, strlen(Broken
)) == 0) /* nt4 */,
631 "Expected '%s', got '%s'\n", Expected
, buffer
);
634 static void test_GetDateFormatW(void)
638 WCHAR buffer
[BUFFER_SIZE
], input
[BUFFER_SIZE
], Expected
[BUFFER_SIZE
];
639 LCID lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
641 STRINGSW("",""); /* If flags is not zero then format must be NULL */
642 ret
= GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, DATE_LONGDATE
, NULL
,
643 input
, buffer
, COUNTOF(buffer
));
644 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
646 win_skip("GetDateFormatW is not implemented\n");
649 ok(!ret
&& GetLastError() == ERROR_INVALID_FLAGS
,
650 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
653 STRINGSW("",""); /* NULL buffer, len > 0 */
654 SetLastError(0xdeadbeef);
655 ret
= GetDateFormatW (lcid
, 0, NULL
, input
, NULL
, COUNTOF(buffer
));
656 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
657 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
659 STRINGSW("",""); /* NULL buffer, len == 0 */
660 ret
= GetDateFormatW (lcid
, 0, NULL
, input
, NULL
, 0);
661 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
662 EXPECT_LENW
; EXPECT_EQW
;
664 curtime
.wYear
= 2002;
667 curtime
.wDayOfWeek
= 45612; /* Should be 3 - Wednesday */
668 curtime
.wHour
= 65432; /* Invalid */
669 curtime
.wMinute
= 34512; /* Invalid */
670 curtime
.wSecond
= 65535; /* Invalid */
671 curtime
.wMilliseconds
= 12345;
672 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
673 ret
= GetDateFormatW (lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
674 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
675 EXPECT_LENW
; EXPECT_EQW
;
679 curtime
.wYear
= 1601;
682 curtime
.wDayOfWeek
= 0; /* Irrelevant */
686 curtime
.wMilliseconds
= 0;
687 STRINGSW("dddd d MMMM yyyy","Monday 1 January 1601");
688 SetLastError(0xdeadbeef);
689 ret
= GetDateFormatW (lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
690 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
691 EXPECT_LENW
; EXPECT_EQW
;
693 curtime
.wYear
= 1600;
696 curtime
.wDayOfWeek
= 0; /* Irrelevant */
698 curtime
.wMinute
= 59;
699 curtime
.wSecond
= 59;
700 curtime
.wMilliseconds
= 999;
701 STRINGSW("dddd d MMMM yyyy","Friday 31 December 1600");
702 SetLastError(0xdeadbeef);
703 ret
= GetDateFormatW (lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
704 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
705 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
709 #define CY_POS_LEFT 0
710 #define CY_POS_RIGHT 1
711 #define CY_POS_LEFT_SPACE 2
712 #define CY_POS_RIGHT_SPACE 3
714 static void test_GetCurrencyFormatA(void)
716 static char szDot
[] = { '.', '\0' };
717 static char szComma
[] = { ',', '\0' };
718 static char szDollar
[] = { '$', '\0' };
720 LCID lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
721 char buffer
[BUFFER_SIZE
], Expected
[BUFFER_SIZE
], input
[BUFFER_SIZE
];
724 memset(&format
, 0, sizeof(format
));
726 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
727 SetLastError(0xdeadbeef);
728 ret
= GetCurrencyFormatA(lcid
, 0, input
, NULL
, NULL
, COUNTOF(buffer
));
729 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
730 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
732 STRINGSA("23,53",""); /* Invalid character --> Error */
733 SetLastError(0xdeadbeef);
734 ret
= GetCurrencyFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
735 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
736 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
738 STRINGSA("--",""); /* Double '-' --> Error */
739 SetLastError(0xdeadbeef);
740 ret
= GetCurrencyFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
741 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
742 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
744 STRINGSA("0-",""); /* Trailing '-' --> Error */
745 SetLastError(0xdeadbeef);
746 ret
= GetCurrencyFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
747 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
748 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
750 STRINGSA("0..",""); /* Double '.' --> Error */
751 SetLastError(0xdeadbeef);
752 ret
= GetCurrencyFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
753 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
754 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
756 STRINGSA(" 0.1",""); /* Leading space --> Error */
757 SetLastError(0xdeadbeef);
758 ret
= GetCurrencyFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
759 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
760 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
762 STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
763 SetLastError(0xdeadbeef);
764 ret
= GetCurrencyFormatA(lcid
, NUO
, input
, NULL
, buffer
, 2);
765 ok( !ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
766 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
768 STRINGSA("2353",""); /* Format and flags given --> Error */
769 SetLastError(0xdeadbeef);
770 ret
= GetCurrencyFormatA(lcid
, NUO
, input
, &format
, buffer
, COUNTOF(buffer
));
771 ok( !ret
, "Expected ret == 0, got %d\n", ret
);
772 ok( GetLastError() == ERROR_INVALID_FLAGS
|| GetLastError() == ERROR_INVALID_PARAMETER
,
773 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
775 STRINGSA("2353",""); /* Invalid format --> Error */
776 SetLastError(0xdeadbeef);
777 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
778 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
779 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
781 STRINGSA("2353","$2,353.00"); /* Valid number */
782 ret
= GetCurrencyFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
783 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
784 EXPECT_LENA
; EXPECT_EQA
;
786 STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
787 ret
= GetCurrencyFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
788 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
789 EXPECT_LENA
; EXPECT_EQA
;
791 STRINGSA("2353.1","$2,353.10"); /* Valid real number */
792 ret
= GetCurrencyFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
793 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
794 EXPECT_LENA
; EXPECT_EQA
;
796 STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
797 ret
= GetCurrencyFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
798 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
799 EXPECT_LENA
; EXPECT_EQA
;
801 STRINGSA("2353.119","$2,353.12"); /* Too many DP --> Rounded */
802 ret
= GetCurrencyFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
803 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
804 EXPECT_LENA
; EXPECT_EQA
;
806 format
.NumDigits
= 0; /* No decimal separator */
807 format
.LeadingZero
= 0;
808 format
.Grouping
= 0; /* No grouping char */
809 format
.NegativeOrder
= 0;
810 format
.PositiveOrder
= CY_POS_LEFT
;
811 format
.lpDecimalSep
= szDot
;
812 format
.lpThousandSep
= szComma
;
813 format
.lpCurrencySymbol
= szDollar
;
815 STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
816 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
817 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
818 EXPECT_LENA
; EXPECT_EQA
;
820 format
.NumDigits
= 1; /* 1 DP --> Expect decimal separator */
821 STRINGSA("2353","$2353.0");
822 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
823 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
824 EXPECT_LENA
; EXPECT_EQA
;
826 format
.Grouping
= 2; /* Group by 100's */
827 STRINGSA("2353","$23,53.0");
828 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
829 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
830 EXPECT_LENA
; EXPECT_EQA
;
832 STRINGSA("235","$235.0"); /* Grouping of a positive number */
834 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
835 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
836 EXPECT_LENA
; EXPECT_EQA
;
838 STRINGSA("-235","$-235.0"); /* Grouping of a negative number */
839 format
.NegativeOrder
= 2;
840 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
841 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
842 EXPECT_LENA
; EXPECT_EQA
;
844 format
.LeadingZero
= 1; /* Always provide leading zero */
845 STRINGSA(".5","$0.5");
846 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
847 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
848 EXPECT_LENA
; EXPECT_EQA
;
850 format
.PositiveOrder
= CY_POS_RIGHT
;
851 STRINGSA("1","1.0$");
852 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
853 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
854 EXPECT_LENA
; EXPECT_EQA
;
856 format
.PositiveOrder
= CY_POS_LEFT_SPACE
;
857 STRINGSA("1","$ 1.0");
858 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
859 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
860 EXPECT_LENA
; EXPECT_EQA
;
862 format
.PositiveOrder
= CY_POS_RIGHT_SPACE
;
863 STRINGSA("1","1.0 $");
864 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
865 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
866 EXPECT_LENA
; EXPECT_EQA
;
868 format
.NegativeOrder
= 0;
869 STRINGSA("-1","($1.0)");
870 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
871 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
872 EXPECT_LENA
; EXPECT_EQA
;
874 format
.NegativeOrder
= 1;
875 STRINGSA("-1","-$1.0");
876 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
877 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
878 EXPECT_LENA
; EXPECT_EQA
;
880 format
.NegativeOrder
= 2;
881 STRINGSA("-1","$-1.0");
882 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
883 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
884 EXPECT_LENA
; EXPECT_EQA
;
886 format
.NegativeOrder
= 3;
887 STRINGSA("-1","$1.0-");
888 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
889 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
890 EXPECT_LENA
; EXPECT_EQA
;
892 format
.NegativeOrder
= 4;
893 STRINGSA("-1","(1.0$)");
894 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
895 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
896 EXPECT_LENA
; EXPECT_EQA
;
898 format
.NegativeOrder
= 5;
899 STRINGSA("-1","-1.0$");
900 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
901 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
902 EXPECT_LENA
; EXPECT_EQA
;
904 format
.NegativeOrder
= 6;
905 STRINGSA("-1","1.0-$");
906 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
907 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
908 EXPECT_LENA
; EXPECT_EQA
;
910 format
.NegativeOrder
= 7;
911 STRINGSA("-1","1.0$-");
912 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
913 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
914 EXPECT_LENA
; EXPECT_EQA
;
916 format
.NegativeOrder
= 8;
917 STRINGSA("-1","-1.0 $");
918 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
919 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
920 EXPECT_LENA
; EXPECT_EQA
;
922 format
.NegativeOrder
= 9;
923 STRINGSA("-1","-$ 1.0");
924 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
925 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
926 EXPECT_LENA
; EXPECT_EQA
;
928 format
.NegativeOrder
= 10;
929 STRINGSA("-1","1.0 $-");
930 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
931 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
932 EXPECT_LENA
; EXPECT_EQA
;
934 format
.NegativeOrder
= 11;
935 STRINGSA("-1","$ 1.0-");
936 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
937 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
938 EXPECT_LENA
; EXPECT_EQA
;
940 format
.NegativeOrder
= 12;
941 STRINGSA("-1","$ -1.0");
942 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
943 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
944 EXPECT_LENA
; EXPECT_EQA
;
946 format
.NegativeOrder
= 13;
947 STRINGSA("-1","1.0- $");
948 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
949 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
950 EXPECT_LENA
; EXPECT_EQA
;
952 format
.NegativeOrder
= 14;
953 STRINGSA("-1","($ 1.0)");
954 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
955 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
956 EXPECT_LENA
; EXPECT_EQA
;
958 format
.NegativeOrder
= 15;
959 STRINGSA("-1","(1.0 $)");
960 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
961 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
962 EXPECT_LENA
; EXPECT_EQA
;
965 #define NEG_PARENS 0 /* "(1.1)" */
966 #define NEG_LEFT 1 /* "-1.1" */
967 #define NEG_LEFT_SPACE 2 /* "- 1.1" */
968 #define NEG_RIGHT 3 /* "1.1-" */
969 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
971 static void test_GetNumberFormatA(void)
973 static char szDot
[] = { '.', '\0' };
974 static char szComma
[] = { ',', '\0' };
976 LCID lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
977 char buffer
[BUFFER_SIZE
], Expected
[BUFFER_SIZE
], input
[BUFFER_SIZE
];
980 memset(&format
, 0, sizeof(format
));
982 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
983 SetLastError(0xdeadbeef);
984 ret
= GetNumberFormatA(lcid
, 0, input
, NULL
, NULL
, COUNTOF(buffer
));
985 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
986 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
988 STRINGSA("23,53",""); /* Invalid character --> Error */
989 SetLastError(0xdeadbeef);
990 ret
= GetNumberFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
991 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
992 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
994 STRINGSA("--",""); /* Double '-' --> Error */
995 SetLastError(0xdeadbeef);
996 ret
= GetNumberFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
997 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
998 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1000 STRINGSA("0-",""); /* Trailing '-' --> Error */
1001 SetLastError(0xdeadbeef);
1002 ret
= GetNumberFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
1003 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1004 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1006 STRINGSA("0..",""); /* Double '.' --> Error */
1007 SetLastError(0xdeadbeef);
1008 ret
= GetNumberFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
1009 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1010 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1012 STRINGSA(" 0.1",""); /* Leading space --> Error */
1013 SetLastError(0xdeadbeef);
1014 ret
= GetNumberFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
1015 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1016 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1018 STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
1019 SetLastError(0xdeadbeef);
1020 ret
= GetNumberFormatA(lcid
, NUO
, input
, NULL
, buffer
, 2);
1021 ok( !ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
1022 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1024 STRINGSA("2353",""); /* Format and flags given --> Error */
1025 SetLastError(0xdeadbeef);
1026 ret
= GetNumberFormatA(lcid
, NUO
, input
, &format
, buffer
, COUNTOF(buffer
));
1027 ok( !ret
, "Expected ret == 0, got %d\n", ret
);
1028 ok( GetLastError() == ERROR_INVALID_FLAGS
|| GetLastError() == ERROR_INVALID_PARAMETER
,
1029 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1031 STRINGSA("2353",""); /* Invalid format --> Error */
1032 SetLastError(0xdeadbeef);
1033 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1034 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1035 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1037 STRINGSA("2353","2,353.00"); /* Valid number */
1038 ret
= GetNumberFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1039 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1040 EXPECT_LENA
; EXPECT_EQA
;
1042 STRINGSA("-2353","-2,353.00"); /* Valid negative number */
1043 ret
= GetNumberFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1044 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1045 EXPECT_LENA
; EXPECT_EQA
;
1047 STRINGSA("-353","-353.00"); /* test for off by one error in grouping */
1048 ret
= GetNumberFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1049 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1050 EXPECT_LENA
; EXPECT_EQA
;
1052 STRINGSA("2353.1","2,353.10"); /* Valid real number */
1053 ret
= GetNumberFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1054 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1055 EXPECT_LENA
; EXPECT_EQA
;
1057 STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
1058 ret
= GetNumberFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1059 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1060 EXPECT_LENA
; EXPECT_EQA
;
1062 STRINGSA("2353.119","2,353.12"); /* Too many DP --> Rounded */
1063 ret
= GetNumberFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1064 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1065 EXPECT_LENA
; EXPECT_EQA
;
1067 format
.NumDigits
= 0; /* No decimal separator */
1068 format
.LeadingZero
= 0;
1069 format
.Grouping
= 0; /* No grouping char */
1070 format
.NegativeOrder
= 0;
1071 format
.lpDecimalSep
= szDot
;
1072 format
.lpThousandSep
= szComma
;
1074 STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
1075 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1076 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1077 EXPECT_LENA
; EXPECT_EQA
;
1079 format
.NumDigits
= 1; /* 1 DP --> Expect decimal separator */
1080 STRINGSA("2353","2353.0");
1081 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1082 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1083 EXPECT_LENA
; EXPECT_EQA
;
1085 format
.Grouping
= 2; /* Group by 100's */
1086 STRINGSA("2353","23,53.0");
1087 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1088 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1089 EXPECT_LENA
; EXPECT_EQA
;
1091 STRINGSA("235","235.0"); /* Grouping of a positive number */
1092 format
.Grouping
= 3;
1093 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1094 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1095 EXPECT_LENA
; EXPECT_EQA
;
1097 STRINGSA("-235","-235.0"); /* Grouping of a negative number */
1098 format
.NegativeOrder
= NEG_LEFT
;
1099 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1100 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1101 EXPECT_LENA
; EXPECT_EQA
;
1103 format
.LeadingZero
= 1; /* Always provide leading zero */
1104 STRINGSA(".5","0.5");
1105 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1106 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1107 EXPECT_LENA
; EXPECT_EQA
;
1109 format
.NegativeOrder
= NEG_PARENS
;
1110 STRINGSA("-1","(1.0)");
1111 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1112 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1113 EXPECT_LENA
; EXPECT_EQA
;
1115 format
.NegativeOrder
= NEG_LEFT
;
1116 STRINGSA("-1","-1.0");
1117 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1118 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1119 EXPECT_LENA
; EXPECT_EQA
;
1121 format
.NegativeOrder
= NEG_LEFT_SPACE
;
1122 STRINGSA("-1","- 1.0");
1123 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1124 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1125 EXPECT_LENA
; EXPECT_EQA
;
1127 format
.NegativeOrder
= NEG_RIGHT
;
1128 STRINGSA("-1","1.0-");
1129 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1130 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1131 EXPECT_LENA
; EXPECT_EQA
;
1133 format
.NegativeOrder
= NEG_RIGHT_SPACE
;
1134 STRINGSA("-1","1.0 -");
1135 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1136 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1137 EXPECT_LENA
; EXPECT_EQA
;
1139 lcid
= MAKELCID(MAKELANGID(LANG_FRENCH
, SUBLANG_DEFAULT
), SORT_DEFAULT
);
1141 if (IsValidLocale(lcid
, 0))
1143 STRINGSA("-12345","-12 345,00"); /* Try French formatting */
1144 Expected
[3] = 160; /* Non breaking space */
1145 ret
= GetNumberFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1146 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1147 EXPECT_LENA
; EXPECT_EQA
;
1151 struct comparestringa_entry
{
1161 static const struct comparestringa_entry comparestringa_data
[] = {
1162 { LOCALE_SYSTEM_DEFAULT
, 0, "EndDialog", -1, "_Property", -1, CSTR_GREATER_THAN
},
1163 { LOCALE_SYSTEM_DEFAULT
, 0, "osp_vba.sreg0070", -1, "_IEWWBrowserComp", -1, CSTR_GREATER_THAN
},
1164 { LOCALE_SYSTEM_DEFAULT
, 0, "r", -1, "\\", -1, CSTR_GREATER_THAN
},
1165 { LOCALE_SYSTEM_DEFAULT
, 0, "osp_vba.sreg0031", -1, "OriginalDatabase", -1, CSTR_GREATER_THAN
},
1166 { LOCALE_SYSTEM_DEFAULT
, 0, "AAA", -1, "aaa", -1, CSTR_GREATER_THAN
},
1167 { LOCALE_SYSTEM_DEFAULT
, 0, "AAA", -1, "aab", -1, CSTR_LESS_THAN
},
1168 { LOCALE_SYSTEM_DEFAULT
, 0, "AAA", -1, "Aab", -1, CSTR_LESS_THAN
},
1169 { LOCALE_SYSTEM_DEFAULT
, 0, ".AAA", -1, "Aab", -1, CSTR_LESS_THAN
},
1170 { LOCALE_SYSTEM_DEFAULT
, 0, ".AAA", -1, "A.ab", -1, CSTR_LESS_THAN
},
1171 { LOCALE_SYSTEM_DEFAULT
, 0, "aa", -1, "AB", -1, CSTR_LESS_THAN
},
1172 { LOCALE_SYSTEM_DEFAULT
, 0, "aa", -1, "Aab", -1, CSTR_LESS_THAN
},
1173 { LOCALE_SYSTEM_DEFAULT
, 0, "aB", -1, "Aab", -1, CSTR_GREATER_THAN
},
1174 { LOCALE_SYSTEM_DEFAULT
, 0, "Ba", -1, "bab", -1, CSTR_LESS_THAN
},
1175 { LOCALE_SYSTEM_DEFAULT
, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1, CSTR_LESS_THAN
},
1176 { LOCALE_SYSTEM_DEFAULT
, 0, "a", -1, "{", -1, CSTR_GREATER_THAN
},
1177 { LOCALE_SYSTEM_DEFAULT
, 0, "A", -1, "{", -1, CSTR_GREATER_THAN
},
1178 { LOCALE_SYSTEM_DEFAULT
, 0, "3.5", 0, "4.0", -1, CSTR_LESS_THAN
},
1179 { LOCALE_SYSTEM_DEFAULT
, 0, "3.5", -1, "4.0", -1, CSTR_LESS_THAN
},
1180 { LOCALE_SYSTEM_DEFAULT
, 0, "3.520.4403.2", -1, "4.0.2927.10", -1, CSTR_LESS_THAN
},
1181 /* hyphen and apostrophe are treated differently depending on whether SORT_STRINGSORT specified or not */
1182 { LOCALE_SYSTEM_DEFAULT
, 0, "-o", -1, "/m", -1, CSTR_GREATER_THAN
},
1183 { LOCALE_SYSTEM_DEFAULT
, 0, "/m", -1, "-o", -1, CSTR_LESS_THAN
},
1184 { LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "-o", -1, "/m", -1, CSTR_LESS_THAN
},
1185 { LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "/m", -1, "-o", -1, CSTR_GREATER_THAN
},
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, "aLuZkUtZ", 8, "aLuZkUtZ", 9, CSTR_EQUAL
},
1191 { LOCALE_SYSTEM_DEFAULT
, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10, CSTR_LESS_THAN
}
1194 static void test_CompareStringA(void)
1197 LCID lcid
= MAKELCID(MAKELANGID(LANG_FRENCH
, SUBLANG_DEFAULT
), SORT_DEFAULT
);
1199 for (i
= 0; i
< sizeof(comparestringa_data
)/sizeof(struct comparestringa_entry
); i
++)
1201 const struct comparestringa_entry
*entry
= &comparestringa_data
[i
];
1203 ret
= CompareStringA(entry
->lcid
, entry
->flags
, entry
->first
, entry
->first_len
,
1204 entry
->second
, entry
->second_len
);
1205 ok(ret
== entry
->ret
, "%d: got %d, expected %d\n", i
, ret
, entry
->ret
);
1208 ret
= CompareStringA(lcid
, NORM_IGNORECASE
, "Salut", -1, "Salute", -1);
1209 ok (ret
== 1, "(Salut/Salute) Expected 1, got %d\n", ret
);
1211 ret
= CompareStringA(lcid
, NORM_IGNORECASE
, "Salut", -1, "SaLuT", -1);
1212 ok (ret
== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret
);
1214 ret
= CompareStringA(lcid
, NORM_IGNORECASE
, "Salut", -1, "hola", -1);
1215 ok (ret
== 3, "(Salut/hola) Expected 3, got %d\n", ret
);
1217 ret
= CompareStringA(lcid
, NORM_IGNORECASE
, "haha", -1, "hoho", -1);
1218 ok (ret
== 1, "(haha/hoho) Expected 1, got %d\n", ret
);
1220 lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
1222 ret
= CompareStringA(lcid
, NORM_IGNORECASE
, "haha", -1, "hoho", -1);
1223 ok (ret
== 1, "(haha/hoho) Expected 1, got %d\n", ret
);
1225 ret
= CompareStringA(lcid
, NORM_IGNORECASE
, "haha", -1, "hoho", 0);
1226 ok (ret
== 3, "(haha/hoho) Expected 3, got %d\n", ret
);
1228 ret
= CompareStringA(lcid
, NORM_IGNORECASE
, "Salut", 5, "saLuT", -1);
1229 ok (ret
== 2, "(Salut/saLuT) Expected 2, got %d\n", ret
);
1231 /* test for CompareStringA flags */
1232 SetLastError(0xdeadbeef);
1233 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0x8, "NULL", -1, "NULL", -1);
1234 ok(GetLastError() == ERROR_INVALID_FLAGS
,
1235 "unexpected error code %d\n", GetLastError());
1236 ok(!ret
, "CompareStringA must fail with invalid flag\n");
1238 SetLastError(0xdeadbeef);
1239 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, LOCALE_USE_CP_ACP
, "NULL", -1, "NULL", -1);
1240 ok(GetLastError() == 0xdeadbeef, "unexpected error code %d\n", GetLastError());
1241 ok(ret
== CSTR_EQUAL
, "CompareStringA error: %d != CSTR_EQUAL\n", ret
);
1242 /* end of test for CompareStringA flags */
1244 ret
= lstrcmpA("", "");
1245 ok (ret
== 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret
);
1247 ret
= lstrcmpA(NULL
, NULL
);
1248 ok (ret
== 0 || broken(ret
== -2) /* win9x */, "lstrcmpA(NULL, NULL) should return 0, got %d\n", ret
);
1250 ret
= lstrcmpA("", NULL
);
1251 ok (ret
== 1 || broken(ret
== -2) /* win9x */, "lstrcmpA(\"\", NULL) should return 1, got %d\n", ret
);
1253 ret
= lstrcmpA(NULL
, "");
1254 ok (ret
== -1 || broken(ret
== -2) /* win9x */, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret
);
1257 if (0) { /* this requires collation table patch to make it MS compatible */
1258 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "'o", -1, "-o", -1 );
1259 ok(ret
== 1, "'o vs -o expected 1, got %d\n", ret
);
1261 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "'o", -1, "-o", -1 );
1262 ok(ret
== 1, "'o vs -o expected 1, got %d\n", ret
);
1264 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "'", -1, "-", -1 );
1265 ok(ret
== 1, "' vs - expected 1, got %d\n", ret
);
1267 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "'", -1, "-", -1 );
1268 ok(ret
== 1, "' vs - expected 1, got %d\n", ret
);
1270 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "`o", -1, "/m", -1 );
1271 ok(ret
== 3, "`o vs /m expected 3, got %d\n", ret
);
1273 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "/m", -1, "`o", -1 );
1274 ok(ret
== 1, "/m vs `o expected 1, got %d\n", ret
);
1276 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "`o", -1, "/m", -1 );
1277 ok(ret
== 3, "`o vs /m expected 3, got %d\n", ret
);
1279 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "/m", -1, "`o", -1 );
1280 ok(ret
== 1, "/m vs `o expected 1, got %d\n", ret
);
1282 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "`o", -1, "-m", -1 );
1283 ok(ret
== 1, "`o vs -m expected 1, got %d\n", ret
);
1285 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "-m", -1, "`o", -1 );
1286 ok(ret
== 3, "-m vs `o expected 3, got %d\n", ret
);
1288 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "`o", -1, "-m", -1 );
1289 ok(ret
== 3, "`o vs -m expected 3, got %d\n", ret
);
1291 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "-m", -1, "`o", -1 );
1292 ok(ret
== 1, "-m vs `o expected 1, got %d\n", ret
);
1296 /* WinXP handles embedded NULLs differently than earlier versions */
1297 ret
= CompareStringA(LOCALE_USER_DEFAULT
, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
1298 ok(ret
== 1 || ret
== 2, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1 or 2, got %d\n", ret
);
1300 ret
= CompareStringA(LOCALE_USER_DEFAULT
, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
1301 ok(ret
== 1 || ret
== 2, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected 1 or 2, got %d\n", ret
);
1303 ret
= CompareStringA(lcid
, 0, "a\0b", -1, "a", -1);
1304 ok(ret
== 2, "a vs a expected 2, got %d\n", ret
);
1306 ret
= CompareStringA(lcid
, 0, "a\0b", 4, "a", 2);
1307 ok(ret
== CSTR_EQUAL
|| /* win2k */
1308 ret
== CSTR_GREATER_THAN
,
1309 "a\\0b vs a expected CSTR_EQUAL or CSTR_GREATER_THAN, got %d\n", ret
);
1311 ret
= CompareStringA(lcid
, 0, "\2", 2, "\1", 2);
1312 todo_wine
ok(ret
!= 2, "\\2 vs \\1 expected unequal\n");
1314 ret
= CompareStringA(lcid
, NORM_IGNORECASE
| LOCALE_USE_CP_ACP
, "#", -1, ".", -1);
1315 todo_wine
ok(ret
== CSTR_LESS_THAN
, "\"#\" vs \".\" expected CSTR_LESS_THAN, got %d\n", ret
);
1317 ret
= CompareStringA(lcid
, NORM_IGNORECASE
, "_", -1, ".", -1);
1318 todo_wine
ok(ret
== CSTR_GREATER_THAN
, "\"_\" vs \".\" expected CSTR_GREATER_THAN, got %d\n", ret
);
1320 ret
= lstrcmpi("#", ".");
1321 todo_wine
ok(ret
== -1, "\"#\" vs \".\" expected -1, got %d\n", ret
);
1323 lcid
= MAKELCID(MAKELANGID(LANG_POLISH
, SUBLANG_DEFAULT
), SORT_DEFAULT
);
1325 /* \xB9 character lies between a and b */
1326 ret
= CompareStringA(lcid
, 0, "a", 1, "\xB9", 1);
1327 todo_wine
ok(ret
== CSTR_LESS_THAN
, "\'\\xB9\' character should be greater than \'a\'\n");
1328 ret
= CompareStringA(lcid
, 0, "\xB9", 1, "b", 1);
1329 ok(ret
== CSTR_LESS_THAN
, "\'\\xB9\' character should be smaller than \'b\'\n");
1332 static void test_LCMapStringA(void)
1335 char buf
[256], buf2
[256];
1336 static const char upper_case
[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
1337 static const char lower_case
[] = "\tjust! a, test; string 1/*+-.\r\n";
1338 static const char symbols_stripped
[] = "justateststring1";
1340 SetLastError(0xdeadbeef);
1341 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LOCALE_USE_CP_ACP
| LCMAP_LOWERCASE
,
1342 lower_case
, -1, buf
, sizeof(buf
));
1343 ok(ret
== lstrlenA(lower_case
) + 1,
1344 "ret %d, error %d, expected value %d\n",
1345 ret
, GetLastError(), lstrlenA(lower_case
) + 1);
1346 ok(!memcmp(buf
, lower_case
, ret
), "LCMapStringA should return %s, but not %s\n", lower_case
, buf
);
1348 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_LOWERCASE
| LCMAP_UPPERCASE
,
1349 upper_case
, -1, buf
, sizeof(buf
));
1350 ok(!ret
, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1351 ok(GetLastError() == ERROR_INVALID_FLAGS
,
1352 "unexpected error code %d\n", GetLastError());
1354 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_HIRAGANA
| LCMAP_KATAKANA
,
1355 upper_case
, -1, buf
, sizeof(buf
));
1356 ok(!ret
, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1357 ok(GetLastError() == ERROR_INVALID_FLAGS
,
1358 "unexpected error code %d\n", GetLastError());
1360 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_HALFWIDTH
| LCMAP_FULLWIDTH
,
1361 upper_case
, -1, buf
, sizeof(buf
));
1362 ok(!ret
, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1363 ok(GetLastError() == ERROR_INVALID_FLAGS
,
1364 "unexpected error code %d\n", GetLastError());
1366 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_TRADITIONAL_CHINESE
| LCMAP_SIMPLIFIED_CHINESE
,
1367 upper_case
, -1, buf
, sizeof(buf
));
1368 ok(!ret
, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1369 ok(GetLastError() == ERROR_INVALID_FLAGS
,
1370 "unexpected error code %d\n", GetLastError());
1372 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1373 SetLastError(0xdeadbeef);
1374 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_LOWERCASE
| SORT_STRINGSORT
,
1375 upper_case
, -1, buf
, sizeof(buf
));
1376 ok(GetLastError() == ERROR_INVALID_FLAGS
, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1377 ok(!ret
, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1379 /* test LCMAP_LOWERCASE */
1380 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_LOWERCASE
,
1381 upper_case
, -1, buf
, sizeof(buf
));
1382 ok(ret
== lstrlenA(upper_case
) + 1,
1383 "ret %d, error %d, expected value %d\n",
1384 ret
, GetLastError(), lstrlenA(upper_case
) + 1);
1385 ok(!lstrcmpA(buf
, lower_case
), "LCMapStringA should return %s, but not %s\n", lower_case
, buf
);
1387 /* test LCMAP_UPPERCASE */
1388 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_UPPERCASE
,
1389 lower_case
, -1, buf
, sizeof(buf
));
1390 ok(ret
== lstrlenA(lower_case
) + 1,
1391 "ret %d, error %d, expected value %d\n",
1392 ret
, GetLastError(), lstrlenA(lower_case
) + 1);
1393 ok(!lstrcmpA(buf
, upper_case
), "LCMapStringA should return %s, but not %s\n", upper_case
, buf
);
1395 /* test buffer overflow */
1396 SetLastError(0xdeadbeef);
1397 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_UPPERCASE
,
1398 lower_case
, -1, buf
, 4);
1399 ok(!ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
1400 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret
);
1402 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1403 lstrcpyA(buf
, lower_case
);
1404 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_UPPERCASE
,
1405 buf
, -1, buf
, sizeof(buf
));
1406 if (!ret
) /* Win9x */
1407 trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1410 ok(ret
== lstrlenA(lower_case
) + 1,
1411 "ret %d, error %d, expected value %d\n",
1412 ret
, GetLastError(), lstrlenA(lower_case
) + 1);
1413 ok(!lstrcmpA(buf
, upper_case
), "LCMapStringA should return %s, but not %s\n", upper_case
, buf
);
1415 lstrcpyA(buf
, upper_case
);
1416 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_LOWERCASE
,
1417 buf
, -1, buf
, sizeof(buf
));
1418 if (!ret
) /* Win9x */
1419 trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1422 ok(ret
== lstrlenA(upper_case
) + 1,
1423 "ret %d, error %d, expected value %d\n",
1424 ret
, GetLastError(), lstrlenA(lower_case
) + 1);
1425 ok(!lstrcmpA(buf
, lower_case
), "LCMapStringA should return %s, but not %s\n", lower_case
, buf
);
1428 /* otherwise src == dst should fail */
1429 SetLastError(0xdeadbeef);
1430 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
| LCMAP_UPPERCASE
,
1431 buf
, 10, buf
, sizeof(buf
));
1432 ok(GetLastError() == ERROR_INVALID_FLAGS
/* NT */ ||
1433 GetLastError() == ERROR_INVALID_PARAMETER
/* Win9x */,
1434 "unexpected error code %d\n", GetLastError());
1435 ok(!ret
, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1437 /* test whether '\0' is always appended */
1438 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
,
1439 upper_case
, -1, buf
, sizeof(buf
));
1440 ok(ret
, "LCMapStringA must succeed\n");
1441 ok(buf
[ret
-1] == 0, "LCMapStringA not null-terminated\n");
1442 ret2
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
,
1443 upper_case
, lstrlenA(upper_case
), buf2
, sizeof(buf2
));
1444 ok(ret2
, "LCMapStringA must succeed\n");
1445 ok(buf2
[ret2
-1] == 0, "LCMapStringA not null-terminated\n" );
1446 ok(ret
== ret2
, "lengths of sort keys must be equal\n");
1447 ok(!lstrcmpA(buf
, buf2
), "sort keys must be equal\n");
1449 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1450 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
| NORM_IGNORECASE
,
1451 upper_case
, -1, buf
, sizeof(buf
));
1452 ok(ret
, "LCMapStringA must succeed\n");
1453 ret2
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
,
1454 lower_case
, -1, buf2
, sizeof(buf2
));
1455 ok(ret2
, "LCMapStringA must succeed\n");
1456 ok(ret
== ret2
, "lengths of sort keys must be equal\n");
1457 ok(!lstrcmpA(buf
, buf2
), "sort keys must be equal\n");
1459 /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1460 results from plain LCMAP_SORTKEY on Vista */
1462 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1463 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
| NORM_IGNORESYMBOLS
,
1464 lower_case
, -1, buf
, sizeof(buf
));
1465 ok(ret
, "LCMapStringA must succeed\n");
1466 ret2
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
,
1467 symbols_stripped
, -1, buf2
, sizeof(buf2
));
1468 ok(ret2
, "LCMapStringA must succeed\n");
1469 ok(ret
== ret2
, "lengths of sort keys must be equal\n");
1470 ok(!lstrcmpA(buf
, buf2
), "sort keys must be equal\n");
1472 /* test NORM_IGNORENONSPACE */
1473 lstrcpyA(buf
, "foo");
1474 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, NORM_IGNORENONSPACE
,
1475 lower_case
, -1, buf
, sizeof(buf
));
1476 ok(ret
== lstrlenA(lower_case
) + 1, "LCMapStringA should return %d, ret = %d\n",
1477 lstrlenA(lower_case
) + 1, ret
);
1478 ok(!lstrcmpA(buf
, lower_case
), "LCMapStringA should return %s, but not %s\n", lower_case
, buf
);
1480 /* test NORM_IGNORESYMBOLS */
1481 lstrcpyA(buf
, "foo");
1482 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, NORM_IGNORESYMBOLS
,
1483 lower_case
, -1, buf
, sizeof(buf
));
1484 ok(ret
== lstrlenA(symbols_stripped
) + 1, "LCMapStringA should return %d, ret = %d\n",
1485 lstrlenA(symbols_stripped
) + 1, ret
);
1486 ok(!lstrcmpA(buf
, symbols_stripped
), "LCMapStringA should return %s, but not %s\n", lower_case
, buf
);
1488 /* test srclen = 0 */
1489 SetLastError(0xdeadbeef);
1490 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, 0, upper_case
, 0, buf
, sizeof(buf
));
1491 ok(!ret
, "LCMapStringA should fail with srclen = 0\n");
1492 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1493 "unexpected error code %d\n", GetLastError());
1496 static void test_LCMapStringW(void)
1499 WCHAR buf
[256], buf2
[256];
1500 char *p_buf
= (char *)buf
, *p_buf2
= (char *)buf2
;
1501 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};
1502 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};
1503 static const WCHAR symbols_stripped
[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
1504 static const WCHAR fooW
[] = {'f','o','o',0};
1506 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_LOWERCASE
| LCMAP_UPPERCASE
,
1507 upper_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
1508 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1510 win_skip("LCMapStringW is not implemented\n");
1514 ok(lstrcmpW(buf
, upper_case
) == 0, "Expected upper case string\n");
1517 ok(!ret
, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1518 ok(GetLastError() == ERROR_INVALID_FLAGS
,
1519 "unexpected error code %d\n", GetLastError());
1522 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_HIRAGANA
| LCMAP_KATAKANA
,
1523 upper_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
1524 ok(!ret
, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1525 ok(GetLastError() == ERROR_INVALID_FLAGS
,
1526 "unexpected error code %d\n", GetLastError());
1528 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_HALFWIDTH
| LCMAP_FULLWIDTH
,
1529 upper_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
1530 ok(!ret
, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1531 ok(GetLastError() == ERROR_INVALID_FLAGS
,
1532 "unexpected error code %d\n", GetLastError());
1534 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_TRADITIONAL_CHINESE
| LCMAP_SIMPLIFIED_CHINESE
,
1535 upper_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
1536 ok(!ret
, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1537 ok(GetLastError() == ERROR_INVALID_FLAGS
,
1538 "unexpected error code %d\n", GetLastError());
1540 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1541 SetLastError(0xdeadbeef);
1542 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_LOWERCASE
| SORT_STRINGSORT
,
1543 upper_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
1544 ok(GetLastError() == ERROR_INVALID_FLAGS
, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1545 ok(!ret
, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1547 /* test LCMAP_LOWERCASE */
1548 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_LOWERCASE
,
1549 upper_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
1550 ok(ret
== lstrlenW(upper_case
) + 1,
1551 "ret %d, error %d, expected value %d\n",
1552 ret
, GetLastError(), lstrlenW(upper_case
) + 1);
1553 ok(!lstrcmpW(buf
, lower_case
), "string compare mismatch\n");
1555 /* test LCMAP_UPPERCASE */
1556 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_UPPERCASE
,
1557 lower_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
1558 ok(ret
== lstrlenW(lower_case
) + 1,
1559 "ret %d, error %d, expected value %d\n",
1560 ret
, GetLastError(), lstrlenW(lower_case
) + 1);
1561 ok(!lstrcmpW(buf
, upper_case
), "string compare mismatch\n");
1563 /* test buffer overflow */
1564 SetLastError(0xdeadbeef);
1565 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_UPPERCASE
,
1566 lower_case
, -1, buf
, 4);
1567 ok(!ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
1568 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret
);
1570 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1571 lstrcpyW(buf
, lower_case
);
1572 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_UPPERCASE
,
1573 buf
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
1574 ok(ret
== lstrlenW(lower_case
) + 1,
1575 "ret %d, error %d, expected value %d\n",
1576 ret
, GetLastError(), lstrlenW(lower_case
) + 1);
1577 ok(!lstrcmpW(buf
, upper_case
), "string compare mismatch\n");
1579 lstrcpyW(buf
, upper_case
);
1580 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_LOWERCASE
,
1581 buf
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
1582 ok(ret
== lstrlenW(upper_case
) + 1,
1583 "ret %d, error %d, expected value %d\n",
1584 ret
, GetLastError(), lstrlenW(lower_case
) + 1);
1585 ok(!lstrcmpW(buf
, lower_case
), "string compare mismatch\n");
1587 /* otherwise src == dst should fail */
1588 SetLastError(0xdeadbeef);
1589 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
| LCMAP_UPPERCASE
,
1590 buf
, 10, buf
, sizeof(buf
));
1591 ok(GetLastError() == ERROR_INVALID_FLAGS
/* NT */ ||
1592 GetLastError() == ERROR_INVALID_PARAMETER
/* Win9x */,
1593 "unexpected error code %d\n", GetLastError());
1594 ok(!ret
, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1596 /* test whether '\0' is always appended */
1597 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
,
1598 upper_case
, -1, buf
, sizeof(buf
));
1599 ok(ret
, "LCMapStringW must succeed\n");
1600 ret2
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
,
1601 upper_case
, lstrlenW(upper_case
), buf2
, sizeof(buf2
));
1602 ok(ret
, "LCMapStringW must succeed\n");
1603 ok(ret
== ret2
, "lengths of sort keys must be equal\n");
1604 ok(!lstrcmpA(p_buf
, p_buf2
), "sort keys must be equal\n");
1606 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1607 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
| NORM_IGNORECASE
,
1608 upper_case
, -1, buf
, sizeof(buf
));
1609 ok(ret
, "LCMapStringW must succeed\n");
1610 ret2
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
,
1611 lower_case
, -1, buf2
, sizeof(buf2
));
1612 ok(ret2
, "LCMapStringW must succeed\n");
1613 ok(ret
== ret2
, "lengths of sort keys must be equal\n");
1614 ok(!lstrcmpA(p_buf
, p_buf2
), "sort keys must be equal\n");
1616 /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
1617 results from plain LCMAP_SORTKEY on Vista */
1619 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1620 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
| NORM_IGNORESYMBOLS
,
1621 lower_case
, -1, buf
, sizeof(buf
));
1622 ok(ret
, "LCMapStringW must succeed\n");
1623 ret2
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
,
1624 symbols_stripped
, -1, buf2
, sizeof(buf2
));
1625 ok(ret2
, "LCMapStringW must succeed\n");
1626 ok(ret
== ret2
, "lengths of sort keys must be equal\n");
1627 ok(!lstrcmpA(p_buf
, p_buf2
), "sort keys must be equal\n");
1629 /* test NORM_IGNORENONSPACE */
1630 lstrcpyW(buf
, fooW
);
1631 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, NORM_IGNORENONSPACE
,
1632 lower_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
1633 ok(ret
== lstrlenW(lower_case
) + 1, "LCMapStringW should return %d, ret = %d\n",
1634 lstrlenW(lower_case
) + 1, ret
);
1635 ok(!lstrcmpW(buf
, lower_case
), "string comparison mismatch\n");
1637 /* test NORM_IGNORESYMBOLS */
1638 lstrcpyW(buf
, fooW
);
1639 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, NORM_IGNORESYMBOLS
,
1640 lower_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
1641 ok(ret
== lstrlenW(symbols_stripped
) + 1, "LCMapStringW should return %d, ret = %d\n",
1642 lstrlenW(symbols_stripped
) + 1, ret
);
1643 ok(!lstrcmpW(buf
, symbols_stripped
), "string comparison mismatch\n");
1645 /* test srclen = 0 */
1646 SetLastError(0xdeadbeef);
1647 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, 0, upper_case
, 0, buf
, sizeof(buf
)/sizeof(WCHAR
));
1648 ok(!ret
, "LCMapStringW should fail with srclen = 0\n");
1649 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1650 "unexpected error code %d\n", GetLastError());
1653 static void test_LocaleNames(void)
1657 WCHAR buffer
[LOCALE_NAME_MAX_LENGTH
];
1659 if (!pLocaleNameToLCID
)
1661 win_skip( "LocaleNameToLCID not available\n" );
1667 lcid
= pLocaleNameToLCID(LOCALE_NAME_USER_DEFAULT
, 0);
1668 ok(lcid
== GetUserDefaultLCID() || broken(GetLastError() == ERROR_INVALID_PARAMETER
/* Vista */),
1669 "Expected lcid == %08x, got %08x, error %d\n", lcid
, GetUserDefaultLCID(), GetLastError());
1670 ret
= pLCIDToLocaleName(lcid
, buffer
, LOCALE_NAME_MAX_LENGTH
, 0);
1671 ok(ret
> 0, "Expected ret > 0, got %d, error %d\n", ret
, GetLastError());
1672 trace("%08x, %s\n", lcid
, wine_dbgstr_w(buffer
));
1675 lcid
= pLocaleNameToLCID(LOCALE_NAME_SYSTEM_DEFAULT
, 0);
1676 todo_wine
ok(!lcid
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1677 "Expected lcid != 0, got %08x, error %d\n", lcid
, GetLastError());
1678 ret
= pLCIDToLocaleName(lcid
, buffer
, LOCALE_NAME_MAX_LENGTH
, 0);
1679 ok(ret
> 0, "Expected ret > 0, got %d, error %d\n", ret
, GetLastError());
1680 trace("%08x, %s\n", lcid
, wine_dbgstr_w(buffer
));
1683 lcid
= pLocaleNameToLCID(LOCALE_NAME_INVARIANT
, 0);
1684 todo_wine
ok(lcid
== 0x7F, "Expected lcid = 0x7F, got %08x, error %d\n", lcid
, GetLastError());
1685 ret
= pLCIDToLocaleName(lcid
, buffer
, LOCALE_NAME_MAX_LENGTH
, 0);
1686 ok(ret
> 0, "Expected ret > 0, got %d, error %d\n", ret
, GetLastError());
1687 trace("%08x, %s\n", lcid
, wine_dbgstr_w(buffer
));
1690 /* this requires collation table patch to make it MS compatible */
1691 static const char * const strings_sorted
[] =
1723 static const char * const strings
[] =
1755 static int compare_string1(const void *e1
, const void *e2
)
1757 const char *s1
= *(const char *const *)e1
;
1758 const char *s2
= *(const char *const *)e2
;
1760 return lstrcmpA(s1
, s2
);
1763 static int compare_string2(const void *e1
, const void *e2
)
1765 const char *s1
= *(const char *const *)e1
;
1766 const char *s2
= *(const char *const *)e2
;
1768 return CompareStringA(0, 0, s1
, -1, s2
, -1) - 2;
1771 static int compare_string3(const void *e1
, const void *e2
)
1773 const char *s1
= *(const char *const *)e1
;
1774 const char *s2
= *(const char *const *)e2
;
1775 char key1
[256], key2
[256];
1777 LCMapStringA(0, LCMAP_SORTKEY
, s1
, -1, key1
, sizeof(key1
));
1778 LCMapStringA(0, LCMAP_SORTKEY
, s2
, -1, key2
, sizeof(key2
));
1779 return strcmp(key1
, key2
);
1782 static void test_sorting(void)
1785 char **str_buf
= (char **)buf
;
1788 assert(sizeof(buf
) >= sizeof(strings
));
1790 /* 1. sort using lstrcmpA */
1791 memcpy(buf
, strings
, sizeof(strings
));
1792 qsort(buf
, sizeof(strings
)/sizeof(strings
[0]), sizeof(strings
[0]), compare_string1
);
1793 for (i
= 0; i
< sizeof(strings
)/sizeof(strings
[0]); i
++)
1795 ok(!strcmp(strings_sorted
[i
], str_buf
[i
]),
1796 "qsort using lstrcmpA failed for element %d\n", i
);
1798 /* 2. sort using CompareStringA */
1799 memcpy(buf
, strings
, sizeof(strings
));
1800 qsort(buf
, sizeof(strings
)/sizeof(strings
[0]), sizeof(strings
[0]), compare_string2
);
1801 for (i
= 0; i
< sizeof(strings
)/sizeof(strings
[0]); i
++)
1803 ok(!strcmp(strings_sorted
[i
], str_buf
[i
]),
1804 "qsort using CompareStringA failed for element %d\n", i
);
1806 /* 3. sort using sort keys */
1807 memcpy(buf
, strings
, sizeof(strings
));
1808 qsort(buf
, sizeof(strings
)/sizeof(strings
[0]), sizeof(strings
[0]), compare_string3
);
1809 for (i
= 0; i
< sizeof(strings
)/sizeof(strings
[0]); i
++)
1811 ok(!strcmp(strings_sorted
[i
], str_buf
[i
]),
1812 "qsort using sort keys failed for element %d\n", i
);
1816 static void test_FoldStringA(void)
1820 char src
[256], dst
[256];
1821 static const char digits_src
[] = { 0xB9,0xB2,0xB3,'\0' };
1822 static const char digits_dst
[] = { '1','2','3','\0' };
1823 static const char composite_src
[] =
1825 0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
1826 0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
1827 0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
1828 0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
1829 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
1830 0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
1831 0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
1832 0xfb,0xfc,0xfd,0xff,'\0'
1834 static const char composite_dst
[] =
1836 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1837 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1838 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1839 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1840 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1841 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1842 0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
1843 0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
1844 0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
1845 0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
1846 0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
1847 0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
1848 0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
1849 0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
1850 0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1852 static const char composite_dst_alt
[] =
1854 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1855 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1856 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1857 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1858 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1859 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1860 0x4f,0x7e,0x4f,0xa8,0xd8,0x55,0x60,0x55,
1861 0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,0x61,
1862 0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,0x61,
1863 0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,0x65,
1864 0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,0x69,
1865 0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,0x6f,
1866 0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,0x6f,
1867 0xa8,0xf8,0x75,0x60,0x75,0xb4,0x75,0x5e,
1868 0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1870 static const char ligatures_src
[] =
1872 0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1874 static const char ligatures_dst
[] =
1876 'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1878 static const struct special
1882 } foldczone_special
[] =
1885 { 0x85, { 0x2e, 0x2e, 0x2e, 0x00 } },
1886 { 0x98, { 0x20, 0x7e, 0x00 } },
1887 { 0x99, { 0x54, 0x4d, 0x00 } },
1888 { 0xa0, { 0x20, 0x00 } },
1889 { 0xa8, { 0x20, 0xa8, 0x00 } },
1890 { 0xaa, { 0x61, 0x00 } },
1891 { 0xaf, { 0x20, 0xaf, 0x00 } },
1892 { 0xb2, { 0x32, 0x00 } },
1893 { 0xb3, { 0x33, 0x00 } },
1894 { 0xb4, { 0x20, 0xb4, 0x00 } },
1895 { 0xb8, { 0x20, 0xb8, 0x00 } },
1896 { 0xb9, { 0x31, 0x00 } },
1897 { 0xba, { 0x6f, 0x00 } },
1898 { 0xbc, { 0x31, 0x2f, 0x34, 0x00 } },
1899 { 0xbd, { 0x31, 0x2f, 0x32, 0x00 } },
1900 { 0xbe, { 0x33, 0x2f, 0x34, 0x00 } },
1905 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1907 /* these tests are locale specific */
1908 if (GetACP() != 1252)
1910 trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1914 /* MAP_FOLDDIGITS */
1916 ret
= pFoldStringA(MAP_FOLDDIGITS
, digits_src
, -1, dst
, 256);
1917 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1919 win_skip("FoldStringA is not implemented\n");
1922 ok(ret
== 4, "Expected ret == 4, got %d, error %d\n", ret
, GetLastError());
1923 ok(strcmp(dst
, digits_dst
) == 0,
1924 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst
, dst
);
1925 for (i
= 1; i
< 256; i
++)
1927 if (!strchr(digits_src
, i
))
1932 ret
= pFoldStringA(MAP_FOLDDIGITS
, src
, -1, dst
, 256);
1933 ok(ret
== 2, "Expected ret == 2, got %d, error %d\n", ret
, GetLastError());
1934 ok(dst
[0] == src
[0],
1935 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src
, dst
);
1939 /* MAP_EXPAND_LIGATURES */
1941 ret
= pFoldStringA(MAP_EXPAND_LIGATURES
, ligatures_src
, -1, dst
, 256);
1942 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
1943 if (!(ret
== 0 && GetLastError() == ERROR_INVALID_FLAGS
)) {
1944 ok(ret
== sizeof(ligatures_dst
), "Got %d, error %d\n", ret
, GetLastError());
1945 ok(strcmp(dst
, ligatures_dst
) == 0,
1946 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst
, dst
);
1947 for (i
= 1; i
< 256; i
++)
1949 if (!strchr(ligatures_src
, i
))
1954 ret
= pFoldStringA(MAP_EXPAND_LIGATURES
, src
, -1, dst
, 256);
1958 ok((i
== 0xDC && lstrcmpA(dst
, "UE") == 0) ||
1959 (i
== 0xFC && lstrcmpA(dst
, "ue") == 0),
1960 "Got %s for %d\n", dst
, i
);
1964 ok(ret
== 2, "Expected ret == 2, got %d, error %d\n", ret
, GetLastError());
1965 ok(dst
[0] == src
[0],
1966 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src
, dst
);
1974 ret
= pFoldStringA(MAP_COMPOSITE
, composite_src
, -1, dst
, 256);
1975 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1976 ok(ret
== 121 || ret
== 119, "Expected 121 or 119, got %d\n", ret
);
1977 ok(strcmp(dst
, composite_dst
) == 0 || strcmp(dst
, composite_dst_alt
) == 0,
1978 "MAP_COMPOSITE: Mismatch, got '%s'\n", dst
);
1980 for (i
= 1; i
< 256; i
++)
1982 if (!strchr(composite_src
, i
))
1987 ret
= pFoldStringA(MAP_COMPOSITE
, src
, -1, dst
, 256);
1988 ok(ret
== 2, "Expected ret == 2, got %d, error %d\n", ret
, GetLastError());
1989 ok(dst
[0] == src
[0],
1990 "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src
[0],
1991 (unsigned char)dst
[0],(unsigned char)dst
[1],(unsigned char)dst
[2]);
1996 for (i
= 1; i
< 256; i
++)
2001 ret
= pFoldStringA(MAP_FOLDCZONE
, src
, -1, dst
, 256);
2003 for (j
= 0; foldczone_special
[j
].src
!= 0 && ! is_special
; j
++)
2005 if (foldczone_special
[j
].src
== src
[0])
2007 ok(ret
== 2 || ret
== lstrlenA(foldczone_special
[j
].dst
) + 1,
2008 "Expected ret == 2 or %d, got %d, error %d\n",
2009 lstrlenA(foldczone_special
[j
].dst
) + 1, ret
, GetLastError());
2010 ok(src
[0] == dst
[0] || lstrcmpA(foldczone_special
[j
].dst
, dst
) == 0,
2011 "MAP_FOLDCZONE: string mismatch for 0x%02x\n",
2012 (unsigned char)src
[0]);
2018 ok(ret
== 2, "Expected ret == 2, got %d, error %d\n", ret
, GetLastError());
2019 ok(src
[0] == dst
[0],
2020 "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
2021 (unsigned char)src
[0], (unsigned char)dst
[0]);
2025 /* MAP_PRECOMPOSED */
2026 for (i
= 1; i
< 256; i
++)
2031 ret
= pFoldStringA(MAP_PRECOMPOSED
, src
, -1, dst
, 256);
2032 ok(ret
== 2, "Expected ret == 2, got %d, error %d\n", ret
, GetLastError());
2033 ok(src
[0] == dst
[0],
2034 "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
2035 (unsigned char)src
[0], (unsigned char)dst
[0]);
2039 static void test_FoldStringW(void)
2043 WCHAR src
[256], dst
[256], ch
, prev_ch
= 1;
2044 static const DWORD badFlags
[] =
2047 MAP_PRECOMPOSED
|MAP_COMPOSITE
,
2048 MAP_PRECOMPOSED
|MAP_EXPAND_LIGATURES
,
2049 MAP_COMPOSITE
|MAP_EXPAND_LIGATURES
2051 /* Ranges of digits 0-9 : Must be sorted! */
2052 static const WCHAR digitRanges
[] =
2054 0x0030, /* '0'-'9' */
2055 0x0660, /* Eastern Arabic */
2056 0x06F0, /* Arabic - Hindu */
2057 0x0966, /* Devengari */
2058 0x09E6, /* Bengalii */
2059 0x0A66, /* Gurmukhi */
2060 0x0AE6, /* Gujarati */
2062 0x0BE6, /* Tamil - No 0 */
2063 0x0C66, /* Telugu */
2064 0x0CE6, /* Kannada */
2065 0x0D66, /* Maylayalam */
2068 0x0F29, /* Tibet - 0 is out of sequence */
2069 0x2070, /* Superscript - 1, 2, 3 are out of sequence */
2070 0x2080, /* Subscript */
2071 0x245F, /* Circled - 0 is out of sequence */
2072 0x2473, /* Bracketed */
2073 0x2487, /* Full stop */
2074 0x2775, /* Inverted circled - No 0 */
2075 0x277F, /* Patterned circled - No 0 */
2076 0x2789, /* Inverted Patterned circled - No 0 */
2077 0x3020, /* Hangzhou */
2078 0xff10, /* Pliene chasse (?) */
2079 0xffff /* Terminator */
2081 /* Digits which are represented, but out of sequence */
2082 static const WCHAR outOfSequenceDigits
[] =
2084 0xB9, /* Superscript 1 */
2085 0xB2, /* Superscript 2 */
2086 0xB3, /* Superscript 3 */
2087 0x0F33, /* Tibetan half zero */
2088 0x24EA, /* Circled 0 */
2089 0x3007, /* Ideographic number zero */
2090 '\0' /* Terminator */
2092 /* Digits in digitRanges for which no representation is available */
2093 static const WCHAR noDigitAvailable
[] =
2095 0x0BE6, /* No Tamil 0 */
2096 0x0F29, /* No Tibetan half zero (out of sequence) */
2097 0x2473, /* No Bracketed 0 */
2098 0x2487, /* No 0 Full stop */
2099 0x2775, /* No inverted circled 0 */
2100 0x277F, /* No patterned circled */
2101 0x2789, /* No inverted Patterned circled */
2102 0x3020, /* No Hangzhou 0 */
2103 '\0' /* Terminator */
2105 static const WCHAR foldczone_src
[] =
2107 'W', 'i', 'n', 'e', 0x0348, 0x0551, 0x1323, 0x280d,
2108 0xff37, 0xff49, 0xff4e, 0xff45, '\0'
2110 static const WCHAR foldczone_dst
[] =
2112 'W','i','n','e',0x0348,0x0551,0x1323,0x280d,'W','i','n','e','\0'
2114 static const WCHAR foldczone_todo_src
[] =
2116 0x3c5,0x308,0x6a,0x30c,0xa0,0xaa,0
2118 static const WCHAR foldczone_todo_dst
[] =
2120 0x3cb,0x1f0,' ','a',0
2122 static const WCHAR foldczone_todo_broken_dst
[] =
2124 0x3cb,0x1f0,0xa0,0xaa,0
2126 static const WCHAR ligatures_src
[] =
2128 'W', 'i', 'n', 'e', 0x03a6, 0x03b9, 0x03bd, 0x03b5,
2129 0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
2130 0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
2131 0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
2132 0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
2133 0xfb04, 0xfb05, 0xfb06, '\0'
2135 static const WCHAR ligatures_dst
[] =
2137 'W','i','n','e',0x03a6,0x03b9,0x03bd,0x03b5,
2138 'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
2139 'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
2140 'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
2141 0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
2142 'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
2147 win_skip("FoldStringW is not available\n");
2148 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
2151 /* Invalid flag combinations */
2152 for (i
= 0; i
< sizeof(badFlags
)/sizeof(badFlags
[0]); i
++)
2154 src
[0] = dst
[0] = '\0';
2156 ret
= pFoldStringW(badFlags
[i
], src
, 256, dst
, 256);
2157 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED
)
2159 win_skip("FoldStringW is not implemented\n");
2162 ok(!ret
&& GetLastError() == ERROR_INVALID_FLAGS
,
2163 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2166 /* src & dst cannot be the same */
2168 ret
= pFoldStringW(MAP_FOLDCZONE
, src
, -1, src
, 256);
2169 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
2170 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2172 /* src can't be NULL */
2174 ret
= pFoldStringW(MAP_FOLDCZONE
, NULL
, -1, dst
, 256);
2175 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
2176 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2178 /* srclen can't be 0 */
2180 ret
= pFoldStringW(MAP_FOLDCZONE
, src
, 0, dst
, 256);
2181 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
2182 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2184 /* dstlen can't be < 0 */
2186 ret
= pFoldStringW(MAP_FOLDCZONE
, src
, -1, dst
, -1);
2187 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
2188 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2190 /* Ret includes terminating NUL which is appended if srclen = -1 */
2195 ret
= pFoldStringW(MAP_FOLDCZONE
, src
, -1, dst
, 256);
2196 ok(ret
== 2, "Expected ret == 2, got %d, error %d\n", ret
, GetLastError());
2197 ok(dst
[0] == 'A' && dst
[1] == '\0',
2198 "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%d\n",
2199 'A', '\0', ret
, dst
[0], dst
[1], GetLastError());
2201 /* If size is given, result is not NUL terminated */
2207 ret
= pFoldStringW(MAP_FOLDCZONE
, src
, 1, dst
, 256);
2208 ok(ret
== 1, "Expected ret == 1, got %d, error %d\n", ret
, GetLastError());
2209 ok(dst
[0] == 'A' && dst
[1] == 'X',
2210 "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%d\n",
2211 'A','X', ret
, dst
[0], dst
[1], GetLastError());
2213 /* MAP_FOLDDIGITS */
2214 for (j
= 0; j
< sizeof(digitRanges
)/sizeof(digitRanges
[0]); j
++)
2216 /* Check everything before this range */
2217 for (ch
= prev_ch
; ch
< digitRanges
[j
]; ch
++)
2221 src
[1] = dst
[0] = '\0';
2222 ret
= pFoldStringW(MAP_FOLDDIGITS
, src
, -1, dst
, 256);
2223 ok(ret
== 2, "Expected ret == 2, got %d, error %d\n", ret
, GetLastError());
2225 ok(dst
[0] == ch
|| strchrW(outOfSequenceDigits
, ch
) ||
2226 /* Wine (correctly) maps all Unicode 4.0+ digits */
2227 isdigitW(ch
) || (ch
>= 0x24F5 && ch
<= 0x24FD) || ch
== 0x24FF || ch
== 0x19da ||
2228 (ch
>= 0x1369 && ch
<= 0x1371),
2229 "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch
, ch
, dst
[0]);
2232 if (digitRanges
[j
] == 0xffff)
2233 break; /* Finished the whole code point space */
2235 for (ch
= digitRanges
[j
]; ch
< digitRanges
[j
] + 10; ch
++)
2239 /* Map out of sequence characters */
2240 if (ch
== 0x2071) c
= 0x00B9; /* Superscript 1 */
2241 else if (ch
== 0x2072) c
= 0x00B2; /* Superscript 2 */
2242 else if (ch
== 0x2073) c
= 0x00B3; /* Superscript 3 */
2243 else if (ch
== 0x245F) c
= 0x24EA; /* Circled 0 */
2247 src
[1] = dst
[0] = '\0';
2248 ret
= pFoldStringW(MAP_FOLDDIGITS
, src
, -1, dst
, 256);
2249 ok(ret
== 2, "Expected ret == 2, got %d, error %d\n", ret
, GetLastError());
2251 ok((dst
[0] == '0' + ch
- digitRanges
[j
] && dst
[1] == '\0') ||
2252 broken( dst
[0] == ch
) || /* old Windows versions don't have all mappings */
2253 (digitRanges
[j
] == 0x3020 && dst
[0] == ch
) || /* Hangzhou not present in all Windows versions */
2254 (digitRanges
[j
] == 0x0F29 && dst
[0] == ch
) || /* Tibetan not present in all Windows versions */
2255 strchrW(noDigitAvailable
, c
),
2256 "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
2257 ch
, '0' + digitRanges
[j
] - ch
, dst
[0]);
2264 ret
= pFoldStringW(MAP_FOLDCZONE
, foldczone_src
, -1, dst
, 256);
2265 ok(ret
== sizeof(foldczone_dst
)/sizeof(foldczone_dst
[0]),
2266 "Got %d, error %d\n", ret
, GetLastError());
2267 ok(!memcmp(dst
, foldczone_dst
, sizeof(foldczone_dst
)),
2268 "MAP_FOLDCZONE: Expanded incorrectly\n");
2270 ret
= pFoldStringW(MAP_FOLDCZONE
|MAP_PRECOMPOSED
, foldczone_todo_src
, -1, dst
, 256);
2271 todo_wine
ok(ret
== sizeof(foldczone_todo_dst
)/sizeof(foldczone_todo_dst
[0]),
2272 "Got %d, error %d\n", ret
, GetLastError());
2273 todo_wine
ok(!memcmp(dst
, foldczone_todo_dst
, sizeof(foldczone_todo_dst
))
2274 || broken(!memcmp(dst
, foldczone_todo_broken_dst
, sizeof(foldczone_todo_broken_dst
))),
2275 "MAP_FOLDCZONE: Expanded incorrectly (%s)\n", wine_dbgstr_w(dst
));
2277 /* MAP_EXPAND_LIGATURES */
2279 ret
= pFoldStringW(MAP_EXPAND_LIGATURES
, ligatures_src
, -1, dst
, 256);
2280 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
2281 if (!(ret
== 0 && GetLastError() == ERROR_INVALID_FLAGS
)) {
2282 ok(ret
== sizeof(ligatures_dst
)/sizeof(ligatures_dst
[0]),
2283 "Got %d, error %d\n", ret
, GetLastError());
2284 ok(!memcmp(dst
, ligatures_dst
, sizeof(ligatures_dst
)),
2285 "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
2288 /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
2293 #define LCID_OK(l) \
2294 ok(lcid == l, "Expected lcid = %08x, got %08x\n", l, lcid)
2295 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
2296 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
2297 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
2298 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
2300 static void test_ConvertDefaultLocale(void)
2304 /* Doesn't change lcid, even if non default sublang/sort used */
2305 TEST_LCID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
, SORT_DEFAULT
);
2306 TEST_LCID(LANG_ENGLISH
, SUBLANG_ENGLISH_UK
, SORT_DEFAULT
);
2307 TEST_LCID(LANG_JAPANESE
, SUBLANG_DEFAULT
, SORT_DEFAULT
);
2308 TEST_LCID(LANG_JAPANESE
, SUBLANG_DEFAULT
, SORT_JAPANESE_UNICODE
);
2310 /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
2311 LCID_RES(MKLCID(LANG_ENGLISH
, SUBLANG_NEUTRAL
, SORT_DEFAULT
),
2312 MKLCID(LANG_ENGLISH
, SUBLANG_DEFAULT
, SORT_DEFAULT
));
2313 LCID_RES(MKLCID(LANG_JAPANESE
, SUBLANG_NEUTRAL
, SORT_DEFAULT
),
2314 MKLCID(LANG_JAPANESE
, SUBLANG_DEFAULT
, SORT_DEFAULT
));
2316 /* Invariant language is not treated specially */
2317 TEST_LCID(LANG_INVARIANT
, SUBLANG_DEFAULT
, SORT_DEFAULT
);
2319 /* User/system default languages alone are not mapped */
2320 TEST_LCIDLANG(LANG_SYSTEM_DEFAULT
, SORT_JAPANESE_UNICODE
);
2321 TEST_LCIDLANG(LANG_USER_DEFAULT
, SORT_JAPANESE_UNICODE
);
2324 LCID_RES(LOCALE_SYSTEM_DEFAULT
, GetSystemDefaultLCID());
2325 LCID_RES(LOCALE_USER_DEFAULT
, GetUserDefaultLCID());
2326 LCID_RES(LOCALE_NEUTRAL
, GetUserDefaultLCID());
2329 static BOOL CALLBACK
langgrp_procA(LGRPID lgrpid
, LPSTR lpszNum
, LPSTR lpszName
,
2330 DWORD dwFlags
, LONG_PTR lParam
)
2332 trace("%08x, %s, %s, %08x, %08lx\n",
2333 lgrpid
, lpszNum
, lpszName
, dwFlags
, lParam
);
2335 ok(pIsValidLanguageGroup(lgrpid
, dwFlags
) == TRUE
,
2336 "Enumerated grp %d not valid (flags %d)\n", lgrpid
, dwFlags
);
2338 /* If lParam is one, we are calling with flags defaulted from 0 */
2339 ok(!lParam
|| (dwFlags
== LGRPID_INSTALLED
|| dwFlags
== LGRPID_SUPPORTED
),
2340 "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %d\n", dwFlags
);
2345 static void test_EnumSystemLanguageGroupsA(void)
2349 if (!pEnumSystemLanguageGroupsA
|| !pIsValidLanguageGroup
)
2351 win_skip("EnumSystemLanguageGroupsA and/or IsValidLanguageGroup are not available\n");
2355 /* No enumeration proc */
2357 ret
= pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED
, 0);
2358 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
2360 win_skip("EnumSystemLanguageGroupsA is not implemented\n");
2363 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
2364 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2368 pEnumSystemLanguageGroupsA(langgrp_procA
, LGRPID_INSTALLED
|LGRPID_SUPPORTED
, 0);
2369 ok(GetLastError() == ERROR_INVALID_FLAGS
, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2371 /* No flags - defaults to LGRPID_INSTALLED */
2372 SetLastError(0xdeadbeef);
2373 pEnumSystemLanguageGroupsA(langgrp_procA
, 0, 1);
2374 ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
2376 pEnumSystemLanguageGroupsA(langgrp_procA
, LGRPID_INSTALLED
, 0);
2377 pEnumSystemLanguageGroupsA(langgrp_procA
, LGRPID_SUPPORTED
, 0);
2380 static BOOL CALLBACK
enum_func( LPWSTR name
, DWORD flags
, LPARAM lparam
)
2382 trace( "%s %x\n", wine_dbgstr_w(name
), flags
);
2386 static void test_EnumSystemLocalesEx(void)
2390 if (!pEnumSystemLocalesEx
)
2392 win_skip( "EnumSystemLocalesEx not available\n" );
2395 SetLastError( 0xdeadbeef );
2396 ret
= pEnumSystemLocalesEx( enum_func
, LOCALE_ALL
, 0, (void *)1 );
2397 ok( !ret
, "should have failed\n" );
2398 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
2399 SetLastError( 0xdeadbeef );
2400 ret
= pEnumSystemLocalesEx( enum_func
, 0, 0, NULL
);
2401 ok( ret
, "failed err %u\n", GetLastError() );
2404 static BOOL CALLBACK
lgrplocale_procA(LGRPID lgrpid
, LCID lcid
, LPSTR lpszNum
,
2407 trace("%08x, %08x, %s, %08lx\n", lgrpid
, lcid
, lpszNum
, lParam
);
2409 /* invalid locale enumerated on some platforms */
2413 ok(pIsValidLanguageGroup(lgrpid
, LGRPID_SUPPORTED
) == TRUE
,
2414 "Enumerated grp %d not valid\n", lgrpid
);
2415 ok(IsValidLocale(lcid
, LCID_SUPPORTED
) == TRUE
,
2416 "Enumerated grp locale %d not valid\n", lcid
);
2420 static void test_EnumLanguageGroupLocalesA(void)
2424 if (!pEnumLanguageGroupLocalesA
|| !pIsValidLanguageGroup
)
2426 win_skip("EnumLanguageGroupLocalesA and/or IsValidLanguageGroup are not available\n");
2430 /* No enumeration proc */
2432 ret
= pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE
, 0, 0);
2433 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
2435 win_skip("EnumLanguageGroupLocalesA is not implemented\n");
2438 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
2439 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2441 /* lgrpid too small */
2443 ret
= pEnumLanguageGroupLocalesA(lgrplocale_procA
, 0, 0, 0);
2444 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
2445 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2447 /* lgrpid too big */
2449 ret
= pEnumLanguageGroupLocalesA(lgrplocale_procA
, LGRPID_ARMENIAN
+ 1, 0, 0);
2450 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
2451 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2453 /* dwFlags is reserved */
2455 ret
= pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE
, 0x1, 0);
2456 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
2457 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2459 pEnumLanguageGroupLocalesA(lgrplocale_procA
, LGRPID_WESTERN_EUROPE
, 0, 0);
2462 static void test_SetLocaleInfoA(void)
2465 LCID lcid
= GetUserDefaultLCID();
2469 bRet
= SetLocaleInfoA(lcid
, LOCALE_SDATE
, 0);
2470 ok( !bRet
&& GetLastError() == ERROR_INVALID_PARAMETER
,
2471 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2475 bRet
= SetLocaleInfoA(lcid
, LOCALE_IDATE
, "test_SetLocaleInfoA");
2476 ok(!bRet
&& GetLastError() == ERROR_INVALID_FLAGS
,
2477 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2481 bRet
= SetLocaleInfoA(lcid
, LOCALE_ILDATE
, "test_SetLocaleInfoA");
2482 ok(!bRet
&& GetLastError() == ERROR_INVALID_FLAGS
,
2483 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2486 static BOOL CALLBACK
luilocale_proc1A(LPSTR value
, LONG_PTR lParam
)
2488 trace("%s %08lx\n", value
, lParam
);
2492 static BOOL CALLBACK
luilocale_proc2A(LPSTR value
, LONG_PTR lParam
)
2494 ok(!enumCount
, "callback called again unexpected\n");
2499 static BOOL CALLBACK
luilocale_proc3A(LPSTR value
, LONG_PTR lParam
)
2501 ok(0,"callback called unexpected\n");
2505 static void test_EnumUILanguageA(void)
2508 if (!pEnumUILanguagesA
) {
2509 win_skip("EnumUILanguagesA is not available on Win9x or NT4\n");
2513 SetLastError(ERROR_SUCCESS
);
2514 ret
= pEnumUILanguagesA(luilocale_proc1A
, 0, 0);
2515 if (ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
2517 win_skip("EnumUILanguagesA is not implemented\n");
2520 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
2523 SetLastError(ERROR_SUCCESS
);
2524 ret
= pEnumUILanguagesA(luilocale_proc2A
, 0, 0);
2525 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
2527 SetLastError(ERROR_SUCCESS
);
2528 ret
= pEnumUILanguagesA(NULL
, 0, 0);
2529 ok(!ret
, "Expected return value FALSE, got %u\n", ret
);
2530 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
2531 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2533 SetLastError(ERROR_SUCCESS
);
2534 ret
= pEnumUILanguagesA(luilocale_proc3A
, 0x5a5a5a5a, 0);
2535 ok(!ret
, "Expected return value FALSE, got %u\n", ret
);
2536 ok(GetLastError() == ERROR_INVALID_FLAGS
, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
2538 SetLastError(ERROR_SUCCESS
);
2539 ret
= pEnumUILanguagesA(NULL
, 0x5a5a5a5a, 0);
2540 ok(!ret
, "Expected return value FALSE, got %u\n", ret
);
2541 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
2542 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2545 static char date_fmt_buf
[1024];
2547 static BOOL CALLBACK
enum_datetime_procA(LPSTR fmt
)
2549 lstrcatA(date_fmt_buf
, fmt
);
2550 lstrcatA(date_fmt_buf
, "\n");
2554 static void test_EnumDateFormatsA(void)
2558 LCID lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
2560 trace("EnumDateFormatsA 0\n");
2561 date_fmt_buf
[0] = 0;
2562 SetLastError(0xdeadbeef);
2563 ret
= EnumDateFormatsA(enum_datetime_procA
, lcid
, 0);
2564 if (!ret
&& (GetLastError() == ERROR_INVALID_FLAGS
))
2566 win_skip("0 for dwFlags is not supported\n");
2570 ok(ret
, "EnumDateFormatsA(0) error %d\n", GetLastError());
2571 trace("%s\n", date_fmt_buf
);
2572 /* test the 1st enumerated format */
2573 if ((p
= strchr(date_fmt_buf
, '\n'))) *p
= 0;
2574 ret
= GetLocaleInfoA(lcid
, LOCALE_SSHORTDATE
, buf
, sizeof(buf
));
2575 ok(ret
, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2576 ok(!lstrcmpA(date_fmt_buf
, buf
), "expected \"%s\" got \"%s\"\n", date_fmt_buf
, buf
);
2579 trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n");
2580 date_fmt_buf
[0] = 0;
2581 SetLastError(0xdeadbeef);
2582 ret
= EnumDateFormatsA(enum_datetime_procA
, lcid
, LOCALE_USE_CP_ACP
);
2583 if (!ret
&& (GetLastError() == ERROR_INVALID_FLAGS
))
2585 win_skip("LOCALE_USE_CP_ACP is not supported\n");
2589 ok(ret
, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2590 trace("%s\n", date_fmt_buf
);
2591 /* test the 1st enumerated format */
2592 if ((p
= strchr(date_fmt_buf
, '\n'))) *p
= 0;
2593 ret
= GetLocaleInfoA(lcid
, LOCALE_SSHORTDATE
, buf
, sizeof(buf
));
2594 ok(ret
, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2595 ok(!lstrcmpA(date_fmt_buf
, buf
), "expected \"%s\" got \"%s\"\n", date_fmt_buf
, buf
);
2598 trace("EnumDateFormatsA DATE_SHORTDATE\n");
2599 date_fmt_buf
[0] = 0;
2600 ret
= EnumDateFormatsA(enum_datetime_procA
, lcid
, DATE_SHORTDATE
);
2601 ok(ret
, "EnumDateFormatsA(DATE_SHORTDATE) error %d\n", GetLastError());
2602 trace("%s\n", date_fmt_buf
);
2603 /* test the 1st enumerated format */
2604 if ((p
= strchr(date_fmt_buf
, '\n'))) *p
= 0;
2605 ret
= GetLocaleInfoA(lcid
, LOCALE_SSHORTDATE
, buf
, sizeof(buf
));
2606 ok(ret
, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
2607 ok(!lstrcmpA(date_fmt_buf
, buf
), "expected \"%s\" got \"%s\"\n", date_fmt_buf
, buf
);
2609 trace("EnumDateFormatsA DATE_LONGDATE\n");
2610 date_fmt_buf
[0] = 0;
2611 ret
= EnumDateFormatsA(enum_datetime_procA
, lcid
, DATE_LONGDATE
);
2612 ok(ret
, "EnumDateFormatsA(DATE_LONGDATE) error %d\n", GetLastError());
2613 trace("%s\n", date_fmt_buf
);
2614 /* test the 1st enumerated format */
2615 if ((p
= strchr(date_fmt_buf
, '\n'))) *p
= 0;
2616 ret
= GetLocaleInfoA(lcid
, LOCALE_SLONGDATE
, buf
, sizeof(buf
));
2617 ok(ret
, "GetLocaleInfoA(LOCALE_SLONGDATE) error %d\n", GetLastError());
2618 ok(!lstrcmpA(date_fmt_buf
, buf
), "expected \"%s\" got \"%s\"\n", date_fmt_buf
, buf
);
2620 trace("EnumDateFormatsA DATE_YEARMONTH\n");
2621 date_fmt_buf
[0] = 0;
2622 SetLastError(0xdeadbeef);
2623 ret
= EnumDateFormatsA(enum_datetime_procA
, lcid
, DATE_YEARMONTH
);
2624 if (!ret
&& (GetLastError() == ERROR_INVALID_FLAGS
))
2626 skip("DATE_YEARMONTH is only present on W2K and later\n");
2629 ok(ret
, "EnumDateFormatsA(DATE_YEARMONTH) error %d\n", GetLastError());
2630 trace("%s\n", date_fmt_buf
);
2631 /* test the 1st enumerated format */
2632 if ((p
= strchr(date_fmt_buf
, '\n'))) *p
= 0;
2633 ret
= GetLocaleInfoA(lcid
, LOCALE_SYEARMONTH
, buf
, sizeof(buf
));
2634 ok(ret
, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %d\n", GetLastError());
2635 ok(!lstrcmpA(date_fmt_buf
, buf
) || broken(!buf
[0]) /* win9x */,
2636 "expected \"%s\" got \"%s\"\n", date_fmt_buf
, buf
);
2639 static void test_EnumTimeFormatsA(void)
2643 LCID lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
2645 trace("EnumTimeFormatsA 0\n");
2646 date_fmt_buf
[0] = 0;
2647 ret
= EnumTimeFormatsA(enum_datetime_procA
, lcid
, 0);
2648 ok(ret
, "EnumTimeFormatsA(0) error %d\n", GetLastError());
2649 trace("%s\n", date_fmt_buf
);
2650 /* test the 1st enumerated format */
2651 if ((p
= strchr(date_fmt_buf
, '\n'))) *p
= 0;
2652 ret
= GetLocaleInfoA(lcid
, LOCALE_STIMEFORMAT
, buf
, sizeof(buf
));
2653 ok(ret
, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2654 ok(!lstrcmpA(date_fmt_buf
, buf
), "expected \"%s\" got \"%s\"\n", date_fmt_buf
, buf
);
2656 trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n");
2657 date_fmt_buf
[0] = 0;
2658 ret
= EnumTimeFormatsA(enum_datetime_procA
, lcid
, LOCALE_USE_CP_ACP
);
2659 ok(ret
, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
2660 trace("%s\n", date_fmt_buf
);
2661 /* test the 1st enumerated format */
2662 if ((p
= strchr(date_fmt_buf
, '\n'))) *p
= 0;
2663 ret
= GetLocaleInfoA(lcid
, LOCALE_STIMEFORMAT
, buf
, sizeof(buf
));
2664 ok(ret
, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
2665 ok(!lstrcmpA(date_fmt_buf
, buf
), "expected \"%s\" got \"%s\"\n", date_fmt_buf
, buf
);
2668 static void test_GetCPInfo(void)
2673 SetLastError(0xdeadbeef);
2674 ret
= GetCPInfo(CP_SYMBOL
, &cpinfo
);
2675 ok(!ret
, "GetCPInfo(CP_SYMBOL) should fail\n");
2676 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
2677 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
2679 SetLastError(0xdeadbeef);
2680 ret
= GetCPInfo(CP_UTF7
, &cpinfo
);
2681 if (!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
)
2683 skip("Codepage CP_UTF7 is not installed/available\n");
2687 ok(ret
, "GetCPInfo(CP_UTF7) error %u\n", GetLastError());
2688 ok(cpinfo
.DefaultChar
[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo
.DefaultChar
[0]);
2689 ok(cpinfo
.DefaultChar
[1] == 0, "expected 0, got 0x%x\n", cpinfo
.DefaultChar
[1]);
2690 ok(cpinfo
.LeadByte
[0] == 0, "expected 0, got 0x%x\n", cpinfo
.LeadByte
[0]);
2691 ok(cpinfo
.LeadByte
[1] == 0, "expected 0, got 0x%x\n", cpinfo
.LeadByte
[1]);
2692 ok(cpinfo
.MaxCharSize
== 5, "expected 5, got 0x%x\n", cpinfo
.MaxCharSize
);
2695 SetLastError(0xdeadbeef);
2696 ret
= GetCPInfo(CP_UTF8
, &cpinfo
);
2697 if (!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
)
2699 skip("Codepage CP_UTF8 is not installed/available\n");
2703 ok(ret
, "GetCPInfo(CP_UTF8) error %u\n", GetLastError());
2704 ok(cpinfo
.DefaultChar
[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo
.DefaultChar
[0]);
2705 ok(cpinfo
.DefaultChar
[1] == 0, "expected 0, got 0x%x\n", cpinfo
.DefaultChar
[1]);
2706 ok(cpinfo
.LeadByte
[0] == 0, "expected 0, got 0x%x\n", cpinfo
.LeadByte
[0]);
2707 ok(cpinfo
.LeadByte
[1] == 0, "expected 0, got 0x%x\n", cpinfo
.LeadByte
[1]);
2708 ok(cpinfo
.MaxCharSize
== 4 || broken(cpinfo
.MaxCharSize
== 3) /* win9x */,
2709 "expected 4, got %u\n", cpinfo
.MaxCharSize
);
2714 * The CT_TYPE1 has varied over windows version.
2715 * The current target for correct behavior is windows 7.
2716 * There was a big shift between windows 2000 (first introduced) and windows Xp
2717 * Most of the old values below are from windows 2000.
2718 * A smaller subset of changes happened between windows Xp and Window vista/7
2720 static void test_GetStringTypeW(void)
2722 static const WCHAR blanks
[] = {0x9, 0x20, 0xa0, 0x3000, 0xfeff};
2723 static const WORD blanks_new
[] = {C1_SPACE
| C1_CNTRL
| C1_BLANK
| C1_DEFINED
,
2724 C1_SPACE
| C1_BLANK
| C1_DEFINED
,
2725 C1_SPACE
| C1_BLANK
| C1_DEFINED
,
2726 C1_SPACE
| C1_BLANK
| C1_DEFINED
,
2727 C1_CNTRL
| C1_BLANK
| C1_DEFINED
};
2728 static const WORD blanks_old
[] ={C1_SPACE
| C1_CNTRL
| C1_BLANK
,
2729 C1_SPACE
| C1_BLANK
,
2730 C1_SPACE
| C1_BLANK
,
2731 C1_SPACE
| C1_BLANK
,
2732 C1_SPACE
| C1_BLANK
};
2734 static const WCHAR undefined
[] = {0x378, 0x379, 0x604, 0xfff8, 0xfffe};
2737 static const WCHAR alpha
[] = {0x47, 0x67, 0x1c5};
2738 static const WORD alpha_old
[] = {C1_UPPER
| C1_ALPHA
,
2739 C1_LOWER
| C1_ALPHA
,
2740 C1_UPPER
| C1_LOWER
| C1_ALPHA
,
2743 /* Sk, Sk, Mn, So, Me */
2744 static const WCHAR oldpunc
[] = { 0x2c2, 0x2e5, 0x322, 0x482, 0x6de,
2746 0xffe0, 0xffe9, 0x2153};
2748 /* Lm, Nl, Cf, 0xad(Cf), 0x1f88 (Lt), Lo, Mc */
2749 static const WCHAR changed
[] = {0x2b0, 0x2160, 0x600, 0xad, 0x1f88, 0x294, 0x903};
2750 static const WORD changed_old
[] = { C1_PUNCT
, C1_PUNCT
, 0, C1_PUNCT
, C1_UPPER
| C1_ALPHA
, C1_ALPHA
, C1_PUNCT
};
2751 static const WORD changed_xp
[] = {C1_ALPHA
| C1_DEFINED
,
2752 C1_ALPHA
| C1_DEFINED
,
2753 C1_CNTRL
| C1_DEFINED
,
2754 C1_PUNCT
| C1_DEFINED
,
2755 C1_UPPER
| C1_LOWER
| C1_ALPHA
| C1_DEFINED
,
2756 C1_ALPHA
| C1_LOWER
| C1_DEFINED
,
2757 C1_ALPHA
| C1_DEFINED
};
2758 static const WORD changed_new
[] = { C1_ALPHA
| C1_DEFINED
,
2759 C1_ALPHA
| C1_DEFINED
,
2760 C1_CNTRL
| C1_DEFINED
,
2761 C1_PUNCT
| C1_CNTRL
| C1_DEFINED
,
2762 C1_UPPER
| C1_LOWER
| C1_ALPHA
| C1_DEFINED
,
2763 C1_ALPHA
| C1_DEFINED
,
2766 /* Pc, Pd, Ps, Pe, Pi, Pf, Po*/
2767 static const WCHAR punct
[] = { 0x5f, 0x2d, 0x28, 0x29, 0xab, 0xbb, 0x21 };
2769 static const WCHAR punct_special
[] = {0x24, 0x2b, 0x3c, 0x3e, 0x5e, 0x60,
2770 0x7c, 0x7e, 0xa2, 0xbe, 0xd7, 0xf7};
2771 static const WCHAR digit_special
[] = {0xb2, 0xb3, 0xb9};
2772 static const WCHAR lower_special
[] = {0x2071, 0x207f};
2773 static const WCHAR cntrl_special
[] = {0x070f, 0x200c, 0x200d,
2774 0x200e, 0x200f, 0x202a, 0x202b, 0x202c, 0x202d, 0x202e,
2775 0x206a, 0x206b, 0x206c, 0x206d, 0x206e, 0x206f, 0xfeff,
2776 0xfff9, 0xfffa, 0xfffb};
2777 static const WCHAR space_special
[] = {0x09, 0x0d, 0x85};
2782 memset(types
,0,sizeof(types
));
2783 GetStringTypeW(CT_CTYPE1
, blanks
, 5, types
);
2784 for (i
= 0; i
< 5; i
++)
2785 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
]);
2787 memset(types
,0,sizeof(types
));
2788 GetStringTypeW(CT_CTYPE1
, alpha
, 3, types
);
2789 for (i
= 0; i
< 3; i
++)
2790 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
]));
2791 memset(types
,0,sizeof(types
));
2792 GetStringTypeW(CT_CTYPE1
, undefined
, 5, types
);
2793 for (i
= 0; i
< 5; i
++)
2794 ok(types
[i
] == 0, "incorrect types returned for %x -> (%x != 0)\n",undefined
[i
], types
[i
]);
2796 memset(types
,0,sizeof(types
));
2797 GetStringTypeW(CT_CTYPE1
, oldpunc
, 8, types
);
2798 for (i
= 0; i
< 8; i
++)
2799 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
);
2801 memset(types
,0,sizeof(types
));
2802 GetStringTypeW(CT_CTYPE1
, changed
, 7, types
);
2803 for (i
= 0; i
< 7; i
++)
2804 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
]);
2806 memset(types
,0,sizeof(types
));
2807 GetStringTypeW(CT_CTYPE1
, punct
, 7, types
);
2808 for (i
= 0; i
< 7; i
++)
2809 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
));
2812 memset(types
,0,sizeof(types
));
2813 GetStringTypeW(CT_CTYPE1
, punct_special
, 12, types
);
2814 for (i
= 0; i
< 12; i
++)
2815 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
);
2817 memset(types
,0,sizeof(types
));
2818 GetStringTypeW(CT_CTYPE1
, digit_special
, 3, types
);
2819 for (i
= 0; i
< 3; i
++)
2820 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
);
2822 memset(types
,0,sizeof(types
));
2823 GetStringTypeW(CT_CTYPE1
, lower_special
, 2, types
);
2824 for (i
= 0; i
< 2; i
++)
2825 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
);
2827 memset(types
,0,sizeof(types
));
2828 GetStringTypeW(CT_CTYPE1
, cntrl_special
, 20, types
);
2829 for (i
= 0; i
< 20; i
++)
2830 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
);
2832 memset(types
,0,sizeof(types
));
2833 GetStringTypeW(CT_CTYPE1
, space_special
, 3, types
);
2834 for (i
= 0; i
< 3; i
++)
2835 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
);
2838 static void test_IdnToNameprepUnicode(void)
2844 const WCHAR out
[64];
2850 5, {'t','e','s','t',0},
2851 5, {'t','e','s','t',0},
2855 3, {'a',0xe111,'b'},
2857 0, ERROR_INVALID_NAME
2862 0, ERROR_INVALID_NAME
2872 0, ERROR_INVALID_NAME
2875 6, {' ','-','/','[',']',0},
2876 6, {' ','-','/','[',']',0},
2882 IDN_USE_STD3_ASCII_RULES
, 0xdeadbeef
2887 IDN_USE_STD3_ASCII_RULES
, ERROR_INVALID_NAME
2889 { /* FoldString is not working as expected when MAP_FOLDCZONE is specified (composition+compatibility) */
2890 10, {'T',0xdf,0x130,0x143,0x37a,0x6a,0x30c,' ',0xaa,0},
2891 12, {'t','s','s','i',0x307,0x144,' ',0x3b9,0x1f0,' ','a',0},
2895 11, {'t',0xad,0x34f,0x1806,0x180b,0x180c,0x180d,0x200b,0x200c,0x200d,0},
2899 { /* Another example of incorrectly working FoldString (composition) */
2907 0, ERROR_NO_UNICODE_TRANSLATION
2912 IDN_ALLOW_UNASSIGNED
, 0xdeadbeef
2915 5, {'a','.','.','a',0},
2917 0, ERROR_INVALID_NAME
2929 if (!pIdnToNameprepUnicode
)
2931 win_skip("IdnToNameprepUnicode is not available\n");
2935 ret
= pIdnToNameprepUnicode(0, test_data
[0].in
,
2936 test_data
[0].in_len
, NULL
, 0);
2937 ok(ret
== test_data
[0].ret
, "ret = %d\n", ret
);
2939 SetLastError(0xdeadbeef);
2940 ret
= pIdnToNameprepUnicode(0, test_data
[1].in
,
2941 test_data
[1].in_len
, NULL
, 0);
2942 err
= GetLastError();
2943 ok(ret
== test_data
[1].ret
, "ret = %d\n", ret
);
2944 ok(err
== test_data
[1].err
, "err = %d\n", err
);
2946 SetLastError(0xdeadbeef);
2947 ret
= pIdnToNameprepUnicode(0, test_data
[0].in
, -1,
2948 buf
, sizeof(buf
)/sizeof(WCHAR
));
2949 err
= GetLastError();
2950 ok(ret
== test_data
[0].ret
, "ret = %d\n", ret
);
2951 ok(err
== 0xdeadbeef, "err = %d\n", err
);
2953 SetLastError(0xdeadbeef);
2954 ret
= pIdnToNameprepUnicode(0, test_data
[0].in
, -2,
2955 buf
, sizeof(buf
)/sizeof(WCHAR
));
2956 err
= GetLastError();
2957 ok(ret
== 0, "ret = %d\n", ret
);
2958 ok(err
== ERROR_INVALID_PARAMETER
, "err = %d\n", err
);
2960 SetLastError(0xdeadbeef);
2961 ret
= pIdnToNameprepUnicode(0, test_data
[0].in
, 0,
2962 buf
, sizeof(buf
)/sizeof(WCHAR
));
2963 err
= GetLastError();
2964 ok(ret
== 0, "ret = %d\n", ret
);
2965 ok(err
== ERROR_INVALID_NAME
, "err = %d\n", err
);
2967 ret
= pIdnToNameprepUnicode(IDN_ALLOW_UNASSIGNED
|IDN_USE_STD3_ASCII_RULES
,
2968 test_data
[0].in
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
2969 ok(ret
== test_data
[0].ret
, "ret = %d\n", ret
);
2971 SetLastError(0xdeadbeef);
2972 ret
= pIdnToNameprepUnicode(0, NULL
, 0, NULL
, 0);
2973 err
= GetLastError();
2974 ok(ret
== 0, "ret = %d\n", ret
);
2975 ok(err
== ERROR_INVALID_PARAMETER
, "err = %d\n", err
);
2977 SetLastError(0xdeadbeef);
2978 ret
= pIdnToNameprepUnicode(4, NULL
, 0, NULL
, 0);
2979 err
= GetLastError();
2980 ok(ret
== 0, "ret = %d\n", ret
);
2981 ok(err
== ERROR_INVALID_FLAGS
, "err = %d\n", err
);
2983 for (i
=0; i
<sizeof(test_data
)/sizeof(*test_data
); i
++)
2985 SetLastError(0xdeadbeef);
2986 ret
= pIdnToNameprepUnicode(test_data
[i
].flags
, test_data
[i
].in
,
2987 test_data
[i
].in_len
, buf
, sizeof(buf
)/sizeof(WCHAR
));
2988 err
= GetLastError();
2989 if(!test_data
[i
].todo
) {
2990 ok(ret
== test_data
[i
].ret
, "%d) ret = %d\n", i
, ret
);
2991 ok(err
== test_data
[i
].err
, "%d) err = %d\n", i
, err
);
2992 ok(!memcmp(test_data
[i
].out
, buf
, ret
*sizeof(WCHAR
)),
2993 "%d) buf = %s\n", i
, wine_dbgstr_wn(buf
, ret
));
2995 todo_wine
ok(!memcmp(test_data
[i
].out
, buf
, ret
*sizeof(WCHAR
)),
2996 "%d) buf = %s\n", i
, wine_dbgstr_wn(buf
, ret
));
3001 static void test_IdnToAscii(void)
3007 const WCHAR out
[64];
3012 5, {'T','e','s','t',0},
3013 5, {'T','e','s','t',0},
3017 5, {'T','e',0x017c,'s','t',0},
3018 12, {'x','n','-','-','t','e','s','t','-','c','b','b',0},
3022 12, {'t','e',0x0105,'s','t','.','t','e',0x017c,'s','t',0},
3023 26, {'x','n','-','-','t','e','s','t','-','c','t','a','.','x','n','-','-','t','e','s','t','-','c','b','b',0},
3028 9, {'x','n','-','-','2','d','a','.',0},
3032 10, {'h','t','t','p',':','/','/','t',0x0106,0},
3033 17, {'x','n','-','-','h','t','t','p',':','/','/','t','-','7','8','a',0},
3037 10, {0x4e3a,0x8bf4,0x4e0d,0x4ed6,0x5011,0x10d,0x11b,0x305c,0x306a,0},
3038 35, {'x','n','-','-','b','e','a','2','a','1','6','3','1','a','v','b','a',
3039 'v','4','4','t','y','h','a','3','2','b','9','1','e','g','s','2','t',0},
3044 8, {'x','n','-','-','6','l','a',0},
3045 IDN_ALLOW_UNASSIGNED
, 0xdeadbeef
3054 win_skip("IdnToAscii is not available\n");
3058 for (i
=0; i
<sizeof(test_data
)/sizeof(*test_data
); i
++)
3060 SetLastError(0xdeadbeef);
3061 ret
= pIdnToAscii(test_data
[i
].flags
, test_data
[i
].in
,
3062 test_data
[i
].in_len
, buf
, sizeof(buf
));
3063 err
= GetLastError();
3064 ok(ret
== test_data
[i
].ret
, "%d) ret = %d\n", i
, ret
);
3065 ok(err
== test_data
[i
].err
, "%d) err = %d\n", i
, err
);
3066 ok(!memcmp(test_data
[i
].out
, buf
, ret
*sizeof(WCHAR
)),
3067 "%d) buf = %s\n", i
, wine_dbgstr_wn(buf
, ret
));
3071 static void test_IdnToUnicode(void)
3077 const WCHAR out
[64];
3082 5, {'T','e','s','.',0},
3083 5, {'T','e','s','.',0},
3089 0, ERROR_INVALID_NAME
3092 33, {'x','n','-','-','4','d','b','c','a','g','d','a','h','y','m','b',
3093 'x','e','k','h','e','h','6','e','0','a','7','f','e','i','0','b',0},
3094 23, {0x05dc,0x05de,0x05d4,0x05d4,0x05dd,0x05e4,0x05e9,0x05d5,0x05d8,
3095 0x05dc,0x05d0,0x05de,0x05d3,0x05d1,0x05e8,0x05d9,0x05dd,0x05e2,
3096 0x05d1,0x05e8,0x05d9,0x05ea,0},
3100 34, {'t','e','s','t','.','x','n','-','-','k','d','a','9','a','g','5','e',
3101 '9','j','n','f','s','j','.','x','n','-','-','p','d','-','f','n','a'},
3102 16, {'t','e','s','t','.',0x0105,0x0119,0x015b,0x0107,
3103 0x0142,0x00f3,0x017c,'.','p',0x0119,'d'},
3107 64, {'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
3108 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
3109 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
3110 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a'},
3112 0, ERROR_INVALID_NAME
3115 8, {'x','n','-','-','6','l','a',0},
3117 IDN_ALLOW_UNASSIGNED
, 0xdeadbeef
3126 win_skip("IdnToUnicode is not available\n");
3130 for (i
=0; i
<sizeof(test_data
)/sizeof(*test_data
); i
++)
3132 SetLastError(0xdeadbeef);
3133 ret
= pIdnToUnicode(test_data
[i
].flags
, test_data
[i
].in
,
3134 test_data
[i
].in_len
, buf
, sizeof(buf
));
3135 err
= GetLastError();
3136 ok(ret
== test_data
[i
].ret
, "%d) ret = %d\n", i
, ret
);
3137 ok(err
== test_data
[i
].err
, "%d) err = %d\n", i
, err
);
3138 ok(!memcmp(test_data
[i
].out
, buf
, ret
*sizeof(WCHAR
)),
3139 "%d) buf = %s\n", i
, wine_dbgstr_wn(buf
, ret
));
3145 InitFunctionPointers();
3147 test_EnumTimeFormatsA();
3148 test_EnumDateFormatsA();
3149 test_GetLocaleInfoA();
3150 test_GetLocaleInfoW();
3151 test_GetTimeFormatA();
3152 test_GetDateFormatA();
3153 test_GetDateFormatW();
3154 test_GetCurrencyFormatA(); /* Also tests the W version */
3155 test_GetNumberFormatA(); /* Also tests the W version */
3156 test_CompareStringA();
3157 test_LCMapStringA();
3158 test_LCMapStringW();
3162 test_ConvertDefaultLocale();
3163 test_EnumSystemLanguageGroupsA();
3164 test_EnumSystemLocalesEx();
3165 test_EnumLanguageGroupLocalesA();
3166 test_SetLocaleInfoA();
3167 test_EnumUILanguageA();
3169 test_GetStringTypeW();
3170 test_IdnToNameprepUnicode();
3172 test_IdnToUnicode();
3173 /* this requires collation table patch to make it MS compatible */
3174 if (0) test_sorting();