Hi Tux,
Ok you twisted my arm


the following works for me without any AVs...
[pascal]
procedure TForm1.FormCreate( Sender : TObject );
var
pdnSPInfo : PDPN_SERVICE_PROVIDER_INFO;
pdnSPInfoEnum : PDPN_SERVICE_PROVIDER_INFO;
dwItems : DWord;
dwSize : DWord;
i : DWord;
strBuf : WideString;
hr : Cardinal;
begin
dwItems := 0;
dwSize := 0;

hr := CoCreateInstance( CLSID_DirectPlay8Peer, nil,
CLSCTX_INPROC_SERVER,
IID_IDirectPlay8Peer,
peer );
if hr = S_OK then
begin
hr := Peer.Initialize( nil, @DirectPlayMessageHandler, 0 );

if hr = S_OK then
begin
//Determine the required buffer size
Peer.EnumServiceProviders( nil, nil, nil, dwSize, dwItems, 0 );

GetMem( pdnSPInfo, dwSize );
try
//Fill the buffer with service provider information
Peer.EnumServiceProviders( nil, nil, pdnSPInfo, dwSize, dwItems, 0 );

// Print the provider descriptions
pdnSPInfoEnum := pdnSPInfo;

for i := 0 to dwItems - 1 do
begin
strBuf := WideString( pdnSPInfoEnum.pwszName );

ListBox1.Items.Add( strBuf );
Inc( pdnSPInfoEnum );
end;
finally
FreeMem( pdnSPInfo );
end;
end;
end;
if hr <> S_OK then
ShowMessage( DXErrorString( hr ) );
end;

procedure TForm1.FormDestroy( Sender : TObject );
begin
Peer.Close( 0 );
Peer := nil;
end;
[/pascal]

Delphi shields you from a lot of COM's nastiness so setting Peer to nil should be all that is necessary ( in this case ) for it to decrement the reference count and free the appropriate COM interface memory.

Also I would suggest checking the return values from most DirectX calls just to make sure your system is set up correctly, or that there is something else causing the error.