1 /*
2  * Unit test suite for environment functions.
3  *
4  * Copyright 2002 Dmitry Timoshkov
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 static CHAR string[MAX_PATH];
24 #define ok_w(res, format, szString) \
25 \
26     WideCharToMultiByte(CP_ACP, 0, szString, -1, string, MAX_PATH, NULL, NULL); \
27     ok(res, format, string);
28 
29 static BOOL (WINAPI *pGetComputerNameExA)(COMPUTER_NAME_FORMAT,LPSTR,LPDWORD);
30 static BOOL (WINAPI *pGetComputerNameExW)(COMPUTER_NAME_FORMAT,LPWSTR,LPDWORD);
31 static BOOL (WINAPI *pOpenProcessToken)(HANDLE,DWORD,PHANDLE);
32 static BOOL (WINAPI *pGetUserProfileDirectoryA)(HANDLE,LPSTR,LPDWORD);
33 
34 static void init_functionpointers(void)
35 {
36     HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
37     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
38     HMODULE huserenv = LoadLibraryA("userenv.dll");
39 
40     pGetComputerNameExA = (void *)GetProcAddress(hkernel32, "GetComputerNameExA");
41     pGetComputerNameExW = (void *)GetProcAddress(hkernel32, "GetComputerNameExW");
42     pOpenProcessToken = (void *)GetProcAddress(hadvapi32, "OpenProcessToken");
43     pGetUserProfileDirectoryA = (void *)GetProcAddress(huserenv,
44                                                        "GetUserProfileDirectoryA");
45 }
46 
47 static void test_Predefined(void)
48 {
49     char Data[1024];
50     DWORD DataSize;
51     char Env[sizeof(Data)];
52     DWORD EnvSize;
53     HANDLE Token;
54     BOOL NoErr;
55 
56     /*
57      * Check value of %USERPROFILE%, should be same as GetUserProfileDirectory()
58      * If this fails, your test environment is probably not set up
59      */
60     if (pOpenProcessToken == NULL || pGetUserProfileDirectoryA == NULL)
61     {
62         skip("Skipping USERPROFILE check\n");
63         return;
64     }
65     NoErr = pOpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token);
66     ok(NoErr, "Failed to open token, error %u\n", GetLastError());
67     DataSize = sizeof(Data);
68     NoErr = pGetUserProfileDirectoryA(Token, Data, &DataSize);
69     ok(NoErr, "Failed to get user profile dir, error %u\n", GetLastError());
70     if (NoErr)
71     {
72         EnvSize = GetEnvironmentVariableA("USERPROFILE", Env, sizeof(Env));
73         ok(EnvSize != 0 && EnvSize <= sizeof(Env),
74            "Failed to retrieve environment variable USERPROFILE, error %u\n",
75            GetLastError());
76         ok(strcmp(Data, Env) == 0,
77            "USERPROFILE env var %s doesn't match GetUserProfileDirectory %s\n",
78            Env, Data);
79     }
80     else
81         skip("Skipping USERPROFILE check, can't get user profile dir\n");
82     NoErr = CloseHandle(Token);
83     ok(NoErr, "Failed to close token, error %u\n", GetLastError());
84 }
85 
86 static void test_GetSetEnvironmentVariableA(void)
87 {
88     char buf[256];
89     BOOL ret;
90     DWORD ret_size;
91     static const char name[] = "SomeWildName";
92     static const char name_cased[] = "sOMEwILDnAME";
93     static const char value[] = "SomeWildValue";
94 
95     ret = SetEnvironmentVariableA(name, value);
96     ok(ret == TRUE,
97        "unexpected error in SetEnvironmentVariableA, GetLastError=%d\n",
98        GetLastError());
99 
100     /* Try to retrieve the environment variable we just set */
101     ret_size = GetEnvironmentVariableA(name, NULL, 0);
102     ok(ret_size == strlen(value) + 1,
103        "should return length with terminating 0 ret_size=%d\n", ret_size);
104 
105     lstrcpyA(buf, "foo");
106     ret_size = GetEnvironmentVariableA(name, buf, lstrlenA(value));
107     ok(lstrcmpA(buf, "foo") == 0, "should not touch the buffer\n");
108     ok(ret_size == strlen(value) + 1,
109        "should return length with terminating 0 ret_size=%d\n", ret_size);
110 
111     lstrcpyA(buf, "foo");
112     ret_size = GetEnvironmentVariableA(name, buf, lstrlenA(value) + 1);
113     ok(lstrcmpA(buf, value) == 0, "should touch the buffer\n");
114     ok(ret_size == strlen(value),
115        "should return length without terminating 0 ret_size=%d\n", ret_size);
116 
117     lstrcpyA(buf, "foo");
118     ret_size = GetEnvironmentVariableA(name_cased, buf, lstrlenA(value) + 1);
119     ok(lstrcmpA(buf, value) == 0, "should touch the buffer\n");
120     ok(ret_size == strlen(value),
121        "should return length without terminating 0 ret_size=%d\n", ret_size);
122 
123     /* Remove that environment variable */
124     ret = SetEnvironmentVariableA(name_cased, NULL);
125     ok(ret == TRUE, "should erase existing variable\n");
126 
127     lstrcpyA(buf, "foo");
128     ret_size = GetEnvironmentVariableA(name, buf, lstrlenA(value) + 1);
129     ok(lstrcmpA(buf, "foo") == 0, "should not touch the buffer\n");
130     ok(ret_size == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND,
131        "should not find variable but ret_size=%d GetLastError=%d\n",
132        ret_size, GetLastError());
133 
134     /* Check behavior of SetEnvironmentVariableA(name, "") */
135     ret = SetEnvironmentVariableA(name, value);
136     ok(ret == TRUE,
137        "unexpected error in SetEnvironmentVariableA, GetLastError=%d\n",
138        GetLastError());
139 
140     lstrcpyA(buf, "foo");
141     ret_size = GetEnvironmentVariableA(name_cased, buf, lstrlenA(value) + 1);
142     ok(lstrcmpA(buf, value) == 0, "should touch the buffer\n");
143     ok(ret_size == strlen(value),
144        "should return length without terminating 0 ret_size=%d\n", ret_size);
145 
146     ret = SetEnvironmentVariableA(name_cased, "");
147     ok(ret == TRUE,
148        "should not fail with empty value but GetLastError=%d\n", GetLastError());
149 
150     lstrcpyA(buf, "foo");
151     SetLastError(0);
152     ret_size = GetEnvironmentVariableA(name, buf, lstrlenA(value) + 1);
153     ok(ret_size == 0 &&
154        ((GetLastError() == 0 && lstrcmpA(buf, "") == 0) ||
155         (GetLastError() == ERROR_ENVVAR_NOT_FOUND)),
156        "%s should be set to \"\" (NT) or removed (Win9x) but ret_size=%d GetLastError=%d and buf=%s\n",
157        name, ret_size, GetLastError(), buf);
158 
159     /* Test the limits */
160     ret_size = GetEnvironmentVariableA(NULL, NULL, 0);
161     ok(ret_size == 0 && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_ENVVAR_NOT_FOUND),
162        "should not find variable but ret_size=%d GetLastError=%d\n",
163        ret_size, GetLastError());
164 
165     ret_size = GetEnvironmentVariableA(NULL, buf, lstrlenA(value) + 1);
166     ok(ret_size == 0 && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_ENVVAR_NOT_FOUND),
167        "should not find variable but ret_size=%d GetLastError=%d\n",
168        ret_size, GetLastError());
169 
170     ret_size = GetEnvironmentVariableA("", buf, lstrlenA(value) + 1);
171     ok(ret_size == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND,
172        "should not find variable but ret_size=%d GetLastError=%d\n",
173        ret_size, GetLastError());
174 }
175 
176 static void test_GetSetEnvironmentVariableW(void)
177 {
178     WCHAR buf[256];
179     BOOL ret;
180     DWORD ret_size;
181     static const WCHAR name[] = {'S','o','m','e','W','i','l','d','N','a','m','e',0};
182     static const WCHAR value[] = {'S','o','m','e','W','i','l','d','V','a','l','u','e',0};
183     static const WCHAR name_cased[] = {'s','O','M','E','w','I','L','D','n','A','M','E',0};
184     static const WCHAR empty_strW[] = { 0 };
185     static const WCHAR fooW[] = {'f','o','o',0};
186 
187     ret = SetEnvironmentVariableW(name, value);
188     if (ret == FALSE && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
189     {
190         /* Must be Win9x which doesn't support the Unicode functions */
191         win_skip("SetEnvironmentVariableW is not implemented\n");
192         return;
193     }
194     ok(ret == TRUE,
195        "unexpected error in SetEnvironmentVariableW, GetLastError=%d\n",
196        GetLastError());
197 
198     /* Try to retrieve the environment variable we just set */
199     ret_size = GetEnvironmentVariableW(name, NULL, 0);
200     ok(ret_size == lstrlenW(value) + 1,
201        "should return length with terminating 0 ret_size=%d\n",
202        ret_size);
203 
204     lstrcpyW(buf, fooW);
205     ret_size = GetEnvironmentVariableW(name, buf, lstrlenW(value));
206     ok_w(lstrcmpW(buf, fooW) == 0 ||
207          lstrlenW(buf) == 0, /* Vista */
208          "Expected untouched or empty buffer, got \"%s\"\n", buf);
209 
210     ok(ret_size == lstrlenW(value) + 1,
211        "should return length with terminating 0 ret_size=%d\n", ret_size);
212 
213     lstrcpyW(buf, fooW);
214     ret_size = GetEnvironmentVariableW(name, buf, lstrlenW(value) + 1);
215     ok(lstrcmpW(buf, value) == 0, "should touch the buffer\n");
216     ok(ret_size == lstrlenW(value),
217        "should return length without terminating 0 ret_size=%d\n", ret_size);
218 
219     lstrcpyW(buf, fooW);
220     ret_size = GetEnvironmentVariableW(name_cased, buf, lstrlenW(value) + 1);
221     ok(lstrcmpW(buf, value) == 0, "should touch the buffer\n");
222     ok(ret_size == lstrlenW(value),
223        "should return length without terminating 0 ret_size=%d\n", ret_size);
224 
225     /* Remove that environment variable */
226     ret = SetEnvironmentVariableW(name_cased, NULL);
227     ok(ret == TRUE, "should erase existing variable\n");
228 
229     lstrcpyW(buf, fooW);
230     ret_size = GetEnvironmentVariableW(name, buf, lstrlenW(value) + 1);
231     ok(lstrcmpW(buf, fooW) == 0, "should not touch the buffer\n");
232     ok(ret_size == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND,
233        "should not find variable but ret_size=%d GetLastError=%d\n",
234        ret_size, GetLastError());
235 
236     /* Check behavior of SetEnvironmentVariableW(name, "") */
237     ret = SetEnvironmentVariableW(name, value);
238     ok(ret == TRUE,
239        "unexpected error in SetEnvironmentVariableW, GetLastError=%d\n",
240        GetLastError());
241 
242     lstrcpyW(buf, fooW);
243     ret_size = GetEnvironmentVariableW(name, buf, lstrlenW(value) + 1);
244     ok(lstrcmpW(buf, value) == 0, "should touch the buffer\n");
245     ok(ret_size == lstrlenW(value),
246        "should return length without terminating 0 ret_size=%d\n", ret_size);
247 
248     ret = SetEnvironmentVariableW(name_cased, empty_strW);
249     ok(ret == TRUE, "should not fail with empty value but GetLastError=%d\n", GetLastError());
250 
251     lstrcpyW(buf, fooW);
252     ret_size = GetEnvironmentVariableW(name, buf, lstrlenW(value) + 1);
253     ok(ret_size == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND,
254        "should not find variable but ret_size=%d GetLastError=%d\n",
255        ret_size, GetLastError());
256     ok(lstrcmpW(buf, empty_strW) == 0, "should copy an empty string\n");
257 
258     /* Test the limits */
259     ret_size = GetEnvironmentVariableW(NULL, NULL, 0);
260     ok(ret_size == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND,
261        "should not find variable but ret_size=%d GetLastError=%d\n",
262        ret_size, GetLastError());
263 
264     if (0) /* Both tests crash on Vista */
265     {
266         ret_size = GetEnvironmentVariableW(NULL, buf, lstrlenW(value) + 1);
267         ok(ret_size == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND,
268            "should not find variable but ret_size=%d GetLastError=%d\n",
269            ret_size, GetLastError());
270 
271         ret = SetEnvironmentVariableW(NULL, NULL);
272         ok(ret == FALSE && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_ENVVAR_NOT_FOUND),
273            "should fail with NULL, NULL but ret=%d and GetLastError=%d\n",
274            ret, GetLastError());
275     }
276 }
277 
278 static void test_ExpandEnvironmentStringsA(void)
279 {
280     const char* value="Long long value";
281     const char* not_an_env_var="%NotAnEnvVar%";
282     char buf[256], buf1[256], buf2[0x8000];
283     DWORD ret_size, ret_size1;
284 
285     SetEnvironmentVariableA("EnvVar", value);
286 
287     ret_size = ExpandEnvironmentStringsA(NULL, buf1, sizeof(buf1));
288     ok(ret_size == 1 || ret_size == 0 /* Win9x */ || ret_size == 2 /* NT4 */,
289        "ExpandEnvironmentStrings returned %d\n", ret_size);
290 
291     /* Try to get the required buffer size 'the natural way' */
292     strcpy(buf, "%EnvVar%");
293     ret_size = ExpandEnvironmentStringsA(buf, NULL, 0);
294     ok(ret_size == strlen(value)+1 || /* win98 */
295        ret_size == (strlen(value)+1)*2 || /* NT4 */
296        ret_size == strlen(value)+2 || /* win2k, XP, win2k3 */
297        ret_size == 0 /* Win95 */,
298        "ExpandEnvironmentStrings returned %d instead of %d, %d or %d\n",
299        ret_size, lstrlenA(value)+1, lstrlenA(value)+2, 0);
300 
301     /* Again, side-stepping the Win95 bug */
302     ret_size = ExpandEnvironmentStringsA(buf, buf1, 0);
303     /* v5.1.2600.2945 (XP SP2) returns len + 2 here! */
304     ok(ret_size == strlen(value)+1 || ret_size == strlen(value)+2 ||
305        ret_size == (strlen(value)+1)*2 /* NT4 */,
306        "ExpandEnvironmentStrings returned %d instead of %d\n",
307        ret_size, lstrlenA(value)+1);
308 
309     /* Try with a buffer that's too small */
310     ret_size = ExpandEnvironmentStringsA(buf, buf1, 12);
311     /* v5.1.2600.2945 (XP SP2) returns len + 2 here! */
312     ok(ret_size == strlen(value)+1 || ret_size == strlen(value)+2 ||
313        ret_size == (strlen(value)+1)*2 /* NT4 */,
314        "ExpandEnvironmentStrings returned %d instead of %d\n",
315        ret_size, lstrlenA(value)+1);
316 
317     /* Try with a buffer of just the right size */
318     /* v5.1.2600.2945 (XP SP2) needs and returns len + 2 here! */
319     ret_size = ExpandEnvironmentStringsA(buf, buf1, ret_size);
320     ok(ret_size == strlen(value)+1 || ret_size == strlen(value)+2 ||
321        ret_size == (strlen(value)+1)*2 /* NT4 */,
322        "ExpandEnvironmentStrings returned %d instead of %d\n",
323        ret_size, lstrlenA(value)+1);
324     ok(!strcmp(buf1, value), "ExpandEnvironmentStrings returned [%s]\n", buf1);
325 
326     /* Try with an unset environment variable */
327     strcpy(buf, not_an_env_var);
328     ret_size = ExpandEnvironmentStringsA(buf, buf1, sizeof(buf1));
329     ok(ret_size == strlen(not_an_env_var)+1 ||
330        ret_size == (strlen(not_an_env_var)+1)*2 /* NT4 */,
331        "ExpandEnvironmentStrings returned %d instead of %d\n", ret_size, lstrlenA(not_an_env_var)+1);
332     ok(!strcmp(buf1, not_an_env_var), "ExpandEnvironmentStrings returned [%s]\n", buf1);
333 
334     /* test a large destination size */
335     strcpy(buf, "12345");
336     ret_size = ExpandEnvironmentStringsA(buf, buf2, sizeof(buf2));
337     ok(!strcmp(buf, buf2), "ExpandEnvironmentStrings failed %s vs %s. ret_size = %d\n", buf, buf2, ret_size);
338 
339     ret_size1 = GetWindowsDirectoryA(buf1,256);
340     ok ((ret_size1 >0) && (ret_size1<256), "GetWindowsDirectory Failed\n");
341     ret_size = ExpandEnvironmentStringsA("%SystemRoot%",buf,sizeof(buf));
342     if (ERROR_ENVVAR_NOT_FOUND != GetLastError())
343     {
344         ok(!strcmp(buf, buf1), "ExpandEnvironmentStrings failed %s vs %s. ret_size = %d\n", buf, buf1, ret_size);
345     }
346 
347     /* Try with a variable that references another */
348     SetEnvironmentVariableA("IndirectVar", "Foo%EnvVar%Bar");
349     strcpy(buf, "Indirect-%IndirectVar%-Indirect");
350     strcpy(buf2, "Indirect-Foo%EnvVar%Bar-Indirect");
351     ret_size = ExpandEnvironmentStringsA(buf, buf1, sizeof(buf1));
352     ok(ret_size == strlen(buf2)+1 ||
353        ret_size == (strlen(buf2)+1)*2 /* NT4 */,
354        "ExpandEnvironmentStrings returned %d instead of %d\n", ret_size, lstrlenA(buf2)+1);
355     ok(!strcmp(buf1, buf2), "ExpandEnvironmentStrings returned [%s]\n", buf1);
356     SetEnvironmentVariableA("IndirectVar", NULL);
357 
358     SetEnvironmentVariableA("EnvVar", NULL);
359 }
360 
361 static void test_GetComputerName(void)
362 {
363     DWORD size;
364     BOOL ret;
365     LPSTR name;
366     LPWSTR nameW;
367     DWORD error;
368     int name_len;
369 
370     size = 0;
371     ret = GetComputerNameA((LPSTR)0xdeadbeef, &size);
372     error = GetLastError();
373     ok(!ret && error == ERROR_BUFFER_OVERFLOW, "GetComputerNameA should have failed with ERROR_BUFFER_OVERFLOW instead of %d\n", error);
374 
375     /* Only Vista returns the computer name length as documented in the MSDN */
376     if (size != 0)
377     {
378         size++; /* nul terminating character */
379         name = HeapAlloc(GetProcessHeap(), 0, size * sizeof(name[0]));
380         ok(name != NULL, "HeapAlloc failed with error %d\n", GetLastError());
381         ret = GetComputerNameA(name, &size);
382         ok(ret, "GetComputerNameA failed with error %d\n", GetLastError());
383         HeapFree(GetProcessHeap(), 0, name);
384     }
385 
386     size = MAX_COMPUTERNAME_LENGTH + 1;
387     name = HeapAlloc(GetProcessHeap(), 0, size * sizeof(name[0]));
388     ok(name != NULL, "HeapAlloc failed with error %d\n", GetLastError());
389     ret = GetComputerNameA(name, &size);
390     ok(ret, "GetComputerNameA failed with error %d\n", GetLastError());
391     trace("computer name is \"%s\"\n", name);
392     name_len = strlen(name);
393     ok(size == name_len, "size should be same as length, name_len=%d, size=%d\n", name_len, size);
394     HeapFree(GetProcessHeap(), 0, name);
395 
396     size = 0;
397     SetLastError(0xdeadbeef);
398     ret = GetComputerNameW((LPWSTR)0xdeadbeef, &size);
399     error = GetLastError();
400     if (error == ERROR_CALL_NOT_IMPLEMENTED)
401         win_skip("GetComputerNameW is not implemented\n");
402     else
403     {
404         ok(!ret && error == ERROR_BUFFER_OVERFLOW, "GetComputerNameW should have failed with ERROR_BUFFER_OVERFLOW instead of %d\n", error);
405         size++; /* nul terminating character */
406         nameW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(nameW[0]));
407         ok(nameW != NULL, "HeapAlloc failed with error %d\n", GetLastError());
408         ret = GetComputerNameW(nameW, &size);
409         ok(ret, "GetComputerNameW failed with error %d\n", GetLastError());
410         HeapFree(GetProcessHeap(), 0, nameW);
411     }
412 }
413 
414 static void test_GetComputerNameExA(void)
415 {
416     DWORD size;
417     BOOL ret;
418     LPSTR name;
419     DWORD error;
420 
421     static const int MAX_COMP_NAME = 32767;
422 
423     if (!pGetComputerNameExA)
424     {
425         win_skip("GetComputerNameExA function not implemented\n");
426         return;
427     }
428 
429     size = 0;
430     ret = pGetComputerNameExA(ComputerNameDnsDomain, (LPSTR)0xdeadbeef, &size);
431     error = GetLastError();
432     ok(ret == 0, "Expected 0, got %d\n", ret);
433     ok(error == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", error);
434 
435     /* size is not set in win2k */
436     if (size == 0)
437     {
438         win_skip("Win2k doesn't set the size\n");
439         size = MAX_COMP_NAME;
440     }
441     name = HeapAlloc(GetProcessHeap(), 0, size * sizeof(name[0]));
442     ok(name != NULL, "HeapAlloc failed with error %d\n", GetLastError());
443     ret = pGetComputerNameExA(ComputerNameDnsDomain, name, &size);
444     ok(ret, "GetComputerNameExA(ComputerNameDnsDomain) failed with error %d\n", GetLastError());
445     trace("domain name is \"%s\"\n", name);
446     HeapFree(GetProcessHeap(), 0, name);
447 
448     size = 0;
449     ret = pGetComputerNameExA(ComputerNameDnsFullyQualified, (LPSTR)0xdeadbeef, &size);
450     error = GetLastError();
451     ok(ret == 0, "Expected 0, got %d\n", ret);
452     ok(error == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", error);
453 
454     /* size is not set in win2k */
455     if (size == 0)
456         size = MAX_COMP_NAME;
457     name = HeapAlloc(GetProcessHeap(), 0, size * sizeof(name[0]));
458     ok(name != NULL, "HeapAlloc failed with error %d\n", GetLastError());
459     ret = pGetComputerNameExA(ComputerNameDnsFullyQualified, name, &size);
460     ok(ret, "GetComputerNameExA(ComputerNameDnsFullyQualified) failed with error %d\n", GetLastError());
461     trace("fully qualified hostname is \"%s\"\n", name);
462     HeapFree(GetProcessHeap(), 0, name);
463 
464     size = 0;
465     ret = pGetComputerNameExA(ComputerNameDnsHostname, (LPSTR)0xdeadbeef, &size);
466     error = GetLastError();
467     ok(ret == 0, "Expected 0, got %d\n", ret);
468     ok(error == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", error);
469 
470     /* size is not set in win2k */
471     if (size == 0)
472         size = MAX_COMP_NAME;
473     name = HeapAlloc(GetProcessHeap(), 0, size * sizeof(name[0]));
474     ok(name != NULL, "HeapAlloc failed with error %d\n", GetLastError());
475     ret = pGetComputerNameExA(ComputerNameDnsHostname, name, &size);
476     ok(ret, "GetComputerNameExA(ComputerNameDnsHostname) failed with error %d\n", GetLastError());
477     trace("hostname is \"%s\"\n", name);
478     HeapFree(GetProcessHeap(), 0, name);
479 
480     size = 0;
481     ret = pGetComputerNameExA(ComputerNameNetBIOS, (LPSTR)0xdeadbeef, &size);
482     error = GetLastError();
483     ok(ret == 0, "Expected 0, got %d\n", ret);
484     ok(error == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", error);
485 
486     /* size is not set in win2k */
487     if (size == 0)
488         size = MAX_COMP_NAME;
489     name = HeapAlloc(GetProcessHeap(), 0, size * sizeof(name[0]));
490     ok(name != NULL, "HeapAlloc failed with error %d\n", GetLastError());
491     ret = pGetComputerNameExA(ComputerNameNetBIOS, name, &size);
492     ok(ret, "GetComputerNameExA(ComputerNameNetBIOS) failed with error %d\n", GetLastError());
493     trace("NetBIOS name is \"%s\"\n", name);
494     HeapFree(GetProcessHeap(), 0, name);
495 }
496 
497 static void test_GetComputerNameExW(void)
498 {
499     DWORD size;
500     BOOL ret;
501     LPWSTR nameW;
502     DWORD error;
503 
504     if (!pGetComputerNameExW)
505     {
506         win_skip("GetComputerNameExW function not implemented\n");
507         return;
508     }
509 
510     size = 0;
511     ret = pGetComputerNameExW(ComputerNameDnsDomain, (LPWSTR)0xdeadbeef, &size);
512     error = GetLastError();
513     ok(!ret && error == ERROR_MORE_DATA, "GetComputerNameExW should have failed with ERROR_MORE_DATA instead of %d\n", error);
514     nameW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(nameW[0]));
515     ok(nameW != NULL, "HeapAlloc failed with error %d\n", GetLastError());
516     ret = pGetComputerNameExW(ComputerNameDnsDomain, nameW, &size);
517     ok(ret, "GetComputerNameExW(ComputerNameDnsDomain) failed with error %d\n", GetLastError());
518     HeapFree(GetProcessHeap(), 0, nameW);
519 
520     size = 0;
521     ret = pGetComputerNameExW(ComputerNameDnsFullyQualified, (LPWSTR)0xdeadbeef, &size);
522     error = GetLastError();
523     ok(!ret && error == ERROR_MORE_DATA, "GetComputerNameExW should have failed with ERROR_MORE_DATA instead of %d\n", error);
524     nameW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(nameW[0]));
525     ok(nameW != NULL, "HeapAlloc failed with error %d\n", GetLastError());
526     ret = pGetComputerNameExW(ComputerNameDnsFullyQualified, nameW, &size);
527     ok(ret, "GetComputerNameExW(ComputerNameDnsFullyQualified) failed with error %d\n", GetLastError());
528     HeapFree(GetProcessHeap(), 0, nameW);
529 
530     size = 0;
531     ret = pGetComputerNameExW(ComputerNameDnsHostname, (LPWSTR)0xdeadbeef, &size);
532     error = GetLastError();
533     ok(!ret && error == ERROR_MORE_DATA, "GetComputerNameExW should have failed with ERROR_MORE_DATA instead of %d\n", error);
534     nameW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(nameW[0]));
535     ok(nameW != NULL, "HeapAlloc failed with error %d\n", GetLastError());
536     ret = pGetComputerNameExW(ComputerNameDnsHostname, nameW, &size);
537     ok(ret, "GetComputerNameExW(ComputerNameDnsHostname) failed with error %d\n", GetLastError());
538     HeapFree(GetProcessHeap(), 0, nameW);
539 
540     size = 0;
541     ret = pGetComputerNameExW(ComputerNameNetBIOS, (LPWSTR)0xdeadbeef, &size);
542     error = GetLastError();
543     ok(!ret && error == ERROR_MORE_DATA, "GetComputerNameExW should have failed with ERROR_MORE_DATA instead of %d\n", error);
544     nameW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(nameW[0]));
545     ok(nameW != NULL, "HeapAlloc failed with error %d\n", GetLastError());
546     ret = pGetComputerNameExW(ComputerNameNetBIOS, nameW, &size);
547     ok(ret, "GetComputerNameExW(ComputerNameNetBIOS) failed with error %d\n", GetLastError());
548     HeapFree(GetProcessHeap(), 0, nameW);
549 }
550 
551 START_TEST(environ)
552 {
553     init_functionpointers();
554 
555     test_Predefined();
556     test_GetSetEnvironmentVariableA();
557     test_GetSetEnvironmentVariableW();
558     test_ExpandEnvironmentStringsA();
559     test_GetComputerName();
560     test_GetComputerNameExA();
561     test_GetComputerNameExW();
562 }
563