This is the complete code. No crashes or leaks:
program WideStringTest;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils, Winapi.ActiveX;
type
TEnumStringTestBase = class(TInterfacedObject, IEnumString)
function Next(celt: Longint; out elt; pceltFetched: PLongint): HResult; virtual; stdcall; abstract;
function Skip(celt: Longint): HResult; stdcall;
function Reset: HResult; stdcall;
function Clone(out enm: IEnumString): HResult; stdcall;
end;
TEnumStringTest1 = class(TEnumStringTestBase)
function Next(celt: Longint; out elt; pceltFetched: PLongint): HResult; override;
end;
TEnumStringTest2 = class(TEnumStringTestBase)
function Next(celt: Longint; out elt; pceltFetched: PLongint): HResult; override;
end;
function TEnumStringTestBase.Skip(celt: Longint): HResult; stdcall;
begin
Result := S_FALSE;
end;
function TEnumStringTestBase.Reset: HResult; stdcall;
begin
Result := S_OK;
end;
function TEnumStringTestBase.Clone(out enm: IEnumString): HResult; stdcall;
begin
Result := E_NOTIMPL;
end;
function TEnumStringTest1.Next(celt: Longint; out elt; pceltFetched: PLongint): HResult;
type
TPointerList = array[0..0] of Pointer;
var
i: Integer;
begin
i := 0;
while (i < celt) do
begin
{$RANGECHECKS OFF}
TPointerList(elt)[I] := nil;
WideString(TPointerList(elt)[I]) := 'test'+IntToStr(I);
Inc(i);
end;
if pceltFetched <> nil then
pceltFetched^ := i;
if i = celt then
Result := S_OK
else
Result := S_FALSE;
end;
function TEnumStringTest2.Next(celt: Longint; out elt; pceltFetched: PLongint): HResult;
type
TWideStringList = array[0..0] of WideString;
var
i: Integer;
begin
i := 0;
while (i < celt) do
begin
{$RANGECHECKS OFF}
Pointer(TWideStringList(elt)[I]) := nil;
TWideStringList(elt)[I] := 'test'+IntToStr(I);
Inc(i);
end;
if pceltFetched <> nil then
pceltFetched^ := i;
if i = celt then
Result := S_OK
else
Result := S_FALSE;
end;
var
Enum: IEnumString;
arr1: array[0..4] of TBstr;
arr2: array[0..4] of WideString;
I: Integer;
begin
Enum := TEnumStringTest1.Create;
Enum.Next(Length(arr1), arr1, nil);
for I := Low(arr1) to High(arr1) do
WriteLn(arr1[i]);
for I := Low(arr1) to High(arr1) do
SysFreeString(arr1[i]);
WriteLn;
Enum := TEnumStringTest2.Create;
Enum.Next(Length(arr2), arr2, nil);
for I := Low(arr2) to High(arr2) do
WriteLn(arr2[i]);
ReadLn;
end.