-/* $Id: env.c,v 1.2 2004/07/03 17:40:23 navaraf Exp $
- *
- * COPYRIGHT: See COPYING in the top level directory
+/* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: lib/rtl/env.c
* PURPOSE: Environment functions
* PROGRAMMER: Eric Kohl
- * UPDATE HISTORY:
- * Created 30/09/98
*/
/* INCLUDES ******************************************************************/
-#include <ddk/ntddk.h>
-#include <ntdll/rtl.h>
-#include <napi/teb.h>
-#include <string.h>
+#include <rtl.h>
#define NDEBUG
-#include <ntdll/ntdll.h>
+#include <debug.h>
+PPEB NTAPI RtlpCurrentPeb(VOID);
/* FUNCTIONS *****************************************************************/
/*
* @implemented
*/
-NTSTATUS STDCALL
+NTSTATUS NTAPI
RtlCreateEnvironment(BOOLEAN Inherit,
PWSTR *Environment)
{
/*
* @implemented
*/
-VOID STDCALL
+VOID NTAPI
RtlDestroyEnvironment(PWSTR Environment)
{
ULONG Size = 0;
NtFreeVirtualMemory(NtCurrentProcess(),
- (PVOID*)&Environment,
+ (PVOID)&Environment,
&Size,
MEM_RELEASE);
}
/*
* @implemented
*/
-NTSTATUS STDCALL
+NTSTATUS NTAPI
RtlExpandEnvironmentStrings_U(PWSTR Environment,
PUNICODE_STRING Source,
PUNICODE_STRING Destination,
PULONG Length)
{
- UNICODE_STRING var;
- UNICODE_STRING val;
- NTSTATUS Status = STATUS_SUCCESS;
- BOOLEAN flag = FALSE;
- PWSTR s;
- PWSTR d;
- PWSTR w;
- int src_len;
- int dst_max;
- int tail;
+ 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);
- src_len = Source->Length / sizeof(WCHAR);
- s = Source->Buffer;
- dst_max = Destination->MaximumLength / sizeof(WCHAR);
- d = Destination->Buffer;
+ SourceLength = Source->Length / sizeof(WCHAR);
+ SourceBuffer = Source->Buffer;
+ DestMax = Destination->MaximumLength / sizeof(WCHAR);
+ DestBuffer = Destination->Buffer;
- while (src_len)
+ while (SourceLength)
{
- if (*s == L'%')
+ if (*SourceBuffer != L'%')
+ {
+ CopyBuffer = SourceBuffer;
+ CopyLength = 0;
+ while (SourceLength != 0 && *SourceBuffer != L'%')
+ {
+ SourceBuffer++;
+ CopyLength++;
+ SourceLength--;
+ }
+ }
+ else
{
- if (flag)
+ /* Process environment variable. */
+
+ VariableEnd = SourceBuffer + 1;
+ Tail = SourceLength - 1;
+ while (*VariableEnd != L'%' && Tail != 0)
{
- flag = FALSE;
- goto copy;
+ VariableEnd++;
+ Tail--;
}
- w = s + 1;
- tail = src_len - 1;
- while (*w != L'%' && tail)
+
+ if (Tail != 0)
{
- w++;
- tail--;
+ Variable.MaximumLength =
+ Variable.Length = (VariableEnd - (SourceBuffer + 1)) * sizeof(WCHAR);
+ Variable.Buffer = SourceBuffer + 1;
+
+ Value.Length = 0;
+ Value.MaximumLength = 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;
+ }
}
- if (!tail)
- goto copy;
-
- var.Length = (w - ( s + 1)) * sizeof(WCHAR);
- var.MaximumLength = var.Length;
- var.Buffer = s + 1;
-
- val.Length = 0;
- val.MaximumLength = dst_max * sizeof(WCHAR);
- val.Buffer = d;
- Status = RtlQueryEnvironmentVariable_U (Environment, &var, &val);
- if (NT_SUCCESS(Status))
+ else
{
- d += val.Length / sizeof(WCHAR);
- dst_max -= val.Length / sizeof(WCHAR);
- s = w + 1;
- src_len = tail - 1;
- continue;
+ /* Unfinished variable name. */
+ CopyBuffer = SourceBuffer;
+ CopyLength = SourceLength;
+ SourceLength = 0;
}
- /* variable not found or buffer too small, just copy %var% */
- flag = TRUE;
}
-copy:
- if (!dst_max)
+
+ TotalLength += CopyLength;
+ if (DestMax)
{
- Status = STATUS_BUFFER_TOO_SMALL;
- break;
+ if (DestMax < CopyLength)
+ {
+ CopyLength = DestMax;
+ ReturnStatus = STATUS_BUFFER_TOO_SMALL;
+ }
+ RtlCopyMemory(DestBuffer, CopyBuffer, CopyLength * sizeof(WCHAR));
+ DestMax -= CopyLength;
+ DestBuffer += CopyLength;
}
-
- *d++ = *s++;
- dst_max--;
- src_len--;
}
- Destination->Length = (d - Destination->Buffer) * sizeof(WCHAR);
+ /* NULL-terminate the buffer. */
+ if (DestMax)
+ *DestBuffer = 0;
+ else
+ ReturnStatus = STATUS_BUFFER_TOO_SMALL;
+
+ Destination->Length = (DestBuffer - Destination->Buffer) * sizeof(WCHAR);
if (Length != NULL)
- *Length = Destination->Length;
- if (dst_max)
- Destination->Buffer[Destination->Length / sizeof(WCHAR)] = 0;
+ *Length = TotalLength * sizeof(WCHAR);
DPRINT("Destination %wZ\n", Destination);
- return(Status);
+
+ return ReturnStatus;
}
/*
* @implemented
*/
-VOID STDCALL
+VOID NTAPI
RtlSetCurrentEnvironment(PWSTR NewEnvironment,
PWSTR *OldEnvironment)
{
PVOID EnvPtr;
- DPRINT("NewEnvironment %x OldEnvironment %x\n",
+ DPRINT("NewEnvironment 0x%p OldEnvironment 0x%p\n",
NewEnvironment, OldEnvironment);
RtlAcquirePebLock();
/*
* @implemented
*/
-NTSTATUS STDCALL
+NTSTATUS NTAPI
RtlSetEnvironmentVariable(PWSTR *Environment,
PUNICODE_STRING Name,
PUNICODE_STRING Value)
DPRINT("RtlSetEnvironmentVariable(Environment %p Name %wZ Value %wZ)\n",
Environment, Name, Value);
+ /* 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;
}
found:
- if (Value->Length > 0)
+ if (Value != NULL && Value->Length > 0)
{
hole_len = tail - hole;
/* calculate new environment size */
{
/* reallocate memory area */
Status = NtAllocateVirtualMemory(NtCurrentProcess(),
- (VOID**)&new_env,
+ (PVOID)&new_env,
0,
&new_size,
MEM_RESERVE | MEM_COMMIT,
{
size = 0;
NtFreeVirtualMemory(NtCurrentProcess(),
- (PVOID*)&env,
+ (PVOID)&env,
&size,
MEM_RELEASE);
}
/*
* @implemented
*/
-NTSTATUS STDCALL
+NTSTATUS NTAPI
RtlQueryEnvironmentVariable_U(PWSTR Environment,
PUNICODE_STRING Name,
PUNICODE_STRING Value)
PWSTR wcs;
UNICODE_STRING var;
PWSTR val;
- int len;
BOOLEAN SysEnvUsed = FALSE;
DPRINT("RtlQueryEnvironmentVariable_U Environment %p Variable %wZ Value %p\n",
if (Environment == NULL)
{
- Environment = NtCurrentPeb()->ProcessParameters->Environment;
- SysEnvUsed = TRUE;
+ PPEB Peb = RtlpCurrentPeb();
+ if (Peb) {
+ Environment = Peb->ProcessParameters->Environment;
+ SysEnvUsed = TRUE;
+ }
}
if (Environment == NULL)
+ {
return(STATUS_VARIABLE_NOT_FOUND);
+ }
Value->Length = 0;
if (SysEnvUsed == TRUE)
RtlAcquirePebLock();
wcs = Environment;
- len = Name->Length / sizeof(WCHAR);
+ DPRINT("Starting search at :%p\n", wcs);
while (*wcs)
{
var.Buffer = wcs++;
if (wcs == NULL)
{
wcs = var.Buffer + wcslen(var.Buffer);
+ DPRINT("Search at :%S\n", wcs);
}
if (*wcs)
{
var.Length = var.MaximumLength = (wcs - var.Buffer) * sizeof(WCHAR);
val = ++wcs;
wcs += wcslen(wcs);
+ DPRINT("Search at :%S\n", wcs);
if (RtlEqualUnicodeString(&var, Name, TRUE))
{
Value->Length = (wcs - val) * sizeof(WCHAR);
- if (Value->Length < Value->MaximumLength)
+ if (Value->Length <= Value->MaximumLength)
{
- memcpy(Value->Buffer, val, Value->Length + sizeof(WCHAR));
+ memcpy(Value->Buffer, val,
+ min(Value->Length + sizeof(WCHAR), Value->MaximumLength));
DPRINT("Value %S\n", val);
DPRINT("Return STATUS_SUCCESS\n");
Status = STATUS_SUCCESS;
if (SysEnvUsed == TRUE)
RtlReleasePebLock();
- DPRINT("Return STATUS_VARIABLE_NOT_FOUND\n");
+ DPRINT("Return STATUS_VARIABLE_NOT_FOUND: %wZ\n", Name);
return(STATUS_VARIABLE_NOT_FOUND);
}