Subversion Repositories recyclebinunit

Compare Revisions

No changes between revisions

Regard whitespace Rev 98 → Rev 99

/trunk/FORMAT.md
5,16 → 5,16
 
### FAT drives:
 
- Windows 95 native: C:\RECYCLED\INFO (with ANSI records, folder deletion is NOT possible, format `00 00 00 00`)
- Windows 95+IE4, 98SE: C:\RECYCLED\INFO2 (with ANSI records, folder deletion is possible, format `04 00 00 00`)
- Windows Me: C:\RECYCLED\INFO2 (with ANSI records, folder deletion is possible, format `05 00 00 00`)
- Windows Vista+: C:\$RECYCLE.BIN\$I...
- Windows 95 native: `C:\RECYCLED\INFO` (with ANSI records, folder deletion is NOT possible, format `00 00 00 00`)
- Windows 95+IE4, 98SE: `C:\RECYCLED\INFO2` (with ANSI records, folder deletion is possible, format `04 00 00 00`)
- Windows Me: `C:\RECYCLED\INFO2` (with ANSI records, folder deletion is possible, format `05 00 00 00`)
- Windows Vista+: `C:\$RECYCLE.BIN\$I...`
 
### NTFS drives:
 
- Windows NT4: C:\RECYCLER\<UserSID>\INFO (with Unicode records, folder deletion is possible, format `02 00 00 00`)
- Windows 2000, XP: C:\RECYCLER\<UserSID>\INFO2 (with Unicode records, folder deletion is possible, format `05 00 00 00`)
- Windows Vista+: C:\$RECYCLE.BIN\<UserSID>\$I...
- Windows NT4: `C:\RECYCLER\<UserSID>\INFO` (with Unicode records, folder deletion is possible, format `02 00 00 00`)
- Windows 2000, XP: `C:\RECYCLER\<UserSID>\INFO2` (with Unicode records, folder deletion is possible, format `05 00 00 00`)
- Windows Vista+: `C:\$RECYCLE.BIN\<UserSID>\$I...`
 
## INFO and INFO2 files
 
22,7 → 22,7
 
INFO2 is written by Win95 with Internet Explorer 4 shell extensions, Win98, WinMe (with ANSI records), Win2000, and WinXP (with Unicode records).
 
Since some Windows versions combinations mix up ANSI records and Unicode records (e.g. Win95+IE4 and Win2000), these Windows versions break the recycle bin information file of each other.
Since some Windows version combinations mix up ANSI records and Unicode records (e.g. Win95+IE4 and Win2000), these Windows versions break the recycle bin information file of each other.
 
INFO and INFO2 is the index file containing all information about the deleted files. The data files are renamed to `Dxy.ext` (`x` replaced with the drive letter, `y` being a dynamic length integer, `ext` being replaced with the file name extension).
 
30,54 → 30,53
 
type
PRbInfoHeader = ^TRbInfoHeader;
TRbInfoHeader = record
format: DWORD; // Unsure if this is just a version field or some unknown flags...!
TRbInfoHeader = packed record
format: DWORD; // Version of the info file
// Win95 (without IE4): 00 00 00 00
// Win95 (with IE4): 04 00 00 00
// Win NT4: 02 00 00 00
// Win Me, 2000, XP: 05 00 00 00
totalEntries: DWORD; // Only Win95 (without IE4) and Win NT4, unknown purpose for other OS versions
nextPossibleID: DWORD; // Only Win95 (without IE4) and Win NT4, unknown purpose for other OS versions
recordLength: DWORD; // 0x181 = INFO structure (without Unicode)
// 0x320 = INFO2 structure (with Unicode)
// Win NT4: 02 00 00 00 (Win96/Cairo?)
// Win95 (with IE4), 98: 04 00 00 00
// Win Me, 2000, XP: 05 00 00 00 (NT4+IE4, NT5?)
totalEntries: DWORD; // Only Win95 (without IE4) and Win NT4, other OS versions might use the registry instead
nextPossibleID: DWORD; // Only Win95 (without IE4) and Win NT4, other OS versions might use the registry instead
recordLength: DWORD; // 0x181 = ANSI records
// 0x320 = Unicode records
totalSize: DWORD; // sum of all "originalSize" values;
// Only Win95 (without IE4) and Win NT4, unknown purpose for other OS versions
// Only Win95 (without IE4) and Win NT4, other OS versions might use the registry instead
end;
 
