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 */
53 UniSize
= (USHORT
)(nSize
- 1);
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 (Status
== STATUS_BUFFER_TOO_SMALL
)
88 /* Fixup the length that the API returned */
89 VarValueU
.MaximumLength
= VarValueU
.Length
+ sizeof(UNICODE_NULL
);
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
;
111 VarValueU
.Buffer
= NULL
;
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
= (USHORT
)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
= (USHORT
)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 RtlFreeHeap(RtlGetProcessHeap(), 0, EnvironmentStrings
);
385 FreeEnvironmentStringsW(IN LPWSTR EnvironmentStrings
)
387 return 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
= (USHORT
)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 (Status
== STATUS_BUFFER_TOO_SMALL
)
449 /* Fixup the length that the API returned */
450 DestU
.MaximumLength
= (SHORT
)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
;
475 else if (NT_SUCCESS(Status
))
477 /* Check if the size is too big to fit */
478 UniSize
= UNICODE_STRING_MAX_BYTES
- 1;
479 if (nSize
<= UniSize
) UniSize
= (USHORT
)nSize
;
482 Result
= RtlUnicodeStringToAnsiSize(&DestU
);
483 if (Result
<= UniSize
)
485 /* Convert the string */
486 RtlInitEmptyAnsiString(&Dest
, lpDst
, UniSize
);
487 Status
= RtlUnicodeStringToAnsiString(&Dest
, &DestU
, FALSE
);
489 /* Write a NULL-char in case of failure only */
490 if (!NT_SUCCESS(Status
)) *lpDst
= ANSI_NULL
;
494 /* Free the strings */
495 RtlFreeUnicodeString(&SourceU
);
496 if (DestU
.Buffer
) RtlFreeHeap(RtlGetProcessHeap(), 0, DestU
.Buffer
);
498 /* Check if we suceeded */
499 if (!NT_SUCCESS(Status
))
501 /* We did not, clear the result and set the error code */
502 BaseSetLastNTError(Status
);
506 /* Return the result */
515 ExpandEnvironmentStringsW(IN LPCWSTR lpSrc
,
519 UNICODE_STRING Source
, Destination
;
523 UniSize
= min(nSize
, UNICODE_STRING_MAX_CHARS
- 2);
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
)