ole32: Fix a few incorrect pointer/integer casts on 64-bit.
[wine] / dlls / userenv / tests / userenv.c
1 /*
2  * Unit test suite for userenv functions
3  *
4  * Copyright 2008 Google (Lei Zhang)
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 <stdio.h>
22 #include <stdlib.h>
23 #include <stdarg.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winnls.h"
28 #include "winreg.h"
29
30 #include "userenv.h"
31
32 #include "wine/test.h"
33
34 #define expect(EXPECTED,GOT) ok((GOT)==(EXPECTED), "Expected %d, got %d\n", (EXPECTED), (GOT))
35 #define expect_env(EXPECTED,GOT,VAR) ok((GOT)==(EXPECTED), "Expected %d, got %d for %s (%d)\n", (EXPECTED), (GOT), (VAR), j)
36 #define expect_gle(EXPECTED) ok(GetLastError() == (EXPECTED), "Expected %d, got %d\n", (EXPECTED), GetLastError())
37
38 struct profile_item
39 {
40     const char * name;
41     const int todo[4];
42 };
43
44 /* Helper function for retrieving environment variables */
45 static BOOL get_env(const WCHAR * env, const char * var, char ** result)
46 {
47     const WCHAR * p = env;
48     int envlen, varlen, buflen;
49     char buf[256];
50
51     if (!env || !var || !result) return FALSE;
52
53     varlen = strlen(var);
54     do
55     {
56         if (!WideCharToMultiByte( CP_ACP, 0, p, -1, buf, sizeof(buf), NULL, NULL )) buf[sizeof(buf)-1] = 0;
57         envlen = strlen(buf);
58         if (CompareStringA(GetThreadLocale(), NORM_IGNORECASE|LOCALE_USE_CP_ACP, buf, min(envlen, varlen), var, varlen) == CSTR_EQUAL)
59         {
60             if (buf[varlen] == '=')
61             {
62                 buflen = strlen(buf);
63                 *result = HeapAlloc(GetProcessHeap(), 0, buflen + 1);
64                 if (!*result) return FALSE;
65                 memcpy(*result, buf, buflen + 1);
66                 return TRUE;
67             }
68         }
69         while (*p) p++;
70         p++;
71     } while (*p);
72     return FALSE;
73 }
74
75 static void test_create_env(void)
76 {
77     BOOL r;
78     HANDLE htok;
79     WCHAR * env[4];
80     char * st;
81     int i, j;
82
83     static const struct profile_item common_vars[] = {
84         { "ComSpec", { 1, 1, 0, 0 } },
85         { "COMPUTERNAME", { 1, 1, 1, 1 } },
86         { "NUMBER_OF_PROCESSORS", { 1, 1, 0, 0 } },
87         { "OS", { 1, 1, 0, 0 } },
88         { "PROCESSOR_ARCHITECTURE", { 1, 1, 0, 0 } },
89         { "PROCESSOR_IDENTIFIER", { 1, 1, 0, 0 } },
90         { "PROCESSOR_LEVEL", { 1, 1, 0, 0 } },
91         { "PROCESSOR_REVISION", { 1, 1, 0, 0 } },
92         { "SystemDrive", { 1, 1, 0, 0 } },
93         { "SystemRoot", { 1, 1, 0, 0 } },
94         { "windir", { 1, 1, 0, 0 } }
95     };
96     static const struct profile_item common_post_nt4_vars[] = {
97         { "ALLUSERSPROFILE", { 1, 1, 0, 0 } },
98         { "TEMP", { 1, 1, 0, 0 } },
99         { "TMP", { 1, 1, 0, 0 } },
100         { "CommonProgramFiles", { 1, 1, 0, 0 } },
101         { "ProgramFiles", { 1, 1, 0, 0 } }
102     };
103     static const struct profile_item htok_vars[] = {
104         { "PATH", { 1, 1, 0, 0 } },
105         { "USERPROFILE", { 1, 1, 0, 0 } }
106     };
107
108     r = SetEnvironmentVariableA("WINE_XYZZY", "ZZYZX");
109     expect(TRUE, r);
110
111     if (0)
112     {
113         /* Crashes on NT4 */
114         r = CreateEnvironmentBlock(NULL, NULL, FALSE);
115         expect(FALSE, r);
116     }
117
118     r = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_DUPLICATE, &htok);
119     expect(TRUE, r);
120
121     if (0)
122     {
123         /* Crashes on NT4 */
124         r = CreateEnvironmentBlock(NULL, htok, FALSE);
125         expect(FALSE, r);
126     }
127
128     r = CreateEnvironmentBlock((LPVOID) &env[0], NULL, FALSE);
129     expect(TRUE, r);
130
131     r = CreateEnvironmentBlock((LPVOID) &env[1], htok, FALSE);
132     expect(TRUE, r);
133
134     r = CreateEnvironmentBlock((LPVOID) &env[2], NULL, TRUE);
135     expect(TRUE, r);
136
137     r = CreateEnvironmentBlock((LPVOID) &env[3], htok, TRUE);
138     expect(TRUE, r);
139
140     /* Test for common environment variables (NT4 and higher) */
141     for (i = 0; i < sizeof(common_vars)/sizeof(common_vars[0]); i++)
142     {
143         for (j = 0; j < 4; j++)
144         {
145             r = get_env(env[j], common_vars[i].name, &st);
146             if (common_vars[i].todo[j])
147                 todo_wine expect_env(TRUE, r, common_vars[i].name);
148             else
149                 expect_env(TRUE, r, common_vars[i].name);
150             if (r) HeapFree(GetProcessHeap(), 0, st);
151         }
152     }
153
154     /* Test for common environment variables (post NT4) */
155     if (!GetEnvironmentVariableA("ALLUSERSPROFILE", NULL, 0))
156     {
157         win_skip("Some environment variables are not present on NT4\n");
158     }
159     else
160     {
161         for (i = 0; i < sizeof(common_post_nt4_vars)/sizeof(common_post_nt4_vars[0]); i++)
162         {
163             for (j = 0; j < 4; j++)
164             {
165                 r = get_env(env[j], common_post_nt4_vars[i].name, &st);
166                 if (common_post_nt4_vars[i].todo[j])
167                     todo_wine expect_env(TRUE, r, common_post_nt4_vars[i].name);
168                 else
169                     expect_env(TRUE, r, common_post_nt4_vars[i].name);
170                 if (r) HeapFree(GetProcessHeap(), 0, st);
171             }
172         }
173     }
174
175     /* Test for environment variables with values that depends on htok */
176     for (i = 0; i < sizeof(htok_vars)/sizeof(htok_vars[0]); i++)
177     {
178         for (j = 0; j < 4; j++)
179         {
180             r = get_env(env[j], htok_vars[i].name, &st);
181             if (htok_vars[i].todo[j])
182                 todo_wine expect_env(TRUE, r, htok_vars[i].name);
183             else
184                 expect_env(TRUE, r, htok_vars[i].name);
185             if (r) HeapFree(GetProcessHeap(), 0, st);
186         }
187     }
188
189     r = get_env(env[0], "WINE_XYZZY", &st);
190     expect(FALSE, r);
191
192     r = get_env(env[1], "WINE_XYZZY", &st);
193     expect(FALSE, r);
194
195     r = get_env(env[2], "WINE_XYZZY", &st);
196     expect(TRUE, r);
197     if (r) HeapFree(GetProcessHeap(), 0, st);
198
199     r = get_env(env[3], "WINE_XYZZY", &st);
200     expect(TRUE, r);
201     if (r) HeapFree(GetProcessHeap(), 0, st);
202
203     for (i = 0; i < sizeof(env) / sizeof(env[0]); i++)
204     {
205         r = DestroyEnvironmentBlock(env[i]);
206         expect(TRUE, r);
207     }
208 }
209
210 static void test_get_profiles_dir(void)
211 {
212     static const char ProfileListA[] = "Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList";
213     static const char ProfilesDirectory[] = "ProfilesDirectory";
214     BOOL r;
215     DWORD cch, profiles_len;
216     LONG l;
217     HKEY key;
218     char *profiles_dir, *buf, small_buf[1];
219
220     l = RegOpenKeyExA(HKEY_LOCAL_MACHINE, ProfileListA, 0, KEY_READ, &key);
221     ok(!l, "RegOpenKeyExA failed: %d\n", GetLastError());
222
223     l = RegQueryValueExA(key, ProfilesDirectory, NULL, NULL, NULL, &cch);
224     if (l)
225     {
226         win_skip("No ProfilesDirectory value (NT4), skipping tests\n");
227         return;
228     }
229     buf = HeapAlloc(GetProcessHeap(), 0, cch);
230     RegQueryValueExA(key, ProfilesDirectory, NULL, NULL, (BYTE *)buf, &cch);
231     RegCloseKey(key);
232     profiles_len = ExpandEnvironmentStringsA(buf, NULL, 0);
233     profiles_dir = HeapAlloc(GetProcessHeap(), 0, profiles_len);
234     ExpandEnvironmentStringsA(buf, profiles_dir, profiles_len);
235     HeapFree(GetProcessHeap(), 0, buf);
236
237     SetLastError(0xdeadbeef);
238     r = GetProfilesDirectoryA(NULL, NULL);
239     expect(FALSE, r);
240     expect_gle(ERROR_INVALID_PARAMETER);
241     SetLastError(0xdeadbeef);
242     r = GetProfilesDirectoryA(NULL, &cch);
243     expect(FALSE, r);
244     expect_gle(ERROR_INVALID_PARAMETER);
245     SetLastError(0xdeadbeef);
246     cch = 1;
247     r = GetProfilesDirectoryA(small_buf, &cch);
248     expect(FALSE, r);
249     expect_gle(ERROR_INSUFFICIENT_BUFFER);
250     /* MSDN claims the returned character count includes the NULL terminator
251      * when the buffer is too small, but that's not in fact what gets returned.
252      */
253     ok(cch == profiles_len - 1, "expected %d, got %d\n", profiles_len - 1, cch);
254     /* Allocate one more character than the return value to prevent a buffer
255      * overrun.
256      */
257     buf = HeapAlloc(GetProcessHeap(), 0, cch + 1);
258     r = GetProfilesDirectoryA(buf, &cch);
259     /* Rather than a BOOL, the return value is also the number of characters
260      * stored in the buffer.
261      */
262     expect(profiles_len - 1, r);
263     ok(!strcmp(buf, profiles_dir), "expected %s, got %s\n", profiles_dir, buf);
264
265     HeapFree(GetProcessHeap(), 0, buf);
266     HeapFree(GetProcessHeap(), 0, profiles_dir);
267
268     SetLastError(0xdeadbeef);
269     r = GetProfilesDirectoryW(NULL, NULL);
270     expect(FALSE, r);
271     expect_gle(ERROR_INVALID_PARAMETER);
272
273     cch = 0;
274     SetLastError(0xdeadbeef);
275     r = GetProfilesDirectoryW(NULL, &cch);
276     expect(FALSE, r);
277     expect_gle(ERROR_INSUFFICIENT_BUFFER);
278     ok(cch, "expected cch > 0\n");
279
280     SetLastError(0xdeadbeef);
281     r = GetProfilesDirectoryW(NULL, &cch);
282     expect(FALSE, r);
283     expect_gle(ERROR_INSUFFICIENT_BUFFER);
284 }
285
286 static void test_get_user_profile_dir(void)
287 {
288     BOOL ret;
289     DWORD error, len;
290     HANDLE token;
291     char *dirA;
292     WCHAR *dirW;
293
294     if (!GetEnvironmentVariableA( "ALLUSERSPROFILE", NULL, 0 ))
295     {
296         win_skip("Skipping tests on NT4\n");
297         return;
298     }
299
300     ret = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &token );
301     ok(ret, "expected success %u\n", GetLastError());
302
303     SetLastError( 0xdeadbeef );
304     ret = GetUserProfileDirectoryA( NULL, NULL, NULL );
305     error = GetLastError();
306     ok(!ret, "expected failure\n");
307     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
308
309     SetLastError( 0xdeadbeef );
310     ret = GetUserProfileDirectoryA( token, NULL, NULL );
311     error = GetLastError();
312     ok(!ret, "expected failure\n");
313     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
314
315     dirA = HeapAlloc( GetProcessHeap(), 0, 32 );
316     SetLastError( 0xdeadbeef );
317     ret = GetUserProfileDirectoryA( token, dirA, NULL );
318     error = GetLastError();
319     ok(!ret, "expected failure\n");
320     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
321     HeapFree( GetProcessHeap(), 0, dirA );
322
323     len = 0;
324     SetLastError( 0xdeadbeef );
325     ret = GetUserProfileDirectoryA( token, NULL, &len );
326     error = GetLastError();
327     ok(!ret, "expected failure\n");
328     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
329     ok(!len, "expected 0, got %u\n", len);
330
331     len = 0;
332     dirA = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 32 );
333     SetLastError( 0xdeadbeef );
334     ret = GetUserProfileDirectoryA( token, dirA, &len );
335     error = GetLastError();
336     ok(!ret, "expected failure\n");
337     ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", error);
338     ok(len, "expected len > 0\n");
339     HeapFree( GetProcessHeap(), 0, dirA );
340
341     dirA = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len );
342     SetLastError( 0xdeadbeef );
343     ret = GetUserProfileDirectoryA( token, dirA, &len );
344     ok(ret, "expected success %u\n", GetLastError());
345     ok(len, "expected len > 0\n");
346     ok(lstrlenA( dirA ) == len - 1, "length mismatch %d != %d - 1\n", lstrlenA( dirA ), len );
347     trace("%s\n", dirA);
348     HeapFree( GetProcessHeap(), 0, dirA );
349
350     SetLastError( 0xdeadbeef );
351     ret = GetUserProfileDirectoryW( NULL, NULL, NULL );
352     error = GetLastError();
353     ok(!ret, "expected failure\n");
354     todo_wine ok(error == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", error);
355
356     SetLastError( 0xdeadbeef );
357     ret = GetUserProfileDirectoryW( token, NULL, NULL );
358     error = GetLastError();
359     ok(!ret, "expected failure\n");
360     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
361
362     dirW = HeapAlloc( GetProcessHeap(), 0, 32 );
363     SetLastError( 0xdeadbeef );
364     ret = GetUserProfileDirectoryW( token, dirW, NULL );
365     error = GetLastError();
366     ok(!ret, "expected failure\n");
367     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
368     HeapFree( GetProcessHeap(), 0, dirW );
369
370     len = 0;
371     SetLastError( 0xdeadbeef );
372     ret = GetUserProfileDirectoryW( token, NULL, &len );
373     error = GetLastError();
374     ok(!ret, "expected failure\n");
375     ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", error);
376     ok(len, "expected len > 0\n");
377
378     dirW = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR) );
379     SetLastError( 0xdeadbeef );
380     ret = GetUserProfileDirectoryW( token, dirW, &len );
381     ok(ret, "expected success %u\n", GetLastError());
382     ok(len, "expected len > 0\n");
383     ok(lstrlenW( dirW ) == len - 1, "length mismatch %d != %d - 1\n", lstrlenW( dirW ), len );
384     HeapFree( GetProcessHeap(), 0, dirW );
385
386     CloseHandle( token );
387 }
388
389 START_TEST(userenv)
390 {
391     test_create_env();
392     test_get_profiles_dir();
393     test_get_user_profile_dir();
394 }