More tests for kernel NLS functions.
[wine] / dlls / kernel / tests / locale.c
1 /*
2  * Unit tests for locale functions
3  *
4  * Copyright 2002 YASAR Mehmet
5  * Copyright 2003 Dmitry Timoshkov
6  * Copyright 2003 Jon Griffiths
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  * NOTES
23  *  We must pass LOCALE_NOUSEROVERRIDE (NUO) to formatting functions so that
24  *  even when the user has overridden their default i8n settings (e.g. in
25  *  the control panel i8n page), we will still get the expected results.
26  */
27 #include <stdarg.h>
28
29 #include "wine/test.h"
30 #include "windef.h"
31 #include "wine/unicode.h"
32 #include "winbase.h"
33 #include "winerror.h"
34 #include "winnls.h"
35
36 #define eq(received, expected, label, type) \
37         ok((received) == (expected), "%s: got " type " instead of " type "\n", \
38            (label), (received), (expected))
39
40 #define BUFFER_SIZE    128
41 char GlobalBuffer[BUFFER_SIZE]; /* Buffer used by callback function */
42 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
43
44 #define EXPECT_LEN(len) ok(ret == len, "Expected Len %d, got %d\n", len, ret)
45 #define EXPECT_INVALID  ok(GetLastError() == ERROR_INVALID_PARAMETER, \
46  "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError())
47 #define EXPECT_BUFFER  ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, \
48  "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError())
49 #define EXPECT_FLAGS  ok(GetLastError() == ERROR_INVALID_FLAGS, \
50  "Expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError())
51 #define EXPECT_INVALIDFLAGS ok(GetLastError() == ERROR_INVALID_FLAGS || \
52   GetLastError() == ERROR_INVALID_PARAMETER, \
53  "Expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError())
54 #define EXPECT_VALID    ok(GetLastError() == 0, \
55  "Expected GetLastError() == 0, got %ld\n", GetLastError())
56
57 #define STRINGSA(x,y) strcpy(input, x); strcpy(Expected, y); SetLastError(0); buffer[0] = '\0'
58 #define EXPECT_LENA EXPECT_LEN(strlen(Expected)+1)
59 #define EXPECT_EQA ok(strncmp(buffer, Expected, strlen(Expected)) == 0, \
60   "Expected '%s', got '%s'", Expected, buffer)
61
62 #define STRINGSW(x,y) MultiByteToWideChar(CP_ACP,0,x,-1,input,COUNTOF(input)); \
63    MultiByteToWideChar(CP_ACP,0,y,-1,Expected,COUNTOF(Expected)); \
64    SetLastError(0); buffer[0] = '\0'
65 #define EXPECT_LENW EXPECT_LEN(strlenW(Expected)+1)
66 #define EXPECT_EQW  ok(strncmpW(buffer, Expected, strlenW(Expected)) == 0, "Bad conversion\n")
67
68 #define NUO LOCALE_NOUSEROVERRIDE
69
70 static void test_GetLocaleInfoA()
71 {
72   int ret;
73   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
74   char buffer[BUFFER_SIZE];
75
76   ok(lcid == 0x409, "wrong LCID calculated - %ld\n", lcid);
77
78   /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
79    * partially fill the buffer even if it is too short. See bug 637.
80    */
81   SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
82   ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 0);
83   ok(ret == 7 && !buffer[0], "Expected len=7, got %d\n", ret);
84
85   SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
86   ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 3);
87   EXPECT_BUFFER; EXPECT_LEN(0);
88   ok(!strcmp(buffer, "Mon"), "Expected 'Mon', got '%s'\n", buffer);
89
90   SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
91   ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 10);
92   EXPECT_VALID; EXPECT_LEN(7);
93   ok(!strcmp(buffer, "Monday"), "Expected 'Monday', got '%s'\n", buffer);
94 }
95
96 static void test_GetTimeFormatA()
97 {
98   int ret;
99   SYSTEMTIME  curtime;
100   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
101   char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
102
103   memset(&curtime, 2, sizeof(SYSTEMTIME));
104   STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
105   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
106   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
107
108   curtime.wHour = 8;
109   curtime.wMinute = 56;
110   curtime.wSecond = 13;
111   curtime.wMilliseconds = 22;
112   STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
113   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
114   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
115
116   STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficent buffer */
117   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, 2);
118   EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
119
120   STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
121   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, NULL, 0);
122   EXPECT_VALID; EXPECT_LENA;
123
124   STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
125   ret = GetTimeFormatA(lcid, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
126   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
127
128   STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
129   ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
130   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
131
132   STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
133   ret = GetTimeFormatA(lcid, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
134   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
135
136   STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
137   strcpy(Expected, "8:56 AM");
138   ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
139   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
140
141   STRINGSA("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
142   ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
143   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
144
145   STRINGSA("s1s2s3", ""); /* Duplicate tokens */
146   ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
147   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
148
149   STRINGSA("t/tt", "A/AM"); /* AM time marker */
150   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
151   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
152
153   curtime.wHour = 13;
154   STRINGSA("t/tt", "P/PM"); /* PM time marker */
155   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
156   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
157
158   STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
159   ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
160   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
161
162   STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
163   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
164   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
165
166   STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
167   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
168   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
169
170   curtime.wHour = 14; /* change this to 14 or 2pm */
171   curtime.wMinute = 5;
172   curtime.wSecond = 3;
173   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 */
174   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
175   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
176
177   curtime.wHour = 0;
178   STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
179   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
180   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
181
182   STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
183   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
184   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
185
186   /* try to convert formatting strings with more than two letters
187    * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
188    * NOTE: We expect any letter for which there is an upper case value
189    *       we should see a replacement.  For letters that DO NOT have
190    *       upper case values we should see NO REPLACEMENT.
191    */
192   curtime.wHour = 8;
193   curtime.wMinute = 56;
194   curtime.wSecond = 13;
195   curtime.wMilliseconds = 22;
196   STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
197            "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
198   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
199   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
200
201   STRINGSA("h", "text"); /* Dont write to buffer if len is 0*/
202   strcpy(buffer, "text");
203   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, 0);
204   EXPECT_VALID; EXPECT_LEN(2); EXPECT_EQA;
205
206   STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
207            "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
208   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
209   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
210
211   STRINGSA("'''", "'"); /* invalid quoted string */
212   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
213   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
214
215   /* test that msdn suggested single quotation usage works as expected */
216   STRINGSA("''''", "'"); /* single quote mark */
217   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
218   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
219
220   STRINGSA("''HHHHHH", "08"); /* Normal use */
221   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
222   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
223
224   /* and test for normal use of the single quotation mark */
225   STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
226   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
227   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
228
229   STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
230   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
231   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
232
233   STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
234   ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
235   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
236
237   curtime.wHour = 25;
238   STRINGSA("'123'tt", ""); /* Invalid time */
239   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
240   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
241
242   curtime.wHour = 12;
243   curtime.wMonth = 60; /* Invalid */
244   STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
245   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
246   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
247 }
248
249 static void test_GetDateFormatA()
250 {
251   int ret;
252   SYSTEMTIME  curtime;
253   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
254   char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
255
256   memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
257   STRINGSA("ddd',' MMM dd yy","");
258   ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
259   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
260
261   curtime.wYear = 2002;
262   curtime.wMonth = 5;
263   curtime.wDay = 4;
264   curtime.wDayOfWeek = 3;
265   STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
266   ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
267   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
268
269   STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
270   ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
271   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
272
273   curtime.wHour = 36; /* Invalid */
274   STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
275   ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
276   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
277
278   STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
279   ret = GetDateFormatA(lcid, 0, &curtime, input, NULL, 0);
280   EXPECT_VALID; EXPECT_LEN(16); EXPECT_EQA;
281
282   STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
283   ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, 2);
284   EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
285
286   STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
287   ret = GetDateFormat(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
288   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
289
290   STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
291   ret = GetDateFormat(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
292   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
293
294   /* test for expected DATE_YEARMONTH behavior with null format */
295   /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
296   STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
297   ret = GetDateFormat(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
298   EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
299
300   /* Test that using invalid DATE_* flags results in the correct error */
301   /* and return values */
302   STRINGSA("m/d/y", ""); /* Invalid flags */
303   ret = GetDateFormat(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
304                       &curtime, input, buffer, COUNTOF(buffer));
305   EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
306 }
307
308 static void test_GetDateFormatW()
309 {
310   int ret;
311   SYSTEMTIME  curtime;
312   WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
313   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
314
315   STRINGSW("",""); /* If flags is not zero then format must be NULL */
316   ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL,
317                        input, buffer, COUNTOF(buffer));
318   if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
319       return;
320   EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQW;
321
322   STRINGSW("",""); /* NULL buffer, len > 0 */
323   ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
324   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQW;
325
326   STRINGSW("",""); /* NULL buffer, len == 0 */
327   ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
328   EXPECT_VALID; EXPECT_LENW; EXPECT_EQW;
329
330   curtime.wYear = 2002;
331   curtime.wMonth = 10;
332   curtime.wDay = 23;
333   curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
334   curtime.wHour = 65432; /* Invalid */
335   curtime.wMinute = 34512; /* Invalid */
336   curtime.wSecond = 65535; /* Invalid */
337   curtime.wMilliseconds = 12345;
338   STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
339   ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
340   EXPECT_VALID; EXPECT_LENW; EXPECT_EQW;
341 }
342
343
344 #define CY_POS_LEFT  0
345 #define CY_POS_RIGHT 1
346 #define CY_POS_LEFT_SPACE  2
347 #define CY_POS_RIGHT_SPACE 3
348
349 static void test_GetCurrencyFormatA()
350 {
351   static char szDot[] = { '.', '\0' };
352   static char szComma[] = { ',', '\0' };
353   static char szDollar[] = { '$', '\0' };
354   int ret;
355   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
356   char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
357   CURRENCYFMTA format;
358
359   memset(&format, 0, sizeof(format));
360
361   STRINGSA("23",""); /* NULL output, length > 0 --> Error */
362   ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
363   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
364
365   STRINGSA("23,53",""); /* Invalid character --> Error */
366   ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
367   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
368
369   STRINGSA("--",""); /* Double '-' --> Error */
370   ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
371   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
372
373   STRINGSA("0-",""); /* Trailing '-' --> Error */
374   ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
375   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
376
377   STRINGSA("0..",""); /* Double '.' --> Error */
378   ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
379   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
380
381   STRINGSA(" 0.1",""); /* Leading space --> Error */
382   ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
383   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
384
385   STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
386   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, 2);
387   EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
388
389   STRINGSA("2353",""); /* Format and flags given --> Error */
390   ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
391   EXPECT_INVALIDFLAGS; EXPECT_LEN(0); EXPECT_EQA;
392
393   STRINGSA("2353",""); /* Invalid format --> Error */
394   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
395   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
396
397   STRINGSA("2353","$2,353.00"); /* Valid number */
398   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
399   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
400
401   STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
402   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
403   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
404
405   STRINGSA("2353.1","$2,353.10"); /* Valid real number */
406   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
407   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
408
409   STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
410   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
411   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
412
413   STRINGSA("2353.119","$2,353.12");  /* Too many DP --> Rounded */
414   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
415   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
416
417   format.NumDigits = 0; /* No decimal seperator */
418   format.LeadingZero = 0;
419   format.Grouping = 0;  /* No grouping char */
420   format.NegativeOrder = 0;
421   format.PositiveOrder = CY_POS_LEFT;
422   format.lpDecimalSep = szDot;
423   format.lpThousandSep = szComma;
424   format.lpCurrencySymbol = szDollar;
425
426   STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
427   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
428   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
429
430   format.NumDigits = 1; /* 1 DP --> Expect decimal seperator */
431   STRINGSA("2353","$2353.0");
432   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
433   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
434
435   format.Grouping = 2; /* Group by 100's */
436   STRINGSA("2353","$23,53.0");
437   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
438   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
439
440   format.LeadingZero = 1; /* Always provide leading zero */
441   STRINGSA(".5","$0.5");
442   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
443   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
444
445   format.PositiveOrder = CY_POS_RIGHT;
446   STRINGSA("1","1.0$");
447   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
448   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
449
450   format.PositiveOrder = CY_POS_LEFT_SPACE;
451   STRINGSA("1","$ 1.0");
452   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
453   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
454
455   format.PositiveOrder = CY_POS_RIGHT_SPACE;
456   STRINGSA("1","1.0 $");
457   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
458   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
459
460   format.NegativeOrder = 0;
461   STRINGSA("-1","($1.0)");
462   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
463   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
464
465   format.NegativeOrder = 1;
466   STRINGSA("-1","-$1.0");
467   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
468   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
469
470   format.NegativeOrder = 2;
471   STRINGSA("-1","$-1.0");
472   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
473   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
474
475   format.NegativeOrder = 3;
476   STRINGSA("-1","$1.0-");
477   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
478   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
479
480   format.NegativeOrder = 4;
481   STRINGSA("-1","(1.0$)");
482   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
483   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
484
485   format.NegativeOrder = 5;
486   STRINGSA("-1","-1.0$");
487   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
488   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
489
490   format.NegativeOrder = 6;
491   STRINGSA("-1","1.0-$");
492   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
493   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
494
495   format.NegativeOrder = 7;
496   STRINGSA("-1","1.0$-");
497   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
498   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
499
500   format.NegativeOrder = 8;
501   STRINGSA("-1","-1.0 $");
502   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
503   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
504
505   format.NegativeOrder = 9;
506   STRINGSA("-1","-$ 1.0");
507   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
508   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
509
510   format.NegativeOrder = 10;
511   STRINGSA("-1","1.0 $-");
512   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
513   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
514
515   format.NegativeOrder = 11;
516   STRINGSA("-1","$ 1.0-");
517   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
518   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
519
520   format.NegativeOrder = 12;
521   STRINGSA("-1","$ -1.0");
522   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
523   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
524
525   format.NegativeOrder = 13;
526   STRINGSA("-1","1.0- $");
527   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
528   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
529
530   format.NegativeOrder = 14;
531   STRINGSA("-1","($ 1.0)");
532   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
533   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
534
535   format.NegativeOrder = 15;
536   STRINGSA("-1","(1.0 $)");
537   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
538   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
539 }
540
541 #define NEG_PARENS      0 /* "(1.1)" */
542 #define NEG_LEFT        1 /* "-1.1"  */
543 #define NEG_LEFT_SPACE  2 /* "- 1.1" */
544 #define NEG_RIGHT       3 /* "1.1-"  */
545 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
546
547 static void test_GetNumberFormatA()
548 {
549   static char szDot[] = { '.', '\0' };
550   static char szComma[] = { ',', '\0' };
551   int ret;
552   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
553   char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
554   NUMBERFMTA format;
555
556   memset(&format, 0, sizeof(format));
557
558   STRINGSA("23",""); /* NULL output, length > 0 --> Error */
559   ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
560   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
561
562   STRINGSA("23,53",""); /* Invalid character --> Error */
563   ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
564   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
565
566   STRINGSA("--",""); /* Double '-' --> Error */
567   ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
568   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
569
570   STRINGSA("0-",""); /* Trailing '-' --> Error */
571   ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
572   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
573
574   STRINGSA("0..",""); /* Double '.' --> Error */
575   ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
576   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
577
578   STRINGSA(" 0.1",""); /* Leading space --> Error */
579   ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
580   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
581
582   STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
583   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, 2);
584   EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
585
586   STRINGSA("2353",""); /* Format and flags given --> Error */
587   ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
588   EXPECT_INVALIDFLAGS; EXPECT_LEN(0); EXPECT_EQA;
589
590   STRINGSA("2353",""); /* Invalid format --> Error */
591   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
592   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
593
594   STRINGSA("2353","2,353.00"); /* Valid number */
595   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
596   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
597
598   STRINGSA("-2353","-2,353.00"); /* Valid negative number */
599   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
600   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
601
602   STRINGSA("2353.1","2,353.10"); /* Valid real number */
603   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
604   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
605
606   STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
607   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
608   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
609
610   STRINGSA("2353.119","2,353.12");  /* Too many DP --> Rounded */
611   ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
612   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
613
614   format.NumDigits = 0; /* No decimal seperator */
615   format.LeadingZero = 0;
616   format.Grouping = 0;  /* No grouping char */
617   format.NegativeOrder = 0;
618   format.lpDecimalSep = szDot;
619   format.lpThousandSep = szComma;
620
621   STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
622   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
623   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
624
625   format.NumDigits = 1; /* 1 DP --> Expect decimal seperator */
626   STRINGSA("2353","2353.0");
627   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
628   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
629
630   format.Grouping = 2; /* Group by 100's */
631   STRINGSA("2353","23,53.0");
632   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
633   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
634
635   format.LeadingZero = 1; /* Always provide leading zero */
636   STRINGSA(".5","0.5");
637   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
638   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
639
640   format.NegativeOrder = NEG_PARENS;
641   STRINGSA("-1","(1.0)");
642   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
643   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
644
645   format.NegativeOrder = NEG_LEFT;
646   STRINGSA("-1","-1.0");
647   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
648   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
649
650   format.NegativeOrder = NEG_LEFT_SPACE;
651   STRINGSA("-1","- 1.0");
652   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
653   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
654
655   format.NegativeOrder = NEG_RIGHT;
656   STRINGSA("-1","1.0-");
657   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
658   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
659
660   format.NegativeOrder = NEG_RIGHT_SPACE;
661   STRINGSA("-1","1.0 -");
662   ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
663   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
664
665   lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
666
667   if (IsValidLocale(lcid, 0))
668   {
669     STRINGSA("-12345","-12 345,00"); /* Try French formatting */
670     Expected[3] = 160; /* Non breaking space */
671     ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
672     EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
673   }
674 }
675
676
677 /* Callback function used by TestEnumTimeFormats */
678 static BOOL CALLBACK EnumTimeFormatsProc(char * lpTimeFormatString)
679 {
680   trace("%s\n", lpTimeFormatString);
681   strcpy(GlobalBuffer, lpTimeFormatString);
682 #if 0
683   return TRUE;
684 #endif
685   return FALSE;
686 }
687
688 void test_EnumTimeFormats()
689 {
690   int ret;
691   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
692
693   GlobalBuffer[0] = '\0';
694   ret = EnumTimeFormatsA(EnumTimeFormatsProc, lcid, 0);
695   ok (ret == 1 && !strcmp(GlobalBuffer,"h:mm:ss tt"), "Expected %d '%s'\n", ret, GlobalBuffer);
696 }
697
698 static void test_CompareStringA()
699 {
700   int ret;
701   LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
702
703   ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
704   ok (ret== 1, "(Salut/Salute) Expected 1, got %d\n", ret);
705
706   ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
707   ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
708
709   ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
710   ok (ret== 3, "(Salut/hola) Expected 3, got %d\n", ret);
711
712   ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
713   ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
714
715   lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
716
717   ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
718   ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
719
720   ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
721   ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
722
723   ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "SaLuT", -1);
724   ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
725 }
726
727 void test_LCMapStringA(void)
728 {
729     int ret, ret2;
730     char buf[256], buf2[256];
731     static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
732     static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
733     static const char symbols_stripped[] = "justateststring1";
734
735     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
736                        upper_case, -1, buf, sizeof(buf));
737     ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
738     ok(GetLastError() == ERROR_INVALID_FLAGS,
739        "unexpected error code %ld\n", GetLastError());
740
741     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
742                        upper_case, -1, buf, sizeof(buf));
743     ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
744     ok(GetLastError() == ERROR_INVALID_FLAGS,
745        "unexpected error code %ld\n", GetLastError());
746
747     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
748
749                        upper_case, -1, buf, sizeof(buf));
750     ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
751     ok(GetLastError() == ERROR_INVALID_FLAGS,
752        "unexpected error code %ld\n", GetLastError());
753
754     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
755                        upper_case, -1, buf, sizeof(buf));
756     ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
757     ok(GetLastError() == ERROR_INVALID_FLAGS,
758        "unexpected error code %ld\n", GetLastError());
759
760     /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
761     SetLastError(0xdeadbeef);
762     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
763                        upper_case, -1, buf, sizeof(buf));
764     ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError());
765     ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
766
767     /* test LCMAP_LOWERCASE */
768     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
769                        upper_case, -1, buf, sizeof(buf));
770     ok(ret == lstrlenA(upper_case) + 1,
771        "ret %d, error %ld, expected value %d\n",
772        ret, GetLastError(), lstrlenA(upper_case) + 1);
773     ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
774
775     /* test LCMAP_UPPERCASE */
776     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
777                        lower_case, -1, buf, sizeof(buf));
778     ok(ret == lstrlenA(lower_case) + 1,
779        "ret %d, error %ld, expected value %d\n",
780        ret, GetLastError(), lstrlenA(lower_case) + 1);
781     ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
782
783     /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
784     lstrcpyA(buf, lower_case);
785     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
786                        buf, -1, buf, sizeof(buf));
787     if (!ret) /* Win9x */
788         trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
789     else
790     {
791         ok(ret == lstrlenA(lower_case) + 1,
792            "ret %d, error %ld, expected value %d\n",
793            ret, GetLastError(), lstrlenA(lower_case) + 1);
794         ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
795     }
796     lstrcpyA(buf, upper_case);
797     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
798                        buf, -1, buf, sizeof(buf));
799     if (!ret) /* Win9x */
800         trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
801     else
802     {
803         ok(ret == lstrlenA(upper_case) + 1,
804            "ret %d, error %ld, expected value %d\n",
805            ret, GetLastError(), lstrlenA(lower_case) + 1);
806         ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
807     }
808
809     /* otherwise src == dst should fail */
810     SetLastError(0xdeadbeef);
811     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
812                        buf, 10, buf, sizeof(buf));
813     ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
814        GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
815        "unexpected error code %ld\n", GetLastError());
816     ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
817
818     /* test whether '\0' is always appended */
819     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
820                        upper_case, -1, buf, sizeof(buf));
821     ok(ret, "LCMapStringA must succeed\n");
822     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
823                        upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
824     ok(ret, "LCMapStringA must succeed\n");
825     ok(ret == ret2, "lengths of sort keys must be equal\n");
826     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
827
828     /* test LCMAP_SORTKEY | NORM_IGNORECASE */
829     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
830                        upper_case, -1, buf, sizeof(buf));
831     ok(ret, "LCMapStringA must succeed\n");
832     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
833                        lower_case, -1, buf2, sizeof(buf2));
834     ok(ret2, "LCMapStringA must succeed\n");
835     ok(ret == ret2, "lengths of sort keys must be equal\n");
836     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
837
838     /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
839     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
840                        lower_case, -1, buf, sizeof(buf));
841     ok(ret, "LCMapStringA must succeed\n");
842     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
843                        lower_case, -1, buf2, sizeof(buf2));
844     ok(ret2, "LCMapStringA must succeed\n");
845     ok(ret == ret2, "lengths of sort keys must be equal\n");
846     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
847
848     /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
849     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
850                        lower_case, -1, buf, sizeof(buf));
851     ok(ret, "LCMapStringA must succeed\n");
852     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
853                        symbols_stripped, -1, buf2, sizeof(buf2));
854     ok(ret2, "LCMapStringA must succeed\n");
855     ok(ret == ret2, "lengths of sort keys must be equal\n");
856     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
857
858     /* test NORM_IGNORENONSPACE */
859     lstrcpyA(buf, "foo");
860     ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
861                        lower_case, -1, buf, sizeof(buf));
862     ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
863         lstrlenA(lower_case) + 1, ret);
864     ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
865
866     /* test NORM_IGNORESYMBOLS */
867     lstrcpyA(buf, "foo");
868     ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
869                        lower_case, -1, buf, sizeof(buf));
870     ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
871         lstrlenA(symbols_stripped) + 1, ret);
872     ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
873 }
874
875 void test_LCMapStringW(void)
876 {
877     int ret, ret2;
878     WCHAR buf[256], buf2[256];
879     char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
880     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};
881     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};
882     static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
883     static const WCHAR fooW[] = {'f','o','o',0};
884
885     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
886                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
887     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
888     {
889         trace("Skipping LCMapStringW tests on Win9x\n");
890         return;
891     }
892     ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
893     ok(GetLastError() == ERROR_INVALID_FLAGS,
894        "unexpected error code %ld\n", GetLastError());
895
896     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
897                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
898     ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
899     ok(GetLastError() == ERROR_INVALID_FLAGS,
900        "unexpected error code %ld\n", GetLastError());
901
902     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
903                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
904     ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
905     ok(GetLastError() == ERROR_INVALID_FLAGS,
906        "unexpected error code %ld\n", GetLastError());
907
908     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
909                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
910     ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
911     ok(GetLastError() == ERROR_INVALID_FLAGS,
912        "unexpected error code %ld\n", GetLastError());
913
914     /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
915     SetLastError(0xdeadbeef);
916     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
917                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
918     ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError());
919     ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
920
921     /* test LCMAP_LOWERCASE */
922     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
923                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
924     ok(ret == lstrlenW(upper_case) + 1,
925        "ret %d, error %ld, expected value %d\n",
926        ret, GetLastError(), lstrlenW(upper_case) + 1);
927     ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
928
929     /* test LCMAP_UPPERCASE */
930     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
931                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
932     ok(ret == lstrlenW(lower_case) + 1,
933        "ret %d, error %ld, expected value %d\n",
934        ret, GetLastError(), lstrlenW(lower_case) + 1);
935     ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
936
937     /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
938     lstrcpyW(buf, lower_case);
939     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
940                        buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
941     ok(ret == lstrlenW(lower_case) + 1,
942        "ret %d, error %ld, expected value %d\n",
943        ret, GetLastError(), lstrlenW(lower_case) + 1);
944     ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
945
946     lstrcpyW(buf, upper_case);
947     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
948                        buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
949     ok(ret == lstrlenW(upper_case) + 1,
950        "ret %d, error %ld, expected value %d\n",
951        ret, GetLastError(), lstrlenW(lower_case) + 1);
952     ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
953
954     /* otherwise src == dst should fail */
955     SetLastError(0xdeadbeef);
956     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
957                        buf, 10, buf, sizeof(buf));
958     ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
959        GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
960        "unexpected error code %ld\n", GetLastError());
961     ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
962
963     /* test whether '\0' is always appended */
964     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
965                        upper_case, -1, buf, sizeof(buf));
966     ok(ret, "LCMapStringW must succeed\n");
967     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
968                        upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
969     ok(ret, "LCMapStringW must succeed\n");
970     ok(ret == ret2, "lengths of sort keys must be equal\n");
971     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
972
973     /* test LCMAP_SORTKEY | NORM_IGNORECASE */
974     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
975                        upper_case, -1, buf, sizeof(buf));
976     ok(ret, "LCMapStringW must succeed\n");
977     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
978                        lower_case, -1, buf2, sizeof(buf2));
979     ok(ret2, "LCMapStringW must succeed\n");
980     ok(ret == ret2, "lengths of sort keys must be equal\n");
981     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
982
983     /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
984     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
985                        lower_case, -1, buf, sizeof(buf));
986     ok(ret, "LCMapStringW must succeed\n");
987     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
988                        lower_case, -1, buf2, sizeof(buf2));
989     ok(ret2, "LCMapStringW must succeed\n");
990     ok(ret == ret2, "lengths of sort keys must be equal\n");
991     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
992
993     /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
994     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
995                        lower_case, -1, buf, sizeof(buf));
996     ok(ret, "LCMapStringW must succeed\n");
997     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
998                        symbols_stripped, -1, buf2, sizeof(buf2));
999     ok(ret2, "LCMapStringW must succeed\n");
1000     ok(ret == ret2, "lengths of sort keys must be equal\n");
1001     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1002
1003     /* test NORM_IGNORENONSPACE */
1004     lstrcpyW(buf, fooW);
1005     ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1006                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1007     ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1008         lstrlenW(lower_case) + 1, ret);
1009     ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1010
1011     /* test NORM_IGNORESYMBOLS */
1012     lstrcpyW(buf, fooW);
1013     ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1014                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1015     ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1016         lstrlenW(symbols_stripped) + 1, ret);
1017     ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1018 }
1019
1020 START_TEST(locale)
1021 {
1022 #if 0
1023   test_EnumTimeFormats();
1024 #endif
1025   test_GetLocaleInfoA();
1026   test_GetTimeFormatA();
1027   test_GetDateFormatA();
1028   test_GetDateFormatW();
1029   test_GetCurrencyFormatA(); /* Also tests the W version */
1030   test_GetNumberFormatA();   /* Also tests the W version */
1031   test_CompareStringA();
1032   test_LCMapStringA();
1033   test_LCMapStringW();
1034 }