Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594/* * 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 *****************************************************************/
NTSTATUSNTAPIRtlSetEnvironmentStrings(IN PWCHAR NewEnvironment, IN ULONG NewEnvironmentSize){ UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED;}
/* * @implemented */NTSTATUSNTAPIRtlCreateEnvironment( 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 NTAPIRtlDestroyEnvironment(PWSTR Environment){ SIZE_T Size = 0;
NtFreeVirtualMemory(NtCurrentProcess(), (PVOID)&Environment, &Size, MEM_RELEASE);}
/* * @implemented */NTSTATUS NTAPIRtlExpandEnvironmentStrings_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 NTAPIRtlSetCurrentEnvironment(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 NTAPIRtlSetEnvironmentVariable(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 NTAPIRtlQueryEnvironmentVariable_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 */