msvcrt: Use WINAPIV calling convention for variadic functions.
[wine.git] / dlls / msvcr120 / tests / msvcr120.c
blob152bfdf42ee7572d0af9178b0333547db01b5d2e
1 /*
2 * Copyright 2014 Yifu Wang for ESRI
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <errno.h>
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <wchar.h>
23 #include <stdio.h>
24 #include <float.h>
25 #include <limits.h>
27 #include <windef.h>
28 #include <winbase.h>
29 #include <winnls.h>
30 #include "wine/test.h"
31 #include <process.h>
33 #include <locale.h>
35 #ifdef __i386__
36 #include "pshpack1.h"
37 struct thiscall_thunk
39 BYTE pop_eax; /* popl %eax (ret addr) */
40 BYTE pop_edx; /* popl %edx (func) */
41 BYTE pop_ecx; /* popl %ecx (this) */
42 BYTE push_eax; /* pushl %eax */
43 WORD jmp_edx; /* jmp *%edx */
45 #include "poppack.h"
47 static ULONG_PTR (WINAPI *call_thiscall_func1)( void *func, void *this );
48 static ULONG_PTR (WINAPI *call_thiscall_func2)( void *func, void *this, const void *a );
49 static ULONG_PTR (WINAPI *call_thiscall_func3)( void *func,
50 void *this, const void *a, const void *b );
52 static void init_thiscall_thunk(void)
54 struct thiscall_thunk *thunk = VirtualAlloc( NULL, sizeof(*thunk),
55 MEM_COMMIT, PAGE_EXECUTE_READWRITE );
56 thunk->pop_eax = 0x58; /* popl %eax */
57 thunk->pop_edx = 0x5a; /* popl %edx */
58 thunk->pop_ecx = 0x59; /* popl %ecx */
59 thunk->push_eax = 0x50; /* pushl %eax */
60 thunk->jmp_edx = 0xe2ff; /* jmp *%edx */
61 call_thiscall_func1 = (void *)thunk;
62 call_thiscall_func2 = (void *)thunk;
63 call_thiscall_func3 = (void *)thunk;
66 #define call_func1(func,_this) call_thiscall_func1(func,_this)
67 #define call_func2(func,_this,a) call_thiscall_func2(func,_this,(const void*)(a))
68 #define call_func3(func,_this,a,b) call_thiscall_func3(func,_this,(const void*)(a),(const void*)(b))
70 #else
72 #define init_thiscall_thunk()
73 #define call_func1(func,_this) func(_this)
74 #define call_func2(func,_this,a) func(_this,a)
75 #define call_func3(func,_this,a,b) func(_this,a,b)
77 #endif /* __i386__ */
79 #undef __thiscall
80 #ifdef __i386__
81 #define __thiscall __stdcall
82 #else
83 #define __thiscall __cdecl
84 #endif
86 typedef unsigned char MSVCRT_bool;
88 typedef struct cs_queue
90 struct cs_queue *next;
91 BOOL free;
92 int unknown;
93 } cs_queue;
95 typedef struct
97 ULONG_PTR unk_thread_id;
98 cs_queue unk_active;
99 void *unknown[2];
100 cs_queue *head;
101 void *tail;
102 } critical_section;
104 typedef struct
106 critical_section *cs;
107 void *unknown[4];
108 int unknown2[2];
109 } critical_section_scoped_lock;
111 typedef struct {
112 void *chain;
113 critical_section lock;
114 } _Condition_variable;
116 static inline float __port_infinity(void)
118 static const unsigned __inf_bytes = 0x7f800000;
119 return *(const float *)&__inf_bytes;
121 #define INFINITY __port_infinity()
123 static inline float __port_nan(void)
125 static const unsigned __nan_bytes = 0x7fc00000;
126 return *(const float *)&__nan_bytes;
128 #define NAN __port_nan()
130 struct MSVCRT_lconv
132 char* decimal_point;
133 char* thousands_sep;
134 char* grouping;
135 char* int_curr_symbol;
136 char* currency_symbol;
137 char* mon_decimal_point;
138 char* mon_thousands_sep;
139 char* mon_grouping;
140 char* positive_sign;
141 char* negative_sign;
142 char int_frac_digits;
143 char frac_digits;
144 char p_cs_precedes;
145 char p_sep_by_space;
146 char n_cs_precedes;
147 char n_sep_by_space;
148 char p_sign_posn;
149 char n_sign_posn;
150 wchar_t* _W_decimal_point;
151 wchar_t* _W_thousands_sep;
152 wchar_t* _W_int_curr_symbol;
153 wchar_t* _W_currency_symbol;
154 wchar_t* _W_mon_decimal_point;
155 wchar_t* _W_mon_thousands_sep;
156 wchar_t* _W_positive_sign;
157 wchar_t* _W_negative_sign;
160 typedef struct
162 unsigned int control;
163 unsigned int status;
164 } fenv_t;
166 static char* (CDECL *p_setlocale)(int category, const char* locale);
167 static struct MSVCRT_lconv* (CDECL *p_localeconv)(void);
168 static size_t (CDECL *p_wcstombs_s)(size_t *ret, char* dest, size_t sz, const wchar_t* src, size_t max);
169 static int (CDECL *p__dsign)(double);
170 static int (CDECL *p__fdsign)(float);
171 static int (__cdecl *p__dpcomp)(double x, double y);
172 static wchar_t** (CDECL *p____lc_locale_name_func)(void);
173 static unsigned int (CDECL *p__GetConcurrency)(void);
174 static void* (CDECL *p__W_Gettnames)(void);
175 static void (CDECL *p_free)(void*);
176 static float (CDECL *p_strtof)(const char *, char **);
177 static int (CDECL *p__finite)(double);
178 static float (CDECL *p_wcstof)(const wchar_t*, wchar_t**);
179 static double (CDECL *p_remainder)(double, double);
180 static int* (CDECL *p_errno)(void);
181 static int (CDECL *p_fegetenv)(fenv_t*);
182 static int (CDECL *p__clearfp)(void);
183 static _locale_t (__cdecl *p_wcreate_locale)(int, const wchar_t *);
184 static void (__cdecl *p_free_locale)(_locale_t);
185 static unsigned short (__cdecl *p_wctype)(const char*);
186 static int (__cdecl *p_vsscanf)(const char*, const char *, __ms_va_list valist);
188 /* make sure we use the correct errno */
189 #undef errno
190 #define errno (*p_errno())
192 static critical_section* (__thiscall *p_critical_section_ctor)(critical_section*);
193 static void (__thiscall *p_critical_section_dtor)(critical_section*);
194 static void (__thiscall *p_critical_section_lock)(critical_section*);
195 static void (__thiscall *p_critical_section_unlock)(critical_section*);
196 static critical_section* (__thiscall *p_critical_section_native_handle)(critical_section*);
197 static MSVCRT_bool (__thiscall *p_critical_section_try_lock)(critical_section*);
198 static MSVCRT_bool (__thiscall *p_critical_section_try_lock_for)(critical_section*, unsigned int);
199 static critical_section_scoped_lock* (__thiscall *p_critical_section_scoped_lock_ctor)
200 (critical_section_scoped_lock*, critical_section *);
201 static void (__thiscall *p_critical_section_scoped_lock_dtor)(critical_section_scoped_lock*);
203 static _Condition_variable* (__thiscall *p__Condition_variable_ctor)(_Condition_variable*);
204 static void (__thiscall *p__Condition_variable_dtor)(_Condition_variable*);
205 static void (__thiscall *p__Condition_variable_wait)(_Condition_variable*, critical_section*);
206 static MSVCRT_bool (__thiscall *p__Condition_variable_wait_for)(_Condition_variable*, critical_section*, unsigned int);
207 static void (__thiscall *p__Condition_variable_notify_one)(_Condition_variable*);
208 static void (__thiscall *p__Condition_variable_notify_all)(_Condition_variable*);
210 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(module,y)
211 #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
213 static BOOL init(void)
215 HMODULE module;
217 module = LoadLibraryA("msvcr120.dll");
218 if (!module)
220 win_skip("msvcr120.dll not installed\n");
221 return FALSE;
224 p_setlocale = (void*)GetProcAddress(module, "setlocale");
225 p_localeconv = (void*)GetProcAddress(module, "localeconv");
226 p_wcstombs_s = (void*)GetProcAddress(module, "wcstombs_s");
227 p__dsign = (void*)GetProcAddress(module, "_dsign");
228 p__fdsign = (void*)GetProcAddress(module, "_fdsign");
229 p__dpcomp = (void*)GetProcAddress(module, "_dpcomp");
230 p____lc_locale_name_func = (void*)GetProcAddress(module, "___lc_locale_name_func");
231 p__GetConcurrency = (void*)GetProcAddress(module,"?_GetConcurrency@details@Concurrency@@YAIXZ");
232 p__W_Gettnames = (void*)GetProcAddress(module, "_W_Gettnames");
233 p_free = (void*)GetProcAddress(module, "free");
234 p_strtof = (void*)GetProcAddress(module, "strtof");
235 p__finite = (void*)GetProcAddress(module, "_finite");
236 p_wcstof = (void*)GetProcAddress(module, "wcstof");
237 p_remainder = (void*)GetProcAddress(module, "remainder");
238 p_errno = (void*)GetProcAddress(module, "_errno");
239 p_wcreate_locale = (void*)GetProcAddress(module, "_wcreate_locale");
240 p_free_locale = (void*)GetProcAddress(module, "_free_locale");
241 SET(p_wctype, "wctype");
242 SET(p_fegetenv, "fegetenv");
243 SET(p__clearfp, "_clearfp");
244 SET(p_vsscanf, "vsscanf");
245 if(sizeof(void*) == 8) { /* 64-bit initialization */
246 SET(p_critical_section_ctor,
247 "??0critical_section@Concurrency@@QEAA@XZ");
248 SET(p_critical_section_dtor,
249 "??1critical_section@Concurrency@@QEAA@XZ");
250 SET(p_critical_section_lock,
251 "?lock@critical_section@Concurrency@@QEAAXXZ");
252 SET(p_critical_section_unlock,
253 "?unlock@critical_section@Concurrency@@QEAAXXZ");
254 SET(p_critical_section_native_handle,
255 "?native_handle@critical_section@Concurrency@@QEAAAEAV12@XZ");
256 SET(p_critical_section_try_lock,
257 "?try_lock@critical_section@Concurrency@@QEAA_NXZ");
258 SET(p_critical_section_try_lock_for,
259 "?try_lock_for@critical_section@Concurrency@@QEAA_NI@Z");
260 SET(p_critical_section_scoped_lock_ctor,
261 "??0scoped_lock@critical_section@Concurrency@@QEAA@AEAV12@@Z");
262 SET(p_critical_section_scoped_lock_dtor,
263 "??1scoped_lock@critical_section@Concurrency@@QEAA@XZ");
264 SET(p__Condition_variable_ctor,
265 "??0_Condition_variable@details@Concurrency@@QEAA@XZ");
266 SET(p__Condition_variable_dtor,
267 "??1_Condition_variable@details@Concurrency@@QEAA@XZ");
268 SET(p__Condition_variable_wait,
269 "?wait@_Condition_variable@details@Concurrency@@QEAAXAEAVcritical_section@3@@Z");
270 SET(p__Condition_variable_wait_for,
271 "?wait_for@_Condition_variable@details@Concurrency@@QEAA_NAEAVcritical_section@3@I@Z");
272 SET(p__Condition_variable_notify_one,
273 "?notify_one@_Condition_variable@details@Concurrency@@QEAAXXZ");
274 SET(p__Condition_variable_notify_all,
275 "?notify_all@_Condition_variable@details@Concurrency@@QEAAXXZ");
276 } else {
277 #ifdef __arm__
278 SET(p_critical_section_ctor,
279 "??0critical_section@Concurrency@@QAA@XZ");
280 SET(p_critical_section_dtor,
281 "??1critical_section@Concurrency@@QAA@XZ");
282 SET(p_critical_section_lock,
283 "?lock@critical_section@Concurrency@@QAAXXZ");
284 SET(p_critical_section_unlock,
285 "?unlock@critical_section@Concurrency@@QAAXXZ");
286 SET(p_critical_section_native_handle,
287 "?native_handle@critical_section@Concurrency@@QAAAAV12@XZ");
288 SET(p_critical_section_try_lock,
289 "?try_lock@critical_section@Concurrency@@QAA_NXZ");
290 SET(p_critical_section_try_lock_for,
291 "?try_lock_for@critical_section@Concurrency@@QAA_NI@Z");
292 SET(p_critical_section_scoped_lock_ctor,
293 "??0scoped_lock@critical_section@Concurrency@@QAA@AAV12@@Z");
294 SET(p_critical_section_scoped_lock_dtor,
295 "??1scoped_lock@critical_section@Concurrency@@QAA@XZ");
296 SET(p__Condition_variable_ctor,
297 "??0_Condition_variable@details@Concurrency@@QAA@XZ");
298 SET(p__Condition_variable_dtor,
299 "??1_Condition_variable@details@Concurrency@@QAA@XZ");
300 SET(p__Condition_variable_wait,
301 "?wait@_Condition_variable@details@Concurrency@@QAAXAAVcritical_section@3@@Z");
302 SET(p__Condition_variable_wait_for,
303 "?wait_for@_Condition_variable@details@Concurrency@@QAA_NAAVcritical_section@3@I@Z");
304 SET(p__Condition_variable_notify_one,
305 "?notify_one@_Condition_variable@details@Concurrency@@QAAXXZ");
306 SET(p__Condition_variable_notify_all,
307 "?notify_all@_Condition_variable@details@Concurrency@@QAAXXZ");
308 #else
309 SET(p_critical_section_ctor,
310 "??0critical_section@Concurrency@@QAE@XZ");
311 SET(p_critical_section_dtor,
312 "??1critical_section@Concurrency@@QAE@XZ");
313 SET(p_critical_section_lock,
314 "?lock@critical_section@Concurrency@@QAEXXZ");
315 SET(p_critical_section_unlock,
316 "?unlock@critical_section@Concurrency@@QAEXXZ");
317 SET(p_critical_section_native_handle,
318 "?native_handle@critical_section@Concurrency@@QAEAAV12@XZ");
319 SET(p_critical_section_try_lock,
320 "?try_lock@critical_section@Concurrency@@QAE_NXZ");
321 SET(p_critical_section_try_lock_for,
322 "?try_lock_for@critical_section@Concurrency@@QAE_NI@Z");
323 SET(p_critical_section_scoped_lock_ctor,
324 "??0scoped_lock@critical_section@Concurrency@@QAE@AAV12@@Z");
325 SET(p_critical_section_scoped_lock_dtor,
326 "??1scoped_lock@critical_section@Concurrency@@QAE@XZ");
327 SET(p__Condition_variable_ctor,
328 "??0_Condition_variable@details@Concurrency@@QAE@XZ");
329 SET(p__Condition_variable_dtor,
330 "??1_Condition_variable@details@Concurrency@@QAE@XZ");
331 SET(p__Condition_variable_wait,
332 "?wait@_Condition_variable@details@Concurrency@@QAEXAAVcritical_section@3@@Z");
333 SET(p__Condition_variable_wait_for,
334 "?wait_for@_Condition_variable@details@Concurrency@@QAE_NAAVcritical_section@3@I@Z");
335 SET(p__Condition_variable_notify_one,
336 "?notify_one@_Condition_variable@details@Concurrency@@QAEXXZ");
337 SET(p__Condition_variable_notify_all,
338 "?notify_all@_Condition_variable@details@Concurrency@@QAEXXZ");
339 #endif
342 init_thiscall_thunk();
343 return TRUE;
346 static void test_lconv_helper(const char *locstr)
348 struct MSVCRT_lconv *lconv;
349 char mbs[256];
350 size_t i;
352 if(!p_setlocale(LC_ALL, locstr))
354 win_skip("locale %s not available\n", locstr);
355 return;
358 lconv = p_localeconv();
360 /* If multi-byte version available, asserts that wide char version also available.
361 * If wide char version can be converted to a multi-byte string , asserts that the
362 * conversion result is the same as the multi-byte version.
364 if(strlen(lconv->decimal_point) > 0)
365 ok(wcslen(lconv->_W_decimal_point) > 0, "%s: decimal_point\n", locstr);
366 if(p_wcstombs_s(&i, mbs, 256, lconv->_W_decimal_point, 256) == 0)
367 ok(strcmp(mbs, lconv->decimal_point) == 0, "%s: decimal_point\n", locstr);
369 if(strlen(lconv->thousands_sep) > 0)
370 ok(wcslen(lconv->_W_thousands_sep) > 0, "%s: thousands_sep\n", locstr);
371 if(p_wcstombs_s(&i, mbs, 256, lconv->_W_thousands_sep, 256) == 0)
372 ok(strcmp(mbs, lconv->thousands_sep) == 0, "%s: thousands_sep\n", locstr);
374 if(strlen(lconv->int_curr_symbol) > 0)
375 ok(wcslen(lconv->_W_int_curr_symbol) > 0, "%s: int_curr_symbol\n", locstr);
376 if(p_wcstombs_s(&i, mbs, 256, lconv->_W_int_curr_symbol, 256) == 0)
377 ok(strcmp(mbs, lconv->int_curr_symbol) == 0, "%s: int_curr_symbol\n", locstr);
379 if(strlen(lconv->currency_symbol) > 0)
380 ok(wcslen(lconv->_W_currency_symbol) > 0, "%s: currency_symbol\n", locstr);
381 if(p_wcstombs_s(&i, mbs, 256, lconv->_W_currency_symbol, 256) == 0)
382 ok(strcmp(mbs, lconv->currency_symbol) == 0, "%s: currency_symbol\n", locstr);
384 if(strlen(lconv->mon_decimal_point) > 0)
385 ok(wcslen(lconv->_W_mon_decimal_point) > 0, "%s: decimal_point\n", locstr);
386 if(p_wcstombs_s(&i, mbs, 256, lconv->_W_mon_decimal_point, 256) == 0)
387 ok(strcmp(mbs, lconv->mon_decimal_point) == 0, "%s: decimal_point\n", locstr);
389 if(strlen(lconv->positive_sign) > 0)
390 ok(wcslen(lconv->_W_positive_sign) > 0, "%s: positive_sign\n", locstr);
391 if(p_wcstombs_s(&i, mbs, 256, lconv->_W_positive_sign, 256) == 0)
392 ok(strcmp(mbs, lconv->positive_sign) == 0, "%s: positive_sign\n", locstr);
394 if(strlen(lconv->negative_sign) > 0)
395 ok(wcslen(lconv->_W_negative_sign) > 0, "%s: negative_sign\n", locstr);
396 if(p_wcstombs_s(&i, mbs, 256, lconv->_W_negative_sign, 256) == 0)
397 ok(strcmp(mbs, lconv->negative_sign) == 0, "%s: negative_sign\n", locstr);
400 static void test_lconv(void)
402 int i;
403 const char *locstrs[] =
405 "American", "Belgian", "Chinese",
406 "Dutch", "English", "French",
407 "German", "Hungarian", "Icelandic",
408 "Japanese", "Korean", "Spanish"
411 for(i = 0; i < sizeof(locstrs) / sizeof(char *); i ++)
412 test_lconv_helper(locstrs[i]);
415 static void test__dsign(void)
417 int ret;
419 ret = p__dsign(1);
420 ok(ret == 0, "p_dsign(1) = %x\n", ret);
421 ret = p__dsign(0);
422 ok(ret == 0, "p_dsign(0) = %x\n", ret);
423 ret = p__dsign(-1);
424 ok(ret == 0x8000, "p_dsign(-1) = %x\n", ret);
426 ret = p__fdsign(1);
427 ok(ret == 0, "p_fdsign(1) = %x\n", ret);
428 ret = p__fdsign(0);
429 ok(ret == 0, "p_fdsign(0) = %x\n", ret);
430 ret = p__fdsign(-1);
431 ok(ret == 0x8000, "p_fdsign(-1) = %x\n", ret);
434 static void test__dpcomp(void)
436 struct {
437 double x, y;
438 int ret;
439 } tests[] = {
440 {0, 0, 2}, {1, 1, 2}, {-1, -1, 2},
441 {-2, -1, 1}, {-1, 1, 1}, {1, 2, 1},
442 {1, -1, 4}, {2, 1, 4}, {-1, -2, 4},
443 {NAN, NAN, 0}, {NAN, 1, 0}, {1, NAN, 0},
444 {INFINITY, INFINITY, 2}, {-1, INFINITY, 1}, {1, INFINITY, 1},
446 int i, ret;
448 for(i=0; i<sizeof(tests)/sizeof(*tests); i++) {
449 ret = p__dpcomp(tests[i].x, tests[i].y);
450 ok(ret == tests[i].ret, "%d) dpcomp(%f, %f) = %x\n", i, tests[i].x, tests[i].y, ret);
454 static void test____lc_locale_name_func(void)
456 struct {
457 const char *locale;
458 const WCHAR name[10];
459 const WCHAR broken_name[10];
460 } tests[] = {
461 { "American", {'e','n',0}, {'e','n','-','U','S',0} },
462 { "Belgian", {'n','l','-','B','E',0} },
463 { "Chinese", {'z','h',0}, {'z','h','-','C','N',0} },
464 { "Dutch", {'n','l',0}, {'n','l','-','N','L',0} },
465 { "English", {'e','n',0}, {'e','n','-','U','S',0} },
466 { "French", {'f','r',0}, {'f','r','-','F','R',0} },
467 { "German", {'d','e',0}, {'d','e','-','D','E',0} },
468 { "Hungarian", {'h','u',0}, {'h','u','-','H','U',0} },
469 { "Icelandic", {'i','s',0}, {'i','s','-','I','S',0} },
470 { "Japanese", {'j','a',0}, {'j','a','-','J','P',0} },
471 { "Korean", {'k','o',0}, {'k','o','-','K','R',0} }
473 int i, j;
474 wchar_t **lc_names;
476 for(i=0; i<sizeof(tests)/sizeof(*tests); i++) {
477 if(!p_setlocale(LC_ALL, tests[i].locale))
478 continue;
480 lc_names = p____lc_locale_name_func();
481 ok(lc_names[0] == NULL, "%d - lc_names[0] = %s\n", i, wine_dbgstr_w(lc_names[0]));
482 ok(!lstrcmpW(lc_names[1], tests[i].name) || broken(!lstrcmpW(lc_names[1], tests[i].broken_name)),
483 "%d - lc_names[1] = %s\n", i, wine_dbgstr_w(lc_names[1]));
485 for(j=LC_MIN+2; j<=LC_MAX; j++) {
486 ok(!lstrcmpW(lc_names[1], lc_names[j]), "%d - lc_names[%d] = %s, expected %s\n",
487 i, j, wine_dbgstr_w(lc_names[j]), wine_dbgstr_w(lc_names[1]));
491 p_setlocale(LC_ALL, "C");
492 lc_names = p____lc_locale_name_func();
493 ok(!lc_names[1], "___lc_locale_name_func()[1] = %s\n", wine_dbgstr_w(lc_names[1]));
496 static void test__GetConcurrency(void)
498 SYSTEM_INFO si;
499 unsigned int c;
501 GetSystemInfo(&si);
502 c = (*p__GetConcurrency)();
503 ok(c == si.dwNumberOfProcessors, "expected %u, got %u\n", si.dwNumberOfProcessors, c);
506 static void test__W_Gettnames(void)
508 static const char *str[] = {
509 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
510 "Sunday", "Monday", "Tuesday", "Wednesday",
511 "Thursday", "Friday", "Saturday",
512 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
513 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
514 "January", "February", "March", "April", "May", "June", "July",
515 "August", "September", "October", "November", "December",
516 "AM", "PM", "M/d/yyyy"
519 struct {
520 char *str[43];
521 int unk[2];
522 wchar_t *wstr[43];
523 wchar_t *locname;
524 char data[1];
525 } *ret;
526 int i, size;
527 WCHAR buf[64];
529 if(!p_setlocale(LC_ALL, "english"))
530 return;
532 ret = p__W_Gettnames();
533 size = ret->str[0]-(char*)ret;
534 if(sizeof(void*) == 8)
535 ok(size==0x2c0, "structure size: %x\n", size);
536 else
537 ok(size==0x164, "structure size: %x\n", size);
539 for(i=0; i<sizeof(str)/sizeof(*str); i++) {
540 ok(!strcmp(ret->str[i], str[i]), "ret->str[%d] = %s, expected %s\n",
541 i, ret->str[i], str[i]);
543 MultiByteToWideChar(CP_ACP, 0, str[i], strlen(str[i])+1,
544 buf, sizeof(buf)/sizeof(*buf));
545 ok(!lstrcmpW(ret->wstr[i], buf), "ret->wstr[%d] = %s, expected %s\n",
546 i, wine_dbgstr_w(ret->wstr[i]), wine_dbgstr_w(buf));
548 p_free(ret);
550 p_setlocale(LC_ALL, "C");
553 static void test__strtof(void)
555 const char float1[] = "12.0";
556 const char float2[] = "3.402823466e+38"; /* FLT_MAX */
557 const char float3[] = "-3.402823466e+38";
558 const char float4[] = "1.7976931348623158e+308"; /* DBL_MAX */
560 const WCHAR twelve[] = {'1','2','.','0',0};
561 const WCHAR arabic23[] = { 0x662, 0x663, 0};
563 char *end;
564 float f;
566 f = p_strtof(float1, &end);
567 ok(f == 12.0, "f = %lf\n", f);
568 ok(end == float1+4, "incorrect end (%d)\n", (int)(end-float1));
570 f = p_strtof(float2, &end);
571 ok(f == FLT_MAX, "f = %lf\n", f);
572 ok(end == float2+15, "incorrect end (%d)\n", (int)(end-float2));
574 f = p_strtof(float3, &end);
575 ok(f == -FLT_MAX, "f = %lf\n", f);
576 ok(end == float3+16, "incorrect end (%d)\n", (int)(end-float3));
578 f = p_strtof(float4, &end);
579 ok(!p__finite(f), "f = %lf\n", f);
580 ok(end == float4+23, "incorrect end (%d)\n", (int)(end-float4));
582 f = p_strtof("inf", NULL);
583 ok(f == 0, "f = %lf\n", f);
585 f = p_strtof("INF", NULL);
586 ok(f == 0, "f = %lf\n", f);
588 f = p_strtof("1.#inf", NULL);
589 ok(f == 1, "f = %lf\n", f);
591 f = p_strtof("INFINITY", NULL);
592 ok(f == 0, "f = %lf\n", f);
594 f = p_strtof("0x12", NULL);
595 ok(f == 0, "f = %lf\n", f);
597 f = p_wcstof(twelve, NULL);
598 ok(f == 12.0, "f = %lf\n", f);
600 f = p_wcstof(arabic23, NULL);
601 ok(f == 0, "f = %lf\n", f);
603 if(!p_setlocale(LC_ALL, "Arabic")) {
604 win_skip("Arabic locale not available\n");
605 return;
608 f = p_wcstof(twelve, NULL);
609 ok(f == 12.0, "f = %lf\n", f);
611 f = p_wcstof(arabic23, NULL);
612 ok(f == 0, "f = %lf\n", f);
614 p_setlocale(LC_ALL, "C");
617 static void test_remainder(void)
619 struct {
620 double x, y, r;
621 errno_t e;
622 } tests[] = {
623 { 3.0, 2.0, -1.0, -1 },
624 { 1.0, 1.0, 0.0, -1 },
625 { INFINITY, 0.0, NAN, EDOM },
626 { INFINITY, 42.0, NAN, EDOM },
627 { NAN, 0.0, NAN, EDOM },
628 { NAN, 42.0, NAN, EDOM },
629 { 0.0, INFINITY, 0.0, -1 },
630 { 42.0, INFINITY, 42.0, -1 },
631 { 0.0, NAN, NAN, EDOM },
632 { 42.0, NAN, NAN, EDOM },
633 { 1.0, 0.0, NAN, EDOM },
634 { INFINITY, INFINITY, NAN, EDOM },
636 errno_t e;
637 double r;
638 int i;
640 if(sizeof(void*) != 8) /* errno handling slightly different on 32-bit */
641 return;
643 for(i=0; i<sizeof(tests)/sizeof(*tests); i++) {
644 errno = -1;
645 r = p_remainder(tests[i].x, tests[i].y);
646 e = errno;
648 ok(tests[i].e == e, "expected errno %i, but got %i\n", tests[i].e, e);
649 if(_isnan(tests[i].r))
650 ok(_isnan(r), "expected NAN, but got %f\n", r);
651 else
652 ok(tests[i].r == r, "expected result %f, but got %f\n", tests[i].r, r);
656 static int enter_flag;
657 static critical_section cs;
658 static unsigned __stdcall test_critical_section_lock(void *arg)
660 critical_section *native_handle;
661 native_handle = (critical_section*)call_func1(p_critical_section_native_handle, &cs);
662 ok(native_handle == &cs, "native_handle = %p\n", native_handle);
663 call_func1(p_critical_section_lock, &cs);
664 ok(enter_flag == 1, "enter_flag = %d\n", enter_flag);
665 call_func1(p_critical_section_unlock, &cs);
666 return 0;
669 static unsigned __stdcall test_critical_section_try_lock(void *arg)
671 ok(!(MSVCRT_bool)call_func1(p_critical_section_try_lock, &cs),
672 "critical_section_try_lock succeeded\n");
673 return 0;
676 static unsigned __stdcall test_critical_section_try_lock_for(void *arg)
678 ok((MSVCRT_bool)call_func2(p_critical_section_try_lock_for, &cs, 5000),
679 "critical_section_try_lock_for failed\n");
680 ok(enter_flag == 1, "enter_flag = %d\n", enter_flag);
681 call_func1(p_critical_section_unlock, &cs);
682 return 0;
685 static unsigned __stdcall test_critical_section_scoped_lock(void *arg)
687 critical_section_scoped_lock counter_scope_lock;
689 call_func2(p_critical_section_scoped_lock_ctor, &counter_scope_lock, &cs);
690 ok(enter_flag == 1, "enter_flag = %d\n", enter_flag);
691 call_func1(p_critical_section_scoped_lock_dtor, &counter_scope_lock);
692 return 0;
695 static void test_critical_section(void)
697 HANDLE thread;
698 DWORD ret;
700 enter_flag = 0;
701 call_func1(p_critical_section_ctor, &cs);
702 call_func1(p_critical_section_lock, &cs);
703 thread = (HANDLE)_beginthreadex(NULL, 0, test_critical_section_lock, NULL, 0, NULL);
704 ok(thread != INVALID_HANDLE_VALUE, "_beginthread failed (%d)\n", errno);
705 ret = WaitForSingleObject(thread, 100);
706 ok(ret == WAIT_TIMEOUT, "WaitForSingleObject returned %d\n", ret);
707 enter_flag = 1;
708 call_func1(p_critical_section_unlock, &cs);
709 ret = WaitForSingleObject(thread, INFINITE);
710 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d\n", ret);
711 ret = CloseHandle(thread);
712 ok(ret, "CloseHandle failed\n");
714 ok((MSVCRT_bool)call_func1(p_critical_section_try_lock, &cs),
715 "critical_section_try_lock failed\n");
716 thread = (HANDLE)_beginthreadex(NULL, 0, test_critical_section_try_lock, NULL, 0, NULL);
717 ok(thread != INVALID_HANDLE_VALUE, "_beginthread failed (%d)\n", errno);
718 ret = WaitForSingleObject(thread, INFINITE);
719 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d\n", ret);
720 ret = CloseHandle(thread);
721 ok(ret, "CloseHandle failed\n");
722 call_func1(p_critical_section_unlock, &cs);
724 enter_flag = 0;
725 ok((MSVCRT_bool)call_func2(p_critical_section_try_lock_for, &cs, 50),
726 "critical_section_try_lock_for failed\n");
727 thread = (HANDLE)_beginthreadex(NULL, 0, test_critical_section_try_lock, NULL, 0, NULL);
728 ok(thread != INVALID_HANDLE_VALUE, "_beginthread failed (%d)\n", errno);
729 ret = WaitForSingleObject(thread, INFINITE);
730 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d\n", ret);
731 ret = CloseHandle(thread);
732 ok(ret, "CloseHandle failed\n");
733 thread = (HANDLE)_beginthreadex(NULL, 0, test_critical_section_try_lock_for, NULL, 0, NULL);
734 ok(thread != INVALID_HANDLE_VALUE, "_beginthread failed (%d)\n", errno);
735 enter_flag = 1;
736 Sleep(10);
737 call_func1(p_critical_section_unlock, &cs);
738 ret = WaitForSingleObject(thread, INFINITE);
739 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d\n", ret);
740 ret = CloseHandle(thread);
741 ok(ret, "CloseHandle failed\n");
743 enter_flag = 0;
744 call_func1(p_critical_section_lock, &cs);
745 thread = (HANDLE)_beginthreadex(NULL, 0, test_critical_section_scoped_lock, NULL, 0, NULL);
746 ok(thread != INVALID_HANDLE_VALUE, "_beginthread failed (%d)\n", errno);
747 ret = WaitForSingleObject(thread, 100);
748 ok(ret == WAIT_TIMEOUT, "WaitForSingleObject returned %d\n", ret);
749 enter_flag = 1;
750 call_func1(p_critical_section_unlock, &cs);
751 ret = WaitForSingleObject(thread, INFINITE);
752 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d\n", ret);
753 ret = CloseHandle(thread);
754 ok(ret, "CloseHandle failed\n");
755 call_func1(p_critical_section_dtor, &cs);
758 static void test_fegetenv(void)
760 int ret;
761 fenv_t env;
763 p__clearfp();
765 ret = p_fegetenv(&env);
766 ok(!ret, "fegetenv returned %x\n", ret);
767 ok(env.control == (_EM_INEXACT|_EM_UNDERFLOW|_EM_OVERFLOW|_EM_ZERODIVIDE|_EM_INVALID),
768 "env.control = %x\n", env.control);
769 ok(!env.status, "env.status = %x\n", env.status);
772 static void test__wcreate_locale(void)
774 static const wchar_t c_locale[] = {'C',0};
775 static const wchar_t bogus[] = {'b','o','g','u','s',0};
776 static const wchar_t empty[] = {0};
777 _locale_t lcl;
778 errno_t e;
780 /* simple success */
781 errno = -1;
782 lcl = p_wcreate_locale(LC_ALL, c_locale);
783 e = errno;
784 ok(!!lcl, "expected success, but got NULL\n");
785 ok(errno == -1, "expected errno -1, but got %i\n", e);
786 p_free_locale(lcl);
788 errno = -1;
789 lcl = p_wcreate_locale(LC_ALL, empty);
790 e = errno;
791 ok(!!lcl, "expected success, but got NULL\n");
792 ok(errno == -1, "expected errno -1, but got %i\n", e);
793 p_free_locale(lcl);
795 /* bogus category */
796 errno = -1;
797 lcl = p_wcreate_locale(-1, c_locale);
798 e = errno;
799 ok(!lcl, "expected failure, but got %p\n", lcl);
800 ok(errno == -1, "expected errno -1, but got %i\n", e);
802 /* bogus names */
803 errno = -1;
804 lcl = p_wcreate_locale(LC_ALL, bogus);
805 e = errno;
806 ok(!lcl, "expected failure, but got %p\n", lcl);
807 ok(errno == -1, "expected errno -1, but got %i\n", e);
809 errno = -1;
810 lcl = p_wcreate_locale(LC_ALL, NULL);
811 e = errno;
812 ok(!lcl, "expected failure, but got %p\n", lcl);
813 ok(errno == -1, "expected errno -1, but got %i\n", e);
816 struct wait_thread_arg
818 critical_section *cs;
819 _Condition_variable *cv;
820 HANDLE thread_initialized;
823 static DWORD WINAPI condition_variable_wait_thread(void *varg)
825 struct wait_thread_arg *arg = varg;
827 call_func1(p_critical_section_lock, arg->cs);
828 SetEvent(arg->thread_initialized);
829 call_func2(p__Condition_variable_wait, arg->cv, arg->cs);
830 call_func1(p_critical_section_unlock, arg->cs);
831 return 0;
834 static void test__Condition_variable(void)
836 critical_section cs;
837 _Condition_variable cv;
838 HANDLE thread_initialized = CreateEventW(NULL, FALSE, FALSE, NULL);
839 struct wait_thread_arg wait_thread_arg = { &cs, &cv, thread_initialized };
840 HANDLE threads[2];
841 DWORD ret;
842 MSVCRT_bool b;
844 ok(thread_initialized != NULL, "CreateEvent failed\n");
846 call_func1(p_critical_section_ctor, &cs);
847 call_func1(p__Condition_variable_ctor, &cv);
849 call_func1(p__Condition_variable_notify_one, &cv);
850 call_func1(p__Condition_variable_notify_all, &cv);
852 threads[0] = CreateThread(0, 0, condition_variable_wait_thread,
853 &wait_thread_arg, 0, 0);
854 ok(threads[0] != NULL, "CreateThread failed\n");
855 WaitForSingleObject(thread_initialized, INFINITE);
856 call_func1(p_critical_section_lock, &cs);
857 call_func1(p_critical_section_unlock, &cs);
859 threads[1] = CreateThread(0, 0, condition_variable_wait_thread,
860 &wait_thread_arg, 0, 0);
861 ok(threads[1] != NULL, "CreateThread failed\n");
862 WaitForSingleObject(thread_initialized, INFINITE);
863 call_func1(p_critical_section_lock, &cs);
864 call_func1(p_critical_section_unlock, &cs);
866 call_func1(p__Condition_variable_notify_one, &cv);
867 ret = WaitForSingleObject(threads[1], 500);
868 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d\n", ret);
869 call_func1(p__Condition_variable_notify_one, &cv);
870 ret = WaitForSingleObject(threads[0], 500);
871 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d\n", ret);
873 CloseHandle(threads[0]);
874 CloseHandle(threads[1]);
876 call_func1(p_critical_section_lock, &cs);
877 b = call_func3(p__Condition_variable_wait_for, &cv, &cs, 1);
878 ok(!b, "_Condition_variable_wait_for returned TRUE\n");
879 call_func1(p_critical_section_unlock, &cs);
881 call_func1(p_critical_section_dtor, &cs);
882 call_func1(p__Condition_variable_dtor, &cv);
884 CloseHandle(thread_initialized);
887 static void test_wctype(void)
889 static const struct {
890 const char *name;
891 unsigned short mask;
892 } properties[] = {
893 { "alnum", 0x107 },
894 { "alpha", 0x103 },
895 { "cntrl", 0x020 },
896 { "digit", 0x004 },
897 { "graph", 0x117 },
898 { "lower", 0x002 },
899 { "print", 0x157 },
900 { "punct", 0x010 },
901 { "space", 0x008 },
902 { "upper", 0x001 },
903 { "xdigit", 0x080 },
904 { "ALNUM", 0x000 },
905 { "Alnum", 0x000 },
906 { "", 0x000 }
908 int i, ret;
910 for(i=0; i<sizeof(properties)/sizeof(properties[0]); i++) {
911 ret = p_wctype(properties[i].name);
912 ok(properties[i].mask == ret, "%d - Expected %x, got %x\n", i, properties[i].mask, ret);
916 static int WINAPIV _vsscanf_wrapper(const char *buffer, const char *format, ...)
918 int ret;
919 __ms_va_list valist;
920 __ms_va_start(valist, format);
921 ret = p_vsscanf(buffer, format, valist);
922 __ms_va_end(valist);
923 return ret;
926 static void test_vsscanf(void)
928 static const char *fmt = "%d";
929 char buff[16];
930 int ret, v;
932 v = 0;
933 strcpy(buff, "10");
934 ret = _vsscanf_wrapper(buff, fmt, &v);
935 ok(ret == 1, "Unexpected ret %d.\n", ret);
936 ok(v == 10, "got %d.\n", v);
939 START_TEST(msvcr120)
941 if (!init()) return;
942 test__strtof();
943 test_lconv();
944 test__dsign();
945 test__dpcomp();
946 test____lc_locale_name_func();
947 test__GetConcurrency();
948 test__W_Gettnames();
949 test__strtof();
950 test_remainder();
951 test_critical_section();
952 test_fegetenv();
953 test__wcreate_locale();
954 test__Condition_variable();
955 test_wctype();
956 test_vsscanf();