fixed calls to NtDuplicateObject
[reactos.git] / reactos / lib / kernel32 / misc / env.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/kernel32/misc/env.c
6 * PURPOSE: Environment functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
8 * UPDATE HISTORY:
9 * Created 01/11/98
10 */
11
12 #include <k32.h>
13
14 #define NDEBUG
15 #include "../include/debug.h"
16
17
18 /* FUNCTIONS ******************************************************************/
19
20 /*
21 * @implemented
22 */
23 DWORD
24 STDCALL
25 GetEnvironmentVariableA (
26 LPCSTR lpName,
27 LPSTR lpBuffer,
28 DWORD nSize
29 )
30 {
31 ANSI_STRING VarName;
32 ANSI_STRING VarValue;
33 UNICODE_STRING VarNameU;
34 UNICODE_STRING VarValueU;
35 NTSTATUS Status;
36
37 /* initialize unicode variable name string */
38 RtlInitAnsiString (&VarName,
39 (LPSTR)lpName);
40 RtlAnsiStringToUnicodeString (&VarNameU,
41 &VarName,
42 TRUE);
43
44 /* initialize ansi variable value string */
45 VarValue.Length = 0;
46 VarValue.MaximumLength = nSize;
47 VarValue.Buffer = lpBuffer;
48
49 /* initialize unicode variable value string and allocate buffer */
50 VarValueU.Length = 0;
51 if (nSize != 0)
52 {
53 VarValueU.MaximumLength = (nSize - 1) * sizeof(WCHAR);
54 VarValueU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
55 0,
56 nSize * sizeof(WCHAR));
57 if (VarValueU.Buffer != NULL)
58 {
59 /* NULL-terminate the buffer in any case! RtlQueryEnvironmentVariable_U
60 only terminates it if MaximumLength < Length! */
61 VarValueU.Buffer[nSize - 1] = L'\0';
62 }
63 }
64 else
65 {
66 VarValueU.MaximumLength = 0;
67 VarValueU.Buffer = NULL;
68 }
69
70 if (VarValueU.Buffer != NULL || nSize == 0)
71 {
72 /* get unicode environment variable */
73 Status = RtlQueryEnvironmentVariable_U (NULL,
74 &VarNameU,
75 &VarValueU);
76 if (!NT_SUCCESS(Status))
77 {
78 /* free unicode buffer */
79 RtlFreeHeap (RtlGetProcessHeap (),
80 0,
81 VarValueU.Buffer);
82
83 /* free unicode variable name string */
84 RtlFreeUnicodeString (&VarNameU);
85
86 SetLastErrorByStatus (Status);
87 if (Status == STATUS_BUFFER_TOO_SMALL)
88 {
89 return (VarValueU.Length / sizeof(WCHAR)) + 1;
90 }
91 else
92 {
93 return 0;
94 }
95 }
96
97 /* convert unicode value string to ansi */
98 RtlUnicodeStringToAnsiString (&VarValue,
99 &VarValueU,
100 FALSE);
101
102 if (VarValueU.Buffer != NULL)
103 {
104 /* free unicode buffer */
105 RtlFreeHeap (RtlGetProcessHeap (),
106 0,
107 VarValueU.Buffer);
108 }
109
110 /* free unicode variable name string */
111 RtlFreeUnicodeString (&VarNameU);
112
113 return (VarValueU.Length / sizeof(WCHAR));
114 }
115 else
116 {
117 SetLastError (ERROR_NOT_ENOUGH_MEMORY);
118 return 0;
119 }
120 }
121
122
123 /*
124 * @implemented
125 */
126 DWORD
127 STDCALL
128 GetEnvironmentVariableW (
129 LPCWSTR lpName,
130 LPWSTR lpBuffer,
131 DWORD nSize
132 )
133 {
134 UNICODE_STRING VarName;
135 UNICODE_STRING VarValue;
136 NTSTATUS Status;
137
138 RtlInitUnicodeString (&VarName,
139 lpName);
140
141 VarValue.Length = 0;
142 VarValue.MaximumLength = (nSize != 0 ? (nSize - 1) * sizeof(WCHAR) : 0);
143 VarValue.Buffer = lpBuffer;
144
145 Status = RtlQueryEnvironmentVariable_U (NULL,
146 &VarName,
147 &VarValue);
148 if (!NT_SUCCESS(Status))
149 {
150 SetLastErrorByStatus (Status);
151 if (Status == STATUS_BUFFER_TOO_SMALL)
152 {
153 return (VarValue.Length / sizeof(WCHAR)) + 1;
154 }
155 else
156 {
157 return 0;
158 }
159 }
160
161 if (nSize != 0)
162 {
163 /* make sure the string is NULL-terminated! RtlQueryEnvironmentVariable_U
164 only terminates it if MaximumLength < Length */
165 VarValue.Buffer[VarValue.Length / sizeof(WCHAR)] = L'\0';
166 }
167
168 return (VarValue.Length / sizeof(WCHAR));
169 }
170
171
172 /*
173 * @implemented
174 */
175 BOOL
176 STDCALL
177 SetEnvironmentVariableA (
178 LPCSTR lpName,
179 LPCSTR lpValue
180 )
181 {
182 ANSI_STRING VarName;
183 ANSI_STRING VarValue;
184 UNICODE_STRING VarNameU;
185 UNICODE_STRING VarValueU;
186 NTSTATUS Status;
187
188 DPRINT("SetEnvironmentVariableA(Name '%s', Value '%s')\n", lpName, lpValue);
189
190 RtlInitAnsiString (&VarName,
191 (LPSTR)lpName);
192 RtlAnsiStringToUnicodeString (&VarNameU,
193 &VarName,
194 TRUE);
195
196 RtlInitAnsiString (&VarValue,
197 (LPSTR)lpValue);
198 RtlAnsiStringToUnicodeString (&VarValueU,
199 &VarValue,
200 TRUE);
201
202 Status = RtlSetEnvironmentVariable (NULL,
203 &VarNameU,
204 &VarValueU);
205
206 RtlFreeUnicodeString (&VarNameU);
207 RtlFreeUnicodeString (&VarValueU);
208
209 if (!NT_SUCCESS(Status))
210 {
211 SetLastErrorByStatus (Status);
212 return FALSE;
213 }
214
215 return TRUE;
216 }
217
218
219 /*
220 * @implemented
221 */
222 BOOL
223 STDCALL
224 SetEnvironmentVariableW (
225 LPCWSTR lpName,
226 LPCWSTR lpValue
227 )
228 {
229 UNICODE_STRING VarName;
230 UNICODE_STRING VarValue;
231 NTSTATUS Status;
232
233 DPRINT("SetEnvironmentVariableW(Name '%S', Value '%S')\n", lpName, lpValue);
234
235 RtlInitUnicodeString (&VarName,
236 lpName);
237
238 RtlInitUnicodeString (&VarValue,
239 lpValue);
240
241 Status = RtlSetEnvironmentVariable (NULL,
242 &VarName,
243 &VarValue);
244 if (!NT_SUCCESS(Status))
245 {
246 SetLastErrorByStatus (Status);
247 return FALSE;
248 }
249
250 return TRUE;
251 }
252
253
254 /*
255 * @implemented
256 */
257 LPSTR
258 STDCALL
259 GetEnvironmentStringsA (
260 VOID
261 )
262 {
263 UNICODE_STRING UnicodeString;
264 ANSI_STRING AnsiString;
265 PWCHAR EnvU;
266 PWCHAR PtrU;
267 ULONG Length;
268 PCHAR EnvPtr = NULL;
269
270 EnvU = (PWCHAR)(NtCurrentPeb ()->ProcessParameters->Environment);
271
272 if (EnvU == NULL)
273 return NULL;
274
275 if (*EnvU == 0)
276 return NULL;
277
278 /* get environment size */
279 PtrU = EnvU;
280 while (*PtrU)
281 {
282 while (*PtrU)
283 PtrU++;
284 PtrU++;
285 }
286 Length = (ULONG)(PtrU - EnvU);
287 DPRINT("Length %lu\n", Length);
288
289 /* allocate environment buffer */
290 EnvPtr = RtlAllocateHeap (RtlGetProcessHeap (),
291 0,
292 Length + 1);
293 DPRINT("EnvPtr %p\n", EnvPtr);
294
295 /* convert unicode environment to ansi */
296 UnicodeString.MaximumLength = Length * sizeof(WCHAR) + sizeof(WCHAR);
297 UnicodeString.Buffer = EnvU;
298
299 AnsiString.MaximumLength = Length + 1;
300 AnsiString.Length = 0;
301 AnsiString.Buffer = EnvPtr;
302
303 DPRINT ("UnicodeString.Buffer \'%S\'\n", UnicodeString.Buffer);
304
305 while (*(UnicodeString.Buffer))
306 {
307 UnicodeString.Length = wcslen (UnicodeString.Buffer) * sizeof(WCHAR);
308 UnicodeString.MaximumLength = UnicodeString.Length + sizeof(WCHAR);
309 if (UnicodeString.Length > 0)
310 {
311 AnsiString.Length = 0;
312 AnsiString.MaximumLength = Length + 1 - (AnsiString.Buffer - EnvPtr);
313
314 RtlUnicodeStringToAnsiString (&AnsiString,
315 &UnicodeString,
316 FALSE);
317
318 AnsiString.Buffer += (AnsiString.Length + 1);
319 UnicodeString.Buffer += ((UnicodeString.Length / sizeof(WCHAR)) + 1);
320 }
321 }
322 *(AnsiString.Buffer) = 0;
323
324 return EnvPtr;
325 }
326
327
328 /*
329 * @implemented
330 */
331 LPWSTR
332 STDCALL
333 GetEnvironmentStringsW (
334 VOID
335 )
336 {
337 return (LPWSTR)(NtCurrentPeb ()->ProcessParameters->Environment);
338 }
339
340
341 /*
342 * @implemented
343 */
344 BOOL
345 STDCALL
346 FreeEnvironmentStringsA (
347 LPSTR EnvironmentStrings
348 )
349 {
350 if (EnvironmentStrings == NULL)
351 return FALSE;
352
353 RtlFreeHeap (RtlGetProcessHeap (),
354 0,
355 EnvironmentStrings);
356
357 return TRUE;
358 }
359
360
361 /*
362 * @implemented
363 */
364 BOOL
365 STDCALL
366 FreeEnvironmentStringsW (
367 LPWSTR EnvironmentStrings
368 )
369 {
370 (void)EnvironmentStrings;
371 return TRUE;
372 }
373
374
375 /*
376 * @implemented
377 */
378 DWORD
379 STDCALL
380 ExpandEnvironmentStringsA (
381 LPCSTR lpSrc,
382 LPSTR lpDst,
383 DWORD nSize
384 )
385 {
386 ANSI_STRING Source;
387 ANSI_STRING Destination;
388 UNICODE_STRING SourceU;
389 UNICODE_STRING DestinationU;
390 NTSTATUS Status;
391 ULONG Length = 0;
392
393 RtlInitAnsiString (&Source,
394 (LPSTR)lpSrc);
395 RtlAnsiStringToUnicodeString (&SourceU,
396 &Source,
397 TRUE);
398
399 Destination.Length = 0;
400 Destination.MaximumLength = nSize;
401 Destination.Buffer = lpDst;
402
403 DestinationU.Length = 0;
404 DestinationU.MaximumLength = nSize * sizeof(WCHAR);
405 DestinationU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
406 0,
407 DestinationU.MaximumLength);
408
409 Status = RtlExpandEnvironmentStrings_U (NULL,
410 &SourceU,
411 &DestinationU,
412 &Length);
413
414 RtlFreeUnicodeString (&SourceU);
415
416 if (!NT_SUCCESS(Status))
417 {
418 SetLastErrorByStatus (Status);
419 if (Status != STATUS_BUFFER_TOO_SMALL)
420 {
421 RtlFreeHeap (RtlGetProcessHeap (),
422 0,
423 DestinationU.Buffer);
424 return 0;
425 }
426 }
427
428 RtlUnicodeStringToAnsiString (&Destination,
429 &DestinationU,
430 FALSE);
431
432 RtlFreeHeap (RtlGetProcessHeap (),
433 0,
434 DestinationU.Buffer);
435
436 return (Length / sizeof(WCHAR));
437 }
438
439
440 /*
441 * @implemented
442 */
443 DWORD
444 STDCALL
445 ExpandEnvironmentStringsW (
446 LPCWSTR lpSrc,
447 LPWSTR lpDst,
448 DWORD nSize
449 )
450 {
451 UNICODE_STRING Source;
452 UNICODE_STRING Destination;
453 NTSTATUS Status;
454 ULONG Length = 0;
455
456 RtlInitUnicodeString (&Source,
457 (LPWSTR)lpSrc);
458
459 Destination.Length = 0;
460 Destination.MaximumLength = nSize * sizeof(WCHAR);
461 Destination.Buffer = lpDst;
462
463 Status = RtlExpandEnvironmentStrings_U (NULL,
464 &Source,
465 &Destination,
466 &Length);
467 if (!NT_SUCCESS(Status))
468 {
469 SetLastErrorByStatus (Status);
470 if (Status != STATUS_BUFFER_TOO_SMALL)
471 return 0;
472 }
473
474 return (Length / sizeof(WCHAR));
475 }
476
477 /* EOF */