Bill Miller
Bill Miller

Reputation: 647

Getting Vista Folder Paths

Why will this not compile in Delphi 2009?

unit VistaFolders;

interface

uses Windows, ShellAPI, ShlObj;

type
  KNOWNFOLDERID = TGuid;

const
  FOLDERID_ProgramData: KNOWNFOLDERID =
    '{374DE290-123F-4565-9164-39C4925E467B}'; // downloads folder

var
  SHGetKnownFolderPathFunc: function( const rfid: KNOWNFOLDERID;
    dwFlags: DWORD; hToken: THandle; var ppszPath: PWideChar ): HResult; stdcall;
  SHGetKnownFolderIDListFunc: function( const rfid: KNOWNFOLDERID;
    dwFlags: DWORD; hToken: THandle; var ppidl: PItemIDList ): HResult; stdcall;

  function GetDownloadsFolderPath: string;

implementation

uses ActiveX;

function PathFromIDList( Pidl: ShlObj.PItemIdList ): string;
var
  Path: array[ 0..MAX_PATH ] of Char;
begin
  if SHGetPathFromIDList( Pidl, Path ) then
    Result := Path
  else
    Result := '';
end;

function GetDownloadsFolderPath: string;
var
  Path: PWideChar;
  Pidl: PItemIdList;
begin
  Result := '';
  if @SHGetKnownFolderPathFunc <> nil then
  begin
    if Succeeded( SHGetKnownFolderPathFunc( FOLDERID_ProgramData, 0, 0, Path ) ) then
      begin
        try
          Result := Path;
        finally; CoTaskMemFree( Path ); end;
        Exit;
      end;
  end
  else if @SHGetKnownFolderIDListFunc <> nil then
  begin
    if Succeeded( SHGetKnownFolderIDListFunc( FOLDERID_ProgramData, 0, 0, Pidl ) ) then
      begin
        try
          Result := PathFromIDList( Pidl );
        finally; CoTaskMemFree( Pidl ); end;
        Exit;
      end;
  end;
  if Succeeded( SHGetFolderLocation( 0, CSIDL_PROFILE, 0, 0, Pidl ) ) then
    try
      Result := PathFromIDList( Pidl ) + '\Downloads';
    finally; CoTaskMemFree( Pidl ); end;
end;

procedure InitVistaFunctions;
var
  hShell32: THandle;
begin
  hShell32 := GetModuleHandle( 'SHELL32' );
  @SHGetKnownFolderPathFunc := Windows.GetProcAddress( Shell32, 'SHGetKnownFolderPath' );
  @SHGetKnownFolderIDListFunc := Windows.GetProcAddress( Shell32, 'SHGetKnownFolderIDList' );
end;

initialization
  InitVistaFunctions;

end.

Upvotes: 1

Views: 3382

Answers (3)

Robbie Matthews
Robbie Matthews

Reputation: 1580

In Delphi 2010, all the SHGetKnownFile functions are defined in the unit "shlobj" The FOLDERID constants are in KnownFolders

Upvotes: 2

sergeantKK
sergeantKK

Reputation: 529

Just to notes for anyone else thinking of using the above code, Delphi 2010 (maybe 2009?) has a unit called KnownFolders.pas containing all the other FOLDERID_ constants eg: FOLDERID_RoamingAppData: TGUID = '{3EB685DB-65F9-4CF6-A03A-E3EF65729F3D}';

Upvotes: 3

mghie
mghie

Reputation: 32344

Because you give Shell32 instead of hShell32 in the GetProcAddress calls.

If you wonder why it fails with

There is no overloaded version of 'GetProcAddress' that can be called with these arguments

you could ctrl-click on the first parameter, and the IDE will take you to the constant that the compiler finds for Shell32.

Upvotes: 8

Related Questions