2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/kernel32/misc/env.c
5 * PURPOSE: Environment functions
6 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
13 /* INCLUDES *******************************************************************/
20 /* FUNCTIONS ******************************************************************/
27 GetEnvironmentVariableA(IN LPCSTR lpName
,
31 ANSI_STRING VarName
, VarValue
;
32 UNICODE_STRING VarNameU
, VarValueU
;
38 /* Initialize all the strings */
39 RtlInitAnsiString(&VarName
, lpName
);
40 RtlInitUnicodeString(&VarNameU
, NULL
);
41 RtlInitUnicodeString(&VarValueU
, NULL
);
42 Status
= RtlAnsiStringToUnicodeString(&VarNameU
, &VarName
, TRUE
);
43 if (!NT_SUCCESS(Status
)) goto Quickie
;
45 /* Check if the size is too big to fit */
46 UniSize
= UNICODE_STRING_MAX_CHARS
- 2;
49 /* It fits, but was there a string at all? */
52 /* Keep the given size, minus a NULL-char */
63 /* String is too big, so we need to return a NULL char as well */
67 /* Allocate the value string buffer */
68 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, UniSize
* sizeof(WCHAR
));
71 Status
= STATUS_NO_MEMORY
;
75 /* And initialize its string */
76 RtlInitEmptyUnicodeString(&VarValueU
, Buffer
, UniSize
* sizeof(WCHAR
));
78 /* Acquire the PEB lock since we'll be querying variables now */
81 /* Query the variable */
82 Status
= RtlQueryEnvironmentVariable_U(NULL
, &VarNameU
, &VarValueU
);
83 if ((NT_SUCCESS(Status
)) && !(nSize
)) Status
= STATUS_BUFFER_TOO_SMALL
;
85 /* Check if we didn't have enough space */
86 if (!(NT_SUCCESS(Status
)) && (Status
== STATUS_BUFFER_TOO_SMALL
))
88 /* Fixup the length that the API returned */
89 VarValueU
.MaximumLength
= VarValueU
.Length
+ 2;
91 /* Free old Unicode buffer */
92 RtlFreeHeap(RtlGetProcessHeap(), 0, VarValueU
.Buffer
);
94 /* Allocate new one */
95 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, VarValueU
.MaximumLength
);
98 /* Query the variable so we can know its size */
99 VarValueU
.Buffer
= Buffer
;
100 Status
= RtlQueryEnvironmentVariable_U(NULL
, &VarNameU
, &VarValueU
);
101 if (NT_SUCCESS(Status
))
103 /* Get the ASCII length of the variable */
104 Result
= RtlUnicodeStringToAnsiSize(&VarValueU
);
109 /* Set failure status */
110 Status
= STATUS_NO_MEMORY
;
113 else if (NT_SUCCESS(Status
))
115 /* Check if the size is too big to fit */
116 UniSize
= UNICODE_STRING_MAX_BYTES
- 1;
117 if (nSize
<= UniSize
) UniSize
= nSize
;
120 Result
= RtlUnicodeStringToAnsiSize(&VarValueU
);
121 if (Result
<= UniSize
)
123 /* Convert the string */
124 RtlInitEmptyAnsiString(&VarValue
, lpBuffer
, UniSize
);
125 Status
= RtlUnicodeStringToAnsiString(&VarValue
, &VarValueU
, FALSE
);
126 if (NT_SUCCESS(Status
))
128 /* NULL-terminate and set the final length */
129 lpBuffer
[VarValue
.Length
] = ANSI_NULL
;
130 Result
= VarValue
.Length
;
135 /* Release the lock */
139 /* Free the strings */
140 RtlFreeUnicodeString(&VarNameU
);
141 if (VarValueU
.Buffer
) RtlFreeHeap(RtlGetProcessHeap(), 0, VarValueU
.Buffer
);
143 /* Check if we suceeded */
144 if (!NT_SUCCESS(Status
))
146 /* We did not, clear the result and set the error code */
147 BaseSetLastNTError(Status
);
151 /* Return the result */
160 GetEnvironmentVariableW(IN LPCWSTR lpName
,
164 UNICODE_STRING VarName
, VarValue
;
168 if (nSize
<= (UNICODE_STRING_MAX_CHARS
- 1))
172 UniSize
= nSize
* sizeof(WCHAR
) - sizeof(UNICODE_NULL
);
181 UniSize
= UNICODE_STRING_MAX_BYTES
- sizeof(UNICODE_NULL
);
184 Status
= RtlInitUnicodeStringEx(&VarName
, lpName
);
185 if (!NT_SUCCESS(Status
))
187 BaseSetLastNTError(Status
);
191 RtlInitEmptyUnicodeString(&VarValue
, lpBuffer
, UniSize
);
193 Status
= RtlQueryEnvironmentVariable_U(NULL
, &VarName
, &VarValue
);
194 if (!NT_SUCCESS(Status
))
196 if (Status
== STATUS_BUFFER_TOO_SMALL
)
198 return (VarValue
.Length
/ sizeof(WCHAR
)) + sizeof(ANSI_NULL
);
200 BaseSetLastNTError (Status
);
204 lpBuffer
[VarValue
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
206 return (VarValue
.Length
/ sizeof(WCHAR
));
214 SetEnvironmentVariableA(IN LPCSTR lpName
,
217 ANSI_STRING VarName
, VarValue
;
218 UNICODE_STRING VarNameU
, VarValueU
;
221 RtlInitAnsiString(&VarName
, (LPSTR
)lpName
);
222 Status
= RtlAnsiStringToUnicodeString(&VarNameU
, &VarName
, TRUE
);
223 if (NT_SUCCESS(Status
))
227 RtlInitAnsiString(&VarValue
, (LPSTR
)lpValue
);
228 Status
= RtlAnsiStringToUnicodeString(&VarValueU
, &VarValue
, TRUE
);
229 if (NT_SUCCESS(Status
))
231 Status
= RtlSetEnvironmentVariable(NULL
, &VarNameU
, &VarValueU
);
232 RtlFreeUnicodeString(&VarValueU
);
237 Status
= RtlSetEnvironmentVariable(NULL
, &VarNameU
, NULL
);
240 RtlFreeUnicodeString(&VarNameU
);
242 if (NT_SUCCESS(Status
)) return TRUE
;
245 BaseSetLastNTError(Status
);
254 SetEnvironmentVariableW(IN LPCWSTR lpName
,
257 UNICODE_STRING VarName
, VarValue
;
260 Status
= RtlInitUnicodeStringEx(&VarName
, lpName
);
261 if (NT_SUCCESS(Status
))
265 Status
= RtlInitUnicodeStringEx(&VarValue
, lpValue
);
266 if (NT_SUCCESS(Status
))
268 Status
= RtlSetEnvironmentVariable(NULL
, &VarName
, &VarValue
);
273 Status
= RtlSetEnvironmentVariable(NULL
, &VarName
, NULL
);
276 if (NT_SUCCESS(Status
)) return TRUE
;
279 BaseSetLastNTError(Status
);
288 GetEnvironmentStringsA(VOID
)
292 PWCHAR Environment
, p
;
296 p
= Environment
= NtCurrentPeb()->ProcessParameters
->Environment
;
303 Length
= p
- Environment
+ 1;
305 Status
= RtlUnicodeToMultiByteSize(&Size
, Environment
, Length
* sizeof(WCHAR
));
306 if (NT_SUCCESS(Status
))
308 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Size
);
311 Status
= RtlUnicodeToOemN(Buffer
, Size
, 0, Environment
, Length
* sizeof(WCHAR
));
312 if (!NT_SUCCESS(Status
))
314 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
317 BaseSetLastNTError(Status
);
322 BaseSetLastNTError(STATUS_NO_MEMORY
);
327 BaseSetLastNTError(Status
);
339 GetEnvironmentStringsW(VOID
)
341 PWCHAR Environment
, p
;
346 p
= Environment
= NtCurrentPeb()->ProcessParameters
->Environment
;
353 Length
= p
- Environment
+ 1;
355 p
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Length
* sizeof(WCHAR
));
358 RtlCopyMemory(p
, Environment
, Length
* sizeof(WCHAR
));
362 BaseSetLastNTError(STATUS_NO_MEMORY
);
374 FreeEnvironmentStringsA(IN LPSTR EnvironmentStrings
)
376 return (BOOL
)RtlFreeHeap(RtlGetProcessHeap(), 0, EnvironmentStrings
);
384 FreeEnvironmentStringsW(IN LPWSTR EnvironmentStrings
)
386 return (BOOL
)RtlFreeHeap(RtlGetProcessHeap(), 0, EnvironmentStrings
);
394 ExpandEnvironmentStringsA(IN LPCSTR lpSrc
,
398 ANSI_STRING Source
, Dest
;
399 UNICODE_STRING SourceU
, DestU
;
401 ULONG Result
= 0, Length
;
405 /* Check if the size is too big to fit */
406 UniSize
= UNICODE_STRING_MAX_CHARS
- 2;
407 if (nSize
<= UniSize
) UniSize
= nSize
;
409 /* Clear the input buffer */
410 if (lpDst
) *lpDst
= ANSI_NULL
;
412 /* Initialize all the strings */
413 RtlInitAnsiString(&Source
, lpSrc
);
414 RtlInitUnicodeString(&SourceU
, NULL
);
415 RtlInitUnicodeString(&DestU
, NULL
);
416 Status
= RtlAnsiStringToUnicodeString(&SourceU
, &Source
, TRUE
);
417 if (!NT_SUCCESS(Status
)) goto Quickie
;
419 /* If the string fit in, make space for a NULL char */
426 /* No input size, so no string size */
430 /* Allocate the value string buffer */
431 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, UniSize
* sizeof(WCHAR
));
434 Status
= STATUS_NO_MEMORY
;
438 /* And initialize its string */
439 RtlInitEmptyUnicodeString(&DestU
, Buffer
, UniSize
* sizeof(WCHAR
));
441 /* Query the variable */
443 Status
= RtlExpandEnvironmentStrings_U(NULL
, &SourceU
, &DestU
, &Length
);
445 /* Check if we didn't have enough space */
446 if (!(NT_SUCCESS(Status
)) && (Status
== STATUS_BUFFER_TOO_SMALL
))
448 /* Fixup the length that the API returned */
449 DestU
.MaximumLength
= Length
;
451 /* Free old Unicode buffer */
452 RtlFreeHeap(RtlGetProcessHeap(), 0, DestU
.Buffer
);
454 /* Allocate new one */
455 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Length
);
458 /* Query the variable so we can know its size */
459 DestU
.Buffer
= Buffer
;
460 Status
= RtlExpandEnvironmentStrings_U(NULL
, &SourceU
, &DestU
, &Length
);
461 if (NT_SUCCESS(Status
))
463 /* Get the ASCII length of the variable, add a byte for NULL */
464 Result
= RtlUnicodeStringToAnsiSize(&DestU
) + sizeof(ANSI_NULL
);
469 /* Set failure status */
470 Status
= STATUS_NO_MEMORY
;
473 else if (NT_SUCCESS(Status
))
475 /* Check if the size is too big to fit */
476 UniSize
= UNICODE_STRING_MAX_BYTES
- 1;
477 if (nSize
<= UniSize
) UniSize
= nSize
;
480 Result
= RtlUnicodeStringToAnsiSize(&DestU
);
481 if (Result
<= UniSize
)
483 /* Convert the string */
484 RtlInitEmptyAnsiString(&Dest
, lpDst
, UniSize
);
485 Status
= RtlUnicodeStringToAnsiString(&Dest
, &DestU
, FALSE
);
487 /* Write a NULL-char in case of failure only */
488 if (!NT_SUCCESS(Status
)) *lpDst
= ANSI_NULL
;
492 /* Free the strings */
493 RtlFreeUnicodeString(&SourceU
);
494 if (DestU
.Buffer
) RtlFreeHeap(RtlGetProcessHeap(), 0, DestU
.Buffer
);
496 /* Check if we suceeded */
497 if (!NT_SUCCESS(Status
))
499 /* We did not, clear the result and set the error code */
500 BaseSetLastNTError(Status
);
504 /* Return the result */
513 ExpandEnvironmentStringsW(IN LPCWSTR lpSrc
,
517 UNICODE_STRING Source
, Destination
;
521 UniSize
= UNICODE_STRING_MAX_CHARS
- 2;
522 if (nSize
<= UniSize
) UniSize
= nSize
;
524 RtlInitUnicodeString(&Source
, (LPWSTR
)lpSrc
);
525 RtlInitEmptyUnicodeString(&Destination
, lpDst
, UniSize
* sizeof(WCHAR
));
527 Status
= RtlExpandEnvironmentStrings_U(NULL
,
531 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_BUFFER_TOO_SMALL
))
533 return nSize
/ sizeof(WCHAR
);
536 BaseSetLastNTError(Status
);
545 SetEnvironmentStringsA(IN LPCH NewEnvironment
)
556 SetEnvironmentStringsW(IN LPWCH NewEnvironment
)