1 /*
2  * Tests msvcrt/data.c
3  *
4  * Copyright 2006 Andrew Ziem
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include "precomp.h"
22 
23 #include <direct.h>
24 
25 void __cdecl __getmainargs(int *, char ***, char ***, int, int *);
26 static int* (__cdecl *p___p___argc)(void);
27 static char*** (__cdecl *p___p___argv)(void);
28 
29 typedef void (__cdecl *_INITTERMFUN)(void);
30 static void (__cdecl *p_initterm)(_INITTERMFUN *start, _INITTERMFUN *end);
31 
32 static int (__cdecl *p_get_pgmptr)(char **p);
33 
34 static int callbacked;
35 
36 static void __cdecl initcallback(void)
37 {
38    callbacked++;
39 }
40 
41 #define initterm_test(start, end, expected) \
42     callbacked = 0; \
43     p_initterm(start, end); \
44     ok(expected == callbacked,"_initterm: callbacks count mismatch: got %i, expected %i\n", callbacked, expected);
45 
46 static void test_initterm(void)
47 {
48     int i;
49     static _INITTERMFUN callbacks[4];
50 
51     if (!p_initterm)
52         return;
53 
54     for (i = 0; i < 4; i++)
55     {
56         callbacks[i] = initcallback;
57     }
58 
59     initterm_test(&callbacks[0], &callbacks[1], 1);
60     initterm_test(&callbacks[0], &callbacks[2], 2);
61     initterm_test(&callbacks[0], &callbacks[3], 3);
62 
63     callbacks[1] = NULL;
64     initterm_test(&callbacks[0], &callbacks[3], 2);
65 }
66 
67 static void test_initvar( HMODULE hmsvcrt )
68 {
69     OSVERSIONINFOA osvi = { sizeof(OSVERSIONINFOA) };
70     int *pp_winver   = (int*)GetProcAddress(hmsvcrt, "_winver");
71     int *pp_winmajor = (int*)GetProcAddress(hmsvcrt, "_winmajor");
72     int *pp_winminor = (int*)GetProcAddress(hmsvcrt, "_winminor");
73     int *pp_osver    = (int*)GetProcAddress(hmsvcrt, "_osver");
74     int *pp_osplatform = (int*)GetProcAddress(hmsvcrt, "_osplatform");
75     unsigned int winver, winmajor, winminor, osver, osplatform;
76 
77     if( !( pp_winmajor && pp_winminor && pp_winver)) {
78         win_skip("_winver variables are not available\n");
79         return;
80     }
81     winver = *pp_winver;
82     winminor = *pp_winminor;
83     winmajor = *pp_winmajor;
84     GetVersionExA( &osvi);
85     ok( winminor == osvi.dwMinorVersion, "Wrong value for _winminor %02x expected %02x\n",
86             winminor, osvi.dwMinorVersion);
87     ok( winmajor == osvi.dwMajorVersion, "Wrong value for _winmajor %02x expected %02x\n",
88             winmajor, osvi.dwMajorVersion);
89     ok( winver == ((osvi.dwMajorVersion << 8) | osvi.dwMinorVersion),
90             "Wrong value for _winver %02x expected %02x\n",
91             winver, ((osvi.dwMajorVersion << 8) | osvi.dwMinorVersion));
92     if( !pp_osver || !pp_osplatform ) {
93         win_skip("_osver variables are not available\n");
94         return;
95     }
96     osver = *pp_osver;
97     osplatform = *pp_osplatform;
98     ok( osver == (osvi.dwBuildNumber & 0xffff) ||
99             ((osvi.dwBuildNumber >> 24) == osvi.dwMajorVersion &&
100                  ((osvi.dwBuildNumber >> 16) & 0xff) == osvi.dwMinorVersion), /* 95/98/ME */
101             "Wrong value for _osver %04x expected %04x\n",
102             osver, osvi.dwBuildNumber);
103     ok(osplatform == osvi.dwPlatformId,
104             "Wrong value for _osplatform %x expected %x\n",
105             osplatform, osvi.dwPlatformId);
106 }
107 
108 static void test_get_pgmptr(void)
109 {
110     char *pgm = NULL;
111     int res;
112 
113     if (!p_get_pgmptr)
114         return;
115 
116     res = p_get_pgmptr(&pgm);
117 
118     ok( res == 0, "Wrong _get_pgmptr return value %d expected 0\n", res);
119     ok( pgm != NULL, "_get_pgmptr returned a NULL pointer\n" );
120 }
121 
122 static void test___getmainargs(void)
123 {
124     int argc, new_argc, mode;
125     char **argv, **new_argv, **envp;
126     char tmppath[MAX_PATH], filepath[MAX_PATH];
127     FILE *f;
128 
129     ok(GetTempPathA(MAX_PATH, tmppath) != 0, "GetTempPath failed\n");
130 
131     mode = 0;
132     __getmainargs(&argc, &argv, &envp, 0, &mode);
133     ok(argc == 4, "argc = %d\n", argc);
134     ok(!strcmp(argv[1], "data"), "argv[1] = %s\n", argv[1]);
135     sprintf(filepath, "%s*\\*", tmppath);
136     ok(!strcmp(argv[2], filepath), "argv[2] = %s\n", argv[2]);
137     sprintf(filepath, "%swine_test/*", tmppath);
138     ok(!strcmp(argv[3], filepath), "argv[3] = %s\n", argv[3]);
139     ok(!argv[4], "argv[4] != NULL\n");
140 
141     if(p___p___argc && p___p___argv) {
142         new_argc = *p___p___argc();
143         new_argv = *p___p___argv();
144         ok(new_argc == 4, "*__p___argc() = %d\n", new_argc);
145         ok(new_argv == argv, "*__p___argv() = %p, expected %p\n", new_argv, argv);
146     }else {
147         win_skip("__p___argc or __p___argv is not available\n");
148     }
149 
150     mode = 0;
151     __getmainargs(&argc, &argv, &envp, 1, &mode);
152     ok(argc == 5, "argc = %d\n", argc);
153     ok(!strcmp(argv[1], "data"), "argv[1] = %s\n", argv[1]);
154     sprintf(filepath, "%s*\\*", tmppath);
155     ok(!strcmp(argv[2], filepath), "argv[2] = %s\n", argv[2]);
156     sprintf(filepath, "%swine_test/a", tmppath);
157     if(argv[3][strlen(argv[3])-1] == 'a') {
158         ok(!strcmp(argv[3], filepath), "argv[3] = %s\n", argv[3]);
159         sprintf(filepath, "%swine_test/test", tmppath);
160         ok(!strcmp(argv[4], filepath), "argv[4] = %s\n", argv[4]);
161     }else {
162         ok(!strcmp(argv[4], filepath), "argv[4] = %s\n", argv[4]);
163         sprintf(filepath, "%swine_test/test", tmppath);
164         ok(!strcmp(argv[3], filepath), "argv[3] = %s\n", argv[3]);
165     }
166     ok(!argv[5], "argv[5] != NULL\n");
167 
168     if(p___p___argc && p___p___argv) {
169         new_argc = *p___p___argc();
170         new_argv = *p___p___argv();
171         ok(new_argc == argc, "*__p___argc() = %d, expected %d\n", new_argc, argc);
172         ok(new_argv == argv, "*__p___argv() = %p, expected %p\n", new_argv, argv);
173     }
174 
175     sprintf(filepath, "%swine_test/b", tmppath);
176     f = fopen(filepath, "w");
177     ok(f != NULL, "fopen(%s) failed: %d\n", filepath, errno);
178     fclose(f);
179     mode = 0;
180     __getmainargs(&new_argc, &new_argv, &envp, 1, &mode);
181     ok(new_argc == argc+1, "new_argc = %d, expected %d\n", new_argc, argc+1);
182     _unlink(filepath);
183 }
184 
185 static void test___getmainargs_parent(char *name)
186 {
187     char cmdline[3*MAX_PATH];
188     char tmppath[MAX_PATH], filepath[MAX_PATH];
189     STARTUPINFOA startup;
190     PROCESS_INFORMATION proc;
191     FILE *f;
192     int ret;
193 
194     ok(GetTempPathA(MAX_PATH, tmppath) != 0, "GetTempPath failed\n");
195     sprintf(cmdline, "%s data %s*\\* %swine_test/*", name, tmppath, tmppath);
196 
197     sprintf(filepath, "%swine_test", tmppath);
198     ret = _mkdir(filepath);
199     ok(!ret, "_mkdir failed: %d\n", errno);
200     sprintf(filepath, "%swine_test\\a", tmppath);
201     f = fopen(filepath, "w");
202     ok(f != NULL, "fopen(%s) failed: %d\n", filepath, errno);
203     fclose(f);
204     sprintf(filepath, "%swine_test\\test", tmppath);
205     f = fopen(filepath, "w");
206     ok(f != NULL, "fopen(%s) failed: %d\n", filepath, errno);
207     fclose(f);
208 
209     memset(&startup, 0, sizeof(startup));
210     startup.cb = sizeof(startup);
211     CreateProcessA(NULL, cmdline, NULL, NULL, TRUE, CREATE_DEFAULT_ERROR_MODE|NORMAL_PRIORITY_CLASS, NULL, NULL, &startup, &proc);
212     winetest_wait_child_process(proc.hProcess);
213 
214     _unlink(filepath);
215     sprintf(filepath, "%swine_test\\a", tmppath);
216     _unlink(filepath);
217     sprintf(filepath, "%swine_test", tmppath);
218     _rmdir(filepath);
219 }
220 
221 START_TEST(data)
222 {
223     HMODULE hmsvcrt;
224     int arg_c;
225     char** arg_v;
226 
227     hmsvcrt = GetModuleHandleA("msvcrt.dll");
228     if (!hmsvcrt)
229         hmsvcrt = GetModuleHandleA("msvcrtd.dll");
230     if (hmsvcrt)
231     {
232         p_initterm=(void*)GetProcAddress(hmsvcrt, "_initterm");
233         p_get_pgmptr=(void*)GetProcAddress(hmsvcrt, "_get_pgmptr");
234         p___p___argc=(void*)GetProcAddress(hmsvcrt, "__p___argc");
235         p___p___argv=(void*)GetProcAddress(hmsvcrt, "__p___argv");
236     }
237 
238     arg_c = winetest_get_mainargs(&arg_v);
239     if(arg_c >= 3) {
240         test___getmainargs();
241         return;
242     }
243 
244     test_initterm();
245     test_initvar(hmsvcrt);
246     test_get_pgmptr();
247     test___getmainargs_parent(arg_v[0]);
248 }
249