1 /* 2 * PROJECT: ReactOS CRT API tests 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Tests for crt data exports 5 * COPYRIGHT: Copyright 2021 Timo Kreuzer <timo.kreuzer@reactos.org> 6 */ 7 8 #include <apitest.h> 9 #include <apitest_guard.h> 10 11 #define WIN32_NO_STATUS 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <time.h> 15 #include <locale.h> 16 #include <mbctype.h> 17 18 static OSVERSIONINFOW s_osvi; 19 extern char __ImageBase; 20 static void* s_ImageEnd; 21 22 int IsLocalSymbol(void* Address) 23 { 24 return ((Address >= (void*)&__ImageBase) && (Address <= s_ImageEnd)); 25 } 26 27 #ifndef TEST_STATIC 28 #define test_is_local_symbol(addr, is) ok_int(IsLocalSymbol(addr), (is)) 29 #else 30 #define test_is_local_symbol(addr, is) 31 #endif 32 33 void Test___argc(void) 34 { 35 void* p = &__argc; 36 test_is_local_symbol(p, FALSE); 37 38 #undef __argc 39 ok_ptr(&__argc, p); 40 #ifdef _M_IX86 41 ok_ptr(__p___argc(), p); 42 #endif 43 } 44 45 void Test___argv(void) 46 { 47 void* p = &__argv; 48 test_is_local_symbol(p, FALSE); 49 50 #undef __argv 51 ok_ptr(&__argv, p); 52 #ifdef _M_IX86 53 ok_ptr(__p___argv(), p); 54 #endif 55 } 56 57 void Test___badioinfo(void) 58 { 59 typedef struct _ioinfo ioinfo; 60 _CRTIMP extern ioinfo* __badioinfo[]; 61 ok(__badioinfo != NULL, "__badioinfo is NULL\n"); 62 ok(__badioinfo[0] != NULL, "__badioinfo is NULL\n"); 63 } 64 65 #ifndef _M_ARM 66 void Test___initenv(void) 67 { 68 _CRTIMP extern char** __initenv; 69 ok(__initenv != NULL, "__initenv is NULL\n"); 70 ok(*__initenv != NULL, "*__initenv is NULL\n"); 71 #ifdef _M_IX86 72 _CRTIMP char*** __p___initenv(void); 73 ok_ptr(__p___initenv(), &__initenv); 74 #endif 75 } 76 77 void Test___lc_codepage(void) 78 { 79 _CRTIMP extern unsigned int __lc_codepage; 80 ok_int(__lc_codepage, 0); 81 ok_int(___lc_codepage_func(), 0); 82 __lc_codepage++; 83 todo_ros ok_int(___lc_codepage_func(), 0); 84 __lc_codepage--; 85 } 86 87 void Test___lc_collate_cp(void) 88 { 89 _CRTIMP extern int __lc_collate_cp; 90 test_is_local_symbol(&__lc_collate_cp, FALSE); 91 ok_int(__lc_collate_cp, 0); 92 ok_int(___lc_collate_cp_func(), 0); 93 __lc_collate_cp++; 94 ok_int(___lc_collate_cp_func(), 0); 95 __lc_collate_cp--; 96 } 97 #endif // !_M_ARM 98 99 void Test___lc_handle(void) 100 { 101 _CRTIMP int __lc_handle; 102 ok_int(__lc_handle, 0); 103 _CRTIMP int* ___lc_handle_func(); 104 ok_int(*___lc_handle_func(), 0); 105 __lc_handle++; 106 todo_ros ok_int(*___lc_handle_func(), 0); 107 __lc_handle--; 108 } 109 110 void Test___mb_cur_max(void) 111 { 112 void* p = &__mb_cur_max; 113 test_is_local_symbol(&__mb_cur_max, FALSE); 114 ok_int(__mb_cur_max, 1); 115 116 #undef __mb_cur_max 117 _CRTIMP extern int __mb_cur_max; 118 ok_ptr(&__mb_cur_max, p); 119 120 ok_int(___mb_cur_max_func(), 1); 121 #ifdef _M_IX86 122 _CRTIMP int* __p___mb_cur_max(void); 123 ok_int(*__p___mb_cur_max(), 1); 124 #endif 125 __mb_cur_max++; 126 if (s_osvi.dwMajorVersion >= 6) 127 { 128 ok_int(___mb_cur_max_func(), 1); 129 #ifdef _M_IX86 130 ok_int(*__p___mb_cur_max(), 1); 131 #endif 132 } 133 else 134 { 135 todo_ros ok_int(___mb_cur_max_func(), 2); 136 #ifdef _M_IX86 137 todo_ros ok_ptr(__p___mb_cur_max(), p); // wine code handles it like on Vista+ 138 todo_ros ok_int(*__p___mb_cur_max(), 2); 139 #endif 140 } 141 142 __mb_cur_max--; 143 } 144 145 void Test___pioinfo(void) 146 { 147 148 } 149 150 #ifndef _M_ARM 151 void Test___setlc_active(void) 152 { 153 _CRTIMP extern unsigned int __setlc_active; 154 ok_int(__setlc_active, 0); 155 156 _CRTIMP unsigned int ___setlc_active_func(void); 157 ok_int(___setlc_active_func(), __setlc_active); 158 __setlc_active++; 159 ok_int(___setlc_active_func(), __setlc_active); 160 __setlc_active--; 161 } 162 163 void Test___unguarded_readlc_active(void) 164 { 165 _CRTIMP extern unsigned int __unguarded_readlc_active; 166 void* p = &__unguarded_readlc_active; 167 ok_int(__unguarded_readlc_active, 0); 168 169 _CRTIMP unsigned int* ___unguarded_readlc_active_add_func(void); 170 ok_ptr(___unguarded_readlc_active_add_func(), p); 171 } 172 #endif // !_M_ARM 173 174 void Test___wargv(void) 175 { 176 void* p = &__wargv; 177 test_is_local_symbol(p, FALSE); 178 179 #undef __wargv 180 _CRTIMP extern wchar_t ** __wargv; 181 ok_ptr(&__wargv, p); 182 #ifdef _M_IX86 183 ok_ptr(__p___wargv(), p); 184 #endif 185 } 186 187 #ifndef _M_ARM 188 void Test___winitenv(void) 189 { 190 _CRTIMP extern wchar_t** __winitenv; 191 todo_ros ok(__winitenv == NULL, "__winitenv is not NULL\n"); 192 #ifdef _M_IX86 193 _CRTIMP wchar_t*** __p___winitenv(void); 194 ok_ptr(__p___winitenv(), &__winitenv); 195 #endif 196 } 197 #endif 198 199 void Test__acmdln(void) 200 { 201 _CRTIMP extern char* _acmdln; 202 ok(_acmdln != NULL, "__winitenv is NULL\n"); 203 #ifdef _M_IX86 204 _CRTIMP char** __p__acmdln(void); 205 ok_ptr(__p__acmdln(), &_acmdln); 206 #endif 207 } 208 209 #ifdef _M_IX86 210 void Test__adjust_fdiv(void) 211 { 212 _CRTIMP extern int _adjust_fdiv; 213 ok_int(_adjust_fdiv, 0); 214 } 215 #endif 216 217 void Test__aexit_rtn(void) 218 { 219 typedef void (*_exit_t)(int exitcode); 220 _CRTIMP extern _exit_t _aexit_rtn; 221 ok_ptr(_aexit_rtn, _exit); 222 } 223 224 void Test__commode(void) 225 { 226 void* p = &_commode; 227 test_is_local_symbol(&_commode, FALSE); 228 ok_int(_commode, 0); 229 230 #undef _commode 231 _CRTIMP extern int _commode; 232 ok_ptr(&_commode, p); 233 #ifdef _M_IX86 234 ok_ptr(__p__commode(), &_commode); 235 #endif 236 } 237 238 void Test__ctype(void) 239 { 240 _CRTIMP extern const unsigned short _ctype[]; 241 ok_int(_ctype[0], 0); 242 ok_int(_ctype[1], _CONTROL); 243 244 #undef _pctype 245 _CRTIMP extern const unsigned short* _pctype; 246 ok(_pctype != &_ctype[0], "_pwctype should not match &_wctype[0]"); 247 if (s_osvi.dwMajorVersion >= 6) 248 { 249 ok(_pctype != &_ctype[1], "_pwctype should not match &_wctype[1]"); 250 } 251 else 252 { 253 ok(_pctype == &_ctype[1], "_pwctype should match &_wctype[1]"); 254 } 255 256 ok(__pctype_func() != _ctype, "__pctype_func() should not match _ctype\n"); 257 ok_int(__pctype_func()[0], _CONTROL); 258 ok_int(__pctype_func()[1], _CONTROL); 259 #ifdef _M_IX86 260 _CRTIMP const unsigned short** __cdecl __p__pctype(void); 261 ok_ptr(*__p__pctype(), __pctype_func()); 262 #endif 263 } 264 265 void Test__wctype(void) 266 { 267 ok_int(_wctype[0], 0); 268 ok_int(_wctype[1], _CONTROL); 269 270 #undef _pwctype 271 _CRTIMP extern const unsigned short* _pwctype; 272 ok_ptr(_pwctype, &_wctype[1]); 273 274 ok(__pwctype_func() != _wctype, "__pwctype_func() == _wctype\n"); 275 ok_int(__pctype_func()[0], _CONTROL); 276 ok_int(__pctype_func()[1], _CONTROL); 277 #ifdef _M_IX86 278 _CRTIMP const unsigned short** __cdecl __p__pwctype(void); 279 ok_ptr(*__p__pwctype(), __pwctype_func()); 280 #endif 281 } 282 283 void Test__daylight(void) 284 { 285 void* p = &_daylight; 286 test_is_local_symbol(&_daylight, FALSE); 287 288 #undef _daylight 289 _CRTIMP extern int _daylight; 290 ok_ptr(&_daylight, p); 291 292 #ifdef _M_IX86 293 _CRTIMP void* __p__daylight(void); 294 ok_ptr(__p__daylight(), &_daylight); 295 #endif 296 #if (WINVER >= 0x600) 297 _CRTIMP int* __cdecl __daylight(void); 298 ok_ptr(&__daylight, &_daylight); 299 #endif 300 } 301 302 #ifndef _M_ARM 303 void Test__dstbias(void) 304 { 305 void* p = &_dstbias; 306 test_is_local_symbol(&_dstbias, FALSE); 307 308 #undef _dstbias 309 _CRTIMP extern long _dstbias; 310 ok_ptr(&_dstbias, p); 311 #ifdef _M_IX86 312 _CRTIMP long* __cdecl __p__dstbias(void); 313 ok_ptr(__p__dstbias(), &_dstbias); 314 #endif 315 #if (WINVER >= 0x600) 316 _CRTIMP long* __cdecl __dstbias(void); 317 ok_ptr(&__dstbias, &_dstbias); 318 #endif 319 } 320 321 void Test__environ(void) 322 { 323 void* p = &_environ; 324 ok(_environ != NULL, "_environ == NULL\n"); 325 326 #undef _environ 327 _CRTIMP extern char** _environ; 328 ok_ptr(&_environ, p); 329 #ifdef _M_IX86 330 ok_ptr(__p__environ(), &_environ); 331 #endif 332 } 333 334 void Test__fileinfo(void) 335 { 336 _CRTIMP extern int _fileinfo; 337 ok_int(_fileinfo, -1); 338 339 #ifdef _M_IX86 340 _CRTIMP int* __p__fileinfo(); 341 ok_ptr(__p__fileinfo(), &_fileinfo); 342 #endif 343 } 344 #endif // !_M_ARM 345 346 void Test__fmode(void) 347 { 348 void* p = &_fmode; 349 test_is_local_symbol(&_fmode, FALSE); 350 ok_int(_fmode, 0); 351 352 #undef _fmode 353 _CRTIMP extern int _fmode; 354 ok_ptr(&_fmode, p); 355 356 #ifdef _M_IX86 357 _CRTIMP int* __cdecl __p__fmode(); 358 ok_ptr(__p__fmode(), p); 359 #endif 360 361 #if (_WIN32_WINNT >= 0x600) 362 _fmode = 1234; 363 _CRTIMP errno_t __cdecl _get_fmode(_Out_ int* _PMode); 364 int mode; 365 ok_int(_get_fmode(&mode), 0); 366 ok_int(mode, _fmode); 367 _fmode = 0; 368 #endif 369 } 370 371 void Test__iob(void) 372 { 373 void* p = &_iob; 374 test_is_local_symbol(&_iob, FALSE); 375 ok_ptr(&_iob[0], stdin); 376 ok_ptr(&_iob[1], stdout); 377 ok_ptr(&_iob[2], stderr); 378 379 #undef _iob 380 _CRTIMP extern FILE _iob[]; 381 ok_ptr(&_iob, p); 382 383 ok_ptr(__iob_func(), &_iob); 384 385 #ifdef _M_IX86 386 _CRTIMP int* __cdecl __p__iob(); 387 ok_ptr(__p__iob(), p); 388 #endif 389 } 390 391 void Test__mbcasemap(void) 392 { 393 void* p = &_mbcasemap; 394 ok_int(_mbcasemap[0], 0); 395 396 #undef _mbcasemap 397 ok_ptr(_mbcasemap, p); 398 399 #ifdef _M_IX86 400 _CRTIMP unsigned char* __cdecl __p__mbcasemap(); 401 ok_ptr(__p__mbcasemap(), &_mbcasemap); 402 #endif 403 } 404 405 void Test__mbctype(void) 406 { 407 void* p = &_mbctype; 408 ok_int(_mbctype[0], 0); 409 410 #undef _mbctype 411 ok_ptr(&_mbctype, p); 412 413 #ifdef _M_IX86 414 _CRTIMP unsigned char* __cdecl __p__mbctype(); 415 todo_ros ok_ptr(__p__mbctype(), &_mbctype); // wine implements thiss like on Vista 416 #endif 417 } 418 419 #ifndef _M_ARM 420 void Test__osplatform(void) 421 { 422 ok_int(_osplatform, s_osvi.dwPlatformId); 423 #if (WINVER >= 0x600) 424 _CRTIMP unsigned int __cdecl _get_osplatform(void); 425 ok_ptr(_get_osplatform(), _osplatform); 426 #endif 427 } 428 #endif 429 430 void Test__osver(void) 431 { 432 ok_int(_osver, s_osvi.dwBuildNumber); 433 434 #ifdef _M_IX86 435 _CRTIMP int* __cdecl __p__osver(); 436 ok_ptr(__p__osver(), &_osver); 437 #endif 438 } 439 440 void Test__pgmptr(void) 441 { 442 void* p = &_pgmptr; 443 ok(_pgmptr != NULL, "_pgmptr should not be NULL\n"); 444 445 #undef _pgmptr 446 _CRTIMP extern char* _pgmptr; 447 ok_ptr(&_pgmptr, p); 448 #ifdef _M_IX86 449 ok_ptr(__p__pgmptr(), &_pgmptr); 450 #endif 451 #if (WINVER >= 0x600) 452 _CRTIMP char* __cdecl _get_pgmptr(void); 453 ok_ptr(_get_pgmptr(), _pgmptr); 454 #endif 455 } 456 457 void Test__sys_errlist(void) 458 { 459 void* p = &_sys_errlist; 460 ok_int(strcmp(_sys_errlist[0], strerror(0)), 0); 461 ok_int(strcmp(_sys_errlist[42], strerror(42)), 0); 462 463 #undef _sys_errlist 464 _CRTIMP extern char* _sys_errlist[]; 465 ok_ptr(&_sys_errlist, p); 466 } 467 468 void Test__sys_nerr(void) 469 { 470 void* p = &_sys_nerr; 471 ok_int(_sys_nerr, 43); 472 473 #undef _sys_nerr 474 _CRTIMP extern int _sys_nerr; 475 ok_ptr(&_sys_nerr, p); 476 } 477 478 void Test__timezone(void) 479 { 480 void* p = &_timezone; 481 test_is_local_symbol(&_timezone, FALSE); 482 483 #undef _timezone 484 _CRTIMP extern long _timezone; 485 ok_ptr(&_timezone, p); 486 487 #ifdef _M_IX86 488 _CRTIMP char** __p__timezone(); 489 ok_ptr(__p__timezone(), &_timezone); 490 #endif 491 } 492 493 void Test__tzname(void) 494 { 495 void* p = &_tzname; 496 test_is_local_symbol(&_tzname, FALSE); 497 ok(_tzname[0] != NULL, "_tzname[0] == NULL\n"); 498 ok(_tzname[0] != NULL, "_tzname[0] == NULL\n"); 499 500 #undef _tzname 501 _CRTIMP extern char * _tzname[2]; 502 ok_ptr(_tzname, p); 503 504 #ifdef _M_IX86 505 _CRTIMP char** __p__tzname(); 506 ok_ptr(__p__tzname(), &_tzname); 507 #endif 508 #if (WINVER >= 0x600) 509 _CRTIMP char* __cdecl __tzname(void); 510 ok_ptr(__tzname(), _wenviron); 511 #endif 512 } 513 514 void Test__wcmdln(void) 515 { 516 _CRTIMP extern wchar_t* _wcmdln; 517 #ifdef _M_IX86 518 _CRTIMP wchar_t** __p__wcmdln(void); 519 ok_ptr(__p__wcmdln(), &_wcmdln); 520 #endif 521 } 522 523 #ifndef _M_ARM 524 void Test__wenviron(void) 525 { 526 void* p = &_wenviron; 527 todo_ros ok(_wenviron == NULL, "_wenviron is not NULL\n"); 528 529 #undef _wenviron 530 _CRTIMP extern wchar_t** _wenviron; 531 ok_ptr(&_wenviron, p); 532 #ifdef _M_IX86 533 ok_ptr(__p__wenviron(), &_wenviron); 534 #endif 535 #if (WINVER >= 0x600) 536 _CRTIMP unsigned int __cdecl _get_wenviron(void); 537 ok_int(_get_wenviron(), _wenviron); 538 #endif 539 } 540 #endif 541 542 void Test__winmajor(void) 543 { 544 ok_int(_winmajor, s_osvi.dwMajorVersion); 545 #ifdef _M_IX86 546 _CRTIMP unsigned int* __cdecl __p__winmajor(); 547 ok_ptr(__p__winmajor(), &_winmajor); 548 #endif 549 #if (WINVER >= 0x600) 550 _CRTIMP unsigned int __cdecl _get_winmajor(void); 551 ok_int(_get_winmajor(), _winmajor); 552 #endif 553 } 554 555 void Test__winminor(void) 556 { 557 ok_int(_winminor, s_osvi.dwMinorVersion); 558 #ifdef _M_IX86 559 _CRTIMP unsigned int* __cdecl __p__winminor(); 560 ok_ptr(__p__winminor(), &_winminor); 561 #endif 562 #if (WINVER >= 0x600) 563 _CRTIMP unsigned int __cdecl _get_winminor(void); 564 ok_int(_get_winminor(), _winminor); 565 #endif 566 } 567 568 #ifndef _M_ARM 569 void Test__winver(void) 570 { 571 ok_int(_winver, (s_osvi.dwMajorVersion << 8) | s_osvi.dwMinorVersion); 572 #ifdef _M_IX86 573 _CRTIMP unsigned int* __cdecl __p__winver(); 574 ok_ptr(__p__winver(), &_winver); 575 #endif 576 #if (WINVER >= 0x600) 577 _CRTIMP unsigned int __cdecl _get_winver(void); 578 ok_int(_get_winver(), _winver); 579 #endif 580 } 581 #endif 582 583 void Test__wpgmptr(void) 584 { 585 void* p = _wpgmptr; 586 ok_ptr(_wpgmptr, NULL); 587 588 #undef _wpgmptr 589 ok_ptr(_wpgmptr, p); 590 591 #ifdef _M_IX86 592 _CRTIMP wchar_t ** __cdecl __p__wpgmptr(); 593 ok_ptr(__p__wpgmptr(), &_wpgmptr); 594 #endif 595 #if (WINVER >= 0x600) 596 _CRTIMP unsigned int __cdecl _get_wpgmptr(void); 597 ok_int(_get_wpgmptr(), _wpgmptr); 598 #endif 599 } 600 601 START_TEST(crtdata) 602 { 603 /* Initialize image size */ 604 PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)&__ImageBase; 605 PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((PUCHAR)dosHeader + dosHeader->e_lfanew); 606 s_ImageEnd = (PUCHAR)dosHeader + ntHeaders->OptionalHeader.SizeOfImage; 607 608 /* initialize version info */ 609 s_osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); 610 GetVersionExW(&s_osvi); 611 612 Test___argc(); 613 Test___argv(); 614 Test___badioinfo(); 615 #ifndef _M_ARM 616 Test___initenv(); 617 Test___lc_codepage(); 618 Test___lc_collate_cp(); 619 #endif 620 Test___lc_handle(); 621 Test___mb_cur_max(); 622 Test___pioinfo(); 623 #ifndef _M_ARM 624 Test___setlc_active(); 625 Test___unguarded_readlc_active(); 626 #endif 627 Test___wargv(); 628 #ifndef _M_ARM 629 Test___winitenv(); 630 #endif 631 Test__acmdln(); 632 #ifdef _M_IX86 633 Test__adjust_fdiv(); 634 #endif 635 Test__aexit_rtn(); 636 Test__commode(); 637 Test__ctype(); 638 Test__daylight(); 639 #ifndef _M_ARM 640 Test__dstbias(); 641 Test__environ(); 642 Test__fileinfo(); 643 #endif 644 Test__fmode(); 645 Test__iob(); 646 Test__mbcasemap(); 647 Test__mbctype(); 648 #ifndef _M_ARM 649 Test__osplatform(); 650 #endif 651 Test__osver(); 652 Test__pgmptr(); 653 Test__sys_errlist(); 654 Test__sys_nerr(); 655 Test__timezone(); 656 Test__tzname(); 657 Test__wcmdln(); 658 Test__wctype(); 659 #ifndef _M_ARM 660 Test__wenviron(); 661 #endif 662 Test__winmajor(); 663 Test__winminor(); 664 #ifndef _M_ARM 665 Test__winver(); 666 #endif 667 Test__wpgmptr(); 668 } 669