4a6f0befb76c72d0424467942b07580046525cc9
[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: environment.c,v 1.7 2004/09/30 20:23:00 ekohl Exp $
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
31 static BOOL
32 SetUserEnvironmentVariable (LPVOID *Environment,
33 LPWSTR lpName,
34 LPWSTR lpValue,
35 BOOL bExpand)
36 {
37 WCHAR ShortName[MAX_PATH];
38 UNICODE_STRING Name;
39 UNICODE_STRING SrcValue;
40 UNICODE_STRING DstValue;
41 ULONG Length;
42 NTSTATUS Status;
43
44 if (bExpand)
45 {
46 RtlInitUnicodeString(&SrcValue,
47 lpValue);
48
49 Length = 2 * MAX_PATH * sizeof(WCHAR);
50
51 DstValue.Length = 0;
52 DstValue.MaximumLength = Length;
53 DstValue.Buffer = LocalAlloc(LPTR,
54 Length);
55 if (DstValue.Buffer == NULL)
56 {
57 DPRINT1("LocalAlloc() failed\n");
58 return FALSE;
59 }
60
61 Status = RtlExpandEnvironmentStrings_U((PWSTR)*Environment,
62 &SrcValue,
63 &DstValue,
64 &Length);
65 if (!NT_SUCCESS(Status))
66 {
67 DPRINT1("RtlExpandEnvironmentStrings_U() failed (Status %lx)\n", Status);
68 DPRINT1("Length %lu\n", Length);
69 return FALSE;
70 }
71 }
72 else
73 {
74 RtlInitUnicodeString(&DstValue,
75 lpValue);
76 }
77
78 if (!_wcsicmp (lpName, L"temp") || !_wcsicmp (lpName, L"tmp"))
79 {
80 if (!GetShortPathNameW(DstValue.Buffer, ShortName, MAX_PATH))
81 {
82 DPRINT1("GetShortPathNameW() failed (Error %lu)\n", GetLastError());
83 return FALSE;
84 }
85
86 DPRINT("Buffer: %S\n", ShortName);
87 RtlInitUnicodeString(&DstValue,
88 ShortName);
89 }
90
91 RtlInitUnicodeString(&Name,
92 lpName);
93
94 DPRINT("Value: %wZ\n", &DstValue);
95
96 Status = RtlSetEnvironmentVariable((PWSTR*)Environment,
97 &Name,
98 &DstValue);
99
100 if (bExpand)
101 {
102 LocalFree(DstValue.Buffer);
103 }
104
105 if (!NT_SUCCESS(Status))
106 {
107 DPRINT1("RtlSetEnvironmentVariable() failed (Status %lx)\n", Status);
108 return FALSE;
109 }
110
111 return TRUE;
112 }
113
114
115 static BOOL
116 AppendUserEnvironmentVariable (LPVOID *Environment,
117 LPWSTR lpName,
118 LPWSTR lpValue)
119 {
120 UNICODE_STRING Name;
121 UNICODE_STRING Value;
122 NTSTATUS Status;
123
124 RtlInitUnicodeString (&Name,
125 lpName);
126
127 Value.Length = 0;
128 Value.MaximumLength = 1024 * sizeof(WCHAR);
129 Value.Buffer = LocalAlloc (LPTR,
130 1024 * sizeof(WCHAR));
131 if (Value.Buffer == NULL)
132 {
133 return FALSE;
134 }
135 Value.Buffer[0] = UNICODE_NULL;
136
137 Status = RtlQueryEnvironmentVariable_U ((PWSTR)*Environment,
138 &Name,
139 &Value);
140 if (NT_SUCCESS(Status))
141 {
142 RtlAppendUnicodeToString (&Value,
143 L";");
144 }
145
146 RtlAppendUnicodeToString (&Value,
147 lpValue);
148
149 Status = RtlSetEnvironmentVariable ((PWSTR*)Environment,
150 &Name,
151 &Value);
152 LocalFree (Value.Buffer);
153 if (!NT_SUCCESS(Status))
154 {
155 DPRINT1 ("RtlSetEnvironmentVariable() failed (Status %lx)\n", Status);
156 return FALSE;
157 }
158
159 return TRUE;
160 }
161
162
163 static HKEY
164 GetCurrentUserKey (HANDLE hToken)
165 {
166 UNICODE_STRING SidString;
167 HKEY hKey;
168
169 if (!GetUserSidFromToken (hToken,
170 &SidString))
171 {
172 DPRINT1 ("GetUserSidFromToken() failed\n");
173 return NULL;
174 }
175
176 if (RegOpenKeyExW (HKEY_USERS,
177 SidString.Buffer,
178 0,
179 KEY_ALL_ACCESS,
180 &hKey))
181 {
182 DPRINT1 ("RegOpenKeyExW() failed (Error %ld)\n", GetLastError());
183 RtlFreeUnicodeString (&SidString);
184 return NULL;
185 }
186
187 RtlFreeUnicodeString (&SidString);
188
189 return hKey;
190 }
191
192
193 static BOOL
194 SetUserEnvironment (LPVOID *lpEnvironment,
195 HKEY hKey,
196 LPWSTR lpSubKeyName)
197 {
198 HKEY hEnvKey;
199 DWORD dwValues;
200 DWORD dwMaxValueNameLength;
201 DWORD dwMaxValueDataLength;
202 DWORD dwValueNameLength;
203 DWORD dwValueDataLength;
204 DWORD dwType;
205 DWORD i;
206 LPWSTR lpValueName;
207 LPWSTR lpValueData;
208
209 if (RegOpenKeyExW (hKey,
210 lpSubKeyName,
211 0,
212 KEY_ALL_ACCESS,
213 &hEnvKey))
214 {
215 DPRINT1 ("RegOpenKeyExW() failed (Error %ld)\n", GetLastError());
216 return FALSE;
217 }
218
219 if (RegQueryInfoKey (hEnvKey,
220 NULL,
221 NULL,
222 NULL,
223 NULL,
224 NULL,
225 NULL,
226 &dwValues,
227 &dwMaxValueNameLength,
228 &dwMaxValueDataLength,
229 NULL,
230 NULL))
231 {
232 DPRINT1 ("RegQueryInforKey() failed (Error %ld)\n", GetLastError());
233 RegCloseKey (hEnvKey);
234 return FALSE;
235 }
236
237 if (dwValues == 0)
238 {
239 RegCloseKey (hEnvKey);
240 return TRUE;
241 }
242
243 /* Allocate buffers */
244 lpValueName = LocalAlloc (LPTR,
245 dwMaxValueNameLength * sizeof(WCHAR));
246 if (lpValueName == NULL)
247 {
248 RegCloseKey (hEnvKey);
249 return FALSE;
250 }
251
252 lpValueData = LocalAlloc (LPTR,
253 dwMaxValueDataLength);
254 if (lpValueData == NULL)
255 {
256 LocalFree (lpValueName);
257 RegCloseKey (hEnvKey);
258 return FALSE;
259 }
260
261 /* Enumerate values */
262 for (i = 0; i < dwValues; i++)
263 {
264 dwValueNameLength = dwMaxValueNameLength;
265 dwValueDataLength = dwMaxValueDataLength;
266 RegEnumValueW (hEnvKey,
267 i,
268 lpValueName,
269 &dwValueNameLength,
270 NULL,
271 &dwType,
272 (LPBYTE)lpValueData,
273 &dwValueDataLength);
274
275 if (!_wcsicmp (lpValueName, L"path"))
276 {
277 /* Append 'Path' environment variable */
278 AppendUserEnvironmentVariable (lpEnvironment,
279 lpValueName,
280 lpValueData);
281 }
282 else
283 {
284 /* Set environment variable */
285 SetUserEnvironmentVariable (lpEnvironment,
286 lpValueName,
287 lpValueData,
288 (dwType == REG_EXPAND_SZ));
289 }
290 }
291
292 LocalFree (lpValueData);
293 LocalFree (lpValueName);
294 RegCloseKey (hEnvKey);
295
296 return TRUE;
297 }
298
299
300 BOOL WINAPI
301 CreateEnvironmentBlock (LPVOID *lpEnvironment,
302 HANDLE hToken,
303 BOOL bInherit)
304 {
305 WCHAR Buffer[MAX_PATH];
306 DWORD Length;
307 HKEY hKeyUser;
308 NTSTATUS Status;
309
310 DPRINT1 ("CreateEnvironmentBlock() called\n");
311
312 if (lpEnvironment == NULL)
313 return FALSE;
314
315 Status = RtlCreateEnvironment ((BOOLEAN)bInherit,
316 (PWSTR*)lpEnvironment);
317 if (!NT_SUCCESS (Status))
318 {
319 DPRINT1 ("RtlCreateEnvironment() failed (Status %lx)\n", Status);
320 return FALSE;
321 }
322
323 /* Set 'COMPUTERNAME' variable */
324 Length = MAX_PATH;
325 if (GetComputerNameW (Buffer,
326 &Length))
327 {
328 SetUserEnvironmentVariable(lpEnvironment,
329 L"COMPUTERNAME",
330 Buffer,
331 FALSE);
332 }
333
334 if (hToken == NULL)
335 return TRUE;
336
337 hKeyUser = GetCurrentUserKey (hToken);
338 if (hKeyUser == NULL)
339 {
340 DPRINT1 ("GetCurrentUserKey() failed\n");
341 RtlDestroyEnvironment (*lpEnvironment);
342 return FALSE;
343 }
344
345 /* Set 'ALLUSERSPROFILE' variable */
346 Length = MAX_PATH;
347 if (GetAllUsersProfileDirectoryW (Buffer,
348 &Length))
349 {
350 SetUserEnvironmentVariable(lpEnvironment,
351 L"ALLUSERSPROFILE",
352 Buffer,
353 FALSE);
354 }
355
356 /* Set 'USERPROFILE' variable */
357 Length = MAX_PATH;
358 if (GetUserProfileDirectoryW (hToken,
359 Buffer,
360 &Length))
361 {
362 SetUserEnvironmentVariable(lpEnvironment,
363 L"USERPROFILE",
364 Buffer,
365 FALSE);
366 }
367
368 /* FIXME: Set 'USERDOMAIN' variable */
369
370 /* FIXME: Set 'USERNAME' variable */
371
372 /* Set user environment variables */
373 SetUserEnvironment (lpEnvironment,
374 hKeyUser,
375 L"Environment");
376
377 RegCloseKey (hKeyUser);
378
379 return TRUE;
380 }
381
382
383 BOOL WINAPI
384 DestroyEnvironmentBlock (LPVOID lpEnvironment)
385 {
386 DPRINT ("DestroyEnvironmentBlock() called\n");
387
388 if (lpEnvironment == NULL)
389 return FALSE;
390
391 RtlDestroyEnvironment (lpEnvironment);
392
393 return TRUE;
394 }
395
396 /* EOF */