1 /* $Id: environ.c 54459 2011-11-20 17:00:39Z pschweitzer $
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)
14 /* INCLUDES *******************************************************************/
21 /* FUNCTIONS ******************************************************************/
28 GetEnvironmentVariableA(IN LPCSTR lpName
,
32 ANSI_STRING VarName
, VarValue
;
33 UNICODE_STRING VarNameU
, VarValueU
;
39 /* Initialize all the strings */
40 RtlInitAnsiString(&VarName
, lpName
);
41 RtlInitUnicodeString(&VarNameU
, NULL
);
42 RtlInitUnicodeString(&VarValueU
, NULL
);
43 Status
= RtlAnsiStringToUnicodeString(&VarNameU
, &VarName
, TRUE
);
44 if (!NT_SUCCESS(Status
)) goto Quickie
;
46 /* Check if the size is too big to fit */
47 UniSize
= UNICODE_STRING_MAX_CHARS
- 2;
50 /* It fits, but was there a string at all? */
53 /* Keep the given size, minus a NULL-char */
64 /* String is too big, so we need to return a NULL char as well */
68 /* Allocate the value string buffer */
69 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, UniSize
* sizeof(WCHAR
));
72 Status
= STATUS_NO_MEMORY
;
76 /* And initialize its string */
77 RtlInitEmptyUnicodeString(&VarValueU
, Buffer
, UniSize
* sizeof(WCHAR
));
79 /* Acquire the PEB lock since we'll be querying variables now */
82 /* Query the variable */
83 Status
= RtlQueryEnvironmentVariable_U(NULL
, &VarNameU
, &VarValueU
);
84 if ((NT_SUCCESS(Status
)) && !(nSize
)) Status
= STATUS_BUFFER_TOO_SMALL
;
86 /* Check if we didn't have enough space */
87 if (!(NT_SUCCESS(Status
)) && (Status
== STATUS_BUFFER_TOO_SMALL
))
89 /* Fixup the length that the API returned */
90 VarValueU
.MaximumLength
= VarValueU
.Length
+ 2;
92 /* Free old Unicode buffer */
93 RtlFreeHeap(RtlGetProcessHeap(), 0, VarValueU
.Buffer
);
95 /* Allocate new one */
96 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, VarValueU
.MaximumLength
);
99 /* Query the variable so we can know its size */
100 VarValueU
.Buffer
= Buffer
;
101 Status
= RtlQueryEnvironmentVariable_U(NULL
, &VarNameU
, &VarValueU
);
102 if (NT_SUCCESS(Status
))
104 /* Get the ASCII length of the variable */
105 Result
= RtlUnicodeStringToAnsiSize(&VarValueU
);
110 /* Set failure status */
111 Status
= STATUS_NO_MEMORY
;
114 else if (NT_SUCCESS(Status
))
116 /* Check if the size is too big to fit */
117 UniSize
= UNICODE_STRING_MAX_BYTES
- 1;
118 if (nSize
<= UniSize
) UniSize
= nSize
;
121 Result
= RtlUnicodeStringToAnsiSize(&VarValueU
);
122 if (Result
<= UniSize
)
124 /* Convert the string */
125 RtlInitEmptyAnsiString(&VarValue
, lpBuffer
, UniSize
);
126 Status
= RtlUnicodeStringToAnsiString(&VarValue
, &VarValueU
, FALSE
);
127 if (NT_SUCCESS(Status
))
129 /* NULL-terminate and set the final length */
130 lpBuffer
[VarValue
.Length
] = ANSI_NULL
;
131 Result
= VarValue
.Length
;
136 /* Release the lock */
140 /* Free the strings */
141 RtlFreeUnicodeString(&VarNameU
);
142 if (VarValueU
.Buffer
) RtlFreeHeap(RtlGetProcessHeap(), 0, VarValueU
.Buffer
);
144 /* Check if we suceeded */
145 if (!NT_SUCCESS(Status
))
147 /* We did not, clear the result and set the error code */
148 BaseSetLastNTError(Status
);
152 /* Return the result */
161 GetEnvironmentVariableW(IN LPCWSTR lpName
,
165 UNICODE_STRING VarName
, VarValue
;
169 if (nSize
<= (UNICODE_STRING_MAX_CHARS
- 1))
173 UniSize
= nSize
* sizeof(WCHAR
) - sizeof(UNICODE_NULL
);
182 UniSize
= UNICODE_STRING_MAX_BYTES
- sizeof(UNICODE_NULL
);
185 Status
= RtlInitUnicodeStringEx(&VarName
, lpName
);
186 if (!NT_SUCCESS(Status
))
188 BaseSetLastNTError(Status
);
192 RtlInitEmptyUnicodeString(&VarValue
, lpBuffer
, UniSize
);
194 Status
= RtlQueryEnvironmentVariable_U(NULL
, &VarName
, &VarValue
);
195 if (!NT_SUCCESS(Status
))
197 if (Status
== STATUS_BUFFER_TOO_SMALL
)
199 return (VarValue
.Length
/ sizeof(WCHAR
)) + sizeof(ANSI_NULL
);
201 BaseSetLastNTError (Status
);
205 lpBuffer
[VarValue
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
207 return (VarValue
.Length
/ sizeof(WCHAR
));
215 SetEnvironmentVariableA(IN LPCSTR lpName
,
218 ANSI_STRING VarName
, VarValue
;
219 UNICODE_STRING VarNameU
, VarValueU
;
222 RtlInitAnsiString(&VarName
, (LPSTR
)lpName
);
223 Status
= RtlAnsiStringToUnicodeString(&VarNameU
, &VarName
, TRUE
);
224 if (NT_SUCCESS(Status
))
228 RtlInitAnsiString(&VarValue
, (LPSTR
)lpValue
);
229 Status
= RtlAnsiStringToUnicodeString(&VarValueU
, &VarValue
, TRUE
);
230 if (NT_SUCCESS(Status
))
232 Status
= RtlSetEnvironmentVariable(NULL
, &VarNameU
, &VarValueU
);
233 RtlFreeUnicodeString(&VarValueU
);
238 Status
= RtlSetEnvironmentVariable(NULL
, &VarNameU
, NULL
);
241 RtlFreeUnicodeString(&VarNameU
);
243 if (NT_SUCCESS(Status
)) return TRUE
;
246 BaseSetLastNTError(Status
);
255 SetEnvironmentVariableW(IN LPCWSTR lpName
,
258 UNICODE_STRING VarName
, VarValue
;
261 Status
= RtlInitUnicodeStringEx(&VarName
, lpName
);
262 if (NT_SUCCESS(Status
))
266 Status
= RtlInitUnicodeStringEx(&VarValue
, lpValue
);
267 if (NT_SUCCESS(Status
))
269 Status
= RtlSetEnvironmentVariable(NULL
, &VarName
, &VarValue
);
274 Status
= RtlSetEnvironmentVariable(NULL
, &VarName
, NULL
);
277 if (NT_SUCCESS(Status
)) return TRUE
;
280 BaseSetLastNTError(Status
);
289 GetEnvironmentStringsA(VOID
)
293 PWCHAR Environment
, p
;
297 p
= Environment
= NtCurrentPeb()->ProcessParameters
->Environment
;
304 Length
= p
- Environment
+ 1;
306 Status
= RtlUnicodeToMultiByteSize(&Size
, Environment
, Length
* sizeof(WCHAR
));
307 if (NT_SUCCESS(Status
))
309 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Size
);
312 Status
= RtlUnicodeToOemN(Buffer
, Size
, 0, Environment
, Length
* sizeof(WCHAR
));
313 if (!NT_SUCCESS(Status
))
315 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
318 BaseSetLastNTError(Status
);
323 BaseSetLastNTError(STATUS_NO_MEMORY
);
328 BaseSetLastNTError(Status
);
340 GetEnvironmentStringsW(VOID
)
342 PWCHAR Environment
, p
;
347 p
= Environment
= NtCurrentPeb()->ProcessParameters
->Environment
;
354 Length
= p
- Environment
+ 1;
356 p
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Length
* sizeof(WCHAR
));
359 RtlCopyMemory(p
, Environment
, Length
* sizeof(WCHAR
));
363 BaseSetLastNTError(STATUS_NO_MEMORY
);
375 FreeEnvironmentStringsA(IN LPSTR EnvironmentStrings
)
377 return (BOOL
)RtlFreeHeap(RtlGetProcessHeap(), 0, EnvironmentStrings
);
385 FreeEnvironmentStringsW(IN LPWSTR EnvironmentStrings
)
387 return (BOOL
)RtlFreeHeap(RtlGetProcessHeap(), 0, EnvironmentStrings
);
395 ExpandEnvironmentStringsA(IN LPCSTR lpSrc
,
399 ANSI_STRING Source
, Dest
;
400 UNICODE_STRING SourceU
, DestU
;
402 ULONG Result
= 0, Length
;
406 /* Check if the size is too big to fit */
407 UniSize
= UNICODE_STRING_MAX_CHARS
- 2;
408 if (nSize
<= UniSize
) UniSize
= nSize
;
410 /* Clear the input buffer */
411 if (lpDst
) *lpDst
= ANSI_NULL
;
413 /* Initialize all the strings */
414 RtlInitAnsiString(&Source
, lpSrc
);
415 RtlInitUnicodeString(&SourceU
, NULL
);
416 RtlInitUnicodeString(&DestU
, NULL
);
417 Status
= RtlAnsiStringToUnicodeString(&SourceU
, &Source
, TRUE
);
418 if (!NT_SUCCESS(Status
)) goto Quickie
;
420 /* If the string fit in, make space for a NULL char */
427 /* No input size, so no string size */
431 /* Allocate the value string buffer */
432 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, UniSize
* sizeof(WCHAR
));
435 Status
= STATUS_NO_MEMORY
;
439 /* And initialize its string */
440 RtlInitEmptyUnicodeString(&DestU
, Buffer
, UniSize
* sizeof(WCHAR
));
442 /* Query the variable */
444 Status
= RtlExpandEnvironmentStrings_U(NULL
, &SourceU
, &DestU
, &Length
);
446 /* Check if we didn't have enough space */
447 if (!(NT_SUCCESS(Status
)) && (Status
== STATUS_BUFFER_TOO_SMALL
))
449 /* Fixup the length that the API returned */
450 DestU
.MaximumLength
= Length
;
452 /* Free old Unicode buffer */
453 RtlFreeHeap(RtlGetProcessHeap(), 0, DestU
.Buffer
);
455 /* Allocate new one */
456 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Length
);
459 /* Query the variable so we can know its size */
460 DestU
.Buffer
= Buffer
;
461 Status
= RtlExpandEnvironmentStrings_U(NULL
, &SourceU
, &DestU
, &Length
);
462 if (NT_SUCCESS(Status
))
464 /* Get the ASCII length of the variable, add a byte for NULL */
465 Result
= RtlUnicodeStringToAnsiSize(&DestU
) + sizeof(ANSI_NULL
);
470 /* Set failure status */
471 Status
= STATUS_NO_MEMORY
;
474 else if (NT_SUCCESS(Status
))
476 /* Check if the size is too big to fit */
477 UniSize
= UNICODE_STRING_MAX_BYTES
- 1;
478 if (nSize
<= UniSize
) UniSize
= nSize
;
481 Result
= RtlUnicodeStringToAnsiSize(&DestU
);
482 if (Result
<= UniSize
)
484 /* Convert the string */
485 RtlInitEmptyAnsiString(&Dest
, lpDst
, UniSize
);
486 Status
= RtlUnicodeStringToAnsiString(&Dest
, &DestU
, FALSE
);
488 /* Write a NULL-char in case of failure only */
489 if (!NT_SUCCESS(Status
)) *lpDst
= ANSI_NULL
;
493 /* Free the strings */
494 RtlFreeUnicodeString(&SourceU
);
495 if (DestU
.Buffer
) RtlFreeHeap(RtlGetProcessHeap(), 0, DestU
.Buffer
);
497 /* Check if we suceeded */
498 if (!NT_SUCCESS(Status
))
500 /* We did not, clear the result and set the error code */
501 BaseSetLastNTError(Status
);
505 /* Return the result */
514 ExpandEnvironmentStringsW(IN LPCWSTR lpSrc
,
518 UNICODE_STRING Source
, Destination
;
522 UniSize
= UNICODE_STRING_MAX_CHARS
- 2;
523 if (nSize
<= UniSize
) UniSize
= nSize
;
525 RtlInitUnicodeString(&Source
, (LPWSTR
)lpSrc
);
526 RtlInitEmptyUnicodeString(&Destination
, lpDst
, UniSize
* sizeof(WCHAR
));
528 Status
= RtlExpandEnvironmentStrings_U(NULL
,
532 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_BUFFER_TOO_SMALL
))
534 return nSize
/ sizeof(WCHAR
);
537 BaseSetLastNTError(Status
);
546 SetEnvironmentStringsA(IN LPCH NewEnvironment
)
557 SetEnvironmentStringsW(IN LPWCH NewEnvironment
)