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*);
187 /* make sure we use the correct errno */
189 #define errno (*p_errno())
191 static critical_section
* (__thiscall
*p_critical_section_ctor
)(critical_section
*);
192 static void (__thiscall
*p_critical_section_dtor
)(critical_section
*);
193 static void (__thiscall
*p_critical_section_lock
)(critical_section
*);
194 static void (__thiscall
*p_critical_section_unlock
)(critical_section
*);
195 static critical_section
* (__thiscall
*p_critical_section_native_handle
)(critical_section
*);
196 static MSVCRT_bool (__thiscall
*p_critical_section_try_lock
)(critical_section
*);
197 static MSVCRT_bool (__thiscall
*p_critical_section_try_lock_for
)(critical_section
*, unsigned int);
198 static critical_section_scoped_lock
* (__thiscall
*p_critical_section_scoped_lock_ctor
)
199 (critical_section_scoped_lock
*, critical_section
*);
200 static void (__thiscall
*p_critical_section_scoped_lock_dtor
)(critical_section_scoped_lock
*);
202 static _Condition_variable
* (__thiscall
*p__Condition_variable_ctor
)(_Condition_variable
*);
203 static void (__thiscall
*p__Condition_variable_dtor
)(_Condition_variable
*);
204 static void (__thiscall
*p__Condition_variable_wait
)(_Condition_variable
*, critical_section
*);
205 static MSVCRT_bool (__thiscall
*p__Condition_variable_wait_for
)(_Condition_variable
*, critical_section
*, unsigned int);
206 static void (__thiscall
*p__Condition_variable_notify_one
)(_Condition_variable
*);
207 static void (__thiscall
*p__Condition_variable_notify_all
)(_Condition_variable
*);
209 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(module,y)
210 #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
212 static BOOL
init(void)
216 module
= LoadLibraryA("msvcr120.dll");
219 win_skip("msvcr120.dll not installed\n");
223 p_setlocale
= (void*)GetProcAddress(module
, "setlocale");
224 p_localeconv
= (void*)GetProcAddress(module
, "localeconv");
225 p_wcstombs_s
= (void*)GetProcAddress(module
, "wcstombs_s");
226 p__dsign
= (void*)GetProcAddress(module
, "_dsign");
227 p__fdsign
= (void*)GetProcAddress(module
, "_fdsign");
228 p__dpcomp
= (void*)GetProcAddress(module
, "_dpcomp");
229 p____lc_locale_name_func
= (void*)GetProcAddress(module
, "___lc_locale_name_func");
230 p__GetConcurrency
= (void*)GetProcAddress(module
,"?_GetConcurrency@details@Concurrency@@YAIXZ");
231 p__W_Gettnames
= (void*)GetProcAddress(module
, "_W_Gettnames");
232 p_free
= (void*)GetProcAddress(module
, "free");
233 p_strtof
= (void*)GetProcAddress(module
, "strtof");
234 p__finite
= (void*)GetProcAddress(module
, "_finite");
235 p_wcstof
= (void*)GetProcAddress(module
, "wcstof");
236 p_remainder
= (void*)GetProcAddress(module
, "remainder");
237 p_errno
= (void*)GetProcAddress(module
, "_errno");
238 p_wcreate_locale
= (void*)GetProcAddress(module
, "_wcreate_locale");
239 p_free_locale
= (void*)GetProcAddress(module
, "_free_locale");
240 SET(p_wctype
, "wctype");
241 SET(p_fegetenv
, "fegetenv");
242 SET(p__clearfp
, "_clearfp");
243 if(sizeof(void*) == 8) { /* 64-bit initialization */
244 SET(p_critical_section_ctor
,
245 "??0critical_section@Concurrency@@QEAA@XZ");
246 SET(p_critical_section_dtor
,
247 "??1critical_section@Concurrency@@QEAA@XZ");
248 SET(p_critical_section_lock
,
249 "?lock@critical_section@Concurrency@@QEAAXXZ");
250 SET(p_critical_section_unlock
,
251 "?unlock@critical_section@Concurrency@@QEAAXXZ");
252 SET(p_critical_section_native_handle
,
253 "?native_handle@critical_section@Concurrency@@QEAAAEAV12@XZ");
254 SET(p_critical_section_try_lock
,
255 "?try_lock@critical_section@Concurrency@@QEAA_NXZ");
256 SET(p_critical_section_try_lock_for
,
257 "?try_lock_for@critical_section@Concurrency@@QEAA_NI@Z");
258 SET(p_critical_section_scoped_lock_ctor
,
259 "??0scoped_lock@critical_section@Concurrency@@QEAA@AEAV12@@Z");
260 SET(p_critical_section_scoped_lock_dtor
,
261 "??1scoped_lock@critical_section@Concurrency@@QEAA@XZ");
262 SET(p__Condition_variable_ctor
,
263 "??0_Condition_variable@details@Concurrency@@QEAA@XZ");
264 SET(p__Condition_variable_dtor
,
265 "??1_Condition_variable@details@Concurrency@@QEAA@XZ");
266 SET(p__Condition_variable_wait
,
267 "?wait@_Condition_variable@details@Concurrency@@QEAAXAEAVcritical_section@3@@Z");
268 SET(p__Condition_variable_wait_for
,
269 "?wait_for@_Condition_variable@details@Concurrency@@QEAA_NAEAVcritical_section@3@I@Z");
270 SET(p__Condition_variable_notify_one
,
271 "?notify_one@_Condition_variable@details@Concurrency@@QEAAXXZ");
272 SET(p__Condition_variable_notify_all
,
273 "?notify_all@_Condition_variable@details@Concurrency@@QEAAXXZ");
276 SET(p_critical_section_ctor
,
277 "??0critical_section@Concurrency@@QAA@XZ");
278 SET(p_critical_section_dtor
,
279 "??1critical_section@Concurrency@@QAA@XZ");
280 SET(p_critical_section_lock
,
281 "?lock@critical_section@Concurrency@@QAAXXZ");
282 SET(p_critical_section_unlock
,
283 "?unlock@critical_section@Concurrency@@QAAXXZ");
284 SET(p_critical_section_native_handle
,
285 "?native_handle@critical_section@Concurrency@@QAAAAV12@XZ");
286 SET(p_critical_section_try_lock
,
287 "?try_lock@critical_section@Concurrency@@QAA_NXZ");
288 SET(p_critical_section_try_lock_for
,
289 "?try_lock_for@critical_section@Concurrency@@QAA_NI@Z");
290 SET(p_critical_section_scoped_lock_ctor
,
291 "??0scoped_lock@critical_section@Concurrency@@QAA@AAV12@@Z");
292 SET(p_critical_section_scoped_lock_dtor
,
293 "??1scoped_lock@critical_section@Concurrency@@QAA@XZ");
294 SET(p__Condition_variable_ctor
,
295 "??0_Condition_variable@details@Concurrency@@QAA@XZ");
296 SET(p__Condition_variable_dtor
,
297 "??1_Condition_variable@details@Concurrency@@QAA@XZ");
298 SET(p__Condition_variable_wait
,
299 "?wait@_Condition_variable@details@Concurrency@@QAAXAAVcritical_section@3@@Z");
300 SET(p__Condition_variable_wait_for
,
301 "?wait_for@_Condition_variable@details@Concurrency@@QAA_NAAVcritical_section@3@I@Z");
302 SET(p__Condition_variable_notify_one
,
303 "?notify_one@_Condition_variable@details@Concurrency@@QAAXXZ");
304 SET(p__Condition_variable_notify_all
,
305 "?notify_all@_Condition_variable@details@Concurrency@@QAAXXZ");
307 SET(p_critical_section_ctor
,
308 "??0critical_section@Concurrency@@QAE@XZ");
309 SET(p_critical_section_dtor
,
310 "??1critical_section@Concurrency@@QAE@XZ");
311 SET(p_critical_section_lock
,
312 "?lock@critical_section@Concurrency@@QAEXXZ");
313 SET(p_critical_section_unlock
,
314 "?unlock@critical_section@Concurrency@@QAEXXZ");
315 SET(p_critical_section_native_handle
,
316 "?native_handle@critical_section@Concurrency@@QAEAAV12@XZ");
317 SET(p_critical_section_try_lock
,
318 "?try_lock@critical_section@Concurrency@@QAE_NXZ");
319 SET(p_critical_section_try_lock_for
,
320 "?try_lock_for@critical_section@Concurrency@@QAE_NI@Z");
321 SET(p_critical_section_scoped_lock_ctor
,
322 "??0scoped_lock@critical_section@Concurrency@@QAE@AAV12@@Z");
323 SET(p_critical_section_scoped_lock_dtor
,
324 "??1scoped_lock@critical_section@Concurrency@@QAE@XZ");
325 SET(p__Condition_variable_ctor
,
326 "??0_Condition_variable@details@Concurrency@@QAE@XZ");
327 SET(p__Condition_variable_dtor
,
328 "??1_Condition_variable@details@Concurrency@@QAE@XZ");
329 SET(p__Condition_variable_wait
,
330 "?wait@_Condition_variable@details@Concurrency@@QAEXAAVcritical_section@3@@Z");
331 SET(p__Condition_variable_wait_for
,
332 "?wait_for@_Condition_variable@details@Concurrency@@QAE_NAAVcritical_section@3@I@Z");
333 SET(p__Condition_variable_notify_one
,
334 "?notify_one@_Condition_variable@details@Concurrency@@QAEXXZ");
335 SET(p__Condition_variable_notify_all
,
336 "?notify_all@_Condition_variable@details@Concurrency@@QAEXXZ");
340 init_thiscall_thunk();
344 static void test_lconv_helper(const char *locstr
)
346 struct MSVCRT_lconv
*lconv
;
350 if(!p_setlocale(LC_ALL
, locstr
))
352 win_skip("locale %s not available\n", locstr
);
356 lconv
= p_localeconv();
358 /* If multi-byte version available, asserts that wide char version also available.
359 * If wide char version can be converted to a multi-byte string , asserts that the
360 * conversion result is the same as the multi-byte version.
362 if(strlen(lconv
->decimal_point
) > 0)
363 ok(wcslen(lconv
->_W_decimal_point
) > 0, "%s: decimal_point\n", locstr
);
364 if(p_wcstombs_s(&i
, mbs
, 256, lconv
->_W_decimal_point
, 256) == 0)
365 ok(strcmp(mbs
, lconv
->decimal_point
) == 0, "%s: decimal_point\n", locstr
);
367 if(strlen(lconv
->thousands_sep
) > 0)
368 ok(wcslen(lconv
->_W_thousands_sep
) > 0, "%s: thousands_sep\n", locstr
);
369 if(p_wcstombs_s(&i
, mbs
, 256, lconv
->_W_thousands_sep
, 256) == 0)
370 ok(strcmp(mbs
, lconv
->thousands_sep
) == 0, "%s: thousands_sep\n", locstr
);
372 if(strlen(lconv
->int_curr_symbol
) > 0)
373 ok(wcslen(lconv
->_W_int_curr_symbol
) > 0, "%s: int_curr_symbol\n", locstr
);
374 if(p_wcstombs_s(&i
, mbs
, 256, lconv
->_W_int_curr_symbol
, 256) == 0)
375 ok(strcmp(mbs
, lconv
->int_curr_symbol
) == 0, "%s: int_curr_symbol\n", locstr
);
377 if(strlen(lconv
->currency_symbol
) > 0)
378 ok(wcslen(lconv
->_W_currency_symbol
) > 0, "%s: currency_symbol\n", locstr
);
379 if(p_wcstombs_s(&i
, mbs
, 256, lconv
->_W_currency_symbol
, 256) == 0)
380 ok(strcmp(mbs
, lconv
->currency_symbol
) == 0, "%s: currency_symbol\n", locstr
);
382 if(strlen(lconv
->mon_decimal_point
) > 0)
383 ok(wcslen(lconv
->_W_mon_decimal_point
) > 0, "%s: decimal_point\n", locstr
);
384 if(p_wcstombs_s(&i
, mbs
, 256, lconv
->_W_mon_decimal_point
, 256) == 0)
385 ok(strcmp(mbs
, lconv
->mon_decimal_point
) == 0, "%s: decimal_point\n", locstr
);
387 if(strlen(lconv
->positive_sign
) > 0)
388 ok(wcslen(lconv
->_W_positive_sign
) > 0, "%s: positive_sign\n", locstr
);
389 if(p_wcstombs_s(&i
, mbs
, 256, lconv
->_W_positive_sign
, 256) == 0)
390 ok(strcmp(mbs
, lconv
->positive_sign
) == 0, "%s: positive_sign\n", locstr
);
392 if(strlen(lconv
->negative_sign
) > 0)
393 ok(wcslen(lconv
->_W_negative_sign
) > 0, "%s: negative_sign\n", locstr
);
394 if(p_wcstombs_s(&i
, mbs
, 256, lconv
->_W_negative_sign
, 256) == 0)
395 ok(strcmp(mbs
, lconv
->negative_sign
) == 0, "%s: negative_sign\n", locstr
);
398 static void test_lconv(void)
401 const char *locstrs
[] =
403 "American", "Belgian", "Chinese",
404 "Dutch", "English", "French",
405 "German", "Hungarian", "Icelandic",
406 "Japanese", "Korean", "Spanish"
409 for(i
= 0; i
< sizeof(locstrs
) / sizeof(char *); i
++)
410 test_lconv_helper(locstrs
[i
]);
413 static void test__dsign(void)
418 ok(ret
== 0, "p_dsign(1) = %x\n", ret
);
420 ok(ret
== 0, "p_dsign(0) = %x\n", ret
);
422 ok(ret
== 0x8000, "p_dsign(-1) = %x\n", ret
);
425 ok(ret
== 0, "p_fdsign(1) = %x\n", ret
);
427 ok(ret
== 0, "p_fdsign(0) = %x\n", ret
);
429 ok(ret
== 0x8000, "p_fdsign(-1) = %x\n", ret
);
432 static void test__dpcomp(void)
438 {0, 0, 2}, {1, 1, 2}, {-1, -1, 2},
439 {-2, -1, 1}, {-1, 1, 1}, {1, 2, 1},
440 {1, -1, 4}, {2, 1, 4}, {-1, -2, 4},
441 {NAN
, NAN
, 0}, {NAN
, 1, 0}, {1, NAN
, 0},
442 {INFINITY
, INFINITY
, 2}, {-1, INFINITY
, 1}, {1, INFINITY
, 1},
446 for(i
=0; i
<sizeof(tests
)/sizeof(*tests
); i
++) {
447 ret
= p__dpcomp(tests
[i
].x
, tests
[i
].y
);
448 ok(ret
== tests
[i
].ret
, "%d) dpcomp(%f, %f) = %x\n", i
, tests
[i
].x
, tests
[i
].y
, ret
);
452 static void test____lc_locale_name_func(void)
456 const WCHAR name
[10];
457 const WCHAR broken_name
[10];
459 { "American", {'e','n',0}, {'e','n','-','U','S',0} },
460 { "Belgian", {'n','l','-','B','E',0} },
461 { "Chinese", {'z','h',0}, {'z','h','-','C','N',0} },
462 { "Dutch", {'n','l',0}, {'n','l','-','N','L',0} },
463 { "English", {'e','n',0}, {'e','n','-','U','S',0} },
464 { "French", {'f','r',0}, {'f','r','-','F','R',0} },
465 { "German", {'d','e',0}, {'d','e','-','D','E',0} },
466 { "Hungarian", {'h','u',0}, {'h','u','-','H','U',0} },
467 { "Icelandic", {'i','s',0}, {'i','s','-','I','S',0} },
468 { "Japanese", {'j','a',0}, {'j','a','-','J','P',0} },
469 { "Korean", {'k','o',0}, {'k','o','-','K','R',0} }
474 for(i
=0; i
<sizeof(tests
)/sizeof(*tests
); i
++) {
475 if(!p_setlocale(LC_ALL
, tests
[i
].locale
))
478 lc_names
= p____lc_locale_name_func();
479 ok(lc_names
[0] == NULL
, "%d - lc_names[0] = %s\n", i
, wine_dbgstr_w(lc_names
[0]));
480 ok(!lstrcmpW(lc_names
[1], tests
[i
].name
) || broken(!lstrcmpW(lc_names
[1], tests
[i
].broken_name
)),
481 "%d - lc_names[1] = %s\n", i
, wine_dbgstr_w(lc_names
[1]));
483 for(j
=LC_MIN
+2; j
<=LC_MAX
; j
++) {
484 ok(!lstrcmpW(lc_names
[1], lc_names
[j
]), "%d - lc_names[%d] = %s, expected %s\n",
485 i
, j
, wine_dbgstr_w(lc_names
[j
]), wine_dbgstr_w(lc_names
[1]));
489 p_setlocale(LC_ALL
, "C");
490 lc_names
= p____lc_locale_name_func();
491 ok(!lc_names
[1], "___lc_locale_name_func()[1] = %s\n", wine_dbgstr_w(lc_names
[1]));
494 static void test__GetConcurrency(void)
500 c
= (*p__GetConcurrency
)();
501 ok(c
== si
.dwNumberOfProcessors
, "expected %u, got %u\n", si
.dwNumberOfProcessors
, c
);
504 static void test__W_Gettnames(void)
506 static const char *str
[] = {
507 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
508 "Sunday", "Monday", "Tuesday", "Wednesday",
509 "Thursday", "Friday", "Saturday",
510 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
511 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
512 "January", "February", "March", "April", "May", "June", "July",
513 "August", "September", "October", "November", "December",
514 "AM", "PM", "M/d/yyyy"
527 if(!p_setlocale(LC_ALL
, "english"))
530 ret
= p__W_Gettnames();
531 size
= ret
->str
[0]-(char*)ret
;
532 if(sizeof(void*) == 8)
533 ok(size
==0x2c0, "structure size: %x\n", size
);
535 ok(size
==0x164, "structure size: %x\n", size
);
537 for(i
=0; i
<sizeof(str
)/sizeof(*str
); i
++) {
538 ok(!strcmp(ret
->str
[i
], str
[i
]), "ret->str[%d] = %s, expected %s\n",
539 i
, ret
->str
[i
], str
[i
]);
541 MultiByteToWideChar(CP_ACP
, 0, str
[i
], strlen(str
[i
])+1,
542 buf
, sizeof(buf
)/sizeof(*buf
));
543 ok(!lstrcmpW(ret
->wstr
[i
], buf
), "ret->wstr[%d] = %s, expected %s\n",
544 i
, wine_dbgstr_w(ret
->wstr
[i
]), wine_dbgstr_w(buf
));
548 p_setlocale(LC_ALL
, "C");
551 static void test__strtof(void)
553 const char float1
[] = "12.0";
554 const char float2
[] = "3.402823466e+38"; /* FLT_MAX */
555 const char float3
[] = "-3.402823466e+38";
556 const char float4
[] = "1.7976931348623158e+308"; /* DBL_MAX */
558 const WCHAR twelve
[] = {'1','2','.','0',0};
559 const WCHAR arabic23
[] = { 0x662, 0x663, 0};
564 f
= p_strtof(float1
, &end
);
565 ok(f
== 12.0, "f = %lf\n", f
);
566 ok(end
== float1
+4, "incorrect end (%d)\n", (int)(end
-float1
));
568 f
= p_strtof(float2
, &end
);
569 ok(f
== FLT_MAX
, "f = %lf\n", f
);
570 ok(end
== float2
+15, "incorrect end (%d)\n", (int)(end
-float2
));
572 f
= p_strtof(float3
, &end
);
573 ok(f
== -FLT_MAX
, "f = %lf\n", f
);
574 ok(end
== float3
+16, "incorrect end (%d)\n", (int)(end
-float3
));
576 f
= p_strtof(float4
, &end
);
577 ok(!p__finite(f
), "f = %lf\n", f
);
578 ok(end
== float4
+23, "incorrect end (%d)\n", (int)(end
-float4
));
580 f
= p_strtof("inf", NULL
);
581 ok(f
== 0, "f = %lf\n", f
);
583 f
= p_strtof("INF", NULL
);
584 ok(f
== 0, "f = %lf\n", f
);
586 f
= p_strtof("1.#inf", NULL
);
587 ok(f
== 1, "f = %lf\n", f
);
589 f
= p_strtof("INFINITY", NULL
);
590 ok(f
== 0, "f = %lf\n", f
);
592 f
= p_strtof("0x12", NULL
);
593 ok(f
== 0, "f = %lf\n", f
);
595 f
= p_wcstof(twelve
, NULL
);
596 ok(f
== 12.0, "f = %lf\n", f
);
598 f
= p_wcstof(arabic23
, NULL
);
599 ok(f
== 0, "f = %lf\n", f
);
601 if(!p_setlocale(LC_ALL
, "Arabic")) {
602 win_skip("Arabic locale not available\n");
606 f
= p_wcstof(twelve
, NULL
);
607 ok(f
== 12.0, "f = %lf\n", f
);
609 f
= p_wcstof(arabic23
, NULL
);
610 ok(f
== 0, "f = %lf\n", f
);
612 p_setlocale(LC_ALL
, "C");
615 static void test_remainder(void)
621 { 3.0, 2.0, -1.0, -1 },
622 { 1.0, 1.0, 0.0, -1 },
623 { INFINITY
, 0.0, NAN
, EDOM
},
624 { INFINITY
, 42.0, NAN
, EDOM
},
625 { NAN
, 0.0, NAN
, EDOM
},
626 { NAN
, 42.0, NAN
, EDOM
},
627 { 0.0, INFINITY
, 0.0, -1 },
628 { 42.0, INFINITY
, 42.0, -1 },
629 { 0.0, NAN
, NAN
, EDOM
},
630 { 42.0, NAN
, NAN
, EDOM
},
631 { 1.0, 0.0, NAN
, EDOM
},
632 { INFINITY
, INFINITY
, NAN
, EDOM
},
638 if(sizeof(void*) != 8) /* errno handling slightly different on 32-bit */
641 for(i
=0; i
<sizeof(tests
)/sizeof(*tests
); i
++) {
643 r
= p_remainder(tests
[i
].x
, tests
[i
].y
);
646 ok(tests
[i
].e
== e
, "expected errno %i, but got %i\n", tests
[i
].e
, e
);
647 if(_isnan(tests
[i
].r
))
648 ok(_isnan(r
), "expected NAN, but got %f\n", r
);
650 ok(tests
[i
].r
== r
, "expected result %f, but got %f\n", tests
[i
].r
, r
);
654 static int enter_flag
;
655 static critical_section cs
;
656 static unsigned __stdcall
test_critical_section_lock(void *arg
)
658 critical_section
*native_handle
;
659 native_handle
= (critical_section
*)call_func1(p_critical_section_native_handle
, &cs
);
660 ok(native_handle
== &cs
, "native_handle = %p\n", native_handle
);
661 call_func1(p_critical_section_lock
, &cs
);
662 ok(enter_flag
== 1, "enter_flag = %d\n", enter_flag
);
663 call_func1(p_critical_section_unlock
, &cs
);
667 static unsigned __stdcall
test_critical_section_try_lock(void *arg
)
669 ok(!(MSVCRT_bool
)call_func1(p_critical_section_try_lock
, &cs
),
670 "critical_section_try_lock succeeded\n");
674 static unsigned __stdcall
test_critical_section_try_lock_for(void *arg
)
676 ok((MSVCRT_bool
)call_func2(p_critical_section_try_lock_for
, &cs
, 5000),
677 "critical_section_try_lock_for failed\n");
678 ok(enter_flag
== 1, "enter_flag = %d\n", enter_flag
);
679 call_func1(p_critical_section_unlock
, &cs
);
683 static unsigned __stdcall
test_critical_section_scoped_lock(void *arg
)
685 critical_section_scoped_lock counter_scope_lock
;
687 call_func2(p_critical_section_scoped_lock_ctor
, &counter_scope_lock
, &cs
);
688 ok(enter_flag
== 1, "enter_flag = %d\n", enter_flag
);
689 call_func1(p_critical_section_scoped_lock_dtor
, &counter_scope_lock
);
693 static void test_critical_section(void)
699 call_func1(p_critical_section_ctor
, &cs
);
700 call_func1(p_critical_section_lock
, &cs
);
701 thread
= (HANDLE
)_beginthreadex(NULL
, 0, test_critical_section_lock
, NULL
, 0, NULL
);
702 ok(thread
!= INVALID_HANDLE_VALUE
, "_beginthread failed (%d)\n", errno
);
703 ret
= WaitForSingleObject(thread
, 100);
704 ok(ret
== WAIT_TIMEOUT
, "WaitForSingleObject returned %d\n", ret
);
706 call_func1(p_critical_section_unlock
, &cs
);
707 ret
= WaitForSingleObject(thread
, INFINITE
);
708 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject returned %d\n", ret
);
709 ret
= CloseHandle(thread
);
710 ok(ret
, "CloseHandle failed\n");
712 ok((MSVCRT_bool
)call_func1(p_critical_section_try_lock
, &cs
),
713 "critical_section_try_lock failed\n");
714 thread
= (HANDLE
)_beginthreadex(NULL
, 0, test_critical_section_try_lock
, NULL
, 0, NULL
);
715 ok(thread
!= INVALID_HANDLE_VALUE
, "_beginthread failed (%d)\n", errno
);
716 ret
= WaitForSingleObject(thread
, INFINITE
);
717 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject returned %d\n", ret
);
718 ret
= CloseHandle(thread
);
719 ok(ret
, "CloseHandle failed\n");
720 call_func1(p_critical_section_unlock
, &cs
);
723 ok((MSVCRT_bool
)call_func2(p_critical_section_try_lock_for
, &cs
, 50),
724 "critical_section_try_lock_for failed\n");
725 thread
= (HANDLE
)_beginthreadex(NULL
, 0, test_critical_section_try_lock
, NULL
, 0, NULL
);
726 ok(thread
!= INVALID_HANDLE_VALUE
, "_beginthread failed (%d)\n", errno
);
727 ret
= WaitForSingleObject(thread
, INFINITE
);
728 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject returned %d\n", ret
);
729 ret
= CloseHandle(thread
);
730 ok(ret
, "CloseHandle failed\n");
731 thread
= (HANDLE
)_beginthreadex(NULL
, 0, test_critical_section_try_lock_for
, NULL
, 0, NULL
);
732 ok(thread
!= INVALID_HANDLE_VALUE
, "_beginthread failed (%d)\n", errno
);
735 call_func1(p_critical_section_unlock
, &cs
);
736 ret
= WaitForSingleObject(thread
, INFINITE
);
737 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject returned %d\n", ret
);
738 ret
= CloseHandle(thread
);
739 ok(ret
, "CloseHandle failed\n");
742 call_func1(p_critical_section_lock
, &cs
);
743 thread
= (HANDLE
)_beginthreadex(NULL
, 0, test_critical_section_scoped_lock
, NULL
, 0, NULL
);
744 ok(thread
!= INVALID_HANDLE_VALUE
, "_beginthread failed (%d)\n", errno
);
745 ret
= WaitForSingleObject(thread
, 100);
746 ok(ret
== WAIT_TIMEOUT
, "WaitForSingleObject returned %d\n", ret
);
748 call_func1(p_critical_section_unlock
, &cs
);
749 ret
= WaitForSingleObject(thread
, INFINITE
);
750 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject returned %d\n", ret
);
751 ret
= CloseHandle(thread
);
752 ok(ret
, "CloseHandle failed\n");
753 call_func1(p_critical_section_dtor
, &cs
);
756 static void test_fegetenv(void)
763 ret
= p_fegetenv(&env
);
764 ok(!ret
, "fegetenv returned %x\n", ret
);
765 ok(env
.control
== (_EM_INEXACT
|_EM_UNDERFLOW
|_EM_OVERFLOW
|_EM_ZERODIVIDE
|_EM_INVALID
),
766 "env.control = %x\n", env
.control
);
767 ok(!env
.status
, "env.status = %x\n", env
.status
);
770 static void test__wcreate_locale(void)
772 static const wchar_t c_locale
[] = {'C',0};
773 static const wchar_t bogus
[] = {'b','o','g','u','s',0};
774 static const wchar_t empty
[] = {0};
780 lcl
= p_wcreate_locale(LC_ALL
, c_locale
);
782 ok(!!lcl
, "expected success, but got NULL\n");
783 ok(errno
== -1, "expected errno -1, but got %i\n", e
);
787 lcl
= p_wcreate_locale(LC_ALL
, empty
);
789 ok(!!lcl
, "expected success, but got NULL\n");
790 ok(errno
== -1, "expected errno -1, but got %i\n", e
);
795 lcl
= p_wcreate_locale(-1, c_locale
);
797 ok(!lcl
, "expected failure, but got %p\n", lcl
);
798 ok(errno
== -1, "expected errno -1, but got %i\n", e
);
802 lcl
= p_wcreate_locale(LC_ALL
, bogus
);
804 ok(!lcl
, "expected failure, but got %p\n", lcl
);
805 ok(errno
== -1, "expected errno -1, but got %i\n", e
);
808 lcl
= p_wcreate_locale(LC_ALL
, NULL
);
810 ok(!lcl
, "expected failure, but got %p\n", lcl
);
811 ok(errno
== -1, "expected errno -1, but got %i\n", e
);
814 struct wait_thread_arg
816 critical_section
*cs
;
817 _Condition_variable
*cv
;
818 HANDLE thread_initialized
;
821 static DWORD WINAPI
condition_variable_wait_thread(void *varg
)
823 struct wait_thread_arg
*arg
= varg
;
825 call_func1(p_critical_section_lock
, arg
->cs
);
826 SetEvent(arg
->thread_initialized
);
827 call_func2(p__Condition_variable_wait
, arg
->cv
, arg
->cs
);
828 call_func1(p_critical_section_unlock
, arg
->cs
);
832 static void test__Condition_variable(void)
835 _Condition_variable cv
;
836 HANDLE thread_initialized
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
837 struct wait_thread_arg wait_thread_arg
= { &cs
, &cv
, thread_initialized
};
842 ok(thread_initialized
!= NULL
, "CreateEvent failed\n");
844 call_func1(p_critical_section_ctor
, &cs
);
845 call_func1(p__Condition_variable_ctor
, &cv
);
847 call_func1(p__Condition_variable_notify_one
, &cv
);
848 call_func1(p__Condition_variable_notify_all
, &cv
);
850 threads
[0] = CreateThread(0, 0, condition_variable_wait_thread
,
851 &wait_thread_arg
, 0, 0);
852 ok(threads
[0] != NULL
, "CreateThread failed\n");
853 WaitForSingleObject(thread_initialized
, INFINITE
);
854 call_func1(p_critical_section_lock
, &cs
);
855 call_func1(p_critical_section_unlock
, &cs
);
857 threads
[1] = CreateThread(0, 0, condition_variable_wait_thread
,
858 &wait_thread_arg
, 0, 0);
859 ok(threads
[1] != NULL
, "CreateThread failed\n");
860 WaitForSingleObject(thread_initialized
, INFINITE
);
861 call_func1(p_critical_section_lock
, &cs
);
862 call_func1(p_critical_section_unlock
, &cs
);
864 call_func1(p__Condition_variable_notify_one
, &cv
);
865 ret
= WaitForSingleObject(threads
[1], 500);
866 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject returned %d\n", ret
);
867 call_func1(p__Condition_variable_notify_one
, &cv
);
868 ret
= WaitForSingleObject(threads
[0], 500);
869 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject returned %d\n", ret
);
871 CloseHandle(threads
[0]);
872 CloseHandle(threads
[1]);
874 call_func1(p_critical_section_lock
, &cs
);
875 b
= call_func3(p__Condition_variable_wait_for
, &cv
, &cs
, 1);
876 ok(!b
, "_Condition_variable_wait_for returned TRUE\n");
877 call_func1(p_critical_section_unlock
, &cs
);
879 call_func1(p_critical_section_dtor
, &cs
);
880 call_func1(p__Condition_variable_dtor
, &cv
);
882 CloseHandle(thread_initialized
);
885 static void test_wctype(void)
887 static const struct {
908 for(i
=0; i
<sizeof(properties
)/sizeof(properties
[0]); i
++) {
909 ret
= p_wctype(properties
[i
].name
);
910 ok(properties
[i
].mask
== ret
, "%d - Expected %x, got %x\n", i
, properties
[i
].mask
, ret
);
921 test____lc_locale_name_func();
922 test__GetConcurrency();
926 test_critical_section();
928 test__wcreate_locale();
929 test__Condition_variable();