### ANSI record (Win95, 98, Me)
### ANSI record (Win95, Win98, WinMe)
 
type
// Windows 95: INFO file with TRbInfoRecordA; Folder deletion NOT possible
// Windows 95 +IE4: INFO2 file with TRbInfoRecordA; Folder deletion possible
PRbInfoRecordA = ^TRbInfoRecordA;
TRbInfoRecordA = record
sourceAnsi: array[0..MAX_PATH-3] of AnsiChar; // 258 elements
TRbInfoRecordA = packed record
sourceAnsi: array[0..MAX_PATH-1] of AnsiChar; // 260 characters (including NUL terminator)
recordNumber: DWORD;
sourceDrive: DWORD;
sourceDrive: DWORD; // 0=A, 1=B, 2=C, ...
deletionTime: FILETIME;
originalSize: DWORD; // Size occupied on disk. Not the actual file size.
// INFO2, for folders: The whole folder size with contents
end;
 
### Unicode record (NT4, 2000, XP)
### Unicode record (WinNT4, Win2000, WinXP)
 
type
// Windows NT4: INFO file with TRbInfoRecordW; Folder deletion possible
// Windows 2000+: INFO2 file with TRbInfoRecordW; Folder deletion possible
PRbInfoRecordW = ^TRbInfoRecordW;
TRbInfoRecordW = record
sourceAnsi: array[0..MAX_PATH-3] of AnsiChar; // 258 elements
TRbInfoRecordW = packed record
sourceAnsi: array[0..MAX_PATH-1] of AnsiChar; // 260 characters (including NUL terminator)
recordNumber: DWORD;
sourceDrive: DWORD;
sourceDrive: DWORD; // 0=A, 1=B, 2=C, ...
deletionTime: FILETIME;
originalSize: DWORD;
sourceUnicode: array[0..MAX_PATH-3] of WideChar; // 258 elements
unknown1: DWORD; // Dummy?
sourceUnicode: array[0..MAX_PATH-1] of WideChar; // 260 characters (including NUL terminator)
end;
 
## $I... files of Windows Vista and above
 
Beginning with Windows Vista, each deleted file gets its own information record. The information record ("index file") has the name `$Ixxxxxx.ext` while the data file is renamed to `$Rxxxxxx.ext` (`xxxxxx` replaced with a random `[0-9A-Z]` string and ext replaced with the file name extension).
Beginning with Windows Vista, each deleted file gets its own information record. The information record ("index file") has the name `$Ixxxxxx.ext` while the data file is renamed to `$Rxxxxxx.ext` (`xxxxxx` replaced with a random `[0-9A-Z]` string and `ext` replaced with the file name extension).
 
### Version 1 (Introduced in Windows Vista)
 
84,7 → 83,7
type
// Introduced in Windows Vista
PRbVistaRecord1 = ^TRbVistaRecord1;
TRbVistaRecord1 = record
TRbVistaRecord1 = packed record
version: int64; // Always 01 00 00 00 00 00 00 00
originalSize: int64;
deletionTime: FILETIME;
96,7 → 95,7
type
// Introduced somewhere in a Win10 release
PRbVistaRecord2Head = ^TRbVistaRecord2Head;
TRbVistaRecord2Head = record
TRbVistaRecord2Head = packed record
version: int64; // Always 02 00 00 00 00 00 00 00
originalSize: int64;
deletionTime: FILETIME;
/trunk/Recycle Bin Data Analysis/Funktionell/Win98SE Info2
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/Recycle Bin Data Analysis/Funktionell/WinMe Info2
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/Recycle Bin Unit/RecyclerFunctions.pas
850,8 → 850,8
var
Dummy2: DWORD;
Dummy3: DWORD;
FileSystem: array[0..MAX_PATH] of char;
VolumeName: array[0..MAX_PATH] of char;
FileSystem: array[0..MAX_PATH-1] of char;
VolumeName: array[0..MAX_PATH-1] of char;
s: string;
begin
result := false;
/trunk/Recycle Bin Unit v2/Changelog.txt
1,6 → 1,10
 
