Oder wieso findete man das
SetLength(Expanded, 1);
dort?
Nja, und dann soll laut
MSDN die
ANSI-Version einen Bug haben (auch wenn er wohl spätestens im Win7 schon nicht mehr vorhanden zu sein scheint),
wonach dort der Buffer ein Byte größer sein muß.
Variante 1 nach
MSDN-Vorgaben und möglichst direkt in den Zielpuffer (Result-String).
OK, abgesehn von dem Bugfix für's
ANSI, aber FastMM wird die Speicherverwaltung optimieren und zu mindestens 99% nichts umkopieren.
Delphi-Quellcode:
function ExpandEnvironmentVars(
var Value:
string): Boolean;
var
R: Integer;
Expanded:
string;
begin
R := ExpandEnvironmentStrings(PChar(Value),
nil, 0);
if R = 0
then
Exit(False);
{$IFDEF UNICODE}
SetLength(Expanded, R - 1);
Result := ExpandEnvironmentStrings(PChar(Value), PChar(Expanded), R) = R;
{$ELSE}
SetLength(Expanded, R);
Result := ExpandEnvironmentStrings(PChar(Value), PChar(Expanded), R + 1) = R;
SetLength(Expanded, R - 1);
{$ENDIF}
if Result
then
Value := Expanded;
end;
Variante 1 ohne den Bugfix (für aktuellere Windowse):
Delphi-Quellcode:
function ExpandEnvironmentVars(var Value: string): Boolean;
var
R: Integer;
Expanded: string;
begin
R := ExpandEnvironmentStrings(PChar(Value), nil, 0);
if R = 0 then
Exit(False);
SetLength(Expanded, R - 1);
Result := ExpandEnvironmentStrings(PChar(Value), PChar(Expanded), R) = R;
if Result then
Value := Expanded;
end;
Variante 2 inkl. Bugfix und mit Zwischenpuffer auf'm Stack.
Delphi-Quellcode:
function ExpandEnvironmentVars(
var Value:
string): Boolean;
var
Buffer:
array[0..MAX_PATH]
of Char;
// maximal 32 KB
R: Integer;
begin
R := ExpandEnvironmentStrings(PChar(Value), @Buffer, MAX_PATH
{$IFDEF UNICODE}+ 1
{$ENDIF});
Result := (R > 0)
and (R < MAX_PATH);
if Result
then
SetString(Value, Buffer, R - 1);
end;
Da man die Umkehrfunktion sowieso nach Variante 2 bauen muß, könnte man Beides nach der gleichen Version deklarieren. (vorallem da es sich positiv auf den Bugfix auswirkt)