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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
32 #include "wine/test.h"
38 static inline unsigned int strlenW( const WCHAR
*str
)
45 static inline int strncmpW( const WCHAR
*str1
, const WCHAR
*str2
, int n
)
48 while ((--n
> 0) && *str1
&& (*str1
== *str2
)) { str1
++; str2
++; }
52 static inline WCHAR
*strchrW( const WCHAR
*str
, WCHAR ch
)
54 for ( ; *str
; str
++) if (*str
== ch
) return (WCHAR
*)str
;
58 inline static int isdigitW( WCHAR wc
)
61 GetStringTypeW( CT_CTYPE1
, &wc
, 1, &type
);
62 return type
& C1_DIGIT
;
65 /* Some functions are only in later versions of kernel32.dll */
66 static HMODULE hKernel32
;
68 typedef BOOL (WINAPI
*EnumSystemLanguageGroupsAFn
)(LANGUAGEGROUP_ENUMPROC
,
70 static EnumSystemLanguageGroupsAFn pEnumSystemLanguageGroupsA
;
71 typedef BOOL (WINAPI
*EnumLanguageGroupLocalesAFn
)(LANGGROUPLOCALE_ENUMPROC
,
72 LGRPID
, DWORD
, LONG_PTR
);
73 static EnumLanguageGroupLocalesAFn pEnumLanguageGroupLocalesA
;
75 typedef INT (WINAPI
*FoldStringAFn
)(DWORD
, LPCSTR
, INT
, LPSTR
, INT
);
76 static FoldStringAFn pFoldStringA
;
77 typedef INT (WINAPI
*FoldStringWFn
)(DWORD
, LPCWSTR
, INT
, LPWSTR
, INT
);
78 static FoldStringWFn pFoldStringW
;
80 typedef BOOL (WINAPI
*IsValidLanguageGroupFn
)(LGRPID
, DWORD
);
81 static IsValidLanguageGroupFn pIsValidLanguageGroup
;
83 static void InitFunctionPointers(void)
85 hKernel32
= GetModuleHandleA("kernel32");
89 pEnumSystemLanguageGroupsA
= (void*)GetProcAddress(hKernel32
, "EnumSystemLanguageGroupsA");
90 pEnumLanguageGroupLocalesA
= (void*)GetProcAddress(hKernel32
, "EnumLanguageGroupLocalesA");
91 pFoldStringA
= (void*)GetProcAddress(hKernel32
, "FoldStringA");
92 pFoldStringW
= (void*)GetProcAddress(hKernel32
, "FoldStringW");
93 pIsValidLanguageGroup
= (void*)GetProcAddress(hKernel32
, "IsValidLanguageGroup");
97 #define eq(received, expected, label, type) \
98 ok((received) == (expected), "%s: got " type " instead of " type "\n", \
99 (label), (received), (expected))
101 #define BUFFER_SIZE 128
102 char GlobalBuffer
[BUFFER_SIZE
]; /* Buffer used by callback function */
103 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
105 #define EXPECT_LEN(len) ok(ret == (len), "Expected Len %d, got %d\n", (len), ret)
106 #define EXPECT_INVALID ok(GetLastError() == ERROR_INVALID_PARAMETER, \
107 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError())
108 #define EXPECT_BUFFER ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, \
109 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError())
110 #define EXPECT_FLAGS ok(GetLastError() == ERROR_INVALID_FLAGS, \
111 "Expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError())
112 #define EXPECT_INVALIDFLAGS ok(GetLastError() == ERROR_INVALID_FLAGS || \
113 GetLastError() == ERROR_INVALID_PARAMETER, \
114 "Expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError())
115 #define EXPECT_VALID ok(GetLastError() == 0, \
116 "Expected GetLastError() == 0, got %ld\n", GetLastError())
118 #define STRINGSA(x,y) strcpy(input, x); strcpy(Expected, y); SetLastError(0); buffer[0] = '\0'
119 #define EXPECT_LENA EXPECT_LEN((int)strlen(Expected)+1)
120 #define EXPECT_EQA ok(strncmp(buffer, Expected, strlen(Expected)) == 0, \
121 "Expected '%s', got '%s'\n", Expected, buffer)
123 #define STRINGSW(x,y) MultiByteToWideChar(CP_ACP,0,x,-1,input,COUNTOF(input)); \
124 MultiByteToWideChar(CP_ACP,0,y,-1,Expected,COUNTOF(Expected)); \
125 SetLastError(0); buffer[0] = '\0'
126 #define EXPECT_LENW EXPECT_LEN((int)strlenW(Expected)+1)
127 #define EXPECT_EQW ok(strncmpW(buffer, Expected, strlenW(Expected)) == 0, "Bad conversion\n")
129 #define NUO LOCALE_NOUSEROVERRIDE
131 static void test_GetLocaleInfoA()
134 LCID lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
135 char buffer
[BUFFER_SIZE
];
137 ok(lcid
== 0x409, "wrong LCID calculated - %ld\n", lcid
);
139 /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
140 * partially fill the buffer even if it is too short. See bug 637.
142 SetLastError(0); memset(buffer
, 0, COUNTOF(buffer
));
143 ret
= GetLocaleInfoA(lcid
, NUO
|LOCALE_SDAYNAME1
, buffer
, 0);
144 ok(ret
== 7 && !buffer
[0], "Expected len=7, got %d\n", ret
);
146 SetLastError(0); memset(buffer
, 0, COUNTOF(buffer
));
147 ret
= GetLocaleInfoA(lcid
, NUO
|LOCALE_SDAYNAME1
, buffer
, 3);
148 EXPECT_BUFFER
; EXPECT_LEN(0);
149 ok(!strcmp(buffer
, "Mon"), "Expected 'Mon', got '%s'\n", buffer
);
151 SetLastError(0); memset(buffer
, 0, COUNTOF(buffer
));
152 ret
= GetLocaleInfoA(lcid
, NUO
|LOCALE_SDAYNAME1
, buffer
, 10);
153 EXPECT_VALID
; EXPECT_LEN(7);
154 ok(!strcmp(buffer
, "Monday"), "Expected 'Monday', got '%s'\n", buffer
);
157 static void test_GetTimeFormatA()
161 LCID lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
162 char buffer
[BUFFER_SIZE
], input
[BUFFER_SIZE
], Expected
[BUFFER_SIZE
];
164 memset(&curtime
, 2, sizeof(SYSTEMTIME
));
165 STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
166 ret
= GetTimeFormatA(lcid
, TIME_FORCE24HOURFORMAT
, &curtime
, input
, buffer
, COUNTOF(buffer
));
167 EXPECT_INVALID
; EXPECT_LEN(0); EXPECT_EQA
;
170 curtime
.wMinute
= 56;
171 curtime
.wSecond
= 13;
172 curtime
.wMilliseconds
= 22;
173 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
174 ret
= GetTimeFormatA(lcid
, TIME_FORCE24HOURFORMAT
, &curtime
, input
, buffer
, COUNTOF(buffer
));
175 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
177 STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficent buffer */
178 ret
= GetTimeFormatA(lcid
, TIME_FORCE24HOURFORMAT
, &curtime
, input
, buffer
, 2);
179 EXPECT_BUFFER
; EXPECT_LEN(0); EXPECT_EQA
;
181 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
182 ret
= GetTimeFormatA(lcid
, TIME_FORCE24HOURFORMAT
, &curtime
, input
, NULL
, 0);
183 EXPECT_VALID
; EXPECT_LENA
;
185 STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
186 ret
= GetTimeFormatA(lcid
, NUO
|TIME_NOMINUTESORSECONDS
, &curtime
, NULL
, buffer
, COUNTOF(buffer
));
187 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
189 STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
190 ret
= GetTimeFormatA(lcid
, TIME_NOMINUTESORSECONDS
, &curtime
, input
, buffer
, COUNTOF(buffer
));
191 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
193 STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
194 ret
= GetTimeFormatA(lcid
, NUO
|TIME_NOSECONDS
, &curtime
, NULL
, buffer
, COUNTOF(buffer
));
195 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
197 STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
198 strcpy(Expected
, "8:56 AM");
199 ret
= GetTimeFormatA(lcid
, TIME_NOSECONDS
, &curtime
, input
, buffer
, COUNTOF(buffer
));
200 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
202 STRINGSA("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
203 ret
= GetTimeFormatA(lcid
, TIME_NOSECONDS
, &curtime
, input
, buffer
, COUNTOF(buffer
));
204 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
206 STRINGSA("s1s2s3", ""); /* Duplicate tokens */
207 ret
= GetTimeFormatA(lcid
, TIME_NOSECONDS
, &curtime
, input
, buffer
, COUNTOF(buffer
));
208 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
210 STRINGSA("t/tt", "A/AM"); /* AM time marker */
211 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
212 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
215 STRINGSA("t/tt", "P/PM"); /* PM time marker */
216 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
217 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
219 STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
220 ret
= GetTimeFormatA(lcid
, TIME_NOTIMEMARKER
, &curtime
, input
, buffer
, COUNTOF(buffer
));
221 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
223 STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
224 ret
= GetTimeFormatA(lcid
, TIME_FORCE24HOURFORMAT
, &curtime
, input
, buffer
, COUNTOF(buffer
));
225 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
227 STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
228 ret
= GetTimeFormatA(lcid
, TIME_FORCE24HOURFORMAT
, &curtime
, input
, buffer
, COUNTOF(buffer
));
229 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
231 curtime
.wHour
= 14; /* change this to 14 or 2pm */
234 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 */
235 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
236 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
239 STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
240 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
241 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
243 STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
244 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
245 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
247 /* try to convert formatting strings with more than two letters
248 * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
249 * NOTE: We expect any letter for which there is an upper case value
250 * we should see a replacement. For letters that DO NOT have
251 * upper case values we should see NO REPLACEMENT.
254 curtime
.wMinute
= 56;
255 curtime
.wSecond
= 13;
256 curtime
.wMilliseconds
= 22;
257 STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
258 "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
259 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
260 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
262 STRINGSA("h", "text"); /* Don't write to buffer if len is 0 */
263 strcpy(buffer
, "text");
264 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, 0);
265 EXPECT_VALID
; EXPECT_LEN(2); EXPECT_EQA
;
267 STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
268 "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
269 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
270 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
272 STRINGSA("'''", "'"); /* invalid quoted string */
273 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
274 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
276 /* test that msdn suggested single quotation usage works as expected */
277 STRINGSA("''''", "'"); /* single quote mark */
278 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
279 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
281 STRINGSA("''HHHHHH", "08"); /* Normal use */
282 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
283 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
285 /* and test for normal use of the single quotation mark */
286 STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
287 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
288 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
290 STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
291 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
292 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
294 STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
295 ret
= GetTimeFormatA(lcid
, TIME_NOTIMEMARKER
, &curtime
, input
, buffer
, COUNTOF(buffer
));
296 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
299 STRINGSA("'123'tt", ""); /* Invalid time */
300 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
301 EXPECT_INVALID
; EXPECT_LEN(0); EXPECT_EQA
;
304 curtime
.wMonth
= 60; /* Invalid */
305 STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
306 ret
= GetTimeFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
307 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
310 static void test_GetDateFormatA()
314 LCID lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
315 char buffer
[BUFFER_SIZE
], input
[BUFFER_SIZE
], Expected
[BUFFER_SIZE
];
317 memset(&curtime
, 2, sizeof(SYSTEMTIME
)); /* Invalid time */
318 STRINGSA("ddd',' MMM dd yy","");
319 ret
= GetDateFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
320 EXPECT_INVALID
; EXPECT_LEN(0); EXPECT_EQA
;
322 curtime
.wYear
= 2002;
325 curtime
.wDayOfWeek
= 3;
326 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
327 ret
= GetDateFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
328 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
330 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
331 ret
= GetDateFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
332 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
334 curtime
.wHour
= 36; /* Invalid */
335 STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
336 ret
= GetDateFormatA(lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
337 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
339 STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
340 ret
= GetDateFormatA(lcid
, 0, &curtime
, input
, NULL
, 0);
341 EXPECT_VALID
; EXPECT_LEN(16); EXPECT_EQA
;
343 STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
344 ret
= GetDateFormatA(lcid
, 0, &curtime
, input
, buffer
, 2);
345 EXPECT_BUFFER
; EXPECT_LEN(0); EXPECT_EQA
;
347 STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
348 ret
= GetDateFormat(lcid
, NUO
, &curtime
, NULL
, buffer
, COUNTOF(buffer
));
349 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
351 STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
352 ret
= GetDateFormat(lcid
, NUO
|DATE_LONGDATE
, &curtime
, NULL
, buffer
, COUNTOF(buffer
));
353 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
355 /* test for expected DATE_YEARMONTH behavior with null format */
356 /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
357 STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
358 ret
= GetDateFormat(lcid
, NUO
|DATE_YEARMONTH
, &curtime
, input
, buffer
, COUNTOF(buffer
));
359 EXPECT_FLAGS
; EXPECT_LEN(0); EXPECT_EQA
;
361 /* Test that using invalid DATE_* flags results in the correct error */
362 /* and return values */
363 STRINGSA("m/d/y", ""); /* Invalid flags */
364 ret
= GetDateFormat(lcid
, DATE_YEARMONTH
|DATE_SHORTDATE
|DATE_LONGDATE
,
365 &curtime
, input
, buffer
, COUNTOF(buffer
));
366 EXPECT_FLAGS
; EXPECT_LEN(0); EXPECT_EQA
;
369 static void test_GetDateFormatW()
373 WCHAR buffer
[BUFFER_SIZE
], input
[BUFFER_SIZE
], Expected
[BUFFER_SIZE
];
374 LCID lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
376 STRINGSW("",""); /* If flags is not zero then format must be NULL */
377 ret
= GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, DATE_LONGDATE
, NULL
,
378 input
, buffer
, COUNTOF(buffer
));
379 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
381 EXPECT_FLAGS
; EXPECT_LEN(0); EXPECT_EQW
;
383 STRINGSW("",""); /* NULL buffer, len > 0 */
384 ret
= GetDateFormatW (lcid
, 0, NULL
, input
, NULL
, COUNTOF(buffer
));
385 EXPECT_INVALID
; EXPECT_LEN(0); EXPECT_EQW
;
387 STRINGSW("",""); /* NULL buffer, len == 0 */
388 ret
= GetDateFormatW (lcid
, 0, NULL
, input
, NULL
, 0);
389 EXPECT_VALID
; EXPECT_LENW
; EXPECT_EQW
;
391 curtime
.wYear
= 2002;
394 curtime
.wDayOfWeek
= 45612; /* Should be 3 - Wednesday */
395 curtime
.wHour
= 65432; /* Invalid */
396 curtime
.wMinute
= 34512; /* Invalid */
397 curtime
.wSecond
= 65535; /* Invalid */
398 curtime
.wMilliseconds
= 12345;
399 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
400 ret
= GetDateFormatW (lcid
, 0, &curtime
, input
, buffer
, COUNTOF(buffer
));
401 EXPECT_VALID
; EXPECT_LENW
; EXPECT_EQW
;
405 #define CY_POS_LEFT 0
406 #define CY_POS_RIGHT 1
407 #define CY_POS_LEFT_SPACE 2
408 #define CY_POS_RIGHT_SPACE 3
410 static void test_GetCurrencyFormatA()
412 static char szDot
[] = { '.', '\0' };
413 static char szComma
[] = { ',', '\0' };
414 static char szDollar
[] = { '$', '\0' };
416 LCID lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
417 char buffer
[BUFFER_SIZE
], Expected
[BUFFER_SIZE
], input
[BUFFER_SIZE
];
420 memset(&format
, 0, sizeof(format
));
422 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
423 ret
= GetCurrencyFormatA(lcid
, 0, input
, NULL
, NULL
, COUNTOF(buffer
));
424 EXPECT_INVALID
; EXPECT_LEN(0); EXPECT_EQA
;
426 STRINGSA("23,53",""); /* Invalid character --> Error */
427 ret
= GetCurrencyFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
428 EXPECT_INVALID
; EXPECT_LEN(0); EXPECT_EQA
;
430 STRINGSA("--",""); /* Double '-' --> Error */
431 ret
= GetCurrencyFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
432 EXPECT_INVALID
; EXPECT_LEN(0); EXPECT_EQA
;
434 STRINGSA("0-",""); /* Trailing '-' --> Error */
435 ret
= GetCurrencyFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
436 EXPECT_INVALID
; EXPECT_LEN(0); EXPECT_EQA
;
438 STRINGSA("0..",""); /* Double '.' --> Error */
439 ret
= GetCurrencyFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
440 EXPECT_INVALID
; EXPECT_LEN(0); EXPECT_EQA
;
442 STRINGSA(" 0.1",""); /* Leading space --> Error */
443 ret
= GetCurrencyFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
444 EXPECT_INVALID
; EXPECT_LEN(0); EXPECT_EQA
;
446 STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
447 ret
= GetCurrencyFormatA(lcid
, NUO
, input
, NULL
, buffer
, 2);
448 EXPECT_BUFFER
; EXPECT_LEN(0); EXPECT_EQA
;
450 STRINGSA("2353",""); /* Format and flags given --> Error */
451 ret
= GetCurrencyFormatA(lcid
, NUO
, input
, &format
, buffer
, COUNTOF(buffer
));
452 EXPECT_INVALIDFLAGS
; EXPECT_LEN(0); EXPECT_EQA
;
454 STRINGSA("2353",""); /* Invalid format --> Error */
455 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
456 EXPECT_INVALID
; EXPECT_LEN(0); EXPECT_EQA
;
458 STRINGSA("2353","$2,353.00"); /* Valid number */
459 ret
= GetCurrencyFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
460 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
462 STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
463 ret
= GetCurrencyFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
464 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
466 STRINGSA("2353.1","$2,353.10"); /* Valid real number */
467 ret
= GetCurrencyFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
468 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
470 STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
471 ret
= GetCurrencyFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
472 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
474 STRINGSA("2353.119","$2,353.12"); /* Too many DP --> Rounded */
475 ret
= GetCurrencyFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
476 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
478 format
.NumDigits
= 0; /* No decimal separator */
479 format
.LeadingZero
= 0;
480 format
.Grouping
= 0; /* No grouping char */
481 format
.NegativeOrder
= 0;
482 format
.PositiveOrder
= CY_POS_LEFT
;
483 format
.lpDecimalSep
= szDot
;
484 format
.lpThousandSep
= szComma
;
485 format
.lpCurrencySymbol
= szDollar
;
487 STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
488 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
489 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
491 format
.NumDigits
= 1; /* 1 DP --> Expect decimal separator */
492 STRINGSA("2353","$2353.0");
493 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
494 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
496 format
.Grouping
= 2; /* Group by 100's */
497 STRINGSA("2353","$23,53.0");
498 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
499 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
501 format
.LeadingZero
= 1; /* Always provide leading zero */
502 STRINGSA(".5","$0.5");
503 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
504 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
506 format
.PositiveOrder
= CY_POS_RIGHT
;
507 STRINGSA("1","1.0$");
508 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
509 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
511 format
.PositiveOrder
= CY_POS_LEFT_SPACE
;
512 STRINGSA("1","$ 1.0");
513 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
514 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
516 format
.PositiveOrder
= CY_POS_RIGHT_SPACE
;
517 STRINGSA("1","1.0 $");
518 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
519 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
521 format
.NegativeOrder
= 0;
522 STRINGSA("-1","($1.0)");
523 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
524 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
526 format
.NegativeOrder
= 1;
527 STRINGSA("-1","-$1.0");
528 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
529 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
531 format
.NegativeOrder
= 2;
532 STRINGSA("-1","$-1.0");
533 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
534 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
536 format
.NegativeOrder
= 3;
537 STRINGSA("-1","$1.0-");
538 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
539 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
541 format
.NegativeOrder
= 4;
542 STRINGSA("-1","(1.0$)");
543 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
544 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
546 format
.NegativeOrder
= 5;
547 STRINGSA("-1","-1.0$");
548 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
549 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
551 format
.NegativeOrder
= 6;
552 STRINGSA("-1","1.0-$");
553 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
554 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
556 format
.NegativeOrder
= 7;
557 STRINGSA("-1","1.0$-");
558 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
559 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
561 format
.NegativeOrder
= 8;
562 STRINGSA("-1","-1.0 $");
563 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
564 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
566 format
.NegativeOrder
= 9;
567 STRINGSA("-1","-$ 1.0");
568 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
569 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
571 format
.NegativeOrder
= 10;
572 STRINGSA("-1","1.0 $-");
573 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
574 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
576 format
.NegativeOrder
= 11;
577 STRINGSA("-1","$ 1.0-");
578 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
579 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
581 format
.NegativeOrder
= 12;
582 STRINGSA("-1","$ -1.0");
583 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
584 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
586 format
.NegativeOrder
= 13;
587 STRINGSA("-1","1.0- $");
588 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
589 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
591 format
.NegativeOrder
= 14;
592 STRINGSA("-1","($ 1.0)");
593 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
594 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
596 format
.NegativeOrder
= 15;
597 STRINGSA("-1","(1.0 $)");
598 ret
= GetCurrencyFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
599 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
602 #define NEG_PARENS 0 /* "(1.1)" */
603 #define NEG_LEFT 1 /* "-1.1" */
604 #define NEG_LEFT_SPACE 2 /* "- 1.1" */
605 #define NEG_RIGHT 3 /* "1.1-" */
606 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
608 static void test_GetNumberFormatA()
610 static char szDot
[] = { '.', '\0' };
611 static char szComma
[] = { ',', '\0' };
613 LCID lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
614 char buffer
[BUFFER_SIZE
], Expected
[BUFFER_SIZE
], input
[BUFFER_SIZE
];
617 memset(&format
, 0, sizeof(format
));
619 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
620 ret
= GetNumberFormatA(lcid
, 0, input
, NULL
, NULL
, COUNTOF(buffer
));
621 EXPECT_INVALID
; EXPECT_LEN(0); EXPECT_EQA
;
623 STRINGSA("23,53",""); /* Invalid character --> Error */
624 ret
= GetNumberFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
625 EXPECT_INVALID
; EXPECT_LEN(0); EXPECT_EQA
;
627 STRINGSA("--",""); /* Double '-' --> Error */
628 ret
= GetNumberFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
629 EXPECT_INVALID
; EXPECT_LEN(0); EXPECT_EQA
;
631 STRINGSA("0-",""); /* Trailing '-' --> Error */
632 ret
= GetNumberFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
633 EXPECT_INVALID
; EXPECT_LEN(0); EXPECT_EQA
;
635 STRINGSA("0..",""); /* Double '.' --> Error */
636 ret
= GetNumberFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
637 EXPECT_INVALID
; EXPECT_LEN(0); EXPECT_EQA
;
639 STRINGSA(" 0.1",""); /* Leading space --> Error */
640 ret
= GetNumberFormatA(lcid
, 0, input
, NULL
, buffer
, COUNTOF(buffer
));
641 EXPECT_INVALID
; EXPECT_LEN(0); EXPECT_EQA
;
643 STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
644 ret
= GetNumberFormatA(lcid
, NUO
, input
, NULL
, buffer
, 2);
645 EXPECT_BUFFER
; EXPECT_LEN(0); EXPECT_EQA
;
647 STRINGSA("2353",""); /* Format and flags given --> Error */
648 ret
= GetNumberFormatA(lcid
, NUO
, input
, &format
, buffer
, COUNTOF(buffer
));
649 EXPECT_INVALIDFLAGS
; EXPECT_LEN(0); EXPECT_EQA
;
651 STRINGSA("2353",""); /* Invalid format --> Error */
652 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
653 EXPECT_INVALID
; EXPECT_LEN(0); EXPECT_EQA
;
655 STRINGSA("2353","2,353.00"); /* Valid number */
656 ret
= GetNumberFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
657 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
659 STRINGSA("-2353","-2,353.00"); /* Valid negative number */
660 ret
= GetNumberFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
661 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
663 STRINGSA("-353","-353.00"); /* test for off by one error in grouping */
664 ret
= GetNumberFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
665 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
667 STRINGSA("2353.1","2,353.10"); /* Valid real number */
668 ret
= GetNumberFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
669 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
671 STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
672 ret
= GetNumberFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
673 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
675 STRINGSA("2353.119","2,353.12"); /* Too many DP --> Rounded */
676 ret
= GetNumberFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
677 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
679 format
.NumDigits
= 0; /* No decimal separator */
680 format
.LeadingZero
= 0;
681 format
.Grouping
= 0; /* No grouping char */
682 format
.NegativeOrder
= 0;
683 format
.lpDecimalSep
= szDot
;
684 format
.lpThousandSep
= szComma
;
686 STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
687 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
688 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
690 format
.NumDigits
= 1; /* 1 DP --> Expect decimal separator */
691 STRINGSA("2353","2353.0");
692 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
693 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
695 format
.Grouping
= 2; /* Group by 100's */
696 STRINGSA("2353","23,53.0");
697 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
698 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
700 format
.LeadingZero
= 1; /* Always provide leading zero */
701 STRINGSA(".5","0.5");
702 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
703 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
705 format
.NegativeOrder
= NEG_PARENS
;
706 STRINGSA("-1","(1.0)");
707 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
708 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
710 format
.NegativeOrder
= NEG_LEFT
;
711 STRINGSA("-1","-1.0");
712 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
713 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
715 format
.NegativeOrder
= NEG_LEFT_SPACE
;
716 STRINGSA("-1","- 1.0");
717 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
718 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
720 format
.NegativeOrder
= NEG_RIGHT
;
721 STRINGSA("-1","1.0-");
722 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
723 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
725 format
.NegativeOrder
= NEG_RIGHT_SPACE
;
726 STRINGSA("-1","1.0 -");
727 ret
= GetNumberFormatA(lcid
, 0, input
, &format
, buffer
, COUNTOF(buffer
));
728 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
730 lcid
= MAKELCID(MAKELANGID(LANG_FRENCH
, SUBLANG_DEFAULT
), SORT_DEFAULT
);
732 if (IsValidLocale(lcid
, 0))
734 STRINGSA("-12345","-12 345,00"); /* Try French formatting */
735 Expected
[3] = 160; /* Non breaking space */
736 ret
= GetNumberFormatA(lcid
, NUO
, input
, NULL
, buffer
, COUNTOF(buffer
));
737 EXPECT_VALID
; EXPECT_LENA
; EXPECT_EQA
;
742 /* Callback function used by TestEnumTimeFormats */
743 static BOOL CALLBACK
EnumTimeFormatsProc(char * lpTimeFormatString
)
745 trace("%s\n", lpTimeFormatString
);
746 strcpy(GlobalBuffer
, lpTimeFormatString
);
753 void test_EnumTimeFormats()
756 LCID lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
758 GlobalBuffer
[0] = '\0';
759 ret
= EnumTimeFormatsA(EnumTimeFormatsProc
, lcid
, 0);
760 ok (ret
== 1 && !strcmp(GlobalBuffer
,"h:mm:ss tt"), "Expected %d '%s'\n", ret
, GlobalBuffer
);
763 static void test_CompareStringA()
766 LCID lcid
= MAKELCID(MAKELANGID(LANG_FRENCH
, SUBLANG_DEFAULT
), SORT_DEFAULT
);
768 ret
= CompareStringA(lcid
, NORM_IGNORECASE
, "Salut", -1, "Salute", -1);
769 ok (ret
== 1, "(Salut/Salute) Expected 1, got %d\n", ret
);
771 ret
= CompareStringA(lcid
, NORM_IGNORECASE
, "Salut", -1, "SaLuT", -1);
772 ok (ret
== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret
);
774 ret
= CompareStringA(lcid
, NORM_IGNORECASE
, "Salut", -1, "hola", -1);
775 ok (ret
== 3, "(Salut/hola) Expected 3, got %d\n", ret
);
777 ret
= CompareStringA(lcid
, NORM_IGNORECASE
, "haha", -1, "hoho", -1);
778 ok (ret
== 1, "(haha/hoho) Expected 1, got %d\n", ret
);
780 lcid
= MAKELCID(MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), SORT_DEFAULT
);
782 ret
= CompareStringA(lcid
, NORM_IGNORECASE
, "haha", -1, "hoho", -1);
783 ok (ret
== 1, "(haha/hoho) Expected 1, got %d\n", ret
);
785 ret
= CompareStringA(lcid
, NORM_IGNORECASE
, "haha", -1, "hoho", 0);
786 ok (ret
== 3, "(haha/hoho) Expected 3, got %d\n", ret
);
788 ret
= CompareStringA(lcid
, NORM_IGNORECASE
, "Salut", 5, "saLuT", -1);
789 ok (ret
== 2, "(Salut/saLuT) Expected 2, got %d\n", ret
);
791 SetLastError(0xdeadbeef);
792 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0x10, "NULL", -1, "NULL", -1);
793 ok(GetLastError() == ERROR_INVALID_FLAGS
,
794 "unexpected error code %ld\n", GetLastError());
795 ok(!ret
, "CompareStringA must fail with invalid flag\n");
797 ret
= lstrcmpA("", "");
798 ok (ret
== 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret
);
800 ret
= lstrcmpA(NULL
, NULL
);
801 ok (ret
== 0, "lstrcmpA(NULL, NULL) should return 0, got %d\n", ret
);
803 ret
= lstrcmpA("", NULL
);
804 ok (ret
== 1, "lstrcmpA(\"\", NULL) should return 1, got %d\n", ret
);
806 ret
= lstrcmpA(NULL
, "");
807 ok (ret
== -1, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret
);
809 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
,0,"EndDialog",-1,"_Property",-1);
810 ok( ret
== 3, "EndDialog vs _Property ... expected 3, got %d\n", ret
);
812 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
,0,"osp_vba.sreg0070",-1,"_IEWWBrowserComp",-1);
813 ok( ret
== 3, "osp_vba.sreg0070 vs _IEWWBrowserComp ... expected 3, got %d\n", ret
);
815 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
,0,"r",-1,"\\",-1);
816 ok( ret
== 3, "r vs \\ ... expected 3, got %d\n", ret
);
818 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
,0,"osp_vba.sreg0031", -1, "OriginalDatabase", -1 );
819 ok( ret
== 3, "osp_vba.sreg0031 vs OriginalDatabase ... expected 3, got %d\n", ret
);
821 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "AAA", -1, "aaa", -1 );
822 ok( ret
== 3, "AAA vs aaa expected 3, got %d\n", ret
);
824 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "AAA", -1, "aab", -1 );
825 ok( ret
== 1, "AAA vs aab expected 1, got %d\n", ret
);
827 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "AAA", -1, "Aab", -1 );
828 ok( ret
== 1, "AAA vs Aab expected 1, got %d\n", ret
);
830 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, ".AAA", -1, "Aab", -1 );
831 ok( ret
== 1, ".AAA vs Aab expected 1, got %d\n", ret
);
833 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, ".AAA", -1, "A.ab", -1 );
834 ok( ret
== 1, ".AAA vs A.ab expected 1, got %d\n", ret
);
836 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "aa", -1, "AB", -1 );
837 ok( ret
== 1, "aa vs AB expected 1, got %d\n", ret
);
839 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "aa", -1, "Aab", -1 );
840 ok( ret
== 1, "aa vs Aab expected 1, got %d\n", ret
);
842 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "aB", -1, "Aab", -1 );
843 ok( ret
== 3, "aB vs Aab expected 3, got %d\n", ret
);
845 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "Ba", -1, "bab", -1 );
846 ok( ret
== 1, "Ba vs bab expected 1, got %d\n", ret
);
848 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1 );
849 ok( ret
== 1, "{100}{83}{71}{71}{71} vs Global_DataAccess_JRO expected 1, got %d\n", ret
);
851 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "a", -1, "{", -1 );
852 ok( ret
== 3, "a vs { expected 3, got %d\n", ret
);
854 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "A", -1, "{", -1 );
855 ok( ret
== 3, "A vs { expected 3, got %d\n", ret
);
857 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "3.5", 0, "4.0", -1 );
858 ok(ret
== 1, "3.5/0 vs 4.0/-1 expected 1, got %d\n", ret
);
860 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "3.5", -1, "4.0", -1 );
861 ok(ret
== 1, "3.5 vs 4.0 expected 1, got %d\n", ret
);
863 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "3.520.4403.2", -1, "4.0.2927.10", -1 );
864 ok(ret
== 1, "3.520.4403.2 vs 4.0.2927.10 expected 1, got %d\n", ret
);
866 /* hyphen and apostrophe are treated differently depending on
867 * whether SORT_STRINGSORT specified or not
869 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "-o", -1, "/m", -1 );
870 ok(ret
== 3, "-o vs /m expected 3, got %d\n", ret
);
872 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "/m", -1, "-o", -1 );
873 ok(ret
== 1, "/m vs -o expected 1, got %d\n", ret
);
875 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "-o", -1, "/m", -1 );
876 ok(ret
== 1, "-o vs /m expected 1, got %d\n", ret
);
878 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "/m", -1, "-o", -1 );
879 ok(ret
== 3, "/m vs -o expected 3, got %d\n", ret
);
881 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "'o", -1, "/m", -1 );
882 ok(ret
== 3, "'o vs /m expected 3, got %d\n", ret
);
884 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "/m", -1, "'o", -1 );
885 ok(ret
== 1, "/m vs 'o expected 1, got %d\n", ret
);
887 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "'o", -1, "/m", -1 );
888 ok(ret
== 1, "'o vs /m expected 1, got %d\n", ret
);
890 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "/m", -1, "'o", -1 );
891 ok(ret
== 3, "/m vs 'o expected 3, got %d\n", ret
);
893 #if 0 /* this requires collation table patch to make it MS compatible */
894 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "'o", -1, "-o", -1 );
895 ok(ret
== 1, "'o vs -o expected 1, got %d\n", ret
);
897 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "'o", -1, "-o", -1 );
898 ok(ret
== 1, "'o vs -o expected 1, got %d\n", ret
);
900 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "'", -1, "-", -1 );
901 ok(ret
== 1, "' vs - expected 1, got %d\n", ret
);
903 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "'", -1, "-", -1 );
904 ok(ret
== 1, "' vs - expected 1, got %d\n", ret
);
906 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "`o", -1, "/m", -1 );
907 ok(ret
== 3, "`o vs /m expected 3, got %d\n", ret
);
909 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "/m", -1, "`o", -1 );
910 ok(ret
== 1, "/m vs `o expected 1, got %d\n", ret
);
912 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "`o", -1, "/m", -1 );
913 ok(ret
== 3, "`o vs /m expected 3, got %d\n", ret
);
915 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "/m", -1, "`o", -1 );
916 ok(ret
== 1, "/m vs `o expected 1, got %d\n", ret
);
918 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "`o", -1, "-m", -1 );
919 ok(ret
== 1, "`o vs -m expected 1, got %d\n", ret
);
921 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, 0, "-m", -1, "`o", -1 );
922 ok(ret
== 3, "-m vs `o expected 3, got %d\n", ret
);
924 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "`o", -1, "-m", -1 );
925 ok(ret
== 3, "`o vs -m expected 3, got %d\n", ret
);
927 ret
= CompareStringA(LOCALE_SYSTEM_DEFAULT
, SORT_STRINGSORT
, "-m", -1, "`o", -1 );
928 ok(ret
== 1, "-m vs `o expected 1, got %d\n", ret
);
931 ret
= CompareStringA(LOCALE_USER_DEFAULT
, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9);
932 ok(ret
== 2, "aLuZkUtZ vs aLuZkUtZ\\0 expected 2, got %d\n", ret
);
934 ret
= CompareStringA(LOCALE_USER_DEFAULT
, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10);
935 ok(ret
== 1, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1, got %d\n", ret
);
937 ret
= CompareStringA(LOCALE_USER_DEFAULT
, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
938 ok(ret
== 2, "aLuZkUtZ vs aLuZkUtZ\\0A expected 2, got %d\n", ret
);
940 ret
= CompareStringA(LOCALE_USER_DEFAULT
, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
941 ok(ret
== 2, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected 2, got %d\n", ret
);
944 void test_LCMapStringA(void)
947 char buf
[256], buf2
[256];
948 static const char upper_case
[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
949 static const char lower_case
[] = "\tjust! a, test; string 1/*+-.\r\n";
950 static const char symbols_stripped
[] = "justateststring1";
952 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_LOWERCASE
| LCMAP_UPPERCASE
,
953 upper_case
, -1, buf
, sizeof(buf
));
954 ok(!ret
, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
955 ok(GetLastError() == ERROR_INVALID_FLAGS
,
956 "unexpected error code %ld\n", GetLastError());
958 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_HIRAGANA
| LCMAP_KATAKANA
,
959 upper_case
, -1, buf
, sizeof(buf
));
960 ok(!ret
, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
961 ok(GetLastError() == ERROR_INVALID_FLAGS
,
962 "unexpected error code %ld\n", GetLastError());
964 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_HALFWIDTH
| LCMAP_FULLWIDTH
,
966 upper_case
, -1, buf
, sizeof(buf
));
967 ok(!ret
, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
968 ok(GetLastError() == ERROR_INVALID_FLAGS
,
969 "unexpected error code %ld\n", GetLastError());
971 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_TRADITIONAL_CHINESE
| LCMAP_SIMPLIFIED_CHINESE
,
972 upper_case
, -1, buf
, sizeof(buf
));
973 ok(!ret
, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
974 ok(GetLastError() == ERROR_INVALID_FLAGS
,
975 "unexpected error code %ld\n", GetLastError());
977 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
978 SetLastError(0xdeadbeef);
979 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_LOWERCASE
| SORT_STRINGSORT
,
980 upper_case
, -1, buf
, sizeof(buf
));
981 ok(GetLastError() == ERROR_INVALID_FLAGS
, "expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError());
982 ok(!ret
, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
984 /* test LCMAP_LOWERCASE */
985 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_LOWERCASE
,
986 upper_case
, -1, buf
, sizeof(buf
));
987 ok(ret
== lstrlenA(upper_case
) + 1,
988 "ret %d, error %ld, expected value %d\n",
989 ret
, GetLastError(), lstrlenA(upper_case
) + 1);
990 ok(!lstrcmpA(buf
, lower_case
), "LCMapStringA should return %s, but not %s\n", lower_case
, buf
);
992 /* test LCMAP_UPPERCASE */
993 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_UPPERCASE
,
994 lower_case
, -1, buf
, sizeof(buf
));
995 ok(ret
== lstrlenA(lower_case
) + 1,
996 "ret %d, error %ld, expected value %d\n",
997 ret
, GetLastError(), lstrlenA(lower_case
) + 1);
998 ok(!lstrcmpA(buf
, upper_case
), "LCMapStringA should return %s, but not %s\n", upper_case
, buf
);
1000 /* test buffer overflow */
1001 SetLastError(0xdeadbeef);
1002 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_UPPERCASE
,
1003 lower_case
, -1, buf
, 4);
1004 ok(!ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
1005 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret
);
1007 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1008 lstrcpyA(buf
, lower_case
);
1009 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_UPPERCASE
,
1010 buf
, -1, buf
, sizeof(buf
));
1011 if (!ret
) /* Win9x */
1012 trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1015 ok(ret
== lstrlenA(lower_case
) + 1,
1016 "ret %d, error %ld, expected value %d\n",
1017 ret
, GetLastError(), lstrlenA(lower_case
) + 1);
1018 ok(!lstrcmpA(buf
, upper_case
), "LCMapStringA should return %s, but not %s\n", upper_case
, buf
);
1020 lstrcpyA(buf
, upper_case
);
1021 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_LOWERCASE
,
1022 buf
, -1, buf
, sizeof(buf
));
1023 if (!ret
) /* Win9x */
1024 trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1027 ok(ret
== lstrlenA(upper_case
) + 1,
1028 "ret %d, error %ld, expected value %d\n",
1029 ret
, GetLastError(), lstrlenA(lower_case
) + 1);
1030 ok(!lstrcmpA(buf
, lower_case
), "LCMapStringA should return %s, but not %s\n", lower_case
, buf
);
1033 /* otherwise src == dst should fail */
1034 SetLastError(0xdeadbeef);
1035 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
| LCMAP_UPPERCASE
,
1036 buf
, 10, buf
, sizeof(buf
));
1037 ok(GetLastError() == ERROR_INVALID_FLAGS
/* NT */ ||
1038 GetLastError() == ERROR_INVALID_PARAMETER
/* Win9x */,
1039 "unexpected error code %ld\n", GetLastError());
1040 ok(!ret
, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1042 /* test whether '\0' is always appended */
1043 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
,
1044 upper_case
, -1, buf
, sizeof(buf
));
1045 ok(ret
, "LCMapStringA must succeed\n");
1046 ret2
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
,
1047 upper_case
, lstrlenA(upper_case
), buf2
, sizeof(buf2
));
1048 ok(ret
, "LCMapStringA must succeed\n");
1049 ok(ret
== ret2
, "lengths of sort keys must be equal\n");
1050 ok(!lstrcmpA(buf
, buf2
), "sort keys must be equal\n");
1052 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1053 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
| NORM_IGNORECASE
,
1054 upper_case
, -1, buf
, sizeof(buf
));
1055 ok(ret
, "LCMapStringA must succeed\n");
1056 ret2
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
,
1057 lower_case
, -1, buf2
, sizeof(buf2
));
1058 ok(ret2
, "LCMapStringA must succeed\n");
1059 ok(ret
== ret2
, "lengths of sort keys must be equal\n");
1060 ok(!lstrcmpA(buf
, buf2
), "sort keys must be equal\n");
1062 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1063 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
| NORM_IGNORENONSPACE
,
1064 lower_case
, -1, buf
, sizeof(buf
));
1065 ok(ret
, "LCMapStringA must succeed\n");
1066 ret2
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
,
1067 lower_case
, -1, buf2
, sizeof(buf2
));
1068 ok(ret2
, "LCMapStringA must succeed\n");
1069 ok(ret
== ret2
, "lengths of sort keys must be equal\n");
1070 ok(!lstrcmpA(buf
, buf2
), "sort keys must be equal\n");
1072 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1073 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
| NORM_IGNORESYMBOLS
,
1074 lower_case
, -1, buf
, sizeof(buf
));
1075 ok(ret
, "LCMapStringA must succeed\n");
1076 ret2
= LCMapStringA(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
,
1077 symbols_stripped
, -1, buf2
, sizeof(buf2
));
1078 ok(ret2
, "LCMapStringA must succeed\n");
1079 ok(ret
== ret2
, "lengths of sort keys must be equal\n");
1080 ok(!lstrcmpA(buf
, buf2
), "sort keys must be equal\n");
1082 /* test NORM_IGNORENONSPACE */
1083 lstrcpyA(buf
, "foo");
1084 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, NORM_IGNORENONSPACE
,
1085 lower_case
, -1, buf
, sizeof(buf
));
1086 ok(ret
== lstrlenA(lower_case
) + 1, "LCMapStringA should return %d, ret = %d\n",
1087 lstrlenA(lower_case
) + 1, ret
);
1088 ok(!lstrcmpA(buf
, lower_case
), "LCMapStringA should return %s, but not %s\n", lower_case
, buf
);
1090 /* test NORM_IGNORESYMBOLS */
1091 lstrcpyA(buf
, "foo");
1092 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, NORM_IGNORESYMBOLS
,
1093 lower_case
, -1, buf
, sizeof(buf
));
1094 ok(ret
== lstrlenA(symbols_stripped
) + 1, "LCMapStringA should return %d, ret = %d\n",
1095 lstrlenA(symbols_stripped
) + 1, ret
);
1096 ok(!lstrcmpA(buf
, symbols_stripped
), "LCMapStringA should return %s, but not %s\n", lower_case
, buf
);
1098 /* test srclen = 0 */
1099 SetLastError(0xdeadbeef);
1100 ret
= LCMapStringA(LOCALE_USER_DEFAULT
, 0, upper_case
, 0, buf
, sizeof(buf
));
1101 ok(!ret
, "LCMapStringA should fail with srclen = 0\n");
1102 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1103 "unexpected error code %ld\n", GetLastError());
1106 void test_LCMapStringW(void)
1109 WCHAR buf
[256], buf2
[256];
1110 char *p_buf
= (char *)buf
, *p_buf2
= (char *)buf2
;
1111 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};
1112 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};
1113 static const WCHAR symbols_stripped
[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
1114 static const WCHAR fooW
[] = {'f','o','o',0};
1116 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_LOWERCASE
| LCMAP_UPPERCASE
,
1117 upper_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
1118 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1120 trace("Skipping LCMapStringW tests on Win9x\n");
1123 ok(!ret
, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1124 ok(GetLastError() == ERROR_INVALID_FLAGS
,
1125 "unexpected error code %ld\n", GetLastError());
1127 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_HIRAGANA
| LCMAP_KATAKANA
,
1128 upper_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
1129 ok(!ret
, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1130 ok(GetLastError() == ERROR_INVALID_FLAGS
,
1131 "unexpected error code %ld\n", GetLastError());
1133 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_HALFWIDTH
| LCMAP_FULLWIDTH
,
1134 upper_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
1135 ok(!ret
, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1136 ok(GetLastError() == ERROR_INVALID_FLAGS
,
1137 "unexpected error code %ld\n", GetLastError());
1139 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_TRADITIONAL_CHINESE
| LCMAP_SIMPLIFIED_CHINESE
,
1140 upper_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
1141 ok(!ret
, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1142 ok(GetLastError() == ERROR_INVALID_FLAGS
,
1143 "unexpected error code %ld\n", GetLastError());
1145 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1146 SetLastError(0xdeadbeef);
1147 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_LOWERCASE
| SORT_STRINGSORT
,
1148 upper_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
1149 ok(GetLastError() == ERROR_INVALID_FLAGS
, "expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError());
1150 ok(!ret
, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1152 /* test LCMAP_LOWERCASE */
1153 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_LOWERCASE
,
1154 upper_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
1155 ok(ret
== lstrlenW(upper_case
) + 1,
1156 "ret %d, error %ld, expected value %d\n",
1157 ret
, GetLastError(), lstrlenW(upper_case
) + 1);
1158 ok(!lstrcmpW(buf
, lower_case
), "string compare mismatch\n");
1160 /* test LCMAP_UPPERCASE */
1161 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_UPPERCASE
,
1162 lower_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
1163 ok(ret
== lstrlenW(lower_case
) + 1,
1164 "ret %d, error %ld, expected value %d\n",
1165 ret
, GetLastError(), lstrlenW(lower_case
) + 1);
1166 ok(!lstrcmpW(buf
, upper_case
), "string compare mismatch\n");
1168 /* test buffer overflow */
1169 SetLastError(0xdeadbeef);
1170 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_UPPERCASE
,
1171 lower_case
, -1, buf
, 4);
1172 ok(!ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
1173 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret
);
1175 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1176 lstrcpyW(buf
, lower_case
);
1177 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_UPPERCASE
,
1178 buf
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
1179 ok(ret
== lstrlenW(lower_case
) + 1,
1180 "ret %d, error %ld, expected value %d\n",
1181 ret
, GetLastError(), lstrlenW(lower_case
) + 1);
1182 ok(!lstrcmpW(buf
, upper_case
), "string compare mismatch\n");
1184 lstrcpyW(buf
, upper_case
);
1185 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_LOWERCASE
,
1186 buf
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
1187 ok(ret
== lstrlenW(upper_case
) + 1,
1188 "ret %d, error %ld, expected value %d\n",
1189 ret
, GetLastError(), lstrlenW(lower_case
) + 1);
1190 ok(!lstrcmpW(buf
, lower_case
), "string compare mismatch\n");
1192 /* otherwise src == dst should fail */
1193 SetLastError(0xdeadbeef);
1194 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
| LCMAP_UPPERCASE
,
1195 buf
, 10, buf
, sizeof(buf
));
1196 ok(GetLastError() == ERROR_INVALID_FLAGS
/* NT */ ||
1197 GetLastError() == ERROR_INVALID_PARAMETER
/* Win9x */,
1198 "unexpected error code %ld\n", GetLastError());
1199 ok(!ret
, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1201 /* test whether '\0' is always appended */
1202 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
,
1203 upper_case
, -1, buf
, sizeof(buf
));
1204 ok(ret
, "LCMapStringW must succeed\n");
1205 ret2
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
,
1206 upper_case
, lstrlenW(upper_case
), buf2
, sizeof(buf2
));
1207 ok(ret
, "LCMapStringW must succeed\n");
1208 ok(ret
== ret2
, "lengths of sort keys must be equal\n");
1209 ok(!lstrcmpA(p_buf
, p_buf2
), "sort keys must be equal\n");
1211 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1212 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
| NORM_IGNORECASE
,
1213 upper_case
, -1, buf
, sizeof(buf
));
1214 ok(ret
, "LCMapStringW must succeed\n");
1215 ret2
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
,
1216 lower_case
, -1, buf2
, sizeof(buf2
));
1217 ok(ret2
, "LCMapStringW must succeed\n");
1218 ok(ret
== ret2
, "lengths of sort keys must be equal\n");
1219 ok(!lstrcmpA(p_buf
, p_buf2
), "sort keys must be equal\n");
1221 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1222 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
| NORM_IGNORENONSPACE
,
1223 lower_case
, -1, buf
, sizeof(buf
));
1224 ok(ret
, "LCMapStringW must succeed\n");
1225 ret2
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
,
1226 lower_case
, -1, buf2
, sizeof(buf2
));
1227 ok(ret2
, "LCMapStringW must succeed\n");
1228 ok(ret
== ret2
, "lengths of sort keys must be equal\n");
1229 ok(!lstrcmpA(p_buf
, p_buf2
), "sort keys must be equal\n");
1231 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1232 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
| NORM_IGNORESYMBOLS
,
1233 lower_case
, -1, buf
, sizeof(buf
));
1234 ok(ret
, "LCMapStringW must succeed\n");
1235 ret2
= LCMapStringW(LOCALE_USER_DEFAULT
, LCMAP_SORTKEY
,
1236 symbols_stripped
, -1, buf2
, sizeof(buf2
));
1237 ok(ret2
, "LCMapStringW must succeed\n");
1238 ok(ret
== ret2
, "lengths of sort keys must be equal\n");
1239 ok(!lstrcmpA(p_buf
, p_buf2
), "sort keys must be equal\n");
1241 /* test NORM_IGNORENONSPACE */
1242 lstrcpyW(buf
, fooW
);
1243 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, NORM_IGNORENONSPACE
,
1244 lower_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
1245 ok(ret
== lstrlenW(lower_case
) + 1, "LCMapStringW should return %d, ret = %d\n",
1246 lstrlenW(lower_case
) + 1, ret
);
1247 ok(!lstrcmpW(buf
, lower_case
), "string comparison mismatch\n");
1249 /* test NORM_IGNORESYMBOLS */
1250 lstrcpyW(buf
, fooW
);
1251 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, NORM_IGNORESYMBOLS
,
1252 lower_case
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
1253 ok(ret
== lstrlenW(symbols_stripped
) + 1, "LCMapStringW should return %d, ret = %d\n",
1254 lstrlenW(symbols_stripped
) + 1, ret
);
1255 ok(!lstrcmpW(buf
, symbols_stripped
), "string comparison mismatch\n");
1257 /* test srclen = 0 */
1258 SetLastError(0xdeadbeef);
1259 ret
= LCMapStringW(LOCALE_USER_DEFAULT
, 0, upper_case
, 0, buf
, sizeof(buf
));
1260 ok(!ret
, "LCMapStringW should fail with srclen = 0\n");
1261 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1262 "unexpected error code %ld\n", GetLastError());
1265 #if 0 /* this requires collation table patch to make it MS compatible */
1266 const char *strings_sorted
[] =
1298 const char *strings
[] =
1330 static int compare_string1(const void *e1
, const void *e2
)
1332 const char *s1
= *(const char **)e1
;
1333 const char *s2
= *(const char **)e2
;
1335 return lstrcmpA(s1
, s2
);
1338 static int compare_string2(const void *e1
, const void *e2
)
1340 const char *s1
= *(const char **)e1
;
1341 const char *s2
= *(const char **)e2
;
1343 return CompareStringA(0, 0, s1
, -1, s2
, -1) - 2;
1346 static int compare_string3(const void *e1
, const void *e2
)
1348 const char *s1
= *(const char **)e1
;
1349 const char *s2
= *(const char **)e2
;
1350 char key1
[256], key2
[256];
1352 LCMapStringA(0, LCMAP_SORTKEY
, s1
, -1, key1
, sizeof(key1
));
1353 LCMapStringA(0, LCMAP_SORTKEY
, s2
, -1, key2
, sizeof(key2
));
1354 return strcmp(key1
, key2
);
1357 static void test_sorting(void)
1360 char **str_buf
= (char **)buf
;
1363 assert(sizeof(buf
) >= sizeof(strings
));
1365 /* 1. sort using lstrcmpA */
1366 memcpy(buf
, strings
, sizeof(strings
));
1367 qsort(buf
, sizeof(strings
)/sizeof(strings
[0]), sizeof(strings
[0]), compare_string1
);
1368 for (i
= 0; i
< sizeof(strings
)/sizeof(strings
[0]); i
++)
1370 ok(!strcmp(strings_sorted
[i
], str_buf
[i
]),
1371 "qsort using lstrcmpA failed for element %d\n", i
);
1373 /* 2. sort using CompareStringA */
1374 memcpy(buf
, strings
, sizeof(strings
));
1375 qsort(buf
, sizeof(strings
)/sizeof(strings
[0]), sizeof(strings
[0]), compare_string2
);
1376 for (i
= 0; i
< sizeof(strings
)/sizeof(strings
[0]); i
++)
1378 ok(!strcmp(strings_sorted
[i
], str_buf
[i
]),
1379 "qsort using CompareStringA failed for element %d\n", i
);
1381 /* 3. sort using sort keys */
1382 memcpy(buf
, strings
, sizeof(strings
));
1383 qsort(buf
, sizeof(strings
)/sizeof(strings
[0]), sizeof(strings
[0]), compare_string3
);
1384 for (i
= 0; i
< sizeof(strings
)/sizeof(strings
[0]); i
++)
1386 ok(!strcmp(strings_sorted
[i
], str_buf
[i
]),
1387 "qsort using sort keys failed for element %d\n", i
);
1392 static void test_FoldStringA(void)
1395 char src
[256], dst
[256];
1396 static const char digits_src
[] = { 0xB9,0xB2,0xB3,'\0' };
1397 static const char digits_dst
[] = { '1','2','3','\0' };
1398 static const char composite_src
[] =
1400 0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
1401 0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
1402 0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
1403 0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
1404 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
1405 0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
1406 0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
1407 0xfb,0xfc,0xfd,0xff,'\0'
1409 static const char composite_dst
[] =
1411 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1412 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1413 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1414 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1415 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1416 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1417 0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
1418 0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
1419 0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
1420 0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
1421 0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
1422 0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
1423 0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
1424 0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
1425 0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1427 static const char ligatures_src
[] =
1429 0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1431 static const char ligatures_dst
[] =
1433 'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1437 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1439 /* these tests are locale specific */
1440 if (GetACP() != 1252)
1442 trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1446 /* MAP_FOLDDIGITS */
1448 ret
= pFoldStringA(MAP_FOLDDIGITS
, digits_src
, -1, dst
, 256);
1449 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED
)
1451 EXPECT_LEN(4); EXPECT_VALID
;
1452 ok(strcmp(dst
, digits_dst
) == 0,
1453 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst
, dst
);
1454 for (i
= 1; i
< 256; i
++)
1456 if (!strchr(digits_src
, i
))
1461 ret
= pFoldStringA(MAP_FOLDDIGITS
, src
, -1, dst
, 256);
1462 EXPECT_LEN(2); EXPECT_VALID
;
1463 ok(dst
[0] == src
[0],
1464 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src
, dst
);
1468 /* MAP_EXPAND_LIGATURES */
1470 ret
= pFoldStringA(MAP_EXPAND_LIGATURES
, ligatures_src
, -1, dst
, 256);
1471 EXPECT_LEN(sizeof(ligatures_dst
)); EXPECT_VALID
;
1472 ok(strcmp(dst
, ligatures_dst
) == 0,
1473 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst
, dst
);
1474 for (i
= 1; i
< 256; i
++)
1476 if (!strchr(ligatures_src
, i
))
1481 ret
= pFoldStringA(MAP_EXPAND_LIGATURES
, src
, -1, dst
, 256);
1482 EXPECT_LEN(2); EXPECT_VALID
;
1483 ok(dst
[0] == src
[0],
1484 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src
, dst
);
1490 ret
= pFoldStringA(MAP_COMPOSITE
, composite_src
, -1, dst
, 256);
1494 /* Wine gets close, but doesn't produce quite the same result as native */
1496 ok(strcmp(dst
, composite_dst
) == 0,
1497 "MAP_COMPOSITE: Expected '%s', got '%s'\n", composite_dst
, dst
);
1500 for (i
= 1; i
< 256; i
++)
1502 if (!strchr(composite_src
, i
))
1507 ret
= pFoldStringA(MAP_COMPOSITE
, src
, -1, dst
, 256);
1508 EXPECT_LEN(2); EXPECT_VALID
;
1509 ok(dst
[0] == src
[0],
1510 "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src
[0],
1511 (unsigned char)dst
[0],(unsigned char)dst
[1],(unsigned char)dst
[2]);
1516 for (i
= 1; i
< 256; i
++)
1521 ret
= pFoldStringA(MAP_FOLDCZONE
, src
, -1, dst
, 256);
1522 EXPECT_LEN(2); EXPECT_VALID
;
1523 ok(src
[0] == dst
[0],
1524 "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
1525 (unsigned char)src
[0], (unsigned char)dst
[0]);
1528 /* MAP_PRECOMPOSED */
1529 for (i
= 1; i
< 256; i
++)
1534 ret
= pFoldStringA(MAP_PRECOMPOSED
, src
, -1, dst
, 256);
1535 EXPECT_LEN(2); EXPECT_VALID
;
1536 ok(src
[0] == dst
[0],
1537 "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
1538 (unsigned char)src
[0], (unsigned char)dst
[0]);
1542 static void test_FoldStringW(void)
1546 WCHAR src
[256], dst
[256], ch
, prev_ch
= 1;
1547 static const DWORD badFlags
[] =
1550 MAP_PRECOMPOSED
|MAP_COMPOSITE
,
1551 MAP_PRECOMPOSED
|MAP_EXPAND_LIGATURES
,
1552 MAP_COMPOSITE
|MAP_EXPAND_LIGATURES
1554 /* Ranges of digits 0-9 : Must be sorted! */
1555 static const WCHAR digitRanges
[] =
1557 0x0030, /* '0'-'9' */
1558 0x0660, /* Eastern Arabic */
1559 0x06F0, /* Arabic - Hindu */
1560 0x0966, /* Devengari */
1561 0x09E6, /* Bengalii */
1562 0x0A66, /* Gurmukhi */
1563 0x0AE6, /* Gujarati */
1565 0x0BE6, /* Tamil - No 0 */
1566 0x0C66, /* Telugu */
1567 0x0CE6, /* Kannada */
1568 0x0D66, /* Maylayalam */
1571 0x2070, /* Superscript - 1, 2, 3 are out of sequence */
1572 0x2080, /* Subscript */
1573 0x245F, /* Circled - 0 is out of sequence */
1574 0x2473, /* Bracketed */
1575 0x2487, /* Full stop */
1576 0x2775, /* Inverted circled - No 0 */
1577 0x277F, /* Patterned circled - No 0 */
1578 0x2789, /* Inverted Patterned circled - No 0 */
1579 0xff10, /* Pliene chasse (?) */
1580 0xffff /* Terminator */
1582 /* Digits which are represented, but out of sequence */
1583 static const WCHAR outOfSequenceDigits
[] =
1585 0xB9, /* Superscript 1 */
1586 0xB2, /* Superscript 2 */
1587 0xB3, /* Superscript 3 */
1588 0x24EA, /* Circled 0 */
1589 '\0' /* Terminator */
1591 /* Digits in digitRanges for which no representation is available */
1592 static const WCHAR noDigitAvailable
[] =
1594 0x0BE6, /* No Tamil 0 */
1595 0x2473, /* No Bracketed 0 */
1596 0x2487, /* No 0 Full stop */
1597 0x2775, /* No inverted circled 0 */
1598 0x277F, /* No patterned circled */
1599 0x2789, /* No inverted Patterned circled */
1600 '\0' /* Terminator */
1602 /* Compatibility conversion results */
1603 static const WCHAR compat_F900_FA2F
[256+48] =
1605 0x8c48, 0x66f4, 0x8eca, 0x8cc8, 0x6ed1, 0x4e32, 0x53e5, 0x9f9c,
1606 0x9f9c, 0x5951, 0x91d1, 0x5587, 0x5948, 0x61f6, 0x7669, 0x7f85,
1607 0x863f, 0x87ba, 0x88f8, 0x908f, 0x6a02, 0x6d1b, 0x70d9, 0x73de,
1608 0x843d, 0x916a, 0x99f1, 0x4e82, 0x5375, 0x6b04, 0x721b, 0x862d,
1609 0x9e1e, 0x5d50, 0x6feb, 0x85cd, 0x8964, 0x62c9, 0x81d8, 0x881f,
1610 0x5eca, 0x6717, 0x6d6a, 0x72fc, 0x0000, 0x4f86, 0x51b7, 0x52de,
1611 0x64c4, 0x6ad3, 0x7210, 0x76e7, 0x8001, 0x8606, 0x865c, 0x8def,
1612 0x9732, 0x9b6f, 0x9dfa, 0x788c, 0x797f, 0x7da0, 0x83c9, 0x9304,
1613 0x9e7f, 0x8ad6, 0x58df, 0x5f04, 0x7c60, 0x807e, 0x7262, 0x78ca,
1614 0x8cc2, 0x96f7, 0x58d8, 0x5c62, 0x6a13, 0x6dda, 0x6f0f, 0x7d2f,
1615 0x7e37, 0x964b, 0x52d2, 0x808b, 0x51dc, 0x51cc, 0x7a1c, 0x7dbe,
1616 0x83f1, 0x9675, 0x8b80, 0x62cf, 0x6a02, 0x8afe, 0x4e39, 0x5be7,
1617 0x6012, 0x7387, 0x7570, 0x5317, 0x78fb, 0x4fbf, 0x5fa9, 0x4e0d,
1618 0x6ccc, 0x6578, 0x7d22, 0x53c3, 0x585e, 0x7701, 0x8449, 0x8aaa,
1619 0x6bba, 0x8fb0, 0x6c88, 0x62fe, 0x82e5, 0x63a0, 0x7565, 0x4eae,
1620 0x5169, 0x0000, 0x6881, 0x7ce7, 0x826f, 0x8ad2, 0x91cf, 0x52f5,
1621 0x5442, 0x5973, 0x5eec, 0x65c5, 0x6ffe, 0x792a, 0x95ad, 0x9a6a,
1622 0x9e97, 0x9ece, 0x529b, 0x66c6, 0x6b77, 0x8f62, 0x5e74, 0x6190,
1623 0x6200, 0x649a, 0x6f23, 0x7149, 0x7489, 0x0000, 0x7df4, 0x806f,
1624 0x8f26, 0x84ee, 0x9023, 0x934a, 0x5217, 0x52a3, 0x54bd, 0x70c8,
1625 0x88c2, 0x8aaa, 0x5ec9, 0x5ff5, 0x637b, 0x6bae, 0x7c3e, 0x7375,
1626 0x4ee4, 0x56f9, 0x5be7, 0x5dba, 0x601c, 0x73b2, 0x7469, 0x7f9a,
1627 0x8046, 0x9234, 0x96f6, 0x9748, 0x9818, 0x4f8b, 0x79ae, 0x91b4,
1628 0x96b8, 0x60e1, 0x4e86, 0x50da, 0x5bee, 0x5c3f, 0x6599, 0x6a02,
1629 0x71ce, 0x7642, 0x84fc, 0x907c, 0x9f8d, 0x6688, 0x962e, 0x5289,
1630 0x677b, 0x67f3, 0x6d41, 0x6e9c, 0x7409, 0x7559, 0x786b, 0x7d10,
1631 0x985e, 0x516d, 0x622e, 0x9678, 0x502b, 0x5d19, 0x6dea, 0x8f2a,
1632 0x5f8b, 0x6144, 0x6817, 0x7387, 0x9686, 0x5229, 0x540f, 0x5c65,
1633 0x6613, 0x674e, 0x68a8, 0x6ce5, 0x7406, 0x75e2, 0x7f79, 0x0000,
1634 0x88e1, 0x91cc, 0x96e2, 0x533f, 0x6eba, 0x541d, 0x71d0, 0x7498,
1635 0x85fa, 0x0000, 0x9c57, 0x9e9f, 0x6797, 0x6dcb, 0x81e8, 0x7acb,
1636 0x7b20, 0x7c92, 0x72c0, 0x7099, 0x8b58, 0x4ec0, 0x8336, 0x523a,
1637 0x5207, 0x5ea6, 0x62d3, 0x7cd6, 0x5b85, 0x6d1e, 0x66b4, 0x8f3b,
1638 0x884c, 0x964d, 0x898b, 0x5ed3, 0x0000, 0x0000, 0x0000, 0x0000,
1639 0x585a, 0x0000, 0x6674, 0x0000, 0x0000, 0x51de, 0x8c6c, 0x76ca,
1640 0x0000, 0x795e, 0x7965, 0x798f, 0x9756, 0x7cbe, 0x7fbd, 0x0000,
1641 0x0000, 0x0000, 0x8af8, 0x0000, 0x0000, 0x9038, 0x90fd, 0x0000,
1642 0x0000, 0x0000, 0x98ef, 0x98fc, 0x9928, 0x9db4, 0x0000, 0x0000
1644 static const WCHAR compat_FE30_FEF7
[200] =
1646 0x2025, 0x2014, 0x2013, 0x005f, 0x005f, 0x0028, 0x0029, 0x007b,
1647 0x007d, 0x3014, 0x3015, 0x3010, 0x3011, 0x300a, 0x300b, 0x3008,
1648 0x3009, 0x300c, 0x300d, 0x300e, 0x300f, 0x0000, 0x0000, 0x0000,
1649 0x0000, 0x203e, 0x203e, 0x203e, 0x203e, 0x005f, 0x005f, 0x005f,
1650 0x002c, 0x3001, 0x002e, 0x0000, 0x003b, 0x003a, 0x003f, 0x0021,
1651 0x2014, 0x0028, 0x0029, 0x007b, 0x007d, 0x3014, 0x3015, 0x0023,
1652 0x0026, 0x002a, 0x002b, 0x002d, 0x003c, 0x003e, 0x003d, 0x0000,
1653 0x0000, 0x0024, 0x0025, 0x0040, 0x0000, 0x0000, 0x0000, 0x0000,
1654 0x064b, 0x064b, 0x064c, 0x0000, 0x064d, 0x0000, 0x064e, 0x064e,
1655 0x064f, 0x064f, 0x0650, 0x0650, 0x0651, 0x0651, 0x0652, 0x0652,
1656 0x0621, 0x0622, 0x0622, 0x0623, 0x0623, 0x0624, 0x0624, 0x0625,
1657 0x0625, 0x0626, 0x0626, 0x0626, 0x0626, 0x0627, 0x0627, 0x0628,
1658 0x0628, 0x0628, 0x0628, 0x0629, 0x0629, 0x062a, 0x062a, 0x062a,
1659 0x062a, 0x062b, 0x062b, 0x062b, 0x062b, 0x062c, 0x062c, 0x062c,
1660 0x062c, 0x062d, 0x062d, 0x062d, 0x062d, 0x062e, 0x062e, 0x062e,
1661 0x062e, 0x062f, 0x062f, 0x0630, 0x0630, 0x0631, 0x0631, 0x0632,
1662 0x0632, 0x0633, 0x0633, 0x0633, 0x0633, 0x0634, 0x0634, 0x0634,
1663 0x0634, 0x0635, 0x0635, 0x0635, 0x0635, 0x0636, 0x0636, 0x0636,
1664 0x0636, 0x0637, 0x0637, 0x0637, 0x0637, 0x0638, 0x0638, 0x0638,
1665 0x0638, 0x0639, 0x0639, 0x0639, 0x0639, 0x063a, 0x063a, 0x063a,
1666 0x063a, 0x0641, 0x0641, 0x0641, 0x0641, 0x0642, 0x0642, 0x0642,
1667 0x0642, 0x0643, 0x0643, 0x0643, 0x0643, 0x0644, 0x0644, 0x0644,
1668 0x0644, 0x0645, 0x0645, 0x0645, 0x0645, 0x0646, 0x0646, 0x0646,
1669 0x0646, 0x0647, 0x0647, 0x0647, 0x0647, 0x0648, 0x0648, 0x0649,
1670 0x0649, 0x064a, 0x064a, 0x064a, 0x064a, 0x0000, 0x0000, 0x0000
1672 static const WCHAR compat_FF00_FFEF
[240] =
1674 0x0000, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
1675 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
1676 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
1677 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
1678 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
1679 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
1680 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
1681 0x0058, 0x0059, 0x005a, 0x005b, 0x0000, 0x005d, 0x005e, 0x005f,
1682 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
1683 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
1684 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
1685 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000,
1686 0x0000, 0x3002, 0x300c, 0x300d, 0x3001, 0x30fb, 0x30f2, 0x30a1,
1687 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, 0x30c3,
1688 0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, 0x30ab, 0x30ad,
1689 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, 0x30b9, 0x30bb, 0x30bd,
1690 0x30bf, 0x30c1, 0x30c4, 0x30c6, 0x30c8, 0x30ca, 0x30cb, 0x30cc,
1691 0x30cd, 0x30ce, 0x30cf, 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de,
1692 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9,
1693 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c,
1694 0x3164, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137,
1695 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f,
1696 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147,
1697 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x0000,
1698 0x0000, 0x0000, 0x314f, 0x3150, 0x3151, 0x3152, 0x3153, 0x3154,
1699 0x0000, 0x0000, 0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315a,
1700 0x0000, 0x0000, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, 0x3160,
1701 0x0000, 0x0000, 0x3161, 0x3162, 0x3163, 0x0000, 0x0000, 0x0000,
1702 0x00a2, 0x00a3, 0x00ac, 0x00af, 0x00a6, 0x00a5, 0x20a9, 0x0000,
1703 0x2502, 0x2190, 0x2191, 0x2192, 0x2193, 0x25a0, 0x25cb, 0x0000
1705 static const WCHAR ligatures_src
[] =
1707 0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
1708 0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
1709 0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
1710 0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
1711 0xfb04, 0xfb05, 0xfb06, '\0'
1713 static const WCHAR ligatures_dst
[] =
1715 'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
1716 'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
1717 'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
1718 0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
1719 'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
1723 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1725 /* Invalid flag combinations */
1726 for (i
= 0; i
< sizeof(badFlags
)/sizeof(badFlags
[0]); i
++)
1728 src
[0] = dst
[0] = '\0';
1730 ret
= pFoldStringW(badFlags
[i
], src
, 256, dst
, 256);
1731 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED
)
1733 EXPECT_LEN(0); EXPECT_FLAGS
;
1736 /* src & dst cannot be the same */
1738 ret
= pFoldStringW(MAP_FOLDCZONE
, src
, -1, src
, 256);
1739 EXPECT_LEN(0); EXPECT_INVALID
;
1741 /* src can't be NULL */
1743 ret
= pFoldStringW(MAP_FOLDCZONE
, NULL
, -1, dst
, 256);
1744 EXPECT_LEN(0); EXPECT_INVALID
;
1746 /* srclen can't be 0 */
1748 ret
= pFoldStringW(MAP_FOLDCZONE
, src
, 0, dst
, 256);
1749 EXPECT_LEN(0); EXPECT_INVALID
;
1751 /* dstlen can't be < 0 */
1753 ret
= pFoldStringW(MAP_FOLDCZONE
, src
, -1, dst
, -1);
1754 EXPECT_LEN(0); EXPECT_INVALID
;
1756 /* Ret includes terminating NUL which is appended if srclen = -1 */
1761 ret
= pFoldStringW(MAP_FOLDCZONE
, src
, -1, dst
, 256);
1762 EXPECT_LEN(2); EXPECT_VALID
;
1763 ok(dst
[0] == 'A' && dst
[1] == '\0',
1764 "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%ld\n",
1765 'A', '\0', ret
, dst
[0], dst
[1], GetLastError());
1767 /* If size is given, result is not NUL terminated */
1773 ret
= pFoldStringW(MAP_FOLDCZONE
, src
, 1, dst
, 256);
1774 EXPECT_LEN(1); EXPECT_VALID
;
1775 ok(dst
[0] == 'A' && dst
[1] == 'X',
1776 "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%ld\n",
1777 'A','X', ret
, dst
[0], dst
[1], GetLastError());
1779 /* MAP_FOLDDIGITS */
1780 for (j
= 0; j
< sizeof(digitRanges
)/sizeof(digitRanges
[0]); j
++)
1782 /* Check everything before this range */
1783 for (ch
= prev_ch
; ch
< digitRanges
[j
]; ch
++)
1787 src
[1] = dst
[0] = '\0';
1788 ret
= pFoldStringW(MAP_FOLDDIGITS
, src
, -1, dst
, 256);
1789 EXPECT_LEN(2); EXPECT_VALID
;
1791 ok(dst
[0] == ch
|| strchrW(outOfSequenceDigits
, ch
) ||
1792 /* Wine (correctly) maps all Unicode 4.0+ digits */
1793 isdigitW(ch
) || (ch
>= 0x24F5 && ch
<= 0x24FD) || ch
== 0x24FF,
1794 "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch
, ch
, dst
[0]);
1797 if (digitRanges
[j
] == 0xffff)
1798 break; /* Finished the whole code point space */
1800 for (ch
= digitRanges
[j
]; ch
< digitRanges
[j
] + 10; ch
++)
1804 /* Map out of sequence characters */
1805 if (ch
== 0x2071) c
= 0x00B9; /* Superscript 1 */
1806 else if (ch
== 0x2072) c
= 0x00B2; /* Superscript 2 */
1807 else if (ch
== 0x2073) c
= 0x00B3; /* Superscript 3 */
1808 else if (ch
== 0x245F) c
= 0x24EA; /* Circled 0 */
1812 src
[1] = dst
[0] = '\0';
1813 ret
= pFoldStringW(MAP_FOLDDIGITS
, src
, -1, dst
, 256);
1814 EXPECT_LEN(2); EXPECT_VALID
;
1816 ok((dst
[0] == '0' + ch
- digitRanges
[j
] && dst
[1] == '\0') ||
1817 strchrW(noDigitAvailable
, c
),
1818 "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
1819 ch
, '0' + digitRanges
[j
] - ch
, dst
[0]);
1825 for (ch
= 1; ch
<0xffff; ch
++)
1829 if (ch
>= 0xF900 && ch
<= 0xFA2F)
1830 expected
= compat_F900_FA2F
[ch
- 0xF900];
1831 else if (ch
>= 0xFE30 && ch
<= 0xFEF7)
1832 expected
= compat_FE30_FEF7
[ch
- 0xFE30];
1833 else if (ch
>= 0xFF00 && ch
<= 0xFFEF)
1834 expected
= compat_FF00_FFEF
[ch
- 0xFF00];
1841 src
[1] = dst
[0] = '\0';
1842 ret
= pFoldStringW(MAP_FOLDCZONE
, src
, -1, dst
, 256);
1843 EXPECT_LEN(2); EXPECT_VALID
;
1844 ok(dst
[0] == expected
||
1845 /* Wine (correctly) uses updated mappings for some Unicode 4.0 chars */
1846 (ch
>= 0xFA0D && ch
<= 0xFA47) ||
1847 0xf92c || ch
== 0xf979 || ch
== 0xf995 || ch
== 0xf9e7 || ch
== 0xf9f1,
1848 "MAP_FOLDCZONE: ch %d 0x%04x Expected 0x%04x got 0x%04x\n",
1849 ch
, ch
, expected
, dst
[0]);
1852 /* MAP_EXPAND_LIGATURES */
1854 ret
= pFoldStringW(MAP_EXPAND_LIGATURES
, ligatures_src
, -1, dst
, 256);
1855 EXPECT_LEN(sizeof(ligatures_dst
)/sizeof(ligatures_dst
[0])); EXPECT_VALID
;
1856 ok(!memcmp(dst
, ligatures_dst
, sizeof(ligatures_dst
)),
1857 "MAP_EXPAND_LIGATURES: Expanded incorrectly\n");
1858 for (i
= 1; i
<= 0xffff; i
++)
1860 if (!strchrW(ligatures_src
, i
))
1865 ret
= pFoldStringW(MAP_EXPAND_LIGATURES
, src
, -1, dst
, 256);
1866 EXPECT_LEN(2); EXPECT_VALID
;
1867 ok(dst
[0] == src
[0],
1868 "MAP_EXPAND_LIGATURES: 0x%02x : Expected 0x%02x, got 0x%02x\n",
1873 /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
1878 #define LCID_OK(l) \
1879 ok(lcid == l, "Expected lcid = %08lx, got %08lx\n", l, lcid)
1880 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
1881 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
1882 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
1883 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
1885 static void test_ConvertDefaultLocale(void)
1889 /* Doesn't change lcid, even if non default sublang/sort used */
1890 TEST_LCID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
, SORT_DEFAULT
);
1891 TEST_LCID(LANG_ENGLISH
, SUBLANG_ENGLISH_UK
, SORT_DEFAULT
);
1892 TEST_LCID(LANG_JAPANESE
, SUBLANG_DEFAULT
, SORT_DEFAULT
);
1893 TEST_LCID(LANG_JAPANESE
, SUBLANG_DEFAULT
, SORT_JAPANESE_UNICODE
);
1895 /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
1896 LCID_RES(MKLCID(LANG_ENGLISH
, SUBLANG_NEUTRAL
, SORT_DEFAULT
),
1897 MKLCID(LANG_ENGLISH
, SUBLANG_DEFAULT
, SORT_DEFAULT
));
1898 LCID_RES(MKLCID(LANG_JAPANESE
, SUBLANG_NEUTRAL
, SORT_DEFAULT
),
1899 MKLCID(LANG_JAPANESE
, SUBLANG_DEFAULT
, SORT_DEFAULT
));
1900 LCID_RES(MKLCID(LANG_JAPANESE
, SUBLANG_NEUTRAL
, SORT_JAPANESE_UNICODE
),
1901 MKLCID(LANG_JAPANESE
, SUBLANG_DEFAULT
, SORT_JAPANESE_UNICODE
));
1903 /* Invariant language is not treated specially */
1904 TEST_LCID(LANG_INVARIANT
, SUBLANG_DEFAULT
, SORT_DEFAULT
);
1905 LCID_RES(MKLCID(LANG_INVARIANT
, SUBLANG_NEUTRAL
, SORT_DEFAULT
),
1906 MKLCID(LANG_INVARIANT
, SUBLANG_DEFAULT
, SORT_DEFAULT
));
1908 /* User/system default languages alone are not mapped */
1909 TEST_LCIDLANG(LANG_SYSTEM_DEFAULT
, SORT_JAPANESE_UNICODE
);
1910 TEST_LCIDLANG(LANG_USER_DEFAULT
, SORT_JAPANESE_UNICODE
);
1913 LCID_RES(LOCALE_SYSTEM_DEFAULT
, GetSystemDefaultLCID());
1914 LCID_RES(LOCALE_USER_DEFAULT
, GetUserDefaultLCID());
1915 LCID_RES(LOCALE_NEUTRAL
, GetUserDefaultLCID());
1918 static BOOL CALLBACK
langgrp_procA(LGRPID lgrpid
, LPSTR lpszNum
, LPSTR lpszName
,
1919 DWORD dwFlags
, LONG_PTR lParam
)
1921 trace("%08lx, %s, %s, %08lx, %08lx\n",
1922 lgrpid
, lpszNum
, lpszName
, dwFlags
, lParam
);
1924 ok(pIsValidLanguageGroup(lgrpid
, dwFlags
) == TRUE
,
1925 "Enumerated grp %ld not valid (flags %ld)\n", lgrpid
, dwFlags
);
1927 /* If lParam is one, we are calling with flags defaulted from 0 */
1928 ok(!lParam
|| (dwFlags
== LGRPID_INSTALLED
|| dwFlags
== LGRPID_SUPPORTED
),
1929 "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %ld\n", dwFlags
);
1934 static void test_EnumSystemLanguageGroupsA(void)
1936 if (!pEnumSystemLanguageGroupsA
|| !pIsValidLanguageGroup
)
1939 /* No enumeration proc */
1941 pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED
, 0);
1946 pEnumSystemLanguageGroupsA(langgrp_procA
, LGRPID_INSTALLED
|LGRPID_SUPPORTED
, 0);
1949 /* No flags - defaults to LGRPID_INSTALLED */
1951 pEnumSystemLanguageGroupsA(langgrp_procA
, 0, 1);
1954 pEnumSystemLanguageGroupsA(langgrp_procA
, LGRPID_INSTALLED
, 0);
1955 pEnumSystemLanguageGroupsA(langgrp_procA
, LGRPID_SUPPORTED
, 0);
1959 static BOOL CALLBACK
lgrplocale_procA(LGRPID lgrpid
, LCID lcid
, LPSTR lpszNum
,
1962 trace("%08lx, %08lx, %s, %08lx\n", lgrpid
, lcid
, lpszNum
, lParam
);
1964 ok(pIsValidLanguageGroup(lgrpid
, LGRPID_SUPPORTED
) == TRUE
,
1965 "Enumerated grp %ld not valid\n", lgrpid
);
1966 ok(IsValidLocale(lcid
, LCID_SUPPORTED
) == TRUE
,
1967 "Enumerated grp locale %ld not valid\n", lcid
);
1971 static void test_EnumLanguageGroupLocalesA(void)
1973 if (!pEnumLanguageGroupLocalesA
|| !pIsValidLanguageGroup
)
1976 /* No enumeration proc */
1978 pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE
, 0, 0);
1981 /* lgrpid too small */
1983 pEnumLanguageGroupLocalesA(lgrplocale_procA
, 0, 0, 0);
1986 /* lgrpid too big */
1988 pEnumLanguageGroupLocalesA(lgrplocale_procA
, LGRPID_ARMENIAN
+ 1, 0, 0);
1991 /* dwFlags is reserved */
1993 pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE
, 0x1, 0);
1996 pEnumLanguageGroupLocalesA(lgrplocale_procA
, LGRPID_WESTERN_EUROPE
, 0, 0);
1999 static void test_SetLocaleInfoA(void)
2002 LCID lcid
= GetUserDefaultLCID();
2006 bRet
= SetLocaleInfoA(lcid
, LOCALE_SDATE
, 0);
2011 bRet
= SetLocaleInfoA(lcid
, LOCALE_IDATE
, (LPSTR
)test_SetLocaleInfoA
);
2016 bRet
= SetLocaleInfoA(lcid
, LOCALE_ILDATE
, (LPSTR
)test_SetLocaleInfoA
);
2022 InitFunctionPointers();
2025 test_EnumTimeFormats();
2027 test_GetLocaleInfoA();
2028 test_GetTimeFormatA();
2029 test_GetDateFormatA();
2030 test_GetDateFormatW();
2031 test_GetCurrencyFormatA(); /* Also tests the W version */
2032 test_GetNumberFormatA(); /* Also tests the W version */
2033 test_CompareStringA();
2034 test_LCMapStringA();
2035 test_LCMapStringW();
2038 test_ConvertDefaultLocale();
2039 test_EnumSystemLanguageGroupsA();
2040 test_EnumLanguageGroupLocalesA();
2041 test_SetLocaleInfoA();
2042 #if 0 /* this requires collation table patch to make it MS compatible */