/* * PROJECT: ReactOS CRT API tests * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * PURPOSE: Tests for crt data exports * COPYRIGHT: Copyright 2021 Timo Kreuzer */ #include #include #define WIN32_NO_STATUS #include #include #include #include #include static OSVERSIONINFOW s_osvi; extern char __ImageBase; static void* s_ImageEnd; int IsLocalSymbol(void* Address) { return ((Address >= (void*)&__ImageBase) && (Address <= s_ImageEnd)); } // Dynamically imported functions (Vista+) int* (__cdecl *p__daylight)(void); long* (__cdecl *p__dstbias)(void); errno_t (__cdecl *p_get_fmode)(int* _PMode); errno_t (__cdecl *p_get_osplatform)(unsigned int *pValue); int (__cdecl *p_get_pgmptr)(char** p); errno_t (__cdecl *p_get_wpgmptr)(_Outptr_result_z_ wchar_t **_Value); errno_t (__cdecl *p_get_winver)(_Out_ unsigned int *_Value); errno_t (__cdecl *p_get_winmajor)(_Out_ unsigned int *_Value); errno_t (__cdecl *p_get_winminor)(_Out_ unsigned int *_Value); errno_t (__cdecl *p_get_environ)(_Out_ char***); errno_t (__cdecl *p_get_wenviron)(_Out_ wchar_t***); #ifndef TEST_STATIC #define test_is_local_symbol(addr, is) ok_int(IsLocalSymbol(addr), (is)) #else #define test_is_local_symbol(addr, is) #endif void Test___argc(void) { void* p = &__argc; test_is_local_symbol(p, FALSE); #undef __argc ok_ptr(&__argc, p); #ifdef _M_IX86 ok_ptr(__p___argc(), p); #endif } void Test___argv(void) { void* p = &__argv; test_is_local_symbol(p, FALSE); #undef __argv ok_ptr(&__argv, p); #ifdef _M_IX86 ok_ptr(__p___argv(), p); #endif } void Test___badioinfo(void) { typedef struct _ioinfo ioinfo; _CRTIMP extern ioinfo* __badioinfo[]; ok(__badioinfo != NULL, "__badioinfo is NULL\n"); ok(__badioinfo[0] != NULL, "__badioinfo is NULL\n"); } #ifndef _M_ARM void Test___initenv(void) { _CRTIMP extern char** __initenv; ok(__initenv != NULL, "__initenv is NULL\n"); ok(*__initenv != NULL, "*__initenv is NULL\n"); #ifdef _M_IX86 _CRTIMP char*** __p___initenv(void); ok_ptr(__p___initenv(), &__initenv); #endif } void Test___lc_codepage(void) { _CRTIMP extern unsigned int __lc_codepage; ok_int(__lc_codepage, 0); ok_int(___lc_codepage_func(), 0); __lc_codepage++; todo_ros ok_int(___lc_codepage_func(), 0); __lc_codepage--; } void Test___lc_collate_cp(void) { _CRTIMP extern int __lc_collate_cp; test_is_local_symbol(&__lc_collate_cp, FALSE); ok_int(__lc_collate_cp, 0); ok_int(___lc_collate_cp_func(), 0); __lc_collate_cp++; ok_int(___lc_collate_cp_func(), 0); __lc_collate_cp--; } #endif // !_M_ARM void Test___lc_handle(void) { _CRTIMP int __lc_handle; ok_int(__lc_handle, 0); _CRTIMP int* ___lc_handle_func(); ok_int(*___lc_handle_func(), 0); __lc_handle++; todo_ros ok_int(*___lc_handle_func(), 0); __lc_handle--; } void Test___mb_cur_max(void) { void* p = &__mb_cur_max; test_is_local_symbol(&__mb_cur_max, FALSE); ok_int(__mb_cur_max, 1); #undef __mb_cur_max _CRTIMP extern int __mb_cur_max; ok_ptr(&__mb_cur_max, p); ok_int(___mb_cur_max_func(), 1); #ifdef _M_IX86 _CRTIMP int* __p___mb_cur_max(void); ok_int(*__p___mb_cur_max(), 1); #endif __mb_cur_max++; if (s_osvi.dwMajorVersion >= 6) { ok_int(___mb_cur_max_func(), 1); #ifdef _M_IX86 ok_int(*__p___mb_cur_max(), 1); #endif } else { todo_ros ok_int(___mb_cur_max_func(), 2); #ifdef _M_IX86 todo_ros ok_ptr(__p___mb_cur_max(), p); // wine code handles it like on Vista+ todo_ros ok_int(*__p___mb_cur_max(), 2); #endif } __mb_cur_max--; } void Test___pioinfo(void) { } #ifndef _M_ARM void Test___setlc_active(void) { _CRTIMP extern unsigned int __setlc_active; ok_int(__setlc_active, 0); _CRTIMP unsigned int ___setlc_active_func(void); ok_int(___setlc_active_func(), __setlc_active); __setlc_active++; ok_int(___setlc_active_func(), __setlc_active); __setlc_active--; } void Test___unguarded_readlc_active(void) { _CRTIMP extern unsigned int __unguarded_readlc_active; void* p = &__unguarded_readlc_active; ok_int(__unguarded_readlc_active, 0); _CRTIMP unsigned int* ___unguarded_readlc_active_add_func(void); ok_ptr(___unguarded_readlc_active_add_func(), p); } #endif // !_M_ARM void Test___wargv(void) { void* p = &__wargv; test_is_local_symbol(p, FALSE); #undef __wargv _CRTIMP extern wchar_t ** __wargv; ok_ptr(&__wargv, p); #ifdef _M_IX86 ok_ptr(__p___wargv(), p); #endif } #ifndef _M_ARM void Test___winitenv(void) { _CRTIMP extern wchar_t** __winitenv; todo_ros ok(__winitenv == NULL, "__winitenv is not NULL\n"); #ifdef _M_IX86 _CRTIMP wchar_t*** __p___winitenv(void); ok_ptr(__p___winitenv(), &__winitenv); #endif } #endif void Test__acmdln(void) { _CRTIMP extern char* _acmdln; ok(_acmdln != NULL, "__winitenv is NULL\n"); #ifdef _M_IX86 _CRTIMP char** __p__acmdln(void); ok_ptr(__p__acmdln(), &_acmdln); #endif } #ifdef _M_IX86 void Test__adjust_fdiv(void) { _CRTIMP extern int _adjust_fdiv; ok_int(_adjust_fdiv, 0); } #endif void Test__aexit_rtn(void) { typedef void (*_exit_t)(int exitcode); _CRTIMP extern _exit_t _aexit_rtn; ok_ptr(_aexit_rtn, _exit); } void Test__commode(void) { void* p = &_commode; test_is_local_symbol(&_commode, FALSE); ok_int(_commode, 0); #undef _commode _CRTIMP extern int _commode; ok_ptr(&_commode, p); #ifdef _M_IX86 ok_ptr(__p__commode(), &_commode); #endif } void Test__ctype(void) { _CRTIMP extern const unsigned short _ctype[]; ok_int(_ctype[0], 0); ok_int(_ctype[1], _CONTROL); #undef _pctype _CRTIMP extern const unsigned short* _pctype; ok(_pctype != &_ctype[0], "_pwctype should not match &_wctype[0]"); if (s_osvi.dwMajorVersion >= 6) { ok(_pctype != &_ctype[1], "_pwctype should not match &_wctype[1]"); } else { ok(_pctype == &_ctype[1], "_pwctype should match &_wctype[1]"); } ok(__pctype_func() != _ctype, "__pctype_func() should not match _ctype\n"); ok_int(__pctype_func()[0], _CONTROL); ok_int(__pctype_func()[1], _CONTROL); #ifdef _M_IX86 _CRTIMP const unsigned short** __cdecl __p__pctype(void); ok_ptr(*__p__pctype(), __pctype_func()); #endif } void Test__wctype(void) { ok_int(_wctype[0], 0); ok_int(_wctype[1], _CONTROL); #undef _pwctype _CRTIMP extern const unsigned short* _pwctype; ok_ptr(_pwctype, &_wctype[1]); ok(__pwctype_func() != _wctype, "__pwctype_func() == _wctype\n"); ok_int(__pctype_func()[0], _CONTROL); ok_int(__pctype_func()[1], _CONTROL); #ifdef _M_IX86 _CRTIMP const unsigned short** __cdecl __p__pwctype(void); ok_ptr(*__p__pwctype(), __pwctype_func()); #endif } void Test__daylight(void) { void* p = &_daylight; test_is_local_symbol(&_daylight, FALSE); #undef _daylight _CRTIMP extern int _daylight; ok_ptr(&_daylight, p); #ifdef _M_IX86 _CRTIMP void* __p__daylight(void); ok_ptr(__p__daylight(), &_daylight); #endif if (p__daylight != NULL) { ok_ptr(p__daylight(), &_daylight); } } #ifndef _M_ARM void Test__dstbias(void) { void* p = &_dstbias; test_is_local_symbol(&_dstbias, FALSE); #undef _dstbias _CRTIMP extern long _dstbias; ok_ptr(&_dstbias, p); #ifdef _M_IX86 _CRTIMP long* __cdecl __p__dstbias(void); ok_ptr(__p__dstbias(), &_dstbias); #endif if (p__dstbias != NULL) { ok_ptr(p__dstbias(), &_dstbias); } } void Test__environ(void) { void* p = &_environ; ok(_environ != NULL, "_environ == NULL\n"); #undef _environ _CRTIMP extern char** _environ; ok_ptr(&_environ, p); #ifdef _M_IX86 ok_ptr(__p__environ(), &_environ); #endif if (p_get_environ != NULL) { char** result_environ; ok_int(p_get_environ(&result_environ), 0); ok_ptr(result_environ, _environ); } } void Test__fileinfo(void) { _CRTIMP extern int _fileinfo; ok_int(_fileinfo, -1); #ifdef _M_IX86 _CRTIMP int* __p__fileinfo(); ok_ptr(__p__fileinfo(), &_fileinfo); #endif } #endif // !_M_ARM void Test__fmode(void) { void* p = &_fmode; test_is_local_symbol(&_fmode, FALSE); ok_int(_fmode, 0); #undef _fmode _CRTIMP extern int _fmode; ok_ptr(&_fmode, p); #ifdef _M_IX86 _CRTIMP int* __cdecl __p__fmode(); ok_ptr(__p__fmode(), p); #endif if (p_get_fmode != NULL) { _fmode = 1234; int mode; ok_int(p_get_fmode(&mode), 0); ok_int(mode, _fmode); _fmode = 0; } } void Test__iob(void) { void* p = &_iob; test_is_local_symbol(&_iob, FALSE); ok_ptr(&_iob[0], stdin); ok_ptr(&_iob[1], stdout); ok_ptr(&_iob[2], stderr); #undef _iob _CRTIMP extern FILE _iob[]; ok_ptr(&_iob, p); ok_ptr(__iob_func(), &_iob); #ifdef _M_IX86 _CRTIMP int* __cdecl __p__iob(); ok_ptr(__p__iob(), p); #endif } void Test__mbcasemap(void) { void* p = &_mbcasemap; ok_int(_mbcasemap[0], 0); #undef _mbcasemap ok_ptr(_mbcasemap, p); #ifdef _M_IX86 _CRTIMP unsigned char* __cdecl __p__mbcasemap(); ok_ptr(__p__mbcasemap(), &_mbcasemap); #endif } void Test__mbctype(void) { void* p = &_mbctype; ok_int(_mbctype[0], 0); #undef _mbctype ok_ptr(&_mbctype, p); #ifdef _M_IX86 _CRTIMP unsigned char* __cdecl __p__mbctype(); todo_ros ok_ptr(__p__mbctype(), &_mbctype); // wine implements thiss like on Vista #endif } #ifndef _M_ARM void Test__osplatform(void) { ok_int(_osplatform, s_osvi.dwPlatformId); if (p_get_osplatform != NULL) { unsigned int result_osplatform; ok_int(p_get_osplatform(&result_osplatform), 0); ok_int(result_osplatform, _osplatform); } } #endif void Test__osver(void) { ok_int(_osver, s_osvi.dwBuildNumber); #ifdef _M_IX86 _CRTIMP int* __cdecl __p__osver(); ok_ptr(__p__osver(), &_osver); #endif } void Test__pgmptr(void) { void* p = &_pgmptr; ok(_pgmptr != NULL, "_pgmptr should not be NULL\n"); #undef _pgmptr _CRTIMP extern char* _pgmptr; ok_ptr(&_pgmptr, p); #ifdef _M_IX86 ok_ptr(__p__pgmptr(), &_pgmptr); #endif if (p_get_pgmptr != NULL) { char *result_pgmptr; ok_int(p_get_pgmptr(&result_pgmptr), 0); ok_ptr(result_pgmptr, _pgmptr); } } void Test__sys_errlist(void) { void* p = &_sys_errlist; ok_int(strcmp(_sys_errlist[0], strerror(0)), 0); ok_int(strcmp(_sys_errlist[42], strerror(42)), 0); #undef _sys_errlist _CRTIMP extern char* _sys_errlist[]; ok_ptr(&_sys_errlist, p); } void Test__sys_nerr(void) { void* p = &_sys_nerr; ok_int(_sys_nerr, 43); #undef _sys_nerr _CRTIMP extern int _sys_nerr; ok_ptr(&_sys_nerr, p); } void Test__timezone(void) { void* p = &_timezone; test_is_local_symbol(&_timezone, FALSE); #undef _timezone _CRTIMP extern long _timezone; ok_ptr(&_timezone, p); #ifdef _M_IX86 _CRTIMP char** __p__timezone(); ok_ptr(__p__timezone(), &_timezone); #endif } void Test__tzname(void) { void* p = &_tzname; test_is_local_symbol(&_tzname, FALSE); ok(_tzname[0] != NULL, "_tzname[0] == NULL\n"); ok(_tzname[0] != NULL, "_tzname[0] == NULL\n"); #undef _tzname _CRTIMP extern char * _tzname[2]; ok_ptr(_tzname, p); #ifdef _M_IX86 _CRTIMP char** __p__tzname(); ok_ptr(__p__tzname(), &_tzname); #endif } void Test__wcmdln(void) { _CRTIMP extern wchar_t* _wcmdln; #ifdef _M_IX86 _CRTIMP wchar_t** __p__wcmdln(void); ok_ptr(__p__wcmdln(), &_wcmdln); #endif } #ifndef _M_ARM void Test__wenviron(void) { void* p = &_wenviron; todo_ros ok(_wenviron == NULL, "_wenviron is not NULL\n"); #undef _wenviron _CRTIMP extern wchar_t** _wenviron; ok_ptr(&_wenviron, p); #ifdef _M_IX86 ok_ptr(__p__wenviron(), &_wenviron); #endif #if 0 // FIXME: This returns an error / NULL on Windows 10 if (p_get_wenviron != NULL) { wchar_t** result_wenviron; ok_int(p_get_wenviron(&result_wenviron), 0); ok_ptr(result_wenviron, _wenviron); } #endif } #endif void Test__winmajor(void) { ok_int(_winmajor, s_osvi.dwMajorVersion); #ifdef _M_IX86 _CRTIMP unsigned int* __cdecl __p__winmajor(); ok_ptr(__p__winmajor(), &_winmajor); #endif if (p_get_winmajor != NULL) { unsigned int result_winmajor; ok_int(p_get_winmajor(&result_winmajor), 0); ok_int(result_winmajor, _winmajor); } } void Test__winminor(void) { ok_int(_winminor, s_osvi.dwMinorVersion); #ifdef _M_IX86 _CRTIMP unsigned int* __cdecl __p__winminor(); ok_ptr(__p__winminor(), &_winminor); #endif if (p_get_winminor != NULL) { unsigned int result_winminor; ok_int(p_get_winminor(&result_winminor), 0); ok_int(result_winminor, _winminor); } } #ifndef _M_ARM void Test__winver(void) { ok_int(_winver, (s_osvi.dwMajorVersion << 8) | s_osvi.dwMinorVersion); #ifdef _M_IX86 _CRTIMP unsigned int* __cdecl __p__winver(); ok_ptr(__p__winver(), &_winver); #endif if (p_get_winver != NULL) { unsigned int result_winver; ok_int(p_get_winver(&result_winver), 0); ok_int(result_winver, _winver); } } #endif void Test__wpgmptr(void) { void* p = _wpgmptr; ok_ptr(_wpgmptr, NULL); #undef _wpgmptr ok_ptr(_wpgmptr, p); #ifdef _M_IX86 _CRTIMP wchar_t ** __cdecl __p__wpgmptr(); ok_ptr(__p__wpgmptr(), &_wpgmptr); #endif #if 0 // FIXME: This returns an error on Windows 10 if (p_get_wpgmptr != NULL) { wchar_t* result_wpgmptr; ok_int(p_get_wpgmptr(&result_wpgmptr), 0); ok_ptr(result_wpgmptr, _wpgmptr); } #endif } START_TEST(crtdata) { /* Initialize image size */ PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)&__ImageBase; PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((PUCHAR)dosHeader + dosHeader->e_lfanew); s_ImageEnd = (PUCHAR)dosHeader + ntHeaders->OptionalHeader.SizeOfImage; /* initialize version info */ s_osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); GetVersionExW(&s_osvi); HMODULE hmsvcrt = GetModuleHandleA("msvcrt.dll"); p__daylight = (void*)GetProcAddress(hmsvcrt, "__daylight"); p__dstbias = (void*)GetProcAddress(hmsvcrt, "__dstbias"); p_get_fmode = (void*)GetProcAddress(hmsvcrt, "_get_fmode"); p_get_osplatform = (void*)GetProcAddress(hmsvcrt, "_get_osplatform"); p_get_pgmptr = (void*)GetProcAddress(hmsvcrt, "_get_pgmptr"); p_get_wpgmptr = (void*)GetProcAddress(hmsvcrt, "_get_wpgmptr"); p_get_winver = (void*)GetProcAddress(hmsvcrt, "_get_winver"); p_get_winmajor = (void*)GetProcAddress(hmsvcrt, "_get_winmajor"); p_get_winminor = (void*)GetProcAddress(hmsvcrt, "_get_winminor"); p_get_environ = (void*)GetProcAddress(hmsvcrt, "_get_environ"); p_get_wenviron = (void*)GetProcAddress(hmsvcrt, "_get_wenviron"); if (s_osvi.dwMajorVersion >= 6) { ok(p__daylight != NULL, "__daylight is NULL\n"); ok(p__dstbias != NULL, "__dstbias is NULL\n"); ok(p_get_fmode != NULL, "_get_fmode is NULL\n"); ok(p_get_osplatform != NULL, "_get_osplatform is NULL\n"); ok(p_get_pgmptr != NULL, "_get_pgmptr is NULL\n"); ok(p_get_wpgmptr != NULL, "_get_wpgmptr is NULL\n"); ok(p_get_winver != NULL, "_get_winver is NULL\n"); ok(p_get_winmajor != NULL, "_get_winmajor is NULL\n"); ok(p_get_winminor != NULL, "_get_winminor is NULL\n"); ok(p_get_environ != NULL, "_get_environ is NULL\n"); ok(p_get_wenviron != NULL, "_get_wenviron is NULL\n"); } Test___argc(); Test___argv(); Test___badioinfo(); #ifndef _M_ARM Test___initenv(); Test___lc_codepage(); Test___lc_collate_cp(); #endif Test___lc_handle(); Test___mb_cur_max(); Test___pioinfo(); #ifndef _M_ARM Test___setlc_active(); Test___unguarded_readlc_active(); #endif Test___wargv(); #ifndef _M_ARM Test___winitenv(); #endif Test__acmdln(); #ifdef _M_IX86 Test__adjust_fdiv(); #endif Test__aexit_rtn(); Test__commode(); Test__ctype(); Test__daylight(); #ifndef _M_ARM Test__dstbias(); Test__environ(); Test__fileinfo(); #endif Test__fmode(); Test__iob(); Test__mbcasemap(); Test__mbctype(); #ifndef _M_ARM Test__osplatform(); #endif Test__osver(); Test__pgmptr(); Test__sys_errlist(); Test__sys_nerr(); Test__timezone(); Test__tzname(); Test__wcmdln(); Test__wctype(); #ifndef _M_ARM Test__wenviron(); #endif Test__winmajor(); Test__winminor(); #ifndef _M_ARM Test__winver(); #endif Test__wpgmptr(); }