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