Remove some stuff added for old GCC versions.
[reactos.git] / reactos / dll / win32 / userenv / environment.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2004 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS system libraries
22 * FILE: dll/win32/userenv/environment.c
23 * PURPOSE: User environment functions
24 * PROGRAMMER: Eric Kohl
25 */
26
27 #include "precomp.h"
28
29 #define NDEBUG
30 #include <debug.h>
31
32
33 static
34 BOOL
35 SetUserEnvironmentVariable(LPVOID *Environment,
36 LPWSTR lpName,
37 LPWSTR lpValue,
38 BOOL bExpand)
39 {
40 WCHAR ShortName[MAX_PATH];
41 UNICODE_STRING Name;
42 UNICODE_STRING SrcValue;
43 UNICODE_STRING DstValue;
44 ULONG Length;
45 NTSTATUS Status;
46 PVOID Buffer = NULL;
47
48 if (bExpand)
49 {
50 RtlInitUnicodeString(&SrcValue,
51 lpValue);
52
53 Length = 2 * MAX_PATH * sizeof(WCHAR);
54
55 DstValue.Length = 0;
56 DstValue.MaximumLength = Length;
57 DstValue.Buffer = Buffer = LocalAlloc(LPTR,
58 Length);
59 if (DstValue.Buffer == NULL)
60 {
61 DPRINT1("LocalAlloc() failed\n");
62 return FALSE;
63 }
64
65 Status = RtlExpandEnvironmentStrings_U((PWSTR)*Environment,
66 &SrcValue,
67 &DstValue,
68 &Length);
69 if (!NT_SUCCESS(Status))
70 {
71 DPRINT1("RtlExpandEnvironmentStrings_U() failed (Status %lx)\n", Status);
72 DPRINT1("Length %lu\n", Length);
73 if (Buffer)
74 LocalFree(Buffer);
75 return FALSE;
76 }
77 }
78 else
79 {
80 RtlInitUnicodeString(&DstValue,
81 lpValue);
82 }
83
84 if (!_wcsicmp(lpName, L"temp") || !_wcsicmp(lpName, L"tmp"))
85 {
86 if (!GetShortPathNameW(DstValue.Buffer, ShortName, MAX_PATH))
87 {
88 DPRINT1("GetShortPathNameW() failed for %S (Error %lu)\n", DstValue.Buffer, GetLastError());
89 if (Buffer)
90 LocalFree(Buffer);
91 return FALSE;
92 }
93
94 DPRINT("Buffer: %S\n", ShortName);
95 RtlInitUnicodeString(&DstValue,
96 ShortName);
97 }
98
99 RtlInitUnicodeString(&Name,
100 lpName);
101
102 DPRINT("Value: %wZ\n", &DstValue);
103
104 Status = RtlSetEnvironmentVariable((PWSTR*)Environment,
105 &Name,
106 &DstValue);
107
108 if (Buffer)
109 LocalFree(Buffer);
110
111 if (!NT_SUCCESS(Status))
112 {
113 DPRINT1("RtlSetEnvironmentVariable() failed (Status %lx)\n", Status);
114 return FALSE;
115 }
116
117 return TRUE;
118 }
119
120
121 static
122 BOOL
123 AppendUserEnvironmentVariable(LPVOID *Environment,
124 LPWSTR lpName,
125 LPWSTR lpValue)
126 {
127 UNICODE_STRING Name;
128 UNICODE_STRING Value;
129 NTSTATUS Status;
130
131 RtlInitUnicodeString(&Name,
132 lpName);
133
134 Value.Length = 0;
135 Value.MaximumLength = 1024 * sizeof(WCHAR);
136 Value.Buffer = LocalAlloc(LPTR,
137 1024 * sizeof(WCHAR));
138 if (Value.Buffer == NULL)
139 {
140 return FALSE;
141 }
142 Value.Buffer[0] = UNICODE_NULL;
143
144 Status = RtlQueryEnvironmentVariable_U((PWSTR)*Environment,
145 &Name,
146 &Value);
147 if (NT_SUCCESS(Status))
148 {
149 RtlAppendUnicodeToString(&Value,
150 L";");
151 }
152
153 RtlAppendUnicodeToString(&Value,
154 lpValue);
155
156 Status = RtlSetEnvironmentVariable((PWSTR*)Environment,
157 &Name,
158 &Value);
159 LocalFree(Value.Buffer);
160 if (!NT_SUCCESS(Status))
161 {
162 DPRINT1("RtlSetEnvironmentVariable() failed (Status %lx)\n", Status);
163 return FALSE;
164 }
165
166 return TRUE;
167 }
168
169
170 static
171 HKEY
172 GetCurrentUserKey(HANDLE hToken)
173 {
174 UNICODE_STRING SidString;
175 HKEY hKey;
176 LONG Error;
177
178 if (!GetUserSidFromToken(hToken,
179 &SidString))
180 {
181 DPRINT1("GetUserSidFromToken() failed\n");
182 return NULL;
183 }
184
185 Error = RegOpenKeyExW(HKEY_USERS,
186 SidString.Buffer,
187 0,
188 MAXIMUM_ALLOWED,
189 &hKey);
190 if (Error != ERROR_SUCCESS)
191 {
192 DPRINT1("RegOpenKeyExW() failed (Error %ld)\n", Error);
193 RtlFreeUnicodeString(&SidString);
194 SetLastError((DWORD)Error);
195 return NULL;
196 }
197
198 RtlFreeUnicodeString(&SidString);
199
200 return hKey;
201 }
202
203
204 static
205 BOOL
206 SetUserEnvironment(LPVOID *lpEnvironment,
207 HKEY hKey,
208 LPWSTR lpSubKeyName)
209 {
210 HKEY hEnvKey;
211 DWORD dwValues;
212 DWORD dwMaxValueNameLength;
213 DWORD dwMaxValueDataLength;
214 DWORD dwValueNameLength;
215 DWORD dwValueDataLength;
216 DWORD dwType;
217 DWORD i;
218 LPWSTR lpValueName;
219 LPWSTR lpValueData;
220 LONG Error;
221
222 Error = RegOpenKeyExW(hKey,
223 lpSubKeyName,
224 0,
225 KEY_QUERY_VALUE,
226 &hEnvKey);
227 if (Error != ERROR_SUCCESS)
228 {
229 DPRINT1("RegOpenKeyExW() failed (Error %ld)\n", Error);
230 SetLastError((DWORD)Error);
231 return FALSE;
232 }
233
234 Error = RegQueryInfoKey(hEnvKey,
235 NULL,
236 NULL,
237 NULL,
238 NULL,
239 NULL,
240 NULL,
241 &dwValues,
242 &dwMaxValueNameLength,
243 &dwMaxValueDataLength,
244 NULL,
245 NULL);
246 if (Error != ERROR_SUCCESS)
247 {
248 DPRINT1("RegQueryInforKey() failed (Error %ld)\n", Error);
249 RegCloseKey(hEnvKey);
250 SetLastError((DWORD)Error);
251 return FALSE;
252 }
253
254 if (dwValues == 0)
255 {
256 RegCloseKey(hEnvKey);
257 return TRUE;
258 }
259
260 /* Allocate buffers */
261 lpValueName = LocalAlloc(LPTR,
262 dwMaxValueNameLength * sizeof(WCHAR));
263 if (lpValueName == NULL)
264 {
265 RegCloseKey(hEnvKey);
266 return FALSE;
267 }
268
269 lpValueData = LocalAlloc(LPTR,
270 dwMaxValueDataLength);
271 if (lpValueData == NULL)
272 {
273 LocalFree(lpValueName);
274 RegCloseKey(hEnvKey);
275 return FALSE;
276 }
277
278 /* Enumerate values */
279 for (i = 0; i < dwValues; i++)
280 {
281 dwValueNameLength = dwMaxValueNameLength;
282 dwValueDataLength = dwMaxValueDataLength;
283 RegEnumValueW(hEnvKey,
284 i,
285 lpValueName,
286 &dwValueNameLength,
287 NULL,
288 &dwType,
289 (LPBYTE)lpValueData,
290 &dwValueDataLength);
291
292 if (!_wcsicmp (lpValueName, L"path"))
293 {
294 /* Append 'Path' environment variable */
295 AppendUserEnvironmentVariable(lpEnvironment,
296 lpValueName,
297 lpValueData);
298 }
299 else
300 {
301 /* Set environment variable */
302 SetUserEnvironmentVariable(lpEnvironment,
303 lpValueName,
304 lpValueData,
305 (dwType == REG_EXPAND_SZ));
306 }
307 }
308
309 LocalFree(lpValueData);
310 LocalFree(lpValueName);
311 RegCloseKey(hEnvKey);
312
313 return TRUE;
314 }
315
316
317 BOOL
318 WINAPI
319 CreateEnvironmentBlock(LPVOID *lpEnvironment,
320 HANDLE hToken,
321 BOOL bInherit)
322 {
323 WCHAR Buffer[MAX_PATH];
324 WCHAR szValue[1024];
325 DWORD Length;
326 DWORD dwType;
327 HKEY hKey;
328 HKEY hKeyUser;
329 NTSTATUS Status;
330 LONG lError;
331
332 DPRINT("CreateEnvironmentBlock() called\n");
333
334 if (lpEnvironment == NULL)
335 {
336 SetLastError(ERROR_INVALID_PARAMETER);
337 return FALSE;
338 }
339
340 Status = RtlCreateEnvironment((BOOLEAN)bInherit,
341 (PWSTR*)lpEnvironment);
342 if (!NT_SUCCESS (Status))
343 {
344 DPRINT1("RtlCreateEnvironment() failed (Status %lx)\n", Status);
345 SetLastError(RtlNtStatusToDosError(Status));
346 return FALSE;
347 }
348
349 /* Set 'COMPUTERNAME' variable */
350 Length = MAX_PATH;
351 if (GetComputerNameW(Buffer,
352 &Length))
353 {
354 SetUserEnvironmentVariable(lpEnvironment,
355 L"COMPUTERNAME",
356 Buffer,
357 FALSE);
358 }
359
360 /* Set 'ALLUSERSPROFILE' variable */
361 Length = MAX_PATH;
362 if (GetAllUsersProfileDirectoryW(Buffer,
363 &Length))
364 {
365 SetUserEnvironmentVariable(lpEnvironment,
366 L"ALLUSERSPROFILE",
367 Buffer,
368 FALSE);
369 }
370
371 lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
372 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion",
373 0,
374 KEY_READ,
375 &hKey);
376 if (lError == ERROR_SUCCESS)
377 {
378 Length = 1024 * sizeof(WCHAR);
379 lError = RegQueryValueExW(hKey,
380 L"ProgramFilesDir",
381 NULL,
382 &dwType,
383 (LPBYTE)szValue,
384 &Length);
385 if (lError == ERROR_SUCCESS)
386 {
387 SetUserEnvironmentVariable(lpEnvironment,
388 L"ProgramFiles",
389 szValue,
390 FALSE);
391 }
392
393 Length = 1024 * sizeof(WCHAR);
394 lError = RegQueryValueExW(hKey,
395 L"CommonFilesDir",
396 NULL,
397 &dwType,
398 (LPBYTE)szValue,
399 &Length);
400 if (lError == ERROR_SUCCESS)
401 {
402 SetUserEnvironmentVariable(lpEnvironment,
403 L"CommonProgramFiles",
404 szValue,
405 FALSE);
406 }
407
408 RegCloseKey(hKey);
409 }
410
411 if (hToken == NULL)
412 return TRUE;
413
414 hKeyUser = GetCurrentUserKey(hToken);
415 if (hKeyUser == NULL)
416 {
417 DPRINT1("GetCurrentUserKey() failed\n");
418 RtlDestroyEnvironment(*lpEnvironment);
419 return FALSE;
420 }
421
422 /* Set 'USERPROFILE' variable */
423 Length = MAX_PATH;
424 if (GetUserProfileDirectoryW(hToken,
425 Buffer,
426 &Length))
427 {
428 SetUserEnvironmentVariable(lpEnvironment,
429 L"USERPROFILE",
430 Buffer,
431 FALSE);
432 }
433
434 /* FIXME: Set 'USERDOMAIN' variable */
435
436 Length = MAX_PATH;
437 if (GetUserNameW(Buffer,
438 &Length))
439 {
440 SetUserEnvironmentVariable(lpEnvironment,
441 L"USERNAME",
442 Buffer,
443 FALSE);
444 }
445
446 /* Set user environment variables */
447 SetUserEnvironment(lpEnvironment,
448 hKeyUser,
449 L"Environment");
450
451 /* Set user volatile environment variables */
452 SetUserEnvironment(lpEnvironment,
453 hKeyUser,
454 L"Volatile Environment");
455
456 RegCloseKey(hKeyUser);
457
458 return TRUE;
459 }
460
461
462 BOOL
463 WINAPI
464 DestroyEnvironmentBlock(LPVOID lpEnvironment)
465 {
466 DPRINT("DestroyEnvironmentBlock() called\n");
467
468 if (lpEnvironment == NULL)
469 {
470 SetLastError(ERROR_INVALID_PARAMETER);
471 return FALSE;
472 }
473
474 RtlDestroyEnvironment(lpEnvironment);
475
476 return TRUE;
477 }
478
479
480 BOOL
481 WINAPI
482 ExpandEnvironmentStringsForUserW(IN HANDLE hToken,
483 IN LPCWSTR lpSrc,
484 OUT LPWSTR lpDest,
485 IN DWORD dwSize)
486 {
487 PVOID lpEnvironment;
488 BOOL Ret = FALSE;
489
490 if (lpSrc == NULL || lpDest == NULL || dwSize == 0)
491 {
492 SetLastError(ERROR_INVALID_PARAMETER);
493 return FALSE;
494 }
495
496 if (CreateEnvironmentBlock(&lpEnvironment,
497 hToken,
498 FALSE))
499 {
500 UNICODE_STRING SrcU, DestU;
501 NTSTATUS Status;
502
503 /* initialize the strings */
504 RtlInitUnicodeString(&SrcU,
505 lpSrc);
506 DestU.Length = 0;
507 DestU.MaximumLength = dwSize * sizeof(WCHAR);
508 DestU.Buffer = lpDest;
509
510 /* expand the strings */
511 Status = RtlExpandEnvironmentStrings_U((PWSTR)lpEnvironment,
512 &SrcU,
513 &DestU,
514 NULL);
515
516 DestroyEnvironmentBlock(lpEnvironment);
517
518 if (NT_SUCCESS(Status))
519 {
520 Ret = TRUE;
521 }
522 else
523 {
524 SetLastError(RtlNtStatusToDosError(Status));
525 }
526 }
527
528 return Ret;
529 }
530
531
532 BOOL
533 WINAPI
534 ExpandEnvironmentStringsForUserA(IN HANDLE hToken,
535 IN LPCSTR lpSrc,
536 OUT LPSTR lpDest,
537 IN DWORD dwSize)
538 {
539 DWORD dwSrcLen;
540 LPWSTR lpSrcW = NULL, lpDestW = NULL;
541 BOOL Ret = FALSE;
542
543 if (lpSrc == NULL || lpDest == NULL || dwSize == 0)
544 {
545 SetLastError(ERROR_INVALID_PARAMETER);
546 return FALSE;
547 }
548
549 dwSrcLen = strlen(lpSrc);
550 lpSrcW = (LPWSTR)GlobalAlloc(GMEM_FIXED,
551 (dwSrcLen + 1) * sizeof(WCHAR));
552 if (lpSrcW == NULL ||
553 MultiByteToWideChar(CP_ACP,
554 0,
555 lpSrc,
556 -1,
557 lpSrcW,
558 dwSrcLen + 1) == 0)
559 {
560 goto Cleanup;
561 }
562
563 lpDestW = (LPWSTR)GlobalAlloc(GMEM_FIXED,
564 dwSize * sizeof(WCHAR));
565 if (lpDestW == NULL)
566 {
567 goto Cleanup;
568 }
569
570 Ret = ExpandEnvironmentStringsForUserW(hToken,
571 lpSrcW,
572 lpDestW,
573 dwSize);
574 if (Ret)
575 {
576 if (WideCharToMultiByte(CP_ACP,
577 0,
578 lpDestW,
579 -1,
580 lpDest,
581 dwSize,
582 NULL,
583 NULL) == 0)
584 {
585 Ret = FALSE;
586 }
587 }
588
589 Cleanup:
590 if (lpSrcW != NULL)
591 {
592 GlobalFree((HGLOBAL)lpSrcW);
593 }
594
595 if (lpDestW != NULL)
596 {
597 GlobalFree((HGLOBAL)lpDestW);
598 }
599
600 return Ret;
601 }
602
603 /* EOF */