5

I get an access violation when trying to get a pidl form a path in Delphi, and the returned pidl is nil. This is my code:

type
  // TParseDisplayName = function(pszPath: PChar; pbc: pointer; var pidl: PItemIDList; sfgaoIn: LongWord; var psfgaoOut: LongWord): LongInt;
  TParseDisplayName = function(pszPath: PWideChar; pbc: IBindCtx; var pidl: PItemIDList; sfgaoIn: ULong; var psfgaoOut: ULong): HResult;

var
  SHParseDisplayName: TParseDisplayName;
  SHELL32DLLHandle : THandle;

procedure test();
var
  ws : WideString;
  tmpLongWord: ULong;
  lpItemID: PItemIDList;
begin
  //ws := 'Mes documents';

  CoInitialize(nil);

  // path to test
  ws := 'C:\inetsdk\Nouveau Document WordPad.doc';

  if (SHParseDisplayName(PWideChar(ws), nil, lpItemID, 0, tmpLongWord) = S_OK) then
    if not assigned(lpItemID) then      
      s := SysErrorMessage(getLastError);

  CoUnInitialize();
end;

initialization
  SHELL32DLLHandle  := LoadLibraryW('shell32.dll');

  @SHParseDisplayName := GetProcAddress(SHELL32DLLHandle, 'SHParseDisplayName');
Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
user382591
  • 1,320
  • 5
  • 19
  • 39

1 Answers1

6

The declaration of TParseDisplayName omits the calling convention. You need to include stdcall.

TParseDisplayName = function(pszPath: PWideChar; pbc: IBindCtx; 
  var pidl: PItemIDList; sfgaoIn: ULong; var psfgaoOut: ULong): HResult; stdcall;

When you don't specify a calling convention the default calling convention is used. The default calling convention is register. This has different semantics for parameter passing and clean up which leads to the type of runtime error you have experienced. Practically all Windows API functions used stdcall.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490