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
30 #include "wine/test.h"
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 */
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))
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)
81 #define __thiscall __stdcall
83 #define __thiscall __cdecl
86 typedef unsigned char MSVCRT_bool
;
88 typedef struct cs_queue
90 struct cs_queue
*next
;
97 ULONG_PTR unk_thread_id
;
106 critical_section
*cs
;
109 } critical_section_scoped_lock
;
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()
135 char* int_curr_symbol
;
136 char* currency_symbol
;
137 char* mon_decimal_point
;
138 char* mon_thousands_sep
;
142 char int_frac_digits
;
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
;
162 unsigned int control
;
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 */
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)
217 module
= LoadLibraryA("msvcr120.dll");
220 win_skip("msvcr120.dll not installed\n");
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");
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");
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");
342 init_thiscall_thunk();
346 static void test_lconv_helper(const char *locstr
)
348 struct MSVCRT_lconv
*lconv
;
352 if(!p_setlocale(LC_ALL
, locstr
))
354 win_skip("locale %s not available\n", locstr
);
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)
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)
420 ok(ret
== 0, "p_dsign(1) = %x\n", ret
);
422 ok(ret
== 0, "p_dsign(0) = %x\n", ret
);
424 ok(ret
== 0x8000, "p_dsign(-1) = %x\n", ret
);
427 ok(ret
== 0, "p_fdsign(1) = %x\n", ret
);
429 ok(ret
== 0, "p_fdsign(0) = %x\n", ret
);
431 ok(ret
== 0x8000, "p_fdsign(-1) = %x\n", ret
);
434 static void test__dpcomp(void)
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},
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)
458 const WCHAR name
[10];
459 const WCHAR broken_name
[10];
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} }
476 for(i
=0; i
<sizeof(tests
)/sizeof(*tests
); i
++) {
477 if(!p_setlocale(LC_ALL
, tests
[i
].locale
))
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)
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"
529 if(!p_setlocale(LC_ALL
, "english"))
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
);
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
));
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};
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");
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)
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
},
640 if(sizeof(void*) != 8) /* errno handling slightly different on 32-bit */
643 for(i
=0; i
<sizeof(tests
)/sizeof(*tests
); i
++) {
645 r
= p_remainder(tests
[i
].x
, tests
[i
].y
);
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
);
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
);
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");
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
);
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
);
695 static void test_critical_section(void)
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
);
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
);
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
);
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");
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
);
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)
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};
782 lcl
= p_wcreate_locale(LC_ALL
, c_locale
);
784 ok(!!lcl
, "expected success, but got NULL\n");
785 ok(errno
== -1, "expected errno -1, but got %i\n", e
);
789 lcl
= p_wcreate_locale(LC_ALL
, empty
);
791 ok(!!lcl
, "expected success, but got NULL\n");
792 ok(errno
== -1, "expected errno -1, but got %i\n", e
);
797 lcl
= p_wcreate_locale(-1, c_locale
);
799 ok(!lcl
, "expected failure, but got %p\n", lcl
);
800 ok(errno
== -1, "expected errno -1, but got %i\n", e
);
804 lcl
= p_wcreate_locale(LC_ALL
, bogus
);
806 ok(!lcl
, "expected failure, but got %p\n", lcl
);
807 ok(errno
== -1, "expected errno -1, but got %i\n", e
);
810 lcl
= p_wcreate_locale(LC_ALL
, NULL
);
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
);
834 static void test__Condition_variable(void)
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
};
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 {
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
, ...)
920 __ms_va_start(valist
, format
);
921 ret
= p_vsscanf(buffer
, format
, valist
);
926 static void test_vsscanf(void)
928 static const char *fmt
= "%d";
934 ret
= _vsscanf_wrapper(buff
, fmt
, &v
);
935 ok(ret
== 1, "Unexpected ret %d.\n", ret
);
936 ok(v
== 10, "got %d.\n", v
);
946 test____lc_locale_name_func();
947 test__GetConcurrency();
951 test_critical_section();
953 test__wcreate_locale();
954 test__Condition_variable();