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 const WCHAR upper_case
[] = {'\t','J','U','S','T','!',' ','A',',',' ','T','E','S','T',';',' ','S','T','R','I','N','G',' ','1','/','*','+','-','.','\r','\n',0};
43 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};
44 static const WCHAR title_case
[] = {'\t','J','u','s','t','!',' ','A',',',' ','T','e','s','t',';',' ','S','t','r','i','n','g',' ','1','/','*','+','-','.','\r','\n',0};
45 static const WCHAR symbols_stripped
[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
46 static const WCHAR localeW
[] = {'e','n','-','U','S',0};
47 static const WCHAR fooW
[] = {'f','o','o',0};
48 static const WCHAR emptyW
[] = {0};
49 static const WCHAR invalidW
[] = {'i','n','v','a','l','i','d',0};
51 static inline unsigned int strlenW( const WCHAR
*str
)
58 static inline int strncmpW( const WCHAR
*str1
, const WCHAR
*str2
, int n
)
61 while ((--n
> 0) && *str1
&& (*str1
== *str2
)) { str1
++; str2
++; }
65 static inline WCHAR
*strchrW( const WCHAR
*str
, WCHAR ch
)
67 do { if (*str
== ch
) return (WCHAR
*)str
; } while (*str
++);
71 static inline BOOL
isdigitW( WCHAR wc
)
74 GetStringTypeW( CT_CTYPE1
, &wc
, 1, &type
);
75 return type
& C1_DIGIT
;
78 /* Some functions are only in later versions of kernel32.dll */
79 static WORD enumCount
;
81 static INT (WINAPI
*pGetTimeFormatEx
)(LPCWSTR
, DWORD
, const SYSTEMTIME
*, LPCWSTR
, LPWSTR
, INT
);
82 static INT (WINAPI
*pGetDateFormatEx
)(LPCWSTR
, DWORD
, const SYSTEMTIME
*, LPCWSTR
, LPWSTR
, INT
, LPCWSTR
);
83 static BOOL (WINAPI
*pEnumSystemLanguageGroupsA
)(LANGUAGEGROUP_ENUMPROCA
, DWORD
, LONG_PTR
);
84 static BOOL (WINAPI
*pEnumLanguageGroupLocalesA
)(LANGGROUPLOCALE_ENUMPROCA
, LGRPID
, DWORD
, LONG_PTR
);
85 static BOOL (WINAPI
*pEnumUILanguagesA
)(UILANGUAGE_ENUMPROCA
, DWORD
, LONG_PTR
);
86 static BOOL (WINAPI
*pEnumSystemLocalesEx
)(LOCALE_ENUMPROCEX
, DWORD
, LPARAM
, LPVOID
);
87 static INT (WINAPI
*pLCMapStringEx
)(LPCWSTR
, DWORD
, LPCWSTR
, INT
, LPWSTR
, INT
, LPNLSVERSIONINFO
, LPVOID
, LPARAM
);
88 static LCID (WINAPI
*pLocaleNameToLCID
)(LPCWSTR
, DWORD
);
89 static INT (WINAPI
*pLCIDToLocaleName
)(LCID
, LPWSTR
, INT
, DWORD
);
90 static INT (WINAPI
*pFoldStringA
)(DWORD
, LPCSTR
, INT
, LPSTR
, INT
);
91 static INT (WINAPI
*pFoldStringW
)(DWORD
, LPCWSTR
, INT
, LPWSTR
, INT
);
92 static BOOL (WINAPI
*pIsValidLanguageGroup
)(LGRPID
, DWORD
);
93 static INT (WINAPI
*pIdnToNameprepUnicode
)(DWORD
, LPCWSTR
, INT
, LPWSTR
, INT
);
94 static INT (WINAPI
*pIdnToAscii
)(DWORD
, LPCWSTR
, INT
, LPWSTR
, INT
);
95 static INT (WINAPI
*pIdnToUnicode
)(DWORD
, LPCWSTR
, INT
, LPWSTR
, INT
);
96 static INT (WINAPI
*pGetLocaleInfoEx
)(LPCWSTR
, LCTYPE
, LPWSTR
, INT
);
97 static BOOL (WINAPI
*pIsValidLocaleName
)(LPCWSTR
);
98 static INT (WINAPI
*pCompareStringOrdinal
)(const WCHAR
*, INT
, const WCHAR
*, INT
, BOOL
);
99 static INT (WINAPI
*pCompareStringEx
)(LPCWSTR
, DWORD
, LPCWSTR
, INT
, LPCWSTR
, INT
,
100 LPNLSVERSIONINFO
, LPVOID
, LPARAM
);
101 static INT (WINAPI
*pGetGeoInfoA
)(GEOID
, GEOTYPE
, LPSTR
, INT
, LANGID
);
102 static INT (WINAPI
*pGetGeoInfoW
)(GEOID
, GEOTYPE
, LPWSTR
, INT
, LANGID
);
103 static BOOL (WINAPI
*pEnumSystemGeoID
)(GEOCLASS
, GEOID
, GEO_ENUMPROC
);
104 static BOOL (WINAPI
*pGetSystemPreferredUILanguages
)(DWORD
, ULONG
*, WCHAR
*, ULONG
*);
105 static BOOL (WINAPI
*pGetThreadPreferredUILanguages
)(DWORD
, ULONG
*, WCHAR
*, ULONG
*);
106 static BOOL (WINAPI
*pGetUserPreferredUILanguages
)(DWORD
, ULONG
*, WCHAR
*, ULONG
*);
107 static WCHAR (WINAPI
*pRtlUpcaseUnicodeChar
)(WCHAR
);
108 static INT (WINAPI
*pGetNumberFormatEx
)(LPCWSTR
, DWORD
, LPCWSTR
, const NUMBERFMTW
*, LPWSTR
, int);
110 static void InitFunctionPointers(void)
112 HMODULE mod
= GetModuleHandleA("kernel32");
114 #define X(f) p##f = (void*)GetProcAddress(mod, #f)
117 X(EnumSystemLanguageGroupsA
);
118 X(EnumLanguageGroupLocalesA
);
124 X(IsValidLanguageGroup
);
126 X(EnumSystemLocalesEx
);
127 X(IdnToNameprepUnicode
);
131 X(IsValidLocaleName
);
132 X(CompareStringOrdinal
);
137 X(GetSystemPreferredUILanguages
);
138 X(GetThreadPreferredUILanguages
);
139 X(GetUserPreferredUILanguages
);
140 X(GetNumberFormatEx
);
142 mod
= GetModuleHandleA("ntdll");
143 X(RtlUpcaseUnicodeChar
);
147 #define eq(received, expected, label, type) \
148 ok((received) == (expected), "%s: got " type " instead of " type "\n", \
149 (label), (received), (expected))
151 #define BUFFER_SIZE 128
152 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
154 #define STRINGSA(x,y) strcpy(input, x); strcpy(Expected, y); SetLastError(0xdeadbeef); buffer[0] = '\0'
155 #define EXPECT_LENA ok(ret == lstrlenA(Expected)+1, "Expected len %d, got %d\n", lstrlenA(Expected)+1, ret)
156 #define EXPECT_EQA ok(strncmp(buffer, Expected, strlen(Expected)) == 0, \
157 "Expected '%s', got '%s'\n", Expected, buffer)
159 #define STRINGSW(x,y) MultiByteToWideChar(CP_ACP,0,x,-1,input,COUNTOF(input)); \
160 MultiByteToWideChar(CP_ACP,0,y,-1,Expected,COUNTOF(Expected)); \
161 SetLastError(0xdeadbeef); buffer[0] = '\0'
162 #define EXPECT_LENW ok(ret == lstrlenW(Expected)+1, "Expected Len %d, got %d\n", lstrlenW(Expected)+1, ret)
163 #define EXPECT_EQW ok(strncmpW(buffer, Expected, strlenW(Expected)) == 0, "Bad conversion\n")
165 #define NUO LOCALE_NOUSEROVERRIDE
167 static void test_GetLocaleInfoA(void)
171 LCID lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
172 char buffer
[BUFFER_SIZE
];
173 char expected
[BUFFER_SIZE
];
176 ok(lcid
== 0x409, "wrong LCID calculated - %d\n", lcid
);
178 ret
= GetLocaleInfoA(lcid
, LOCALE_ILANGUAGE
|LOCALE_RETURN_NUMBER
, (char*)&val
, sizeof(val
));
179 ok(ret
, "got %d\n", ret
);
180 ok(val
== lcid
, "got 0x%08x\n", val
);
182 /* en and ar use SUBLANG_NEUTRAL, but GetLocaleInfo assume SUBLANG_DEFAULT
183 Same is true for zh on pre-Vista, but on Vista and higher GetLocaleInfo
184 assumes SUBLANG_NEUTRAL for zh */
185 memset(expected
, 0, COUNTOF(expected
));
186 len
= GetLocaleInfoA(MAKELANGID(LANG_ENGLISH
, SUBLANG_DEFAULT
), LOCALE_SLANGUAGE
, expected
, COUNTOF(expected
));
187 SetLastError(0xdeadbeef);
188 memset(buffer
, 0, COUNTOF(buffer
));
189 ret
= GetLocaleInfoA(LANG_ENGLISH
, LOCALE_SLANGUAGE
, buffer
, COUNTOF(buffer
));
190 ok((ret
== len
) && !lstrcmpA(buffer
, expected
),
191 "got %d with '%s' (expected %d with '%s')\n",
192 ret
, buffer
, len
, expected
);
194 memset(expected
, 0, COUNTOF(expected
));
195 len
= GetLocaleInfoA(MAKELANGID(LANG_ARABIC
, SUBLANG_DEFAULT
), LOCALE_SLANGUAGE
, expected
, COUNTOF(expected
));
197 SetLastError(0xdeadbeef);
198 memset(buffer
, 0, COUNTOF(buffer
));
199 ret
= GetLocaleInfoA(LANG_ARABIC
, LOCALE_SLANGUAGE
, buffer
, COUNTOF(buffer
));
200 ok((ret
== len
) && !lstrcmpA(buffer
, expected
),
201 "got %d with '%s' (expected %d with '%s')\n",
202 ret
, buffer
, len
, expected
);
205 win_skip("LANG_ARABIC not installed\n");
207 /* SUBLANG_DEFAULT is required for mlang.dll, but optional for GetLocaleInfo */
208 memset(expected
, 0, COUNTOF(expected
));
209 len
= GetLocaleInfoA(MAKELANGID(LANG_GERMAN
, SUBLANG_DEFAULT
), LOCALE_SLANGUAGE
, expected
, COUNTOF(expected
));
210 SetLastError(0xdeadbeef);
211 memset(buffer
, 0, COUNTOF(buffer
));
212 ret
= GetLocaleInfoA(LANG_GERMAN
, LOCALE_SLANGUAGE
, buffer
, COUNTOF(buffer
));
213 ok((ret
== len
) && !lstrcmpA(buffer
, expected
),
214 "got %d with '%s' (expected %d with '%s')\n",
215 ret
, buffer
, len
, expected
);
218 /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
219 * partially fill the buffer even if it is too short. See bug 637.
221 SetLastError(0xdeadbeef);
222 memset(buffer
, 0, COUNTOF(buffer
));
223 ret
= GetLocaleInfoA(lcid
, NUO
|LOCALE_SDAYNAME1
, buffer
, 0);
224 ok(ret
== 7 && !buffer
[0], "Expected len=7, got %d\n", ret
);
226 SetLastError(0xdeadbeef);
227 memset(buffer
, 0, COUNTOF(buffer
));
228 ret
= GetLocaleInfoA(lcid
, NUO
|LOCALE_SDAYNAME1
, buffer
, 3);
229 ok( !ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
230 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
231 ok(!strcmp(buffer
, "Mon"), "Expected 'Mon', got '%s'\n", buffer
);
233 SetLastError(0xdeadbeef);
234 memset(buffer
, 0, COUNTOF(buffer
));
235 ret
= GetLocaleInfoA(lcid
, NUO
|LOCALE_SDAYNAME1
, buffer
, 10);
236 ok(ret
== 7, "Expected ret == 7, got %d, error %d\n", ret
, GetLastError());
237 ok(!strcmp(buffer
, "Monday"), "Expected 'Monday', got '%s'\n", buffer
);
240 struct neutralsublang_name2_t
{
245 WCHAR sname_broken
[15];
249 static const struct neutralsublang_name2_t neutralsublang_names2
[] = {
250 { {'a','r',0}, {'a','r','-','S','A',0},
251 MAKELCID(MAKELANGID(LANG_ARABIC
, SUBLANG_ARABIC_SAUDI_ARABIA
), SORT_DEFAULT
) },
252 { {'a','z',0}, {'a','z','-','L','a','t','n','-','A','Z',0},
253 MAKELCID(MAKELANGID(LANG_AZERI
, SUBLANG_AZERI_LATIN
), SORT_DEFAULT
) },
254 { {'d','e',0}, {'d','e','-','D','E',0},
255 MAKELCID(MAKELANGID(LANG_GERMAN
, SUBLANG_GERMAN
), SORT_DEFAULT
) },
256 { {'e','n',0}, {'e','n','-','U','S',0},
257 MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
) },
258 { {'e','s',0}, {'e','s','-','E','S',0},
259 MAKELCID(MAKELANGID(LANG_SPANISH
, SUBLANG_SPANISH_MODERN
), SORT_DEFAULT
),
260 MAKELCID(MAKELANGID(LANG_SPANISH
, SUBLANG_SPANISH
), SORT_DEFAULT
) /* vista */,
261 {'e','s','-','E','S','_','t','r','a','d','n','l',0} },
262 { {'g','a',0}, {'g','a','-','I','E',0},
263 MAKELCID(MAKELANGID(LANG_IRISH
, SUBLANG_IRISH_IRELAND
), SORT_DEFAULT
), 0, {0}, 0x3 },
264 { {'i','t',0}, {'i','t','-','I','T',0},
265 MAKELCID(MAKELANGID(LANG_ITALIAN
, SUBLANG_ITALIAN
), SORT_DEFAULT
) },
266 { {'m','s',0}, {'m','s','-','M','Y',0},
267 MAKELCID(MAKELANGID(LANG_MALAY
, SUBLANG_MALAY_MALAYSIA
), SORT_DEFAULT
) },
268 { {'n','l',0}, {'n','l','-','N','L',0},
269 MAKELCID(MAKELANGID(LANG_DUTCH
, SUBLANG_DUTCH
), SORT_DEFAULT
) },
270 { {'p','t',0}, {'p','t','-','B','R',0},
271 MAKELCID(MAKELANGID(LANG_PORTUGUESE
, SUBLANG_PORTUGUESE_BRAZILIAN
), SORT_DEFAULT
) },
272 { {'s','r',0}, {'h','r','-','H','R',0},
273 MAKELCID(MAKELANGID(LANG_SERBIAN
, SUBLANG_SERBIAN_CROATIA
), SORT_DEFAULT
) },
274 { {'s','v',0}, {'s','v','-','S','E',0},
275 MAKELCID(MAKELANGID(LANG_SWEDISH
, SUBLANG_SWEDISH
), SORT_DEFAULT
) },
276 { {'u','z',0}, {'u','z','-','L','a','t','n','-','U','Z',0},
277 MAKELCID(MAKELANGID(LANG_UZBEK
, SUBLANG_UZBEK_LATIN
), SORT_DEFAULT
) },
278 { {'z','h',0}, {'z','h','-','C','N',0},
279 MAKELCID(MAKELANGID(LANG_CHINESE
, SUBLANG_CHINESE_SIMPLIFIED
), SORT_DEFAULT
) },
283 static void test_GetLocaleInfoW(void)
285 LCID lcid_en
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
286 LCID lcid_ru
= MAKELCID(MAKELANGID(LANG_RUSSIAN
, SUBLANG_NEUTRAL
), SORT_DEFAULT
);
287 LCID lcid_en_neut
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_NEUTRAL
), SORT_DEFAULT
);
288 WCHAR bufferW
[80], buffer2W
[80];
294 ret
= GetLocaleInfoW(lcid_en
, LOCALE_SMONTHNAME1
, bufferW
, COUNTOF(bufferW
));
296 win_skip("GetLocaleInfoW() isn't implemented\n");
300 ret
= GetLocaleInfoW(lcid_en
, LOCALE_ILANGUAGE
|LOCALE_RETURN_NUMBER
, (WCHAR
*)&val
, sizeof(val
)/sizeof(WCHAR
));
301 ok(ret
, "got %d\n", ret
);
302 ok(val
== lcid_en
, "got 0x%08x\n", val
);
304 ret
= GetLocaleInfoW(lcid_en_neut
, LOCALE_SNAME
, bufferW
, COUNTOF(bufferW
));
307 static const WCHAR slangW
[] = {'E','n','g','l','i','s','h',' ','(','U','n','i','t','e','d',' ',
308 'S','t','a','t','e','s',')',0};
309 static const WCHAR statesW
[] = {'U','n','i','t','e','d',' ','S','t','a','t','e','s',0};
310 static const WCHAR enW
[] = {'e','n','-','U','S',0};
311 const struct neutralsublang_name2_t
*ptr
= neutralsublang_names2
;
313 ok(!lstrcmpW(bufferW
, enW
), "got wrong name %s\n", wine_dbgstr_w(bufferW
));
315 ret
= GetLocaleInfoW(lcid_en_neut
, LOCALE_SCOUNTRY
, bufferW
, COUNTOF(bufferW
));
316 ok(ret
, "got %d\n", ret
);
317 if ((PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID())) != LANG_ENGLISH
) ||
318 (PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale())) != LANG_ENGLISH
))
320 skip("Non-English locale\n");
323 ok(!lstrcmpW(statesW
, bufferW
), "got wrong name %s\n", wine_dbgstr_w(bufferW
));
325 ret
= GetLocaleInfoW(lcid_en_neut
, LOCALE_SLANGUAGE
, bufferW
, COUNTOF(bufferW
));
326 ok(ret
, "got %d\n", ret
);
327 if ((PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID())) != LANG_ENGLISH
) ||
328 (PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale())) != LANG_ENGLISH
))
330 skip("Non-English locale\n");
333 ok(!lstrcmpW(slangW
, bufferW
), "got wrong name %s\n", wine_dbgstr_w(bufferW
));
340 /* make neutral lcid */
341 langid
= MAKELANGID(PRIMARYLANGID(LANGIDFROMLCID(ptr
->lcid
)), SUBLANG_NEUTRAL
);
342 lcid
= MAKELCID(langid
, SORT_DEFAULT
);
345 GetLocaleInfoW(lcid
, LOCALE_ILANGUAGE
|LOCALE_RETURN_NUMBER
, (WCHAR
*)&val
, sizeof(val
)/sizeof(WCHAR
));
346 todo_wine_if (ptr
->todo
& 0x1)
347 ok(val
== ptr
->lcid
|| (val
&& broken(val
== ptr
->lcid_broken
)), "%s: got wrong lcid 0x%04x, expected 0x%04x\n",
348 wine_dbgstr_w(ptr
->name
), val
, ptr
->lcid
);
350 /* now check LOCALE_SNAME */
351 GetLocaleInfoW(lcid
, LOCALE_SNAME
, bufferW
, COUNTOF(bufferW
));
352 todo_wine_if (ptr
->todo
& 0x2)
353 ok(!lstrcmpW(bufferW
, ptr
->sname
) ||
354 (*ptr
->sname_broken
&& broken(!lstrcmpW(bufferW
, ptr
->sname_broken
))),
355 "%s: got %s\n", wine_dbgstr_w(ptr
->name
), wine_dbgstr_w(bufferW
));
360 win_skip("English neutral locale not supported\n");
362 ret
= GetLocaleInfoW(lcid_ru
, LOCALE_SMONTHNAME1
, bufferW
, COUNTOF(bufferW
));
364 win_skip("LANG_RUSSIAN locale data unavailable\n");
367 ret
= GetLocaleInfoW(lcid_ru
, LOCALE_SMONTHNAME1
|LOCALE_RETURN_GENITIVE_NAMES
,
368 bufferW
, COUNTOF(bufferW
));
370 win_skip("LOCALE_RETURN_GENITIVE_NAMES isn't supported\n");
374 /* LOCALE_RETURN_GENITIVE_NAMES isn't supported for GetLocaleInfoA */
376 SetLastError(0xdeadbeef);
377 ret
= GetLocaleInfoA(lcid_ru
, LOCALE_SMONTHNAME1
|LOCALE_RETURN_GENITIVE_NAMES
,
378 bufferA
, COUNTOF(bufferA
));
379 ok(ret
== 0, "LOCALE_RETURN_GENITIVE_NAMES should fail with GetLocaleInfoA\n");
380 ok(bufferA
[0] == 'a', "Expected buffer to be untouched\n");
381 ok(GetLastError() == ERROR_INVALID_FLAGS
,
382 "Expected ERROR_INVALID_FLAGS, got %x\n", GetLastError());
385 SetLastError(0xdeadbeef);
386 ret
= GetLocaleInfoW(lcid_ru
, LOCALE_RETURN_GENITIVE_NAMES
,
387 bufferW
, COUNTOF(bufferW
));
389 "LOCALE_RETURN_GENITIVE_NAMES itself doesn't return anything, got %d\n", ret
);
390 ok(bufferW
[0] == 'a', "Expected buffer to be untouched\n");
391 ok(GetLastError() == ERROR_INVALID_FLAGS
,
392 "Expected ERROR_INVALID_FLAGS, got %x\n", GetLastError());
394 /* yes, test empty 13 month entry too */
395 for (i
= 0; i
< 12; i
++) {
397 ret
= GetLocaleInfoW(lcid_ru
, (LOCALE_SMONTHNAME1
+i
)|LOCALE_RETURN_GENITIVE_NAMES
,
398 bufferW
, COUNTOF(bufferW
));
399 ok(ret
, "Expected non zero result\n");
400 ok(ret
== lstrlenW(bufferW
)+1, "Expected actual length, got %d, length %d\n",
401 ret
, lstrlenW(bufferW
));
403 ret
= GetLocaleInfoW(lcid_ru
, LOCALE_SMONTHNAME1
+i
,
404 buffer2W
, COUNTOF(buffer2W
));
405 ok(ret
, "Expected non zero result\n");
406 ok(ret
== lstrlenW(buffer2W
)+1, "Expected actual length, got %d, length %d\n",
407 ret
, lstrlenW(buffer2W
));
409 ok(lstrcmpW(bufferW
, buffer2W
) != 0,
410 "Expected genitive name to differ, got the same for month %d\n", i
+1);
412 /* for locale without genitive names nominative returned in both cases */
414 ret
= GetLocaleInfoW(lcid_en
, (LOCALE_SMONTHNAME1
+i
)|LOCALE_RETURN_GENITIVE_NAMES
,
415 bufferW
, COUNTOF(bufferW
));
416 ok(ret
, "Expected non zero result\n");
417 ok(ret
== lstrlenW(bufferW
)+1, "Expected actual length, got %d, length %d\n",
418 ret
, lstrlenW(bufferW
));
420 ret
= GetLocaleInfoW(lcid_en
, LOCALE_SMONTHNAME1
+i
,
421 buffer2W
, COUNTOF(buffer2W
));
422 ok(ret
, "Expected non zero result\n");
423 ok(ret
== lstrlenW(buffer2W
)+1, "Expected actual length, got %d, length %d\n",
424 ret
, lstrlenW(buffer2W
));
426 ok(lstrcmpW(bufferW
, buffer2W
) == 0,
427 "Expected same names, got different for month %d\n", i
+1);
431 static void test_GetTimeFormatA(void)
435 LCID lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
436 char buffer
[BUFFER_SIZE
], input
[BUFFER_SIZE
], Expected
[BUFFER_SIZE
];
438 memset(&curtime
, 2, sizeof(SYSTEMTIME
));
439 STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
440 SetLastError(0xdeadbeef);
441 ret
= GetTimeFormatA(lcid
, TIME_FORCE24HOURFORMAT
, &curtime
, input
, buffer
, COUNTOF(buffer
));
442 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
443 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
446 curtime
.wMinute
= 56;
447 curtime
.wSecond
= 13;
448 curtime
.wMilliseconds
= 22;
449 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
450 SetLastError(0xdeadbeef);
451 ret
= GetTimeFormatA(lcid
, TIME_FORCE24HOURFORMAT
, &curtime
, input
, buffer
, COUNTOF(buffer
));
452 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
453 EXPECT_LENA
; EXPECT_EQA
;
455 /* MSDN: LOCALE_NOUSEROVERRIDE can't be specified with a format string */
456 SetLastError(0xdeadbeef);
457 ret
= GetTimeFormatA(lcid
, NUO
|TIME_FORCE24HOURFORMAT
, &curtime
, input
, buffer
, COUNTOF(buffer
));
458 ok(!ret
&& GetLastError() == ERROR_INVALID_FLAGS
,
459 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
461 STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficient buffer */
462 SetLastError(0xdeadbeef);
463 ret
= GetTimeFormatA(lcid
, TIME_FORCE24HOURFORMAT
, &curtime
, input
, buffer
, 2);
464 ok( !ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
465 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
467 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
468 ret
= GetTimeFormatA(lcid
, TIME_FORCE24HOURFORMAT
, &curtime
, input
, NULL
, 0);
469 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
472 STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
473 ret
= GetTimeFormatA(lcid
, NUO
|TIME_NOMINUTESORSECONDS
, &curtime
, NULL
, buffer
, COUNTOF(buffer
));
474 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
475 EXPECT_LENA
; EXPECT_EQA
;
477 STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
478 ret
= GetTimeFormatA(lcid
, TIME_NOMINUTESORSECONDS
, &curtime
, input
, buffer
, COUNTOF(buffer
));
479 ok(ret
== strlen(buffer
)+1, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
480 ok( !strcmp( buffer
, "" ) || broken( !strcmp( buffer
, "4" )), /* win9x */
481 "Expected '', got '%s'\n", buffer
);
483 STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
484 ret
= GetTimeFormatA(lcid
, NUO
|TIME_NOSECONDS
, &curtime
, NULL
, buffer
, COUNTOF(buffer
));
485 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
486 EXPECT_LENA
; EXPECT_EQA
;
488 STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
489 strcpy(Expected
, "8:56 AM");
490 ret
= GetTimeFormatA(lcid
, TIME_NOSECONDS
, &curtime
, input
, buffer
, COUNTOF(buffer
));
491 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
492 EXPECT_LENA
; EXPECT_EQA
;
494 STRINGSA("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
495 ret
= GetTimeFormatA(lcid
, TIME_NOSECONDS
, &curtime
, input
, buffer
, COUNTOF(buffer
));
496 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
497 ok( !strcmp( buffer
, "8.@:56AM" ) || broken( !strcmp( buffer
, "8.@:56.@:AM" )) /* win9x */,
498 "Expected '8.@:56AM', got '%s'\n", buffer
);
500 STRINGSA("s1s2s3", ""); /* Duplicate tokens */
501 ret
= GetTimeFormatA(lcid
, TIME_NOSECONDS
, &curtime
, input
, buffer
, COUNTOF(buffer
));
502 ok(ret
== strlen(buffer
)+1, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
503 ok( !strcmp( buffer
, "" ) || broken( !strcmp( buffer
, "3" )), /* win9x */
504 "Expected '', got '%s'\n", buffer
);
506 STRINGSA("t/tt", "A/AM"); /* AM time marker */
507 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
508 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
509 EXPECT_LENA
; EXPECT_EQA
;
512 STRINGSA("t/tt", "P/PM"); /* PM time marker */
513 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
514 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
515 EXPECT_LENA
; EXPECT_EQA
;
517 STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
518 ret
= GetTimeFormatA(lcid
, TIME_NOTIMEMARKER
, &curtime
, input
, buffer
, COUNTOF(buffer
));
519 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
520 EXPECT_LENA
; EXPECT_EQA
;
522 STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
523 ret
= GetTimeFormatA(lcid
, TIME_FORCE24HOURFORMAT
, &curtime
, input
, buffer
, COUNTOF(buffer
));
524 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
525 EXPECT_LENA
; EXPECT_EQA
;
527 STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
528 ret
= GetTimeFormatA(lcid
, TIME_FORCE24HOURFORMAT
, &curtime
, input
, buffer
, COUNTOF(buffer
));
529 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
530 EXPECT_LENA
; EXPECT_EQA
;
532 curtime
.wHour
= 14; /* change this to 14 or 2pm */
535 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 */
536 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
537 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
538 EXPECT_LENA
; EXPECT_EQA
;
541 STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
542 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
543 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
544 EXPECT_LENA
; EXPECT_EQA
;
546 STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
547 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
548 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
549 EXPECT_LENA
; EXPECT_EQA
;
551 /* try to convert formatting strings with more than two letters
552 * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
553 * NOTE: We expect any letter for which there is an upper case value
554 * we should see a replacement. For letters that DO NOT have
555 * upper case values we should see NO REPLACEMENT.
558 curtime
.wMinute
= 56;
559 curtime
.wSecond
= 13;
560 curtime
.wMilliseconds
= 22;
561 STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
562 "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
563 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
564 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
565 EXPECT_LENA
; EXPECT_EQA
;
567 STRINGSA("h", "text"); /* Don't write to buffer if len is 0 */
568 strcpy(buffer
, "text");
569 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, 0);
570 ok(ret
== 2, "Expected ret == 2, got %d, error %d\n", ret
, GetLastError());
573 STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
574 "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
575 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
576 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
577 EXPECT_LENA
; EXPECT_EQA
;
579 STRINGSA("'''", "'"); /* invalid quoted string */
580 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
581 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
582 EXPECT_LENA
; EXPECT_EQA
;
584 /* test that msdn suggested single quotation usage works as expected */
585 STRINGSA("''''", "'"); /* single quote mark */
586 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
587 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
588 EXPECT_LENA
; EXPECT_EQA
;
590 STRINGSA("''HHHHHH", "08"); /* Normal use */
591 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
592 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
593 EXPECT_LENA
; EXPECT_EQA
;
595 /* and test for normal use of the single quotation mark */
596 STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
597 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
598 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
599 EXPECT_LENA
; EXPECT_EQA
;
601 STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
602 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
603 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
604 EXPECT_LENA
; EXPECT_EQA
;
606 STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
607 ret
= GetTimeFormatA(lcid
, TIME_NOTIMEMARKER
, &curtime
, input
, buffer
, COUNTOF(buffer
));
608 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
609 EXPECT_LENA
; EXPECT_EQA
;
612 STRINGSA("'123'tt", ""); /* Invalid time */
613 SetLastError(0xdeadbeef);
614 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
615 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
616 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
619 curtime
.wMonth
= 60; /* Invalid */
620 STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
621 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
622 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
623 EXPECT_LENA
; EXPECT_EQA
;
626 static void test_GetTimeFormatEx(void)
630 WCHAR buffer
[BUFFER_SIZE
], input
[BUFFER_SIZE
], Expected
[BUFFER_SIZE
];
632 if (!pGetTimeFormatEx
)
634 win_skip("GetTimeFormatEx not supported\n");
638 memset(&curtime
, 2, sizeof(SYSTEMTIME
));
639 STRINGSW("tt HH':'mm'@'ss", ""); /* Invalid time */
640 SetLastError(0xdeadbeef);
641 ret
= pGetTimeFormatEx(localeW
, TIME_FORCE24HOURFORMAT
, &curtime
, input
, buffer
, COUNTOF(buffer
));
642 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
643 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
646 curtime
.wMinute
= 56;
647 curtime
.wSecond
= 13;
648 curtime
.wMilliseconds
= 22;
649 STRINGSW("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
650 SetLastError(0xdeadbeef);
651 ret
= pGetTimeFormatEx(localeW
, TIME_FORCE24HOURFORMAT
, &curtime
, input
, buffer
, COUNTOF(buffer
));
652 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
653 EXPECT_LENW
; EXPECT_EQW
;
655 /* MSDN: LOCALE_NOUSEROVERRIDE can't be specified with a format string */
656 SetLastError(0xdeadbeef);
657 ret
= pGetTimeFormatEx(localeW
, NUO
|TIME_FORCE24HOURFORMAT
, &curtime
, input
, buffer
, COUNTOF(buffer
));
658 ok(!ret
&& GetLastError() == ERROR_INVALID_FLAGS
,
659 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
661 STRINGSW("tt HH':'mm'@'ss", "A"); /* Insufficient buffer */
662 SetLastError(0xdeadbeef);
663 ret
= pGetTimeFormatEx(localeW
, TIME_FORCE24HOURFORMAT
, &curtime
, input
, buffer
, 2);
664 ok( !ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
665 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
667 STRINGSW("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
668 ret
= pGetTimeFormatEx(localeW
, TIME_FORCE24HOURFORMAT
, &curtime
, input
, NULL
, 0);
669 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
672 STRINGSW("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
673 ret
= pGetTimeFormatEx(localeW
, NUO
|TIME_NOMINUTESORSECONDS
, &curtime
, NULL
, buffer
, COUNTOF(buffer
));
674 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
675 EXPECT_LENW
; EXPECT_EQW
;
677 STRINGSW("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
678 ret
= pGetTimeFormatEx(localeW
, TIME_NOMINUTESORSECONDS
, &curtime
, input
, buffer
, COUNTOF(buffer
));
679 ok(ret
== strlenW(buffer
)+1, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
680 EXPECT_LENW
; EXPECT_EQW
;
682 STRINGSW("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
683 ret
= pGetTimeFormatEx(localeW
, NUO
|TIME_NOSECONDS
, &curtime
, NULL
, buffer
, COUNTOF(buffer
));
684 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
685 EXPECT_LENW
; EXPECT_EQW
;
687 STRINGSW("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
688 ret
= pGetTimeFormatEx(localeW
, TIME_NOSECONDS
, &curtime
, input
, buffer
, COUNTOF(buffer
));
689 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
690 EXPECT_LENW
; EXPECT_EQW
;
692 STRINGSW("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
693 ret
= pGetTimeFormatEx(localeW
, TIME_NOSECONDS
, &curtime
, input
, buffer
, COUNTOF(buffer
));
694 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
695 EXPECT_LENW
; EXPECT_EQW
;
697 STRINGSW("s1s2s3", ""); /* Duplicate tokens */
698 ret
= pGetTimeFormatEx(localeW
, TIME_NOSECONDS
, &curtime
, input
, buffer
, COUNTOF(buffer
));
699 ok(ret
== strlenW(buffer
)+1, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
700 EXPECT_LENW
; EXPECT_EQW
;
702 STRINGSW("t/tt", "A/AM"); /* AM time marker */
703 ret
= pGetTimeFormatEx(localeW
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
704 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
705 EXPECT_LENW
; EXPECT_EQW
;
708 STRINGSW("t/tt", "P/PM"); /* PM time marker */
709 ret
= pGetTimeFormatEx(localeW
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
710 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
711 EXPECT_LENW
; EXPECT_EQW
;
713 STRINGSW("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
714 ret
= pGetTimeFormatEx(localeW
, TIME_NOTIMEMARKER
, &curtime
, input
, buffer
, COUNTOF(buffer
));
715 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
716 EXPECT_LENW
; EXPECT_EQW
;
718 STRINGSW("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
719 ret
= pGetTimeFormatEx(localeW
, TIME_FORCE24HOURFORMAT
, &curtime
, input
, buffer
, COUNTOF(buffer
));
720 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
721 EXPECT_LENW
; EXPECT_EQW
;
723 STRINGSW("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
724 ret
= pGetTimeFormatEx(localeW
, TIME_FORCE24HOURFORMAT
, &curtime
, input
, buffer
, COUNTOF(buffer
));
725 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
726 EXPECT_LENW
; EXPECT_EQW
;
728 curtime
.wHour
= 14; /* change this to 14 or 2pm */
731 STRINGSW("h hh H HH m mm s ss t tt", "2 02 14 14 5 05 3 03 P PM"); /* 24 hrs, leading 0 */
732 ret
= pGetTimeFormatEx(localeW
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
733 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
734 EXPECT_LENW
; EXPECT_EQW
;
737 STRINGSW("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
738 ret
= pGetTimeFormatEx(localeW
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
739 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
740 EXPECT_LENW
; EXPECT_EQW
;
742 STRINGSW("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
743 ret
= pGetTimeFormatEx(localeW
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
744 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
745 EXPECT_LENW
; EXPECT_EQW
;
747 /* try to convert formatting strings with more than two letters
748 * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
749 * NOTE: We expect any letter for which there is an upper case value
750 * we should see a replacement. For letters that DO NOT have
751 * upper case values we should see NO REPLACEMENT.
754 curtime
.wMinute
= 56;
755 curtime
.wSecond
= 13;
756 curtime
.wMilliseconds
= 22;
757 STRINGSW("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
758 "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
759 ret
= pGetTimeFormatEx(localeW
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
760 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
761 EXPECT_LENW
; EXPECT_EQW
;
763 STRINGSW("h", "text"); /* Don't write to buffer if len is 0 */
764 lstrcpyW(buffer
, Expected
);
765 ret
= pGetTimeFormatEx(localeW
, 0, &curtime
, input
, buffer
, 0);
766 ok(ret
== 2, "Expected ret == 2, got %d, error %d\n", ret
, GetLastError());
769 STRINGSW("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
770 "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
771 ret
= pGetTimeFormatEx(localeW
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
772 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
773 EXPECT_LENW
; EXPECT_EQW
;
775 STRINGSW("'''", "'"); /* invalid quoted string */
776 ret
= pGetTimeFormatEx(localeW
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
777 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
778 EXPECT_LENW
; EXPECT_EQW
;
780 /* test that msdn suggested single quotation usage works as expected */
781 STRINGSW("''''", "'"); /* single quote mark */
782 ret
= pGetTimeFormatEx(localeW
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
783 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
784 EXPECT_LENW
; EXPECT_EQW
;
786 STRINGSW("''HHHHHH", "08"); /* Normal use */
787 ret
= pGetTimeFormatEx(localeW
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
788 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
789 EXPECT_LENW
; EXPECT_EQW
;
791 /* and test for normal use of the single quotation mark */
792 STRINGSW("'''HHHHHH'", "'HHHHHH"); /* Normal use */
793 ret
= pGetTimeFormatEx(localeW
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
794 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
795 EXPECT_LENW
; EXPECT_EQW
;
797 STRINGSW("'''HHHHHH", "'HHHHHH"); /* Odd use */
798 ret
= pGetTimeFormatEx(localeW
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
799 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
800 EXPECT_LENW
; EXPECT_EQW
;
802 STRINGSW("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
803 ret
= pGetTimeFormatEx(localeW
, TIME_NOTIMEMARKER
, &curtime
, input
, buffer
, COUNTOF(buffer
));
804 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
805 EXPECT_LENW
; EXPECT_EQW
;
808 STRINGSW("'123'tt", ""); /* Invalid time */
809 SetLastError(0xdeadbeef);
810 ret
= pGetTimeFormatEx(localeW
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
811 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
812 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
815 curtime
.wMonth
= 60; /* Invalid */
816 STRINGSW("h:m:s", "12:56:13"); /* Invalid date */
817 ret
= pGetTimeFormatEx(localeW
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
818 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
819 EXPECT_LENW
; EXPECT_EQW
;
822 static void test_GetDateFormatA(void)
826 LCID lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
827 LCID lcid_ru
= MAKELCID(MAKELANGID(LANG_RUSSIAN
, SUBLANG_NEUTRAL
), SORT_DEFAULT
);
828 char buffer
[BUFFER_SIZE
], input
[BUFFER_SIZE
], Expected
[BUFFER_SIZE
];
829 char Broken
[BUFFER_SIZE
];
830 char short_day
[10], month
[10], genitive_month
[10];
832 memset(&curtime
, 2, sizeof(SYSTEMTIME
)); /* Invalid time */
833 STRINGSA("ddd',' MMM dd yy","");
834 SetLastError(0xdeadbeef);
835 ret
= GetDateFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
836 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
837 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
839 curtime
.wYear
= 2002;
842 curtime
.wDayOfWeek
= 3;
843 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
844 ret
= GetDateFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
845 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
846 EXPECT_LENA
; EXPECT_EQA
;
848 /* Same as above but with LOCALE_NOUSEROVERRIDE */
849 STRINGSA("ddd',' MMM dd yy",""); /* Simple case */
850 SetLastError(0xdeadbeef);
851 ret
= GetDateFormatA(lcid
, NUO
, &curtime
, input
, buffer
, COUNTOF(buffer
));
852 ok(!ret
&& GetLastError() == ERROR_INVALID_FLAGS
,
853 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
856 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
857 ret
= GetDateFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
858 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
859 EXPECT_LENA
; EXPECT_EQA
;
861 curtime
.wHour
= 36; /* Invalid */
862 STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
863 ret
= GetDateFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
864 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
865 EXPECT_LENA
; EXPECT_EQA
;
867 STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
868 ret
= GetDateFormatA(lcid
, 0, &curtime
, input
, NULL
, 0);
869 ok(ret
== 16, "Expected ret == 16, got %d, error %d\n", ret
, GetLastError());
872 STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
873 SetLastError(0xdeadbeef);
874 ret
= GetDateFormatA(lcid
, 0, &curtime
, input
, buffer
, 2);
875 ok( !ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
876 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
878 STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
879 ret
= GetDateFormatA(lcid
, NUO
, &curtime
, NULL
, buffer
, COUNTOF(buffer
));
880 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
881 if (strncmp(buffer
, Expected
, strlen(Expected
)) && strncmp(buffer
, "5/4/02", strlen(Expected
)) != 0)
882 ok (0, "Expected '%s' or '5/4/02', got '%s'\n", Expected
, buffer
);
884 SetLastError(0xdeadbeef); buffer
[0] = '\0'; /* DATE_LONGDATE */
885 ret
= GetDateFormatA(lcid
, NUO
|DATE_LONGDATE
, &curtime
, NULL
, buffer
, COUNTOF(buffer
));
886 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
887 ok(strcmp(buffer
, "Saturday, May 04, 2002") == 0 ||
888 strcmp(buffer
, "Saturday, May 4, 2002") == 0 /* Win 8 */,
889 "got an unexpected date string '%s'\n", buffer
);
891 /* test for expected DATE_YEARMONTH behavior with null format */
892 /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
893 STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
894 SetLastError(0xdeadbeef);
895 ret
= GetDateFormatA(lcid
, NUO
|DATE_YEARMONTH
, &curtime
, input
, buffer
, COUNTOF(buffer
));
896 ok(!ret
&& GetLastError() == ERROR_INVALID_FLAGS
,
897 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
900 /* Test that using invalid DATE_* flags results in the correct error */
901 /* and return values */
902 STRINGSA("m/d/y", ""); /* Invalid flags */
903 SetLastError(0xdeadbeef);
904 ret
= GetDateFormatA(lcid
, DATE_YEARMONTH
|DATE_SHORTDATE
|DATE_LONGDATE
,
905 &curtime
, input
, buffer
, COUNTOF(buffer
));
906 ok(!ret
&& GetLastError() == ERROR_INVALID_FLAGS
,
907 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
909 ret
= GetDateFormatA(lcid_ru
, 0, &curtime
, "ddMMMM", buffer
, COUNTOF(buffer
));
912 win_skip("LANG_RUSSIAN locale data unavailable\n");
916 /* month part should be in genitive form */
917 strcpy(genitive_month
, buffer
+ 2);
918 ret
= GetDateFormatA(lcid_ru
, 0, &curtime
, "MMMM", buffer
, COUNTOF(buffer
));
919 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
920 strcpy(month
, buffer
);
921 ok(strcmp(genitive_month
, month
) != 0, "Expected different month forms\n");
923 ret
= GetDateFormatA(lcid_ru
, 0, &curtime
, "ddd", buffer
, COUNTOF(buffer
));
924 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
925 strcpy(short_day
, buffer
);
927 STRINGSA("dd MMMMddd dd", "");
928 sprintf(Expected
, "04 %s%s 04", genitive_month
, short_day
);
929 ret
= GetDateFormatA(lcid_ru
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
930 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
933 STRINGSA("MMMMddd dd", "");
934 sprintf(Expected
, "%s%s 04", month
, short_day
);
935 ret
= GetDateFormatA(lcid_ru
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
936 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
939 STRINGSA("MMMMddd", "");
940 sprintf(Expected
, "%s%s", month
, short_day
);
941 ret
= GetDateFormatA(lcid_ru
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
942 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
945 STRINGSA("MMMMdd", "");
946 sprintf(Expected
, "%s04", genitive_month
);
947 sprintf(Broken
, "%s04", month
);
948 ret
= GetDateFormatA(lcid_ru
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
949 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
950 ok(strncmp(buffer
, Expected
, strlen(Expected
)) == 0 ||
951 broken(strncmp(buffer
, Broken
, strlen(Broken
)) == 0) /* nt4 */,
952 "Expected '%s', got '%s'\n", Expected
, buffer
);
954 STRINGSA("MMMMdd ddd", "");
955 sprintf(Expected
, "%s04 %s", genitive_month
, short_day
);
956 sprintf(Broken
, "%s04 %s", month
, short_day
);
957 ret
= GetDateFormatA(lcid_ru
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
958 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
959 ok(strncmp(buffer
, Expected
, strlen(Expected
)) == 0 ||
960 broken(strncmp(buffer
, Broken
, strlen(Broken
)) == 0) /* nt4 */,
961 "Expected '%s', got '%s'\n", Expected
, buffer
);
963 STRINGSA("dd dddMMMM", "");
964 sprintf(Expected
, "04 %s%s", short_day
, month
);
965 ret
= GetDateFormatA(lcid_ru
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
966 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
969 STRINGSA("dd dddMMMM ddd MMMMdd", "");
970 sprintf(Expected
, "04 %s%s %s %s04", short_day
, month
, short_day
, genitive_month
);
971 sprintf(Broken
, "04 %s%s %s %s04", short_day
, month
, short_day
, month
);
972 ret
= GetDateFormatA(lcid_ru
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
973 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
974 ok(strncmp(buffer
, Expected
, strlen(Expected
)) == 0 ||
975 broken(strncmp(buffer
, Broken
, strlen(Broken
)) == 0) /* nt4 */,
976 "Expected '%s', got '%s'\n", Expected
, buffer
);
978 /* with literal part */
979 STRINGSA("ddd',' MMMM dd", "");
980 sprintf(Expected
, "%s, %s 04", short_day
, genitive_month
);
981 sprintf(Broken
, "%s, %s 04", short_day
, month
);
982 ret
= GetDateFormatA(lcid_ru
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
983 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
984 ok(strncmp(buffer
, Expected
, strlen(Expected
)) == 0 ||
985 broken(strncmp(buffer
, Broken
, strlen(Broken
)) == 0) /* nt4 */,
986 "Expected '%s', got '%s'\n", Expected
, buffer
);
989 static void test_GetDateFormatEx(void)
993 WCHAR buffer
[BUFFER_SIZE
], input
[BUFFER_SIZE
], Expected
[BUFFER_SIZE
];
995 if (!pGetDateFormatEx
)
997 win_skip("GetDateFormatEx not supported\n");
1001 STRINGSW("",""); /* If flags are set, then format must be NULL */
1002 SetLastError(0xdeadbeef);
1003 ret
= pGetDateFormatEx(localeW
, DATE_LONGDATE
, NULL
,
1004 input
, buffer
, COUNTOF(buffer
), NULL
);
1005 ok(!ret
&& GetLastError() == ERROR_INVALID_FLAGS
,
1006 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1009 STRINGSW("",""); /* NULL buffer, len > 0 */
1010 SetLastError(0xdeadbeef);
1011 ret
= pGetDateFormatEx(localeW
, 0, NULL
, input
, NULL
, COUNTOF(buffer
), NULL
);
1012 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1013 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1015 STRINGSW("",""); /* NULL buffer, len == 0 */
1016 ret
= pGetDateFormatEx(localeW
, 0, NULL
, input
, NULL
, 0, NULL
);
1017 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1018 EXPECT_LENW
; EXPECT_EQW
;
1020 STRINGSW("",""); /* Invalid flag combination */
1021 SetLastError(0xdeadbeef);
1022 ret
= pGetDateFormatEx(localeW
, DATE_LONGDATE
|DATE_SHORTDATE
, NULL
,
1023 input
, NULL
, 0, NULL
);
1024 ok(!ret
&& GetLastError() == ERROR_INVALID_FLAGS
,
1025 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1028 curtime
.wYear
= 2002;
1029 curtime
.wMonth
= 10;
1031 curtime
.wDayOfWeek
= 45612; /* Should be 3 - Wednesday */
1032 curtime
.wHour
= 65432; /* Invalid */
1033 curtime
.wMinute
= 34512; /* Invalid */
1034 curtime
.wSecond
= 65535; /* Invalid */
1035 curtime
.wMilliseconds
= 12345;
1036 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
1037 ret
= pGetDateFormatEx(localeW
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
), NULL
);
1038 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1039 EXPECT_LENW
; EXPECT_EQW
;
1041 curtime
.wYear
= 2002;
1042 curtime
.wMonth
= 10;
1044 curtime
.wDayOfWeek
= 45612; /* Should be 3 - Wednesday */
1045 curtime
.wHour
= 65432; /* Invalid */
1046 curtime
.wMinute
= 34512; /* Invalid */
1047 curtime
.wSecond
= 65535; /* Invalid */
1048 curtime
.wMilliseconds
= 12345;
1049 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002");
1050 ret
= pGetDateFormatEx(localeW
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
), emptyW
); /* Use reserved arg */
1051 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1052 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1056 curtime
.wYear
= 1601;
1059 curtime
.wDayOfWeek
= 0; /* Irrelevant */
1061 curtime
.wMinute
= 0;
1062 curtime
.wSecond
= 0;
1063 curtime
.wMilliseconds
= 0;
1064 STRINGSW("dddd d MMMM yyyy","Monday 1 January 1601");
1065 SetLastError(0xdeadbeef);
1066 ret
= pGetDateFormatEx(localeW
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
), NULL
);
1067 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1068 EXPECT_LENW
; EXPECT_EQW
;
1070 curtime
.wYear
= 1600;
1071 curtime
.wMonth
= 12;
1073 curtime
.wDayOfWeek
= 0; /* Irrelevant */
1075 curtime
.wMinute
= 59;
1076 curtime
.wSecond
= 59;
1077 curtime
.wMilliseconds
= 999;
1078 STRINGSW("dddd d MMMM yyyy","Friday 31 December 1600");
1079 SetLastError(0xdeadbeef);
1080 ret
= pGetDateFormatEx(localeW
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
), NULL
);
1081 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1082 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1085 static void test_GetDateFormatW(void)
1089 WCHAR buffer
[BUFFER_SIZE
], input
[BUFFER_SIZE
], Expected
[BUFFER_SIZE
];
1090 LCID lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
1092 STRINGSW("",""); /* If flags is not zero then format must be NULL */
1093 ret
= GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, DATE_LONGDATE
, NULL
,
1094 input
, buffer
, COUNTOF(buffer
));
1095 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1097 win_skip("GetDateFormatW is not implemented\n");
1100 ok(!ret
&& GetLastError() == ERROR_INVALID_FLAGS
,
1101 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1104 STRINGSW("",""); /* NULL buffer, len > 0 */
1105 SetLastError(0xdeadbeef);
1106 ret
= GetDateFormatW (lcid
, 0, NULL
, input
, NULL
, COUNTOF(buffer
));
1107 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1108 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1110 STRINGSW("",""); /* NULL buffer, len == 0 */
1111 ret
= GetDateFormatW (lcid
, 0, NULL
, input
, NULL
, 0);
1112 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1113 EXPECT_LENW
; EXPECT_EQW
;
1115 curtime
.wYear
= 2002;
1116 curtime
.wMonth
= 10;
1118 curtime
.wDayOfWeek
= 45612; /* Should be 3 - Wednesday */
1119 curtime
.wHour
= 65432; /* Invalid */
1120 curtime
.wMinute
= 34512; /* Invalid */
1121 curtime
.wSecond
= 65535; /* Invalid */
1122 curtime
.wMilliseconds
= 12345;
1123 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
1124 ret
= GetDateFormatW (lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
1125 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1126 EXPECT_LENW
; EXPECT_EQW
;
1130 curtime
.wYear
= 1601;
1133 curtime
.wDayOfWeek
= 0; /* Irrelevant */
1135 curtime
.wMinute
= 0;
1136 curtime
.wSecond
= 0;
1137 curtime
.wMilliseconds
= 0;
1138 STRINGSW("dddd d MMMM yyyy","Monday 1 January 1601");
1139 SetLastError(0xdeadbeef);
1140 ret
= GetDateFormatW (lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
1141 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1142 EXPECT_LENW
; EXPECT_EQW
;
1144 curtime
.wYear
= 1600;
1145 curtime
.wMonth
= 12;
1147 curtime
.wDayOfWeek
= 0; /* Irrelevant */
1149 curtime
.wMinute
= 59;
1150 curtime
.wSecond
= 59;
1151 curtime
.wMilliseconds
= 999;
1152 STRINGSW("dddd d MMMM yyyy","Friday 31 December 1600");
1153 SetLastError(0xdeadbeef);
1154 ret
= GetDateFormatW (lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
1155 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1156 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1160 #define CY_POS_LEFT 0
1161 #define CY_POS_RIGHT 1
1162 #define CY_POS_LEFT_SPACE 2
1163 #define CY_POS_RIGHT_SPACE 3
1165 static void test_GetCurrencyFormatA(void)
1167 static char szDot
[] = { '.', '\0' };
1168 static char szComma
[] = { ',', '\0' };
1169 static char szDollar
[] = { '$', '\0' };
1171 LCID lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
1172 char buffer
[BUFFER_SIZE
], Expected
[BUFFER_SIZE
], input
[BUFFER_SIZE
];
1173 CURRENCYFMTA format
;
1175 memset(&format
, 0, sizeof(format
));
1177 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
1178 SetLastError(0xdeadbeef);
1179 ret
= GetCurrencyFormatA(lcid
, 0, input
, NULL
, NULL
, COUNTOF(buffer
));
1180 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1181 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1183 STRINGSA("23,53",""); /* Invalid character --> Error */
1184 SetLastError(0xdeadbeef);
1185 ret
= GetCurrencyFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
1186 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1187 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1189 STRINGSA("--",""); /* Double '-' --> Error */
1190 SetLastError(0xdeadbeef);
1191 ret
= GetCurrencyFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
1192 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1193 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1195 STRINGSA("0-",""); /* Trailing '-' --> Error */
1196 SetLastError(0xdeadbeef);
1197 ret
= GetCurrencyFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
1198 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1199 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1201 STRINGSA("0..",""); /* Double '.' --> Error */
1202 SetLastError(0xdeadbeef);
1203 ret
= GetCurrencyFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
1204 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1205 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1207 STRINGSA(" 0.1",""); /* Leading space --> Error */
1208 SetLastError(0xdeadbeef);
1209 ret
= GetCurrencyFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
1210 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1211 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1213 STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
1214 SetLastError(0xdeadbeef);
1215 ret
= GetCurrencyFormatA(lcid
, NUO
, input
, NULL
, buffer
, 2);
1216 ok( !ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
1217 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1219 STRINGSA("2353",""); /* Format and flags given --> Error */
1220 SetLastError(0xdeadbeef);
1221 ret
= GetCurrencyFormatA(lcid
, NUO
, input
, &format
, buffer
, COUNTOF(buffer
));
1222 ok( !ret
, "Expected ret == 0, got %d\n", ret
);
1223 ok( GetLastError() == ERROR_INVALID_FLAGS
|| GetLastError() == ERROR_INVALID_PARAMETER
,
1224 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1226 STRINGSA("2353",""); /* Invalid format --> Error */
1227 SetLastError(0xdeadbeef);
1228 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1229 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1230 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1232 STRINGSA("2353","$2,353.00"); /* Valid number */
1233 ret
= GetCurrencyFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1234 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1235 EXPECT_LENA
; EXPECT_EQA
;
1237 STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
1238 ret
= GetCurrencyFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1239 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1240 EXPECT_LENA
; EXPECT_EQA
;
1242 STRINGSA("2353.1","$2,353.10"); /* Valid real number */
1243 ret
= GetCurrencyFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1244 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1245 EXPECT_LENA
; EXPECT_EQA
;
1247 STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
1248 ret
= GetCurrencyFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1249 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1250 EXPECT_LENA
; EXPECT_EQA
;
1252 STRINGSA("2353.119","$2,353.12"); /* Too many DP --> Rounded */
1253 ret
= GetCurrencyFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1254 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1255 EXPECT_LENA
; EXPECT_EQA
;
1257 format
.NumDigits
= 0; /* No decimal separator */
1258 format
.LeadingZero
= 0;
1259 format
.Grouping
= 0; /* No grouping char */
1260 format
.NegativeOrder
= 0;
1261 format
.PositiveOrder
= CY_POS_LEFT
;
1262 format
.lpDecimalSep
= szDot
;
1263 format
.lpThousandSep
= szComma
;
1264 format
.lpCurrencySymbol
= szDollar
;
1266 STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
1267 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1268 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1269 EXPECT_LENA
; EXPECT_EQA
;
1271 format
.NumDigits
= 1; /* 1 DP --> Expect decimal separator */
1272 STRINGSA("2353","$2353.0");
1273 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1274 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1275 EXPECT_LENA
; EXPECT_EQA
;
1277 format
.Grouping
= 2; /* Group by 100's */
1278 STRINGSA("2353","$23,53.0");
1279 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1280 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1281 EXPECT_LENA
; EXPECT_EQA
;
1283 STRINGSA("235","$235.0"); /* Grouping of a positive number */
1284 format
.Grouping
= 3;
1285 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1286 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1287 EXPECT_LENA
; EXPECT_EQA
;
1289 STRINGSA("-235","$-235.0"); /* Grouping of a negative number */
1290 format
.NegativeOrder
= 2;
1291 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1292 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1293 EXPECT_LENA
; EXPECT_EQA
;
1295 format
.LeadingZero
= 1; /* Always provide leading zero */
1296 STRINGSA(".5","$0.5");
1297 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1298 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1299 EXPECT_LENA
; EXPECT_EQA
;
1301 format
.PositiveOrder
= CY_POS_RIGHT
;
1302 STRINGSA("1","1.0$");
1303 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1304 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1305 EXPECT_LENA
; EXPECT_EQA
;
1307 format
.PositiveOrder
= CY_POS_LEFT_SPACE
;
1308 STRINGSA("1","$ 1.0");
1309 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1310 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1311 EXPECT_LENA
; EXPECT_EQA
;
1313 format
.PositiveOrder
= CY_POS_RIGHT_SPACE
;
1314 STRINGSA("1","1.0 $");
1315 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1316 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1317 EXPECT_LENA
; EXPECT_EQA
;
1319 format
.NegativeOrder
= 0;
1320 STRINGSA("-1","($1.0)");
1321 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1322 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1323 EXPECT_LENA
; EXPECT_EQA
;
1325 format
.NegativeOrder
= 1;
1326 STRINGSA("-1","-$1.0");
1327 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1328 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1329 EXPECT_LENA
; EXPECT_EQA
;
1331 format
.NegativeOrder
= 2;
1332 STRINGSA("-1","$-1.0");
1333 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1334 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1335 EXPECT_LENA
; EXPECT_EQA
;
1337 format
.NegativeOrder
= 3;
1338 STRINGSA("-1","$1.0-");
1339 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1340 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1341 EXPECT_LENA
; EXPECT_EQA
;
1343 format
.NegativeOrder
= 4;
1344 STRINGSA("-1","(1.0$)");
1345 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1346 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1347 EXPECT_LENA
; EXPECT_EQA
;
1349 format
.NegativeOrder
= 5;
1350 STRINGSA("-1","-1.0$");
1351 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1352 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1353 EXPECT_LENA
; EXPECT_EQA
;
1355 format
.NegativeOrder
= 6;
1356 STRINGSA("-1","1.0-$");
1357 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1358 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1359 EXPECT_LENA
; EXPECT_EQA
;
1361 format
.NegativeOrder
= 7;
1362 STRINGSA("-1","1.0$-");
1363 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1364 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1365 EXPECT_LENA
; EXPECT_EQA
;
1367 format
.NegativeOrder
= 8;
1368 STRINGSA("-1","-1.0 $");
1369 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1370 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1371 EXPECT_LENA
; EXPECT_EQA
;
1373 format
.NegativeOrder
= 9;
1374 STRINGSA("-1","-$ 1.0");
1375 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1376 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1377 EXPECT_LENA
; EXPECT_EQA
;
1379 format
.NegativeOrder
= 10;
1380 STRINGSA("-1","1.0 $-");
1381 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1382 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1383 EXPECT_LENA
; EXPECT_EQA
;
1385 format
.NegativeOrder
= 11;
1386 STRINGSA("-1","$ 1.0-");
1387 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1388 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1389 EXPECT_LENA
; EXPECT_EQA
;
1391 format
.NegativeOrder
= 12;
1392 STRINGSA("-1","$ -1.0");
1393 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1394 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1395 EXPECT_LENA
; EXPECT_EQA
;
1397 format
.NegativeOrder
= 13;
1398 STRINGSA("-1","1.0- $");
1399 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1400 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1401 EXPECT_LENA
; EXPECT_EQA
;
1403 format
.NegativeOrder
= 14;
1404 STRINGSA("-1","($ 1.0)");
1405 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1406 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1407 EXPECT_LENA
; EXPECT_EQA
;
1409 format
.NegativeOrder
= 15;
1410 STRINGSA("-1","(1.0 $)");
1411 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1412 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1413 EXPECT_LENA
; EXPECT_EQA
;
1416 #define NEG_PARENS 0 /* "(1.1)" */
1417 #define NEG_LEFT 1 /* "-1.1" */
1418 #define NEG_LEFT_SPACE 2 /* "- 1.1" */
1419 #define NEG_RIGHT 3 /* "1.1-" */
1420 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
1422 static void test_GetNumberFormatA(void)
1424 static char szDot
[] = { '.', '\0' };
1425 static char szComma
[] = { ',', '\0' };
1427 LCID lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
1428 char buffer
[BUFFER_SIZE
], Expected
[BUFFER_SIZE
], input
[BUFFER_SIZE
];
1431 memset(&format
, 0, sizeof(format
));
1433 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
1434 SetLastError(0xdeadbeef);
1435 ret
= GetNumberFormatA(lcid
, 0, input
, NULL
, NULL
, COUNTOF(buffer
));
1436 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1437 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1439 STRINGSA("23,53",""); /* Invalid character --> Error */
1440 SetLastError(0xdeadbeef);
1441 ret
= GetNumberFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
1442 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1443 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1445 STRINGSA("--",""); /* Double '-' --> Error */
1446 SetLastError(0xdeadbeef);
1447 ret
= GetNumberFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
1448 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1449 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1451 STRINGSA("0-",""); /* Trailing '-' --> Error */
1452 SetLastError(0xdeadbeef);
1453 ret
= GetNumberFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
1454 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1455 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1457 STRINGSA("0..",""); /* Double '.' --> Error */
1458 SetLastError(0xdeadbeef);
1459 ret
= GetNumberFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
1460 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1461 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1463 STRINGSA(" 0.1",""); /* Leading space --> Error */
1464 SetLastError(0xdeadbeef);
1465 ret
= GetNumberFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
1466 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1467 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1469 STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
1470 SetLastError(0xdeadbeef);
1471 ret
= GetNumberFormatA(lcid
, NUO
, input
, NULL
, buffer
, 2);
1472 ok( !ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
1473 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1475 STRINGSA("2353",""); /* Format and flags given --> Error */
1476 SetLastError(0xdeadbeef);
1477 ret
= GetNumberFormatA(lcid
, NUO
, input
, &format
, buffer
, COUNTOF(buffer
));
1478 ok( !ret
, "Expected ret == 0, got %d\n", ret
);
1479 ok( GetLastError() == ERROR_INVALID_FLAGS
|| GetLastError() == ERROR_INVALID_PARAMETER
,
1480 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1482 STRINGSA("2353",""); /* Invalid format --> Error */
1483 SetLastError(0xdeadbeef);
1484 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1485 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1486 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1488 STRINGSA("2353","2,353.00"); /* Valid number */
1489 ret
= GetNumberFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1490 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1491 EXPECT_LENA
; EXPECT_EQA
;
1493 STRINGSA("-2353","-2,353.00"); /* Valid negative number */
1494 ret
= GetNumberFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1495 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1496 EXPECT_LENA
; EXPECT_EQA
;
1498 STRINGSA("-353","-353.00"); /* test for off by one error in grouping */
1499 ret
= GetNumberFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1500 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1501 EXPECT_LENA
; EXPECT_EQA
;
1503 STRINGSA("2353.1","2,353.10"); /* Valid real number */
1504 ret
= GetNumberFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1505 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1506 EXPECT_LENA
; EXPECT_EQA
;
1508 STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
1509 ret
= GetNumberFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1510 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1511 EXPECT_LENA
; EXPECT_EQA
;
1513 STRINGSA("2353.119","2,353.12"); /* Too many DP --> Rounded */
1514 ret
= GetNumberFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1515 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1516 EXPECT_LENA
; EXPECT_EQA
;
1518 format
.NumDigits
= 0; /* No decimal separator */
1519 format
.LeadingZero
= 0;
1520 format
.Grouping
= 0; /* No grouping char */
1521 format
.NegativeOrder
= 0;
1522 format
.lpDecimalSep
= szDot
;
1523 format
.lpThousandSep
= szComma
;
1525 STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
1526 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1527 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1528 EXPECT_LENA
; EXPECT_EQA
;
1530 format
.NumDigits
= 1; /* 1 DP --> Expect decimal separator */
1531 STRINGSA("2353","2353.0");
1532 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1533 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1534 EXPECT_LENA
; EXPECT_EQA
;
1536 format
.Grouping
= 2; /* Group by 100's */
1537 STRINGSA("2353","23,53.0");
1538 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1539 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1540 EXPECT_LENA
; EXPECT_EQA
;
1542 STRINGSA("235","235.0"); /* Grouping of a positive number */
1543 format
.Grouping
= 3;
1544 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1545 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1546 EXPECT_LENA
; EXPECT_EQA
;
1548 STRINGSA("-235","-235.0"); /* Grouping of a negative number */
1549 format
.NegativeOrder
= NEG_LEFT
;
1550 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1551 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1552 EXPECT_LENA
; EXPECT_EQA
;
1554 format
.LeadingZero
= 1; /* Always provide leading zero */
1555 STRINGSA(".5","0.5");
1556 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1557 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1558 EXPECT_LENA
; EXPECT_EQA
;
1560 format
.NegativeOrder
= NEG_PARENS
;
1561 STRINGSA("-1","(1.0)");
1562 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1563 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1564 EXPECT_LENA
; EXPECT_EQA
;
1566 format
.NegativeOrder
= NEG_LEFT
;
1567 STRINGSA("-1","-1.0");
1568 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1569 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1570 EXPECT_LENA
; EXPECT_EQA
;
1572 format
.NegativeOrder
= NEG_LEFT_SPACE
;
1573 STRINGSA("-1","- 1.0");
1574 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1575 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1576 EXPECT_LENA
; EXPECT_EQA
;
1578 format
.NegativeOrder
= NEG_RIGHT
;
1579 STRINGSA("-1","1.0-");
1580 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1581 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1582 EXPECT_LENA
; EXPECT_EQA
;
1584 format
.NegativeOrder
= NEG_RIGHT_SPACE
;
1585 STRINGSA("-1","1.0 -");
1586 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1587 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1588 EXPECT_LENA
; EXPECT_EQA
;
1590 lcid
= MAKELCID(MAKELANGID(LANG_FRENCH
, SUBLANG_DEFAULT
), SORT_DEFAULT
);
1592 if (IsValidLocale(lcid
, 0))
1594 STRINGSA("-12345","-12 345,00"); /* Try French formatting */
1595 Expected
[3] = 160; /* Non breaking space */
1596 ret
= GetNumberFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1597 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1598 EXPECT_LENA
; EXPECT_EQA
;
1602 static void test_GetNumberFormatEx(void)
1606 static WCHAR dotW
[] = {'.',0};
1607 static WCHAR commaW
[] = {',',0};
1608 static const WCHAR enW
[] = {'e','n','-','U','S',0};
1609 static const WCHAR frW
[] = {'f','r','-','F','R',0};
1610 static const WCHAR bogusW
[] = {'b','o','g','u','s',0};
1611 WCHAR buffer
[BUFFER_SIZE
], input
[BUFFER_SIZE
], Expected
[BUFFER_SIZE
];
1613 if (!pGetNumberFormatEx
)
1615 win_skip("GetNumberFormatEx is not available.\n");
1619 STRINGSW("23",""); /* NULL output, length > 0 --> Error */
1620 ret
= pGetNumberFormatEx(enW
, 0, input
, NULL
, NULL
, COUNTOF(buffer
));
1621 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1622 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1624 STRINGSW("23,53",""); /* Invalid character --> Error */
1625 ret
= pGetNumberFormatEx(enW
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
1626 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1627 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1629 STRINGSW("--",""); /* Double '-' --> Error */
1630 ret
= pGetNumberFormatEx(enW
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
1631 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1632 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1634 STRINGSW("0-",""); /* Trailing '-' --> Error */
1635 ret
= pGetNumberFormatEx(enW
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
1636 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1637 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1639 STRINGSW("0..",""); /* Double '.' --> Error */
1640 ret
= pGetNumberFormatEx(enW
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
1641 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1642 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1644 STRINGSW(" 0.1",""); /* Leading space --> Error */
1645 ret
= pGetNumberFormatEx(enW
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
1646 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1647 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1649 STRINGSW("1234","1"); /* Length too small --> Write up to length chars */
1650 ret
= pGetNumberFormatEx(enW
, NUO
, input
, NULL
, buffer
, 2);
1651 ok( !ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
1652 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1654 STRINGSW("23",""); /* Bogus locale --> Error */
1655 ret
= pGetNumberFormatEx(bogusW
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1656 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1657 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1659 memset(&format
, 0, sizeof(format
));
1661 STRINGSW("2353",""); /* Format and flags given --> Error */
1662 ret
= pGetNumberFormatEx(enW
, NUO
, input
, &format
, buffer
, COUNTOF(buffer
));
1663 ok( !ret
, "Expected ret == 0, got %d\n", ret
);
1664 ok( GetLastError() == ERROR_INVALID_FLAGS
|| GetLastError() == ERROR_INVALID_PARAMETER
,
1665 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1667 STRINGSW("2353",""); /* Invalid format --> Error */
1668 ret
= pGetNumberFormatEx(enW
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1669 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1670 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1672 STRINGSW("2353","2,353.00"); /* Valid number */
1673 ret
= pGetNumberFormatEx(enW
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1674 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1675 EXPECT_LENW
; EXPECT_EQW
;
1677 STRINGSW("-2353","-2,353.00"); /* Valid negative number */
1678 ret
= pGetNumberFormatEx(enW
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1679 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1680 EXPECT_LENW
; EXPECT_EQW
;
1682 STRINGSW("-353","-353.00"); /* test for off by one error in grouping */
1683 ret
= pGetNumberFormatEx(enW
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1684 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1685 EXPECT_LENW
; EXPECT_EQW
;
1687 STRINGSW("2353.1","2,353.10"); /* Valid real number */
1688 ret
= pGetNumberFormatEx(enW
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1689 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1690 EXPECT_LENW
; EXPECT_EQW
;
1692 STRINGSW("2353.111","2,353.11"); /* Too many DP --> Truncated */
1693 ret
= pGetNumberFormatEx(enW
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1694 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1695 EXPECT_LENW
; EXPECT_EQW
;
1697 STRINGSW("2353.119","2,353.12"); /* Too many DP --> Rounded */
1698 ret
= pGetNumberFormatEx(enW
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1699 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1700 EXPECT_LENW
; EXPECT_EQW
;
1702 format
.NumDigits
= 0; /* No decimal separator */
1703 format
.LeadingZero
= 0;
1704 format
.Grouping
= 0; /* No grouping char */
1705 format
.NegativeOrder
= 0;
1706 format
.lpDecimalSep
= dotW
;
1707 format
.lpThousandSep
= commaW
;
1709 STRINGSW("2353","2353"); /* No decimal or grouping chars expected */
1710 ret
= pGetNumberFormatEx(enW
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1711 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1712 EXPECT_LENW
; EXPECT_EQW
;
1714 format
.NumDigits
= 1; /* 1 DP --> Expect decimal separator */
1715 STRINGSW("2353","2353.0");
1716 ret
= pGetNumberFormatEx(enW
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1717 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1718 EXPECT_LENW
; EXPECT_EQW
;
1720 format
.Grouping
= 2; /* Group by 100's */
1721 STRINGSW("2353","23,53.0");
1722 ret
= pGetNumberFormatEx(enW
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1723 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1724 EXPECT_LENW
; EXPECT_EQW
;
1726 STRINGSW("235","235.0"); /* Grouping of a positive number */
1727 format
.Grouping
= 3;
1728 ret
= pGetNumberFormatEx(enW
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1729 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1730 EXPECT_LENW
; EXPECT_EQW
;
1732 STRINGSW("-235","-235.0"); /* Grouping of a negative number */
1733 format
.NegativeOrder
= NEG_LEFT
;
1734 ret
= pGetNumberFormatEx(enW
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1735 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1736 EXPECT_LENW
; EXPECT_EQW
;
1738 format
.LeadingZero
= 1; /* Always provide leading zero */
1739 STRINGSW(".5","0.5");
1740 ret
= pGetNumberFormatEx(enW
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1741 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1742 EXPECT_LENW
; EXPECT_EQW
;
1744 format
.NegativeOrder
= NEG_PARENS
;
1745 STRINGSW("-1","(1.0)");
1746 ret
= pGetNumberFormatEx(enW
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1747 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1748 EXPECT_LENW
; EXPECT_EQW
;
1750 format
.NegativeOrder
= NEG_LEFT
;
1751 STRINGSW("-1","-1.0");
1752 ret
= pGetNumberFormatEx(enW
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1753 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1754 EXPECT_LENW
; EXPECT_EQW
;
1756 format
.NegativeOrder
= NEG_LEFT_SPACE
;
1757 STRINGSW("-1","- 1.0");
1758 ret
= pGetNumberFormatEx(enW
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1759 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1760 EXPECT_LENW
; EXPECT_EQW
;
1762 format
.NegativeOrder
= NEG_RIGHT
;
1763 STRINGSW("-1","1.0-");
1764 ret
= pGetNumberFormatEx(enW
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1765 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1766 EXPECT_LENW
; EXPECT_EQW
;
1768 format
.NegativeOrder
= NEG_RIGHT_SPACE
;
1769 STRINGSW("-1","1.0 -");
1770 ret
= pGetNumberFormatEx(enW
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
1771 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1772 EXPECT_LENW
; EXPECT_EQW
;
1774 if (pIsValidLocaleName(frW
))
1776 STRINGSW("-12345","-12 345,00"); /* Try French formatting */
1777 Expected
[3] = 160; /* Non breaking space */
1778 ret
= pGetNumberFormatEx(frW
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
1779 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
1780 EXPECT_LENW
; EXPECT_EQW
;
1784 struct comparestringa_entry
{
1794 static const struct comparestringa_entry comparestringa_data
[] = {
1795 { LOCALE_SYSTEM_DEFAULT
, 0, "EndDialog", -1, "_Property", -1, CSTR_GREATER_THAN
},
1796 { LOCALE_SYSTEM_DEFAULT
, 0, "osp_vba.sreg0070", -1, "_IEWWBrowserComp", -1, CSTR_GREATER_THAN
},
1797 { LOCALE_SYSTEM_DEFAULT
, 0, "r", -1, "\\", -1, CSTR_GREATER_THAN
},
1798 { LOCALE_SYSTEM_DEFAULT
, 0, "osp_vba.sreg0031", -1, "OriginalDatabase", -1, CSTR_GREATER_THAN
},
1799 { LOCALE_SYSTEM_DEFAULT
, 0, "AAA", -1, "aaa", -1, CSTR_GREATER_THAN
},
1800 { LOCALE_SYSTEM_DEFAULT
, 0, "AAA", -1, "aab", -1, CSTR_LESS_THAN
},
1801 { LOCALE_SYSTEM_DEFAULT
, 0, "AAA", -1, "Aab", -1, CSTR_LESS_THAN
},
1802 { LOCALE_SYSTEM_DEFAULT
, 0, ".AAA", -1, "Aab", -1, CSTR_LESS_THAN
},
1803 { LOCALE_SYSTEM_DEFAULT
, 0, ".AAA", -1, "A.ab", -1, CSTR_LESS_THAN
},
1804 { LOCALE_SYSTEM_DEFAULT
, 0, "aa", -1, "AB", -1, CSTR_LESS_THAN
},
1805 { LOCALE_SYSTEM_DEFAULT
, 0, "aa", -1, "Aab", -1, CSTR_LESS_THAN
},
1806 { LOCALE_SYSTEM_DEFAULT
, 0, "aB", -1, "Aab", -1, CSTR_GREATER_THAN
},
1807 { LOCALE_SYSTEM_DEFAULT
, 0, "Ba", -1, "bab", -1, CSTR_LESS_THAN
},
1808 { LOCALE_SYSTEM_DEFAULT
, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1, CSTR_LESS_THAN
},
1809 { LOCALE_SYSTEM_DEFAULT
, 0, "a", -1, "{", -1, CSTR_GREATER_THAN
},
1810 { LOCALE_SYSTEM_DEFAULT
, 0, "A", -1, "{", -1, CSTR_GREATER_THAN
},
1811 { LOCALE_SYSTEM_DEFAULT
, 0, "3.5", 0, "4.0", -1, CSTR_LESS_THAN
},
1812 { LOCALE_SYSTEM_DEFAULT
, 0, "3.5", -1, "4.0", -1, CSTR_LESS_THAN
},
1813 { LOCALE_SYSTEM_DEFAULT
, 0, "3.520.4403.2", -1, "4.0.2927.10", -1, CSTR_LESS_THAN
},
1814 /* hyphen and apostrophe are treated differently depending on whether SORT_STRINGSORT specified or not */
1815 { LOCALE_SYSTEM_DEFAULT
, 0, "-o", -1, "/m", -1, CSTR_GREATER_THAN
},
1816 { LOCALE_SYSTEM_DEFAULT
, 0, "/m", -1, "-o", -1, CSTR_LESS_THAN
},
1817 { LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "-o", -1, "/m", -1, CSTR_LESS_THAN
},
1818 { LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "/m", -1, "-o", -1, CSTR_GREATER_THAN
},
1819 { LOCALE_SYSTEM_DEFAULT
, 0, "'o", -1, "/m", -1, CSTR_GREATER_THAN
},
1820 { LOCALE_SYSTEM_DEFAULT
, 0, "/m", -1, "'o", -1, CSTR_LESS_THAN
},
1821 { LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "'o", -1, "/m", -1, CSTR_LESS_THAN
},
1822 { LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "/m", -1, "'o", -1, CSTR_GREATER_THAN
},
1823 { LOCALE_SYSTEM_DEFAULT
, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9, CSTR_EQUAL
},
1824 { LOCALE_SYSTEM_DEFAULT
, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10, CSTR_LESS_THAN
},
1825 { LOCALE_SYSTEM_DEFAULT
, 0, "a-", 3, "a\0", 3, CSTR_GREATER_THAN
},
1826 { LOCALE_SYSTEM_DEFAULT
, 0, "a'", 3, "a\0", 3, CSTR_GREATER_THAN
},
1827 { LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "a-", 3, "a\0", 3, CSTR_GREATER_THAN
},
1828 { LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "a'", 3, "a\0", 3, CSTR_GREATER_THAN
},
1829 { LOCALE_SYSTEM_DEFAULT
, NORM_IGNORESYMBOLS
, "a.", 3, "a\0", 3, CSTR_EQUAL
},
1830 { LOCALE_SYSTEM_DEFAULT
, NORM_IGNORESYMBOLS
, "a ", 3, "a\0", 3, CSTR_EQUAL
},
1831 { LOCALE_SYSTEM_DEFAULT
, 0, "a", 1, "a\0\0", 4, CSTR_EQUAL
},
1832 { LOCALE_SYSTEM_DEFAULT
, 0, "a", 2, "a\0\0", 4, CSTR_EQUAL
},
1833 { LOCALE_SYSTEM_DEFAULT
, 0, "a\0\0", 4, "a", 1, CSTR_EQUAL
},
1834 { LOCALE_SYSTEM_DEFAULT
, 0, "a\0\0", 4, "a", 2, CSTR_EQUAL
},
1835 { LOCALE_SYSTEM_DEFAULT
, 0, "a", 1, "a\0x", 4, CSTR_LESS_THAN
},
1836 { LOCALE_SYSTEM_DEFAULT
, 0, "a", 2, "a\0x", 4, CSTR_LESS_THAN
},
1837 { LOCALE_SYSTEM_DEFAULT
, 0, "a\0x", 4, "a", 1, CSTR_GREATER_THAN
},
1838 { LOCALE_SYSTEM_DEFAULT
, 0, "a\0x", 4, "a", 2, CSTR_GREATER_THAN
},
1841 static void test_CompareStringA(void)
1845 LCID lcid
= MAKELCID(MAKELANGID(LANG_FRENCH
, SUBLANG_DEFAULT
), SORT_DEFAULT
);
1847 for (i
= 0; i
< sizeof(comparestringa_data
)/sizeof(struct comparestringa_entry
); i
++)
1849 const struct comparestringa_entry
*entry
= &comparestringa_data
[i
];
1851 ret
= CompareStringA(entry
->lcid
, entry
->flags
, entry
->first
, entry
->first_len
,
1852 entry
->second
, entry
->second_len
);
1853 ok(ret
== entry
->ret
, "%d: got %d, expected %d\n", i
, ret
, entry
->ret
);
1856 ret
= CompareStringA(lcid
, NORM_IGNORECASE
, "Salut", -1, "Salute", -1);
1857 ok (ret
== CSTR_LESS_THAN
, "(Salut/Salute) Expected CSTR_LESS_THAN, got %d\n", ret
);
1859 ret
= CompareStringA(lcid
, NORM_IGNORECASE
, "Salut", -1, "SaLuT", -1);
1860 ok (ret
== CSTR_EQUAL
, "(Salut/SaLuT) Expected CSTR_EQUAL, got %d\n", ret
);
1862 ret
= CompareStringA(lcid
, NORM_IGNORECASE
, "Salut", -1, "hola", -1);
1863 ok (ret
== CSTR_GREATER_THAN
, "(Salut/hola) Expected CSTR_GREATER_THAN, got %d\n", ret
);
1865 ret
= CompareStringA(lcid
, NORM_IGNORECASE
, "haha", -1, "hoho", -1);
1866 ok (ret
== CSTR_LESS_THAN
, "(haha/hoho) Expected CSTR_LESS_THAN, got %d\n", ret
);
1868 lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
1870 ret
= CompareStringA(lcid
, NORM_IGNORECASE
, "haha", -1, "hoho", -1);
1871 ok (ret
== CSTR_LESS_THAN
, "(haha/hoho) Expected CSTR_LESS_THAN, got %d\n", ret
);
1873 ret
= CompareStringA(lcid
, NORM_IGNORECASE
, "haha", -1, "hoho", 0);
1874 ok (ret
== CSTR_GREATER_THAN
, "(haha/hoho) Expected CSTR_GREATER_THAN, got %d\n", ret
);
1876 ret
= CompareStringA(lcid
, NORM_IGNORECASE
, "Salut", 5, "saLuT", -1);
1877 ok (ret
== CSTR_EQUAL
, "(Salut/saLuT) Expected CSTR_EQUAL, got %d\n", ret
);
1879 /* test for CompareStringA flags */
1880 SetLastError(0xdeadbeef);
1881 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0x8, "NULL", -1, "NULL", -1);
1882 ok(GetLastError() == ERROR_INVALID_FLAGS
,
1883 "unexpected error code %d\n", GetLastError());
1884 ok(!ret
, "CompareStringA must fail with invalid flag\n");
1886 SetLastError(0xdeadbeef);
1887 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, LOCALE_USE_CP_ACP
, "NULL", -1, "NULL", -1);
1888 ok(GetLastError() == 0xdeadbeef, "unexpected error code %d\n", GetLastError());
1889 ok(ret
== CSTR_EQUAL
, "CompareStringA error: %d != CSTR_EQUAL\n", ret
);
1890 /* end of test for CompareStringA flags */
1892 ret
= lstrcmpA("", "");
1893 ok (ret
== 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret
);
1895 ret
= lstrcmpA(NULL
, NULL
);
1896 ok (ret
== 0 || broken(ret
== -2) /* win9x */, "lstrcmpA(NULL, NULL) should return 0, got %d\n", ret
);
1898 ret
= lstrcmpA("", NULL
);
1899 ok (ret
== 1 || broken(ret
== -2) /* win9x */, "lstrcmpA(\"\", NULL) should return 1, got %d\n", ret
);
1901 ret
= lstrcmpA(NULL
, "");
1902 ok (ret
== -1 || broken(ret
== -2) /* win9x */, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret
);
1905 if (0) { /* this requires collation table patch to make it MS compatible */
1906 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "'o", -1, "-o", -1 );
1907 ok(ret
== CSTR_LESS_THAN
, "'o vs -o expected CSTR_LESS_THAN, got %d\n", ret
);
1909 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "'o", -1, "-o", -1 );
1910 ok(ret
== CSTR_LESS_THAN
, "'o vs -o expected CSTR_LESS_THAN, got %d\n", ret
);
1912 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "'", -1, "-", -1 );
1913 ok(ret
== CSTR_LESS_THAN
, "' vs - expected CSTR_LESS_THAN, got %d\n", ret
);
1915 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "'", -1, "-", -1 );
1916 ok(ret
== CSTR_LESS_THAN
, "' vs - expected CSTR_LESS_THAN, got %d\n", ret
);
1918 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "`o", -1, "/m", -1 );
1919 ok(ret
== CSTR_GREATER_THAN
, "`o vs /m CSTR_GREATER_THAN got %d\n", ret
);
1921 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "/m", -1, "`o", -1 );
1922 ok(ret
== CSTR_LESS_THAN
, "/m vs `o expected CSTR_LESS_THAN, got %d\n", ret
);
1924 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "`o", -1, "/m", -1 );
1925 ok(ret
== CSTR_GREATER_THAN
, "`o vs /m CSTR_GREATER_THAN got %d\n", ret
);
1927 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "/m", -1, "`o", -1 );
1928 ok(ret
== CSTR_LESS_THAN
, "/m vs `o expected CSTR_LESS_THAN, got %d\n", ret
);
1930 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "`o", -1, "-m", -1 );
1931 ok(ret
== CSTR_LESS_THAN
, "`o vs -m expected CSTR_LESS_THAN, got %d\n", ret
);
1933 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "-m", -1, "`o", -1 );
1934 ok(ret
== CSTR_GREATER_THAN
, "-m vs `o CSTR_GREATER_THAN got %d\n", ret
);
1936 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "`o", -1, "-m", -1 );
1937 ok(ret
== CSTR_GREATER_THAN
, "`o vs -m CSTR_GREATER_THAN got %d\n", ret
);
1939 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "-m", -1, "`o", -1 );
1940 ok(ret
== CSTR_LESS_THAN
, "-m vs `o expected CSTR_LESS_THAN, got %d\n", ret
);
1944 /* WinXP handles embedded NULLs differently than earlier versions */
1945 ret
= CompareStringA(LOCALE_USER_DEFAULT
, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
1946 ok(ret
== CSTR_LESS_THAN
|| ret
== CSTR_EQUAL
, "aLuZkUtZ vs aLuZkUtZ\\0A expected CSTR_LESS_THAN or CSTR_EQUAL, got %d\n", ret
);
1948 ret
= CompareStringA(LOCALE_USER_DEFAULT
, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
1949 ok(ret
== CSTR_LESS_THAN
|| ret
== CSTR_EQUAL
, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected CSTR_LESS_THAN or CSTR_EQUAL, got %d\n", ret
);
1951 ret
= CompareStringA(lcid
, 0, "a\0b", -1, "a", -1);
1952 ok(ret
== CSTR_EQUAL
, "a vs a expected CSTR_EQUAL, got %d\n", ret
);
1954 ret
= CompareStringA(lcid
, 0, "a\0b", 4, "a", 2);
1955 ok(ret
== CSTR_EQUAL
|| /* win2k */
1956 ret
== CSTR_GREATER_THAN
,
1957 "a\\0b vs a expected CSTR_EQUAL or CSTR_GREATER_THAN, got %d\n", ret
);
1959 ret
= CompareStringA(lcid
, 0, "\2", 2, "\1", 2);
1960 todo_wine
ok(ret
!= CSTR_EQUAL
, "\\2 vs \\1 expected unequal\n");
1962 ret
= CompareStringA(lcid
, NORM_IGNORECASE
| LOCALE_USE_CP_ACP
, "#", -1, ".", -1);
1963 ok(ret
== CSTR_LESS_THAN
, "\"#\" vs \".\" expected CSTR_LESS_THAN, got %d\n", ret
);
1965 ret
= CompareStringA(lcid
, NORM_IGNORECASE
, "_", -1, ".", -1);
1966 ok(ret
== CSTR_GREATER_THAN
, "\"_\" vs \".\" expected CSTR_GREATER_THAN, got %d\n", ret
);
1968 ret
= lstrcmpiA("#", ".");
1969 ok(ret
== -1, "\"#\" vs \".\" expected -1, got %d\n", ret
);
1971 lcid
= MAKELCID(MAKELANGID(LANG_POLISH
, SUBLANG_DEFAULT
), SORT_DEFAULT
);
1973 /* \xB9 character lies between a and b */
1974 ret
= CompareStringA(lcid
, 0, "a", 1, "\xB9", 1);
1975 todo_wine
ok(ret
== CSTR_LESS_THAN
, "\'\\xB9\' character should be greater than \'a\'\n");
1976 ret
= CompareStringA(lcid
, 0, "\xB9", 1, "b", 1);
1977 ok(ret
== CSTR_LESS_THAN
, "\'\\xB9\' character should be smaller than \'b\'\n");
1979 memset(a
, 'a', sizeof(a
));
1980 SetLastError(0xdeadbeef);
1981 ret
= CompareStringA(lcid
, 0, a
, sizeof(a
), a
, sizeof(a
));
1982 ok (GetLastError() == 0xdeadbeef && ret
== CSTR_EQUAL
,
1983 "ret %d, error %d, expected value %d\n", ret
, GetLastError(), CSTR_EQUAL
);
1986 static void test_CompareStringW(void)
1996 buf
= VirtualAlloc(NULL
, si
.dwPageSize
* 4, MEM_COMMIT
, PAGE_READWRITE
);
1997 ok(buf
!= NULL
, "VirtualAlloc failed with %u\n", GetLastError());
1998 success
= VirtualProtect(buf
+ si
.dwPageSize
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
1999 ok(success
, "VirtualProtect failed with %u\n", GetLastError());
2000 success
= VirtualProtect(buf
+ 3 * si
.dwPageSize
, si
.dwPageSize
, PAGE_NOACCESS
, &old_prot
);
2001 ok(success
, "VirtualProtect failed with %u\n", GetLastError());
2003 str1
= (WCHAR
*)(buf
+ si
.dwPageSize
- sizeof(WCHAR
));
2004 str2
= (WCHAR
*)(buf
+ 3 * si
.dwPageSize
- sizeof(WCHAR
));
2008 /* CompareStringW should abort on the first non-matching character */
2009 ret
= CompareStringW(CP_ACP
, 0, str1
, 100, str2
, 100);
2010 ok(ret
== CSTR_LESS_THAN
, "expected CSTR_LESS_THAN, got %d\n", ret
);
2012 success
= VirtualFree(buf
, 0, MEM_RELEASE
);
2013 ok(success
, "VirtualFree failed with %u\n", GetLastError());
2016 struct comparestringex_test
{
2019 const WCHAR first
[2];
2020 const WCHAR second
[2];
2026 static const struct comparestringex_test comparestringex_tests
[] = {
2027 /* default behavior */
2030 {'i',0}, {'I',0}, CSTR_LESS_THAN
, -1, FALSE
2034 {'i',0}, {0x130,0}, CSTR_LESS_THAN
, -1, FALSE
2038 {'i',0}, {0x131,0}, CSTR_LESS_THAN
, -1, FALSE
2042 {'I',0}, {0x130,0}, CSTR_LESS_THAN
, -1, TRUE
2046 {'I',0}, {0x131,0}, CSTR_LESS_THAN
, -1, FALSE
2050 {0x130,0}, {0x131,0}, CSTR_GREATER_THAN
, -1, TRUE
2052 /* with NORM_IGNORECASE */
2054 "tr-TR", NORM_IGNORECASE
,
2055 {'i',0}, {'I',0}, CSTR_EQUAL
, -1, FALSE
2058 "tr-TR", NORM_IGNORECASE
,
2059 {'i',0}, {0x130,0}, CSTR_LESS_THAN
, -1, TRUE
2062 "tr-TR", NORM_IGNORECASE
,
2063 {'i',0}, {0x131,0}, CSTR_LESS_THAN
, -1, FALSE
2066 "tr-TR", NORM_IGNORECASE
,
2067 {'I',0}, {0x130,0}, CSTR_LESS_THAN
, -1, TRUE
2070 "tr-TR", NORM_IGNORECASE
,
2071 {'I',0}, {0x131,0}, CSTR_LESS_THAN
, -1, FALSE
2074 "tr-TR", NORM_IGNORECASE
,
2075 {0x130,0}, {0x131,0}, CSTR_GREATER_THAN
, -1, TRUE
2077 /* with NORM_LINGUISTIC_CASING */
2079 "tr-TR", NORM_LINGUISTIC_CASING
,
2080 {'i',0}, {'I',0}, CSTR_GREATER_THAN
, CSTR_LESS_THAN
, TRUE
2083 "tr-TR", NORM_LINGUISTIC_CASING
,
2084 {'i',0}, {0x130,0}, CSTR_LESS_THAN
, -1, FALSE
2087 "tr-TR", NORM_LINGUISTIC_CASING
,
2088 {'i',0}, {0x131,0}, CSTR_GREATER_THAN
, CSTR_LESS_THAN
, TRUE
2091 "tr-TR", NORM_LINGUISTIC_CASING
,
2092 {'I',0}, {0x130,0}, CSTR_LESS_THAN
, -1, TRUE
2095 "tr-TR", NORM_LINGUISTIC_CASING
,
2096 {'I',0}, {0x131,0}, CSTR_GREATER_THAN
, CSTR_LESS_THAN
, TRUE
2099 "tr-TR", NORM_LINGUISTIC_CASING
,
2100 {0x130,0}, {0x131,0}, CSTR_GREATER_THAN
, -1, TRUE
2102 /* with LINGUISTIC_IGNORECASE */
2104 "tr-TR", LINGUISTIC_IGNORECASE
,
2105 {'i',0}, {'I',0}, CSTR_EQUAL
, -1, TRUE
2108 "tr-TR", LINGUISTIC_IGNORECASE
,
2109 {'i',0}, {0x130,0}, CSTR_LESS_THAN
, -1, FALSE
2112 "tr-TR", LINGUISTIC_IGNORECASE
,
2113 {'i',0}, {0x131,0}, CSTR_LESS_THAN
, -1, FALSE
2116 "tr-TR", LINGUISTIC_IGNORECASE
,
2117 {'I',0}, {0x130,0}, CSTR_LESS_THAN
, -1, TRUE
2120 "tr-TR", LINGUISTIC_IGNORECASE
,
2121 {'I',0}, {0x131,0}, CSTR_LESS_THAN
, -1, FALSE
2124 "tr-TR", LINGUISTIC_IGNORECASE
,
2125 {0x130,0}, {0x131,0}, CSTR_GREATER_THAN
, -1, TRUE
2127 /* with NORM_LINGUISTIC_CASING | NORM_IGNORECASE */
2129 "tr-TR", NORM_LINGUISTIC_CASING
| NORM_IGNORECASE
,
2130 {'i',0}, {'I',0}, CSTR_GREATER_THAN
, CSTR_EQUAL
, TRUE
2133 "tr-TR", NORM_LINGUISTIC_CASING
| NORM_IGNORECASE
,
2134 {'i',0}, {0x130,0}, CSTR_EQUAL
, CSTR_LESS_THAN
, FALSE
2137 "tr-TR", NORM_LINGUISTIC_CASING
| NORM_IGNORECASE
,
2138 {'i',0}, {0x131,0}, CSTR_GREATER_THAN
, CSTR_LESS_THAN
, TRUE
2141 "tr-TR", NORM_LINGUISTIC_CASING
| NORM_IGNORECASE
,
2142 {'I',0}, {0x130,0}, CSTR_LESS_THAN
, -1, TRUE
2145 "tr-TR", NORM_LINGUISTIC_CASING
| NORM_IGNORECASE
,
2146 {'I',0}, {0x131,0}, CSTR_EQUAL
, CSTR_LESS_THAN
, TRUE
2149 "tr-TR", NORM_LINGUISTIC_CASING
| NORM_IGNORECASE
,
2150 {0x130,0}, {0x131,0}, CSTR_GREATER_THAN
, -1, TRUE
2152 /* with NORM_LINGUISTIC_CASING | LINGUISTIC_IGNORECASE */
2154 "tr-TR", NORM_LINGUISTIC_CASING
| LINGUISTIC_IGNORECASE
,
2155 {'i',0}, {'I',0}, CSTR_GREATER_THAN
, CSTR_EQUAL
, TRUE
2158 "tr-TR", NORM_LINGUISTIC_CASING
| LINGUISTIC_IGNORECASE
,
2159 {'i',0}, {0x130,0}, CSTR_EQUAL
, CSTR_LESS_THAN
, TRUE
2162 "tr-TR", NORM_LINGUISTIC_CASING
| LINGUISTIC_IGNORECASE
,
2163 {'i',0}, {0x131,0}, CSTR_GREATER_THAN
, CSTR_LESS_THAN
, TRUE
2166 "tr-TR", NORM_LINGUISTIC_CASING
| LINGUISTIC_IGNORECASE
,
2167 {'I',0}, {0x130,0}, CSTR_LESS_THAN
, -1, TRUE
2170 "tr-TR", NORM_LINGUISTIC_CASING
| LINGUISTIC_IGNORECASE
,
2171 {'I',0}, {0x131,0}, CSTR_EQUAL
, CSTR_LESS_THAN
, TRUE
2174 "tr-TR", NORM_LINGUISTIC_CASING
| LINGUISTIC_IGNORECASE
,
2175 {0x130,0}, {0x131,0}, CSTR_GREATER_THAN
, CSTR_LESS_THAN
, TRUE
2179 static void test_CompareStringEx(void)
2181 const char *op
[] = {"ERROR", "CSTR_LESS_THAN", "CSTR_EQUAL", "CSTR_GREATER_THAN"};
2185 /* CompareStringEx is only available on Vista+ */
2186 if (!pCompareStringEx
)
2188 win_skip("CompareStringEx not supported\n");
2192 for (i
= 0; i
< sizeof(comparestringex_tests
)/sizeof(comparestringex_tests
[0]); i
++)
2194 const struct comparestringex_test
*e
= &comparestringex_tests
[i
];
2196 MultiByteToWideChar(CP_ACP
, 0, e
->locale
, -1, locale
, sizeof(locale
)/sizeof(WCHAR
));
2197 ret
= pCompareStringEx(locale
, e
->flags
, e
->first
, -1, e
->second
, -1, NULL
, NULL
, 0);
2198 todo_wine_if (e
->todo
)
2199 ok(ret
== e
->ret
|| broken(ret
== e
->broken
),
2200 "%d: got %s, expected %s\n", i
, op
[ret
], op
[e
->ret
]);
2205 static const DWORD lcmap_invalid_flags
[] = {
2207 LCMAP_HIRAGANA
| LCMAP_KATAKANA
,
2208 LCMAP_HALFWIDTH
| LCMAP_FULLWIDTH
,
2209 LCMAP_TRADITIONAL_CHINESE
| LCMAP_SIMPLIFIED_CHINESE
,
2210 LCMAP_LOWERCASE
| SORT_STRINGSORT
,
2211 LCMAP_UPPERCASE
| NORM_IGNORESYMBOLS
,
2212 LCMAP_LOWERCASE
| NORM_IGNORESYMBOLS
,
2213 LCMAP_UPPERCASE
| NORM_IGNORENONSPACE
,
2214 LCMAP_LOWERCASE
| NORM_IGNORENONSPACE
,
2215 LCMAP_HIRAGANA
| NORM_IGNORENONSPACE
,
2216 LCMAP_HIRAGANA
| NORM_IGNORESYMBOLS
,
2217 LCMAP_HIRAGANA
| LCMAP_SIMPLIFIED_CHINESE
,
2218 LCMAP_HIRAGANA
| LCMAP_TRADITIONAL_CHINESE
,
2219 LCMAP_KATAKANA
| NORM_IGNORENONSPACE
,
2220 LCMAP_KATAKANA
| NORM_IGNORESYMBOLS
,
2221 LCMAP_KATAKANA
| LCMAP_SIMPLIFIED_CHINESE
,
2222 LCMAP_KATAKANA
| LCMAP_TRADITIONAL_CHINESE
,
2223 LCMAP_FULLWIDTH
| NORM_IGNORENONSPACE
,
2224 LCMAP_FULLWIDTH
| NORM_IGNORESYMBOLS
,
2225 LCMAP_FULLWIDTH
| LCMAP_SIMPLIFIED_CHINESE
,
2226 LCMAP_FULLWIDTH
| LCMAP_TRADITIONAL_CHINESE
,
2227 LCMAP_HALFWIDTH
| NORM_IGNORENONSPACE
,
2228 LCMAP_HALFWIDTH
| NORM_IGNORESYMBOLS
,
2229 LCMAP_HALFWIDTH
| LCMAP_SIMPLIFIED_CHINESE
,
2230 LCMAP_HALFWIDTH
| LCMAP_TRADITIONAL_CHINESE
,
2233 static void test_LCMapStringA(void)
2236 char buf
[256], buf2
[256];
2237 static const char upper_case
[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
2238 static const char lower_case
[] = "\tjust! a, test; string 1/*+-.\r\n";
2239 static const char symbols_stripped
[] = "justateststring1";
2241 SetLastError(0xdeadbeef);
2242 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LOCALE_USE_CP_ACP
| LCMAP_LOWERCASE
,
2243 lower_case
, -1, buf
, sizeof(buf
));
2244 ok(ret
== lstrlenA(lower_case
) + 1,
2245 "ret %d, error %d, expected value %d\n",
2246 ret
, GetLastError(), lstrlenA(lower_case
) + 1);
2247 ok(!memcmp(buf
, lower_case
, ret
), "LCMapStringA should return %s, but not %s\n", lower_case
, buf
);
2249 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_LOWERCASE
| LCMAP_UPPERCASE
,
2250 upper_case
, -1, buf
, sizeof(buf
));
2251 ok(!ret
, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
2252 ok(GetLastError() == ERROR_INVALID_FLAGS
,
2253 "unexpected error code %d\n", GetLastError());
2255 /* test invalid flag combinations */
2256 for (i
= 0; i
< sizeof(lcmap_invalid_flags
)/sizeof(lcmap_invalid_flags
[0]); i
++) {
2257 lstrcpyA(buf
, "foo");
2258 SetLastError(0xdeadbeef);
2259 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, lcmap_invalid_flags
[i
],
2260 lower_case
, -1, buf
, sizeof(buf
));
2261 ok(GetLastError() == ERROR_INVALID_FLAGS
,
2262 "LCMapStringA (flag %08x) unexpected error code %d\n",
2263 lcmap_invalid_flags
[i
], GetLastError());
2264 ok(!ret
, "LCMapStringA (flag %08x) should return 0, got %d\n",
2265 lcmap_invalid_flags
[i
], ret
);
2268 /* test LCMAP_LOWERCASE */
2269 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_LOWERCASE
,
2270 upper_case
, -1, buf
, sizeof(buf
));
2271 ok(ret
== lstrlenA(upper_case
) + 1,
2272 "ret %d, error %d, expected value %d\n",
2273 ret
, GetLastError(), lstrlenA(upper_case
) + 1);
2274 ok(!lstrcmpA(buf
, lower_case
), "LCMapStringA should return %s, but not %s\n", lower_case
, buf
);
2276 /* test LCMAP_UPPERCASE */
2277 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_UPPERCASE
,
2278 lower_case
, -1, buf
, sizeof(buf
));
2279 ok(ret
== lstrlenA(lower_case
) + 1,
2280 "ret %d, error %d, expected value %d\n",
2281 ret
, GetLastError(), lstrlenA(lower_case
) + 1);
2282 ok(!lstrcmpA(buf
, upper_case
), "LCMapStringA should return %s, but not %s\n", upper_case
, buf
);
2284 /* test buffer overflow */
2285 SetLastError(0xdeadbeef);
2286 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_UPPERCASE
,
2287 lower_case
, -1, buf
, 4);
2288 ok(!ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
2289 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret
);
2291 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
2292 lstrcpyA(buf
, lower_case
);
2293 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_UPPERCASE
,
2294 buf
, -1, buf
, sizeof(buf
));
2295 if (!ret
) /* Win9x */
2296 trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
2299 ok(ret
== lstrlenA(lower_case
) + 1,
2300 "ret %d, error %d, expected value %d\n",
2301 ret
, GetLastError(), lstrlenA(lower_case
) + 1);
2302 ok(!lstrcmpA(buf
, upper_case
), "LCMapStringA should return %s, but not %s\n", upper_case
, buf
);
2304 lstrcpyA(buf
, upper_case
);
2305 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_LOWERCASE
,
2306 buf
, -1, buf
, sizeof(buf
));
2307 if (!ret
) /* Win9x */
2308 trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
2311 ok(ret
== lstrlenA(upper_case
) + 1,
2312 "ret %d, error %d, expected value %d\n",
2313 ret
, GetLastError(), lstrlenA(lower_case
) + 1);
2314 ok(!lstrcmpA(buf
, lower_case
), "LCMapStringA should return %s, but not %s\n", lower_case
, buf
);
2317 /* otherwise src == dst should fail */
2318 SetLastError(0xdeadbeef);
2319 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
| LCMAP_UPPERCASE
,
2320 buf
, 10, buf
, sizeof(buf
));
2321 ok(GetLastError() == ERROR_INVALID_FLAGS
/* NT */ ||
2322 GetLastError() == ERROR_INVALID_PARAMETER
/* Win9x */,
2323 "unexpected error code %d\n", GetLastError());
2324 ok(!ret
, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
2326 /* test whether '\0' is always appended */
2327 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
,
2328 upper_case
, -1, buf
, sizeof(buf
));
2329 ok(ret
, "LCMapStringA must succeed\n");
2330 ok(buf
[ret
-1] == 0, "LCMapStringA not null-terminated\n");
2331 ret2
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
,
2332 upper_case
, lstrlenA(upper_case
), buf2
, sizeof(buf2
));
2333 ok(ret2
, "LCMapStringA must succeed\n");
2334 ok(buf2
[ret2
-1] == 0, "LCMapStringA not null-terminated\n" );
2335 ok(ret
== ret2
, "lengths of sort keys must be equal\n");
2336 ok(!lstrcmpA(buf
, buf2
), "sort keys must be equal\n");
2338 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
2339 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
| NORM_IGNORECASE
,
2340 upper_case
, -1, buf
, sizeof(buf
));
2341 ok(ret
, "LCMapStringA must succeed\n");
2342 ret2
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
,
2343 lower_case
, -1, buf2
, sizeof(buf2
));
2344 ok(ret2
, "LCMapStringA must succeed\n");
2345 ok(ret
== ret2
, "lengths of sort keys must be equal\n");
2346 ok(!lstrcmpA(buf
, buf2
), "sort keys must be equal\n");
2348 /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
2349 results from plain LCMAP_SORTKEY on Vista */
2351 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
2352 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
| NORM_IGNORESYMBOLS
,
2353 lower_case
, -1, buf
, sizeof(buf
));
2354 ok(ret
, "LCMapStringA must succeed\n");
2355 ret2
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
,
2356 symbols_stripped
, -1, buf2
, sizeof(buf2
));
2357 ok(ret2
, "LCMapStringA must succeed\n");
2358 ok(ret
== ret2
, "lengths of sort keys must be equal\n");
2359 ok(!lstrcmpA(buf
, buf2
), "sort keys must be equal\n");
2361 /* test NORM_IGNORENONSPACE */
2362 lstrcpyA(buf
, "foo");
2363 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, NORM_IGNORENONSPACE
,
2364 lower_case
, -1, buf
, sizeof(buf
));
2365 ok(ret
== lstrlenA(lower_case
) + 1, "LCMapStringA should return %d, ret = %d\n",
2366 lstrlenA(lower_case
) + 1, ret
);
2367 ok(!lstrcmpA(buf
, lower_case
), "LCMapStringA should return %s, but not %s\n", lower_case
, buf
);
2369 /* test NORM_IGNORESYMBOLS */
2370 lstrcpyA(buf
, "foo");
2371 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, NORM_IGNORESYMBOLS
,
2372 lower_case
, -1, buf
, sizeof(buf
));
2373 ok(ret
== lstrlenA(symbols_stripped
) + 1, "LCMapStringA should return %d, ret = %d\n",
2374 lstrlenA(symbols_stripped
) + 1, ret
);
2375 ok(!lstrcmpA(buf
, symbols_stripped
), "LCMapStringA should return %s, but not %s\n", lower_case
, buf
);
2377 /* test NORM_IGNORESYMBOLS | NORM_IGNORENONSPACE */
2378 lstrcpyA(buf
, "foo");
2379 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, NORM_IGNORESYMBOLS
| NORM_IGNORENONSPACE
,
2380 lower_case
, -1, buf
, sizeof(buf
));
2381 ok(ret
== lstrlenA(symbols_stripped
) + 1, "LCMapStringA should return %d, ret = %d\n",
2382 lstrlenA(symbols_stripped
) + 1, ret
);
2383 ok(!lstrcmpA(buf
, symbols_stripped
), "LCMapStringA should return %s, but not %s\n", lower_case
, buf
);
2385 /* test srclen = 0 */
2386 SetLastError(0xdeadbeef);
2387 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, 0, upper_case
, 0, buf
, sizeof(buf
));
2388 ok(!ret
, "LCMapStringA should fail with srclen = 0\n");
2389 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
2390 "unexpected error code %d\n", GetLastError());
2393 typedef INT (*lcmapstring_wrapper
)(DWORD
, LPCWSTR
, INT
, LPWSTR
, INT
);
2395 static void test_lcmapstring_unicode(lcmapstring_wrapper func_ptr
, const char *func_name
)
2397 static const WCHAR japanese_text
[] = {
2398 0x3044, 0x309d, 0x3084, 0x3001, 0x30a4, 0x30fc, 0x30cf,
2399 0x30c8, 0x30fc, 0x30f4, 0x30a9, 0x306e, 0x2026, 0
2401 static const WCHAR hiragana_text
[] = {
2402 0x3044, 0x309d, 0x3084, 0x3001, 0x3044, 0x30fc, 0x306f,
2403 0x3068, 0x30fc, 0x3094, 0x3049, 0x306e, 0x2026, 0
2405 static const WCHAR katakana_text
[] = {
2406 0x30a4, 0x30fd, 0x30e4, 0x3001, 0x30a4, 0x30fc, 0x30cf,
2407 0x30c8, 0x30fc, 0x30f4, 0x30a9, 0x30ce, 0x2026, 0
2409 static const WCHAR halfwidth_text
[] = {
2410 0x3044, 0x309d, 0x3084, 0xff64, 0xff72, 0xff70, 0xff8a,
2411 0xff84, 0xff70, 0xff73, 0xff9e, 0xff6b, 0x306e, 0x2026, 0
2414 WCHAR buf
[256], buf2
[256];
2415 char *p_buf
= (char *)buf
, *p_buf2
= (char *)buf2
;
2417 /* LCMAP_LOWERCASE | LCMAP_UPPERCASE makes LCMAP_TITLECASE, so it's valid now. */
2418 ret
= func_ptr(LCMAP_LOWERCASE
| LCMAP_UPPERCASE
,
2419 lower_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
2420 todo_wine
ok(ret
== lstrlenW(title_case
) + 1 || broken(!ret
),
2421 "%s ret %d, error %d, expected value %d\n", func_name
,
2422 ret
, GetLastError(), lstrlenW(title_case
) + 1);
2423 todo_wine
ok(lstrcmpW(buf
, title_case
) == 0 || broken(!ret
),
2424 "Expected title case string\n");
2426 /* test invalid flag combinations */
2427 for (i
= 0; i
< sizeof(lcmap_invalid_flags
)/sizeof(lcmap_invalid_flags
[0]); i
++) {
2428 lstrcpyW(buf
, fooW
);
2429 SetLastError(0xdeadbeef);
2430 ret
= func_ptr(lcmap_invalid_flags
[i
],
2431 lower_case
, -1, buf
, sizeof(buf
));
2432 ok(GetLastError() == ERROR_INVALID_FLAGS
,
2433 "%s (flag %08x) unexpected error code %d\n",
2434 func_name
, lcmap_invalid_flags
[i
], GetLastError());
2435 ok(!ret
, "%s (flag %08x) should return 0, got %d\n",
2436 func_name
, lcmap_invalid_flags
[i
], ret
);
2439 /* test LCMAP_LOWERCASE */
2440 ret
= func_ptr(LCMAP_LOWERCASE
,
2441 upper_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
2442 ok(ret
== lstrlenW(upper_case
) + 1, "%s ret %d, error %d, expected value %d\n", func_name
,
2443 ret
, GetLastError(), lstrlenW(upper_case
) + 1);
2444 ok(!lstrcmpW(buf
, lower_case
), "%s string compare mismatch\n", func_name
);
2446 /* test LCMAP_UPPERCASE */
2447 ret
= func_ptr(LCMAP_UPPERCASE
,
2448 lower_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
2449 ok(ret
== lstrlenW(lower_case
) + 1, "%s ret %d, error %d, expected value %d\n", func_name
,
2450 ret
, GetLastError(), lstrlenW(lower_case
) + 1);
2451 ok(!lstrcmpW(buf
, upper_case
), "%s string compare mismatch\n", func_name
);
2453 /* test LCMAP_HIRAGANA */
2454 ret
= func_ptr(LCMAP_HIRAGANA
,
2455 japanese_text
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
2456 ok(ret
== lstrlenW(hiragana_text
) + 1, "%s ret %d, error %d, expected value %d\n", func_name
,
2457 ret
, GetLastError(), lstrlenW(hiragana_text
) + 1);
2458 ok(!lstrcmpW(buf
, hiragana_text
), "%s string compare mismatch\n", func_name
);
2460 buf
[0] = 0x30f5; /* KATAKANA LETTER SMALL KA */
2461 ret
= func_ptr(LCMAP_HIRAGANA
, buf
, 1, buf2
, 1);
2462 ok(ret
== 1, "%s ret %d, error %d, expected value 1\n", func_name
,
2463 ret
, GetLastError());
2464 /* U+3095: HIRAGANA LETTER SMALL KA was added in Unicode 3.2 */
2465 ok(buf2
[0] == 0x3095 || broken(buf2
[0] == 0x30f5 /* Vista and earlier versions */),
2466 "%s expected %04x, got %04x\n", func_name
, 0x3095, buf2
[0]);
2468 /* test LCMAP_KATAKANA | LCMAP_LOWERCASE */
2469 ret
= func_ptr(LCMAP_KATAKANA
| LCMAP_LOWERCASE
,
2470 japanese_text
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
2471 ok(ret
== lstrlenW(katakana_text
) + 1, "%s ret %d, error %d, expected value %d\n", func_name
,
2472 ret
, GetLastError(), lstrlenW(katakana_text
) + 1);
2473 ok(!lstrcmpW(buf
, katakana_text
), "%s string compare mismatch\n", func_name
);
2475 /* test LCMAP_FULLWIDTH */
2476 ret
= func_ptr(LCMAP_FULLWIDTH
,
2477 halfwidth_text
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
2478 ok(ret
== lstrlenW(japanese_text
) + 1, "%s ret %d, error %d, expected value %d\n", func_name
,
2479 ret
, GetLastError(), lstrlenW(japanese_text
) + 1);
2480 ok(!lstrcmpW(buf
, japanese_text
), "%s string compare mismatch\n", func_name
);
2482 ret2
= func_ptr(LCMAP_FULLWIDTH
, halfwidth_text
, -1, NULL
, 0);
2483 ok(ret
== ret2
, "%s ret %d, expected value %d\n", func_name
, ret2
, ret
);
2485 /* test LCMAP_FULLWIDTH | LCMAP_HIRAGANA
2486 (half-width katakana is converted into full-wdith hiragana) */
2487 ret
= func_ptr(LCMAP_FULLWIDTH
| LCMAP_HIRAGANA
,
2488 halfwidth_text
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
2489 ok(ret
== lstrlenW(hiragana_text
) + 1, "%s ret %d, error %d, expected value %d\n", func_name
,
2490 ret
, GetLastError(), lstrlenW(hiragana_text
) + 1);
2491 ok(!lstrcmpW(buf
, hiragana_text
), "%s string compare mismatch\n", func_name
);
2493 ret2
= func_ptr(LCMAP_FULLWIDTH
| LCMAP_HIRAGANA
, halfwidth_text
, -1, NULL
, 0);
2494 ok(ret
== ret2
, "%s ret %d, expected value %d\n", func_name
, ret
, ret2
);
2496 /* test LCMAP_HALFWIDTH */
2497 ret
= func_ptr(LCMAP_HALFWIDTH
,
2498 japanese_text
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
2499 ok(ret
== lstrlenW(halfwidth_text
) + 1, "%s ret %d, error %d, expected value %d\n", func_name
,
2500 ret
, GetLastError(), lstrlenW(halfwidth_text
) + 1);
2501 ok(!lstrcmpW(buf
, halfwidth_text
), "%s string compare mismatch\n", func_name
);
2503 ret2
= func_ptr(LCMAP_HALFWIDTH
, japanese_text
, -1, NULL
, 0);
2504 ok(ret
== ret2
, "%s ret %d, expected value %d\n", func_name
, ret
, ret2
);
2506 /* test buffer overflow */
2507 SetLastError(0xdeadbeef);
2508 ret
= func_ptr(LCMAP_UPPERCASE
,
2509 lower_case
, -1, buf
, 4);
2510 ok(!ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
2511 "%s should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", func_name
, ret
);
2513 /* KATAKANA LETTER GA (U+30AC) is converted into two half-width characters.
2514 Thus, it requires two WCHARs. */
2516 SetLastError(0xdeadbeef);
2517 ret
= func_ptr(LCMAP_HALFWIDTH
, buf
, 1, buf2
, 1);
2518 ok(!ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
2519 "%s should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", func_name
, ret
);
2521 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
2522 lstrcpyW(buf
, lower_case
);
2523 ret
= func_ptr(LCMAP_UPPERCASE
,
2524 buf
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
2525 ok(ret
== lstrlenW(lower_case
) + 1, "%s ret %d, error %d, expected value %d\n", func_name
,
2526 ret
, GetLastError(), lstrlenW(lower_case
) + 1);
2527 ok(!lstrcmpW(buf
, upper_case
), "%s string compare mismatch\n", func_name
);
2529 lstrcpyW(buf
, upper_case
);
2530 ret
= func_ptr(LCMAP_LOWERCASE
,
2531 buf
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
2532 ok(ret
== lstrlenW(upper_case
) + 1, "%s ret %d, error %d, expected value %d\n", func_name
,
2533 ret
, GetLastError(), lstrlenW(lower_case
) + 1);
2534 ok(!lstrcmpW(buf
, lower_case
), "%s string compare mismatch\n", func_name
);
2536 /* otherwise src == dst should fail */
2537 SetLastError(0xdeadbeef);
2538 ret
= func_ptr(LCMAP_SORTKEY
| LCMAP_UPPERCASE
,
2539 buf
, 10, buf
, sizeof(buf
));
2540 ok(GetLastError() == ERROR_INVALID_FLAGS
/* NT */ ||
2541 GetLastError() == ERROR_INVALID_PARAMETER
/* Win7+ */,
2542 "%s unexpected error code %d\n", func_name
, GetLastError());
2543 ok(!ret
, "%s src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n", func_name
);
2545 /* test whether '\0' is always appended */
2546 ret
= func_ptr(LCMAP_SORTKEY
,
2547 upper_case
, -1, buf
, sizeof(buf
));
2548 ok(ret
, "%s func_ptr must succeed\n", func_name
);
2549 ret2
= func_ptr(LCMAP_SORTKEY
,
2550 upper_case
, lstrlenW(upper_case
), buf2
, sizeof(buf2
));
2551 ok(ret
, "%s func_ptr must succeed\n", func_name
);
2552 ok(ret
== ret2
, "%s lengths of sort keys must be equal\n", func_name
);
2553 ok(!lstrcmpA(p_buf
, p_buf2
), "%s sort keys must be equal\n", func_name
);
2555 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
2556 ret
= func_ptr(LCMAP_SORTKEY
| NORM_IGNORECASE
,
2557 upper_case
, -1, buf
, sizeof(buf
));
2558 ok(ret
, "%s func_ptr must succeed\n", func_name
);
2559 ret2
= func_ptr(LCMAP_SORTKEY
,
2560 lower_case
, -1, buf2
, sizeof(buf2
));
2561 ok(ret2
, "%s func_ptr must succeed\n", func_name
);
2562 ok(ret
== ret2
, "%s lengths of sort keys must be equal\n", func_name
);
2563 ok(!lstrcmpA(p_buf
, p_buf2
), "%s sort keys must be equal\n", func_name
);
2565 /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
2566 results from plain LCMAP_SORTKEY on Vista */
2568 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
2569 ret
= func_ptr(LCMAP_SORTKEY
| NORM_IGNORESYMBOLS
,
2570 lower_case
, -1, buf
, sizeof(buf
));
2571 ok(ret
, "%s func_ptr must succeed\n", func_name
);
2572 ret2
= func_ptr(LCMAP_SORTKEY
,
2573 symbols_stripped
, -1, buf2
, sizeof(buf2
));
2574 ok(ret2
, "%s func_ptr must succeed\n", func_name
);
2575 ok(ret
== ret2
, "%s lengths of sort keys must be equal\n", func_name
);
2576 ok(!lstrcmpA(p_buf
, p_buf2
), "%s sort keys must be equal\n", func_name
);
2578 /* test NORM_IGNORENONSPACE */
2579 lstrcpyW(buf
, fooW
);
2580 ret
= func_ptr(NORM_IGNORENONSPACE
,
2581 lower_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
2582 ok(ret
== lstrlenW(lower_case
) + 1, "%s func_ptr should return %d, ret = %d\n", func_name
,
2583 lstrlenW(lower_case
) + 1, ret
);
2584 ok(!lstrcmpW(buf
, lower_case
), "%s string comparison mismatch\n", func_name
);
2586 /* test NORM_IGNORESYMBOLS */
2587 lstrcpyW(buf
, fooW
);
2588 ret
= func_ptr(NORM_IGNORESYMBOLS
,
2589 lower_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
2590 ok(ret
== lstrlenW(symbols_stripped
) + 1, "%s func_ptr should return %d, ret = %d\n", func_name
,
2591 lstrlenW(symbols_stripped
) + 1, ret
);
2592 ok(!lstrcmpW(buf
, symbols_stripped
), "%s string comparison mismatch\n", func_name
);
2594 /* test NORM_IGNORESYMBOLS | NORM_IGNORENONSPACE */
2595 lstrcpyW(buf
, fooW
);
2596 ret
= func_ptr(NORM_IGNORESYMBOLS
| NORM_IGNORENONSPACE
,
2597 lower_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
2598 ok(ret
== lstrlenW(symbols_stripped
) + 1, "%s func_ptr should return %d, ret = %d\n", func_name
,
2599 lstrlenW(symbols_stripped
) + 1, ret
);
2600 ok(!lstrcmpW(buf
, symbols_stripped
), "%s string comparison mismatch\n", func_name
);
2602 /* test srclen = 0 */
2603 SetLastError(0xdeadbeef);
2604 ret
= func_ptr(0, upper_case
, 0, buf
, sizeof(buf
)/sizeof(WCHAR
));
2605 ok(!ret
, "%s func_ptr should fail with srclen = 0\n", func_name
);
2606 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
2607 "%s unexpected error code %d\n", func_name
, GetLastError());
2610 static INT
LCMapStringW_wrapper(DWORD flags
, LPCWSTR src
, INT srclen
, LPWSTR dst
, INT dstlen
)
2612 return LCMapStringW(LOCALE_USER_DEFAULT
, flags
, src
, srclen
, dst
, dstlen
);
2615 static void test_LCMapStringW(void)
2620 trace("testing LCMapStringW\n");
2622 SetLastError(0xdeadbeef);
2623 ret
= LCMapStringW((LCID
)-1, LCMAP_LOWERCASE
, upper_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
2625 ok(!ret
, "LCMapStringW should fail with bad lcid\n");
2626 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "unexpected error code %d\n", GetLastError());
2629 test_lcmapstring_unicode(LCMapStringW_wrapper
, "LCMapStringW:");
2632 static INT
LCMapStringEx_wrapper(DWORD flags
, LPCWSTR src
, INT srclen
, LPWSTR dst
, INT dstlen
)
2634 return pLCMapStringEx(LOCALE_NAME_USER_DEFAULT
, flags
, src
, srclen
, dst
, dstlen
, NULL
, NULL
, 0);
2637 static void test_LCMapStringEx(void)
2642 if (!pLCMapStringEx
)
2644 win_skip( "LCMapStringEx not available\n" );
2648 trace("testing LCMapStringEx\n");
2650 SetLastError(0xdeadbeef);
2651 ret
= pLCMapStringEx(invalidW
, LCMAP_LOWERCASE
,
2652 upper_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
), NULL
, NULL
, 0);
2654 ok(!ret
, "LCMapStringEx should fail with bad locale name\n");
2655 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "unexpected error code %d\n", GetLastError());
2658 /* test reserved parameters */
2659 ret
= pLCMapStringEx(LOCALE_NAME_USER_DEFAULT
, LCMAP_LOWERCASE
,
2660 upper_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
), NULL
, NULL
, 1);
2661 ok(ret
== lstrlenW(upper_case
) + 1, "ret %d, error %d, expected value %d\n",
2662 ret
, GetLastError(), lstrlenW(upper_case
) + 1);
2663 ok(!lstrcmpW(buf
, lower_case
), "string compare mismatch\n");
2665 ret
= pLCMapStringEx(LOCALE_NAME_USER_DEFAULT
, LCMAP_LOWERCASE
,
2666 upper_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
), NULL
, (void*)1, 0);
2667 ok(ret
== lstrlenW(upper_case
) + 1, "ret %d, error %d, expected value %d\n",
2668 ret
, GetLastError(), lstrlenW(upper_case
) + 1);
2669 ok(!lstrcmpW(buf
, lower_case
), "string compare mismatch\n");
2671 /* crashes on native */
2673 ret
= pLCMapStringEx(LOCALE_NAME_USER_DEFAULT
, LCMAP_LOWERCASE
,
2674 upper_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
), (void*)1, NULL
, 0);
2676 test_lcmapstring_unicode(LCMapStringEx_wrapper
, "LCMapStringEx:");
2679 struct neutralsublang_name_t
{
2686 static const struct neutralsublang_name_t neutralsublang_names
[] = {
2687 { {'a','r',0}, {'a','r','-','S','A',0}, MAKELCID(MAKELANGID(LANG_ARABIC
, SUBLANG_ARABIC_SAUDI_ARABIA
), SORT_DEFAULT
) },
2688 { {'a','z',0}, {'a','z','-','L','a','t','n','-','A','Z',0}, MAKELCID(MAKELANGID(LANG_AZERI
, SUBLANG_AZERI_LATIN
), SORT_DEFAULT
) },
2689 { {'d','e',0}, {'d','e','-','D','E',0}, MAKELCID(MAKELANGID(LANG_GERMAN
, SUBLANG_GERMAN
), SORT_DEFAULT
) },
2690 { {'e','n',0}, {'e','n','-','U','S',0}, MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
) },
2691 { {'e','s',0}, {'e','s','-','E','S',0}, MAKELCID(MAKELANGID(LANG_SPANISH
, SUBLANG_SPANISH_MODERN
), SORT_DEFAULT
) },
2692 { {'g','a',0}, {'g','a','-','I','E',0}, MAKELCID(MAKELANGID(LANG_IRISH
, SUBLANG_IRISH_IRELAND
), SORT_DEFAULT
) },
2693 { {'i','t',0}, {'i','t','-','I','T',0}, MAKELCID(MAKELANGID(LANG_ITALIAN
, SUBLANG_ITALIAN
), SORT_DEFAULT
) },
2694 { {'m','s',0}, {'m','s','-','M','Y',0}, MAKELCID(MAKELANGID(LANG_MALAY
, SUBLANG_MALAY_MALAYSIA
), SORT_DEFAULT
) },
2695 { {'n','l',0}, {'n','l','-','N','L',0}, MAKELCID(MAKELANGID(LANG_DUTCH
, SUBLANG_DUTCH
), SORT_DEFAULT
) },
2696 { {'p','t',0}, {'p','t','-','B','R',0}, MAKELCID(MAKELANGID(LANG_PORTUGUESE
, SUBLANG_PORTUGUESE_BRAZILIAN
), SORT_DEFAULT
) },
2697 { {'s','r',0}, {'s','r','-','L','a','t','n','-','R','S',0}, MAKELCID(MAKELANGID(LANG_SERBIAN
, SUBLANG_SERBIAN_SERBIA_LATIN
), SORT_DEFAULT
), 1 },
2698 { {'s','v',0}, {'s','v','-','S','E',0}, MAKELCID(MAKELANGID(LANG_SWEDISH
, SUBLANG_SWEDISH
), SORT_DEFAULT
) },
2699 { {'u','z',0}, {'u','z','-','L','a','t','n','-','U','Z',0}, MAKELCID(MAKELANGID(LANG_UZBEK
, SUBLANG_UZBEK_LATIN
), SORT_DEFAULT
) },
2700 { {'z','h',0}, {'z','h','-','C','N',0}, MAKELCID(MAKELANGID(LANG_CHINESE
, SUBLANG_CHINESE_SIMPLIFIED
), SORT_DEFAULT
) },
2704 static void test_LocaleNameToLCID(void)
2708 WCHAR buffer
[LOCALE_NAME_MAX_LENGTH
];
2709 static const WCHAR enW
[] = {'e','n',0};
2710 static const WCHAR esesW
[] = {'e','s','-','e','s',0};
2711 static const WCHAR zhHansW
[] = {'z','h','-','H','a','n','s',0};
2712 static const WCHAR zhhansW
[] = {'z','h','-','h','a','n','s',0};
2713 static const WCHAR zhHantW
[] = {'z','h','-','H','a','n','t',0};
2714 static const WCHAR zhhantW
[] = {'z','h','-','h','a','n','t',0};
2715 static const WCHAR zhcnW
[] = {'z','h','-','C','N',0};
2716 static const WCHAR zhhkW
[] = {'z','h','-','H','K',0};
2718 if (!pLocaleNameToLCID
)
2720 win_skip( "LocaleNameToLCID not available\n" );
2726 SetLastError(0xdeadbeef);
2727 lcid
= pLocaleNameToLCID(LOCALE_NAME_USER_DEFAULT
, 0);
2728 ok(lcid
== GetUserDefaultLCID() || broken(GetLastError() == ERROR_INVALID_PARAMETER
/* Vista */),
2729 "Expected lcid == %08x, got %08x, error %d\n", GetUserDefaultLCID(), lcid
, GetLastError());
2730 ret
= pLCIDToLocaleName(lcid
, buffer
, LOCALE_NAME_MAX_LENGTH
, 0);
2731 ok(ret
> 0, "Expected ret > 0, got %d, error %d\n", ret
, GetLastError());
2732 trace("%08x, %s\n", lcid
, wine_dbgstr_w(buffer
));
2735 SetLastError(0xdeadbeef);
2736 lcid
= pLocaleNameToLCID(LOCALE_NAME_SYSTEM_DEFAULT
, 0);
2737 ok(!lcid
&& GetLastError() == ERROR_INVALID_PARAMETER
,
2738 "Expected lcid == 0, got %08x, error %d\n", lcid
, GetLastError());
2739 ret
= pLCIDToLocaleName(lcid
, buffer
, LOCALE_NAME_MAX_LENGTH
, 0);
2740 ok(ret
> 0, "Expected ret > 0, got %d, error %d\n", ret
, GetLastError());
2741 trace("%08x, %s\n", lcid
, wine_dbgstr_w(buffer
));
2744 SetLastError(0xdeadbeef);
2745 lcid
= pLocaleNameToLCID(LOCALE_NAME_INVARIANT
, 0);
2746 ok(lcid
== 0x7F, "Expected lcid = 0x7F, got %08x, error %d\n", lcid
, GetLastError());
2747 ret
= pLCIDToLocaleName(lcid
, buffer
, LOCALE_NAME_MAX_LENGTH
, 0);
2748 ok(ret
> 0, "Expected ret > 0, got %d, error %d\n", ret
, GetLastError());
2749 trace("%08x, %s\n", lcid
, wine_dbgstr_w(buffer
));
2752 SetLastError(0xdeadbeef);
2753 lcid
= pLocaleNameToLCID(invalidW
, 0);
2754 ok(!lcid
&& GetLastError() == ERROR_INVALID_PARAMETER
,
2755 "Expected lcid == 0, got %08x, error %d\n", lcid
, GetLastError());
2758 lcid
= pLocaleNameToLCID(esesW
, 0);
2759 ok(lcid
== MAKELCID(MAKELANGID(LANG_SPANISH
, SUBLANG_SPANISH_MODERN
), SORT_DEFAULT
), "Got wrong lcid for es-es: 0x%x\n", lcid
);
2761 /* english neutral name */
2762 lcid
= pLocaleNameToLCID(enW
, 0);
2763 ok(lcid
== MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
) ||
2764 broken(lcid
== 0) /* Vista */, "got 0x%04x\n", lcid
);
2767 const struct neutralsublang_name_t
*ptr
= neutralsublang_names
;
2771 lcid
= pLocaleNameToLCID(ptr
->name
, 0);
2772 todo_wine_if (ptr
->todo
)
2773 ok(lcid
== ptr
->lcid
, "%s: got wrong lcid 0x%04x, expected 0x%04x\n",
2774 wine_dbgstr_w(ptr
->name
), lcid
, ptr
->lcid
);
2777 ret
= pLCIDToLocaleName(lcid
, buffer
, sizeof(buffer
)/sizeof(WCHAR
), 0);
2778 ok(ret
> 0, "%s: got %d\n", wine_dbgstr_w(ptr
->name
), ret
);
2779 ok(!lstrcmpW(ptr
->sname
, buffer
), "%s: got wrong locale name %s\n",
2780 wine_dbgstr_w(ptr
->name
), wine_dbgstr_w(buffer
));
2786 lcid
= pLocaleNameToLCID(zhHantW
, 0);
2787 todo_wine
ok(lcid
== MAKELCID(MAKELANGID(LANG_CHINESE
, SUBLANG_CHINESE_HONGKONG
), SORT_DEFAULT
),
2788 "%s: got wrong lcid 0x%04x\n", wine_dbgstr_w(zhHantW
), lcid
);
2789 ret
= pLCIDToLocaleName(lcid
, buffer
, sizeof(buffer
)/sizeof(WCHAR
), 0);
2790 ok(ret
> 0, "%s: got %d\n", wine_dbgstr_w(zhHantW
), ret
);
2791 todo_wine
ok(!lstrcmpW(zhhkW
, buffer
), "%s: got wrong locale name %s\n",
2792 wine_dbgstr_w(zhHantW
), wine_dbgstr_w(buffer
));
2795 lcid
= pLocaleNameToLCID(zhhantW
, 0);
2796 todo_wine
ok(lcid
== MAKELCID(MAKELANGID(LANG_CHINESE
, SUBLANG_CHINESE_HONGKONG
), SORT_DEFAULT
),
2797 "%s: got wrong lcid 0x%04x\n", wine_dbgstr_w(zhhantW
),
2798 MAKELCID(MAKELANGID(LANG_CHINESE
, SUBLANG_CHINESE_HONGKONG
), SORT_DEFAULT
));
2799 ret
= pLCIDToLocaleName(lcid
, buffer
, sizeof(buffer
)/sizeof(WCHAR
), 0);
2800 ok(ret
> 0, "%s: got %d\n", wine_dbgstr_w(zhhantW
), ret
);
2801 todo_wine
ok(!lstrcmpW(zhhkW
, buffer
), "%s: got wrong locale name %s\n",
2802 wine_dbgstr_w(zhhantW
), wine_dbgstr_w(buffer
));
2805 lcid
= pLocaleNameToLCID(zhHansW
, 0);
2806 todo_wine
ok(lcid
== MAKELCID(MAKELANGID(LANG_CHINESE_SIMPLIFIED
, SUBLANG_CHINESE_SIMPLIFIED
), SORT_DEFAULT
),
2807 "%s: got wrong lcid 0x%04x\n", wine_dbgstr_w(zhHansW
), lcid
);
2808 ret
= pLCIDToLocaleName(lcid
, buffer
, sizeof(buffer
)/sizeof(WCHAR
), 0);
2809 ok(ret
> 0, "%s: got %d\n", wine_dbgstr_w(zhHansW
), ret
);
2810 todo_wine
ok(!lstrcmpW(zhcnW
, buffer
), "%s: got wrong locale name %s\n",
2811 wine_dbgstr_w(zhHansW
), wine_dbgstr_w(buffer
));
2814 lcid
= pLocaleNameToLCID(zhhansW
, 0);
2815 todo_wine
ok(lcid
== MAKELCID(MAKELANGID(LANG_CHINESE_SIMPLIFIED
, SUBLANG_CHINESE_SIMPLIFIED
), SORT_DEFAULT
),
2816 "%s: got wrong lcid 0x%04x\n", wine_dbgstr_w(zhhansW
),
2817 MAKELCID(MAKELANGID(LANG_CHINESE_SIMPLIFIED
, SUBLANG_CHINESE_SIMPLIFIED
), SORT_DEFAULT
));
2818 ret
= pLCIDToLocaleName(lcid
, buffer
, sizeof(buffer
)/sizeof(WCHAR
), 0);
2819 ok(ret
> 0, "%s: got %d\n", wine_dbgstr_w(zhhansW
), ret
);
2820 todo_wine
ok(!lstrcmpW(zhcnW
, buffer
), "%s: got wrong locale name %s\n",
2821 wine_dbgstr_w(zhhansW
), wine_dbgstr_w(buffer
));
2825 /* this requires collation table patch to make it MS compatible */
2826 static const char * const strings_sorted
[] =
2858 static const char * const strings
[] =
2890 static int compare_string1(const void *e1
, const void *e2
)
2892 const char *s1
= *(const char *const *)e1
;
2893 const char *s2
= *(const char *const *)e2
;
2895 return lstrcmpA(s1
, s2
);
2898 static int compare_string2(const void *e1
, const void *e2
)
2900 const char *s1
= *(const char *const *)e1
;
2901 const char *s2
= *(const char *const *)e2
;
2903 return CompareStringA(0, 0, s1
, -1, s2
, -1) - 2;
2906 static int compare_string3(const void *e1
, const void *e2
)
2908 const char *s1
= *(const char *const *)e1
;
2909 const char *s2
= *(const char *const *)e2
;
2910 char key1
[256], key2
[256];
2912 LCMapStringA(0, LCMAP_SORTKEY
, s1
, -1, key1
, sizeof(key1
));
2913 LCMapStringA(0, LCMAP_SORTKEY
, s2
, -1, key2
, sizeof(key2
));
2914 return strcmp(key1
, key2
);
2917 static void test_sorting(void)
2920 char **str_buf
= (char **)buf
;
2923 assert(sizeof(buf
) >= sizeof(strings
));
2925 /* 1. sort using lstrcmpA */
2926 memcpy(buf
, strings
, sizeof(strings
));
2927 qsort(buf
, sizeof(strings
)/sizeof(strings
[0]), sizeof(strings
[0]), compare_string1
);
2928 for (i
= 0; i
< sizeof(strings
)/sizeof(strings
[0]); i
++)
2930 ok(!strcmp(strings_sorted
[i
], str_buf
[i
]),
2931 "qsort using lstrcmpA failed for element %d\n", i
);
2933 /* 2. sort using CompareStringA */
2934 memcpy(buf
, strings
, sizeof(strings
));
2935 qsort(buf
, sizeof(strings
)/sizeof(strings
[0]), sizeof(strings
[0]), compare_string2
);
2936 for (i
= 0; i
< sizeof(strings
)/sizeof(strings
[0]); i
++)
2938 ok(!strcmp(strings_sorted
[i
], str_buf
[i
]),
2939 "qsort using CompareStringA failed for element %d\n", i
);
2941 /* 3. sort using sort keys */
2942 memcpy(buf
, strings
, sizeof(strings
));
2943 qsort(buf
, sizeof(strings
)/sizeof(strings
[0]), sizeof(strings
[0]), compare_string3
);
2944 for (i
= 0; i
< sizeof(strings
)/sizeof(strings
[0]); i
++)
2946 ok(!strcmp(strings_sorted
[i
], str_buf
[i
]),
2947 "qsort using sort keys failed for element %d\n", i
);
2951 static void test_FoldStringA(void)
2955 char src
[256], dst
[256];
2956 static const char digits_src
[] = { 0xB9,0xB2,0xB3,'\0' };
2957 static const char digits_dst
[] = { '1','2','3','\0' };
2958 static const char composite_src
[] =
2960 0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
2961 0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
2962 0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
2963 0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
2964 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
2965 0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
2966 0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
2967 0xfb,0xfc,0xfd,0xff,'\0'
2969 static const char composite_dst
[] =
2971 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
2972 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
2973 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
2974 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
2975 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
2976 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
2977 0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
2978 0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
2979 0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
2980 0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
2981 0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
2982 0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
2983 0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
2984 0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
2985 0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
2987 static const char composite_dst_alt
[] =
2989 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
2990 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
2991 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
2992 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
2993 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
2994 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
2995 0x4f,0x7e,0x4f,0xa8,0xd8,0x55,0x60,0x55,
2996 0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,0x61,
2997 0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,0x61,
2998 0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,0x65,
2999 0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,0x69,
3000 0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,0x6f,
3001 0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,0x6f,
3002 0xa8,0xf8,0x75,0x60,0x75,0xb4,0x75,0x5e,
3003 0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
3005 static const char ligatures_src
[] =
3007 0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
3009 static const char ligatures_dst
[] =
3011 'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
3013 static const struct special
3017 } foldczone_special
[] =
3020 { 0x85, { 0x2e, 0x2e, 0x2e, 0x00 } },
3021 { 0x98, { 0x20, 0x7e, 0x00 } },
3022 { 0x99, { 0x54, 0x4d, 0x00 } },
3023 { 0xa0, { 0x20, 0x00 } },
3024 { 0xa8, { 0x20, 0xa8, 0x00 } },
3025 { 0xaa, { 0x61, 0x00 } },
3026 { 0xaf, { 0x20, 0xaf, 0x00 } },
3027 { 0xb2, { 0x32, 0x00 } },
3028 { 0xb3, { 0x33, 0x00 } },
3029 { 0xb4, { 0x20, 0xb4, 0x00 } },
3030 { 0xb8, { 0x20, 0xb8, 0x00 } },
3031 { 0xb9, { 0x31, 0x00 } },
3032 { 0xba, { 0x6f, 0x00 } },
3033 { 0xbc, { 0x31, 0x2f, 0x34, 0x00 } },
3034 { 0xbd, { 0x31, 0x2f, 0x32, 0x00 } },
3035 { 0xbe, { 0x33, 0x2f, 0x34, 0x00 } },
3040 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
3042 /* these tests are locale specific */
3043 if (GetACP() != 1252)
3045 trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
3049 /* MAP_FOLDDIGITS */
3051 ret
= pFoldStringA(MAP_FOLDDIGITS
, digits_src
, -1, dst
, 256);
3052 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
3054 win_skip("FoldStringA is not implemented\n");
3057 ok(ret
== 4, "Expected ret == 4, got %d, error %d\n", ret
, GetLastError());
3058 ok(strcmp(dst
, digits_dst
) == 0,
3059 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst
, dst
);
3060 for (i
= 1; i
< 256; i
++)
3062 if (!strchr(digits_src
, i
))
3067 ret
= pFoldStringA(MAP_FOLDDIGITS
, src
, -1, dst
, 256);
3068 ok(ret
== 2, "Expected ret == 2, got %d, error %d\n", ret
, GetLastError());
3069 ok(dst
[0] == src
[0],
3070 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src
, dst
);
3074 /* MAP_EXPAND_LIGATURES */
3076 ret
= pFoldStringA(MAP_EXPAND_LIGATURES
, ligatures_src
, -1, dst
, 256);
3077 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
3078 if (!(ret
== 0 && GetLastError() == ERROR_INVALID_FLAGS
)) {
3079 ok(ret
== sizeof(ligatures_dst
), "Got %d, error %d\n", ret
, GetLastError());
3080 ok(strcmp(dst
, ligatures_dst
) == 0,
3081 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst
, dst
);
3082 for (i
= 1; i
< 256; i
++)
3084 if (!strchr(ligatures_src
, i
))
3089 ret
= pFoldStringA(MAP_EXPAND_LIGATURES
, src
, -1, dst
, 256);
3093 ok((i
== 0xDC && lstrcmpA(dst
, "UE") == 0) ||
3094 (i
== 0xFC && lstrcmpA(dst
, "ue") == 0),
3095 "Got %s for %d\n", dst
, i
);
3099 ok(ret
== 2, "Expected ret == 2, got %d, error %d\n", ret
, GetLastError());
3100 ok(dst
[0] == src
[0],
3101 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src
, dst
);
3109 ret
= pFoldStringA(MAP_COMPOSITE
, composite_src
, -1, dst
, 256);
3110 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
3111 ok(ret
== 121 || ret
== 119, "Expected 121 or 119, got %d\n", ret
);
3112 ok(strcmp(dst
, composite_dst
) == 0 || strcmp(dst
, composite_dst_alt
) == 0,
3113 "MAP_COMPOSITE: Mismatch, got '%s'\n", dst
);
3115 for (i
= 1; i
< 256; i
++)
3117 if (!strchr(composite_src
, i
))
3122 ret
= pFoldStringA(MAP_COMPOSITE
, src
, -1, dst
, 256);
3123 ok(ret
== 2, "Expected ret == 2, got %d, error %d\n", ret
, GetLastError());
3124 ok(dst
[0] == src
[0],
3125 "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src
[0],
3126 (unsigned char)dst
[0],(unsigned char)dst
[1],(unsigned char)dst
[2]);
3131 for (i
= 1; i
< 256; i
++)
3136 ret
= pFoldStringA(MAP_FOLDCZONE
, src
, -1, dst
, 256);
3138 for (j
= 0; foldczone_special
[j
].src
!= 0 && ! is_special
; j
++)
3140 if (foldczone_special
[j
].src
== src
[0])
3142 ok(ret
== 2 || ret
== lstrlenA(foldczone_special
[j
].dst
) + 1,
3143 "Expected ret == 2 or %d, got %d, error %d\n",
3144 lstrlenA(foldczone_special
[j
].dst
) + 1, ret
, GetLastError());
3145 ok(src
[0] == dst
[0] || lstrcmpA(foldczone_special
[j
].dst
, dst
) == 0,
3146 "MAP_FOLDCZONE: string mismatch for 0x%02x\n",
3147 (unsigned char)src
[0]);
3153 ok(ret
== 2, "Expected ret == 2, got %d, error %d\n", ret
, GetLastError());
3154 ok(src
[0] == dst
[0],
3155 "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
3156 (unsigned char)src
[0], (unsigned char)dst
[0]);
3160 /* MAP_PRECOMPOSED */
3161 for (i
= 1; i
< 256; i
++)
3166 ret
= pFoldStringA(MAP_PRECOMPOSED
, src
, -1, dst
, 256);
3167 ok(ret
== 2, "Expected ret == 2, got %d, error %d\n", ret
, GetLastError());
3168 ok(src
[0] == dst
[0],
3169 "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
3170 (unsigned char)src
[0], (unsigned char)dst
[0]);
3174 static void test_FoldStringW(void)
3178 WCHAR src
[256], dst
[256], ch
, prev_ch
= 1;
3179 static const DWORD badFlags
[] =
3182 MAP_PRECOMPOSED
|MAP_COMPOSITE
,
3183 MAP_PRECOMPOSED
|MAP_EXPAND_LIGATURES
,
3184 MAP_COMPOSITE
|MAP_EXPAND_LIGATURES
3186 /* Ranges of digits 0-9 : Must be sorted! */
3187 static const WCHAR digitRanges
[] =
3189 0x0030, /* '0'-'9' */
3190 0x0660, /* Eastern Arabic */
3191 0x06F0, /* Arabic - Hindu */
3193 0x0966, /* Devengari */
3194 0x09E6, /* Bengalii */
3195 0x0A66, /* Gurmukhi */
3196 0x0AE6, /* Gujarati */
3198 0x0BE6, /* Tamil - No 0 */
3199 0x0C66, /* Telugu */
3200 0x0CE6, /* Kannada */
3201 0x0D66, /* Maylayalam */
3202 0x0DE6, /* Sinhala Lith */
3206 0x0F29, /* Tibet half - 0 is out of sequence */
3207 0x1040, /* Myanmar */
3208 0x1090, /* Myanmar Shan */
3209 0x1368, /* Ethiopic - no 0 */
3211 0x1810, /* Mongolian */
3213 0x19D0, /* New Tai Lue */
3214 0x1A80, /* Tai Tham Hora */
3215 0x1A90, /* Tai Tham Tham */
3216 0x1B50, /* Balinese */
3217 0x1BB0, /* Sundanese */
3218 0x1C40, /* Lepcha */
3219 0x1C50, /* Ol Chiki */
3220 0x2070, /* Superscript - 1, 2, 3 are out of sequence */
3221 0x2080, /* Subscript */
3222 0x245F, /* Circled - 0 is out of sequence */
3223 0x2473, /* Bracketed */
3224 0x2487, /* Full stop */
3225 0x24F4, /* Double Circled */
3226 0x2775, /* Inverted circled - No 0 */
3227 0x277F, /* Patterned circled - No 0 */
3228 0x2789, /* Inverted Patterned circled - No 0 */
3229 0x3020, /* Hangzhou */
3231 0xA8D0, /* Saurashtra */
3232 0xA900, /* Kayah Li */
3233 0xA9D0, /* Javanese */
3234 0xA9F0, /* Myanmar Tai Laing */
3236 0xABF0, /* Meetei Mayek */
3237 0xff10, /* Pliene chasse (?) */
3238 0xffff /* Terminator */
3240 /* Digits which are represented, but out of sequence */
3241 static const WCHAR outOfSequenceDigits
[] =
3243 0xB9, /* Superscript 1 */
3244 0xB2, /* Superscript 2 */
3245 0xB3, /* Superscript 3 */
3246 0x0C78, /* Telugu Fraction 0 */
3247 0x0C79, /* Telugu Fraction 1 */
3248 0x0C7A, /* Telugu Fraction 2 */
3249 0x0C7B, /* Telugu Fraction 3 */
3250 0x0C7C, /* Telugu Fraction 1 */
3251 0x0C7D, /* Telugu Fraction 2 */
3252 0x0C7E, /* Telugu Fraction 3 */
3253 0x0F33, /* Tibetan half zero */
3254 0x19DA, /* New Tai Lue Tham 1 */
3255 0x24EA, /* Circled 0 */
3256 0x24FF, /* Negative Circled 0 */
3257 0x3007, /* Ideographic number zero */
3258 '\0' /* Terminator */
3260 /* Digits in digitRanges for which no representation is available */
3261 static const WCHAR noDigitAvailable
[] =
3263 0x0BE6, /* No Tamil 0 */
3264 0x0F29, /* No Tibetan half zero (out of sequence) */
3265 0x1368, /* No Ethiopic 0 */
3266 0x2473, /* No Bracketed 0 */
3267 0x2487, /* No 0 Full stop */
3268 0x24F4, /* No double circled 0 */
3269 0x2775, /* No inverted circled 0 */
3270 0x277F, /* No patterned circled */
3271 0x2789, /* No inverted Patterned circled */
3272 0x3020, /* No Hangzhou 0 */
3273 '\0' /* Terminator */
3275 static const WCHAR foldczone_src
[] =
3277 'W', 'i', 'n', 'e', 0x0348, 0x0551, 0x1323, 0x280d,
3278 0xff37, 0xff49, 0xff4e, 0xff45, '\0'
3280 static const WCHAR foldczone_dst
[] =
3282 'W','i','n','e',0x0348,0x0551,0x1323,0x280d,'W','i','n','e','\0'
3284 static const WCHAR foldczone_todo_src
[] =
3286 0x3c5,0x308,0x6a,0x30c,0xa0,0xaa,0
3288 static const WCHAR foldczone_todo_dst
[] =
3290 0x3cb,0x1f0,' ','a',0
3292 static const WCHAR foldczone_todo_broken_dst
[] =
3294 0x3cb,0x1f0,0xa0,0xaa,0
3296 static const WCHAR ligatures_src
[] =
3298 'W', 'i', 'n', 'e', 0x03a6, 0x03b9, 0x03bd, 0x03b5,
3299 0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
3300 0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
3301 0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
3302 0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
3303 0xfb04, 0xfb05, 0xfb06, '\0'
3305 static const WCHAR ligatures_dst
[] =
3307 'W','i','n','e',0x03a6,0x03b9,0x03bd,0x03b5,
3308 'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
3309 'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
3310 'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
3311 0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
3312 'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
3317 win_skip("FoldStringW is not available\n");
3318 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
3321 /* Invalid flag combinations */
3322 for (i
= 0; i
< sizeof(badFlags
)/sizeof(badFlags
[0]); i
++)
3324 src
[0] = dst
[0] = '\0';
3326 ret
= pFoldStringW(badFlags
[i
], src
, 256, dst
, 256);
3327 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED
)
3329 win_skip("FoldStringW is not implemented\n");
3332 ok(!ret
&& GetLastError() == ERROR_INVALID_FLAGS
,
3333 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
3336 /* src & dst cannot be the same */
3338 ret
= pFoldStringW(MAP_FOLDCZONE
, src
, -1, src
, 256);
3339 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
3340 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3342 /* src can't be NULL */
3344 ret
= pFoldStringW(MAP_FOLDCZONE
, NULL
, -1, dst
, 256);
3345 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
3346 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3348 /* srclen can't be 0 */
3350 ret
= pFoldStringW(MAP_FOLDCZONE
, src
, 0, dst
, 256);
3351 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
3352 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3354 /* dstlen can't be < 0 */
3356 ret
= pFoldStringW(MAP_FOLDCZONE
, src
, -1, dst
, -1);
3357 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
3358 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3360 /* Ret includes terminating NUL which is appended if srclen = -1 */
3365 ret
= pFoldStringW(MAP_FOLDCZONE
, src
, -1, dst
, 256);
3366 ok(ret
== 2, "Expected ret == 2, got %d, error %d\n", ret
, GetLastError());
3367 ok(dst
[0] == 'A' && dst
[1] == '\0',
3368 "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%d\n",
3369 'A', '\0', ret
, dst
[0], dst
[1], GetLastError());
3371 /* If size is given, result is not NUL terminated */
3377 ret
= pFoldStringW(MAP_FOLDCZONE
, src
, 1, dst
, 256);
3378 ok(ret
== 1, "Expected ret == 1, got %d, error %d\n", ret
, GetLastError());
3379 ok(dst
[0] == 'A' && dst
[1] == 'X',
3380 "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%d\n",
3381 'A','X', ret
, dst
[0], dst
[1], GetLastError());
3383 /* MAP_FOLDDIGITS */
3384 for (j
= 0; j
< sizeof(digitRanges
)/sizeof(digitRanges
[0]); j
++)
3386 /* Check everything before this range */
3387 for (ch
= prev_ch
; ch
< digitRanges
[j
]; ch
++)
3391 src
[1] = dst
[0] = '\0';
3392 ret
= pFoldStringW(MAP_FOLDDIGITS
, src
, -1, dst
, 256);
3393 ok(ret
== 2, "Expected ret == 2, got %d, error %d\n", ret
, GetLastError());
3395 ok(dst
[0] == ch
|| strchrW(outOfSequenceDigits
, ch
) ||
3396 (ch
>= 0xa8e0 && ch
<= 0xa8e9), /* combining Devanagari on Win8 */
3397 "MAP_FOLDDIGITS: ch 0x%04x Expected unchanged got %04x\n", ch
, dst
[0]);
3398 ok(!isdigitW(ch
) || strchrW(outOfSequenceDigits
, ch
) ||
3399 broken( ch
>= 0xbf0 && ch
<= 0xbf2 ), /* win2k */
3400 "char %04x should not be a digit\n", ch
);
3403 if (digitRanges
[j
] == 0xffff)
3404 break; /* Finished the whole code point space */
3406 for (ch
= digitRanges
[j
]; ch
< digitRanges
[j
] + 10; ch
++)
3410 /* Map out of sequence characters */
3411 if (ch
== 0x2071) c
= 0x00B9; /* Superscript 1 */
3412 else if (ch
== 0x2072) c
= 0x00B2; /* Superscript 2 */
3413 else if (ch
== 0x2073) c
= 0x00B3; /* Superscript 3 */
3414 else if (ch
== 0x245F) c
= 0x24EA; /* Circled 0 */
3418 src
[1] = dst
[0] = '\0';
3419 ret
= pFoldStringW(MAP_FOLDDIGITS
, src
, -1, dst
, 256);
3420 ok(ret
== 2, "Expected ret == 2, got %d, error %d\n", ret
, GetLastError());
3422 ok((dst
[0] == '0' + ch
- digitRanges
[j
] && dst
[1] == '\0') ||
3423 broken( dst
[0] == ch
) || /* old Windows versions don't have all mappings */
3424 (digitRanges
[j
] == 0x3020 && dst
[0] == ch
) || /* Hangzhou not present in all Windows versions */
3425 (digitRanges
[j
] == 0x0F29 && dst
[0] == ch
) || /* Tibetan not present in all Windows versions */
3426 strchrW(noDigitAvailable
, c
),
3427 "MAP_FOLDDIGITS: ch %04x Expected %04x got %04x\n",
3428 ch
, '0' + digitRanges
[j
] - ch
, dst
[0]);
3435 ret
= pFoldStringW(MAP_FOLDCZONE
, foldczone_src
, -1, dst
, 256);
3436 ok(ret
== sizeof(foldczone_dst
)/sizeof(foldczone_dst
[0]),
3437 "Got %d, error %d\n", ret
, GetLastError());
3438 ok(!memcmp(dst
, foldczone_dst
, sizeof(foldczone_dst
)),
3439 "MAP_FOLDCZONE: Expanded incorrectly\n");
3441 ret
= pFoldStringW(MAP_FOLDCZONE
|MAP_PRECOMPOSED
, foldczone_todo_src
, -1, dst
, 256);
3442 todo_wine
ok(ret
== sizeof(foldczone_todo_dst
)/sizeof(foldczone_todo_dst
[0]),
3443 "Got %d, error %d\n", ret
, GetLastError());
3444 todo_wine
ok(!memcmp(dst
, foldczone_todo_dst
, sizeof(foldczone_todo_dst
))
3445 || broken(!memcmp(dst
, foldczone_todo_broken_dst
, sizeof(foldczone_todo_broken_dst
))),
3446 "MAP_FOLDCZONE: Expanded incorrectly (%s)\n", wine_dbgstr_w(dst
));
3448 /* MAP_EXPAND_LIGATURES */
3450 ret
= pFoldStringW(MAP_EXPAND_LIGATURES
, ligatures_src
, -1, dst
, 256);
3451 /* NT 4.0 doesn't support MAP_EXPAND_LIGATURES */
3452 if (!(ret
== 0 && GetLastError() == ERROR_INVALID_FLAGS
)) {
3453 ok(ret
== sizeof(ligatures_dst
)/sizeof(ligatures_dst
[0]),
3454 "Got %d, error %d\n", ret
, GetLastError());
3455 ok(!memcmp(dst
, ligatures_dst
, sizeof(ligatures_dst
)),
3456 "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
3459 /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
3464 #define LCID_OK(l) \
3465 ok(lcid == l, "Expected lcid = %08x, got %08x\n", l, lcid)
3466 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
3467 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
3468 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
3469 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
3471 static void test_ConvertDefaultLocale(void)
3475 /* Doesn't change lcid, even if non default sublang/sort used */
3476 TEST_LCID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
, SORT_DEFAULT
);
3477 TEST_LCID(LANG_ENGLISH
, SUBLANG_ENGLISH_UK
, SORT_DEFAULT
);
3478 TEST_LCID(LANG_JAPANESE
, SUBLANG_DEFAULT
, SORT_DEFAULT
);
3479 TEST_LCID(LANG_JAPANESE
, SUBLANG_DEFAULT
, SORT_JAPANESE_UNICODE
);
3481 /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
3482 LCID_RES(MKLCID(LANG_ENGLISH
, SUBLANG_NEUTRAL
, SORT_DEFAULT
),
3483 MKLCID(LANG_ENGLISH
, SUBLANG_DEFAULT
, SORT_DEFAULT
));
3484 LCID_RES(MKLCID(LANG_JAPANESE
, SUBLANG_NEUTRAL
, SORT_DEFAULT
),
3485 MKLCID(LANG_JAPANESE
, SUBLANG_DEFAULT
, SORT_DEFAULT
));
3487 /* Invariant language is not treated specially */
3488 TEST_LCID(LANG_INVARIANT
, SUBLANG_DEFAULT
, SORT_DEFAULT
);
3490 /* User/system default languages alone are not mapped */
3491 TEST_LCIDLANG(LANG_SYSTEM_DEFAULT
, SORT_JAPANESE_UNICODE
);
3492 TEST_LCIDLANG(LANG_USER_DEFAULT
, SORT_JAPANESE_UNICODE
);
3495 LCID_RES(LOCALE_SYSTEM_DEFAULT
, GetSystemDefaultLCID());
3496 LCID_RES(LOCALE_USER_DEFAULT
, GetUserDefaultLCID());
3497 LCID_RES(LOCALE_NEUTRAL
, GetUserDefaultLCID());
3498 lcid
= ConvertDefaultLocale(LOCALE_INVARIANT
);
3499 ok(lcid
== LOCALE_INVARIANT
|| broken(lcid
== 0x47f) /* win2k[3]/winxp */,
3500 "Expected lcid = %08x, got %08x\n", LOCALE_INVARIANT
, lcid
);
3503 static BOOL CALLBACK
langgrp_procA(LGRPID lgrpid
, LPSTR lpszNum
, LPSTR lpszName
,
3504 DWORD dwFlags
, LONG_PTR lParam
)
3506 if (winetest_debug
> 1)
3507 trace("%08x, %s, %s, %08x, %08lx\n",
3508 lgrpid
, lpszNum
, lpszName
, dwFlags
, lParam
);
3510 ok(pIsValidLanguageGroup(lgrpid
, dwFlags
) == TRUE
,
3511 "Enumerated grp %d not valid (flags %d)\n", lgrpid
, dwFlags
);
3513 /* If lParam is one, we are calling with flags defaulted from 0 */
3514 ok(!lParam
|| (dwFlags
== LGRPID_INSTALLED
|| dwFlags
== LGRPID_SUPPORTED
),
3515 "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %d\n", dwFlags
);
3520 static void test_EnumSystemLanguageGroupsA(void)
3524 if (!pEnumSystemLanguageGroupsA
|| !pIsValidLanguageGroup
)
3526 win_skip("EnumSystemLanguageGroupsA and/or IsValidLanguageGroup are not available\n");
3530 /* No enumeration proc */
3532 ret
= pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED
, 0);
3533 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
3535 win_skip("EnumSystemLanguageGroupsA is not implemented\n");
3538 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
3539 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3543 pEnumSystemLanguageGroupsA(langgrp_procA
, LGRPID_INSTALLED
|LGRPID_SUPPORTED
, 0);
3544 ok(GetLastError() == ERROR_INVALID_FLAGS
, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
3546 /* No flags - defaults to LGRPID_INSTALLED */
3547 SetLastError(0xdeadbeef);
3548 pEnumSystemLanguageGroupsA(langgrp_procA
, 0, 1);
3549 ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
3551 pEnumSystemLanguageGroupsA(langgrp_procA
, LGRPID_INSTALLED
, 0);
3552 pEnumSystemLanguageGroupsA(langgrp_procA
, LGRPID_SUPPORTED
, 0);
3555 static BOOL CALLBACK
enum_func( LPWSTR name
, DWORD flags
, LPARAM lparam
)
3557 if (winetest_debug
> 1)
3558 trace( "%s %x\n", wine_dbgstr_w(name
), flags
);
3562 static void test_EnumSystemLocalesEx(void)
3566 if (!pEnumSystemLocalesEx
)
3568 win_skip( "EnumSystemLocalesEx not available\n" );
3571 SetLastError( 0xdeadbeef );
3572 ret
= pEnumSystemLocalesEx( enum_func
, LOCALE_ALL
, 0, (void *)1 );
3573 ok( !ret
, "should have failed\n" );
3574 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
3575 SetLastError( 0xdeadbeef );
3576 ret
= pEnumSystemLocalesEx( enum_func
, 0, 0, NULL
);
3577 ok( ret
, "failed err %u\n", GetLastError() );
3580 static BOOL CALLBACK
lgrplocale_procA(LGRPID lgrpid
, LCID lcid
, LPSTR lpszNum
,
3583 if (winetest_debug
> 1)
3584 trace("%08x, %08x, %s, %08lx\n", lgrpid
, lcid
, lpszNum
, lParam
);
3586 /* invalid locale enumerated on some platforms */
3590 ok(pIsValidLanguageGroup(lgrpid
, LGRPID_SUPPORTED
) == TRUE
,
3591 "Enumerated grp %d not valid\n", lgrpid
);
3592 ok(IsValidLocale(lcid
, LCID_SUPPORTED
) == TRUE
,
3593 "Enumerated grp locale %04x not valid\n", lcid
);
3597 static void test_EnumLanguageGroupLocalesA(void)
3601 if (!pEnumLanguageGroupLocalesA
|| !pIsValidLanguageGroup
)
3603 win_skip("EnumLanguageGroupLocalesA and/or IsValidLanguageGroup are not available\n");
3607 /* No enumeration proc */
3609 ret
= pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE
, 0, 0);
3610 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
3612 win_skip("EnumLanguageGroupLocalesA is not implemented\n");
3615 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
3616 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3618 /* lgrpid too small */
3620 ret
= pEnumLanguageGroupLocalesA(lgrplocale_procA
, 0, 0, 0);
3621 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
3622 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3624 /* lgrpid too big */
3626 ret
= pEnumLanguageGroupLocalesA(lgrplocale_procA
, LGRPID_ARMENIAN
+ 1, 0, 0);
3627 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
3628 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3630 /* dwFlags is reserved */
3632 ret
= pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE
, 0x1, 0);
3633 ok( !ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
3634 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3636 pEnumLanguageGroupLocalesA(lgrplocale_procA
, LGRPID_WESTERN_EUROPE
, 0, 0);
3639 static void test_SetLocaleInfoA(void)
3642 LCID lcid
= GetUserDefaultLCID();
3646 bRet
= SetLocaleInfoA(lcid
, LOCALE_SDATE
, 0);
3647 ok( !bRet
&& GetLastError() == ERROR_INVALID_PARAMETER
,
3648 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3652 bRet
= SetLocaleInfoA(lcid
, LOCALE_IDATE
, "test_SetLocaleInfoA");
3653 ok(!bRet
&& GetLastError() == ERROR_INVALID_FLAGS
,
3654 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
3658 bRet
= SetLocaleInfoA(lcid
, LOCALE_ILDATE
, "test_SetLocaleInfoA");
3659 ok(!bRet
&& GetLastError() == ERROR_INVALID_FLAGS
,
3660 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
3663 static BOOL CALLBACK
luilocale_proc1A(LPSTR value
, LONG_PTR lParam
)
3665 if (winetest_debug
> 1)
3666 trace("%s %08lx\n", value
, lParam
);
3670 static BOOL CALLBACK
luilocale_proc2A(LPSTR value
, LONG_PTR lParam
)
3672 ok(!enumCount
, "callback called again unexpected\n");
3677 static BOOL CALLBACK
luilocale_proc3A(LPSTR value
, LONG_PTR lParam
)
3679 ok(0,"callback called unexpected\n");
3683 static void test_EnumUILanguageA(void)
3686 if (!pEnumUILanguagesA
) {
3687 win_skip("EnumUILanguagesA is not available on Win9x or NT4\n");
3691 SetLastError(ERROR_SUCCESS
);
3692 ret
= pEnumUILanguagesA(luilocale_proc1A
, 0, 0);
3693 if (ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
3695 win_skip("EnumUILanguagesA is not implemented\n");
3698 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
3701 SetLastError(ERROR_SUCCESS
);
3702 ret
= pEnumUILanguagesA(luilocale_proc2A
, 0, 0);
3703 ok(ret
, "Expected ret != 0, got %d, error %d\n", ret
, GetLastError());
3705 SetLastError(ERROR_SUCCESS
);
3706 ret
= pEnumUILanguagesA(NULL
, 0, 0);
3707 ok(!ret
, "Expected return value FALSE, got %u\n", ret
);
3708 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
3709 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3711 SetLastError(ERROR_SUCCESS
);
3712 ret
= pEnumUILanguagesA(luilocale_proc3A
, 0x5a5a5a5a, 0);
3713 ok(!ret
, "Expected return value FALSE, got %u\n", ret
);
3714 ok(GetLastError() == ERROR_INVALID_FLAGS
, "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
3716 SetLastError(ERROR_SUCCESS
);
3717 ret
= pEnumUILanguagesA(NULL
, 0x5a5a5a5a, 0);
3718 ok(!ret
, "Expected return value FALSE, got %u\n", ret
);
3719 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
3720 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
3723 static char date_fmt_buf
[1024];
3724 static WCHAR date_fmt_bufW
[1024];
3726 static BOOL CALLBACK
enum_datetime_procA(LPSTR fmt
)
3728 lstrcatA(date_fmt_buf
, fmt
);
3729 lstrcatA(date_fmt_buf
, "\n");
3733 static BOOL CALLBACK
enum_datetime_procW(WCHAR
*fmt
)
3735 lstrcatW(date_fmt_bufW
, fmt
);
3739 static void test_EnumDateFormatsA(void)
3743 LCID lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
3745 date_fmt_buf
[0] = 0;
3746 SetLastError(0xdeadbeef);
3747 ret
= EnumDateFormatsA(enum_datetime_procA
, lcid
, 0);
3748 if (!ret
&& (GetLastError() == ERROR_INVALID_FLAGS
))
3750 win_skip("0 for dwFlags is not supported\n");
3754 ok(ret
, "EnumDateFormatsA(0) error %d\n", GetLastError());
3755 trace("EnumDateFormatsA(0): %s\n", date_fmt_buf
);
3756 /* test the 1st enumerated format */
3757 if ((p
= strchr(date_fmt_buf
, '\n'))) *p
= 0;
3758 ret
= GetLocaleInfoA(lcid
, LOCALE_SSHORTDATE
, buf
, sizeof(buf
));
3759 ok(ret
, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
3760 ok(!lstrcmpA(date_fmt_buf
, buf
), "expected \"%s\" got \"%s\"\n", date_fmt_buf
, buf
);
3763 date_fmt_buf
[0] = 0;
3764 SetLastError(0xdeadbeef);
3765 ret
= EnumDateFormatsA(enum_datetime_procA
, lcid
, LOCALE_USE_CP_ACP
);
3766 if (!ret
&& (GetLastError() == ERROR_INVALID_FLAGS
))
3768 win_skip("LOCALE_USE_CP_ACP is not supported\n");
3772 ok(ret
, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
3773 trace("EnumDateFormatsA(LOCALE_USE_CP_ACP): %s\n", date_fmt_buf
);
3774 /* test the 1st enumerated format */
3775 if ((p
= strchr(date_fmt_buf
, '\n'))) *p
= 0;
3776 ret
= GetLocaleInfoA(lcid
, LOCALE_SSHORTDATE
, buf
, sizeof(buf
));
3777 ok(ret
, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
3778 ok(!lstrcmpA(date_fmt_buf
, buf
), "expected \"%s\" got \"%s\"\n", date_fmt_buf
, buf
);
3781 date_fmt_buf
[0] = 0;
3782 ret
= EnumDateFormatsA(enum_datetime_procA
, lcid
, DATE_SHORTDATE
);
3783 ok(ret
, "EnumDateFormatsA(DATE_SHORTDATE) error %d\n", GetLastError());
3784 trace("EnumDateFormatsA(DATE_SHORTDATE): %s\n", date_fmt_buf
);
3785 /* test the 1st enumerated format */
3786 if ((p
= strchr(date_fmt_buf
, '\n'))) *p
= 0;
3787 ret
= GetLocaleInfoA(lcid
, LOCALE_SSHORTDATE
, buf
, sizeof(buf
));
3788 ok(ret
, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError());
3789 ok(!lstrcmpA(date_fmt_buf
, buf
), "expected \"%s\" got \"%s\"\n", date_fmt_buf
, buf
);
3791 date_fmt_buf
[0] = 0;
3792 ret
= EnumDateFormatsA(enum_datetime_procA
, lcid
, DATE_LONGDATE
);
3793 ok(ret
, "EnumDateFormatsA(DATE_LONGDATE) error %d\n", GetLastError());
3794 trace("EnumDateFormatsA(DATE_LONGDATE): %s\n", date_fmt_buf
);
3795 /* test the 1st enumerated format */
3796 if ((p
= strchr(date_fmt_buf
, '\n'))) *p
= 0;
3797 ret
= GetLocaleInfoA(lcid
, LOCALE_SLONGDATE
, buf
, sizeof(buf
));
3798 ok(ret
, "GetLocaleInfoA(LOCALE_SLONGDATE) error %d\n", GetLastError());
3799 ok(!lstrcmpA(date_fmt_buf
, buf
), "expected \"%s\" got \"%s\"\n", date_fmt_buf
, buf
);
3801 date_fmt_buf
[0] = 0;
3802 SetLastError(0xdeadbeef);
3803 ret
= EnumDateFormatsA(enum_datetime_procA
, lcid
, DATE_YEARMONTH
);
3804 if (!ret
&& (GetLastError() == ERROR_INVALID_FLAGS
))
3806 win_skip("DATE_YEARMONTH is only present on W2K and later\n");
3809 ok(ret
, "EnumDateFormatsA(DATE_YEARMONTH) error %d\n", GetLastError());
3810 trace("EnumDateFormatsA(DATE_YEARMONTH): %s\n", date_fmt_buf
);
3811 /* test the 1st enumerated format */
3812 if ((p
= strchr(date_fmt_buf
, '\n'))) *p
= 0;
3813 ret
= GetLocaleInfoA(lcid
, LOCALE_SYEARMONTH
, buf
, sizeof(buf
));
3814 ok(ret
, "GetLocaleInfoA(LOCALE_SYEARMONTH) error %d\n", GetLastError());
3815 ok(!lstrcmpA(date_fmt_buf
, buf
) || broken(!buf
[0]) /* win9x */,
3816 "expected \"%s\" got \"%s\"\n", date_fmt_buf
, buf
);
3819 static void test_EnumTimeFormatsA(void)
3823 LCID lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
3825 date_fmt_buf
[0] = 0;
3826 ret
= EnumTimeFormatsA(enum_datetime_procA
, lcid
, 0);
3827 ok(ret
, "EnumTimeFormatsA(0) error %d\n", GetLastError());
3828 trace("EnumTimeFormatsA(0): %s\n", date_fmt_buf
);
3829 /* test the 1st enumerated format */
3830 if ((p
= strchr(date_fmt_buf
, '\n'))) *p
= 0;
3831 ret
= GetLocaleInfoA(lcid
, LOCALE_STIMEFORMAT
, buf
, sizeof(buf
));
3832 ok(ret
, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
3833 ok(!lstrcmpA(date_fmt_buf
, buf
), "expected \"%s\" got \"%s\"\n", date_fmt_buf
, buf
);
3835 date_fmt_buf
[0] = 0;
3836 ret
= EnumTimeFormatsA(enum_datetime_procA
, lcid
, LOCALE_USE_CP_ACP
);
3837 ok(ret
, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
3838 trace("EnumTimeFormatsA(LOCALE_USE_CP_ACP): %s\n", date_fmt_buf
);
3839 /* test the 1st enumerated format */
3840 if ((p
= strchr(date_fmt_buf
, '\n'))) *p
= 0;
3841 ret
= GetLocaleInfoA(lcid
, LOCALE_STIMEFORMAT
, buf
, sizeof(buf
));
3842 ok(ret
, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
3843 ok(!lstrcmpA(date_fmt_buf
, buf
), "expected \"%s\" got \"%s\"\n", date_fmt_buf
, buf
);
3846 static void test_EnumTimeFormatsW(void)
3848 LCID lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
3852 date_fmt_bufW
[0] = 0;
3853 ret
= EnumTimeFormatsW(enum_datetime_procW
, lcid
, 0);
3854 ok(ret
, "EnumTimeFormatsW(0) error %d\n", GetLastError());
3855 ret
= GetLocaleInfoW(lcid
, LOCALE_STIMEFORMAT
, bufW
, sizeof(bufW
)/sizeof(bufW
[0]));
3856 ok(ret
, "GetLocaleInfoW(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
3857 ok(!lstrcmpW(date_fmt_bufW
, bufW
), "expected \"%s\" got \"%s\"\n", wine_dbgstr_w(date_fmt_bufW
),
3858 wine_dbgstr_w(bufW
));
3860 date_fmt_bufW
[0] = 0;
3861 ret
= EnumTimeFormatsW(enum_datetime_procW
, lcid
, LOCALE_USE_CP_ACP
);
3862 ok(ret
, "EnumTimeFormatsW(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
3863 ret
= GetLocaleInfoW(lcid
, LOCALE_STIMEFORMAT
, bufW
, sizeof(bufW
)/sizeof(bufW
[0]));
3864 ok(ret
, "GetLocaleInfoW(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
3865 ok(!lstrcmpW(date_fmt_bufW
, bufW
), "expected \"%s\" got \"%s\"\n", wine_dbgstr_w(date_fmt_bufW
),
3866 wine_dbgstr_w(bufW
));
3868 /* TIME_NOSECONDS is Win7+ feature */
3869 date_fmt_bufW
[0] = 0;
3870 ret
= EnumTimeFormatsW(enum_datetime_procW
, lcid
, TIME_NOSECONDS
);
3871 if (!ret
&& GetLastError() == ERROR_INVALID_FLAGS
)
3872 win_skip("EnumTimeFormatsW doesn't support TIME_NOSECONDS\n");
3876 ok(ret
, "EnumTimeFormatsW(TIME_NOSECONDS) error %d\n", GetLastError());
3877 ret
= GetLocaleInfoW(lcid
, LOCALE_SSHORTTIME
, bufW
, sizeof(bufW
)/sizeof(bufW
[0]));
3878 ok(ret
, "GetLocaleInfoW(LOCALE_SSHORTTIME) error %d\n", GetLastError());
3879 ok(!lstrcmpW(date_fmt_bufW
, bufW
), "expected \"%s\" got \"%s\"\n", wine_dbgstr_w(date_fmt_bufW
),
3880 wine_dbgstr_w(bufW
));
3882 /* EnumTimeFormatsA doesn't support this flag */
3883 ret
= EnumTimeFormatsA(enum_datetime_procA
, lcid
, TIME_NOSECONDS
);
3884 ok(!ret
&& GetLastError() == ERROR_INVALID_FLAGS
, "EnumTimeFormatsA(TIME_NOSECONDS) ret %d, error %d\n", ret
,
3887 ret
= EnumTimeFormatsA(NULL
, lcid
, TIME_NOSECONDS
);
3888 ok(!ret
&& GetLastError() == ERROR_INVALID_FLAGS
, "EnumTimeFormatsA(TIME_NOSECONDS) ret %d, error %d\n", ret
,
3891 /* And it's not supported by GetLocaleInfoA either */
3892 ret
= GetLocaleInfoA(lcid
, LOCALE_SSHORTTIME
, buf
, sizeof(buf
)/sizeof(buf
[0]));
3893 ok(!ret
&& GetLastError() == ERROR_INVALID_FLAGS
, "GetLocaleInfoA(LOCALE_SSHORTTIME) ret %d, error %d\n", ret
,
3897 static void test_GetCPInfo(void)
3902 SetLastError(0xdeadbeef);
3903 ret
= GetCPInfo(CP_SYMBOL
, &cpinfo
);
3904 ok(!ret
, "GetCPInfo(CP_SYMBOL) should fail\n");
3905 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
3906 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
3908 SetLastError(0xdeadbeef);
3909 ret
= GetCPInfo(CP_UTF7
, &cpinfo
);
3910 if (!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
)
3912 win_skip("Codepage CP_UTF7 is not installed/available\n");
3916 ok(ret
, "GetCPInfo(CP_UTF7) error %u\n", GetLastError());
3917 ok(cpinfo
.DefaultChar
[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo
.DefaultChar
[0]);
3918 ok(cpinfo
.DefaultChar
[1] == 0, "expected 0, got 0x%x\n", cpinfo
.DefaultChar
[1]);
3919 ok(cpinfo
.LeadByte
[0] == 0, "expected 0, got 0x%x\n", cpinfo
.LeadByte
[0]);
3920 ok(cpinfo
.LeadByte
[1] == 0, "expected 0, got 0x%x\n", cpinfo
.LeadByte
[1]);
3921 ok(cpinfo
.MaxCharSize
== 5, "expected 5, got 0x%x\n", cpinfo
.MaxCharSize
);
3924 SetLastError(0xdeadbeef);
3925 ret
= GetCPInfo(CP_UTF8
, &cpinfo
);
3926 if (!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
)
3928 win_skip("Codepage CP_UTF8 is not installed/available\n");
3932 ok(ret
, "GetCPInfo(CP_UTF8) error %u\n", GetLastError());
3933 ok(cpinfo
.DefaultChar
[0] == 0x3f, "expected 0x3f, got 0x%x\n", cpinfo
.DefaultChar
[0]);
3934 ok(cpinfo
.DefaultChar
[1] == 0, "expected 0, got 0x%x\n", cpinfo
.DefaultChar
[1]);
3935 ok(cpinfo
.LeadByte
[0] == 0, "expected 0, got 0x%x\n", cpinfo
.LeadByte
[0]);
3936 ok(cpinfo
.LeadByte
[1] == 0, "expected 0, got 0x%x\n", cpinfo
.LeadByte
[1]);
3937 ok(cpinfo
.MaxCharSize
== 4 || broken(cpinfo
.MaxCharSize
== 3) /* win9x */,
3938 "expected 4, got %u\n", cpinfo
.MaxCharSize
);
3943 * The CT_TYPE1 has varied over windows version.
3944 * The current target for correct behavior is windows 7.
3945 * There was a big shift between windows 2000 (first introduced) and windows Xp
3946 * Most of the old values below are from windows 2000.
3947 * A smaller subset of changes happened between windows Xp and Window vista/7
3949 static void test_GetStringTypeW(void)
3951 static const WCHAR blanks
[] = {0x9, 0x20, 0xa0, 0x3000, 0xfeff};
3952 static const WORD blanks_new
[] = {C1_SPACE
| C1_CNTRL
| C1_BLANK
| C1_DEFINED
,
3953 C1_SPACE
| C1_BLANK
| C1_DEFINED
,
3954 C1_SPACE
| C1_BLANK
| C1_DEFINED
,
3955 C1_SPACE
| C1_BLANK
| C1_DEFINED
,
3956 C1_CNTRL
| C1_BLANK
| C1_DEFINED
};
3957 static const WORD blanks_old
[] ={C1_SPACE
| C1_CNTRL
| C1_BLANK
,
3958 C1_SPACE
| C1_BLANK
,
3959 C1_SPACE
| C1_BLANK
,
3960 C1_SPACE
| C1_BLANK
,
3961 C1_SPACE
| C1_BLANK
};
3963 static const WCHAR undefined
[] = {0x378, 0x379, 0x5ff, 0xfff8, 0xfffe};
3966 static const WCHAR alpha
[] = {0x47, 0x67, 0x1c5};
3967 static const WORD alpha_old
[] = {C1_UPPER
| C1_ALPHA
,
3968 C1_LOWER
| C1_ALPHA
,
3969 C1_UPPER
| C1_LOWER
| C1_ALPHA
,
3972 /* Sk, Sk, Mn, So, Me */
3973 static const WCHAR oldpunc
[] = { 0x2c2, 0x2e5, 0x322, 0x482, 0x6de,
3975 0xffe0, 0xffe9, 0x2153};
3977 /* Lm, Nl, Cf, 0xad(Cf), 0x1f88 (Lt), Lo, Mc */
3978 static const WCHAR changed
[] = {0x2b0, 0x2160, 0x600, 0xad, 0x1f88, 0x294, 0x903};
3979 static const WORD changed_old
[] = { C1_PUNCT
, C1_PUNCT
, 0, C1_PUNCT
, C1_UPPER
| C1_ALPHA
, C1_ALPHA
, C1_PUNCT
};
3980 static const WORD changed_xp
[] = {C1_ALPHA
| C1_DEFINED
,
3981 C1_ALPHA
| C1_DEFINED
,
3982 C1_CNTRL
| C1_DEFINED
,
3983 C1_PUNCT
| C1_DEFINED
,
3984 C1_UPPER
| C1_LOWER
| C1_ALPHA
| C1_DEFINED
,
3985 C1_ALPHA
| C1_LOWER
| C1_DEFINED
,
3986 C1_ALPHA
| C1_DEFINED
};
3987 static const WORD changed_new
[] = { C1_ALPHA
| C1_DEFINED
,
3988 C1_ALPHA
| C1_DEFINED
,
3989 C1_CNTRL
| C1_DEFINED
,
3990 C1_PUNCT
| C1_CNTRL
| C1_DEFINED
,
3991 C1_UPPER
| C1_LOWER
| C1_ALPHA
| C1_DEFINED
,
3992 C1_ALPHA
| C1_DEFINED
,
3995 /* Pc, Pd, Ps, Pe, Pi, Pf, Po*/
3996 static const WCHAR punct
[] = { 0x5f, 0x2d, 0x28, 0x29, 0xab, 0xbb, 0x21 };
3998 static const WCHAR punct_special
[] = {0x24, 0x2b, 0x3c, 0x3e, 0x5e, 0x60,
3999 0x7c, 0x7e, 0xa2, 0xbe, 0xd7, 0xf7};
4000 static const WCHAR digit_special
[] = {0xb2, 0xb3, 0xb9};
4001 static const WCHAR lower_special
[] = {0x2071, 0x207f};
4002 static const WCHAR cntrl_special
[] = {0x070f, 0x200c, 0x200d,
4003 0x200e, 0x200f, 0x202a, 0x202b, 0x202c, 0x202d, 0x202e,
4004 0x206a, 0x206b, 0x206c, 0x206d, 0x206e, 0x206f, 0xfeff,
4005 0xfff9, 0xfffa, 0xfffb};
4006 static const WCHAR space_special
[] = {0x09, 0x0d, 0x85};
4014 SetLastError(0xdeadbeef);
4015 ret
= GetStringTypeW(CT_CTYPE1
, NULL
, 0, NULL
);
4016 ok(!ret
, "got %d\n", ret
);
4017 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got error %d\n", GetLastError());
4019 SetLastError(0xdeadbeef);
4020 ret
= GetStringTypeW(CT_CTYPE1
, NULL
, 0, types
);
4021 ok(!ret
, "got %d\n", ret
);
4022 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got error %d\n", GetLastError());
4024 SetLastError(0xdeadbeef);
4025 ret
= GetStringTypeW(CT_CTYPE1
, NULL
, 5, types
);
4026 ok(!ret
, "got %d\n", ret
);
4027 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got error %d\n", GetLastError());
4029 memset(types
,0,sizeof(types
));
4030 GetStringTypeW(CT_CTYPE1
, blanks
, 5, types
);
4031 for (i
= 0; i
< 5; i
++)
4032 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
]);
4034 memset(types
,0,sizeof(types
));
4035 GetStringTypeW(CT_CTYPE1
, alpha
, 3, types
);
4036 for (i
= 0; i
< 3; i
++)
4037 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
]));
4038 memset(types
,0,sizeof(types
));
4039 GetStringTypeW(CT_CTYPE1
, undefined
, 5, types
);
4040 for (i
= 0; i
< 5; i
++)
4041 ok(types
[i
] == 0, "incorrect types returned for %x -> (%x != 0)\n",undefined
[i
], types
[i
]);
4043 memset(types
,0,sizeof(types
));
4044 GetStringTypeW(CT_CTYPE1
, oldpunc
, 8, types
);
4045 for (i
= 0; i
< 8; i
++)
4046 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
);
4048 memset(types
,0,sizeof(types
));
4049 GetStringTypeW(CT_CTYPE1
, changed
, 7, types
);
4050 for (i
= 0; i
< 7; i
++)
4051 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
]);
4053 memset(types
,0,sizeof(types
));
4054 GetStringTypeW(CT_CTYPE1
, punct
, 7, types
);
4055 for (i
= 0; i
< 7; i
++)
4056 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
));
4059 memset(types
,0,sizeof(types
));
4060 GetStringTypeW(CT_CTYPE1
, punct_special
, 12, types
);
4061 for (i
= 0; i
< 12; i
++)
4062 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
);
4064 memset(types
,0,sizeof(types
));
4065 GetStringTypeW(CT_CTYPE1
, digit_special
, 3, types
);
4066 for (i
= 0; i
< 3; i
++)
4067 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
);
4069 memset(types
,0,sizeof(types
));
4070 GetStringTypeW(CT_CTYPE1
, lower_special
, 2, types
);
4071 for (i
= 0; i
< 2; i
++)
4072 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
);
4074 memset(types
,0,sizeof(types
));
4075 GetStringTypeW(CT_CTYPE1
, cntrl_special
, 20, types
);
4076 for (i
= 0; i
< 20; i
++)
4077 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
);
4079 memset(types
,0,sizeof(types
));
4080 GetStringTypeW(CT_CTYPE1
, space_special
, 3, types
);
4081 for (i
= 0; i
< 3; i
++)
4082 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
);
4084 /* surrogate pairs */
4086 memset(types
, 0, sizeof(types
));
4087 GetStringTypeW(CT_CTYPE3
, ch
, 1, types
);
4088 if (types
[0] == C3_NOTAPPLICABLE
)
4089 win_skip("C3_HIGHSURROGATE/C3_LOWSURROGATE are not supported.\n");
4091 ok(types
[0] == C3_HIGHSURROGATE
, "got %x\n", types
[0]);
4094 memset(types
, 0, sizeof(types
));
4095 GetStringTypeW(CT_CTYPE3
, ch
, 1, types
);
4096 ok(types
[0] == C3_LOWSURROGATE
, "got %x\n", types
[0]);
4099 /* Zl, Zp categories */
4102 memset(types
, 0, sizeof(types
));
4103 GetStringTypeW(CT_CTYPE1
, ch
, 2, types
);
4104 ok(types
[0] == (C1_DEFINED
|C1_SPACE
), "got %x\n", types
[0]);
4105 ok(types
[1] == (C1_DEFINED
|C1_SPACE
), "got %x\n", types
[1]);
4107 /* check Arabic range for kashida flag */
4108 for (ch
[0] = 0x600; ch
[0] <= 0x6ff; ch
[0] += 1)
4111 ret
= GetStringTypeW(CT_CTYPE3
, ch
, 1, types
);
4112 ok(ret
, "%#x: failed %d\n", ch
[0], ret
);
4113 if (ch
[0] == 0x640) /* ARABIC TATWEEL (Kashida) */
4114 ok(types
[0] & C3_KASHIDA
, "%#x: type %#x\n", ch
[0], types
[0]);
4116 ok(!(types
[0] & C3_KASHIDA
), "%#x: type %#x\n", ch
[0], types
[0]);
4120 static void test_IdnToNameprepUnicode(void)
4127 const WCHAR out
[64];
4133 5, {'t','e','s','t',0},
4134 5, 5, {'t','e','s','t',0},
4138 3, {'a',0xe111,'b'},
4140 0, ERROR_INVALID_NAME
4145 0, ERROR_INVALID_NAME
4155 0, ERROR_INVALID_NAME
4158 6, {' ','-','/','[',']',0},
4159 6, 6, {' ','-','/','[',']',0},
4164 3, 3, {'a','-','a'},
4165 IDN_USE_STD3_ASCII_RULES
, 0xdeadbeef
4170 IDN_USE_STD3_ASCII_RULES
, ERROR_INVALID_NAME
4172 { /* FoldString is not working as expected when MAP_FOLDCZONE is specified (composition+compatibility) */
4173 10, {'T',0xdf,0x130,0x143,0x37a,0x6a,0x30c,' ',0xaa,0},
4174 12, 12, {'t','s','s','i',0x307,0x144,' ',0x3b9,0x1f0,' ','a',0},
4178 11, {'t',0xad,0x34f,0x1806,0x180b,0x180c,0x180d,0x200b,0x200c,0x200d,0},
4182 { /* Another example of incorrectly working FoldString (composition) */
4190 0, ERROR_NO_UNICODE_TRANSLATION
4195 IDN_ALLOW_UNASSIGNED
, 0xdeadbeef
4198 5, {'a','.','.','a',0},
4200 0, ERROR_INVALID_NAME
4212 if (!pIdnToNameprepUnicode
)
4214 win_skip("IdnToNameprepUnicode is not available\n");
4218 ret
= pIdnToNameprepUnicode(0, test_data
[0].in
,
4219 test_data
[0].in_len
, NULL
, 0);
4220 ok(ret
== test_data
[0].ret
, "ret = %d\n", ret
);
4222 SetLastError(0xdeadbeef);
4223 ret
= pIdnToNameprepUnicode(0, test_data
[1].in
,
4224 test_data
[1].in_len
, NULL
, 0);
4225 err
= GetLastError();
4226 ok(ret
== test_data
[1].ret
, "ret = %d\n", ret
);
4227 ok(err
== test_data
[1].err
, "err = %d\n", err
);
4229 SetLastError(0xdeadbeef);
4230 ret
= pIdnToNameprepUnicode(0, test_data
[0].in
, -1,
4231 buf
, sizeof(buf
)/sizeof(WCHAR
));
4232 err
= GetLastError();
4233 ok(ret
== test_data
[0].ret
, "ret = %d\n", ret
);
4234 ok(err
== 0xdeadbeef, "err = %d\n", err
);
4236 SetLastError(0xdeadbeef);
4237 ret
= pIdnToNameprepUnicode(0, test_data
[0].in
, -2,
4238 buf
, sizeof(buf
)/sizeof(WCHAR
));
4239 err
= GetLastError();
4240 ok(ret
== 0, "ret = %d\n", ret
);
4241 ok(err
== ERROR_INVALID_PARAMETER
, "err = %d\n", err
);
4243 SetLastError(0xdeadbeef);
4244 ret
= pIdnToNameprepUnicode(0, test_data
[0].in
, 0,
4245 buf
, sizeof(buf
)/sizeof(WCHAR
));
4246 err
= GetLastError();
4247 ok(ret
== 0, "ret = %d\n", ret
);
4248 ok(err
== ERROR_INVALID_NAME
, "err = %d\n", err
);
4250 ret
= pIdnToNameprepUnicode(IDN_ALLOW_UNASSIGNED
|IDN_USE_STD3_ASCII_RULES
,
4251 test_data
[0].in
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
4252 ok(ret
== test_data
[0].ret
, "ret = %d\n", ret
);
4254 SetLastError(0xdeadbeef);
4255 ret
= pIdnToNameprepUnicode(0, NULL
, 0, NULL
, 0);
4256 err
= GetLastError();
4257 ok(ret
== 0, "ret = %d\n", ret
);
4258 ok(err
== ERROR_INVALID_PARAMETER
, "err = %d\n", err
);
4260 SetLastError(0xdeadbeef);
4261 ret
= pIdnToNameprepUnicode(4, NULL
, 0, NULL
, 0);
4262 err
= GetLastError();
4263 ok(ret
== 0, "ret = %d\n", ret
);
4264 ok(err
== ERROR_INVALID_FLAGS
|| err
== ERROR_INVALID_PARAMETER
/* Win8 */,
4267 for (i
=0; i
<sizeof(test_data
)/sizeof(*test_data
); i
++)
4269 SetLastError(0xdeadbeef);
4270 ret
= pIdnToNameprepUnicode(test_data
[i
].flags
, test_data
[i
].in
,
4271 test_data
[i
].in_len
, buf
, sizeof(buf
)/sizeof(WCHAR
));
4272 err
= GetLastError();
4274 todo_wine_if (test_data
[i
].todo
)
4275 ok(ret
== test_data
[i
].ret
||
4276 broken(ret
== test_data
[i
].broken_ret
), "%d) ret = %d\n", i
, ret
);
4278 if(ret
!= test_data
[i
].ret
)
4281 ok(err
== test_data
[i
].err
, "%d) err = %d\n", i
, err
);
4282 ok(!memcmp(test_data
[i
].out
, buf
, ret
*sizeof(WCHAR
)),
4283 "%d) buf = %s\n", i
, wine_dbgstr_wn(buf
, ret
));
4287 static void test_IdnToAscii(void)
4293 const WCHAR out
[64];
4298 5, {'T','e','s','t',0},
4299 5, {'T','e','s','t',0},
4303 5, {'T','e',0x017c,'s','t',0},
4304 12, {'x','n','-','-','t','e','s','t','-','c','b','b',0},
4308 12, {'t','e',0x0105,'s','t','.','t','e',0x017c,'s','t',0},
4309 26, {'x','n','-','-','t','e','s','t','-','c','t','a','.','x','n','-','-','t','e','s','t','-','c','b','b',0},
4314 9, {'x','n','-','-','2','d','a','.',0},
4318 10, {'h','t','t','p',':','/','/','t',0x0106,0},
4319 17, {'x','n','-','-','h','t','t','p',':','/','/','t','-','7','8','a',0},
4323 10, {0x4e3a,0x8bf4,0x4e0d,0x4ed6,0x5011,0x10d,0x11b,0x305c,0x306a,0},
4324 35, {'x','n','-','-','b','e','a','2','a','1','6','3','1','a','v','b','a',
4325 'v','4','4','t','y','h','a','3','2','b','9','1','e','g','s','2','t',0},
4330 8, {'x','n','-','-','6','l','a',0},
4331 IDN_ALLOW_UNASSIGNED
, 0xdeadbeef
4340 win_skip("IdnToAscii is not available\n");
4344 for (i
=0; i
<sizeof(test_data
)/sizeof(*test_data
); i
++)
4346 SetLastError(0xdeadbeef);
4347 ret
= pIdnToAscii(test_data
[i
].flags
, test_data
[i
].in
,
4348 test_data
[i
].in_len
, buf
, sizeof(buf
));
4349 err
= GetLastError();
4350 ok(ret
== test_data
[i
].ret
, "%d) ret = %d\n", i
, ret
);
4351 ok(err
== test_data
[i
].err
, "%d) err = %d\n", i
, err
);
4352 ok(!memcmp(test_data
[i
].out
, buf
, ret
*sizeof(WCHAR
)),
4353 "%d) buf = %s\n", i
, wine_dbgstr_wn(buf
, ret
));
4357 static void test_IdnToUnicode(void)
4363 const WCHAR out
[64];
4368 5, {'T','e','s','.',0},
4369 5, {'T','e','s','.',0},
4375 0, ERROR_INVALID_NAME
4378 33, {'x','n','-','-','4','d','b','c','a','g','d','a','h','y','m','b',
4379 'x','e','k','h','e','h','6','e','0','a','7','f','e','i','0','b',0},
4380 23, {0x05dc,0x05de,0x05d4,0x05d4,0x05dd,0x05e4,0x05e9,0x05d5,0x05d8,
4381 0x05dc,0x05d0,0x05de,0x05d3,0x05d1,0x05e8,0x05d9,0x05dd,0x05e2,
4382 0x05d1,0x05e8,0x05d9,0x05ea,0},
4386 34, {'t','e','s','t','.','x','n','-','-','k','d','a','9','a','g','5','e',
4387 '9','j','n','f','s','j','.','x','n','-','-','p','d','-','f','n','a'},
4388 16, {'t','e','s','t','.',0x0105,0x0119,0x015b,0x0107,
4389 0x0142,0x00f3,0x017c,'.','p',0x0119,'d'},
4393 64, {'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4394 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4395 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
4396 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a'},
4398 0, ERROR_INVALID_NAME
4401 8, {'x','n','-','-','6','l','a',0},
4403 IDN_ALLOW_UNASSIGNED
, 0xdeadbeef
4412 win_skip("IdnToUnicode is not available\n");
4416 for (i
=0; i
<sizeof(test_data
)/sizeof(*test_data
); i
++)
4418 ret
= pIdnToUnicode(test_data
[i
].flags
, test_data
[i
].in
,
4419 test_data
[i
].in_len
, NULL
, 0);
4420 ok(ret
== test_data
[i
].ret
, "%d) ret = %d\n", i
, ret
);
4422 SetLastError(0xdeadbeef);
4423 ret
= pIdnToUnicode(test_data
[i
].flags
, test_data
[i
].in
,
4424 test_data
[i
].in_len
, buf
, sizeof(buf
));
4425 err
= GetLastError();
4426 ok(ret
== test_data
[i
].ret
, "%d) ret = %d\n", i
, ret
);
4427 ok(err
== test_data
[i
].err
, "%d) err = %d\n", i
, err
);
4428 ok(!memcmp(test_data
[i
].out
, buf
, ret
*sizeof(WCHAR
)),
4429 "%d) buf = %s\n", i
, wine_dbgstr_wn(buf
, ret
));
4433 static void test_GetLocaleInfoEx(void)
4435 static const WCHAR enW
[] = {'e','n',0};
4436 WCHAR bufferW
[80], buffer2
[80];
4439 if (!pGetLocaleInfoEx
)
4441 win_skip("GetLocaleInfoEx not supported\n");
4445 ret
= pGetLocaleInfoEx(enW
, LOCALE_SNAME
, bufferW
, sizeof(bufferW
)/sizeof(WCHAR
));
4446 ok(ret
|| broken(ret
== 0) /* Vista */, "got %d\n", ret
);
4449 static const WCHAR statesW
[] = {'U','n','i','t','e','d',' ','S','t','a','t','e','s',0};
4450 static const WCHAR dummyW
[] = {'d','u','m','m','y',0};
4451 static const WCHAR enusW
[] = {'e','n','-','U','S',0};
4452 static const WCHAR usaW
[] = {'U','S','A',0};
4453 static const WCHAR enuW
[] = {'E','N','U',0};
4454 const struct neutralsublang_name_t
*ptr
= neutralsublang_names
;
4457 ok(ret
== lstrlenW(bufferW
)+1, "got %d\n", ret
);
4458 ok(!lstrcmpW(bufferW
, enW
), "got %s\n", wine_dbgstr_w(bufferW
));
4460 SetLastError(0xdeadbeef);
4461 ret
= pGetLocaleInfoEx(enW
, LOCALE_SNAME
, bufferW
, 2);
4462 ok(!ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "got %d, %d\n", ret
, GetLastError());
4464 SetLastError(0xdeadbeef);
4465 ret
= pGetLocaleInfoEx(enW
, LOCALE_SNAME
, NULL
, 0);
4466 ok(ret
== 3 && GetLastError() == 0xdeadbeef, "got %d, %d\n", ret
, GetLastError());
4468 ret
= pGetLocaleInfoEx(enusW
, LOCALE_SNAME
, bufferW
, sizeof(bufferW
)/sizeof(WCHAR
));
4469 ok(ret
== lstrlenW(bufferW
)+1, "got %d\n", ret
);
4470 ok(!lstrcmpW(bufferW
, enusW
), "got %s\n", wine_dbgstr_w(bufferW
));
4472 ret
= pGetLocaleInfoEx(enW
, LOCALE_SABBREVCTRYNAME
, bufferW
, sizeof(bufferW
)/sizeof(WCHAR
));
4473 ok(ret
== lstrlenW(bufferW
)+1, "got %d\n", ret
);
4474 ok(!lstrcmpW(bufferW
, usaW
), "got %s\n", wine_dbgstr_w(bufferW
));
4476 ret
= pGetLocaleInfoEx(enW
, LOCALE_SABBREVLANGNAME
, bufferW
, sizeof(bufferW
)/sizeof(WCHAR
));
4477 ok(ret
== lstrlenW(bufferW
)+1, "got %d\n", ret
);
4478 ok(!lstrcmpW(bufferW
, enuW
), "got %s\n", wine_dbgstr_w(bufferW
));
4480 ret
= pGetLocaleInfoEx(enW
, LOCALE_SCOUNTRY
, bufferW
, sizeof(bufferW
)/sizeof(WCHAR
));
4481 ok(ret
== lstrlenW(bufferW
)+1, "got %d\n", ret
);
4482 if ((PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID())) != LANG_ENGLISH
) ||
4483 (PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale())) != LANG_ENGLISH
))
4485 skip("Non-English locale\n");
4488 ok(!lstrcmpW(bufferW
, statesW
), "got %s\n", wine_dbgstr_w(bufferW
));
4491 SetLastError(0xdeadbeef);
4492 ret
= pGetLocaleInfoEx(dummyW
, LOCALE_SNAME
, bufferW
, sizeof(bufferW
)/sizeof(WCHAR
));
4493 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "got %d, error %d\n", ret
, GetLastError());
4498 pGetLocaleInfoEx(ptr
->name
, LOCALE_ILANGUAGE
|LOCALE_RETURN_NUMBER
, (WCHAR
*)&val
, sizeof(val
)/sizeof(WCHAR
));
4499 todo_wine_if (ptr
->todo
)
4500 ok(val
== ptr
->lcid
, "%s: got wrong lcid 0x%04x, expected 0x%04x\n", wine_dbgstr_w(ptr
->name
), val
, ptr
->lcid
);
4502 ret
= pGetLocaleInfoEx(ptr
->name
, LOCALE_SNAME
, bufferW
, sizeof(bufferW
)/sizeof(WCHAR
));
4503 ok(ret
== lstrlenW(bufferW
)+1, "%s: got ret value %d\n", wine_dbgstr_w(ptr
->name
), ret
);
4504 ok(!lstrcmpW(bufferW
, ptr
->name
), "%s: got wrong LOCALE_SNAME %s\n", wine_dbgstr_w(ptr
->name
), wine_dbgstr_w(bufferW
));
4508 ret
= pGetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT
, LOCALE_SNAME
, bufferW
, sizeof(bufferW
)/sizeof(WCHAR
));
4509 ok(ret
&& ret
== lstrlenW(bufferW
)+1, "got ret value %d\n", ret
);
4510 ret
= GetLocaleInfoW(GetUserDefaultLCID(), LOCALE_SNAME
, buffer2
, sizeof(buffer2
)/sizeof(WCHAR
));
4511 ok(ret
&& ret
== lstrlenW(buffer2
)+1, "got ret value %d\n", ret
);
4512 ok(!lstrcmpW(bufferW
, buffer2
), "LOCALE_SNAMEs don't match %s %s\n", wine_dbgstr_w(bufferW
), wine_dbgstr_w(buffer2
));
4516 static void test_IsValidLocaleName(void)
4518 static const WCHAR enusW
[] = {'e','n','-','U','S',0};
4519 static const WCHAR zzW
[] = {'z','z',0};
4520 static const WCHAR zz_zzW
[] = {'z','z','-','Z','Z',0};
4521 static const WCHAR zzzzW
[] = {'z','z','z','z',0};
4524 if (!pIsValidLocaleName
)
4526 win_skip("IsValidLocaleName not supported\n");
4530 ret
= pIsValidLocaleName(enusW
);
4531 ok(ret
, "IsValidLocaleName failed\n");
4532 ret
= pIsValidLocaleName(zzW
);
4533 ok(!ret
|| broken(ret
), "IsValidLocaleName should have failed\n");
4534 ret
= pIsValidLocaleName(zz_zzW
);
4535 ok(!ret
|| broken(ret
), "IsValidLocaleName should have failed\n");
4536 ret
= pIsValidLocaleName(zzzzW
);
4537 ok(!ret
, "IsValidLocaleName should have failed\n");
4538 ret
= pIsValidLocaleName(LOCALE_NAME_INVARIANT
);
4539 ok(ret
, "IsValidLocaleName failed\n");
4540 ret
= pIsValidLocaleName(NULL
);
4541 ok(!ret
, "IsValidLocaleName should have failed\n");
4544 static void test_CompareStringOrdinal(void)
4547 WCHAR test1
[] = { 't','e','s','t',0 };
4548 WCHAR test2
[] = { 'T','e','S','t',0 };
4549 WCHAR test3
[] = { 't','e','s','t','3',0 };
4550 WCHAR null1
[] = { 'a',0,'a',0 };
4551 WCHAR null2
[] = { 'a',0,'b',0 };
4552 WCHAR bills1
[] = { 'b','i','l','l','\'','s',0 };
4553 WCHAR bills2
[] = { 'b','i','l','l','s',0 };
4554 WCHAR coop1
[] = { 'c','o','-','o','p',0 };
4555 WCHAR coop2
[] = { 'c','o','o','p',0 };
4556 WCHAR nonascii1
[] = { 0x0102,0 };
4557 WCHAR nonascii2
[] = { 0x0201,0 };
4560 if (!pCompareStringOrdinal
)
4562 win_skip("CompareStringOrdinal not supported\n");
4567 SetLastError(0xdeadbeef);
4568 ret
= pCompareStringOrdinal(NULL
, 0, NULL
, 0, FALSE
);
4569 ok(!ret
, "Got %u, expected 0\n", ret
);
4570 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Got %x, expected %x\n", GetLastError(), ERROR_INVALID_PARAMETER
);
4571 SetLastError(0xdeadbeef);
4572 ret
= pCompareStringOrdinal(test1
, -1, NULL
, 0, FALSE
);
4573 ok(!ret
, "Got %u, expected 0\n", ret
);
4574 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Got %x, expected %x\n", GetLastError(), ERROR_INVALID_PARAMETER
);
4575 SetLastError(0xdeadbeef);
4576 ret
= pCompareStringOrdinal(NULL
, 0, test1
, -1, FALSE
);
4577 ok(!ret
, "Got %u, expected 0\n", ret
);
4578 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Got %x, expected %x\n", GetLastError(), ERROR_INVALID_PARAMETER
);
4581 ret
= pCompareStringOrdinal(test1
, -1, test1
, -1, FALSE
);
4582 ok(ret
== CSTR_EQUAL
, "Got %u, expected %u\n", ret
, CSTR_EQUAL
);
4583 ret
= pCompareStringOrdinal(test1
, -1, test2
, -1, FALSE
);
4584 ok(ret
== CSTR_GREATER_THAN
, "Got %u, expected %u\n", ret
, CSTR_GREATER_THAN
);
4585 ret
= pCompareStringOrdinal(test2
, -1, test1
, -1, FALSE
);
4586 ok(ret
== CSTR_LESS_THAN
, "Got %u, expected %u\n", ret
, CSTR_LESS_THAN
);
4587 ret
= pCompareStringOrdinal(test1
, -1, test2
, -1, TRUE
);
4588 ok(ret
== CSTR_EQUAL
, "Got %u, expected %u\n", ret
, CSTR_EQUAL
);
4590 /* Check different sizes */
4591 ret
= pCompareStringOrdinal(test1
, 3, test2
, -1, TRUE
);
4592 ok(ret
== CSTR_LESS_THAN
, "Got %u, expected %u\n", ret
, CSTR_LESS_THAN
);
4593 ret
= pCompareStringOrdinal(test1
, -1, test2
, 3, TRUE
);
4594 ok(ret
== CSTR_GREATER_THAN
, "Got %u, expected %u\n", ret
, CSTR_GREATER_THAN
);
4596 /* Check null character */
4597 ret
= pCompareStringOrdinal(null1
, 3, null2
, 3, FALSE
);
4598 ok(ret
== CSTR_LESS_THAN
, "Got %u, expected %u\n", ret
, CSTR_LESS_THAN
);
4599 ret
= pCompareStringOrdinal(null1
, 3, null2
, 3, TRUE
);
4600 ok(ret
== CSTR_LESS_THAN
, "Got %u, expected %u\n", ret
, CSTR_LESS_THAN
);
4601 ret
= pCompareStringOrdinal(test1
, 5, test3
, 5, FALSE
);
4602 ok(ret
== CSTR_LESS_THAN
, "Got %u, expected %u\n", ret
, CSTR_LESS_THAN
);
4603 ret
= pCompareStringOrdinal(test1
, 4, test1
, 5, FALSE
);
4604 ok(ret
== CSTR_LESS_THAN
, "Got %u, expected %u\n", ret
, CSTR_LESS_THAN
);
4606 /* Check ordinal behaviour */
4607 ret
= pCompareStringOrdinal(bills1
, -1, bills2
, -1, FALSE
);
4608 ok(ret
== CSTR_LESS_THAN
, "Got %u, expected %u\n", ret
, CSTR_LESS_THAN
);
4609 ret
= pCompareStringOrdinal(coop2
, -1, coop1
, -1, FALSE
);
4610 ok(ret
== CSTR_GREATER_THAN
, "Got %u, expected %u\n", ret
, CSTR_GREATER_THAN
);
4611 ret
= pCompareStringOrdinal(nonascii1
, -1, nonascii2
, -1, FALSE
);
4612 ok(ret
== CSTR_LESS_THAN
, "Got %u, expected %u\n", ret
, CSTR_LESS_THAN
);
4613 ret
= pCompareStringOrdinal(nonascii1
, -1, nonascii2
, -1, TRUE
);
4614 ok(ret
== CSTR_LESS_THAN
, "Got %u, expected %u\n", ret
, CSTR_LESS_THAN
);
4616 for (ch1
= 0; ch1
< 512; ch1
++)
4618 for (ch2
= 0; ch2
< 1024; ch2
++)
4620 int diff
= ch1
- ch2
;
4621 ret
= pCompareStringOrdinal( &ch1
, 1, &ch2
, 1, FALSE
);
4622 ok( ret
== (diff
> 0 ? CSTR_GREATER_THAN
: diff
< 0 ? CSTR_LESS_THAN
: CSTR_EQUAL
),
4623 "wrong result %d %04x %04x\n", ret
, ch1
, ch2
);
4624 diff
= pRtlUpcaseUnicodeChar( ch1
) - pRtlUpcaseUnicodeChar( ch2
);
4625 ret
= pCompareStringOrdinal( &ch1
, 1, &ch2
, 1, TRUE
);
4626 ok( ret
== (diff
> 0 ? CSTR_GREATER_THAN
: diff
< 0 ? CSTR_LESS_THAN
: CSTR_EQUAL
),
4627 "wrong result %d %04x %04x\n", ret
, ch1
, ch2
);
4632 static void test_GetGeoInfo(void)
4639 win_skip("GetGeoInfo is not available.\n");
4644 SetLastError(0xdeadbeef);
4645 ret
= pGetGeoInfoA(344, GEO_ISO2
, NULL
, 0, 0);
4646 ok(ret
== 0, "got %d\n", ret
);
4647 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %d\n", GetLastError());
4649 ret
= pGetGeoInfoA(203, GEO_ISO2
, NULL
, 0, 0);
4650 ok(ret
== 3, "got %d\n", ret
);
4652 ret
= pGetGeoInfoA(203, GEO_ISO3
, NULL
, 0, 0);
4653 ok(ret
== 4, "got %d\n", ret
);
4655 ret
= pGetGeoInfoA(203, GEO_ISO2
, buffA
, 3, 0);
4656 ok(ret
== 3, "got %d\n", ret
);
4657 ok(!strcmp(buffA
, "RU"), "got %s\n", buffA
);
4659 /* buffer pointer not NULL, length is 0 - return required length */
4661 SetLastError(0xdeadbeef);
4662 ret
= pGetGeoInfoA(203, GEO_ISO2
, buffA
, 0, 0);
4663 ok(ret
== 3, "got %d\n", ret
);
4664 ok(buffA
[0] == 'a', "got %c\n", buffA
[0]);
4666 ret
= pGetGeoInfoA(203, GEO_ISO3
, buffA
, 4, 0);
4667 ok(ret
== 4, "got %d\n", ret
);
4668 ok(!strcmp(buffA
, "RUS"), "got %s\n", buffA
);
4670 /* shorter buffer */
4671 SetLastError(0xdeadbeef);
4672 buffA
[1] = buffA
[2] = 0;
4673 ret
= pGetGeoInfoA(203, GEO_ISO2
, buffA
, 2, 0);
4674 ok(ret
== 0, "got %d\n", ret
);
4675 ok(!strcmp(buffA
, "RU"), "got %s\n", buffA
);
4676 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "got %d\n", GetLastError());
4678 /* GEO_NATION returns GEOID in a string form */
4680 ret
= pGetGeoInfoA(203, GEO_NATION
, buffA
, 20, 0);
4681 ok(ret
== 4, "got %d\n", ret
);
4682 ok(!strcmp(buffA
, "203"), "got %s\n", buffA
);
4686 ret
= pGetGeoInfoA(203, GEO_PARENT
, buffA
, 20, 0);
4688 win_skip("GEO_PARENT not supported.\n");
4691 ok(ret
== 6, "got %d\n", ret
);
4692 ok(!strcmp(buffA
, "47609"), "got %s\n", buffA
);
4696 ret
= pGetGeoInfoA(203, GEO_ISO_UN_NUMBER
, buffA
, 20, 0);
4698 win_skip("GEO_ISO_UN_NUMBER not supported.\n");
4701 ok(ret
== 4, "got %d\n", ret
);
4702 ok(!strcmp(buffA
, "643"), "got %s\n", buffA
);
4705 /* try invalid type value */
4706 SetLastError(0xdeadbeef);
4707 ret
= pGetGeoInfoA(203, GEO_CURRENCYSYMBOL
+ 1, NULL
, 0, 0);
4708 ok(ret
== 0, "got %d\n", ret
);
4709 ok(GetLastError() == ERROR_INVALID_FLAGS
, "got %d\n", GetLastError());
4712 static int geoidenum_count
;
4713 static BOOL CALLBACK
test_geoid_enumproc(GEOID geoid
)
4715 INT ret
= pGetGeoInfoA(geoid
, GEO_ISO2
, NULL
, 0, 0);
4716 ok(ret
== 3, "got %d for %d\n", ret
, geoid
);
4717 /* valid geoid starts at 2 */
4718 ok(geoid
>= 2, "got geoid %d\n", geoid
);
4720 return geoidenum_count
++ < 5;
4723 static BOOL CALLBACK
test_geoid_enumproc2(GEOID geoid
)
4729 static void test_EnumSystemGeoID(void)
4733 if (!pEnumSystemGeoID
)
4735 win_skip("EnumSystemGeoID is not available.\n");
4739 SetLastError(0xdeadbeef);
4740 ret
= pEnumSystemGeoID(GEOCLASS_NATION
, 0, NULL
);
4741 ok(!ret
, "got %d\n", ret
);
4742 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %d\n", GetLastError());
4744 SetLastError(0xdeadbeef);
4745 ret
= pEnumSystemGeoID(GEOCLASS_NATION
+1, 0, test_geoid_enumproc
);
4746 ok(!ret
, "got %d\n", ret
);
4747 ok(GetLastError() == ERROR_INVALID_FLAGS
, "got %d\n", GetLastError());
4749 SetLastError(0xdeadbeef);
4750 ret
= pEnumSystemGeoID(GEOCLASS_NATION
+1, 0, NULL
);
4751 ok(!ret
, "got %d\n", ret
);
4752 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %d\n", GetLastError());
4754 ret
= pEnumSystemGeoID(GEOCLASS_NATION
, 0, test_geoid_enumproc
);
4755 ok(ret
, "got %d\n", ret
);
4757 /* only the first level is enumerated, not the whole hierarchy */
4758 geoidenum_count
= 0;
4759 ret
= pEnumSystemGeoID(GEOCLASS_NATION
, 39070, test_geoid_enumproc2
);
4761 win_skip("Parent GEOID is not supported in EnumSystemGeoID.\n");
4763 ok(ret
&& geoidenum_count
> 0, "got %d, count %d\n", ret
, geoidenum_count
);
4765 geoidenum_count
= 0;
4766 ret
= pEnumSystemGeoID(GEOCLASS_REGION
, 39070, test_geoid_enumproc2
);
4768 win_skip("GEOCLASS_REGION is not supported in EnumSystemGeoID.\n");
4771 ok(ret
&& geoidenum_count
> 0, "got %d, count %d\n", ret
, geoidenum_count
);
4773 geoidenum_count
= 0;
4774 ret
= pEnumSystemGeoID(GEOCLASS_REGION
, 0, test_geoid_enumproc2
);
4775 ok(ret
&& geoidenum_count
> 0, "got %d, count %d\n", ret
, geoidenum_count
);
4779 struct invariant_entry
{
4782 const char *expect
, *expect2
;
4786 static const struct invariant_entry invariant_list
[] = {
4787 { X(LOCALE_ILANGUAGE
), "007f" },
4788 { X(LOCALE_SENGLANGUAGE
), "Invariant Language" },
4789 { X(LOCALE_SABBREVLANGNAME
), "IVL" },
4790 { X(LOCALE_SNATIVELANGNAME
), "Invariant Language" },
4791 { X(LOCALE_ICOUNTRY
), "1" },
4792 { X(LOCALE_SENGCOUNTRY
), "Invariant Country" },
4793 { X(LOCALE_SABBREVCTRYNAME
), "IVC", "" },
4794 { X(LOCALE_SNATIVECTRYNAME
), "Invariant Country" },
4795 { X(LOCALE_IDEFAULTLANGUAGE
), "0409" },
4796 { X(LOCALE_IDEFAULTCOUNTRY
), "1" },
4797 { X(LOCALE_IDEFAULTCODEPAGE
), "437" },
4798 { X(LOCALE_IDEFAULTANSICODEPAGE
), "1252" },
4799 { X(LOCALE_IDEFAULTMACCODEPAGE
), "10000" },
4800 { X(LOCALE_SLIST
), "," },
4801 { X(LOCALE_IMEASURE
), "0" },
4802 { X(LOCALE_SDECIMAL
), "." },
4803 { X(LOCALE_STHOUSAND
), "," },
4804 { X(LOCALE_SGROUPING
), "3;0" },
4805 { X(LOCALE_IDIGITS
), "2" },
4806 { X(LOCALE_ILZERO
), "1" },
4807 { X(LOCALE_INEGNUMBER
), "1" },
4808 { X(LOCALE_SNATIVEDIGITS
), "0123456789" },
4809 { X(LOCALE_SCURRENCY
), "\x00a4" },
4810 { X(LOCALE_SINTLSYMBOL
), "XDR" },
4811 { X(LOCALE_SMONDECIMALSEP
), "." },
4812 { X(LOCALE_SMONTHOUSANDSEP
), "," },
4813 { X(LOCALE_SMONGROUPING
), "3;0" },
4814 { X(LOCALE_ICURRDIGITS
), "2" },
4815 { X(LOCALE_IINTLCURRDIGITS
), "2" },
4816 { X(LOCALE_ICURRENCY
), "0" },
4817 { X(LOCALE_INEGCURR
), "0" },
4818 { X(LOCALE_SDATE
), "/" },
4819 { X(LOCALE_STIME
), ":" },
4820 { X(LOCALE_SSHORTDATE
), "MM/dd/yyyy" },
4821 { X(LOCALE_SLONGDATE
), "dddd, dd MMMM yyyy" },
4822 { X(LOCALE_STIMEFORMAT
), "HH:mm:ss" },
4823 { X(LOCALE_IDATE
), "0" },
4824 { X(LOCALE_ILDATE
), "1" },
4825 { X(LOCALE_ITIME
), "1" },
4826 { X(LOCALE_ITIMEMARKPOSN
), "0" },
4827 { X(LOCALE_ICENTURY
), "1" },
4828 { X(LOCALE_ITLZERO
), "1" },
4829 { X(LOCALE_IDAYLZERO
), "1" },
4830 { X(LOCALE_IMONLZERO
), "1" },
4831 { X(LOCALE_S1159
), "AM" },
4832 { X(LOCALE_S2359
), "PM" },
4833 { X(LOCALE_ICALENDARTYPE
), "1" },
4834 { X(LOCALE_IOPTIONALCALENDAR
), "0" },
4835 { X(LOCALE_IFIRSTDAYOFWEEK
), "6" },
4836 { X(LOCALE_IFIRSTWEEKOFYEAR
), "0" },
4837 { X(LOCALE_SDAYNAME1
), "Monday" },
4838 { X(LOCALE_SDAYNAME2
), "Tuesday" },
4839 { X(LOCALE_SDAYNAME3
), "Wednesday" },
4840 { X(LOCALE_SDAYNAME4
), "Thursday" },
4841 { X(LOCALE_SDAYNAME5
), "Friday" },
4842 { X(LOCALE_SDAYNAME6
), "Saturday" },
4843 { X(LOCALE_SDAYNAME7
), "Sunday" },
4844 { X(LOCALE_SABBREVDAYNAME1
), "Mon" },
4845 { X(LOCALE_SABBREVDAYNAME2
), "Tue" },
4846 { X(LOCALE_SABBREVDAYNAME3
), "Wed" },
4847 { X(LOCALE_SABBREVDAYNAME4
), "Thu" },
4848 { X(LOCALE_SABBREVDAYNAME5
), "Fri" },
4849 { X(LOCALE_SABBREVDAYNAME6
), "Sat" },
4850 { X(LOCALE_SABBREVDAYNAME7
), "Sun" },
4851 { X(LOCALE_SMONTHNAME1
), "January" },
4852 { X(LOCALE_SMONTHNAME2
), "February" },
4853 { X(LOCALE_SMONTHNAME3
), "March" },
4854 { X(LOCALE_SMONTHNAME4
), "April" },
4855 { X(LOCALE_SMONTHNAME5
), "May" },
4856 { X(LOCALE_SMONTHNAME6
), "June" },
4857 { X(LOCALE_SMONTHNAME7
), "July" },
4858 { X(LOCALE_SMONTHNAME8
), "August" },
4859 { X(LOCALE_SMONTHNAME9
), "September" },
4860 { X(LOCALE_SMONTHNAME10
), "October" },
4861 { X(LOCALE_SMONTHNAME11
), "November" },
4862 { X(LOCALE_SMONTHNAME12
), "December" },
4863 { X(LOCALE_SMONTHNAME13
), "" },
4864 { X(LOCALE_SABBREVMONTHNAME1
), "Jan" },
4865 { X(LOCALE_SABBREVMONTHNAME2
), "Feb" },
4866 { X(LOCALE_SABBREVMONTHNAME3
), "Mar" },
4867 { X(LOCALE_SABBREVMONTHNAME4
), "Apr" },
4868 { X(LOCALE_SABBREVMONTHNAME5
), "May" },
4869 { X(LOCALE_SABBREVMONTHNAME6
), "Jun" },
4870 { X(LOCALE_SABBREVMONTHNAME7
), "Jul" },
4871 { X(LOCALE_SABBREVMONTHNAME8
), "Aug" },
4872 { X(LOCALE_SABBREVMONTHNAME9
), "Sep" },
4873 { X(LOCALE_SABBREVMONTHNAME10
), "Oct" },
4874 { X(LOCALE_SABBREVMONTHNAME11
), "Nov" },
4875 { X(LOCALE_SABBREVMONTHNAME12
), "Dec" },
4876 { X(LOCALE_SABBREVMONTHNAME13
), "" },
4877 { X(LOCALE_SPOSITIVESIGN
), "+" },
4878 { X(LOCALE_SNEGATIVESIGN
), "-" },
4879 { X(LOCALE_IPOSSIGNPOSN
), "3" },
4880 { X(LOCALE_INEGSIGNPOSN
), "0" },
4881 { X(LOCALE_IPOSSYMPRECEDES
), "1" },
4882 { X(LOCALE_IPOSSEPBYSPACE
), "0" },
4883 { X(LOCALE_INEGSYMPRECEDES
), "1" },
4884 { X(LOCALE_INEGSEPBYSPACE
), "0" },
4885 { X(LOCALE_SISO639LANGNAME
), "iv" },
4886 { X(LOCALE_SISO3166CTRYNAME
), "IV" },
4887 { X(LOCALE_IDEFAULTEBCDICCODEPAGE
), "037" },
4888 { X(LOCALE_IPAPERSIZE
), "9" },
4889 { X(LOCALE_SENGCURRNAME
), "International Monetary Fund" },
4890 { X(LOCALE_SNATIVECURRNAME
), "International Monetary Fund" },
4891 { X(LOCALE_SYEARMONTH
), "yyyy MMMM" },
4892 { X(LOCALE_IDIGITSUBSTITUTION
), "1" },
4893 { X(LOCALE_SNAME
), "" },
4894 { X(LOCALE_SSCRIPTS
), "Latn;" },
4899 static void test_invariant(void)
4903 char buffer
[BUFFER_SIZE
];
4904 const struct invariant_entry
*ptr
= invariant_list
;
4906 if (!GetLocaleInfoA(LOCALE_INVARIANT
, NUO
|LOCALE_SLANGUAGE
, buffer
, sizeof(buffer
)))
4908 win_skip("GetLocaleInfoA(LOCALE_INVARIANT) not supported\n"); /* win2k */
4914 ret
= GetLocaleInfoA(LOCALE_INVARIANT
, NUO
|ptr
->id
, buffer
, sizeof(buffer
));
4915 if (!ret
&& (ptr
->id
== LOCALE_SNAME
|| ptr
->id
== LOCALE_SSCRIPTS
))
4916 win_skip("not supported\n"); /* winxp/win2k3 */
4919 len
= strlen(ptr
->expect
)+1; /* include \0 */
4920 ok(ret
== len
|| (ptr
->expect2
&& ret
== strlen(ptr
->expect2
)+1),
4921 "For id %d, expected ret == %d, got %d, error %d\n",
4922 ptr
->id
, len
, ret
, GetLastError());
4923 ok(!strcmp(buffer
, ptr
->expect
) || (ptr
->expect2
&& !strcmp(buffer
, ptr
->expect2
)),
4924 "For id %d, Expected %s, got '%s'\n",
4925 ptr
->id
, ptr
->expect
, buffer
);
4931 if ((LANGIDFROMLCID(GetSystemDefaultLCID()) != MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
)) ||
4932 (LANGIDFROMLCID(GetThreadLocale()) != MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
)))
4934 skip("Non US-English locale\n");
4938 /* some locales translate these */
4939 static const char lang
[] = "Invariant Language (Invariant Country)";
4940 static const char cntry
[] = "Invariant Country";
4941 static const char sortm
[] = "Math Alphanumerics";
4942 static const char sortd
[] = "Default"; /* win2k3 */
4944 ret
= GetLocaleInfoA(LOCALE_INVARIANT
, NUO
|LOCALE_SLANGUAGE
, buffer
, sizeof(buffer
));
4945 len
= lstrlenA(lang
) + 1;
4946 ok(ret
== len
, "Expected ret == %d, got %d, error %d\n", len
, ret
, GetLastError());
4947 ok(!strcmp(buffer
, lang
), "Expected %s, got '%s'\n", lang
, buffer
);
4949 ret
= GetLocaleInfoA(LOCALE_INVARIANT
, NUO
|LOCALE_SCOUNTRY
, buffer
, sizeof(buffer
));
4950 len
= lstrlenA(cntry
) + 1;
4951 ok(ret
== len
, "Expected ret == %d, got %d, error %d\n", len
, ret
, GetLastError());
4952 ok(!strcmp(buffer
, cntry
), "Expected %s, got '%s'\n", cntry
, buffer
);
4954 ret
= GetLocaleInfoA(LOCALE_INVARIANT
, NUO
|LOCALE_SSORTNAME
, buffer
, sizeof(buffer
));
4955 if (ret
== lstrlenA(sortm
)+1)
4956 ok(!strcmp(buffer
, sortm
), "Expected %s, got '%s'\n", sortm
, buffer
);
4957 else if (ret
== lstrlenA(sortd
)+1) /* win2k3 */
4958 ok(!strcmp(buffer
, sortd
), "Expected %s, got '%s'\n", sortd
, buffer
);
4960 ok(0, "Expected ret == %d or %d, got %d, error %d\n",
4961 lstrlenA(sortm
)+1, lstrlenA(sortd
)+1, ret
, GetLastError());
4965 static void test_GetSystemPreferredUILanguages(void)
4968 ULONG count
, size
, size_id
, size_name
, size_buffer
;
4972 if (!pGetSystemPreferredUILanguages
)
4974 win_skip("GetSystemPreferredUILanguages is not available.\n");
4978 /* (in)valid first parameter */
4981 SetLastError(0xdeadbeef);
4982 ret
= pGetSystemPreferredUILanguages(0, &count
, NULL
, &size
);
4983 ok(ret
, "Expected GetSystemPreferredUILanguages to succeed\n");
4984 ok(count
, "Expected count > 0\n");
4985 ok(size
% 6 == 1, "Expected size (%d) %% 6 == 1\n", size
);
4989 SetLastError(0xdeadbeef);
4990 ret
= pGetSystemPreferredUILanguages(MUI_FULL_LANGUAGE
, &count
, NULL
, &size
);
4991 ok(!ret
, "Expected GetSystemPreferredUILanguages to fail\n");
4992 ok(ERROR_INVALID_PARAMETER
== GetLastError(),
4993 "Expected error ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
4997 SetLastError(0xdeadbeef);
4998 ret
= pGetSystemPreferredUILanguages(MUI_LANGUAGE_ID
| MUI_FULL_LANGUAGE
, &count
, NULL
, &size
);
4999 ok(!ret
, "Expected GetSystemPreferredUILanguages to fail\n");
5000 ok(ERROR_INVALID_PARAMETER
== GetLastError(),
5001 "Expected error ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
5005 SetLastError(0xdeadbeef);
5006 ret
= pGetSystemPreferredUILanguages(MUI_LANGUAGE_ID
| MUI_LANGUAGE_NAME
, &count
, NULL
, &size
);
5007 ok(!ret
, "Expected GetSystemPreferredUILanguages to fail\n");
5008 ok(ERROR_INVALID_PARAMETER
== GetLastError(),
5009 "Expected error ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
5013 SetLastError(0xdeadbeef);
5014 ret
= pGetSystemPreferredUILanguages(MUI_LANGUAGE_ID
| MUI_MACHINE_LANGUAGE_SETTINGS
, &count
, NULL
, &size
);
5015 ok(ret
, "Expected GetSystemPreferredUILanguages to succeed\n");
5016 ok(count
, "Expected count > 0\n");
5017 ok(size
% 5 == 1, "Expected size (%d) %% 5 == 1\n", size
);
5021 SetLastError(0xdeadbeef);
5022 ret
= pGetSystemPreferredUILanguages(MUI_LANGUAGE_NAME
| MUI_MACHINE_LANGUAGE_SETTINGS
, &count
, NULL
, &size
);
5023 ok(ret
, "Expected GetSystemPreferredUILanguages to succeed\n");
5024 ok(count
, "Expected count > 0\n");
5025 ok(size
% 6 == 1, "Expected size (%d) %% 6 == 1\n", size
);
5028 * ret = pGetSystemPreferredUILanguages(MUI_LANGUAGE_ID, NULL, NULL, &size);
5029 * -> unhandled exception c0000005
5032 /* invalid third parameter */
5035 SetLastError(0xdeadbeef);
5036 ret
= pGetSystemPreferredUILanguages(MUI_LANGUAGE_ID
, &count
, NULL
, &size
);
5037 ok(!ret
, "Expected GetSystemPreferredUILanguages to fail\n");
5038 ok(ERROR_INVALID_PARAMETER
== GetLastError(),
5039 "Expected error ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
5042 * ret = pGetSystemPreferredUILanguages(MUI_LANGUAGE_ID, &count, NULL, NULL);
5043 * -> unhandled exception c0000005
5048 SetLastError(0xdeadbeef);
5049 ret
= pGetSystemPreferredUILanguages(MUI_LANGUAGE_ID
, &count
, NULL
, &size_id
);
5050 ok(ret
, "Expected GetSystemPreferredUILanguages to succeed\n");
5051 ok(count
, "Expected count > 0\n");
5052 ok(size_id
% 5 == 1, "Expected size (%d) %% 5 == 1\n", size_id
);
5056 SetLastError(0xdeadbeef);
5057 ret
= pGetSystemPreferredUILanguages(MUI_LANGUAGE_NAME
, &count
, NULL
, &size_name
);
5058 ok(ret
, "Expected GetSystemPreferredUILanguages to succeed\n");
5059 ok(count
, "Expected count > 0\n");
5060 ok(size_name
% 6 == 1, "Expected size (%d) %% 6 == 1\n", size_name
);
5062 size_buffer
= max(size_id
, size_name
);
5065 skip("No valid buffer size\n");
5069 buffer
= HeapAlloc(GetProcessHeap(), 0, size_buffer
* sizeof(WCHAR
));
5072 skip("Failed to allocate memory for %d chars\n", size_buffer
);
5078 memset(buffer
, 0x5a, size_buffer
* sizeof(WCHAR
));
5079 SetLastError(0xdeadbeef);
5080 ret
= pGetSystemPreferredUILanguages(0, &count
, buffer
, &size
);
5081 ok(ret
, "Expected GetSystemPreferredUILanguages to succeed\n");
5082 ok(count
, "Expected count > 0\n");
5083 ok(size
% 6 == 1, "Expected size (%d) %% 6 == 1\n", size
);
5084 if (ret
&& size
% 6 == 1)
5085 ok(!buffer
[size
-2] && !buffer
[size
-1],
5086 "Expected last two WCHARs being empty, got 0x%x 0x%x\n",
5087 buffer
[size
-2], buffer
[size
-1]);
5091 memset(buffer
, 0x5a, size_buffer
* sizeof(WCHAR
));
5092 SetLastError(0xdeadbeef);
5093 ret
= pGetSystemPreferredUILanguages(MUI_LANGUAGE_ID
, &count
, buffer
, &size
);
5094 ok(ret
, "Expected GetSystemPreferredUILanguages to succeed\n");
5095 ok(count
, "Expected count > 0\n");
5096 ok(size
% 5 == 1, "Expected size (%d) %% 5 == 1\n", size
);
5097 if (ret
&& size
% 5 == 1)
5098 ok(!buffer
[size
-2] && !buffer
[size
-1],
5099 "Expected last two WCHARs being empty, got 0x%x 0x%x\n",
5100 buffer
[size
-2], buffer
[size
-1]);
5104 SetLastError(0xdeadbeef);
5105 ret
= pGetSystemPreferredUILanguages(MUI_LANGUAGE_NAME
, &count
, buffer
, &size
);
5106 ok(ret
, "Expected GetSystemPreferredUILanguages to succeed\n");
5107 ok(count
, "Expected count > 0\n");
5108 ok(size
% 6 == 1, "Expected size (%d) %% 6 == 1\n", size
);
5109 if (ret
&& size
% 5 == 1)
5110 ok(!buffer
[size
-2] && !buffer
[size
-1],
5111 "Expected last two WCHARs being empty, got 0x%x 0x%x\n",
5112 buffer
[size
-2], buffer
[size
-1]);
5116 SetLastError(0xdeadbeef);
5117 ret
= pGetSystemPreferredUILanguages(MUI_MACHINE_LANGUAGE_SETTINGS
, &count
, NULL
, &size
);
5118 ok(ret
, "Expected GetSystemPreferredUILanguages to succeed\n");
5119 ok(count
, "Expected count > 0\n");
5120 ok(size
% 6 == 1, "Expected size (%d) %% 6 == 1\n", size
);
5121 if (ret
&& size
% 6 == 1)
5122 ok(!buffer
[size
-2] && !buffer
[size
-1],
5123 "Expected last two WCHARs being empty, got 0x%x 0x%x\n",
5124 buffer
[size
-2], buffer
[size
-1]);
5128 SetLastError(0xdeadbeef);
5129 ret
= pGetSystemPreferredUILanguages(MUI_LANGUAGE_ID
, &count
, buffer
, &size
);
5130 ok(!ret
, "Expected GetSystemPreferredUILanguages to fail\n");
5131 ok(ERROR_INSUFFICIENT_BUFFER
== GetLastError(),
5132 "Expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
5136 memset(buffer
, 0x5a, size_buffer
* sizeof(WCHAR
));
5137 SetLastError(0xdeadbeef);
5138 ret
= pGetSystemPreferredUILanguages(MUI_LANGUAGE_ID
, &count
, buffer
, &size
);
5139 ok(!ret
, "Expected GetSystemPreferredUILanguages to fail\n");
5140 ok(ERROR_INSUFFICIENT_BUFFER
== GetLastError(),
5141 "Expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
5145 memset(buffer
, 0x5a, size_buffer
* sizeof(WCHAR
));
5146 SetLastError(0xdeadbeef);
5147 ret
= pGetSystemPreferredUILanguages(0, &count
, buffer
, &size
);
5148 ok(!ret
, "Expected GetSystemPreferredUILanguages to fail\n");
5149 ok(ERROR_INSUFFICIENT_BUFFER
== GetLastError(),
5150 "Expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
5152 HeapFree(GetProcessHeap(), 0, buffer
);
5155 static void test_GetThreadPreferredUILanguages(void)
5161 if (!pGetThreadPreferredUILanguages
)
5163 win_skip("GetThreadPreferredUILanguages is not available.\n");
5168 ret
= pGetThreadPreferredUILanguages(MUI_LANGUAGE_ID
|MUI_UI_FALLBACK
, &count
, NULL
, &size
);
5169 ok(ret
, "got %u\n", GetLastError());
5170 ok(count
, "expected count > 0\n");
5171 ok(size
, "expected size > 0\n");
5174 buf
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
* sizeof(WCHAR
));
5175 ret
= pGetThreadPreferredUILanguages(MUI_LANGUAGE_ID
|MUI_UI_FALLBACK
, &count
, buf
, &size
);
5176 ok(ret
, "got %u\n", GetLastError());
5177 ok(count
, "expected count > 0\n");
5178 HeapFree(GetProcessHeap(), 0, buf
);
5181 static void test_GetUserPreferredUILanguages(void)
5184 ULONG count
, size
, size_id
, size_name
, size_buffer
;
5188 if (!pGetUserPreferredUILanguages
)
5190 win_skip("GetUserPreferredUILanguages is not available.\n");
5196 SetLastError(0xdeadbeef);
5197 ret
= pGetUserPreferredUILanguages(MUI_FULL_LANGUAGE
, &count
, NULL
, &size
);
5198 ok(!ret
, "Expected GetUserPreferredUILanguages to fail\n");
5199 ok(ERROR_INVALID_PARAMETER
== GetLastError(),
5200 "Expected error ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
5204 SetLastError(0xdeadbeef);
5205 ret
= pGetUserPreferredUILanguages(MUI_LANGUAGE_ID
| MUI_FULL_LANGUAGE
, &count
, NULL
, &size
);
5206 ok(!ret
, "Expected GetUserPreferredUILanguages to fail\n");
5207 ok(ERROR_INVALID_PARAMETER
== GetLastError(),
5208 "Expected error ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
5212 SetLastError(0xdeadbeef);
5213 ret
= pGetUserPreferredUILanguages(MUI_LANGUAGE_ID
| MUI_MACHINE_LANGUAGE_SETTINGS
, &count
, NULL
, &size
);
5214 ok(!ret
, "Expected GetUserPreferredUILanguages to fail\n");
5215 ok(ERROR_INVALID_PARAMETER
== GetLastError(),
5216 "Expected error ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
5220 SetLastError(0xdeadbeef);
5221 ret
= pGetUserPreferredUILanguages(MUI_LANGUAGE_ID
, &count
, NULL
, &size
);
5222 ok(!ret
, "Expected GetUserPreferredUILanguages to fail\n");
5223 ok(ERROR_INVALID_PARAMETER
== GetLastError(),
5224 "Expected error ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
5228 SetLastError(0xdeadbeef);
5229 ret
= pGetUserPreferredUILanguages(MUI_LANGUAGE_ID
, &count
, NULL
, &size_id
);
5230 ok(ret
, "Expected GetUserPreferredUILanguages to succeed\n");
5231 ok(count
, "Expected count > 0\n");
5232 ok(size_id
% 5 == 1, "Expected size (%d) %% 5 == 1\n", size_id
);
5236 SetLastError(0xdeadbeef);
5237 ret
= pGetUserPreferredUILanguages(MUI_LANGUAGE_NAME
, &count
, NULL
, &size_name
);
5238 ok(ret
, "Expected GetUserPreferredUILanguages to succeed\n");
5239 ok(count
, "Expected count > 0\n");
5240 ok(size_name
% 6 == 1, "Expected size (%d) %% 6 == 1\n", size_name
);
5242 size_buffer
= max(size_id
, size_name
);
5245 skip("No valid buffer size\n");
5249 buffer
= HeapAlloc(GetProcessHeap(), 0, size_buffer
* sizeof(WCHAR
));
5253 memset(buffer
, 0x5a, size_buffer
* sizeof(WCHAR
));
5254 SetLastError(0xdeadbeef);
5255 ret
= pGetUserPreferredUILanguages(0, &count
, buffer
, &size
);
5256 ok(ret
, "Expected GetUserPreferredUILanguages to succeed\n");
5257 ok(count
, "Expected count > 0\n");
5258 ok(size
% 6 == 1, "Expected size (%d) %% 6 == 1\n", size
);
5259 if (ret
&& size
% 6 == 1)
5260 ok(!buffer
[size
-2] && !buffer
[size
-1],
5261 "Expected last two WCHARs being empty, got 0x%x 0x%x\n",
5262 buffer
[size
-2], buffer
[size
-1]);
5266 memset(buffer
, 0x5a, size_buffer
* sizeof(WCHAR
));
5267 SetLastError(0xdeadbeef);
5268 ret
= pGetUserPreferredUILanguages(MUI_LANGUAGE_ID
, &count
, buffer
, &size
);
5269 ok(ret
, "Expected GetUserPreferredUILanguages to succeed\n");
5270 ok(count
, "Expected count > 0\n");
5271 ok(size
% 5 == 1, "Expected size (%d) %% 5 == 1\n", size
);
5272 if (ret
&& size
% 5 == 1)
5273 ok(!buffer
[size
-2] && !buffer
[size
-1],
5274 "Expected last two WCHARs being empty, got 0x%x 0x%x\n",
5275 buffer
[size
-2], buffer
[size
-1]);
5279 SetLastError(0xdeadbeef);
5280 ret
= pGetUserPreferredUILanguages(MUI_LANGUAGE_NAME
, &count
, buffer
, &size
);
5281 ok(ret
, "Expected GetUserPreferredUILanguages to succeed\n");
5282 ok(count
, "Expected count > 0\n");
5283 ok(size
% 6 == 1, "Expected size (%d) %% 6 == 1\n", size
);
5284 if (ret
&& size
% 5 == 1)
5285 ok(!buffer
[size
-2] && !buffer
[size
-1],
5286 "Expected last two WCHARs being empty, got 0x%x 0x%x\n",
5287 buffer
[size
-2], buffer
[size
-1]);
5291 SetLastError(0xdeadbeef);
5292 ret
= pGetUserPreferredUILanguages(MUI_LANGUAGE_ID
, &count
, buffer
, &size
);
5293 ok(!ret
, "Expected GetUserPreferredUILanguages to fail\n");
5294 ok(ERROR_INSUFFICIENT_BUFFER
== GetLastError(),
5295 "Expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
5299 memset(buffer
, 0x5a, size_buffer
* sizeof(WCHAR
));
5300 SetLastError(0xdeadbeef);
5301 ret
= pGetUserPreferredUILanguages(MUI_LANGUAGE_ID
, &count
, buffer
, &size
);
5302 ok(!ret
, "Expected GetUserPreferredUILanguages to fail\n");
5303 ok(ERROR_INSUFFICIENT_BUFFER
== GetLastError(),
5304 "Expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
5308 memset(buffer
, 0x5a, size_buffer
* sizeof(WCHAR
));
5309 SetLastError(0xdeadbeef);
5310 ret
= pGetUserPreferredUILanguages(0, &count
, buffer
, &size
);
5311 ok(!ret
, "Expected GetUserPreferredUILanguages to fail\n");
5312 ok(ERROR_INSUFFICIENT_BUFFER
== GetLastError(),
5313 "Expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
5315 HeapFree(GetProcessHeap(), 0, buffer
);
5320 InitFunctionPointers();
5322 test_EnumTimeFormatsA();
5323 test_EnumTimeFormatsW();
5324 test_EnumDateFormatsA();
5325 test_GetLocaleInfoA();
5326 test_GetLocaleInfoW();
5327 test_GetLocaleInfoEx();
5328 test_GetTimeFormatA();
5329 test_GetTimeFormatEx();
5330 test_GetDateFormatA();
5331 test_GetDateFormatEx();
5332 test_GetDateFormatW();
5333 test_GetCurrencyFormatA(); /* Also tests the W version */
5334 test_GetNumberFormatA(); /* Also tests the W version */
5335 test_GetNumberFormatEx();
5336 test_CompareStringA();
5337 test_CompareStringW();
5338 test_CompareStringEx();
5339 test_LCMapStringA();
5340 test_LCMapStringW();
5341 test_LCMapStringEx();
5342 test_LocaleNameToLCID();
5345 test_ConvertDefaultLocale();
5346 test_EnumSystemLanguageGroupsA();
5347 test_EnumSystemLocalesEx();
5348 test_EnumLanguageGroupLocalesA();
5349 test_SetLocaleInfoA();
5350 test_EnumUILanguageA();
5352 test_GetStringTypeW();
5353 test_IdnToNameprepUnicode();
5355 test_IdnToUnicode();
5356 test_IsValidLocaleName();
5357 test_CompareStringOrdinal();
5359 test_EnumSystemGeoID();
5361 test_GetSystemPreferredUILanguages();
5362 test_GetThreadPreferredUILanguages();
5363 test_GetUserPreferredUILanguages();