|
@@ -114,13 +114,14 @@ function GetIsFolder(AParent: IShellFolder; PIDL: PItemIDList): Boolean;
|
|
|
function GetDisplayName(AFolder: IShellFolder; PIDL: PItemIDList; Flags: DWORD): String;
|
|
|
function GetDisplayNameEx(AFolder: IShellFolder2; PIDL: PItemIDList; Flags: DWORD): String;
|
|
|
function GetDetails(AFolder: IShellFolder2; PIDL: PItemIDList; const pscid: SHCOLUMNID): OleVariant;
|
|
|
+function ParseDisplayName(Desktop: IShellFolder; const AName: String; out PIDL: PItemIDList): HRESULT;
|
|
|
|
|
|
function CreateDefaultContextMenu(constref pdcm: TDefContextMenu; const riid: REFIID; out ppv): HRESULT;
|
|
|
|
|
|
implementation
|
|
|
|
|
|
uses
|
|
|
- Variants, ShellApi, LazUTF8, DCConvertEncoding;
|
|
|
+ Variants, ShellApi, LazUTF8, DCConvertEncoding, DCStrUtils;
|
|
|
|
|
|
const
|
|
|
KF_FLAG_DEFAULT = $00000000;
|
|
@@ -189,6 +190,110 @@ begin
|
|
|
Result:= Unassigned;
|
|
|
end;
|
|
|
|
|
|
+function SplitParsingPath(const S: String): TStringArray;
|
|
|
+var
|
|
|
+ P: PAnsiChar;
|
|
|
+ AItem: String;
|
|
|
+ I, Len: Integer;
|
|
|
+ Start: Integer = 0;
|
|
|
+begin
|
|
|
+ I:= 0;
|
|
|
+ Len:= Length(S);
|
|
|
+ P:= PAnsiChar(S);
|
|
|
+ Result:= Default(TStringArray);
|
|
|
+ while I < Len do
|
|
|
+ begin
|
|
|
+ if P[I] = '\' then
|
|
|
+ begin
|
|
|
+ SetString(AItem, @P[Start], I - Start);
|
|
|
+ AddString(Result, AItem);
|
|
|
+ Start:= I + 1;
|
|
|
+ // Special case for "\\?\" and "\\.\"
|
|
|
+ if (P[I + 1] = '\') and (P[I + 2] = '\') and (P[I + 3] in ['?', '.']) and (P[I + 4] = '\') then
|
|
|
+ Inc(I, 4);
|
|
|
+ end;
|
|
|
+ Inc(I);
|
|
|
+ end;
|
|
|
+ if Start < Len then
|
|
|
+ begin
|
|
|
+ SetString(AItem, @P[Start], Len - Start);
|
|
|
+ AddString(Result, AItem);
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+function ParseDisplayName(Desktop: IShellFolder; const AName: String; out
|
|
|
+ PIDL: PItemIDList): HRESULT;
|
|
|
+var
|
|
|
+ AItem: String;
|
|
|
+ Index: Integer;
|
|
|
+ pchEaten: ULONG;
|
|
|
+ APath: TStringArray;
|
|
|
+ NumIDs: LongWord = 0;
|
|
|
+ dwAttributes: ULONG = 0;
|
|
|
+ EnumIDList: IEnumIDList;
|
|
|
+ ParentFolder, AFolder: IShellFolder;
|
|
|
+ ParentPIDL, RelativePIDL: PItemIDList;
|
|
|
+begin
|
|
|
+ APath:= SplitParsingPath(AName);
|
|
|
+
|
|
|
+ ParentFolder:= Desktop;
|
|
|
+ SHGetFolderLocation(0, CSIDL_DESKTOP, 0, 0, {%H-}ParentPIDL);
|
|
|
+
|
|
|
+ for Index:= 0 to High(APath) do
|
|
|
+ begin
|
|
|
+ dwAttributes:= 0;
|
|
|
+ AItem:= APath[Index];
|
|
|
+ Result:= ParentFolder.ParseDisplayName(0, nil, PWideChar(CeUtf8ToUtf16(AItem)), pchEaten, RelativePIDL, dwAttributes);
|
|
|
+
|
|
|
+ if Failed(Result) then
|
|
|
+ begin
|
|
|
+ Result:= ParentFolder.EnumObjects(0, SHCONTF_FOLDERS or SHCONTF_NONFOLDERS or SHCONTF_STORAGE or SHCONTF_INCLUDEHIDDEN, EnumIDList);
|
|
|
+
|
|
|
+ if Succeeded(Result) then
|
|
|
+ begin
|
|
|
+ Result:= STG_E_PATHNOTFOUND;
|
|
|
+
|
|
|
+ while EnumIDList.Next(1, RelativePIDL, NumIDs) = S_OK do
|
|
|
+ begin
|
|
|
+ if AItem = GetDisplayName(ParentFolder, RelativePIDL, SHGDN_INFOLDER or SHGDN_FORPARSING) then
|
|
|
+ begin
|
|
|
+ Result:= S_OK;
|
|
|
+ Break;
|
|
|
+ end;
|
|
|
+ CoTaskMemFree(RelativePIDL);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+ if Succeeded(Result) then
|
|
|
+ begin
|
|
|
+ PIDL:= ILCombine(ParentPIDL, RelativePIDL);
|
|
|
+ end;
|
|
|
+
|
|
|
+ CoTaskMemFree(ParentPIDL);
|
|
|
+
|
|
|
+ if Failed(Result) then Break;
|
|
|
+
|
|
|
+ if Index < High(APath) then
|
|
|
+ begin
|
|
|
+ Result:= ParentFolder.BindToObject(RelativePIDL, nil, IID_IShellFolder, Pointer(AFolder));
|
|
|
+ if Succeeded(Result) then
|
|
|
+ begin
|
|
|
+ ParentPIDL:= PIDL;
|
|
|
+ ParentFolder:= AFolder;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+ CoTaskMemFree(RelativePIDL);
|
|
|
+
|
|
|
+ if Failed(Result) then
|
|
|
+ begin
|
|
|
+ CoTaskMemFree(PIDL);
|
|
|
+ Break;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
function CreateDefaultContextMenu(constref pdcm: TDefContextMenu;
|
|
|
const riid: REFIID; out ppv): HRESULT;
|
|
|
begin
|