Modify winetest_ok to only add a trailing '\n' if there is none.
[wine] / dlls / kernel / tests / locale.c
1 /*
2  * Very basic unit test for locale functions
3  * Test run on win2K (French)
4  *
5  * Copyright (c) 2002 YASAR Mehmet
6  * Copyright 2003 Dmitry Timoshkov
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
23 #include <stdarg.h>
24
25 #include "wine/test.h"
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winerror.h"
29 #include "winnls.h"
30
31 #define eq(received, expected, label, type) \
32         ok((received) == (expected), "%s: got " type " instead of " type "\n", (label),(received),(expected))
33
34 #define BUFFER_SIZE             128
35 /* Buffer used by callback function */
36 char GlobalBuffer[BUFFER_SIZE];
37 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
38
39 /* TODO :
40  * Unicode versions
41  * EnumTimeFormatsA
42  * EnumDateFormatsA
43  * LCMapStringA
44  * GetUserDefaultLangID
45  * ...
46  */
47
48 void TestGetLocaleInfoA()
49 {
50         int ret, cmp;
51         LCID lcid;
52         char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE];
53
54         strcpy(Expected, "Monday");
55         lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT );
56         ok (lcid == 0x409, "wrong LCID calculated");
57
58         /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
59         * partially fill the buffer even if it is too short. See bug 637.
60         */
61         strcpy(Expected, "xxxxx");
62         memset( buffer, 'x', sizeof(buffer) );
63         ret = GetLocaleInfoA(lcid, LOCALE_SDAYNAME1, buffer, 0);
64         cmp = strncmp (buffer, Expected, strlen(Expected));
65         ok (cmp == 0, "GetLocaleInfoA got %s instead of %s", buffer, Expected);
66         eq (ret, lstrlenA("Monday") + 1, "GetLocaleInfoA with len=0", "%d");
67
68         strcpy(Expected, "Monxx");
69         memset( buffer, 'x', sizeof(buffer) );
70         ret = GetLocaleInfoA(lcid, LOCALE_SDAYNAME1, buffer, 3);
71         cmp = strncmp (buffer, Expected, strlen(Expected));
72         ok (cmp == 0, "GetLocaleInfoA got %s instead of %s", buffer, Expected);
73         eq (ret, 0, "GetLocaleInfoA with len = 3", "%d");
74
75         strcpy(Expected, "Monday");
76         memset( buffer, 'x', sizeof(buffer) );
77         ret = GetLocaleInfoA(lcid, LOCALE_SDAYNAME1, buffer, 10);
78         /* We check also presence of '\0' */
79         cmp = strncmp (buffer, Expected, strlen(Expected) + 1);
80         ok (cmp == 0, "GetLocaleInfoA got %s instead of %s", buffer, Expected);
81         eq (ret, lstrlenA(Expected)+1, "GetLocaleInfoA with len = 10", "%d" );
82
83         /* We check the whole buffer with strncmp */
84         memset( Expected, 'x', sizeof(Expected) );
85         strcpy(Expected, "Monday");
86         memset( buffer, 'x', sizeof(buffer) );
87         ret = GetLocaleInfoA(lcid, LOCALE_SDAYNAME1, buffer, BUFFER_SIZE);
88         cmp = strncmp (buffer, Expected, BUFFER_SIZE);
89         ok (cmp == 0, "GetLocaleInfoA got %s instead of %s", buffer, Expected);
90         eq (ret, lstrlenA(Expected)+1, "GetLocaleInfoA with len = 10", "%d" );
91
92 }
93
94
95 void TestGetTimeFormatA()
96 {
97   int ret, error, cmp;
98   SYSTEMTIME  curtime;
99   char buffer[BUFFER_SIZE], format[BUFFER_SIZE], Expected[BUFFER_SIZE];
100   LCID lcid;
101
102   lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT );
103   strcpy(format, "tt HH':'mm'@'ss");
104
105   /* fill curtime with dummy data */
106   memset(&curtime, 2, sizeof(SYSTEMTIME));
107   memset(buffer, '0', sizeof(buffer));
108   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, format, buffer, COUNTOF(buffer));
109   error = GetLastError ();
110   ok (ret == 0, "GetTimeFormat should fail on dummy data");
111   eq (error, ERROR_INVALID_PARAMETER, "GetTimeFormat GetLastError()", "%d");
112   SetLastError(NO_ERROR);   /* clear out the last error */
113
114   /* test that we can correctly produce the expected output, not a very */
115   /* demanding test ;-) */
116   strcpy(Expected, "AM 08:56@13");
117   curtime.wHour = 8;  curtime.wMinute = 56;
118   curtime.wSecond = 13; curtime.wMilliseconds = 22;
119   memset(buffer, '0', sizeof(buffer));
120   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, format, buffer, COUNTOF(buffer));
121   cmp = strncmp (Expected, buffer, strlen(Expected)+1);
122   ok (cmp == 0, "GetTimeFormat got %s instead of %s", buffer, Expected);
123   eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
124
125   /* check that the size reported by the above call is accuate */
126   memset(buffer, 'x', sizeof(buffer));
127   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, format, buffer, ret);
128   ok(ret==lstrlenA(Expected)+1 && GetLastError()==0,
129            "GetTimeFormat(right size): ret=%d error=%ld\n",ret,GetLastError());
130   ok(buffer[0] != 'x',"GetTimeFormat(right size): buffer=[%s]\n",buffer);
131
132   /* test failure due to insufficent buffer */
133   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, format, buffer, 2);
134   ok(ret==0 && GetLastError()==ERROR_INSUFFICIENT_BUFFER,
135            "GetTimeFormat(len=2): ret=%d error=%ld", ret, GetLastError());
136
137   /* test with too small buffers */
138   SetLastError(0);
139   memset(buffer, '0', sizeof(buffer));
140   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, format, NULL, 0);
141   ok(ret==lstrlenA(Expected)+1 && GetLastError()==0,
142            "GetTimeFormat(len=0): ret=%d error=%ld\n",ret,GetLastError());
143
144   /************************************/
145   /* test out TIME_NOMINUTESORSECONDS */
146   strcpy(Expected, "8 AM");
147   memset(buffer, '0', sizeof(buffer));
148   ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, sizeof(buffer));
149   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
150   ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
151   eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
152
153   /* test out TIME_NOMINUTESORSECONDS with complex format strings */
154   strcpy(Expected, "4");
155   memset(buffer, '0', sizeof(buffer));
156   ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, "m1s2m3s4", buffer, sizeof(buffer));
157   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
158   ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
159   eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
160
161
162   /************************************/
163   /* test out TIME_NOSECONDS */
164   strcpy(Expected, "8:56 AM");
165   ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, NULL, buffer, sizeof(buffer));
166   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
167   ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
168   eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
169
170   /* test out TIME_NOSECONDS with a format string of "h:m:s tt" */
171   strcpy(Expected, "8:56 AM");
172   memset(buffer, '0', sizeof(buffer));
173   ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, "h:m:s tt", buffer, sizeof(buffer));
174   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
175   ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
176   eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
177
178   /* test out TIME_NOSECONDS a strange format string of multiple delimiters "h@:m@:s tt" */
179   /* expected behavior is to turn "hD1D2...mD3D4...sD5D6...tt" and turn this into */
180   /* "hD1D2...mD3D4...tt" */
181   strcpy(Expected, "8.@:56.@:AM");
182   memset(buffer, '0', sizeof(buffer));
183   ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, "h.@:m.@:s.@:tt", buffer, sizeof(buffer));
184   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
185   ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
186   eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
187
188   /* test out TIME_NOSECONDS with an string of "1s2s3s4" */
189   /* expect to see only "3" */
190   strcpy(Expected, "3");
191   memset(buffer, '0', sizeof(buffer));
192   ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, "s1s2s3", buffer, sizeof(buffer));
193   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
194   ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
195   eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
196
197   /************************/
198   /* Test out time marker */
199   /* test out time marker(AM/PM) behavior */
200   strcpy(Expected, "A/AM");
201   memset(buffer, '0', sizeof(buffer));
202   ret = GetTimeFormatA(lcid, 0, &curtime, "t/tt", buffer, sizeof(buffer));
203   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
204   ok (cmp == 0, "GetTimeFormat got '%s' instead of %s", buffer, Expected);
205   eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
206
207   /* time marker testing part 2 */
208   curtime.wHour = 13;
209   strcpy(Expected, "P/PM");
210   memset(buffer, '0', sizeof(buffer));
211   ret = GetTimeFormatA(lcid, 0, &curtime, "t/tt", buffer, sizeof(buffer));
212   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
213   ok (cmp == 0, "GetTimeFormat got '%s' instead of %s", buffer, Expected);
214   eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
215
216   /******************************/
217   /* test out TIME_NOTIMEMARKER */
218   /* NOTE: TIME_NOTIMEMARKER elminates all text around any time marker */
219   /*      formatting character until the previous or next formatting character */
220   strcpy(Expected, "156");
221   memset(buffer, '0', sizeof(buffer));
222   ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, "h1t2tt3m", buffer, sizeof(buffer));
223   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
224   ok (cmp == 0, "GetTimeFormat got '%s' instead of %s", buffer, Expected);
225   eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
226
227   /***********************************/
228   /* test out TIME_FORCE24HOURFORMAT */
229   strcpy(Expected, "13:56:13 PM");
230   memset(buffer, '0', sizeof(buffer));
231   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, "h:m:s tt", buffer, sizeof(buffer));
232   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
233   ok (cmp == 0, "GetTimeFormat got '%s' instead of %s", buffer, Expected);
234   eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
235
236   /* check to confirm that unlike what msdn documentation suggests, the time marker */
237   /* is not added under TIME_FORCE24HOURFORMAT */
238   strcpy(Expected, "13:56:13");
239   memset(buffer, '0', sizeof(buffer));
240   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, "h:m:s", buffer, sizeof(buffer));
241   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
242   ok (cmp == 0, "GetTimeFormat got '%s' instead of %s", buffer, Expected);
243   eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
244
245
246   /*********************************************/
247   /* test advanced formatting of GetTimeFormat */
248
249   /* test for 24 hour conversion and for leading zero */
250   /* NOTE: we do not test the "hh or HH" case since hours is two digits */
251   /* "h hh H HH m mm s ss t tt" */
252   curtime.wHour = 14; /* change this to 14 or 2pm */
253   curtime.wMinute = 5;
254   curtime.wSecond = 3;
255   strcpy(Expected, "2 02 14 14 5 05 3 03 P PM");
256   memset(buffer, '0', sizeof(buffer));
257   ret = GetTimeFormatA(lcid, 0, &curtime, "h hh H HH m mm s ss t tt", 
258 buffer, sizeof(buffer));
259   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
260   ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
261   eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
262
263   /* complete testing on the advanced formatting by testing "hh" and "HH" */
264   /* 0 hour is 12 o'clock or 00 hundred hours */
265   curtime.wHour = 0;
266   strcpy(Expected, "12/0/12/00");
267   memset(buffer, '0', sizeof(buffer));
268   ret = GetTimeFormatA(lcid, 0, &curtime, "h/H/hh/HH", buffer, sizeof(buffer));
269   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
270   ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
271   eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
272
273   /* test for LOCALE_NOUSEROVERRIDE set, lpFormat must be NULL */
274   strcpy(Expected, "0:5:3 AM");
275   memset(buffer, '0', sizeof(buffer));
276   ret = GetTimeFormatA(lcid, LOCALE_NOUSEROVERRIDE, &curtime, "h:m:s tt", buffer, sizeof(buffer));
277   /* NOTE: we expect this to FAIL */
278   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
279   ok (ret == 0, "GetTimeFormat succeeded instead of failing for LOCALE_NOUSEROVERRIDE and a non-null lpFormat\n");
280
281   /* try to convert formatting strings with more than two letters */
282   /* "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS" */
283   /* NOTE: we expect any letter for which there is an upper case value */
284   /*    we should expect to see a replacement.  For letters that DO NOT */
285   /*    have upper case values we expect to see NO REPLACEMENT */
286   curtime.wHour = 8;  curtime.wMinute = 56;
287   curtime.wSecond = 13; curtime.wMilliseconds = 22;
288   strcpy(Expected, "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
289   memset(buffer, '0', sizeof(buffer));
290   ret = GetTimeFormatA(lcid, 0, &curtime, "h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS", buffer, sizeof(buffer));
291   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
292   ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
293   eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
294
295   /* test that if the size of the buffer is zero that the buffer is not modified */
296   /* and that the number of necessary characters is returned */
297   /* NOTE: The count includes the terminating null. */
298   strcpy(buffer, "THIS SHOULD NOT BE MODIFIED");
299   strcpy(Expected, "THIS SHOULD NOT BE MODIFIED");
300   ret = GetTimeFormatA(lcid, 0, &curtime, "h", buffer, 0);
301   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
302   ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
303   eq (ret, 2, "GetTimeFormat", "%d"); /* we expect to require two characters of space from "h" */
304
305   /* test that characters in single quotation marks are ignored and left in */
306   /* the same location in the output string */
307   strcpy(Expected, "8 h 8 H 08 HH 56 m 13 s A t AM tt");
308   memset(buffer, '0', sizeof(buffer));
309   ret = GetTimeFormatA(lcid, 0, &curtime, "h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'", buffer, sizeof(buffer));
310   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
311   ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
312   eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
313
314   /* test the printing of the single quotation marks when */
315   /* we use an invalid formatting string of "'''" instead of "''''" */
316   strcpy(Expected, "'");
317   memset(buffer, '0', sizeof(buffer));
318   ret = GetTimeFormatA(lcid, 0, &curtime, "'''", buffer, sizeof(buffer));
319   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
320   ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
321   eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
322
323   /* test that msdn suggested single quotation usage works as expected */
324   strcpy(Expected, "'");
325   memset(buffer, '0', sizeof(buffer));
326   ret = GetTimeFormatA(lcid, 0, &curtime, "''''", buffer, sizeof(buffer));
327   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
328   ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
329   eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
330
331   /* test for more normal use of single quotation mark */
332   strcpy(Expected, "08");
333   memset(buffer, '0', sizeof(buffer));
334   ret = GetTimeFormatA(lcid, 0, &curtime, "''HHHHHH", buffer, sizeof(buffer));
335   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
336   ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
337   eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
338
339   /* and test for normal use of the single quotation mark */
340   strcpy(Expected, "'HHHHHH");
341   memset(buffer, '0', sizeof(buffer));
342   ret = GetTimeFormatA(lcid, 0, &curtime, "'''HHHHHH'", buffer, sizeof(buffer));
343   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
344   ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
345   eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
346
347   /* test for more odd use of the single quotation mark */
348   strcpy(Expected, "'HHHHHH");
349   memset(buffer, '0', sizeof(buffer));
350   ret = GetTimeFormatA(lcid, 0, &curtime, "'''HHHHHH", buffer, sizeof(buffer));
351   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
352   ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
353   eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
354
355   /* test that with TIME_NOTIMEMARKER that even if something is defined */
356   /* as a literal we drop it before and after the markers until the next */
357   /* formatting character */
358   strcpy(Expected, "");
359   memset(buffer, '0', sizeof(buffer));
360   ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, "'123'tt", buffer, sizeof(buffer));
361   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
362   ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
363   eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
364
365   /* test for expected return and error value when we have a */
366   /* non-null format and LOCALE_NOUSEROVERRIDE for flags */
367   SetLastError(NO_ERROR); /* reset last error value */
368   memset(buffer, '0', sizeof(buffer));
369   ret = GetTimeFormatA(lcid, LOCALE_NOUSEROVERRIDE, &curtime, "'123'tt", buffer, sizeof(buffer));
370   error = GetLastError();
371   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
372   ok ((ret == 0) && (error == ERROR_INVALID_FLAGS), "GetTimeFormat got ret of '%d' and error of '%d'", ret, error);
373
374   /* test that invalid time values result in ERROR_INVALID_PARAMETER */
375   /* and a return value of 0 */
376   curtime.wHour = 25;
377   SetLastError(NO_ERROR); /* reset last error value */
378   memset(buffer, '0', sizeof(buffer));
379   ret = GetTimeFormatA(lcid, 0, &curtime, "'123'tt", buffer, sizeof(buffer));
380   error = GetLastError();
381   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
382   ok ((ret == 0) && (error == ERROR_INVALID_PARAMETER), "GetTimeFormat got ret of '%d' and error of '%d'", ret, error);
383
384   /* test that invalid information in the date section of the current time */
385   /* doesn't result in an error since GetTimeFormat() should ignore this information */
386   curtime.wHour = 12; /* valid wHour */
387   curtime.wMonth = 60; /* very invalid wMonth */
388   strcpy(Expected, "12:56:13");
389   SetLastError(NO_ERROR); /* reset last error value */
390   ret = GetTimeFormatA(lcid, 0, &curtime, "h:m:s", buffer, sizeof(buffer));
391   error = GetLastError();
392   cmp = strncmp(buffer, Expected, BUFFER_SIZE);
393   ok ((ret == lstrlenA(Expected)+1) && (error == NO_ERROR), "GetTimeFormat got ret of '%d' and error of '%d' and a buffer of '%s'", ret, error, buffer);
394 }
395
396 void TestGetDateFormatA()
397 {
398   int ret, error, cmp;
399   SYSTEMTIME  curtime;
400   char buffer[BUFFER_SIZE], format[BUFFER_SIZE], Expected[BUFFER_SIZE];
401   LCID lcid;
402
403   lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT );
404   strcpy(format, "ddd',' MMM dd yy");
405
406   /* test for failure on dummy data */
407   memset(&curtime, 2, sizeof(SYSTEMTIME));
408   memset(buffer, '0', sizeof(buffer));
409   SetLastError(NO_ERROR);
410   ret = GetDateFormatA(lcid, 0, &curtime, format, buffer, COUNTOF(buffer));
411   error = GetLastError ();
412   ok(ret == 0, "GetDateFormat should fail on dummy data");
413   eq(error, ERROR_INVALID_PARAMETER, "GetDateFormat", "%d");
414
415   /* test for a simple case of date conversion */
416   strcpy(Expected, "Sat, May 04 02");
417   curtime.wYear = 2002;
418   curtime.wMonth = 5;
419   curtime.wDay = 4;
420   curtime.wDayOfWeek = 3;
421   memset(buffer, 0, sizeof(buffer));
422   ret = GetDateFormatA(lcid, 0, &curtime, format, buffer, COUNTOF(buffer));
423   cmp = strncmp (Expected, buffer, strlen(Expected)+1);
424   ok (cmp == 0, "GetDateFormat got %s instead of %s", buffer, Expected);
425   eq (ret, lstrlenA(Expected)+1, "GetDateFormat", "%d");
426
427   /* test format with "'" */
428   strcpy(format, "ddd',' MMM dd ''''yy");
429   strcpy(Expected, "Sat, May 04 '02");
430   memset(buffer, 0, sizeof(buffer));
431   ret = GetDateFormatA(lcid, 0, &curtime, format, buffer, COUNTOF(buffer));
432   cmp = strncmp (Expected, buffer, strlen(Expected)+1);
433   ok (cmp == 0, "GetDateFormat got %s instead of %s", buffer, Expected);
434   eq (ret, lstrlenA(Expected)+1, "GetDateFormat", "%d");
435
436   /* test for success with dummy time data */
437   curtime.wHour = 36;
438   memset(buffer, 0, sizeof(buffer));
439   ret = GetDateFormatA(lcid, 0, &curtime, format, buffer, COUNTOF(buffer));
440   cmp = strncmp (Expected, buffer, strlen(Expected)+1);
441   ok (cmp == 0, "GetDateFormat got %s instead of %s", buffer, Expected);
442   eq (ret, lstrlenA(Expected)+1, "GetDateFormat", "%d");
443
444   /* test that we retrieve the expected size for the necessary output of this string */
445   SetLastError(NO_ERROR);
446   memset(buffer, 0, sizeof(buffer));
447   ret = GetDateFormatA(lcid, 0, &curtime, format, NULL, 0);
448   ok(ret==lstrlenA(Expected)+1 && GetLastError() == 0,
449           "GetDateFormat(len=0): ret=%d error=%ld buffer='%s', expected NO_ERROR(0)\n",ret,GetLastError(), buffer);
450
451   /* test that the expected size matches the actual required size by passing */
452   /* in the expected size */
453   memset(buffer, '0', sizeof(buffer));
454   ret = GetDateFormatA(lcid, 0, &curtime, format, buffer, ret);
455   ok(ret==lstrlenA(Expected)+1 && GetLastError()==0,
456            "GetDateFormat(right size): ret=%d error=%ld, buffer = '%s'\n",ret,GetLastError(), buffer);
457   ok(buffer[0]!='x',"GetDateFormat(right size): buffer=[%s]\n",buffer);
458
459   /* test that a buffer shorter than the necessary size results in ERROR_INSUFFICIENT_BUFFER */
460   ret = GetDateFormatA(lcid, 0, &curtime, format, buffer, 2);
461   ok(ret==0 && GetLastError()==ERROR_INSUFFICIENT_BUFFER,
462            "GetDateFormat(len=2): ret=%d error=%ld", ret, GetLastError());
463
464   /* test for default behavior being DATE_SHORTDATE */
465   todo_wine {
466     strcpy(Expected, "5/4/02");
467     memset(buffer, '0', sizeof(buffer));
468     ret = GetDateFormat(lcid, 0, &curtime, NULL, buffer, sizeof(buffer));
469     cmp = strncmp (Expected, buffer, strlen(Expected)+1);
470     ok (cmp == 0, "GetDateFormat got '%s' instead of '%s'", buffer, Expected);
471     eq (ret, lstrlenA(Expected)+1, "GetDateFormat", "%d");
472   }
473
474
475   /* test for expected DATE_LONGDATE behavior with null format */
476   strcpy(Expected, "Saturday, May 04, 2002");
477   memset(buffer, '0', sizeof(buffer));
478   ret = GetDateFormat(lcid, DATE_LONGDATE, &curtime, NULL, buffer, sizeof(buffer));
479   cmp = strncmp (Expected, buffer, strlen(Expected)+1);
480   ok (cmp == 0, "GetDateFormat got '%s' instead of '%s'", buffer, Expected);
481   eq (ret, lstrlenA(Expected)+1, "GetDateFormat", "%d");
482
483   /* test for expected DATE_YEARMONTH behavior with null format */
484   /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
485   todo_wine {
486     strcpy(Expected, "");
487     buffer[0] = 0;
488     SetLastError(NO_ERROR);
489     memset(buffer, '0', sizeof(buffer));
490     ret = GetDateFormat(lcid, DATE_YEARMONTH, &curtime, NULL, buffer, sizeof(buffer));
491     error = GetLastError();
492     cmp = strncmp (Expected, buffer, strlen(Expected)+1);
493     ok (ret == 0 && (error == ERROR_INVALID_FLAGS), "GetDateFormat check DATE_YEARMONTH with null format expected ERROR_INVALID_FLAGS got return of '%d' and error of '%d'", ret, error);
494   }
495
496   /* Test that using invalid DATE_* flags results in the correct error */
497   /* and return values */
498   strcpy(format, "m/d/y");
499   strcpy(Expected, "Saturday May 2002");
500   SetLastError(NO_ERROR);
501   memset(buffer, '0', sizeof(buffer));
502   ret = GetDateFormat(lcid, DATE_YEARMONTH | DATE_SHORTDATE | DATE_LONGDATE, &curtime, format, buffer, sizeof(buffer));
503   error = GetLastError();
504   cmp = strncmp (Expected, buffer, strlen(Expected)+1);
505   ok ((ret == 0) && (error == ERROR_INVALID_FLAGS), "GetDateFormat checking for mutually exclusive flags got '%s' instead of '%s', got error of %d, expected ERROR_INVALID_FLAGS", buffer, Expected, error);
506 }
507
508 void TestGetDateFormatW()
509 {
510     int ret, error, cmp;
511     SYSTEMTIME  curtime;
512     WCHAR buffer[BUFFER_SIZE], format[BUFFER_SIZE], Expected[BUFFER_SIZE];
513     LCID lcid;
514
515     lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT );
516
517     /* 1. Error cases */
518
519     /* 1a If flags is not zero then format must be null. */
520     ret = GetDateFormatW (LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL, format, buffer, COUNTOF(buffer));
521     if (ret==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
522         return;
523     error = ret ? 0 : GetLastError();
524     ok (ret == 0 && error == ERROR_INVALID_FLAGS, "GetDateFormatW allowed flags and format");
525
526     /* 1b The buffer can only be null if the count is zero */
527     /* For the record other bad pointers result in a page fault (Win98) */
528     ret = GetDateFormatW (lcid, 0, NULL, format, NULL, COUNTOF(buffer));
529     error = ret ? 0 : GetLastError();
530     ok (ret == 0 && error == ERROR_INVALID_PARAMETER, "GetDateFormatW did not detect null buffer pointer.");
531     ret = GetDateFormatW (lcid, 0, NULL, format, NULL, 0);
532     error = ret ? 0 : GetLastError();
533     ok (ret != 0 && error == 0, "GetDateFormatW did not permit null buffer pointer when counting.");
534
535     /* 1c An incorrect day of week is corrected. */
536     /* 1d The incorrect day of week can even be out of range. */
537     /* 1e The time doesn't matter */
538     curtime.wYear = 2002;
539     curtime.wMonth = 10;
540     curtime.wDay = 23;
541     curtime.wDayOfWeek = 45612; /* should be 3 - Wednesday */
542     curtime.wHour = 65432;
543     curtime.wMinute = 34512;
544     curtime.wSecond = 65535;
545     curtime.wMilliseconds = 12345;
546     MultiByteToWideChar (CP_ACP, 0, "dddd d MMMM yyyy", -1, format, COUNTOF(format));
547     ret = GetDateFormatW (lcid, 0, &curtime, format, buffer, COUNTOF(buffer));
548     error = ret ? 0 : GetLastError();
549     MultiByteToWideChar (CP_ACP, 0, "Wednesday 23 October 2002", -1, Expected, COUNTOF(Expected));
550     cmp = ret ? lstrcmpW (buffer, Expected) : 2;
551     ok (ret == lstrlenW(Expected)+1 && error == 0 && cmp == 0, "Day of week correction failed\n");
552 }
553
554
555 void TestGetCurrencyFormat()
556 {
557 int ret, error, cmp;
558 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], format[BUFFER_SIZE];
559 LCID lcid;
560
561         lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT );
562 #if 0
563         lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT );
564 #endif
565
566         memset( buffer, 'x', sizeof(buffer) );
567         ret = GetCurrencyFormatA(lcid, 0, "23,65", NULL, buffer, COUNTOF(buffer));
568         error = GetLastError ();
569         cmp = strncmp ("xxxx", buffer, 4);
570
571         ok (cmp == 0, "GetCurrencyFormat should fail with ','");
572         eq (ret, 0, "GetCurrencyFormat with ','", "%d");
573         eq (error, ERROR_INVALID_PARAMETER, "GetCurrencyFormat", "%d");
574
575         /* We check the whole buffer with strncmp */
576         strcpy (Expected, "$23.53");
577         strcpy (format, "23.53");
578         memset( buffer, 'x', sizeof(buffer) );
579         ret = GetCurrencyFormatA(lcid, 0, format, NULL, buffer, COUNTOF(buffer));
580         cmp = strncmp (Expected, buffer, BUFFER_SIZE);
581         ok (cmp == 0, "GetCurrencyFormatA got %s instead of %s", buffer, Expected);
582         eq (ret, lstrlenA(Expected)+1, "GetCurrencyFormatA","%d");
583
584         /* Test too small buffers */
585         SetLastError(0);
586         ret = GetCurrencyFormatA(lcid, 0, format, NULL, NULL, 0);
587         ok(ret==lstrlenA(Expected)+1 && GetLastError()==0,
588        "GetCurrencyFormatA(size=0): ret=%d error=%ld", ret, GetLastError());
589
590         memset( buffer, 'x', sizeof(buffer) );
591         ret = GetCurrencyFormatA(lcid, 0, format, NULL, buffer, ret);
592         ok(strcmp(buffer,Expected)==0,
593            "GetCurrencyFormatA(right size): got [%s] instead of [%s]", buffer, Expected);
594         eq (ret, lstrlenA(Expected)+1, "GetCurrencyFormatA(right size)", "%d");
595
596         ret = GetCurrencyFormatA(lcid, 0, format, NULL, buffer, 2);
597         ok(ret==0 && GetLastError()==ERROR_INSUFFICIENT_BUFFER,
598            "GetCurrencyFormatA(size=2): ret=%d error=%ld", ret, GetLastError());
599 }
600
601
602 void TestGetNumberFormat()
603 {
604 int ret, error, cmp;
605 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
606 LCID lcid;
607 NUMBERFMTA format;
608
609         lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT );
610
611         memset( buffer, 'x', sizeof(buffer) );
612         ret = GetNumberFormatA(lcid, 0, "23,65", NULL, buffer, COUNTOF(buffer));
613         error = GetLastError ();
614         cmp = strncmp ("xxx", buffer, 3);
615         ok (cmp == 0, "GetNumberFormat");
616         ok (ret == 0, "GetNumberFormat should return 0");
617         eq (error, ERROR_INVALID_PARAMETER, "GetNumberFormat", "%d");
618
619         strcpy(input, "2353");
620         strcpy(Expected, "2,353.00");
621         SetLastError(0);
622         ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, 0);
623         ok(ret==lstrlenA(Expected)+1 && GetLastError()==0,
624        "GetNumberFormatA(size=0): ret=%d error=%ld", ret, GetLastError());
625
626         memset( buffer, 'x', sizeof(buffer) );
627         ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, ret);
628         ok(strcmp(buffer,Expected)==0,
629            "GetNumberFormatA(right size): got [%s] instead of [%s]", buffer, Expected);
630         eq(ret, lstrlenA(Expected)+1, "GetNumberFormat", "%d");
631
632         ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, 2);
633         ok(ret==0 && GetLastError()==ERROR_INSUFFICIENT_BUFFER,
634            "GetNumberFormatA(size=2): ret=%d error=%ld", ret, GetLastError());
635
636         /* We check the whole buffer with strncmp */
637         memset(Expected, 'x', sizeof(Expected) );
638         strcpy(Expected, "2,353.00");
639         memset( buffer, 'x', sizeof(buffer) );
640         ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
641         cmp = strncmp (Expected, buffer, BUFFER_SIZE);
642         ok (cmp == 0, "GetNumberFormat got %s instead of %s", buffer, Expected);
643         eq (ret, lstrlenA(Expected)+1, "GetNumberFormat", "%d");
644
645         /* If the number of decimals is zero there should be no decimal
646          * separator.
647          * If the grouping size is zero there should be no grouping symbol
648          */
649         format.NumDigits = 0;
650         format.LeadingZero = 0;
651         format.Grouping = 0;
652         format.NegativeOrder = 0;
653         format.lpDecimalSep = ".";
654         format.lpThousandSep = ",";
655         strcpy (Expected, "123456789");
656         memset( buffer, 'x', sizeof(buffer) );
657         ret = GetNumberFormatA (0, 0, "123456789.0", &format, buffer, COUNTOF(buffer));
658         cmp = strncmp (Expected, buffer, sizeof(buffer));
659         ok (cmp == 0, "GetNumberFormat got %s instead of %s", buffer, Expected);
660
661 }
662
663
664 /* Callback function used by TestEnumTimeFormats */
665 BOOL CALLBACK EnumTimeFormatsProc(char * lpTimeFormatString)
666 {
667         trace("%s\n", lpTimeFormatString);
668         strcpy(GlobalBuffer, lpTimeFormatString);
669 #if 0
670         return TRUE;
671 #endif
672         return FALSE;
673 }
674
675 void TestEnumTimeFormats()
676 {
677 int ret;
678 LCID lcid;
679 char Expected[BUFFER_SIZE];
680
681         lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT );
682         memset( GlobalBuffer, 'x', sizeof(GlobalBuffer) );
683         strcpy(Expected, "h:mm:ss tt");
684         ret = EnumTimeFormatsA(EnumTimeFormatsProc, lcid, 0);
685
686         eq (ret, 1, "EnumTimeFormats should return 1", "%d");
687         ok (strncmp (GlobalBuffer, Expected, strlen(Expected)) == 0,
688                                 "EnumTimeFormats failed");
689         ok (ret == 1, "EnumTimeFormats should return 1");
690 }
691
692
693 void TestCompareStringA()
694 {
695 int ret;
696 LCID lcid;
697 char buffer1[BUFFER_SIZE], buffer2[BUFFER_SIZE];
698
699         lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT );
700
701         strcpy(buffer1, "Salut"); strcpy(buffer2, "Salute");
702         ret = CompareStringA(lcid, NORM_IGNORECASE, buffer1, -1, buffer2, -1);
703         ok(ret == 1, "CompareStringA (st1=%s str2=%s) expected result=1, got %d", buffer1, buffer2, ret);
704
705         strcpy(buffer1, "Salut"); strcpy(buffer2, "saLuT");
706         ret = CompareStringA(lcid, NORM_IGNORECASE, buffer1, -1, buffer2, -1);
707         ok(ret == 2, "CompareStringA (st1=%s str2=%s) expected result=2, got %d", buffer1, buffer2, ret);
708
709         strcpy(buffer1, "Salut"); strcpy(buffer2, "hola");
710         ret = CompareStringA(lcid, NORM_IGNORECASE, buffer1, -1, buffer2, -1);
711         ok(ret == 3, "CompareStringA (st1=%s str2=%s) expected result=3, got %d", buffer1, buffer2, ret);
712
713         strcpy(buffer1, "haha"); strcpy(buffer2, "hoho");
714         ret = CompareStringA(lcid, NORM_IGNORECASE, buffer1, -1, buffer2, -1);
715         ok (ret == 1, "CompareStringA (st1=%s str2=%s) expected result=1, got %d", buffer1, buffer2, ret);
716
717         lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT );
718
719         strcpy(buffer1, "haha"); strcpy(buffer2, "hoho");
720         ret = CompareStringA(lcid, NORM_IGNORECASE, buffer1, -1, buffer2, -1);
721         ok (ret == 1, "CompareStringA (st1=%s str2=%s) expected result=1, got %d", buffer1, buffer2, ret);
722
723         ret = CompareStringA(lcid, NORM_IGNORECASE, buffer1, -1, buffer2, 0);
724         ok (ret == 3, "CompareStringA (st1=%s str2=%s) expected result=3, got %d", buffer1, buffer2, ret);
725
726         strcpy(buffer1, "Salut"); strcpy(buffer2, "saLuT");
727         ret = CompareStringA(lcid, NORM_IGNORECASE, buffer1, 5, buffer2, -1);
728         ok (ret == 2, "CompareStringA (st1=%s str2=%s) expected result=2, got %d", buffer1, buffer2, ret);
729 }
730
731 void test_LCMapStringA(void)
732 {
733     int ret, ret2;
734     char buf[256], buf2[256];
735     static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
736     static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
737     static const char symbols_stripped[] = "justateststring1";
738
739     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
740                        upper_case, -1, buf, sizeof(buf));
741     ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
742     ok(GetLastError() == ERROR_INVALID_FLAGS,
743        "unexpected error code %ld\n", GetLastError());
744
745     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
746                        upper_case, -1, buf, sizeof(buf));
747     ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
748     ok(GetLastError() == ERROR_INVALID_FLAGS,
749        "unexpected error code %ld\n", GetLastError());
750
751     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
752
753                        upper_case, -1, buf, sizeof(buf));
754     ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
755     ok(GetLastError() == ERROR_INVALID_FLAGS,
756        "unexpected error code %ld\n", GetLastError());
757
758     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
759                        upper_case, -1, buf, sizeof(buf));
760     ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
761     ok(GetLastError() == ERROR_INVALID_FLAGS,
762        "unexpected error code %ld\n", GetLastError());
763
764     /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
765     SetLastError(0xdeadbeef);
766     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
767                        upper_case, -1, buf, sizeof(buf));
768     ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError());
769     ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
770
771     /* test LCMAP_LOWERCASE */
772     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
773                        upper_case, -1, buf, sizeof(buf));
774     ok(ret == lstrlenA(upper_case) + 1,
775        "ret %d, error %ld, expected value %d\n",
776        ret, GetLastError(), lstrlenA(upper_case) + 1);
777     ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
778
779     /* test LCMAP_UPPERCASE */
780     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
781                        lower_case, -1, buf, sizeof(buf));
782     ok(ret == lstrlenA(lower_case) + 1,
783        "ret %d, error %ld, expected value %d\n",
784        ret, GetLastError(), lstrlenA(lower_case) + 1);
785     ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
786
787     /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
788     lstrcpyA(buf, lower_case);
789     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
790                        buf, -1, buf, sizeof(buf));
791     if (!ret) /* Win9x */
792         trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
793     else
794     {
795         ok(ret == lstrlenA(lower_case) + 1,
796            "ret %d, error %ld, expected value %d\n",
797            ret, GetLastError(), lstrlenA(lower_case) + 1);
798         ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
799     }
800     lstrcpyA(buf, upper_case);
801     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
802                        buf, -1, buf, sizeof(buf));
803     if (!ret) /* Win9x */
804         trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
805     else
806     {
807         ok(ret == lstrlenA(upper_case) + 1,
808            "ret %d, error %ld, expected value %d\n",
809            ret, GetLastError(), lstrlenA(lower_case) + 1);
810         ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
811     }
812
813     /* otherwise src == dst should fail */
814     SetLastError(0xdeadbeef);
815     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
816                        buf, 10, buf, sizeof(buf));
817     ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
818        GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
819        "unexpected error code %ld\n", GetLastError());
820     ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
821
822     /* test whether '\0' is always appended */
823     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
824                        upper_case, -1, buf, sizeof(buf));
825     ok(ret, "LCMapStringA must succeed\n");
826     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
827                        upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
828     ok(ret, "LCMapStringA must succeed\n");
829     ok(ret == ret2, "lengths of sort keys must be equal\n");
830     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
831
832     /* test LCMAP_SORTKEY | NORM_IGNORECASE */
833     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
834                        upper_case, -1, buf, sizeof(buf));
835     ok(ret, "LCMapStringA must succeed\n");
836     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
837                        lower_case, -1, buf2, sizeof(buf2));
838     ok(ret2, "LCMapStringA must succeed\n");
839     ok(ret == ret2, "lengths of sort keys must be equal\n");
840     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
841
842     /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
843     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
844                        lower_case, -1, buf, sizeof(buf));
845     ok(ret, "LCMapStringA must succeed\n");
846     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
847                        lower_case, -1, buf2, sizeof(buf2));
848     ok(ret2, "LCMapStringA must succeed\n");
849     ok(ret == ret2, "lengths of sort keys must be equal\n");
850     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
851
852     /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
853     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
854                        lower_case, -1, buf, sizeof(buf));
855     ok(ret, "LCMapStringA must succeed\n");
856     ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
857                        symbols_stripped, -1, buf2, sizeof(buf2));
858     ok(ret2, "LCMapStringA must succeed\n");
859     ok(ret == ret2, "lengths of sort keys must be equal\n");
860     ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
861
862     /* test NORM_IGNORENONSPACE */
863     lstrcpyA(buf, "foo");
864     ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
865                        lower_case, -1, buf, sizeof(buf));
866     ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
867         lstrlenA(lower_case) + 1, ret);
868     ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
869
870     /* test NORM_IGNORESYMBOLS */
871     lstrcpyA(buf, "foo");
872     ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
873                        lower_case, -1, buf, sizeof(buf));
874     ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
875         lstrlenA(symbols_stripped) + 1, ret);
876     ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
877 }
878
879 void test_LCMapStringW(void)
880 {
881     int ret, ret2;
882     WCHAR buf[256], buf2[256];
883     char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
884     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};
885     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};
886     static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
887     static const WCHAR fooW[] = {'f','o','o',0};
888
889     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
890                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
891     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
892     {
893         trace("Skipping LCMapStringW tests on Win9x\n");
894         return;
895     }
896     ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
897     ok(GetLastError() == ERROR_INVALID_FLAGS,
898        "unexpected error code %ld\n", GetLastError());
899
900     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
901                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
902     ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
903     ok(GetLastError() == ERROR_INVALID_FLAGS,
904        "unexpected error code %ld\n", GetLastError());
905
906     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
907                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
908     ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
909     ok(GetLastError() == ERROR_INVALID_FLAGS,
910        "unexpected error code %ld\n", GetLastError());
911
912     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
913                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
914     ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
915     ok(GetLastError() == ERROR_INVALID_FLAGS,
916        "unexpected error code %ld\n", GetLastError());
917
918     /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
919     SetLastError(0xdeadbeef);
920     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
921                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
922     ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError());
923     ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
924
925     /* test LCMAP_LOWERCASE */
926     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
927                        upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
928     ok(ret == lstrlenW(upper_case) + 1,
929        "ret %d, error %ld, expected value %d\n",
930        ret, GetLastError(), lstrlenW(upper_case) + 1);
931     ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
932
933     /* test LCMAP_UPPERCASE */
934     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
935                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
936     ok(ret == lstrlenW(lower_case) + 1,
937        "ret %d, error %ld, expected value %d\n",
938        ret, GetLastError(), lstrlenW(lower_case) + 1);
939     ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
940
941     /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
942     lstrcpyW(buf, lower_case);
943     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
944                        buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
945     ok(ret == lstrlenW(lower_case) + 1,
946        "ret %d, error %ld, expected value %d\n",
947        ret, GetLastError(), lstrlenW(lower_case) + 1);
948     ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
949
950     lstrcpyW(buf, upper_case);
951     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
952                        buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
953     ok(ret == lstrlenW(upper_case) + 1,
954        "ret %d, error %ld, expected value %d\n",
955        ret, GetLastError(), lstrlenW(lower_case) + 1);
956     ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
957  
958     /* otherwise src == dst should fail */
959     SetLastError(0xdeadbeef);
960     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
961                        buf, 10, buf, sizeof(buf));
962     ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
963        GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
964        "unexpected error code %ld\n", GetLastError());
965     ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
966
967     /* test whether '\0' is always appended */
968     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
969                        upper_case, -1, buf, sizeof(buf));
970     ok(ret, "LCMapStringW must succeed\n");
971     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
972                        upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
973     ok(ret, "LCMapStringW must succeed\n");
974     ok(ret == ret2, "lengths of sort keys must be equal\n");
975     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
976
977     /* test LCMAP_SORTKEY | NORM_IGNORECASE */
978     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
979                        upper_case, -1, buf, sizeof(buf));
980     ok(ret, "LCMapStringW must succeed\n");
981     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
982                        lower_case, -1, buf2, sizeof(buf2));
983     ok(ret2, "LCMapStringW must succeed\n");
984     ok(ret == ret2, "lengths of sort keys must be equal\n");
985     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
986
987     /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
988     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
989                        lower_case, -1, buf, sizeof(buf));
990     ok(ret, "LCMapStringW must succeed\n");
991     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
992                        lower_case, -1, buf2, sizeof(buf2));
993     ok(ret2, "LCMapStringW must succeed\n");
994     ok(ret == ret2, "lengths of sort keys must be equal\n");
995     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
996
997     /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
998     ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
999                        lower_case, -1, buf, sizeof(buf));
1000     ok(ret, "LCMapStringW must succeed\n");
1001     ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1002                        symbols_stripped, -1, buf2, sizeof(buf2));
1003     ok(ret2, "LCMapStringW must succeed\n");
1004     ok(ret == ret2, "lengths of sort keys must be equal\n");
1005     ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1006
1007     /* test NORM_IGNORENONSPACE */
1008     lstrcpyW(buf, fooW);
1009     ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1010                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1011     ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1012         lstrlenW(lower_case) + 1, ret);
1013     ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1014
1015     /* test NORM_IGNORESYMBOLS */
1016     lstrcpyW(buf, fooW);
1017     ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1018                        lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1019     ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1020         lstrlenW(symbols_stripped) + 1, ret);
1021     ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1022 }
1023
1024 START_TEST(locale)
1025 {
1026 #if 0
1027         TestEnumTimeFormats();
1028 #endif
1029         TestGetLocaleInfoA();
1030         TestGetTimeFormatA();
1031         TestGetDateFormatA();
1032         TestGetDateFormatW();
1033         TestGetNumberFormat();
1034         TestGetCurrencyFormat();
1035         TestCompareStringA();
1036
1037     test_LCMapStringW();
1038     test_LCMapStringA();
1039 }