d5f5bb59c0e8369c522f4da8af0386fb3affdf3a
[reactos.git] / reactos / lib / 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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS system libraries
23 * FILE: lib/userenv/environment.c
24 * PURPOSE: User environment functions
25 * PROGRAMMER: Eric Kohl
26 */
27
28 #include <precomp.h>
29
30 #define NDEBUG
31 #include <debug.h>
32
33
34 static 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
60 if (DstValue.Buffer == NULL)
61 {
62 DPRINT1("LocalAlloc() failed\n");
63 return FALSE;
64 }
65
66 Status = RtlExpandEnvironmentStrings_U((PWSTR)*Environment,
67 &SrcValue,
68 &DstValue,
69 &Length);
70 if (!NT_SUCCESS(Status))
71 {
72 DPRINT1("RtlExpandEnvironmentStrings_U() failed (Status %lx)\n", Status);
73 DPRINT1("Length %lu\n", Length);
74 if (Buffer) 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 (Error %lu)\n", GetLastError());
89 if (Buffer) LocalFree(Buffer);
90 return FALSE;
91 }
92
93 DPRINT("Buffer: %S\n", ShortName);
94 RtlInitUnicodeString(&DstValue,
95 ShortName);
96 }
97
98 RtlInitUnicodeString(&Name,
99 lpName);
100
101 DPRINT("Value: %wZ\n", &DstValue);
102
103 Status = RtlSetEnvironmentVariable((PWSTR*)Environment,
104 &Name,
105 &DstValue);
106
107 if (Buffer) LocalFree(Buffer);
108
109 if (!NT_SUCCESS(Status))
110 {
111 DPRINT1("RtlSetEnvironmentVariable() failed (Status %lx)\n", Status);
112 return FALSE;
113 }
114
115 return TRUE;
116 }
117
118
119 static BOOL
120 AppendUserEnvironmentVariable (LPVOID *Environment,
121 LPWSTR lpName,
122 LPWSTR lpValue)
123 {
124 UNICODE_STRING Name;
125 UNICODE_STRING Value;
126 NTSTATUS Status;
127
128 RtlInitUnicodeString (&Name,
129 lpName);
130
131 Value.Length = 0;
132 Value.MaximumLength = 1024 * sizeof(WCHAR);
133 Value.Buffer = LocalAlloc (LPTR,
134 1024 * sizeof(WCHAR));
135 if (Value.Buffer == NULL)
136 {
137 return FALSE;
138 }
139 Value.Buffer[0] = UNICODE_NULL;
140
141 Status = RtlQueryEnvironmentVariable_U ((PWSTR)*Environment,
142 &Name,
143 &Value);
144 if (NT_SUCCESS(Status))
145 {
146 RtlAppendUnicodeToString (&Value,
147 L";");
148 }
149
150 RtlAppendUnicodeToString (&Value,
151 lpValue);
152
153 Status = RtlSetEnvironmentVariable ((PWSTR*)Environment,
154 &Name,
155 &Value);
156 LocalFree (Value.Buffer);
157 if (!NT_SUCCESS(Status))
158 {
159 DPRINT1 ("RtlSetEnvironmentVariable() failed (Status %lx)\n", Status);
160 return FALSE;
161 }
162
163 return TRUE;
164 }
165
166
167 static HKEY
168 GetCurrentUserKey (HANDLE hToken)
169 {
170 UNICODE_STRING SidString;
171 HKEY hKey;
172 LONG Error;
173
174 if (!GetUserSidFromToken (hToken,
175 &SidString))
176 {
177 DPRINT1 ("GetUserSidFromToken() failed\n");
178 return NULL;
179 }
180
181 Error = RegOpenKeyExW (HKEY_USERS,
182 SidString.Buffer,
183 0,
184 KEY_ALL_ACCESS,
185 &hKey);
186 if (Error != ERROR_SUCCESS)
187 {
188 DPRINT1 ("RegOpenKeyExW() failed (Error %ld)\n", Error);
189 RtlFreeUnicodeString (&SidString);
190 SetLastError((DWORD)Error);
191 return NULL;
192 }
193
194 RtlFreeUnicodeString (&SidString);
195
196 return hKey;
197 }
198
199
200 static BOOL
201 SetUserEnvironment (LPVOID *lpEnvironment,
202 HKEY hKey,
203 LPWSTR lpSubKeyName)
204 {
205 HKEY hEnvKey;
206 DWORD dwValues;
207 DWORD dwMaxValueNameLength;
208 DWORD dwMaxValueDataLength;
209 DWORD dwValueNameLength;
210 DWORD dwValueDataLength;
211 DWORD dwType;
212 DWORD i;
213 LPWSTR lpValueName;
214 LPWSTR lpValueData;
215 LONG Error;
216
217 Error = RegOpenKeyExW (hKey,
218 lpSubKeyName,
219 0,
220 KEY_ALL_ACCESS,
221 &hEnvKey);
222 if (Error != ERROR_SUCCESS)
223 {
224 DPRINT1 ("RegOpenKeyExW() failed (Error %ld)\n", Error);
225 SetLastError((DWORD)Error);
226 return FALSE;
227 }
228
229 Error = RegQueryInfoKey (hEnvKey,
230 NULL,
231 NULL,
232 NULL,
233 NULL,
234 NULL,
235 NULL,
236 &dwValues,
237 &dwMaxValueNameLength,
238 &dwMaxValueDataLength,
239 NULL,
240 NULL);
241 if (Error != ERROR_SUCCESS)
242 {
243 DPRINT1 ("RegQueryInforKey() failed (Error %ld)\n", Error);
244 RegCloseKey (hEnvKey);
245 SetLastError((DWORD)Error);
246 return FALSE;
247 }
248
249 if (dwValues == 0)
250 {
251 RegCloseKey (hEnvKey);
252 return TRUE;
253 }
254
255 /* Allocate buffers */
256 lpValueName = LocalAlloc (LPTR,
257 dwMaxValueNameLength * sizeof(WCHAR));
258 if (lpValueName == NULL)
259 {
260 RegCloseKey (hEnvKey);
261 return FALSE;
262 }
263
264 lpValueData = LocalAlloc (LPTR,
265 dwMaxValueDataLength);
266 if (lpValueData == NULL)
267 {
268 LocalFree (lpValueName);
269 RegCloseKey (hEnvKey);
270 return FALSE;
271 }
272
273 /* Enumerate values */
274 for (i = 0; i < dwValues; i++)
275 {
276 dwValueNameLength = dwMaxValueNameLength;
277 dwValueDataLength = dwMaxValueDataLength;
278 RegEnumValueW (hEnvKey,
279 i,
280 lpValueName,
281 &dwValueNameLength,
282 NULL,
283 &dwType,
284 (LPBYTE)lpValueData,
285 &dwValueDataLength);
286
287 if (!_wcsicmp (lpValueName, L"path"))
288 {
289 /* Append 'Path' environment variable */
290 AppendUserEnvironmentVariable (lpEnvironment,
291 lpValueName,
292 lpValueData);
293 }
294 else
295 {
296 /* Set environment variable */
297 SetUserEnvironmentVariable (lpEnvironment,
298 lpValueName,
299 lpValueData,
300 (dwType == REG_EXPAND_SZ));
301 }
302 }
303
304 LocalFree (lpValueData);
305 LocalFree (lpValueName);
306 RegCloseKey (hEnvKey);
307
308 return TRUE;
309 }
310
311
312 BOOL WINAPI
313 CreateEnvironmentBlock (LPVOID *lpEnvironment,
314 HANDLE hToken,
315 BOOL bInherit)
316 {
317 WCHAR Buffer[MAX_PATH];
318 DWORD Length;
319 HKEY hKeyUser;
320 NTSTATUS Status;
321
322 DPRINT("CreateEnvironmentBlock() called\n");
323
324 if (lpEnvironment == NULL)
325 {
326 SetLastError(ERROR_INVALID_PARAMETER);
327 return FALSE;
328 }
329
330 Status = RtlCreateEnvironment ((BOOLEAN)bInherit,
331 (PWSTR*)lpEnvironment);
332 if (!NT_SUCCESS (Status))
333 {
334 DPRINT1 ("RtlCreateEnvironment() failed (Status %lx)\n", Status);
335 SetLastError (RtlNtStatusToDosError (Status));
336 return FALSE;
337 }
338
339 /* Set 'COMPUTERNAME' variable */
340 Length = MAX_PATH;
341 if (GetComputerNameW (Buffer,
342 &Length))
343 {
344 SetUserEnvironmentVariable(lpEnvironment,
345 L"COMPUTERNAME",
346 Buffer,
347 FALSE);
348 }
349
350 if (hToken == NULL)
351 return TRUE;
352
353 hKeyUser = GetCurrentUserKey (hToken);
354 if (hKeyUser == NULL)
355 {
356 DPRINT1 ("GetCurrentUserKey() failed\n");
357 RtlDestroyEnvironment (*lpEnvironment);
358 return FALSE;
359 }
360
361 /* Set 'ALLUSERSPROFILE' variable */
362 Length = MAX_PATH;
363 if (GetAllUsersProfileDirectoryW (Buffer,
364 &Length))
365 {
366 SetUserEnvironmentVariable(lpEnvironment,
367 L"ALLUSERSPROFILE",
368 Buffer,
369 FALSE);
370 }
371
372 /* Set 'USERPROFILE' variable */
373 Length = MAX_PATH;
374 if (GetUserProfileDirectoryW (hToken,
375 Buffer,
376 &Length))
377 {
378 SetUserEnvironmentVariable(lpEnvironment,
379 L"USERPROFILE",
380 Buffer,
381 FALSE);
382 }
383
384 /* FIXME: Set 'USERDOMAIN' variable */
385
386 /* FIXME: Set 'USERNAME' variable */
387
388 /* Set user environment variables */
389 SetUserEnvironment (lpEnvironment,
390 hKeyUser,
391 L"Environment");
392
393 RegCloseKey (hKeyUser);
394
395 return TRUE;
396 }
397
398
399 BOOL WINAPI
400 DestroyEnvironmentBlock (LPVOID lpEnvironment)
401 {
402 DPRINT ("DestroyEnvironmentBlock() called\n");
403
404 if (lpEnvironment == NULL)
405 {
406 SetLastError(ERROR_INVALID_PARAMETER);
407 return FALSE;
408 }
409
410 RtlDestroyEnvironment (lpEnvironment);
411
412 return TRUE;
413 }
414
415
416 BOOL WINAPI
417 ExpandEnvironmentStringsForUserW(IN HANDLE hToken,
418 IN LPCWSTR lpSrc,
419 OUT LPWSTR lpDest,
420 IN DWORD dwSize)
421 {
422 PVOID lpEnvironment;
423 BOOL Ret = FALSE;
424
425 if (lpSrc == NULL || lpDest == NULL || dwSize == 0)
426 {
427 SetLastError(ERROR_INVALID_PARAMETER);
428 return FALSE;
429 }
430
431 if (CreateEnvironmentBlock(&lpEnvironment,
432 hToken,
433 FALSE))
434 {
435 UNICODE_STRING SrcU, DestU;
436 NTSTATUS Status;
437
438 /* initialize the strings */
439 RtlInitUnicodeString(&SrcU,
440 lpSrc);
441 DestU.Length = 0;
442 DestU.MaximumLength = dwSize * sizeof(WCHAR);
443 DestU.Buffer = lpDest;
444
445 /* expand the strings */
446 Status = RtlExpandEnvironmentStrings_U((PWSTR)lpEnvironment,
447 &SrcU,
448 &DestU,
449 NULL);
450
451 DestroyEnvironmentBlock(lpEnvironment);
452
453 if (NT_SUCCESS(Status))
454 {
455 Ret = TRUE;
456 }
457 else
458 {
459 SetLastError(RtlNtStatusToDosError(Status));
460 }
461 }
462
463 return Ret;
464 }
465
466
467 BOOL WINAPI
468 ExpandEnvironmentStringsForUserA(IN HANDLE hToken,
469 IN LPCSTR lpSrc,
470 OUT LPSTR lpDest,
471 IN DWORD dwSize)
472 {
473 DWORD dwSrcLen;
474 LPWSTR lpSrcW = NULL, lpDestW = NULL;
475 BOOL Ret = FALSE;
476
477 if (lpSrc == NULL || lpDest == NULL || dwSize == 0)
478 {
479 SetLastError(ERROR_INVALID_PARAMETER);
480 return FALSE;
481 }
482
483 dwSrcLen = strlen(lpSrc);
484 lpSrcW = (LPWSTR)GlobalAlloc(GMEM_FIXED,
485 (dwSrcLen + 1) * sizeof(WCHAR));
486 if (lpSrcW == NULL ||
487 MultiByteToWideChar(CP_ACP,
488 0,
489 lpSrc,
490 -1,
491 lpSrcW,
492 dwSrcLen + 1) == 0)
493 {
494 goto Cleanup;
495 }
496
497 lpDestW = (LPWSTR)GlobalAlloc(GMEM_FIXED,
498 dwSize * sizeof(WCHAR));
499 if (lpDestW == NULL)
500 {
501 goto Cleanup;
502 }
503
504 Ret = ExpandEnvironmentStringsForUserW(hToken,
505 lpSrcW,
506 lpDestW,
507 dwSize);
508 if (Ret)
509 {
510 if (WideCharToMultiByte(CP_ACP,
511 0,
512 lpDestW,
513 -1,
514 lpDest,
515 dwSize,
516 NULL,
517 NULL) == 0)
518 {
519 Ret = FALSE;
520 }
521 }
522
523 Cleanup:
524 if (lpSrcW != NULL)
525 {
526 GlobalFree((HGLOBAL)lpSrcW);
527 }
528
529 if (lpDestW != NULL)
530 {
531 GlobalFree((HGLOBAL)lpDestW);
532 }
533
534 return Ret;
535 }
536
537 /* EOF */