mirror of
https://github.com/reactos/reactos.git
synced 2025-06-25 13:49:43 +00:00
Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers into modules, and delete rossubsys.
This commit is contained in:
parent
b94e2d8ca0
commit
c2c66aff7d
24198 changed files with 0 additions and 37285 deletions
593
sdk/lib/rtl/env.c
Normal file
593
sdk/lib/rtl/env.c
Normal file
|
@ -0,0 +1,593 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* FILE: lib/rtl/env.c
|
||||
* PURPOSE: Environment functions
|
||||
* PROGRAMMER: Eric Kohl
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <rtl.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RtlSetEnvironmentStrings(IN PWCHAR NewEnvironment, IN ULONG NewEnvironmentSize)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RtlCreateEnvironment(
|
||||
BOOLEAN Inherit,
|
||||
PWSTR *OutEnvironment)
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION MemInfo;
|
||||
PVOID CurrentEnvironment, NewEnvironment = NULL;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
SIZE_T RegionSize = PAGE_SIZE;
|
||||
|
||||
/* Check if we should inherit the current environment */
|
||||
if (Inherit)
|
||||
{
|
||||
/* In this case we need to lock the PEB */
|
||||
RtlAcquirePebLock();
|
||||
|
||||
/* Get a pointer to the current Environment and check if it's not NULL */
|
||||
CurrentEnvironment = NtCurrentPeb()->ProcessParameters->Environment;
|
||||
if (CurrentEnvironment != NULL)
|
||||
{
|
||||
/* Query the size of the current environment allocation */
|
||||
Status = NtQueryVirtualMemory(NtCurrentProcess(),
|
||||
CurrentEnvironment,
|
||||
MemoryBasicInformation,
|
||||
&MemInfo,
|
||||
sizeof(MEMORY_BASIC_INFORMATION),
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
RtlReleasePebLock();
|
||||
*OutEnvironment = NULL;
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Allocate a new region of the same size */
|
||||
RegionSize = MemInfo.RegionSize;
|
||||
Status = NtAllocateVirtualMemory(NtCurrentProcess(),
|
||||
&NewEnvironment,
|
||||
0,
|
||||
&RegionSize,
|
||||
MEM_RESERVE | MEM_COMMIT,
|
||||
PAGE_READWRITE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
RtlReleasePebLock();
|
||||
*OutEnvironment = NULL;
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Copy the current environment */
|
||||
RtlCopyMemory(NewEnvironment,
|
||||
CurrentEnvironment,
|
||||
MemInfo.RegionSize);
|
||||
}
|
||||
|
||||
/* We are done with the PEB, release the lock */
|
||||
RtlReleasePebLock ();
|
||||
}
|
||||
|
||||
/* Check if we still need an environment */
|
||||
if (NewEnvironment == NULL)
|
||||
{
|
||||
/* Allocate a new environment */
|
||||
Status = NtAllocateVirtualMemory(NtCurrentProcess(),
|
||||
&NewEnvironment,
|
||||
0,
|
||||
&RegionSize,
|
||||
MEM_RESERVE | MEM_COMMIT,
|
||||
PAGE_READWRITE);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
RtlZeroMemory(NewEnvironment, RegionSize);
|
||||
}
|
||||
}
|
||||
|
||||
*OutEnvironment = NewEnvironment;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID NTAPI
|
||||
RtlDestroyEnvironment(PWSTR Environment)
|
||||
{
|
||||
SIZE_T Size = 0;
|
||||
|
||||
NtFreeVirtualMemory(NtCurrentProcess(),
|
||||
(PVOID)&Environment,
|
||||
&Size,
|
||||
MEM_RELEASE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS NTAPI
|
||||
RtlExpandEnvironmentStrings_U(PWSTR Environment,
|
||||
PUNICODE_STRING Source,
|
||||
PUNICODE_STRING Destination,
|
||||
PULONG Length)
|
||||
{
|
||||
UNICODE_STRING Variable;
|
||||
UNICODE_STRING Value;
|
||||
NTSTATUS ReturnStatus = STATUS_SUCCESS;
|
||||
NTSTATUS Status;
|
||||
PWSTR SourceBuffer;
|
||||
PWSTR DestBuffer;
|
||||
PWSTR CopyBuffer;
|
||||
PWSTR VariableEnd;
|
||||
ULONG SourceLength;
|
||||
ULONG DestMax;
|
||||
ULONG CopyLength;
|
||||
ULONG Tail;
|
||||
ULONG TotalLength = 1; /* for terminating NULL */
|
||||
|
||||
DPRINT("RtlExpandEnvironmentStrings_U %p %wZ %p %p\n",
|
||||
Environment, Source, Destination, Length);
|
||||
|
||||
SourceLength = Source->Length / sizeof(WCHAR);
|
||||
SourceBuffer = Source->Buffer;
|
||||
DestMax = Destination->MaximumLength / sizeof(WCHAR);
|
||||
DestBuffer = Destination->Buffer;
|
||||
|
||||
while (SourceLength)
|
||||
{
|
||||
if (*SourceBuffer != L'%')
|
||||
{
|
||||
CopyBuffer = SourceBuffer;
|
||||
CopyLength = 0;
|
||||
while (SourceLength != 0 && *SourceBuffer != L'%')
|
||||
{
|
||||
SourceBuffer++;
|
||||
CopyLength++;
|
||||
SourceLength--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Process environment variable. */
|
||||
|
||||
VariableEnd = SourceBuffer + 1;
|
||||
Tail = SourceLength - 1;
|
||||
while (*VariableEnd != L'%' && Tail != 0)
|
||||
{
|
||||
VariableEnd++;
|
||||
Tail--;
|
||||
}
|
||||
|
||||
if (Tail != 0)
|
||||
{
|
||||
Variable.MaximumLength =
|
||||
Variable.Length = (USHORT)(VariableEnd - (SourceBuffer + 1)) * sizeof(WCHAR);
|
||||
Variable.Buffer = SourceBuffer + 1;
|
||||
|
||||
Value.Length = 0;
|
||||
Value.MaximumLength = (USHORT)DestMax * sizeof(WCHAR);
|
||||
Value.Buffer = DestBuffer;
|
||||
|
||||
Status = RtlQueryEnvironmentVariable_U(Environment, &Variable,
|
||||
&Value);
|
||||
if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_TOO_SMALL)
|
||||
{
|
||||
SourceBuffer = VariableEnd + 1;
|
||||
SourceLength = Tail - 1;
|
||||
TotalLength += Value.Length / sizeof(WCHAR);
|
||||
if (Status != STATUS_BUFFER_TOO_SMALL)
|
||||
{
|
||||
DestBuffer += Value.Length / sizeof(WCHAR);
|
||||
DestMax -= Value.Length / sizeof(WCHAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
DestMax = 0;
|
||||
ReturnStatus = STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Variable not found. */
|
||||
CopyBuffer = SourceBuffer;
|
||||
CopyLength = SourceLength - Tail + 1;
|
||||
SourceLength -= CopyLength;
|
||||
SourceBuffer += CopyLength;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unfinished variable name. */
|
||||
CopyBuffer = SourceBuffer;
|
||||
CopyLength = SourceLength;
|
||||
SourceLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
TotalLength += CopyLength;
|
||||
if (DestMax)
|
||||
{
|
||||
if (DestMax < CopyLength)
|
||||
{
|
||||
CopyLength = DestMax;
|
||||
ReturnStatus = STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
RtlCopyMemory(DestBuffer, CopyBuffer, CopyLength * sizeof(WCHAR));
|
||||
DestMax -= CopyLength;
|
||||
DestBuffer += CopyLength;
|
||||
}
|
||||
}
|
||||
|
||||
/* NULL-terminate the buffer. */
|
||||
if (DestMax)
|
||||
*DestBuffer = 0;
|
||||
else
|
||||
ReturnStatus = STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
Destination->Length = (USHORT)(DestBuffer - Destination->Buffer) * sizeof(WCHAR);
|
||||
if (Length != NULL)
|
||||
*Length = TotalLength * sizeof(WCHAR);
|
||||
|
||||
DPRINT("Destination %wZ\n", Destination);
|
||||
|
||||
return ReturnStatus;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID NTAPI
|
||||
RtlSetCurrentEnvironment(PWSTR NewEnvironment,
|
||||
PWSTR *OldEnvironment)
|
||||
{
|
||||
PVOID EnvPtr;
|
||||
|
||||
DPRINT("NewEnvironment 0x%p OldEnvironment 0x%p\n",
|
||||
NewEnvironment, OldEnvironment);
|
||||
|
||||
RtlAcquirePebLock();
|
||||
|
||||
EnvPtr = NtCurrentPeb()->ProcessParameters->Environment;
|
||||
NtCurrentPeb()->ProcessParameters->Environment = NewEnvironment;
|
||||
|
||||
if (OldEnvironment != NULL)
|
||||
*OldEnvironment = EnvPtr;
|
||||
|
||||
RtlReleasePebLock();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS NTAPI
|
||||
RtlSetEnvironmentVariable(PWSTR *Environment,
|
||||
PUNICODE_STRING Name,
|
||||
PUNICODE_STRING Value)
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
UNICODE_STRING var;
|
||||
size_t hole_len, new_len, env_len = 0;
|
||||
WCHAR *new_env = 0, *env_end = 0, *wcs, *env, *val = 0, *tail = 0, *hole = 0;
|
||||
PWSTR head = NULL;
|
||||
SIZE_T size = 0, new_size;
|
||||
LONG f = 1;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
DPRINT("RtlSetEnvironmentVariable(Environment %p Name %wZ Value %wZ)\n",
|
||||
Environment, Name, Value);
|
||||
|
||||
/* Variable name must not be empty */
|
||||
if (Name->Length < sizeof(WCHAR))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* Variable names can't contain a '=' except as a first character. */
|
||||
for (wcs = Name->Buffer + 1;
|
||||
wcs < Name->Buffer + (Name->Length / sizeof(WCHAR));
|
||||
wcs++)
|
||||
{
|
||||
if (*wcs == L'=')
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (Environment)
|
||||
{
|
||||
env = *Environment;
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlAcquirePebLock();
|
||||
env = NtCurrentPeb()->ProcessParameters->Environment;
|
||||
}
|
||||
|
||||
if (env)
|
||||
{
|
||||
/* get environment length */
|
||||
wcs = env_end = env;
|
||||
do
|
||||
{
|
||||
env_end += wcslen(env_end) + 1;
|
||||
}
|
||||
while (*env_end);
|
||||
env_end++;
|
||||
env_len = env_end - env;
|
||||
DPRINT("environment length %lu characters\n", env_len);
|
||||
|
||||
/* find where to insert */
|
||||
while (*wcs)
|
||||
{
|
||||
var.Buffer = wcs++;
|
||||
wcs = wcschr(wcs, L'=');
|
||||
if (wcs == NULL)
|
||||
{
|
||||
wcs = var.Buffer + wcslen(var.Buffer);
|
||||
}
|
||||
if (*wcs)
|
||||
{
|
||||
var.Length = (USHORT)(wcs - var.Buffer) * sizeof(WCHAR);
|
||||
var.MaximumLength = var.Length;
|
||||
val = ++wcs;
|
||||
wcs += wcslen(wcs);
|
||||
f = RtlCompareUnicodeString(&var, Name, TRUE);
|
||||
if (f >= 0)
|
||||
{
|
||||
if (f) /* Insert before found */
|
||||
{
|
||||
hole = tail = var.Buffer;
|
||||
}
|
||||
else /* Exact match */
|
||||
{
|
||||
head = var.Buffer;
|
||||
tail = ++wcs;
|
||||
hole = val;
|
||||
}
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
wcs++;
|
||||
}
|
||||
hole = tail = wcs; /* Append to environment */
|
||||
}
|
||||
|
||||
found:
|
||||
if (Value != NULL && Value->Buffer != NULL)
|
||||
{
|
||||
hole_len = tail - hole;
|
||||
/* calculate new environment size */
|
||||
new_size = Value->Length + sizeof(WCHAR);
|
||||
/* adding new variable */
|
||||
if (f)
|
||||
new_size += Name->Length + sizeof(WCHAR);
|
||||
new_len = new_size / sizeof(WCHAR);
|
||||
if (hole_len < new_len)
|
||||
{
|
||||
/* enlarge environment size */
|
||||
/* check the size of available memory */
|
||||
new_size += (env_len - hole_len) * sizeof(WCHAR);
|
||||
new_size = ROUND_UP(new_size, PAGE_SIZE);
|
||||
mbi.RegionSize = 0;
|
||||
DPRINT("new_size %lu\n", new_size);
|
||||
|
||||
if (env)
|
||||
{
|
||||
Status = NtQueryVirtualMemory(NtCurrentProcess(),
|
||||
env,
|
||||
MemoryBasicInformation,
|
||||
&mbi,
|
||||
sizeof(MEMORY_BASIC_INFORMATION),
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
if (Environment == NULL)
|
||||
{
|
||||
RtlReleasePebLock();
|
||||
}
|
||||
return(Status);
|
||||
}
|
||||
}
|
||||
|
||||
if (new_size > mbi.RegionSize)
|
||||
{
|
||||
/* reallocate memory area */
|
||||
Status = NtAllocateVirtualMemory(NtCurrentProcess(),
|
||||
(PVOID)&new_env,
|
||||
0,
|
||||
&new_size,
|
||||
MEM_RESERVE | MEM_COMMIT,
|
||||
PAGE_READWRITE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
if (Environment == NULL)
|
||||
{
|
||||
RtlReleasePebLock();
|
||||
}
|
||||
return(Status);
|
||||
}
|
||||
|
||||
if (env)
|
||||
{
|
||||
memmove(new_env,
|
||||
env,
|
||||
(hole - env) * sizeof(WCHAR));
|
||||
hole = new_env + (hole - env);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* absolutely new environment */
|
||||
tail = hole = new_env;
|
||||
*hole = 0;
|
||||
env_end = hole + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* move tail */
|
||||
memmove (hole + new_len, tail, (env_end - tail) * sizeof(WCHAR));
|
||||
|
||||
if (new_env)
|
||||
{
|
||||
/* we reallocated environment, let's free the old one */
|
||||
if (Environment)
|
||||
*Environment = new_env;
|
||||
else
|
||||
NtCurrentPeb()->ProcessParameters->Environment = new_env;
|
||||
|
||||
if (env)
|
||||
{
|
||||
size = 0;
|
||||
NtFreeVirtualMemory(NtCurrentProcess(),
|
||||
(PVOID)&env,
|
||||
&size,
|
||||
MEM_RELEASE);
|
||||
}
|
||||
}
|
||||
|
||||
/* and now copy given stuff */
|
||||
if (f)
|
||||
{
|
||||
/* copy variable name and '=' character */
|
||||
memmove(hole,
|
||||
Name->Buffer,
|
||||
Name->Length);
|
||||
hole += Name->Length / sizeof(WCHAR);
|
||||
*hole++ = L'=';
|
||||
}
|
||||
|
||||
/* copy value */
|
||||
memmove(hole,
|
||||
Value->Buffer,
|
||||
Value->Length);
|
||||
hole += Value->Length / sizeof(WCHAR);
|
||||
*hole = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* remove the environment variable */
|
||||
if (f == 0)
|
||||
{
|
||||
memmove(head,
|
||||
tail,
|
||||
(env_end - tail) * sizeof(WCHAR));
|
||||
}
|
||||
}
|
||||
|
||||
if (Environment == NULL)
|
||||
{
|
||||
RtlReleasePebLock();
|
||||
}
|
||||
|
||||
return(Status);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS NTAPI
|
||||
RtlQueryEnvironmentVariable_U(PWSTR Environment,
|
||||
PCUNICODE_STRING Name,
|
||||
PUNICODE_STRING Value)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PWSTR wcs;
|
||||
UNICODE_STRING var;
|
||||
PWSTR val;
|
||||
BOOLEAN SysEnvUsed = FALSE;
|
||||
|
||||
DPRINT("RtlQueryEnvironmentVariable_U Environment %p Variable %wZ Value %p\n",
|
||||
Environment, Name, Value);
|
||||
|
||||
if (Environment == NULL)
|
||||
{
|
||||
PPEB Peb = RtlGetCurrentPeb();
|
||||
if (Peb) {
|
||||
RtlAcquirePebLock();
|
||||
Environment = Peb->ProcessParameters->Environment;
|
||||
SysEnvUsed = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (Environment == NULL)
|
||||
{
|
||||
if (SysEnvUsed)
|
||||
RtlReleasePebLock();
|
||||
return(STATUS_VARIABLE_NOT_FOUND);
|
||||
}
|
||||
|
||||
Value->Length = 0;
|
||||
|
||||
wcs = Environment;
|
||||
DPRINT("Starting search at :%p\n", wcs);
|
||||
while (*wcs)
|
||||
{
|
||||
var.Buffer = wcs++;
|
||||
wcs = wcschr(wcs, L'=');
|
||||
if (wcs == NULL)
|
||||
{
|
||||
wcs = var.Buffer + wcslen(var.Buffer);
|
||||
DPRINT("Search at :%S\n", wcs);
|
||||
}
|
||||
if (*wcs)
|
||||
{
|
||||
var.Length = var.MaximumLength = (USHORT)(wcs - var.Buffer) * sizeof(WCHAR);
|
||||
val = ++wcs;
|
||||
wcs += wcslen(wcs);
|
||||
DPRINT("Search at :%S\n", wcs);
|
||||
|
||||
if (RtlEqualUnicodeString(&var, Name, TRUE))
|
||||
{
|
||||
Value->Length = (USHORT)(wcs - val) * sizeof(WCHAR);
|
||||
if (Value->Length <= Value->MaximumLength)
|
||||
{
|
||||
memcpy(Value->Buffer, val,
|
||||
min(Value->Length + sizeof(WCHAR), Value->MaximumLength));
|
||||
DPRINT("Value %S\n", val);
|
||||
DPRINT("Return STATUS_SUCCESS\n");
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("Return STATUS_BUFFER_TOO_SMALL\n");
|
||||
Status = STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
if (SysEnvUsed)
|
||||
RtlReleasePebLock();
|
||||
|
||||
return(Status);
|
||||
}
|
||||
}
|
||||
wcs++;
|
||||
}
|
||||
|
||||
if (SysEnvUsed)
|
||||
RtlReleasePebLock();
|
||||
|
||||
DPRINT("Return STATUS_VARIABLE_NOT_FOUND: %wZ\n", Name);
|
||||
return(STATUS_VARIABLE_NOT_FOUND);
|
||||
}
|
||||
|
||||
/* EOF */
|
Loading…
Add table
Add a link
Reference in a new issue