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