d3drm: Implement DeleteKey().
[wine.git] / dlls / msvcr120 / tests / msvcr120.c
blobde0ccc480ef30f790be0191f59ed748d7d64026c
1 /*
2 * Copyright 2014 Yifu Wang for ESRI
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <errno.h>
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <wchar.h>
23 #include <stdio.h>
24 #include <float.h>
25 #include <limits.h>
27 #include <windef.h>
28 #include <winbase.h>
29 #include <winnls.h>
30 #include "wine/test.h"
31 #include <process.h>
33 #include <locale.h>
35 #ifdef __i386__
36 #include "pshpack1.h"
37 struct thiscall_thunk
39 BYTE pop_eax; /* popl %eax (ret addr) */
40 BYTE pop_edx; /* popl %edx (func) */
41 BYTE pop_ecx; /* popl %ecx (this) */
42 BYTE push_eax; /* pushl %eax */
43 WORD jmp_edx; /* jmp *%edx */
45 #include "poppack.h"
47 static ULONG_PTR (WINAPI *call_thiscall_func1)( void *func, void *this );
48 static ULONG_PTR (WINAPI *call_thiscall_func2)( void *func, void *this, const void *a );
49 static ULONG_PTR (WINAPI *call_thiscall_func3)( void *func,
50 void *this, const void *a, const void *b );
52 static void init_thiscall_thunk(void)
54 struct thiscall_thunk *thunk = VirtualAlloc( NULL, sizeof(*thunk),
55 MEM_COMMIT, PAGE_EXECUTE_READWRITE );
56 thunk->pop_eax = 0x58; /* popl %eax */
57 thunk->pop_edx = 0x5a; /* popl %edx */
58 thunk->pop_ecx = 0x59; /* popl %ecx */
59 thunk->push_eax = 0x50; /* pushl %eax */
60 thunk->jmp_edx = 0xe2ff; /* jmp *%edx */
61 call_thiscall_func1 = (void *)thunk;
62 call_thiscall_func2 = (void *)thunk;
63 call_thiscall_func3 = (void *)thunk;
66 #define call_func1(func,_this) call_thiscall_func1(func,_this)
67 #define call_func2(func,_this,a) call_thiscall_func2(func,_this,(const void*)(a))
68 #define call_func3(func,_this,a,b) call_thiscall_func3(func,_this,(const void*)(a),(const void*)(b))
70 #else
72 #define init_thiscall_thunk()
73 #define call_func1(func,_this) func(_this)
74 #define call_func2(func,_this,a) func(_this,a)
75 #define call_func3(func,_this,a,b) func(_this,a,b)
77 #endif /* __i386__ */
79 #undef __thiscall
80 #ifdef __i386__
81 #define __thiscall __stdcall
82 #else
83 #define __thiscall __cdecl
84 #endif
86 typedef unsigned char MSVCRT_bool;
88 typedef struct cs_queue
90 struct cs_queue *next;
91 BOOL free;
92 int unknown;
93 } cs_queue;
95 typedef struct
97 ULONG_PTR unk_thread_id;
98 cs_queue unk_active;
99 void *unknown[2];
100 cs_queue *head;
101 void *tail;
102 } critical_section;
104 typedef struct
106 critical_section *cs;
107 void *unknown[4];
108 int unknown2[2];
109 } critical_section_scoped_lock;
111 typedef struct {
112 void *chain;
113 critical_section lock;
114 } _Condition_variable;
116 static inline float __port_infinity(void)
118 static const unsigned __inf_bytes = 0x7f800000;
119 return *(const float *)&__inf_bytes;
121 #define INFINITY __port_infinity()
123 static inline float __port_nan(void)
125 static const unsigned __nan_bytes = 0x7fc00000;
126 return *(const float *)&__nan_bytes;
128 #define NAN __port_nan()
130 struct MSVCRT_lconv
132 char* decimal_point;
133 char* thousands_sep;
134 char* grouping;
135 char* int_curr_symbol;
136 char* currency_symbol;
137 char* mon_decimal_point;
138 char* mon_thousands_sep;
139 char* mon_grouping;
140 char* positive_sign;
141 char* negative_sign;
142 char int_frac_digits;
143 char frac_digits;
144 char p_cs_precedes;
145 char p_sep_by_space;
146 char n_cs_precedes;
147 char n_sep_by_space;
148 char p_sign_posn;
149 char n_sign_posn;
150 wchar_t* _W_decimal_point;
151 wchar_t* _W_thousands_sep;
152 wchar_t* _W_int_curr_symbol;
153 wchar_t* _W_currency_symbol;
154 wchar_t* _W_mon_decimal_point;
155 wchar_t* _W_mon_thousands_sep;
156 wchar_t* _W_positive_sign;
157 wchar_t* _W_negative_sign;
160 typedef struct
162 unsigned int control;
163 unsigned int status;
164 } fenv_t;
166 static char* (CDECL *p_setlocale)(int category, const char* locale);
167 static struct MSVCRT_lconv* (CDECL *p_localeconv)(void);
168 static size_t (CDECL *p_wcstombs_s)(size_t *ret, char* dest, size_t sz, const wchar_t* src, size_t max);
169 static int (CDECL *p__dsign)(double);
170 static int (CDECL *p__fdsign)(float);
171 static int (__cdecl *p__dpcomp)(double x, double y);
172 static wchar_t** (CDECL *p____lc_locale_name_func)(void);
173 static unsigned int (CDECL *p__GetConcurrency)(void);
174 static void* (CDECL *p__W_Gettnames)(void);
175 static void (CDECL *p_free)(void*);
176 static float (CDECL *p_strtof)(const char *, char **);
177 static int (CDECL *p__finite)(double);
178 static float (CDECL *p_wcstof)(const wchar_t*, wchar_t**);
179 static double (CDECL *p_remainder)(double, double);
180 static int* (CDECL *p_errno)(void);
181 static int (CDECL *p_fegetenv)(fenv_t*);
182 static int (CDECL *p__clearfp)(void);
183 static _locale_t (__cdecl *p_wcreate_locale)(int, const wchar_t *);
184 static void (__cdecl *p_free_locale)(_locale_t);
185 static unsigned short (__cdecl *p_wctype)(const char*);
187 /* make sure we use the correct errno */
188 #undef 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)
214 HMODULE module;
216 module = LoadLibraryA("msvcr120.dll");
217 if (!module)
219 win_skip("msvcr120.dll not installed\n");
220 return FALSE;
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");
274 } else {
275 #ifdef __arm__
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");
306 #else
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");
337 #endif
340 init_thiscall_thunk();
341 return TRUE;
344 static void test_lconv_helper(const char *locstr)
346 struct MSVCRT_lconv *lconv;
347 char mbs[256];
348 size_t i;
350 if(!p_setlocale(LC_ALL, locstr))
352 win_skip("locale %s not available\n", locstr);
353 return;
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)
400 int i;
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)
415 int ret;
417 ret = p__dsign(1);
418 ok(ret == 0, "p_dsign(1) = %x\n", ret);
419 ret = p__dsign(0);
420 ok(ret == 0, "p_dsign(0) = %x\n", ret);
421 ret = p__dsign(-1);
422 ok(ret == 0x8000, "p_dsign(-1) = %x\n", ret);
424 ret = p__fdsign(1);
425 ok(ret == 0, "p_fdsign(1) = %x\n", ret);
426 ret = p__fdsign(0);
427 ok(ret == 0, "p_fdsign(0) = %x\n", ret);
428 ret = p__fdsign(-1);
429 ok(ret == 0x8000, "p_fdsign(-1) = %x\n", ret);
432 static void test__dpcomp(void)
434 struct {
435 double x, y;
436 int ret;
437 } tests[] = {
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},
444 int i, ret;
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)
454 struct {
455 const char *locale;
456 const WCHAR name[10];
457 const WCHAR broken_name[10];
458 } tests[] = {
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} }
471 int i, j;
472 wchar_t **lc_names;
474 for(i=0; i<sizeof(tests)/sizeof(*tests); i++) {
475 if(!p_setlocale(LC_ALL, tests[i].locale))
476 continue;
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)
496 SYSTEM_INFO si;
497 unsigned int c;
499 GetSystemInfo(&si);
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"
517 struct {
518 char *str[43];
519 int unk[2];
520 wchar_t *wstr[43];
521 wchar_t *locname;
522 char data[1];
523 } *ret;
524 int i, size;
525 WCHAR buf[64];
527 if(!p_setlocale(LC_ALL, "english"))
528 return;
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);
534 else
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));
546 p_free(ret);
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};
561 char *end;
562 float f;
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");
603 return;
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)
617 struct {
618 double x, y, r;
619 errno_t e;
620 } tests[] = {
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 },
634 errno_t e;
635 double r;
636 int i;
638 if(sizeof(void*) != 8) /* errno handling slightly different on 32-bit */
639 return;
641 for(i=0; i<sizeof(tests)/sizeof(*tests); i++) {
642 errno = -1;
643 r = p_remainder(tests[i].x, tests[i].y);
644 e = errno;
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);
649 else
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);
664 return 0;
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");
671 return 0;
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);
680 return 0;
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);
690 return 0;
693 static void test_critical_section(void)
695 HANDLE thread;
696 DWORD ret;
698 enter_flag = 0;
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);
705 enter_flag = 1;
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);
722 enter_flag = 0;
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);
733 enter_flag = 1;
734 Sleep(10);
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");
741 enter_flag = 0;
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);
747 enter_flag = 1;
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)
758 int ret;
759 fenv_t env;
761 p__clearfp();
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};
775 _locale_t lcl;
776 errno_t e;
778 /* simple success */
779 errno = -1;
780 lcl = p_wcreate_locale(LC_ALL, c_locale);
781 e = errno;
782 ok(!!lcl, "expected success, but got NULL\n");
783 ok(errno == -1, "expected errno -1, but got %i\n", e);
784 p_free_locale(lcl);
786 errno = -1;
787 lcl = p_wcreate_locale(LC_ALL, empty);
788 e = errno;
789 ok(!!lcl, "expected success, but got NULL\n");
790 ok(errno == -1, "expected errno -1, but got %i\n", e);
791 p_free_locale(lcl);
793 /* bogus category */
794 errno = -1;
795 lcl = p_wcreate_locale(-1, c_locale);
796 e = errno;
797 ok(!lcl, "expected failure, but got %p\n", lcl);
798 ok(errno == -1, "expected errno -1, but got %i\n", e);
800 /* bogus names */
801 errno = -1;
802 lcl = p_wcreate_locale(LC_ALL, bogus);
803 e = errno;
804 ok(!lcl, "expected failure, but got %p\n", lcl);
805 ok(errno == -1, "expected errno -1, but got %i\n", e);
807 errno = -1;
808 lcl = p_wcreate_locale(LC_ALL, NULL);
809 e = errno;
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);
829 return 0;
832 static void test__Condition_variable(void)
834 critical_section cs;
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 };
838 HANDLE threads[2];
839 DWORD ret;
840 MSVCRT_bool b;
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 {
888 const char *name;
889 unsigned short mask;
890 } properties[] = {
891 { "alnum", 0x107 },
892 { "alpha", 0x103 },
893 { "cntrl", 0x020 },
894 { "digit", 0x004 },
895 { "graph", 0x117 },
896 { "lower", 0x002 },
897 { "print", 0x157 },
898 { "punct", 0x010 },
899 { "space", 0x008 },
900 { "upper", 0x001 },
901 { "xdigit", 0x080 },
902 { "ALNUM", 0x000 },
903 { "Alnum", 0x000 },
904 { "", 0x000 }
906 int i, ret;
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);
914 START_TEST(msvcr120)
916 if (!init()) return;
917 test__strtof();
918 test_lconv();
919 test__dsign();
920 test__dpcomp();
921 test____lc_locale_name_func();
922 test__GetConcurrency();
923 test__W_Gettnames();
924 test__strtof();
925 test_remainder();
926 test_critical_section();
927 test_fegetenv();
928 test__wcreate_locale();
929 test__Condition_variable();
930 test_wctype();