Reactos
at master 1761 lines 65 kB view raw
1/* 2 * Copyright 2016 Nikolay Sivov for CodeWeavers 3 * 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. 8 * 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. 13 * 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 17 */ 18 19#include <errno.h> 20#include <stdarg.h> 21#include <stdlib.h> 22#include <wchar.h> 23#include <stdio.h> 24#include <math.h> 25#include <float.h> 26#include <io.h> 27#include <sys/stat.h> 28#include <share.h> 29#include <fcntl.h> 30#include <time.h> 31#include <direct.h> 32#include <locale.h> 33#include <process.h> 34#include <fenv.h> 35#include <malloc.h> 36 37#include <windef.h> 38#include <winbase.h> 39#include "wine/test.h" 40 41#define DEFINE_EXPECT(func) \ 42 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE 43 44#define SET_EXPECT(func) \ 45 expect_ ## func = TRUE 46 47#define CHECK_EXPECT2(func) \ 48 do { \ 49 ok(expect_ ##func, "unexpected call " #func "\n"); \ 50 called_ ## func = TRUE; \ 51 }while(0) 52 53#define CHECK_EXPECT(func) \ 54 do { \ 55 CHECK_EXPECT2(func); \ 56 expect_ ## func = FALSE; \ 57 }while(0) 58 59#define CHECK_CALLED(func) \ 60 do { \ 61 ok(called_ ## func, "expected " #func "\n"); \ 62 expect_ ## func = called_ ## func = FALSE; \ 63 }while(0) 64 65static inline double __port_min_pos_double(void) 66{ 67 static const UINT64 __min_pos_double = 0x10000000000000; 68 return *(const double *)&__min_pos_double; 69} 70 71static inline double __port_max_double(void) 72{ 73 static const UINT64 __max_double = 0x7FEFFFFFFFFFFFFF; 74 return *(const double *)&__max_double; 75} 76 77DEFINE_EXPECT(global_invalid_parameter_handler); 78DEFINE_EXPECT(thread_invalid_parameter_handler); 79 80typedef struct { 81 const char *short_wday[7]; 82 const char *wday[7]; 83 const char *short_mon[12]; 84 const char *mon[12]; 85 const char *am; 86 const char *pm; 87 const char *short_date; 88 const char *date; 89 const char *time; 90 int unk; 91 int refcount; 92 const wchar_t *short_wdayW[7]; 93 const wchar_t *wdayW[7]; 94 const wchar_t *short_monW[12]; 95 const wchar_t *monW[12]; 96 const wchar_t *amW; 97 const wchar_t *pmW; 98 const wchar_t *short_dateW; 99 const wchar_t *dateW; 100 const wchar_t *timeW; 101 const wchar_t *locnameW; 102} __lc_time_data; 103 104typedef void (__cdecl *_se_translator_function)(unsigned int code, struct _EXCEPTION_POINTERS *info); 105 106static LONGLONG crt_init_end; 107 108_ACRTIMP int __cdecl _o__initialize_onexit_table(_onexit_table_t *table); 109_ACRTIMP int __cdecl _o__register_onexit_function(_onexit_table_t *table, _onexit_t func); 110_ACRTIMP int __cdecl _o__execute_onexit_table(_onexit_table_t *table); 111_ACRTIMP void *__cdecl _o_malloc(size_t); 112_se_translator_function __cdecl _set_se_translator(_se_translator_function func); 113void** __cdecl __current_exception(void); 114int* __cdecl __processing_throw(void); 115 116#define _MAX__TIME64_T (((__time64_t)0x00000007 << 32) | 0x93406FFF) 117 118static void test__initialize_onexit_table(void) 119{ 120 _onexit_table_t table, table2; 121 int ret; 122 123 ret = _initialize_onexit_table(NULL); 124 ok(ret == -1, "got %d\n", ret); 125 126 memset(&table, 0, sizeof(table)); 127 ret = _initialize_onexit_table(&table); 128 ok(ret == 0, "got %d\n", ret); 129 ok(table._first == table._last && table._first == table._end, "got first %p, last %p, end %p\n", 130 table._first, table._last, table._end); 131 132 memset(&table2, 0, sizeof(table2)); 133 ret = _initialize_onexit_table(&table2); 134 ok(ret == 0, "got %d\n", ret); 135 ok(table2._first == table._first, "got %p, %p\n", table2._first, table._first); 136 ok(table2._last == table._last, "got %p, %p\n", table2._last, table._last); 137 ok(table2._end == table._end, "got %p, %p\n", table2._end, table._end); 138 139 memset(&table2, 0, sizeof(table2)); 140 ret = _o__initialize_onexit_table(&table2); 141 ok(ret == 0, "got %d\n", ret); 142 ok(table2._first == table._first, "got %p, %p\n", table2._first, table._first); 143 ok(table2._last == table._last, "got %p, %p\n", table2._last, table._last); 144 ok(table2._end == table._end, "got %p, %p\n", table2._end, table._end); 145 146 /* uninitialized table */ 147 table._first = table._last = table._end = (void*)0x123; 148 ret = _initialize_onexit_table(&table); 149 ok(ret == 0, "got %d\n", ret); 150 ok(table._first == table._last && table._first == table._end, "got first %p, last %p, end %p\n", 151 table._first, table._last, table._end); 152 ok(table._first != (void*)0x123, "got %p\n", table._first); 153 154 table._first = (void*)0x123; 155 table._last = (void*)0x456; 156 table._end = (void*)0x123; 157 ret = _initialize_onexit_table(&table); 158 ok(ret == 0, "got %d\n", ret); 159 ok(table._first == table._last && table._first == table._end, "got first %p, last %p, end %p\n", 160 table._first, table._last, table._end); 161 ok(table._first != (void*)0x123, "got %p\n", table._first); 162 163 table._first = (void*)0x123; 164 table._last = (void*)0x456; 165 table._end = (void*)0x789; 166 ret = _initialize_onexit_table(&table); 167 ok(ret == 0, "got %d\n", ret); 168 ok(table._first == (void*)0x123, "got %p\n", table._first); 169 ok(table._last == (void*)0x456, "got %p\n", table._last); 170 ok(table._end == (void*)0x789, "got %p\n", table._end); 171 172 table._first = NULL; 173 table._last = (void*)0x456; 174 table._end = NULL; 175 ret = _initialize_onexit_table(&table); 176 ok(ret == 0, "got %d\n", ret); 177 ok(table._first == table._last && table._first == table._end, "got first %p, last %p, end %p\n", 178 table._first, table._last, table._end); 179} 180 181static int g_onexit_called; 182static int CDECL onexit_func(void) 183{ 184 g_onexit_called++; 185 return 0; 186} 187 188static int CDECL onexit_func2(void) 189{ 190 ok(g_onexit_called == 0, "got %d\n", g_onexit_called); 191 g_onexit_called++; 192 return 0; 193} 194 195static void test__register_onexit_function(void) 196{ 197 _onexit_table_t table; 198 _PVFV *f; 199 int ret; 200 201 memset(&table, 0, sizeof(table)); 202 ret = _initialize_onexit_table(&table); 203 ok(ret == 0, "got %d\n", ret); 204 205 ret = _register_onexit_function(NULL, NULL); 206 ok(ret == -1, "got %d\n", ret); 207 208 ret = _register_onexit_function(NULL, onexit_func); 209 ok(ret == -1, "got %d\n", ret); 210 211 f = table._last; 212 ret = _register_onexit_function(&table, NULL); 213 ok(ret == 0, "got %d\n", ret); 214 ok(f != table._last, "got %p, initial %p\n", table._last, f); 215 216 ret = _register_onexit_function(&table, onexit_func); 217 ok(ret == 0, "got %d\n", ret); 218 219 f = table._last; 220 ret = _register_onexit_function(&table, onexit_func); 221 ok(ret == 0, "got %d\n", ret); 222 ok(f != table._last, "got %p, initial %p\n", table._last, f); 223 224 f = table._last; 225 ret = _o__register_onexit_function(&table, NULL); 226 ok(ret == 0, "got %d\n", ret); 227 ok(f != table._last, "got %p, initial %p\n", table._last, f); 228 229 f = table._last; 230 ret = _o__register_onexit_function(&table, onexit_func); 231 ok(ret == 0, "got %d\n", ret); 232 ok(f != table._last, "got %p, initial %p\n", table._last, f); 233 234 ret = _execute_onexit_table(&table); 235 ok(ret == 0, "got %d\n", ret); 236} 237 238static void test__execute_onexit_table(void) 239{ 240 _onexit_table_t table; 241 int ret; 242 243 ret = _execute_onexit_table(NULL); 244 ok(ret == -1, "got %d\n", ret); 245 246 memset(&table, 0, sizeof(table)); 247 ret = _initialize_onexit_table(&table); 248 ok(ret == 0, "got %d\n", ret); 249 250 /* execute empty table */ 251 ret = _execute_onexit_table(&table); 252 ok(ret == 0, "got %d\n", ret); 253 254 /* same function registered multiple times */ 255 ret = _register_onexit_function(&table, onexit_func); 256 ok(ret == 0, "got %d\n", ret); 257 258 ret = _register_onexit_function(&table, NULL); 259 ok(ret == 0, "got %d\n", ret); 260 261 ret = _register_onexit_function(&table, onexit_func); 262 ok(ret == 0, "got %d\n", ret); 263 264 ret = _o__register_onexit_function(&table, onexit_func); 265 ok(ret == 0, "got %d\n", ret); 266 267 ok(table._first != table._end, "got %p, %p\n", table._first, table._end); 268 g_onexit_called = 0; 269 ret = _execute_onexit_table(&table); 270 ok(ret == 0, "got %d\n", ret); 271 ok(g_onexit_called == 3, "got %d\n", g_onexit_called); 272 ok(table._first == table._end, "got %p, %p\n", table._first, table._end); 273 274 ret = _register_onexit_function(&table, onexit_func); 275 ok(ret == 0, "got %d\n", ret); 276 277 ret = _register_onexit_function(&table, NULL); 278 ok(ret == 0, "got %d\n", ret); 279 280 ret = _register_onexit_function(&table, onexit_func); 281 ok(ret == 0, "got %d\n", ret); 282 283 ret = _o__register_onexit_function(&table, onexit_func); 284 ok(ret == 0, "got %d\n", ret); 285 286 ok(table._first != table._end, "got %p, %p\n", table._first, table._end); 287 g_onexit_called = 0; 288 ret = _o__execute_onexit_table(&table); 289 ok(ret == 0, "got %d\n", ret); 290 ok(g_onexit_called == 3, "got %d\n", g_onexit_called); 291 ok(table._first == table._end, "got %p, %p\n", table._first, table._end); 292 293 /* execute again, table is already empty */ 294 g_onexit_called = 0; 295 ret = _execute_onexit_table(&table); 296 ok(ret == 0, "got %d\n", ret); 297 ok(g_onexit_called == 0, "got %d\n", g_onexit_called); 298 299 /* check call order */ 300 memset(&table, 0, sizeof(table)); 301 ret = _initialize_onexit_table(&table); 302 ok(ret == 0, "got %d\n", ret); 303 304 ret = _register_onexit_function(&table, onexit_func); 305 ok(ret == 0, "got %d\n", ret); 306 307 ret = _register_onexit_function(&table, onexit_func2); 308 ok(ret == 0, "got %d\n", ret); 309 310 g_onexit_called = 0; 311 ret = _execute_onexit_table(&table); 312 ok(ret == 0, "got %d\n", ret); 313 ok(g_onexit_called == 2, "got %d\n", g_onexit_called); 314} 315 316static void test___fpe_flt_rounds(void) 317{ 318 unsigned int cfp = _controlfp(0, 0); 319 int ret; 320 321 if(!cfp) { 322 skip("_controlfp not supported\n"); 323 return; 324 } 325 326 ok((_controlfp(_RC_NEAR, _RC_CHOP) & _RC_CHOP) == _RC_NEAR, "_controlfp(_RC_NEAR, _RC_CHOP) failed\n"); 327 ret = __fpe_flt_rounds(); 328 ok(ret == 1, "__fpe_flt_rounds returned %d\n", ret); 329 330 ok((_controlfp(_RC_UP, _RC_CHOP) & _RC_CHOP) == _RC_UP, "_controlfp(_RC_UP, _RC_CHOP) failed\n"); 331 ret = __fpe_flt_rounds(); 332 ok(ret == 2 || broken(ret == 3) /* w1064v1507 */, "__fpe_flt_rounds returned %d\n", ret); 333 334 ok((_controlfp(_RC_DOWN, _RC_CHOP) & _RC_CHOP) == _RC_DOWN, "_controlfp(_RC_DOWN, _RC_CHOP) failed\n"); 335 ret = __fpe_flt_rounds(); 336 ok(ret == 3 || broken(ret == 2) /* w1064v1507 */, "__fpe_flt_rounds returned %d\n", ret); 337 338 ok((_controlfp(_RC_CHOP, _RC_CHOP) & _RC_CHOP) == _RC_CHOP, "_controlfp(_RC_CHOP, _RC_CHOP) failed\n"); 339 ret = __fpe_flt_rounds(); 340 ok(ret == 0, "__fpe_flt_rounds returned %d\n", ret); 341 342 _controlfp(cfp, _MCW_EM | _MCW_RC | _MCW_PC); 343} 344 345static void test__control87_2(void) 346{ 347#ifdef __i386__ 348 unsigned int x86_cw_init, sse2_cw_init, x86_cw, sse2_cw, r; 349 350 r = __control87_2(0, 0, &x86_cw_init, &sse2_cw_init); 351 ok(r == 1, "__control87_2 returned %d\n", r); 352 353 r = __control87_2(0, _EM_INVALID, &x86_cw, NULL); 354 ok(r == 1, "__control87_2 returned %d\n", r); 355 ok(x86_cw == (x86_cw_init & ~_EM_INVALID), "x86_cw = %x, x86_cw_init = %x\n", x86_cw, x86_cw_init); 356 357 r = __control87_2(0, 0, &x86_cw, &sse2_cw); 358 ok(r == 1, "__control87_2 returned %d\n", r); 359 ok(x86_cw == (x86_cw_init & ~_EM_INVALID), "x86_cw = %x, x86_cw_init = %x\n", x86_cw, x86_cw_init); 360 ok(sse2_cw == sse2_cw_init, "sse2_cw = %x, sse2_cw_init = %x\n", sse2_cw, sse2_cw_init); 361 362 r = _control87(0, 0); 363 ok(r == (x86_cw | sse2_cw | _EM_AMBIGUOUS), "r = %x, expected %x\n", 364 r, x86_cw | sse2_cw | _EM_AMBIGUOUS); 365 366 _control87(x86_cw_init, ~0); 367#endif 368} 369 370static void __cdecl global_invalid_parameter_handler( 371 const wchar_t *expression, const wchar_t *function, 372 const wchar_t *file, unsigned line, uintptr_t arg) 373{ 374 CHECK_EXPECT2(global_invalid_parameter_handler); 375} 376 377static void __cdecl thread_invalid_parameter_handler( 378 const wchar_t *expression, const wchar_t *function, 379 const wchar_t *file, unsigned line, uintptr_t arg) 380{ 381 CHECK_EXPECT(thread_invalid_parameter_handler); 382} 383 384static void test_invalid_parameter_handler(void) 385{ 386 _invalid_parameter_handler ret; 387 388 ret = _get_invalid_parameter_handler(); 389 ok(!ret, "ret != NULL\n"); 390 391 ret = _get_thread_local_invalid_parameter_handler(); 392 ok(!ret, "ret != NULL\n"); 393 394 ret = _set_thread_local_invalid_parameter_handler(thread_invalid_parameter_handler); 395 ok(!ret, "ret != NULL\n"); 396 397 ret = _get_thread_local_invalid_parameter_handler(); 398 ok(ret == thread_invalid_parameter_handler, "ret = %p\n", ret); 399 400 ret = _get_invalid_parameter_handler(); 401 ok(!ret, "ret != NULL\n"); 402 403 ret = _set_invalid_parameter_handler(global_invalid_parameter_handler); 404 ok(!ret, "ret != NULL\n"); 405 406 ret = _get_invalid_parameter_handler(); 407 ok(ret == global_invalid_parameter_handler, "ret = %p\n", ret); 408 409 ret = _get_thread_local_invalid_parameter_handler(); 410 ok(ret == thread_invalid_parameter_handler, "ret = %p\n", ret); 411 412 SET_EXPECT(thread_invalid_parameter_handler); 413 _ltoa_s(0, NULL, 0, 0); 414 CHECK_CALLED(thread_invalid_parameter_handler); 415 416 ret = _set_thread_local_invalid_parameter_handler(NULL); 417 ok(ret == thread_invalid_parameter_handler, "ret = %p\n", ret); 418 419 SET_EXPECT(global_invalid_parameter_handler); 420 _ltoa_s(0, NULL, 0, 0); 421 CHECK_CALLED(global_invalid_parameter_handler); 422 423 ret = _set_invalid_parameter_handler(NULL); 424 ok(ret == global_invalid_parameter_handler, "ret = %p\n", ret); 425 426 ret = _set_invalid_parameter_handler(global_invalid_parameter_handler); 427 ok(!ret, "ret != NULL\n"); 428} 429 430static void test__get_narrow_winmain_command_line(char *path) 431{ 432 PROCESS_INFORMATION proc; 433 STARTUPINFOA startup; 434 char cmd[MAX_PATH+32]; 435 char *ret, *cmdline, *name; 436 int len; 437 438 ret = _get_narrow_winmain_command_line(); 439 cmdline = GetCommandLineA(); 440 len = strlen(cmdline); 441 ok(ret>cmdline && ret<cmdline+len, "ret = %p, cmdline = %p (len = %d)\n", ret, cmdline, len); 442 443 if(!path) { 444 ok(!lstrcmpA(ret, "\"misc\" cmd"), "ret = %s\n", ret); 445 return; 446 } 447 448 for(len = strlen(path); len>0; len--) 449 if(path[len-1]=='\\' || path[len-1]=='/') break; 450 if(len) name = path+len; 451 else name = path; 452 453 sprintf(cmd, "\"\"%c\"\"\"%s\" \t \"misc\" cmd", name[0], name+1); 454 memset(&startup, 0, sizeof(startup)); 455 startup.cb = sizeof(startup); 456 CreateProcessA(path, cmd, NULL, NULL, TRUE, 457 CREATE_DEFAULT_ERROR_MODE|NORMAL_PRIORITY_CLASS, 458 NULL, NULL, &startup, &proc); 459 wait_child_process(proc.hProcess); 460 CloseHandle(proc.hProcess); 461 CloseHandle(proc.hThread); 462} 463 464static void test__sopen_dispatch(void) 465{ 466 int ret, fd; 467 char *tempf; 468 469 tempf = _tempnam(".", "wne"); 470 471 fd = 0; 472 ret = _sopen_dispatch(tempf, _O_CREAT, _SH_DENYWR, 0xff, &fd, 0); 473 ok(!ret, "got %d\n", ret); 474 ok(fd > 0, "got fd %d\n", fd); 475 _close(fd); 476 unlink(tempf); 477 478 SET_EXPECT(global_invalid_parameter_handler); 479 fd = 0; 480 ret = _sopen_dispatch(tempf, _O_CREAT, _SH_DENYWR, 0xff, &fd, 1); 481 ok(ret == EINVAL, "got %d\n", ret); 482 ok(fd == -1, "got fd %d\n", fd); 483 CHECK_CALLED(global_invalid_parameter_handler); 484 if (fd > 0) 485 { 486 _close(fd); 487 unlink(tempf); 488 } 489 490 free(tempf); 491} 492 493static void test__sopen_s(void) 494{ 495 int ret, fd; 496 char *tempf; 497 498 tempf = _tempnam(".", "wne"); 499 500 fd = 0; 501 ret = _sopen_s(&fd, tempf, _O_CREAT, _SH_DENYWR, 0); 502 ok(!ret, "got %d\n", ret); 503 ok(fd > 0, "got fd %d\n", fd); 504 _close(fd); 505 unlink(tempf); 506 507 /* _open() does not validate pmode */ 508 fd = _open(tempf, _O_CREAT, 0xff); 509 ok(fd > 0, "got fd %d\n", fd); 510 _close(fd); 511 unlink(tempf); 512 513 /* _sopen_s() invokes invalid parameter handler on invalid pmode */ 514 SET_EXPECT(global_invalid_parameter_handler); 515 fd = 0; 516 ret = _sopen_s(&fd, tempf, _O_CREAT, _SH_DENYWR, 0xff); 517 ok(ret == EINVAL, "got %d\n", ret); 518 ok(fd == -1, "got fd %d\n", fd); 519 CHECK_CALLED(global_invalid_parameter_handler); 520 521 free(tempf); 522} 523 524static void test_lldiv(void) 525{ 526 lldiv_t r; 527 528 r = lldiv(((LONGLONG)0x111 << 32) + 0x222, (LONGLONG)1 << 32); 529 ok(r.quot == 0x111, "quot = %s\n", wine_dbgstr_longlong(r.quot)); 530 ok(r.rem == 0x222, "rem = %s\n", wine_dbgstr_longlong(r.rem)); 531 532 r = lldiv(((LONGLONG)0x69CF0012 << 32) + 0x0033E78A, 0x30); 533 ok(r.quot == ((LONGLONG)0x02345000 << 32) + 0x600114D2, "quot = %s\n", wine_dbgstr_longlong(r.quot)); 534 ok(r.rem == 0x2A, "rem = %s\n", wine_dbgstr_longlong(r.rem)); 535 536 r = lldiv(((LONGLONG)0x243A5678 << 32) + 0x9ABCDEF0, (LONGLONG)0x12 << 48); 537 ok(r.quot == 0x0203, "quot = %s\n", wine_dbgstr_longlong(r.quot)); 538 ok(r.rem == ((LONGLONG)0x00045678 << 32) + 0x9ABCDEF0, "rem = %s\n", wine_dbgstr_longlong(r.rem)); 539} 540 541static void test_isblank(void) 542{ 543 int c, r; 544 545 for(c = 0; c <= 0xff; c++) { 546 if(c == '\t') { 547 ok(!_isctype(c, _BLANK), "tab shouldn't be blank\n"); 548 ok(isblank(c), "%d should be blank\n", c); 549 r = _isblank_l(c, NULL); 550 ok(!r || broken(r == _BLANK), "tab shouldn't be blank (got %x)\n", r); 551 } else if(c == ' ') { 552 ok(_isctype(c, _BLANK), "space should be blank\n"); 553 ok(isblank(c), "%d should be blank\n", c); 554 r = _isblank_l(c, NULL); 555 ok(r == _BLANK, "space should be blank (got %x)\n", r); 556 } else { 557 ok(!_isctype(c, _BLANK), "%d shouldn't be blank\n", c); 558 ok(!isblank(c), "%d shouldn't be blank\n", c); 559 ok(!_isblank_l(c, NULL), "%d shouldn't be blank\n", c); 560 } 561 } 562 563 for(c = 0; c <= 0xffff; c++) { 564 if(c == '\t' || c == ' ' || c == 0x3000 || c == 0xfeff) { 565 if(c == '\t') 566 ok(!_iswctype_l(c, _BLANK, NULL), "tab shouldn't be blank\n"); 567 else 568 ok(_iswctype_l(c, _BLANK, NULL), "%d should be blank\n", c); 569 ok(iswblank(c), "%d should be blank\n", c); 570 ok(_iswblank_l(c, NULL), "%d should be blank\n", c); 571 } else { 572 ok(!_iswctype_l(c, _BLANK, NULL), "%d shouldn't be blank\n", c); 573 ok(!iswblank(c), "%d shouldn't be blank\n", c); 574 ok(!_iswblank_l(c, NULL), "%d shouldn't be blank\n", c); 575 } 576 } 577} 578 579static struct _exception exception; 580 581static int CDECL matherr_callback(struct _exception *e) 582{ 583 exception = *e; 584 585 if (!strcmp(e->name, "acos") && e->arg1 == 2) 586 e->retval = -1; 587 return 0; 588} 589 590static void test_math_errors(void) 591{ 592 const struct { 593 char func[16]; 594 double x; 595 int error; 596 int exception; 597 } testsd[] = { 598 {"_logb", -INFINITY, -1, -1}, 599 {"_logb", -1, -1, -1}, 600 {"_logb", 0, ERANGE, _SING}, 601 {"_logb", INFINITY, -1, -1}, 602 {"acos", -INFINITY, EDOM, _DOMAIN}, 603 {"acos", -2, EDOM, _DOMAIN}, 604 {"acos", -1, -1, -1}, 605 {"acos", 1, -1, -1}, 606 {"acos", 2, EDOM, _DOMAIN}, 607 {"acos", INFINITY, EDOM, _DOMAIN}, 608 {"acosh", -INFINITY, EDOM, -1}, 609 {"acosh", 0, EDOM, -1}, 610 {"acosh", 1, -1, -1}, 611 {"acosh", INFINITY, -1, -1}, 612 {"asin", -INFINITY, EDOM, _DOMAIN}, 613 {"asin", -2, EDOM, _DOMAIN}, 614 {"asin", -1, -1, -1}, 615 {"asin", 1, -1, -1}, 616 {"asin", 2, EDOM, _DOMAIN}, 617 {"asin", INFINITY, EDOM, _DOMAIN}, 618 {"asinh", -INFINITY, -1, -1}, 619 {"asinh", INFINITY, -1, -1}, 620 {"atan", -INFINITY, -1, -1}, 621 {"atan", 0, -1, -1}, 622 {"atan", INFINITY, -1, -1}, 623 {"atanh", -INFINITY, EDOM, -1}, 624 {"atanh", -2, EDOM, -1}, 625 {"atanh", -1, ERANGE, -1}, 626 {"atanh", 1, ERANGE, -1}, 627 {"atanh", 2, EDOM, -1}, 628 {"atanh", INFINITY, EDOM, -1}, 629 {"cos", -INFINITY, EDOM, _DOMAIN}, 630 {"cos", INFINITY, EDOM, _DOMAIN}, 631 {"cosh", -INFINITY, -1, -1}, 632 {"cosh", 0, -1, -1}, 633 {"cosh", INFINITY, -1, -1}, 634 {"exp", -INFINITY, -1, -1}, 635 {"exp", -1e100, -1, _UNDERFLOW}, 636 {"exp", 1e100, ERANGE, _OVERFLOW}, 637 {"exp", INFINITY, -1, -1}, 638 {"exp2", -INFINITY, -1, -1}, 639 {"exp2", -1e100, -1, -1}, 640 {"exp2", 1e100, ERANGE, -1}, 641 {"exp2", INFINITY, -1, -1}, 642 {"expm1", -INFINITY, -1, -1}, 643 {"expm1", INFINITY, -1, -1}, 644 {"log", -INFINITY, EDOM, _DOMAIN}, 645 {"log", -1, EDOM, _DOMAIN}, 646 {"log", 0, ERANGE, _SING}, 647 {"log", INFINITY, -1, -1}, 648 {"log10", -INFINITY, EDOM, _DOMAIN}, 649 {"log10", -1, EDOM, _DOMAIN}, 650 {"log10", 0, ERANGE, _SING}, 651 {"log10", INFINITY, -1, -1}, 652 {"log1p", -INFINITY, EDOM, -1}, 653 {"log1p", -2, EDOM, -1}, 654 {"log1p", -1, ERANGE, -1}, 655 {"log1p", INFINITY, -1, -1}, 656 {"log2", INFINITY, -1, -1}, 657 {"sin", -INFINITY, EDOM, _DOMAIN}, 658 {"sin", INFINITY, EDOM, _DOMAIN}, 659 {"sinh", -INFINITY, -1, -1}, 660 {"sinh", 0, -1, -1}, 661 {"sinh", INFINITY, -1, -1}, 662 {"sqrt", -INFINITY, EDOM, _DOMAIN}, 663 {"sqrt", -1, EDOM, _DOMAIN}, 664 {"sqrt", 0, -1, -1}, 665 {"sqrt", INFINITY, -1, -1}, 666 {"tan", -INFINITY, EDOM, _DOMAIN}, 667 {"tan", -M_PI_2, -1, -1}, 668 {"tan", M_PI_2, -1, -1}, 669 {"tan", INFINITY, EDOM, _DOMAIN}, 670 {"tanh", -INFINITY, -1, -1}, 671 {"tanh", 0, -1, -1}, 672 {"tanh", INFINITY, -1, -1}, 673 }; 674 const struct { 675 char func[16]; 676 double a; 677 double b; 678 int error; 679 int exception; 680 } tests2d[] = { 681 {"atan2", -INFINITY, 0, -1, -1}, 682 {"atan2", 0, 0, -1, -1}, 683 {"atan2", INFINITY, 0, -1, -1}, 684 {"atan2", 0, -INFINITY, -1, -1}, 685 {"atan2", 0, INFINITY, -1, -1}, 686 {"pow", -INFINITY, -2, -1, -1}, 687 {"pow", -INFINITY, -1, -1, -1}, 688 {"pow", -INFINITY, 0, -1, -1}, 689 {"pow", -INFINITY, 1, -1, -1}, 690 {"pow", -INFINITY, 2, -1, -1}, 691 {"pow", -1e100, -10, -1, _UNDERFLOW}, 692 {"pow", -1e100, 10, ERANGE, _OVERFLOW}, 693 {"pow", -1, 1.5, EDOM, _DOMAIN}, 694 {"pow", 0, -2, ERANGE, _SING}, 695 {"pow", 0, -1, ERANGE, _SING}, 696 {"pow", 0.5, -INFINITY, -1, -1}, 697 {"pow", 0.5, INFINITY, -1, -1}, 698 {"pow", 2, -INFINITY, -1, -1}, 699 {"pow", 2, -1e100, -1, _UNDERFLOW}, 700 {"pow", 2, 1e100, ERANGE, _OVERFLOW}, 701 {"pow", 2, INFINITY, -1, -1}, 702 {"pow", 1e100, -10, -1, _UNDERFLOW}, 703 {"pow", 1e100, 10, ERANGE, _OVERFLOW}, 704 {"pow", INFINITY, -2, -1, -1}, 705 {"pow", INFINITY, -1, -1, -1}, 706 {"pow", INFINITY, 0, -1, -1}, 707 {"pow", INFINITY, 1, -1, -1}, 708 {"pow", INFINITY, 2, -1, -1}, 709 }; 710 const struct { 711 char func[16]; 712 double a; 713 double b; 714 double c; 715 int error; 716 int exception; 717 } tests3d[] = { 718 /* 0 * inf --> EDOM */ 719 {"fma", INFINITY, 0, 0, EDOM, -1}, 720 {"fma", 0, INFINITY, 0, EDOM, -1}, 721 /* inf - inf -> EDOM */ 722 {"fma", INFINITY, 1, -INFINITY, EDOM, -1}, 723 {"fma", -INFINITY, 1, INFINITY, EDOM, -1}, 724 {"fma", 1, INFINITY, -INFINITY, EDOM, -1}, 725 {"fma", 1, -INFINITY, INFINITY, EDOM, -1}, 726 /* NaN */ 727 {"fma", NAN, 0, 0, -1, -1}, 728 {"fma", 0, NAN, 0, -1, -1}, 729 {"fma", 0, 0, NAN, -1, -1}, 730 /* over/underflow */ 731 {"fma", __port_max_double(), __port_max_double(), __port_max_double(), -1, -1}, 732 {"fma", __port_min_pos_double(), __port_min_pos_double(), 1, -1, -1}, 733 }; 734 const struct { 735 char func[16]; 736 double a; 737 long b; 738 int error; 739 int exception; 740 } testsdl[] = { 741 {"_scalb", -INFINITY, 1, -1, -1}, 742 {"_scalb", -1e100, 1, -1, -1}, 743 {"_scalb", 0, 1, -1, -1}, 744 {"_scalb", 1e100, 1, -1, -1}, 745 {"_scalb", INFINITY, 1, -1, -1}, 746 {"_scalb", 1, 1e9, ERANGE, _OVERFLOW}, 747 {"ldexp", -INFINITY, 1, -1, -1}, 748 {"ldexp", -1e100, 1, -1, -1}, 749 {"ldexp", 0, 1, -1, -1}, 750 {"ldexp", 1e100, 1, -1, -1}, 751 {"ldexp", INFINITY, 1, -1, -1}, 752 {"ldexp", 1, -1e9, -1, _UNDERFLOW}, 753 {"ldexp", 1, 1e9, ERANGE, _OVERFLOW}, 754 }; 755 double (CDECL *p_funcd)(double); 756 double (CDECL *p_func2d)(double, double); 757 double (CDECL *p_func3d)(double, double, double); 758 double (CDECL *p_funcdl)(double, long); 759 HMODULE module; 760 double d; 761 int i; 762 763 __setusermatherr(matherr_callback); 764 module = GetModuleHandleW(L"ucrtbase.dll"); 765 766 /* necessary so that exp(1e100)==INFINITY on glibc, we can remove this if we change our implementation */ 767 fesetround(FE_TONEAREST); 768 769 for(i = 0; i < ARRAY_SIZE(testsd); i++) { 770 p_funcd = (void*)GetProcAddress(module, testsd[i].func); 771 errno = -1; 772 exception.type = -1; 773 p_funcd(testsd[i].x); 774 ok(errno == testsd[i].error, 775 "%s(%f) got errno %d\n", testsd[i].func, testsd[i].x, errno); 776 ok(exception.type == testsd[i].exception, 777 "%s(%f) got exception type %d\n", testsd[i].func, testsd[i].x, exception.type); 778 if(exception.type == -1) continue; 779 ok(exception.arg1 == testsd[i].x, 780 "%s(%f) got exception arg1 %f\n", testsd[i].func, testsd[i].x, exception.arg1); 781 } 782 783 for(i = 0; i < ARRAY_SIZE(tests2d); i++) { 784 p_func2d = (void*)GetProcAddress(module, tests2d[i].func); 785 errno = -1; 786 exception.type = -1; 787 p_func2d(tests2d[i].a, tests2d[i].b); 788 ok(errno == tests2d[i].error, 789 "%s(%f, %f) got errno %d\n", tests2d[i].func, tests2d[i].a, tests2d[i].b, errno); 790 ok(exception.type == tests2d[i].exception, 791 "%s(%f, %f) got exception type %d\n", tests2d[i].func, tests2d[i].a, tests2d[i].b, exception.type); 792 if(exception.type == -1) continue; 793 ok(exception.arg1 == tests2d[i].a, 794 "%s(%f, %f) got exception arg1 %f\n", tests2d[i].func, tests2d[i].a, tests2d[i].b, exception.arg1); 795 ok(exception.arg2 == tests2d[i].b, 796 "%s(%f, %f) got exception arg2 %f\n", tests2d[i].func, tests2d[i].a, tests2d[i].b, exception.arg2); 797 } 798 799 for(i = 0; i < ARRAY_SIZE(tests3d); i++) { 800 p_func3d = (void*)GetProcAddress(module, tests3d[i].func); 801 errno = -1; 802 exception.type = -1; 803 p_func3d(tests3d[i].a, tests3d[i].b, tests3d[i].c); 804 ok(errno == tests3d[i].error || errno == -1, /* native is not setting errno if FMA3 is supported */ 805 "%s(%f, %f, %f) got errno %d\n", tests3d[i].func, tests3d[i].a, tests3d[i].b, tests3d[i].c, errno); 806 ok(exception.type == tests3d[i].exception, 807 "%s(%f, %f, %f) got exception type %d\n", tests3d[i].func, tests3d[i].a, tests3d[i].b, tests3d[i].c, exception.type); 808 if(exception.type == -1) continue; 809 ok(exception.arg1 == tests3d[i].a, 810 "%s(%f, %f, %f) got exception arg1 %f\n", tests3d[i].func, tests3d[i].a, tests3d[i].b, tests3d[i].c, exception.arg1); 811 ok(exception.arg2 == tests3d[i].b, 812 "%s(%f, %f, %f) got exception arg2 %f\n", tests3d[i].func, tests3d[i].a, tests3d[i].b, tests3d[i].c, exception.arg2); 813 } 814 815 for(i = 0; i < ARRAY_SIZE(testsdl); i++) { 816 p_funcdl = (void*)GetProcAddress(module, testsdl[i].func); 817 errno = -1; 818 exception.type = -1; 819 p_funcdl(testsdl[i].a, testsdl[i].b); 820 ok(errno == testsdl[i].error, 821 "%s(%f, %ld) got errno %d\n", testsdl[i].func, testsdl[i].a, testsdl[i].b, errno); 822 ok(exception.type == testsdl[i].exception, 823 "%s(%f, %ld) got exception type %d\n", testsdl[i].func, testsdl[i].a, testsdl[i].b, exception.type); 824 if(exception.type == -1) continue; 825 ok(exception.arg1 == testsdl[i].a, 826 "%s(%f, %ld) got exception arg1 %f\n", testsdl[i].func, testsdl[i].a, testsdl[i].b, exception.arg1); 827 ok(exception.arg2 == testsdl[i].b, 828 "%s(%f, %ld) got exception arg2 %f\n", testsdl[i].func, testsdl[i].a, testsdl[i].b, exception.arg2); 829 } 830 831 d = acos(2.0); 832 ok(d == -1.0, "failed to change log10 return value: %e\n", d); 833} 834 835static void test_asctime(void) 836{ 837 const struct tm epoch = { 0, 0, 0, 1, 0, 70, 4, 0, 0 }; 838 char *ret; 839 840 ret = asctime(&epoch); 841 ok(!strcmp(ret, "Thu Jan 1 00:00:00 1970\n"), "asctime returned %s\n", ret); 842} 843 844static void test_strftime(void) 845{ 846 const struct { 847 const char *format; 848 const char *ret; 849 struct tm tm; 850 BOOL todo_value; 851 BOOL todo_handler; 852 } tests[] = { 853 {"%C", "", { 0, 0, 0, 1, 0, -2000, 4, 0, 0 }}, 854 {"%C", "", { 0, 0, 0, 1, 0, -1901, 4, 0, 0 }}, 855 {"%C", "00", { 0, 0, 0, 1, 0, -1900, 4, 0, 0 }}, 856 {"%C", "18", { 0, 0, 0, 1, 0, -1, 4, 0, 0 }}, 857 {"%C", "19", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 858 {"%C", "99", { 0, 0, 0, 1, 0, 8099, 4, 0, 0 }}, 859 {"%C", "", { 0, 0, 0, 1, 0, 8100, 4, 0, 0 }}, 860 {"%d", "", { 0, 0, 0, 0, 0, 70, 4, 0, 0 }}, 861 {"%d", "01", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 862 {"%d", "31", { 0, 0, 0, 31, 0, 70, 4, 0, 0 }}, 863 {"%d", "", { 0, 0, 0, 32, 0, 70, 4, 0, 0 }}, 864 {"%D", "", { 0, 0, 0, 1, 0, -1901, 4, 0, 0 }}, 865 {"%D", "01/01/00", { 0, 0, 0, 1, 0, -1900, 4, 0, 0 }}, 866 {"%D", "01/01/99", { 0, 0, 0, 1, 0, -1, 4, 0, 0 }}, 867 {"%D", "01/01/70", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 868 {"%D", "01/01/99", { 0, 0, 0, 1, 0, 8099, 4, 0, 0 }}, 869 {"%D", "", { 0, 0, 0, 1, 0, 8100, 4, 0, 0 }}, 870 {"%#D", "1/1/70", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 871 {"%e", "", { 0, 0, 0, 0, 0, 70, 4, 0, 0 }}, 872 {"%e", " 1", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 873 {"%e", "31", { 0, 0, 0, 31, 0, 70, 4, 0, 0 }}, 874 {"%e", "", { 0, 0, 0, 32, 0, 70, 4, 0, 0 }}, 875 {"%#e", "1", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 876 {"%F", "1970-01-01", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 877 {"%#F", "1970-1-1", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 878 {"%R", "00:00", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 879 {"%#R", "0:0", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 880 {"%T", "00:00:00", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 881 {"%#T", "0:0:0", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 882 {"%u", "", { 0, 0, 0, 1, 0, 117, -1, 0, 0 }}, 883 {"%u", "7", { 0, 0, 0, 1, 0, 117, 0, 0, 0 }}, 884 {"%u", "1", { 0, 0, 0, 1, 0, 117, 1, 0, 0 }}, 885 {"%u", "6", { 0, 0, 0, 1, 0, 117, 6, 0, 0 }}, 886 {"%u", "", { 0, 0, 0, 1, 0, 117, 7, 0, 0 }}, 887 {"%h", "Jan", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 888 {"%I", "", { 0, 0, -1, 1, 0, 70, 4, 0, 0 }}, 889 {"%I", "12", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 890 {"%I", "01", { 0, 0, 1, 1, 0, 70, 4, 0, 0 }}, 891 {"%I", "11", { 0, 0, 11, 1, 0, 70, 4, 0, 0 }}, 892 {"%I", "12", { 0, 0, 12, 1, 0, 70, 4, 0, 0 }}, 893 {"%I", "01", { 0, 0, 13, 1, 0, 70, 4, 0, 0 }}, 894 {"%I", "11", { 0, 0, 23, 1, 0, 70, 4, 0, 0 }}, 895 {"%I", "", { 0, 0, 24, 1, 0, 70, 4, 0, 0 }}, 896 {"%n", "\n", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 897 {"%r", "12:00:00 AM", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 898 {"%r", "02:00:00 PM", { 0, 0, 14, 1, 0, 121, 6, 0, 0 }}, 899 {"%#r", "12:0:0 AM", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 900 {"%#r", "2:0:0 PM", { 0, 0, 14, 1, 0, 121, 6, 0, 0 }}, 901 {"%t", "\t", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 902 {"%g", "", { 0, 0, 0, 1, 0, -1901, 4, 0, 0 }}, 903 {"%g", "", { 0, 0, 0, 1, 0, -1901, 3, 364, 0 }}, 904 {"%g", "00", { 0, 0, 0, 1, 0, -1900, 4, 0, 0 }}, 905 {"%g", "70", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 906 {"%g", "71", { 0, 0, 0, 2, 0, 72, 0, 1, 0 }}, 907 {"%g", "72", { 0, 0, 0, 3, 0, 72, 1, 2, 0 }}, 908 {"%g", "16", { 0, 0, 0, 1, 0, 117, 0, 0, 0 }}, 909 {"%g", "99", { 0, 0, 0, 1, 0, 8099, 4, 0, 0 }}, 910 {"%g", "00", { 0, 0, 0, 1, 0, 8099, 3, 364, 0 }}, 911 {"%g", "", { 0, 0, 0, 1, 0, 8100, 0, 0, 0 }}, 912 {"%g", "", { 0, 0, 0, 1, 0, 8100, 4, 0, 0 }}, 913 {"%G", "1970", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 914 {"%G", "1971", { 0, 0, 0, 2, 0, 72, 0, 1, 0 }}, 915 {"%G", "1972", { 0, 0, 0, 3, 0, 72, 1, 2, 0 }}, 916 {"%G", "2016", { 0, 0, 0, 1, 0, 117, 0, 0, 0 }}, 917 {"%V", "01", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 918 {"%V", "52", { 0, 0, 0, 1, 0, 117, 0, 0, 0 }}, 919 {"%V", "53", { 0, 0, 14, 1, 0, 121, 6, 0, 0 }}, 920 {"%y", "", { 0, 0, 0, 0, 0, -1901, 0, 0, 0 }}, 921 {"%y", "00", { 0, 0, 0, 0, 0, -1900, 0, 0, 0 }}, 922 {"%y", "99", { 0, 0, 0, 0, 0, 8099, 0, 0, 0 }}, 923 {"%y", "", { 0, 0, 0, 0, 0, 8100, 0, 0, 0 }}, 924 {"%c", "Thu Jan 1 00:00:00 1970", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 925 {"%c", "Thu Feb 30 00:00:00 1970", { 0, 0, 0, 30, 1, 70, 4, 0, 0 }}, 926 {"%#c", "Thursday, January 01, 1970 00:00:00", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 927 {"%#c", "Thursday, February 30, 1970 00:00:00", { 0, 0, 0, 30, 1, 70, 4, 0, 0 }}, 928 {"%x", "01/01/70", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 929 {"%x", "02/30/70", { 0, 0, 0, 30, 1, 70, 4, 0, 0 }}, 930 {"%#x", "Thursday, January 01, 1970", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 931 {"%#x", "Thursday, February 30, 1970", { 0, 0, 0, 30, 1, 70, 4, 0, 0 }}, 932 {"%#x", "", { 0, 0, 0, 30, 1, 70, 7, 0, 0 }}, 933 {"%#x", "", { 0, 0, 0, 30, 12, 70, 4, 0, 0 }}, 934 {"%X", "00:00:00", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }}, 935 {"%X", "14:00:00", { 0, 0, 14, 1, 0, 70, 4, 0, 0 }}, 936 {"%X", "23:59:60", { 60, 59, 23, 1, 0, 70, 4, 0, 0 }}, 937 }; 938 939 const struct { 940 const char *format; 941 const char *ret; 942 const wchar_t *short_date; 943 const wchar_t *date; 944 const wchar_t *time; 945 struct tm tm; 946 BOOL todo; 947 } tests_td[] = { 948 { "%c", "x z", L"x", L"y", L"z", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 949 { "%#c", "y z", L"x", L"y", L"z", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 950 { "%X", "M1", 0, 0, L"MMM", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }}, 951 { "%X", "1", 0, 0, L"h", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }}, 952 { "%X", "01", 0, 0, L"hh", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }}, 953 { "%X", "h01", 0, 0, L"hhh", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }}, 954 { "%X", "hh01", 0, 0, L"hhhh", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }}, 955 { "%X", "1", 0, 0, L"H", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }}, 956 { "%X", "01", 0, 0, L"HH", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }}, 957 { "%X", "H13", 0, 0, L"HHH", { 0, 0, 13, 1, 0, 70, 0, 0, 0 }}, 958 { "%X", "0", 0, 0, L"m", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 959 { "%X", "00", 0, 0, L"mm", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 960 { "%X", "m00", 0, 0, L"mmm", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 961 { "%X", "0", 0, 0, L"s", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 962 { "%X", "00", 0, 0, L"ss", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 963 { "%X", "s00", 0, 0, L"sss", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 964 { "%X", "T", 0, 0, L"t", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 965 { "%X", "TAM", 0, 0, L"tt", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 966 { "%X", "TAM", 0, 0, L"ttttttttt", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 967 { "%X", "TAM", 0, 0, L"a", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 968 { "%X", "TAM", 0, 0, L"aaaaa", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 969 { "%X", "TAM", 0, 0, L"A", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 970 { "%X", "TAM", 0, 0, L"AAAAA", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 971 { "%x", "1", L"d", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 972 { "%x", "01", L"dd", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 973 { "%x", "D1", L"ddd", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 974 { "%x", "Day1", L"dddd", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 975 { "%x", "dDay1", L"ddddd", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 976 { "%x", "1", L"M", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 977 { "%x", "01", L"MM", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 978 { "%x", "M1", L"MMM", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 979 { "%x", "Mon1", L"MMMM", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 980 { "%x", "MMon1", L"MMMMM", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 981 { "%x", "y", L"y", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 982 { "%x", "70", L"yy", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 983 { "%x", "y70", L"yyy", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 984 { "%x", "1970", L"yyyy", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 985 { "%x", "y1970", L"yyyyy", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 986 { "%x", "ggggggggggg", L"ggggggggggg", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 987 { "%#x", "1", 0, L"d", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 988 { "%#x", "01", 0, L"dd", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 989 { "%#x", "D1", 0, L"ddd", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 990 { "%#x", "Day1", 0, L"dddd", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 991 { "%#x", "dDay1", 0, L"ddddd", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 992 { "%#x", "1", 0, L"M", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 993 { "%#x", "01", 0, L"MM", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 994 { "%#x", "M1", 0, L"MMM", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 995 { "%#x", "Mon1", 0, L"MMMM", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 996 { "%#x", "MMon1", 0, L"MMMMM", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 997 { "%#x", "y", 0, L"y", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 998 { "%#x", "70", 0, L"yy", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 999 { "%#x", "y70", 0, L"yyy", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 1000 { "%#x", "1970", 0, L"yyyy", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 1001 { "%#x", "y1970", 0, L"yyyyy", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 1002 { "%r", "z", L"x", L"y", L"z", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }}, 1003 }; 1004 1005 const struct { 1006 int year; 1007 int yday; 1008 const char *ret[7]; 1009 } tests_yweek[] = { 1010 { 100, 0, { "99 52", "00 01", "00 01", "00 01", "00 01", "99 53", "99 52" }}, 1011 { 100, 1, { "99 52", "00 01", "00 01", "00 01", "00 01", "00 01", "99 53" }}, 1012 { 100, 2, { "99 53", "00 01", "00 01", "00 01", "00 01", "00 01", "00 01" }}, 1013 { 100, 3, { "00 01", "00 01", "00 01", "00 01", "00 01", "00 01", "00 01" }}, 1014 { 100, 4, { "00 01", "00 02", "00 01", "00 01", "00 01", "00 01", "00 01" }}, 1015 { 100, 5, { "00 01", "00 02", "00 02", "00 01", "00 01", "00 01", "00 01" }}, 1016 { 100, 6, { "00 01", "00 02", "00 02", "00 02", "00 01", "00 01", "00 01" }}, 1017 { 100, 358, { "00 51", "00 52", "00 52", "00 52", "00 52", "00 52", "00 51" }}, 1018 { 100, 359, { "00 51", "00 52", "00 52", "00 52", "00 52", "00 52", "00 52" }}, 1019 { 100, 360, { "00 52", "00 52", "00 52", "00 52", "00 52", "00 52", "00 52" }}, 1020 { 100, 361, { "00 52", "00 53", "00 52", "00 52", "00 52", "00 52", "00 52" }}, 1021 { 100, 362, { "00 52", "00 53", "00 53", "00 52", "00 52", "00 52", "00 52" }}, 1022 { 100, 363, { "00 52", "01 01", "00 53", "00 53", "00 52", "00 52", "00 52" }}, 1023 { 100, 364, { "00 52", "01 01", "01 01", "00 53", "00 53", "00 52", "00 52" }}, 1024 { 100, 365, { "00 52", "01 01", "01 01", "01 01", "00 53", "00 53", "00 52" }}, 1025 { 101, 0, { "00 52", "01 01", "01 01", "01 01", "01 01", "00 53", "00 53" }}, 1026 { 101, 1, { "00 53", "01 01", "01 01", "01 01", "01 01", "01 01", "00 53" }}, 1027 { 101, 2, { "00 53", "01 01", "01 01", "01 01", "01 01", "01 01", "01 01" }}, 1028 { 101, 3, { "01 01", "01 01", "01 01", "01 01", "01 01", "01 01", "01 01" }}, 1029 { 101, 4, { "01 01", "01 02", "01 01", "01 01", "01 01", "01 01", "01 01" }}, 1030 { 101, 5, { "01 01", "01 02", "01 02", "01 01", "01 01", "01 01", "01 01" }}, 1031 { 101, 6, { "01 01", "01 02", "01 02", "01 02", "01 01", "01 01", "01 01" }}, 1032 { 101, 358, { "01 51", "01 52", "01 52", "01 52", "01 52", "01 52", "01 51" }}, 1033 { 101, 359, { "01 51", "01 52", "01 52", "01 52", "01 52", "01 52", "01 52" }}, 1034 { 101, 360, { "01 52", "01 52", "01 52", "01 52", "01 52", "01 52", "01 52" }}, 1035 { 101, 361, { "01 52", "01 53", "01 52", "01 52", "01 52", "01 52", "01 52" }}, 1036 { 101, 362, { "01 52", "02 01", "01 53", "01 52", "01 52", "01 52", "01 52" }}, 1037 { 101, 363, { "01 52", "02 01", "02 01", "01 53", "01 52", "01 52", "01 52" }}, 1038 { 101, 364, { "01 52", "02 01", "02 01", "02 01", "01 53", "01 52", "01 52" }}, 1039 }; 1040 1041 __lc_time_data time_data = { 1042 { "d1", "d2", "d3", "d4", "d5", "d6", "d7" }, 1043 { "day1", "day2", "day3", "day4", "day5", "day6", "day7" }, 1044 { "m1", "m2", "m3", "m4", "m5", "m6", "m7", "m8", "m9", "m10", "m11", "m12" }, 1045 { "mon1", "mon2", "mon3", "mon4", "mon5", "mon6", "mon7", "mon8", "mon9", "mon10", "mon11", "mon12" }, 1046 "tam", "tpm", 0, 0, 0, 1, 0, 1047 { L"D1", L"D2", L"D3", L"D4", L"D5", L"D6", L"D7" }, 1048 { L"Day1", L"Day2", L"Day3", L"Day4", L"Day5", L"Day6", L"Day7" }, 1049 { L"M1", L"M2", L"M3", L"M4", L"M5", L"M6", L"M7", L"M8", L"M9", L"M10", L"M11", L"M12" }, 1050 { L"Mon1", L"Mon2", L"Mon3", L"Mon4", L"Mon5", L"Mon6", L"Mon7", L"Mon8", L"Mon9", L"Mon10", L"Mon11", L"Mon12" }, 1051 L"TAM", L"TPM" 1052 }; 1053 1054 const struct tm epoch = { 0, 0, 0, 1, 0, 70, 4, 0, 0 }; 1055 struct tm tm_yweek = { 0, 0, 0, 1, 0, 70, 0, 0, 0 }; 1056 char buf[256]; 1057 int i, ret=0; 1058 1059 for (i=0; i<ARRAY_SIZE(tests); i++) 1060 { 1061 todo_wine_if(tests[i].todo_handler) { 1062 if (!tests[i].ret[0]) 1063 SET_EXPECT(global_invalid_parameter_handler); 1064 ret = strftime(buf, sizeof(buf), tests[i].format, &tests[i].tm); 1065 if (!tests[i].ret[0]) 1066 CHECK_CALLED(global_invalid_parameter_handler); 1067 } 1068 1069 todo_wine_if(tests[i].todo_value) { 1070 ok(ret == strlen(tests[i].ret), "%d) ret = %d\n", i, ret); 1071 ok(!strcmp(buf, tests[i].ret), "%d) buf = \"%s\", expected \"%s\"\n", 1072 i, buf, tests[i].ret); 1073 } 1074 } 1075 1076 ret = strftime(buf, sizeof(buf), "%z", &epoch); 1077 ok(ret == 5, "expected 5, got %d\n", ret); 1078 ok((buf[0] == '+' || buf[0] == '-') && 1079 isdigit(buf[1]) && isdigit(buf[2]) && 1080 isdigit(buf[3]) && isdigit(buf[4]), "got %s\n", buf); 1081 1082 for (i=0; i<ARRAY_SIZE(tests_td); i++) 1083 { 1084 time_data.short_dateW = tests_td[i].short_date; 1085 time_data.dateW = tests_td[i].date; 1086 time_data.timeW = tests_td[i].time; 1087 ret = _Strftime(buf, sizeof(buf), tests_td[i].format, &tests_td[i].tm, &time_data); 1088 ok(ret == strlen(buf), "%d) ret = %d\n", i, ret); 1089 todo_wine_if(tests_td[i].todo) { 1090 ok(!strcmp(buf, tests_td[i].ret), "%d) buf = \"%s\", expected \"%s\"\n", 1091 i, buf, tests_td[i].ret); 1092 } 1093 } 1094 1095 for (i=0; i<ARRAY_SIZE(tests_yweek); i++) 1096 { 1097 int j; 1098 tm_yweek.tm_year = tests_yweek[i].year; 1099 tm_yweek.tm_yday = tests_yweek[i].yday; 1100 for (j=0; j<7; j++) 1101 { 1102 tm_yweek.tm_wday = j; 1103 strftime(buf, sizeof(buf), "%g %V", &tm_yweek); 1104 ok(!strcmp(buf, tests_yweek[i].ret[j]), "%d,%d) buf = \"%s\", expected \"%s\"\n", 1105 i, j, buf, tests_yweek[i].ret[j]); 1106 } 1107 } 1108 1109 if(!setlocale(LC_ALL, "fr-FR")) { 1110 win_skip("fr-FR locale not available\n"); 1111 return; 1112 } 1113 ret = strftime(buf, sizeof(buf), "%c", &epoch); 1114 ok(ret == 19, "ret = %d\n", ret); 1115 ok(!strcmp(buf, "01/01/1970 00:00:00"), "buf = \"%s\", expected \"%s\"\n", buf, "01/01/1970 00:00:00"); 1116 ret = strftime(buf, sizeof(buf), "%r", &epoch); 1117 ok(ret == 8, "ret = %d\n", ret); 1118 ok(!strcmp(buf, "00:00:00"), "buf = \"%s\", expected \"%s\"\n", buf, "00:00:00"); 1119 setlocale(LC_ALL, "C"); 1120 1121 if(!setlocale(LC_TIME, "Japanese_Japan.932")) { 1122 win_skip("Japanese_Japan.932 locale not available\n"); 1123 return; 1124 } 1125 ret = strftime(buf, sizeof(buf), "%a", &epoch); 1126 ok(ret == 2 || broken(ret == 1), "ret = %d\n", ret); 1127 ok(!strcmp(buf, "\x96\xd8"), "buf = %s, expected \"\\x96\\xd8\"\n", wine_dbgstr_an(buf, 2)); 1128 setlocale(LC_ALL, "C"); 1129} 1130 1131static LONG* get_failures_counter(HANDLE *map) 1132{ 1133 *map = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 1134 0, sizeof(LONG), "winetest_failures_counter"); 1135 return MapViewOfFile(*map, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(LONG)); 1136} 1137 1138static void free_failures_counter(LONG *mem, HANDLE map) 1139{ 1140 UnmapViewOfFile(mem); 1141 CloseHandle(map); 1142} 1143 1144static void set_failures_counter(LONG add) 1145{ 1146 HANDLE failures_map; 1147 LONG *failures; 1148 1149 failures = get_failures_counter(&failures_map); 1150 *failures = add; 1151 free_failures_counter(failures, failures_map); 1152} 1153 1154static void test_exit(const char *argv0) 1155{ 1156 PROCESS_INFORMATION proc; 1157 STARTUPINFOA startup = {0}; 1158 char path[MAX_PATH]; 1159 HANDLE failures_map, exit_event, quick_exit_event; 1160 LONG *failures; 1161 DWORD ret; 1162 1163 exit_event = CreateEventA(NULL, FALSE, FALSE, "exit_event"); 1164 quick_exit_event = CreateEventA(NULL, FALSE, FALSE, "quick_exit_event"); 1165 1166 failures = get_failures_counter(&failures_map); 1167 sprintf(path, "%s misc exit", argv0); 1168 startup.cb = sizeof(startup); 1169 CreateProcessA(NULL, path, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &proc); 1170 ret = WaitForSingleObject(proc.hProcess, INFINITE); 1171 ok(ret == WAIT_OBJECT_0, "child process wait failed\n"); 1172 GetExitCodeProcess(proc.hProcess, &ret); 1173 ok(ret == 1, "child process exited with code %ld\n", ret); 1174 CloseHandle(proc.hProcess); 1175 CloseHandle(proc.hThread); 1176 ok(!*failures, "%ld tests failed in child process\n", *failures); 1177 free_failures_counter(failures, failures_map); 1178 1179 1180 ret = WaitForSingleObject(exit_event, 0); 1181 ok(ret == WAIT_OBJECT_0, "exit_event was not set (%lx)\n", ret); 1182 ret = WaitForSingleObject(quick_exit_event, 0); 1183 ok(ret == WAIT_TIMEOUT, "quick_exit_event should not have be set (%lx)\n", ret); 1184 1185 CloseHandle(exit_event); 1186 CloseHandle(quick_exit_event); 1187} 1188 1189static int atexit_called; 1190 1191static void CDECL at_exit_func1(void) 1192{ 1193 HANDLE exit_event = CreateEventA(NULL, FALSE, FALSE, "exit_event"); 1194 1195 ok(exit_event != NULL, "CreateEvent failed: %ld\n", GetLastError()); 1196 ok(atexit_called == 1, "atexit_called = %d\n", atexit_called); 1197 atexit_called++; 1198 SetEvent(exit_event); 1199 CloseHandle(exit_event); 1200 set_failures_counter(winetest_get_failures()); 1201} 1202 1203static void CDECL at_exit_func2(void) 1204{ 1205 ok(!atexit_called, "atexit_called = %d\n", atexit_called); 1206 atexit_called++; 1207 set_failures_counter(winetest_get_failures()); 1208} 1209 1210static int atquick_exit_called; 1211 1212static void CDECL at_quick_exit_func1(void) 1213{ 1214 HANDLE quick_exit_event = CreateEventA(NULL, FALSE, FALSE, "quick_exit_event"); 1215 1216 ok(quick_exit_event != NULL, "CreateEvent failed: %ld\n", GetLastError()); 1217 ok(atquick_exit_called == 1, "atquick_exit_called = %d\n", atquick_exit_called); 1218 atquick_exit_called++; 1219 SetEvent(quick_exit_event); 1220 CloseHandle(quick_exit_event); 1221 set_failures_counter(winetest_get_failures()); 1222} 1223 1224static void CDECL at_quick_exit_func2(void) 1225{ 1226 ok(!atquick_exit_called, "atquick_exit_called = %d\n", atquick_exit_called); 1227 atquick_exit_called++; 1228 set_failures_counter(winetest_get_failures()); 1229} 1230 1231static void test_call_exit(void) 1232{ 1233 ok(!_crt_atexit(at_exit_func1), "_crt_atexit failed\n"); 1234 ok(!_crt_atexit(at_exit_func2), "_crt_atexit failed\n"); 1235 1236 ok(!_crt_at_quick_exit(at_quick_exit_func1), "_crt_at_quick_exit failed\n"); 1237 ok(!_crt_at_quick_exit(at_quick_exit_func2), "_crt_at_quick_exit failed\n"); 1238 1239 set_failures_counter(winetest_get_failures()); 1240 exit(1); 1241} 1242 1243static void test_call_quick_exit(void) 1244{ 1245 ok(!_crt_atexit(at_exit_func1), "_crt_atexit failed\n"); 1246 ok(!_crt_atexit(at_exit_func2), "_crt_atexit failed\n"); 1247 1248 ok(!_crt_at_quick_exit(at_quick_exit_func1), "_crt_at_quick_exit failed\n"); 1249 ok(!_crt_at_quick_exit(at_quick_exit_func2), "_crt_at_quick_exit failed\n"); 1250 1251 set_failures_counter(winetest_get_failures()); 1252 quick_exit(2); 1253} 1254 1255static void test_quick_exit(const char *argv0) 1256{ 1257 PROCESS_INFORMATION proc; 1258 STARTUPINFOA startup = {0}; 1259 char path[MAX_PATH]; 1260 HANDLE failures_map, exit_event, quick_exit_event; 1261 LONG *failures; 1262 DWORD ret; 1263 1264 exit_event = CreateEventA(NULL, FALSE, FALSE, "exit_event"); 1265 quick_exit_event = CreateEventA(NULL, FALSE, FALSE, "quick_exit_event"); 1266 1267 failures = get_failures_counter(&failures_map); 1268 sprintf(path, "%s misc quick_exit", argv0); 1269 startup.cb = sizeof(startup); 1270 CreateProcessA(NULL, path, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &proc); 1271 ret = WaitForSingleObject(proc.hProcess, INFINITE); 1272 ok(ret == WAIT_OBJECT_0, "child process wait failed\n"); 1273 GetExitCodeProcess(proc.hProcess, &ret); 1274 ok(ret == 2, "child process exited with code %ld\n", ret); 1275 CloseHandle(proc.hProcess); 1276 CloseHandle(proc.hThread); 1277 ok(!*failures, "%ld tests failed in child process\n", *failures); 1278 free_failures_counter(failures, failures_map); 1279 1280 ret = WaitForSingleObject(quick_exit_event, 0); 1281 ok(ret == WAIT_OBJECT_0, "quick_exit_event was not set (%lx)\n", ret); 1282 ret = WaitForSingleObject(exit_event, 0); 1283 ok(ret == WAIT_TIMEOUT, "exit_event should not have be set (%lx)\n", ret); 1284 1285 CloseHandle(exit_event); 1286 CloseHandle(quick_exit_event); 1287} 1288 1289static void test__stat32(void) 1290{ 1291 static const char test_file[] = "\\stat_file.tst"; 1292 static const char test_dir[] = "\\stat_dir.tst"; 1293 1294 char path[2*MAX_PATH]; 1295 struct _stat32 buf; 1296 int fd, ret; 1297 DWORD len; 1298 1299 len = GetTempPathA(MAX_PATH, path); 1300 ok(len, "GetTempPathA failed\n"); 1301 1302 ret = _stat32("c:", &buf); 1303 ok(ret == -1, "_stat32('c:') returned %d\n", ret); 1304 ret = _stat32("c:\\", &buf); 1305 ok(!ret, "_stat32('c:\\') returned %d\n", ret); 1306 1307 memcpy(path+len, test_file, sizeof(test_file)); 1308 if((fd = open(path, O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE)) >= 0) 1309 { 1310 ret = _stat32(path, &buf); 1311 ok(!ret, "_stat32('%s') returned %d\n", path, ret); 1312 strcat(path, "\\"); 1313 ret = _stat32(path, &buf); 1314 ok(ret, "_stat32('%s') returned %d\n", path, ret); 1315 close(fd); 1316 remove(path); 1317 } 1318 1319 memcpy(path+len, test_dir, sizeof(test_dir)); 1320 if(!mkdir(path)) 1321 { 1322 ret = _stat32(path, &buf); 1323 ok(!ret, "_stat32('%s') returned %d\n", path, ret); 1324 strcat(path, "\\"); 1325 ret = _stat32(path, &buf); 1326 ok(!ret, "_stat32('%s') returned %d\n", path, ret); 1327 rmdir(path); 1328 } 1329} 1330 1331static void test__o_malloc(void) 1332{ 1333 void *m; 1334 size_t s; 1335 1336 m = _o_malloc(1); 1337 ok(m != NULL, "p__o_malloc(1) returned NULL\n"); 1338 1339 s = _msize(m); 1340 ok(s == 1, "_msize returned %d\n", (int)s); 1341 1342 free(m); 1343} 1344 1345static void test_clock(void) 1346{ 1347 static const int thresh = 100, max_load_delay = 1000; 1348 int c, expect_min; 1349 FILETIME cur; 1350 1351 GetSystemTimeAsFileTime(&cur); 1352 c = clock(); 1353 1354 expect_min = (((LONGLONG)cur.dwHighDateTime << 32) + cur.dwLowDateTime - crt_init_end) / 10000; 1355 ok(c >= expect_min - thresh && c < expect_min + max_load_delay, "clock() = %d, expected range [%d, %d]\n", 1356 c, expect_min - thresh, expect_min + max_load_delay); 1357} 1358 1359static void __cdecl se_translator(unsigned int u, EXCEPTION_POINTERS *ep) 1360{ 1361} 1362 1363static void test_thread_storage(void) 1364{ 1365 void **current_exception; 1366 void *processing_throw; 1367 1368 _set_se_translator(se_translator); 1369 current_exception = __current_exception(); 1370 processing_throw = __processing_throw(); 1371 1372 ok(current_exception+2 == processing_throw, 1373 "current_exception = %p, processing_throw = %p\n", 1374 current_exception, processing_throw); 1375 ok(current_exception[-2] == se_translator, 1376 "can't find se_translator in thread storage\n"); 1377} 1378 1379static unsigned long fenv_encode(unsigned int e) 1380{ 1381 ok(!(e & ~FE_ALL_EXCEPT), "incorrect argument: %x\n", e); 1382 1383#if defined(__i386__) 1384 return e<<24 | e<<16 | e; 1385#elif defined(__x86_64__) 1386 return e<<24 | e; 1387#else 1388 return e; 1389#endif 1390} 1391 1392static void test_fenv(void) 1393{ 1394 static const int tests[] = { 1395 0, 1396 FE_INEXACT, 1397 FE_UNDERFLOW, 1398 FE_OVERFLOW, 1399 FE_DIVBYZERO, 1400 FE_INVALID, 1401 FE_ALL_EXCEPT, 1402 }; 1403 static const struct { 1404 fexcept_t except; 1405 unsigned int flag; 1406 unsigned int get; 1407 fexcept_t expect; 1408 } tests2[] = { 1409 /* except flag get expect */ 1410 { 0, 0, 0, 0 }, 1411 { FE_ALL_EXCEPT, FE_INEXACT, 0, 0 }, 1412 { FE_ALL_EXCEPT, FE_INEXACT, FE_ALL_EXCEPT, FE_INEXACT }, 1413 { FE_ALL_EXCEPT, FE_INEXACT, FE_INEXACT, FE_INEXACT }, 1414 { FE_ALL_EXCEPT, FE_INEXACT, FE_OVERFLOW, 0 }, 1415 { FE_ALL_EXCEPT, FE_ALL_EXCEPT, FE_ALL_EXCEPT, FE_ALL_EXCEPT }, 1416 { FE_ALL_EXCEPT, FE_ALL_EXCEPT, FE_INEXACT, FE_INEXACT }, 1417 { FE_ALL_EXCEPT, FE_ALL_EXCEPT, 0, 0 }, 1418 { FE_ALL_EXCEPT, FE_ALL_EXCEPT, ~0, FE_ALL_EXCEPT }, 1419 { FE_ALL_EXCEPT, FE_ALL_EXCEPT, ~FE_ALL_EXCEPT, 0 }, 1420 { FE_INEXACT, FE_ALL_EXCEPT, FE_ALL_EXCEPT, FE_INEXACT }, 1421 { FE_INEXACT, FE_UNDERFLOW, FE_ALL_EXCEPT, 0 }, 1422 { FE_UNDERFLOW, FE_INEXACT, FE_ALL_EXCEPT, 0 }, 1423 { FE_INEXACT|FE_UNDERFLOW, FE_UNDERFLOW, FE_ALL_EXCEPT, FE_UNDERFLOW }, 1424 { FE_UNDERFLOW, FE_INEXACT|FE_UNDERFLOW, FE_ALL_EXCEPT, FE_UNDERFLOW }, 1425 }; 1426 fenv_t env, env2; 1427 fexcept_t except; 1428 int i, ret, flags; 1429 1430 _clearfp(); 1431 1432 ret = fegetenv(&env); 1433 ok(!ret, "fegetenv returned %x\n", ret); 1434#if defined(__i386__) || defined(__x86_64__) 1435 if (env._Fe_ctl >> 24 != (env._Fe_ctl & 0xff)) 1436 { 1437 win_skip("fenv_t format not supported (too old ucrtbase)\n"); 1438 return; 1439 } 1440#endif 1441 fesetround(FE_UPWARD); 1442 ok(!env._Fe_stat, "env._Fe_stat = %lx\n", env._Fe_stat); 1443 ret = fegetenv(&env2); 1444 ok(!ret, "fegetenv returned %x\n", ret); 1445 ok(env._Fe_ctl != env2._Fe_ctl, "fesetround didn't change _Fe_ctl (%lx).\n", env._Fe_ctl); 1446 ret = fesetenv(&env); 1447 ok(!ret, "fesetenv returned %x\n", ret); 1448 ret = fegetround(); 1449 ok(ret == FE_TONEAREST, "Got unexpected round mode %#x.\n", ret); 1450 1451 except = fenv_encode(FE_ALL_EXCEPT); 1452 ret = fesetexceptflag(&except, FE_INEXACT|FE_UNDERFLOW); 1453 ok(!ret, "fesetexceptflag returned %x\n", ret); 1454 except = fetestexcept(FE_ALL_EXCEPT); 1455 ok(except == (FE_INEXACT|FE_UNDERFLOW), "expected %x, got %lx\n", FE_INEXACT|FE_UNDERFLOW, except); 1456 1457 ret = feclearexcept(~FE_ALL_EXCEPT); 1458 ok(!ret, "feclearexceptflag returned %x\n", ret); 1459 except = fetestexcept(FE_ALL_EXCEPT); 1460 ok(except == (FE_INEXACT|FE_UNDERFLOW), "expected %x, got %lx\n", FE_INEXACT|FE_UNDERFLOW, except); 1461 1462 /* no crash, but no-op */ 1463 ret = fesetexceptflag(NULL, 0); 1464 ok(!ret, "fesetexceptflag returned %x\n", ret); 1465 except = fetestexcept(FE_ALL_EXCEPT); 1466 ok(except == (FE_INEXACT|FE_UNDERFLOW), "expected %x, got %lx\n", FE_INEXACT|FE_UNDERFLOW, except); 1467 1468 /* zero clears all */ 1469 except = 0; 1470 ret = fesetexceptflag(&except, FE_ALL_EXCEPT); 1471 ok(!ret, "fesetexceptflag returned %x\n", ret); 1472 except = fetestexcept(FE_ALL_EXCEPT); 1473 ok(!except, "expected 0, got %lx\n", except); 1474 1475 ret = fetestexcept(FE_ALL_EXCEPT); 1476 ok(!ret, "fetestexcept returned %x\n", ret); 1477 1478 flags = 0; 1479 /* adding bits with flags */ 1480 for(i=0; i<ARRAY_SIZE(tests); i++) { 1481 except = fenv_encode(FE_ALL_EXCEPT); 1482 ret = fesetexceptflag(&except, tests[i]); 1483 ok(!ret, "Test %d: fesetexceptflag returned %x\n", i, ret); 1484 1485 ret = fetestexcept(tests[i]); 1486 ok(ret == tests[i], "Test %d: expected %x, got %x\n", i, tests[i], ret); 1487 1488 flags |= tests[i]; 1489 ret = fetestexcept(FE_ALL_EXCEPT); 1490 ok(ret == flags, "Test %d: expected %x, got %x\n", i, flags, ret); 1491 1492 except = ~0; 1493 ret = fegetexceptflag(&except, ~0); 1494 ok(!ret, "Test %d: fegetexceptflag returned %x.\n", i, ret); 1495 ok(except == fenv_encode(flags), 1496 "Test %d: expected %lx, got %lx\n", i, fenv_encode(flags), except); 1497 1498 except = ~0; 1499 ret = fegetexceptflag(&except, tests[i]); 1500 ok(!ret, "Test %d: fegetexceptflag returned %x.\n", i, ret); 1501 ok(except == fenv_encode(tests[i]), 1502 "Test %d: expected %lx, got %lx\n", i, fenv_encode(tests[i]), except); 1503 } 1504 1505 for(i=0; i<ARRAY_SIZE(tests); i++) { 1506 ret = feclearexcept(tests[i]); 1507 ok(!ret, "Test %d: feclearexceptflag returned %x\n", i, ret); 1508 1509 flags &= ~tests[i]; 1510 except = fetestexcept(tests[i]); 1511 ok(!except, "Test %d: expected %x, got %lx\n", i, flags, except); 1512 } 1513 1514 except = fetestexcept(FE_ALL_EXCEPT); 1515 ok(!except, "expected 0, got %lx\n", except); 1516 1517 /* setting bits with except */ 1518 for(i=0; i<ARRAY_SIZE(tests); i++) { 1519 except = fenv_encode(tests[i]); 1520 ret = fesetexceptflag(&except, FE_ALL_EXCEPT); 1521 ok(!ret, "Test %d: fesetexceptflag returned %x\n", i, ret); 1522 1523 ret = fetestexcept(tests[i]); 1524 ok(ret == tests[i], "Test %d: expected %x, got %x\n", i, tests[i], ret); 1525 1526 ret = fetestexcept(FE_ALL_EXCEPT); 1527 ok(ret == tests[i], "Test %d: expected %x, got %x\n", i, tests[i], ret); 1528 } 1529 1530 for(i=0; i<ARRAY_SIZE(tests2); i++) { 1531 _clearfp(); 1532 1533 except = fenv_encode(tests2[i].except); 1534 ret = fesetexceptflag(&except, tests2[i].flag); 1535 ok(!ret, "Test %d: fesetexceptflag returned %x\n", i, ret); 1536 1537 ret = fetestexcept(tests2[i].get); 1538 ok(ret == tests2[i].expect, "Test %d: expected %lx, got %x\n", i, tests2[i].expect, ret); 1539 } 1540 1541 ret = feclearexcept(FE_ALL_EXCEPT); 1542 ok(!ret, "feclearexceptflag returned %x\n", ret); 1543 except = fetestexcept(FE_ALL_EXCEPT); 1544 ok(!except, "expected 0, got %lx\n", except); 1545} 1546 1547static void test_fopen_exclusive( void ) 1548{ 1549 char path[MAX_PATH*2]; 1550 DWORD len; 1551 FILE *fp; 1552 1553 len = GetTempPathA(MAX_PATH, path); 1554 ok(len, "GetTempPathA failed\n"); 1555 strcat(path, "\\fileexcl.tst"); 1556 1557 SET_EXPECT(global_invalid_parameter_handler); 1558 fp = fopen(path, "wx"); 1559 if(called_global_invalid_parameter_handler) 1560 { 1561 win_skip("skipping fopen x mode tests.\n"); 1562 return; 1563 } 1564 expect_global_invalid_parameter_handler = FALSE; 1565 ok(fp != NULL, "creating file with mode wx failed\n"); 1566 fclose(fp); 1567 1568 fp = fopen(path, "wx"); 1569 ok(!fp, "overwrote existing file with mode wx\n"); 1570 unlink(path); 1571 1572 fp = fopen(path, "w+x"); 1573 ok(fp != NULL, "creating file with mode w+x failed\n"); 1574 fclose(fp); 1575 1576 fp = fopen(path, "w+x"); 1577 ok(!fp, "overwrote existing file with mode w+x\n"); 1578 1579 SET_EXPECT(global_invalid_parameter_handler); 1580 fp = fopen(path, "rx"); 1581 CHECK_CALLED(global_invalid_parameter_handler); 1582 ok(!fp, "opening file with mode rx succeeded\n"); 1583 unlink(path); 1584 1585 SET_EXPECT(global_invalid_parameter_handler); 1586 fp = fopen(path, "xw"); 1587 CHECK_CALLED(global_invalid_parameter_handler); 1588 ok(!fp, "creating file with mode xw succeeded\n"); 1589 1590 fp = fopen(path, "wbx"); 1591 ok(fp != NULL, "creating file with mode wbx failed\n"); 1592 fclose(fp); 1593 unlink(path); 1594} 1595 1596#if defined(__i386__) 1597#include "pshpack1.h" 1598struct rewind_thunk { 1599 BYTE push_esp[4]; /* push [esp+0x4] */ 1600 BYTE call_rewind; /* call */ 1601 DWORD rewind_addr; /* relative addr of rewind */ 1602 BYTE pop_eax; /* pop eax */ 1603 BYTE ret; /* ret */ 1604}; 1605#include "poppack.h" 1606 1607static FILE * (CDECL *test_rewind_wrapper)(FILE *fp); 1608 1609static void test_rewind_i386_abi(void) 1610{ 1611 FILE *fp_in, *fp_out; 1612 1613 struct rewind_thunk *thunk = VirtualAlloc(NULL, sizeof(*thunk), MEM_COMMIT, PAGE_EXECUTE_READWRITE); 1614 1615 thunk->push_esp[0] = 0xff; 1616 thunk->push_esp[1] = 0x74; 1617 thunk->push_esp[2] = 0x24; 1618 thunk->push_esp[3] = 0x04; 1619 1620 thunk->call_rewind = 0xe8; 1621 thunk->rewind_addr = (BYTE *) rewind - (BYTE *) (&thunk->rewind_addr + 1); 1622 1623 thunk->pop_eax = 0x58; 1624 thunk->ret = 0xc3; 1625 1626 test_rewind_wrapper = (void *) thunk; 1627 1628 fp_in = fopen("rewind_abi.tst", "wb"); 1629 fp_out = test_rewind_wrapper(fp_in); 1630 ok(fp_in == fp_out, "rewind modified the first argument in the stack\n"); 1631 1632 fclose(fp_in); 1633 unlink("rewind_abi.tst"); 1634} 1635#endif 1636 1637static void test_gmtime64(void) 1638{ 1639 struct tm *ptm, tm; 1640 __time64_t t; 1641 int ret; 1642 1643 t = -1; 1644 memset(&tm, 0xcc, sizeof(tm)); 1645 ptm = _gmtime64(&t); 1646 ok(!!ptm, "got NULL.\n"); 1647 ret = _gmtime64_s(&tm, &t); 1648 ok(!ret, "got %d.\n", ret); 1649 ok(tm.tm_year == 69 && tm.tm_hour == 23 && tm.tm_min == 59 && tm.tm_sec == 59, "got %d, %d, %d, %d.\n", 1650 tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec); 1651 1652 t = -43200; 1653 memset(&tm, 0xcc, sizeof(tm)); 1654 ptm = _gmtime64(&t); 1655 ok(!!ptm, "got NULL.\n"); 1656 ret = _gmtime64_s(&tm, &t); 1657 ok(!ret, "got %d.\n", ret); 1658 ok(tm.tm_year == 69 && tm.tm_hour == 12 && tm.tm_min == 0 && tm.tm_sec == 0, "got %d, %d, %d, %d.\n", 1659 tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec); 1660 ptm = _gmtime32((__time32_t *)&t); 1661 ok(!!ptm, "got NULL.\n"); 1662 memset(&tm, 0xcc, sizeof(tm)); 1663 ret = _gmtime32_s(&tm, (__time32_t *)&t); 1664 ok(!ret, "got %d.\n", ret); 1665 todo_wine_if(tm.tm_year == 69 && tm.tm_hour == 12) 1666 ok(tm.tm_year == 70 && tm.tm_hour == -12 && tm.tm_min == 0 && tm.tm_sec == 0, "got %d, %d, %d, %d.\n", 1667 tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec); 1668 1669 t = -43201; 1670 ptm = _gmtime64(&t); 1671 ok(!ptm, "got non-NULL.\n"); 1672 memset(&tm, 0xcc, sizeof(tm)); 1673 ret = _gmtime64_s(&tm, &t); 1674 ok(ret == EINVAL, "got %d.\n", ret); 1675 ok(tm.tm_year == -1 && tm.tm_hour == -1 && tm.tm_min == -1 && tm.tm_sec == -1, "got %d, %d, %d, %d.\n", 1676 tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec); 1677 ptm = _gmtime32((__time32_t *)&t); 1678 ok(!ptm, "got NULL.\n"); 1679 memset(&tm, 0xcc, sizeof(tm)); 1680 ret = _gmtime32_s(&tm, (__time32_t *)&t); 1681 ok(ret == EINVAL, "got %d.\n", ret); 1682 ok(tm.tm_year == -1 && tm.tm_hour == -1 && tm.tm_min == -1 && tm.tm_sec == -1, "got %d, %d, %d, %d.\n", 1683 tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec); 1684 1685 t = _MAX__TIME64_T + 1605600; 1686 memset(&tm, 0xcc, sizeof(tm)); 1687 ptm = _gmtime64(&t); 1688 ok(!!ptm || broken(!ptm) /* before Win10 1909 */, "got NULL.\n"); 1689 if (!ptm) 1690 { 1691 win_skip("Old gmtime64 limits, skipping tests.\n"); 1692 return; 1693 } 1694 ret = _gmtime64_s(&tm, &t); 1695 ok(!ret, "got %d.\n", ret); 1696 ok(tm.tm_year == 1101 && tm.tm_hour == 21 && tm.tm_min == 59 && tm.tm_sec == 59, "got %d, %d, %d, %d.\n", 1697 tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec); 1698 1699 t = _MAX__TIME64_T + 1605601; 1700 ptm = _gmtime64(&t); 1701 ok(!ptm, "got non-NULL.\n"); 1702 memset(&tm, 0xcc, sizeof(tm)); 1703 ret = _gmtime64_s(&tm, &t); 1704 ok(ret == EINVAL, "got %d.\n", ret); 1705 ok(tm.tm_year == -1 && tm.tm_hour == -1 && tm.tm_min == -1 && tm.tm_sec == -1, "got %d, %d, %d, %d.\n", 1706 tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec); 1707} 1708 1709static void test__get_heap_handle(void) 1710{ 1711 ok((HANDLE)_get_heap_handle() == GetProcessHeap(), "Expected _get_heap_handle() to return GetProcessHeap()\n"); 1712} 1713 1714START_TEST(misc) 1715{ 1716 int arg_c; 1717 char** arg_v; 1718 FILETIME cur; 1719 1720 GetSystemTimeAsFileTime(&cur); 1721 crt_init_end = ((LONGLONG)cur.dwHighDateTime << 32) + cur.dwLowDateTime; 1722 1723 arg_c = winetest_get_mainargs(&arg_v); 1724 if(arg_c == 3) { 1725 if(!strcmp(arg_v[2], "cmd")) 1726 test__get_narrow_winmain_command_line(NULL); 1727 else if(!strcmp(arg_v[2], "exit")) 1728 test_call_exit(); 1729 else if(!strcmp(arg_v[2], "quick_exit")) 1730 test_call_quick_exit(); 1731 return; 1732 } 1733 1734 test_invalid_parameter_handler(); 1735 test__initialize_onexit_table(); 1736 test__register_onexit_function(); 1737 test__execute_onexit_table(); 1738 test___fpe_flt_rounds(); 1739 test__control87_2(); 1740 test__get_narrow_winmain_command_line(arg_v[0]); 1741 test__sopen_dispatch(); 1742 test__sopen_s(); 1743 test_lldiv(); 1744 test_isblank(); 1745 test_math_errors(); 1746 test_asctime(); 1747 test_strftime(); 1748 test_exit(arg_v[0]); 1749 test_quick_exit(arg_v[0]); 1750 test__stat32(); 1751 test__o_malloc(); 1752 test_clock(); 1753 test_thread_storage(); 1754 test_fenv(); 1755 test_fopen_exclusive(); 1756#if defined(__i386__) 1757 test_rewind_i386_abi(); 1758#endif 1759 test_gmtime64(); 1760 test__get_heap_handle(); 1761}