diff --git a/reactos/lib/kernel32/misc/env.c b/reactos/lib/kernel32/misc/env.c index 477a3e4eace..cb0a3f2163c 100644 --- a/reactos/lib/kernel32/misc/env.c +++ b/reactos/lib/kernel32/misc/env.c @@ -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 * PROJECT: ReactOS system libraries @@ -581,7 +581,7 @@ ExpandEnvironmentStringsA ( Destination.Length = 0; Destination.MaximumLength = nSize; - Destination.Buffer = lpDst, + Destination.Buffer = lpDst; DestinationU.Length = 0; DestinationU.MaximumLength = nSize * sizeof(WCHAR); @@ -598,11 +598,14 @@ ExpandEnvironmentStringsA ( if (!NT_SUCCESS(Status)) { - RtlFreeHeap (RtlGetProcessHeap (), - 0, - DestinationU.Buffer); SetLastErrorByStatus (Status); - return 0; + if (Status != STATUS_BUFFER_TOO_SMALL) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + DestinationU.Buffer); + return 0; + } } RtlUnicodeStringToAnsiString (&Destination, @@ -647,7 +650,8 @@ ExpandEnvironmentStringsW ( if (!NT_SUCCESS(Status)) { SetLastErrorByStatus (Status); - return 0; + if (Status != STATUS_BUFFER_TOO_SMALL) + return 0; } return (Length / sizeof(WCHAR)); diff --git a/reactos/lib/rtl/env.c b/reactos/lib/rtl/env.c index 5300d8b1c32..06eeb68174a 100644 --- a/reactos/lib/rtl/env.c +++ b/reactos/lib/rtl/env.c @@ -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 * PROJECT: ReactOS system libraries @@ -120,83 +120,125 @@ RtlExpandEnvironmentStrings_U(PWSTR Environment, 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'%') { - if (flag) + CopyBuffer = SourceBuffer; + CopyLength = 0; + while (SourceLength != 0 && *SourceBuffer != L'%') { - flag = FALSE; - goto copy; + SourceBuffer++; + 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: - if (!dst_max) + else { - Status = STATUS_BUFFER_TOO_SMALL; - break; + /* Process environment variable. */ + + 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++; - dst_max--; - src_len--; + TotalLength += CopyLength; + if (DestMax) + { + 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) - *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; }