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