Link to home
Create AccountLog in
Avatar of thebeersmith
thebeersmith

asked on

Issues with SHGetPathFromiDList

I'm trying to pull the paths from an IDataObject, however the string added to the list is always empty. The following method is being called from "IShellExtInit.Initialize".

function ProcessItemIDListData(lpdobj: IDataObject; filesList: TStringList): HResult;
var
stgMedium: TStgMedium;
formatEtc: TFormatEtc;
i: integer;
lpIDA: PIDA;
lpRootPidl: PItemiDList;
lpPidl: PItemiDList;
lpFileName: array[0..MAX_PATH] of Char;
begin
    formatEtc.cfFormat := RegisterClipboardFormat(CFSTR_SHELLIDLIST);
    formatEtc.ptd := nil;
    formatEtc.dwAspect := DVASPECT_CONTENT;
    formatEtc.lindex := -1;
    formatEtc.tymed := TYMED_HGLOBAL;
    Result := lpdobj.GetData(formatEtc, stgMedium);

    if not Failed(Result) then
        begin
            try
                lpIDA := GlobalLock(stgMedium.hGlobal);
                try
                    lpRootPidl := PItemiDList(LPBYTE(lpIDA) + lpIDA.aoffset[0]);
                    for i := 1 to lpIDA.cidl do
                        begin
                            lpPidl := ILCombine(lpRootPidl, PItemiDList(LPBYTE(lpIDA) + lpIDA.aoffset[i]));
                            if lpPidl <> nil then
                                begin
                                    SHGetPathFromiDList(lpPidl, lpFileName);
                                    filesList.Add(StrPas(lpFileName));
                                end;
                        end;
                    Result := NOERROR;
                finally
                    GlobalUnlock(stgMedium.hGlobal);
                end;
            finally
                ReleaseStgMedium(stgMedium);
            end;
            Result := NOERROR;
        end;
end;

Open in new window


There are a few things I have noted.
1) SHGetPathFromiDList always returns false??
2) If I change the code to something like (where s is a string)
SetLength(s, 1024);
SHGetPathFromiDList(lpPidl, PChar(s));
filesList.Add(s);

Open in new window

I actually get a path for the object, except the string is not trimmed correctly (and I have also tried filesList.Add(StrPas(PChar(s))); etc)

Can anyone help, or point me in the right direction?

Thanks
SOLUTION
Avatar of mccarl
mccarl
Flag of Australia image

Link to home
membership
Create an account to see this answer
Signing up is free. No credit card required.
Create Account
if the SHGetPathFromIDList returns 0  (false), it has failed. the contents of the buffer you provided was not (likely to be) filled.

you may call GetLastError after call what should give a more specific error.

Sara
Avatar of thebeersmith
thebeersmith

ASKER

@Sara - Well that is what you would expect, however GetLastError reports "The operation completed successfully". This is why I removed the checking of the result (as a side note, all sample code I've looked at, in C++ and Delphi does not check the result of this call, which is odd)... this also does not explain why using the string method returns something... albeit a bit wacky.
SOLUTION
Link to home
membership
Create an account to see this answer
Signing up is free. No credit card required.
Create Account
@Sara - Thanks for the input. I'm using Delphi XE3 which supports unicode, and as such a PChar is in fact a PWideChar (so lpFileName is a PWideChar) and SHGetPathFromIDList is expecting PWideChar. The same is true of StrPas, this is overloaded to handle either ansi or unicode.
ASKER CERTIFIED SOLUTION
Link to home
membership
Create an account to see this answer
Signing up is free. No credit card required.
Create Account