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