- RtlExpandEnvironmentStrings_U and ExpandEnvironmentStrings[AW] should return the total length needed for the string with all the environment variables expanded.

svn path=/trunk/; revision=12363
This commit is contained in:
Filip Navara 2004-12-27 16:40:14 +00:00
parent ea579e1a95
commit 691f45eb54
2 changed files with 113 additions and 67 deletions

View file

@ -1,4 +1,4 @@
/* $Id: env.c,v 1.26 2004/12/18 21:06:25 gvg Exp $ /* $Id: env.c,v 1.27 2004/12/27 16:40:14 navaraf Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries * PROJECT: ReactOS system libraries
@ -581,7 +581,7 @@ ExpandEnvironmentStringsA (
Destination.Length = 0; Destination.Length = 0;
Destination.MaximumLength = nSize; Destination.MaximumLength = nSize;
Destination.Buffer = lpDst, Destination.Buffer = lpDst;
DestinationU.Length = 0; DestinationU.Length = 0;
DestinationU.MaximumLength = nSize * sizeof(WCHAR); DestinationU.MaximumLength = nSize * sizeof(WCHAR);
@ -598,11 +598,14 @@ ExpandEnvironmentStringsA (
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
RtlFreeHeap (RtlGetProcessHeap (),
0,
DestinationU.Buffer);
SetLastErrorByStatus (Status); SetLastErrorByStatus (Status);
return 0; if (Status != STATUS_BUFFER_TOO_SMALL)
{
RtlFreeHeap (RtlGetProcessHeap (),
0,
DestinationU.Buffer);
return 0;
}
} }
RtlUnicodeStringToAnsiString (&Destination, RtlUnicodeStringToAnsiString (&Destination,
@ -647,7 +650,8 @@ ExpandEnvironmentStringsW (
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
SetLastErrorByStatus (Status); SetLastErrorByStatus (Status);
return 0; if (Status != STATUS_BUFFER_TOO_SMALL)
return 0;
} }
return (Length / sizeof(WCHAR)); return (Length / sizeof(WCHAR));

View file

@ -1,4 +1,4 @@
/* $Id: env.c,v 1.3 2004/09/18 09:31:53 greatlrd Exp $ /* $Id: env.c,v 1.4 2004/12/27 16:40:14 navaraf Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries * PROJECT: ReactOS system libraries
@ -120,83 +120,125 @@ RtlExpandEnvironmentStrings_U(PWSTR Environment,
PUNICODE_STRING Destination, PUNICODE_STRING Destination,
PULONG Length) PULONG Length)
{ {
UNICODE_STRING var; UNICODE_STRING Variable;
UNICODE_STRING val; UNICODE_STRING Value;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS ReturnStatus = STATUS_SUCCESS;
BOOLEAN flag = FALSE; NTSTATUS Status;
PWSTR s; PWSTR SourceBuffer;
PWSTR d; PWSTR DestBuffer;
PWSTR w; PWSTR CopyBuffer;
int src_len; PWSTR VariableEnd;
int dst_max; ULONG SourceLength;
int tail; ULONG DestMax;
ULONG CopyLength;
ULONG Tail;
ULONG TotalLength = 1; /* for terminating NULL */
DPRINT("RtlExpandEnvironmentStrings_U %p %wZ %p %p\n", DPRINT("RtlExpandEnvironmentStrings_U %p %wZ %p %p\n",
Environment, Source, Destination, Length); Environment, Source, Destination, Length);
src_len = Source->Length / sizeof(WCHAR); SourceLength = Source->Length / sizeof(WCHAR);
s = Source->Buffer; SourceBuffer = Source->Buffer;
dst_max = Destination->MaximumLength / sizeof(WCHAR); DestMax = Destination->MaximumLength / sizeof(WCHAR);
d = Destination->Buffer; DestBuffer = Destination->Buffer;
while (src_len) while (SourceLength)
{ {
if (*s == L'%') if (*SourceBuffer != L'%')
{ {
if (flag) CopyBuffer = SourceBuffer;
CopyLength = 0;
while (SourceLength != 0 && *SourceBuffer != L'%')
{ {
flag = FALSE; SourceBuffer++;
goto copy; CopyLength++;
SourceLength--;
} }
w = s + 1;
tail = src_len - 1;
while (*w != L'%' && tail)
{
w++;
tail--;
}
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))
{
d += val.Length / sizeof(WCHAR);
dst_max -= val.Length / sizeof(WCHAR);
s = w + 1;
src_len = tail - 1;
continue;
}
/* variable not found or buffer too small, just copy %var% */
flag = TRUE;
} }
copy: else
if (!dst_max)
{ {
Status = STATUS_BUFFER_TOO_SMALL; /* Process environment variable. */
break;
VariableEnd = SourceBuffer + 1;
Tail = SourceLength - 1;
while (*VariableEnd != L'%' && Tail != 0)
{
VariableEnd++;
Tail--;
}
if (Tail != 0)
{
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;
}
}
else
{
/* Unfinished variable name. */
CopyBuffer = SourceBuffer;
CopyLength = SourceLength;
SourceLength = 0;
}
} }
*d++ = *s++; TotalLength += CopyLength;
dst_max--; if (DestMax)
src_len--; {
if (DestMax < CopyLength)
{
CopyLength = DestMax;
ReturnStatus = STATUS_BUFFER_TOO_SMALL;
}
RtlCopyMemory(DestBuffer, CopyBuffer, CopyLength * sizeof(WCHAR));
DestMax -= CopyLength;
DestBuffer += CopyLength;
}
} }
Destination->Length = (d - Destination->Buffer) * sizeof(WCHAR); /* NULL-terminate the buffer. */
if (DestMax)
*DestBuffer = 0;
Destination->Length = (DestBuffer - Destination->Buffer) * sizeof(WCHAR);
if (Length != NULL) if (Length != NULL)
*Length = Destination->Length; *Length = TotalLength * sizeof(WCHAR);
if (dst_max)
Destination->Buffer[Destination->Length / sizeof(WCHAR)] = 0;
DPRINT("Destination %wZ\n", Destination); DPRINT("Destination %wZ\n", Destination);
return(Status);
return ReturnStatus;
} }