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