1 /*
2  * Unit test suite for locale functions.
3  *
4  * Copyright 2010 Piotr Caban for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include "precomp.h"
22 
23 static BOOL (__cdecl *p__crtGetStringTypeW)(DWORD, DWORD, const wchar_t*, int, WORD*);
24 static int (__cdecl *pmemcpy_s)(void *, size_t, void*, size_t);
25 static int (__cdecl *p___mb_cur_max_func)(void);
26 static int *(__cdecl *p__p___mb_cur_max)(void);
27 void* __cdecl _Gettnames(void);
28 
29 static void init(void)
30 {
31     HMODULE hmod = GetModuleHandleA("msvcrt.dll");
32 
33     p__crtGetStringTypeW = (void*)GetProcAddress(hmod, "__crtGetStringTypeW");
34     pmemcpy_s = (void*)GetProcAddress(hmod, "memcpy_s");
35     p___mb_cur_max_func = (void*)GetProcAddress(hmod, "___mb_cur_max_func");
36     p__p___mb_cur_max = (void*)GetProcAddress(hmod, "__p___mb_cur_max");
37 }
38 
39 static void test_setlocale(void)
40 {
41     static const char lc_all[] = "LC_COLLATE=C;LC_CTYPE=C;"
42         "LC_MONETARY=Greek_Greece.1253;LC_NUMERIC=Polish_Poland.1250;LC_TIME=C";
43 
44     char *ret, buf[100];
45 
46     ret = setlocale(20, "C");
47     ok(ret == NULL, "ret = %s\n", ret);
48 
49     ret = setlocale(LC_ALL, "C");
50     ok(!strcmp(ret, "C"), "ret = %s\n", ret);
51 
52     ret = setlocale(LC_ALL, NULL);
53     ok(!strcmp(ret, "C"), "ret = %s\n", ret);
54 
55     if(!setlocale(LC_NUMERIC, "Polish")
56             || !setlocale(LC_NUMERIC, "Greek")
57             || !setlocale(LC_NUMERIC, "German")
58             || !setlocale(LC_NUMERIC, "English")) {
59         win_skip("System with limited locales\n");
60         return;
61     }
62 
63     ret = setlocale(LC_NUMERIC, "Polish");
64     ok(!strcmp(ret, "Polish_Poland.1250"), "ret = %s\n", ret);
65 
66     ret = setlocale(LC_MONETARY, "Greek");
67     ok(!strcmp(ret, "Greek_Greece.1253"), "ret = %s\n", ret);
68 
69     ret = setlocale(LC_ALL, NULL);
70     ok(!strcmp(ret, lc_all), "ret = %s\n", ret);
71 
72     strcpy(buf, ret);
73     ret = setlocale(LC_ALL, buf);
74     ok(!strcmp(ret, lc_all), "ret = %s\n", ret);
75 
76     ret = setlocale(LC_ALL, "German");
77     ok(!strcmp(ret, "German_Germany.1252"), "ret = %s\n", ret);
78 
79     ret = setlocale(LC_ALL, "american");
80     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
81     if(ret)
82         ok(!strcmp(ret, "English_United States.1252"), "ret = %s\n", ret);
83 
84     ret = setlocale(LC_ALL, "american english");
85     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
86     if(ret)
87         ok(!strcmp(ret, "English_United States.1252"), "ret = %s\n", ret);
88 
89     ret = setlocale(LC_ALL, "american-english");
90     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
91     if(ret)
92         ok(!strcmp(ret, "English_United States.1252"), "ret = %s\n", ret);
93 
94     ret = setlocale(LC_ALL, "australian");
95     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
96     if(ret)
97         ok(!strcmp(ret, "English_Australia.1252"), "ret = %s\n", ret);
98 
99     ret = setlocale(LC_ALL, "belgian");
100     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
101     if(ret)
102         ok(!strcmp(ret, "Dutch_Belgium.1252"), "ret = %s\n", ret);
103 
104     ret = setlocale(LC_ALL, "canadian");
105     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
106     if(ret)
107         ok(!strcmp(ret, "English_Canada.1252"), "ret = %s\n", ret);
108 
109     ret = setlocale(LC_ALL, "chinese");
110     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
111     if(ret)
112         ok(!strcmp(ret, "Chinese (Simplified)_People's Republic of China.936")
113         || !strcmp(ret, "Chinese (Simplified)_China.936")
114         || broken(!strcmp(ret, "Chinese_Taiwan.950")), "ret = %s\n", ret);
115 
116     ret = setlocale(LC_ALL, "chinese-simplified");
117     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
118     if(ret)
119         ok(!strcmp(ret, "Chinese (Simplified)_People's Republic of China.936")
120         || !strcmp(ret, "Chinese (Simplified)_China.936")
121         || broken(!strcmp(ret, "Chinese_People's Republic of China.936"))
122         || broken(!strcmp(ret, "Chinese_Taiwan.950")), "ret = %s\n", ret);
123 
124     ret = setlocale(LC_ALL, "chinese-traditional");
125     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
126     if(ret)
127         ok(!strcmp(ret, "Chinese (Traditional)_Taiwan.950")
128         || broken(!strcmp(ret, "Chinese_Taiwan.950")), "ret = %s\n", ret);
129 
130     ret = setlocale(LC_ALL, "chs");
131     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
132     if(ret)
133         ok(!strcmp(ret, "Chinese (Simplified)_People's Republic of China.936")
134         || !strcmp(ret, "Chinese (Simplified)_China.936")
135         || broken(!strcmp(ret, "Chinese_People's Republic of China.936")), "ret = %s\n", ret);
136 
137     ret = setlocale(LC_ALL, "cht");
138     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
139     if(ret)
140         ok(!strcmp(ret, "Chinese (Traditional)_Taiwan.950")
141         || broken(!strcmp(ret, "Chinese_Taiwan.950")), "ret = %s\n", ret);
142 
143     ret = setlocale(LC_ALL, "Chinese_China.936");
144 todo_wine
145     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
146     if(ret)
147     {
148         trace("Chinese_China.936=%s\n", ret);
149 todo_wine
150         ok(!strcmp(ret, "Chinese (Simplified)_People's Republic of China.936") /* Vista - Win7 */
151         || !strcmp(ret, "Chinese (Simplified)_China.936") /* Win8 - Win10 */
152         || broken(!strcmp(ret, "Chinese_People's Republic of China.936")), "ret = %s\n", ret);
153     }
154 
155     ret = setlocale(LC_ALL, "csy");
156     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
157     if(ret)
158         ok(!strcmp(ret, "Czech_Czech Republic.1250"), "ret = %s\n", ret);
159 
160     ret = setlocale(LC_ALL, "czech");
161     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
162     if(ret)
163         ok(!strcmp(ret, "Czech_Czech Republic.1250"), "ret = %s\n", ret);
164 
165     ret = setlocale(LC_ALL, "dan");
166     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
167     if(ret)
168         ok(!strcmp(ret, "Danish_Denmark.1252"), "ret = %s\n", ret);
169 
170     ret = setlocale(LC_ALL, "danish");
171     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
172     if(ret)
173         ok(!strcmp(ret, "Danish_Denmark.1252"), "ret = %s\n", ret);
174 
175     ret = setlocale(LC_ALL, "dea");
176     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
177     if(ret)
178         ok(!strcmp(ret, "German_Austria.1252"), "ret = %s\n", ret);
179 
180     ret = setlocale(LC_ALL, "des");
181     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
182     if(ret)
183         ok(!strcmp(ret, "German_Switzerland.1252"), "ret = %s\n", ret);
184 
185     ret = setlocale(LC_ALL, "deu");
186     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
187     if(ret)
188         ok(!strcmp(ret, "German_Germany.1252"), "ret = %s\n", ret);
189 
190     ret = setlocale(LC_ALL, "dutch");
191     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
192     if(ret)
193         ok(!strcmp(ret, "Dutch_Netherlands.1252"), "ret = %s\n", ret);
194 
195     ret = setlocale(LC_ALL, "dutch-belgian");
196     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
197     if(ret)
198         ok(!strcmp(ret, "Dutch_Belgium.1252")
199         || broken(!strcmp(ret, "Dutch_Netherlands.1252")), "ret = %s\n", ret);
200 
201     ret = setlocale(LC_ALL, "ena");
202     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
203     if(ret)
204         ok(!strcmp(ret, "English_Australia.1252")
205         || broken(!strcmp(ret, "English_United States.1252")), "ret = %s\n", ret);
206 
207     ret = setlocale(LC_ALL, "ell");
208     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
209     if(ret)
210         ok(!strcmp(ret, "Greek_Greece.1253"), "ret = %s\n", ret);
211 
212     ret = setlocale(LC_ALL, "enc");
213     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
214     if(ret)
215         ok(!strcmp(ret, "English_Canada.1252")
216         || broken(!strcmp(ret, "English_United States.1252")), "ret = %s\n", ret);
217 
218     ret = setlocale(LC_ALL, "eng");
219     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
220     if(ret)
221         ok(!strcmp(ret, "English_United Kingdom.1252")
222         || broken(!strcmp(ret, "English_United States.1252")), "ret = %s\n", ret);
223 
224     ret = setlocale(LC_ALL, "enu");
225     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
226     if(ret)
227         ok(!strcmp(ret, "English_United States.1252"), "ret = %s\n", ret);
228 
229     ret = setlocale(LC_ALL, "enz");
230     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
231     if(ret)
232         ok(!strcmp(ret, "English_New Zealand.1252")
233         || broken(!strcmp(ret, "English_United States.1252")), "ret = %s\n", ret);
234 
235     ret = setlocale(LC_ALL, "english");
236     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
237     if(ret)
238         ok(!strcmp(ret, "English_United States.1252"), "ret = %s\n", ret);
239 
240     ret = setlocale(LC_ALL, "english-american");
241     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
242     if(ret)
243         ok(!strcmp(ret, "English_United States.1252"), "ret = %s\n", ret);
244 
245     ret = setlocale(LC_ALL, "english-aus");
246     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
247     if(ret)
248         ok(!strcmp(ret, "English_Australia.1252")
249         || broken(!strcmp(ret, "English_United States.1252")), "ret = %s\n", ret);
250 
251     ret = setlocale(LC_ALL, "english-can");
252     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
253     if(ret)
254         ok(!strcmp(ret, "English_Canada.1252")
255         || broken(!strcmp(ret, "English_United States.1252")), "ret = %s\n", ret);
256 
257     ret = setlocale(LC_ALL, "english-nz");
258     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
259     if(ret)
260         ok(!strcmp(ret, "English_New Zealand.1252")
261         || broken(!strcmp(ret, "English_United States.1252")), "ret = %s\n", ret);
262 
263     ret = setlocale(LC_ALL, "english-uk");
264     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
265     if(ret)
266         ok(!strcmp(ret, "English_United Kingdom.1252")
267         || broken(!strcmp(ret, "English_United States.1252")), "ret = %s\n", ret);
268 
269     ret = setlocale(LC_ALL, "english-us");
270     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
271     if(ret)
272         ok(!strcmp(ret, "English_United States.1252"), "ret = %s\n", ret);
273 
274     ret = setlocale(LC_ALL, "english-usa");
275     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
276     if(ret)
277         ok(!strcmp(ret, "English_United States.1252"), "ret = %s\n", ret);
278 
279     ret = setlocale(LC_ALL, "esm");
280     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
281     if(ret)
282         ok(!strcmp(ret, "Spanish_Mexico.1252"), "ret = %s\n", ret);
283 
284     ret = setlocale(LC_ALL, "esn");
285     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
286     if(ret)
287         ok(!strcmp(ret, "Spanish_Spain.1252")
288         || broken(!strcmp(ret, "Spanish - Modern Sort_Spain.1252")), "ret = %s\n", ret);
289 
290     ret = setlocale(LC_ALL, "esp");
291     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
292     if(ret)
293         ok(!strcmp(ret, "Spanish_Spain.1252")
294         || broken(!strcmp(ret, "Spanish - Traditional Sort_Spain.1252")), "ret = %s\n", ret);
295 
296     ret = setlocale(LC_ALL, "fin");
297     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
298     if(ret)
299         ok(!strcmp(ret, "Finnish_Finland.1252"), "ret = %s\n", ret);
300 
301     ret = setlocale(LC_ALL, "finnish");
302     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
303     if(ret)
304         ok(!strcmp(ret, "Finnish_Finland.1252"), "ret = %s\n", ret);
305 
306     ret = setlocale(LC_ALL, "fra");
307     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
308     if(ret)
309         ok(!strcmp(ret, "French_France.1252"), "ret = %s\n", ret);
310 
311     ret = setlocale(LC_ALL, "frb");
312     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
313     if(ret)
314         ok(!strcmp(ret, "French_Belgium.1252")
315         || broken(!strcmp(ret, "French_France.1252")), "ret = %s\n", ret);
316 
317     ret = setlocale(LC_ALL, "frc");
318     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
319     if(ret)
320         ok(!strcmp(ret, "French_Canada.1252")
321         || broken(!strcmp(ret, "French_France.1252")), "ret = %s\n", ret);
322 
323     ret = setlocale(LC_ALL, "french");
324     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
325     if(ret)
326         ok(!strcmp(ret, "French_France.1252"), "ret = %s\n", ret);
327 
328     ret = setlocale(LC_ALL, "french-belgian");
329     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
330     if(ret)
331         ok(!strcmp(ret, "French_Belgium.1252")
332         || broken(!strcmp(ret, "French_France.1252")), "ret = %s\n", ret);
333 
334     ret = setlocale(LC_ALL, "french-canadian");
335     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
336     if(ret)
337         ok(!strcmp(ret, "French_Canada.1252")
338         || broken(!strcmp(ret, "French_France.1252")), "ret = %s\n", ret);
339 
340     ret = setlocale(LC_ALL, "french-swiss");
341     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
342     if(ret)
343         ok(!strcmp(ret, "French_Switzerland.1252")
344         || broken(!strcmp(ret, "French_France.1252")), "ret = %s\n", ret);
345 
346     ret = setlocale(LC_ALL, "frs");
347     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
348     if(ret)
349         ok(!strcmp(ret, "French_Switzerland.1252")
350         || broken(!strcmp(ret, "French_France.1252")), "ret = %s\n", ret);
351 
352     ret = setlocale(LC_ALL, "german");
353     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
354     if(ret)
355         ok(!strcmp(ret, "German_Germany.1252"), "ret = %s\n", ret);
356 
357     ret = setlocale(LC_ALL, "german-austrian");
358     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
359     if(ret)
360         ok(!strcmp(ret, "German_Austria.1252")
361         || broken(!strcmp(ret, "German_Germany.1252")), "ret = %s\n", ret);
362 
363     ret = setlocale(LC_ALL, "german-swiss");
364     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
365     if(ret)
366         ok(!strcmp(ret, "German_Switzerland.1252")
367         || broken(!strcmp(ret, "German_Germany.1252")), "ret = %s\n", ret);
368 
369     ret = setlocale(LC_ALL, "greek");
370     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
371     if(ret)
372         ok(!strcmp(ret, "Greek_Greece.1253"), "ret = %s\n", ret);
373 
374     ret = setlocale(LC_ALL, "hun");
375     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
376     if(ret)
377         ok(!strcmp(ret, "Hungarian_Hungary.1250"), "ret = %s\n", ret);
378 
379     ret = setlocale(LC_ALL, "hungarian");
380     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
381     if(ret)
382         ok(!strcmp(ret, "Hungarian_Hungary.1250"), "ret = %s\n", ret);
383 
384     ret = setlocale(LC_ALL, "icelandic");
385     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
386     if(ret)
387         ok(!strcmp(ret, "Icelandic_Iceland.1252"), "ret = %s\n", ret);
388 
389     ret = setlocale(LC_ALL, "isl");
390     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
391     if(ret)
392         ok(!strcmp(ret, "Icelandic_Iceland.1252"), "ret = %s\n", ret);
393 
394     ret = setlocale(LC_ALL, "ita");
395     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
396     if(ret)
397         ok(!strcmp(ret, "Italian_Italy.1252"), "ret = %s\n", ret);
398 
399     ret = setlocale(LC_ALL, "italian");
400     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
401     if(ret)
402         ok(!strcmp(ret, "Italian_Italy.1252"), "ret = %s\n", ret);
403 
404     ret = setlocale(LC_ALL, "italian-swiss");
405     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
406     if(ret)
407         ok(!strcmp(ret, "Italian_Switzerland.1252")
408         || broken(!strcmp(ret, "Italian_Italy.1252")), "ret = %s\n", ret);
409 
410     ret = setlocale(LC_ALL, "its");
411     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
412     if(ret)
413         ok(!strcmp(ret, "Italian_Switzerland.1252")
414         || broken(!strcmp(ret, "Italian_Italy.1252")), "ret = %s\n", ret);
415 
416     ret = setlocale(LC_ALL, "japanese");
417     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
418     if(ret)
419         ok(!strcmp(ret, "Japanese_Japan.932"), "ret = %s\n", ret);
420 
421     ret = setlocale(LC_ALL, "jpn");
422     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
423     if(ret)
424         ok(!strcmp(ret, "Japanese_Japan.932"), "ret = %s\n", ret);
425 
426     ret = setlocale(LC_ALL, "korean");
427     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
428     if(ret)
429         ok(!strcmp(ret, "Korean_Korea.949"), "ret = %s\n", ret);
430 
431     ret = setlocale(LC_ALL, "korean");
432     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
433     if(ret)
434         ok(!strcmp(ret, "Korean_Korea.949"), "ret = %s\n", ret);
435 
436     ret = setlocale(LC_ALL, "nlb");
437     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
438     if(ret)
439         ok(!strcmp(ret, "Dutch_Belgium.1252")
440         || broken(!strcmp(ret, "Dutch_Netherlands.1252")), "ret = %s\n", ret);
441 
442     ret = setlocale(LC_ALL, "nld");
443     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
444     if(ret)
445         ok(!strcmp(ret, "Dutch_Netherlands.1252"), "ret = %s\n", ret);
446 
447     ret = setlocale(LC_ALL, "non");
448     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
449     if(ret)
450         ok(!strcmp( ret, "Norwegian-Nynorsk_Norway.1252") /* XP - Win10 */
451         || !strcmp(ret, "Norwegian (Nynorsk)_Norway.1252")
452         || broken(!strcmp(ret, "Norwegian (Bokm\xe5l)_Norway.1252"))
453         || broken(!strcmp(ret, "Norwegian_Norway.1252")), /* WinME */
454            "ret = %s\n", ret);
455 
456     ret = setlocale(LC_ALL, "nor");
457     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
458     if(ret)
459         ok(!strcmp(ret, "Norwegian (Bokm\xe5l)_Norway.1252") /* XP - Win8 */
460         || !strcmp(ret, "Norwegian Bokm\xe5l_Norway.1252") /* Win10 */
461         || !strcmp(ret, "Norwegian (Bokmal)_Norway.1252")
462         || broken(!strcmp(ret, "Norwegian_Norway.1252")), /* WinME */
463            "ret = %s\n", ret);
464 
465     ret = setlocale(LC_ALL, "norwegian-bokmal");
466     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
467     if(ret)
468         ok(!strcmp(ret, "Norwegian (Bokm\xe5l)_Norway.1252") /* XP - Win8 */
469         || !strcmp(ret, "Norwegian Bokm\xe5l_Norway.1252") /* Win10 */
470         || !strcmp(ret, "Norwegian (Bokmal)_Norway.1252")
471         || broken(!strcmp(ret, "Norwegian_Norway.1252")), /* WinME */
472            "ret = %s\n", ret);
473 
474     ret = setlocale(LC_ALL, "norwegian-nynorsk");
475     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
476     if(ret)
477         ok(!strcmp(ret, "Norwegian-Nynorsk_Norway.1252") /* Vista - Win10 */
478         || !strcmp(ret, "Norwegian (Nynorsk)_Norway.1252")
479         || broken(!strcmp(ret, "Norwegian_Norway.1252")) /* WinME */
480         || broken(!strcmp(ret, "Norwegian (Bokmal)_Norway.1252"))
481         || broken(!strcmp(ret, "Norwegian (Bokm\xe5l)_Norway.1252")) /* XP & 2003 */,
482            "ret = %s\n", ret);
483 
484     ret = setlocale(LC_ALL, "plk");
485     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
486     if(ret)
487         ok(!strcmp(ret, "Polish_Poland.1250"), "ret = %s\n", ret);
488 
489     ret = setlocale(LC_ALL, "polish");
490     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
491     if(ret)
492         ok(!strcmp(ret, "Polish_Poland.1250"), "ret = %s\n", ret);
493 
494     ret = setlocale(LC_ALL, "portuguese");
495     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
496     if(ret)
497         ok(!strcmp(ret, "Portuguese_Brazil.1252")
498         || broken(!strcmp(ret, "Portuguese_Portugal.1252")) /* NT4 */, "ret = %s\n", ret);
499 
500     ret = setlocale(LC_ALL, "portuguese-brazil");
501     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
502     if(ret)
503         ok(!strcmp(ret, "Portuguese_Brazil.1252"), "ret = %s\n", ret);
504 
505     ret = setlocale(LC_ALL, "ptb");
506     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
507     if(ret)
508         ok(!strcmp(ret, "Portuguese_Brazil.1252"), "ret = %s\n", ret);
509 
510     ret = setlocale(LC_ALL, "ptg");
511     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
512     if(ret)
513         ok(!strcmp(ret, "Portuguese_Portugal.1252"), "ret = %s\n", ret);
514 
515     ret = setlocale(LC_ALL, "rus");
516     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
517     if(ret)
518         ok(!strcmp(ret, "Russian_Russia.1251"), "ret = %s\n", ret);
519 
520     ret = setlocale(LC_ALL, "russian");
521     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
522     if(ret)
523         ok(!strcmp(ret, "Russian_Russia.1251"), "ret = %s\n", ret);
524 
525     ret = setlocale(LC_ALL, "sky");
526     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
527     if(ret)
528         ok(!strcmp(ret, "Slovak_Slovakia.1250"), "ret = %s\n", ret);
529 
530     ret = setlocale(LC_ALL, "slovak");
531     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
532     if(ret)
533         ok(!strcmp(ret, "Slovak_Slovakia.1250"), "ret = %s\n", ret);
534 
535     ret = setlocale(LC_ALL, "spanish");
536     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
537     if(ret)
538         ok(!strcmp(ret, "Spanish_Spain.1252")
539         || broken(!strcmp(ret, "Spanish - Traditional Sort_Spain.1252")), "ret = %s\n", ret);
540 
541     ret = setlocale(LC_ALL, "spanish-mexican");
542     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
543     if(ret)
544         ok(!strcmp(ret, "Spanish_Mexico.1252")
545         || broken(!strcmp(ret, "Spanish_Spain.1252")), "ret = %s\n", ret);
546 
547     ret = setlocale(LC_ALL, "spanish-modern");
548     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
549     if(ret)
550         ok(!strcmp(ret, "Spanish - Modern Sort_Spain.1252")
551            || !strcmp(ret, "Spanish_Spain.1252"), "ret = %s\n", ret);
552 
553     ret = setlocale(LC_ALL, "sve");
554     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
555     if(ret)
556         ok(!strcmp(ret, "Swedish_Sweden.1252"), "ret = %s\n", ret);
557 
558     ret = setlocale(LC_ALL, "swedish");
559     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
560     if(ret)
561         ok(!strcmp(ret, "Swedish_Sweden.1252"), "ret = %s\n", ret);
562 
563     ret = setlocale(LC_ALL, "swiss");
564     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
565     if(ret)
566         ok(!strcmp(ret, "German_Switzerland.1252"), "ret = %s\n", ret);
567 
568     ret = setlocale(LC_ALL, "trk");
569     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
570     if(ret)
571         ok(!strcmp(ret, "Turkish_Turkey.1254"), "ret = %s\n", ret);
572 
573     ret = setlocale(LC_ALL, "turkish");
574     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
575     if(ret)
576         ok(!strcmp(ret, "Turkish_Turkey.1254"), "ret = %s\n", ret);
577 
578     ret = setlocale(LC_ALL, "uk");
579     ok(ret != NULL, "ret == NULL\n");
580     if(ret)
581         ok(!strcmp(ret, "English_United Kingdom.1252")
582         || broken(!strcmp(ret, "Ukrainian_Ukraine.1251")), "ret = %s\n", ret);
583 
584     ret = setlocale(LC_ALL, "us");
585     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
586     if(ret)
587         ok(!strcmp(ret, "English_United States.1252"), "ret = %s\n", ret);
588 
589     ret = setlocale(LC_ALL, "usa");
590     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
591     if(ret)
592         ok(!strcmp(ret, "English_United States.1252"), "ret = %s\n", ret);
593 
594     ret = setlocale(LC_ALL, "English_United States.ACP");
595     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
596     if(ret) {
597         strcpy(buf, "English_United States.");
598         GetLocaleInfoA(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT),
599                 LOCALE_IDEFAULTANSICODEPAGE, buf+strlen(buf), 80);
600         ok(!strcmp(ret, buf), "ret = %s, expected %s\n", ret, buf);
601     }
602 
603     ret = setlocale(LC_ALL, "English_United States.OCP");
604     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
605     if(ret) {
606         strcpy(buf, "English_United States.");
607         GetLocaleInfoA(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT),
608                 LOCALE_IDEFAULTCODEPAGE, buf+strlen(buf), 80);
609         ok(!strcmp(ret, buf), "ret = %s, expected %s\n", ret, buf);
610     }
611 
612     ret = setlocale(LC_ALL, "English_United States.UTF8");
613     ok(ret == NULL, "ret != NULL\n");
614 }
615 
616 static void test_crtGetStringTypeW(void)
617 {
618     static const wchar_t str0[] = { '0', '\0' };
619     static const wchar_t strA[] = { 'A', '\0' };
620     static const wchar_t str_space[] = { ' ', '\0' };
621     static const wchar_t str_null[] = { '\0', '\0' };
622     static const wchar_t str_rand[] = { 1234, '\0' };
623 
624     const wchar_t *str[] = { str0, strA, str_space, str_null, str_rand };
625 
626     WORD out_crt, out;
627     BOOL ret_crt, ret;
628     int i;
629 
630     if(!p__crtGetStringTypeW) {
631         win_skip("Skipping __crtGetStringTypeW tests\n");
632         return;
633     }
634 
635     if(!pmemcpy_s) {
636         win_skip("Too old version of msvcrt.dll\n");
637         return;
638     }
639 
640     for(i=0; i<sizeof(str)/sizeof(*str); i++) {
641         ret_crt = p__crtGetStringTypeW(0, CT_CTYPE1, str[i], 1, &out_crt);
642         ret = GetStringTypeW(CT_CTYPE1, str[i], 1, &out);
643         ok(ret == ret_crt, "%d) ret_crt = %d\n", i, (int)ret_crt);
644         ok(out == out_crt, "%d) out_crt = %x, expected %x\n", i, (int)out_crt, (int)out);
645 
646         ret_crt = p__crtGetStringTypeW(0, CT_CTYPE2, str[i], 1, &out_crt);
647         ret = GetStringTypeW(CT_CTYPE2, str[i], 1, &out);
648         ok(ret == ret_crt, "%d) ret_crt = %d\n", i, (int)ret_crt);
649         ok(out == out_crt, "%d) out_crt = %x, expected %x\n", i, (int)out_crt, (int)out);
650 
651         ret_crt = p__crtGetStringTypeW(0, CT_CTYPE3, str[i], 1, &out_crt);
652         ret = GetStringTypeW(CT_CTYPE3, str[i], 1, &out);
653         ok(ret == ret_crt, "%d) ret_crt = %d\n", i, (int)ret_crt);
654         ok(out == out_crt, "%d) out_crt = %x, expected %x\n", i, (int)out_crt, (int)out);
655     }
656 
657     ret = p__crtGetStringTypeW(0, 3, str[0], 1, &out);
658     ok(!ret, "ret == TRUE\n");
659 }
660 
661 static void test__Gettnames(void)
662 {
663     struct {
664         char *str[43];
665         LCID lcid;
666         int  unk[2];
667         wchar_t *wstr[43];
668         char data[1];
669     } *ret;
670     int size;
671     char buf[64];
672 
673     if(!setlocale(LC_ALL, "english"))
674         return;
675 
676     ret = _Gettnames();
677     size = ret->str[0]-(char*)ret;
678     /* Newer version of the structure stores both ascii and unicode strings.
679      * Unicode strings are only initialized on Windows 7
680      */
681     if(sizeof(void*) == 8)
682         ok(size==0x2c0 || broken(size==0x168), "structure size: %x\n", size);
683     else
684         ok(size==0x164 || broken(size==0xb8), "structure size: %x\n", size);
685 
686     ok(!strcmp(ret->str[0], "Sun"), "ret->str[0] = %s\n", ret->str[0]);
687     ok(!strcmp(ret->str[1], "Mon"), "ret->str[1] = %s\n", ret->str[1]);
688     ok(!strcmp(ret->str[2], "Tue"), "ret->str[2] = %s\n", ret->str[2]);
689     ok(!strcmp(ret->str[3], "Wed"), "ret->str[3] = %s\n", ret->str[3]);
690     ok(!strcmp(ret->str[4], "Thu"), "ret->str[4] = %s\n", ret->str[4]);
691     ok(!strcmp(ret->str[5], "Fri"), "ret->str[5] = %s\n", ret->str[5]);
692     ok(!strcmp(ret->str[6], "Sat"), "ret->str[6] = %s\n", ret->str[6]);
693     ok(!strcmp(ret->str[7], "Sunday"), "ret->str[7] = %s\n", ret->str[7]);
694     ok(!strcmp(ret->str[8], "Monday"), "ret->str[8] = %s\n", ret->str[8]);
695     ok(!strcmp(ret->str[9], "Tuesday"), "ret->str[9] = %s\n", ret->str[9]);
696     ok(!strcmp(ret->str[10], "Wednesday"), "ret->str[10] = %s\n", ret->str[10]);
697     ok(!strcmp(ret->str[11], "Thursday"), "ret->str[11] = %s\n", ret->str[11]);
698     ok(!strcmp(ret->str[12], "Friday"), "ret->str[12] = %s\n", ret->str[12]);
699     ok(!strcmp(ret->str[13], "Saturday"), "ret->str[13] = %s\n", ret->str[13]);
700     ok(!strcmp(ret->str[14], "Jan"), "ret->str[14] = %s\n", ret->str[14]);
701     ok(!strcmp(ret->str[15], "Feb"), "ret->str[15] = %s\n", ret->str[15]);
702     ok(!strcmp(ret->str[16], "Mar"), "ret->str[16] = %s\n", ret->str[16]);
703     ok(!strcmp(ret->str[17], "Apr"), "ret->str[17] = %s\n", ret->str[17]);
704     ok(!strcmp(ret->str[18], "May"), "ret->str[18] = %s\n", ret->str[18]);
705     ok(!strcmp(ret->str[19], "Jun"), "ret->str[19] = %s\n", ret->str[19]);
706     ok(!strcmp(ret->str[20], "Jul"), "ret->str[20] = %s\n", ret->str[20]);
707     ok(!strcmp(ret->str[21], "Aug"), "ret->str[21] = %s\n", ret->str[21]);
708     ok(!strcmp(ret->str[22], "Sep"), "ret->str[22] = %s\n", ret->str[22]);
709     ok(!strcmp(ret->str[23], "Oct"), "ret->str[23] = %s\n", ret->str[23]);
710     ok(!strcmp(ret->str[24], "Nov"), "ret->str[24] = %s\n", ret->str[24]);
711     ok(!strcmp(ret->str[25], "Dec"), "ret->str[25] = %s\n", ret->str[25]);
712     ok(!strcmp(ret->str[26], "January"), "ret->str[26] = %s\n", ret->str[26]);
713     ok(!strcmp(ret->str[27], "February"), "ret->str[27] = %s\n", ret->str[27]);
714     ok(!strcmp(ret->str[28], "March"), "ret->str[28] = %s\n", ret->str[28]);
715     ok(!strcmp(ret->str[29], "April"), "ret->str[29] = %s\n", ret->str[29]);
716     ok(!strcmp(ret->str[30], "May"), "ret->str[30] = %s\n", ret->str[30]);
717     ok(!strcmp(ret->str[31], "June"), "ret->str[31] = %s\n", ret->str[31]);
718     ok(!strcmp(ret->str[32], "July"), "ret->str[32] = %s\n", ret->str[32]);
719     ok(!strcmp(ret->str[33], "August"), "ret->str[33] = %s\n", ret->str[33]);
720     ok(!strcmp(ret->str[34], "September"), "ret->str[34] = %s\n", ret->str[34]);
721     ok(!strcmp(ret->str[35], "October"), "ret->str[35] = %s\n", ret->str[35]);
722     ok(!strcmp(ret->str[36], "November"), "ret->str[36] = %s\n", ret->str[36]);
723     ok(!strcmp(ret->str[37], "December"), "ret->str[37] = %s\n", ret->str[37]);
724     ok(!strcmp(ret->str[38], "AM"), "ret->str[38] = %s\n", ret->str[38]);
725     ok(!strcmp(ret->str[39], "PM"), "ret->str[39] = %s\n", ret->str[39]);
726     ok(!strcmp(ret->str[40], "M/d/yyyy") || broken(!strcmp(ret->str[40], "M/d/yy"))/*NT*/,
727             "ret->str[40] = %s\n", ret->str[40]);
728     size = GetLocaleInfoA(MAKELCID(LANG_ENGLISH, SORT_DEFAULT),
729            LOCALE_SLONGDATE|LOCALE_NOUSEROVERRIDE, buf, sizeof(buf));
730     ok(size, "GetLocaleInfo failed: %x\n", GetLastError());
731     ok(!strcmp(ret->str[41], buf), "ret->str[41] = %s, expected %s\n", ret->str[41], buf);
732     free(ret);
733 
734     if(!setlocale(LC_TIME, "german"))
735         return;
736 
737     ret = _Gettnames();
738     ok(!strcmp(ret->str[0], "So"), "ret->str[0] = %s\n", ret->str[0]);
739     ok(!strcmp(ret->str[1], "Mo"), "ret->str[1] = %s\n", ret->str[1]);
740     ok(!strcmp(ret->str[2], "Di"), "ret->str[2] = %s\n", ret->str[2]);
741     ok(!strcmp(ret->str[3], "Mi"), "ret->str[3] = %s\n", ret->str[3]);
742     ok(!strcmp(ret->str[4], "Do"), "ret->str[4] = %s\n", ret->str[4]);
743     ok(!strcmp(ret->str[5], "Fr"), "ret->str[5] = %s\n", ret->str[5]);
744     ok(!strcmp(ret->str[6], "Sa"), "ret->str[6] = %s\n", ret->str[6]);
745     ok(!strcmp(ret->str[7], "Sonntag"), "ret->str[7] = %s\n", ret->str[7]);
746     ok(!strcmp(ret->str[8], "Montag"), "ret->str[8] = %s\n", ret->str[8]);
747     ok(!strcmp(ret->str[9], "Dienstag"), "ret->str[9] = %s\n", ret->str[9]);
748     ok(!strcmp(ret->str[10], "Mittwoch"), "ret->str[10] = %s\n", ret->str[10]);
749     ok(!strcmp(ret->str[11], "Donnerstag"), "ret->str[11] = %s\n", ret->str[11]);
750     ok(!strcmp(ret->str[12], "Freitag"), "ret->str[12] = %s\n", ret->str[12]);
751     ok(!strcmp(ret->str[13], "Samstag"), "ret->str[13] = %s\n", ret->str[13]);
752     ok(!strcmp(ret->str[14], "Jan"), "ret->str[14] = %s\n", ret->str[14]);
753     ok(!strcmp(ret->str[15], "Feb"), "ret->str[15] = %s\n", ret->str[15]);
754     ok(!strcmp(ret->str[16], "Mrz"), "ret->str[16] = %s\n", ret->str[16]);
755     ok(!strcmp(ret->str[17], "Apr"), "ret->str[17] = %s\n", ret->str[17]);
756     ok(!strcmp(ret->str[18], "Mai"), "ret->str[18] = %s\n", ret->str[18]);
757     ok(!strcmp(ret->str[19], "Jun"), "ret->str[19] = %s\n", ret->str[19]);
758     ok(!strcmp(ret->str[20], "Jul"), "ret->str[20] = %s\n", ret->str[20]);
759     ok(!strcmp(ret->str[21], "Aug"), "ret->str[21] = %s\n", ret->str[21]);
760     ok(!strcmp(ret->str[22], "Sep"), "ret->str[22] = %s\n", ret->str[22]);
761     ok(!strcmp(ret->str[23], "Okt"), "ret->str[23] = %s\n", ret->str[23]);
762     ok(!strcmp(ret->str[24], "Nov"), "ret->str[24] = %s\n", ret->str[24]);
763     ok(!strcmp(ret->str[25], "Dez"), "ret->str[25] = %s\n", ret->str[25]);
764     ok(!strcmp(ret->str[26], "Januar"), "ret->str[26] = %s\n", ret->str[26]);
765     ok(!strcmp(ret->str[27], "Februar"), "ret->str[27] = %s\n", ret->str[27]);
766     ok(!strcmp(ret->str[29], "April"), "ret->str[29] = %s\n", ret->str[29]);
767     ok(!strcmp(ret->str[30], "Mai"), "ret->str[30] = %s\n", ret->str[30]);
768     ok(!strcmp(ret->str[31], "Juni"), "ret->str[31] = %s\n", ret->str[31]);
769     ok(!strcmp(ret->str[32], "Juli"), "ret->str[32] = %s\n", ret->str[32]);
770     ok(!strcmp(ret->str[33], "August"), "ret->str[33] = %s\n", ret->str[33]);
771     ok(!strcmp(ret->str[34], "September"), "ret->str[34] = %s\n", ret->str[34]);
772     ok(!strcmp(ret->str[35], "Oktober"), "ret->str[35] = %s\n", ret->str[35]);
773     ok(!strcmp(ret->str[36], "November"), "ret->str[36] = %s\n", ret->str[36]);
774     ok(!strcmp(ret->str[37], "Dezember"), "ret->str[37] = %s\n", ret->str[37]);
775     ok(!strcmp(ret->str[38], ""), "ret->str[38] = %s\n", ret->str[38]);
776     ok(!strcmp(ret->str[39], ""), "ret->str[39] = %s\n", ret->str[39]);
777     ok(!strcmp(ret->str[40], "dd.MM.yyyy") || broken(!strcmp(ret->str[40], "dd.MM.yy"))/*NT*/,
778             "ret->str[40] = %s\n", ret->str[40]);
779     ok(!strcmp(ret->str[41], "dddd, d. MMMM yyyy"), "ret->str[41] = %s\n", ret->str[41]);
780     free(ret);
781 
782     setlocale(LC_ALL, "C");
783 }
784 
785 static void test___mb_cur_max_func(void)
786 {
787     int mb_cur_max;
788 
789     setlocale(LC_ALL, "C");
790 
791     /* for newer Windows */
792     if(!p___mb_cur_max_func)
793         win_skip("Skipping ___mb_cur_max_func tests\n");
794     else {
795         mb_cur_max = p___mb_cur_max_func();
796         ok(mb_cur_max == 1, "mb_cur_max = %d, expected 1\n", mb_cur_max);
797 
798         /* some old Windows don't set chinese */
799         if (!setlocale(LC_ALL, "chinese"))
800             win_skip("Skipping test with chinese locale\n");
801         else {
802             mb_cur_max = p___mb_cur_max_func();
803             ok(mb_cur_max == 2, "mb_cur_max = %d, expected 2\n", mb_cur_max);
804             setlocale(LC_ALL, "C");
805         }
806     }
807 
808     /* for older Windows */
809     if (!p__p___mb_cur_max)
810         win_skip("Skipping __p___mb_cur_max tests\n");
811     else {
812         mb_cur_max = *p__p___mb_cur_max();
813         ok(mb_cur_max == 1, "mb_cur_max = %d, expected 1\n", mb_cur_max);
814 
815         /* some old Windows don't set chinese */
816         if (!setlocale(LC_ALL, "chinese"))
817             win_skip("Skipping test with chinese locale\n");
818         else {
819             mb_cur_max = *p__p___mb_cur_max();
820             ok(mb_cur_max == 2, "mb_cur_max = %d, expected 2\n", mb_cur_max);
821             setlocale(LC_ALL, "C");
822         }
823     }
824 }
825 
826 START_TEST(locale)
827 {
828     init();
829 
830     test_crtGetStringTypeW();
831     test_setlocale();
832     test__Gettnames();
833     test___mb_cur_max_func();
834 }
835