5f0a83666c8f73d056c3152ba83174b31bc18a93
[reactos.git] / modules / rostests / winetests / 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 #include <stdio.h>
32
33 #undef WINVER
34 #define WINVER 0x0600
35
36 #include "wine/test.h"
37 #include "windef.h"
38 #include "winbase.h"
39 #include "winerror.h"
40 #include "winnls.h"
41
42 static const WCHAR upper_case[] = {'\t','J','U','S','T','!',' ','A',',',' ','T','E','S','T',';',' ','S','T','R','I','N','G',' ','1','/','*','+','-','.','\r','\n',0};
43 static const WCHAR lower_case[] = {'\t','j','u','s','t','!',' ','a',',',' ','t','e','s','t',';',' ','s','t','r','i','n','g',' ','1','/','*','+','-','.','\r','\n',0};
44 static const WCHAR title_case[] = {'\t','J','u','s','t','!',' ','A',',',' ','T','e','s','t',';',' ','S','t','r','i','n','g',' ','1','/','*','+','-','.','\r','\n',0};
45 static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
46 static const WCHAR localeW[] = {'e','n','-','U','S',0};
47 static const WCHAR fooW[] = {'f','o','o',0};
48 static const WCHAR emptyW[] = {0};
49 static const WCHAR invalidW[] = {'i','n','v','a','l','i','d',0};
50
51 static inline unsigned int strlenW( const WCHAR *str )
52 {
53 const WCHAR *s = str;
54 while (*s) s++;
55 return s - str;
56 }
57
58 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
59 {
60 if (n <= 0) return 0;
61 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
62 return *str1 - *str2;
63 }
64
65 static inline WCHAR *strchrW( const WCHAR *str, WCHAR ch )
66 {
67 do { if (*str == ch) return (WCHAR *)str; } while (*str++);
68 return NULL;
69 }
70
71 static inline BOOL isdigitW( WCHAR wc )
72 {
73 WORD type;
74 GetStringTypeW( CT_CTYPE1, &wc, 1, &type );
75 return type & C1_DIGIT;
76 }
77
78 /* Some functions are only in later versions of kernel32.dll */
79 static WORD enumCount;
80
81 static INT (WINAPI *pGetTimeFormatEx)(LPCWSTR, DWORD, const SYSTEMTIME *, LPCWSTR, LPWSTR, INT);
82 static INT (WINAPI *pGetDateFormatEx)(LPCWSTR, DWORD, const SYSTEMTIME *, LPCWSTR, LPWSTR, INT, LPCWSTR);
83 static BOOL (WINAPI *pEnumSystemLanguageGroupsA)(LANGUAGEGROUP_ENUMPROCA, DWORD, LONG_PTR);
84 static BOOL (WINAPI *pEnumLanguageGroupLocalesA)(LANGGROUPLOCALE_ENUMPROCA, LGRPID, DWORD, LONG_PTR);
85 static BOOL (WINAPI *pEnumUILanguagesA)(UILANGUAGE_ENUMPROCA, DWORD, LONG_PTR);
86 static BOOL (WINAPI *pEnumSystemLocalesEx)(LOCALE_ENUMPROCEX, DWORD, LPARAM, LPVOID);
87 static INT (WINAPI *pLCMapStringEx)(LPCWSTR, DWORD, LPCWSTR, INT, LPWSTR, INT, LPNLSVERSIONINFO, LPVOID, LPARAM);
88 static LCID (WINAPI *pLocaleNameToLCID)(LPCWSTR, DWORD);
89 static INT (WINAPI *pLCIDToLocaleName)(LCID, LPWSTR, INT, DWORD);
90 static INT (WINAPI *pFoldStringA)(DWORD, LPCSTR, INT, LPSTR, INT);
91 static INT (WINAPI *pFoldStringW)(DWORD, LPCWSTR, INT, LPWSTR, INT);
92 static BOOL (WINAPI *pIsValidLanguageGroup)(LGRPID, DWORD);
93 static INT (WINAPI *pIdnToNameprepUnicode)(DWORD, LPCWSTR, INT, LPWSTR, INT);
94 static INT (WINAPI *pIdnToAscii)(DWORD, LPCWSTR, INT, LPWSTR, INT);
95 static INT (WINAPI *pIdnToUnicode)(DWORD, LPCWSTR, INT, LPWSTR, INT);
96 static INT (WINAPI *pGetLocaleInfoEx)(LPCWSTR, LCTYPE, LPWSTR, INT);
97 static BOOL (WINAPI *pIsValidLocaleName)(LPCWSTR);
98 static INT (WINAPI *pCompareStringOrdinal)(const WCHAR *, INT, const WCHAR *, INT, BOOL);
99 static INT (WINAPI *pCompareStringEx)(LPCWSTR, DWORD, LPCWSTR, INT, LPCWSTR, INT,
100 LPNLSVERSIONINFO, LPVOID, LPARAM);
101 static INT (WINAPI *pGetGeoInfoA)(GEOID, GEOTYPE, LPSTR, INT, LANGID);
102 static INT (WINAPI *pGetGeoInfoW)(GEOID, GEOTYPE, LPWSTR, INT, LANGID);
103 static BOOL (WINAPI *pEnumSystemGeoID)(GEOCLASS, GEOID, GEO_ENUMPROC);
104 static BOOL (WINAPI *pGetSystemPreferredUILanguages)(DWORD, ULONG*, WCHAR*, ULONG*);
105 static BOOL (WINAPI *pGetThreadPreferredUILanguages)(DWORD, ULONG*, WCHAR*, ULONG*);
106 static BOOL (WINAPI *pGetUserPreferredUILanguages)(DWORD, ULONG*, WCHAR*, ULONG*);
107 static WCHAR (WINAPI *pRtlUpcaseUnicodeChar)(WCHAR);
108 static INT (WINAPI *pGetNumberFormatEx)(LPCWSTR, DWORD, LPCWSTR, const NUMBERFMTW *, LPWSTR, int);
109
110 static void InitFunctionPointers(void)
111 {
112 HMODULE mod = GetModuleHandleA("kernel32");
113
114 #define X(f) p##f = (void*)GetProcAddress(mod, #f)
115 X(GetTimeFormatEx);
116 X(GetDateFormatEx);
117 X(EnumSystemLanguageGroupsA);
118 X(EnumLanguageGroupLocalesA);
119 X(LocaleNameToLCID);
120 X(LCIDToLocaleName);
121 X(LCMapStringEx);
122 X(FoldStringA);
123 X(FoldStringW);
124 X(IsValidLanguageGroup);
125 X(EnumUILanguagesA);
126 X(EnumSystemLocalesEx);
127 X(IdnToNameprepUnicode);
128 X(IdnToAscii);
129 X(IdnToUnicode);
130 X(GetLocaleInfoEx);
131 X(IsValidLocaleName);
132 X(CompareStringOrdinal);
133 X(CompareStringEx);
134 X(GetGeoInfoA);
135 X(GetGeoInfoW);
136 X(EnumSystemGeoID);
137 X(GetSystemPreferredUILanguages);
138 X(GetThreadPreferredUILanguages);
139 X(GetUserPreferredUILanguages);
140 X(GetNumberFormatEx);
141
142 mod = GetModuleHandleA("ntdll");
143 X(RtlUpcaseUnicodeChar);
144 #undef X
145 }
146
147 #define eq(received, expected, label, type) \
148 ok((received) == (expected), "%s: got " type " instead of " type "\n", \
149 (label), (received), (expected))
150
151 #define BUFFER_SIZE 128
152 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
153
154 #define STRINGSA(x,y) strcpy(input, x); strcpy(Expected, y); SetLastError(0xdeadbeef); buffer[0] = '\0'
155 #define EXPECT_LENA ok(ret == lstrlenA(Expected)+1, "Expected len %d, got %d\n", lstrlenA(Expected)+1, ret)
156 #define EXPECT_EQA ok(strncmp(buffer, Expected, strlen(Expected)) == 0, \
157 "Expected '%s', got '%s'\n", Expected, buffer)
158
159 #define STRINGSW(x,y) MultiByteToWideChar(CP_ACP,0,x,-1,input,COUNTOF(input)); \
160 MultiByteToWideChar(CP_ACP,0,y,-1,Expected,COUNTOF(Expected)); \
161 SetLastError(0xdeadbeef); buffer[0] = '\0'
162 #define EXPECT_LENW ok(ret == lstrlenW(Expected)+1, "Expected Len %d, got %d\n", lstrlenW(Expected)+1, ret)
163 #define EXPECT_EQW ok(strncmpW(buffer, Expected, strlenW(Expected)) == 0, "Bad conversion\n")
164
165 #define NUO LOCALE_NOUSEROVERRIDE
166
167 static void test_GetLocaleInfoA(void)
168 {
169 int ret;
170 int len;
171 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
172 char buffer[BUFFER_SIZE];
173 char expected[BUFFER_SIZE];
174 DWORD val;
175
176 ok(lcid == 0x409, "wrong LCID calculated - %d\n", lcid);
177
178 ret = GetLocaleInfoA(lcid, LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER, (char*)&val, sizeof(val));
179 ok(ret, "got %d\n", ret);
180 ok(val == lcid, "got 0x%08x\n", val);
181
182 /* en and ar use SUBLANG_NEUTRAL, but GetLocaleInfo assume SUBLANG_DEFAULT
183 Same is true for zh on pre-Vista, but on Vista and higher GetLocaleInfo
184 assumes SUBLANG_NEUTRAL for zh */
185 memset(expected, 0, COUNTOF(expected));
186 len = GetLocaleInfoA(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
187 SetLastError(0xdeadbeef);
188 memset(buffer, 0, COUNTOF(buffer));
189 ret = GetLocaleInfoA(LANG_ENGLISH, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
190 ok((ret == len) && !lstrcmpA(buffer, expected),
191 "got %d with '%s' (expected %d with '%s')\n",
192 ret, buffer, len, expected);
193
194 memset(expected, 0, COUNTOF(expected));
195 len = GetLocaleInfoA(MAKELANGID(LANG_ARABIC, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
196 if (len) {
197 SetLastError(0xdeadbeef);
198 memset(buffer, 0, COUNTOF(buffer));
199 ret = GetLocaleInfoA(LANG_ARABIC, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
200 ok((ret == len) && !lstrcmpA(buffer, expected),
201 "got %d with '%s' (expected %d with '%s')\n",
202 ret, buffer, len, expected);
203 }
204 else
205 win_skip("LANG_ARABIC not installed\n");
206
207 /* SUBLANG_DEFAULT is required for mlang.dll, but optional for GetLocaleInfo */
208 memset(expected, 0, COUNTOF(expected));
209 len = GetLocaleInfoA(MAKELANGID(LANG_GERMAN, SUBLANG_DEFAULT), LOCALE_SLANGUAGE, expected, COUNTOF(expected));
210 SetLastError(0xdeadbeef);
211 memset(buffer, 0, COUNTOF(buffer));
212 ret = GetLocaleInfoA(LANG_GERMAN, LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
213 ok((ret == len) && !lstrcmpA(buffer, expected),
214 "got %d with '%s' (expected %d with '%s')\n",
215 ret, buffer, len, expected);
216
217
218 /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
219 * partially fill the buffer even if it is too short. See bug 637.
220 */
221 SetLastError(0xdeadbeef);
222 memset(buffer, 0, COUNTOF(buffer));
223 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 0);
224 ok(ret == 7 && !buffer[0], "Expected len=7, got %d\n", ret);
225
226 SetLastError(0xdeadbeef);
227 memset(buffer, 0, COUNTOF(buffer));
228 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 3);
229 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
230 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
231 ok(!strcmp(buffer, "Mon"), "Expected 'Mon', got '%s'\n", buffer);
232
233 SetLastError(0xdeadbeef);
234 memset(buffer, 0, COUNTOF(buffer));
235 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 10);
236 ok(ret == 7, "Expected ret == 7, got %d, error %d\n", ret, GetLastError());
237 ok(!strcmp(buffer, "Monday"), "Expected 'Monday', got '%s'\n", buffer);
238 }
239
240 struct neutralsublang_name2_t {
241 WCHAR name[3];
242 WCHAR sname[15];
243 LCID lcid;
244 LCID lcid_broken;
245 WCHAR sname_broken[15];
246 int todo;
247 };
248
249 static const struct neutralsublang_name2_t neutralsublang_names2[] = {
250 { {'a','r',0}, {'a','r','-','S','A',0},
251 MAKELCID(MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA), SORT_DEFAULT) },
252 { {'a','z',0}, {'a','z','-','L','a','t','n','-','A','Z',0},
253 MAKELCID(MAKELANGID(LANG_AZERI, SUBLANG_AZERI_LATIN), SORT_DEFAULT) },
254 { {'d','e',0}, {'d','e','-','D','E',0},
255 MAKELCID(MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN), SORT_DEFAULT) },
256 { {'e','n',0}, {'e','n','-','U','S',0},
257 MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT) },
258 { {'e','s',0}, {'e','s','-','E','S',0},
259 MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN), SORT_DEFAULT),
260 MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH), SORT_DEFAULT) /* vista */,
261 {'e','s','-','E','S','_','t','r','a','d','n','l',0} },
262 { {'g','a',0}, {'g','a','-','I','E',0},
263 MAKELCID(MAKELANGID(LANG_IRISH, SUBLANG_IRISH_IRELAND), SORT_DEFAULT), 0, {0}, 0x3 },
264 { {'i','t',0}, {'i','t','-','I','T',0},
265 MAKELCID(MAKELANGID(LANG_ITALIAN, SUBLANG_ITALIAN), SORT_DEFAULT) },
266 { {'m','s',0}, {'m','s','-','M','Y',0},
267 MAKELCID(MAKELANGID(LANG_MALAY, SUBLANG_MALAY_MALAYSIA), SORT_DEFAULT) },
268 { {'n','l',0}, {'n','l','-','N','L',0},
269 MAKELCID(MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH), SORT_DEFAULT) },
270 { {'p','t',0}, {'p','t','-','B','R',0},
271 MAKELCID(MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN), SORT_DEFAULT) },
272 { {'s','r',0}, {'h','r','-','H','R',0},
273 MAKELCID(MAKELANGID(LANG_SERBIAN, SUBLANG_SERBIAN_CROATIA), SORT_DEFAULT) },
274 { {'s','v',0}, {'s','v','-','S','E',0},
275 MAKELCID(MAKELANGID(LANG_SWEDISH, SUBLANG_SWEDISH), SORT_DEFAULT) },
276 { {'u','z',0}, {'u','z','-','L','a','t','n','-','U','Z',0},
277 MAKELCID(MAKELANGID(LANG_UZBEK, SUBLANG_UZBEK_LATIN), SORT_DEFAULT) },
278 { {'z','h',0}, {'z','h','-','C','N',0},
279 MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT) },
280 { {0} }
281 };
282
283 static void test_GetLocaleInfoW(void)
284 {
285 LCID lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
286 LCID lcid_ru = MAKELCID(MAKELANGID(LANG_RUSSIAN, SUBLANG_NEUTRAL), SORT_DEFAULT);
287 LCID lcid_en_neut = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL), SORT_DEFAULT);
288 WCHAR bufferW[80], buffer2W[80];
289 CHAR bufferA[80];
290 DWORD val;
291 DWORD ret;
292 INT i;
293
294 ret = GetLocaleInfoW(lcid_en, LOCALE_SMONTHNAME1, bufferW, COUNTOF(bufferW));
295 if (!ret) {
296 win_skip("GetLocaleInfoW() isn't implemented\n");
297 return;
298 }
299
300 ret = GetLocaleInfoW(lcid_en, LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER, (WCHAR*)&val, sizeof(val)/sizeof(WCHAR));
301 ok(ret, "got %d\n", ret);
302 ok(val == lcid_en, "got 0x%08x\n", val);
303
304 ret = GetLocaleInfoW(lcid_en_neut, LOCALE_SNAME, bufferW, COUNTOF(bufferW));
305 if (ret)
306 {
307 static const WCHAR slangW[] = {'E','n','g','l','i','s','h',' ','(','U','n','i','t','e','d',' ',
308 'S','t','a','t','e','s',')',0};
309 static const WCHAR statesW[] = {'U','n','i','t','e','d',' ','S','t','a','t','e','s',0};
310 static const WCHAR enW[] = {'e','n','-','U','S',0};
311 const struct neutralsublang_name2_t *ptr = neutralsublang_names2;
312
313 ok(!lstrcmpW(bufferW, enW), "got wrong name %s\n", wine_dbgstr_w(bufferW));
314
315 ret = GetLocaleInfoW(lcid_en_neut, LOCALE_SCOUNTRY, bufferW, COUNTOF(bufferW));
316 ok(ret, "got %d\n", ret);
317 if ((PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID())) != LANG_ENGLISH) ||
318 (PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale())) != LANG_ENGLISH))
319 {
320 skip("Non-English locale\n");
321 }
322 else
323 ok(!lstrcmpW(statesW, bufferW), "got wrong name %s\n", wine_dbgstr_w(bufferW));
324
325 ret = GetLocaleInfoW(lcid_en_neut, LOCALE_SLANGUAGE, bufferW, COUNTOF(bufferW));
326 ok(ret, "got %d\n", ret);
327 if ((PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID())) != LANG_ENGLISH) ||
328 (PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale())) != LANG_ENGLISH))
329 {
330 skip("Non-English locale\n");
331 }
332 else
333 ok(!lstrcmpW(slangW, bufferW), "got wrong name %s\n", wine_dbgstr_w(bufferW));
334
335 while (*ptr->name)
336 {
337 LANGID langid;
338 LCID lcid;
339
340 /* make neutral lcid */
341 langid = MAKELANGID(PRIMARYLANGID(LANGIDFROMLCID(ptr->lcid)), SUBLANG_NEUTRAL);
342 lcid = MAKELCID(langid, SORT_DEFAULT);
343
344 val = 0;
345 GetLocaleInfoW(lcid, LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER, (WCHAR*)&val, sizeof(val)/sizeof(WCHAR));
346 todo_wine_if (ptr->todo & 0x1)
347 ok(val == ptr->lcid || (val && broken(val == ptr->lcid_broken)), "%s: got wrong lcid 0x%04x, expected 0x%04x\n",
348 wine_dbgstr_w(ptr->name), val, ptr->lcid);
349
350 /* now check LOCALE_SNAME */
351 GetLocaleInfoW(lcid, LOCALE_SNAME, bufferW, COUNTOF(bufferW));
352 todo_wine_if (ptr->todo & 0x2)
353 ok(!lstrcmpW(bufferW, ptr->sname) ||
354 (*ptr->sname_broken && broken(!lstrcmpW(bufferW, ptr->sname_broken))),
355 "%s: got %s\n", wine_dbgstr_w(ptr->name), wine_dbgstr_w(bufferW));
356 ptr++;
357 }
358 }
359 else
360 win_skip("English neutral locale not supported\n");
361
362 ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1, bufferW, COUNTOF(bufferW));
363 if (!ret) {
364 win_skip("LANG_RUSSIAN locale data unavailable\n");
365 return;
366 }
367 ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1|LOCALE_RETURN_GENITIVE_NAMES,
368 bufferW, COUNTOF(bufferW));
369 if (!ret) {
370 win_skip("LOCALE_RETURN_GENITIVE_NAMES isn't supported\n");
371 return;
372 }
373
374 /* LOCALE_RETURN_GENITIVE_NAMES isn't supported for GetLocaleInfoA */
375 bufferA[0] = 'a';
376 SetLastError(0xdeadbeef);
377 ret = GetLocaleInfoA(lcid_ru, LOCALE_SMONTHNAME1|LOCALE_RETURN_GENITIVE_NAMES,
378 bufferA, COUNTOF(bufferA));
379 ok(ret == 0, "LOCALE_RETURN_GENITIVE_NAMES should fail with GetLocaleInfoA\n");
380 ok(bufferA[0] == 'a', "Expected buffer to be untouched\n");
381 ok(GetLastError() == ERROR_INVALID_FLAGS,
382 "Expected ERROR_INVALID_FLAGS, got %x\n", GetLastError());
383
384 bufferW[0] = 'a';
385 SetLastError(0xdeadbeef);
386 ret = GetLocaleInfoW(lcid_ru, LOCALE_RETURN_GENITIVE_NAMES,
387 bufferW, COUNTOF(bufferW));
388 ok(ret == 0,
389 "LOCALE_RETURN_GENITIVE_NAMES itself doesn't return anything, got %d\n", ret);
390 ok(bufferW[0] == 'a', "Expected buffer to be untouched\n");
391 ok(GetLastError() == ERROR_INVALID_FLAGS,
392 "Expected ERROR_INVALID_FLAGS, got %x\n", GetLastError());
393
394 /* yes, test empty 13 month entry too */
395 for (i = 0; i < 12; i++) {
396 bufferW[0] = 0;
397 ret = GetLocaleInfoW(lcid_ru, (LOCALE_SMONTHNAME1+i)|LOCALE_RETURN_GENITIVE_NAMES,
398 bufferW, COUNTOF(bufferW));
399 ok(ret, "Expected non zero result\n");
400 ok(ret == lstrlenW(bufferW)+1, "Expected actual length, got %d, length %d\n",
401 ret, lstrlenW(bufferW));
402 buffer2W[0] = 0;
403 ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1+i,
404 buffer2W, COUNTOF(buffer2W));
405 ok(ret, "Expected non zero result\n");
406 ok(ret == lstrlenW(buffer2W)+1, "Expected actual length, got %d, length %d\n",
407 ret, lstrlenW(buffer2W));
408
409 ok(lstrcmpW(bufferW, buffer2W) != 0,
410 "Expected genitive name to differ, got the same for month %d\n", i+1);
411
412 /* for locale without genitive names nominative returned in both cases */
413 bufferW[0] = 0;
414 ret = GetLocaleInfoW(lcid_en, (LOCALE_SMONTHNAME1+i)|LOCALE_RETURN_GENITIVE_NAMES,
415 bufferW, COUNTOF(bufferW));
416 ok(ret, "Expected non zero result\n");
417 ok(ret == lstrlenW(bufferW)+1, "Expected actual length, got %d, length %d\n",
418 ret, lstrlenW(bufferW));
419 buffer2W[0] = 0;
420 ret = GetLocaleInfoW(lcid_en, LOCALE_SMONTHNAME1+i,
421 buffer2W, COUNTOF(buffer2W));
422 ok(ret, "Expected non zero result\n");
423 ok(ret == lstrlenW(buffer2W)+1, "Expected actual length, got %d, length %d\n",
424 ret, lstrlenW(buffer2W));
425
426 ok(lstrcmpW(bufferW, buffer2W) == 0,
427 "Expected same names, got different for month %d\n", i+1);
428 }
429 }
430
431 static void test_GetTimeFormatA(void)
432 {
433 int ret;
434 SYSTEMTIME curtime;
435 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
436 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
437
438 memset(&curtime, 2, sizeof(SYSTEMTIME));
439 STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
440 SetLastError(0xdeadbeef);
441 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
442 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
443 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
444
445 curtime.wHour = 8;
446 curtime.wMinute = 56;
447 curtime.wSecond = 13;
448 curtime.wMilliseconds = 22;
449 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
450 SetLastError(0xdeadbeef);
451 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
452 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
453 EXPECT_LENA; EXPECT_EQA;
454
455 /* MSDN: LOCALE_NOUSEROVERRIDE can't be specified with a format string */
456 SetLastError(0xdeadbeef);
457 ret = GetTimeFormatA(lcid, NUO|TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
458 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
459 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
460
461 STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficient buffer */
462 SetLastError(0xdeadbeef);
463 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, 2);
464 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
465 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
466
467 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
468 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, NULL, 0);
469 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
470 EXPECT_LENA;
471
472 STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
473 ret = GetTimeFormatA(lcid, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
474 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
475 EXPECT_LENA; EXPECT_EQA;
476
477 STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
478 ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
479 ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
480 ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "4" )), /* win9x */
481 "Expected '', got '%s'\n", buffer );
482
483 STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
484 ret = GetTimeFormatA(lcid, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
485 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
486 EXPECT_LENA; EXPECT_EQA;
487
488 STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
489 strcpy(Expected, "8:56 AM");
490 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
491 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
492 EXPECT_LENA; EXPECT_EQA;
493
494 STRINGSA("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
495 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
496 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
497 ok( !strcmp( buffer, "8.@:56AM" ) || broken( !strcmp( buffer, "8.@:56.@:AM" )) /* win9x */,
498 "Expected '8.@:56AM', got '%s'\n", buffer );
499
500 STRINGSA("s1s2s3", ""); /* Duplicate tokens */
501 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
502 ok(ret == strlen(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
503 ok( !strcmp( buffer, "" ) || broken( !strcmp( buffer, "3" )), /* win9x */
504 "Expected '', got '%s'\n", buffer );
505
506 STRINGSA("t/tt", "A/AM"); /* AM time marker */
507 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
508 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
509 EXPECT_LENA; EXPECT_EQA;
510
511 curtime.wHour = 13;
512 STRINGSA("t/tt", "P/PM"); /* PM time marker */
513 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
514 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
515 EXPECT_LENA; EXPECT_EQA;
516
517 STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
518 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
519 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
520 EXPECT_LENA; EXPECT_EQA;
521
522 STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
523 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
524 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
525 EXPECT_LENA; EXPECT_EQA;
526
527 STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
528 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
529 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
530 EXPECT_LENA; EXPECT_EQA;
531
532 curtime.wHour = 14; /* change this to 14 or 2pm */
533 curtime.wMinute = 5;
534 curtime.wSecond = 3;
535 STRINGSA("h hh H HH m mm s ss t tt", "2 02 14 14 5 05 3 03 P PM"); /* 24 hrs, leading 0 */
536 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
537 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
538 EXPECT_LENA; EXPECT_EQA;
539
540 curtime.wHour = 0;
541 STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
542 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
543 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
544 EXPECT_LENA; EXPECT_EQA;
545
546 STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
547 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
548 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
549 EXPECT_LENA; EXPECT_EQA;
550
551 /* try to convert formatting strings with more than two letters
552 * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
553 * NOTE: We expect any letter for which there is an upper case value
554 * we should see a replacement. For letters that DO NOT have
555 * upper case values we should see NO REPLACEMENT.
556 */
557 curtime.wHour = 8;
558 curtime.wMinute = 56;
559 curtime.wSecond = 13;
560 curtime.wMilliseconds = 22;
561 STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
562 "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
563 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
564 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
565 EXPECT_LENA; EXPECT_EQA;
566
567 STRINGSA("h", "text"); /* Don't write to buffer if len is 0 */
568 strcpy(buffer, "text");
569 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, 0);
570 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
571 EXPECT_EQA;
572
573 STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
574 "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
575 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
576 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
577 EXPECT_LENA; EXPECT_EQA;
578
579 STRINGSA("'''", "'"); /* invalid quoted string */
580 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
581 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
582 EXPECT_LENA; EXPECT_EQA;
583
584 /* test that msdn suggested single quotation usage works as expected */
585 STRINGSA("''''", "'"); /* single quote mark */
586 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
587 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
588 EXPECT_LENA; EXPECT_EQA;
589
590 STRINGSA("''HHHHHH", "08"); /* Normal use */
591 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
592 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
593 EXPECT_LENA; EXPECT_EQA;
594
595 /* and test for normal use of the single quotation mark */
596 STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
597 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
598 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
599 EXPECT_LENA; EXPECT_EQA;
600
601 STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
602 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
603 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
604 EXPECT_LENA; EXPECT_EQA;
605
606 STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
607 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
608 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
609 EXPECT_LENA; EXPECT_EQA;
610
611 curtime.wHour = 25;
612 STRINGSA("'123'tt", ""); /* Invalid time */
613 SetLastError(0xdeadbeef);
614 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
615 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
616 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
617
618 curtime.wHour = 12;
619 curtime.wMonth = 60; /* Invalid */
620 STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
621 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
622 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
623 EXPECT_LENA; EXPECT_EQA;
624 }
625
626 static void test_GetTimeFormatEx(void)
627 {
628 int ret;
629 SYSTEMTIME curtime;
630 WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
631
632 if (!pGetTimeFormatEx)
633 {
634 win_skip("GetTimeFormatEx not supported\n");
635 return;
636 }
637
638 memset(&curtime, 2, sizeof(SYSTEMTIME));
639 STRINGSW("tt HH':'mm'@'ss", ""); /* Invalid time */
640 SetLastError(0xdeadbeef);
641 ret = pGetTimeFormatEx(localeW, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
642 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
643 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
644
645 curtime.wHour = 8;
646 curtime.wMinute = 56;
647 curtime.wSecond = 13;
648 curtime.wMilliseconds = 22;
649 STRINGSW("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
650 SetLastError(0xdeadbeef);
651 ret = pGetTimeFormatEx(localeW, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
652 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
653 EXPECT_LENW; EXPECT_EQW;
654
655 /* MSDN: LOCALE_NOUSEROVERRIDE can't be specified with a format string */
656 SetLastError(0xdeadbeef);
657 ret = pGetTimeFormatEx(localeW, NUO|TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
658 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
659 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
660
661 STRINGSW("tt HH':'mm'@'ss", "A"); /* Insufficient buffer */
662 SetLastError(0xdeadbeef);
663 ret = pGetTimeFormatEx(localeW, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, 2);
664 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
665 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
666
667 STRINGSW("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
668 ret = pGetTimeFormatEx(localeW, TIME_FORCE24HOURFORMAT, &curtime, input, NULL, 0);
669 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
670 EXPECT_LENW;
671
672 STRINGSW("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
673 ret = pGetTimeFormatEx(localeW, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
674 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
675 EXPECT_LENW; EXPECT_EQW;
676
677 STRINGSW("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
678 ret = pGetTimeFormatEx(localeW, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
679 ok(ret == strlenW(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
680 EXPECT_LENW; EXPECT_EQW;
681
682 STRINGSW("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
683 ret = pGetTimeFormatEx(localeW, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
684 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
685 EXPECT_LENW; EXPECT_EQW;
686
687 STRINGSW("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
688 ret = pGetTimeFormatEx(localeW, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
689 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
690 EXPECT_LENW; EXPECT_EQW;
691
692 STRINGSW("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
693 ret = pGetTimeFormatEx(localeW, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
694 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
695 EXPECT_LENW; EXPECT_EQW;
696
697 STRINGSW("s1s2s3", ""); /* Duplicate tokens */
698 ret = pGetTimeFormatEx(localeW, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
699 ok(ret == strlenW(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
700 EXPECT_LENW; EXPECT_EQW;
701
702 STRINGSW("t/tt", "A/AM"); /* AM time marker */
703 ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
704 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
705 EXPECT_LENW; EXPECT_EQW;
706
707 curtime.wHour = 13;
708 STRINGSW("t/tt", "P/PM"); /* PM time marker */
709 ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
710 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
711 EXPECT_LENW; EXPECT_EQW;
712
713 STRINGSW("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
714 ret = pGetTimeFormatEx(localeW, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
715 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
716 EXPECT_LENW; EXPECT_EQW;
717
718 STRINGSW("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
719 ret = pGetTimeFormatEx(localeW, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
720 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
721 EXPECT_LENW; EXPECT_EQW;
722
723 STRINGSW("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
724 ret = pGetTimeFormatEx(localeW, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
725 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
726 EXPECT_LENW; EXPECT_EQW;
727
728 curtime.wHour = 14; /* change this to 14 or 2pm */
729 curtime.wMinute = 5;
730 curtime.wSecond = 3;
731 STRINGSW("h hh H HH m mm s ss t tt", "2 02 14 14 5 05 3 03 P PM"); /* 24 hrs, leading 0 */
732 ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
733 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
734 EXPECT_LENW; EXPECT_EQW;
735
736 curtime.wHour = 0;
737 STRINGSW("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
738 ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
739 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
740 EXPECT_LENW; EXPECT_EQW;
741
742 STRINGSW("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
743 ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
744 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
745 EXPECT_LENW; EXPECT_EQW;
746
747 /* try to convert formatting strings with more than two letters
748 * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
749 * NOTE: We expect any letter for which there is an upper case value
750 * we should see a replacement. For letters that DO NOT have
751 * upper case values we should see NO REPLACEMENT.
752 */
753 curtime.wHour = 8;
754 curtime.wMinute = 56;
755 curtime.wSecond = 13;
756 curtime.wMilliseconds = 22;
757 STRINGSW("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
758 "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
759 ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
760 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
761 EXPECT_LENW; EXPECT_EQW;
762
763 STRINGSW("h", "text"); /* Don't write to buffer if len is 0 */
764 lstrcpyW(buffer, Expected);
765 ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, 0);
766 ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
767 EXPECT_EQW;
768
769 STRINGSW("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
770 "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
771 ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
772 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
773 EXPECT_LENW; EXPECT_EQW;
774
775 STRINGSW("'''", "'"); /* invalid quoted string */
776 ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
777 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
778 EXPECT_LENW; EXPECT_EQW;
779
780 /* test that msdn suggested single quotation usage works as expected */
781 STRINGSW("''''", "'"); /* single quote mark */
782 ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
783 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
784 EXPECT_LENW; EXPECT_EQW;
785
786 STRINGSW("''HHHHHH", "08"); /* Normal use */
787 ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
788 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
789 EXPECT_LENW; EXPECT_EQW;
790
791 /* and test for normal use of the single quotation mark */
792 STRINGSW("'''HHHHHH'", "'HHHHHH"); /* Normal use */
793 ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
794 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
795 EXPECT_LENW; EXPECT_EQW;
796
797 STRINGSW("'''HHHHHH", "'HHHHHH"); /* Odd use */
798 ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
799 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
800 EXPECT_LENW; EXPECT_EQW;
801
802 STRINGSW("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
803 ret = pGetTimeFormatEx(localeW, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
804 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
805 EXPECT_LENW; EXPECT_EQW;
806
807 curtime.wHour = 25;
808 STRINGSW("'123'tt", ""); /* Invalid time */
809 SetLastError(0xdeadbeef);
810 ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
811 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
812 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
813
814 curtime.wHour = 12;
815 curtime.wMonth = 60; /* Invalid */
816 STRINGSW("h:m:s", "12:56:13"); /* Invalid date */
817 ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
818 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
819 EXPECT_LENW; EXPECT_EQW;
820 }
821
822 static void test_GetDateFormatA(void)
823 {
824 int ret;
825 SYSTEMTIME curtime;
826 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
827 LCID lcid_ru = MAKELCID(MAKELANGID(LANG_RUSSIAN, SUBLANG_NEUTRAL), SORT_DEFAULT);
828 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
829 char Broken[BUFFER_SIZE];
830 char short_day[10], month[10], genitive_month[10];
831
832 memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
833 STRINGSA("ddd',' MMM dd yy","");
834 SetLastError(0xdeadbeef);
835 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
836 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
837 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
838
839 curtime.wYear = 2002;
840 curtime.wMonth = 5;
841 curtime.wDay = 4;
842 curtime.wDayOfWeek = 3;
843 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
844 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
845 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
846 EXPECT_LENA; EXPECT_EQA;
847
848 /* Same as above but with LOCALE_NOUSEROVERRIDE */
849 STRINGSA("ddd',' MMM dd yy",""); /* Simple case */
850 SetLastError(0xdeadbeef);
851 ret = GetDateFormatA(lcid, NUO, &curtime, input, buffer, COUNTOF(buffer));
852 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
853 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
854 EXPECT_EQA;
855
856 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
857 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
858 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
859 EXPECT_LENA; EXPECT_EQA;
860
861 curtime.wHour = 36; /* Invalid */
862 STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
863 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
864 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
865 EXPECT_LENA; EXPECT_EQA;
866
867 STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
868 ret = GetDateFormatA(lcid, 0, &curtime, input, NULL, 0);
869 ok(ret == 16, "Expected ret == 16, got %d, error %d\n", ret, GetLastError());
870 EXPECT_EQA;
871
872 STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
873 SetLastError(0xdeadbeef);
874 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, 2);
875 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
876 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
877
878 STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
879 ret = GetDateFormatA(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
880 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
881 if (strncmp(buffer, Expected, strlen(Expected)) && strncmp(buffer, "5/4/02", strlen(Expected)) != 0)
882 ok (0, "Expected '%s' or '5/4/02', got '%s'\n", Expected, buffer);
883
884 SetLastError(0xdeadbeef); buffer[0] = '\0'; /* DATE_LONGDATE */
885 ret = GetDateFormatA(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
886 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
887 ok(strcmp(buffer, "Saturday, May 04, 2002") == 0 ||
888 strcmp(buffer, "Saturday, May 4, 2002") == 0 /* Win 8 */,
889 "got an unexpected date string '%s'\n", buffer);
890
891 /* test for expected DATE_YEARMONTH behavior with null format */
892 /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
893 STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
894 SetLastError(0xdeadbeef);
895 ret = GetDateFormatA(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
896 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
897 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
898 EXPECT_EQA;
899
900 /* Test that using invalid DATE_* flags results in the correct error */
901 /* and return values */
902 STRINGSA("m/d/y", ""); /* Invalid flags */
903 SetLastError(0xdeadbeef);
904 ret = GetDateFormatA(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
905 &curtime, input, buffer, COUNTOF(buffer));
906 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
907 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
908
909 ret = GetDateFormatA(lcid_ru, 0, &curtime, "ddMMMM", buffer, COUNTOF(buffer));
910 if (!ret)
911 {
912 win_skip("LANG_RUSSIAN locale data unavailable\n");
913 return;
914 }
915
916 /* month part should be in genitive form */
917 strcpy(genitive_month, buffer + 2);
918 ret = GetDateFormatA(lcid_ru, 0, &curtime, "MMMM", buffer, COUNTOF(buffer));
919 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
920 strcpy(month, buffer);
921 ok(strcmp(genitive_month, month) != 0, "Expected different month forms\n");
922
923 ret = GetDateFormatA(lcid_ru, 0, &curtime, "ddd", buffer, COUNTOF(buffer));
924 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
925 strcpy(short_day, buffer);
926
927 STRINGSA("dd MMMMddd dd", "");
928 sprintf(Expected, "04 %s%s 04", genitive_month, short_day);
929 ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
930 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
931 EXPECT_EQA;
932
933 STRINGSA("MMMMddd dd", "");
934 sprintf(Expected, "%s%s 04", month, short_day);
935 ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
936 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
937 EXPECT_EQA;
938
939 STRINGSA("MMMMddd", "");
940 sprintf(Expected, "%s%s", month, short_day);
941 ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
942 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
943 EXPECT_EQA;
944
945 STRINGSA("MMMMdd", "");
946 sprintf(Expected, "%s04", genitive_month);
947 sprintf(Broken, "%s04", month);
948 ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
949 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
950 ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
951 broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
952 "Expected '%s', got '%s'\n", Expected, buffer);
953
954 STRINGSA("MMMMdd ddd", "");
955 sprintf(Expected, "%s04 %s", genitive_month, short_day);
956 sprintf(Broken, "%s04 %s", month, short_day);
957 ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
958 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
959 ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
960 broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
961 "Expected '%s', got '%s'\n", Expected, buffer);
962
963 STRINGSA("dd dddMMMM", "");
964 sprintf(Expected, "04 %s%s", short_day, month);
965 ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
966 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
967 EXPECT_EQA;
968
969 STRINGSA("dd dddMMMM ddd MMMMdd", "");
970 sprintf(Expected, "04 %s%s %s %s04", short_day, month, short_day, genitive_month);
971 sprintf(Broken, "04 %s%s %s %s04", short_day, month, short_day, month);
972 ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
973 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
974 ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
975 broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
976 "Expected '%s', got '%s'\n", Expected, buffer);
977
978 /* with literal part */
979 STRINGSA("ddd',' MMMM dd", "");
980 sprintf(Expected, "%s, %s 04", short_day, genitive_month);
981 sprintf(Broken, "%s, %s 04", short_day, month);
982 ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
983 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
984 ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
985 broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
986 "Expected '%s', got '%s'\n", Expected, buffer);
987 }
988
989 static void test_GetDateFormatEx(void)
990 {
991 int ret;
992 SYSTEMTIME curtime;
993 WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
994
995 if (!pGetDateFormatEx)
996 {
997 win_skip("GetDateFormatEx not supported\n");
998 return;
999 }
1000
1001 STRINGSW("",""); /* If flags are set, then format must be NULL */
1002 SetLastError(0xdeadbeef);
1003 ret = pGetDateFormatEx(localeW, DATE_LONGDATE, NULL,
1004 input, buffer, COUNTOF(buffer), NULL);
1005 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
1006 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1007 EXPECT_EQW;
1008
1009 STRINGSW("",""); /* NULL buffer, len > 0 */
1010 SetLastError(0xdeadbeef);
1011 ret = pGetDateFormatEx(localeW, 0, NULL, input, NULL, COUNTOF(buffer), NULL);
1012 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1013 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1014
1015 STRINGSW("",""); /* NULL buffer, len == 0 */
1016 ret = pGetDateFormatEx(localeW, 0, NULL, input, NULL, 0, NULL);
1017 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1018 EXPECT_LENW; EXPECT_EQW;
1019
1020 STRINGSW("",""); /* Invalid flag combination */
1021 SetLastError(0xdeadbeef);
1022 ret = pGetDateFormatEx(localeW, DATE_LONGDATE|DATE_SHORTDATE, NULL,
1023 input, NULL, 0, NULL);
1024 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
1025 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1026 EXPECT_EQW;
1027
1028 curtime.wYear = 2002;
1029 curtime.wMonth = 10;
1030 curtime.wDay = 23;
1031 curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
1032 curtime.wHour = 65432; /* Invalid */
1033 curtime.wMinute = 34512; /* Invalid */
1034 curtime.wSecond = 65535; /* Invalid */
1035 curtime.wMilliseconds = 12345;
1036 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
1037 ret = pGetDateFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer), NULL);
1038 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1039 EXPECT_LENW; EXPECT_EQW;
1040
1041 curtime.wYear = 2002;
1042 curtime.wMonth = 10;
1043 curtime.wDay = 23;
1044 curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
1045 curtime.wHour = 65432; /* Invalid */
1046 curtime.wMinute = 34512; /* Invalid */
1047 curtime.wSecond = 65535; /* Invalid */
1048 curtime.wMilliseconds = 12345;
1049 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002");
1050 ret = pGetDateFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer), emptyW); /* Use reserved arg */
1051 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1052 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1053
1054 /* Limit tests */
1055
1056 curtime.wYear = 1601;
1057 curtime.wMonth = 1;
1058 curtime.wDay = 1;
1059 curtime.wDayOfWeek = 0; /* Irrelevant */
1060 curtime.wHour = 0;
1061 curtime.wMinute = 0;
1062 curtime.wSecond = 0;
1063 curtime.wMilliseconds = 0;
1064 STRINGSW("dddd d MMMM yyyy","Monday 1 January 1601");
1065 SetLastError(0xdeadbeef);
1066 ret = pGetDateFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer), NULL);
1067 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1068 EXPECT_LENW; EXPECT_EQW;
1069
1070 curtime.wYear = 1600;
1071 curtime.wMonth = 12;
1072 curtime.wDay = 31;
1073 curtime.wDayOfWeek = 0; /* Irrelevant */
1074 curtime.wHour = 23;
1075 curtime.wMinute = 59;
1076 curtime.wSecond = 59;
1077 curtime.wMilliseconds = 999;
1078 STRINGSW("dddd d MMMM yyyy","Friday 31 December 1600");
1079 SetLastError(0xdeadbeef);
1080 ret = pGetDateFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer), NULL);
1081 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1082 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1083 }
1084
1085 static void test_GetDateFormatW(void)
1086 {
1087 int ret;
1088 SYSTEMTIME curtime;
1089 WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
1090 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
1091
1092 STRINGSW("",""); /* If flags is not zero then format must be NULL */
1093 ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL,
1094 input, buffer, COUNTOF(buffer));
1095 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1096 {
1097 win_skip("GetDateFormatW is not implemented\n");
1098 return;
1099 }
1100 ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
1101 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1102 EXPECT_EQW;
1103
1104 STRINGSW("",""); /* NULL buffer, len > 0 */
1105 SetLastError(0xdeadbeef);
1106 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
1107 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1108 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1109
1110 STRINGSW("",""); /* NULL buffer, len == 0 */
1111 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
1112 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1113 EXPECT_LENW; EXPECT_EQW;
1114
1115 curtime.wYear = 2002;
1116 curtime.wMonth = 10;
1117 curtime.wDay = 23;
1118 curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
1119 curtime.wHour = 65432; /* Invalid */
1120 curtime.wMinute = 34512; /* Invalid */
1121 curtime.wSecond = 65535; /* Invalid */
1122 curtime.wMilliseconds = 12345;
1123 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
1124 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
1125 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1126 EXPECT_LENW; EXPECT_EQW;
1127
1128 /* Limit tests */
1129
1130 curtime.wYear = 1601;
1131 curtime.wMonth = 1;
1132 curtime.wDay = 1;
1133 curtime.wDayOfWeek = 0; /* Irrelevant */
1134 curtime.wHour = 0;
1135 curtime.wMinute = 0;
1136 curtime.wSecond = 0;
1137 curtime.wMilliseconds = 0;
1138 STRINGSW("dddd d MMMM yyyy","Monday 1 January 1601");
1139 SetLastError(0xdeadbeef);
1140 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
1141 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1142 EXPECT_LENW; EXPECT_EQW;
1143
1144 curtime.wYear = 1600;
1145 curtime.wMonth = 12;
1146 curtime.wDay = 31;
1147 curtime.wDayOfWeek = 0; /* Irrelevant */
1148 curtime.wHour = 23;
1149 curtime.wMinute = 59;
1150 curtime.wSecond = 59;
1151 curtime.wMilliseconds = 999;
1152 STRINGSW("dddd d MMMM yyyy","Friday 31 December 1600");
1153 SetLastError(0xdeadbeef);
1154 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
1155 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1156 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1157 }
1158
1159
1160 #define CY_POS_LEFT 0
1161 #define CY_POS_RIGHT 1
1162 #define CY_POS_LEFT_SPACE 2
1163 #define CY_POS_RIGHT_SPACE 3
1164
1165 static void test_GetCurrencyFormatA(void)
1166 {
1167 static char szDot[] = { '.', '\0' };
1168 static char szComma[] = { ',', '\0' };
1169 static char szDollar[] = { '$', '\0' };
1170 int ret;
1171 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
1172 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
1173 CURRENCYFMTA format;
1174
1175 memset(&format, 0, sizeof(format));
1176
1177 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
1178 SetLastError(0xdeadbeef);
1179 ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
1180 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1181 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1182
1183 STRINGSA("23,53",""); /* Invalid character --> Error */
1184 SetLastError(0xdeadbeef);
1185 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1186 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1187 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1188
1189 STRINGSA("--",""); /* Double '-' --> Error */
1190 SetLastError(0xdeadbeef);
1191 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1192 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1193 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1194
1195 STRINGSA("0-",""); /* Trailing '-' --> Error */
1196 SetLastError(0xdeadbeef);
1197 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1198 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1199 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1200
1201 STRINGSA("0..",""); /* Double '.' --> Error */
1202 SetLastError(0xdeadbeef);
1203 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1204 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1205 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1206
1207 STRINGSA(" 0.1",""); /* Leading space --> Error */
1208 SetLastError(0xdeadbeef);
1209 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1210 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1211 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1212
1213 STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
1214 SetLastError(0xdeadbeef);
1215 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, 2);
1216 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1217 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1218
1219 STRINGSA("2353",""); /* Format and flags given --> Error */
1220 SetLastError(0xdeadbeef);
1221 ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
1222 ok( !ret, "Expected ret == 0, got %d\n", ret);
1223 ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
1224 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1225
1226 STRINGSA("2353",""); /* Invalid format --> Error */
1227 SetLastError(0xdeadbeef);
1228 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1229 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1230 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1231
1232 STRINGSA("2353","$2,353.00"); /* Valid number */
1233 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1234 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1235 EXPECT_LENA; EXPECT_EQA;
1236
1237 STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
1238 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1239 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1240 EXPECT_LENA; EXPECT_EQA;
1241
1242 STRINGSA("2353.1","$2,353.10"); /* Valid real number */
1243 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1244 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1245 EXPECT_LENA; EXPECT_EQA;
1246
1247 STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
1248 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1249 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1250 EXPECT_LENA; EXPECT_EQA;
1251
1252 STRINGSA("2353.119","$2,353.12"); /* Too many DP --> Rounded */
1253 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1254 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1255 EXPECT_LENA; EXPECT_EQA;
1256
1257 format.NumDigits = 0; /* No decimal separator */
1258 format.LeadingZero = 0;
1259 format.Grouping = 0; /* No grouping char */
1260 format.NegativeOrder = 0;
1261 format.PositiveOrder = CY_POS_LEFT;
1262 format.lpDecimalSep = szDot;
1263 format.lpThousandSep = szComma;
1264 format.lpCurrencySymbol = szDollar;
1265
1266 STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
1267 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1268 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1269 EXPECT_LENA; EXPECT_EQA;
1270
1271 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
1272 STRINGSA("2353","$2353.0");
1273 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1274 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1275 EXPECT_LENA; EXPECT_EQA;
1276
1277 format.Grouping = 2; /* Group by 100's */
1278 STRINGSA("2353","$23,53.0");
1279 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1280 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1281 EXPECT_LENA; EXPECT_EQA;
1282
1283 STRINGSA("235","$235.0"); /* Grouping of a positive number */
1284 format.Grouping = 3;
1285 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1286 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1287 EXPECT_LENA; EXPECT_EQA;
1288
1289 STRINGSA("-235","$-235.0"); /* Grouping of a negative number */
1290 format.NegativeOrder = 2;
1291 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1292 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1293 EXPECT_LENA; EXPECT_EQA;
1294
1295 format.LeadingZero = 1; /* Always provide leading zero */
1296 STRINGSA(".5","$0.5");
1297 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1298 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1299 EXPECT_LENA; EXPECT_EQA;
1300
1301 format.PositiveOrder = CY_POS_RIGHT;
1302 STRINGSA("1","1.0$");
1303 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1304 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1305 EXPECT_LENA; EXPECT_EQA;
1306
1307 format.PositiveOrder = CY_POS_LEFT_SPACE;
1308 STRINGSA("1","$ 1.0");
1309 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1310 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1311 EXPECT_LENA; EXPECT_EQA;
1312
1313 format.PositiveOrder = CY_POS_RIGHT_SPACE;
1314 STRINGSA("1","1.0 $");
1315 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1316 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1317 EXPECT_LENA; EXPECT_EQA;
1318
1319 format.NegativeOrder = 0;
1320 STRINGSA("-1","($1.0)");
1321 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1322 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1323 EXPECT_LENA; EXPECT_EQA;
1324
1325 format.NegativeOrder = 1;
1326 STRINGSA("-1","-$1.0");
1327 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1328 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1329 EXPECT_LENA; EXPECT_EQA;
1330
1331 format.NegativeOrder = 2;
1332 STRINGSA("-1","$-1.0");
1333 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1334 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1335 EXPECT_LENA; EXPECT_EQA;
1336
1337 format.NegativeOrder = 3;
1338 STRINGSA("-1","$1.0-");
1339 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1340 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1341 EXPECT_LENA; EXPECT_EQA;
1342
1343 format.NegativeOrder = 4;
1344 STRINGSA("-1","(1.0$)");
1345 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1346 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1347 EXPECT_LENA; EXPECT_EQA;
1348
1349 format.NegativeOrder = 5;
1350 STRINGSA("-1","-1.0$");
1351 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1352 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1353 EXPECT_LENA; EXPECT_EQA;
1354
1355 format.NegativeOrder = 6;
1356 STRINGSA("-1","1.0-$");
1357 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1358 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1359 EXPECT_LENA; EXPECT_EQA;
1360
1361 format.NegativeOrder = 7;
1362 STRINGSA("-1","1.0$-");
1363 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1364 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1365 EXPECT_LENA; EXPECT_EQA;
1366
1367 format.NegativeOrder = 8;
1368 STRINGSA("-1","-1.0 $");
1369 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1370 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1371 EXPECT_LENA; EXPECT_EQA;
1372
1373 format.NegativeOrder = 9;
1374 STRINGSA("-1","-$ 1.0");
1375 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1376 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1377 EXPECT_LENA; EXPECT_EQA;
1378
1379 format.NegativeOrder = 10;
1380 STRINGSA("-1","1.0 $-");
1381 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1382 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1383 EXPECT_LENA; EXPECT_EQA;
1384
1385 format.NegativeOrder = 11;
1386 STRINGSA("-1","$ 1.0-");
1387 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1388 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1389 EXPECT_LENA; EXPECT_EQA;
1390
1391 format.NegativeOrder = 12;
1392 STRINGSA("-1","$ -1.0");
1393 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1394 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1395 EXPECT_LENA; EXPECT_EQA;
1396
1397 format.NegativeOrder = 13;
1398 STRINGSA("-1","1.0- $");
1399 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1400 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1401 EXPECT_LENA; EXPECT_EQA;
1402
1403 format.NegativeOrder = 14;
1404 STRINGSA("-1","($ 1.0)");
1405 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1406 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1407 EXPECT_LENA; EXPECT_EQA;
1408
1409 format.NegativeOrder = 15;
1410 STRINGSA("-1","(1.0 $)");
1411 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1412 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1413 EXPECT_LENA; EXPECT_EQA;
1414 }
1415
1416 #define NEG_PARENS 0 /* "(1.1)" */
1417 #define NEG_LEFT 1 /* "-1.1" */
1418 #define NEG_LEFT_SPACE 2 /* "- 1.1" */
1419 #define NEG_RIGHT 3 /* "1.1-" */
1420 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
1421
1422 static void test_GetNumberFormatA(void)
1423 {
1424 static char szDot[] = { '.', '\0' };
1425 static char szComma[] = { ',', '\0' };
1426 int ret;
1427 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
1428 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
1429 NUMBERFMTA format;
1430
1431 memset(&format, 0, sizeof(format));
1432
1433 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
1434 SetLastError(0xdeadbeef);
1435 ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
1436 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1437 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1438
1439 STRINGSA("23,53",""); /* Invalid character --> Error */
1440 SetLastError(0xdeadbeef);
1441 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1442 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1443 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1444
1445 STRINGSA("--",""); /* Double '-' --> Error */
1446 SetLastError(0xdeadbeef);
1447 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1448 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1449 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1450
1451 STRINGSA("0-",""); /* Trailing '-' --> Error */
1452 SetLastError(0xdeadbeef);
1453 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1454 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1455 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1456
1457 STRINGSA("0..",""); /* Double '.' --> Error */
1458 SetLastError(0xdeadbeef);
1459 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1460 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1461 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1462
1463 STRINGSA(" 0.1",""); /* Leading space --> Error */
1464 SetLastError(0xdeadbeef);
1465 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
1466 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1467 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1468
1469 STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
1470 SetLastError(0xdeadbeef);
1471 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, 2);
1472 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1473 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1474
1475 STRINGSA("2353",""); /* Format and flags given --> Error */
1476 SetLastError(0xdeadbeef);
1477 ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
1478 ok( !ret, "Expected ret == 0, got %d\n", ret);
1479 ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
1480 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1481
1482 STRINGSA("2353",""); /* Invalid format --> Error */
1483 SetLastError(0xdeadbeef);
1484 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1485 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1486 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1487
1488 STRINGSA("2353","2,353.00"); /* Valid number */
1489 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1490 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1491 EXPECT_LENA; EXPECT_EQA;
1492
1493 STRINGSA("-2353","-2,353.00"); /* Valid negative number */
1494 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1495 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1496 EXPECT_LENA; EXPECT_EQA;
1497
1498 STRINGSA("-353","-353.00"); /* test for off by one error in grouping */
1499 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1500 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1501 EXPECT_LENA; EXPECT_EQA;
1502
1503 STRINGSA("2353.1","2,353.10"); /* Valid real number */
1504 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1505 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1506 EXPECT_LENA; EXPECT_EQA;
1507
1508 STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
1509 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1510 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1511 EXPECT_LENA; EXPECT_EQA;
1512
1513 STRINGSA("2353.119","2,353.12"); /* Too many DP --> Rounded */
1514 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1515 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1516 EXPECT_LENA; EXPECT_EQA;
1517
1518 format.NumDigits = 0; /* No decimal separator */
1519 format.LeadingZero = 0;
1520 format.Grouping = 0; /* No grouping char */
1521 format.NegativeOrder = 0;
1522 format.lpDecimalSep = szDot;
1523 format.lpThousandSep = szComma;
1524
1525 STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
1526 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1527 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1528 EXPECT_LENA; EXPECT_EQA;
1529
1530 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
1531 STRINGSA("2353","2353.0");
1532 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1533 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1534 EXPECT_LENA; EXPECT_EQA;
1535
1536 format.Grouping = 2; /* Group by 100's */
1537 STRINGSA("2353","23,53.0");
1538 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1539 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1540 EXPECT_LENA; EXPECT_EQA;
1541
1542 STRINGSA("235","235.0"); /* Grouping of a positive number */
1543 format.Grouping = 3;
1544 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1545 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1546 EXPECT_LENA; EXPECT_EQA;
1547
1548 STRINGSA("-235","-235.0"); /* Grouping of a negative number */
1549 format.NegativeOrder = NEG_LEFT;
1550 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1551 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1552 EXPECT_LENA; EXPECT_EQA;
1553
1554 format.LeadingZero = 1; /* Always provide leading zero */
1555 STRINGSA(".5","0.5");
1556 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1557 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1558 EXPECT_LENA; EXPECT_EQA;
1559
1560 format.NegativeOrder = NEG_PARENS;
1561 STRINGSA("-1","(1.0)");
1562 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1563 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1564 EXPECT_LENA; EXPECT_EQA;
1565
1566 format.NegativeOrder = NEG_LEFT;
1567 STRINGSA("-1","-1.0");
1568 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1569 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1570 EXPECT_LENA; EXPECT_EQA;
1571
1572 format.NegativeOrder = NEG_LEFT_SPACE;
1573 STRINGSA("-1","- 1.0");
1574 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1575 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1576 EXPECT_LENA; EXPECT_EQA;
1577
1578 format.NegativeOrder = NEG_RIGHT;
1579 STRINGSA("-1","1.0-");
1580 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1581 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1582 EXPECT_LENA; EXPECT_EQA;
1583
1584 format.NegativeOrder = NEG_RIGHT_SPACE;
1585 STRINGSA("-1","1.0 -");
1586 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
1587 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1588 EXPECT_LENA; EXPECT_EQA;
1589
1590 lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
1591
1592 if (IsValidLocale(lcid, 0))
1593 {
1594 STRINGSA("-12345","-12 345,00"); /* Try French formatting */
1595 Expected[3] = 160; /* Non breaking space */
1596 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
1597 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1598 EXPECT_LENA; EXPECT_EQA;
1599 }
1600 }
1601
1602 static void test_GetNumberFormatEx(void)
1603 {
1604 int ret;
1605 NUMBERFMTW format;
1606 static WCHAR dotW[] = {'.',0};
1607 static WCHAR commaW[] = {',',0};
1608 static const WCHAR enW[] = {'e','n','-','U','S',0};
1609 static const WCHAR frW[] = {'f','r','-','F','R',0};
1610 static const WCHAR bogusW[] = {'b','o','g','u','s',0};
1611 WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
1612
1613 if (!pGetNumberFormatEx)
1614 {
1615 win_skip("GetNumberFormatEx is not available.\n");
1616 return;
1617 }
1618
1619 STRINGSW("23",""); /* NULL output, length > 0 --> Error */
1620 ret = pGetNumberFormatEx(enW, 0, input, NULL, NULL, COUNTOF(buffer));
1621 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1622 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1623
1624 STRINGSW("23,53",""); /* Invalid character --> Error */
1625 ret = pGetNumberFormatEx(enW, 0, input, NULL, buffer, COUNTOF(buffer));
1626 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1627 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1628
1629 STRINGSW("--",""); /* Double '-' --> Error */
1630 ret = pGetNumberFormatEx(enW, 0, input, NULL, buffer, COUNTOF(buffer));
1631 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1632 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1633
1634 STRINGSW("0-",""); /* Trailing '-' --> Error */
1635 ret = pGetNumberFormatEx(enW, 0, input, NULL, buffer, COUNTOF(buffer));
1636 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1637 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1638
1639 STRINGSW("0..",""); /* Double '.' --> Error */
1640 ret = pGetNumberFormatEx(enW, 0, input, NULL, buffer, COUNTOF(buffer));
1641 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1642 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1643
1644 STRINGSW(" 0.1",""); /* Leading space --> Error */
1645 ret = pGetNumberFormatEx(enW, 0, input, NULL, buffer, COUNTOF(buffer));
1646 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1647 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1648
1649 STRINGSW("1234","1"); /* Length too small --> Write up to length chars */
1650 ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, 2);
1651 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1652 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1653
1654 STRINGSW("23",""); /* Bogus locale --> Error */
1655 ret = pGetNumberFormatEx(bogusW, NUO, input, NULL, buffer, COUNTOF(buffer));
1656 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1657 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1658
1659 memset(&format, 0, sizeof(format));
1660
1661 STRINGSW("2353",""); /* Format and flags given --> Error */
1662 ret = pGetNumberFormatEx(enW, NUO, input, &format, buffer, COUNTOF(buffer));
1663 ok( !ret, "Expected ret == 0, got %d\n", ret);
1664 ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER,
1665 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
1666
1667 STRINGSW("2353",""); /* Invalid format --> Error */
1668 ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer));
1669 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
1670 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1671
1672 STRINGSW("2353","2,353.00"); /* Valid number */
1673 ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, COUNTOF(buffer));
1674 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1675 EXPECT_LENW; EXPECT_EQW;
1676
1677 STRINGSW("-2353","-2,353.00"); /* Valid negative number */
1678 ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, COUNTOF(buffer));
1679 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1680 EXPECT_LENW; EXPECT_EQW;
1681
1682 STRINGSW("-353","-353.00"); /* test for off by one error in grouping */
1683 ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, COUNTOF(buffer));
1684 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1685 EXPECT_LENW; EXPECT_EQW;
1686
1687 STRINGSW("2353.1","2,353.10"); /* Valid real number */
1688 ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, COUNTOF(buffer));
1689 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1690 EXPECT_LENW; EXPECT_EQW;
1691
1692 STRINGSW("2353.111","2,353.11"); /* Too many DP --> Truncated */
1693 ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, COUNTOF(buffer));
1694 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1695 EXPECT_LENW; EXPECT_EQW;
1696
1697 STRINGSW("2353.119","2,353.12"); /* Too many DP --> Rounded */
1698 ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, COUNTOF(buffer));
1699 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1700 EXPECT_LENW; EXPECT_EQW;
1701
1702 format.NumDigits = 0; /* No decimal separator */
1703 format.LeadingZero = 0;
1704 format.Grouping = 0; /* No grouping char */
1705 format.NegativeOrder = 0;
1706 format.lpDecimalSep = dotW;
1707 format.lpThousandSep = commaW;
1708
1709 STRINGSW("2353","2353"); /* No decimal or grouping chars expected */
1710 ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer));
1711 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1712 EXPECT_LENW; EXPECT_EQW;
1713
1714 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
1715 STRINGSW("2353","2353.0");
1716 ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer));
1717 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1718 EXPECT_LENW; EXPECT_EQW;
1719
1720 format.Grouping = 2; /* Group by 100's */
1721 STRINGSW("2353","23,53.0");
1722 ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer));
1723 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1724 EXPECT_LENW; EXPECT_EQW;
1725
1726 STRINGSW("235","235.0"); /* Grouping of a positive number */
1727 format.Grouping = 3;
1728 ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer));
1729 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1730 EXPECT_LENW; EXPECT_EQW;
1731
1732 STRINGSW("-235","-235.0"); /* Grouping of a negative number */
1733 format.NegativeOrder = NEG_LEFT;
1734 ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer));
1735 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1736 EXPECT_LENW; EXPECT_EQW;
1737
1738 format.LeadingZero = 1; /* Always provide leading zero */
1739 STRINGSW(".5","0.5");
1740 ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer));
1741 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1742 EXPECT_LENW; EXPECT_EQW;
1743
1744 format.NegativeOrder = NEG_PARENS;
1745 STRINGSW("-1","(1.0)");
1746 ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer));
1747 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1748 EXPECT_LENW; EXPECT_EQW;
1749
1750 format.NegativeOrder = NEG_LEFT;
1751 STRINGSW("-1","-1.0");
1752 ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer));
1753 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1754 EXPECT_LENW; EXPECT_EQW;
1755
1756 format.NegativeOrder = NEG_LEFT_SPACE;
1757 STRINGSW("-1","- 1.0");
1758 ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer));
1759 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1760 EXPECT_LENW; EXPECT_EQW;
1761
1762 format.NegativeOrder = NEG_RIGHT;
1763 STRINGSW("-1","1.0-");
1764 ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer));
1765 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1766 EXPECT_LENW; EXPECT_EQW;
1767
1768 format.NegativeOrder = NEG_RIGHT_SPACE;
1769 STRINGSW("-1","1.0 -");
1770 ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer));
1771 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1772 EXPECT_LENW; EXPECT_EQW;
1773
1774 if (pIsValidLocaleName(frW))
1775 {
1776 STRINGSW("-12345","-12 345,00"); /* Try French formatting */
1777 Expected[3] = 160; /* Non breaking space */
1778 ret = pGetNumberFormatEx(frW, NUO, input, NULL, buffer, COUNTOF(buffer));
1779 ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
1780 EXPECT_LENW; EXPECT_EQW;
1781 }
1782 }
1783
1784 struct comparestringa_entry {
1785 LCID lcid;
1786 DWORD flags;
1787 const char *first;
1788 int first_len;
1789 const char *second;
1790 int second_len;
1791 int ret;
1792 };
1793
1794 static const struct comparestringa_entry comparestringa_data[] = {
1795 { LOCALE_SYSTEM_DEFAULT, 0, "EndDialog", -1, "_Property", -1, CSTR_GREATER_THAN },
1796 { LOCALE_SYSTEM_DEFAULT, 0, "osp_vba.sreg0070", -1, "_IEWWBrowserComp", -1, CSTR_GREATER_THAN },
1797 { LOCALE_SYSTEM_DEFAULT, 0, "r", -1, "\\", -1, CSTR_GREATER_THAN },
1798 { LOCALE_SYSTEM_DEFAULT, 0, "osp_vba.sreg0031", -1, "OriginalDatabase", -1, CSTR_GREATER_THAN },
1799 { LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1, CSTR_GREATER_THAN },
1800 { LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1, CSTR_LESS_THAN },
1801 { LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1, CSTR_LESS_THAN },
1802 { LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1, CSTR_LESS_THAN },
1803 { LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1, CSTR_LESS_THAN },
1804 { LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1, CSTR_LESS_THAN },
1805 { LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1, CSTR_LESS_THAN },
1806 { LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1, CSTR_GREATER_THAN },
1807 { LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1, CSTR_LESS_THAN },
1808 { LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1, CSTR_LESS_THAN },
1809 { LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1, CSTR_GREATER_THAN },
1810 { LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1, CSTR_GREATER_THAN },
1811 { LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1, CSTR_LESS_THAN },
1812 { LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1, CSTR_LESS_THAN },
1813 { LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1, CSTR_LESS_THAN },
1814 /* hyphen and apostrophe are treated differently depending on whether SORT_STRINGSORT specified or not */
1815 { LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1, CSTR_GREATER_THAN },
1816 { LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1, CSTR_LESS_THAN },
1817 { LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1, CSTR_LESS_THAN },
1818 { LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1, CSTR_GREATER_THAN },
1819 { LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1, CSTR_GREATER_THAN },
1820 { LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1, CSTR_LESS_THAN },
1821 { LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1, CSTR_LESS_THAN },
1822 { LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1, CSTR_GREATER_THAN },
1823 { LOCALE_SYSTEM_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9, CSTR_EQUAL },
1824 { LOCALE_SYSTEM_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10, CSTR_LESS_THAN },
1825 { LOCALE_SYSTEM_DEFAULT, 0, "a-", 3, "a\0", 3, CSTR_GREATER_THAN },
1826 { LOCALE_SYSTEM_DEFAULT, 0, "a'", 3, "a\0", 3, CSTR_GREATER_THAN },
1827 { LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "a-", 3, "a\0", 3, CSTR_GREATER_THAN },
1828 { LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "a'", 3, "a\0", 3, CSTR_GREATER_THAN },
1829 { LOCALE_SYSTEM_DEFAULT, NORM_IGNORESYMBOLS, "a.", 3, "a\0", 3, CSTR_EQUAL },
1830 { LOCALE_SYSTEM_DEFAULT, NORM_IGNORESYMBOLS, "a ", 3, "a\0", 3, CSTR_EQUAL },
1831 { LOCALE_SYSTEM_DEFAULT, 0, "a", 1, "a\0\0", 4, CSTR_EQUAL },
1832 { LOCALE_SYSTEM_DEFAULT, 0, "a", 2, "a\0\0", 4, CSTR_EQUAL },
1833 { LOCALE_SYSTEM_DEFAULT, 0, "a\0\0", 4, "a", 1, CSTR_EQUAL },
1834 { LOCALE_SYSTEM_DEFAULT, 0, "a\0\0", 4, "a", 2, CSTR_EQUAL },
1835 { LOCALE_SYSTEM_DEFAULT, 0, "a", 1, "a\0x", 4, CSTR_LESS_THAN },
1836 { LOCALE_SYSTEM_DEFAULT, 0, "a", 2, "a\0x", 4, CSTR_LESS_THAN },
1837 { LOCALE_SYSTEM_DEFAULT, 0, "a\0x", 4, "a", 1, CSTR_GREATER_THAN },
1838 { LOCALE_SYSTEM_DEFAULT, 0, "a\0x", 4, "a", 2, CSTR_GREATER_THAN },
1839 };
1840
1841 static void test_CompareStringA(void)
1842 {
1843 int ret, i;
1844 char a[256];
1845 LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
1846
1847 for (i = 0; i < sizeof(comparestringa_data)/sizeof(struct comparestringa_entry); i++)
1848 {
1849 const struct comparestringa_entry *entry = &comparestringa_data[i];
1850
1851 ret = CompareStringA(entry->lcid, entry->flags, entry->first, entry->first_len,
1852 entry->second, entry->second_len);
1853 ok(ret == entry->ret, "%d: got %d, expected %d\n", i, ret, entry->ret);
1854 }
1855
1856 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
1857 ok (ret == CSTR_LESS_THAN, "(Salut/Salute) Expected CSTR_LESS_THAN, got %d\n", ret);
1858
1859 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
1860 ok (ret == CSTR_EQUAL, "(Salut/SaLuT) Expected CSTR_EQUAL, got %d\n", ret);
1861
1862 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
1863 ok (ret == CSTR_GREATER_THAN, "(Salut/hola) Expected CSTR_GREATER_THAN, got %d\n", ret);
1864
1865 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
1866 ok (ret == CSTR_LESS_THAN, "(haha/hoho) Expected CSTR_LESS_THAN, got %d\n", ret);
1867
1868 lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
1869
1870 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
1871 ok (ret == CSTR_LESS_THAN, "(haha/hoho) Expected CSTR_LESS_THAN, got %d\n", ret);
1872
1873 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
1874 ok (ret == CSTR_GREATER_THAN, "(haha/hoho) Expected CSTR_GREATER_THAN, got %d\n", ret);
1875
1876 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
1877 ok (ret == CSTR_EQUAL, "(Salut/saLuT) Expected CSTR_EQUAL, got %d\n", ret);
1878
1879 /* test for CompareStringA flags */
1880 SetLastError(0xdeadbeef);
1881 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0x8, "NULL", -1, "NULL", -1);
1882 ok(GetLastError() == ERROR_INVALID_FLAGS,
1883 "unexpected error code %d\n", GetLastError());
1884 ok(!ret, "CompareStringA must fail with invalid flag\n");
1885
1886 SetLastError(0xdeadbeef);
1887 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, LOCALE_USE_CP_ACP, "NULL", -1, "NULL", -1);
1888 ok(GetLastError() == 0xdeadbeef, "unexpected error code %d\n", GetLastError());
1889 ok(ret == CSTR_EQUAL, "CompareStringA error: %d != CSTR_EQUAL\n", ret);
1890 /* end of test for CompareStringA flags */
1891
1892 ret = lstrcmpA("", "");
1893 ok (ret == 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret);
1894
1895 ret = lstrcmpA(NULL, NULL);
1896 ok (ret == 0 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, NULL) should return 0, got %d\n", ret);
1897
1898 ret = lstrcmpA("", NULL);
1899 ok (ret == 1 || broken(ret == -2) /* win9x */, "lstrcmpA(\"\", NULL) should return 1, got %d\n", ret);
1900
1901 ret = lstrcmpA(NULL, "");
1902 ok (ret == -1 || broken(ret == -2) /* win9x */, "lstrcmpA(NULL, \"\") should return -1, got %d\n", ret);
1903
1904
1905 if (0) { /* this requires collation table patch to make it MS compatible */
1906 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
1907 ok(ret == CSTR_LESS_THAN, "'o vs -o expected CSTR_LESS_THAN, got %d\n", ret);
1908
1909 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
1910 ok(ret == CSTR_LESS_THAN, "'o vs -o expected CSTR_LESS_THAN, got %d\n", ret);
1911
1912 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
1913 ok(ret == CSTR_LESS_THAN, "' vs - expected CSTR_LESS_THAN, got %d\n", ret);
1914
1915 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
1916 ok(ret == CSTR_LESS_THAN, "' vs - expected CSTR_LESS_THAN, got %d\n", ret);
1917
1918 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
1919 ok(ret == CSTR_GREATER_THAN, "`o vs /m CSTR_GREATER_THAN got %d\n", ret);
1920
1921 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
1922 ok(ret == CSTR_LESS_THAN, "/m vs `o expected CSTR_LESS_THAN, got %d\n", ret);
1923
1924 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
1925 ok(ret == CSTR_GREATER_THAN, "`o vs /m CSTR_GREATER_THAN got %d\n", ret);
1926
1927 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
1928 ok(ret == CSTR_LESS_THAN, "/m vs `o expected CSTR_LESS_THAN, got %d\n", ret);
1929
1930 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
1931 ok(ret == CSTR_LESS_THAN, "`o vs -m expected CSTR_LESS_THAN, got %d\n", ret);
1932
1933 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
1934 ok(ret == CSTR_GREATER_THAN, "-m vs `o CSTR_GREATER_THAN got %d\n", ret);
1935
1936 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
1937 ok(ret == CSTR_GREATER_THAN, "`o vs -m CSTR_GREATER_THAN got %d\n", ret);
1938
1939 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
1940 ok(ret == CSTR_LESS_THAN, "-m vs `o expected CSTR_LESS_THAN, got %d\n", ret);
1941 }
1942
1943
1944 /* WinXP handles embedded NULLs differently than earlier versions */
1945 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
1946 ok(ret == CSTR_LESS_THAN || ret == CSTR_EQUAL, "aLuZkUtZ vs aLuZkUtZ\\0A expected CSTR_LESS_THAN or CSTR_EQUAL, got %d\n", ret);
1947
1948 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
1949 ok(ret == CSTR_LESS_THAN || ret == CSTR_EQUAL, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected CSTR_LESS_THAN or CSTR_EQUAL, got %d\n", ret);
1950
1951 ret = CompareStringA(lcid, 0, "a\0b", -1, "a", -1);
1952 ok(ret == CSTR_EQUAL, "a vs a expected CSTR_EQUAL, got %d\n", ret);
1953
1954 ret = CompareStringA(lcid, 0, "a\0b", 4, "a", 2);
1955 ok(ret == CSTR_EQUAL || /* win2k */
1956 ret == CSTR_GREATER_THAN,
1957 "a\\0b vs a expected CSTR_EQUAL or CSTR_GREATER_THAN, got %d\n", ret);
1958
1959 ret = CompareStringA(lcid, 0, "\2", 2, "\1", 2);
1960 todo_wine ok(ret != CSTR_EQUAL, "\\2 vs \\1 expected unequal\n");
1961
1962 ret = CompareStringA(lcid, NORM_IGNORECASE | LOCALE_USE_CP_ACP, "#", -1, ".", -1);
1963 ok(ret == CSTR_LESS_THAN, "\"#\" vs \".\" expected CSTR_LESS_THAN, got %d\n", ret);
1964
1965 ret = CompareStringA(lcid, NORM_IGNORECASE, "_", -1, ".", -1);
1966 ok(ret == CSTR_GREATER_THAN, "\"_\" vs \".\" expected CSTR_GREATER_THAN, got %d\n", ret);
1967
1968 ret = lstrcmpiA("#", ".");
1969 ok(ret == -1, "\"#\" vs \".\" expected -1, got %d\n", ret);
1970
1971 lcid = MAKELCID(MAKELANGID(LANG_POLISH, SUBLANG_DEFAULT), SORT_DEFAULT);
1972
1973 /* \xB9 character lies between a and b */
1974 ret = CompareStringA(lcid, 0, "a", 1, "\xB9", 1);
1975 todo_wine ok(ret == CSTR_LESS_THAN, "\'\\xB9\' character should be greater than \'a\'\n");
1976 ret = CompareStringA(lcid, 0, "\xB9", 1, "b", 1);
1977 ok(ret == CSTR_LESS_THAN, "\'\\xB9\' character should be smaller than \'b\'\n");
1978
1979 memset(a, 'a', sizeof(a));
1980 SetLastError(0xdeadbeef);
1981 ret = CompareStringA(lcid, 0, a, sizeof(a), a, sizeof(a));
1982 ok (GetLastError() == 0xdeadbeef && ret == CSTR_EQUAL,
1983 "ret %d, error %d, expected value %d\n", ret, GetLastError(), CSTR_EQUAL);
1984 }
1985
1986 static void test_CompareStringW(void)
1987 {
1988 WCHAR *str1, *str2;
1989 SYSTEM_INFO si;
1990 DWORD old_prot;
1991 BOOL success;
1992 char *buf;
1993 int ret;
1994
1995 GetSystemInfo(&si);
1996 buf = VirtualAlloc(NULL, si.dwPageSize * 4, MEM_COMMIT, PAGE_READWRITE);
1997 ok(buf != NULL, "VirtualAlloc failed with %u\n", GetLastError());
1998 success = VirtualProtect(buf + si.dwPageSize, si.dwPageSize, PAGE_NOACCESS, &old_prot);
1999 ok(success, "VirtualProtect failed with %u\n", GetLastError());
2000 success = VirtualProtect(buf + 3 * si.dwPageSize, si.dwPageSize, PAGE_NOACCESS, &old_prot);
2001 ok(success, "VirtualProtect failed with %u\n", GetLastError());
2002
2003 str1 = (WCHAR *)(buf + si.dwPageSize - sizeof(WCHAR));
2004 str2 = (WCHAR *)(buf + 3 * si.dwPageSize - sizeof(WCHAR));
2005 *str1 = 'A';
2006 *str2 = 'B';
2007
2008 /* CompareStringW should abort on the first non-matching character */
2009 ret = CompareStringW(CP_ACP, 0, str1, 100, str2, 100);
2010 ok(ret == CSTR_LESS_THAN, "expected CSTR_LESS_THAN, got %d\n", ret);
2011
2012 success = VirtualFree(buf, 0, MEM_RELEASE);
2013 ok(success, "VirtualFree failed with %u\n", GetLastError());
2014 }
2015
2016 struct comparestringex_test {
2017 const char *locale;
2018 DWORD flags;
2019 const WCHAR first[2];
2020 const WCHAR second[2];
2021 INT ret;
2022 INT broken;
2023 BOOL todo;
2024 };
2025
2026 static const struct comparestringex_test comparestringex_tests[] = {
2027 /* default behavior */
2028 { /* 0 */
2029 "tr-TR", 0,
2030 {'i',0}, {'I',0}, CSTR_LESS_THAN, -1, FALSE
2031 },
2032 { /* 1 */
2033 "tr-TR", 0,
2034 {'i',0}, {0x130,0}, CSTR_LESS_THAN, -1, FALSE
2035 },
2036 { /* 2 */
2037 "tr-TR", 0,
2038 {'i',0}, {0x131,0}, CSTR_LESS_THAN, -1, FALSE
2039 },
2040 { /* 3 */
2041 "tr-TR", 0,
2042 {'I',0}, {0x130,0}, CSTR_LESS_THAN, -1, TRUE
2043 },
2044 { /* 4 */
2045 "tr-TR", 0,
2046 {'I',0}, {0x131,0}, CSTR_LESS_THAN, -1, FALSE
2047 },
2048 { /* 5 */
2049 "tr-TR", 0,
2050 {0x130,0}, {0x131,0}, CSTR_GREATER_THAN, -1, TRUE
2051 },
2052 /* with NORM_IGNORECASE */
2053 { /* 6 */
2054 "tr-TR", NORM_IGNORECASE,
2055 {'i',0}, {'I',0}, CSTR_EQUAL, -1, FALSE
2056 },
2057 { /* 7 */
2058 "tr-TR", NORM_IGNORECASE,
2059 {'i',0}, {0x130,0}, CSTR_LESS_THAN, -1, TRUE
2060 },
2061 { /* 8 */
2062 "tr-TR", NORM_IGNORECASE,
2063 {'i',0}, {0x131,0}, CSTR_LESS_THAN, -1, FALSE
2064 },
2065 { /* 9 */
2066 "tr-TR", NORM_IGNORECASE,
2067 {'I',0}, {0x130,0}, CSTR_LESS_THAN, -1, TRUE
2068 },
2069 { /* 10 */
2070 "tr-TR", NORM_IGNORECASE,
2071 {'I',0}, {0x131,0}, CSTR_LESS_THAN, -1, FALSE
2072 },
2073 { /* 11 */
2074 "tr-TR", NORM_IGNORECASE,
2075 {0x130,0}, {0x131,0}, CSTR_GREATER_THAN, -1, TRUE
2076 },
2077 /* with NORM_LINGUISTIC_CASING */
2078 { /* 12 */
2079 "tr-TR", NORM_LINGUISTIC_CASING,
2080 {'i',0}, {'I',0}, CSTR_GREATER_THAN, CSTR_LESS_THAN, TRUE
2081 },
2082 { /* 13 */
2083 "tr-TR", NORM_LINGUISTIC_CASING,
2084 {'i',0}, {0x130,0}, CSTR_LESS_THAN, -1, FALSE
2085 },
2086 { /* 14 */
2087 "tr-TR", NORM_LINGUISTIC_CASING,
2088 {'i',0}, {0x131,0}, CSTR_GREATER_THAN, CSTR_LESS_THAN, TRUE
2089 },
2090 { /* 15 */
2091 "tr-TR", NORM_LINGUISTIC_CASING,
2092 {'I',0}, {0x130,0}, CSTR_LESS_THAN, -1, TRUE
2093 },
2094 { /* 16 */
2095 "tr-TR", NORM_LINGUISTIC_CASING,
2096 {'I',0}, {0x131,0}, CSTR_GREATER_THAN, CSTR_LESS_THAN, TRUE
2097 },
2098 { /* 17 */
2099 "tr-TR", NORM_LINGUISTIC_CASING,
2100 {0x130,0}, {0x131,0}, CSTR_GREATER_THAN, -1, TRUE
2101 },
2102 /* with LINGUISTIC_IGNORECASE */
2103 { /* 18 */
2104 "tr-TR", LINGUISTIC_IGNORECASE,
2105 {'i',0}, {'I',0}, CSTR_EQUAL, -1, TRUE
2106 },
2107 { /* 19 */
2108 "tr-TR", LINGUISTIC_IGNORECASE,
2109 {'i',0}, {0x130,0}, CSTR_LESS_THAN, -1, FALSE
2110 },
2111 { /* 20 */
2112 "tr-TR", LINGUISTIC_IGNORECASE,
2113 {'i',0}, {0x131,0}, CSTR_LESS_THAN, -1, FALSE
2114 },
2115 { /* 21 */
2116 "tr-TR", LINGUISTIC_IGNORECASE,
2117 {'I',0}, {0x130,0}, CSTR_LESS_THAN, -1, TRUE
2118 },
2119 { /* 22 */
2120 "tr-TR", LINGUISTIC_IGNORECASE,
2121 {'I',0}, {0x131,0}, CSTR_LESS_THAN, -1, FALSE
2122 },
2123 { /* 23 */
2124 "tr-TR", LINGUISTIC_IGNORECASE,
2125 {0x130,0}, {0x131,0}, CSTR_GREATER_THAN, -1, TRUE
2126 },
2127 /* with NORM_LINGUISTIC_CASING | NORM_IGNORECASE */
2128 { /* 24 */
2129 "tr-TR", NORM_LINGUISTIC_CASING | NORM_IGNORECASE,
2130 {'i',0}, {'I',0}, CSTR_GREATER_THAN, CSTR_EQUAL, TRUE
2131 },
2132 { /* 25 */
2133 "tr-TR", NORM_LINGUISTIC_CASING | NORM_IGNORECASE,
2134 {'i',0}, {0x130,0}, CSTR_EQUAL, CSTR_LESS_THAN, FALSE
2135 },
2136 { /* 26 */
2137 "tr-TR", NORM_LINGUISTIC_CASING | NORM_IGNORECASE,
2138 {'i',0}, {0x131,0}, CSTR_GREATER_THAN, CSTR_LESS_THAN, TRUE
2139 },
2140 { /* 27 */
2141 "tr-TR", NORM_LINGUISTIC_CASING | NORM_IGNORECASE,
2142 {'I',0}, {0x130,0}, CSTR_LESS_THAN, -1, TRUE
2143 },
2144 { /* 28 */
2145 "tr-TR", NORM_LINGUISTIC_CASING | NORM_IGNORECASE,
2146 {'I',0}, {0x131,0}, CSTR_EQUAL, CSTR_LESS_THAN, TRUE
2147 },
2148 { /* 29 */
2149 "tr-TR", NORM_LINGUISTIC_CASING | NORM_IGNORECASE,
2150 {0x130,0}, {0x131,0}, CSTR_GREATER_THAN, -1, TRUE
2151 },
2152 /* with NORM_LINGUISTIC_CASING | LINGUISTIC_IGNORECASE */
2153 { /* 30 */
2154 "tr-TR", NORM_LINGUISTIC_CASING | LINGUISTIC_IGNORECASE,
2155 {'i',0}, {'I',0}, CSTR_GREATER_THAN, CSTR_EQUAL, TRUE
2156 },
2157 { /* 31 */
2158 "tr-TR", NORM_LINGUISTIC_CASING | LINGUISTIC_IGNORECASE,
2159 {'i',0}, {0x130,0}, CSTR_EQUAL, CSTR_LESS_THAN, TRUE
2160 },
2161 { /* 32 */
2162 "tr-TR", NORM_LINGUISTIC_CASING | LINGUISTIC_IGNORECASE,
2163 {'i',0}, {0x131,0}, CSTR_GREATER_THAN, CSTR_LESS_THAN, TRUE
2164 },
2165 { /* 33 */
2166 "tr-TR", NORM_LINGUISTIC_CASING | LINGUISTIC_IGNORECASE,
2167 {'I',0}, {0x130,0}, CSTR_LESS_THAN, -1, TRUE
2168 },
2169 { /* 34 */
2170 "tr-TR", NORM_LINGUISTIC_CASING | LINGUISTIC_IGNORECASE,
2171 {'I',0}, {0x131,0}, CSTR_EQUAL, CSTR_LESS_THAN, TRUE
2172 },
2173 { /* 35 */
2174 "tr-TR", NORM_LINGUISTIC_CASING | LINGUISTIC_IGNORECASE,
2175 {0x130,0}, {0x131,0}, CSTR_GREATER_THAN, CSTR_LESS_THAN, TRUE
2176 }
2177 };
2178
2179 static void test_CompareStringEx(void)
2180 {
2181 const char *op[] = {"ERROR", "CSTR_LESS_THAN", "CSTR_EQUAL", "CSTR_GREATER_THAN"};
2182 WCHAR locale[6];
2183 INT ret, i;
2184
2185 /* CompareStringEx is only available on Vista+ */
2186 if (!pCompareStringEx)
2187 {
2188 win_skip("CompareStringEx not supported\n");
2189 return;
2190 }
2191
2192 for (i = 0; i < sizeof(comparestringex_tests)/sizeof(comparestringex_tests[0]); i++)
2193 {
2194 const struct comparestringex_test *e = &comparestringex_tests[i];
2195
2196 MultiByteToWideChar(CP_ACP, 0, e->locale, -1, locale, sizeof(locale)/sizeof(WCHAR));
2197 ret = pCompareStringEx(locale, e->flags, e->first, -1, e->second, -1, NULL, NULL, 0);
2198 todo_wine_if (e->todo)
2199 ok(ret == e->ret || broken(ret == e->broken),
2200 "%d: got %s, expected %s\n", i, op[ret], op[e->ret]);
2201 }
2202
2203 }
2204
2205 static const DWORD lcmap_invalid_flags[] = {
2206 0,
2207 LCMAP_HIRAGANA | LCMAP_KATAKANA,
2208 LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
2209 LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
2210 LCMAP_LOWERCASE | SORT_STRINGSORT,
2211 LCMAP_UPPERCASE | NORM_IGNORESYMBOLS,
2212 LCMAP_LOWERCASE | NORM_IGNORESYMBOLS,
2213 LCMAP_UPPERCASE | NORM_IGNORENONSPACE,
2214 LCMAP_LOWERCASE | NORM_IGNORENONSPACE,
2215 LCMAP_HIRAGANA | NORM_IGNORENONSPACE,
2216 LCMAP_HIRAGANA | NORM_IGNORESYMBOLS,
2217 LCMAP_HIRAGANA | LCMAP_SIMPLIFIED_CHINESE,
2218 LCMAP_HIRAGANA | LCMAP_TRADITIONAL_CHINESE,
2219 LCMAP_KATAKANA | NORM_IGNORENONSPACE,
2220 LCMAP_KATAKANA | NORM_IGNORESYMBOLS,
2221 LCMAP_KATAKANA | LCMAP_SIMPLIFIED_CHINESE,
2222 LCMAP_KATAKANA | LCMAP_TRADITIONAL_CHINESE,
2223 LCMAP_FULLWIDTH | NORM_IGNORENONSPACE,
2224 LCMAP_FULLWIDTH | NORM_IGNORESYMBOLS,
2225 LCMAP_FULLWIDTH | LCMAP_SIMPLIFIED_CHINESE,
2226 LCMAP_FULLWIDTH | LCMAP_TRADITIONAL_CHINESE,
2227 LCMAP_HALFWIDTH | NORM_IGNORENONSPACE,
2228 LCMAP_HALFWIDTH | NORM_IGNORESYMBOLS,
2229 LCMAP_HALFWIDTH | LCMAP_SIMPLIFIED_CHINESE,
2230 LCMAP_HALFWIDTH | LCMAP_TRADITIONAL_CHINESE,
2231 };
2232
2233 static void test_LCMapStringA(void)
2234 {
2235 int ret, ret2, i;
2236 char buf[256], buf2[256];
2237 static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
2238 static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
2239 static const char symbols_stripped[] = "justateststring1";
2240
2241 SetLastError(0xdeadbeef);
2242 ret = LCMapStringA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP | LCMAP_LOWERCASE,
2243 lower_case, -1, buf, sizeof(buf));
2244 ok(ret == lstrlenA(lower_case) + 1,
2245 "ret %d, error %d, expected value %d\n",
2246 ret, GetLastError(), lstrlenA(lower_case) + 1);
2247 ok(!memcmp(buf, lower_case, ret), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
2248
2249 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
2250 upper_case, -1, buf, sizeof(buf));
2251 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
2252 ok(GetLastError() == ERROR_INVALID_FLAGS,
2253 "unexpected error code %d\n", GetLastError());
2254
2255 /* test invalid flag combinations */
2256 for (i = 0; i < sizeof(lcmap_invalid_flags)/sizeof(lcmap_invalid_flags[0]); i++) {
2257 lstrcpyA(buf, "foo");
2258 SetLastError(0xdeadbeef);
2259 ret = LCMapStringA(LOCALE_USER_DEFAULT, lcmap_invalid_flags[i],
2260 lower_case, -1, buf, sizeof(buf));
2261 ok(GetLastError() == ERROR_INVALID_FLAGS,
2262 "LCMapStringA (flag %08x) unexpected error code %d\n",
2263 lcmap_invalid_flags[i], GetLastError());
2264 ok(!ret, "LCMapStringA (flag %08x) should return 0, got %d\n",
2265 lcmap_invalid_flags[i], ret);
2266 }
2267
2268 /* test LCMAP_LOWERCASE */
2269 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
2270 upper_case, -1, buf, sizeof(buf));
2271 ok(ret == lstrlenA(upper_case) + 1,
2272 "ret %d, error %d, expected value %d\n",
2273 ret, GetLastError(), lstrlenA(upper_case) + 1);
2274 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
2275
2276 /* test LCMAP_UPPERCASE */
2277 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
2278 lower_case, -1, buf, sizeof(buf));
2279 ok(ret == lstrlenA(lower_case) + 1,
2280 "ret %d, error %d, expected value %d\n",
2281 ret, GetLastError(), lstrlenA(lower_case) + 1);
2282 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
2283
2284 /* test buffer overflow */
2285 SetLastError(0xdeadbeef);
2286 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
2287 lower_case, -1, buf, 4);
2288 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2289 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
2290
2291 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
2292 lstrcpyA(buf, lower_case);
2293 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
2294 buf, -1, buf, sizeof(buf));
2295 if (!ret) /* Win9x */
2296 trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
2297 else
2298 {
2299 ok(ret == lstrlenA(lower_case) + 1,
2300 "ret %d, error %d, expected value %d\n",
2301 ret, GetLastError(), lstrlenA(lower_case) + 1);
2302 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
2303 }
2304 lstrcpyA(buf, upper_case);
2305 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
2306 buf, -1, buf, sizeof(buf));
2307 if (!ret) /* Win9x */
2308 trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
2309 else
2310 {
2311 ok(ret == lstrlenA(upper_case) + 1,
2312 "ret %d, error %d, expected value %d\n",
2313 ret, GetLastError(), lstrlenA(lower_case) + 1);
2314 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
2315 }
2316
2317 /* otherwise src == dst should fail */
2318 SetLastError(0xdeadbeef);
2319 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
2320 buf, 10, buf, sizeof(buf));
2321 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
2322 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
2323 "unexpected error code %d\n", GetLastError());
2324 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
2325
2326 /* test whether '\0' is always appended */
2327 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
2328 upper_case, -1, buf, sizeof(buf));
2329 ok(ret, "LCMapStringA must succeed\n");
2330 ok(buf[ret-1] == 0, "LCMapStringA not null-terminated\n");
2331 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
2332 upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
2333 ok(ret2, "LCMapStringA must succeed\n");
2334 ok(buf2[ret2-1] == 0, "LCMapStringA not null-terminated\n" );
2335 ok(ret == ret2, "lengths of sort keys must be equal\n");
2336 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
2337
2338 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
2339 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
2340 upper_case, -1, buf, sizeof(buf));
2341 ok(ret, "LCMapStringA must succeed\n");
2342 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
2343 lower_case, -1, buf2, sizeof(buf2));
2344 ok(ret2, "LCMapStringA must succeed\n");
2345 ok(ret == ret2, "lengths of sort keys must be equal\n");
2346 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
2347
2348 /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
2349 results from plain LCMAP_SORTKEY on Vista */
2350
2351 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
2352 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
2353 lower_case, -1, buf, sizeof(buf));
2354 ok(ret, "LCMapStringA must succeed\n");
2355 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
2356 symbols_stripped, -1, buf2, sizeof(buf2));
2357 ok(ret2, "LCMapStringA must succeed\n");
2358 ok(ret == ret2, "lengths of sort keys must be equal\n");
2359 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
2360
2361 /* test NORM_IGNORENONSPACE */
2362 lstrcpyA(buf, "foo");
2363 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
2364 lower_case, -1, buf, sizeof(buf));
2365 ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
2366 lstrlenA(lower_case) + 1, ret);
2367 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
2368
2369 /* test NORM_IGNORESYMBOLS */
2370 lstrcpyA(buf, "foo");
2371 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
2372 lower_case, -1, buf, sizeof(buf));
2373 ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
2374 lstrlenA(symbols_stripped) + 1, ret);
2375 ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
2376
2377 /* test NORM_IGNORESYMBOLS | NORM_IGNORENONSPACE */
2378 lstrcpyA(buf, "foo");
2379 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS | NORM_IGNORENONSPACE,
2380 lower_case, -1, buf, sizeof(buf));
2381 ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
2382 lstrlenA(symbols_stripped) + 1, ret);
2383 ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
2384
2385 /* test srclen = 0 */
2386 SetLastError(0xdeadbeef);
2387 ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
2388 ok(!ret, "LCMapStringA should fail with srclen = 0\n");
2389 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2390 "unexpected error code %d\n", GetLastError());
2391 }
2392
2393 typedef INT (*lcmapstring_wrapper)(DWORD, LPCWSTR, INT, LPWSTR, INT);
2394
2395 static void test_lcmapstring_unicode(lcmapstring_wrapper func_ptr, const char *func_name)
2396 {
2397 static const WCHAR japanese_text[] = {
2398 0x3044, 0x309d, 0x3084, 0x3001, 0x30a4, 0x30fc, 0x30cf,
2399 0x30c8, 0x30fc, 0x30f4, 0x30a9, 0x306e, 0x2026, 0
2400 };
2401 static const WCHAR hiragana_text[] = {
2402 0x3044, 0x309d, 0x3084, 0x3001, 0x3044, 0x30fc, 0x306f,
2403 0x3068, 0x30fc, 0x3094, 0x3049, 0x306e, 0x2026, 0
2404 };
2405 static const WCHAR katakana_text[] = {
2406 0x30a4, 0x30fd, 0x30e4, 0x3001, 0x30a4, 0x30fc, 0x30cf,
2407 0x30c8, 0x30fc, 0x30f4, 0x30a9, 0x30ce, 0x2026, 0
2408 };
2409 static const WCHAR halfwidth_text[] = {
2410 0x3044, 0x309d, 0x3084, 0xff64, 0xff72, 0xff70, 0xff8a,
2411 0xff84, 0xff70, 0xff73, 0xff9e, 0xff6b, 0x306e, 0x2026, 0
2412 };
2413 int ret, ret2, i;
2414 WCHAR buf[256], buf2[256];
2415 char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
2416
2417 /* LCMAP_LOWERCASE | LCMAP_UPPERCASE makes LCMAP_TITLECASE, so it's valid now. */
2418 ret = func_ptr(LCMAP_LOWERCASE | LCMAP_UPPERCASE,
2419 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
2420 todo_wine ok(ret == lstrlenW(title_case) + 1 || broken(!ret),
2421 "%s ret %d, error %d, expected value %d\n", func_name,
2422 ret, GetLastError(), lstrlenW(title_case) + 1);
2423 todo_wine ok(lstrcmpW(buf, title_case) == 0 || broken(!ret),
2424 "Expected title case string\n");
2425
2426 /* test invalid flag combinations */
2427 for (i = 0; i < sizeof(lcmap_invalid_flags)/sizeof(lcmap_invalid_flags[0]); i++) {
2428 lstrcpyW(buf, fooW);
2429 SetLastError(0xdeadbeef);
2430 ret = func_ptr(lcmap_invalid_flags[i],
2431 lower_case, -1, buf, sizeof(buf));
2432 ok(GetLastError() == ERROR_INVALID_FLAGS,
2433 "%s (flag %08x) unexpected error code %d\n",
2434 func_name, lcmap_invalid_flags[i], GetLastError());
2435 ok(!ret, "%s (flag %08x) should return 0, got %d\n",
2436 func_name, lcmap_invalid_flags[i], ret);
2437 }
2438
2439 /* test LCMAP_LOWERCASE */
2440 ret = func_ptr(LCMAP_LOWERCASE,
2441 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
2442 ok(ret == lstrlenW(upper_case) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
2443 ret, GetLastError(), lstrlenW(upper_case) + 1);
2444 ok(!lstrcmpW(buf, lower_case), "%s string compare mismatch\n", func_name);
2445
2446 /* test LCMAP_UPPERCASE */
2447 ret = func_ptr(LCMAP_UPPERCASE,
2448 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
2449 ok(ret == lstrlenW(lower_case) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
2450 ret, GetLastError(), lstrlenW(lower_case) + 1);
2451 ok(!lstrcmpW(buf, upper_case), "%s string compare mismatch\n", func_name);
2452
2453 /* test LCMAP_HIRAGANA */
2454 ret = func_ptr(LCMAP_HIRAGANA,
2455 japanese_text, -1, buf, sizeof(buf)/sizeof(WCHAR));
2456 ok(ret == lstrlenW(hiragana_text) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
2457 ret, GetLastError(), lstrlenW(hiragana_text) + 1);
2458 ok(!lstrcmpW(buf, hiragana_text), "%s string compare mismatch\n", func_name);
2459
2460 buf[0] = 0x30f5; /* KATAKANA LETTER SMALL KA */
2461 ret = func_ptr(LCMAP_HIRAGANA, buf, 1, buf2, 1);
2462 ok(ret == 1, "%s ret %d, error %d, expected value 1\n", func_name,
2463 ret, GetLastError());
2464 /* U+3095: HIRAGANA LETTER SMALL KA was added in Unicode 3.2 */
2465 ok(buf2[0] == 0x3095 || broken(buf2[0] == 0x30f5 /* Vista and earlier versions */),
2466 "%s expected %04x, got %04x\n", func_name, 0x3095, buf2[0]);
2467
2468 /* test LCMAP_KATAKANA | LCMAP_LOWERCASE */
2469 ret = func_ptr(LCMAP_KATAKANA | LCMAP_LOWERCASE,
2470 japanese_text, -1, buf, sizeof(buf)/sizeof(WCHAR));
2471 ok(ret == lstrlenW(katakana_text) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
2472 ret, GetLastError(), lstrlenW(katakana_text) + 1);
2473 ok(!lstrcmpW(buf, katakana_text), "%s string compare mismatch\n", func_name);
2474
2475 /* test LCMAP_FULLWIDTH */
2476 ret = func_ptr(LCMAP_FULLWIDTH,
2477 halfwidth_text, -1, buf, sizeof(buf)/sizeof(WCHAR));
2478 ok(ret == lstrlenW(japanese_text) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
2479 ret, GetLastError(), lstrlenW(japanese_text) + 1);
2480 ok(!lstrcmpW(buf, japanese_text), "%s string compare mismatch\n", func_name);
2481
2482 ret2 = func_ptr(LCMAP_FULLWIDTH, halfwidth_text, -1, NULL, 0);
2483 ok(ret == ret2, "%s ret %d, expected value %d\n", func_name, ret2, ret);
2484
2485 /* test LCMAP_FULLWIDTH | LCMAP_HIRAGANA
2486 (half-width katakana is converted into full-wdith hiragana) */
2487 ret = func_ptr(LCMAP_FULLWIDTH | LCMAP_HIRAGANA,
2488 halfwidth_text, -1, buf, sizeof(buf)/sizeof(WCHAR));
2489 ok(ret == lstrlenW(hiragana_text) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
2490 ret, GetLastError(), lstrlenW(hiragana_text) + 1);
2491 ok(!lstrcmpW(buf, hiragana_text), "%s string compare mismatch\n", func_name);
2492
2493 ret2 = func_ptr(LCMAP_FULLWIDTH | LCMAP_HIRAGANA, halfwidth_text, -1, NULL, 0);
2494 ok(ret == ret2, "%s ret %d, expected value %d\n", func_name, ret, ret2);
2495
2496 /* test LCMAP_HALFWIDTH */
2497 ret = func_ptr(LCMAP_HALFWIDTH,
2498 japanese_text, -1, buf, sizeof(buf)/sizeof(WCHAR));
2499 ok(ret == lstrlenW(halfwidth_text) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
2500 ret, GetLastError(), lstrlenW(halfwidth_text) + 1);
2501 ok(!lstrcmpW(buf, halfwidth_text), "%s string compare mismatch\n", func_name);
2502
2503 ret2 = func_ptr(LCMAP_HALFWIDTH, japanese_text, -1, NULL, 0);
2504 ok(ret == ret2, "%s ret %d, expected value %d\n", func_name, ret, ret2);
2505
2506 /* test buffer overflow */
2507 SetLastError(0xdeadbeef);
2508 ret = func_ptr(LCMAP_UPPERCASE,
2509 lower_case, -1, buf, 4);
2510 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2511 "%s should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", func_name, ret);
2512
2513 /* KATAKANA LETTER GA (U+30AC) is converted into two half-width characters.
2514 Thus, it requires two WCHARs. */
2515 buf[0] = 0x30ac;
2516 SetLastError(0xdeadbeef);
2517 ret = func_ptr(LCMAP_HALFWIDTH, buf, 1, buf2, 1);
2518 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2519 "%s should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", func_name, ret);
2520
2521 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
2522 lstrcpyW(buf, lower_case);
2523 ret = func_ptr(LCMAP_UPPERCASE,
2524 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
2525 ok(ret == lstrlenW(lower_case) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
2526 ret, GetLastError(), lstrlenW(lower_case) + 1);
2527 ok(!lstrcmpW(buf, upper_case), "%s string compare mismatch\n", func_name);
2528
2529 lstrcpyW(buf, upper_case);
2530 ret = func_ptr(LCMAP_LOWERCASE,
2531 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
2532 ok(ret == lstrlenW(upper_case) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
2533 ret, GetLastError(), lstrlenW(lower_case) + 1);
2534 ok(!lstrcmpW(buf, lower_case), "%s string compare mismatch\n", func_name);
2535
2536 /* otherwise src == dst should fail */
2537 SetLastError(0xdeadbeef);
2538 ret = func_ptr(LCMAP_SORTKEY | LCMAP_UPPERCASE,
2539 buf, 10, buf, sizeof(buf));
2540 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
2541 GetLastError() == ERROR_INVALID_PARAMETER /* Win7+ */,
2542 "%s unexpected error code %d\n", func_name, GetLastError());
2543 ok(!ret, "%s src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n", func_name);
2544
2545 /* test whether '\0' is always appended */
2546 ret = func_ptr(LCMAP_SORTKEY,
2547 upper_case, -1, buf, sizeof(buf));
2548 ok(ret, "%s func_ptr must succeed\n", func_name);
2549 ret2 = func_ptr(LCMAP_SORTKEY,
2550 upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
2551 ok(ret, "%s func_ptr must succeed\n", func_name);
2552 ok(ret == ret2, "%s lengths of sort keys must be equal\n", func_name);
2553 ok(!lstrcmpA(p_buf, p_buf2), "%s sort keys must be equal\n", func_name);
2554
2555 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
2556 ret = func_ptr(LCMAP_SORTKEY | NORM_IGNORECASE,
2557 upper_case, -1, buf, sizeof(buf));
2558 ok(ret, "%s func_ptr must succeed\n", func_name);
2559 ret2 = func_ptr(LCMAP_SORTKEY,
2560 lower_case, -1, buf2, sizeof(buf2));
2561 ok(ret2, "%s func_ptr must succeed\n", func_name);
2562 ok(ret == ret2, "%s lengths of sort keys must be equal\n", func_name);
2563 ok(!lstrcmpA(p_buf, p_buf2), "%s sort keys must be equal\n", func_name);
2564
2565 /* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
2566 results from plain LCMAP_SORTKEY on Vista */
2567
2568 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
2569 ret = func_ptr(LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
2570 lower_case, -1, buf, sizeof(buf));
2571 ok(ret, "%s func_ptr must succeed\n", func_name);
2572 ret2 = func_ptr(LCMAP_SORTKEY,
2573 symbols_stripped, -1, buf2, sizeof(buf2));
2574 ok(ret2, "%s func_ptr must succeed\n", func_name);
2575 ok(ret == ret2, "%s lengths of sort keys must be equal\n", func_name);
2576 ok(!lstrcmpA(p_buf, p_buf2), "%s sort keys must be equal\n", func_name);
2577
2578 /* test NORM_IGNORENONSPACE */
2579 lstrcpyW(buf, fooW);
2580 ret = func_ptr(NORM_IGNORENONSPACE,
2581 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
2582 ok(ret == lstrlenW(lower_case) + 1, "%s func_ptr should return %d, ret = %d\n", func_name,
2583 lstrlenW(lower_case) + 1, ret);
2584 ok(!lstrcmpW(buf, lower_case), "%s string comparison mismatch\n", func_name);
2585
2586 /* test NORM_IGNORESYMBOLS */
2587 lstrcpyW(buf, fooW);
2588 ret = func_ptr(NORM_IGNORESYMBOLS,
2589 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
2590 ok(ret == lstrlenW(symbols_stripped) + 1, "%s func_ptr should return %d, ret = %d\n", func_name,
2591 lstrlenW(symbols_stripped) + 1, ret);
2592 ok(!lstrcmpW(buf, symbols_stripped), "%s string comparison mismatch\n", func_name);
2593
2594 /* test NORM_IGNORESYMBOLS | NORM_IGNORENONSPACE */
2595 lstrcpyW(buf, fooW);
2596 ret = func_ptr(NORM_IGNORESYMBOLS | NORM_IGNORENONSPACE,
2597 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
2598 ok(ret == lstrlenW(symbols_stripped) + 1, "%s func_ptr should return %d, ret = %d\n", func_name,
2599 lstrlenW(symbols_stripped) + 1, ret);
2600 ok(!lstrcmpW(buf, symbols_stripped), "%s string comparison mismatch\n", func_name);
2601
2602 /* test srclen = 0 */
2603 SetLastError(0xdeadbeef);
2604 ret = func_ptr(0, upper_case, 0, buf, sizeof(buf)/sizeof(WCHAR));
2605 ok(!ret, "%s func_ptr should fail with srclen = 0\n", func_name);
2606 ok(GetLastError() == ERROR_INVALID_PARAMETER,
2607 "%s unexpected error code %d\n", func_name, GetLastError());
2608 }
2609
2610 static INT LCMapStringW_wrapper(DWORD flags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen)
2611 {
2612 return LCMapStringW(LOCALE_USER_DEFAULT, flags, src, srclen, dst, dstlen);
2613 }
2614
2615 static void test_LCMapStringW(void)
2616 {
2617 int ret;
2618 WCHAR buf[256];
2619
2620 trace("testing LCMapStringW\n");
2621
2622 SetLastError(0xdeadbeef);
2623 ret = LCMapStringW((LCID)-1, LCMAP_LOWERCASE, upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
2624 todo_wine {
2625 ok(!ret, "LCMapStringW should fail with bad lcid\n");
2626 ok(GetLastError() == ERROR_INVALID_PARAMETER, "unexpected error code %d\n", GetLastError());
2627 }
2628
2629 test_lcmapstring_unicode(LCMapStringW_wrapper, "LCMapStringW:");
2630 }
2631
2632 static INT LCMapStringEx_wrapper(DWORD flags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen)
2633 {
2634 return pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, flags, src, srclen, dst, dstlen, NULL, NULL, 0);
2635 }
2636
2637 static void test_LCMapStringEx(void)
2638 {
2639 int ret;
2640 WCHAR buf[256];
2641
2642 if (!pLCMapStringEx)
2643 {
2644 win_skip( "LCMapStringEx not available\n" );
2645 return;
2646 }
2647
2648 trace("testing LCMapStringEx\n");
2649
2650 SetLastError(0xdeadbeef);
2651 ret = pLCMapStringEx(invalidW, LCMAP_LOWERCASE,
2652 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), NULL, NULL, 0);
2653 todo_wine {
2654 ok(!ret, "LCMapStringEx should fail with bad locale name\n");
2655 ok(GetLastError() == ERROR_INVALID_PARAMETER, "unexpected error code %d\n", GetLastError());
2656 }
2657
2658 /* test reserved parameters */
2659 ret = pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_LOWERCASE,
2660 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), NULL, NULL, 1);
2661 ok(ret == lstrlenW(upper_case) + 1, "ret %d, error %d, expected value %d\n",
2662 ret, GetLastError(), lstrlenW(upper_case) + 1);
2663 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");