=== Changelog RecBinUnit v2 ===
 
2022-07-02
+ Improved recognition of Vista+ index files which are not named with file name $I...
+ Fixed issues in FORMAT.md
 
2022-06-30
+ Added support for $Ixxx "Vista" format 2 files (added somewhere in a Windows 10 build)
The difference towards $Ixxx "Vista" format 1 files is that the filename is not limited to MAX_PATH anymore. (New limit 0xFFFFFFFD)
/trunk/Recycle Bin Unit v2/RecBinUnit2.pas
5,7 → 5,7
// E-MAIL: info@daniel-marschall.de //
// Web: www.daniel-marschall.de & www.viathinksoft.de //
////////////////////////////////////////////////////////////////////////////////////
// Revision: 30 JUN 2022 //
// Revision: 02 JUL 2022 //
// This unit is freeware, but please link to my website if you are using it! //
////////////////////////////////////////////////////////////////////////////////////
// Successfully tested with: //
55,7 → 55,7
Windows, SysUtils, Classes, ContNrs, ShellAPI, Registry, Messages, Math;
 
const
RECBINUNIT_VERSION = '2022-06-30';
RECBINUNIT_VERSION = '2022-07-02';
 
RECYCLER_CLSID: TGUID = '{645FF040-5081-101B-9F08-00AA002F954E}';
NULL_GUID: TGUID = '{00000000-0000-0000-0000-000000000000}';
816,21 → 816,42
var
fs: TFileStream;
infoHdr: TRbInfoHeader;
testID: string;
vistaId: string;
wTest: TRbInfoWItem;
bakPosition: int64;
testVistaItem: TRbVistaItem;
begin
fs := TFileStream.Create(AFile, fmOpenRead);
try
fs.Seek(0, soFromBeginning);
 
{$REGION 'First try if it is a Vista index file'}
testVistaItem := nil;
if SameText(copy(ExtractFileName(AFile), 1, 2), '$I') then
begin
testID := copy(testID, 3, Length(testID)-2);
list.Add(TRbVistaItem.Create(fs, AFile, testID));
vistaId := copy(AFile, 3, Length(AFile)-2);
testVistaItem := TRbVistaItem.Create(fs, AFile, vistaId);
end
else
begin
vistaId := ''; // manual file that was not named $I..., so we cannot get $R... ID and therefore no physical file!
try
testVistaItem := TRbVistaItem.Create(fs, AFile, vistaId);
if Copy(testVistaItem.Source,2,2) <> ':\' then
FreeAndNil(testVistaItem);
except
testVistaItem := nil;
end;
end;
{$ENDREGION}
 
if Assigned(testVistaItem) then
begin
list.Add(testVistaItem);
end
else
begin
fs.Seek(0, soFromBeginning);
if TolerantReading then
begin
// This is a special treatment how to recover data from an INFO/INFO2 file
850,7 → 871,7
// a ':' at the Unicode string.
bakPosition := fs.Position;
wTest := TRbInfoWItem.Create(fs, AFile);
if Copy(wTest.SourceUnicode, 2, 1) = ':' then
if Copy(wTest.SourceUnicode, 2, 2) = ':\' then
begin
// Yes, it is a valid Unicode record.
list.Add(wTest);
863,11 → 884,16
list.Add(TRbInfoAItem.Create(fs, AFile));
end;
end
else
else if fs.Position + SizeOf(TRbInfoRecordA) <= fs.Size then
begin
// No, there is not enough space left for an Unicode record.
// So we assume that the following record will be a valid ANSI record.
list.Add(TRbInfoAItem.Create(fs, AFile));
end
else
begin
// Not enough space to read a Ansi record!
// Ignore it
end;
end;
end
1266,8 → 1292,8
var
Dummy2: DWORD;
Dummy3: DWORD;
FileSystem: array[0..MAX_PATH] of char;
VolumeName: array[0..MAX_PATH] of char;
FileSystem: array[0..MAX_PATH-1] of char;
VolumeName: array[0..MAX_PATH-1] of char;
s: string;
begin
s := FDriveLetter + DriveDelim + PathDelim; // ohne die Auslagerung in einen String kommt es zu einer AV in ntdll
1536,7 → 1562,7
r1: TRbVistaRecord1;
r2: TRbVistaRecord2Head;
r2SourceUnicode: array of WideChar;
version: DWORD;
version: int64;
i: Integer;
resourcestring
LNG_VISTA_WRONG_FORMAT = 'Invalid Vista index format version %d';
1614,6 → 1640,9
function TRbVistaItem.GetPhysicalFile: string;
begin
result := FIndexFile;
if Pos('$I', Result) = 0 then
result := ''
else
result := StringReplace(Result, '$I', '$R', [rfIgnoreCase]);
end;
 
/trunk/Recycle Bin Unit v2/RecBinUnitLowLvl.pas
1,7 → 1,6
unit RecBinUnitLowLvl;
 
// TODO: Gain more information about drive '@' / Homedrive / Netdrive? Win2000 source
// + überall verwenden
// TODO: Gain more information about drive '@' / Homedrive / Netdrive?
 
interface
 
10,18 → 9,18
 
type
PRbInfoHeader = ^TRbInfoHeader;
TRbInfoHeader = record
format: DWORD; // Unsure if this is just a version field or some unknown flags...!
TRbInfoHeader = packed record
format: DWORD; // Version of the info file
// Win95 (without IE4): 00 00 00 00
// Win95 (with IE4): 04 00 00 00
// Win NT4: 02 00 00 00
// Win Me, 2000, XP: 05 00 00 00
totalEntries: DWORD; // Only Win95 (without IE4) and Win NT4, unknown purpose for other OS versions
nextPossibleID: DWORD; // Only Win95 (without IE4) and Win NT4, unknown purpose for other OS versions
recordLength: DWORD; // 0x181 = INFO structure (without Unicode)
// 0x320 = INFO2 structure (with Unicode)
// Win NT4: 02 00 00 00 (Win96/Cairo?)
// Win95 (with IE4), 98: 04 00 00 00
// Win Me, 2000, XP: 05 00 00 00 (NT4+IE4, NT5?)
totalEntries: DWORD; // Only Win95 (without IE4) and Win NT4, other OS versions might use the registry instead
nextPossibleID: DWORD; // Only Win95 (without IE4) and Win NT4, other OS versions might use the registry instead
recordLength: DWORD; // 0x181 = ANSI records
// 0x320 = Unicode records
totalSize: DWORD; // sum of all "originalSize" values;
// Only Win95 (without IE4) and Win NT4, unknown purpose for other OS versions
// Only Win95 (without IE4) and Win NT4, other OS versions might use the registry instead
end;
 
type
28,10 → 27,10
// Windows 95: INFO file with TRbInfoRecordA; Folder deletion NOT possible
// Windows 95 +IE4: INFO2 file with TRbInfoRecordA; Folder deletion possible
PRbInfoRecordA = ^TRbInfoRecordA;
TRbInfoRecordA = record
sourceAnsi: array[0..MAX_PATH-3] of AnsiChar; // 258 elements
TRbInfoRecordA = packed record
sourceAnsi: array[0..MAX_PATH-1] of AnsiChar; // 260 characters (including NUL terminator)
recordNumber: DWORD;
sourceDrive: DWORD;
sourceDrive: DWORD; // 0=A, 1=B, 2=C, ...
deletionTime: FILETIME;
originalSize: DWORD; // Size occupied on disk. Not the actual file size.
// INFO2, for folders: The whole folder size with contents
41,20 → 40,19
// Windows NT4: INFO file with TRbInfoRecordW; Folder deletion possible
// Windows 2000+: INFO2 file with TRbInfoRecordW; Folder deletion possible
PRbInfoRecordW = ^TRbInfoRecordW;
TRbInfoRecordW = record
sourceAnsi: array[0..MAX_PATH-3] of AnsiChar; // 258 elements
TRbInfoRecordW = packed record
sourceAnsi: array[0..MAX_PATH-1] of AnsiChar; // 260 characters (including NUL terminator)
recordNumber: DWORD;
sourceDrive: DWORD;
sourceDrive: DWORD; // 0=A, 1=B, 2=C, ...
deletionTime: FILETIME;
originalSize: DWORD;
sourceUnicode: array[0..MAX_PATH-3] of WideChar; // 258 elements
unknown1: DWORD; // Dummy?
sourceUnicode: array[0..MAX_PATH-1] of WideChar; // 260 characters (including NUL terminator)
end;
 
