mirror of
https://github.com/reactos/reactos.git
synced 2024-10-23 14:36:11 +00:00
[KERNEL32]: Rewrite (in some cases, simply clean-up) environment handling functions for better string handling, error codes, and performance. Part of ongoing kernel32 work.
svn path=/trunk/; revision=54274
This commit is contained in:
parent
bfc68fc3a1
commit
0bf4287f08
|
@ -24,489 +24,506 @@
|
||||||
*/
|
*/
|
||||||
DWORD
|
DWORD
|
||||||
WINAPI
|
WINAPI
|
||||||
GetEnvironmentVariableA (
|
GetEnvironmentVariableA(IN LPCSTR lpName,
|
||||||
LPCSTR lpName,
|
IN LPSTR lpBuffer,
|
||||||
LPSTR lpBuffer,
|
IN DWORD nSize)
|
||||||
DWORD nSize
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
ANSI_STRING VarName;
|
ANSI_STRING VarName, VarValue;
|
||||||
ANSI_STRING VarValue;
|
UNICODE_STRING VarNameU, VarValueU;
|
||||||
UNICODE_STRING VarNameU;
|
PWSTR Buffer;
|
||||||
UNICODE_STRING VarValueU;
|
ULONG Result = 0, UniSize = 0;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
/* initialize unicode variable name string */
|
/* Initialize all the strings */
|
||||||
RtlInitAnsiString (&VarName,
|
RtlInitAnsiString(&VarName, lpName);
|
||||||
(LPSTR)lpName);
|
RtlInitUnicodeString(&VarNameU, NULL);
|
||||||
RtlAnsiStringToUnicodeString (&VarNameU,
|
RtlInitUnicodeString(&VarValueU, NULL);
|
||||||
&VarName,
|
Status = RtlAnsiStringToUnicodeString(&VarNameU, &VarName, TRUE);
|
||||||
TRUE);
|
if (!NT_SUCCESS(Status)) goto Quickie;
|
||||||
|
|
||||||
/* initialize ansi variable value string */
|
/* Check if the size is too big to fit */
|
||||||
VarValue.Length = 0;
|
if (nSize <= UNICODE_STRING_MAX_BYTES)
|
||||||
VarValue.MaximumLength = (USHORT)nSize;
|
|
||||||
VarValue.Buffer = lpBuffer;
|
|
||||||
|
|
||||||
/* initialize unicode variable value string and allocate buffer */
|
|
||||||
VarValueU.Length = 0;
|
|
||||||
if (nSize != 0)
|
|
||||||
{
|
{
|
||||||
VarValueU.MaximumLength = (USHORT)(nSize - 1) * sizeof(WCHAR);
|
/* Keep the given size, minus a NULL-char */
|
||||||
VarValueU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
|
if (nSize) UniSize = nSize * sizeof(WCHAR) - sizeof(UNICODE_NULL);
|
||||||
0,
|
|
||||||
nSize * sizeof(WCHAR));
|
|
||||||
if (VarValueU.Buffer != NULL)
|
|
||||||
{
|
|
||||||
/* NULL-terminate the buffer in any case! RtlQueryEnvironmentVariable_U
|
|
||||||
only terminates it if MaximumLength < Length! */
|
|
||||||
VarValueU.Buffer[nSize - 1] = L'\0';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VarValueU.MaximumLength = 0;
|
/* Set the maximum possible */
|
||||||
VarValueU.Buffer = NULL;
|
UniSize = UNICODE_STRING_MAX_BYTES - sizeof(UNICODE_NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VarValueU.Buffer != NULL || nSize == 0)
|
/* Allocate the value string buffer */
|
||||||
|
Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, UniSize);
|
||||||
|
if (!Buffer)
|
||||||
{
|
{
|
||||||
/* get unicode environment variable */
|
Status = STATUS_NO_MEMORY;
|
||||||
Status = RtlQueryEnvironmentVariable_U (NULL,
|
goto Quickie;
|
||||||
&VarNameU,
|
}
|
||||||
&VarValueU);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
/* free unicode buffer */
|
|
||||||
RtlFreeHeap (RtlGetProcessHeap (),
|
|
||||||
0,
|
|
||||||
VarValueU.Buffer);
|
|
||||||
|
|
||||||
/* free unicode variable name string */
|
/* And initialize its string */
|
||||||
RtlFreeUnicodeString (&VarNameU);
|
RtlInitEmptyUnicodeString(&VarValueU, Buffer, UniSize);
|
||||||
|
|
||||||
BaseSetLastNTError (Status);
|
/* Acquire the PEB lock since we'll be querying variables now */
|
||||||
|
RtlAcquirePebLock();
|
||||||
|
|
||||||
|
/* Query the variable */
|
||||||
|
Status = RtlQueryEnvironmentVariable_U(NULL, &VarNameU, &VarValueU);
|
||||||
|
if ((NT_SUCCESS(Status)) && !(nSize)) Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
|
|
||||||
|
/* Check if we didn't have enough space */
|
||||||
if (Status == STATUS_BUFFER_TOO_SMALL)
|
if (Status == STATUS_BUFFER_TOO_SMALL)
|
||||||
{
|
{
|
||||||
return (VarValueU.Length / sizeof(WCHAR)) + 1;
|
/* Fixup the length that the API returned */
|
||||||
|
VarValueU.MaximumLength = VarValueU.Length + 2;
|
||||||
|
|
||||||
|
/* Free old Unicode buffer */
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, VarValueU.Buffer);
|
||||||
|
|
||||||
|
/* Allocate new one */
|
||||||
|
Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, VarValueU.MaximumLength);
|
||||||
|
if (Buffer)
|
||||||
|
{
|
||||||
|
/* Query the variable so we can know its size */
|
||||||
|
VarValueU.Buffer = Buffer;
|
||||||
|
Status = RtlQueryEnvironmentVariable_U(NULL, &VarNameU, &VarValueU);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Get the ASCII length of the variable */
|
||||||
|
Result = RtlUnicodeStringToAnsiSize(&VarValueU);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return 0;
|
/* Set failure status */
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
/* convert unicode value string to ansi */
|
|
||||||
RtlUnicodeStringToAnsiString (&VarValue,
|
|
||||||
&VarValueU,
|
|
||||||
FALSE);
|
|
||||||
|
|
||||||
if (VarValueU.Buffer != NULL)
|
|
||||||
{
|
{
|
||||||
/* free unicode buffer */
|
/* Check if the size is too big to fit */
|
||||||
RtlFreeHeap (RtlGetProcessHeap (),
|
if (nSize <= MAXULONG)
|
||||||
0,
|
{
|
||||||
VarValueU.Buffer);
|
/* Keep the given size, minus a NULL-char */
|
||||||
|
if (nSize) nSize = nSize - sizeof(ANSI_NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set the maximum possible */
|
||||||
|
nSize = MAXULONG - sizeof(ANSI_NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free unicode variable name string */
|
/* Check the size */
|
||||||
|
Result = RtlUnicodeStringToAnsiSize(&VarValueU);
|
||||||
|
if (Result <= nSize)
|
||||||
|
{
|
||||||
|
/* Convert the string */
|
||||||
|
RtlInitEmptyAnsiString(&VarValue, lpBuffer, nSize);
|
||||||
|
Status = RtlUnicodeStringToAnsiString(&VarValue, &VarValueU, FALSE);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* NULL-terminate and set the final length */
|
||||||
|
lpBuffer[VarValue.Length] = ANSI_NULL;
|
||||||
|
Result = VarValue.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release the lock */
|
||||||
|
RtlReleasePebLock();
|
||||||
|
|
||||||
|
Quickie:
|
||||||
|
/* Free the strings */
|
||||||
RtlFreeUnicodeString(&VarNameU);
|
RtlFreeUnicodeString(&VarNameU);
|
||||||
|
if (VarValueU.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, VarValueU.Buffer);
|
||||||
|
|
||||||
return (VarValueU.Length / sizeof(WCHAR));
|
/* Check if we suceeded */
|
||||||
}
|
if (!NT_SUCCESS(Status))
|
||||||
else
|
|
||||||
{
|
{
|
||||||
SetLastError (ERROR_NOT_ENOUGH_MEMORY);
|
/* We did not, clear the result and set the error code */
|
||||||
return 0;
|
BaseSetLastNTError(Status);
|
||||||
}
|
Result = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return the result */
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
DWORD
|
DWORD
|
||||||
WINAPI
|
WINAPI
|
||||||
GetEnvironmentVariableW (
|
GetEnvironmentVariableW(IN LPCWSTR lpName,
|
||||||
LPCWSTR lpName,
|
IN LPWSTR lpBuffer,
|
||||||
LPWSTR lpBuffer,
|
IN DWORD nSize)
|
||||||
DWORD nSize
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
UNICODE_STRING VarName;
|
UNICODE_STRING VarName, VarValue;
|
||||||
UNICODE_STRING VarValue;
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
RtlInitUnicodeString (&VarName,
|
if (nSize <= UNICODE_STRING_MAX_BYTES)
|
||||||
lpName);
|
{
|
||||||
|
if (nSize) nSize = nSize * sizeof(WCHAR) - sizeof(UNICODE_NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nSize = UNICODE_STRING_MAX_BYTES - sizeof(UNICODE_NULL);
|
||||||
|
}
|
||||||
|
|
||||||
VarValue.Length = 0;
|
Status = RtlInitUnicodeStringEx(&VarName, lpName);
|
||||||
VarValue.MaximumLength = (USHORT) (nSize ? nSize - 1 : 0) * sizeof(WCHAR);
|
if (NT_SUCCESS(Status))
|
||||||
VarValue.Buffer = lpBuffer;
|
{
|
||||||
|
RtlInitEmptyUnicodeString(&VarValue, lpBuffer, nSize);
|
||||||
|
|
||||||
Status = RtlQueryEnvironmentVariable_U (NULL,
|
Status = RtlQueryEnvironmentVariable_U(NULL, &VarName, &VarValue);
|
||||||
&VarName,
|
|
||||||
&VarValue);
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
if (Status == STATUS_BUFFER_TOO_SMALL)
|
if (Status == STATUS_BUFFER_TOO_SMALL)
|
||||||
{
|
{
|
||||||
return (VarValue.Length / sizeof(WCHAR)) + 1;
|
return (VarValue.Length / sizeof(WCHAR)) + sizeof(ANSI_NULL);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
BaseSetLastNTError (Status);
|
BaseSetLastNTError (Status);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (nSize != 0)
|
lpBuffer[VarValue.Length / sizeof(WCHAR)] = UNICODE_NULL;
|
||||||
{
|
|
||||||
/* make sure the string is NULL-terminated! RtlQueryEnvironmentVariable_U
|
|
||||||
only terminates it if MaximumLength < Length */
|
|
||||||
lpBuffer[VarValue.Length / sizeof(WCHAR)] = L'\0';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (VarValue.Length / sizeof(WCHAR));
|
return (VarValue.Length / sizeof(WCHAR));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
BOOL
|
BOOL
|
||||||
WINAPI
|
WINAPI
|
||||||
SetEnvironmentVariableA (
|
SetEnvironmentVariableA(IN LPCSTR lpName,
|
||||||
LPCSTR lpName,
|
IN LPCSTR lpValue)
|
||||||
LPCSTR lpValue
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
ANSI_STRING VarName;
|
ANSI_STRING VarName, VarValue;
|
||||||
ANSI_STRING VarValue;
|
UNICODE_STRING VarNameU, VarValueU;
|
||||||
UNICODE_STRING VarNameU;
|
|
||||||
UNICODE_STRING VarValueU;
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
DPRINT("SetEnvironmentVariableA(Name '%s', Value '%s')\n", lpName, lpValue);
|
RtlInitAnsiString(&VarName, (LPSTR)lpName);
|
||||||
|
Status = RtlAnsiStringToUnicodeString(&VarNameU, &VarName, TRUE);
|
||||||
RtlInitAnsiString (&VarName,
|
if (NT_SUCCESS(Status))
|
||||||
(LPSTR)lpName);
|
{
|
||||||
RtlAnsiStringToUnicodeString (&VarNameU,
|
|
||||||
&VarName,
|
|
||||||
TRUE);
|
|
||||||
|
|
||||||
if (lpValue)
|
if (lpValue)
|
||||||
{
|
{
|
||||||
RtlInitAnsiString (&VarValue,
|
RtlInitAnsiString(&VarValue, (LPSTR)lpValue);
|
||||||
(LPSTR)lpValue);
|
Status = RtlAnsiStringToUnicodeString(&VarValueU, &VarValue, TRUE);
|
||||||
RtlAnsiStringToUnicodeString (&VarValueU,
|
if (NT_SUCCESS(Status))
|
||||||
&VarValue,
|
{
|
||||||
TRUE);
|
Status = RtlSetEnvironmentVariable(NULL, &VarNameU, &VarValueU);
|
||||||
|
|
||||||
Status = RtlSetEnvironmentVariable (NULL,
|
|
||||||
&VarNameU,
|
|
||||||
&VarValueU);
|
|
||||||
|
|
||||||
RtlFreeUnicodeString(&VarValueU);
|
RtlFreeUnicodeString(&VarValueU);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Status = RtlSetEnvironmentVariable (NULL,
|
Status = RtlSetEnvironmentVariable(NULL, &VarNameU, NULL);
|
||||||
&VarNameU,
|
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RtlFreeUnicodeString(&VarNameU);
|
RtlFreeUnicodeString(&VarNameU);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status)) return TRUE;
|
||||||
{
|
}
|
||||||
|
|
||||||
BaseSetLastNTError(Status);
|
BaseSetLastNTError(Status);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
BOOL
|
BOOL
|
||||||
WINAPI
|
WINAPI
|
||||||
SetEnvironmentVariableW (
|
SetEnvironmentVariableW(IN LPCWSTR lpName,
|
||||||
LPCWSTR lpName,
|
IN LPCWSTR lpValue)
|
||||||
LPCWSTR lpValue
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
UNICODE_STRING VarName;
|
UNICODE_STRING VarName, VarValue;
|
||||||
UNICODE_STRING VarValue;
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
DPRINT("SetEnvironmentVariableW(Name '%S', Value '%S')\n", lpName, lpValue);
|
Status = RtlInitUnicodeStringEx(&VarName, lpName);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
RtlInitUnicodeString (&VarName,
|
|
||||||
lpName);
|
|
||||||
|
|
||||||
RtlInitUnicodeString (&VarValue,
|
|
||||||
lpValue);
|
|
||||||
|
|
||||||
Status = RtlSetEnvironmentVariable (NULL,
|
|
||||||
&VarName,
|
|
||||||
&VarValue);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
|
if (lpValue)
|
||||||
|
{
|
||||||
|
Status = RtlInitUnicodeStringEx(&VarValue, lpValue);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
Status = RtlSetEnvironmentVariable(NULL, &VarName, &VarValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Status = RtlSetEnvironmentVariable(NULL, &VarName, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Status)) return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
BaseSetLastNTError(Status);
|
BaseSetLastNTError(Status);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
LPSTR
|
LPSTR
|
||||||
WINAPI
|
WINAPI
|
||||||
GetEnvironmentStringsA (
|
GetEnvironmentStringsA(VOID)
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
UNICODE_STRING UnicodeString;
|
ULONG Length, Size;
|
||||||
ANSI_STRING AnsiString;
|
NTSTATUS Status;
|
||||||
PWCHAR EnvU;
|
PWCHAR Environment, p;
|
||||||
PWCHAR PtrU;
|
PCHAR Buffer = NULL;
|
||||||
ULONG Length;
|
|
||||||
PCHAR EnvPtr = NULL;
|
|
||||||
|
|
||||||
EnvU = (PWCHAR)(NtCurrentPeb ()->ProcessParameters->Environment);
|
RtlAcquirePebLock();
|
||||||
|
p = Environment = NtCurrentPeb()->ProcessParameters->Environment;
|
||||||
|
|
||||||
if (EnvU == NULL)
|
do
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (*EnvU == 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* get environment size */
|
|
||||||
PtrU = EnvU;
|
|
||||||
while (*PtrU)
|
|
||||||
{
|
{
|
||||||
while (*PtrU)
|
p += wcslen(Environment) + 1;
|
||||||
PtrU++;
|
} while (*p);
|
||||||
PtrU++;
|
|
||||||
}
|
|
||||||
Length = (ULONG)(PtrU - EnvU);
|
|
||||||
DPRINT("Length %lu\n", Length);
|
|
||||||
|
|
||||||
/* allocate environment buffer */
|
Length = p - Environment + sizeof(UNICODE_NULL);
|
||||||
EnvPtr = RtlAllocateHeap (RtlGetProcessHeap (),
|
|
||||||
0,
|
Status = RtlUnicodeToMultiByteSize(&Size, Environment, Length);
|
||||||
Length + 1);
|
if (NT_SUCCESS(Status))
|
||||||
if (EnvPtr == NULL)
|
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Size);
|
||||||
return NULL;
|
if (Buffer)
|
||||||
}
|
|
||||||
DPRINT("EnvPtr %p\n", EnvPtr);
|
|
||||||
|
|
||||||
/* convert unicode environment to ansi */
|
|
||||||
UnicodeString.MaximumLength = (USHORT)Length * sizeof(WCHAR) + sizeof(WCHAR);
|
|
||||||
UnicodeString.Buffer = EnvU;
|
|
||||||
|
|
||||||
AnsiString.MaximumLength = (USHORT)Length + 1;
|
|
||||||
AnsiString.Length = 0;
|
|
||||||
AnsiString.Buffer = EnvPtr;
|
|
||||||
|
|
||||||
DPRINT ("UnicodeString.Buffer \'%S\'\n", UnicodeString.Buffer);
|
|
||||||
|
|
||||||
while (*(UnicodeString.Buffer))
|
|
||||||
{
|
{
|
||||||
UnicodeString.Length = wcslen (UnicodeString.Buffer) * sizeof(WCHAR);
|
Status = RtlUnicodeToOemN(Buffer, Size, 0, Environment, Length);
|
||||||
UnicodeString.MaximumLength = UnicodeString.Length + sizeof(WCHAR);
|
if (!NT_SUCCESS(Status))
|
||||||
if (UnicodeString.Length > 0)
|
|
||||||
{
|
{
|
||||||
AnsiString.Length = 0;
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
|
||||||
AnsiString.MaximumLength = (USHORT)Length + 1 - (AnsiString.Buffer - EnvPtr);
|
Buffer = NULL;
|
||||||
|
|
||||||
RtlUnicodeStringToAnsiString (&AnsiString,
|
BaseSetLastNTError(Status);
|
||||||
&UnicodeString,
|
|
||||||
FALSE);
|
|
||||||
|
|
||||||
AnsiString.Buffer += (AnsiString.Length + 1);
|
|
||||||
UnicodeString.Buffer += ((UnicodeString.Length / sizeof(WCHAR)) + 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*(AnsiString.Buffer) = 0;
|
else
|
||||||
|
{
|
||||||
return EnvPtr;
|
BaseSetLastNTError(STATUS_NO_MEMORY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BaseSetLastNTError(Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RtlReleasePebLock();
|
||||||
|
return Buffer;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
LPWSTR
|
LPWSTR
|
||||||
WINAPI
|
WINAPI
|
||||||
GetEnvironmentStringsW (
|
GetEnvironmentStringsW(VOID)
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return (LPWSTR)(NtCurrentPeb ()->ProcessParameters->Environment);
|
PWCHAR Environment, p;
|
||||||
|
ULONG Length;
|
||||||
|
|
||||||
|
RtlAcquirePebLock();
|
||||||
|
|
||||||
|
p = Environment = NtCurrentPeb()->ProcessParameters->Environment;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p += wcslen(Environment) + 1;
|
||||||
|
} while (*p);
|
||||||
|
|
||||||
|
Length = p - Environment + sizeof(UNICODE_NULL);
|
||||||
|
|
||||||
|
p = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length);
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
RtlCopyMemory(p, Environment, Length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BaseSetLastNTError(STATUS_NO_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RtlReleasePebLock();
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
BOOL
|
BOOL
|
||||||
WINAPI
|
WINAPI
|
||||||
FreeEnvironmentStringsA (
|
FreeEnvironmentStringsA(IN LPSTR EnvironmentStrings)
|
||||||
LPSTR EnvironmentStrings
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (EnvironmentStrings == NULL)
|
return (BOOL)RtlFreeHeap(RtlGetProcessHeap(), 0, EnvironmentStrings);
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
RtlFreeHeap (RtlGetProcessHeap (),
|
|
||||||
0,
|
|
||||||
EnvironmentStrings);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
BOOL
|
BOOL
|
||||||
WINAPI
|
WINAPI
|
||||||
FreeEnvironmentStringsW (
|
FreeEnvironmentStringsW(IN LPWSTR EnvironmentStrings)
|
||||||
LPWSTR EnvironmentStrings
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return TRUE;
|
return (BOOL)RtlFreeHeap(RtlGetProcessHeap(), 0, EnvironmentStrings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
DWORD
|
DWORD
|
||||||
WINAPI
|
WINAPI
|
||||||
ExpandEnvironmentStringsA (
|
ExpandEnvironmentStringsA(IN LPCSTR lpSrc,
|
||||||
LPCSTR lpSrc,
|
IN LPSTR lpDst,
|
||||||
LPSTR lpDst,
|
IN DWORD nSize)
|
||||||
DWORD nSize
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
ANSI_STRING Source;
|
ANSI_STRING Source, Dest;
|
||||||
ANSI_STRING Destination;
|
UNICODE_STRING SourceU, DestU;
|
||||||
UNICODE_STRING SourceU;
|
PWSTR Buffer;
|
||||||
UNICODE_STRING DestinationU;
|
ULONG Result = 0, UniSize = 0, Length;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
ULONG Length = 0;
|
|
||||||
|
|
||||||
RtlInitAnsiString (&Source,
|
/* Initialize all the strings */
|
||||||
(LPSTR)lpSrc);
|
RtlInitAnsiString(&Source, lpSrc);
|
||||||
Status = RtlAnsiStringToUnicodeString (&SourceU,
|
RtlInitUnicodeString(&SourceU, NULL);
|
||||||
&Source,
|
RtlInitUnicodeString(&DestU, NULL);
|
||||||
TRUE);
|
Status = RtlAnsiStringToUnicodeString(&SourceU, &Source, TRUE);
|
||||||
|
if (!NT_SUCCESS(Status)) goto Quickie;
|
||||||
|
|
||||||
|
/* Check if the size is too big to fit */
|
||||||
|
if (nSize <= UNICODE_STRING_MAX_BYTES)
|
||||||
|
{
|
||||||
|
/* Keep the given size, minus a NULL-char */
|
||||||
|
if (nSize) UniSize = nSize * sizeof(WCHAR) - sizeof(UNICODE_NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set the maximum possible */
|
||||||
|
UniSize = UNICODE_STRING_MAX_BYTES - sizeof(UNICODE_NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate the value string buffer */
|
||||||
|
Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, UniSize);
|
||||||
|
if (!Buffer)
|
||||||
|
{
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And initialize its string */
|
||||||
|
RtlInitEmptyUnicodeString(&DestU, Buffer, UniSize);
|
||||||
|
|
||||||
|
/* Query the variable */
|
||||||
|
Length = 0;
|
||||||
|
Status = RtlExpandEnvironmentStrings_U(NULL, &SourceU, &DestU, &Length);
|
||||||
|
|
||||||
|
/* Check if we didn't have enough space */
|
||||||
|
if (Status == STATUS_BUFFER_TOO_SMALL)
|
||||||
|
{
|
||||||
|
/* Fixup the length that the API returned */
|
||||||
|
DestU.MaximumLength = Length;
|
||||||
|
|
||||||
|
/* Free old Unicode buffer */
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, DestU.Buffer);
|
||||||
|
|
||||||
|
/* Allocate new one */
|
||||||
|
Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length);
|
||||||
|
if (Buffer)
|
||||||
|
{
|
||||||
|
/* Query the variable so we can know its size */
|
||||||
|
DestU.Buffer = Buffer;
|
||||||
|
Status = RtlExpandEnvironmentStrings_U(NULL, &SourceU, &DestU, &Length);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Get the ASCII length of the variable */
|
||||||
|
Result = RtlUnicodeStringToAnsiSize(&DestU);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set failure status */
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Check if the size is too big to fit */
|
||||||
|
if (nSize <= MAXULONG)
|
||||||
|
{
|
||||||
|
/* Keep the given size, minus a NULL-char */
|
||||||
|
if (nSize) nSize = nSize - sizeof(ANSI_NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set the maximum possible */
|
||||||
|
nSize = MAXULONG - sizeof(ANSI_NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the size */
|
||||||
|
Result = RtlUnicodeStringToAnsiSize(&DestU);
|
||||||
|
if (Result <= nSize)
|
||||||
|
{
|
||||||
|
/* Convert the string */
|
||||||
|
RtlInitEmptyAnsiString(&Dest, lpDst, nSize);
|
||||||
|
Status = RtlUnicodeStringToAnsiString(&Dest, &DestU, FALSE);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
BaseSetLastNTError (Status);
|
/* Clear the destination */
|
||||||
return 0;
|
*lpDst = ANSI_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make sure we don't overflow the maximum ANSI_STRING size */
|
|
||||||
if (nSize > 0x7fff)
|
|
||||||
nSize = 0x7fff;
|
|
||||||
|
|
||||||
Destination.Length = 0;
|
|
||||||
Destination.MaximumLength = (USHORT)nSize;
|
|
||||||
Destination.Buffer = lpDst;
|
|
||||||
|
|
||||||
DestinationU.Length = 0;
|
|
||||||
DestinationU.MaximumLength = (USHORT)nSize * sizeof(WCHAR);
|
|
||||||
DestinationU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
|
|
||||||
0,
|
|
||||||
DestinationU.MaximumLength);
|
|
||||||
if (DestinationU.Buffer == NULL)
|
|
||||||
{
|
|
||||||
RtlFreeUnicodeString(&SourceU);
|
|
||||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Status = RtlExpandEnvironmentStrings_U (NULL,
|
Quickie:
|
||||||
&SourceU,
|
/* Free the strings */
|
||||||
&DestinationU,
|
|
||||||
&Length);
|
|
||||||
|
|
||||||
RtlFreeUnicodeString(&SourceU);
|
RtlFreeUnicodeString(&SourceU);
|
||||||
|
if (DestU.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, DestU.Buffer);
|
||||||
|
|
||||||
|
/* Check if we suceeded */
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
/* We did not, clear the result and set the error code */
|
||||||
BaseSetLastNTError(Status);
|
BaseSetLastNTError(Status);
|
||||||
if (Status != STATUS_BUFFER_TOO_SMALL)
|
Result = 0;
|
||||||
{
|
|
||||||
RtlFreeHeap (RtlGetProcessHeap (),
|
|
||||||
0,
|
|
||||||
DestinationU.Buffer);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RtlUnicodeStringToAnsiString (&Destination,
|
/* Return the result */
|
||||||
&DestinationU,
|
return Result;
|
||||||
FALSE);
|
|
||||||
|
|
||||||
RtlFreeHeap (RtlGetProcessHeap (),
|
|
||||||
0,
|
|
||||||
DestinationU.Buffer);
|
|
||||||
|
|
||||||
return (Length / sizeof(WCHAR));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
DWORD
|
DWORD
|
||||||
WINAPI
|
WINAPI
|
||||||
ExpandEnvironmentStringsW (
|
ExpandEnvironmentStringsW(IN LPCWSTR lpSrc,
|
||||||
LPCWSTR lpSrc,
|
IN LPWSTR lpDst,
|
||||||
LPWSTR lpDst,
|
IN DWORD nSize)
|
||||||
DWORD nSize
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
UNICODE_STRING Source;
|
UNICODE_STRING Source, Destination;
|
||||||
UNICODE_STRING Destination;
|
NTSTATUS Status;;
|
||||||
NTSTATUS Status;
|
|
||||||
ULONG Length = 0;
|
|
||||||
|
|
||||||
RtlInitUnicodeString (&Source,
|
RtlInitUnicodeString(&Source, (LPWSTR)lpSrc);
|
||||||
(LPWSTR)lpSrc);
|
|
||||||
|
|
||||||
/* make sure we don't overflow the maximum UNICODE_STRING size */
|
/* make sure we don't overflow the maximum UNICODE_STRING size */
|
||||||
if (nSize > 0x7fff)
|
if (nSize > UNICODE_STRING_MAX_BYTES) nSize = UNICODE_STRING_MAX_BYTES;
|
||||||
nSize = 0x7fff;
|
|
||||||
|
|
||||||
Destination.Length = 0;
|
|
||||||
Destination.MaximumLength = (USHORT)nSize * sizeof(WCHAR);
|
|
||||||
Destination.Buffer = lpDst;
|
|
||||||
|
|
||||||
|
RtlInitEmptyUnicodeString(&Destination, lpDst, nSize * sizeof(WCHAR));
|
||||||
Status = RtlExpandEnvironmentStrings_U(NULL,
|
Status = RtlExpandEnvironmentStrings_U(NULL,
|
||||||
&Source,
|
&Source,
|
||||||
&Destination,
|
&Destination,
|
||||||
&Length);
|
&nSize);
|
||||||
if (!NT_SUCCESS(Status))
|
if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_TOO_SMALL))
|
||||||
{
|
{
|
||||||
BaseSetLastNTError (Status);
|
return nSize / sizeof(WCHAR);
|
||||||
if (Status != STATUS_BUFFER_TOO_SMALL)
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (Length / sizeof(WCHAR));
|
BaseSetLastNTError (Status);
|
||||||
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in a new issue