- partially implemented RegisterGPNotification() and UnregisterGPNotification() ...
[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
173 if (!GetUserSidFromToken (hToken,
174 &SidString))
175 {
176 DPRINT1 ("GetUserSidFromToken() failed\n");
177 return NULL;
178 }
179
180 if (RegOpenKeyExW (HKEY_USERS,
181 SidString.Buffer,
182 0,
183 KEY_ALL_ACCESS,
184 &hKey))
185 {
186 DPRINT1 ("RegOpenKeyExW() failed (Error %ld)\n", GetLastError());
187 RtlFreeUnicodeString (&SidString);
188 return NULL;
189 }
190
191 RtlFreeUnicodeString (&SidString);
192
193 return hKey;
194 }
195
196
197 static BOOL
198 SetUserEnvironment (LPVOID *lpEnvironment,
199 HKEY hKey,
200 LPWSTR lpSubKeyName)
201 {
202 HKEY hEnvKey;
203 DWORD dwValues;
204 DWORD dwMaxValueNameLength;
205 DWORD dwMaxValueDataLength;
206 DWORD dwValueNameLength;
207 DWORD dwValueDataLength;
208 DWORD dwType;
209 DWORD i;
210 LPWSTR lpValueName;
211 LPWSTR lpValueData;
212
213 if (RegOpenKeyExW (hKey,
214 lpSubKeyName,
215 0,
216 KEY_ALL_ACCESS,
217 &hEnvKey))
218 {
219 DPRINT1 ("RegOpenKeyExW() failed (Error %ld)\n", GetLastError());
220 return FALSE;
221 }
222
223 if (RegQueryInfoKey (hEnvKey,
224 NULL,
225 NULL,
226 NULL,
227 NULL,
228 NULL,
229 NULL,
230 &dwValues,
231 &dwMaxValueNameLength,
232 &dwMaxValueDataLength,
233 NULL,
234 NULL))
235 {
236 DPRINT1 ("RegQueryInforKey() failed (Error %ld)\n", GetLastError());
237 RegCloseKey (hEnvKey);
238 return FALSE;
239 }
240
241 if (dwValues == 0)
242 {
243 RegCloseKey (hEnvKey);
244 return TRUE;
245 }
246
247 /* Allocate buffers */
248 lpValueName = LocalAlloc (LPTR,
249 dwMaxValueNameLength * sizeof(WCHAR));
250 if (lpValueName == NULL)
251 {
252 RegCloseKey (hEnvKey);
253 return FALSE;
254 }
255
256 lpValueData = LocalAlloc (LPTR,
257 dwMaxValueDataLength);
258 if (lpValueData == NULL)
259 {
260 LocalFree (lpValueName);
261 RegCloseKey (hEnvKey);
262 return FALSE;
263 }
264
265 /* Enumerate values */
266 for (i = 0; i < dwValues; i++)
267 {
268 dwValueNameLength = dwMaxValueNameLength;
269 dwValueDataLength = dwMaxValueDataLength;
270 RegEnumValueW (hEnvKey,
271 i,
272 lpValueName,
273 &dwValueNameLength,
274 NULL,
275 &dwType,
276 (LPBYTE)lpValueData,
277 &dwValueDataLength);
278
279 if (!_wcsicmp (lpValueName, L"path"))
280 {
281 /* Append 'Path' environment variable */
282 AppendUserEnvironmentVariable (lpEnvironment,
283 lpValueName,
284 lpValueData);
285 }
286 else
287 {
288 /* Set environment variable */
289 SetUserEnvironmentVariable (lpEnvironment,
290 lpValueName,
291 lpValueData,
292 (dwType == REG_EXPAND_SZ));
293 }
294 }
295
296 LocalFree (lpValueData);
297 LocalFree (lpValueName);
298 RegCloseKey (hEnvKey);
299
300 return TRUE;
301 }
302
303
304 BOOL WINAPI
305 CreateEnvironmentBlock (LPVOID *lpEnvironment,
306 HANDLE hToken,
307 BOOL bInherit)
308 {
309 WCHAR Buffer[MAX_PATH];
310 DWORD Length;
311 HKEY hKeyUser;
312 NTSTATUS Status;
313
314 DPRINT("CreateEnvironmentBlock() called\n");
315
316 if (lpEnvironment == NULL)
317 return FALSE;
318
319 Status = RtlCreateEnvironment ((BOOLEAN)bInherit,
320 (PWSTR*)lpEnvironment);
321 if (!NT_SUCCESS (Status))
322 {
323 DPRINT1 ("RtlCreateEnvironment() failed (Status %lx)\n", Status);
324 return FALSE;
325 }
326
327 /* Set 'COMPUTERNAME' variable */
328 Length = MAX_PATH;
329 if (GetComputerNameW (Buffer,
330 &Length))
331 {
332 SetUserEnvironmentVariable(lpEnvironment,
333 L"COMPUTERNAME",
334 Buffer,
335 FALSE);
336 }
337
338 if (hToken == NULL)
339 return TRUE;
340
341 hKeyUser = GetCurrentUserKey (hToken);
342 if (hKeyUser == NULL)
343 {
344 DPRINT1 ("GetCurrentUserKey() failed\n");
345 RtlDestroyEnvironment (*lpEnvironment);
346 return FALSE;
347 }
348
349 /* Set 'ALLUSERSPROFILE' variable */
350 Length = MAX_PATH;
351 if (GetAllUsersProfileDirectoryW (Buffer,
352 &Length))
353 {
354 SetUserEnvironmentVariable(lpEnvironment,
355 L"ALLUSERSPROFILE",
356 Buffer,
357 FALSE);
358 }
359
360 /* Set 'USERPROFILE' variable */
361 Length = MAX_PATH;
362 if (GetUserProfileDirectoryW (hToken,
363 Buffer,
364 &Length))
365 {
366 SetUserEnvironmentVariable(lpEnvironment,
367 L"USERPROFILE",
368 Buffer,
369 FALSE);
370 }
371
372 /* FIXME: Set 'USERDOMAIN' variable */
373
374 /* FIXME: Set 'USERNAME' variable */
375
376 /* Set user environment variables */
377 SetUserEnvironment (lpEnvironment,
378 hKeyUser,
379 L"Environment");
380
381 RegCloseKey (hKeyUser);
382
383 return TRUE;
384 }
385
386
387 BOOL WINAPI
388 DestroyEnvironmentBlock (LPVOID lpEnvironment)
389 {
390 DPRINT ("DestroyEnvironmentBlock() called\n");
391
392 if (lpEnvironment == NULL)
393 return FALSE;
394
395 RtlDestroyEnvironment (lpEnvironment);
396
397 return TRUE;
398 }
399
400
401 BOOL WINAPI
402 ExpandEnvironmentStringsForUserW(IN HANDLE hToken,
403 IN LPCWSTR lpSrc,
404 OUT LPWSTR lpDest,
405 IN DWORD dwSize)
406 {
407 PVOID lpEnvironment;
408 BOOL Ret = FALSE;
409
410 if (lpSrc == NULL || lpDest == NULL || dwSize == 0)
411 {
412 SetLastError(ERROR_INVALID_PARAMETER);
413 return FALSE;
414 }
415
416 if (CreateEnvironmentBlock(&lpEnvironment,
417 hToken,
418 FALSE))
419 {
420 UNICODE_STRING SrcU, DestU;
421 NTSTATUS Status;
422
423 /* initialize the strings */
424 RtlInitUnicodeString(&SrcU,
425 lpSrc);
426 DestU.Length = 0;
427 DestU.MaximumLength = dwSize * sizeof(WCHAR);
428 DestU.Buffer = lpDest;
429
430 /* expand the strings */
431 Status = RtlExpandEnvironmentStrings_U((PWSTR)lpEnvironment,
432 &SrcU,
433 &DestU,
434 NULL);
435
436 DestroyEnvironmentBlock(lpEnvironment);
437
438 if (NT_SUCCESS(Status))
439 {
440 Ret = TRUE;
441 }
442 else
443 {
444 SetLastError(RtlNtStatusToDosError(Status));
445 }
446 }
447
448 return Ret;
449 }
450
451
452 BOOL WINAPI
453 ExpandEnvironmentStringsForUserA(IN HANDLE hToken,
454 IN LPCSTR lpSrc,
455 OUT LPSTR lpDest,
456 IN DWORD dwSize)
457 {
458 DWORD dwSrcLen;
459 LPWSTR lpSrcW = NULL, lpDestW = NULL;
460 BOOL Ret = FALSE;
461
462 if (lpSrc == NULL || lpDest == NULL || dwSize == 0)
463 {
464 SetLastError(ERROR_INVALID_PARAMETER);
465 return FALSE;
466 }
467
468 dwSrcLen = strlen(lpSrc);
469 lpSrcW = (LPWSTR)GlobalAlloc(GMEM_FIXED,
470 (dwSrcLen + 1) * sizeof(WCHAR));
471 if (lpSrcW == NULL ||
472 MultiByteToWideChar(CP_ACP,
473 0,
474 lpSrc,
475 -1,
476 lpSrcW,
477 dwSrcLen + 1) == 0)
478 {
479 goto Cleanup;
480 }
481
482 lpDestW = (LPWSTR)GlobalAlloc(GMEM_FIXED,
483 dwSize * sizeof(WCHAR));
484 if (lpDestW == NULL)
485 {
486 goto Cleanup;
487 }
488
489 Ret = ExpandEnvironmentStringsForUserW(hToken,
490 lpSrcW,
491 lpDestW,
492 dwSize);
493 if (Ret)
494 {
495 if (WideCharToMultiByte(CP_ACP,
496 0,
497 lpDestW,
498 -1,
499 lpDest,
500 dwSize,
501 NULL,
502 NULL) == 0)
503 {
504 Ret = FALSE;
505 }
506 }
507
508 Cleanup:
509 if (lpSrcW != NULL)
510 {
511 GlobalFree((HGLOBAL)lpSrcW);
512 }
513
514 if (lpDestW != NULL)
515 {
516 GlobalFree((HGLOBAL)lpDestW);
517 }
518
519 return Ret;
520 }
521
522 /* EOF */