scroll mode for very long start menus
[reactos.git] / reactos / apps / tests / kernel32 / locale.c
1 /*
2 * Unit tests for locale functions
3 *
4 * Copyright 2002 YASAR Mehmet
5 * Copyright 2003 Dmitry Timoshkov
6 * Copyright 2003 Jon Griffiths
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 * NOTES
23 * We must pass LOCALE_NOUSEROVERRIDE (NUO) to formatting functions so that
24 * even when the user has overridden their default i8n settings (e.g. in
25 * the control panel i8n page), we will still get the expected results.
26 */
27
28 #include <assert.h>
29 #include <stdlib.h>
30 #include <stdarg.h>
31
32 #include "wine/test.h"
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winerror.h"
36 #include "winnls.h"
37
38 static inline unsigned int strlenW( const WCHAR *str )
39 {
40 const WCHAR *s = str;
41 while (*s) s++;
42 return s - str;
43 }
44
45 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
46 {
47 if (n <= 0) return 0;
48 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
49 return *str1 - *str2;
50 }
51
52 static inline WCHAR *strchrW( const WCHAR *str, WCHAR ch )
53 {
54 for ( ; *str; str++) if (*str == ch) return (WCHAR *)str;
55 return NULL;
56 }
57
58 inline static int isdigitW( WCHAR wc )
59 {
60 WORD type;
61 GetStringTypeW( CT_CTYPE1, &wc, 1, &type );
62 return type & C1_DIGIT;
63 }
64
65 /* Some functions are only in later versions of kernel32.dll */
66 static HMODULE hKernel32;
67
68 typedef BOOL (WINAPI *EnumSystemLanguageGroupsAFn)(LANGUAGEGROUP_ENUMPROC,
69 DWORD, LONG_PTR);
70 static EnumSystemLanguageGroupsAFn pEnumSystemLanguageGroupsA;
71 typedef BOOL (WINAPI *EnumLanguageGroupLocalesAFn)(LANGGROUPLOCALE_ENUMPROC,
72 LGRPID, DWORD, LONG_PTR);
73 static EnumLanguageGroupLocalesAFn pEnumLanguageGroupLocalesA;
74
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;
79
80 typedef BOOL (WINAPI *IsValidLanguageGroupFn)(LGRPID, DWORD);
81 static IsValidLanguageGroupFn pIsValidLanguageGroup;
82
83 static void InitFunctionPointers(void)
84 {
85 hKernel32 = GetModuleHandleA("kernel32");
86
87 if (hKernel32)
88 {
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");
94 }
95 }
96
97 #define eq(received, expected, label, type) \
98 ok((received) == (expected), "%s: got " type " instead of " type "\n", \
99 (label), (received), (expected))
100
101 #define BUFFER_SIZE 128
102 char GlobalBuffer[BUFFER_SIZE]; /* Buffer used by callback function */
103 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
104
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())
117
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)
122
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")
128
129 #define NUO LOCALE_NOUSEROVERRIDE
130
131 static void test_GetLocaleInfoA()
132 {
133 int ret;
134 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
135 char buffer[BUFFER_SIZE];
136
137 ok(lcid == 0x409, "wrong LCID calculated - %ld\n", lcid);
138
139 /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
140 * partially fill the buffer even if it is too short. See bug 637.
141 */
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);
145
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);
150
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);
155 }
156
157 static void test_GetTimeFormatA()
158 {
159 int ret;
160 SYSTEMTIME curtime;
161 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
162 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
163
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;
168
169 curtime.wHour = 8;
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;
176
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;
180
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;
184
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;
188
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;
192
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;
196
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;
201
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;
205
206 STRINGSA("s1s2s3", ""); /* Duplicate tokens */
207 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
208 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
209
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;
213
214 curtime.wHour = 13;
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;
218
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;
222
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;
226
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;
230
231 curtime.wHour = 14; /* change this to 14 or 2pm */
232 curtime.wMinute = 5;
233 curtime.wSecond = 3;
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;
237
238 curtime.wHour = 0;
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;
242
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;
246
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.
252 */
253 curtime.wHour = 8;
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;
261
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;
266
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;
271
272 STRINGSA("'''", "'"); /* invalid quoted string */
273 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
274 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
275
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;
280
281 STRINGSA("''HHHHHH", "08"); /* Normal use */
282 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
283 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
284
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;
289
290 STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
291 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
292 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
293
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;
297
298 curtime.wHour = 25;
299 STRINGSA("'123'tt", ""); /* Invalid time */
300 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
301 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
302
303 curtime.wHour = 12;
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;
308 }
309
310 static void test_GetDateFormatA()
311 {
312 int ret;
313 SYSTEMTIME curtime;
314 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
315 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
316
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;
321
322 curtime.wYear = 2002;
323 curtime.wMonth = 5;
324 curtime.wDay = 4;
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;
329
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;
333
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;
338
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;
342
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;
346
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;
350
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;
354
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;
360
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;
367 }
368
369 static void test_GetDateFormatW()
370 {
371 int ret;
372 SYSTEMTIME curtime;
373 WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
374 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
375
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)
380 return;
381 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQW;
382
383 STRINGSW("",""); /* NULL buffer, len > 0 */
384 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
385 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQW;
386
387 STRINGSW("",""); /* NULL buffer, len == 0 */
388 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
389 EXPECT_VALID; EXPECT_LENW; EXPECT_EQW;
390
391 curtime.wYear = 2002;
392 curtime.wMonth = 10;
393 curtime.wDay = 23;
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;
402 }
403
404
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
409
410 static void test_GetCurrencyFormatA()
411 {
412 static char szDot[] = { '.', '\0' };
413 static char szComma[] = { ',', '\0' };
414 static char szDollar[] = { '$', '\0' };
415 int ret;
416 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
417 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
418 CURRENCYFMTA format;
419
420 memset(&format, 0, sizeof(format));
421
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;
425
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;
429
430 STRINGSA("--",""); /* Double '-' --> Error */
431 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
432 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
433
434 STRINGSA("0-",""); /* Trailing '-' --> Error */
435 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
436 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
437
438 STRINGSA("0..",""); /* Double '.' --> Error */
439 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
440 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
441
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;
445
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;
449
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;
453
454 STRINGSA("2353",""); /* Invalid format --> Error */
455 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
456 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
457
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;
461
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;
465
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;
469
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;
473
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;
477
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;
486
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;
490
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;
495
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;
500
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;
505
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;
510
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;
515
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;
520
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;
525
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;
530
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;
535
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;
540
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;
545
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;
550
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;
555
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;
560
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;
565
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;
570
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;
575
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;
580
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;
585
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;
590
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;
595
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;
600 }
601
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 -" */
607
608 static void test_GetNumberFormatA()
609 {
610 static char szDot[] = { '.', '\0' };
611 static char szComma[] = { ',', '\0' };
612 int ret;
613 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
614 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
615 NUMBERFMTA format;
616
617 memset(&format, 0, sizeof(format));
618
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;
622
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;
626
627 STRINGSA("--",""); /* Double '-' --> Error */
628 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
629 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
630
631 STRINGSA("0-",""); /* Trailing '-' --> Error */
632 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
633 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
634
635 STRINGSA("0..",""); /* Double '.' --> Error */
636 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
637 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
638
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;
642
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;
646
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;
650
651 STRINGSA("2353",""); /* Invalid format --> Error */
652 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
653 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
654
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;
658
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;
662
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;
666
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;
670
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;
674
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;
678
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;
685
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;
689
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;
694
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;
699
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;
704
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;
709
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;
714
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;
719
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;
724
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;
729
730 lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
731
732 if (IsValidLocale(lcid, 0))
733 {
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;
738 }
739 }
740
741
742 /* Callback function used by TestEnumTimeFormats */
743 static BOOL CALLBACK EnumTimeFormatsProc(char * lpTimeFormatString)
744 {
745 trace("%s\n", lpTimeFormatString);
746 strcpy(GlobalBuffer, lpTimeFormatString);
747 #if 0
748 return TRUE;
749 #endif
750 return FALSE;
751 }
752
753 void test_EnumTimeFormats()
754 {
755 int ret;
756 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
757
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);
761 }
762
763 static void test_CompareStringA()
764 {
765 int ret;
766 LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
767
768 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
769 ok (ret== 1, "(Salut/Salute) Expected 1, got %d\n", ret);
770
771 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
772 ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
773
774 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
775 ok (ret== 3, "(Salut/hola) Expected 3, got %d\n", ret);
776
777 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
778 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
779
780 lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
781
782 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
783 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
784
785 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
786 ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
787
788 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
789 ok (ret == 2, "(Salut/saLuT) Expected 2, got %d\n", ret);
790
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");
796
797 ret = lstrcmpA("", "");
798 ok (ret == 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret);
799
800 ret = lstrcmpA(NULL, NULL);
801 ok (ret == 0, "lstrcmpA(NULL, NULL) should return 0, got %d\n", ret);
802
803 ret = lstrcmpA("", NULL);
804 ok (ret == 1, "lstrcmpA(\"\", NULL) should return 1, got %d\n", ret);
805
806 ret = lstrcmpA(NULL, "");
807 ok (ret == -1, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret);
808
809 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"EndDialog",-1,"_Property",-1);
810 ok( ret == 3, "EndDialog vs _Property ... expected 3, got %d\n", ret);
811
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);
814
815 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"r",-1,"\\",-1);
816 ok( ret == 3, "r vs \\ ... expected 3, got %d\n", ret);
817
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);
820
821 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1 );
822 ok( ret == 3, "AAA vs aaa expected 3, got %d\n", ret);
823
824 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1 );
825 ok( ret == 1, "AAA vs aab expected 1, got %d\n", ret);
826
827 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1 );
828 ok( ret == 1, "AAA vs Aab expected 1, got %d\n", ret);
829
830 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1 );
831 ok( ret == 1, ".AAA vs Aab expected 1, got %d\n", ret);
832
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);
835
836 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1 );
837 ok( ret == 1, "aa vs AB expected 1, got %d\n", ret);
838
839 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1 );
840 ok( ret == 1, "aa vs Aab expected 1, got %d\n", ret);
841
842 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1 );
843 ok( ret == 3, "aB vs Aab expected 3, got %d\n", ret);
844
845 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1 );
846 ok( ret == 1, "Ba vs bab expected 1, got %d\n", ret);
847
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);
850
851 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1 );
852 ok( ret == 3, "a vs { expected 3, got %d\n", ret);
853
854 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1 );
855 ok( ret == 3, "A vs { expected 3, got %d\n", ret);
856
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);
859
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);
862
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);
865
866 /* hyphen and apostrophe are treated differently depending on
867 * whether SORT_STRINGSORT specified or not
868 */
869 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1 );
870 ok(ret == 3, "-o vs /m expected 3, got %d\n", ret);
871
872 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1 );
873 ok(ret == 1, "/m vs -o expected 1, got %d\n", ret);
874
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);
877
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);
880
881 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1 );
882 ok(ret == 3, "'o vs /m expected 3, got %d\n", ret);
883
884 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1 );
885 ok(ret == 1, "/m vs 'o expected 1, got %d\n", ret);
886
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);
889
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);
892
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);
896
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);
899
900 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
901 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
902
903 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
904 ok(ret == 1, "' vs - expected 1, got %d\n", ret);
905
906 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
907 ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
908
909 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
910 ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
911
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);
914
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);
917
918 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
919 ok(ret == 1, "`o vs -m expected 1, got %d\n", ret);
920
921 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
922 ok(ret == 3, "-m vs `o expected 3, got %d\n", ret);
923
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);
926
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);
929 #endif
930
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);
933
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);
936
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);
939
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);
942 }
943
944 void test_LCMapStringA(void)
945 {
946 int ret, ret2;
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";
951
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());
957
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());
963
964 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
965
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());
970
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());
976
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");
983
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);
991
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);
999
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);
1006
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");
1013 else
1014 {
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);
1019 }
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");
1025 else
1026 {
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);
1031 }
1032
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");
1041
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");
1051
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");
1061
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");
1071
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");
1081
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);
1089
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);
1097
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());
1104 }
1105
1106 void test_LCMapStringW(void)
1107 {
1108 int ret, ret2;
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};
1115
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)
1119 {
1120 trace("Skipping LCMapStringW tests on Win9x\n");
1121 return;
1122 }
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());
1126
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());
1132
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());
1138
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());
1144
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");
1151
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");
1159
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");
1167
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);
1174
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");
1183
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");
1191
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");
1200
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");
1210
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");
1220
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");
1230
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");
1240
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");
1248
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");
1256
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());
1263 }
1264
1265 #if 0 /* this requires collation table patch to make it MS compatible */
1266 const char *strings_sorted[] =
1267 {
1268 "'",
1269 "-",
1270 "!",
1271 "\"",
1272 ".",
1273 ":",
1274 "\\",
1275 "_",
1276 "`",
1277 "{",
1278 "}",
1279 "+",
1280 "0",
1281 "1",
1282 "2",
1283 "3",
1284 "4",
1285 "5",
1286 "6",
1287 "7",
1288 "8",
1289 "9",
1290 "a",
1291 "A",
1292 "b",
1293 "B",
1294 "c",
1295 "C"
1296 };
1297
1298 const char *strings[] =
1299 {
1300 "C",
1301 "\"",
1302 "9",
1303 "'",
1304 "}",
1305 "-",
1306 "7",
1307 "+",
1308 "`",
1309 "1",
1310 "a",
1311 "5",
1312 "\\",
1313 "8",
1314 "B",
1315 "3",
1316 "_",
1317 "6",
1318 "{",
1319 "2",
1320 "c",
1321 "4",
1322 "!",
1323 "0",
1324 "A",
1325 ":",
1326 "b",
1327 "."
1328 };
1329
1330 static int compare_string1(const void *e1, const void *e2)
1331 {
1332 const char *s1 = *(const char **)e1;
1333 const char *s2 = *(const char **)e2;
1334
1335 return lstrcmpA(s1, s2);
1336 }
1337
1338 static int compare_string2(const void *e1, const void *e2)
1339 {
1340 const char *s1 = *(const char **)e1;
1341 const char *s2 = *(const char **)e2;
1342
1343 return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1344 }
1345
1346 static int compare_string3(const void *e1, const void *e2)
1347 {
1348 const char *s1 = *(const char **)e1;
1349 const char *s2 = *(const char **)e2;
1350 char key1[256], key2[256];
1351
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);
1355 }
1356
1357 static void test_sorting(void)
1358 {
1359 char buf[256];
1360 char **str_buf = (char **)buf;
1361 int i;
1362
1363 assert(sizeof(buf) >= sizeof(strings));
1364
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++)
1369 {
1370 ok(!strcmp(strings_sorted[i], str_buf[i]),
1371 "qsort using lstrcmpA failed for element %d\n", i);
1372 }
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++)
1377 {
1378 ok(!strcmp(strings_sorted[i], str_buf[i]),
1379 "qsort using CompareStringA failed for element %d\n", i);
1380 }
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++)
1385 {
1386 ok(!strcmp(strings_sorted[i], str_buf[i]),
1387 "qsort using sort keys failed for element %d\n", i);
1388 }
1389 }
1390 #endif
1391
1392 static void test_FoldStringA(void)
1393 {
1394 int ret, i;
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[] =
1399 {
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'
1408 };
1409 static const char composite_dst[] =
1410 {
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'
1426 };
1427 static const char ligatures_src[] =
1428 {
1429 0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1430 };
1431 static const char ligatures_dst[] =
1432 {
1433 'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1434 };
1435
1436 if (!pFoldStringA)
1437 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1438
1439 /* these tests are locale specific */
1440 if (GetACP() != 1252)
1441 {
1442 trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1443 return;
1444 }
1445
1446 /* MAP_FOLDDIGITS */
1447 SetLastError(0);
1448 ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
1449 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1450 return;
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++)
1455 {
1456 if (!strchr(digits_src, i))
1457 {
1458 src[0] = i;
1459 src[1] = '\0';
1460 SetLastError(0);
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);
1465 }
1466 }
1467
1468 /* MAP_EXPAND_LIGATURES */
1469 SetLastError(0);
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++)
1475 {
1476 if (!strchr(ligatures_src, i))
1477 {
1478 src[0] = i;
1479 src[1] = '\0';
1480 SetLastError(0);
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);
1485 }
1486 }
1487
1488 /* MAP_COMPOSITE */
1489 SetLastError(0);
1490 ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
1491 EXPECT_VALID;
1492 todo_wine
1493 {
1494 /* Wine gets close, but doesn't produce quite the same result as native */
1495 EXPECT_LEN(121);
1496 ok(strcmp(dst, composite_dst) == 0,
1497 "MAP_COMPOSITE: Expected '%s', got '%s'\n", composite_dst, dst);
1498 }
1499
1500 for (i = 1; i < 256; i++)
1501 {
1502 if (!strchr(composite_src, i))
1503 {
1504 src[0] = i;
1505 src[1] = '\0';
1506 SetLastError(0);
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]);
1512 }
1513 }
1514
1515 /* MAP_FOLDCZONE */
1516 for (i = 1; i < 256; i++)
1517 {
1518 src[0] = i;
1519 src[1] = '\0';
1520 SetLastError(0);
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]);
1526 }
1527
1528 /* MAP_PRECOMPOSED */
1529 for (i = 1; i < 256; i++)
1530 {
1531 src[0] = i;
1532 src[1] = '\0';
1533 SetLastError(0);
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]);
1539 }
1540 }
1541
1542 static void test_FoldStringW(void)
1543 {
1544 int ret;
1545 size_t i, j;
1546 WCHAR src[256], dst[256], ch, prev_ch = 1;
1547 static const DWORD badFlags[] =
1548 {
1549 0,
1550 MAP_PRECOMPOSED|MAP_COMPOSITE,
1551 MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
1552 MAP_COMPOSITE|MAP_EXPAND_LIGATURES
1553 };
1554 /* Ranges of digits 0-9 : Must be sorted! */
1555 static const WCHAR digitRanges[] =
1556 {
1557 0x0030, /* '0'-'9' */
1558 0x0660, /* Eastern Arabic */
1559 0x06F0, /* Arabic - Hindu */
1560 0x0966, /* Devengari */
1561 0x09E6, /* Bengalii */
1562 0x0A66, /* Gurmukhi */
1563 0x0AE6, /* Gujarati */
1564 0x0B66, /* Oriya */
1565 0x0BE6, /* Tamil - No 0 */
1566 0x0C66, /* Telugu */
1567 0x0CE6, /* Kannada */
1568 0x0D66, /* Maylayalam */
1569 0x0E50, /* Thai */
1570 0x0ED0, /* Laos */
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 */
1581 };
1582 /* Digits which are represented, but out of sequence */
1583 static const WCHAR outOfSequenceDigits[] =
1584 {
1585 0xB9, /* Superscript 1 */
1586 0xB2, /* Superscript 2 */
1587 0xB3, /* Superscript 3 */
1588 0x24EA, /* Circled 0 */
1589 '\0' /* Terminator */
1590 };
1591 /* Digits in digitRanges for which no representation is available */
1592 static const WCHAR noDigitAvailable[] =
1593 {
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 */
1601 };
1602 /* Compatibility conversion results */
1603 static const WCHAR compat_F900_FA2F[256+48] =
1604 {
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
1643 };
1644 static const WCHAR compat_FE30_FEF7[200] =
1645 {
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
1671 };
1672 static const WCHAR compat_FF00_FFEF[240] =
1673 {
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
1704 };
1705 static const WCHAR ligatures_src[] =
1706 {
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'
1712 };
1713 static const WCHAR ligatures_dst[] =
1714 {
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'
1720 };
1721
1722 if (!pFoldStringW)
1723 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1724
1725 /* Invalid flag combinations */
1726 for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
1727 {
1728 src[0] = dst[0] = '\0';
1729 SetLastError(0);
1730 ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
1731 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1732 return;
1733 EXPECT_LEN(0); EXPECT_FLAGS;
1734 }
1735
1736 /* src & dst cannot be the same */
1737 SetLastError(0);
1738 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
1739 EXPECT_LEN(0); EXPECT_INVALID;
1740
1741 /* src can't be NULL */
1742 SetLastError(0);
1743 ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
1744 EXPECT_LEN(0); EXPECT_INVALID;
1745
1746 /* srclen can't be 0 */
1747 SetLastError(0);
1748 ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
1749 EXPECT_LEN(0); EXPECT_INVALID;
1750
1751 /* dstlen can't be < 0 */
1752 SetLastError(0);
1753 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
1754 EXPECT_LEN(0); EXPECT_INVALID;
1755
1756 /* Ret includes terminating NUL which is appended if srclen = -1 */
1757 SetLastError(0);
1758 src[0] = 'A';
1759 src[1] = '\0';
1760 dst[0] = '\0';
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());
1766
1767 /* If size is given, result is not NUL terminated */
1768 SetLastError(0);
1769 src[0] = 'A';
1770 src[1] = 'A';
1771 dst[0] = 'X';
1772 dst[1] = 'X';
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());
1778
1779 /* MAP_FOLDDIGITS */
1780 for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
1781 {
1782 /* Check everything before this range */
1783 for (ch = prev_ch; ch < digitRanges[j]; ch++)
1784 {
1785 SetLastError(0);
1786 src[0] = ch;
1787 src[1] = dst[0] = '\0';
1788 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
1789 EXPECT_LEN(2); EXPECT_VALID;
1790
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]);
1795 }
1796
1797 if (digitRanges[j] == 0xffff)
1798 break; /* Finished the whole code point space */
1799
1800 for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
1801 {
1802 WCHAR c;
1803
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 */
1809 else c = ch;
1810 SetLastError(0);
1811 src[0] = c;
1812 src[1] = dst[0] = '\0';
1813 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
1814 EXPECT_LEN(2); EXPECT_VALID;
1815
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]);
1820 }
1821 prev_ch = ch;
1822 }
1823
1824 /* MAP_FOLDCZONE */
1825 for (ch = 1; ch <0xffff; ch++)
1826 {
1827 WCHAR expected = 0;
1828
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];
1835
1836 if (!expected)
1837 expected = ch;
1838
1839 SetLastError(0);
1840 src[0] = ch;
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]);
1850 }
1851
1852 /* MAP_EXPAND_LIGATURES */
1853 SetLastError(0);
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++)
1859 {
1860 if (!strchrW(ligatures_src, i))
1861 {
1862 src[0] = i;
1863 src[1] = '\0';
1864 SetLastError(0);
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",
1869 i, src[0], dst[0]);
1870 }
1871 }
1872
1873 /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
1874 }
1875
1876
1877
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))
1884
1885 static void test_ConvertDefaultLocale(void)
1886 {
1887 LCID lcid;
1888
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);
1894
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));
1902
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));
1907
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);
1911
1912 /* Default lcids */
1913 LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
1914 LCID_RES(LOCALE_USER_DEFAULT, GetUserDefaultLCID());
1915 LCID_RES(LOCALE_NEUTRAL, GetUserDefaultLCID());
1916 }
1917
1918 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
1919 DWORD dwFlags, LONG_PTR lParam)
1920 {
1921 trace("%08lx, %s, %s, %08lx, %08lx\n",
1922 lgrpid, lpszNum, lpszName, dwFlags, lParam);
1923
1924 ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
1925 "Enumerated grp %ld not valid (flags %ld)\n", lgrpid, dwFlags);
1926
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);
1930
1931 return TRUE;
1932 }
1933
1934 static void test_EnumSystemLanguageGroupsA(void)
1935 {
1936 if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
1937 return;
1938
1939 /* No enumeration proc */
1940 SetLastError(0);
1941 pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
1942 EXPECT_INVALID;
1943
1944 /* Invalid flags */
1945 SetLastError(0);
1946 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
1947 EXPECT_FLAGS;
1948
1949 /* No flags - defaults to LGRPID_INSTALLED */
1950 SetLastError(0);
1951 pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
1952 EXPECT_VALID;
1953
1954 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
1955 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
1956 }
1957
1958
1959 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
1960 LONG_PTR lParam)
1961 {
1962 trace("%08lx, %08lx, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
1963
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);
1968 return TRUE;
1969 }
1970
1971 static void test_EnumLanguageGroupLocalesA(void)
1972 {
1973 if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
1974 return;
1975
1976 /* No enumeration proc */
1977 SetLastError(0);
1978 pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
1979 EXPECT_INVALID;
1980
1981 /* lgrpid too small */
1982 SetLastError(0);
1983 pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
1984 EXPECT_INVALID;
1985
1986 /* lgrpid too big */
1987 SetLastError(0);
1988 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
1989 EXPECT_INVALID;
1990
1991 /* dwFlags is reserved */
1992 SetLastError(0);
1993 pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
1994 EXPECT_INVALID;
1995
1996 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
1997 }
1998
1999 static void test_SetLocaleInfoA(void)
2000 {
2001 BOOL bRet;
2002 LCID lcid = GetUserDefaultLCID();
2003
2004 /* Null data */
2005 SetLastError(0);
2006 bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
2007 EXPECT_INVALID;
2008
2009 /* IDATE */
2010 SetLastError(0);
2011 bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
2012 EXPECT_FLAGS;
2013
2014 /* ILDATE */
2015 SetLastError(0);
2016 bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
2017 EXPECT_FLAGS;
2018 }
2019
2020 START_TEST(locale)
2021 {
2022 InitFunctionPointers();
2023
2024 #if 0
2025 test_EnumTimeFormats();
2026 #endif
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();
2036 test_FoldStringA();
2037 test_FoldStringW();
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 */
2043 test_sorting();
2044 #endif
2045 }