Subversion Repositories recyclebinunit

Rev

Rev 91 | Rev 96 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 91 Rev 92
Line 7... Line 7...
7
////////////////////////////////////////////////////////////////////////////////////
7
////////////////////////////////////////////////////////////////////////////////////
8
// RECYCLE-BIN-FUNCTIONS BY DANIEL MARSCHALL                                      //
8
// RECYCLE-BIN-FUNCTIONS BY DANIEL MARSCHALL                                      //
9
// E-MAIL: info@daniel-marschall.de                                               //
9
// E-MAIL: info@daniel-marschall.de                                               //
10
// WEB:    www.daniel-marschall.de                                                //
10
// WEB:    www.daniel-marschall.de                                                //
11
////////////////////////////////////////////////////////////////////////////////////
11
////////////////////////////////////////////////////////////////////////////////////
12
// Revision: 01 NOV 2016                                                          //
12
// Revision: 30 Jun 2022                                                          //
13
// This unit is freeware, but please link to my website if you are using it!      //
13
// This unit is freeware, but please link to my website if you are using it!      //
14
////////////////////////////////////////////////////////////////////////////////////
14
////////////////////////////////////////////////////////////////////////////////////
15
// Successfully tested with:                                                      //
15
// Successfully tested with:                                                      //
16
// Windows 95b (without IE4 Shell Extensions)                                     //
16
// Windows 95b (without IE4 Shell Extensions)                                     //
17
// Windows 95b (with IE4 Shell Extensions)                                        //
17
// Windows 95b (with IE4 Shell Extensions)                                        //
Line 20... Line 20...
20
// Windows XP-SP3                                                                 //
20
// Windows XP-SP3                                                                 //
21
// Windows 2000-SP4                                                               //
21
// Windows 2000-SP4                                                               //
22
// Windows 2003 Server EE SP1                                                     //
22
// Windows 2003 Server EE SP1                                                     //
23
// Windows Vista                                                                  //
23
// Windows Vista                                                                  //
24
// Windows 7                                                                      //
24
// Windows 7                                                                      //
25
////////////////////////////////////////////////////////////////////////////////////
-
 
26
// DOES **NOT** WORK WITH "VERSION 2" INDEX FILES USED IN LATER VERSIONS OF WIN10 //
25
// Windows 10 (version 1 and version 2 format)                                    //
27
// USE RECYCLE BIN UNIT V2 INSTEAD!                                               //
26
// Windows 11                                                                     //
28
////////////////////////////////////////////////////////////////////////////////////
27
////////////////////////////////////////////////////////////////////////////////////
29
//                                                                                //
28
//                                                                                //
30
//  Needs Delphi 4 or higher. If you are using Delphi 4 or 5, you can not use the //
29
//  Needs Delphi 4 or higher. If you are using Delphi 4 or 5, you can not use the //
31
//  RecyclerGetDateTime() functions, because the unit "DateUtils" is missing.     //
30
//  RecyclerGetDateTime() functions, because the unit "DateUtils" is missing.     //
32
//  Warning! This is a platform unit.                                             //
31
//  Warning! This is a platform unit.                                             //
Line 133... Line 132...
133
  EUnknownState = class(Exception);
132
  EUnknownState = class(Exception);
134
  EEventCategoryNotDefined = class(Exception);
133
  EEventCategoryNotDefined = class(Exception);
135
  EAPICallError = class(Exception);
134
  EAPICallError = class(Exception);
136
 
135
 
137
  PSHQueryRBInfo = ^TSHQueryRBInfo;
136
  PSHQueryRBInfo = ^TSHQueryRBInfo;
-
 
137
  {$IFDEF WIN64}
-
 
138
  // ATTENTION! MUST NOT BE PACKED! Alignment for 64 bit must be 8 and for 32 bit must be 4
-
 
139
  TSHQueryRBInfo = record
-
 
140
  {$ELSE}
138
  TSHQueryRBInfo = packed record
141
  TSHQueryRBInfo = packed record
-
 
142
  {$ENDIF}
139
    cbSize      : dword;
143
    cbSize      : dword;
140
    i64Size     : int64;
144
    i64Size     : int64;
141
    i64NumItems : int64;
145
    i64NumItems : int64;
142
  end;
146
  end;
143
 
147
 
Line 861... Line 865...
861
 
865
 
862
// **********************************************************
866
// **********************************************************
863
// VISTA AND WINDOWS 7 FUNCTIONS, INTERNAL USED
867
// VISTA AND WINDOWS 7 FUNCTIONS, INTERNAL USED
864
// **********************************************************
868
// **********************************************************
865
 
869
 
866
const
-
 
867
  vista_valid_index_size = $220; // 544
-
 
868
 
-
 
869
function _isFileVistaRealfile(filename: string): boolean;
870
function _isFileVistaRealfile(filename: string): boolean;
870
begin
871
begin
871
  result := uppercase(copy(extractfilename(filename), 0, 2)) = '$R';
872
  result := uppercase(copy(extractfilename(filename), 0, 2)) = '$R';
872
end;
873
end;
873
 
874
 
Line 918... Line 919...
918
  r := FindFirst(tmp+PathDelim + '$I*', faAnyFile, sr);
919
  r := FindFirst(tmp+PathDelim + '$I*', faAnyFile, sr);
919
  while r = 0 do
920
  while r = 0 do
920
  begin
921
  begin
921
    if (sr.Name <> '.') and (sr.Name <> '..') then
922
    if (sr.Name <> '.') and (sr.Name <> '..') then
922
    begin
923
    begin
923
      if sr.Size = vista_valid_index_size then
-
 
924
      begin
-
 
925
        result.Add(copy(sr.name, 3, length(sr.name)-2));
924
      result.Add(copy(sr.name, 3, length(sr.name)-2));
926
      end;
925
    end;
927
    end;
-
 
928
    r := FindNext(sr);
926
    r := FindNext(sr);
929
  end;
927
  end;
930
 
928
 
931
  FindClose(sr);
929
  FindClose(sr);
932
end;
930
end;
Line 952... Line 950...
952
 
950
 
953
function _VistaGetSourceDrive(infofile: string): char;
951
function _VistaGetSourceDrive(infofile: string): char;
954
var
952
var
955
  fs: TFileStream;
953
  fs: TFileStream;
956
  tmp: string;
954
  tmp: string;
-
 
955
  version: DWORD;
957
const
956
const
958
  drive_vista_position = $18;
957
  drive_vista_position = $18;
959
begin
958
begin
960
  result := #0;
959
  result := #0;
961
 
960
 
Line 963... Line 962...
963
  tmp := _VistaChangeRealfileToIndexfile(tmp);
962
  tmp := _VistaChangeRealfileToIndexfile(tmp);
964
  if not fileexists(tmp) then exit;
963
  if not fileexists(tmp) then exit;
965
 
964
 
966
  fs := TFileStream.Create(tmp, fmOpenRead);
965
  fs := TFileStream.Create(tmp, fmOpenRead);
967
  try
966
  try
-
 
967
    fs.ReadBuffer(version, 4);
-
 
968
    if version > 2 then
-
 
969
      raise Exception.CreateFmt('Unexpeceted version %d of Vista index file', [version]);
968
    fs.seek(drive_vista_position, soFromBeginning);
970
    fs.seek(drive_vista_position, soFromBeginning);
969
    result := _readChar(fs);
971
    result := _readChar(fs);
970
  finally
972
  finally
971
    fs.free;
973
    fs.free;
972
  end;
974
  end;
Line 975... Line 977...
975
{$IFDEF DEL6UP}
977
{$IFDEF DEL6UP}
976
function _VistaGetDateTime(infofile: string): TDateTime;
978
function _VistaGetDateTime(infofile: string): TDateTime;
977
var
979
var
978
  fs: TFileStream;
980
  fs: TFileStream;
979
  tmp: string;
981
  tmp: string;
-
 
982
  version: DWORD;
980
const
983
const
981
  timestamp_vista_position = $10;
984
  timestamp_vista_position = $10;
982
begin
985
begin
983
  result := EncodeDateTime(1601, 1, 1, 0, 0, 0, 0);
986
  result := EncodeDateTime(1601, 1, 1, 0, 0, 0, 0);
984
 
987
 
Line 986... Line 989...
986
  tmp := _VistaChangeRealfileToIndexfile(tmp);
989
  tmp := _VistaChangeRealfileToIndexfile(tmp);
987
  if not fileexists(tmp) then exit;
990
  if not fileexists(tmp) then exit;
988
 
991
 
989
  fs := TFileStream.Create(tmp, fmOpenRead);
992
  fs := TFileStream.Create(tmp, fmOpenRead);
990
  try
993
  try
-
 
994
    fs.ReadBuffer(version, 4);
-
 
995
    if version > 2 then
-
 
996
      raise Exception.CreateFmt('Unexpeceted version %d of Vista index file', [version]);
991
    fs.seek(timestamp_vista_position, soFromBeginning);
997
    fs.seek(timestamp_vista_position, soFromBeginning);
992
    result := _fileTimeToDateTime(_readInt64(fs));
998
    result := _fileTimeToDateTime(_readInt64(fs));
993
  finally
999
  finally
994
    fs.free;
1000
    fs.free;
995
  end;
1001
  end;
Line 998... Line 1004...
998
 
1004
 
999
function _VistaGetSourceUnicode(infofile: string): string;
1005
function _VistaGetSourceUnicode(infofile: string): string;
1000
var
1006
var
1001
  fs: TFileStream;
1007
  fs: TFileStream;
1002
  tmp: string;
1008
  tmp: string;
-
 
1009
  version: DWORD;
1003
const
1010
const
1004
  unicode_vista_position = $18;
1011
  unicode_vista_position_v1 = $18;
-
 
1012
  unicode_vista_position_v2 = $1C;
1005
begin
1013
begin
1006
  result := '';
1014
  result := '';
1007
 
1015
 
1008
  tmp := infofile;
1016
  tmp := infofile;
1009
  tmp := _VistaChangeRealfileToIndexfile(tmp);
1017
  tmp := _VistaChangeRealfileToIndexfile(tmp);
1010
  if not fileexists(tmp) then exit;
1018
  if not fileexists(tmp) then exit;
1011
 
1019
 
1012
  fs := TFileStream.Create(tmp, fmOpenRead);
1020
  fs := TFileStream.Create(tmp, fmOpenRead);
1013
  try
1021
  try
-
 
1022
    fs.ReadBuffer(version, 4);
-
 
1023
    if version = 2 then
-
 
1024
      // Note: This is not the official way to read the source. Actually, you should check the size and only read this specified size
1014
    fs.seek(unicode_vista_position, soFromBeginning);
1025
      fs.seek(unicode_vista_position_v2, soFromBeginning)
-
 
1026
    else if version = 1 then
-
 
1027
      fs.seek(unicode_vista_position_v1, soFromBeginning)
-
 
1028
    else
-
 
1029
      raise Exception.CreateFmt('Unexpeceted version %d of Vista index file', [version]);
1015
    result := _readNullTerminatedWideString(fs);
1030
    result := _readNullTerminatedWideString(fs);
1016
  finally
1031
  finally
1017
    fs.free;
1032
    fs.free;
1018
  end;
1033
  end;
1019
end;
1034
end;
1020
 
1035
 
1021
function _VistaOriginalSize(infofile: string): integer;
1036
function _VistaOriginalSize(infofile: string): integer;
1022
var
1037
var
1023
  fs: TFileStream;
1038
  fs: TFileStream;
1024
  tmp: string;
1039
  tmp: string;
-
 
1040
  version: DWORD;
1025
const
1041
const
1026
  size_vista_position = $8;
1042
  size_vista_position = $8;
1027
begin
1043
begin
1028
  result := -1;
1044
  result := -1;
1029
 
1045
 
Line 1031... Line 1047...
1031
  tmp := _VistaChangeRealfileToIndexfile(tmp);
1047
  tmp := _VistaChangeRealfileToIndexfile(tmp);
1032
  if not fileexists(tmp) then exit;
1048
  if not fileexists(tmp) then exit;
1033
 
1049
 
1034
  fs := TFileStream.Create(tmp, fmOpenRead);
1050
  fs := TFileStream.Create(tmp, fmOpenRead);
1035
  try
1051
  try
-
 
1052
    fs.ReadBuffer(version, 4);
-
 
1053
    if version > 2 then
-
 
1054
      raise Exception.CreateFmt('Unexpeceted version %d of Vista index file', [version]);
1036
    fs.seek(size_vista_position, soFromBeginning);
1055
    fs.seek(size_vista_position, soFromBeginning);
1037
    result := _readInt32(fs);
1056
    result := _readInt32(fs);
1038
  finally
1057
  finally
1039
    fs.free;
1058
    fs.free;
1040
  end;
1059
  end;
Line 1065... Line 1084...
1065
 
1084
 
1066
function _VistaIsValid(infofile: string): boolean;
1085
function _VistaIsValid(infofile: string): boolean;
1067
var
1086
var
1068
  tmp: string;
1087
  tmp: string;
1069
begin
1088
begin
1070
  result := false;
-
 
1071
 
-
 
1072
  tmp := infofile;
1089
  tmp := infofile;
1073
  tmp := _VistaChangeRealfileToIndexfile(tmp);
1090
  tmp := _VistaChangeRealfileToIndexfile(tmp);
1074
  if not fileexists(tmp) then exit;
1091
  result := fileexists(tmp);
1075
 
-
 
1076
  // Check the file length
-
 
1077
  result := _FileSize(tmp) = vista_valid_index_size;
-
 
1078
end;
1092
end;
1079
 
1093
 
1080
// **********************************************************
1094
// **********************************************************
1081
// PUBLIC FUNCTIONS
1095
// PUBLIC FUNCTIONS
1082
// **********************************************************
1096
// **********************************************************
Line 2114... Line 2128...
2114
                                 HRESULT; stdcall;
2128
                                 HRESULT; stdcall;
2115
var
2129
var
2116
  PSHEmptyRecycleBin: TSHEmptyRecycleBin;
2130
  PSHEmptyRecycleBin: TSHEmptyRecycleBin;
2117
  LibHandle: THandle;
2131
  LibHandle: THandle;
2118
const
2132
const
-
 
2133
  {$IFDEF UNICODE}
-
 
2134
  C_SHEmptyRecycleBin = 'SHEmptyRecycleBinW';
-
 
2135
  {$ELSE}
2119
  C_SHEmptyRecycleBinA = 'SHEmptyRecycleBinA';
2136
  C_SHEmptyRecycleBin = 'SHEmptyRecycleBinA';
-
 
2137
  {$ENDIF}
2120
begin
2138
begin
2121
  result := true;
2139
  result := true;
2122
  LibHandle := LoadLibrary(shell32) ;
2140
  LibHandle := LoadLibrary(shell32) ;
2123
  try
2141
  try
2124
    if LibHandle <> 0 then
2142
    if LibHandle <> 0 then
2125
    begin
2143
    begin
2126
      @PSHEmptyRecycleBin:= GetProcAddress(LibHandle, C_SHEmptyRecycleBinA);
2144
      @PSHEmptyRecycleBin:= GetProcAddress(LibHandle, C_SHEmptyRecycleBin);
2127
      if @PSHEmptyRecycleBin <> nil then
2145
      if @PSHEmptyRecycleBin <> nil then
2128
      begin
2146
      begin
2129
        PSHEmptyRecycleBin(hInstance, nil, flags);
2147
        PSHEmptyRecycleBin(hInstance, nil, flags);
2130
      end
2148
      end
2131
      else
2149
      else
Line 2908... Line 2926...
2908
begin
2926
begin
2909
  result := RecyclerGetAPIInfo(Drive + ':\');
2927
  result := RecyclerGetAPIInfo(Drive + ':\');
2910
end;
2928
end;
2911
 
2929
 
2912
const
2930
const
-
 
2931
  {$IFDEF UNICODE}
-
 
2932
  C_SHQueryRecycleBin = 'SHQueryRecycleBinW';
-
 
2933
  {$ELSE}
2913
  C_SHQueryRecycleBin = 'SHQueryRecycleBinA';
2934
  C_SHQueryRecycleBin = 'SHQueryRecycleBinA';
-
 
2935
  {$ENDIF}
2914
 
2936
 
2915
type
2937
type
2916
  TSHQueryRecycleBin = function(pszRootPath: LPCTSTR;
2938
  TSHQueryRecycleBin = function(pszRootPath: LPCTSTR;
2917
    var pSHQueryRBInfo: TSHQueryRBInfo): HRESULT; stdcall;
2939
    var pSHQueryRBInfo: TSHQueryRBInfo): HRESULT; stdcall;
2918
 
2940
 
Line 2950... Line 2972...
2950
    end
2972
    end
2951
    else
2973
    else
2952
    begin
2974
    begin
2953
      // Since Windows Vista, SHQueryRecycleBin will fail with E_FAIL (80004005)
2975
      // Since Windows Vista, SHQueryRecycleBin will fail with E_FAIL (80004005)
2954
      // if Path is a floppy or CD drive...
2976
      // if Path is a floppy or CD drive...
2955
      // Windows 10: Error 0x8007003 for Path 'C:\'
-
 
2956
      raise EAPICallError.CreateFmt(LNG_API_CALL_ERROR, [Format(LNG_ERROR_CODE, [C_SHQueryRecycleBin, Path, '0x'+IntToHex(res, 2*SizeOf(HRESULT))])]);
2977
      raise EAPICallError.CreateFmt(LNG_API_CALL_ERROR, [Format(LNG_ERROR_CODE, [C_SHQueryRecycleBin, Path, '0x'+IntToHex(res, 2*SizeOf(HRESULT))])]);
2957
    end;
2978
    end;
2958
  end
2979
  end
2959
  else
2980
  else
2960
    raise EAPICallError.CreateFmt(LNG_API_CALL_ERROR, [Format(LNG_NOT_CALLABLE, [C_SHQueryRecycleBin])]);
2981
    raise EAPICallError.CreateFmt(LNG_API_CALL_ERROR, [Format(LNG_NOT_CALLABLE, [C_SHQueryRecycleBin])]);
Line 3138... Line 3159...
3138
  result := typ = DRIVE_FIXED;
3159
  result := typ = DRIVE_FIXED;
3139
end;
3160
end;
3140
 
3161
 
3141
function RecyclerLibraryVersion: string;
3162
function RecyclerLibraryVersion: string;
3142
begin
3163
begin
3143
  result := 'ViaThinkSoft Recycle Bin Unit [01 JUL 2016]';
3164
  result := 'ViaThinkSoft Recycle Bin Unit [30 JUN 2022]';
3144
end;
3165
end;
3145
 
3166
 
3146
end.
3167
end.