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