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 <locale.h>
22 #include <process.h>
23 
24 #include "wine/test.h"
25 #include "winnls.h"
26 
27 static BOOL (__cdecl *p__crtGetStringTypeW)(DWORD, DWORD, const wchar_t*, int, WORD*);
28 static int (__cdecl *pmemcpy_s)(void *, size_t, void*, size_t);
29 static int (__cdecl *p___mb_cur_max_func)(void);
30 static int *(__cdecl *p__p___mb_cur_max)(void);
31 static _locale_t(__cdecl *p_create_locale)(int, const char*);
32 static void(__cdecl *p_free_locale)(_locale_t);
33 static int (__cdecl *p_wcsicmp_l)(const wchar_t*, const wchar_t*, _locale_t);
34 void* __cdecl _Gettnames(void);
35 
36 static void init(void)
37 {
38     HMODULE hmod = GetModuleHandleA("msvcrt.dll");
39 
40     p__crtGetStringTypeW = (void*)GetProcAddress(hmod, "__crtGetStringTypeW");
41     pmemcpy_s = (void*)GetProcAddress(hmod, "memcpy_s");
42     p___mb_cur_max_func = (void*)GetProcAddress(hmod, "___mb_cur_max_func");
43     p__p___mb_cur_max = (void*)GetProcAddress(hmod, "__p___mb_cur_max");
44     p_create_locale = (void*)GetProcAddress(hmod, "_create_locale");
45     p_free_locale = (void*)GetProcAddress(hmod, "_free_locale");
46     p_wcsicmp_l = (void*)GetProcAddress(hmod, "_wcsicmp_l");
47 }
48 
49 static void test_setlocale(void)
50 {
51     static const char lc_all[] = "LC_COLLATE=C;LC_CTYPE=C;"
52         "LC_MONETARY=Greek_Greece.1253;LC_NUMERIC=Polish_Poland.1250;LC_TIME=C";
53 
54     char *ret, buf[100];
55     char *ptr;
56     int len;
57 
58     ret = setlocale(20, "C");
59     ok(ret == NULL, "ret = %s\n", ret);
60 
61     ret = setlocale(LC_ALL, "C");
62     ok(!strcmp(ret, "C"), "ret = %s\n", ret);
63 
64     ret = setlocale(LC_ALL, NULL);
65     ok(!strcmp(ret, "C"), "ret = %s\n", ret);
66 
67     if(!setlocale(LC_NUMERIC, "Polish")
68             || !setlocale(LC_NUMERIC, "Greek")
69             || !setlocale(LC_NUMERIC, "German")
70             || !setlocale(LC_NUMERIC, "English")) {
71         win_skip("System with limited locales\n");
72         return;
73     }
74 
75     ret = setlocale(LC_NUMERIC, "Polish");
76     ok(!strcmp(ret, "Polish_Poland.1250"), "ret = %s\n", ret);
77 
78     ret = setlocale(LC_MONETARY, "Greek");
79     ok(!strcmp(ret, "Greek_Greece.1253"), "ret = %s\n", ret);
80 
81     ret = setlocale(LC_ALL, NULL);
82     ok(!strcmp(ret, lc_all), "ret = %s\n", ret);
83 
84     strcpy(buf, ret);
85     ret = setlocale(LC_ALL, buf);
86     ok(!strcmp(ret, lc_all), "ret = %s\n", ret);
87 
88     ret = setlocale(LC_ALL, "German");
89     ok(!strcmp(ret, "German_Germany.1252"), "ret = %s\n", ret);
90 
91     ret = setlocale(LC_ALL, "american");
92     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
93     if(ret)
94         ok(!strcmp(ret, "English_United States.1252"), "ret = %s\n", ret);
95 
96     ret = setlocale(LC_ALL, "american english");
97     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
98     if(ret)
99         ok(!strcmp(ret, "English_United States.1252"), "ret = %s\n", ret);
100 
101     ret = setlocale(LC_ALL, "american-english");
102     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
103     if(ret)
104         ok(!strcmp(ret, "English_United States.1252"), "ret = %s\n", ret);
105 
106     ret = setlocale(LC_ALL, "australian");
107     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
108     if(ret)
109         ok(!strcmp(ret, "English_Australia.1252"), "ret = %s\n", ret);
110 
111     ret = setlocale(LC_ALL, "belgian");
112     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
113     if(ret)
114         ok(!strcmp(ret, "Dutch_Belgium.1252"), "ret = %s\n", ret);
115 
116     ret = setlocale(LC_ALL, "canadian");
117     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
118     if(ret)
119         ok(!strcmp(ret, "English_Canada.1252"), "ret = %s\n", ret);
120 
121     ret = setlocale(LC_ALL, "chinese");
122     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
123     if(ret)
124         ok(!strcmp(ret, "Chinese (Simplified)_People's Republic of China.936")
125         || !strcmp(ret, "Chinese (Simplified)_China.936")
126         || broken(!strcmp(ret, "Chinese_Taiwan.950")), "ret = %s\n", ret);
127 
128     ret = setlocale(LC_ALL, "chinese-simplified");
129     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
130     if(ret)
131         ok(!strcmp(ret, "Chinese (Simplified)_People's Republic of China.936")
132         || !strcmp(ret, "Chinese (Simplified)_China.936")
133         || broken(!strcmp(ret, "Chinese_People's Republic of China.936"))
134         || broken(!strcmp(ret, "Chinese_Taiwan.950")), "ret = %s\n", ret);
135 
136     ret = setlocale(LC_ALL, "chinese-traditional");
137     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
138     if(ret)
139         ok(!strcmp(ret, "Chinese (Traditional)_Taiwan.950")
140         || broken(!strcmp(ret, "Chinese_Taiwan.950")), "ret = %s\n", ret);
141 
142     ret = setlocale(LC_ALL, "chs");
143     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
144     if(ret)
145         ok(!strcmp(ret, "Chinese (Simplified)_People's Republic of China.936")
146         || !strcmp(ret, "Chinese (Simplified)_China.936")
147         || broken(!strcmp(ret, "Chinese_People's Republic of China.936")), "ret = %s\n", ret);
148 
149     ret = setlocale(LC_ALL, "cht");
150     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
151     if(ret)
152         ok(!strcmp(ret, "Chinese (Traditional)_Taiwan.950")
153         || broken(!strcmp(ret, "Chinese_Taiwan.950")), "ret = %s\n", ret);
154 
155     ret = setlocale(LC_ALL, "Chinese_China.936");
156     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
157     if(ret)
158     {
159         trace("Chinese_China.936=%s\n", ret);
160         ok(!strcmp(ret, "Chinese (Simplified)_People's Republic of China.936") /* Vista - Win7 */
161         || !strcmp(ret, "Chinese (Simplified)_China.936") /* Win8 - Win10 */
162         || broken(!strcmp(ret, "Chinese_People's Republic of China.936")), "ret = %s\n", ret);
163     }
164 
165     ret = setlocale(LC_ALL, "csy");
166     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
167     if(ret)
168         ok(!strcmp(ret, "Czech_Czech Republic.1250")
169         || !strcmp(ret, "Czech_Czechia.1250"), "ret = %s\n", ret);
170 
171     ret = setlocale(LC_ALL, "czech");
172     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
173     if(ret)
174         ok(!strcmp(ret, "Czech_Czech Republic.1250")
175         || !strcmp(ret, "Czech_Czechia.1250"), "ret = %s\n", ret);
176 
177     ret = setlocale(LC_ALL, "dan");
178     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
179     if(ret)
180         ok(!strcmp(ret, "Danish_Denmark.1252"), "ret = %s\n", ret);
181 
182     ret = setlocale(LC_ALL, "danish");
183     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
184     if(ret)
185         ok(!strcmp(ret, "Danish_Denmark.1252"), "ret = %s\n", ret);
186 
187     ret = setlocale(LC_ALL, "dea");
188     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
189     if(ret)
190         ok(!strcmp(ret, "German_Austria.1252"), "ret = %s\n", ret);
191 
192     ret = setlocale(LC_ALL, "des");
193     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
194     if(ret)
195         ok(!strcmp(ret, "German_Switzerland.1252"), "ret = %s\n", ret);
196 
197     ret = setlocale(LC_ALL, "deu");
198     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
199     if(ret)
200         ok(!strcmp(ret, "German_Germany.1252"), "ret = %s\n", ret);
201 
202     ret = setlocale(LC_ALL, "dutch");
203     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
204     if(ret)
205         ok(!strcmp(ret, "Dutch_Netherlands.1252"), "ret = %s\n", ret);
206 
207     ret = setlocale(LC_ALL, "dutch-belgian");
208     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
209     if(ret)
210         ok(!strcmp(ret, "Dutch_Belgium.1252")
211         || broken(!strcmp(ret, "Dutch_Netherlands.1252")), "ret = %s\n", ret);
212 
213     ret = setlocale(LC_ALL, "ena");
214     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
215     if(ret)
216         ok(!strcmp(ret, "English_Australia.1252")
217         || broken(!strcmp(ret, "English_United States.1252")), "ret = %s\n", ret);
218 
219     ret = setlocale(LC_ALL, "ell");
220     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
221     if(ret)
222         ok(!strcmp(ret, "Greek_Greece.1253"), "ret = %s\n", ret);
223 
224     ret = setlocale(LC_ALL, "enc");
225     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
226     if(ret)
227         ok(!strcmp(ret, "English_Canada.1252")
228         || broken(!strcmp(ret, "English_United States.1252")), "ret = %s\n", ret);
229 
230     ret = setlocale(LC_ALL, "eng");
231     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
232     if(ret)
233         ok(!strcmp(ret, "English_United Kingdom.1252")
234         || broken(!strcmp(ret, "English_United States.1252")), "ret = %s\n", ret);
235 
236     ret = setlocale(LC_ALL, "enu");
237     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
238     if(ret)
239         ok(!strcmp(ret, "English_United States.1252"), "ret = %s\n", ret);
240 
241     ret = setlocale(LC_ALL, "enz");
242     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
243     if(ret)
244         ok(!strcmp(ret, "English_New Zealand.1252")
245         || broken(!strcmp(ret, "English_United States.1252")), "ret = %s\n", ret);
246 
247     ret = setlocale(LC_ALL, "english");
248     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
249     if(ret)
250         ok(!strcmp(ret, "English_United States.1252"), "ret = %s\n", ret);
251 
252     ret = setlocale(LC_ALL, "english-american");
253     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
254     if(ret)
255         ok(!strcmp(ret, "English_United States.1252"), "ret = %s\n", ret);
256 
257     ret = setlocale(LC_ALL, "english-aus");
258     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
259     if(ret)
260         ok(!strcmp(ret, "English_Australia.1252")
261         || broken(!strcmp(ret, "English_United States.1252")), "ret = %s\n", ret);
262 
263     ret = setlocale(LC_ALL, "english-can");
264     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
265     if(ret)
266         ok(!strcmp(ret, "English_Canada.1252")
267         || broken(!strcmp(ret, "English_United States.1252")), "ret = %s\n", ret);
268 
269     ret = setlocale(LC_ALL, "english-nz");
270     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
271     if(ret)
272         ok(!strcmp(ret, "English_New Zealand.1252")
273         || broken(!strcmp(ret, "English_United States.1252")), "ret = %s\n", ret);
274 
275     ret = setlocale(LC_ALL, "english-uk");
276     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
277     if(ret)
278         ok(!strcmp(ret, "English_United Kingdom.1252")
279         || broken(!strcmp(ret, "English_United States.1252")), "ret = %s\n", ret);
280 
281     ret = setlocale(LC_ALL, "english-us");
282     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
283     if(ret)
284         ok(!strcmp(ret, "English_United States.1252"), "ret = %s\n", ret);
285 
286     ret = setlocale(LC_ALL, "english-usa");
287     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
288     if(ret)
289         ok(!strcmp(ret, "English_United States.1252"), "ret = %s\n", ret);
290 
291     ret = setlocale(LC_ALL, "esm");
292     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
293     if(ret)
294         ok(!strcmp(ret, "Spanish_Mexico.1252"), "ret = %s\n", ret);
295 
296     ret = setlocale(LC_ALL, "esn");
297     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
298     if(ret)
299         ok(!strcmp(ret, "Spanish_Spain.1252")
300         || broken(!strcmp(ret, "Spanish - Modern Sort_Spain.1252")), "ret = %s\n", ret);
301 
302     ret = setlocale(LC_ALL, "esp");
303     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
304     if(ret)
305         ok(!strcmp(ret, "Spanish_Spain.1252")
306         || broken(!strcmp(ret, "Spanish - Traditional Sort_Spain.1252")), "ret = %s\n", ret);
307 
308     ret = setlocale(LC_ALL, "fin");
309     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
310     if(ret)
311         ok(!strcmp(ret, "Finnish_Finland.1252"), "ret = %s\n", ret);
312 
313     ret = setlocale(LC_ALL, "finnish");
314     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
315     if(ret)
316         ok(!strcmp(ret, "Finnish_Finland.1252"), "ret = %s\n", ret);
317 
318     ret = setlocale(LC_ALL, "fra");
319     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
320     if(ret)
321         ok(!strcmp(ret, "French_France.1252"), "ret = %s\n", ret);
322 
323     ret = setlocale(LC_ALL, "frb");
324     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
325     if(ret)
326         ok(!strcmp(ret, "French_Belgium.1252")
327         || broken(!strcmp(ret, "French_France.1252")), "ret = %s\n", ret);
328 
329     ret = setlocale(LC_ALL, "frc");
330     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
331     if(ret)
332         ok(!strcmp(ret, "French_Canada.1252")
333         || broken(!strcmp(ret, "French_France.1252")), "ret = %s\n", ret);
334 
335     ret = setlocale(LC_ALL, "french");
336     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
337     if(ret)
338         ok(!strcmp(ret, "French_France.1252"), "ret = %s\n", ret);
339 
340     ret = setlocale(LC_ALL, "french-belgian");
341     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
342     if(ret)
343         ok(!strcmp(ret, "French_Belgium.1252")
344         || broken(!strcmp(ret, "French_France.1252")), "ret = %s\n", ret);
345 
346     ret = setlocale(LC_ALL, "french-canadian");
347     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
348     if(ret)
349         ok(!strcmp(ret, "French_Canada.1252")
350         || broken(!strcmp(ret, "French_France.1252")), "ret = %s\n", ret);
351 
352     ret = setlocale(LC_ALL, "french-swiss");
353     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
354     if(ret)
355         ok(!strcmp(ret, "French_Switzerland.1252")
356         || broken(!strcmp(ret, "French_France.1252")), "ret = %s\n", ret);
357 
358     ret = setlocale(LC_ALL, "frs");
359     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
360     if(ret)
361         ok(!strcmp(ret, "French_Switzerland.1252")
362         || broken(!strcmp(ret, "French_France.1252")), "ret = %s\n", ret);
363 
364     ret = setlocale(LC_ALL, "german");
365     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
366     if(ret)
367         ok(!strcmp(ret, "German_Germany.1252"), "ret = %s\n", ret);
368 
369     ret = setlocale(LC_ALL, "german-austrian");
370     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
371     if(ret)
372         ok(!strcmp(ret, "German_Austria.1252")
373         || broken(!strcmp(ret, "German_Germany.1252")), "ret = %s\n", ret);
374 
375     ret = setlocale(LC_ALL, "german-swiss");
376     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
377     if(ret)
378         ok(!strcmp(ret, "German_Switzerland.1252")
379         || broken(!strcmp(ret, "German_Germany.1252")), "ret = %s\n", ret);
380 
381     ret = setlocale(LC_ALL, "greek");
382     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
383     if(ret)
384         ok(!strcmp(ret, "Greek_Greece.1253"), "ret = %s\n", ret);
385 
386     ret = setlocale(LC_ALL, "hun");
387     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
388     if(ret)
389         ok(!strcmp(ret, "Hungarian_Hungary.1250"), "ret = %s\n", ret);
390 
391     ret = setlocale(LC_ALL, "hungarian");
392     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
393     if(ret)
394         ok(!strcmp(ret, "Hungarian_Hungary.1250"), "ret = %s\n", ret);
395 
396     ret = setlocale(LC_ALL, "icelandic");
397     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
398     if(ret)
399         ok(!strcmp(ret, "Icelandic_Iceland.1252"), "ret = %s\n", ret);
400 
401     ret = setlocale(LC_ALL, "isl");
402     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
403     if(ret)
404         ok(!strcmp(ret, "Icelandic_Iceland.1252"), "ret = %s\n", ret);
405 
406     ret = setlocale(LC_ALL, "ita");
407     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
408     if(ret)
409         ok(!strcmp(ret, "Italian_Italy.1252"), "ret = %s\n", ret);
410 
411     ret = setlocale(LC_ALL, "italian");
412     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
413     if(ret)
414         ok(!strcmp(ret, "Italian_Italy.1252"), "ret = %s\n", ret);
415 
416     ret = setlocale(LC_ALL, "italian-swiss");
417     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
418     if(ret)
419         ok(!strcmp(ret, "Italian_Switzerland.1252")
420         || broken(!strcmp(ret, "Italian_Italy.1252")), "ret = %s\n", ret);
421 
422     ret = setlocale(LC_ALL, "its");
423     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
424     if(ret)
425         ok(!strcmp(ret, "Italian_Switzerland.1252")
426         || broken(!strcmp(ret, "Italian_Italy.1252")), "ret = %s\n", ret);
427 
428     ret = setlocale(LC_ALL, "japanese");
429     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
430     if(ret)
431         ok(!strcmp(ret, "Japanese_Japan.932"), "ret = %s\n", ret);
432 
433     ret = setlocale(LC_ALL, "jpn");
434     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
435     if(ret)
436         ok(!strcmp(ret, "Japanese_Japan.932"), "ret = %s\n", ret);
437 
438     ret = setlocale(LC_ALL, "korean");
439     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
440     if(ret)
441         ok(!strcmp(ret, "Korean_Korea.949"), "ret = %s\n", ret);
442 
443     ret = setlocale(LC_ALL, "korean");
444     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
445     if(ret)
446         ok(!strcmp(ret, "Korean_Korea.949"), "ret = %s\n", ret);
447 
448     ret = setlocale(LC_ALL, "nlb");
449     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
450     if(ret)
451         ok(!strcmp(ret, "Dutch_Belgium.1252")
452         || broken(!strcmp(ret, "Dutch_Netherlands.1252")), "ret = %s\n", ret);
453 
454     ret = setlocale(LC_ALL, "nld");
455     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
456     if(ret)
457         ok(!strcmp(ret, "Dutch_Netherlands.1252"), "ret = %s\n", ret);
458 
459     ret = setlocale(LC_ALL, "non");
460     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
461     if(ret)
462         ok(!strcmp( ret, "Norwegian-Nynorsk_Norway.1252") /* XP - Win10 */
463         || !strcmp(ret, "Norwegian (Nynorsk)_Norway.1252")
464         || broken(!strcmp(ret, "Norwegian (Bokm\xe5l)_Norway.1252"))
465         || broken(!strcmp(ret, "Norwegian_Norway.1252")), /* WinME */
466            "ret = %s\n", ret);
467 
468     ret = setlocale(LC_ALL, "nor");
469     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
470     if(ret)
471         ok(!strcmp(ret, "Norwegian (Bokm\xe5l)_Norway.1252") /* XP - Win8 */
472         || !strcmp(ret, "Norwegian Bokm\xe5l_Norway.1252") /* Win10 */
473         || !strcmp(ret, "Norwegian (Bokmal)_Norway.1252")
474         || broken(!strcmp(ret, "Norwegian_Norway.1252")), /* WinME */
475            "ret = %s\n", ret);
476 
477     ret = setlocale(LC_ALL, "norwegian-bokmal");
478     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
479     if(ret)
480         ok(!strcmp(ret, "Norwegian (Bokm\xe5l)_Norway.1252") /* XP - Win8 */
481         || !strcmp(ret, "Norwegian Bokm\xe5l_Norway.1252") /* Win10 */
482         || !strcmp(ret, "Norwegian (Bokmal)_Norway.1252")
483         || broken(!strcmp(ret, "Norwegian_Norway.1252")), /* WinME */
484            "ret = %s\n", ret);
485 
486     ret = setlocale(LC_ALL, "norwegian-nynorsk");
487     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
488     if(ret)
489         ok(!strcmp(ret, "Norwegian-Nynorsk_Norway.1252") /* Vista - Win10 */
490         || !strcmp(ret, "Norwegian (Nynorsk)_Norway.1252")
491         || broken(!strcmp(ret, "Norwegian_Norway.1252")) /* WinME */
492         || broken(!strcmp(ret, "Norwegian (Bokmal)_Norway.1252"))
493         || broken(!strcmp(ret, "Norwegian (Bokm\xe5l)_Norway.1252")) /* XP & 2003 */,
494            "ret = %s\n", ret);
495 
496     ret = setlocale(LC_ALL, "plk");
497     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
498     if(ret)
499         ok(!strcmp(ret, "Polish_Poland.1250"), "ret = %s\n", ret);
500 
501     ret = setlocale(LC_ALL, "polish");
502     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
503     if(ret)
504         ok(!strcmp(ret, "Polish_Poland.1250"), "ret = %s\n", ret);
505 
506     ret = setlocale(LC_ALL, "portuguese");
507     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
508     if(ret)
509         ok(!strcmp(ret, "Portuguese_Brazil.1252")
510         || broken(!strcmp(ret, "Portuguese_Portugal.1252")) /* NT4 */, "ret = %s\n", ret);
511 
512     ret = setlocale(LC_ALL, "portuguese-brazil");
513     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
514     if(ret)
515         ok(!strcmp(ret, "Portuguese_Brazil.1252"), "ret = %s\n", ret);
516 
517     ret = setlocale(LC_ALL, "ptb");
518     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
519     if(ret)
520         ok(!strcmp(ret, "Portuguese_Brazil.1252"), "ret = %s\n", ret);
521 
522     ret = setlocale(LC_ALL, "ptg");
523     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
524     if(ret)
525         ok(!strcmp(ret, "Portuguese_Portugal.1252"), "ret = %s\n", ret);
526 
527     ret = setlocale(LC_ALL, "rus");
528     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
529     if(ret)
530         ok(!strcmp(ret, "Russian_Russia.1251"), "ret = %s\n", ret);
531 
532     ret = setlocale(LC_ALL, "russian");
533     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
534     if(ret)
535         ok(!strcmp(ret, "Russian_Russia.1251"), "ret = %s\n", ret);
536 
537     ret = setlocale(LC_ALL, "sky");
538     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
539     if(ret)
540         ok(!strcmp(ret, "Slovak_Slovakia.1250"), "ret = %s\n", ret);
541 
542     ret = setlocale(LC_ALL, "slovak");
543     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
544     if(ret)
545         ok(!strcmp(ret, "Slovak_Slovakia.1250"), "ret = %s\n", ret);
546 
547     ret = setlocale(LC_ALL, "spanish");
548     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
549     if(ret)
550         ok(!strcmp(ret, "Spanish_Spain.1252")
551         || broken(!strcmp(ret, "Spanish - Traditional Sort_Spain.1252")), "ret = %s\n", ret);
552 
553     ret = setlocale(LC_ALL, "spanish-mexican");
554     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
555     if(ret)
556         ok(!strcmp(ret, "Spanish_Mexico.1252")
557         || broken(!strcmp(ret, "Spanish_Spain.1252")), "ret = %s\n", ret);
558 
559     ret = setlocale(LC_ALL, "spanish-modern");
560     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
561     if(ret)
562         ok(!strcmp(ret, "Spanish - Modern Sort_Spain.1252")
563            || !strcmp(ret, "Spanish_Spain.1252"), "ret = %s\n", ret);
564 
565     ret = setlocale(LC_ALL, "sve");
566     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
567     if(ret)
568         ok(!strcmp(ret, "Swedish_Sweden.1252"), "ret = %s\n", ret);
569 
570     ret = setlocale(LC_ALL, "swedish");
571     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
572     if(ret)
573         ok(!strcmp(ret, "Swedish_Sweden.1252"), "ret = %s\n", ret);
574 
575     ret = setlocale(LC_ALL, "swiss");
576     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
577     if(ret)
578         ok(!strcmp(ret, "German_Switzerland.1252"), "ret = %s\n", ret);
579 
580     ret = setlocale(LC_ALL, "trk");
581     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
582     if(ret)
583         ok(!strcmp(ret, "Turkish_Turkey.1254")
584         || !strcmp(ret, "Turkish_T\xfcrkiye.1254"), "ret = %s\n", ret);
585 
586     ret = setlocale(LC_ALL, "turkish");
587     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
588     if(ret)
589         ok(!strcmp(ret, "Turkish_Turkey.1254")
590         || !strcmp(ret, "Turkish_T\xfcrkiye.1254"), "ret = %s\n", ret);
591 
592     ret = setlocale(LC_ALL, "uk");
593     ok(ret != NULL, "ret == NULL\n");
594     if(ret)
595         ok(!strcmp(ret, "English_United Kingdom.1252")
596         || broken(!strcmp(ret, "Ukrainian_Ukraine.1251")), "ret = %s\n", ret);
597 
598     ret = setlocale(LC_ALL, "us");
599     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
600     if(ret)
601         ok(!strcmp(ret, "English_United States.1252"), "ret = %s\n", ret);
602 
603     ret = setlocale(LC_ALL, "usa");
604     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
605     if(ret)
606         ok(!strcmp(ret, "English_United States.1252"), "ret = %s\n", ret);
607 
608     ret = setlocale(LC_ALL, "English_United States.ACP");
609     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
610     if(ret) {
611         strcpy(buf, "English_United States.");
612         GetLocaleInfoA(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT),
613                 LOCALE_IDEFAULTANSICODEPAGE, buf+strlen(buf), 80);
614         ok(!strcmp(ret, buf), "ret = %s, expected %s\n", ret, buf);
615     }
616 
617     ret = setlocale(LC_ALL, "English_United States.OCP");
618     ok(ret != NULL || broken (ret == NULL), "ret == NULL\n");
619     if(ret) {
620         strcpy(buf, "English_United States.");
621         GetLocaleInfoA(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT),
622                 LOCALE_IDEFAULTCODEPAGE, buf+strlen(buf), 80);
623         ok(!strcmp(ret, buf), "ret = %s, expected %s\n", ret, buf);
624     }
625 
626     GetLocaleInfoA(GetUserDefaultLCID(), LOCALE_IDEFAULTCODEPAGE, buf, sizeof(buf));
627     if(IsValidCodePage(atoi(buf))) {
628         ret = setlocale(LC_ALL, ".OCP");
629         ok(ret != NULL, "ret == NULL\n");
630 #ifdef __REACTOS__
631         if (ret == NULL) ptr = NULL; else
632 #endif
633         ptr = strchr(ret, '.');
634         ok(ptr && !strcmp(ptr + 1, buf), "ret %s, buf %s.\n", ret, buf);
635     }
636 
637     len = GetLocaleInfoA(GetUserDefaultLCID(), LOCALE_IDEFAULTANSICODEPAGE, buf, sizeof(buf)) - 1;
638     if(buf[0] == '0' && !buf[1])
639         len = sprintf(buf, "%d", GetACP());
640     ret = setlocale(LC_ALL, ".ACP");
641     ok(ret != NULL, "ret == NULL\n");
642 #ifdef __REACTOS__
643     if (ret == NULL) ptr = NULL; else
644 #endif
645     ptr = strchr(ret, '.');
646     ok(ptr && !strncmp(ptr + 1, buf, len), "ret %s, buf %s.\n", ret, buf);
647 
648     ret = setlocale(LC_ALL, ".1250");
649     ok(ret != NULL, "ret == NULL\n");
650     ptr = strchr(ret, '.');
651     ok(ptr && !strcmp(ptr, ".1250"), "ret %s, buf %s.\n", ret, buf);
652 
653     ret = setlocale(LC_ALL, "English_United States.UTF8");
654     ok(ret == NULL, "ret != NULL\n");
655 
656     ret = setlocale(LC_ALL, "en-US");
657     ok(ret == NULL || broken (ret != NULL), "ret != NULL\n"); /* XP & 2003 */
658 }
659 
660 static void test_crtGetStringTypeW(void)
661 {
662     const wchar_t *str[] = { L"0", L"A", L" ", L"\0", L"\x04d2" };
663 
664     WORD out_crt, out;
665     BOOL ret_crt, ret;
666     int i;
667 
668     if(!p__crtGetStringTypeW) {
669         win_skip("Skipping __crtGetStringTypeW tests\n");
670         return;
671     }
672 
673     if(!pmemcpy_s) {
674         win_skip("Too old version of msvcrt.dll\n");
675         return;
676     }
677 
678     for(i=0; i<ARRAY_SIZE(str); i++) {
679         ret_crt = p__crtGetStringTypeW(0, CT_CTYPE1, str[i], 1, &out_crt);
680         ret = GetStringTypeW(CT_CTYPE1, str[i], 1, &out);
681         ok(ret == ret_crt, "%d) ret_crt = %d\n", i, (int)ret_crt);
682         ok(out == out_crt, "%d) out_crt = %x, expected %x\n", i, (int)out_crt, (int)out);
683 
684         ret_crt = p__crtGetStringTypeW(0, CT_CTYPE2, str[i], 1, &out_crt);
685         ret = GetStringTypeW(CT_CTYPE2, str[i], 1, &out);
686         ok(ret == ret_crt, "%d) ret_crt = %d\n", i, (int)ret_crt);
687         ok(out == out_crt, "%d) out_crt = %x, expected %x\n", i, (int)out_crt, (int)out);
688 
689         ret_crt = p__crtGetStringTypeW(0, CT_CTYPE3, str[i], 1, &out_crt);
690         ret = GetStringTypeW(CT_CTYPE3, str[i], 1, &out);
691         ok(ret == ret_crt, "%d) ret_crt = %d\n", i, (int)ret_crt);
692         ok(out == out_crt, "%d) out_crt = %x, expected %x\n", i, (int)out_crt, (int)out);
693     }
694 
695     ret = p__crtGetStringTypeW(0, 3, str[0], 1, &out);
696     ok(!ret, "ret == TRUE\n");
697 }
698 
699 static void test__Gettnames(void)
700 {
701     static const DWORD time_data[] = {
702         LOCALE_SABBREVDAYNAME7, LOCALE_SABBREVDAYNAME1, LOCALE_SABBREVDAYNAME2,
703         LOCALE_SABBREVDAYNAME3, LOCALE_SABBREVDAYNAME4, LOCALE_SABBREVDAYNAME5,
704         LOCALE_SABBREVDAYNAME6,
705         LOCALE_SDAYNAME7, LOCALE_SDAYNAME1, LOCALE_SDAYNAME2, LOCALE_SDAYNAME3,
706         LOCALE_SDAYNAME4, LOCALE_SDAYNAME5, LOCALE_SDAYNAME6,
707         LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2, LOCALE_SABBREVMONTHNAME3,
708         LOCALE_SABBREVMONTHNAME4, LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
709         LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8, LOCALE_SABBREVMONTHNAME9,
710         LOCALE_SABBREVMONTHNAME10, LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12,
711         LOCALE_SMONTHNAME1, LOCALE_SMONTHNAME2, LOCALE_SMONTHNAME3, LOCALE_SMONTHNAME4,
712         LOCALE_SMONTHNAME5, LOCALE_SMONTHNAME6, LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME8,
713         LOCALE_SMONTHNAME9, LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME11, LOCALE_SMONTHNAME12,
714         LOCALE_S1159, LOCALE_S2359,
715         LOCALE_SSHORTDATE, LOCALE_SLONGDATE,
716         LOCALE_STIMEFORMAT
717     };
718 
719     struct {
720         char *str[43];
721         LCID lcid;
722         int  unk[2];
723         wchar_t *wstr[43];
724         char data[1];
725     } *ret;
726     int size;
727     char buf[64];
728     int i;
729 
730     if(!setlocale(LC_ALL, "english"))
731         return;
732 
733     ret = _Gettnames();
734     size = ret->str[0]-(char*)ret;
735     /* Newer version of the structure stores both ascii and unicode strings.
736      * Unicode strings are only initialized on Windows 7
737      */
738     if(sizeof(void*) == 8)
739         ok(size==0x2c0 || broken(size==0x168), "structure size: %x\n", size);
740     else
741         ok(size==0x164 || broken(size==0xb8), "structure size: %x\n", size);
742 
743     for (i = 0; i < ARRAY_SIZE(time_data); i++)
744     {
745         size = GetLocaleInfoA(MAKELCID(LANG_ENGLISH, SORT_DEFAULT),
746                               time_data[i], buf, sizeof(buf));
747         ok(size, "GetLocaleInfo failed: %lx\n", GetLastError());
748         ok(!strcmp(ret->str[i], buf), "ret->str[%i] = %s, expected %s\n", i, ret->str[i], buf);
749     }
750 
751     ok(ret->wstr[0] != NULL, "ret->wstr[0] = NULL\n");
752     ok(ret->str[42] + strlen(ret->str[42])+1 != (char*)ret->wstr[0],
753             "ret->str[42] = %p len = %Id, ret->wstr[0] = %p\n",
754             ret->str[42], strlen(ret->str[42]), ret->wstr[0]);
755     free(ret);
756 
757     if(!setlocale(LC_TIME, "german"))
758         return;
759 
760     ret = _Gettnames();
761     for (i = 0; i < ARRAY_SIZE(time_data); i++)
762     {
763         size = GetLocaleInfoA(MAKELCID(LANG_GERMAN, SORT_DEFAULT),
764                               time_data[i], buf, sizeof(buf));
765         ok(size, "GetLocaleInfo failed: %lx\n", GetLastError());
766         ok(!strcmp(ret->str[i], buf), "ret->str[%i] = %s, expected %s\n", i, ret->str[i], buf);
767     }
768     free(ret);
769 
770     setlocale(LC_ALL, "C");
771 }
772 
773 static void test___mb_cur_max_func(void)
774 {
775     int mb_cur_max;
776 
777     setlocale(LC_ALL, "C");
778 
779     /* for newer Windows */
780     if(!p___mb_cur_max_func)
781         win_skip("Skipping ___mb_cur_max_func tests\n");
782     else {
783         mb_cur_max = p___mb_cur_max_func();
784         ok(mb_cur_max == 1, "mb_cur_max = %d, expected 1\n", mb_cur_max);
785 
786         /* some old Windows don't set chinese */
787         if (!setlocale(LC_ALL, "chinese"))
788             win_skip("Skipping test with chinese locale\n");
789         else {
790             mb_cur_max = p___mb_cur_max_func();
791             ok(mb_cur_max == 2, "mb_cur_max = %d, expected 2\n", mb_cur_max);
792             setlocale(LC_ALL, "C");
793         }
794     }
795 
796     /* for older Windows */
797     if (!p__p___mb_cur_max)
798         skip("Skipping __p___mb_cur_max tests\n");
799     else {
800         mb_cur_max = *p__p___mb_cur_max();
801         ok(mb_cur_max == 1, "mb_cur_max = %d, expected 1\n", mb_cur_max);
802 
803         /* some old Windows don't set chinese */
804         if (!setlocale(LC_ALL, "chinese"))
805             win_skip("Skipping test with chinese locale\n");
806         else {
807             mb_cur_max = *p__p___mb_cur_max();
808             ok(mb_cur_max == 2, "mb_cur_max = %d, expected 2\n", mb_cur_max);
809             setlocale(LC_ALL, "C");
810         }
811     }
812 }
813 
814 static void test__wcsicmp_l(void)
815 {
816     const struct {
817         const wchar_t *str1;
818         const wchar_t *str2;
819         int exp;
820         const char *loc;
821     } tests[] = {
822         { L"i", L"i",  0 },
823         { L"I", L"i",  0 },
824         { L"I", L"i",  0, "Turkish" },
825         { L"i", L"a",  8 },
826         { L"a", L"i", -8 },
827         { L"i", L"a",  8, "Turkish" },
828     };
829     int ret, i;
830 
831     if (!p_wcsicmp_l || !p_create_locale)
832     {
833         win_skip("_wcsicmp_l or _create_locale not available\n");
834         return;
835     }
836     ok(!!p_free_locale, "_free_locale not available\n");
837 
838     for(i=0; i<ARRAY_SIZE(tests); i++) {
839         _locale_t loc = NULL;
840 
841         if(tests[i].loc && !(loc = p_create_locale(LC_ALL, tests[i].loc))) {
842             win_skip("locale %s not available.  skipping\n", tests[i].loc);
843             continue;
844         }
845 
846         ret = p_wcsicmp_l(tests[i].str1, tests[i].str2, loc);
847         ok(ret == tests[i].exp, "_wcsicmp_l = %d, expected %d for test %d '%ls' vs '%ls' using %s locale\n",
848             ret, tests[i].exp, i, tests[i].str1, tests[i].str2, loc ? tests[i].loc : "current");
849 
850         if(loc)
851             p_free_locale(loc);
852     }
853 }
854 
855 static unsigned __stdcall test_thread_setlocale_func(void *arg)
856 {
857     char *ret;
858 
859     ret = setlocale(LC_ALL, NULL);
860     ok(!strcmp(ret, "C"), "expected ret=C, but received ret=%s\n", ret);
861 
862     ret = setlocale(LC_ALL, "");
863     ok(strcmp(ret, "Invariant Language_Invariant Country.0"), "expected valid locale\n");
864 
865     return 0;
866 }
867 
868 static void test_thread_setlocale(void)
869 {
870     HANDLE hThread;
871 
872     hThread = (HANDLE)_beginthreadex(NULL, 0, test_thread_setlocale_func, NULL, 0, NULL);
873     ok(hThread != INVALID_HANDLE_VALUE, "_beginthread failed (%d)\n", errno);
874     WaitForSingleObject(hThread, 5000);
875     CloseHandle(hThread);
876 }
877 
878 static void test_locale_info(void)
879 {
880     pthreadlocinfo locinfo, locinfo2;
881     _locale_t locale, locale2;
882     int ret;
883 
884     if (!p_create_locale)
885     {
886         win_skip("_create_locale isn't available.\n");
887         return;
888     }
889 
890     if (PRIMARYLANGID(GetUserDefaultLangID()) == LANG_JAPANESE)
891         skip("Skip language-specific tests on Japanese system.\n");
892     else
893     {
894         locale = p_create_locale(LC_ALL, "Japanese_Japan.932");
895         locale2 = p_create_locale(LC_ALL, ".932");
896         locinfo = locale->locinfo;
897         locinfo2 = locale2->locinfo;
898 
899         ok(locinfo->mb_cur_max == locinfo2->mb_cur_max, "Got wrong max char size %d %d.\n",
900                 locinfo->mb_cur_max, locinfo2->mb_cur_max);
901         ok(locinfo->ctype1_refcount != locinfo2->ctype1_refcount, "Got wrong refcount pointer %p vs %p.\n",
902                 locinfo->ctype1_refcount, locinfo2->ctype1_refcount);
903         ok(locinfo->lc_codepage == 932 && locinfo->lc_codepage == locinfo2->lc_codepage,
904                 "Got wrong codepage %d vs %d.\n", locinfo->lc_codepage, locinfo2->lc_codepage);
905         ok(locinfo->lc_id[LC_CTYPE].wCodePage == 932
906                 && locinfo->lc_id[LC_CTYPE].wCodePage == locinfo2->lc_id[LC_CTYPE].wCodePage,
907                 "Got wrong LC_CTYPE codepage %d vs %d.\n", locinfo->lc_id[LC_CTYPE].wCodePage,
908                 locinfo2->lc_id[LC_CTYPE].wCodePage);
909         ret = strcmp(locinfo->lc_category[LC_CTYPE].locale, locinfo2->lc_category[LC_CTYPE].locale);
910         ok(!!ret, "Got locale name %s vs %s.\n", locinfo->lc_category[LC_CTYPE].locale,
911                 locinfo2->lc_category[LC_CTYPE].locale);
912         ret = memcmp(locinfo->ctype1, locinfo2->ctype1, 257 * sizeof(*locinfo->ctype1));
913         ok(!ret, "Got wrong ctype1 data.\n");
914         ret = memcmp(locinfo->pclmap, locinfo2->pclmap, 256 * sizeof(*locinfo->pclmap));
915         ok(!ret, "Got wrong pclmap data.\n");
916         ret = memcmp(locinfo->pcumap, locinfo2->pcumap, 256 * sizeof(*locinfo->pcumap));
917         ok(!ret, "Got wrong pcumap data.\n");
918         ok(locinfo->lc_handle[LC_CTYPE] != locinfo2->lc_handle[LC_CTYPE],
919                 "Got wrong LC_CTYPE %#lx vs %#lx.\n", locinfo->lc_handle[LC_CTYPE], locinfo2->lc_handle[LC_CTYPE]);
920 
921         p_free_locale(locale2);
922         locale2 = p_create_locale(LC_ALL, "Japanese_Japan.1252");
923         locinfo2 = locale2->locinfo;
924 
925         ok(locinfo->mb_cur_max != locinfo2->mb_cur_max, "Got wrong max char size %d %d.\n",
926                 locinfo->mb_cur_max, locinfo2->mb_cur_max);
927         ok(locinfo->ctype1_refcount != locinfo2->ctype1_refcount, "Got wrong refcount pointer %p vs %p.\n",
928                 locinfo->ctype1_refcount, locinfo2->ctype1_refcount);
929         ok(locinfo2->lc_codepage == 1252, "Got wrong codepage %d.\n", locinfo2->lc_codepage);
930         ok(locinfo2->lc_id[LC_CTYPE].wCodePage == 1252, "Got wrong LC_CTYPE codepage %d.\n",
931                 locinfo2->lc_id[LC_CTYPE].wCodePage);
932         ok(locinfo->lc_codepage != locinfo2->lc_codepage, "Got wrong codepage %d vs %d.\n",
933                 locinfo->lc_codepage, locinfo2->lc_codepage);
934         ok(locinfo->lc_id[LC_CTYPE].wCodePage != locinfo2->lc_id[LC_CTYPE].wCodePage,
935                 "Got wrong LC_CTYPE codepage %d vs %d.\n", locinfo->lc_id[LC_CTYPE].wCodePage,
936                 locinfo2->lc_id[LC_CTYPE].wCodePage);
937         ret = strcmp(locinfo->lc_category[LC_CTYPE].locale, locinfo2->lc_category[LC_CTYPE].locale);
938         ok(!!ret, "Got locale name %s vs %s.\n", locinfo->lc_category[LC_CTYPE].locale,
939                 locinfo2->lc_category[LC_CTYPE].locale);
940         ret = memcmp(locinfo->ctype1, locinfo2->ctype1, 257 * sizeof(*locinfo->ctype1));
941         ok(!!ret, "Got wrong ctype1 data.\n");
942         ret = memcmp(locinfo->pclmap, locinfo2->pclmap, 256 * sizeof(*locinfo->pclmap));
943         ok(!!ret, "Got wrong pclmap data.\n");
944         ret = memcmp(locinfo->pcumap, locinfo2->pcumap, 256 * sizeof(*locinfo->pcumap));
945         ok(!!ret, "Got wrong pcumap data.\n");
946         ok(locinfo->lc_handle[LC_CTYPE] == locinfo2->lc_handle[LC_CTYPE],
947                 "Got wrong LC_CTYPE %#lx vs %#lx.\n", locinfo->lc_handle[LC_CTYPE], locinfo2->lc_handle[LC_CTYPE]);
948 
949         p_free_locale(locale2);
950         locale2 = p_create_locale(LC_ALL, "Japanese_Japan.3000"); /* an invalid codepage */
951         ok(!locale2, "Got %p.\n", locale2);
952 
953         p_free_locale(locale);
954     }
955 
956     locale = p_create_locale(LC_ALL, "German_Germany.437");
957     locale2 = p_create_locale(LC_ALL, "German_Germany.1252");
958     locinfo = locale->locinfo;
959     locinfo2 = locale2->locinfo;
960 
961     ok(locinfo->mb_cur_max == locinfo2->mb_cur_max, "Got wrong max char size %d %d.\n",
962             locinfo->mb_cur_max, locinfo2->mb_cur_max);
963     ok(locinfo->ctype1_refcount != locinfo2->ctype1_refcount, "Got wrong refcount pointer %p vs %p.\n",
964             locinfo->ctype1_refcount, locinfo2->ctype1_refcount);
965     ok(locinfo->lc_codepage != locinfo2->lc_codepage, "Got wrong codepage %d vs %d.\n",
966             locinfo->lc_codepage, locinfo2->lc_codepage);
967     ok(locinfo->lc_id[LC_CTYPE].wCodePage != locinfo2->lc_id[LC_CTYPE].wCodePage,
968             "Got wrong LC_CTYPE codepage %d vs %d.\n", locinfo->lc_id[LC_CTYPE].wCodePage,
969             locinfo2->lc_id[LC_CTYPE].wCodePage);
970     ret = strcmp(locinfo->lc_category[LC_CTYPE].locale, locinfo2->lc_category[LC_CTYPE].locale);
971     ok(!!ret, "Got locale name %s vs %s.\n", locinfo->lc_category[LC_CTYPE].locale,
972             locinfo2->lc_category[LC_CTYPE].locale);
973     ret = memcmp(locinfo->ctype1, locinfo2->ctype1, 257 * sizeof(*locinfo->ctype1));
974     ok(!!ret, "Got wrong ctype1 data.\n");
975     ret = memcmp(locinfo->pclmap, locinfo2->pclmap, 256 * sizeof(*locinfo->pclmap));
976     ok(!!ret, "Got wrong pclmap data.\n");
977     ret = memcmp(locinfo->pcumap, locinfo2->pcumap, 256 * sizeof(*locinfo->pcumap));
978     ok(!!ret, "Got wrong pcumap data.\n");
979     ok(locinfo->lc_handle[LC_CTYPE] == locinfo2->lc_handle[LC_CTYPE],
980             "Got wrong LC_CTYPE %#lx vs %#lx.\n", locinfo->lc_handle[LC_CTYPE], locinfo2->lc_handle[LC_CTYPE]);
981 
982     p_free_locale(locale2);
983     p_free_locale(locale);
984 }
985 
986 START_TEST(locale)
987 {
988     init();
989 
990     test_crtGetStringTypeW();
991     test_setlocale();
992     test__Gettnames();
993     test___mb_cur_max_func();
994     test__wcsicmp_l();
995     test_thread_setlocale();
996     test_locale_info();
997 }
998