[KERNEL32]
[reactos.git] / reactos / dll / win32 / 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 <debug.h>
16
17
18 /* FUNCTIONS ******************************************************************/
19
20 /*
21 * @implemented
22 */
23 DWORD
24 WINAPI
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 = (USHORT)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 = (USHORT)(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 WINAPI
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 = (USHORT) (nSize ? nSize - 1 : 0) * sizeof(WCHAR);
143 VarValue.Buffer = lpBuffer;
144
145 Status = RtlQueryEnvironmentVariable_U (NULL,
146 &VarName,
147 &VarValue);
148 if (!NT_SUCCESS(Status))
149 {
150 if (Status == STATUS_BUFFER_TOO_SMALL)
151 {
152 return (VarValue.Length / sizeof(WCHAR)) + 1;
153 }
154 else
155 {
156 SetLastErrorByStatus (Status);
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 lpBuffer[VarValue.Length / sizeof(WCHAR)] = L'\0';
166 }
167
168 return (VarValue.Length / sizeof(WCHAR));
169 }
170
171
172 /*
173 * @implemented
174 */
175 BOOL
176 WINAPI
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 if (lpValue)
197 {
198 RtlInitAnsiString (&VarValue,
199 (LPSTR)lpValue);
200 RtlAnsiStringToUnicodeString (&VarValueU,
201 &VarValue,
202 TRUE);
203
204 Status = RtlSetEnvironmentVariable (NULL,
205 &VarNameU,
206 &VarValueU);
207
208 RtlFreeUnicodeString (&VarValueU);
209 }
210 else
211 {
212 Status = RtlSetEnvironmentVariable (NULL,
213 &VarNameU,
214 NULL);
215 }
216 RtlFreeUnicodeString (&VarNameU);
217
218 if (!NT_SUCCESS(Status))
219 {
220 SetLastErrorByStatus (Status);
221 return FALSE;
222 }
223
224 return TRUE;
225 }
226
227
228 /*
229 * @implemented
230 */
231 BOOL
232 WINAPI
233 SetEnvironmentVariableW (
234 LPCWSTR lpName,
235 LPCWSTR lpValue
236 )
237 {
238 UNICODE_STRING VarName;
239 UNICODE_STRING VarValue;
240 NTSTATUS Status;
241
242 DPRINT("SetEnvironmentVariableW(Name '%S', Value '%S')\n", lpName, lpValue);
243
244 RtlInitUnicodeString (&VarName,
245 lpName);
246
247 RtlInitUnicodeString (&VarValue,
248 lpValue);
249
250 Status = RtlSetEnvironmentVariable (NULL,
251 &VarName,
252 &VarValue);
253
254 if (!NT_SUCCESS(Status))
255 {
256 SetLastErrorByStatus (Status);
257 return FALSE;
258 }
259
260 return TRUE;
261 }
262
263
264 /*
265 * @implemented
266 */
267 LPSTR
268 WINAPI
269 GetEnvironmentStringsA (
270 VOID
271 )
272 {
273 UNICODE_STRING UnicodeString;
274 ANSI_STRING AnsiString;
275 PWCHAR EnvU;
276 PWCHAR PtrU;
277 ULONG Length;
278 PCHAR EnvPtr = NULL;
279
280 EnvU = (PWCHAR)(NtCurrentPeb ()->ProcessParameters->Environment);
281
282 if (EnvU == NULL)
283 return NULL;
284
285 if (*EnvU == 0)
286 return NULL;
287
288 /* get environment size */
289 PtrU = EnvU;
290 while (*PtrU)
291 {
292 while (*PtrU)
293 PtrU++;
294 PtrU++;
295 }
296 Length = (ULONG)(PtrU - EnvU);
297 DPRINT("Length %lu\n", Length);
298
299 /* allocate environment buffer */
300 EnvPtr = RtlAllocateHeap (RtlGetProcessHeap (),
301 0,
302 Length + 1);
303 if (EnvPtr == NULL)
304 {
305 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
306 return NULL;
307 }
308 DPRINT("EnvPtr %p\n", EnvPtr);
309
310 /* convert unicode environment to ansi */
311 UnicodeString.MaximumLength = (USHORT)Length * sizeof(WCHAR) + sizeof(WCHAR);
312 UnicodeString.Buffer = EnvU;
313
314 AnsiString.MaximumLength = (USHORT)Length + 1;
315 AnsiString.Length = 0;
316 AnsiString.Buffer = EnvPtr;
317
318 DPRINT ("UnicodeString.Buffer \'%S\'\n", UnicodeString.Buffer);
319
320 while (*(UnicodeString.Buffer))
321 {
322 UnicodeString.Length = wcslen (UnicodeString.Buffer) * sizeof(WCHAR);
323 UnicodeString.MaximumLength = UnicodeString.Length + sizeof(WCHAR);
324 if (UnicodeString.Length > 0)
325 {
326 AnsiString.Length = 0;
327 AnsiString.MaximumLength = (USHORT)Length + 1 - (AnsiString.Buffer - EnvPtr);
328
329 RtlUnicodeStringToAnsiString (&AnsiString,
330 &UnicodeString,
331 FALSE);
332
333 AnsiString.Buffer += (AnsiString.Length + 1);
334 UnicodeString.Buffer += ((UnicodeString.Length / sizeof(WCHAR)) + 1);
335 }
336 }
337 *(AnsiString.Buffer) = 0;
338
339 return EnvPtr;
340 }
341
342
343 /*
344 * @implemented
345 */
346 LPWSTR
347 WINAPI
348 GetEnvironmentStringsW (
349 VOID
350 )
351 {
352 return (LPWSTR)(NtCurrentPeb ()->ProcessParameters->Environment);
353 }
354
355
356 /*
357 * @implemented
358 */
359 BOOL
360 WINAPI
361 FreeEnvironmentStringsA (
362 LPSTR EnvironmentStrings
363 )
364 {
365 if (EnvironmentStrings == NULL)
366 return FALSE;
367
368 RtlFreeHeap (RtlGetProcessHeap (),
369 0,
370 EnvironmentStrings);
371
372 return TRUE;
373 }
374
375
376 /*
377 * @implemented
378 */
379 BOOL
380 WINAPI
381 FreeEnvironmentStringsW (
382 LPWSTR EnvironmentStrings
383 )
384 {
385 return TRUE;
386 }
387
388
389 /*
390 * @implemented
391 */
392 DWORD
393 WINAPI
394 ExpandEnvironmentStringsA (
395 LPCSTR lpSrc,
396 LPSTR lpDst,
397 DWORD nSize
398 )
399 {
400 ANSI_STRING Source;
401 ANSI_STRING Destination;
402 UNICODE_STRING SourceU;
403 UNICODE_STRING DestinationU;
404 NTSTATUS Status;
405 ULONG Length = 0;
406
407 RtlInitAnsiString (&Source,
408 (LPSTR)lpSrc);
409 Status = RtlAnsiStringToUnicodeString (&SourceU,
410 &Source,
411 TRUE);
412 if (!NT_SUCCESS(Status))
413 {
414 SetLastErrorByStatus (Status);
415 return 0;
416 }
417
418 /* make sure we don't overflow the maximum ANSI_STRING size */
419 if (nSize > 0x7fff)
420 nSize = 0x7fff;
421
422 Destination.Length = 0;
423 Destination.MaximumLength = (USHORT)nSize;
424 Destination.Buffer = lpDst;
425
426 DestinationU.Length = 0;
427 DestinationU.MaximumLength = (USHORT)nSize * sizeof(WCHAR);
428 DestinationU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
429 0,
430 DestinationU.MaximumLength);
431 if (DestinationU.Buffer == NULL)
432 {
433 RtlFreeUnicodeString(&SourceU);
434 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
435 return 0;
436 }
437
438 Status = RtlExpandEnvironmentStrings_U (NULL,
439 &SourceU,
440 &DestinationU,
441 &Length);
442
443 RtlFreeUnicodeString (&SourceU);
444
445 if (!NT_SUCCESS(Status))
446 {
447 SetLastErrorByStatus (Status);
448 if (Status != STATUS_BUFFER_TOO_SMALL)
449 {
450 RtlFreeHeap (RtlGetProcessHeap (),
451 0,
452 DestinationU.Buffer);
453 return 0;
454 }
455 }
456
457 RtlUnicodeStringToAnsiString (&Destination,
458 &DestinationU,
459 FALSE);
460
461 RtlFreeHeap (RtlGetProcessHeap (),
462 0,
463 DestinationU.Buffer);
464
465 return (Length / sizeof(WCHAR));
466 }
467
468
469 /*
470 * @implemented
471 */
472 DWORD
473 WINAPI
474 ExpandEnvironmentStringsW (
475 LPCWSTR lpSrc,
476 LPWSTR lpDst,
477 DWORD nSize
478 )
479 {
480 UNICODE_STRING Source;
481 UNICODE_STRING Destination;
482 NTSTATUS Status;
483 ULONG Length = 0;
484
485 RtlInitUnicodeString (&Source,
486 (LPWSTR)lpSrc);
487
488 /* make sure we don't overflow the maximum UNICODE_STRING size */
489 if (nSize > 0x7fff)
490 nSize = 0x7fff;
491
492 Destination.Length = 0;
493 Destination.MaximumLength = (USHORT)nSize * sizeof(WCHAR);
494 Destination.Buffer = lpDst;
495
496 Status = RtlExpandEnvironmentStrings_U (NULL,
497 &Source,
498 &Destination,
499 &Length);
500 if (!NT_SUCCESS(Status))
501 {
502 SetLastErrorByStatus (Status);
503 if (Status != STATUS_BUFFER_TOO_SMALL)
504 return 0;
505 }
506
507 return (Length / sizeof(WCHAR));
508 }
509
510 /* EOF */