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
33 #include "wine/test.h"
42 BYTE pop_eax
; /* popl %eax (ret addr) */
43 BYTE pop_edx
; /* popl %edx (func) */
44 BYTE pop_ecx
; /* popl %ecx (this) */
45 BYTE push_eax
; /* pushl %eax */
46 WORD jmp_edx
; /* jmp *%edx */
50 static ULONG_PTR (WINAPI
*call_thiscall_func1
)( void *func
, void *this );
51 static ULONG_PTR (WINAPI
*call_thiscall_func2
)( void *func
, void *this, const void *a
);
52 static ULONG_PTR (WINAPI
*call_thiscall_func3
)( void *func
,
53 void *this, const void *a
, const void *b
);
55 static void init_thiscall_thunk(void)
57 struct thiscall_thunk
*thunk
= VirtualAlloc( NULL
, sizeof(*thunk
),
58 MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
59 thunk
->pop_eax
= 0x58; /* popl %eax */
60 thunk
->pop_edx
= 0x5a; /* popl %edx */
61 thunk
->pop_ecx
= 0x59; /* popl %ecx */
62 thunk
->push_eax
= 0x50; /* pushl %eax */
63 thunk
->jmp_edx
= 0xe2ff; /* jmp *%edx */
64 call_thiscall_func1
= (void *)thunk
;
65 call_thiscall_func2
= (void *)thunk
;
66 call_thiscall_func3
= (void *)thunk
;
69 #define call_func1(func,_this) call_thiscall_func1(func,_this)
70 #define call_func2(func,_this,a) call_thiscall_func2(func,_this,(const void*)(a))
71 #define call_func3(func,_this,a,b) call_thiscall_func3(func,_this,(const void*)(a),(const void*)(b))
75 #define init_thiscall_thunk()
76 #define call_func1(func,_this) func(_this)
77 #define call_func2(func,_this,a) func(_this,a)
78 #define call_func3(func,_this,a,b) func(_this,a,b)
84 #define __thiscall __stdcall
86 #define __thiscall __cdecl
89 typedef unsigned char MSVCRT_bool
;
91 typedef struct cs_queue
93 struct cs_queue
*next
;
100 ULONG_PTR unk_thread_id
;
109 critical_section
*cs
;
112 } critical_section_scoped_lock
;
116 critical_section lock
;
117 } _Condition_variable
;
124 char* int_curr_symbol
;
125 char* currency_symbol
;
126 char* mon_decimal_point
;
127 char* mon_thousands_sep
;
131 char int_frac_digits
;
139 wchar_t* _W_decimal_point
;
140 wchar_t* _W_thousands_sep
;
141 wchar_t* _W_int_curr_symbol
;
142 wchar_t* _W_currency_symbol
;
143 wchar_t* _W_mon_decimal_point
;
144 wchar_t* _W_mon_thousands_sep
;
145 wchar_t* _W_positive_sign
;
146 wchar_t* _W_negative_sign
;
151 unsigned int control
;
161 typedef void (*vtable_ptr
)(void);
164 const vtable_ptr
*vtable
;
171 static char* (CDECL
*p_setlocale
)(int category
, const char* locale
);
172 static struct MSVCRT_lconv
* (CDECL
*p_localeconv
)(void);
173 static size_t (CDECL
*p_wcstombs_s
)(size_t *ret
, char* dest
, size_t sz
, const wchar_t* src
, size_t max
);
174 static int (CDECL
*p__dsign
)(double);
175 static int (CDECL
*p__fdsign
)(float);
176 static int (__cdecl
*p__dpcomp
)(double x
, double y
);
177 static wchar_t** (CDECL
*p____lc_locale_name_func
)(void);
178 static unsigned int (CDECL
*p__GetConcurrency
)(void);
179 static void* (CDECL
*p__W_Gettnames
)(void);
180 static void (CDECL
*p_free
)(void*);
181 static float (CDECL
*p_strtof
)(const char *, char **);
182 static int (CDECL
*p__finite
)(double);
183 static float (CDECL
*p_wcstof
)(const wchar_t*, wchar_t**);
184 static double (CDECL
*p_remainder
)(double, double);
185 static int* (CDECL
*p_errno
)(void);
186 static int (CDECL
*p_fegetenv
)(fenv_t
*);
187 static int (CDECL
*p_fesetenv
)(const fenv_t
*);
188 static int (CDECL
*p_fegetround
)(void);
189 static int (CDECL
*p_fesetround
)(int);
190 static int (CDECL
*p__clearfp
)(void);
191 static _locale_t (__cdecl
*p_wcreate_locale
)(int, const wchar_t *);
192 static void (__cdecl
*p_free_locale
)(_locale_t
);
193 static unsigned short (__cdecl
*p_wctype
)(const char*);
194 static int (__cdecl
*p_vsscanf
)(const char*, const char *, __ms_va_list valist
);
195 static _Dcomplex
* (__cdecl
*p__Cbuild
)(_Dcomplex
*, double, double);
196 static double (__cdecl
*p_creal
)(_Dcomplex
);
197 static double (__cdecl
*p_nexttoward
)(double, double);
198 static float (__cdecl
*p_nexttowardf
)(float, double);
199 static double (__cdecl
*p_nexttowardl
)(double, double);
200 static wctrans_t (__cdecl
*p_wctrans
)(const char*);
201 static wint_t (__cdecl
*p_towctrans
)(wint_t, wctrans_t);
203 /* make sure we use the correct errno */
205 #define errno (*p_errno())
207 static critical_section
* (__thiscall
*p_critical_section_ctor
)(critical_section
*);
208 static void (__thiscall
*p_critical_section_dtor
)(critical_section
*);
209 static void (__thiscall
*p_critical_section_lock
)(critical_section
*);
210 static void (__thiscall
*p_critical_section_unlock
)(critical_section
*);
211 static critical_section
* (__thiscall
*p_critical_section_native_handle
)(critical_section
*);
212 static MSVCRT_bool (__thiscall
*p_critical_section_try_lock
)(critical_section
*);
213 static MSVCRT_bool (__thiscall
*p_critical_section_try_lock_for
)(critical_section
*, unsigned int);
214 static critical_section_scoped_lock
* (__thiscall
*p_critical_section_scoped_lock_ctor
)
215 (critical_section_scoped_lock
*, critical_section
*);
216 static void (__thiscall
*p_critical_section_scoped_lock_dtor
)(critical_section_scoped_lock
*);
218 static _Condition_variable
* (__thiscall
*p__Condition_variable_ctor
)(_Condition_variable
*);
219 static void (__thiscall
*p__Condition_variable_dtor
)(_Condition_variable
*);
220 static void (__thiscall
*p__Condition_variable_wait
)(_Condition_variable
*, critical_section
*);
221 static MSVCRT_bool (__thiscall
*p__Condition_variable_wait_for
)(_Condition_variable
*, critical_section
*, unsigned int);
222 static void (__thiscall
*p__Condition_variable_notify_one
)(_Condition_variable
*);
223 static void (__thiscall
*p__Condition_variable_notify_all
)(_Condition_variable
*);
225 static Context
* (__cdecl
*p_Context_CurrentContext
)(void);
226 static _Context
* (__cdecl
*p__Context__CurrentContext
)(_Context
*);
228 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(module,y)
229 #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
231 static BOOL
init(void)
235 module
= LoadLibraryA("msvcr120.dll");
238 win_skip("msvcr120.dll not installed\n");
242 p_setlocale
= (void*)GetProcAddress(module
, "setlocale");
243 p_localeconv
= (void*)GetProcAddress(module
, "localeconv");
244 p_wcstombs_s
= (void*)GetProcAddress(module
, "wcstombs_s");
245 p__dsign
= (void*)GetProcAddress(module
, "_dsign");
246 p__fdsign
= (void*)GetProcAddress(module
, "_fdsign");
247 p__dpcomp
= (void*)GetProcAddress(module
, "_dpcomp");
248 p____lc_locale_name_func
= (void*)GetProcAddress(module
, "___lc_locale_name_func");
249 p__GetConcurrency
= (void*)GetProcAddress(module
,"?_GetConcurrency@details@Concurrency@@YAIXZ");
250 p__W_Gettnames
= (void*)GetProcAddress(module
, "_W_Gettnames");
251 p_free
= (void*)GetProcAddress(module
, "free");
252 p_strtof
= (void*)GetProcAddress(module
, "strtof");
253 p__finite
= (void*)GetProcAddress(module
, "_finite");
254 p_wcstof
= (void*)GetProcAddress(module
, "wcstof");
255 p_remainder
= (void*)GetProcAddress(module
, "remainder");
256 p_errno
= (void*)GetProcAddress(module
, "_errno");
257 p_wcreate_locale
= (void*)GetProcAddress(module
, "_wcreate_locale");
258 p_free_locale
= (void*)GetProcAddress(module
, "_free_locale");
259 SET(p_wctype
, "wctype");
260 SET(p_fegetenv
, "fegetenv");
261 SET(p_fesetenv
, "fesetenv");
262 SET(p_fegetround
, "fegetround");
263 SET(p_fesetround
, "fesetround");
265 SET(p__clearfp
, "_clearfp");
266 SET(p_vsscanf
, "vsscanf");
267 SET(p__Cbuild
, "_Cbuild");
268 SET(p_creal
, "creal");
269 SET(p_nexttoward
, "nexttoward");
270 SET(p_nexttowardf
, "nexttowardf");
271 SET(p_nexttowardl
, "nexttowardl");
272 SET(p_wctrans
, "wctrans");
273 SET(p_towctrans
, "towctrans");
274 SET(p__Context__CurrentContext
, "?_CurrentContext@_Context@details@Concurrency@@SA?AV123@XZ");
275 if(sizeof(void*) == 8) { /* 64-bit initialization */
276 SET(p_critical_section_ctor
,
277 "??0critical_section@Concurrency@@QEAA@XZ");
278 SET(p_critical_section_dtor
,
279 "??1critical_section@Concurrency@@QEAA@XZ");
280 SET(p_critical_section_lock
,
281 "?lock@critical_section@Concurrency@@QEAAXXZ");
282 SET(p_critical_section_unlock
,
283 "?unlock@critical_section@Concurrency@@QEAAXXZ");
284 SET(p_critical_section_native_handle
,
285 "?native_handle@critical_section@Concurrency@@QEAAAEAV12@XZ");
286 SET(p_critical_section_try_lock
,
287 "?try_lock@critical_section@Concurrency@@QEAA_NXZ");
288 SET(p_critical_section_try_lock_for
,
289 "?try_lock_for@critical_section@Concurrency@@QEAA_NI@Z");
290 SET(p_critical_section_scoped_lock_ctor
,
291 "??0scoped_lock@critical_section@Concurrency@@QEAA@AEAV12@@Z");
292 SET(p_critical_section_scoped_lock_dtor
,
293 "??1scoped_lock@critical_section@Concurrency@@QEAA@XZ");
294 SET(p__Condition_variable_ctor
,
295 "??0_Condition_variable@details@Concurrency@@QEAA@XZ");
296 SET(p__Condition_variable_dtor
,
297 "??1_Condition_variable@details@Concurrency@@QEAA@XZ");
298 SET(p__Condition_variable_wait
,
299 "?wait@_Condition_variable@details@Concurrency@@QEAAXAEAVcritical_section@3@@Z");
300 SET(p__Condition_variable_wait_for
,
301 "?wait_for@_Condition_variable@details@Concurrency@@QEAA_NAEAVcritical_section@3@I@Z");
302 SET(p__Condition_variable_notify_one
,
303 "?notify_one@_Condition_variable@details@Concurrency@@QEAAXXZ");
304 SET(p__Condition_variable_notify_all
,
305 "?notify_all@_Condition_variable@details@Concurrency@@QEAAXXZ");
306 SET(p_Context_CurrentContext
,
307 "?CurrentContext@Context@Concurrency@@SAPEAV12@XZ");
310 SET(p_critical_section_ctor
,
311 "??0critical_section@Concurrency@@QAA@XZ");
312 SET(p_critical_section_dtor
,
313 "??1critical_section@Concurrency@@QAA@XZ");
314 SET(p_critical_section_lock
,
315 "?lock@critical_section@Concurrency@@QAAXXZ");
316 SET(p_critical_section_unlock
,
317 "?unlock@critical_section@Concurrency@@QAAXXZ");
318 SET(p_critical_section_native_handle
,
319 "?native_handle@critical_section@Concurrency@@QAAAAV12@XZ");
320 SET(p_critical_section_try_lock
,
321 "?try_lock@critical_section@Concurrency@@QAA_NXZ");
322 SET(p_critical_section_try_lock_for
,
323 "?try_lock_for@critical_section@Concurrency@@QAA_NI@Z");
324 SET(p_critical_section_scoped_lock_ctor
,
325 "??0scoped_lock@critical_section@Concurrency@@QAA@AAV12@@Z");
326 SET(p_critical_section_scoped_lock_dtor
,
327 "??1scoped_lock@critical_section@Concurrency@@QAA@XZ");
328 SET(p__Condition_variable_ctor
,
329 "??0_Condition_variable@details@Concurrency@@QAA@XZ");
330 SET(p__Condition_variable_dtor
,
331 "??1_Condition_variable@details@Concurrency@@QAA@XZ");
332 SET(p__Condition_variable_wait
,
333 "?wait@_Condition_variable@details@Concurrency@@QAAXAAVcritical_section@3@@Z");
334 SET(p__Condition_variable_wait_for
,
335 "?wait_for@_Condition_variable@details@Concurrency@@QAA_NAAVcritical_section@3@I@Z");
336 SET(p__Condition_variable_notify_one
,
337 "?notify_one@_Condition_variable@details@Concurrency@@QAAXXZ");
338 SET(p__Condition_variable_notify_all
,
339 "?notify_all@_Condition_variable@details@Concurrency@@QAAXXZ");
341 SET(p_critical_section_ctor
,
342 "??0critical_section@Concurrency@@QAE@XZ");
343 SET(p_critical_section_dtor
,
344 "??1critical_section@Concurrency@@QAE@XZ");
345 SET(p_critical_section_lock
,
346 "?lock@critical_section@Concurrency@@QAEXXZ");
347 SET(p_critical_section_unlock
,
348 "?unlock@critical_section@Concurrency@@QAEXXZ");
349 SET(p_critical_section_native_handle
,
350 "?native_handle@critical_section@Concurrency@@QAEAAV12@XZ");
351 SET(p_critical_section_try_lock
,
352 "?try_lock@critical_section@Concurrency@@QAE_NXZ");
353 SET(p_critical_section_try_lock_for
,
354 "?try_lock_for@critical_section@Concurrency@@QAE_NI@Z");
355 SET(p_critical_section_scoped_lock_ctor
,
356 "??0scoped_lock@critical_section@Concurrency@@QAE@AAV12@@Z");
357 SET(p_critical_section_scoped_lock_dtor
,
358 "??1scoped_lock@critical_section@Concurrency@@QAE@XZ");
359 SET(p__Condition_variable_ctor
,
360 "??0_Condition_variable@details@Concurrency@@QAE@XZ");
361 SET(p__Condition_variable_dtor
,
362 "??1_Condition_variable@details@Concurrency@@QAE@XZ");
363 SET(p__Condition_variable_wait
,
364 "?wait@_Condition_variable@details@Concurrency@@QAEXAAVcritical_section@3@@Z");
365 SET(p__Condition_variable_wait_for
,
366 "?wait_for@_Condition_variable@details@Concurrency@@QAE_NAAVcritical_section@3@I@Z");
367 SET(p__Condition_variable_notify_one
,
368 "?notify_one@_Condition_variable@details@Concurrency@@QAEXXZ");
369 SET(p__Condition_variable_notify_all
,
370 "?notify_all@_Condition_variable@details@Concurrency@@QAEXXZ");
372 SET(p_Context_CurrentContext
,
373 "?CurrentContext@Context@Concurrency@@SAPAV12@XZ");
376 init_thiscall_thunk();
380 static void test_lconv_helper(const char *locstr
)
382 struct MSVCRT_lconv
*lconv
;
386 if(!p_setlocale(LC_ALL
, locstr
))
388 win_skip("locale %s not available\n", locstr
);
392 lconv
= p_localeconv();
394 /* If multi-byte version available, asserts that wide char version also available.
395 * If wide char version can be converted to a multi-byte string , asserts that the
396 * conversion result is the same as the multi-byte version.
398 if(strlen(lconv
->decimal_point
) > 0)
399 ok(wcslen(lconv
->_W_decimal_point
) > 0, "%s: decimal_point\n", locstr
);
400 if(p_wcstombs_s(&i
, mbs
, 256, lconv
->_W_decimal_point
, 256) == 0)
401 ok(strcmp(mbs
, lconv
->decimal_point
) == 0, "%s: decimal_point\n", locstr
);
403 if(strlen(lconv
->thousands_sep
) > 0)
404 ok(wcslen(lconv
->_W_thousands_sep
) > 0, "%s: thousands_sep\n", locstr
);
405 if(p_wcstombs_s(&i
, mbs
, 256, lconv
->_W_thousands_sep
, 256) == 0)
406 ok(strcmp(mbs
, lconv
->thousands_sep
) == 0, "%s: thousands_sep\n", locstr
);
408 if(strlen(lconv
->int_curr_symbol
) > 0)
409 ok(wcslen(lconv
->_W_int_curr_symbol
) > 0, "%s: int_curr_symbol\n", locstr
);
410 if(p_wcstombs_s(&i
, mbs
, 256, lconv
->_W_int_curr_symbol
, 256) == 0)
411 ok(strcmp(mbs
, lconv
->int_curr_symbol
) == 0, "%s: int_curr_symbol\n", locstr
);
413 if(strlen(lconv
->currency_symbol
) > 0)
414 ok(wcslen(lconv
->_W_currency_symbol
) > 0, "%s: currency_symbol\n", locstr
);
415 if(p_wcstombs_s(&i
, mbs
, 256, lconv
->_W_currency_symbol
, 256) == 0)
416 ok(strcmp(mbs
, lconv
->currency_symbol
) == 0, "%s: currency_symbol\n", locstr
);
418 if(strlen(lconv
->mon_decimal_point
) > 0)
419 ok(wcslen(lconv
->_W_mon_decimal_point
) > 0, "%s: decimal_point\n", locstr
);
420 if(p_wcstombs_s(&i
, mbs
, 256, lconv
->_W_mon_decimal_point
, 256) == 0)
421 ok(strcmp(mbs
, lconv
->mon_decimal_point
) == 0, "%s: decimal_point\n", locstr
);
423 if(strlen(lconv
->positive_sign
) > 0)
424 ok(wcslen(lconv
->_W_positive_sign
) > 0, "%s: positive_sign\n", locstr
);
425 if(p_wcstombs_s(&i
, mbs
, 256, lconv
->_W_positive_sign
, 256) == 0)
426 ok(strcmp(mbs
, lconv
->positive_sign
) == 0, "%s: positive_sign\n", locstr
);
428 if(strlen(lconv
->negative_sign
) > 0)
429 ok(wcslen(lconv
->_W_negative_sign
) > 0, "%s: negative_sign\n", locstr
);
430 if(p_wcstombs_s(&i
, mbs
, 256, lconv
->_W_negative_sign
, 256) == 0)
431 ok(strcmp(mbs
, lconv
->negative_sign
) == 0, "%s: negative_sign\n", locstr
);
434 static void test_lconv(void)
437 const char *locstrs
[] =
439 "American", "Belgian", "Chinese",
440 "Dutch", "English", "French",
441 "German", "Hungarian", "Icelandic",
442 "Japanese", "Korean", "Spanish"
445 for(i
= 0; i
< ARRAY_SIZE(locstrs
); i
++)
446 test_lconv_helper(locstrs
[i
]);
449 static void test__dsign(void)
454 ok(ret
== 0, "p_dsign(1) = %x\n", ret
);
456 ok(ret
== 0, "p_dsign(0) = %x\n", ret
);
458 ok(ret
== 0x8000, "p_dsign(-1) = %x\n", ret
);
461 ok(ret
== 0, "p_fdsign(1) = %x\n", ret
);
463 ok(ret
== 0, "p_fdsign(0) = %x\n", ret
);
465 ok(ret
== 0x8000, "p_fdsign(-1) = %x\n", ret
);
468 static void test__dpcomp(void)
474 {0, 0, 2}, {1, 1, 2}, {-1, -1, 2},
475 {-2, -1, 1}, {-1, 1, 1}, {1, 2, 1},
476 {1, -1, 4}, {2, 1, 4}, {-1, -2, 4},
477 {NAN
, NAN
, 0}, {NAN
, 1, 0}, {1, NAN
, 0},
478 {INFINITY
, INFINITY
, 2}, {-1, INFINITY
, 1}, {1, INFINITY
, 1},
482 for(i
=0; i
<ARRAY_SIZE(tests
); i
++) {
483 ret
= p__dpcomp(tests
[i
].x
, tests
[i
].y
);
484 ok(ret
== tests
[i
].ret
, "%d) dpcomp(%f, %f) = %x\n", i
, tests
[i
].x
, tests
[i
].y
, ret
);
488 static void test____lc_locale_name_func(void)
492 const WCHAR name
[10];
493 const WCHAR broken_name
[10];
495 { "American", {'e','n',0}, {'e','n','-','U','S',0} },
496 { "Belgian", {'n','l','-','B','E',0} },
497 { "Chinese", {'z','h',0}, {'z','h','-','C','N',0} },
498 { "Dutch", {'n','l',0}, {'n','l','-','N','L',0} },
499 { "English", {'e','n',0}, {'e','n','-','U','S',0} },
500 { "French", {'f','r',0}, {'f','r','-','F','R',0} },
501 { "German", {'d','e',0}, {'d','e','-','D','E',0} },
502 { "Hungarian", {'h','u',0}, {'h','u','-','H','U',0} },
503 { "Icelandic", {'i','s',0}, {'i','s','-','I','S',0} },
504 { "Japanese", {'j','a',0}, {'j','a','-','J','P',0} },
505 { "Korean", {'k','o',0}, {'k','o','-','K','R',0} }
510 for(i
=0; i
<ARRAY_SIZE(tests
); i
++) {
511 if(!p_setlocale(LC_ALL
, tests
[i
].locale
))
514 lc_names
= p____lc_locale_name_func();
515 ok(lc_names
[0] == NULL
, "%d - lc_names[0] = %s\n", i
, wine_dbgstr_w(lc_names
[0]));
516 ok(!lstrcmpW(lc_names
[1], tests
[i
].name
) || broken(!lstrcmpW(lc_names
[1], tests
[i
].broken_name
)),
517 "%d - lc_names[1] = %s\n", i
, wine_dbgstr_w(lc_names
[1]));
519 for(j
=LC_MIN
+2; j
<=LC_MAX
; j
++) {
520 ok(!lstrcmpW(lc_names
[1], lc_names
[j
]), "%d - lc_names[%d] = %s, expected %s\n",
521 i
, j
, wine_dbgstr_w(lc_names
[j
]), wine_dbgstr_w(lc_names
[1]));
525 p_setlocale(LC_ALL
, "C");
526 lc_names
= p____lc_locale_name_func();
527 ok(!lc_names
[1], "___lc_locale_name_func()[1] = %s\n", wine_dbgstr_w(lc_names
[1]));
530 static void test__GetConcurrency(void)
536 c
= (*p__GetConcurrency
)();
537 ok(c
== si
.dwNumberOfProcessors
, "expected %u, got %u\n", si
.dwNumberOfProcessors
, c
);
540 static void test__W_Gettnames(void)
542 static const char *str
[] = {
543 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
544 "Sunday", "Monday", "Tuesday", "Wednesday",
545 "Thursday", "Friday", "Saturday",
546 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
547 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
548 "January", "February", "March", "April", "May", "June", "July",
549 "August", "September", "October", "November", "December",
550 "AM", "PM", "M/d/yyyy"
563 if(!p_setlocale(LC_ALL
, "english"))
566 ret
= p__W_Gettnames();
567 size
= ret
->str
[0]-(char*)ret
;
568 if(sizeof(void*) == 8)
569 ok(size
==0x2c0, "structure size: %x\n", size
);
571 ok(size
==0x164, "structure size: %x\n", size
);
573 for(i
=0; i
<ARRAY_SIZE(str
); i
++) {
574 ok(!strcmp(ret
->str
[i
], str
[i
]), "ret->str[%d] = %s, expected %s\n",
575 i
, ret
->str
[i
], str
[i
]);
577 MultiByteToWideChar(CP_ACP
, 0, str
[i
], strlen(str
[i
])+1, buf
, ARRAY_SIZE(buf
));
578 ok(!lstrcmpW(ret
->wstr
[i
], buf
), "ret->wstr[%d] = %s, expected %s\n",
579 i
, wine_dbgstr_w(ret
->wstr
[i
]), wine_dbgstr_w(buf
));
583 p_setlocale(LC_ALL
, "C");
586 static void test__strtof(void)
588 const char float1
[] = "12.0";
589 const char float2
[] = "3.402823466e+38"; /* FLT_MAX */
590 const char float3
[] = "-3.402823466e+38";
591 const char float4
[] = "1.7976931348623158e+308"; /* DBL_MAX */
593 const WCHAR twelve
[] = {'1','2','.','0',0};
594 const WCHAR arabic23
[] = { 0x662, 0x663, 0};
599 f
= p_strtof(float1
, &end
);
600 ok(f
== 12.0, "f = %lf\n", f
);
601 ok(end
== float1
+4, "incorrect end (%d)\n", (int)(end
-float1
));
603 f
= p_strtof(float2
, &end
);
604 ok(f
== FLT_MAX
, "f = %lf\n", f
);
605 ok(end
== float2
+15, "incorrect end (%d)\n", (int)(end
-float2
));
607 f
= p_strtof(float3
, &end
);
608 ok(f
== -FLT_MAX
, "f = %lf\n", f
);
609 ok(end
== float3
+16, "incorrect end (%d)\n", (int)(end
-float3
));
611 f
= p_strtof(float4
, &end
);
612 ok(!p__finite(f
), "f = %lf\n", f
);
613 ok(end
== float4
+23, "incorrect end (%d)\n", (int)(end
-float4
));
615 f
= p_strtof("inf", NULL
);
616 ok(f
== 0, "f = %lf\n", f
);
618 f
= p_strtof("INF", NULL
);
619 ok(f
== 0, "f = %lf\n", f
);
621 f
= p_strtof("1.#inf", NULL
);
622 ok(f
== 1, "f = %lf\n", f
);
624 f
= p_strtof("INFINITY", NULL
);
625 ok(f
== 0, "f = %lf\n", f
);
627 f
= p_strtof("0x12", NULL
);
628 ok(f
== 0, "f = %lf\n", f
);
630 f
= p_wcstof(twelve
, NULL
);
631 ok(f
== 12.0, "f = %lf\n", f
);
633 f
= p_wcstof(arabic23
, NULL
);
634 ok(f
== 0, "f = %lf\n", f
);
636 if(!p_setlocale(LC_ALL
, "Arabic")) {
637 win_skip("Arabic locale not available\n");
641 f
= p_wcstof(twelve
, NULL
);
642 ok(f
== 12.0, "f = %lf\n", f
);
644 f
= p_wcstof(arabic23
, NULL
);
645 ok(f
== 0, "f = %lf\n", f
);
647 p_setlocale(LC_ALL
, "C");
650 static void test_remainder(void)
656 { 3.0, 2.0, -1.0, -1 },
657 { 1.0, 1.0, 0.0, -1 },
658 { INFINITY
, 0.0, NAN
, EDOM
},
659 { INFINITY
, 42.0, NAN
, EDOM
},
660 { NAN
, 0.0, NAN
, EDOM
},
661 { NAN
, 42.0, NAN
, EDOM
},
662 { 0.0, INFINITY
, 0.0, -1 },
663 { 42.0, INFINITY
, 42.0, -1 },
664 { 0.0, NAN
, NAN
, EDOM
},
665 { 42.0, NAN
, NAN
, EDOM
},
666 { 1.0, 0.0, NAN
, EDOM
},
667 { INFINITY
, INFINITY
, NAN
, EDOM
},
673 if(sizeof(void*) != 8) /* errno handling slightly different on 32-bit */
676 for(i
=0; i
<ARRAY_SIZE(tests
); i
++) {
678 r
= p_remainder(tests
[i
].x
, tests
[i
].y
);
681 ok(tests
[i
].e
== e
, "expected errno %i, but got %i\n", tests
[i
].e
, e
);
682 if(_isnan(tests
[i
].r
))
683 ok(_isnan(r
), "expected NAN, but got %f\n", r
);
685 ok(tests
[i
].r
== r
, "expected result %f, but got %f\n", tests
[i
].r
, r
);
689 static int enter_flag
;
690 static critical_section cs
;
691 static unsigned __stdcall
test_critical_section_lock(void *arg
)
693 critical_section
*native_handle
;
694 native_handle
= (critical_section
*)call_func1(p_critical_section_native_handle
, &cs
);
695 ok(native_handle
== &cs
, "native_handle = %p\n", native_handle
);
696 call_func1(p_critical_section_lock
, &cs
);
697 ok(enter_flag
== 1, "enter_flag = %d\n", enter_flag
);
698 call_func1(p_critical_section_unlock
, &cs
);
702 static unsigned __stdcall
test_critical_section_try_lock(void *arg
)
704 ok(!(MSVCRT_bool
)call_func1(p_critical_section_try_lock
, &cs
),
705 "critical_section_try_lock succeeded\n");
709 static unsigned __stdcall
test_critical_section_try_lock_for(void *arg
)
711 ok((MSVCRT_bool
)call_func2(p_critical_section_try_lock_for
, &cs
, 5000),
712 "critical_section_try_lock_for failed\n");
713 ok(enter_flag
== 1, "enter_flag = %d\n", enter_flag
);
714 call_func1(p_critical_section_unlock
, &cs
);
718 static unsigned __stdcall
test_critical_section_scoped_lock(void *arg
)
720 critical_section_scoped_lock counter_scope_lock
;
722 call_func2(p_critical_section_scoped_lock_ctor
, &counter_scope_lock
, &cs
);
723 ok(enter_flag
== 1, "enter_flag = %d\n", enter_flag
);
724 call_func1(p_critical_section_scoped_lock_dtor
, &counter_scope_lock
);
728 static void test_critical_section(void)
734 call_func1(p_critical_section_ctor
, &cs
);
735 call_func1(p_critical_section_lock
, &cs
);
736 thread
= (HANDLE
)_beginthreadex(NULL
, 0, test_critical_section_lock
, NULL
, 0, NULL
);
737 ok(thread
!= INVALID_HANDLE_VALUE
, "_beginthread failed (%d)\n", errno
);
738 ret
= WaitForSingleObject(thread
, 100);
739 ok(ret
== WAIT_TIMEOUT
, "WaitForSingleObject returned %d\n", ret
);
741 call_func1(p_critical_section_unlock
, &cs
);
742 ret
= WaitForSingleObject(thread
, INFINITE
);
743 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject returned %d\n", ret
);
744 ret
= CloseHandle(thread
);
745 ok(ret
, "CloseHandle failed\n");
747 ok((MSVCRT_bool
)call_func1(p_critical_section_try_lock
, &cs
),
748 "critical_section_try_lock failed\n");
749 thread
= (HANDLE
)_beginthreadex(NULL
, 0, test_critical_section_try_lock
, NULL
, 0, NULL
);
750 ok(thread
!= INVALID_HANDLE_VALUE
, "_beginthread failed (%d)\n", errno
);
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_unlock
, &cs
);
758 ok((MSVCRT_bool
)call_func2(p_critical_section_try_lock_for
, &cs
, 50),
759 "critical_section_try_lock_for failed\n");
760 thread
= (HANDLE
)_beginthreadex(NULL
, 0, test_critical_section_try_lock
, NULL
, 0, NULL
);
761 ok(thread
!= INVALID_HANDLE_VALUE
, "_beginthread failed (%d)\n", errno
);
762 ret
= WaitForSingleObject(thread
, INFINITE
);
763 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject returned %d\n", ret
);
764 ret
= CloseHandle(thread
);
765 ok(ret
, "CloseHandle failed\n");
766 thread
= (HANDLE
)_beginthreadex(NULL
, 0, test_critical_section_try_lock_for
, NULL
, 0, NULL
);
767 ok(thread
!= INVALID_HANDLE_VALUE
, "_beginthread failed (%d)\n", errno
);
770 call_func1(p_critical_section_unlock
, &cs
);
771 ret
= WaitForSingleObject(thread
, INFINITE
);
772 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject returned %d\n", ret
);
773 ret
= CloseHandle(thread
);
774 ok(ret
, "CloseHandle failed\n");
777 call_func1(p_critical_section_lock
, &cs
);
778 thread
= (HANDLE
)_beginthreadex(NULL
, 0, test_critical_section_scoped_lock
, NULL
, 0, NULL
);
779 ok(thread
!= INVALID_HANDLE_VALUE
, "_beginthread failed (%d)\n", errno
);
780 ret
= WaitForSingleObject(thread
, 100);
781 ok(ret
== WAIT_TIMEOUT
, "WaitForSingleObject returned %d\n", ret
);
783 call_func1(p_critical_section_unlock
, &cs
);
784 ret
= WaitForSingleObject(thread
, INFINITE
);
785 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject returned %d\n", ret
);
786 ret
= CloseHandle(thread
);
787 ok(ret
, "CloseHandle failed\n");
788 call_func1(p_critical_section_dtor
, &cs
);
791 static void test_feenv(void)
798 ret
= p_fegetenv(&env
);
799 ok(!ret
, "fegetenv returned %x\n", ret
);
800 p_fesetround(FE_UPWARD
);
801 ok(env
.control
== (_EM_INEXACT
|_EM_UNDERFLOW
|_EM_OVERFLOW
|_EM_ZERODIVIDE
|_EM_INVALID
),
802 "env.control = %x\n", env
.control
);
803 ok(!env
.status
, "env.status = %x\n", env
.status
);
804 ret
= p_fegetenv(&env2
);
805 ok(!ret
, "fegetenv returned %x\n", ret
);
806 ok(env2
.control
== (_EM_INEXACT
|_EM_UNDERFLOW
|_EM_OVERFLOW
|_EM_ZERODIVIDE
|_EM_INVALID
| FE_UPWARD
),
807 "env2.control = %x\n", env2
.control
);
808 ret
= p_fesetenv(&env
);
809 ok(!ret
, "fesetenv returned %x\n", ret
);
810 ret
= p_fegetround();
811 ok(ret
== FE_TONEAREST
, "Got unexpected round mode %#x.\n", ret
);
814 static void test__wcreate_locale(void)
816 static const wchar_t c_locale
[] = {'C',0};
817 static const wchar_t bogus
[] = {'b','o','g','u','s',0};
818 static const wchar_t empty
[] = {0};
824 lcl
= p_wcreate_locale(LC_ALL
, c_locale
);
826 ok(!!lcl
, "expected success, but got NULL\n");
827 ok(errno
== -1, "expected errno -1, but got %i\n", e
);
831 lcl
= p_wcreate_locale(LC_ALL
, empty
);
833 ok(!!lcl
, "expected success, but got NULL\n");
834 ok(errno
== -1, "expected errno -1, but got %i\n", e
);
839 lcl
= p_wcreate_locale(-1, c_locale
);
841 ok(!lcl
, "expected failure, but got %p\n", lcl
);
842 ok(errno
== -1, "expected errno -1, but got %i\n", e
);
846 lcl
= p_wcreate_locale(LC_ALL
, bogus
);
848 ok(!lcl
, "expected failure, but got %p\n", lcl
);
849 ok(errno
== -1, "expected errno -1, but got %i\n", e
);
852 lcl
= p_wcreate_locale(LC_ALL
, NULL
);
854 ok(!lcl
, "expected failure, but got %p\n", lcl
);
855 ok(errno
== -1, "expected errno -1, but got %i\n", e
);
858 struct wait_thread_arg
860 critical_section
*cs
;
861 _Condition_variable
*cv
;
862 HANDLE thread_initialized
;
865 static DWORD WINAPI
condition_variable_wait_thread(void *varg
)
867 struct wait_thread_arg
*arg
= varg
;
869 call_func1(p_critical_section_lock
, arg
->cs
);
870 SetEvent(arg
->thread_initialized
);
871 call_func2(p__Condition_variable_wait
, arg
->cv
, arg
->cs
);
872 call_func1(p_critical_section_unlock
, arg
->cs
);
876 static void test__Condition_variable(void)
879 _Condition_variable cv
;
880 HANDLE thread_initialized
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
881 struct wait_thread_arg wait_thread_arg
= { &cs
, &cv
, thread_initialized
};
886 ok(thread_initialized
!= NULL
, "CreateEvent failed\n");
888 call_func1(p_critical_section_ctor
, &cs
);
889 call_func1(p__Condition_variable_ctor
, &cv
);
891 call_func1(p__Condition_variable_notify_one
, &cv
);
892 call_func1(p__Condition_variable_notify_all
, &cv
);
894 threads
[0] = CreateThread(0, 0, condition_variable_wait_thread
,
895 &wait_thread_arg
, 0, 0);
896 ok(threads
[0] != NULL
, "CreateThread failed\n");
897 WaitForSingleObject(thread_initialized
, INFINITE
);
898 call_func1(p_critical_section_lock
, &cs
);
899 call_func1(p_critical_section_unlock
, &cs
);
901 threads
[1] = CreateThread(0, 0, condition_variable_wait_thread
,
902 &wait_thread_arg
, 0, 0);
903 ok(threads
[1] != NULL
, "CreateThread failed\n");
904 WaitForSingleObject(thread_initialized
, INFINITE
);
905 call_func1(p_critical_section_lock
, &cs
);
906 call_func1(p_critical_section_unlock
, &cs
);
908 call_func1(p__Condition_variable_notify_one
, &cv
);
909 ret
= WaitForSingleObject(threads
[1], 500);
910 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject returned %d\n", ret
);
911 call_func1(p__Condition_variable_notify_one
, &cv
);
912 ret
= WaitForSingleObject(threads
[0], 500);
913 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject returned %d\n", ret
);
915 CloseHandle(threads
[0]);
916 CloseHandle(threads
[1]);
918 call_func1(p_critical_section_lock
, &cs
);
919 b
= call_func3(p__Condition_variable_wait_for
, &cv
, &cs
, 1);
920 ok(!b
, "_Condition_variable_wait_for returned TRUE\n");
921 call_func1(p_critical_section_unlock
, &cs
);
923 call_func1(p_critical_section_dtor
, &cs
);
924 call_func1(p__Condition_variable_dtor
, &cv
);
926 CloseHandle(thread_initialized
);
929 static void test_wctype(void)
931 static const struct {
952 for(i
=0; i
<ARRAY_SIZE(properties
); i
++) {
953 ret
= p_wctype(properties
[i
].name
);
954 ok(properties
[i
].mask
== ret
, "%d - Expected %x, got %x\n", i
, properties
[i
].mask
, ret
);
958 static int WINAPIV
_vsscanf_wrapper(const char *buffer
, const char *format
, ...)
962 __ms_va_start(valist
, format
);
963 ret
= p_vsscanf(buffer
, format
, valist
);
968 static void test_vsscanf(void)
970 static const char *fmt
= "%d";
976 ret
= _vsscanf_wrapper(buff
, fmt
, &v
);
977 ok(ret
== 1, "Unexpected ret %d.\n", ret
);
978 ok(v
== 10, "got %d.\n", v
);
981 static void test__Cbuild(void)
986 memset(&c
, 0, sizeof(c
));
987 p__Cbuild(&c
, 1.0, 2.0);
988 ok(c
.r
== 1.0, "c.r = %lf\n", c
.r
);
989 ok(c
.i
== 2.0, "c.i = %lf\n", c
.i
);
991 ok(d
== 1.0, "creal returned %lf\n", d
);
993 p__Cbuild(&c
, 3.0, NAN
);
994 ok(c
.r
== 3.0, "c.r = %lf\n", c
.r
);
995 ok(_isnan(c
.i
), "c.i = %lf\n", c
.i
);
997 ok(d
== 3.0, "creal returned %lf\n", d
);
1000 static void test_nexttoward(void)
1016 {0.0, 0.0, 0.0f
, 0.0},
1017 {0.0, 1.0, 1.0e-45f
, 5.0e-324},
1018 {0.0, -1.0, -1.0e-45f
, -5.0e-324},
1019 {2.2250738585072009e-308, 0.0, 0.0f
, 2.2250738585072004e-308},
1020 {2.2250738585072009e-308, 2.2250738585072010e-308, 1.0e-45f
, 2.2250738585072009e-308},
1021 {2.2250738585072009e-308, 1.0, 1.0e-45f
, 2.2250738585072014e-308},
1022 {2.2250738585072014e-308, 0.0, 0.0f
, 2.2250738585072009e-308},
1023 {2.2250738585072014e-308, 2.2250738585072014e-308, 1.0e-45f
, 2.2250738585072014e-308},
1024 {2.2250738585072014e-308, 1.0, 1.0e-45f
, 2.2250738585072019e-308},
1025 {1.0, 2.0, 1.00000012f
, 1.0000000000000002},
1026 {1.0, 0.0, 0.99999994f
, 0.9999999999999999},
1027 {1.0, 1.0, 1.0f
, 1.0},
1028 {0.0, INFINITY
, 1.0e-45f
, 5.0e-324},
1029 {FLT_MAX
, INFINITY
, INFINITY
, 3.402823466385289e+038},
1030 {DBL_MAX
, INFINITY
, INFINITY
, INFINITY
},
1031 {INFINITY
, INFINITY
, INFINITY
, INFINITY
},
1032 {INFINITY
, 0, FLT_MAX
, DBL_MAX
},
1035 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
)
1037 f
= p_nexttowardf(tests
[i
].source
, tests
[i
].dir
);
1038 ok(f
== tests
[i
].f
, "Test %d: expected %0.8ef, got %0.8ef.\n", i
, tests
[i
].f
, f
);
1041 d
= p_nexttoward(tests
[i
].source
, tests
[i
].dir
);
1043 ok(d
== tests
[i
].d
, "Test %d: expected %0.16e, got %0.16e.\n", i
, tests
[i
].d
, d
);
1044 if (!isnormal(d
) && !isinf(tests
[i
].source
))
1045 ok(e
== ERANGE
, "Test %d: expected ERANGE, got %d.\n", i
, e
);
1047 ok(e
== -1, "Test %d: expected no error, got %d.\n", i
, e
);
1049 d
= p_nexttowardl(tests
[i
].source
, tests
[i
].dir
);
1050 ok(d
== tests
[i
].d
, "Test %d: expected %0.16e, got %0.16e.\n", i
, tests
[i
].d
, d
);
1054 d
= p_nexttoward(NAN
, 0);
1056 ok(_isnan(d
), "Expected NAN, got %0.16e.\n", d
);
1057 ok(e
== -1, "Expected no error, got %d.\n", e
);
1060 d
= p_nexttoward(NAN
, NAN
);
1062 ok(_isnan(d
), "Expected NAN, got %0.16e.\n", d
);
1063 ok(e
== -1, "Expected no error, got %d.\n", e
);
1066 d
= p_nexttoward(0, NAN
);
1068 ok(_isnan(d
), "Expected NAN, got %0.16e.\n", d
);
1069 ok(e
== -1, "Expected no error, got %d.\n", e
);
1072 static void test_towctrans(void)
1076 ret
= p_wctrans("tolower");
1077 ok(ret
== 2, "wctrans returned %d, expected 2\n", ret
);
1078 ret
= p_wctrans("toupper");
1079 ok(ret
== 1, "wctrans returned %d, expected 1\n", ret
);
1080 ret
= p_wctrans("toLower");
1081 ok(ret
== 0, "wctrans returned %d, expected 0\n", ret
);
1082 ret
= p_wctrans("");
1083 ok(ret
== 0, "wctrans returned %d, expected 0\n", ret
);
1084 if(0) { /* crashes on windows */
1085 ret
= p_wctrans(NULL
);
1086 ok(ret
== 0, "wctrans returned %d, expected 0\n", ret
);
1089 ret
= p_towctrans('t', 2);
1090 ok(ret
== 't', "towctrans('t', 2) returned %c, expected t\n", ret
);
1091 ret
= p_towctrans('T', 2);
1092 ok(ret
== 't', "towctrans('T', 2) returned %c, expected t\n", ret
);
1093 ret
= p_towctrans('T', 0);
1094 ok(ret
== 't', "towctrans('T', 0) returned %c, expected t\n", ret
);
1095 ret
= p_towctrans('T', 3);
1096 ok(ret
== 't', "towctrans('T', 3) returned %c, expected t\n", ret
);
1097 ret
= p_towctrans('t', 1);
1098 ok(ret
== 'T', "towctrans('t', 1) returned %c, expected T\n", ret
);
1099 ret
= p_towctrans('T', 1);
1100 ok(ret
== 'T', "towctrans('T', 1) returned %c, expected T\n", ret
);
1103 static void test_CurrentContext(void)
1105 _Context _ctx
, *ret
;
1108 ctx
= p_Context_CurrentContext();
1109 ok(!!ctx
, "got NULL\n");
1111 memset(&_ctx
, 0xcc, sizeof(_ctx
));
1112 ret
= p__Context__CurrentContext(&_ctx
);
1113 ok(_ctx
.ctx
== ctx
, "expected %p, got %p\n", ctx
, _ctx
.ctx
);
1114 ok(ret
== &_ctx
, "expected %p, got %p\n", &_ctx
, ret
);
1117 START_TEST(msvcr120
)
1119 if (!init()) return;
1124 test____lc_locale_name_func();
1125 test__GetConcurrency();
1126 test__W_Gettnames();
1129 test_critical_section();
1131 test__wcreate_locale();
1132 test__Condition_variable();
1138 test_CurrentContext();