Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does SHParseDisplayName give an access violation if I've imported it myself?

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');
like image 351
user382591 Avatar asked Oct 11 '11 08:10

user382591


1 Answers

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.

like image 159
David Heffernan Avatar answered Sep 24 '22 16:09

David Heffernan