Subversion Repositories recyclebinunit

Compare Revisions

Regard whitespace Rev 38 → Rev 39

/trunk/Recycle Bin Unit/clean.bat
File deleted
/trunk/Recycle Bin Unit/renew_bitops.bat
File deleted
/trunk/Recycle Bin Unit/Windows 95 Bit Bucket Reader/BitBucketReader.exe
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/trunk/Recycle Bin Unit/Recycler.exe
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/trunk/Recycle Bin Unit/Patch Recycle Bin Unit Objektorientiert (Gescheitert).patch
0,0 → 1,4787
Index: alt header.txt
===================================================================
--- alt header.txt (revision 0)
+++ alt header.txt (revision 0)
@@ -0,0 +1,74 @@
+////////////////////////////////////////////////////////////////////////////////////
+// RECYCLE-BIN-FUNCTIONS BY DANIEL MARSCHALL //
+// E-MAIL: info@daniel-marschall.de //
+// WEB: www.daniel-marschall.de //
+////////////////////////////////////////////////////////////////////////////////////
+// Revision: 05 JUL 2010 //
+// This unit is freeware, but please link to my website if you are using it! //
+////////////////////////////////////////////////////////////////////////////////////
+// Successful tested with: //
+// Windows 95b (without IE4 Shell Extensions) //
+// Windows 95b (with IE4 Shell Extensions) //
+// Windows 98-SE //
+// Windows XP-SP3 //
+// Windows 2000-SP4 //
+// Windows 2003 Server EE SP1 //
+// Windows Vista //
+// Windows 7 //
+////////////////////////////////////////////////////////////////////////////////////
+// //
+// Needs Delphi 4 or higher. If you are using Delphi 4 or 5, you can not use the //
+// RecyclerGetDateTime() functions, because the unit "DateUtils" is missing. //
+// Warning! This is a platform unit. //
+// //
+// To do! Can you help? //
+// - WideString-Support (input/output) //
+// - GetLoginNameW: Really 255 maximum? //
+// - Always do EOF before reading anything? //
+// - Is it possible to identify a Vista-file that is not named $Ixxxxxx.ext? //
+// - RecyclerGetInfofiles() check additionally for removable device? //
+// RecyclerIsValid() is false. //
+// - Make it possible to empty the recycle bin of one specific drive! //
+// //
+// Unknown! Do you know the answer? //
+// - How does Windows 9x/NT manage the daylight saving time (if it does)? //
+// - How does Windows Vista react to a RECYCLER\ folder on a NTFS device? //
+// - How does Windows Vista react to a RECYCLED\ folder on a FAT device? //
+// //
+// Not analyzed yet! Please send me your trash folder contents for analyzing! //
+// - Windows NT //
+// - Windows CE? //
+// - Windows 7 //
+// //
+// Thanks to all these who have helped me solving coding problems. //
+// Thanks to SEBA for sending in the Windows Vista trash structure files. //
+// Thanks to OMATA for testing the unit with Delphi 4. //
+// Thanks to DEITYSOU for making a bugfix of DriveExists() //
+// //
+////////////////////////////////////////////////////////////////////////////////////
+
+(*
+
+== TODO LISTE ==
+
+Wichtig! Windows XP: InfoTip, IntroText und LocalizedString sind Resourcenangaben und müssen ausgelesen werden!
+Testen: Wie reagiert Windows, wenn Bitbucket\C existiert, aber kein Wert 'Percent' hat? Mit der Standardeinstellung?
+Bug: Windows 2000 bei bestehenden Windows 95 Partition: Recycler Filename ist dann Recycled und nicht Recycler!
+bug? w95 recycled file hat immer selben löschzeitpunkt und größe? war die nicht verschieden?
+beachtet? bei leerem papierkorb auf fat ist weder info noch info2 vorhanden?
+testen: auch möglich, einen vista papierkorb offline öffnen?
+Problem: bei win95(ohne ie4) und win2000 gleichzeitiger installation: es existiert info UND info2!!!
+Implement SETTER functions to every kind of configuration thing. (percentage etc)
+Registry CURRENT_USER: Funktionen auch für fremde Benutzer zur Verfügung stellen?
+Es sollte möglich sein, dass ein Laufwerk mehr als 1 Recycler beinhaltet -- behandeln
+
+- Future -
+
+Demoapplikation: Dateien statt Text als Explorer-Like?
+Einzelne Elemente oder alle wiederherstellen oder löschen
+Konfiguration für Laufwerke ändern etc
+IconString -> TIcon Convertion functions
+platzreservierung in mb-angabe berechnen
+I don't know if there exists any API function which checks the state at any internal way.
+
+*)
Index: Kopie von RecyclerFunctions.pas
===================================================================
--- Kopie von RecyclerFunctions.pas (revision 0)
+++ Kopie von RecyclerFunctions.pas (revision 0)
@@ -0,0 +1,2953 @@
+// TODO: Also include BC++ Versions
+{$IFNDEF BCB}
+{$DEFINE DEL1UP}
+{$IFNDEF VER80}
+{$DEFINE DEL2UP}
+{$IFNDEF VER90}
+{$DEFINE DEL3UP}
+{$IFNDEF VER100}
+{$DEFINE DEL4UP}
+{$IFNDEF VER120}
+{$DEFINE DEL5UP}
+{$IFNDEF VER130}
+{$DEFINE DEL6UP}
+{$IFNDEF VER140}
+{$DEFINE DEL7UP}
+{$ENDIF}
+{$ENDIF}
+{$ENDIF}
+{$ENDIF}
+{$ENDIF}
+{$ENDIF}
+{$ENDIF}
+
+{$IFDEF DEL7UP}
+{$WARN UNSAFE_TYPE OFF}
+{$WARN UNSAFE_CODE OFF}
+{$WARN UNSAFE_CAST OFF}
+{$ENDIF}
+
+{$IFDEF DEL6UP}
+unit RecyclerFunctions platform;
+{$ELSE}
+unit RecyclerFunctions;
+{$ENDIF}
+
+// Configuration
+
+// If enabled, all functions with parameter "InfofileOrRecycleFolder" will
+// also accept files which are not the indexfile (then, a INFO2 or INFO file
+// will be searched in this directory).
+{.$DEFINE allow_all_filenames}
+
+interface
+
+uses
+ Windows, SysUtils, Classes, {$IFDEF DEL6UP}DateUtils,{$ENDIF}
+ ShellApi{$IFNDEF DEL6UP}, FileCtrl{$ENDIF}, Registry,
+ Messages, BitOps;
+
+type
+ EUnknownState = class(Exception);
+ EEventCategoryNotDefined = class(Exception);
+ EAPICallError = class(Exception);
+
+ PSHQueryRBInfo = ^TSHQueryRBInfo;
+ TSHQueryRBInfo = packed record
+ cbSize : dword;
+ i64Size : int64;
+ i64NumItems : int64;
+ end;
+
+ GPOLICYBOOL = (gpUndefined, gpEnabled, gpDisabled);
+
+ // TODO: $Recycle.Bin at external harddisk with Vista??
+
+ TRecycleBinManager = class(TObject)
+ class function RecyclerGetCurrentIconString: string;
+ class function RecyclerGetDefaultIconString: string;
+ class function RecyclerGetEmptyIconString: string;
+ class function RecyclerGetFullIconString: string;
+
+ class function RecyclerIsEmpty: boolean; overload;
+ class function RecyclerIsEmpty(Drive: Char): boolean; overload;
+
+ {$IFDEF DEL6UP}
+ class function RecyclerGetDateTime(drive: char; fileid: string): tdatetime; overload;
+ class function RecyclerGetDateTime(drive: char; UserSID: string; fileid: string): tdatetime; overload;
+ class function RecyclerGetDateTime(InfofileOrRecycleFolder: string): tdatetime; overload;
+ class function RecyclerGetDateTime(InfofileOrRecycleFolder: string; id: string): tdatetime; overload;
+ {$ENDIF}
+
+ class function RecyclerGetSourceUnicode(drive: char; fileid: string): WideString; overload;
+ class function RecyclerGetSourceUnicode(drive: char; UserSID: string; fileid: string): WideString; overload;
+ class function RecyclerGetSourceUnicode(InfofileOrRecycleFolder: string): WideString; overload;
+ class function RecyclerGetSourceUnicode(InfofileOrRecycleFolder: string; id: string): WideString; overload;
+
+ class function RecyclerGetSource(drive: char; fileid: string): string; overload;
+ class function RecyclerGetSource(drive: char; UserSID: string; fileid: string): string; overload;
+ class function RecyclerGetSource(InfofileOrRecycleFolder: string): string; overload;
+ class function RecyclerGetSource(InfofileOrRecycleFolder: string; id: string): string; overload;
+
+ class procedure RecyclerListIndexes(drive: char; result: TStringList); overload;
+ class procedure RecyclerListIndexes(drive: char; UserSID: string; result: TStringList); overload;
+ class procedure RecyclerListIndexes(InfofileOrRecycleFolder: string; result: TStringList); overload;
+
+ class function RecyclerGetSourceDrive(drive: char; fileid: string): char; overload;
+ class function RecyclerGetSourceDrive(drive: char; UserSID: string; fileid: string): char; overload;
+ class function RecyclerGetSourceDrive(InfofileOrRecycleFolder: string): char; overload;
+ class function RecyclerGetSourceDrive(InfofileOrRecycleFolder: string; id: string): char; overload;
+
+ class function RecyclerOriginalSize(drive: char; fileid: string): integer; overload;
+ class function RecyclerOriginalSize(drive: char; UserSID: string; fileid: string): integer; overload;
+ class function RecyclerOriginalSize(InfofileOrRecycleFolder: string): integer; overload;
+ class function RecyclerOriginalSize(InfofileOrRecycleFolder: string; id: string): integer; overload;
+
+ class function RecyclerIsValid(drive: char): boolean; overload;
+ class function RecyclerIsValid(drive: char; UserSID: string): boolean; overload;
+ class function RecyclerIsValid(InfofileOrRecycleFolder: string): boolean; overload;
+
+ class function RecyclerCurrentFilename(drive: char; fileid: string): string; overload;
+ class function RecyclerCurrentFilename(drive: char; UserSID: string; fileid: string): string; overload;
+ class function RecyclerCurrentFilename(InfofileOrRecycleFolder: string): string; overload;
+ class function RecyclerCurrentFilename(InfofileOrRecycleFolder: string; id: string): string; overload;
+
+ class function RecyclerGetPath(drive: char; UserSID: string; IncludeInfofile: boolean; fileid: string): string; overload;
+ class function RecyclerGetPath(drive: char; UserSID: string; IncludeInfofile: boolean): string; overload;
+ class function RecyclerGetPath(drive: char; IncludeInfofile: boolean): string; overload;
+ class function RecyclerGetPath(drive: char; UserSID: string): string; overload;
+ class function RecyclerGetPath(drive: char): string; overload;
+
+ class procedure RecyclerGetInfofiles(drive: char; UserSID: string; IncludeInfofile: boolean; fileid: string; result: TStringList); overload;
+ class procedure RecyclerGetInfofiles(drive: char; UserSID: string; IncludeInfofile: boolean; result: TStringList); overload;
+ class procedure RecyclerGetInfofiles(drive: char; IncludeInfofile: boolean; result: TStringList); overload;
+ class procedure RecyclerGetInfofiles(drive: char; UserSID: string; result: TStringList); overload;
+ class procedure RecyclerGetInfofiles(drive: char; result: TStringList); overload;
+
+ class function RecyclerCurrentFilenameAndPath(drive: char; UserSID: string; fileid: string): string; overload;
+ class function RecyclerCurrentFilenameAndPath(drive: char; fileid: string): string; overload;
+ class function RecyclerCurrentFilenameAndPath(InfofileOrRecycleFolder: string; id: string): string; overload;
+
+ class function RecyclerRemoveItem(drive: char; UserSID: string; fileid: string): boolean; overload;
+ class function RecyclerRemoveItem(drive: char; fileid: string): boolean; overload;
+ class function RecyclerRemoveItem(InfofileOrRecycleFolder: string; id: string): boolean; overload;
+
+ class procedure RecyclerGetAllRecyclerDrives(result: TStringList);
+
+ class function RecyclerEmptyRecycleBin(flags: cardinal): boolean; overload;
+ class function RecyclerEmptyRecycleBin(sound, progress, confirmation: boolean): boolean; overload;
+
+ class function RecyclerAddFileOrFolder(FileOrFolder: string; confirmation: boolean): boolean; overload;
+ class function RecyclerAddFileOrFolder(FileOrFolder: string): boolean; overload;
+
+ class function RecyclerConfirmationDialogEnabled: boolean;
+ class function RecyclerShellStateConfirmationDialogEnabled: boolean;
+ class procedure RecyclerConfirmationDialogSetEnabled(NewSetting: boolean);
+
+ class function RecyclerGetName: string;
+ class function RecyclerGetInfoTip: string;
+ class function RecyclerGetIntroText: string;
+
+ class function RecyclerEmptyEventGetName: string;
+ class function RecyclerEmptyEventGetCurrentSound: string;
+ class function RecyclerEmptyEventGetDefaultSound: string;
+ class procedure RecyclerEmptyEventGetSoundCategories(AStringList: TStringList);
+ class function RecyclerEmptyEventGetSound(ACategory: string): string;
+
+ class function RecyclerGlobalGetPercentUsage: integer;
+ class function RecyclerSpecificGetPercentUsage(Drive: Char): integer;
+ class function RecyclerGetPercentUsageAutoDeterminate(Drive: Char): integer;
+
+ class function RecyclerGlobalIsNukeOnDelete: boolean;
+ class function RecyclerSpecificIsNukeOnDelete(Drive: Char): boolean;
+ class function RecyclerIsNukeOnDeleteAutoDeterminate(Drive: Char): boolean;
+
+ class function RecyclerHasGlobalSettings: boolean;
+
+ class function RecyclerGetNumItems: int64; overload;
+ class function RecyclerGetNumItems(Drive: Char): int64; overload;
+
+ class function RecyclerGetSize: int64; overload;
+ class function RecyclerGetSize(Drive: Char): int64; overload;
+
+ class function RecyclerGetAPIInfo(Drive: Char): TSHQueryRBInfo; overload;
+ class function RecyclerGetAPIInfo(Path: String): TSHQueryRBInfo; overload;
+
+ class function RecyclerGetCLSID: string;
+
+ // Diese Funktion ist false, wenn sie z.B. unter Windows 95 ohne Internet Explorer
+ // 4.0 Shell Extension ausgeführt wird. Wenn abwärtskompatibler Code geschrieben
+ // werden soll, sollte RecyclerQueryFunctionAvailable() verwendet werden, da
+ // unter Windows 95 folgende Funktionalitäten NICHT vorhanden sind:
+ // - RecyclerIsEmpty
+ // - RecyclerGetNumItems
+ // - RecyclerGetSize
+ // - RecyclerGetAPIInfo
+ class function RecyclerQueryFunctionAvailable: boolean;
+
+ class function RecyclerGroupPolicyNoRecycleFiles: GPOLICYBOOL;
+ class function RecyclerGroupPolicyConfirmFileDelete: GPOLICYBOOL;
+ class function RecyclerGroupPolicyRecycleBinSize: integer;
+
+ class function RecyclerIsPossible(Drive: Char): boolean;
+
+ class function RecyclerLibraryVersion: string;
+ end;
+
+ function GPBoolToString(value: GPOLICYBOOL): String;
+
+const
+ RECYCLER_CLSID = '{645FF040-5081-101B-9F08-00AA002F954E}';
+
+implementation
+
+type
+ SHELLSTATE = record
+ Flags1: DWORD;
+(*
+ BOOL fShowAllObjects : 1;
+ BOOL fShowExtensions : 1;
+ BOOL fNoConfirmRecycle : 1;
+
+ BOOL fShowSysFiles : 1;
+ BOOL fShowCompColor : 1;
+ BOOL fDoubleClickInWebView : 1;
+ BOOL fDesktopHTML : 1;
+ BOOL fWin95Classic : 1;
+ BOOL fDontPrettyPath : 1;
+ BOOL fShowAttribCol : 1; // No longer used, dead bit
+ BOOL fMapNetDrvBtn : 1;
+ BOOL fShowInfoTip : 1;
+ BOOL fHideIcons : 1;
+ BOOL fWebView : 1;
+ BOOL fFilter : 1;
+ BOOL fShowSuperHidden : 1;
+ BOOL fNoNetCrawling : 1;
+*)
+ dwWin95Unused: DWORD; // Win95 only - no longer supported pszHiddenFileExts
+ uWin95Unused: UINT; // Win95 only - no longer supported cbHiddenFileExts
+
+ // Note: Not a typo! This is a persisted structure so we cannot use LPARAM
+ lParamSort: Integer;
+ iSortDirection: Integer;
+
+ version: UINT;
+
+ // new for win2k. need notUsed var to calc the right size of ie4 struct
+ // FIELD_OFFSET does not work on bit fields
+ uNotUsed: UINT; // feel free to rename and use
+ Flags2: DWORD;
+(*
+ BOOL fSepProcess: 1;
+ // new for Whistler.
+ BOOL fStartPanelOn: 1; //Indicates if the Whistler StartPanel mode is ON or OFF.
+ BOOL fShowStartPage: 1; //Indicates if the Whistler StartPage on desktop is ON or OFF.
+ UINT fSpareFlags : 13;
+*)
+ end;
+ LPSHELLSTATE = ^SHELLSTATE;
+
+const
+ {$IFDEF MSWINDOWS}
+ shell32 = 'shell32.dll';
+ advapi32 = 'advapi32.dll';
+ {$ENDIF}
+ {$IFDEF LINUX}
+ shell32 = 'libshell32.borland.so';
+ advapi32 = 'libwine.borland.so';
+ {$ENDIF}
+
+ // Masks for the shellstate
+ SSF_SHOWALLOBJECTS = $00000001;
+ SSF_SHOWEXTENSIONS = $00000002;
+ SSF_HIDDENFILEEXTS = $00000004;
+ SSF_SERVERADMINUI = $00000004;
+ SSF_SHOWCOMPCOLOR = $00000008;
+ SSF_SORTCOLUMNS = $00000010;
+ SSF_SHOWSYSFILES = $00000020;
+ SSF_DOUBLECLICKINWEBVIEW = $00000080;
+ SSF_SHOWATTRIBCOL = $00000100;
+ SSF_DESKTOPHTML = $00000200;
+ SSF_WIN95CLASSIC = $00000400;
+ SSF_DONTPRETTYPATH = $00000800;
+ SSF_SHOWINFOTIP = $00002000;
+ SSF_MAPNETDRVBUTTON = $00001000;
+ SSF_NOCONFIRMRECYCLE = $00008000;
+ SSF_HIDEICONS = $00004000;
+ SSF_FILTER = $00010000;
+ SSF_WEBVIEW = $00020000;
+ SSF_SHOWSUPERHIDDEN = $00040000;
+ SSF_SEPPROCESS = $00080000;
+ SSF_NONETCRAWLING = $00100000;
+ SSF_STARTPANELON = $00200000;
+ SSF_SHOWSTARTPAGE = $00400000;
+
+// **********************************************************
+// COMPATIBILITY FUNCTIONS
+// **********************************************************
+
+{$IFNDEF DEL5UP}
+function IncludeTrailingBackslash(str: string): string;
+begin
+ if Copy(str, length(str), 1) = '\' then // TODO? Gibt es PathDelim in Delphi 4?
+ Result := str
+ else
+ Result := str + '\';
+end;
+{$ENDIF}
+
+// **********************************************************
+// INTERNALLY USED FUNCTIONS
+// **********************************************************
+
+resourcestring
+ LNG_UNEXPECTED_STATE = 'Cannot determinate state of "%s" because of an unknown value in the configuration of your operation system. Please contact the developer of the Recycler Bin Unit and help improving the determination methods!';
+ LNG_API_CALL_ERROR = 'Error while calling the API. Additional information: "%s".';
+ LNG_NOT_CALLABLE = '%s not callable';
+ LNG_ERROR_CODE = '%s (Arguments: %s) returns error code %s';
+
+function _FileSize(FileName: string): int64;
+var
+ fs: TFileStream;
+begin
+ fs := TFileStream.Create(FileName, fmOpenRead);
+ try
+ result := fs.size;
+ finally
+ fs.free;
+ end;
+end;
+
+function _DriveNum(Drive: Char): Byte;
+// a->0, ..., z->25
+var
+ tmp: string;
+begin
+ tmp := LowerCase(Drive);
+ result := Ord(tmp[1])-Ord('a');
+end;
+
+function _registryReadDump(AReg: TRegistry; AName: string): string;
+const
+ // Win2000 RegEdit has set the max input length of a REG_BINARY to $3FFF.
+ // Probably its the longest possible binary string and not just a GUI limit.
+ BufMax = $3FFF;
+var
+ buf: array[0..BufMax] of byte;
+ i: integer;
+ realsize: integer;
+begin
+ realsize := AReg.ReadBinaryData(AName, buf, SizeOf(buf));
+
+ for i := 0 to realsize-1 do
+ begin
+ result := result + chr(buf[i]);
+ end;
+end;
+
+function _GetStringFromDLL(filename: string; num: integer): string;
+const
+ // http://www.eggheadcafe.com/forumarchives/vcmfc/sep2005/post23917443.asp
+ MAX_BUF = 4097; // OK?
+var
+ hLib: THandle;
+ buf: array[0..MAX_BUF] of char;
+begin
+ hLib := LoadLibrary(PChar(filename));
+ try
+ LoadString(hLib, num, buf, sizeof(buf));
+ result := buf;
+ finally
+ FreeLibrary(hLib);
+ end;
+end;
+
+// http://www.delphi-library.de/topic_Umgebungsvariable+in+einem+String+aufloesen_20516,0.html
+function _ExpandEnvStr(const szInput: string): string;
+const
+ MAXSIZE = 32768; // laut PSDK sind 32k das Maximum
+begin
+ SetLength(Result,MAXSIZE);
+ SetLength(Result,ExpandEnvironmentStrings(pchar(szInput),
+ @Result[1],length(Result))-1); //-1 um abschließendes #0 zu verwerfen
+end;
+
+// Beispiele
+// Papierkorb -- Windows 95
+// @C:\WINNT\system32\shell32.dll,-8964@1031,Papierkorb -- Windows 2000
+
+function _DecodeReferenceString(s: string): string;
+var
+ dll, id, lang, cache: string;
+ sl, sl2: tstringlist;
+begin
+ if Copy(s, 1, 1) = '@' then
+ begin
+ // Referenz auf eine DLL
+ // @<dll>,-<id>[@<lang>][,<cache>]
+
+ sl := TStringList.Create;
+ try
+ // '@' am Anfang entfernen
+ s := Copy(s, 2, length(s)-1);
+
+ // Nach ',' auftrennen
+ // sl[0] --> dll
+ // sl[1] --> -id@lang
+ // sl[2] --> cache
+ sl.CommaText := s;
+
+ if sl.Count > 2 then
+ begin
+ // Das Ergebnis ist bereits im Klartext vorhanden und muss nicht extrahiert werden
+ // Ist bei Windows 2000 der Fall
+ cache := sl[2];
+ result := cache;
+ exit;
+ end;
+
+ if sl.Count > 1 then
+ begin
+ dll := sl[0];
+
+ sl2 := TStringList.Create;
+ try
+ // Nach '@' auftrennen
+ // sl2[0] --> id
+ // sl2[1] --> lang
+ sl2.CommaText := StringReplace(sl[1], '@', ',', [rfReplaceAll]);
+
+ id := sl2[0];
+
+ if sl2.Count > 1 then
+ begin
+ // ToDo: In Zukunft beachten, sofern möglich
+ lang := sl2[1];
+ end;
+
+ // Umgebungsvariablen erkennen und Minuszeichen entfernen
+ result := _GetStringFromDLL(_ExpandEnvStr(dll), -StrToInt(id));
+ finally
+ sl2.Free;
+ end;
+ end
+ else
+ begin
+ // Zu wenige Informationen!
+
+ result := '';
+ end;
+ finally
+ sl.Free;
+ end;
+ end
+ else
+ begin
+ // Kein Hinweis auf eine Referenz
+ result := s;
+ end;
+end;
+
+function _readInt8(const Stream: TStream): byte;
+var
+ I: integer;
+begin
+ i := 0;
+ Stream.ReadBuffer(i, 1);
+ Result := i;
+end;
+
+function _readInt32(const Stream: TStream): Longword;
+var
+ I: integer;
+begin
+ i := 0;
+ Stream.ReadBuffer(i, 4);
+ Result := i;
+end;
+
+function _readInt64(const Stream: TStream): int64;
+var
+ I: int64;
+begin
+ i := 0;
+ Stream.ReadBuffer(i, 8);
+ Result := i;
+end;
+
+function _readChar(const Stream: TStream): char;
+var
+ C: Char;
+begin
+ C := #0;
+ Stream.ReadBuffer(C, 1);
+ Result := C;
+end;
+
+function _readNullTerminatedString(const Stream: TStream): String;
+var
+ S: String;
+ C: Char;
+begin
+ S := '';
+ repeat
+ Stream.ReadBuffer(C, 1);
+ if (C <> #0) then
+ S := S + C;
+ until C = #0;
+ Result := S;
+end;
+
+// http://www.delphipraxis.net/post761928.html#761928
+function _readNullTerminatedWideString(const Stream: TStream): WideString;
+var
+ S: WideString;
+ WC: WideChar;
+begin
+ S := '';
+ repeat
+ Stream.ReadBuffer(WC, 2);
+ if (WC <> #0) then
+ S := S + WC;
+ until WC = #0;
+ Result := S;
+end;
+
+// http://www.delphipraxis.net/post340194.html#340194
+function _nowUTC: TDateTime;
+var
+ SystemTime: TSystemTime;
+begin
+ GetSystemTime(SystemTime);
+ with SystemTime do
+ begin
+ Result := EncodeDate(wYear, wMonth, wDay) +
+ EncodeTime(wHour, wMinute, wSecond, wMilliseconds);
+ end;
+end;
+
+{$IFDEF DEL6UP}
+function _getGMTDifference(): extended;
+begin
+ result := - (datetimetounix(_nowUTC())-datetimetounix(Now())) / 3600;
+end;
+
+function _fileTimeToDateTime(FileTime: int64): TDateTime;
+begin
+ // http://www.e-fense.com/helix/Docs/Recycler_Bin_Record_Reconstruction.pdf
+ // UnixTime = 0.0000001 * NTTime + 11644473600
+ // This is wrong! The correct formula is:
+ // UnixTime = 0.0000001 * NTTime - 11644473600 + c * 3600
+ // c = GMT-Difference (MEZ = 1) inclusive daylight saving time (+3600 seconds)
+ result := unixtodatetime(FileTime div 10000000 - 11644473600 + round(_getGMTDifference() * 3600));
+end;
+{$ENDIF}
+
+// http://www.delphipraxis.net/post471470.html
+function _getAccountSid(const Server, User: WideString; var Sid: PSID): DWORD;
+var
+ dwDomainSize, dwSidSize: DWord;
+ R: LongBool;
+ wDomain: WideString;
+ Use: DWord;
+begin
+ Result := 0;
+ SetLastError(0);
+ dwSidSize := 0;
+ dwDomainSize := 0;
+ R := LookupAccountNameW(PWideChar(Server), PWideChar(User), nil, dwSidSize,
+ nil, dwDomainSize, Use);
+ if (not R) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then
+ begin
+ SetLength(wDomain, dwDomainSize);
+ Sid := GetMemory(dwSidSize);
+ R := LookupAccountNameW(PWideChar(Server), PWideChar(User), Sid,
+ dwSidSize, PWideChar(wDomain), dwDomainSize, Use);
+ if not R then
+ begin
+ FreeMemory(Sid);
+ Sid := nil;
+ end;
+ end
+ else
+ Result := GetLastError;
+end;
+
+// Template:
+// http://www.latiumsoftware.com/en/pascal/0014.php
+function _getLoginNameW: widestring;
+var
+ Buffer: array[0..255] of widechar;
+ Size: dword;
+begin
+ Size := 256;
+ if GetUserNameW(Buffer, Size) then
+ Result := Buffer
+ else
+ Result := 'User';
+end;
+
+function _Dyn_ConvertSidToStringSidA(SID: PSID; var strSID: LPSTR): boolean;
+type
+ DllReg = function(SID: PSID; var StringSid: LPSTR): Boolean; stdcall;
+var
+ hDll: THandle;
+ dr: DllReg;
+begin
+ result := false;
+ hDll := LoadLibrary(advapi32);
+ if hDll <> 0 then
+ begin
+ @dr := GetProcAddress(hDll, 'ConvertSidToStringSidA');
+ if assigned(dr) then
+ begin
+ result := dr(SID, strSID);
+ end;
+ end;
+end;
+
+// http://www.delphipraxis.net/post471470.html
+// Changed
+function _getMySID(): string;
+var
+ SID: PSID;
+ strSID: PAnsiChar;
+ s: String;
+ err: DWORD;
+begin
+ SID := nil;
+
+ err := _getAccountSid('', _getLoginNameW(), SID);
+
+ if err = 0 then
+ begin
+ if _Dyn_ConvertSidToStringSidA(SID, strSID) then
+ s := string(strSID)
+ else
+ s := SysErrorMessage(err);
+ end
+ else
+ s := SysErrorMessage(err);
+
+ result := s;
+end;
+
+// Originalcode aus http://www.delphipraxis.net/post2933.html
+function _DriveExists(DriveByte: Byte): Boolean; overload;
+begin
+ Result := GetLogicalDrives and (1 shl DriveByte) <> 0;
+end;
+
+function _driveExists(Drive: Char): Boolean; overload;
+var
+ DriveByte: Byte;
+ tmp: string;
+begin
+ // Make drive letter upper case (for older Delphi versions)
+ tmp := UpperCase(Drive);
+ Drive := tmp[1];
+
+ DriveByte := Ord(Drive) - Ord('A');
+ Result := _DriveExists(DriveByte);
+end;
+
+function _isFAT(drive: char): boolean;
+var
+ Dummy2: DWORD;
+ Dummy3: DWORD;
+ FileSystem: array[0..MAX_PATH] of char;
+ VolumeName: array[0..MAX_PATH] of char;
+ s: string;
+begin
+ result := false;
+ if _driveExists(drive) then
+ begin
+ s := drive + DriveDelim + PathDelim; // ohne die Auslagerung in einen String kommt es zu einer AV in ntdll
+ GetVolumeInformation(PChar(s), VolumeName,
+ SizeOf(VolumeName), nil, Dummy2, Dummy3, FileSystem, SizeOf(FileSystem));
+ result := uppercase(copy(FileSystem, 0, 3)) = 'FAT';
+ end;
+end;
+
+// **********************************************************
+// VISTA AND WINDOWS 7 FUNCTIONS, INTERNAL USED
+// **********************************************************
+
+const
+ vista_valid_index_size = $220; // 544
+
+function _isFileVistaRealfile(filename: string): boolean;
+begin
+ result := uppercase(copy(extractfilename(filename), 0, 2)) = '$R';
+end;
+
+function _isFileVistaIndexfile(filename: string): boolean;
+begin
+ result := uppercase(copy(extractfilename(filename), 0, 2)) = '$I';
+end;
+
+function _isFileVistaNamed(filename: string): boolean;
+begin
+ result := _isFileVistaIndexfile(filename) or
+ _isFileVistaRealfile(filename);
+end;
+
+function _VistaChangeRealfileToIndexfile(realfile: string): string;
+begin
+ if _isFileVistaRealfile(realfile) then
+ begin
+ result := extractfilepath(realfile)+'$I'+
+ copy(extractfilename(realfile), 3, length(extractfilename(realfile))-2);
+ end
+ else
+ result := realfile; // ignore, even if it is not a vista recycle-file
+end;
+
+function _VistaChangeIndexfileToRealfile(indexfile: string): string;
+begin
+ if _isFileVistaIndexfile(indexfile) then
+ begin
+ result := extractfilepath(indexfile)+'$R'+
+ copy(extractfilename(indexfile), 3, length(extractfilename(indexfile))-2);
+ end
+ else
+ result := indexfile; // ignore, even if it is not a vista recycle-file
+end;
+
+procedure _VistaListIndexes(recyclerpath: string; result: TStringList);
+var
+ sr: TSearchRec;
+ r: Integer;
+ tmp: string;
+begin
+ tmp := recyclerpath;
+ tmp := IncludeTrailingBackslash(tmp);
+
+ if not directoryexists(tmp) then exit;
+
+ r := FindFirst(tmp+PathDelim + '$I*', faAnyFile, sr);
+ while r = 0 do
+ begin
+ if (sr.Name <> '.') and (sr.Name <> '..') then
+ begin
+ if sr.Size = vista_valid_index_size then
+ begin
+ result.Add(copy(sr.name, 3, length(sr.name)-2));
+ end;
+ end;
+ r := FindNext(sr);
+ end;
+
+ FindClose(sr);
+end;
+
+function _VistaCurrentFilename(infofilename: string): string;
+begin
+ result := extractfilename(infofilename);
+
+ if _isFileVistaRealfile(result) then
+ begin
+ exit;
+ end;
+
+ if _isFileVistaIndexfile(result) then
+ begin
+ result := _VistaChangeIndexfileToRealfile(result);
+ exit;
+ end;
+
+ result := copy(result, 3, length(result)-2);
+ result := '$R'+result;
+end;
+
+function _VistaGetSourceDrive(infofile: string): char;
+var
+ fs: TFileStream;
+ tmp: string;
+const
+ drive_vista_position = $18;
+begin
+ result := #0;
+
+ tmp := infofile;
+ tmp := _VistaChangeRealfileToIndexfile(tmp);
+ if not fileexists(tmp) then exit;
+
+ fs := TFileStream.Create(tmp, fmOpenRead);
+ try
+ fs.seek(drive_vista_position, soFromBeginning);
+ result := _readChar(fs);
+ finally
+ fs.free;
+ end;
+end;
+
+{$IFDEF DEL6UP}
+function _VistaGetDateTime(infofile: string): TDateTime;
+var
+ fs: TFileStream;
+ tmp: string;
+const
+ timestamp_vista_position = $10;
+begin
+ result := EncodeDateTime(1601, 1, 1, 0, 0, 0, 0);
+
+ tmp := infofile;
+ tmp := _VistaChangeRealfileToIndexfile(tmp);
+ if not fileexists(tmp) then exit;
+
+ fs := TFileStream.Create(tmp, fmOpenRead);
+ try
+ fs.seek(timestamp_vista_position, soFromBeginning);
+ result := _fileTimeToDateTime(_readInt64(fs));
+ finally
+ fs.free;
+ end;
+end;
+{$ENDIF}
+
+function _VistaGetSourceUnicode(infofile: string): string;
+var
+ fs: TFileStream;
+ tmp: string;
+const
+ unicode_vista_position = $18;
+begin
+ result := '';
+
+ tmp := infofile;
+ tmp := _VistaChangeRealfileToIndexfile(tmp);
+ if not fileexists(tmp) then exit;
+
+ fs := TFileStream.Create(tmp, fmOpenRead);
+ try
+ fs.seek(unicode_vista_position, soFromBeginning);
+ result := _readNullTerminatedWideString(fs);
+ finally
+ fs.free;
+ end;
+end;
+
+function _VistaOriginalSize(infofile: string): integer;
+var
+ fs: TFileStream;
+ tmp: string;
+const
+ size_vista_position = $8;
+begin
+ result := -1;
+
+ tmp := infofile;
+ tmp := _VistaChangeRealfileToIndexfile(tmp);
+ if not fileexists(tmp) then exit;
+
+ fs := TFileStream.Create(tmp, fmOpenRead);
+ try
+ fs.seek(size_vista_position, soFromBeginning);
+ result := _readInt32(fs);
+ finally
+ fs.free;
+ end;
+end;
+
+function _checkInfo1or2File(filename: string): boolean;
+var
+ fs: TStream;
+ record_length: integer;
+const
+ length_position = $C;
+ empty_size = 20;
+begin
+ fs := TFileStream.Create(filename, fmOpenRead);
+ try
+ fs.seek(length_position, soFromBeginning);
+ record_length := _readInt32(fs);
+
+ // Check the file length
+ if record_length = 0 then
+ result := false
+ else
+ result := (fs.size - empty_size) mod record_length = 0;
+ finally
+ fs.free;
+ end;
+end;
+
+function _VistaIsValid(infofile: string): boolean;
+var
+ tmp: string;
+begin
+ result := false;
+
+ tmp := infofile;
+ tmp := _VistaChangeRealfileToIndexfile(tmp);
+ if not fileexists(tmp) then exit;
+
+ // Check the file length
+ result := _FileSize(tmp) = vista_valid_index_size;
+end;
+
+// **********************************************************
+// PUBLIC FUNCTIONS
+// **********************************************************
+
+{$IFDEF DEL6UP}
+
+class function TRecycleBinManager.RecyclerGetDateTime(InfofileOrRecycleFolder: string): tdatetime;
+begin
+ result := RecyclerGetDateTime(InfofileOrRecycleFolder, '');
+end;
+
+class function TRecycleBinManager.RecyclerGetDateTime(drive: char; fileid: string): tdatetime;
+begin
+ result := RecyclerGetDateTime(drive, '', fileid);
+end;
+
+class function TRecycleBinManager.RecyclerGetDateTime(drive: char; UserSID: string; fileid: string): tdatetime;
+var
+ infofile: string;
+begin
+ infofile := RecyclerGetPath(drive, UserSID, true, fileid);
+ result := RecyclerGetDateTime(infofile, fileid);
+end;
+
+class function TRecycleBinManager.RecyclerGetDateTime(InfofileOrRecycleFolder: string; id: string): tdatetime;
+var
+ fs: TFileStream;
+ i, record_length: integer;
+ tmp: string;
+const
+ length_position = $C;
+ unique_index_position = $118;
+ timestamp_position = $120;
+begin
+ // FILETIME does start at 01.01.1601 00:00:00 (GMT)
+ result := EncodeDateTime(1601, 1, 1, 0, 0, 0, 0);
+
+ tmp := InfofileOrRecycleFolder;
+
+ if _isFileVistaNamed(tmp) then
+ begin
+ result := _VistaGetDateTime(tmp);
+ exit;
+ end;
+
+ {$IFDEF allow_all_filenames}
+ if not RecyclerIsValid(tmp) and fileexists(tmp) then
+ begin
+ if fileexists(extractfilepath(tmp)+'INFO2') then
+ tmp := extractfilepath(tmp)+'INFO2'
+ else if fileexists(extractfilepath(tmp)+'INFO') then
+ tmp := extractfilepath(tmp)+'INFO';
+ end;
+ {$ENDIF}
+
+ if directoryexists(tmp) then
+ begin
+ tmp := IncludeTrailingBackslash(tmp);
+
+ if fileexists(tmp+'$I'+id) then
+ begin
+ result := _VistaGetDateTime(tmp+'$I'+id);
+ exit;
+ end
+ else if fileexists(tmp+'INFO2') then tmp := tmp+'INFO2'
+ else if fileexists(tmp+'INFO') then tmp := tmp+'INFO';
+ end;
+
+ if not fileexists(tmp) then exit;
+ if not RecyclerIsValid(tmp) then exit;
+
+ fs := TFileStream.Create(tmp, fmOpenRead);
+ try
+ fs.seek(length_position, soFromBeginning);
+ record_length := _readInt32(fs);
+
+ i := -1;
+ repeat
+ inc(i);
+ if unique_index_position+i*record_length > fs.size then break;
+ fs.seek(unique_index_position+i*record_length, soFromBeginning);
+ if inttostr(_readInt32(fs)) = id then
+ begin
+ fs.seek(timestamp_position+i*record_length, soFromBeginning);
+ result := _fileTimeToDateTime(_readInt64(fs));
+ break;
+ end;
+ until false;
+ finally
+ fs.free;
+ end;
+end;
+
+{$ENDIF}
+
+////////////////////////////////////////////////////////////////////////////////
+
+{ TRecycleBinManager }
+
+class function TRecycleBinManager.RecyclerGetCurrentIconString: string;
+begin
+ if TRecycleBinManager.RecyclerIsEmpty then
+ result := RecyclerGetEmptyIconString
+ else
+ result := RecyclerGetFullIconString;
+end;
+
+class function TRecycleBinManager.RecyclerGetDefaultIconString: string;
+var
+ reg: TRegistry;
+begin
+ // Please note: The "default" icon is not always the icon of the
+ // current recycle bin in its current state (full, empty)
+ // At Windows 95b, the registry value actually did change every time the
+ // recycle bin state did change, but at Windows 2000 I could not see any
+ // update, even after reboot. So, the registry value is possible fixed as
+ // default = empty on newer OS versions.
+
+ reg := TRegistry.Create;
+ try
+ reg.RootKey := HKEY_CLASSES_ROOT;
+ if reg.OpenKeyReadOnly('CLSID\'+RECYCLER_CLSID+'\DefaultIcon') then
+ begin
+ result := reg.ReadString('');
+ reg.CloseKey;
+ end;
+ finally
+ reg.Free;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerGetEmptyIconString: string;
+var
+ reg: TRegistry;
+begin
+ reg := TRegistry.Create;
+ try
+ reg.RootKey := HKEY_CLASSES_ROOT;
+ if reg.OpenKeyReadOnly('CLSID\'+RECYCLER_CLSID+'\DefaultIcon') then
+ begin
+ result := reg.ReadString('Empty');
+ reg.CloseKey;
+ end;
+ finally
+ reg.Free;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerGetFullIconString: string;
+var
+ reg: TRegistry;
+begin
+ reg := TRegistry.Create;
+ try
+ reg.RootKey := HKEY_CLASSES_ROOT;
+ if reg.OpenKeyReadOnly('CLSID\'+RECYCLER_CLSID+'\DefaultIcon') then
+ begin
+ result := reg.ReadString('Full');
+ reg.CloseKey;
+ end;
+ finally
+ reg.Free;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerIsEmpty: boolean;
+var
+ Drive: Char;
+begin
+ result := true;
+ for Drive := 'A' to 'Z' do
+ begin
+ if RecyclerIsPossible(Drive) and not RecyclerIsEmpty(Drive) then
+ begin
+ result := false;
+ exit;
+ end;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerIsEmpty(Drive: Char): boolean;
+begin
+ result := RecyclerGetAPIInfo(Drive).i64NumItems = 0;
+end;
+
+class function TRecycleBinManager.RecyclerGetSourceUnicode(InfofileOrRecycleFolder: string): WideString;
+begin
+ result := RecyclerGetSourceUnicode(InfofileOrRecycleFolder, '');
+end;
+
+class function TRecycleBinManager.RecyclerGetSourceUnicode(drive: char; fileid: string): WideString;
+begin
+ result := RecyclerGetSourceUnicode(drive, '', fileid);
+end;
+
+class function TRecycleBinManager.RecyclerGetSourceUnicode(drive: char; UserSID: string; fileid: string): WideString;
+var
+ infofile: string;
+begin
+ if Win32Platform = VER_PLATFORM_WIN32_NT then
+ begin
+ infofile := RecyclerGetPath(drive, UserSID, true, fileid);
+ result := RecyclerGetSourceUnicode(infofile, fileid);
+ end
+ else
+ begin
+ // Windows 9x does not support unicode
+ result := RecyclerGetSource(drive, UserSID, fileid);
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerGetSourceUnicode(InfofileOrRecycleFolder: string; id: string): WideString;
+var
+ fs: TFileStream;
+ i, record_length: integer;
+ tmp: string;
+const
+ length_position = $C;
+ unique_index_position = $118;
+ unicode_source_position = $12C;
+begin
+ result := '';
+
+ tmp := InfofileOrRecycleFolder;
+
+ if _isFileVistaNamed(tmp) then
+ begin
+ // Vista only gives unicode names
+ result := _VistaGetSourceUnicode(tmp);
+ exit;
+ end;
+
+ {$IFDEF allow_all_filenames}
+ if not RecyclerIsValid(tmp) and fileexists(tmp) then
+ begin
+ if fileexists(extractfilepath(tmp)+'INFO2') then
+ tmp := extractfilepath(tmp)+'INFO2'
+ else if fileexists(extractfilepath(tmp)+'INFO') then
+ tmp := extractfilepath(tmp)+'INFO';
+ end;
+ {$ENDIF}
+
+ if directoryexists(tmp) then
+ begin
+ tmp := IncludeTrailingBackslash(tmp);
+
+ if fileexists(tmp+'$I'+id) then
+ begin
+ // Vista only gives unicode names
+ result := _VistaGetSourceUnicode(tmp+'$I'+id);
+ exit;
+ end
+ else if fileexists(tmp+'INFO2') then tmp := tmp+'INFO2'
+ else if fileexists(tmp+'INFO') then tmp := tmp+'INFO';
+ end;
+
+ if not fileexists(tmp) then exit;
+ if not RecyclerIsValid(tmp) then exit;
+
+ fs := TFileStream.Create(tmp, fmOpenRead);
+ try
+ fs.seek(length_position, soFromBeginning);
+ record_length := _readInt32(fs);
+
+ if record_length <> $118 then
+ begin
+ // Windows NT
+ i := -1;
+ repeat
+ inc(i);
+ if unique_index_position+i*record_length > fs.size then break;
+ fs.seek(unique_index_position+i*record_length, soFromBeginning);
+ if inttostr(_readInt32(fs)) = id then
+ begin
+ fs.seek(unicode_source_position+i*record_length, soFromBeginning);
+ result := _readNullTerminatedWideString(fs);
+ break;
+ end;
+ until false;
+ end;
+ finally
+ fs.free;
+ end;
+
+ if record_length = $118 then
+ begin
+ // Windows 9x has no unicode support
+ result := RecyclerGetSource(tmp, id);
+ end;
+end;
+
+////////////////////////////////////////////////////////////////////////////////
+
+class function TRecycleBinManager.RecyclerGetSource(InfofileOrRecycleFolder: string): string;
+begin
+ result := RecyclerGetSource(InfofileOrRecycleFolder, '');
+end;
+
+class function TRecycleBinManager.RecyclerGetSource(drive: char; fileid: string): string;
+begin
+ result := RecyclerGetSource(drive, '', fileid);
+end;
+
+class function TRecycleBinManager.RecyclerGetSource(drive: char; UserSID: string; fileid: string): string;
+var
+ infofile: string;
+begin
+ infofile := RecyclerGetPath(drive, UserSID, true, fileid);
+ result := RecyclerGetSource(infofile, fileid);
+end;
+
+class function TRecycleBinManager.RecyclerGetSource(InfofileOrRecycleFolder: string; id: string): string;
+var
+ fs: TFileStream;
+ i, record_length: integer;
+ tmp: string;
+ alternativ: string;
+const
+ length_position = $C;
+ unique_index_position = $118;
+ source_position = $14;
+begin
+ result := '';
+
+ tmp := InfofileOrRecycleFolder;
+
+ if _isFileVistaNamed(tmp) then
+ begin
+ // Vista only gives unicode names
+ result := _VistaGetSourceUnicode(tmp);
+ exit;
+ end;
+
+ {$IFDEF allow_all_filenames}
+ if not RecyclerIsValid(tmp) and fileexists(tmp) then
+ begin
+ if fileexists(extractfilepath(tmp)+'INFO2') then
+ tmp := extractfilepath(tmp)+'INFO2'
+ else if fileexists(extractfilepath(tmp)+'INFO') then
+ tmp := extractfilepath(tmp)+'INFO';
+ end;
+ {$ENDIF}
+
+ if directoryexists(tmp) then
+ begin
+ tmp := IncludeTrailingBackslash(tmp);
+
+ if fileexists(tmp+'$I'+id) then
+ begin
+ // Vista only gives unicode names
+ result := _VistaGetSourceUnicode(tmp+'$I'+id);
+ exit;
+ end
+ else if fileexists(tmp+'INFO2') then tmp := tmp+'INFO2'
+ else if fileexists(tmp+'INFO') then tmp := tmp+'INFO';
+ end;
+
+ if not fileexists(tmp) then exit;
+ if not RecyclerIsValid(tmp) then exit;
+
+ fs := TFileStream.Create(tmp, fmOpenRead);
+ try
+ fs.seek(length_position, soFromBeginning);
+ record_length := _readInt32(fs);
+
+ i := -1;
+ repeat
+ inc(i);
+ if unique_index_position+i*record_length > fs.size then break;
+ fs.seek(unique_index_position+i*record_length, soFromBeginning);
+ if inttostr(_readInt32(fs)) = id then
+ begin
+ fs.seek(source_position+i*record_length, soFromBeginning);
+ alternativ := _readChar(fs);
+
+ if alternativ = #0 then
+ begin
+ fs.seek(source_position+i*record_length+1, soFromBeginning);
+ result := _readNullTerminatedString(fs);
+ end
+ else
+ begin
+ fs.seek(source_position+i*record_length, soFromBeginning);
+ result := _readNullTerminatedString(fs);
+ end;
+
+ break;
+ end;
+ until false;
+ finally
+ fs.free;
+ end;
+
+ // In some cases the ansi-source-name is [Null]:\...\
+ if alternativ = #0 then
+ begin
+ result := RecyclerGetSourceDrive(InfofileOrRecycleFolder, id) + result;
+ end;
+end;
+
+////////////////////////////////////////////////////////////////////////////////
+
+class procedure TRecycleBinManager.RecyclerListIndexes(drive: char; result: TStringList);
+begin
+ RecyclerListIndexes(drive, '', result);
+end;
+
+class procedure TRecycleBinManager.RecyclerListIndexes(drive: char; UserSID: string; result: TStringList);
+var
+ infofile: string;
+begin
+ infofile := RecyclerGetPath(drive, UserSID, false);
+ RecyclerListIndexes(infofile, result);
+end;
+
+class procedure TRecycleBinManager.RecyclerListIndexes(InfofileOrRecycleFolder: string; result: TStringList);
+var
+ fs: TFileStream;
+ i, record_length: integer;
+ tmp: string;
+const
+ length_position = $C;
+ unique_index_position = $118;
+begin
+ tmp := InfofileOrRecycleFolder;
+
+ if _isFileVistaNamed(tmp) then
+ begin
+ _VistaListIndexes(extractfilepath(tmp), result);
+ exit;
+ end;
+
+ {$IFDEF allow_all_filenames}
+ if not RecyclerIsValid(tmp) and fileexists(tmp) then
+ begin
+ if fileexists(extractfilepath(tmp)+'INFO2') then
+ tmp := extractfilepath(tmp)+'INFO2'
+ else if fileexists(extractfilepath(tmp)+'INFO') then
+ tmp := extractfilepath(tmp)+'INFO';
+ end;
+ {$ENDIF}
+
+ if directoryexists(tmp) then
+ begin
+ tmp := IncludeTrailingBackslash(tmp);
+
+ if fileexists(tmp+'INFO2') then tmp := tmp+'INFO2'
+ else if fileexists(tmp+'INFO') then tmp := tmp+'INFO'
+ else
+ begin
+ // Last try: is it a vista-directory?
+ _VistaListIndexes(tmp, result);
+ exit;
+ end;
+ end;
+
+ if not fileexists(tmp) then exit;
+ if not RecyclerIsValid(tmp) then exit;
+
+ fs := TFileStream.Create(tmp, fmOpenRead);
+ try
+ fs.seek(length_position, soFromBeginning);
+ record_length := _readInt32(fs);
+
+ i := -1;
+ repeat
+ inc(i);
+ if unique_index_position+i*record_length > fs.size then break;
+ fs.seek(unique_index_position+i*record_length, soFromBeginning);
+
+ result.Add(inttostr(_readInt32(fs)));
+ until false;
+ finally
+ fs.free;
+ end;
+end;
+
+////////////////////////////////////////////////////////////////////////////////
+
+class function TRecycleBinManager.RecyclerGetSourceDrive(InfofileOrRecycleFolder: string): char;
+begin
+ result := RecyclerGetSourceDrive(InfofileOrRecycleFolder, '');
+end;
+
+class function TRecycleBinManager.RecyclerGetSourceDrive(drive: char; fileid: string): char;
+begin
+ result := RecyclerGetSourceDrive(drive, '', fileid);
+end;
+
+class function TRecycleBinManager.RecyclerGetSourceDrive(drive: char; UserSID: string; fileid: string): char;
+var
+ infofile: string;
+begin
+ infofile := RecyclerGetPath(drive, UserSID, true, fileid);
+ result := RecyclerGetSourceDrive(infofile, fileid);
+end;
+
+class function TRecycleBinManager.RecyclerGetSourceDrive(InfofileOrRecycleFolder: string; id: string): char;
+var
+ fs: TFileStream;
+ i, record_length: integer;
+ tmp: string;
+const
+ length_position = $C;
+ unique_index_position = $118;
+ source_drive_position = $11C;
+begin
+ result := #0;
+
+ tmp := InfofileOrRecycleFolder;
+
+ if _isFileVistaNamed(tmp) then
+ begin
+ result := _VistaGetSourceDrive(tmp);
+ exit;
+ end;
+
+ {$IFDEF allow_all_filenames}
+ if not RecyclerIsValid(tmp) and fileexists(tmp) then
+ begin
+ if fileexists(extractfilepath(tmp)+'INFO2') then
+ tmp := extractfilepath(tmp)+'INFO2'
+ else if fileexists(extractfilepath(tmp)+'INFO') then
+ tmp := extractfilepath(tmp)+'INFO';
+ end;
+ {$ENDIF}
+
+ if directoryexists(tmp) then
+ begin
+ tmp := IncludeTrailingBackslash(tmp);
+
+ if fileexists(tmp+'$I'+id) then
+ begin
+ result := _VistaGetSourceDrive(tmp+'$I'+id);
+ exit;
+ end
+ else if fileexists(tmp+'INFO2') then tmp := tmp+'INFO2'
+ else if fileexists(tmp+'INFO') then tmp := tmp+'INFO';
+ end;
+
+ if not fileexists(tmp) then exit;
+ if not RecyclerIsValid(tmp) then exit;
+
+ fs := TFileStream.Create(tmp, fmOpenRead);
+ try
+ fs.seek(length_position, soFromBeginning);
+ record_length := _readInt32(fs);
+
+ i := -1;
+ repeat
+ inc(i);
+ if unique_index_position+i*record_length > fs.size then break;
+ fs.seek(unique_index_position+i*record_length, soFromBeginning);
+ if inttostr(_readInt32(fs)) = id then
+ begin
+ fs.seek(source_drive_position+i*record_length, soFromBeginning);
+ result := chr(ord('A') + _readInt8(fs));
+ break;
+ end;
+ until false;
+ finally
+ fs.free;
+ end;
+end;
+
+////////////////////////////////////////////////////////////////////////////////
+
+class function TRecycleBinManager.RecyclerOriginalSize(InfofileOrRecycleFolder: string): integer;
+begin
+ result := RecyclerOriginalSize(InfofileOrRecycleFolder, '');
+end;
+
+class function TRecycleBinManager.RecyclerOriginalSize(drive: char; fileid: string): integer;
+begin
+ result := RecyclerOriginalSize(drive, '', fileid);
+end;
+
+class function TRecycleBinManager.RecyclerOriginalSize(drive: char; UserSID: string; fileid: string): integer;
+var
+ infofile: string;
+begin
+ infofile := RecyclerGetPath(drive, UserSID, true, fileid);
+ result := RecyclerOriginalSize(infofile, fileid);
+end;
+
+class function TRecycleBinManager.RecyclerOriginalSize(InfofileOrRecycleFolder: string; id: string): integer;
+var
+ fs: TFileStream;
+ i, record_length: integer;
+ tmp: string;
+const
+ length_position = $C;
+ unique_index_position = $118;
+ original_size_position = $128;
+begin
+ result := -1;
+
+ tmp := InfofileOrRecycleFolder;
+
+ if _isFileVistaNamed(tmp) then
+ begin
+ result := _VistaOriginalSize(tmp);
+ exit;
+ end;
+
+ {$IFDEF allow_all_filenames}
+ if not RecyclerIsValid(tmp) and fileexists(tmp) then
+ begin
+ if fileexists(extractfilepath(tmp)+'INFO2') then
+ tmp := extractfilepath(tmp)+'INFO2'
+ else if fileexists(extractfilepath(tmp)+'INFO') then
+ tmp := extractfilepath(tmp)+'INFO';
+ end;
+ {$ENDIF}
+
+ if directoryexists(tmp) then
+ begin
+ tmp := IncludeTrailingBackslash(tmp);
+
+ if fileexists(tmp+'$I'+id) then
+ begin
+ result := _VistaOriginalSize(tmp+'$I'+id);
+ exit;
+ end
+ else if fileexists(tmp+'INFO2') then tmp := tmp+'INFO2'
+ else if fileexists(tmp+'INFO') then tmp := tmp+'INFO';
+ end;
+
+ if not fileexists(tmp) then exit;
+ if not RecyclerIsValid(tmp) then exit;
+
+ fs := TFileStream.Create(tmp, fmOpenRead);
+ try
+ fs.seek(length_position, soFromBeginning);
+ record_length := _readInt32(fs);
+
+ i := -1;
+ repeat
+ inc(i);
+ if unique_index_position+i*record_length > fs.size then break;
+ fs.seek(unique_index_position+i*record_length, soFromBeginning);
+ if inttostr(_readInt32(fs)) = id then
+ begin
+ fs.seek(original_size_position+i*record_length, soFromBeginning);
+ result := _readInt32(fs);
+ break;
+ end;
+ until false;
+ finally
+ fs.free;
+ end;
+end;
+
+////////////////////////////////////////////////////////////////////////////////
+
+class function TRecycleBinManager.RecyclerIsValid(drive: char): boolean;
+begin
+ // Bei Vista und W2k3 (VM) erhalte ich bei LW A: die Meldung
+ // "c0000013 Kein Datenträger". Exception Abfangen geht nicht.
+ // Daher erstmal überprüfen, ob Laufwerk existiert.
+ result := false;
+ if not RecyclerIsPossible(drive) then exit;
+
+ result := RecyclerIsValid(drive, '');
+end;
+
+class function TRecycleBinManager.RecyclerIsValid(drive: char; UserSID: string): boolean;
+var
+ infofile: string;
+begin
+ // Anmerkung siehe oben.
+ result := false;
+ if not RecyclerIsPossible(drive) then exit;
+
+ infofile := RecyclerGetPath(drive, UserSID, false);
+ result := RecyclerIsValid(infofile);
+end;
+
+class function TRecycleBinManager.RecyclerIsValid(InfofileOrRecycleFolder: string): boolean;
+var
+ tmp: string;
+ x: TStringList;
+ i: integer;
+ eine_fehlerhaft: boolean;
+begin
+ result := false;
+
+ tmp := InfofileOrRecycleFolder;
+
+ if _isFileVistaNamed(tmp) then
+ begin
+ result := _VistaIsValid(tmp);
+ exit;
+ end;
+
+ {$IFDEF allow_all_filenames}
+ if not RecyclerIsValid(tmp) and fileexists(tmp) then
+ begin
+ if fileexists(extractfilepath(tmp)+'INFO2') then
+ tmp := extractfilepath(tmp)+'INFO2'
+ else if fileexists(extractfilepath(tmp)+'INFO') then
+ tmp := extractfilepath(tmp)+'INFO';
+ end;
+ {$ENDIF}
+
+ if directoryexists(tmp) then
+ begin
+ tmp := IncludeTrailingBackslash(tmp);
+
+ if fileexists(tmp+'INFO2') then
+ begin
+ result := _checkInfo1or2File(tmp+'INFO2');
+ end;
+
+ if not result and fileexists(tmp+'INFO') then
+ begin
+ result := _checkInfo1or2File(tmp+'INFO');
+ end;
+
+ if not result then
+ begin
+ // Complete vista-directory declared?
+ eine_fehlerhaft := false;
+ x := TStringList.Create;
+ try
+ _VistaListIndexes(tmp, x);
+ for i := 0 to x.Count - 1 do
+ begin
+ if not _VistaIsValid(tmp+'$I'+x.Strings[i]) then
+ begin
+ eine_fehlerhaft := true;
+ end;
+ end;
+ finally
+ x.Free;
+ end;
+ result := not eine_fehlerhaft;
+ end;
+ end;
+
+ if not fileexists(tmp) then exit;
+
+ result := _checkInfo1or2File(tmp);
+end;
+
+////////////////////////////////////////////////////////////////////////////////
+
+class function TRecycleBinManager.RecyclerCurrentFilename(InfofileOrRecycleFolder: string): string;
+begin
+ result := RecyclerCurrentFilename(InfofileOrRecycleFolder, '');
+end;
+
+class function TRecycleBinManager.RecyclerCurrentFilename(drive: char; fileid: string): string;
+begin
+ result := RecyclerCurrentFilename(drive, '', fileid);
+end;
+
+class function TRecycleBinManager.RecyclerCurrentFilename(drive: char; UserSID: string; fileid: string): string;
+var
+ infofile: string;
+begin
+ infofile := RecyclerGetPath(drive, UserSID, true, fileid);
+ result := RecyclerCurrentFilename(infofile, fileid);
+end;
+
+class function TRecycleBinManager.RecyclerCurrentFilename(InfofileOrRecycleFolder: string; id: string): string;
+var
+ a, c: string;
+ tmp: string;
+begin
+ result := '';
+
+ tmp := InfofileOrRecycleFolder;
+
+ if _isFileVistaNamed(tmp) then
+ begin
+ result := _VistaCurrentFilename(tmp);
+ exit;
+ end;
+
+ {$IFDEF allow_all_filenames}
+ if not RecyclerIsValid(tmp) and fileexists(tmp) then
+ begin
+ if fileexists(extractfilepath(tmp)+'INFO2') then
+ tmp := extractfilepath(tmp)+'INFO2'
+ else if fileexists(extractfilepath(tmp)+'INFO') then
+ tmp := extractfilepath(tmp)+'INFO';
+ end;
+ {$ENDIF}
+
+ if directoryexists(tmp) then
+ begin
+ tmp := IncludeTrailingBackslash(tmp);
+
+ if fileexists(tmp+'$I'+id) then
+ begin
+ result := _VistaCurrentFilename(tmp+'$I'+id);
+ exit;
+ end
+ else if fileexists(tmp+'INFO2') then tmp := tmp+'INFO2'
+ else if fileexists(tmp+'INFO') then tmp := tmp+'INFO';
+ end;
+
+ a := RecyclerGetSourceDrive(tmp, id);
+ c := extractfileext(RecyclerGetSourceUnicode(tmp, id));
+ if (a <> '') then
+ begin
+ result := 'D' + a + id + c;
+ end;
+end;
+
+////////////////////////////////////////////////////////////////////////////////
+
+class function TRecycleBinManager.RecyclerGetPath(drive: char; UserSID: string; IncludeInfofile: boolean; fileid: string): string;
+var
+ sl: TStringList;
+begin
+ sl := TStringList.Create;
+ try
+ RecyclerGetInfofiles(drive, UserSID, IncludeInfofile, fileid, sl);
+ if sl.Count > 0 then
+ result := ExtractFilePath(sl.Strings[0])
+ else
+ result := '';
+ finally
+ sl.free;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerGetPath(drive: char; UserSID: string; IncludeInfofile: boolean): string;
+var
+ sl: TStringList;
+begin
+ sl := TStringList.Create;
+ try
+ RecyclerGetInfofiles(drive, UserSID, IncludeInfofile, sl);
+ if sl.Count > 0 then
+ result := ExtractFilePath(sl.Strings[0])
+ else
+ result := '';
+ finally
+ sl.free;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerGetPath(drive: char; IncludeInfofile: boolean): string;
+var
+ sl: TStringList;
+begin
+ sl := TStringList.Create;
+ try
+ RecyclerGetInfofiles(drive, IncludeInfofile, sl);
+ if sl.Count > 0 then
+ result := ExtractFilePath(sl.Strings[0])
+ else
+ result := '';
+ finally
+ sl.free;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerGetPath(drive: char; UserSID: string): string;
+var
+ sl: TStringList;
+begin
+ sl := TStringList.Create;
+ try
+ RecyclerGetInfofiles(drive, UserSID, sl);
+ if sl.Count > 0 then
+ result := ExtractFilePath(sl.Strings[0])
+ else
+ result := '';
+ finally
+ sl.free;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerGetPath(drive: char): string;
+var
+ sl: TStringList;
+begin
+ sl := TStringList.Create;
+ try
+ RecyclerGetInfofiles(drive, sl);
+ if sl.Count > 0 then
+ result := ExtractFilePath(sl.Strings[0])
+ else
+ result := '';
+ finally
+ sl.free;
+ end;
+end;
+
+////////////////////////////////////////////////////////////////////////////////
+
+class procedure TRecycleBinManager.RecyclerGetInfofiles(drive: char; UserSID: string; IncludeInfofile: boolean; fileid: string; result: TStringList);
+var
+ dir: string;
+begin
+ // Find recyclers from Windows Vista or higher
+
+ if _isFAT(drive) then
+ begin
+ dir := drive + DriveDelim + PathDelim + '$recycle.bin' + PathDelim;
+ if IncludeInfofile and (fileid <> '') then
+ begin
+ if fileExists(dir + '$I'+fileid) then
+ begin
+ result.Add(dir + '$I'+fileid);
+ end;
+ end
+ else
+ begin
+ if directoryExists(dir) then
+ begin
+ result.Add(dir);
+ end;
+ end;
+ end
+ else
+ begin
+ if UserSID <> '' then
+ begin
+ dir := drive + DriveDelim + PathDelim + '$recycle.bin'+PathDelim+UserSID+PathDelim;
+ if IncludeInfofile and (fileid <> '') then
+ begin
+ if fileExists(dir + '$I'+fileid) then
+ begin
+ result.Add(dir + '$I'+fileid);
+ end;
+ end
+ else
+ begin
+ if directoryExists(dir) then
+ begin
+ result.Add(dir);
+ end;
+ end;
+ end
+ else
+ begin
+ dir := drive + DriveDelim + PathDelim + '$recycle.bin'+PathDelim+_getMySID()+PathDelim;
+ if IncludeInfofile and (fileid <> '') then
+ begin
+ if fileExists(dir + '$I'+fileid) then
+ begin
+ result.Add(dir + '$I'+fileid);
+ end;
+ end
+ else
+ begin
+ if directoryExists(dir) then
+ begin
+ result.Add(dir);
+ end;
+ end;
+ end;
+ end;
+
+ // Find recyclers from Windows before Vista
+
+ if _isFAT(drive) then
+ begin
+ dir := drive + DriveDelim + PathDelim + 'Recycled' + PathDelim;
+ if IncludeInfofile then
+ begin
+ // Both "recycle bins" are possible if you have multiboot (but do overwrite themselfes if you empty them)
+ if fileExists(dir + 'INFO2') then
+ result.Add(dir + 'INFO2'); // Windows 95 with Internet Explorer 4 Extension or higher Windows versions
+ if fileExists(dir + 'INFO') then
+ result.Add(dir + 'INFO'); // Windows 95 native
+ end
+ else
+ begin
+ if directoryExists(dir) then
+ result.Add(dir);
+ end;
+ end
+ else
+ begin
+ if UserSID <> '' then
+ begin
+ dir := drive + DriveDelim + PathDelim + 'Recycler'+PathDelim+UserSID+PathDelim;
+ if IncludeInfofile then
+ begin
+ if fileExists(dir + 'INFO2') then
+ result.Add(dir + 'INFO2');
+ end
+ else
+ begin
+ if directoryExists(dir) then
+ result.Add(dir);
+ end;
+ end
+ else
+ begin
+ dir := drive + DriveDelim + PathDelim + 'Recycler'+PathDelim+_getMySID()+PathDelim;
+ if IncludeInfofile then
+ begin
+ if fileExists(dir + 'INFO2') then
+ result.Add(dir + 'INFO2');
+ end
+ else
+ begin
+ if directoryExists(dir) then
+ result.Add(dir);
+ end;
+ end;
+ end;
+end;
+
+class procedure TRecycleBinManager.RecyclerGetInfofiles(drive: char; UserSID: string; IncludeInfofile: boolean; result: TStringList);
+begin
+ RecyclerGetInfofiles(drive, UserSID, IncludeInfofile, '', result);
+end;
+
+class procedure TRecycleBinManager.RecyclerGetInfofiles(drive: char; IncludeInfofile: boolean; result: TStringList);
+begin
+ RecyclerGetInfofiles(drive, '', IncludeInfofile, '', result);
+end;
+
+class procedure TRecycleBinManager.RecyclerGetInfofiles(drive: char; UserSID: string; result: TStringList);
+begin
+ RecyclerGetInfofiles(drive, UserSID, false, '', result);
+end;
+
+class procedure TRecycleBinManager.RecyclerGetInfofiles(drive: char; result: TStringList);
+begin
+ RecyclerGetInfofiles(drive, '', false, '', result);
+end;
+
+////////////////////////////////////////////////////////////////////////////////
+
+class function TRecycleBinManager.RecyclerCurrentFilenameAndPath(drive: char; UserSID: string; fileid: string): string;
+begin
+ result := RecyclerGetPath(drive, UserSID, false, fileid) +
+ RecyclerCurrentFilename(drive, UserSID, fileid);
+end;
+
+class function TRecycleBinManager.RecyclerCurrentFilenameAndPath(drive: char; fileid: string): string;
+begin
+ result := RecyclerCurrentFilenameAndPath(drive, '', fileid);
+end;
+
+class function TRecycleBinManager.RecyclerCurrentFilenameAndPath(InfofileOrRecycleFolder: string; id: string): string;
+begin
+ if RecyclerIsValid(InfofileOrRecycleFolder) then
+ begin
+ result := extractfilepath(InfofileOrRecycleFolder) +
+ RecyclerCurrentFilename(InfofileOrRecycleFolder, id);
+ end
+ else
+ result := '';
+end;
+
+////////////////////////////////////////////////////////////////////////////////
+
+class function TRecycleBinManager.RecyclerRemoveItem(drive: char; UserSID: string; fileid: string): boolean;
+var
+ tmp: string;
+begin
+ tmp := RecyclerCurrentFilenameAndPath(drive, UserSID, fileid);
+ if fileexists(tmp) then
+ begin
+ deletefile(tmp);
+ result := fileexists(tmp);
+ end
+ else
+ begin
+ directoryexists(tmp);
+ result := directoryexists(tmp);
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerRemoveItem(drive: char; fileid: string): boolean;
+begin
+ result := RecyclerRemoveItem(drive, '', fileid);
+end;
+
+class function TRecycleBinManager.RecyclerRemoveItem(InfofileOrRecycleFolder: string; id: string): boolean;
+var
+ tmp: string;
+begin
+ tmp := RecyclerCurrentFilenameAndPath(InfofileOrRecycleFolder, id);
+ if fileexists(tmp) then
+ begin
+ deletefile(tmp);
+ result := fileexists(tmp);
+ end
+ else
+ begin
+ directoryexists(tmp);
+ result := directoryexists(tmp);
+ end;
+end;
+
+class procedure TRecycleBinManager.RecyclerGetAllRecyclerDrives(result: TStringList);
+var
+ Drive: char;
+begin
+ for Drive := 'A' to 'Z' do
+ begin
+ if RecyclerIsPossible(Drive) and RecyclerIsValid(Drive) then
+ begin
+ result.Add(Drive);
+ end;
+ end;
+end;
+
+////////////////////////////////////////////////////////////////////////////////
+
+// http://www.dsdt.info/tipps/?id=176
+class function TRecycleBinManager.RecyclerEmptyRecycleBin(flags: cardinal): boolean;
+type
+ TSHEmptyRecycleBin = function (Wnd: HWND;
+ pszRootPath: PChar;
+ dwFlags: DWORD):
+ HRESULT; stdcall;
+var
+ PSHEmptyRecycleBin: TSHEmptyRecycleBin;
+ LibHandle: THandle;
+const
+ C_SHEmptyRecycleBinA = 'SHEmptyRecycleBinA';
+begin
+ result := true;
+ LibHandle := LoadLibrary(shell32) ;
+ try
+ if LibHandle <> 0 then
+ begin
+ @PSHEmptyRecycleBin:= GetProcAddress(LibHandle, C_SHEmptyRecycleBinA);
+ if @PSHEmptyRecycleBin <> nil then
+ begin
+ PSHEmptyRecycleBin(hInstance, nil, flags);
+ end
+ else
+ result := false;
+ end
+ else
+ result := false;
+ finally
+ @PSHEmptyRecycleBin := nil;
+ FreeLibrary(LibHandle);
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerEmptyRecycleBin(sound, progress, confirmation: boolean): boolean;
+const
+ SHERB_NOCONFIRMATION = $00000001;
+ SHERB_NOPROGRESSUI = $00000002;
+ SHERB_NOSOUND = $00000004;
+var
+ flags: cardinal;
+begin
+ flags := 0;
+
+ if not progress then
+ flags := flags or SHERB_NOPROGRESSUI;
+ if not confirmation then
+ flags := flags or SHERB_NOCONFIRMATION;
+ if not sound then
+ flags := flags or SHERB_NOSOUND;
+
+ result := RecyclerEmptyRecycleBin(flags);
+end;
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Template
+// http://www.dsdt.info/tipps/?id=116
+class function TRecycleBinManager.RecyclerAddFileOrFolder(FileOrFolder: string; confirmation: boolean): boolean;
+var
+ Operation: TSHFileOpStruct;
+begin
+ with Operation do
+ begin
+ Wnd := hInstance; // OK?
+ wFunc := FO_DELETE;
+ pFrom := PChar(FileOrFolder + #0);
+ pTo := nil;
+ fFlags := FOF_ALLOWUNDO;
+ if not confirmation then fFlags := fFlags or FOF_NOCONFIRMATION;
+ end;
+ Result := SHFileOperation(Operation) = 0;
+end;
+
+class function TRecycleBinManager.RecyclerAddFileOrFolder(FileOrFolder: string): boolean;
+begin
+ result := RecyclerAddFileOrFolder(FileOrFolder, false);
+end;
+
+class function TRecycleBinManager.RecyclerConfirmationDialogEnabled: boolean;
+var
+ gp: GPOLICYBOOL;
+begin
+ gp := RecyclerGroupPolicyConfirmFileDelete;
+ if gp <> gpUndefined then
+ begin
+ result := gp = gpEnabled;
+ end
+ else
+ begin
+ result := RecyclerShellStateConfirmationDialogEnabled;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerShellStateConfirmationDialogEnabled: boolean;
+type
+ TSHGetSettings = procedure (var lpss: SHELLSTATE; dwMask: DWORD) stdcall;
+const
+ C_SHGetSettings = 'SHGetSettings';
+var
+ lpss: SHELLSTATE;
+ bNoConfirmRecycle: boolean;
+
+ PSHGetSettings: TSHGetSettings;
+ RBHandle: THandle;
+
+ reg: TRegistry;
+ rbuf: array[0..255] of byte;
+begin
+ PSHGetSettings := nil;
+ result := false; // Avoid warning message
+
+ RBHandle := LoadLibrary(shell32);
+ if(RBHandle <> 0) then
+ begin
+ PSHGetSettings := GetProcAddress(RBHandle, C_SHGetSettings);
+ if (@PSHGetSettings = nil) then
+ begin
+ FreeLibrary(RBHandle);
+ RBHandle := 0;
+ end;
+ end;
+
+ if (RBHandle <> 0) and (Assigned(PSHGetSettings)) then
+ begin
+ ZeroMemory(@lpss, SizeOf(lpss));
+ PSHGetSettings(lpss, SSF_NOCONFIRMRECYCLE);
+ // bNoConfirmRecycle := (lpss.Flags1 and 4) = 4; // fNoConfirmRecycle
+ bNoConfirmRecycle := GetByteBit(lpss.Flags1, 2);
+
+ result := not bNoConfirmRecycle;
+ end
+ else
+ begin
+ reg := TRegistry.Create;
+ try
+ // API function call failed. Probably because Windows is too old.
+ // Try to read out from registry.
+ // The 3rd bit of the 5th byte of "ShellState" is the value
+ // of "fNoConfirmRecycle".
+
+ reg.RootKey := HKEY_CURRENT_USER;
+ if (reg.OpenKeyReadOnly('Software\Microsoft\Windows\CurrentVersion\Explorer')) then
+ begin
+ ZeroMemory(@rbuf, SizeOf(rbuf));
+ reg.ReadBinaryData('ShellState', rbuf, SizeOf(rbuf));
+
+ // Lese 3tes Bit vom 5ten Byte
+ // bNoConfirmRecycle := ((rbuf[4] and 4) = 4);
+ bNoConfirmRecycle := GetByteBit(rbuf[4], 2);
+ result := not bNoConfirmRecycle;
+
+ reg.CloseKey;
+ end
+ else
+ begin
+ raise EAPICallError.CreateFmt(LNG_API_CALL_ERROR, [Format(LNG_NOT_CALLABLE, [C_SHGetSettings])]);
+ end;
+ finally
+ reg.Free;
+ end;
+ end;
+
+ if (RBHandle <> 0) then FreeLibrary(RBHandle);
+end;
+
+class procedure TRecycleBinManager.RecyclerConfirmationDialogSetEnabled(NewSetting: boolean);
+type
+ TSHGetSetSettings = procedure (var lpss: SHELLSTATE; dwMask: DWORD; bSet: BOOL) stdcall;
+const
+ C_SHGetSetSettings = 'SHGetSetSettings';
+var
+ lpss: SHELLSTATE;
+
+ PSHGetSetSettings: TSHGetSetSettings;
+ RBHandle: THandle;
+
+ reg: TRegistry;
+ rbuf: array[0..255] of byte;
+
+ dwResult: DWORD;
+begin
+ PSHGetSetSettings := nil;
+
+ RBHandle := LoadLibrary(shell32);
+ if(RBHandle <> 0) then
+ begin
+ PSHGetSetSettings := GetProcAddress(RBHandle, C_SHGetSetSettings);
+ if (@PSHGetSetSettings = nil) then
+ begin
+ FreeLibrary(RBHandle);
+ RBHandle := 0;
+ end;
+ end;
+
+ if (RBHandle <> 0) and (Assigned(PSHGetSetSettings)) then
+ begin
+ ZeroMemory(@lpss, SizeOf(lpss));
+ PSHGetSetSettings(lpss, SSF_NOCONFIRMRECYCLE, false); // Get
+ lpss.Flags1 := SetByteBit(lpss.Flags1, 2, NewSetting);
+ PSHGetSetSettings(lpss, SSF_NOCONFIRMRECYCLE, true); // Set
+
+ SendMessageTimeout (
+ HWND_BROADCAST, WM_SETTINGCHANGE,
+ 0, lParam (pChar ('ShellState')),
+ SMTO_ABORTIFHUNG, 5000, dwResult
+ );
+ end
+ else
+ begin
+ reg := TRegistry.Create;
+ try
+ // API function call failed. Probably because Windows is too old.
+ // Try to read out from registry.
+ // The 3rd bit of the 5th byte of "ShellState" is the value
+ // of "fNoConfirmRecycle".
+
+ reg.RootKey := HKEY_CURRENT_USER;
+ if (reg.OpenKey('Software\Microsoft\Windows\CurrentVersion\Explorer', false)) then
+ begin
+ ZeroMemory(@rbuf, SizeOf(rbuf));
+ reg.ReadBinaryData('ShellState', rbuf, SizeOf(rbuf)); // Get
+ rbuf[4] := SetByteBit(rbuf[4], 2, NewSetting);
+ reg.WriteBinaryData('ShellState', rbuf, SizeOf(rbuf)); // Set
+
+ SendMessageTimeout (
+ HWND_BROADCAST, WM_SETTINGCHANGE,
+ 0, lParam (pChar ('ShellState')),
+ SMTO_ABORTIFHUNG, 5000, dwResult
+ );
+
+ reg.CloseKey;
+ end
+ else
+ begin
+ raise EAPICallError.CreateFmt(LNG_API_CALL_ERROR, [Format(LNG_NOT_CALLABLE, [C_SHGetSetSettings])]);
+ end;
+ finally
+ reg.Free;
+ end;
+ end;
+
+ if (RBHandle <> 0) then FreeLibrary(RBHandle);
+end;
+
+
+class function TRecycleBinManager.RecyclerGetName: string;
+var
+ reg: TRegistry;
+begin
+ // Windows 95b:
+ // Change of CLSID\{645FF040-5081-101B-9F08-00AA002F954E} will change the desktop name of the recycle bin.
+
+ // Windows 2000: If LocalizedString is available, the 3rd argument will be parsed
+ // (if the third argument will removed, it will be read out from the DLL resource string automatically)
+
+ reg := TRegistry.Create;
+ try
+ reg.RootKey := HKEY_CLASSES_ROOT;
+ if reg.OpenKeyReadOnly('CLSID\'+RECYCLER_CLSID) then
+ begin
+ if reg.ValueExists('LocalizedString') then
+ begin
+ result := reg.ReadString('LocalizedString');
+ result := _DecodeReferenceString(result);
+ end
+ else
+ begin
+ result := reg.ReadString('');
+ end;
+
+ reg.CloseKey;
+ end;
+ finally
+ reg.Free;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerGetInfoTip: string;
+var
+ reg: TRegistry;
+begin
+ // Not available in some older versions of Windows
+
+ reg := TRegistry.Create;
+ try
+ reg.RootKey := HKEY_CLASSES_ROOT;
+ if reg.OpenKeyReadOnly('CLSID\'+RECYCLER_CLSID) then
+ begin
+ result := reg.ReadString('InfoTip');
+ result := _DecodeReferenceString(result);
+
+ reg.CloseKey;
+ end;
+ finally
+ reg.Free;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerGetIntroText: string;
+var
+ reg: TRegistry;
+begin
+ // Not available in some older versions of Windows
+
+ reg := TRegistry.Create;
+ try
+ reg.RootKey := HKEY_CLASSES_ROOT;
+ if reg.OpenKeyReadOnly('CLSID\'+RECYCLER_CLSID) then
+ begin
+ result := reg.ReadString('IntroText');
+ result := _DecodeReferenceString(result);
+
+ reg.CloseKey;
+ end;
+ finally
+ reg.Free;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerEmptyEventGetName: string;
+var
+ reg: TRegistry;
+begin
+ reg := TRegistry.Create;
+ try
+ reg.RootKey := HKEY_CURRENT_USER;
+ if reg.OpenKeyReadOnly('AppEvents\EventLabels\EmptyRecycleBin') then
+ begin
+ result := reg.ReadString('');
+ reg.CloseKey;
+ end;
+ finally
+ reg.Free;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerEmptyEventGetCurrentSound: string;
+begin
+ result := RecyclerEmptyEventGetSound('.Current');
+end;
+
+class function TRecycleBinManager.RecyclerEmptyEventGetDefaultSound: string;
+begin
+ result := RecyclerEmptyEventGetSound('.Default');
+end;
+
+class procedure TRecycleBinManager.RecyclerEmptyEventGetSoundCategories(AStringList: TStringList);
+var
+ reg: TRegistry;
+begin
+ reg := TRegistry.Create;
+ try
+ reg.RootKey := HKEY_CURRENT_USER;
+ if reg.OpenKeyReadOnly('AppEvents\Schemes\Apps\Explorer\EmptyRecycleBin') then
+ begin
+ reg.GetKeyNames(AStringList);
+ reg.CloseKey;
+ end;
+ finally
+ reg.Free;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerEmptyEventGetSound(ACategory: string): string;
+var
+ reg: TRegistry;
+resourcestring
+ LNG_SND_EVENT_CAT_ERROR = 'The category "%s" is not available for the notification event "%s".';
+begin
+ // Outputs an filename or empty string for no sound defined.
+
+ reg := TRegistry.Create;
+ try
+ reg.RootKey := HKEY_CURRENT_USER;
+ if reg.OpenKeyReadOnly('AppEvents\Schemes\Apps\Explorer\EmptyRecycleBin') then
+ begin
+ if reg.OpenKeyReadOnly(ACategory) then
+ begin
+ result := reg.ReadString('');
+ reg.CloseKey;
+ end
+ else
+ raise EEventCategoryNotDefined.CreateFmt(LNG_SND_EVENT_CAT_ERROR, [ACategory, 'EmptyRecycleBin']);
+ reg.CloseKey;
+ end;
+ finally
+ reg.Free;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerGlobalGetPercentUsage: integer;
+var
+ reg: TRegistry;
+ dump: string;
+const
+ RES_DEFAULT = 10;
+begin
+ result := -1;
+
+ reg := TRegistry.Create;
+ try
+ reg.RootKey := HKEY_LOCAL_MACHINE;
+
+ if reg.OpenKeyReadOnly('SOFTWARE\Microsoft\Windows\CurrentVersion\explorer\BitBucket') then
+ begin
+ if reg.ValueExists('Percent') then
+ begin
+ // Windows 2000 - Informationen liegen aufgeschlüsselt in der Registry
+
+ result := reg.ReadInteger('Percent');
+ end
+ else if reg.ValueExists('PurgeInfo') then
+ begin
+ // Windows 95 - Verschlüsselte Informationen liegen in PurgeInfo
+
+ dump := _registryReadDump(reg, 'PurgeInfo');
+ result := Ord(dump[63]);
+ end
+ else
+ begin
+ // Windows 95 - Standardwerte sind gegeben, deswegen existiert kein PurgeInfo
+
+ result := RES_DEFAULT; // Standardeinstellung bei Windows
+ end;
+
+ reg.CloseKey;
+ end;
+ finally
+ reg.Free;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerSpecificGetPercentUsage(Drive: Char): integer;
+var
+ reg: TRegistry;
+ dump: string;
+const
+ RES_DEFAULT = 10;
+begin
+ result := -1;
+
+ reg := TRegistry.Create;
+ try
+ reg.RootKey := HKEY_LOCAL_MACHINE;
+
+ if reg.OpenKeyReadOnly('SOFTWARE\Microsoft\Windows\CurrentVersion\explorer\BitBucket') then
+ begin
+ if reg.OpenKeyReadOnly(Drive) then
+ begin
+ if reg.ValueExists('Percent') then
+ begin
+ // Windows 2000 - Informationen liegen aufgeschlüsselt in der Registry
+
+ result := reg.ReadInteger('Percent');
+ end
+ else
+ begin
+ result := RES_DEFAULT;
+ end;
+ reg.CloseKey;
+ end
+ else
+ begin
+ if reg.ValueExists('PurgeInfo') then
+ begin
+ // Windows 95 - Verschlüsselte Informationen liegen in PurgeInfo
+
+ dump := _registryReadDump(reg, 'PurgeInfo');
+
+ // NOT tested, only theoretical! My idea about the possible structure is:
+ // 0x08 = Drive A
+ // 0x0a = Drive B
+ // 0x0c = Drive C (validated)
+ // 0x0e = Drive D
+ // ...
+
+ result := Ord(dump[9+_DriveNum(Drive)*2]);
+ end
+ else
+ begin
+ // Windows 95 - Standardwerte sind gegeben, deswegen existiert kein PurgeInfo
+
+ result := RES_DEFAULT; // Standardeinstellung bei Windows
+ end;
+ end;
+
+ reg.CloseKey;
+ end;
+ finally
+ reg.Free;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerGetPercentUsageAutoDeterminate(Drive: Char): integer;
+var
+ gpSetting: integer;
+begin
+ gpSetting := RecyclerGroupPolicyRecycleBinSize;
+ if gpSetting <> -1 then
+ result := gpSetting
+ else if RecyclerHasGlobalSettings then
+ result := RecyclerGlobalGetPercentUsage
+ else
+ result := RecyclerSpecificGetPercentUsage(Drive);
+end;
+
+class function TRecycleBinManager.RecyclerGlobalIsNukeOnDelete: boolean;
+var
+ reg: TRegistry;
+ dump: string;
+const
+ RES_DEFAULT = false;
+begin
+ result := false;
+
+ reg := TRegistry.Create;
+ try
+ reg.RootKey := HKEY_LOCAL_MACHINE;
+
+ if reg.OpenKeyReadOnly('SOFTWARE\Microsoft\Windows\CurrentVersion\explorer\BitBucket') then
+ begin
+ if reg.ValueExists('NukeOnDelete') then
+ begin
+ // Windows 2000 - Informationen liegen aufgeschlüsselt in der Registry
+
+ result := reg.ReadBool('NukeOnDelete');
+ end
+ else if reg.ValueExists('PurgeInfo') then
+ begin
+ // Windows 95 - Verschlüsselte Informationen liegen in PurgeInfo
+
+ // See comment at RecyclerSpecificIsNukeOnDelete()
+
+ dump := _registryReadDump(reg, 'PurgeInfo');
+ result := GetAnsiCharBit(dump[68], 3);
+ end
+ else
+ begin
+ // Windows 95 - Standardwerte sind gegeben, deswegen existiert kein PurgeInfo
+
+ result := RES_DEFAULT; // Standardeinstellung bei Windows
+ end;
+
+ reg.CloseKey;
+ end;
+ finally
+ reg.Free;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerSpecificIsNukeOnDelete(Drive: Char): boolean;
+var
+ reg: TRegistry;
+ dump: string;
+ d: Byte;
+const
+ RES_DEFAULT = false;
+begin
+ result := false;
+
+ reg := TRegistry.Create;
+ try
+ reg.RootKey := HKEY_LOCAL_MACHINE;
+
+ if reg.OpenKeyReadOnly('SOFTWARE\Microsoft\Windows\CurrentVersion\explorer\BitBucket') then
+ begin
+ if reg.OpenKeyReadOnly(Drive) then
+ begin
+ if reg.ValueExists('NukeOnDelete') then
+ begin
+ // Windows 2000 - Informationen liegen aufgeschlüsselt in der Registry
+
+ result := reg.ReadBool('NukeOnDelete');
+ end;
+ reg.CloseKey;
+ end
+ else
+ begin
+ if reg.ValueExists('PurgeInfo') then
+ begin
+ // Windows 95 - Verschlüsselte Informationen liegen in PurgeInfo
+
+ dump := _registryReadDump(reg, 'PurgeInfo');
+
+ // NOT tested, only theoretical! My idea about the possible structure is:
+ //
+ // Byte 0x40 0x41 0x42 0x43
+ // Bit 76543210 76543210 76543210 76543210
+ // -------- -------- -------- --------
+ // Meaning hgfedcba ponmlkji xwvutsrq ????G?zy
+ //
+ // a..z = Drives
+ // G = global settings
+ //
+ // Already validated:
+ // 0x64 = 04 (00000100)
+ // 0x67 = 08 (00001000)
+
+ d := _DriveNum(Drive);
+ result := GetAnsiCharBit(dump[65+(d div 7)], d mod 7);
+ end
+ else
+ begin
+ // Windows 95 - Standardwerte sind gegeben, deswegen existiert kein PurgeInfo
+
+ result := RES_DEFAULT; // Standardeinstellung bei Windows
+ end;
+ end;
+
+ reg.CloseKey;
+ end;
+ finally
+ reg.Free;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerIsNukeOnDeleteAutoDeterminate(Drive: Char): boolean;
+begin
+ if RecyclerGroupPolicyNoRecycleFiles = gpEnabled then
+ result := true
+ else if RecyclerHasGlobalSettings then
+ result := RecyclerGlobalIsNukeOnDelete
+ else
+ result := RecyclerSpecificIsNukeOnDelete(Drive);
+end;
+
+class function TRecycleBinManager.RecyclerHasGlobalSettings: boolean;
+var
+ reg: TRegistry;
+ dump: string;
+begin
+ result := false;
+
+ reg := TRegistry.Create;
+ try
+ reg.RootKey := HKEY_LOCAL_MACHINE;
+
+ if reg.OpenKeyReadOnly('SOFTWARE\Microsoft\Windows\CurrentVersion\explorer\BitBucket') then
+ begin
+ if reg.ValueExists('UseGlobalSettings') then
+ begin
+ // Windows 2000 - Informationen liegen aufgeschlüsselt in der Registry
+
+ result := reg.ReadBool('UseGlobalSettings');
+ end
+ else if reg.ValueExists('PurgeInfo') then
+ begin
+ // Windows 95 - Verschlüsselte Informationen liegen in PurgeInfo
+ // TODO: Gibt es ein offizielles Dokument oder ein API, indem PurgeInfo
+ // offiziell entschlüsselbar ist?
+
+ dump := _registryReadDump(reg, 'PurgeInfo');
+ if dump[5] = #$01 then
+ result := true
+ else if dump[5] = #$00 then
+ result := false
+ else
+ raise EUnknownState.Create(Format(LNG_UNEXPECTED_STATE, ['PurgeInfo']));
+ end
+ else
+ begin
+ // Windows 95 - Standardwerte sind gegeben, deswegen existiert kein PurgeInfo
+
+ result := true; // Standardeinstellung bei Windows
+ end;
+
+ reg.CloseKey;
+ end;
+ finally
+ reg.Free;
+ end;
+end;
+
+
+class function TRecycleBinManager.RecyclerGetNumItems: int64;
+var
+ Drive: Char;
+begin
+ result := 0;
+ for Drive := 'A' to 'Z' do
+ begin
+ if RecyclerIsPossible(Drive) then
+ begin
+ result := result + RecyclerGetNumItems(Drive);
+ end;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerGetNumItems(Drive: Char): int64;
+begin
+ result := RecyclerGetAPIInfo(Drive).i64NumItems;
+end;
+
+class function TRecycleBinManager.RecyclerGetSize: int64;
+var
+ Drive: Char;
+begin
+ result := 0;
+ for Drive := 'A' to 'Z' do
+ begin
+ if RecyclerIsPossible(Drive) then
+ begin
+ result := result + RecyclerGetSize(Drive);
+ end;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerGetSize(Drive: Char): int64;
+begin
+ result := RecyclerGetAPIInfo(Drive).i64Size;
+end;
+
+class function TRecycleBinManager.RecyclerGetAPIInfo(Drive: Char): TSHQueryRBInfo;
+begin
+ result := RecyclerGetAPIInfo(Drive + ':\');
+end;
+
+const
+ C_SHQueryRecycleBin = 'SHQueryRecycleBinA';
+
+type
+ TSHQueryRecycleBin = function(pszRootPath: LPCTSTR;
+ var pSHQueryRBInfo: TSHQueryRBInfo): HRESULT; stdcall;
+
+class function TRecycleBinManager.RecyclerGetAPIInfo(Path: String): TSHQueryRBInfo;
+var
+ PSHQueryRecycleBin: TSHQueryRecycleBin;
+ RBHandle: THandle;
+ res: HRESULT;
+begin
+ PSHQueryRecycleBin := nil;
+
+ // Ref: http://www.delphipraxis.net/post1291.html
+
+ RBHandle := LoadLibrary(shell32);
+ if(RBHandle <> 0) then
+ begin
+ PSHQueryRecycleBin := GetProcAddress(RBHandle, C_SHQueryRecycleBin);
+ if(@PSHQueryRecycleBin = nil) then
+ begin
+ FreeLibrary(RBHandle);
+ RBHandle := 0;
+ end;
+ end;
+
+ fillchar(result, SizeOf(TSHQueryRBInfo),0);
+ result.cbSize := SizeOf(TSHQueryRBInfo);
+
+ if (RBHandle <> 0) and (Assigned(PSHQueryRecycleBin)) then
+ begin
+ res := PSHQueryRecycleBin(PChar(Path), result);
+ // if Succeeded(res) then
+ if res = S_OK then
+ begin
+ // Alles OK, unser result hat nun die gewünschten Daten.
+ end
+ else
+ begin
+ // Since Windows Vista, SHQueryRecycleBin will fail with E_FAIL (80004005)
+ // if Path is a floppy or CD drive...
+ raise EAPICallError.CreateFmt(LNG_API_CALL_ERROR, [Format(LNG_ERROR_CODE, [C_SHQueryRecycleBin, Path, '0x'+IntToHex(res, 2*SizeOf(HRESULT))])]);
+ end;
+ end
+ else
+ raise EAPICallError.CreateFmt(LNG_API_CALL_ERROR, [Format(LNG_NOT_CALLABLE, [C_SHQueryRecycleBin])]);
+
+ if (RBHandle <> 0) then FreeLibrary(RBHandle);
+end;
+
+class function TRecycleBinManager.RecyclerGetCLSID: string;
+begin
+ result := RECYCLER_CLSID;
+end;
+
+// Windows 95 without Internet Explorer 4 has no SHQueryRecycleBinA.
+class function TRecycleBinManager.RecyclerQueryFunctionAvailable: boolean;
+var
+ RBHandle: THandle;
+ SHQueryRecycleBin: TSHQueryRecycleBin;
+begin
+ RBHandle := LoadLibrary(shell32);
+ if(RBHandle <> 0) then
+ begin
+ SHQueryRecycleBin := GetProcAddress(RBHandle, C_SHQueryRecycleBin);
+ if(@SHQueryRecycleBin = nil) then
+ begin
+ FreeLibrary(RBHandle);
+ RBHandle := 0;
+ end;
+ end;
+
+ result := RBHandle <> 0;
+end;
+
+const
+ GroupPolicyAcceptHKLMTrick = true;
+
+// TODO: In future also detect for other users
+// TODO: Also make a setter (inkl. Message to Windows Explorer?)
+class function TRecycleBinManager.RecyclerGroupPolicyNoRecycleFiles: GPOLICYBOOL;
+var
+ reg: TRegistry;
+begin
+ result := gpUndefined;
+
+ reg := TRegistry.Create;
+ try
+ // If a value is set in HKEY_LOCAL_MACHINE, it will be prefered,
+ // even if gpedit.msc shows "Not configured"!
+ if GroupPolicyAcceptHKLMTrick then
+ begin
+ reg.RootKey := HKEY_LOCAL_MACHINE;
+ if reg.OpenKeyReadOnly('Software\Microsoft\Windows\CurrentVersion\Policies\Explorer') then
+ begin
+ if reg.ValueExists('NoRecycleFiles') then
+ begin
+ if reg.ReadBool('NoRecycleFiles') then
+ result := gpEnabled
+ else
+ result := gpDisabled;
+ Exit;
+ end;
+ reg.CloseKey;
+ end;
+ end;
+
+ reg.RootKey := HKEY_CURRENT_USER;
+ if reg.OpenKeyReadOnly('Software\Microsoft\Windows\CurrentVersion\Policies\Explorer') then
+ begin
+ if reg.ValueExists('NoRecycleFiles') then
+ begin
+ if reg.ReadBool('NoRecycleFiles') then
+ result := gpEnabled
+ else
+ result := gpDisabled;
+ end;
+ reg.CloseKey;
+ end;
+ finally
+ reg.Free;
+ end;
+end;
+
+// TODO: In future also detect for other users
+// TODO: Also make a setter (inkl. Message to Windows Explorer?)
+class function TRecycleBinManager.RecyclerGroupPolicyConfirmFileDelete: GPOLICYBOOL;
+var
+ reg: TRegistry;
+begin
+ result := gpUndefined;
+ reg := TRegistry.Create;
+ try
+ // If a value is set in HKEY_LOCAL_MACHINE, it will be prefered,
+ // even if gpedit.msc shows "Not configured"!
+ if GroupPolicyAcceptHKLMTrick then
+ begin
+ reg.RootKey := HKEY_LOCAL_MACHINE;
+ if reg.OpenKeyReadOnly('Software\Microsoft\Windows\CurrentVersion\Policies\Explorer') then
+ begin
+ if reg.ValueExists('ConfirmFileDelete') then
+ begin
+ if reg.ReadBool('ConfirmFileDelete') then
+ result := gpEnabled
+ else
+ result := gpDisabled;
+ Exit;
+ end;
+ reg.CloseKey;
+ end;
+ end;
+
+ reg.RootKey := HKEY_CURRENT_USER;
+ if reg.OpenKeyReadOnly('Software\Microsoft\Windows\CurrentVersion\Policies\Explorer') then
+ begin
+ if reg.ValueExists('ConfirmFileDelete') then
+ begin
+ if reg.ReadBool('ConfirmFileDelete') then
+ result := gpEnabled
+ else
+ result := gpDisabled;
+ end;
+ reg.CloseKey;
+ end;
+ finally
+ reg.Free;
+ end;
+end;
+
+
+// TODO: In future also detect for other users
+// TODO: Also make a setter (inkl. Message to Windows Explorer?)
+class function TRecycleBinManager.RecyclerGroupPolicyRecycleBinSize: integer;
+var
+ reg: TRegistry;
+begin
+ result := -1;
+ reg := TRegistry.Create;
+ try
+ // If a value is set in HKEY_LOCAL_MACHINE, it will be prefered,
+ // even if gpedit.msc shows "Not configured"!
+ if GroupPolicyAcceptHKLMTrick then
+ begin
+ reg.RootKey := HKEY_LOCAL_MACHINE;
+ if reg.OpenKeyReadOnly('Software\Microsoft\Windows\CurrentVersion\Policies\Explorer') then
+ begin
+ if reg.ValueExists('RecycleBinSize') then
+ begin
+ result := reg.ReadInteger('RecycleBinSize');
+ Exit;
+ end;
+ reg.CloseKey;
+ end;
+ end;
+
+ reg.RootKey := HKEY_CURRENT_USER;
+ if reg.OpenKeyReadOnly('Software\Microsoft\Windows\CurrentVersion\Policies\Explorer') then
+ begin
+ if reg.ValueExists('RecycleBinSize') then
+ begin
+ result := reg.ReadInteger('RecycleBinSize');
+ end;
+ reg.CloseKey;
+ end;
+ finally
+ reg.Free;
+ end;
+end;
+
+function GPBoolToString(value: GPOLICYBOOL): String;
+begin
+ case value of
+ gpUndefined: result := 'Not configured';
+ gpEnabled: result := 'Enabled';
+ gpDisabled: result := 'Disabled';
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerIsPossible(Drive: Char): boolean;
+var
+ typ: Integer;
+begin
+ typ := GetDriveType(PChar(Drive + ':\'));
+ result := typ = DRIVE_FIXED;
+end;
+
+class function TRecycleBinManager.RecyclerLibraryVersion: string;
+begin
+ result := 'ViaThinkSoft Recycle Bin Unit [05 JUL 2010]';
+end;
+
+end.
+
Index: Main.dfm
===================================================================
--- Main.dfm (revision 35)
+++ Main.dfm (working copy)
@@ -5,8 +5,8 @@
ClientHeight = 459
ClientWidth = 636
Color = clBtnFace
- Constraints.MinHeight = 495
- Constraints.MinWidth = 652
+ Constraints.MinHeight = 493
+ Constraints.MinWidth = 644
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Index: Main.pas
===================================================================
--- Main.pas (revision 35)
+++ Main.pas (working copy)
@@ -116,7 +116,7 @@
outputMemo.Lines.Add(tmp);
outputMemo.lines.add('');
- if not RecyclerIsValid(filename) then
+ if not TRecycleBinManager.RecyclerIsValid(filename) then
begin
outputMemo.lines.add('Recycler is not valid.');
outputMemo.lines.add('');
@@ -125,7 +125,7 @@
begin
x := TStringList.Create;
try
- RecyclerListIndexes(filename, x);
+ TRecycleBinManager.RecyclerListIndexes(filename, x);
if x.Count = 0 then
begin
outputMemo.lines.add('No items available.');
@@ -133,7 +133,7 @@
end;
for i := 0 to x.Count - 1 do
begin
- fn := RecyclerCurrentFilenameAndPath(tmp, x[i]);
+ fn := TRecycleBinManager.RecyclerCurrentFilenameAndPath(tmp, x[i]);
outputMemo.lines.add(inttostr(i+1)+'. Entry');
outputMemo.lines.add('# Unique ID: ' + changefileext(x[i], ''));
outputMemo.lines.add('# Recycler filename: '+fn);
@@ -145,18 +145,18 @@
{$IFDEF DEL6UP}
outputMemo.lines.add('# Deleted: '+
- datetimetostr(RecyclerGetDateTime(tmp, x[i])));
+ datetimetostr(TRecycleBinManager.RecyclerGetDateTime(tmp, x[i])));
{$ELSE}
outputMemo.lines.add('# Deleted: You have to compile this demo with Delphi 6 or higher.');
{$ENDIF}
outputMemo.lines.add('# Original filename: '+
- RecyclerGetSource(tmp, x[i]));
+ TRecycleBinManager.RecyclerGetSource(tmp, x[i]));
outputMemo.lines.add('# Unicode filename: '+
- RecyclerGetSourceUnicode(tmp, x[i]));
+ TRecycleBinManager.RecyclerGetSourceUnicode(tmp, x[i]));
outputMemo.lines.add('# Source device: '+
- RecyclerGetSourceDrive(tmp, x[i]));
+ TRecycleBinManager.RecyclerGetSourceDrive(tmp, x[i]));
outputMemo.lines.add('# Original size on disk: '+
- inttostr(RecyclerOriginalSize(tmp, x[i]))+' Byte');
+ inttostr(TRecycleBinManager.RecyclerOriginalSize(tmp, x[i]))+' Byte');
outputMemo.lines.add('');
end;
finally
@@ -189,7 +189,7 @@
outputMemo.Clear;
x := TStringList.Create;
try
- RecyclerGetAllRecyclerDrives(x);
+ TRecycleBinManager.RecyclerGetAllRecyclerDrives(x);
somethingfound := false;
if x.Count > 0 then
begin
@@ -199,7 +199,7 @@
sl := TStringList.Create;
try
- RecyclerGetInfofiles(x[i][1], true, sl);
+ TRecycleBinManager.RecyclerGetInfofiles(x[i][1], true, sl);
if sl.Count > 0 then
begin
for j := 0 to sl.Count - 1 do
@@ -246,7 +246,7 @@
outputMemo.Clear;
- outputMemo.Lines.Add(RecyclerLibraryVersion);
+ outputMemo.Lines.Add(TRecycleBinManager.RecyclerLibraryVersion);
outputMemo.Lines.Add('');
outputMemo.Lines.Add('= Possible recyclers (fixed drives) =');
@@ -254,7 +254,7 @@
for d := 'A' to 'Z' do
begin
- outputMemo.Lines.Add('Recycler is possible at drive '+d+': ' + _BoolToYesNo(RecyclerIsPossible(d)));
+ outputMemo.Lines.Add('Recycler is possible at drive '+d+': ' + _BoolToYesNo(TRecycleBinManager.RecyclerIsPossible(d)));
end;
outputMemo.Lines.Add('');
@@ -263,24 +263,24 @@
for d := 'A' to 'Z' do
begin
- outputMemo.Lines.Add('Drive '+d+': ' + _BoolToYesNo(RecyclerIsValid(d)));
+ outputMemo.Lines.Add('Drive '+d+': ' + _BoolToYesNo(TRecycleBinManager.RecyclerIsValid(d)));
end;
outputMemo.Lines.Add('');
outputMemo.Lines.Add('= Current status =');
outputMemo.Lines.Add('');
- if RecyclerQueryFunctionAvailable then
+ if TRecycleBinManager.RecyclerQueryFunctionAvailable then
begin
- outputMemo.Lines.Add('GLOBAL Empty = ' + _BoolToYesNo(RecyclerIsEmpty));
- outputMemo.Lines.Add('GLOBAL Number of items = ' + IntToStr(RecyclerGetNumItems));
- outputMemo.Lines.Add('GLOBAL Size = ' + IntToStr(RecyclerGetSize) + ' Bytes');
+ outputMemo.Lines.Add('GLOBAL Empty = ' + _BoolToYesNo(TRecycleBinManager.RecyclerIsEmpty));
+ outputMemo.Lines.Add('GLOBAL Number of items = ' + IntToStr(TRecycleBinManager.RecyclerGetNumItems));
+ outputMemo.Lines.Add('GLOBAL Size = ' + IntToStr(TRecycleBinManager.RecyclerGetSize) + ' Bytes');
for d := 'A' to 'Z' do
begin
- if not RecyclerIsPossible(d) then Continue; // Important since Windows Vista throws Exceptions!
- outputMemo.Lines.Add('Drive '+d+' Empty = ' + _BoolToYesNo(RecyclerIsEmpty(d)));
- outputMemo.Lines.Add('Drive '+d+' Number of items = ' + IntToStr(RecyclerGetNumItems(d)));
- outputMemo.Lines.Add('Drive '+d+' Size = ' + IntToStr(RecyclerGetSize(d)) + ' Bytes');
+ if not TRecycleBinManager.RecyclerIsPossible(d) then Continue; // Important since Windows Vista throws Exceptions!
+ outputMemo.Lines.Add('Drive '+d+' Empty = ' + _BoolToYesNo(TRecycleBinManager.RecyclerIsEmpty(d)));
+ outputMemo.Lines.Add('Drive '+d+' Number of items = ' + IntToStr(TRecycleBinManager.RecyclerGetNumItems(d)));
+ outputMemo.Lines.Add('Drive '+d+' Size = ' + IntToStr(TRecycleBinManager.RecyclerGetSize(d)) + ' Bytes');
end;
end
else
@@ -293,42 +293,42 @@
outputMemo.Lines.Add('= Name and Infotips =');
outputMemo.Lines.Add('');
- outputMemo.Lines.Add('Name: '+RecyclerGetName());
- outputMemo.Lines.Add('Info Tip: '+RecyclerGetInfoTip());
- outputMemo.Lines.Add('Intro Text: '+RecyclerGetIntroText());
- outputMemo.Lines.Add('Class-ID: '+RecyclerGetCLSID());
+ outputMemo.Lines.Add('Name: '+TRecycleBinManager.RecyclerGetName());
+ outputMemo.Lines.Add('Info Tip: '+TRecycleBinManager.RecyclerGetInfoTip());
+ outputMemo.Lines.Add('Intro Text: '+TRecycleBinManager.RecyclerGetIntroText());
+ outputMemo.Lines.Add('Class-ID: '+TRecycleBinManager.RecyclerGetCLSID());
outputMemo.Lines.Add('');
outputMemo.Lines.Add('= Icons =');
outputMemo.Lines.Add('');
- outputMemo.Lines.Add('Default Icon: '+RecyclerGetDefaultIconString());
- if RecyclerQueryFunctionAvailable then
+ outputMemo.Lines.Add('Default Icon: '+TRecycleBinManager.RecyclerGetDefaultIconString());
+ if TRecycleBinManager.RecyclerQueryFunctionAvailable then
begin
- outputMemo.Lines.Add('Current Icon (Empty / Full): '+RecyclerGetCurrentIconString());
+ outputMemo.Lines.Add('Current Icon (Empty / Full): '+TRecycleBinManager.RecyclerGetCurrentIconString());
end
else
begin
outputMemo.Lines.Add('Current Icon (Empty / Full):');
outputMemo.Lines.Add(' Functionality not working with your operating system.');
end;
- outputMemo.Lines.Add('Full Icon: '+RecyclerGetFullIconString());
- outputMemo.Lines.Add('Empty Icon: '+RecyclerGetEmptyIconString());
+ outputMemo.Lines.Add('Full Icon: '+TRecycleBinManager.RecyclerGetFullIconString());
+ outputMemo.Lines.Add('Empty Icon: '+TRecycleBinManager.RecyclerGetEmptyIconString());
outputMemo.Lines.Add('');
outputMemo.Lines.Add('= Events =');
outputMemo.Lines.Add('');
- outputMemo.Lines.Add('Empty Event Name: '+RecyclerEmptyEventGetName());
- outputMemo.Lines.Add('Empty Event Current Sound: '+RecyclerEmptyEventGetCurrentSound());
- outputMemo.Lines.Add('Empty Event Default Sound: '+RecyclerEmptyEventGetDefaultSound());
+ outputMemo.Lines.Add('Empty Event Name: '+TRecycleBinManager.RecyclerEmptyEventGetName());
+ outputMemo.Lines.Add('Empty Event Current Sound: '+TRecycleBinManager.RecyclerEmptyEventGetCurrentSound());
+ outputMemo.Lines.Add('Empty Event Default Sound: '+TRecycleBinManager.RecyclerEmptyEventGetDefaultSound());
sl := TStringList.Create;
try
- RecyclerEmptyEventGetSoundCategories(sl);
+ TRecycleBinManager.RecyclerEmptyEventGetSoundCategories(sl);
for i := 0 to sl.Count - 1 do
begin
- outputMemo.Lines.Add(Format('Event "%s" = %s', [sl.Strings[i], RecyclerEmptyEventGetSound(sl.Strings[i])]));
+ outputMemo.Lines.Add(Format('Event "%s" = %s', [sl.Strings[i], TRecycleBinManager.RecyclerEmptyEventGetSound(sl.Strings[i])]));
end;
finally
sl.Free;
@@ -338,37 +338,37 @@
outputMemo.Lines.Add('= Nuke on Delete =');
outputMemo.Lines.Add('');
- outputMemo.Lines.Add('Group policy setting: ' + GPBoolToString(RecyclerGroupPolicyNoRecycleFiles));
- outputMemo.Lines.Add('Global settings selected: ' + _BoolToYesNo(RecyclerHasGlobalSettings));
- outputMemo.Lines.Add('Global setting: ' + _BoolToEnabledDisabled(RecyclerGlobalIsNukeOnDelete()));
+ outputMemo.Lines.Add('Group policy setting: ' + GPBoolToString(TRecycleBinManager.RecyclerGroupPolicyNoRecycleFiles));
+ outputMemo.Lines.Add('Global settings selected: ' + _BoolToYesNo(TRecycleBinManager.RecyclerHasGlobalSettings));
+ outputMemo.Lines.Add('Global setting: ' + _BoolToEnabledDisabled(TRecycleBinManager.RecyclerGlobalIsNukeOnDelete()));
for d := 'A' to 'Z' do
begin
// if not RecyclerIsPossible(d) then Continue;
- outputMemo.Lines.Add('Individual setting for drive '+d+': ' + _BoolToEnabledDisabled(RecyclerSpecificIsNukeOnDelete(d)));
- outputMemo.Lines.Add('Auto determinated setting for drive '+d+' (includes group policy and global setting): ' + _BoolToEnabledDisabled(RecyclerIsNukeOnDeleteAutoDeterminate(d)));
+ outputMemo.Lines.Add('Individual setting for drive '+d+': ' + _BoolToEnabledDisabled(TRecycleBinManager.RecyclerSpecificIsNukeOnDelete(d)));
+ outputMemo.Lines.Add('Auto determinated setting for drive '+d+' (includes group policy and global setting): ' + _BoolToEnabledDisabled(TRecycleBinManager.RecyclerIsNukeOnDeleteAutoDeterminate(d)));
end;
outputMemo.Lines.Add('');
outputMemo.Lines.Add('= Usage Percent =');
outputMemo.Lines.Add('');
- outputMemo.Lines.Add('Group policy setting: ' + IntToStr(RecyclerGroupPolicyRecycleBinSize));
- outputMemo.Lines.Add('Global settings selected: ' + _BoolToYesNo(RecyclerHasGlobalSettings));
- outputMemo.Lines.Add('Global setting: ' + IntToStr(RecyclerGlobalGetPercentUsage()));
+ outputMemo.Lines.Add('Group policy setting: ' + IntToStr(TRecycleBinManager.RecyclerGroupPolicyRecycleBinSize));
+ outputMemo.Lines.Add('Global settings selected: ' + _BoolToYesNo(TRecycleBinManager.RecyclerHasGlobalSettings));
+ outputMemo.Lines.Add('Global setting: ' + IntToStr(TRecycleBinManager.RecyclerGlobalGetPercentUsage()));
for d := 'A' to 'Z' do
begin
// if not RecyclerIsPossible(d) then Continue;
- outputMemo.Lines.Add('Setting for drive '+d+': ' + IntToStr(RecyclerSpecificGetPercentUsage(d)));
- outputMemo.Lines.Add('Auto determinated setting for drive '+d+' (includes group policy and global setting): ' + IntToStr(RecyclerGetPercentUsageAutoDeterminate(d)));
+ outputMemo.Lines.Add('Setting for drive '+d+': ' + IntToStr(TRecycleBinManager.RecyclerSpecificGetPercentUsage(d)));
+ outputMemo.Lines.Add('Auto determinated setting for drive '+d+' (includes group policy and global setting): ' + IntToStr(TRecycleBinManager.RecyclerGetPercentUsageAutoDeterminate(d)));
end;
outputMemo.Lines.Add('');
outputMemo.Lines.Add('= Confirmation Dialog =');
outputMemo.Lines.Add('');
- outputMemo.Lines.Add('Setting in Shell: ' + _BoolToEnabledDisabled(RecyclerShellStateConfirmationDialogEnabled()));
- outputMemo.Lines.Add('Setting in Group Policy: ' + GPBoolToString(RecyclerGroupPolicyConfirmFileDelete()));
- outputMemo.Lines.Add('Resulting Setting (Group policy before Shell): ' + _BoolToEnabledDisabled(RecyclerConfirmationDialogEnabled()));
+ outputMemo.Lines.Add('Setting in Shell: ' + _BoolToEnabledDisabled(TRecycleBinManager.RecyclerShellStateConfirmationDialogEnabled()));
+ outputMemo.Lines.Add('Setting in Group Policy: ' + GPBoolToString(TRecycleBinManager.RecyclerGroupPolicyConfirmFileDelete()));
+ outputMemo.Lines.Add('Resulting Setting (Group policy before Shell): ' + _BoolToEnabledDisabled(TRecycleBinManager.RecyclerConfirmationDialogEnabled()));
finally
outputMemo.Visible := true;
end;
Index: RecBinUnit2/RB2Common.pas
===================================================================
--- RecBinUnit2/RB2Common.pas (revision 0)
+++ RecBinUnit2/RB2Common.pas (revision 0)
@@ -0,0 +1,301 @@
+unit RB2Common;
+
+(*
+ * OBJECT ORIENTED RECYCLE BIN UNIT
+ * VERSION 2.0 ALPHA
+ * Diese Unit soll Funktionen unterscheiden, die Forensisch und
+ * OS-Spezifisch ("alles was ich sehen kann") sind. (TODO)
+ *)
+
+interface
+
+uses
+ Windows, SysUtils, Classes, {$IFDEF DEL6UP}DateUtils,{$ENDIF}
+ ShellApi{$IFNDEF DEL6UP}, FileCtrl{$ENDIF}, Registry,
+ Messages, BitOps, contnrs;
+
+type
+ TRecycleBinItem = class(TObject)
+ function exists(): boolean; virtual; abstract;
+ function removeItem(): boolean; virtual; abstract;
+ end;
+
+ TRecycleBinItemList = class(TObjectList);
+
+ TRecycleBin = class(TObject)
+ private
+ location: string;
+ public
+ function getDrive(): char;
+ function getLocation(): string;
+ function getInfoFile(): string; virtual; abstract;
+ function getItems(): TRecycleBinItemList; virtual; abstract;
+ function isEmpty(): boolean; virtual; abstract;
+ constructor Create(location: string);
+ end;
+
+ TRecycleBinList = class(TObjectList);
+
+ TSIDRecycleBin = class(TRecycleBin)
+ public
+ SID: string;
+ end;
+
+ // X:\RECYCLED\INFO
+ // Windows 95 without Internet Explorer 4 ShellExtension
+ TRecycledInfo = class(TRecycleBin)
+
+ end;
+
+
+ TRecycledInfoItem = class(TRecycleBinItem)
+
+ end;
+
+ // X:\RECYCLED\INFO2
+ // Windows 95 with Internet Explorer 4 ShellExtension
+ TRecycledInfo2 = class(TRecycleBin)
+
+ end;
+
+ TRecycledInfo2Item = class(TRecycleBinItem)
+
+ end;
+
+ // X:\RECYCLER\<SID>\INFO2
+ // Windows NT with SID
+ TRecyclerSIDInfo2 = class(TSIDRecycleBin)
+
+ end;
+
+ TRecyclerInfo2Item = class(TRecycleBinItem)
+
+ end;
+
+ // X:\$RECYCLE.BIN\<SID>\$I...
+ // Windows Vista and higher and SID
+ TRecycleBinSIDVista = class(TSIDRecycleBin)
+
+ end;
+
+ TRecycleBinSIDVistaItem = class(TRecycleBinItem)
+
+ end;
+
+ // X:\$RECYCLE.BIN\<SID>\$I...
+ // Windows Vista and higher without SID (FAT32)
+ TRecycleBinVista = class(TRecycleBin)
+
+ end;
+
+ TRecycleBinVistaItem = class(TRecycleBinItem)
+
+ end;
+
+ TRecycleBinManager = class(TObject)
+ public
+ class procedure RecyclerGetAllRecyclerDrives(result: TStringList);
+ procedure GetAllRecycleBins(drive: Char; result: TRecycleBinItemList); overload;
+ procedure GetAllRecycleBins(result: TRecycleBinList); overload;
+ class function RecyclerIsPossible(Drive: Char): boolean;
+ end;
+
+implementation
+
+{ TRecycleBinManager }
+
+procedure ListAllDirectories (const Path: String;
+ List: TStrings) ;
+var
+ Res: TSearchRec;
+ EOFound: Boolean;
+begin
+ EOFound:= False;
+ if FindFirst(Path, faDirectory, Res) < 0 then
+ exit
+ else
+ while not EOFound do begin
+ List.Add(Res.Name) ;
+ EOFound:= FindNext(Res) <> 0;
+ end;
+ FindClose(Res) ;
+end;
+
+function isValidSID(const sid: string): boolean;
+begin
+ result := true; // TODO
+end;
+
+procedure ListAllSIDs(Path: string; Result: TStringList);
+var
+ sl: TStringList;
+ i: integer;
+ dir, sid: string;
+begin
+ Path := IncludeTrailingPathDelimiter(Path);
+ sl := TStringList.Create;
+ ListAllDirectories(Path, sl);
+ try
+ for i := 0 to sl.Count - 1 do
+ begin
+ sid := sl.Strings[i];
+ dir := Path + sid + PathDelim;
+ if isValidSID(sid) then
+ begin
+ result.Add(dir);
+ end;
+ end;
+ finally
+ sl.Free;
+ end;
+end;
+
+// Source: http://www.delphipraxis.net/post2933.html
+function DriveExists(DriveByte: Byte): Boolean; overload;
+begin
+ Result := GetLogicalDrives and (1 shl DriveByte) <> 0;
+end;
+
+function isFAT(drive: char): boolean;
+var
+ Dummy2: DWORD;
+ Dummy3: DWORD;
+ FileSystem: array[0..MAX_PATH] of char;
+ VolumeName: array[0..MAX_PATH] of char;
+ s: string;
+begin
+ result := false;
+ if DriveExists(drive) then
+ begin
+ s := drive + DriveDelim + PathDelim; // ohne die Auslagerung in einen String kommt es zu einer AV in ntdll
+ GetVolumeInformation(PChar(s), VolumeName,
+ SizeOf(VolumeName), nil, Dummy2, Dummy3, FileSystem, SizeOf(FileSystem));
+ result := uppercase(copy(FileSystem, 0, 3)) = 'FAT';
+ end;
+end;
+
+class procedure TRecycleBinManager.RecyclerGetAllRecyclerDrives(result: TStringList);
+var
+ Drive: char;
+begin
+ for Drive := 'A' to 'Z' do
+ begin
+ if RecyclerIsPossible(Drive) (* and RecyclerIsValid(Drive) *) then // TODO: Das ist eine OS und nicht Forensische Analyse
+ begin
+ result.Add(Drive);
+ end;
+ end;
+end;
+
+procedure TRecycleBinManager.GetAllRecycleBins(drive: Char; result: TRecycleBinItemList);
+var
+ dir: string;
+ sl: TStringList;
+ i: Integer;
+ sid: string;
+begin
+ // Find recyclers from Windows Vista or higher
+
+ // TODO: Unabhängig vom Partitionstyp behandeln?
+ if isFAT(drive) then
+ begin
+ dir := drive + DriveDelim + PathDelim + '$recycle.bin' + PathDelim;
+ result.Add(TRecycleBinVista.Create(dir));
+ end
+ else
+ begin
+ dir := drive + DriveDelim + PathDelim + '$recycle.bin' + PathDelim;
+ sl := TStringList.Create;
+ try
+ ListAllSIDs(dir, sl);
+ for i := 0 to sl.Count - 1 do
+ begin
+ sid := sl.Strings[i];
+ result.Add(TRecycleBinSIDVista.Create(dir+sid+PathDelim));
+ end;
+ finally
+ sl.Free;
+ end;
+ end;
+
+ // Find recyclers from Windows before Vista
+
+ if isFAT(drive) then
+ begin
+ dir := drive + DriveDelim + PathDelim + 'Recycled' + PathDelim;
+
+ // Both "recycle bins" are possible if you have multiboot
+ // (but do overwrite themselfes if you empty them)
+ if fileExists(dir + 'INFO2') then
+ begin
+ // Windows 95 with Internet Explorer 4 Extension or higher Windows versions
+ result.Add(TRecycledInfo2.Create(dir));
+ end;
+ if fileExists(dir + 'INFO') then
+ begin
+ // Windows 95 native
+ result.Add(TRecycledInfo.Create(dir));
+ end;
+ end
+ else
+ begin
+ dir := drive + DriveDelim + PathDelim + 'Recycler' + PathDelim;
+ sl := TStringList.Create;
+ try
+ ListAllSIDs(dir, sl);
+ for i := 0 to sl.Count - 1 do
+ begin
+ sid := sl.Strings[i];
+ result.Add(TRecyclerSIDInfo2.Create(dir+sid+PathDelim));
+ end;
+ finally
+ sl.Free;
+ end;
+ end;
+end;
+
+procedure TRecycleBinManager.GetAllRecycleBins(result: TRecycleBinList);
+var
+ sl: TStringList;
+ i: Integer;
+begin
+ sl := TStringList.Create();
+ try
+ RecyclerGetAllRecyclerDrives(sl);
+ for i := 0 to sl.Count - 1 do
+ begin
+ GetAllRecycleBins(sl.Strings[i], result);
+ end;
+ finally
+ sl.Free;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerIsPossible(Drive: Char): boolean;
+var
+ typ: Integer;
+begin
+ typ := GetDriveType(PChar(Drive + ':\'));
+ result := typ = DRIVE_FIXED;
+end;
+
+{ TRecycleBin }
+
+constructor TRecycleBin.Create(location: string);
+begin
+ inherited;
+
+ self.location := location;
+end;
+
+function TRecycleBin.getDrive: char;
+begin
+ result := UpperCase(Copy(location, 1, 1));
+end;
+
+function TRecycleBin.getLocation: string;
+begin
+ result := location;
+end;
+
+end.
Index: Recycler.dpr
===================================================================
--- Recycler.dpr (revision 35)
+++ Recycler.dpr (working copy)
@@ -3,7 +3,9 @@
uses
Forms,
Main in 'Main.pas' {MainForm},
- RecyclerFunctions in 'RecyclerFunctions.pas';
+ RecyclerFunctions in 'RecyclerFunctions.pas',
+ RB2Common in 'RecBinUnit2\RB2Common.pas',
+ RB2RecycledInfo in 'RecBinUnit2\RB2RecycledInfo.pas';
{$R *.res}
Index: Recycler.exe
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: RecyclerFunctions.pas
===================================================================
--- RecyclerFunctions.pas (revision 35)
+++ RecyclerFunctions.pas (working copy)
@@ -1,78 +1,3 @@
-////////////////////////////////////////////////////////////////////////////////////
-// RECYCLE-BIN-FUNCTIONS BY DANIEL MARSCHALL //
-// E-MAIL: info@daniel-marschall.de //
-// WEB: www.daniel-marschall.de //
-////////////////////////////////////////////////////////////////////////////////////
-// Revision: 05 JUL 2010 //
-// This unit is freeware, but please link to my website if you are using it! //
-////////////////////////////////////////////////////////////////////////////////////
-// Successful tested with: //
-// Windows 95b (without IE4 Shell Extensions) //
-// Windows 95b (with IE4 Shell Extensions) //
-// Windows 98-SE //
-// Windows XP-SP3 //
-// Windows 2000-SP4 //
-// Windows 2003 Server EE SP1 //
-// Windows Vista //
-// Windows 7 //
-////////////////////////////////////////////////////////////////////////////////////
-// //
-// Needs Delphi 4 or higher. If you are using Delphi 4 or 5, you can not use the //
-// RecyclerGetDateTime() functions, because the unit "DateUtils" is missing. //
-// Warning! This is a platform unit. //
-// //
-// To do! Can you help? //
-// - WideString-Support (input/output) //
-// - GetLoginNameW: Really 255 maximum? //
-// - Always do EOF before reading anything? //
-// - Is it possible to identify a Vista-file that is not named $Ixxxxxx.ext? //
-// - RecyclerGetInfofiles() check additionally for removable device? //
-// RecyclerIsValid() is false. //
-// - Make it possible to empty the recycle bin of one specific drive! //
-// //
-// Unknown! Do you know the answer? //
-// - How does Windows 9x/NT manage the daylight saving time (if it does)? //
-// - How does Windows Vista react to a RECYCLER\ folder on a NTFS device? //
-// - How does Windows Vista react to a RECYCLED\ folder on a FAT device? //
-// //
-// Not analyzed yet! Please send me your trash folder contents for analyzing! //
-// - Windows NT //
-// - Windows CE? //
-// - Windows 7 //
-// //
-// Thanks to all these who have helped me solving coding problems. //
-// Thanks to SEBA for sending in the Windows Vista trash structure files. //
-// Thanks to OMATA for testing the unit with Delphi 4. //
-// Thanks to DEITYSOU for making a bugfix of DriveExists() //
-// //
-////////////////////////////////////////////////////////////////////////////////////
-
-(*
-
-== TODO LISTE ==
-
-Wichtig! Windows XP: InfoTip, IntroText und LocalizedString sind Resourcenangaben und müssen ausgelesen werden!
-Testen: Wie reagiert Windows, wenn Bitbucket\C existiert, aber kein Wert 'Percent' hat? Mit der Standardeinstellung?
-Bug: Windows 2000 bei bestehenden Windows 95 Partition: Recycler Filename ist dann Recycled und nicht Recycler!
-bug? w95 recycled file hat immer selben löschzeitpunkt und größe? war die nicht verschieden?
-beachtet? bei leerem papierkorb auf fat ist weder info noch info2 vorhanden?
-testen: auch möglich, einen vista papierkorb offline öffnen?
-Problem: bei win95(ohne ie4) und win2000 gleichzeitiger installation: es existiert info UND info2!!!
-Implement SETTER functions to every kind of configuration thing. (percentage etc)
-Registry CURRENT_USER: Funktionen auch für fremde Benutzer zur Verfügung stellen?
-Es sollte möglich sein, dass ein Laufwerk mehr als 1 Recycler beinhaltet -- behandeln
-
-- Future -
-
-Demoapplikation: Dateien statt Text als Explorer-Like?
-Einzelne Elemente oder alle wiederherstellen oder löschen
-Konfiguration für Laufwerke ändern etc
-IconString -> TIcon Convertion functions
-platzreservierung in mb-angabe berechnen
-I don't know if there exists any API function which checks the state at any internal way.
-
-*)
-
// TODO: Also include BC++ Versions
{$IFNDEF BCB}
{$DEFINE DEL1UP}
@@ -136,140 +61,144 @@
GPOLICYBOOL = (gpUndefined, gpEnabled, gpDisabled);
-const
- RECYCLER_CLSID = '{645FF040-5081-101B-9F08-00AA002F954E}';
+ // TODO: $Recycle.Bin at external harddisk with Vista??
-{$IFDEF DEL6UP}
-function RecyclerGetDateTime(drive: char; fileid: string): tdatetime; overload;
-function RecyclerGetDateTime(drive: char; UserSID: string; fileid: string): tdatetime; overload;
-function RecyclerGetDateTime(InfofileOrRecycleFolder: string): tdatetime; overload;
-function RecyclerGetDateTime(InfofileOrRecycleFolder: string; id: string): tdatetime; overload;
-{$ENDIF}
+ TRecycleBinManager = class(TObject)
+ class function RecyclerGetCurrentIconString: string;
+ class function RecyclerGetDefaultIconString: string;
+ class function RecyclerGetEmptyIconString: string;
+ class function RecyclerGetFullIconString: string;
-function RecyclerGetSourceUnicode(drive: char; fileid: string): WideString; overload;
-function RecyclerGetSourceUnicode(drive: char; UserSID: string; fileid: string): WideString; overload;
-function RecyclerGetSourceUnicode(InfofileOrRecycleFolder: string): WideString; overload;
-function RecyclerGetSourceUnicode(InfofileOrRecycleFolder: string; id: string): WideString; overload;
+ class function RecyclerIsEmpty: boolean; overload;
+ class function RecyclerIsEmpty(Drive: Char): boolean; overload;
-function RecyclerGetSource(drive: char; fileid: string): string; overload;
-function RecyclerGetSource(drive: char; UserSID: string; fileid: string): string; overload;
-function RecyclerGetSource(InfofileOrRecycleFolder: string): string; overload;
-function RecyclerGetSource(InfofileOrRecycleFolder: string; id: string): string; overload;
+ {$IFDEF DEL6UP}
+ class function RecyclerGetDateTime(drive: char; fileid: string): tdatetime; overload;
+ class function RecyclerGetDateTime(drive: char; UserSID: string; fileid: string): tdatetime; overload;
+ class function RecyclerGetDateTime(InfofileOrRecycleFolder: string): tdatetime; overload;
+ class function RecyclerGetDateTime(InfofileOrRecycleFolder: string; id: string): tdatetime; overload;
+ {$ENDIF}
-procedure RecyclerListIndexes(drive: char; result: TStringList); overload;
-procedure RecyclerListIndexes(drive: char; UserSID: string; result: TStringList); overload;
-procedure RecyclerListIndexes(InfofileOrRecycleFolder: string; result: TStringList); overload;
+ class function RecyclerGetSourceUnicode(drive: char; fileid: string): WideString; overload;
+ class function RecyclerGetSourceUnicode(drive: char; UserSID: string; fileid: string): WideString; overload;
+ class function RecyclerGetSourceUnicode(InfofileOrRecycleFolder: string): WideString; overload;
+ class function RecyclerGetSourceUnicode(InfofileOrRecycleFolder: string; id: string): WideString; overload;
-function RecyclerGetSourceDrive(drive: char; fileid: string): char; overload;
-function RecyclerGetSourceDrive(drive: char; UserSID: string; fileid: string): char; overload;
-function RecyclerGetSourceDrive(InfofileOrRecycleFolder: string): char; overload;
-function RecyclerGetSourceDrive(InfofileOrRecycleFolder: string; id: string): char; overload;
+ class function RecyclerGetSource(drive: char; fileid: string): string; overload;
+ class function RecyclerGetSource(drive: char; UserSID: string; fileid: string): string; overload;
+ class function RecyclerGetSource(InfofileOrRecycleFolder: string): string; overload;
+ class function RecyclerGetSource(InfofileOrRecycleFolder: string; id: string): string; overload;
-function RecyclerOriginalSize(drive: char; fileid: string): integer; overload;
-function RecyclerOriginalSize(drive: char; UserSID: string; fileid: string): integer; overload;
-function RecyclerOriginalSize(InfofileOrRecycleFolder: string): integer; overload;
-function RecyclerOriginalSize(InfofileOrRecycleFolder: string; id: string): integer; overload;
+ class procedure RecyclerListIndexes(drive: char; result: TStringList); overload;
+ class procedure RecyclerListIndexes(drive: char; UserSID: string; result: TStringList); overload;
+ class procedure RecyclerListIndexes(InfofileOrRecycleFolder: string; result: TStringList); overload;
-function RecyclerIsValid(drive: char): boolean; overload;
-function RecyclerIsValid(drive: char; UserSID: string): boolean; overload;
-function RecyclerIsValid(InfofileOrRecycleFolder: string): boolean; overload;
+ class function RecyclerGetSourceDrive(drive: char; fileid: string): char; overload;
+ class function RecyclerGetSourceDrive(drive: char; UserSID: string; fileid: string): char; overload;
+ class function RecyclerGetSourceDrive(InfofileOrRecycleFolder: string): char; overload;
+ class function RecyclerGetSourceDrive(InfofileOrRecycleFolder: string; id: string): char; overload;
-function RecyclerCurrentFilename(drive: char; fileid: string): string; overload;
-function RecyclerCurrentFilename(drive: char; UserSID: string; fileid: string): string; overload;
-function RecyclerCurrentFilename(InfofileOrRecycleFolder: string): string; overload;
-function RecyclerCurrentFilename(InfofileOrRecycleFolder: string; id: string): string; overload;
+ class function RecyclerOriginalSize(drive: char; fileid: string): integer; overload;
+ class function RecyclerOriginalSize(drive: char; UserSID: string; fileid: string): integer; overload;
+ class function RecyclerOriginalSize(InfofileOrRecycleFolder: string): integer; overload;
+ class function RecyclerOriginalSize(InfofileOrRecycleFolder: string; id: string): integer; overload;
-function RecyclerGetPath(drive: char; UserSID: string; IncludeInfofile: boolean; fileid: string): string; overload;
-function RecyclerGetPath(drive: char; UserSID: string; IncludeInfofile: boolean): string; overload;
-function RecyclerGetPath(drive: char; IncludeInfofile: boolean): string; overload;
-function RecyclerGetPath(drive: char; UserSID: string): string; overload;
-function RecyclerGetPath(drive: char): string; overload;
+ class function RecyclerIsValid(drive: char): boolean; overload;
+ class function RecyclerIsValid(drive: char; UserSID: string): boolean; overload;
+ class function RecyclerIsValid(InfofileOrRecycleFolder: string): boolean; overload;
-procedure RecyclerGetInfofiles(drive: char; UserSID: string; IncludeInfofile: boolean; fileid: string; result: TStringList); overload;
-procedure RecyclerGetInfofiles(drive: char; UserSID: string; IncludeInfofile: boolean; result: TStringList); overload;
-procedure RecyclerGetInfofiles(drive: char; IncludeInfofile: boolean; result: TStringList); overload;
-procedure RecyclerGetInfofiles(drive: char; UserSID: string; result: TStringList); overload;
-procedure RecyclerGetInfofiles(drive: char; result: TStringList); overload;
+ class function RecyclerCurrentFilename(drive: char; fileid: string): string; overload;
+ class function RecyclerCurrentFilename(drive: char; UserSID: string; fileid: string): string; overload;
+ class function RecyclerCurrentFilename(InfofileOrRecycleFolder: string): string; overload;
+ class function RecyclerCurrentFilename(InfofileOrRecycleFolder: string; id: string): string; overload;
-function RecyclerCurrentFilenameAndPath(drive: char; UserSID: string; fileid: string): string; overload;
-function RecyclerCurrentFilenameAndPath(drive: char; fileid: string): string; overload;
-function RecyclerCurrentFilenameAndPath(InfofileOrRecycleFolder: string; id: string): string; overload;
+ class function RecyclerGetPath(drive: char; UserSID: string; IncludeInfofile: boolean; fileid: string): string; overload;
+ class function RecyclerGetPath(drive: char; UserSID: string; IncludeInfofile: boolean): string; overload;
+ class function RecyclerGetPath(drive: char; IncludeInfofile: boolean): string; overload;
+ class function RecyclerGetPath(drive: char; UserSID: string): string; overload;
+ class function RecyclerGetPath(drive: char): string; overload;
-function RecyclerRemoveItem(drive: char; UserSID: string; fileid: string): boolean; overload;
-function RecyclerRemoveItem(drive: char; fileid: string): boolean; overload;
-function RecyclerRemoveItem(InfofileOrRecycleFolder: string; id: string): boolean; overload;
+ class procedure RecyclerGetInfofiles(drive: char; UserSID: string; IncludeInfofile: boolean; fileid: string; result: TStringList); overload;
+ class procedure RecyclerGetInfofiles(drive: char; UserSID: string; IncludeInfofile: boolean; result: TStringList); overload;
+ class procedure RecyclerGetInfofiles(drive: char; IncludeInfofile: boolean; result: TStringList); overload;
+ class procedure RecyclerGetInfofiles(drive: char; UserSID: string; result: TStringList); overload;
+ class procedure RecyclerGetInfofiles(drive: char; result: TStringList); overload;
-procedure RecyclerGetAllRecyclerDrives(result: TStringList);
+ class function RecyclerCurrentFilenameAndPath(drive: char; UserSID: string; fileid: string): string; overload;
+ class function RecyclerCurrentFilenameAndPath(drive: char; fileid: string): string; overload;
+ class function RecyclerCurrentFilenameAndPath(InfofileOrRecycleFolder: string; id: string): string; overload;
-function RecyclerEmptyRecycleBin(flags: cardinal): boolean; overload;
-function RecyclerEmptyRecycleBin(sound, progress, confirmation: boolean): boolean; overload;
+ class function RecyclerRemoveItem(drive: char; UserSID: string; fileid: string): boolean; overload;
+ class function RecyclerRemoveItem(drive: char; fileid: string): boolean; overload;
+ class function RecyclerRemoveItem(InfofileOrRecycleFolder: string; id: string): boolean; overload;
-function RecyclerAddFileOrFolder(FileOrFolder: string; confirmation: boolean): boolean; overload;
-function RecyclerAddFileOrFolder(FileOrFolder: string): boolean; overload;
+ class procedure RecyclerGetAllRecyclerDrives(result: TStringList);
-function RecyclerConfirmationDialogEnabled: boolean;
-function RecyclerShellStateConfirmationDialogEnabled: boolean;
-procedure RecyclerConfirmationDialogSetEnabled(NewSetting: boolean);
+ class function RecyclerEmptyRecycleBin(flags: cardinal): boolean; overload;
+ class function RecyclerEmptyRecycleBin(sound, progress, confirmation: boolean): boolean; overload;
-function RecyclerGetCurrentIconString: string;
-function RecyclerGetDefaultIconString: string;
-function RecyclerGetEmptyIconString: string;
-function RecyclerGetFullIconString: string;
+ class function RecyclerAddFileOrFolder(FileOrFolder: string; confirmation: boolean): boolean; overload;
+ class function RecyclerAddFileOrFolder(FileOrFolder: string): boolean; overload;
-function RecyclerGetName: string;
-function RecyclerGetInfoTip: string;
-function RecyclerGetIntroText: string;
+ class function RecyclerConfirmationDialogEnabled: boolean;
+ class function RecyclerShellStateConfirmationDialogEnabled: boolean;
+ class procedure RecyclerConfirmationDialogSetEnabled(NewSetting: boolean);
-function RecyclerEmptyEventGetName: string;
-function RecyclerEmptyEventGetCurrentSound: string;
-function RecyclerEmptyEventGetDefaultSound: string;
-procedure RecyclerEmptyEventGetSoundCategories(AStringList: TStringList);
-function RecyclerEmptyEventGetSound(ACategory: string): string;
+ class function RecyclerGetName: string;
+ class function RecyclerGetInfoTip: string;
+ class function RecyclerGetIntroText: string;
-function RecyclerGlobalGetPercentUsage: integer;
-function RecyclerSpecificGetPercentUsage(Drive: Char): integer;
-function RecyclerGetPercentUsageAutoDeterminate(Drive: Char): integer;
+ class function RecyclerEmptyEventGetName: string;
+ class function RecyclerEmptyEventGetCurrentSound: string;
+ class function RecyclerEmptyEventGetDefaultSound: string;
+ class procedure RecyclerEmptyEventGetSoundCategories(AStringList: TStringList);
+ class function RecyclerEmptyEventGetSound(ACategory: string): string;
-function RecyclerGlobalIsNukeOnDelete: boolean;
-function RecyclerSpecificIsNukeOnDelete(Drive: Char): boolean;
-function RecyclerIsNukeOnDeleteAutoDeterminate(Drive: Char): boolean;
+ class function RecyclerGlobalGetPercentUsage: integer;
+ class function RecyclerSpecificGetPercentUsage(Drive: Char): integer;
+ class function RecyclerGetPercentUsageAutoDeterminate(Drive: Char): integer;
-function RecyclerHasGlobalSettings: boolean;
+ class function RecyclerGlobalIsNukeOnDelete: boolean;
+ class function RecyclerSpecificIsNukeOnDelete(Drive: Char): boolean;
+ class function RecyclerIsNukeOnDeleteAutoDeterminate(Drive: Char): boolean;
-function RecyclerIsEmpty: boolean; overload;
-function RecyclerIsEmpty(Drive: Char): boolean; overload;
+ class function RecyclerHasGlobalSettings: boolean;
-function RecyclerGetNumItems: int64; overload;
-function RecyclerGetNumItems(Drive: Char): int64; overload;
+ class function RecyclerGetNumItems: int64; overload;
+ class function RecyclerGetNumItems(Drive: Char): int64; overload;
-function RecyclerGetSize: int64; overload;
-function RecyclerGetSize(Drive: Char): int64; overload;
+ class function RecyclerGetSize: int64; overload;
+ class function RecyclerGetSize(Drive: Char): int64; overload;
-function RecyclerGetAPIInfo(Drive: Char): TSHQueryRBInfo; overload;
-function RecyclerGetAPIInfo(Path: String): TSHQueryRBInfo; overload;
+ class function RecyclerGetAPIInfo(Drive: Char): TSHQueryRBInfo; overload;
+ class function RecyclerGetAPIInfo(Path: String): TSHQueryRBInfo; overload;
-function RecyclerGetCLSID: string;
+ class function RecyclerGetCLSID: string;
-// Diese Funktion ist false, wenn sie z.B. unter Windows 95 ohne Internet Explorer
-// 4.0 Shell Extension ausgeführt wird. Wenn abwärtskompatibler Code geschrieben
-// werden soll, sollte RecyclerQueryFunctionAvailable() verwendet werden, da
-// unter Windows 95 folgende Funktionalitäten NICHT vorhanden sind:
-// - RecyclerIsEmpty
-// - RecyclerGetNumItems
-// - RecyclerGetSize
-// - RecyclerGetAPIInfo
-function RecyclerQueryFunctionAvailable: boolean;
+ // Diese Funktion ist false, wenn sie z.B. unter Windows 95 ohne Internet Explorer
+ // 4.0 Shell Extension ausgeführt wird. Wenn abwärtskompatibler Code geschrieben
+ // werden soll, sollte RecyclerQueryFunctionAvailable() verwendet werden, da
+ // unter Windows 95 folgende Funktionalitäten NICHT vorhanden sind:
+ // - RecyclerIsEmpty
+ // - RecyclerGetNumItems
+ // - RecyclerGetSize
+ // - RecyclerGetAPIInfo
+ class function RecyclerQueryFunctionAvailable: boolean;
-function RecyclerGroupPolicyNoRecycleFiles: GPOLICYBOOL;
-function RecyclerGroupPolicyConfirmFileDelete: GPOLICYBOOL;
-function RecyclerGroupPolicyRecycleBinSize: integer;
+ class function RecyclerGroupPolicyNoRecycleFiles: GPOLICYBOOL;
+ class function RecyclerGroupPolicyConfirmFileDelete: GPOLICYBOOL;
+ class function RecyclerGroupPolicyRecycleBinSize: integer;
-function GPBoolToString(value: GPOLICYBOOL): String;
+ class function RecyclerIsPossible(Drive: Char): boolean;
-function RecyclerIsPossible(Drive: Char): boolean;
+ class function RecyclerLibraryVersion: string;
+ end;
-function RecyclerLibraryVersion: string;
+ function GPBoolToString(value: GPOLICYBOOL): String;
+const
+ RECYCLER_CLSID = '{645FF040-5081-101B-9F08-00AA002F954E}';
+
implementation
type
@@ -964,17 +893,17 @@
{$IFDEF DEL6UP}
-function RecyclerGetDateTime(InfofileOrRecycleFolder: string): tdatetime; overload;
+class function TRecycleBinManager.RecyclerGetDateTime(InfofileOrRecycleFolder: string): tdatetime;
begin
result := RecyclerGetDateTime(InfofileOrRecycleFolder, '');
end;
-function RecyclerGetDateTime(drive: char; fileid: string): tdatetime; overload;
+class function TRecycleBinManager.RecyclerGetDateTime(drive: char; fileid: string): tdatetime;
begin
result := RecyclerGetDateTime(drive, '', fileid);
end;
-function RecyclerGetDateTime(drive: char; UserSID: string; fileid: string): tdatetime; overload;
+class function TRecycleBinManager.RecyclerGetDateTime(drive: char; UserSID: string; fileid: string): tdatetime;
var
infofile: string;
begin
@@ -982,7 +911,7 @@
result := RecyclerGetDateTime(infofile, fileid);
end;
-function RecyclerGetDateTime(InfofileOrRecycleFolder: string; id: string): tdatetime; overload;
+class function TRecycleBinManager.RecyclerGetDateTime(InfofileOrRecycleFolder: string; id: string): tdatetime;
var
fs: TFileStream;
i, record_length: integer;
@@ -1055,17 +984,105 @@
////////////////////////////////////////////////////////////////////////////////
-function RecyclerGetSourceUnicode(InfofileOrRecycleFolder: string): WideString; overload;
+{ TRecycleBinManager }
+
+class function TRecycleBinManager.RecyclerGetCurrentIconString: string;
begin
+ if TRecycleBinManager.RecyclerIsEmpty then
+ result := RecyclerGetEmptyIconString
+ else
+ result := RecyclerGetFullIconString;
+end;
+
+class function TRecycleBinManager.RecyclerGetDefaultIconString: string;
+var
+ reg: TRegistry;
+begin
+ // Please note: The "default" icon is not always the icon of the
+ // current recycle bin in its current state (full, empty)
+ // At Windows 95b, the registry value actually did change every time the
+ // recycle bin state did change, but at Windows 2000 I could not see any
+ // update, even after reboot. So, the registry value is possible fixed as
+ // default = empty on newer OS versions.
+
+ reg := TRegistry.Create;
+ try
+ reg.RootKey := HKEY_CLASSES_ROOT;
+ if reg.OpenKeyReadOnly('CLSID\'+RECYCLER_CLSID+'\DefaultIcon') then
+ begin
+ result := reg.ReadString('');
+ reg.CloseKey;
+ end;
+ finally
+ reg.Free;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerGetEmptyIconString: string;
+var
+ reg: TRegistry;
+begin
+ reg := TRegistry.Create;
+ try
+ reg.RootKey := HKEY_CLASSES_ROOT;
+ if reg.OpenKeyReadOnly('CLSID\'+RECYCLER_CLSID+'\DefaultIcon') then
+ begin
+ result := reg.ReadString('Empty');
+ reg.CloseKey;
+ end;
+ finally
+ reg.Free;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerGetFullIconString: string;
+var
+ reg: TRegistry;
+begin
+ reg := TRegistry.Create;
+ try
+ reg.RootKey := HKEY_CLASSES_ROOT;
+ if reg.OpenKeyReadOnly('CLSID\'+RECYCLER_CLSID+'\DefaultIcon') then
+ begin
+ result := reg.ReadString('Full');
+ reg.CloseKey;
+ end;
+ finally
+ reg.Free;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerIsEmpty: boolean;
+var
+ Drive: Char;
+begin
+ result := true;
+ for Drive := 'A' to 'Z' do
+ begin
+ if RecyclerIsPossible(Drive) and not RecyclerIsEmpty(Drive) then
+ begin
+ result := false;
+ exit;
+ end;
+ end;
+end;
+
+class function TRecycleBinManager.RecyclerIsEmpty(Drive: Char): boolean;
+begin
+ result := RecyclerGetAPIInfo(Drive).i64NumItems = 0;
+end;
+
+class function TRecycleBinManager.RecyclerGetSourceUnicode(InfofileOrRecycleFolder: string): WideString;
+begin
result := RecyclerGetSourceUnicode(InfofileOrRecycleFolder, '');
end;
-function RecyclerGetSourceUnicode(drive: char; fileid: string): WideString; overload;
+class function TRecycleBinManager.RecyclerGetSourceUnicode(drive: char; fileid: string): WideString;
begin
result := RecyclerGetSourceUnicode(drive, '', fileid);
end;
-function RecyclerGetSourceUnicode(drive: char; UserSID: string; fileid: string): WideString; overload;
+class function TRecycleBinManager.RecyclerGetSourceUnicode(drive: char; UserSID: string; fileid: string): WideString;
var
infofile: string;
begin
@@ -1081,7 +1098,7 @@
end;
end;
-function RecyclerGetSourceUnicode(InfofileOrRecycleFolder: string; id: string): WideString; overload;
+class function TRecycleBinManager.RecyclerGetSourceUnicode(InfofileOrRecycleFolder: string; id: string): WideString;
var
fs: TFileStream;
i, record_length: integer;
@@ -1163,17 +1180,17 @@
////////////////////////////////////////////////////////////////////////////////
-function RecyclerGetSource(InfofileOrRecycleFolder: string): string; overload;
+class function TRecycleBinManager.RecyclerGetSource(InfofileOrRecycleFolder: string): string;
begin
result := RecyclerGetSource(InfofileOrRecycleFolder, '');
end;
-function RecyclerGetSource(drive: char; fileid: string): string; overload;
+class function TRecycleBinManager.RecyclerGetSource(drive: char; fileid: string): string;
begin
result := RecyclerGetSource(drive, '', fileid);
end;
-function RecyclerGetSource(drive: char; UserSID: string; fileid: string): string; overload;
+class function TRecycleBinManager.RecyclerGetSource(drive: char; UserSID: string; fileid: string): string;
var
infofile: string;
begin
@@ -1181,7 +1198,7 @@
result := RecyclerGetSource(infofile, fileid);
end;
-function RecyclerGetSource(InfofileOrRecycleFolder: string; id: string): string; overload;
+class function TRecycleBinManager.RecyclerGetSource(InfofileOrRecycleFolder: string; id: string): string;
var
fs: TFileStream;
i, record_length: integer;
@@ -1272,12 +1289,12 @@
////////////////////////////////////////////////////////////////////////////////
-procedure RecyclerListIndexes(drive: char; result: TStringList); overload;
+class procedure TRecycleBinManager.RecyclerListIndexes(drive: char; result: TStringList);
begin
RecyclerListIndexes(drive, '', result);
end;
-procedure RecyclerListIndexes(drive: char; UserSID: string; result: TStringList); overload;
+class procedure TRecycleBinManager.RecyclerListIndexes(drive: char; UserSID: string; result: TStringList);
var
infofile: string;
begin
@@ -1285,7 +1302,7 @@
RecyclerListIndexes(infofile, result);
end;
-procedure RecyclerListIndexes(InfofileOrRecycleFolder: string; result: TStringList); overload;
+class procedure TRecycleBinManager.RecyclerListIndexes(InfofileOrRecycleFolder: string; result: TStringList);
var
fs: TFileStream;
i, record_length: integer;
@@ -1349,17 +1366,17 @@
////////////////////////////////////////////////////////////////////////////////
-function RecyclerGetSourceDrive(InfofileOrRecycleFolder: string): char; overload;
+class function TRecycleBinManager.RecyclerGetSourceDrive(InfofileOrRecycleFolder: string): char;
begin
result := RecyclerGetSourceDrive(InfofileOrRecycleFolder, '');
end;
-function RecyclerGetSourceDrive(drive: char; fileid: string): char; overload;
+class function TRecycleBinManager.RecyclerGetSourceDrive(drive: char; fileid: string): char;
begin
result := RecyclerGetSourceDrive(drive, '', fileid);
end;
-function RecyclerGetSourceDrive(drive: char; UserSID: string; fileid: string): char; overload;
+class function TRecycleBinManager.RecyclerGetSourceDrive(drive: char; UserSID: string; fileid: string): char;
var
infofile: string;
begin
@@ -1367,7 +1384,7 @@
result := RecyclerGetSourceDrive(infofile, fileid);
end;
-function RecyclerGetSourceDrive(InfofileOrRecycleFolder: string; id: string): char; overload;
+class function TRecycleBinManager.RecyclerGetSourceDrive(InfofileOrRecycleFolder: string; id: string): char;
var
fs: TFileStream;
i, record_length: integer;
@@ -1437,17 +1454,17 @@
////////////////////////////////////////////////////////////////////////////////
-function RecyclerOriginalSize(InfofileOrRecycleFolder: string): integer; overload;
+class function TRecycleBinManager.RecyclerOriginalSize(InfofileOrRecycleFolder: string): integer;
begin
result := RecyclerOriginalSize(InfofileOrRecycleFolder, '');
end;
-function RecyclerOriginalSize(drive: char; fileid: string): integer; overload;
+class function TRecycleBinManager.RecyclerOriginalSize(drive: char; fileid: string): integer;
begin
result := RecyclerOriginalSize(drive, '', fileid);
end;
-function RecyclerOriginalSize(drive: char; UserSID: string; fileid: string): integer; overload;
+class function TRecycleBinManager.RecyclerOriginalSize(drive: char; UserSID: string; fileid: string): integer;
var
infofile: string;
begin
@@ -1455,7 +1472,7 @@
result := RecyclerOriginalSize(infofile, fileid);
end;
-function RecyclerOriginalSize(InfofileOrRecycleFolder: string; id: string): integer; overload;
+class function TRecycleBinManager.RecyclerOriginalSize(InfofileOrRecycleFolder: string; id: string): integer;
var
fs: TFileStream;
i, record_length: integer;
@@ -1525,7 +1542,7 @@
////////////////////////////////////////////////////////////////////////////////
-function RecyclerIsValid(drive: char): boolean; overload;
+class function TRecycleBinManager.RecyclerIsValid(drive: char): boolean;
begin
// Bei Vista und W2k3 (VM) erhalte ich bei LW A: die Meldung
// "c0000013 Kein Datenträger". Exception Abfangen geht nicht.
@@ -1536,7 +1553,7 @@
result := RecyclerIsValid(drive, '');
end;
-function RecyclerIsValid(drive: char; UserSID: string): boolean; overload;
+class function TRecycleBinManager.RecyclerIsValid(drive: char; UserSID: string): boolean;
var
infofile: string;
begin
@@ -1548,7 +1565,7 @@
result := RecyclerIsValid(infofile);
end;
-function RecyclerIsValid(InfofileOrRecycleFolder: string): boolean; overload;
+class function TRecycleBinManager.RecyclerIsValid(InfofileOrRecycleFolder: string): boolean;
var
tmp: string;
x: TStringList;
@@ -1617,17 +1634,17 @@
////////////////////////////////////////////////////////////////////////////////
-function RecyclerCurrentFilename(InfofileOrRecycleFolder: string): string; overload;
+class function TRecycleBinManager.RecyclerCurrentFilename(InfofileOrRecycleFolder: string): string;
begin
result := RecyclerCurrentFilename(InfofileOrRecycleFolder, '');
end;
-function RecyclerCurrentFilename(drive: char; fileid: string): string; overload;
+class function TRecycleBinManager.RecyclerCurrentFilename(drive: char; fileid: string): string;
begin
result := RecyclerCurrentFilename(drive, '', fileid);
end;
-function RecyclerCurrentFilename(drive: char; UserSID: string; fileid: string): string; overload;
+class function TRecycleBinManager.RecyclerCurrentFilename(drive: char; UserSID: string; fileid: string): string;
var
infofile: string;
begin
@@ -1635,7 +1652,7 @@
result := RecyclerCurrentFilename(infofile, fileid);
end;
-function RecyclerCurrentFilename(InfofileOrRecycleFolder: string; id: string): string; overload;
+class function TRecycleBinManager.RecyclerCurrentFilename(InfofileOrRecycleFolder: string; id: string): string;
var
a, c: string;
tmp: string;
@@ -1683,7 +1700,7 @@
////////////////////////////////////////////////////////////////////////////////
-function RecyclerGetPath(drive: char; UserSID: string; IncludeInfofile: boolean; fileid: string): string; overload;
+class function TRecycleBinManager.RecyclerGetPath(drive: char; UserSID: string; IncludeInfofile: boolean; fileid: string): string;
var
sl: TStringList;
begin
@@ -1699,7 +1716,7 @@
end;
end;
-function RecyclerGetPath(drive: char; UserSID: string; IncludeInfofile: boolean): string; overload;
+class function TRecycleBinManager.RecyclerGetPath(drive: char; UserSID: string; IncludeInfofile: boolean): string;
var
sl: TStringList;
begin
@@ -1715,7 +1732,7 @@
end;
end;
-function RecyclerGetPath(drive: char; IncludeInfofile: boolean): string; overload;
+class function TRecycleBinManager.RecyclerGetPath(drive: char; IncludeInfofile: boolean): string;
var
sl: TStringList;
begin
@@ -1731,7 +1748,7 @@
end;
end;
-function RecyclerGetPath(drive: char; UserSID: string): string; overload;
+class function TRecycleBinManager.RecyclerGetPath(drive: char; UserSID: string): string;
var
sl: TStringList;
begin
@@ -1747,7 +1764,7 @@
end;
end;
-function RecyclerGetPath(drive: char): string; overload;
+class function TRecycleBinManager.RecyclerGetPath(drive: char): string;
var
sl: TStringList;
begin
@@ -1765,7 +1782,7 @@
////////////////////////////////////////////////////////////////////////////////
-procedure RecyclerGetInfofiles(drive: char; UserSID: string; IncludeInfofile: boolean; fileid: string; result: TStringList); overload;
+class procedure TRecycleBinManager.RecyclerGetInfofiles(drive: char; UserSID: string; IncludeInfofile: boolean; fileid: string; result: TStringList);
var
dir: string;
begin
@@ -1881,40 +1898,40 @@
end;
end;
-procedure RecyclerGetInfofiles(drive: char; UserSID: string; IncludeInfofile: boolean; result: TStringList); overload;
+class procedure TRecycleBinManager.RecyclerGetInfofiles(drive: char; UserSID: string; IncludeInfofile: boolean; result: TStringList);
begin
RecyclerGetInfofiles(drive, UserSID, IncludeInfofile, '', result);
end;
-procedure RecyclerGetInfofiles(drive: char; IncludeInfofile: boolean; result: TStringList); overload;
+class procedure TRecycleBinManager.RecyclerGetInfofiles(drive: char; IncludeInfofile: boolean; result: TStringList);
begin
RecyclerGetInfofiles(drive, '', IncludeInfofile, '', result);
end;
-procedure RecyclerGetInfofiles(drive: char; UserSID: string; result: TStringList); overload;
+class procedure TRecycleBinManager.RecyclerGetInfofiles(drive: char; UserSID: string; result: TStringList);
begin
RecyclerGetInfofiles(drive, UserSID, false, '', result);
end;
-procedure RecyclerGetInfofiles(drive: char; result: TStringList); overload;
+class procedure TRecycleBinManager.RecyclerGetInfofiles(drive: char; result: TStringList);
begin
RecyclerGetInfofiles(drive, '', false, '', result);
end;
////////////////////////////////////////////////////////////////////////////////
-function RecyclerCurrentFilenameAndPath(drive: char; UserSID: string; fileid: string): string; overload;
+class function TRecycleBinManager.RecyclerCurrentFilenameAndPath(drive: char; UserSID: string; fileid: string): string;
begin
result := RecyclerGetPath(drive, UserSID, false, fileid) +
RecyclerCurrentFilename(drive, UserSID, fileid);
end;
-function RecyclerCurrentFilenameAndPath(drive: char; fileid: string): string; overload;
+class function TRecycleBinManager.RecyclerCurrentFilenameAndPath(drive: char; fileid: string): string;
begin
result := RecyclerCurrentFilenameAndPath(drive, '', fileid);
end;
-function RecyclerCurrentFilenameAndPath(InfofileOrRecycleFolder: string; id: string): string; overload;
+class function TRecycleBinManager.RecyclerCurrentFilenameAndPath(InfofileOrRecycleFolder: string; id: string): string;
begin
if RecyclerIsValid(InfofileOrRecycleFolder) then
begin
@@ -1927,7 +1944,7 @@
////////////////////////////////////////////////////////////////////////////////
-function RecyclerRemoveItem(drive: char; UserSID: string; fileid: string): boolean; overload;
+class function TRecycleBinManager.RecyclerRemoveItem(drive: char; UserSID: string; fileid: string): boolean;
var
tmp: string;
begin
@@ -1944,12 +1961,12 @@
end;
end;
-function RecyclerRemoveItem(drive: char; fileid: string): boolean; overload;
+class function TRecycleBinManager.RecyclerRemoveItem(drive: char; fileid: string): boolean;
begin
result := RecyclerRemoveItem(drive, '', fileid);
end;
-function RecyclerRemoveItem(InfofileOrRecycleFolder: string; id: string): boolean; overload;
+class function TRecycleBinManager.RecyclerRemoveItem(InfofileOrRecycleFolder: string; id: string): boolean;
var
tmp: string;
begin
@@ -1966,7 +1983,7 @@
end;
end;
-procedure RecyclerGetAllRecyclerDrives(result: TStringList);
+class procedure TRecycleBinManager.RecyclerGetAllRecyclerDrives(result: TStringList);
var
Drive: char;
begin
@@ -1982,7 +1999,7 @@
////////////////////////////////////////////////////////////////////////////////
// http://www.dsdt.info/tipps/?id=176
-function RecyclerEmptyRecycleBin(flags: cardinal): boolean; overload;
+class function TRecycleBinManager.RecyclerEmptyRecycleBin(flags: cardinal): boolean;
type
TSHEmptyRecycleBin = function (Wnd: HWND;
pszRootPath: PChar;
@@ -2015,7 +2032,7 @@
end;
end;
-function RecyclerEmptyRecycleBin(sound, progress, confirmation: boolean): boolean; overload;
+class function TRecycleBinManager.RecyclerEmptyRecycleBin(sound, progress, confirmation: boolean): boolean;
const
SHERB_NOCONFIRMATION = $00000001;
SHERB_NOPROGRESSUI = $00000002;
@@ -2039,7 +2056,7 @@
// Template
// http://www.dsdt.info/tipps/?id=116
-function RecyclerAddFileOrFolder(FileOrFolder: string; confirmation: boolean): boolean; overload;
+class function TRecycleBinManager.RecyclerAddFileOrFolder(FileOrFolder: string; confirmation: boolean): boolean;
var
Operation: TSHFileOpStruct;
begin
@@ -2055,12 +2072,12 @@
Result := SHFileOperation(Operation) = 0;
end;
-function RecyclerAddFileOrFolder(FileOrFolder: string): boolean; overload;
+class function TRecycleBinManager.RecyclerAddFileOrFolder(FileOrFolder: string): boolean;
begin
result := RecyclerAddFileOrFolder(FileOrFolder, false);
end;
-function RecyclerConfirmationDialogEnabled: boolean;
+class function TRecycleBinManager.RecyclerConfirmationDialogEnabled: boolean;
var
gp: GPOLICYBOOL;
begin
@@ -2075,7 +2092,7 @@
end;
end;
-function RecyclerShellStateConfirmationDialogEnabled: boolean;
+class function TRecycleBinManager.RecyclerShellStateConfirmationDialogEnabled: boolean;
type
TSHGetSettings = procedure (var lpss: SHELLSTATE; dwMask: DWORD) stdcall;
const
@@ -2147,7 +2164,7 @@
if (RBHandle <> 0) then FreeLibrary(RBHandle);
end;
-procedure RecyclerConfirmationDialogSetEnabled(NewSetting: boolean);
+class procedure TRecycleBinManager.RecyclerConfirmationDialogSetEnabled(NewSetting: boolean);
type
TSHGetSetSettings = procedure (var lpss: SHELLSTATE; dwMask: DWORD; bSet: BOOL) stdcall;
const
@@ -2226,76 +2243,11 @@
if (RBHandle <> 0) then FreeLibrary(RBHandle);
end;
-function RecyclerGetCurrentIconString: string;
-begin
- if RecyclerIsEmpty then
- result := RecyclerGetEmptyIconString
- else
- result := RecyclerGetFullIconString;
-end;
-function RecyclerGetDefaultIconString: string;
+class function TRecycleBinManager.RecyclerGetName: string;
var
reg: TRegistry;
begin
- // Please note: The "default" icon is not always the icon of the
- // current recycle bin in its current state (full, empty)
- // At Windows 95b, the registry value actually did change every time the
- // recycle bin state did change, but at Windows 2000 I could not see any
- // update, even after reboot. So, the registry value is possible fixed as
- // default = empty on newer OS versions.
-
- reg := TRegistry.Create;
- try
- reg.RootKey := HKEY_CLASSES_ROOT;
- if reg.OpenKeyReadOnly('CLSID\'+RECYCLER_CLSID+'\DefaultIcon') then
- begin
- result := reg.ReadString('');
- reg.CloseKey;
- end;
- finally
- reg.Free;
- end;
-end;
-
-function RecyclerGetEmptyIconString: string;
-var
- reg: TRegistry;
-begin
- reg := TRegistry.Create;
- try
- reg.RootKey := HKEY_CLASSES_ROOT;
- if reg.OpenKeyReadOnly('CLSID\'+RECYCLER_CLSID+'\DefaultIcon') then
- begin
- result := reg.ReadString('Empty');
- reg.CloseKey;
- end;
- finally
- reg.Free;
- end;
-end;
-
-function RecyclerGetFullIconString: string;
-var
- reg: TRegistry;
-begin
- reg := TRegistry.Create;
- try
- reg.RootKey := HKEY_CLASSES_ROOT;
- if reg.OpenKeyReadOnly('CLSID\'+RECYCLER_CLSID+'\DefaultIcon') then
- begin
- result := reg.ReadString('Full');
- reg.CloseKey;
- end;
- finally
- reg.Free;
- end;
-end;
-
-function RecyclerGetName: string;
-var
- reg: TRegistry;
-begin
// Windows 95b:
// Change of CLSID\{645FF040-5081-101B-9F08-00AA002F954E} will change the desktop name of the recycle bin.
@@ -2324,7 +2276,7 @@
end;
end;
-function RecyclerGetInfoTip: string;
+class function TRecycleBinManager.RecyclerGetInfoTip: string;
var
reg: TRegistry;
begin
@@ -2345,7 +2297,7 @@
end;
end;
-function RecyclerGetIntroText: string;
+class function TRecycleBinManager.RecyclerGetIntroText: string;
var
reg: TRegistry;
begin
@@ -2366,7 +2318,7 @@
end;
end;
-function RecyclerEmptyEventGetName: string;
+class function TRecycleBinManager.RecyclerEmptyEventGetName: string;
var
reg: TRegistry;
begin
@@ -2383,17 +2335,17 @@
end;
end;
-function RecyclerEmptyEventGetCurrentSound: string;
+class function TRecycleBinManager.RecyclerEmptyEventGetCurrentSound: string;
begin
result := RecyclerEmptyEventGetSound('.Current');
end;
-function RecyclerEmptyEventGetDefaultSound: string;
+class function TRecycleBinManager.RecyclerEmptyEventGetDefaultSound: string;
begin
result := RecyclerEmptyEventGetSound('.Default');
end;
-procedure RecyclerEmptyEventGetSoundCategories(AStringList: TStringList);
+class procedure TRecycleBinManager.RecyclerEmptyEventGetSoundCategories(AStringList: TStringList);
var
reg: TRegistry;
begin
@@ -2410,7 +2362,7 @@
end;
end;
-function RecyclerEmptyEventGetSound(ACategory: string): string;
+class function TRecycleBinManager.RecyclerEmptyEventGetSound(ACategory: string): string;
var
reg: TRegistry;
resourcestring
@@ -2437,7 +2389,7 @@
end;
end;
-function RecyclerGlobalGetPercentUsage: integer;
+class function TRecycleBinManager.RecyclerGlobalGetPercentUsage: integer;
var
reg: TRegistry;
dump: string;
@@ -2479,7 +2431,7 @@
end;
end;
-function RecyclerSpecificGetPercentUsage(Drive: Char): integer;
+class function TRecycleBinManager.RecyclerSpecificGetPercentUsage(Drive: Char): integer;
var
reg: TRegistry;
dump: string;
@@ -2540,7 +2492,7 @@
end;
end;
-function RecyclerGetPercentUsageAutoDeterminate(Drive: Char): integer;
+class function TRecycleBinManager.RecyclerGetPercentUsageAutoDeterminate(Drive: Char): integer;
var
gpSetting: integer;
begin
@@ -2553,7 +2505,7 @@
result := RecyclerSpecificGetPercentUsage(Drive);
end;
-function RecyclerGlobalIsNukeOnDelete: boolean;
+class function TRecycleBinManager.RecyclerGlobalIsNukeOnDelete: boolean;
var
reg: TRegistry;
dump: string;
@@ -2597,7 +2549,7 @@
end;
end;
-function RecyclerSpecificIsNukeOnDelete(Drive: Char): boolean;
+class function TRecycleBinManager.RecyclerSpecificIsNukeOnDelete(Drive: Char): boolean;
var
reg: TRegistry;
dump: string;
@@ -2663,7 +2615,7 @@
end;
end;
-function RecyclerIsNukeOnDeleteAutoDeterminate(Drive: Char): boolean;
+class function TRecycleBinManager.RecyclerIsNukeOnDeleteAutoDeterminate(Drive: Char): boolean;
begin
if RecyclerGroupPolicyNoRecycleFiles = gpEnabled then
result := true
@@ -2673,7 +2625,7 @@
result := RecyclerSpecificIsNukeOnDelete(Drive);
end;
-function RecyclerHasGlobalSettings: boolean;
+class function TRecycleBinManager.RecyclerHasGlobalSettings: boolean;
var
reg: TRegistry;
dump: string;
@@ -2720,27 +2672,8 @@
end;
end;
-function RecyclerIsEmpty: boolean;
-var
- Drive: Char;
-begin
- result := true;
- for Drive := 'A' to 'Z' do
- begin
- if RecyclerIsPossible(Drive) and not RecyclerIsEmpty(Drive) then
- begin
- result := false;
- exit;
- end;
- end;
-end;
-function RecyclerIsEmpty(Drive: Char): boolean;
-begin
- result := RecyclerGetAPIInfo(Drive).i64NumItems = 0;
-end;
-
-function RecyclerGetNumItems: int64;
+class function TRecycleBinManager.RecyclerGetNumItems: int64;
var
Drive: Char;
begin
@@ -2754,12 +2687,12 @@
end;
end;
-function RecyclerGetNumItems(Drive: Char): int64;
+class function TRecycleBinManager.RecyclerGetNumItems(Drive: Char): int64;
begin
result := RecyclerGetAPIInfo(Drive).i64NumItems;
end;
-function RecyclerGetSize: int64;
+class function TRecycleBinManager.RecyclerGetSize: int64;
var
Drive: Char;
begin
@@ -2773,12 +2706,12 @@
end;
end;
-function RecyclerGetSize(Drive: Char): int64;
+class function TRecycleBinManager.RecyclerGetSize(Drive: Char): int64;
begin
result := RecyclerGetAPIInfo(Drive).i64Size;
end;
-function RecyclerGetAPIInfo(Drive: Char): TSHQueryRBInfo;
+class function TRecycleBinManager.RecyclerGetAPIInfo(Drive: Char): TSHQueryRBInfo;
begin
result := RecyclerGetAPIInfo(Drive + ':\');
end;
@@ -2790,7 +2723,7 @@
TSHQueryRecycleBin = function(pszRootPath: LPCTSTR;
var pSHQueryRBInfo: TSHQueryRBInfo): HRESULT; stdcall;
-function RecyclerGetAPIInfo(Path: String): TSHQueryRBInfo;
+class function TRecycleBinManager.RecyclerGetAPIInfo(Path: String): TSHQueryRBInfo;
var
PSHQueryRecycleBin: TSHQueryRecycleBin;
RBHandle: THandle;
@@ -2835,13 +2768,13 @@
if (RBHandle <> 0) then FreeLibrary(RBHandle);
end;
-function RecyclerGetCLSID: string;
+class function TRecycleBinManager.RecyclerGetCLSID: string;
begin
result := RECYCLER_CLSID;
end;
// Windows 95 without Internet Explorer 4 has no SHQueryRecycleBinA.
-function RecyclerQueryFunctionAvailable: boolean;
+class function TRecycleBinManager.RecyclerQueryFunctionAvailable: boolean;
var
RBHandle: THandle;
SHQueryRecycleBin: TSHQueryRecycleBin;
@@ -2865,7 +2798,7 @@
// TODO: In future also detect for other users
// TODO: Also make a setter (inkl. Message to Windows Explorer?)
-function RecyclerGroupPolicyNoRecycleFiles: GPOLICYBOOL;
+class function TRecycleBinManager.RecyclerGroupPolicyNoRecycleFiles: GPOLICYBOOL;
var
reg: TRegistry;
begin
@@ -2911,7 +2844,7 @@
// TODO: In future also detect for other users
// TODO: Also make a setter (inkl. Message to Windows Explorer?)
-function RecyclerGroupPolicyConfirmFileDelete: GPOLICYBOOL;
+class function TRecycleBinManager.RecyclerGroupPolicyConfirmFileDelete: GPOLICYBOOL;
var
reg: TRegistry;
begin
@@ -2957,7 +2890,7 @@
// TODO: In future also detect for other users
// TODO: Also make a setter (inkl. Message to Windows Explorer?)
-function RecyclerGroupPolicyRecycleBinSize: integer;
+class function TRecycleBinManager.RecyclerGroupPolicyRecycleBinSize: integer;
var
reg: TRegistry;
begin
@@ -3003,7 +2936,7 @@
end;
end;
-function RecyclerIsPossible(Drive: Char): boolean;
+class function TRecycleBinManager.RecyclerIsPossible(Drive: Char): boolean;
var
typ: Integer;
begin
@@ -3011,9 +2944,10 @@
result := typ = DRIVE_FIXED;
end;
-function RecyclerLibraryVersion: string;
+class function TRecycleBinManager.RecyclerLibraryVersion: string;
begin
result := 'ViaThinkSoft Recycle Bin Unit [05 JUL 2010]';
end;
end.
+
Index: Windows 95 Bit Bucket Reader/BitBucketReader.exe
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream