unit uRecycleBinListOperation;

{$mode ObjFPC}{$H+}

interface

uses
  Classes, SysUtils,
  uFileSystemListOperation,
  uRecycleBinFileSource,
  uFileSource;

type

  { TRecycleBinListOperation }

  TRecycleBinListOperation = class(TFileSystemListOperation)
  public
    constructor Create(aFileSource: IFileSource; aPath: String); override;
    procedure MainExecute; override;
  end;

implementation

uses
  Windows, ShlObj, ComObj, JwaShlGuid, Variants, DCOSUtils, DCDateTimeUtils,
  ActiveX, uFile, uShellFolder, uShlObjAdditional, uShowMsg;

const
  SID_DISPLACED = '{9B174B33-40FF-11d2-A27E-00C04FC30871}';
  SCID_OriginalLocation: TSHColumnID = ( fmtid: SID_DISPLACED; pid: PID_DISPLACED_FROM );
  SCID_DateDeleted:      TSHColumnID = ( fmtid: SID_DISPLACED; pid: PID_DISPLACED_DATE );

{ TRecycleBinListOperation }

constructor TRecycleBinListOperation.Create(aFileSource: IFileSource;
  aPath: String);
begin
  FFiles := TFiles.Create(aPath);
  inherited Create(aFileSource, aPath);
end;

procedure TRecycleBinListOperation.MainExecute;
var
  AFile: TFile;
  NumIDs: LongWord = 0;
  AFolder: IShellFolder2;
  EnumIDList: IEnumIDList;
  Attr: TFileAttributeData;
  DesktopFolder: IShellFolder;
  PIDL, TrashPIDL: PItemIDList;
begin
  FFiles.Clear;
  try
    OleCheckUTF8(SHGetDesktopFolder(DesktopFolder));
    OleCheckUTF8(SHGetFolderLocation(0, CSIDL_BITBUCKET, 0, 0, {%H-}TrashPIDL));
    try
      OleCheckUTF8(DesktopFolder.BindToObject(TrashPIDL, nil, IID_IShellFolder2, Pointer(AFolder)));
      OleCheckUTF8(AFolder.EnumObjects(0, SHCONTF_FOLDERS or SHCONTF_NONFOLDERS or SHCONTF_INCLUDEHIDDEN, EnumIDList));

      while EnumIDList.Next(1, PIDL, NumIDs) = S_OK do
      try
        CheckOperationState;

        aFile:= TRecycleBinFileSource.CreateFile(Path);
        AFile.FullPath:= GetDisplayName(AFolder, PIDL, SHGDN_NORMAL);
        AFile.LinkProperty.LinkTo:= GetDisplayName(AFolder, PIDL, SHGDN_FORPARSING);

        if mbFileGetAttr(AFile.LinkProperty.LinkTo, Attr) then
        begin
          AFile.Size:= Attr.Size;
          AFile.Attributes:= Attr.Attr;
          AFile.CreationTime:= WinFileTimeToDateTime(Attr.PlatformTime);
          AFile.LastAccessTime:= WinFileTimeToDateTime(Attr.LastAccessTime);
          AFile.ModificationTime:= WinFileTimeToDateTime(Attr.LastWriteTime);
          AFile.CommentProperty.Value:= GetDetails(AFolder, PIDL, SCID_OriginalLocation);
          AFile.ChangeTime:= VariantTimeToDateTime(VarToDateTime(GetDetails(AFolder, PIDL, SCID_DateDeleted)));
        end;

        FFiles.Add(AFile);
      finally
        CoTaskMemFree(PIDL);
      end;
    finally
      CoTaskMemFree(TrashPIDL);
    end;
  except
    on E: Exception do msgError(Thread, E.Message);
  end;
end;

end.