type
// Introduced in Windows Vista
PRbVistaRecord1 = ^TRbVistaRecord1;
TRbVistaRecord1 = record
TRbVistaRecord1 = packed record
version: int64; // Always 01 00 00 00 00 00 00 00
originalSize: int64;
deletionTime: FILETIME;
64,7 → 62,7
type
// Introduced somewhere in a Win10 release
PRbVistaRecord2Head = ^TRbVistaRecord2Head;
TRbVistaRecord2Head = record
TRbVistaRecord2Head = packed record
version: int64; // Always 02 00 00 00 00 00 00 00
originalSize: int64;
deletionTime: FILETIME;
77,7 → 75,7
// Windows 95 + Windows NT 4
// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\explorer\BitBucket: PurgeInfo (Binary)
PRbWin95PurgeInfo = ^TRbWin95PurgeInfo;
TRbWin95PurgeInfo = record
TRbWin95PurgeInfo = packed record
cbSize: DWORD;
bGlobalSettings: BOOL;
percentDrive: array['A'..'Z'] of WORD; // 0x00..0x64 = 0%..100%
/trunk/Recycle Bin Unit v2/RecyclerListing.exe
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/trunk/Recycle Bin Unit v2/RecyclerListingMain.dfm
54,7 → 54,7
TabOrder = 1
end
object Button2: TButton
Left = 599
Left = 615
Top = 48
Width = 106
Height = 33
77,14 → 77,21
object CheckBox2: TCheckBox
Left = 183
Top = 6
Width = 146
Width = 138
Height = 17
Caption = 'Hide orphan Index files'
Checked = True
State = cbChecked
Caption = 'Hide non-existing files'
TabOrder = 2
end
object Button3: TButton
Left = 592
Top = 56
Width = 17
Height = 21
Caption = '...'
TabOrder = 5
OnClick = Button3Click
end
end
object OpenDialog1: TOpenDialog
Left = 928
Top = 16
93,7 → 100,7
Left = 928
Top = 48
Bitmap = {
494C01010E001000140010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
494C01010E001000040010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
0000000000003600000028000000400000004000000001002000000000000040
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
/trunk/Recycle Bin Unit v2/RecyclerListingMain.pas
17,10 → 17,12
LabeledEdit1: TLabeledEdit;
ImageList1: TImageList;
CheckBox2: TCheckBox;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure TreeView1DblClick(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
localRecyclersNode: TTreeNode;
individualRecyclersNode: TTreeNode;
40,6 → 42,14
// TODO: zu jedem element mehr informationen anzeigen, nicht nur den ursprungsnamen
// TODO: Einstellungen usw anzeigen, so wie im alten Demo
 
const
ICON_FILE = 0;
ICON_TREEVIEW = 2;
ICON_BIN = 4;
ICON_DRIVE = 6;
ICON_UNKNOWN = 8;
ICON_FOLDER = 10;
 
procedure TRecyclerListingMainForm.Button1Click(Sender: TObject);
var
drives: TObjectList{TRbDrive};
77,7 → 87,7
nDrive := TreeView1.Items.AddChildObject(localRecyclersNode, Format(S_DRIVE, [drive.DriveLetter])+': ' + GUIDToString(drive.VolumeGUID), drive)
else
nDrive := TreeView1.Items.AddChildObject(localRecyclersNode, Format(S_DRIVE, [drive.DriveLetter])+':', drive);
nDrive.ImageIndex := 6;
nDrive.ImageIndex := ICON_DRIVE;
nDrive.SelectedIndex := nDrive.ImageIndex;
 
bins.Clear;
90,7 → 100,7
bin := bins.Items[iBin] as TRbRecycleBin;
 
nBin := TreeView1.Items.AddChildObject(nDrive, bin.FileOrDirectory, bin);
nBin.ImageIndex := 4;
nBin.ImageIndex := ICON_BIN;
nBin.SelectedIndex := nBin.ImageIndex;
 
items.Clear;
108,11 → 118,11
nItem := TreeView1.Items.AddChildObject(nBin, sCaption, item);
 
if FileExists(item.PhysicalFile) then
nItem.ImageIndex := 0
nItem.ImageIndex := ICON_FILE
else if DirectoryExists(item.PhysicalFile) then
nItem.ImageIndex := 10 // TODO: Feature: Read folder contents and display them in this treeview. (Also change icon to "open folder")
nItem.ImageIndex := ICON_FOLDER // TODO: Feature: Read folder contents and display them in this treeview. (Also change icon to "open folder")
else
nItem.ImageIndex := 8;
nItem.ImageIndex := ICON_UNKNOWN;
nItem.SelectedIndex := nItem.ImageIndex;
end;
end;
141,6 → 151,8
bin := TRbRecycleBin.Create(LabeledEdit1.Text);
 
nBin := TreeView1.Items.AddChildObject(individualRecyclersNode, bin.FileOrDirectory, bin);
nBin.ImageIndex := ICON_BIN;
nBin.SelectedIndex := nBin.ImageIndex;
individualRecyclersNode.Expand(false);
 
items := TObjectList.Create(false);
160,11 → 172,11
nItem := TreeView1.Items.AddChildObject(nBin, sCaption, item);
 
if FileExists(item.PhysicalFile) then
nItem.ImageIndex := 0
nItem.ImageIndex := ICON_FILE
else if DirectoryExists(item.PhysicalFile) then
nItem.ImageIndex := 10 // TODO: Feature: Read folder contents and display them in this treeview. (Also change icon to "open folder")
nItem.ImageIndex := ICON_FOLDER // TODO: Feature: Read folder contents and display them in this treeview. (Also change icon to "open folder")
else
nItem.ImageIndex := 8;
nItem.ImageIndex := ICON_UNKNOWN;
nItem.SelectedIndex := nItem.ImageIndex;
end;
finally
174,6 → 186,12
nBin.Expand(false);
end;
 
procedure TRecyclerListingMainForm.Button3Click(Sender: TObject);
begin
if OpenDialog1.Execute then
LabeledEdit1.Text := OpenDialog1.FileName;
end;
 
procedure TRecyclerListingMainForm.FormShow(Sender: TObject);
resourcestring
S_LOCAL_RECYCLE_BINS = 'Local recycle bins';
180,11 → 198,11
S_MANUAL_RECYCLE_BINS ='Manually added recycle bins';
begin
localRecyclersNode := TreeView1.Items.Add(nil, S_LOCAL_RECYCLE_BINS);
localRecyclersNode.ImageIndex := 2;
localRecyclersNode.ImageIndex := ICON_TREEVIEW;
localRecyclersNode.SelectedIndex := localRecyclersNode.ImageIndex;
 
individualRecyclersNode := TreeView1.Items.Add(nil, S_MANUAL_RECYCLE_BINS);
individualRecyclersNode.ImageIndex := 2;
individualRecyclersNode.ImageIndex := ICON_TREEVIEW;
individualRecyclersNode.SelectedIndex := individualRecyclersNode.ImageIndex;
end;
 
192,7 → 210,7
var
item: TRbRecycleBinItem;
begin
if TreeView1.Selected.ImageIndex = 0 then
if TreeView1.Selected.ImageIndex = ICON_FILE then
begin
// File
item := TRbRecycleBinItem(TreeView1.Selected.Data);
200,7 → 218,7
// TODO: Maybe we should add a feature to drag'n'drop a file/folder out of RecycleBinUnit into the explorer (With options copy or move, depending on the ShiftState)
ShellExecute(Handle, 'open', PChar(item.PhysicalFile), '', '', SW_NORMAL);
end;
if TreeView1.Selected.ImageIndex = 10 then
if TreeView1.Selected.ImageIndex = ICON_FOLDER then
begin
// Folder
item := TRbRecycleBinItem(TreeView1.Selected.Data);