Subversion Repositories delphiutils

Rev

Blame | Last modification | View Log | RSS feed

  1. Index: alt header.txt
  2. ===================================================================
  3. --- alt header.txt      (revision 0)
  4. +++ alt header.txt      (revision 0)
  5. @@ -0,0 +1,74 @@
  6. +////////////////////////////////////////////////////////////////////////////////////
  7. +// RECYCLE-BIN-FUNCTIONS BY DANIEL MARSCHALL                                      //
  8. +// E-MAIL: info@daniel-marschall.de                                               //
  9. +// WEB:    www.daniel-marschall.de                                                //
  10. +////////////////////////////////////////////////////////////////////////////////////
  11. +// Revision: 05 JUL 2010                                                          //
  12. +// This unit is freeware, but please link to my website if you are using it!      //
  13. +////////////////////////////////////////////////////////////////////////////////////
  14. +// Successful tested with:                                                        //
  15. +// Windows 95b (without IE4 Shell Extensions)                                     //
  16. +// Windows 95b (with IE4 Shell Extensions)                                        //
  17. +// Windows 98-SE                                                                  //
  18. +// Windows XP-SP3                                                                 //
  19. +// Windows 2000-SP4                                                               //
  20. +// Windows 2003 Server EE SP1                                                     //
  21. +// Windows Vista                                                                  //
  22. +// Windows 7                                                                      //
  23. +////////////////////////////////////////////////////////////////////////////////////
  24. +//                                                                                //
  25. +//  Needs Delphi 4 or higher. If you are using Delphi 4 or 5, you can not use the //
  26. +//  RecyclerGetDateTime() functions, because the unit "DateUtils" is missing.     //
  27. +//  Warning! This is a platform unit.                                             //
  28. +//                                                                                //
  29. +//  To do! Can you help?                                                          //
  30. +//    - WideString-Support (input/output)                                         //
  31. +//    - GetLoginNameW: Really 255 maximum?                                        //
  32. +//    - Always do EOF before reading anything?                                    //
  33. +//    - Is it possible to identify a Vista-file that is not named $Ixxxxxx.ext?   //
  34. +//    - RecyclerGetInfofiles() check additionally for removable device?           //
  35. +//      RecyclerIsValid() is false.                                               //
  36. +//    - Make it possible to empty the recycle bin of one specific drive!          //
  37. +//                                                                                //
  38. +//  Unknown! Do you know the answer?                                              //
  39. +//    - How does Windows 9x/NT manage the daylight saving time (if it does)?      //
  40. +//    - How does Windows Vista react to a RECYCLER\ folder on a NTFS device?      //
  41. +//    - How does Windows Vista react to a RECYCLED\ folder on a FAT device?       //
  42. +//                                                                                //
  43. +//  Not analyzed yet! Please send me your trash folder contents for analyzing!    //
  44. +//    - Windows NT                                                                //
  45. +//    - Windows CE?                                                               //
  46. +//    - Windows 7                                                                 //
  47. +//                                                                                //
  48. +//  Thanks to all these who have helped me solving coding problems.               //
  49. +//  Thanks to SEBA for sending in the Windows Vista trash structure files.        //
  50. +//  Thanks to OMATA for testing the unit with Delphi 4.                           //
  51. +//  Thanks to DEITYSOU for making a bugfix of DriveExists()                       //
  52. +//                                                                                //
  53. +////////////////////////////////////////////////////////////////////////////////////
  54. +
  55. +(*
  56. +
  57. +== TODO LISTE ==
  58. +
  59. +Wichtig! Windows XP: InfoTip, IntroText und LocalizedString sind Resourcenangaben und müssen ausgelesen werden!
  60. +Testen: Wie reagiert Windows, wenn Bitbucket\C existiert, aber kein Wert 'Percent' hat? Mit der Standardeinstellung?
  61. +Bug: Windows 2000 bei bestehenden Windows 95 Partition: Recycler Filename ist dann Recycled und nicht Recycler!
  62. +bug? w95 recycled file hat immer selben löschzeitpunkt und größe? war die nicht verschieden?
  63. +beachtet? bei leerem papierkorb auf fat ist weder info noch info2 vorhanden?
  64. +testen: auch möglich, einen vista papierkorb offline öffnen?
  65. +Problem: bei win95(ohne ie4) und win2000 gleichzeitiger installation: es existiert info UND info2!!!
  66. +Implement SETTER functions to every kind of configuration thing. (percentage etc)
  67. +Registry CURRENT_USER: Funktionen auch für fremde Benutzer zur Verfügung stellen?
  68. +Es sollte möglich sein, dass ein Laufwerk mehr als 1 Recycler beinhaltet -- behandeln
  69. +
  70. +- Future -
  71. +
  72. +Demoapplikation: Dateien statt Text als Explorer-Like?
  73. +Einzelne Elemente oder alle wiederherstellen oder löschen
  74. +Konfiguration für Laufwerke ändern etc
  75. +IconString -> TIcon Convertion functions
  76. +platzreservierung in mb-angabe berechnen
  77. +I don't know if there exists any API function which checks the state at any internal way.
  78. +
  79. +*)
  80. Index: Kopie von RecyclerFunctions.pas
  81. ===================================================================
  82. --- Kopie von RecyclerFunctions.pas     (revision 0)
  83. +++ Kopie von RecyclerFunctions.pas     (revision 0)
  84. @@ -0,0 +1,2953 @@
  85. +// TODO: Also include BC++ Versions
  86. +{$IFNDEF BCB}
  87. +{$DEFINE DEL1UP}
  88. +{$IFNDEF VER80}
  89. +{$DEFINE DEL2UP}
  90. +{$IFNDEF VER90}
  91. +{$DEFINE DEL3UP}
  92. +{$IFNDEF VER100}
  93. +{$DEFINE DEL4UP}
  94. +{$IFNDEF VER120}
  95. +{$DEFINE DEL5UP}
  96. +{$IFNDEF VER130}
  97. +{$DEFINE DEL6UP}
  98. +{$IFNDEF VER140}
  99. +{$DEFINE DEL7UP}
  100. +{$ENDIF}
  101. +{$ENDIF}
  102. +{$ENDIF}
  103. +{$ENDIF}
  104. +{$ENDIF}
  105. +{$ENDIF}
  106. +{$ENDIF}
  107. +
  108. +{$IFDEF DEL7UP}
  109. +{$WARN UNSAFE_TYPE OFF}
  110. +{$WARN UNSAFE_CODE OFF}
  111. +{$WARN UNSAFE_CAST OFF}
  112. +{$ENDIF}
  113. +
  114. +{$IFDEF DEL6UP}
  115. +unit RecyclerFunctions platform;
  116. +{$ELSE}
  117. +unit RecyclerFunctions;
  118. +{$ENDIF}
  119. +
  120. +// Configuration
  121. +
  122. +// If enabled, all functions with parameter "InfofileOrRecycleFolder" will
  123. +// also accept files which are not the indexfile (then, a INFO2 or INFO file
  124. +// will be searched in this directory).
  125. +{.$DEFINE allow_all_filenames}
  126. +
  127. +interface
  128. +
  129. +uses
  130. +  Windows, SysUtils, Classes, {$IFDEF DEL6UP}DateUtils,{$ENDIF}
  131. +  ShellApi{$IFNDEF DEL6UP}, FileCtrl{$ENDIF}, Registry,
  132. +  Messages, BitOps;
  133. +
  134. +type
  135. +  EUnknownState = class(Exception);
  136. +  EEventCategoryNotDefined = class(Exception);
  137. +  EAPICallError = class(Exception);
  138. +
  139. +  PSHQueryRBInfo = ^TSHQueryRBInfo;
  140. +  TSHQueryRBInfo = packed record
  141. +    cbSize      : dword;
  142. +    i64Size     : int64;
  143. +    i64NumItems : int64;
  144. +  end;
  145. +
  146. +  GPOLICYBOOL = (gpUndefined, gpEnabled, gpDisabled);
  147. +
  148. +  // TODO: $Recycle.Bin at external harddisk with Vista??
  149. +
  150. +  TRecycleBinManager = class(TObject)
  151. +    class function RecyclerGetCurrentIconString: string;
  152. +    class function RecyclerGetDefaultIconString: string;
  153. +    class function RecyclerGetEmptyIconString: string;
  154. +    class function RecyclerGetFullIconString: string;
  155. +
  156. +    class function RecyclerIsEmpty: boolean; overload;
  157. +    class function RecyclerIsEmpty(Drive: Char): boolean; overload;
  158. +
  159. +    {$IFDEF DEL6UP}
  160. +    class function RecyclerGetDateTime(drive: char; fileid: string): tdatetime; overload;
  161. +    class function RecyclerGetDateTime(drive: char; UserSID: string; fileid: string): tdatetime; overload;
  162. +    class function RecyclerGetDateTime(InfofileOrRecycleFolder: string): tdatetime; overload;
  163. +    class function RecyclerGetDateTime(InfofileOrRecycleFolder: string; id: string): tdatetime; overload;
  164. +    {$ENDIF}
  165. +
  166. +    class function RecyclerGetSourceUnicode(drive: char; fileid: string): WideString; overload;
  167. +    class function RecyclerGetSourceUnicode(drive: char; UserSID: string; fileid: string): WideString; overload;
  168. +    class function RecyclerGetSourceUnicode(InfofileOrRecycleFolder: string): WideString; overload;
  169. +    class function RecyclerGetSourceUnicode(InfofileOrRecycleFolder: string; id: string): WideString; overload;
  170. +
  171. +    class function RecyclerGetSource(drive: char; fileid: string): string; overload;
  172. +    class function RecyclerGetSource(drive: char; UserSID: string; fileid: string): string; overload;
  173. +    class function RecyclerGetSource(InfofileOrRecycleFolder: string): string; overload;
  174. +    class function RecyclerGetSource(InfofileOrRecycleFolder: string; id: string): string; overload;
  175. +
  176. +    class procedure RecyclerListIndexes(drive: char; result: TStringList); overload;
  177. +    class procedure RecyclerListIndexes(drive: char; UserSID: string; result: TStringList); overload;
  178. +    class procedure RecyclerListIndexes(InfofileOrRecycleFolder: string; result: TStringList); overload;
  179. +
  180. +    class function RecyclerGetSourceDrive(drive: char; fileid: string): char; overload;
  181. +    class function RecyclerGetSourceDrive(drive: char; UserSID: string; fileid: string): char; overload;
  182. +    class function RecyclerGetSourceDrive(InfofileOrRecycleFolder: string): char; overload;
  183. +    class function RecyclerGetSourceDrive(InfofileOrRecycleFolder: string; id: string): char; overload;
  184. +
  185. +    class function RecyclerOriginalSize(drive: char; fileid: string): integer; overload;
  186. +    class function RecyclerOriginalSize(drive: char; UserSID: string; fileid: string): integer; overload;
  187. +    class function RecyclerOriginalSize(InfofileOrRecycleFolder: string): integer; overload;
  188. +    class function RecyclerOriginalSize(InfofileOrRecycleFolder: string; id: string): integer; overload;
  189. +
  190. +    class function RecyclerIsValid(drive: char): boolean; overload;
  191. +    class function RecyclerIsValid(drive: char; UserSID: string): boolean; overload;
  192. +    class function RecyclerIsValid(InfofileOrRecycleFolder: string): boolean; overload;
  193. +
  194. +    class function RecyclerCurrentFilename(drive: char; fileid: string): string; overload;
  195. +    class function RecyclerCurrentFilename(drive: char; UserSID: string; fileid: string): string; overload;
  196. +    class function RecyclerCurrentFilename(InfofileOrRecycleFolder: string): string; overload;
  197. +    class function RecyclerCurrentFilename(InfofileOrRecycleFolder: string; id: string): string; overload;
  198. +
  199. +    class function RecyclerGetPath(drive: char; UserSID: string; IncludeInfofile: boolean; fileid: string): string; overload;
  200. +    class function RecyclerGetPath(drive: char; UserSID: string; IncludeInfofile: boolean): string; overload;
  201. +    class function RecyclerGetPath(drive: char; IncludeInfofile: boolean): string; overload;
  202. +    class function RecyclerGetPath(drive: char; UserSID: string): string; overload;
  203. +    class function RecyclerGetPath(drive: char): string; overload;
  204. +
  205. +    class procedure RecyclerGetInfofiles(drive: char; UserSID: string; IncludeInfofile: boolean; fileid: string; result: TStringList); overload;
  206. +    class procedure RecyclerGetInfofiles(drive: char; UserSID: string; IncludeInfofile: boolean; result: TStringList); overload;
  207. +    class procedure RecyclerGetInfofiles(drive: char; IncludeInfofile: boolean; result: TStringList); overload;
  208. +    class procedure RecyclerGetInfofiles(drive: char; UserSID: string; result: TStringList); overload;
  209. +    class procedure RecyclerGetInfofiles(drive: char; result: TStringList); overload;
  210. +
  211. +    class function RecyclerCurrentFilenameAndPath(drive: char; UserSID: string; fileid: string): string; overload;
  212. +    class function RecyclerCurrentFilenameAndPath(drive: char; fileid: string): string; overload;
  213. +    class function RecyclerCurrentFilenameAndPath(InfofileOrRecycleFolder: string; id: string): string; overload;
  214. +
  215. +    class function RecyclerRemoveItem(drive: char; UserSID: string; fileid: string): boolean; overload;
  216. +    class function RecyclerRemoveItem(drive: char; fileid: string): boolean; overload;
  217. +    class function RecyclerRemoveItem(InfofileOrRecycleFolder: string; id: string): boolean; overload;
  218. +
  219. +    class procedure RecyclerGetAllRecyclerDrives(result: TStringList);
  220. +
  221. +    class function RecyclerEmptyRecycleBin(flags: cardinal): boolean; overload;
  222. +    class function RecyclerEmptyRecycleBin(sound, progress, confirmation: boolean): boolean; overload;
  223. +
  224. +    class function RecyclerAddFileOrFolder(FileOrFolder: string; confirmation: boolean): boolean; overload;
  225. +    class function RecyclerAddFileOrFolder(FileOrFolder: string): boolean; overload;
  226. +
  227. +    class function RecyclerConfirmationDialogEnabled: boolean;
  228. +    class function RecyclerShellStateConfirmationDialogEnabled: boolean;
  229. +    class procedure RecyclerConfirmationDialogSetEnabled(NewSetting: boolean);
  230. +
  231. +    class function RecyclerGetName: string;
  232. +    class function RecyclerGetInfoTip: string;
  233. +    class function RecyclerGetIntroText: string;
  234. +
  235. +    class function RecyclerEmptyEventGetName: string;
  236. +    class function RecyclerEmptyEventGetCurrentSound: string;
  237. +    class function RecyclerEmptyEventGetDefaultSound: string;
  238. +    class procedure RecyclerEmptyEventGetSoundCategories(AStringList: TStringList);
  239. +    class function RecyclerEmptyEventGetSound(ACategory: string): string;
  240. +
  241. +    class function RecyclerGlobalGetPercentUsage: integer;
  242. +    class function RecyclerSpecificGetPercentUsage(Drive: Char): integer;
  243. +    class function RecyclerGetPercentUsageAutoDeterminate(Drive: Char): integer;
  244. +
  245. +    class function RecyclerGlobalIsNukeOnDelete: boolean;
  246. +    class function RecyclerSpecificIsNukeOnDelete(Drive: Char): boolean;
  247. +    class function RecyclerIsNukeOnDeleteAutoDeterminate(Drive: Char): boolean;
  248. +
  249. +    class function RecyclerHasGlobalSettings: boolean;
  250. +
  251. +    class function RecyclerGetNumItems: int64; overload;
  252. +    class function RecyclerGetNumItems(Drive: Char): int64; overload;
  253. +
  254. +    class function RecyclerGetSize: int64; overload;
  255. +    class function RecyclerGetSize(Drive: Char): int64; overload;
  256. +
  257. +    class function RecyclerGetAPIInfo(Drive: Char): TSHQueryRBInfo; overload;
  258. +    class function RecyclerGetAPIInfo(Path: String): TSHQueryRBInfo; overload;
  259. +
  260. +    class function RecyclerGetCLSID: string;
  261. +
  262. +    // Diese Funktion ist false, wenn sie z.B. unter Windows 95 ohne Internet Explorer
  263. +    // 4.0 Shell Extension ausgeführt wird. Wenn abwärtskompatibler Code geschrieben
  264. +    // werden soll, sollte RecyclerQueryFunctionAvailable() verwendet werden, da
  265. +    // unter Windows 95 folgende Funktionalitäten NICHT vorhanden sind:
  266. +    // - RecyclerIsEmpty
  267. +    // - RecyclerGetNumItems
  268. +    // - RecyclerGetSize
  269. +    // - RecyclerGetAPIInfo
  270. +    class function RecyclerQueryFunctionAvailable: boolean;
  271. +
  272. +    class function RecyclerGroupPolicyNoRecycleFiles: GPOLICYBOOL;
  273. +    class function RecyclerGroupPolicyConfirmFileDelete: GPOLICYBOOL;
  274. +    class function RecyclerGroupPolicyRecycleBinSize: integer;
  275. +
  276. +    class function RecyclerIsPossible(Drive: Char): boolean;
  277. +
  278. +    class function RecyclerLibraryVersion: string;
  279. +  end;
  280. +
  281. +  function GPBoolToString(value: GPOLICYBOOL): String;
  282. +
  283. +const
  284. +  RECYCLER_CLSID = '{645FF040-5081-101B-9F08-00AA002F954E}';
  285. +
  286. +implementation
  287. +
  288. +type
  289. +  SHELLSTATE = record
  290. +    Flags1: DWORD;
  291. +(*
  292. +    BOOL fShowAllObjects : 1;
  293. +    BOOL fShowExtensions : 1;
  294. +    BOOL fNoConfirmRecycle : 1;
  295. +
  296. +    BOOL fShowSysFiles : 1;
  297. +    BOOL fShowCompColor : 1;
  298. +    BOOL fDoubleClickInWebView : 1;
  299. +    BOOL fDesktopHTML : 1;
  300. +    BOOL fWin95Classic : 1;
  301. +    BOOL fDontPrettyPath : 1;
  302. +    BOOL fShowAttribCol : 1; // No longer used, dead bit
  303. +    BOOL fMapNetDrvBtn : 1;
  304. +    BOOL fShowInfoTip : 1;
  305. +    BOOL fHideIcons : 1;
  306. +    BOOL fWebView : 1;
  307. +    BOOL fFilter : 1;
  308. +    BOOL fShowSuperHidden : 1;
  309. +    BOOL fNoNetCrawling : 1;
  310. +*)
  311. +    dwWin95Unused: DWORD; // Win95 only - no longer supported pszHiddenFileExts
  312. +    uWin95Unused: UINT; // Win95 only - no longer supported cbHiddenFileExts
  313. +
  314. +    // Note: Not a typo!  This is a persisted structure so we cannot use LPARAM
  315. +    lParamSort: Integer;
  316. +    iSortDirection: Integer;
  317. +
  318. +    version: UINT;
  319. +
  320. +    // new for win2k. need notUsed var to calc the right size of ie4 struct
  321. +    // FIELD_OFFSET does not work on bit fields
  322. +    uNotUsed: UINT; // feel free to rename and use
  323. +    Flags2: DWORD;
  324. +(*
  325. +    BOOL fSepProcess: 1;
  326. +    // new for Whistler.
  327. +    BOOL fStartPanelOn: 1;       //Indicates if the Whistler StartPanel mode is ON or OFF.
  328. +    BOOL fShowStartPage: 1;      //Indicates if the Whistler StartPage on desktop is ON or OFF.
  329. +    UINT fSpareFlags : 13;
  330. +*)
  331. +  end;
  332. +  LPSHELLSTATE = ^SHELLSTATE;
  333. +
  334. +const
  335. +  {$IFDEF MSWINDOWS}
  336. +    shell32  = 'shell32.dll';
  337. +    advapi32 = 'advapi32.dll';
  338. +  {$ENDIF}
  339. +  {$IFDEF LINUX}
  340. +    shell32  = 'libshell32.borland.so';
  341. +    advapi32 = 'libwine.borland.so';
  342. +  {$ENDIF}
  343. +
  344. +  // Masks for the shellstate
  345. +   SSF_SHOWALLOBJECTS  = $00000001;
  346. +  SSF_SHOWEXTENSIONS  = $00000002;
  347. +  SSF_HIDDENFILEEXTS  = $00000004;
  348. +  SSF_SERVERADMINUI   = $00000004;
  349. +  SSF_SHOWCOMPCOLOR   = $00000008;
  350. +  SSF_SORTCOLUMNS     = $00000010;
  351. +  SSF_SHOWSYSFILES    = $00000020;
  352. +  SSF_DOUBLECLICKINWEBVIEW = $00000080;
  353. +  SSF_SHOWATTRIBCOL   = $00000100;
  354. +  SSF_DESKTOPHTML     = $00000200;
  355. +  SSF_WIN95CLASSIC    = $00000400;
  356. +  SSF_DONTPRETTYPATH  = $00000800;
  357. +  SSF_SHOWINFOTIP     = $00002000;
  358. +  SSF_MAPNETDRVBUTTON = $00001000;
  359. +  SSF_NOCONFIRMRECYCLE = $00008000;
  360. +  SSF_HIDEICONS       = $00004000;
  361. +  SSF_FILTER          = $00010000;
  362. +  SSF_WEBVIEW         = $00020000;
  363. +  SSF_SHOWSUPERHIDDEN = $00040000;
  364. +  SSF_SEPPROCESS      = $00080000;
  365. +  SSF_NONETCRAWLING   = $00100000;
  366. +  SSF_STARTPANELON    = $00200000;
  367. +  SSF_SHOWSTARTPAGE   = $00400000;
  368. +
  369. +// **********************************************************
  370. +// COMPATIBILITY FUNCTIONS
  371. +// **********************************************************
  372. +
  373. +{$IFNDEF DEL5UP}
  374. +function IncludeTrailingBackslash(str: string): string;
  375. +begin
  376. +  if Copy(str, length(str), 1) = '\' then    // TODO? Gibt es PathDelim in Delphi 4?
  377. +    Result := str
  378. +  else
  379. +    Result := str + '\';
  380. +end;
  381. +{$ENDIF}
  382. +
  383. +// **********************************************************
  384. +// INTERNALLY USED FUNCTIONS
  385. +// **********************************************************
  386. +
  387. +resourcestring
  388. +  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!';
  389. +  LNG_API_CALL_ERROR = 'Error while calling the API. Additional information: "%s".';
  390. +  LNG_NOT_CALLABLE = '%s not callable';
  391. +  LNG_ERROR_CODE = '%s (Arguments: %s) returns error code %s';
  392. +
  393. +function _FileSize(FileName: string): int64;
  394. +var
  395. +  fs: TFileStream;
  396. +begin
  397. +  fs := TFileStream.Create(FileName, fmOpenRead);
  398. +  try
  399. +    result := fs.size;
  400. +  finally
  401. +    fs.free;
  402. +  end;
  403. +end;
  404. +
  405. +function _DriveNum(Drive: Char): Byte;
  406. +// a->0, ..., z->25
  407. +var
  408. +  tmp: string;
  409. +begin
  410. +  tmp := LowerCase(Drive);
  411. +  result := Ord(tmp[1])-Ord('a');
  412. +end;
  413. +
  414. +function _registryReadDump(AReg: TRegistry; AName: string): string;
  415. +const
  416. +  // Win2000 RegEdit has set the max input length of a REG_BINARY to $3FFF.
  417. +  // Probably its the longest possible binary string and not just a GUI limit.
  418. +  BufMax = $3FFF;
  419. +var
  420. +  buf: array[0..BufMax] of byte;
  421. +  i: integer;
  422. +  realsize: integer;
  423. +begin
  424. +  realsize := AReg.ReadBinaryData(AName, buf, SizeOf(buf));
  425. +
  426. +  for i := 0 to realsize-1 do
  427. +  begin
  428. +    result := result + chr(buf[i]);
  429. +  end;
  430. +end;
  431. +
  432. +function _GetStringFromDLL(filename: string; num: integer): string;
  433. +const
  434. +  // http://www.eggheadcafe.com/forumarchives/vcmfc/sep2005/post23917443.asp
  435. +  MAX_BUF = 4097; // OK?
  436. +var
  437. +  hLib: THandle;
  438. +  buf: array[0..MAX_BUF] of char;
  439. +begin
  440. +  hLib := LoadLibrary(PChar(filename));
  441. +  try
  442. +    LoadString(hLib, num, buf, sizeof(buf));
  443. +    result := buf;
  444. +  finally
  445. +    FreeLibrary(hLib);
  446. +  end;
  447. +end;
  448. +
  449. +// http://www.delphi-library.de/topic_Umgebungsvariable+in+einem+String+aufloesen_20516,0.html
  450. +function _ExpandEnvStr(const szInput: string): string;
  451. +const
  452. +  MAXSIZE = 32768; // laut PSDK sind 32k das Maximum
  453. +begin
  454. +  SetLength(Result,MAXSIZE);
  455. +  SetLength(Result,ExpandEnvironmentStrings(pchar(szInput),
  456. +    @Result[1],length(Result))-1); //-1 um abschließendes #0 zu verwerfen
  457. +end;
  458. +
  459. +// Beispiele
  460. +// Papierkorb                                                 -- Windows 95
  461. +// @C:\WINNT\system32\shell32.dll,-8964@1031,Papierkorb       -- Windows 2000
  462. +
  463. +function _DecodeReferenceString(s: string): string;
  464. +var
  465. +  dll, id, lang, cache: string;
  466. +  sl, sl2: tstringlist;
  467. +begin
  468. +  if Copy(s, 1, 1) = '@' then
  469. +  begin
  470. +    // Referenz auf eine DLL
  471. +    // @<dll>,-<id>[@<lang>][,<cache>]
  472. +
  473. +    sl := TStringList.Create;
  474. +    try
  475. +      // '@' am Anfang entfernen
  476. +      s := Copy(s, 2, length(s)-1);
  477. +
  478. +      // Nach ',' auftrennen
  479. +      // sl[0] --> dll
  480. +      // sl[1] --> -id@lang
  481. +      // sl[2] --> cache
  482. +      sl.CommaText := s;
  483. +
  484. +      if sl.Count > 2 then
  485. +      begin
  486. +        // Das Ergebnis ist bereits im Klartext vorhanden und muss nicht extrahiert werden
  487. +        // Ist bei Windows 2000 der Fall
  488. +        cache := sl[2];
  489. +        result := cache;
  490. +        exit;
  491. +      end;
  492. +
  493. +      if sl.Count > 1 then
  494. +      begin
  495. +        dll := sl[0];
  496. +
  497. +        sl2 := TStringList.Create;
  498. +        try
  499. +          // Nach '@' auftrennen
  500. +          // sl2[0] --> id
  501. +          // sl2[1] --> lang
  502. +          sl2.CommaText := StringReplace(sl[1], '@', ',', [rfReplaceAll]);
  503. +
  504. +          id := sl2[0];
  505. +
  506. +          if sl2.Count > 1 then
  507. +          begin
  508. +            // ToDo: In Zukunft beachten, sofern möglich
  509. +            lang := sl2[1];
  510. +          end;
  511. +
  512. +          // Umgebungsvariablen erkennen und Minuszeichen entfernen
  513. +          result := _GetStringFromDLL(_ExpandEnvStr(dll), -StrToInt(id));
  514. +        finally
  515. +          sl2.Free;
  516. +        end;
  517. +      end
  518. +      else
  519. +      begin
  520. +        // Zu wenige Informationen!
  521. +
  522. +        result := '';
  523. +      end;
  524. +    finally
  525. +      sl.Free;
  526. +    end;
  527. +  end
  528. +  else
  529. +  begin
  530. +    // Kein Hinweis auf eine Referenz
  531. +    result := s;
  532. +  end;
  533. +end;
  534. +
  535. +function _readInt8(const Stream: TStream): byte;
  536. +var
  537. +  I: integer;
  538. +begin
  539. +  i := 0;
  540. +  Stream.ReadBuffer(i, 1);
  541. +  Result := i;
  542. +end;
  543. +
  544. +function _readInt32(const Stream: TStream): Longword;
  545. +var
  546. +  I: integer;
  547. +begin
  548. +  i := 0;
  549. +  Stream.ReadBuffer(i, 4);
  550. +  Result := i;
  551. +end;
  552. +
  553. +function _readInt64(const Stream: TStream): int64;
  554. +var
  555. +  I: int64;
  556. +begin
  557. +  i := 0;
  558. +  Stream.ReadBuffer(i, 8);
  559. +  Result := i;
  560. +end;
  561. +
  562. +function _readChar(const Stream: TStream): char;
  563. +var
  564. +  C: Char;
  565. +begin
  566. +  C := #0;
  567. +  Stream.ReadBuffer(C, 1);
  568. +  Result := C;
  569. +end;
  570. +
  571. +function _readNullTerminatedString(const Stream: TStream): String;
  572. +var
  573. +  S: String;
  574. +  C: Char;
  575. +begin
  576. +  S := '';
  577. +  repeat
  578. +    Stream.ReadBuffer(C, 1);
  579. +    if (C <> #0) then
  580. +      S := S + C;
  581. +  until C = #0;
  582. +  Result := S;
  583. +end;
  584. +
  585. +// http://www.delphipraxis.net/post761928.html#761928
  586. +function _readNullTerminatedWideString(const Stream: TStream): WideString;
  587. +var
  588. +  S: WideString;
  589. +  WC: WideChar;
  590. +begin
  591. +  S := '';
  592. +  repeat
  593. +    Stream.ReadBuffer(WC, 2);
  594. +    if (WC <> #0) then
  595. +      S := S + WC;
  596. +  until WC = #0;
  597. +  Result := S;
  598. +end;
  599. +
  600. +// http://www.delphipraxis.net/post340194.html#340194
  601. +function _nowUTC: TDateTime;
  602. +var
  603. +  SystemTime: TSystemTime;
  604. +begin
  605. +  GetSystemTime(SystemTime);
  606. +  with SystemTime do
  607. +  begin
  608. +    Result := EncodeDate(wYear, wMonth, wDay) +
  609. +              EncodeTime(wHour, wMinute, wSecond, wMilliseconds);
  610. +  end;
  611. +end;
  612. +
  613. +{$IFDEF DEL6UP}
  614. +function _getGMTDifference(): extended;
  615. +begin
  616. +  result := - (datetimetounix(_nowUTC())-datetimetounix(Now())) / 3600;
  617. +end;
  618. +
  619. +function _fileTimeToDateTime(FileTime: int64): TDateTime;
  620. +begin
  621. +  // http://www.e-fense.com/helix/Docs/Recycler_Bin_Record_Reconstruction.pdf
  622. +  // UnixTime = 0.0000001 * NTTime + 11644473600
  623. +  // This is wrong! The correct formula is:
  624. +  // UnixTime = 0.0000001 * NTTime - 11644473600 + c * 3600
  625. +  // c = GMT-Difference (MEZ = 1) inclusive daylight saving time (+3600 seconds)
  626. +  result := unixtodatetime(FileTime div 10000000 - 11644473600 + round(_getGMTDifference() * 3600));
  627. +end;
  628. +{$ENDIF}
  629. +
  630. +// http://www.delphipraxis.net/post471470.html
  631. +function _getAccountSid(const Server, User: WideString; var Sid: PSID): DWORD;
  632. +var
  633. +  dwDomainSize, dwSidSize: DWord;
  634. +  R: LongBool;
  635. +  wDomain: WideString;
  636. +  Use: DWord;
  637. +begin
  638. +  Result := 0;
  639. +  SetLastError(0);
  640. +  dwSidSize := 0;
  641. +  dwDomainSize := 0;
  642. +  R := LookupAccountNameW(PWideChar(Server), PWideChar(User), nil, dwSidSize,
  643. +       nil, dwDomainSize, Use);
  644. +  if (not R) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then
  645. +  begin
  646. +    SetLength(wDomain, dwDomainSize);
  647. +    Sid := GetMemory(dwSidSize);
  648. +    R := LookupAccountNameW(PWideChar(Server), PWideChar(User), Sid,
  649. +         dwSidSize, PWideChar(wDomain), dwDomainSize, Use);
  650. +    if not R then
  651. +    begin
  652. +      FreeMemory(Sid);
  653. +      Sid := nil;
  654. +    end;
  655. +  end
  656. +  else
  657. +    Result := GetLastError;
  658. +end;
  659. +
  660. +// Template:
  661. +// http://www.latiumsoftware.com/en/pascal/0014.php
  662. +function _getLoginNameW: widestring;
  663. +var
  664. +  Buffer: array[0..255] of widechar;
  665. +  Size: dword;
  666. +begin
  667. +  Size := 256;
  668. +  if GetUserNameW(Buffer, Size) then
  669. +    Result := Buffer
  670. +  else
  671. +    Result := 'User';
  672. +end;
  673. +
  674. +function _Dyn_ConvertSidToStringSidA(SID: PSID; var strSID: LPSTR): boolean;
  675. +type
  676. +  DllReg = function(SID: PSID; var StringSid: LPSTR): Boolean; stdcall;
  677. +var
  678. +  hDll: THandle;
  679. +  dr: DllReg;
  680. +begin
  681. +  result := false;
  682. +  hDll := LoadLibrary(advapi32);
  683. +  if hDll <> 0 then
  684. +  begin
  685. +    @dr := GetProcAddress(hDll, 'ConvertSidToStringSidA');
  686. +    if assigned(dr) then
  687. +    begin
  688. +      result := dr(SID, strSID);
  689. +    end;
  690. +  end;
  691. +end;
  692. +
  693. +// http://www.delphipraxis.net/post471470.html
  694. +// Changed
  695. +function _getMySID(): string;
  696. +var
  697. +  SID: PSID;
  698. +  strSID: PAnsiChar;
  699. +  s: String;
  700. +  err: DWORD;
  701. +begin
  702. +  SID := nil;
  703. +
  704. +  err := _getAccountSid('', _getLoginNameW(), SID);
  705. +
  706. +  if err = 0 then
  707. +  begin
  708. +    if _Dyn_ConvertSidToStringSidA(SID, strSID) then
  709. +      s := string(strSID)
  710. +    else
  711. +      s := SysErrorMessage(err);
  712. +  end
  713. +  else
  714. +    s := SysErrorMessage(err);
  715. +
  716. +  result := s;
  717. +end;
  718. +
  719. +// Originalcode aus http://www.delphipraxis.net/post2933.html
  720. +function _DriveExists(DriveByte: Byte): Boolean; overload;
  721. +begin
  722. +  Result := GetLogicalDrives and (1 shl DriveByte) <> 0;
  723. +end;
  724. +
  725. +function _driveExists(Drive: Char): Boolean; overload;
  726. +var
  727. +  DriveByte: Byte;
  728. +  tmp: string;
  729. +begin
  730. +  // Make drive letter upper case (for older Delphi versions)
  731. +  tmp := UpperCase(Drive);
  732. +  Drive := tmp[1];
  733. +
  734. +  DriveByte := Ord(Drive) - Ord('A');
  735. +  Result := _DriveExists(DriveByte);
  736. +end;
  737. +
  738. +function _isFAT(drive: char): boolean;
  739. +var
  740. +  Dummy2: DWORD;
  741. +  Dummy3: DWORD;
  742. +  FileSystem: array[0..MAX_PATH] of char;
  743. +  VolumeName: array[0..MAX_PATH] of char;
  744. +  s: string;
  745. +begin
  746. +  result := false;
  747. +  if _driveExists(drive) then
  748. +  begin
  749. +    s := drive + DriveDelim + PathDelim; // ohne die Auslagerung in einen String kommt es zu einer AV in ntdll
  750. +    GetVolumeInformation(PChar(s), VolumeName,
  751. +      SizeOf(VolumeName), nil, Dummy2, Dummy3, FileSystem, SizeOf(FileSystem));
  752. +    result := uppercase(copy(FileSystem, 0, 3)) = 'FAT';
  753. +  end;
  754. +end;
  755. +
  756. +// **********************************************************
  757. +// VISTA AND WINDOWS 7 FUNCTIONS, INTERNAL USED
  758. +// **********************************************************
  759. +
  760. +const
  761. +  vista_valid_index_size = $220; // 544
  762. +
  763. +function _isFileVistaRealfile(filename: string): boolean;
  764. +begin
  765. +  result := uppercase(copy(extractfilename(filename), 0, 2)) = '$R';
  766. +end;
  767. +
  768. +function _isFileVistaIndexfile(filename: string): boolean;
  769. +begin
  770. +  result := uppercase(copy(extractfilename(filename), 0, 2)) = '$I';
  771. +end;
  772. +
  773. +function _isFileVistaNamed(filename: string): boolean;
  774. +begin
  775. +  result := _isFileVistaIndexfile(filename) or
  776. +            _isFileVistaRealfile(filename);
  777. +end;
  778. +
  779. +function _VistaChangeRealfileToIndexfile(realfile: string): string;
  780. +begin
  781. +  if _isFileVistaRealfile(realfile) then
  782. +  begin
  783. +    result := extractfilepath(realfile)+'$I'+
  784. +      copy(extractfilename(realfile), 3, length(extractfilename(realfile))-2);
  785. +  end
  786. +  else
  787. +    result := realfile; // ignore, even if it is not a vista recycle-file
  788. +end;
  789. +
  790. +function _VistaChangeIndexfileToRealfile(indexfile: string): string;
  791. +begin
  792. +  if _isFileVistaIndexfile(indexfile) then
  793. +  begin
  794. +    result := extractfilepath(indexfile)+'$R'+
  795. +      copy(extractfilename(indexfile), 3, length(extractfilename(indexfile))-2);
  796. +  end
  797. +  else
  798. +    result := indexfile; // ignore, even if it is not a vista recycle-file
  799. +end;
  800. +
  801. +procedure _VistaListIndexes(recyclerpath: string; result: TStringList);
  802. +var
  803. +  sr: TSearchRec;
  804. +  r: Integer;
  805. +  tmp: string;
  806. +begin
  807. +  tmp := recyclerpath;
  808. +  tmp := IncludeTrailingBackslash(tmp);
  809. +
  810. +  if not directoryexists(tmp) then exit;
  811. +
  812. +  r := FindFirst(tmp+PathDelim + '$I*', faAnyFile, sr);
  813. +  while r = 0 do
  814. +  begin
  815. +    if (sr.Name <> '.') and (sr.Name <> '..') then
  816. +    begin
  817. +      if sr.Size = vista_valid_index_size then
  818. +      begin
  819. +        result.Add(copy(sr.name, 3, length(sr.name)-2));
  820. +      end;
  821. +    end;
  822. +    r := FindNext(sr);
  823. +  end;
  824. +
  825. +  FindClose(sr);
  826. +end;
  827. +
  828. +function _VistaCurrentFilename(infofilename: string): string;
  829. +begin
  830. +  result := extractfilename(infofilename);
  831. +
  832. +  if _isFileVistaRealfile(result) then
  833. +  begin
  834. +    exit;
  835. +  end;
  836. +
  837. +  if _isFileVistaIndexfile(result) then
  838. +  begin
  839. +    result := _VistaChangeIndexfileToRealfile(result);
  840. +    exit;
  841. +  end;
  842. +
  843. +  result := copy(result, 3, length(result)-2);
  844. +  result := '$R'+result;
  845. +end;
  846. +
  847. +function _VistaGetSourceDrive(infofile: string): char;
  848. +var
  849. +  fs: TFileStream;
  850. +  tmp: string;
  851. +const
  852. +  drive_vista_position = $18;
  853. +begin
  854. +  result := #0;
  855. +
  856. +  tmp := infofile;
  857. +  tmp := _VistaChangeRealfileToIndexfile(tmp);
  858. +  if not fileexists(tmp) then exit;
  859. +
  860. +  fs := TFileStream.Create(tmp, fmOpenRead);
  861. +  try
  862. +    fs.seek(drive_vista_position, soFromBeginning);
  863. +    result := _readChar(fs);
  864. +  finally
  865. +    fs.free;
  866. +  end;
  867. +end;
  868. +
  869. +{$IFDEF DEL6UP}
  870. +function _VistaGetDateTime(infofile: string): TDateTime;
  871. +var
  872. +  fs: TFileStream;
  873. +  tmp: string;
  874. +const
  875. +  timestamp_vista_position = $10;
  876. +begin
  877. +  result := EncodeDateTime(1601, 1, 1, 0, 0, 0, 0);
  878. +
  879. +  tmp := infofile;
  880. +  tmp := _VistaChangeRealfileToIndexfile(tmp);
  881. +  if not fileexists(tmp) then exit;
  882. +
  883. +  fs := TFileStream.Create(tmp, fmOpenRead);
  884. +  try
  885. +    fs.seek(timestamp_vista_position, soFromBeginning);
  886. +    result := _fileTimeToDateTime(_readInt64(fs));
  887. +  finally
  888. +    fs.free;
  889. +  end;
  890. +end;
  891. +{$ENDIF}
  892. +
  893. +function _VistaGetSourceUnicode(infofile: string): string;
  894. +var
  895. +  fs: TFileStream;
  896. +  tmp: string;
  897. +const
  898. +  unicode_vista_position = $18;
  899. +begin
  900. +  result := '';
  901. +
  902. +  tmp := infofile;
  903. +  tmp := _VistaChangeRealfileToIndexfile(tmp);
  904. +  if not fileexists(tmp) then exit;
  905. +
  906. +  fs := TFileStream.Create(tmp, fmOpenRead);
  907. +  try
  908. +    fs.seek(unicode_vista_position, soFromBeginning);
  909. +    result := _readNullTerminatedWideString(fs);
  910. +  finally
  911. +    fs.free;
  912. +  end;
  913. +end;
  914. +
  915. +function _VistaOriginalSize(infofile: string): integer;
  916. +var
  917. +  fs: TFileStream;
  918. +  tmp: string;
  919. +const
  920. +  size_vista_position = $8;
  921. +begin
  922. +  result := -1;
  923. +
  924. +  tmp := infofile;
  925. +  tmp := _VistaChangeRealfileToIndexfile(tmp);
  926. +  if not fileexists(tmp) then exit;
  927. +
  928. +  fs := TFileStream.Create(tmp, fmOpenRead);
  929. +  try
  930. +    fs.seek(size_vista_position, soFromBeginning);
  931. +    result := _readInt32(fs);
  932. +  finally
  933. +    fs.free;
  934. +  end;
  935. +end;
  936. +
  937. +function _checkInfo1or2File(filename: string): boolean;
  938. +var
  939. +  fs: TStream;
  940. +  record_length: integer;
  941. +const
  942. +  length_position = $C;
  943. +  empty_size = 20;
  944. +begin
  945. +  fs := TFileStream.Create(filename, fmOpenRead);
  946. +  try
  947. +    fs.seek(length_position, soFromBeginning);
  948. +    record_length := _readInt32(fs);
  949. +
  950. +    // Check the file length
  951. +    if record_length = 0 then
  952. +      result := false
  953. +    else
  954. +      result := (fs.size - empty_size) mod record_length = 0;
  955. +  finally
  956. +    fs.free;
  957. +  end;
  958. +end;
  959. +
  960. +function _VistaIsValid(infofile: string): boolean;
  961. +var
  962. +  tmp: string;
  963. +begin
  964. +  result := false;
  965. +
  966. +  tmp := infofile;
  967. +  tmp := _VistaChangeRealfileToIndexfile(tmp);
  968. +  if not fileexists(tmp) then exit;
  969. +
  970. +  // Check the file length
  971. +  result := _FileSize(tmp) = vista_valid_index_size;
  972. +end;
  973. +
  974. +// **********************************************************
  975. +// PUBLIC FUNCTIONS
  976. +// **********************************************************
  977. +
  978. +{$IFDEF DEL6UP}
  979. +
  980. +class function TRecycleBinManager.RecyclerGetDateTime(InfofileOrRecycleFolder: string): tdatetime;
  981. +begin
  982. +  result := RecyclerGetDateTime(InfofileOrRecycleFolder, '');
  983. +end;
  984. +
  985. +class function TRecycleBinManager.RecyclerGetDateTime(drive: char; fileid: string): tdatetime;
  986. +begin
  987. +  result := RecyclerGetDateTime(drive, '', fileid);
  988. +end;
  989. +
  990. +class function TRecycleBinManager.RecyclerGetDateTime(drive: char; UserSID: string; fileid: string): tdatetime;
  991. +var
  992. +  infofile: string;
  993. +begin
  994. +  infofile := RecyclerGetPath(drive, UserSID, true, fileid);
  995. +  result := RecyclerGetDateTime(infofile, fileid);
  996. +end;
  997. +
  998. +class function TRecycleBinManager.RecyclerGetDateTime(InfofileOrRecycleFolder: string; id: string): tdatetime;
  999. +var
  1000. +  fs: TFileStream;
  1001. +  i, record_length: integer;
  1002. +  tmp: string;
  1003. +const
  1004. +  length_position = $C;
  1005. +  unique_index_position = $118;
  1006. +  timestamp_position = $120;
  1007. +begin
  1008. +  // FILETIME does start at 01.01.1601 00:00:00 (GMT)
  1009. +  result := EncodeDateTime(1601, 1, 1, 0, 0, 0, 0);
  1010. +
  1011. +  tmp := InfofileOrRecycleFolder;
  1012. +
  1013. +  if _isFileVistaNamed(tmp) then
  1014. +  begin
  1015. +    result := _VistaGetDateTime(tmp);
  1016. +    exit;
  1017. +  end;
  1018. +
  1019. +  {$IFDEF allow_all_filenames}
  1020. +  if not RecyclerIsValid(tmp) and fileexists(tmp) then
  1021. +  begin
  1022. +    if fileexists(extractfilepath(tmp)+'INFO2') then
  1023. +      tmp := extractfilepath(tmp)+'INFO2'
  1024. +    else if fileexists(extractfilepath(tmp)+'INFO') then
  1025. +      tmp := extractfilepath(tmp)+'INFO';
  1026. +  end;
  1027. +  {$ENDIF}
  1028. +
  1029. +  if directoryexists(tmp) then
  1030. +  begin
  1031. +    tmp := IncludeTrailingBackslash(tmp);
  1032. +
  1033. +    if fileexists(tmp+'$I'+id) then
  1034. +    begin
  1035. +      result := _VistaGetDateTime(tmp+'$I'+id);
  1036. +      exit;
  1037. +    end
  1038. +    else if fileexists(tmp+'INFO2') then tmp := tmp+'INFO2'
  1039. +    else if fileexists(tmp+'INFO') then  tmp := tmp+'INFO';
  1040. +  end;
  1041. +
  1042. +  if not fileexists(tmp) then exit;
  1043. +  if not RecyclerIsValid(tmp) then exit;
  1044. +
  1045. +  fs := TFileStream.Create(tmp, fmOpenRead);
  1046. +  try
  1047. +    fs.seek(length_position, soFromBeginning);
  1048. +    record_length := _readInt32(fs);
  1049. +
  1050. +    i := -1;
  1051. +    repeat
  1052. +      inc(i);
  1053. +      if unique_index_position+i*record_length > fs.size then break;
  1054. +      fs.seek(unique_index_position+i*record_length, soFromBeginning);
  1055. +      if inttostr(_readInt32(fs)) = id then
  1056. +      begin
  1057. +        fs.seek(timestamp_position+i*record_length, soFromBeginning);
  1058. +        result := _fileTimeToDateTime(_readInt64(fs));
  1059. +        break;
  1060. +      end;
  1061. +      until false;
  1062. +  finally
  1063. +    fs.free;
  1064. +  end;
  1065. +end;
  1066. +
  1067. +{$ENDIF}
  1068. +
  1069. +////////////////////////////////////////////////////////////////////////////////
  1070. +
  1071. +{ TRecycleBinManager }
  1072. +
  1073. +class function TRecycleBinManager.RecyclerGetCurrentIconString: string;
  1074. +begin
  1075. +  if TRecycleBinManager.RecyclerIsEmpty then
  1076. +    result := RecyclerGetEmptyIconString
  1077. +  else
  1078. +    result := RecyclerGetFullIconString;
  1079. +end;
  1080. +
  1081. +class function TRecycleBinManager.RecyclerGetDefaultIconString: string;
  1082. +var
  1083. +  reg: TRegistry;
  1084. +begin
  1085. +  // Please note: The "default" icon is not always the icon of the
  1086. +  // current recycle bin in its current state (full, empty)
  1087. +  // At Windows 95b, the registry value actually did change every time the
  1088. +  // recycle bin state did change, but at Windows 2000 I could not see any
  1089. +  // update, even after reboot. So, the registry value is possible fixed as
  1090. +  // default = empty on newer OS versions.
  1091. +
  1092. +  reg := TRegistry.Create;
  1093. +  try
  1094. +    reg.RootKey := HKEY_CLASSES_ROOT;
  1095. +    if reg.OpenKeyReadOnly('CLSID\'+RECYCLER_CLSID+'\DefaultIcon') then
  1096. +    begin
  1097. +      result := reg.ReadString('');
  1098. +      reg.CloseKey;
  1099. +    end;
  1100. +  finally
  1101. +    reg.Free;
  1102. +  end;
  1103. +end;
  1104. +
  1105. +class function TRecycleBinManager.RecyclerGetEmptyIconString: string;
  1106. +var
  1107. +  reg: TRegistry;
  1108. +begin
  1109. +  reg := TRegistry.Create;
  1110. +  try
  1111. +    reg.RootKey := HKEY_CLASSES_ROOT;
  1112. +    if reg.OpenKeyReadOnly('CLSID\'+RECYCLER_CLSID+'\DefaultIcon') then
  1113. +    begin
  1114. +      result := reg.ReadString('Empty');
  1115. +      reg.CloseKey;
  1116. +    end;
  1117. +  finally
  1118. +    reg.Free;
  1119. +  end;
  1120. +end;
  1121. +
  1122. +class function TRecycleBinManager.RecyclerGetFullIconString: string;
  1123. +var
  1124. +  reg: TRegistry;
  1125. +begin
  1126. +  reg := TRegistry.Create;
  1127. +  try
  1128. +    reg.RootKey := HKEY_CLASSES_ROOT;
  1129. +    if reg.OpenKeyReadOnly('CLSID\'+RECYCLER_CLSID+'\DefaultIcon') then
  1130. +    begin
  1131. +      result := reg.ReadString('Full');
  1132. +      reg.CloseKey;
  1133. +    end;
  1134. +  finally
  1135. +    reg.Free;
  1136. +  end;
  1137. +end;
  1138. +
  1139. +class function TRecycleBinManager.RecyclerIsEmpty: boolean;
  1140. +var
  1141. +  Drive: Char;
  1142. +begin
  1143. +  result := true;
  1144. +  for Drive := 'A' to 'Z' do
  1145. +  begin
  1146. +    if RecyclerIsPossible(Drive) and not RecyclerIsEmpty(Drive) then
  1147. +    begin
  1148. +      result := false;
  1149. +      exit;
  1150. +    end;
  1151. +  end;
  1152. +end;
  1153. +
  1154. +class function TRecycleBinManager.RecyclerIsEmpty(Drive: Char): boolean;
  1155. +begin
  1156. +  result := RecyclerGetAPIInfo(Drive).i64NumItems = 0;
  1157. +end;
  1158. +
  1159. +class function TRecycleBinManager.RecyclerGetSourceUnicode(InfofileOrRecycleFolder: string): WideString;
  1160. +begin
  1161. +  result := RecyclerGetSourceUnicode(InfofileOrRecycleFolder, '');
  1162. +end;
  1163. +
  1164. +class function TRecycleBinManager.RecyclerGetSourceUnicode(drive: char; fileid: string): WideString;
  1165. +begin
  1166. +  result := RecyclerGetSourceUnicode(drive, '', fileid);
  1167. +end;
  1168. +
  1169. +class function TRecycleBinManager.RecyclerGetSourceUnicode(drive: char; UserSID: string; fileid: string): WideString;
  1170. +var
  1171. +  infofile: string;
  1172. +begin
  1173. +  if Win32Platform = VER_PLATFORM_WIN32_NT then
  1174. +  begin
  1175. +    infofile := RecyclerGetPath(drive, UserSID, true, fileid);
  1176. +    result := RecyclerGetSourceUnicode(infofile, fileid);
  1177. +  end
  1178. +  else
  1179. +  begin
  1180. +    // Windows 9x does not support unicode
  1181. +    result := RecyclerGetSource(drive, UserSID, fileid);
  1182. +  end;
  1183. +end;
  1184. +
  1185. +class function TRecycleBinManager.RecyclerGetSourceUnicode(InfofileOrRecycleFolder: string; id: string): WideString;
  1186. +var
  1187. +  fs: TFileStream;
  1188. +  i, record_length: integer;
  1189. +  tmp: string;
  1190. +const
  1191. +  length_position = $C;
  1192. +  unique_index_position = $118;
  1193. +  unicode_source_position = $12C;
  1194. +begin
  1195. +  result := '';
  1196. +
  1197. +  tmp := InfofileOrRecycleFolder;
  1198. +
  1199. +  if _isFileVistaNamed(tmp) then
  1200. +  begin
  1201. +    // Vista only gives unicode names
  1202. +    result := _VistaGetSourceUnicode(tmp);
  1203. +    exit;
  1204. +  end;
  1205. +
  1206. +  {$IFDEF allow_all_filenames}
  1207. +  if not RecyclerIsValid(tmp) and fileexists(tmp) then
  1208. +  begin
  1209. +    if fileexists(extractfilepath(tmp)+'INFO2') then
  1210. +      tmp := extractfilepath(tmp)+'INFO2'
  1211. +    else if fileexists(extractfilepath(tmp)+'INFO') then
  1212. +      tmp := extractfilepath(tmp)+'INFO';
  1213. +  end;
  1214. +  {$ENDIF}
  1215. +
  1216. +  if directoryexists(tmp) then
  1217. +  begin
  1218. +    tmp := IncludeTrailingBackslash(tmp);
  1219. +
  1220. +    if fileexists(tmp+'$I'+id) then
  1221. +    begin
  1222. +      // Vista only gives unicode names
  1223. +      result := _VistaGetSourceUnicode(tmp+'$I'+id);
  1224. +      exit;
  1225. +    end
  1226. +    else if fileexists(tmp+'INFO2') then tmp := tmp+'INFO2'
  1227. +    else if fileexists(tmp+'INFO') then  tmp := tmp+'INFO';
  1228. +  end;
  1229. +
  1230. +  if not fileexists(tmp) then exit;
  1231. +  if not RecyclerIsValid(tmp) then exit;
  1232. +
  1233. +  fs := TFileStream.Create(tmp, fmOpenRead);
  1234. +  try
  1235. +    fs.seek(length_position, soFromBeginning);
  1236. +    record_length := _readInt32(fs);
  1237. +
  1238. +    if record_length <> $118 then
  1239. +    begin
  1240. +      // Windows NT
  1241. +      i := -1;
  1242. +      repeat
  1243. +        inc(i);
  1244. +        if unique_index_position+i*record_length > fs.size then break;
  1245. +        fs.seek(unique_index_position+i*record_length, soFromBeginning);
  1246. +        if inttostr(_readInt32(fs)) = id then
  1247. +        begin
  1248. +          fs.seek(unicode_source_position+i*record_length, soFromBeginning);
  1249. +          result := _readNullTerminatedWideString(fs);
  1250. +          break;
  1251. +        end;
  1252. +      until false;
  1253. +    end;
  1254. +  finally
  1255. +    fs.free;
  1256. +  end;
  1257. +
  1258. +  if record_length = $118 then
  1259. +  begin
  1260. +    // Windows 9x has no unicode support
  1261. +    result := RecyclerGetSource(tmp, id);
  1262. +  end;
  1263. +end;
  1264. +
  1265. +////////////////////////////////////////////////////////////////////////////////
  1266. +
  1267. +class function TRecycleBinManager.RecyclerGetSource(InfofileOrRecycleFolder: string): string;
  1268. +begin
  1269. +  result := RecyclerGetSource(InfofileOrRecycleFolder, '');
  1270. +end;
  1271. +
  1272. +class function TRecycleBinManager.RecyclerGetSource(drive: char; fileid: string): string;
  1273. +begin
  1274. +  result := RecyclerGetSource(drive, '', fileid);
  1275. +end;
  1276. +
  1277. +class function TRecycleBinManager.RecyclerGetSource(drive: char; UserSID: string; fileid: string): string;
  1278. +var
  1279. +  infofile: string;
  1280. +begin
  1281. +  infofile := RecyclerGetPath(drive, UserSID, true, fileid);
  1282. +  result := RecyclerGetSource(infofile, fileid);
  1283. +end;
  1284. +
  1285. +class function TRecycleBinManager.RecyclerGetSource(InfofileOrRecycleFolder: string; id: string): string;
  1286. +var
  1287. +  fs: TFileStream;
  1288. +  i, record_length: integer;
  1289. +  tmp: string;
  1290. +  alternativ: string;
  1291. +const
  1292. +  length_position = $C;
  1293. +  unique_index_position = $118;
  1294. +  source_position = $14;
  1295. +begin
  1296. +  result := '';
  1297. +
  1298. +  tmp := InfofileOrRecycleFolder;
  1299. +
  1300. +  if _isFileVistaNamed(tmp) then
  1301. +  begin
  1302. +    // Vista only gives unicode names
  1303. +    result := _VistaGetSourceUnicode(tmp);
  1304. +    exit;
  1305. +  end;
  1306. +
  1307. +  {$IFDEF allow_all_filenames}
  1308. +  if not RecyclerIsValid(tmp) and fileexists(tmp) then
  1309. +  begin
  1310. +    if fileexists(extractfilepath(tmp)+'INFO2') then
  1311. +      tmp := extractfilepath(tmp)+'INFO2'
  1312. +    else if fileexists(extractfilepath(tmp)+'INFO') then
  1313. +      tmp := extractfilepath(tmp)+'INFO';
  1314. +  end;
  1315. +  {$ENDIF}
  1316. +
  1317. +  if directoryexists(tmp) then
  1318. +  begin
  1319. +    tmp := IncludeTrailingBackslash(tmp);
  1320. +
  1321. +    if fileexists(tmp+'$I'+id) then
  1322. +    begin
  1323. +      // Vista only gives unicode names
  1324. +      result := _VistaGetSourceUnicode(tmp+'$I'+id);
  1325. +      exit;
  1326. +    end
  1327. +    else if fileexists(tmp+'INFO2') then tmp := tmp+'INFO2'
  1328. +    else if fileexists(tmp+'INFO') then  tmp := tmp+'INFO';
  1329. +  end;
  1330. +
  1331. +  if not fileexists(tmp) then exit;
  1332. +  if not RecyclerIsValid(tmp) then exit;
  1333. +
  1334. +  fs := TFileStream.Create(tmp, fmOpenRead);
  1335. +  try
  1336. +    fs.seek(length_position, soFromBeginning);
  1337. +    record_length := _readInt32(fs);
  1338. +
  1339. +    i := -1;
  1340. +    repeat
  1341. +      inc(i);
  1342. +      if unique_index_position+i*record_length > fs.size then break;
  1343. +      fs.seek(unique_index_position+i*record_length, soFromBeginning);
  1344. +      if inttostr(_readInt32(fs)) = id then
  1345. +      begin
  1346. +        fs.seek(source_position+i*record_length, soFromBeginning);
  1347. +        alternativ := _readChar(fs);
  1348. +
  1349. +        if alternativ = #0 then
  1350. +        begin
  1351. +          fs.seek(source_position+i*record_length+1, soFromBeginning);
  1352. +          result := _readNullTerminatedString(fs);
  1353. +        end
  1354. +        else
  1355. +        begin
  1356. +          fs.seek(source_position+i*record_length, soFromBeginning);
  1357. +          result := _readNullTerminatedString(fs);
  1358. +        end;
  1359. +
  1360. +        break;
  1361. +      end;
  1362. +    until false;
  1363. +  finally
  1364. +    fs.free;
  1365. +  end;
  1366. +
  1367. +  // In some cases the ansi-source-name is [Null]:\...\
  1368. +  if alternativ = #0 then
  1369. +  begin
  1370. +    result := RecyclerGetSourceDrive(InfofileOrRecycleFolder, id) + result;
  1371. +  end;
  1372. +end;
  1373. +
  1374. +////////////////////////////////////////////////////////////////////////////////
  1375. +
  1376. +class procedure TRecycleBinManager.RecyclerListIndexes(drive: char; result: TStringList);
  1377. +begin
  1378. +  RecyclerListIndexes(drive, '', result);
  1379. +end;
  1380. +
  1381. +class procedure TRecycleBinManager.RecyclerListIndexes(drive: char; UserSID: string; result: TStringList);
  1382. +var
  1383. +  infofile: string;
  1384. +begin
  1385. +  infofile := RecyclerGetPath(drive, UserSID, false);
  1386. +  RecyclerListIndexes(infofile, result);
  1387. +end;
  1388. +
  1389. +class procedure TRecycleBinManager.RecyclerListIndexes(InfofileOrRecycleFolder: string; result: TStringList);
  1390. +var
  1391. +  fs: TFileStream;
  1392. +  i, record_length: integer;
  1393. +  tmp: string;
  1394. +const
  1395. +  length_position = $C;
  1396. +  unique_index_position = $118;
  1397. +begin
  1398. +  tmp := InfofileOrRecycleFolder;
  1399. +
  1400. +  if _isFileVistaNamed(tmp) then
  1401. +  begin
  1402. +    _VistaListIndexes(extractfilepath(tmp), result);
  1403. +    exit;
  1404. +  end;
  1405. +
  1406. +  {$IFDEF allow_all_filenames}
  1407. +  if not RecyclerIsValid(tmp) and fileexists(tmp) then
  1408. +  begin
  1409. +    if fileexists(extractfilepath(tmp)+'INFO2') then
  1410. +      tmp := extractfilepath(tmp)+'INFO2'
  1411. +    else if fileexists(extractfilepath(tmp)+'INFO') then
  1412. +      tmp := extractfilepath(tmp)+'INFO';
  1413. +  end;
  1414. +  {$ENDIF}
  1415. +
  1416. +  if directoryexists(tmp) then
  1417. +  begin
  1418. +    tmp := IncludeTrailingBackslash(tmp);
  1419. +
  1420. +    if fileexists(tmp+'INFO2') then     tmp := tmp+'INFO2'
  1421. +    else if fileexists(tmp+'INFO') then tmp := tmp+'INFO'
  1422. +    else
  1423. +    begin
  1424. +      // Last try: is it a vista-directory?
  1425. +      _VistaListIndexes(tmp, result);
  1426. +      exit;
  1427. +    end;
  1428. +  end;
  1429. +
  1430. +  if not fileexists(tmp) then exit;
  1431. +  if not RecyclerIsValid(tmp) then exit;
  1432. +
  1433. +  fs := TFileStream.Create(tmp, fmOpenRead);
  1434. +  try
  1435. +    fs.seek(length_position, soFromBeginning);
  1436. +    record_length := _readInt32(fs);
  1437. +
  1438. +    i := -1;
  1439. +    repeat
  1440. +      inc(i);
  1441. +      if unique_index_position+i*record_length > fs.size then break;
  1442. +      fs.seek(unique_index_position+i*record_length, soFromBeginning);
  1443. +
  1444. +      result.Add(inttostr(_readInt32(fs)));
  1445. +    until false;
  1446. +  finally
  1447. +    fs.free;
  1448. +  end;
  1449. +end;
  1450. +
  1451. +////////////////////////////////////////////////////////////////////////////////
  1452. +
  1453. +class function TRecycleBinManager.RecyclerGetSourceDrive(InfofileOrRecycleFolder: string): char;
  1454. +begin
  1455. +  result := RecyclerGetSourceDrive(InfofileOrRecycleFolder, '');
  1456. +end;
  1457. +
  1458. +class function TRecycleBinManager.RecyclerGetSourceDrive(drive: char; fileid: string): char;
  1459. +begin
  1460. +  result := RecyclerGetSourceDrive(drive, '', fileid);
  1461. +end;
  1462. +
  1463. +class function TRecycleBinManager.RecyclerGetSourceDrive(drive: char; UserSID: string; fileid: string): char;
  1464. +var
  1465. +  infofile: string;
  1466. +begin
  1467. +  infofile := RecyclerGetPath(drive, UserSID, true, fileid);
  1468. +  result := RecyclerGetSourceDrive(infofile, fileid);
  1469. +end;
  1470. +
  1471. +class function TRecycleBinManager.RecyclerGetSourceDrive(InfofileOrRecycleFolder: string; id: string): char;
  1472. +var
  1473. +  fs: TFileStream;
  1474. +  i, record_length: integer;
  1475. +  tmp: string;
  1476. +const
  1477. +  length_position = $C;
  1478. +  unique_index_position = $118;
  1479. +  source_drive_position = $11C;
  1480. +begin
  1481. +  result := #0;
  1482. +
  1483. +  tmp := InfofileOrRecycleFolder;
  1484. +
  1485. +  if _isFileVistaNamed(tmp) then
  1486. +  begin
  1487. +    result := _VistaGetSourceDrive(tmp);
  1488. +    exit;
  1489. +  end;
  1490. +
  1491. +  {$IFDEF allow_all_filenames}
  1492. +  if not RecyclerIsValid(tmp) and fileexists(tmp) then
  1493. +  begin
  1494. +    if fileexists(extractfilepath(tmp)+'INFO2') then
  1495. +      tmp := extractfilepath(tmp)+'INFO2'
  1496. +    else if fileexists(extractfilepath(tmp)+'INFO') then
  1497. +      tmp := extractfilepath(tmp)+'INFO';
  1498. +  end;
  1499. +  {$ENDIF}
  1500. +
  1501. +  if directoryexists(tmp) then
  1502. +  begin
  1503. +    tmp := IncludeTrailingBackslash(tmp);
  1504. +
  1505. +    if fileexists(tmp+'$I'+id) then
  1506. +    begin
  1507. +      result := _VistaGetSourceDrive(tmp+'$I'+id);
  1508. +      exit;
  1509. +    end
  1510. +    else if fileexists(tmp+'INFO2') then tmp := tmp+'INFO2'
  1511. +    else if fileexists(tmp+'INFO') then  tmp := tmp+'INFO';
  1512. +  end;
  1513. +
  1514. +  if not fileexists(tmp) then exit;
  1515. +  if not RecyclerIsValid(tmp) then exit;
  1516. +
  1517. +  fs := TFileStream.Create(tmp, fmOpenRead);
  1518. +  try
  1519. +    fs.seek(length_position, soFromBeginning);
  1520. +    record_length := _readInt32(fs);
  1521. +
  1522. +    i := -1;
  1523. +    repeat
  1524. +      inc(i);
  1525. +      if unique_index_position+i*record_length > fs.size then break;
  1526. +      fs.seek(unique_index_position+i*record_length, soFromBeginning);
  1527. +      if inttostr(_readInt32(fs)) = id then
  1528. +      begin
  1529. +        fs.seek(source_drive_position+i*record_length, soFromBeginning);
  1530. +        result := chr(ord('A') + _readInt8(fs));
  1531. +        break;
  1532. +      end;
  1533. +    until false;
  1534. +  finally
  1535. +    fs.free;
  1536. +  end;
  1537. +end;
  1538. +
  1539. +////////////////////////////////////////////////////////////////////////////////
  1540. +
  1541. +class function TRecycleBinManager.RecyclerOriginalSize(InfofileOrRecycleFolder: string): integer;
  1542. +begin
  1543. +  result := RecyclerOriginalSize(InfofileOrRecycleFolder, '');
  1544. +end;
  1545. +
  1546. +class function TRecycleBinManager.RecyclerOriginalSize(drive: char; fileid: string): integer;
  1547. +begin
  1548. +  result := RecyclerOriginalSize(drive, '', fileid);
  1549. +end;
  1550. +
  1551. +class function TRecycleBinManager.RecyclerOriginalSize(drive: char; UserSID: string; fileid: string): integer;
  1552. +var
  1553. +  infofile: string;
  1554. +begin
  1555. +  infofile := RecyclerGetPath(drive, UserSID, true, fileid);
  1556. +  result := RecyclerOriginalSize(infofile, fileid);
  1557. +end;
  1558. +
  1559. +class function TRecycleBinManager.RecyclerOriginalSize(InfofileOrRecycleFolder: string; id: string): integer;
  1560. +var
  1561. +  fs: TFileStream;
  1562. +  i, record_length: integer;
  1563. +  tmp: string;
  1564. +const
  1565. +  length_position = $C;
  1566. +  unique_index_position = $118;
  1567. +  original_size_position = $128;
  1568. +begin
  1569. +  result := -1;
  1570. +
  1571. +  tmp := InfofileOrRecycleFolder;
  1572. +
  1573. +  if _isFileVistaNamed(tmp) then
  1574. +  begin
  1575. +    result := _VistaOriginalSize(tmp);
  1576. +    exit;
  1577. +  end;
  1578. +
  1579. +  {$IFDEF allow_all_filenames}
  1580. +  if not RecyclerIsValid(tmp) and fileexists(tmp) then
  1581. +  begin
  1582. +    if fileexists(extractfilepath(tmp)+'INFO2') then
  1583. +      tmp := extractfilepath(tmp)+'INFO2'
  1584. +    else if fileexists(extractfilepath(tmp)+'INFO') then
  1585. +      tmp := extractfilepath(tmp)+'INFO';
  1586. +  end;
  1587. +  {$ENDIF}
  1588. +
  1589. +  if directoryexists(tmp) then
  1590. +  begin
  1591. +    tmp := IncludeTrailingBackslash(tmp);
  1592. +
  1593. +    if fileexists(tmp+'$I'+id) then
  1594. +    begin
  1595. +      result := _VistaOriginalSize(tmp+'$I'+id);
  1596. +      exit;
  1597. +    end
  1598. +    else if fileexists(tmp+'INFO2') then tmp := tmp+'INFO2'
  1599. +    else if fileexists(tmp+'INFO') then  tmp := tmp+'INFO';
  1600. +  end;
  1601. +
  1602. +  if not fileexists(tmp) then exit;
  1603. +  if not RecyclerIsValid(tmp) then exit;
  1604. +
  1605. +  fs := TFileStream.Create(tmp, fmOpenRead);
  1606. +  try
  1607. +    fs.seek(length_position, soFromBeginning);
  1608. +    record_length := _readInt32(fs);
  1609. +
  1610. +    i := -1;
  1611. +    repeat
  1612. +      inc(i);
  1613. +      if unique_index_position+i*record_length > fs.size then break;
  1614. +      fs.seek(unique_index_position+i*record_length, soFromBeginning);
  1615. +      if inttostr(_readInt32(fs)) = id then
  1616. +      begin
  1617. +        fs.seek(original_size_position+i*record_length, soFromBeginning);
  1618. +        result := _readInt32(fs);
  1619. +        break;
  1620. +      end;
  1621. +    until false;
  1622. +  finally
  1623. +    fs.free;
  1624. +  end;
  1625. +end;
  1626. +
  1627. +////////////////////////////////////////////////////////////////////////////////
  1628. +
  1629. +class function TRecycleBinManager.RecyclerIsValid(drive: char): boolean;
  1630. +begin
  1631. +  // Bei Vista und W2k3 (VM) erhalte ich bei LW A: die Meldung
  1632. +  // "c0000013 Kein Datenträger". Exception Abfangen geht nicht.
  1633. +  // Daher erstmal überprüfen, ob Laufwerk existiert.
  1634. +  result := false;
  1635. +  if not RecyclerIsPossible(drive) then exit;
  1636. +
  1637. +  result := RecyclerIsValid(drive, '');
  1638. +end;
  1639. +
  1640. +class function TRecycleBinManager.RecyclerIsValid(drive: char; UserSID: string): boolean;
  1641. +var
  1642. +  infofile: string;
  1643. +begin
  1644. +  // Anmerkung siehe oben.
  1645. +  result := false;
  1646. +  if not RecyclerIsPossible(drive) then exit;
  1647. +
  1648. +  infofile := RecyclerGetPath(drive, UserSID, false);
  1649. +  result := RecyclerIsValid(infofile);
  1650. +end;
  1651. +
  1652. +class function TRecycleBinManager.RecyclerIsValid(InfofileOrRecycleFolder: string): boolean;
  1653. +var
  1654. +  tmp: string;
  1655. +  x: TStringList;
  1656. +  i: integer;
  1657. +  eine_fehlerhaft: boolean;
  1658. +begin
  1659. +  result := false;
  1660. +
  1661. +  tmp := InfofileOrRecycleFolder;
  1662. +
  1663. +  if _isFileVistaNamed(tmp) then
  1664. +  begin
  1665. +    result := _VistaIsValid(tmp);
  1666. +    exit;
  1667. +  end;
  1668. +
  1669. +  {$IFDEF allow_all_filenames}
  1670. +  if not RecyclerIsValid(tmp) and fileexists(tmp) then
  1671. +  begin
  1672. +    if fileexists(extractfilepath(tmp)+'INFO2') then
  1673. +      tmp := extractfilepath(tmp)+'INFO2'
  1674. +    else if fileexists(extractfilepath(tmp)+'INFO') then
  1675. +      tmp := extractfilepath(tmp)+'INFO';
  1676. +  end;
  1677. +  {$ENDIF}
  1678. +
  1679. +  if directoryexists(tmp) then
  1680. +  begin
  1681. +    tmp := IncludeTrailingBackslash(tmp);
  1682. +
  1683. +    if fileexists(tmp+'INFO2') then
  1684. +    begin
  1685. +      result := _checkInfo1or2File(tmp+'INFO2');
  1686. +    end;
  1687. +
  1688. +    if not result and fileexists(tmp+'INFO') then
  1689. +    begin
  1690. +      result := _checkInfo1or2File(tmp+'INFO');
  1691. +    end;
  1692. +
  1693. +    if not result then
  1694. +    begin
  1695. +      // Complete vista-directory declared?
  1696. +      eine_fehlerhaft := false;
  1697. +      x := TStringList.Create;
  1698. +      try
  1699. +        _VistaListIndexes(tmp, x);
  1700. +        for i := 0 to x.Count - 1 do
  1701. +        begin
  1702. +          if not _VistaIsValid(tmp+'$I'+x.Strings[i]) then
  1703. +          begin
  1704. +            eine_fehlerhaft := true;
  1705. +          end;
  1706. +        end;
  1707. +      finally
  1708. +        x.Free;
  1709. +      end;
  1710. +      result := not eine_fehlerhaft;
  1711. +    end;
  1712. +  end;
  1713. +
  1714. +  if not fileexists(tmp) then exit;
  1715. +
  1716. +  result := _checkInfo1or2File(tmp);
  1717. +end;
  1718. +
  1719. +////////////////////////////////////////////////////////////////////////////////
  1720. +
  1721. +class function TRecycleBinManager.RecyclerCurrentFilename(InfofileOrRecycleFolder: string): string;
  1722. +begin
  1723. +  result := RecyclerCurrentFilename(InfofileOrRecycleFolder, '');
  1724. +end;
  1725. +
  1726. +class function TRecycleBinManager.RecyclerCurrentFilename(drive: char; fileid: string): string;
  1727. +begin
  1728. +  result := RecyclerCurrentFilename(drive, '', fileid);
  1729. +end;
  1730. +
  1731. +class function TRecycleBinManager.RecyclerCurrentFilename(drive: char; UserSID: string; fileid: string): string;
  1732. +var
  1733. +  infofile: string;
  1734. +begin
  1735. +  infofile := RecyclerGetPath(drive, UserSID, true, fileid);
  1736. +  result := RecyclerCurrentFilename(infofile, fileid);
  1737. +end;
  1738. +
  1739. +class function TRecycleBinManager.RecyclerCurrentFilename(InfofileOrRecycleFolder: string; id: string): string;
  1740. +var
  1741. +  a, c: string;
  1742. +  tmp: string;
  1743. +begin
  1744. +  result := '';
  1745. +
  1746. +  tmp := InfofileOrRecycleFolder;
  1747. +
  1748. +  if _isFileVistaNamed(tmp) then
  1749. +  begin
  1750. +    result := _VistaCurrentFilename(tmp);
  1751. +    exit;
  1752. +  end;
  1753. +
  1754. +  {$IFDEF allow_all_filenames}
  1755. +  if not RecyclerIsValid(tmp) and fileexists(tmp) then
  1756. +  begin
  1757. +    if fileexists(extractfilepath(tmp)+'INFO2') then
  1758. +      tmp := extractfilepath(tmp)+'INFO2'
  1759. +    else if fileexists(extractfilepath(tmp)+'INFO') then
  1760. +      tmp := extractfilepath(tmp)+'INFO';
  1761. +  end;
  1762. +  {$ENDIF}
  1763. +
  1764. +  if directoryexists(tmp) then
  1765. +  begin
  1766. +    tmp := IncludeTrailingBackslash(tmp);
  1767. +
  1768. +    if fileexists(tmp+'$I'+id) then
  1769. +    begin
  1770. +      result := _VistaCurrentFilename(tmp+'$I'+id);
  1771. +      exit;
  1772. +    end
  1773. +    else if fileexists(tmp+'INFO2') then tmp := tmp+'INFO2'
  1774. +    else if fileexists(tmp+'INFO') then  tmp := tmp+'INFO';
  1775. +  end;
  1776. +
  1777. +  a := RecyclerGetSourceDrive(tmp, id);
  1778. +  c := extractfileext(RecyclerGetSourceUnicode(tmp, id));
  1779. +  if (a <> '') then
  1780. +  begin
  1781. +    result := 'D' + a + id + c;
  1782. +  end;
  1783. +end;
  1784. +
  1785. +////////////////////////////////////////////////////////////////////////////////
  1786. +
  1787. +class function TRecycleBinManager.RecyclerGetPath(drive: char; UserSID: string; IncludeInfofile: boolean; fileid: string): string;
  1788. +var
  1789. +  sl: TStringList;
  1790. +begin
  1791. +  sl := TStringList.Create;
  1792. +  try
  1793. +    RecyclerGetInfofiles(drive, UserSID, IncludeInfofile, fileid, sl);
  1794. +    if sl.Count > 0 then
  1795. +      result := ExtractFilePath(sl.Strings[0])
  1796. +    else
  1797. +      result := '';
  1798. +  finally
  1799. +    sl.free;
  1800. +  end;
  1801. +end;
  1802. +
  1803. +class function TRecycleBinManager.RecyclerGetPath(drive: char; UserSID: string; IncludeInfofile: boolean): string;
  1804. +var
  1805. +  sl: TStringList;
  1806. +begin
  1807. +  sl := TStringList.Create;
  1808. +  try
  1809. +    RecyclerGetInfofiles(drive, UserSID, IncludeInfofile, sl);
  1810. +    if sl.Count > 0 then
  1811. +      result := ExtractFilePath(sl.Strings[0])
  1812. +    else
  1813. +      result := '';
  1814. +  finally
  1815. +    sl.free;
  1816. +  end;
  1817. +end;
  1818. +
  1819. +class function TRecycleBinManager.RecyclerGetPath(drive: char; IncludeInfofile: boolean): string;
  1820. +var
  1821. +  sl: TStringList;
  1822. +begin
  1823. +  sl := TStringList.Create;
  1824. +  try
  1825. +    RecyclerGetInfofiles(drive, IncludeInfofile, sl);
  1826. +    if sl.Count > 0 then
  1827. +      result := ExtractFilePath(sl.Strings[0])
  1828. +    else
  1829. +      result := '';
  1830. +  finally
  1831. +    sl.free;
  1832. +  end;
  1833. +end;
  1834. +
  1835. +class function TRecycleBinManager.RecyclerGetPath(drive: char; UserSID: string): string;
  1836. +var
  1837. +  sl: TStringList;
  1838. +begin
  1839. +  sl := TStringList.Create;
  1840. +  try
  1841. +    RecyclerGetInfofiles(drive, UserSID, sl);
  1842. +    if sl.Count > 0 then
  1843. +      result := ExtractFilePath(sl.Strings[0])
  1844. +    else
  1845. +      result := '';
  1846. +  finally
  1847. +    sl.free;
  1848. +  end;
  1849. +end;
  1850. +
  1851. +class function TRecycleBinManager.RecyclerGetPath(drive: char): string;
  1852. +var
  1853. +  sl: TStringList;
  1854. +begin
  1855. +  sl := TStringList.Create;
  1856. +  try
  1857. +    RecyclerGetInfofiles(drive, sl);
  1858. +    if sl.Count > 0 then
  1859. +      result := ExtractFilePath(sl.Strings[0])
  1860. +    else
  1861. +      result := '';
  1862. +  finally
  1863. +    sl.free;
  1864. +  end;
  1865. +end;
  1866. +
  1867. +////////////////////////////////////////////////////////////////////////////////
  1868. +
  1869. +class procedure TRecycleBinManager.RecyclerGetInfofiles(drive: char; UserSID: string; IncludeInfofile: boolean; fileid: string; result: TStringList);
  1870. +var
  1871. +  dir: string;
  1872. +begin
  1873. +  // Find recyclers from Windows Vista or higher
  1874. +
  1875. +  if _isFAT(drive) then
  1876. +  begin
  1877. +    dir := drive + DriveDelim + PathDelim + '$recycle.bin' + PathDelim;
  1878. +    if IncludeInfofile and (fileid <> '') then
  1879. +    begin
  1880. +      if fileExists(dir + '$I'+fileid) then
  1881. +      begin
  1882. +        result.Add(dir + '$I'+fileid);
  1883. +      end;
  1884. +    end
  1885. +    else
  1886. +    begin
  1887. +      if directoryExists(dir) then
  1888. +      begin
  1889. +        result.Add(dir);
  1890. +      end;
  1891. +    end;
  1892. +  end
  1893. +  else
  1894. +  begin
  1895. +    if UserSID <> '' then
  1896. +    begin
  1897. +      dir := drive + DriveDelim + PathDelim + '$recycle.bin'+PathDelim+UserSID+PathDelim;
  1898. +      if IncludeInfofile and (fileid <> '') then
  1899. +      begin
  1900. +        if fileExists(dir + '$I'+fileid) then
  1901. +        begin
  1902. +          result.Add(dir + '$I'+fileid);
  1903. +        end;
  1904. +      end
  1905. +      else
  1906. +      begin
  1907. +        if directoryExists(dir) then
  1908. +        begin
  1909. +          result.Add(dir);
  1910. +        end;
  1911. +      end;
  1912. +    end
  1913. +    else
  1914. +    begin
  1915. +      dir := drive + DriveDelim + PathDelim + '$recycle.bin'+PathDelim+_getMySID()+PathDelim;
  1916. +      if IncludeInfofile and (fileid <> '') then
  1917. +      begin
  1918. +        if fileExists(dir + '$I'+fileid) then
  1919. +        begin
  1920. +          result.Add(dir + '$I'+fileid);
  1921. +        end;
  1922. +      end
  1923. +      else
  1924. +      begin
  1925. +        if directoryExists(dir) then
  1926. +        begin
  1927. +          result.Add(dir);
  1928. +        end;
  1929. +      end;
  1930. +    end;
  1931. +  end;
  1932. +
  1933. +  // Find recyclers from Windows before Vista
  1934. +
  1935. +  if _isFAT(drive) then
  1936. +  begin
  1937. +    dir := drive + DriveDelim + PathDelim + 'Recycled' + PathDelim;
  1938. +    if IncludeInfofile then
  1939. +    begin
  1940. +      // Both "recycle bins" are possible if you have multiboot (but do overwrite themselfes if you empty them)
  1941. +      if fileExists(dir + 'INFO2') then
  1942. +        result.Add(dir + 'INFO2'); // Windows 95 with Internet Explorer 4 Extension or higher Windows versions
  1943. +      if fileExists(dir + 'INFO') then
  1944. +        result.Add(dir + 'INFO'); // Windows 95 native
  1945. +    end
  1946. +    else
  1947. +    begin
  1948. +      if directoryExists(dir) then
  1949. +        result.Add(dir);
  1950. +    end;
  1951. +  end
  1952. +  else
  1953. +  begin
  1954. +    if UserSID <> '' then
  1955. +    begin
  1956. +      dir := drive + DriveDelim + PathDelim + 'Recycler'+PathDelim+UserSID+PathDelim;
  1957. +      if IncludeInfofile then
  1958. +      begin
  1959. +        if fileExists(dir + 'INFO2') then
  1960. +          result.Add(dir + 'INFO2');
  1961. +      end
  1962. +      else
  1963. +      begin
  1964. +        if directoryExists(dir) then
  1965. +          result.Add(dir);
  1966. +      end;
  1967. +    end
  1968. +    else
  1969. +    begin
  1970. +      dir := drive + DriveDelim + PathDelim + 'Recycler'+PathDelim+_getMySID()+PathDelim;
  1971. +      if IncludeInfofile then
  1972. +      begin
  1973. +        if fileExists(dir + 'INFO2') then
  1974. +          result.Add(dir + 'INFO2');
  1975. +      end
  1976. +      else
  1977. +      begin
  1978. +        if directoryExists(dir) then
  1979. +          result.Add(dir);
  1980. +      end;
  1981. +    end;
  1982. +  end;
  1983. +end;
  1984. +
  1985. +class procedure TRecycleBinManager.RecyclerGetInfofiles(drive: char; UserSID: string; IncludeInfofile: boolean; result: TStringList);
  1986. +begin
  1987. +  RecyclerGetInfofiles(drive, UserSID, IncludeInfofile, '', result);
  1988. +end;
  1989. +
  1990. +class procedure TRecycleBinManager.RecyclerGetInfofiles(drive: char; IncludeInfofile: boolean; result: TStringList);
  1991. +begin
  1992. +  RecyclerGetInfofiles(drive, '', IncludeInfofile, '', result);
  1993. +end;
  1994. +
  1995. +class procedure TRecycleBinManager.RecyclerGetInfofiles(drive: char; UserSID: string; result: TStringList);
  1996. +begin
  1997. +  RecyclerGetInfofiles(drive, UserSID, false, '', result);
  1998. +end;
  1999. +
  2000. +class procedure TRecycleBinManager.RecyclerGetInfofiles(drive: char; result: TStringList);
  2001. +begin
  2002. +  RecyclerGetInfofiles(drive, '', false, '', result);
  2003. +end;
  2004. +
  2005. +////////////////////////////////////////////////////////////////////////////////
  2006. +
  2007. +class function TRecycleBinManager.RecyclerCurrentFilenameAndPath(drive: char; UserSID: string; fileid: string): string;
  2008. +begin
  2009. +  result := RecyclerGetPath(drive, UserSID, false, fileid) +
  2010. +    RecyclerCurrentFilename(drive, UserSID, fileid);
  2011. +end;
  2012. +
  2013. +class function TRecycleBinManager.RecyclerCurrentFilenameAndPath(drive: char; fileid: string): string;
  2014. +begin
  2015. +  result := RecyclerCurrentFilenameAndPath(drive, '', fileid);
  2016. +end;
  2017. +
  2018. +class function TRecycleBinManager.RecyclerCurrentFilenameAndPath(InfofileOrRecycleFolder: string; id: string): string;
  2019. +begin
  2020. +  if RecyclerIsValid(InfofileOrRecycleFolder) then
  2021. +  begin
  2022. +    result := extractfilepath(InfofileOrRecycleFolder) +
  2023. +      RecyclerCurrentFilename(InfofileOrRecycleFolder, id);
  2024. +  end
  2025. +  else
  2026. +    result := '';
  2027. +end;
  2028. +
  2029. +////////////////////////////////////////////////////////////////////////////////
  2030. +
  2031. +class function TRecycleBinManager.RecyclerRemoveItem(drive: char; UserSID: string; fileid: string): boolean;
  2032. +var
  2033. +  tmp: string;
  2034. +begin
  2035. +  tmp := RecyclerCurrentFilenameAndPath(drive, UserSID, fileid);
  2036. +  if fileexists(tmp) then
  2037. +  begin
  2038. +    deletefile(tmp);
  2039. +    result := fileexists(tmp);
  2040. +  end
  2041. +  else
  2042. +  begin
  2043. +    directoryexists(tmp);
  2044. +    result := directoryexists(tmp);
  2045. +  end;
  2046. +end;
  2047. +
  2048. +class function TRecycleBinManager.RecyclerRemoveItem(drive: char; fileid: string): boolean;
  2049. +begin
  2050. +  result := RecyclerRemoveItem(drive, '', fileid);
  2051. +end;
  2052. +
  2053. +class function TRecycleBinManager.RecyclerRemoveItem(InfofileOrRecycleFolder: string; id: string): boolean;
  2054. +var
  2055. +  tmp: string;
  2056. +begin
  2057. +  tmp := RecyclerCurrentFilenameAndPath(InfofileOrRecycleFolder, id);
  2058. +  if fileexists(tmp) then
  2059. +  begin
  2060. +    deletefile(tmp);
  2061. +    result := fileexists(tmp);
  2062. +  end
  2063. +  else
  2064. +  begin
  2065. +    directoryexists(tmp);
  2066. +    result := directoryexists(tmp);
  2067. +  end;
  2068. +end;
  2069. +
  2070. +class procedure TRecycleBinManager.RecyclerGetAllRecyclerDrives(result: TStringList);
  2071. +var
  2072. +  Drive: char;
  2073. +begin
  2074. +  for Drive := 'A' to 'Z' do
  2075. +  begin
  2076. +    if RecyclerIsPossible(Drive) and RecyclerIsValid(Drive) then
  2077. +    begin
  2078. +      result.Add(Drive);
  2079. +    end;
  2080. +  end;
  2081. +end;
  2082. +
  2083. +////////////////////////////////////////////////////////////////////////////////
  2084. +
  2085. +// http://www.dsdt.info/tipps/?id=176
  2086. +class function TRecycleBinManager.RecyclerEmptyRecycleBin(flags: cardinal): boolean;
  2087. +type
  2088. +  TSHEmptyRecycleBin = function (Wnd: HWND;
  2089. +                                 pszRootPath: PChar;
  2090. +                                 dwFlags: DWORD):
  2091. +                                 HRESULT; stdcall;
  2092. +var
  2093. +  PSHEmptyRecycleBin: TSHEmptyRecycleBin;
  2094. +  LibHandle: THandle;
  2095. +const
  2096. +  C_SHEmptyRecycleBinA = 'SHEmptyRecycleBinA';
  2097. +begin
  2098. +  result := true;
  2099. +  LibHandle := LoadLibrary(shell32) ;
  2100. +  try
  2101. +    if LibHandle <> 0 then
  2102. +    begin
  2103. +      @PSHEmptyRecycleBin:= GetProcAddress(LibHandle, C_SHEmptyRecycleBinA);
  2104. +      if @PSHEmptyRecycleBin <> nil then
  2105. +      begin
  2106. +        PSHEmptyRecycleBin(hInstance, nil, flags);
  2107. +      end
  2108. +      else
  2109. +        result := false;
  2110. +    end
  2111. +    else
  2112. +      result := false;
  2113. +  finally
  2114. +    @PSHEmptyRecycleBin := nil;
  2115. +    FreeLibrary(LibHandle);
  2116. +  end;
  2117. +end;
  2118. +
  2119. +class function TRecycleBinManager.RecyclerEmptyRecycleBin(sound, progress, confirmation: boolean): boolean;
  2120. +const
  2121. +  SHERB_NOCONFIRMATION = $00000001;
  2122. +  SHERB_NOPROGRESSUI   = $00000002;
  2123. +  SHERB_NOSOUND        = $00000004;
  2124. +var
  2125. +  flags: cardinal;
  2126. +begin
  2127. +  flags := 0;
  2128. +
  2129. +  if not progress then
  2130. +    flags := flags or SHERB_NOPROGRESSUI;
  2131. +  if not confirmation then
  2132. +    flags := flags or SHERB_NOCONFIRMATION;
  2133. +  if not sound then
  2134. +    flags := flags or SHERB_NOSOUND;
  2135. +
  2136. +  result := RecyclerEmptyRecycleBin(flags);
  2137. +end;
  2138. +
  2139. +////////////////////////////////////////////////////////////////////////////////
  2140. +
  2141. +// Template
  2142. +// http://www.dsdt.info/tipps/?id=116
  2143. +class function TRecycleBinManager.RecyclerAddFileOrFolder(FileOrFolder: string; confirmation: boolean): boolean;
  2144. +var
  2145. +  Operation: TSHFileOpStruct;
  2146. +begin
  2147. +  with Operation do
  2148. +  begin
  2149. +    Wnd := hInstance; // OK?
  2150. +    wFunc := FO_DELETE;
  2151. +    pFrom := PChar(FileOrFolder + #0);
  2152. +    pTo := nil;
  2153. +    fFlags := FOF_ALLOWUNDO;
  2154. +    if not confirmation then fFlags := fFlags or FOF_NOCONFIRMATION;
  2155. +  end;
  2156. +  Result := SHFileOperation(Operation) = 0;
  2157. +end;
  2158. +
  2159. +class function TRecycleBinManager.RecyclerAddFileOrFolder(FileOrFolder: string): boolean;
  2160. +begin
  2161. +  result := RecyclerAddFileOrFolder(FileOrFolder, false);
  2162. +end;
  2163. +
  2164. +class function TRecycleBinManager.RecyclerConfirmationDialogEnabled: boolean;
  2165. +var
  2166. +  gp: GPOLICYBOOL;
  2167. +begin
  2168. +  gp := RecyclerGroupPolicyConfirmFileDelete;
  2169. +  if gp <> gpUndefined then
  2170. +  begin
  2171. +    result := gp = gpEnabled;
  2172. +  end
  2173. +  else
  2174. +  begin
  2175. +    result := RecyclerShellStateConfirmationDialogEnabled;
  2176. +  end;
  2177. +end;
  2178. +
  2179. +class function TRecycleBinManager.RecyclerShellStateConfirmationDialogEnabled: boolean;
  2180. +type
  2181. +  TSHGetSettings = procedure (var lpss: SHELLSTATE; dwMask: DWORD) stdcall;
  2182. +const
  2183. +  C_SHGetSettings = 'SHGetSettings';
  2184. +var
  2185. +  lpss: SHELLSTATE;
  2186. +  bNoConfirmRecycle: boolean;
  2187. +
  2188. +  PSHGetSettings: TSHGetSettings;
  2189. +  RBHandle: THandle;
  2190. +
  2191. +  reg: TRegistry;
  2192. +  rbuf: array[0..255] of byte;
  2193. +begin
  2194. +  PSHGetSettings := nil;
  2195. +  result := false; // Avoid warning message
  2196. +
  2197. +  RBHandle := LoadLibrary(shell32);
  2198. +  if(RBHandle <> 0) then
  2199. +  begin
  2200. +    PSHGetSettings := GetProcAddress(RBHandle, C_SHGetSettings);
  2201. +    if (@PSHGetSettings = nil) then
  2202. +    begin
  2203. +      FreeLibrary(RBHandle);
  2204. +      RBHandle := 0;
  2205. +    end;
  2206. +  end;
  2207. +
  2208. +  if (RBHandle <> 0) and (Assigned(PSHGetSettings)) then
  2209. +  begin
  2210. +    ZeroMemory(@lpss, SizeOf(lpss));
  2211. +    PSHGetSettings(lpss, SSF_NOCONFIRMRECYCLE);
  2212. +    // bNoConfirmRecycle := (lpss.Flags1 and 4) = 4; // fNoConfirmRecycle
  2213. +    bNoConfirmRecycle := GetByteBit(lpss.Flags1, 2);
  2214. +
  2215. +    result := not bNoConfirmRecycle;
  2216. +  end
  2217. +  else
  2218. +  begin
  2219. +    reg := TRegistry.Create;
  2220. +    try
  2221. +      // API function call failed. Probably because Windows is too old.
  2222. +      // Try to read out from registry.
  2223. +      // The 3rd bit of the 5th byte of "ShellState" is the value
  2224. +      // of "fNoConfirmRecycle".
  2225. +
  2226. +      reg.RootKey := HKEY_CURRENT_USER;
  2227. +      if (reg.OpenKeyReadOnly('Software\Microsoft\Windows\CurrentVersion\Explorer')) then
  2228. +      begin
  2229. +        ZeroMemory(@rbuf, SizeOf(rbuf));
  2230. +        reg.ReadBinaryData('ShellState', rbuf, SizeOf(rbuf));
  2231. +
  2232. +        // Lese 3tes Bit vom 5ten Byte
  2233. +        // bNoConfirmRecycle := ((rbuf[4] and 4) = 4);
  2234. +        bNoConfirmRecycle := GetByteBit(rbuf[4], 2);
  2235. +        result := not bNoConfirmRecycle;
  2236. +
  2237. +        reg.CloseKey;
  2238. +      end
  2239. +      else
  2240. +      begin
  2241. +        raise EAPICallError.CreateFmt(LNG_API_CALL_ERROR, [Format(LNG_NOT_CALLABLE, [C_SHGetSettings])]);
  2242. +      end;
  2243. +    finally
  2244. +      reg.Free;
  2245. +    end;
  2246. +  end;
  2247. +
  2248. +  if (RBHandle <> 0) then FreeLibrary(RBHandle);
  2249. +end;
  2250. +
  2251. +class procedure TRecycleBinManager.RecyclerConfirmationDialogSetEnabled(NewSetting: boolean);
  2252. +type
  2253. +  TSHGetSetSettings = procedure (var lpss: SHELLSTATE; dwMask: DWORD; bSet: BOOL) stdcall;
  2254. +const
  2255. +  C_SHGetSetSettings = 'SHGetSetSettings';
  2256. +var
  2257. +  lpss: SHELLSTATE;
  2258. +
  2259. +  PSHGetSetSettings: TSHGetSetSettings;
  2260. +  RBHandle: THandle;
  2261. +
  2262. +  reg: TRegistry;
  2263. +  rbuf: array[0..255] of byte;
  2264. +
  2265. +  dwResult: DWORD;
  2266. +begin
  2267. +  PSHGetSetSettings := nil;
  2268. +
  2269. +  RBHandle := LoadLibrary(shell32);
  2270. +  if(RBHandle <> 0) then
  2271. +  begin
  2272. +    PSHGetSetSettings := GetProcAddress(RBHandle, C_SHGetSetSettings);
  2273. +    if (@PSHGetSetSettings = nil) then
  2274. +    begin
  2275. +      FreeLibrary(RBHandle);
  2276. +      RBHandle := 0;
  2277. +    end;
  2278. +  end;
  2279. +
  2280. +  if (RBHandle <> 0) and (Assigned(PSHGetSetSettings)) then
  2281. +  begin
  2282. +    ZeroMemory(@lpss, SizeOf(lpss));
  2283. +    PSHGetSetSettings(lpss, SSF_NOCONFIRMRECYCLE, false); // Get
  2284. +    lpss.Flags1 := SetByteBit(lpss.Flags1, 2, NewSetting);
  2285. +    PSHGetSetSettings(lpss, SSF_NOCONFIRMRECYCLE, true); // Set
  2286. +
  2287. +    SendMessageTimeout (
  2288. +      HWND_BROADCAST, WM_SETTINGCHANGE,
  2289. +      0, lParam (pChar ('ShellState')),
  2290. +      SMTO_ABORTIFHUNG, 5000, dwResult
  2291. +    );
  2292. +  end
  2293. +  else
  2294. +  begin
  2295. +    reg := TRegistry.Create;
  2296. +    try
  2297. +      // API function call failed. Probably because Windows is too old.
  2298. +      // Try to read out from registry.
  2299. +      // The 3rd bit of the 5th byte of "ShellState" is the value
  2300. +      // of "fNoConfirmRecycle".
  2301. +
  2302. +      reg.RootKey := HKEY_CURRENT_USER;
  2303. +      if (reg.OpenKey('Software\Microsoft\Windows\CurrentVersion\Explorer', false)) then
  2304. +      begin
  2305. +        ZeroMemory(@rbuf, SizeOf(rbuf));
  2306. +        reg.ReadBinaryData('ShellState', rbuf, SizeOf(rbuf)); // Get
  2307. +        rbuf[4] := SetByteBit(rbuf[4], 2, NewSetting);
  2308. +        reg.WriteBinaryData('ShellState', rbuf, SizeOf(rbuf)); // Set
  2309. +
  2310. +        SendMessageTimeout (
  2311. +          HWND_BROADCAST, WM_SETTINGCHANGE,
  2312. +          0, lParam (pChar ('ShellState')),
  2313. +          SMTO_ABORTIFHUNG, 5000, dwResult
  2314. +        );
  2315. +
  2316. +        reg.CloseKey;
  2317. +      end
  2318. +      else
  2319. +      begin
  2320. +        raise EAPICallError.CreateFmt(LNG_API_CALL_ERROR, [Format(LNG_NOT_CALLABLE, [C_SHGetSetSettings])]);
  2321. +      end;
  2322. +    finally
  2323. +      reg.Free;
  2324. +    end;
  2325. +  end;
  2326. +
  2327. +  if (RBHandle <> 0) then FreeLibrary(RBHandle);
  2328. +end;
  2329. +
  2330. +
  2331. +class function TRecycleBinManager.RecyclerGetName: string;
  2332. +var
  2333. +  reg: TRegistry;
  2334. +begin
  2335. +  // Windows 95b:
  2336. +  // Change of CLSID\{645FF040-5081-101B-9F08-00AA002F954E} will change the desktop name of the recycle bin.
  2337. +
  2338. +  // Windows 2000: If LocalizedString is available, the 3rd argument will be parsed
  2339. +  // (if the third argument will removed, it will be read out from the DLL resource string automatically)
  2340. +
  2341. +  reg := TRegistry.Create;
  2342. +  try
  2343. +    reg.RootKey := HKEY_CLASSES_ROOT;
  2344. +    if reg.OpenKeyReadOnly('CLSID\'+RECYCLER_CLSID) then
  2345. +    begin
  2346. +      if reg.ValueExists('LocalizedString') then
  2347. +      begin
  2348. +        result := reg.ReadString('LocalizedString');
  2349. +        result := _DecodeReferenceString(result);
  2350. +      end
  2351. +      else
  2352. +      begin
  2353. +        result := reg.ReadString('');
  2354. +      end;
  2355. +
  2356. +      reg.CloseKey;
  2357. +    end;
  2358. +  finally
  2359. +    reg.Free;
  2360. +  end;
  2361. +end;
  2362. +
  2363. +class function TRecycleBinManager.RecyclerGetInfoTip: string;
  2364. +var
  2365. +  reg: TRegistry;
  2366. +begin
  2367. +  // Not available in some older versions of Windows
  2368. +
  2369. +  reg := TRegistry.Create;
  2370. +  try
  2371. +    reg.RootKey := HKEY_CLASSES_ROOT;
  2372. +    if reg.OpenKeyReadOnly('CLSID\'+RECYCLER_CLSID) then
  2373. +    begin
  2374. +      result := reg.ReadString('InfoTip');
  2375. +      result := _DecodeReferenceString(result);
  2376. +
  2377. +      reg.CloseKey;
  2378. +    end;
  2379. +  finally
  2380. +    reg.Free;
  2381. +  end;
  2382. +end;
  2383. +
  2384. +class function TRecycleBinManager.RecyclerGetIntroText: string;
  2385. +var
  2386. +  reg: TRegistry;
  2387. +begin
  2388. +  // Not available in some older versions of Windows
  2389. +
  2390. +  reg := TRegistry.Create;
  2391. +  try
  2392. +    reg.RootKey := HKEY_CLASSES_ROOT;
  2393. +    if reg.OpenKeyReadOnly('CLSID\'+RECYCLER_CLSID) then
  2394. +    begin
  2395. +      result := reg.ReadString('IntroText');
  2396. +      result := _DecodeReferenceString(result);
  2397. +
  2398. +      reg.CloseKey;
  2399. +    end;
  2400. +  finally
  2401. +    reg.Free;
  2402. +  end;
  2403. +end;
  2404. +
  2405. +class function TRecycleBinManager.RecyclerEmptyEventGetName: string;
  2406. +var
  2407. +  reg: TRegistry;
  2408. +begin
  2409. +  reg := TRegistry.Create;
  2410. +  try
  2411. +    reg.RootKey := HKEY_CURRENT_USER;
  2412. +    if reg.OpenKeyReadOnly('AppEvents\EventLabels\EmptyRecycleBin') then
  2413. +    begin
  2414. +      result := reg.ReadString('');
  2415. +      reg.CloseKey;
  2416. +    end;
  2417. +  finally
  2418. +    reg.Free;
  2419. +  end;
  2420. +end;
  2421. +
  2422. +class function TRecycleBinManager.RecyclerEmptyEventGetCurrentSound: string;
  2423. +begin
  2424. +  result := RecyclerEmptyEventGetSound('.Current');
  2425. +end;
  2426. +
  2427. +class function TRecycleBinManager.RecyclerEmptyEventGetDefaultSound: string;
  2428. +begin
  2429. +  result := RecyclerEmptyEventGetSound('.Default');
  2430. +end;
  2431. +
  2432. +class procedure TRecycleBinManager.RecyclerEmptyEventGetSoundCategories(AStringList: TStringList);
  2433. +var
  2434. +  reg: TRegistry;
  2435. +begin
  2436. +  reg := TRegistry.Create;
  2437. +  try
  2438. +    reg.RootKey := HKEY_CURRENT_USER;
  2439. +    if reg.OpenKeyReadOnly('AppEvents\Schemes\Apps\Explorer\EmptyRecycleBin') then
  2440. +    begin
  2441. +      reg.GetKeyNames(AStringList);
  2442. +      reg.CloseKey;
  2443. +    end;
  2444. +  finally
  2445. +    reg.Free;
  2446. +  end;
  2447. +end;
  2448. +
  2449. +class function TRecycleBinManager.RecyclerEmptyEventGetSound(ACategory: string): string;
  2450. +var
  2451. +  reg: TRegistry;
  2452. +resourcestring
  2453. +  LNG_SND_EVENT_CAT_ERROR = 'The category "%s" is not available for the notification event "%s".';
  2454. +begin
  2455. +  // Outputs an filename or empty string for no sound defined.
  2456. +
  2457. +  reg := TRegistry.Create;
  2458. +  try
  2459. +    reg.RootKey := HKEY_CURRENT_USER;
  2460. +    if reg.OpenKeyReadOnly('AppEvents\Schemes\Apps\Explorer\EmptyRecycleBin') then
  2461. +    begin
  2462. +      if reg.OpenKeyReadOnly(ACategory) then
  2463. +      begin
  2464. +        result := reg.ReadString('');
  2465. +        reg.CloseKey;
  2466. +      end
  2467. +      else
  2468. +        raise EEventCategoryNotDefined.CreateFmt(LNG_SND_EVENT_CAT_ERROR, [ACategory, 'EmptyRecycleBin']);
  2469. +      reg.CloseKey;
  2470. +    end;
  2471. +  finally
  2472. +    reg.Free;
  2473. +  end;
  2474. +end;
  2475. +
  2476. +class function TRecycleBinManager.RecyclerGlobalGetPercentUsage: integer;
  2477. +var
  2478. +  reg: TRegistry;
  2479. +  dump: string;
  2480. +const
  2481. +  RES_DEFAULT = 10;
  2482. +begin
  2483. +  result := -1;
  2484. +
  2485. +  reg := TRegistry.Create;
  2486. +  try
  2487. +    reg.RootKey := HKEY_LOCAL_MACHINE;
  2488. +
  2489. +    if reg.OpenKeyReadOnly('SOFTWARE\Microsoft\Windows\CurrentVersion\explorer\BitBucket') then
  2490. +    begin
  2491. +      if reg.ValueExists('Percent') then
  2492. +      begin
  2493. +        // Windows 2000 - Informationen liegen aufgeschlüsselt in der Registry
  2494. +
  2495. +        result := reg.ReadInteger('Percent');
  2496. +      end
  2497. +      else if reg.ValueExists('PurgeInfo') then
  2498. +      begin
  2499. +        // Windows 95 - Verschlüsselte Informationen liegen in PurgeInfo
  2500. +
  2501. +        dump := _registryReadDump(reg, 'PurgeInfo');
  2502. +        result := Ord(dump[63]);
  2503. +      end
  2504. +      else
  2505. +      begin
  2506. +        // Windows 95 - Standardwerte sind gegeben, deswegen existiert kein PurgeInfo
  2507. +
  2508. +        result := RES_DEFAULT; // Standardeinstellung bei Windows
  2509. +      end;
  2510. +
  2511. +      reg.CloseKey;
  2512. +    end;
  2513. +  finally
  2514. +    reg.Free;
  2515. +  end;
  2516. +end;
  2517. +
  2518. +class function TRecycleBinManager.RecyclerSpecificGetPercentUsage(Drive: Char): integer;
  2519. +var
  2520. +  reg: TRegistry;
  2521. +  dump: string;
  2522. +const
  2523. +  RES_DEFAULT = 10;
  2524. +begin
  2525. +  result := -1;
  2526. +
  2527. +  reg := TRegistry.Create;
  2528. +  try
  2529. +    reg.RootKey := HKEY_LOCAL_MACHINE;
  2530. +
  2531. +    if reg.OpenKeyReadOnly('SOFTWARE\Microsoft\Windows\CurrentVersion\explorer\BitBucket') then
  2532. +    begin
  2533. +      if reg.OpenKeyReadOnly(Drive) then
  2534. +      begin
  2535. +        if reg.ValueExists('Percent') then
  2536. +        begin
  2537. +          // Windows 2000 - Informationen liegen aufgeschlüsselt in der Registry
  2538. +
  2539. +          result := reg.ReadInteger('Percent');
  2540. +        end
  2541. +        else
  2542. +        begin
  2543. +          result := RES_DEFAULT;
  2544. +        end;
  2545. +        reg.CloseKey;
  2546. +      end
  2547. +      else
  2548. +      begin
  2549. +        if reg.ValueExists('PurgeInfo') then
  2550. +        begin
  2551. +          // Windows 95 - Verschlüsselte Informationen liegen in PurgeInfo
  2552. +
  2553. +          dump := _registryReadDump(reg, 'PurgeInfo');
  2554. +
  2555. +          // NOT tested, only theoretical! My idea about the possible structure is:
  2556. +          // 0x08 = Drive A
  2557. +          // 0x0a = Drive B
  2558. +          // 0x0c = Drive C (validated)
  2559. +          // 0x0e = Drive D
  2560. +          // ...
  2561. +
  2562. +          result := Ord(dump[9+_DriveNum(Drive)*2]);
  2563. +        end
  2564. +        else
  2565. +        begin
  2566. +          // Windows 95 - Standardwerte sind gegeben, deswegen existiert kein PurgeInfo
  2567. +
  2568. +          result := RES_DEFAULT; // Standardeinstellung bei Windows
  2569. +        end;
  2570. +      end;
  2571. +
  2572. +      reg.CloseKey;
  2573. +    end;
  2574. +  finally
  2575. +    reg.Free;
  2576. +  end;
  2577. +end;
  2578. +
  2579. +class function TRecycleBinManager.RecyclerGetPercentUsageAutoDeterminate(Drive: Char): integer;
  2580. +var
  2581. +  gpSetting: integer;
  2582. +begin
  2583. +  gpSetting := RecyclerGroupPolicyRecycleBinSize;
  2584. +  if gpSetting <> -1 then
  2585. +    result := gpSetting
  2586. +  else if RecyclerHasGlobalSettings then
  2587. +    result := RecyclerGlobalGetPercentUsage
  2588. +  else
  2589. +    result := RecyclerSpecificGetPercentUsage(Drive);
  2590. +end;
  2591. +
  2592. +class function TRecycleBinManager.RecyclerGlobalIsNukeOnDelete: boolean;
  2593. +var
  2594. +  reg: TRegistry;
  2595. +  dump: string;
  2596. +const
  2597. +  RES_DEFAULT = false;
  2598. +begin
  2599. +  result := false;
  2600. +
  2601. +  reg := TRegistry.Create;
  2602. +  try
  2603. +    reg.RootKey := HKEY_LOCAL_MACHINE;
  2604. +
  2605. +    if reg.OpenKeyReadOnly('SOFTWARE\Microsoft\Windows\CurrentVersion\explorer\BitBucket') then
  2606. +    begin
  2607. +      if reg.ValueExists('NukeOnDelete') then
  2608. +      begin
  2609. +        // Windows 2000 - Informationen liegen aufgeschlüsselt in der Registry
  2610. +
  2611. +        result := reg.ReadBool('NukeOnDelete');
  2612. +      end
  2613. +      else if reg.ValueExists('PurgeInfo') then
  2614. +      begin
  2615. +        // Windows 95 - Verschlüsselte Informationen liegen in PurgeInfo
  2616. +
  2617. +        // See comment at RecyclerSpecificIsNukeOnDelete()
  2618. +
  2619. +        dump := _registryReadDump(reg, 'PurgeInfo');
  2620. +        result := GetAnsiCharBit(dump[68], 3);
  2621. +      end
  2622. +      else
  2623. +      begin
  2624. +        // Windows 95 - Standardwerte sind gegeben, deswegen existiert kein PurgeInfo
  2625. +
  2626. +        result := RES_DEFAULT; // Standardeinstellung bei Windows
  2627. +      end;
  2628. +
  2629. +      reg.CloseKey;
  2630. +    end;
  2631. +  finally
  2632. +    reg.Free;
  2633. +  end;
  2634. +end;
  2635. +
  2636. +class function TRecycleBinManager.RecyclerSpecificIsNukeOnDelete(Drive: Char): boolean;
  2637. +var
  2638. +  reg: TRegistry;
  2639. +  dump: string;
  2640. +  d: Byte;
  2641. +const
  2642. +  RES_DEFAULT = false;
  2643. +begin
  2644. +  result := false;
  2645. +
  2646. +  reg := TRegistry.Create;
  2647. +  try
  2648. +    reg.RootKey := HKEY_LOCAL_MACHINE;
  2649. +
  2650. +    if reg.OpenKeyReadOnly('SOFTWARE\Microsoft\Windows\CurrentVersion\explorer\BitBucket') then
  2651. +    begin
  2652. +      if reg.OpenKeyReadOnly(Drive) then
  2653. +      begin
  2654. +        if reg.ValueExists('NukeOnDelete') then
  2655. +        begin
  2656. +          // Windows 2000 - Informationen liegen aufgeschlüsselt in der Registry
  2657. +
  2658. +          result := reg.ReadBool('NukeOnDelete');
  2659. +        end;
  2660. +        reg.CloseKey;
  2661. +      end
  2662. +      else
  2663. +      begin
  2664. +        if reg.ValueExists('PurgeInfo') then
  2665. +        begin
  2666. +          // Windows 95 - Verschlüsselte Informationen liegen in PurgeInfo
  2667. +
  2668. +          dump := _registryReadDump(reg, 'PurgeInfo');
  2669. +
  2670. +          // NOT tested, only theoretical! My idea about the possible structure is:
  2671. +          //
  2672. +          // Byte      0x40       0x41       0x42       0x43
  2673. +          // Bit       76543210   76543210   76543210   76543210
  2674. +          //           --------   --------   --------   --------
  2675. +          // Meaning   hgfedcba   ponmlkji   xwvutsrq   ????G?zy
  2676. +          //
  2677. +          // a..z = Drives
  2678. +          // G    = global settings
  2679. +          //
  2680. +          // Already validated:
  2681. +          // 0x64 = 04 (00000100)
  2682. +          // 0x67 = 08 (00001000)
  2683. +
  2684. +          d := _DriveNum(Drive);
  2685. +          result := GetAnsiCharBit(dump[65+(d div 7)], d mod 7);
  2686. +        end
  2687. +        else
  2688. +        begin
  2689. +          // Windows 95 - Standardwerte sind gegeben, deswegen existiert kein PurgeInfo
  2690. +
  2691. +          result := RES_DEFAULT; // Standardeinstellung bei Windows
  2692. +        end;
  2693. +      end;
  2694. +
  2695. +      reg.CloseKey;
  2696. +    end;
  2697. +  finally
  2698. +    reg.Free;
  2699. +  end;
  2700. +end;
  2701. +
  2702. +class function TRecycleBinManager.RecyclerIsNukeOnDeleteAutoDeterminate(Drive: Char): boolean;
  2703. +begin
  2704. +  if RecyclerGroupPolicyNoRecycleFiles = gpEnabled then
  2705. +    result := true
  2706. +  else if RecyclerHasGlobalSettings then
  2707. +    result := RecyclerGlobalIsNukeOnDelete
  2708. +  else
  2709. +    result := RecyclerSpecificIsNukeOnDelete(Drive);
  2710. +end;
  2711. +
  2712. +class function TRecycleBinManager.RecyclerHasGlobalSettings: boolean;
  2713. +var
  2714. +  reg: TRegistry;
  2715. +  dump: string;
  2716. +begin
  2717. +  result := false;
  2718. +  
  2719. +  reg := TRegistry.Create;
  2720. +  try
  2721. +    reg.RootKey := HKEY_LOCAL_MACHINE;
  2722. +
  2723. +    if reg.OpenKeyReadOnly('SOFTWARE\Microsoft\Windows\CurrentVersion\explorer\BitBucket') then
  2724. +    begin
  2725. +      if reg.ValueExists('UseGlobalSettings') then
  2726. +      begin
  2727. +        // Windows 2000 - Informationen liegen aufgeschlüsselt in der Registry
  2728. +
  2729. +        result := reg.ReadBool('UseGlobalSettings');
  2730. +      end
  2731. +      else if reg.ValueExists('PurgeInfo') then
  2732. +      begin
  2733. +        // Windows 95 - Verschlüsselte Informationen liegen in PurgeInfo
  2734. +        // TODO: Gibt es ein offizielles Dokument oder ein API, indem PurgeInfo
  2735. +        // offiziell entschlüsselbar ist?
  2736. +
  2737. +        dump := _registryReadDump(reg, 'PurgeInfo');
  2738. +        if dump[5] = #$01 then
  2739. +          result := true
  2740. +        else if dump[5] = #$00 then
  2741. +          result := false
  2742. +        else
  2743. +          raise EUnknownState.Create(Format(LNG_UNEXPECTED_STATE, ['PurgeInfo']));
  2744. +      end
  2745. +      else
  2746. +      begin
  2747. +        // Windows 95 - Standardwerte sind gegeben, deswegen existiert kein PurgeInfo
  2748. +
  2749. +        result := true; // Standardeinstellung bei Windows
  2750. +      end;
  2751. +
  2752. +      reg.CloseKey;
  2753. +    end;
  2754. +  finally
  2755. +    reg.Free;
  2756. +  end;
  2757. +end;
  2758. +
  2759. +
  2760. +class function TRecycleBinManager.RecyclerGetNumItems: int64;
  2761. +var
  2762. +  Drive: Char;
  2763. +begin
  2764. +  result := 0;
  2765. +  for Drive := 'A' to 'Z' do
  2766. +  begin
  2767. +    if RecyclerIsPossible(Drive) then
  2768. +    begin
  2769. +      result := result + RecyclerGetNumItems(Drive);
  2770. +    end;
  2771. +  end;
  2772. +end;
  2773. +
  2774. +class function TRecycleBinManager.RecyclerGetNumItems(Drive: Char): int64;
  2775. +begin
  2776. +  result := RecyclerGetAPIInfo(Drive).i64NumItems;
  2777. +end;
  2778. +
  2779. +class function TRecycleBinManager.RecyclerGetSize: int64;
  2780. +var
  2781. +  Drive: Char;
  2782. +begin
  2783. +  result := 0;
  2784. +  for Drive := 'A' to 'Z' do
  2785. +  begin
  2786. +    if RecyclerIsPossible(Drive) then
  2787. +    begin
  2788. +      result := result + RecyclerGetSize(Drive);
  2789. +    end;
  2790. +  end;
  2791. +end;
  2792. +
  2793. +class function TRecycleBinManager.RecyclerGetSize(Drive: Char): int64;
  2794. +begin
  2795. +  result := RecyclerGetAPIInfo(Drive).i64Size;
  2796. +end;
  2797. +
  2798. +class function TRecycleBinManager.RecyclerGetAPIInfo(Drive: Char): TSHQueryRBInfo;
  2799. +begin
  2800. +  result := RecyclerGetAPIInfo(Drive + ':\');
  2801. +end;
  2802. +
  2803. +const
  2804. +  C_SHQueryRecycleBin = 'SHQueryRecycleBinA';
  2805. +
  2806. +type
  2807. +  TSHQueryRecycleBin = function(pszRootPath: LPCTSTR;
  2808. +    var pSHQueryRBInfo: TSHQueryRBInfo): HRESULT; stdcall;
  2809. +
  2810. +class function TRecycleBinManager.RecyclerGetAPIInfo(Path: String): TSHQueryRBInfo;
  2811. +var
  2812. +  PSHQueryRecycleBin: TSHQueryRecycleBin;
  2813. +  RBHandle: THandle;
  2814. +  res: HRESULT;
  2815. +begin
  2816. +  PSHQueryRecycleBin := nil;
  2817. +
  2818. +  // Ref: http://www.delphipraxis.net/post1291.html
  2819. +
  2820. +  RBHandle := LoadLibrary(shell32);
  2821. +  if(RBHandle <> 0) then
  2822. +  begin
  2823. +    PSHQueryRecycleBin := GetProcAddress(RBHandle, C_SHQueryRecycleBin);
  2824. +    if(@PSHQueryRecycleBin = nil) then
  2825. +    begin
  2826. +      FreeLibrary(RBHandle);
  2827. +      RBHandle := 0;
  2828. +    end;
  2829. +  end;
  2830. +
  2831. +  fillchar(result, SizeOf(TSHQueryRBInfo),0);
  2832. +  result.cbSize := SizeOf(TSHQueryRBInfo);
  2833. +
  2834. +  if (RBHandle <> 0) and (Assigned(PSHQueryRecycleBin)) then
  2835. +  begin
  2836. +    res := PSHQueryRecycleBin(PChar(Path), result);
  2837. +    // if Succeeded(res) then
  2838. +    if res = S_OK then
  2839. +    begin
  2840. +      // Alles OK, unser result hat nun die gewünschten Daten.
  2841. +    end
  2842. +    else
  2843. +    begin
  2844. +      // Since Windows Vista, SHQueryRecycleBin will fail with E_FAIL (80004005)
  2845. +      // if Path is a floppy or CD drive...
  2846. +      raise EAPICallError.CreateFmt(LNG_API_CALL_ERROR, [Format(LNG_ERROR_CODE, [C_SHQueryRecycleBin, Path, '0x'+IntToHex(res, 2*SizeOf(HRESULT))])]);
  2847. +    end;
  2848. +  end
  2849. +  else
  2850. +    raise EAPICallError.CreateFmt(LNG_API_CALL_ERROR, [Format(LNG_NOT_CALLABLE, [C_SHQueryRecycleBin])]);
  2851. +
  2852. +  if (RBHandle <> 0) then FreeLibrary(RBHandle);
  2853. +end;
  2854. +
  2855. +class function TRecycleBinManager.RecyclerGetCLSID: string;
  2856. +begin
  2857. +  result := RECYCLER_CLSID;
  2858. +end;
  2859. +
  2860. +// Windows 95 without Internet Explorer 4 has no SHQueryRecycleBinA.
  2861. +class function TRecycleBinManager.RecyclerQueryFunctionAvailable: boolean;
  2862. +var
  2863. +  RBHandle: THandle;
  2864. +  SHQueryRecycleBin: TSHQueryRecycleBin;
  2865. +begin
  2866. +  RBHandle := LoadLibrary(shell32);
  2867. +  if(RBHandle <> 0) then
  2868. +  begin
  2869. +    SHQueryRecycleBin := GetProcAddress(RBHandle, C_SHQueryRecycleBin);
  2870. +    if(@SHQueryRecycleBin = nil) then
  2871. +    begin
  2872. +      FreeLibrary(RBHandle);
  2873. +      RBHandle := 0;
  2874. +    end;
  2875. +  end;
  2876. +
  2877. +  result := RBHandle <> 0;
  2878. +end;
  2879. +
  2880. +const
  2881. +  GroupPolicyAcceptHKLMTrick = true;
  2882. +
  2883. +// TODO: In future also detect for other users
  2884. +// TODO: Also make a setter (inkl. Message to Windows Explorer?)
  2885. +class function TRecycleBinManager.RecyclerGroupPolicyNoRecycleFiles: GPOLICYBOOL;
  2886. +var
  2887. +  reg: TRegistry;
  2888. +begin
  2889. +  result := gpUndefined;
  2890. +
  2891. +  reg := TRegistry.Create;
  2892. +  try
  2893. +    // If a value is set in HKEY_LOCAL_MACHINE, it will be prefered,
  2894. +    // even if gpedit.msc shows "Not configured"!
  2895. +    if GroupPolicyAcceptHKLMTrick then
  2896. +    begin
  2897. +      reg.RootKey := HKEY_LOCAL_MACHINE;
  2898. +      if reg.OpenKeyReadOnly('Software\Microsoft\Windows\CurrentVersion\Policies\Explorer') then
  2899. +      begin
  2900. +        if reg.ValueExists('NoRecycleFiles') then
  2901. +        begin
  2902. +          if reg.ReadBool('NoRecycleFiles') then
  2903. +            result := gpEnabled
  2904. +          else
  2905. +            result := gpDisabled;
  2906. +          Exit;
  2907. +        end;
  2908. +        reg.CloseKey;
  2909. +      end;
  2910. +    end;
  2911. +
  2912. +    reg.RootKey := HKEY_CURRENT_USER;
  2913. +    if reg.OpenKeyReadOnly('Software\Microsoft\Windows\CurrentVersion\Policies\Explorer') then
  2914. +    begin
  2915. +      if reg.ValueExists('NoRecycleFiles') then
  2916. +      begin
  2917. +        if reg.ReadBool('NoRecycleFiles') then
  2918. +          result := gpEnabled
  2919. +        else
  2920. +          result := gpDisabled;
  2921. +      end;
  2922. +      reg.CloseKey;
  2923. +    end;
  2924. +  finally
  2925. +    reg.Free;
  2926. +  end;
  2927. +end;
  2928. +
  2929. +// TODO: In future also detect for other users
  2930. +// TODO: Also make a setter (inkl. Message to Windows Explorer?)
  2931. +class function TRecycleBinManager.RecyclerGroupPolicyConfirmFileDelete: GPOLICYBOOL;
  2932. +var
  2933. +  reg: TRegistry;
  2934. +begin
  2935. +  result := gpUndefined;
  2936. +  reg := TRegistry.Create;
  2937. +  try
  2938. +    // If a value is set in HKEY_LOCAL_MACHINE, it will be prefered,
  2939. +    // even if gpedit.msc shows "Not configured"!
  2940. +    if GroupPolicyAcceptHKLMTrick then
  2941. +    begin
  2942. +      reg.RootKey := HKEY_LOCAL_MACHINE;
  2943. +      if reg.OpenKeyReadOnly('Software\Microsoft\Windows\CurrentVersion\Policies\Explorer') then
  2944. +      begin
  2945. +        if reg.ValueExists('ConfirmFileDelete') then
  2946. +        begin
  2947. +          if reg.ReadBool('ConfirmFileDelete') then
  2948. +            result := gpEnabled
  2949. +          else
  2950. +            result := gpDisabled;
  2951. +          Exit;
  2952. +        end;
  2953. +        reg.CloseKey;
  2954. +      end;
  2955. +    end;
  2956. +
  2957. +    reg.RootKey := HKEY_CURRENT_USER;
  2958. +    if reg.OpenKeyReadOnly('Software\Microsoft\Windows\CurrentVersion\Policies\Explorer') then
  2959. +    begin
  2960. +      if reg.ValueExists('ConfirmFileDelete') then
  2961. +      begin
  2962. +        if reg.ReadBool('ConfirmFileDelete') then
  2963. +          result := gpEnabled
  2964. +        else
  2965. +          result := gpDisabled;
  2966. +      end;
  2967. +      reg.CloseKey;
  2968. +    end;
  2969. +  finally
  2970. +    reg.Free;
  2971. +  end;
  2972. +end;
  2973. +
  2974. +
  2975. +// TODO: In future also detect for other users
  2976. +// TODO: Also make a setter (inkl. Message to Windows Explorer?)
  2977. +class function TRecycleBinManager.RecyclerGroupPolicyRecycleBinSize: integer;
  2978. +var
  2979. +  reg: TRegistry;
  2980. +begin
  2981. +  result := -1;
  2982. +  reg := TRegistry.Create;
  2983. +  try
  2984. +    // If a value is set in HKEY_LOCAL_MACHINE, it will be prefered,
  2985. +    // even if gpedit.msc shows "Not configured"!
  2986. +    if GroupPolicyAcceptHKLMTrick then
  2987. +    begin
  2988. +      reg.RootKey := HKEY_LOCAL_MACHINE;
  2989. +      if reg.OpenKeyReadOnly('Software\Microsoft\Windows\CurrentVersion\Policies\Explorer') then
  2990. +      begin
  2991. +        if reg.ValueExists('RecycleBinSize') then
  2992. +        begin
  2993. +          result := reg.ReadInteger('RecycleBinSize');
  2994. +          Exit;
  2995. +        end;
  2996. +        reg.CloseKey;
  2997. +      end;
  2998. +    end;
  2999. +
  3000. +    reg.RootKey := HKEY_CURRENT_USER;
  3001. +    if reg.OpenKeyReadOnly('Software\Microsoft\Windows\CurrentVersion\Policies\Explorer') then
  3002. +    begin
  3003. +      if reg.ValueExists('RecycleBinSize') then
  3004. +      begin
  3005. +        result := reg.ReadInteger('RecycleBinSize');
  3006. +      end;
  3007. +      reg.CloseKey;
  3008. +    end;
  3009. +  finally
  3010. +    reg.Free;
  3011. +  end;
  3012. +end;
  3013. +
  3014. +function GPBoolToString(value: GPOLICYBOOL): String;
  3015. +begin
  3016. +  case value of
  3017. +    gpUndefined: result := 'Not configured';
  3018. +    gpEnabled: result := 'Enabled';
  3019. +    gpDisabled: result := 'Disabled';
  3020. +  end;
  3021. +end;
  3022. +
  3023. +class function TRecycleBinManager.RecyclerIsPossible(Drive: Char): boolean;
  3024. +var
  3025. +  typ: Integer;
  3026. +begin
  3027. +  typ := GetDriveType(PChar(Drive + ':\'));
  3028. +  result := typ = DRIVE_FIXED;
  3029. +end;
  3030. +
  3031. +class function TRecycleBinManager.RecyclerLibraryVersion: string;
  3032. +begin
  3033. +  result := 'ViaThinkSoft Recycle Bin Unit [05 JUL 2010]';
  3034. +end;
  3035. +
  3036. +end.
  3037. +
  3038. Index: Main.dfm
  3039. ===================================================================
  3040. --- Main.dfm    (revision 35)
  3041. +++ Main.dfm    (working copy)
  3042. @@ -5,8 +5,8 @@
  3043.    ClientHeight = 459
  3044.    ClientWidth = 636
  3045.    Color = clBtnFace
  3046. -  Constraints.MinHeight = 495
  3047. -  Constraints.MinWidth = 652
  3048. +  Constraints.MinHeight = 493
  3049. +  Constraints.MinWidth = 644
  3050.    Font.Charset = DEFAULT_CHARSET
  3051.    Font.Color = clWindowText
  3052.    Font.Height = -11
  3053. Index: Main.pas
  3054. ===================================================================
  3055. --- Main.pas    (revision 35)
  3056. +++ Main.pas    (working copy)
  3057. @@ -116,7 +116,7 @@
  3058.    outputMemo.Lines.Add(tmp);
  3059.    outputMemo.lines.add('');
  3060.  
  3061. -  if not RecyclerIsValid(filename) then
  3062. +  if not TRecycleBinManager.RecyclerIsValid(filename) then
  3063.    begin
  3064.      outputMemo.lines.add('Recycler is not valid.');
  3065.      outputMemo.lines.add('');
  3066. @@ -125,7 +125,7 @@
  3067.    begin
  3068.      x := TStringList.Create;
  3069.      try
  3070. -      RecyclerListIndexes(filename, x);
  3071. +      TRecycleBinManager.RecyclerListIndexes(filename, x);
  3072.        if x.Count = 0 then
  3073.        begin
  3074.          outputMemo.lines.add('No items available.');
  3075. @@ -133,7 +133,7 @@
  3076.        end;
  3077.        for i := 0 to x.Count - 1 do
  3078.        begin
  3079. -        fn := RecyclerCurrentFilenameAndPath(tmp, x[i]);
  3080. +        fn := TRecycleBinManager.RecyclerCurrentFilenameAndPath(tmp, x[i]);
  3081.          outputMemo.lines.add(inttostr(i+1)+'. Entry');
  3082.          outputMemo.lines.add('# Unique ID: ' + changefileext(x[i], ''));
  3083.          outputMemo.lines.add('# Recycler filename: '+fn);
  3084. @@ -145,18 +145,18 @@
  3085.  
  3086.          {$IFDEF DEL6UP}
  3087.          outputMemo.lines.add('# Deleted: '+
  3088. -          datetimetostr(RecyclerGetDateTime(tmp, x[i])));
  3089. +          datetimetostr(TRecycleBinManager.RecyclerGetDateTime(tmp, x[i])));
  3090.          {$ELSE}
  3091.          outputMemo.lines.add('# Deleted: You have to compile this demo with Delphi 6 or higher.');
  3092.          {$ENDIF}
  3093.          outputMemo.lines.add('# Original filename: '+
  3094. -          RecyclerGetSource(tmp, x[i]));
  3095. +          TRecycleBinManager.RecyclerGetSource(tmp, x[i]));
  3096.          outputMemo.lines.add('# Unicode filename: '+
  3097. -          RecyclerGetSourceUnicode(tmp, x[i]));
  3098. +          TRecycleBinManager.RecyclerGetSourceUnicode(tmp, x[i]));
  3099.          outputMemo.lines.add('# Source device: '+
  3100. -          RecyclerGetSourceDrive(tmp, x[i]));
  3101. +          TRecycleBinManager.RecyclerGetSourceDrive(tmp, x[i]));
  3102.          outputMemo.lines.add('# Original size on disk: '+
  3103. -          inttostr(RecyclerOriginalSize(tmp, x[i]))+' Byte');
  3104. +          inttostr(TRecycleBinManager.RecyclerOriginalSize(tmp, x[i]))+' Byte');
  3105.          outputMemo.lines.add('');
  3106.        end;
  3107.      finally
  3108. @@ -189,7 +189,7 @@
  3109.      outputMemo.Clear;
  3110.      x := TStringList.Create;
  3111.      try
  3112. -      RecyclerGetAllRecyclerDrives(x);
  3113. +      TRecycleBinManager.RecyclerGetAllRecyclerDrives(x);
  3114.        somethingfound := false;
  3115.        if x.Count > 0 then
  3116.        begin
  3117. @@ -199,7 +199,7 @@
  3118.  
  3119.            sl := TStringList.Create;
  3120.            try
  3121. -            RecyclerGetInfofiles(x[i][1], true, sl);
  3122. +            TRecycleBinManager.RecyclerGetInfofiles(x[i][1], true, sl);
  3123.              if sl.Count > 0 then
  3124.              begin
  3125.                for j := 0 to sl.Count - 1 do
  3126. @@ -246,7 +246,7 @@
  3127.  
  3128.      outputMemo.Clear;
  3129.  
  3130. -    outputMemo.Lines.Add(RecyclerLibraryVersion);
  3131. +    outputMemo.Lines.Add(TRecycleBinManager.RecyclerLibraryVersion);
  3132.  
  3133.      outputMemo.Lines.Add('');
  3134.      outputMemo.Lines.Add('= Possible recyclers (fixed drives) =');
  3135. @@ -254,7 +254,7 @@
  3136.  
  3137.      for d := 'A' to 'Z' do
  3138.      begin
  3139. -      outputMemo.Lines.Add('Recycler is possible at drive '+d+': ' + _BoolToYesNo(RecyclerIsPossible(d)));
  3140. +      outputMemo.Lines.Add('Recycler is possible at drive '+d+': ' + _BoolToYesNo(TRecycleBinManager.RecyclerIsPossible(d)));
  3141.      end;
  3142.  
  3143.      outputMemo.Lines.Add('');
  3144. @@ -263,24 +263,24 @@
  3145.  
  3146.      for d := 'A' to 'Z' do
  3147.      begin
  3148. -      outputMemo.Lines.Add('Drive '+d+': ' + _BoolToYesNo(RecyclerIsValid(d)));
  3149. +      outputMemo.Lines.Add('Drive '+d+': ' + _BoolToYesNo(TRecycleBinManager.RecyclerIsValid(d)));
  3150.      end;
  3151.  
  3152.      outputMemo.Lines.Add('');
  3153.      outputMemo.Lines.Add('= Current status =');
  3154.      outputMemo.Lines.Add('');
  3155.  
  3156. -    if RecyclerQueryFunctionAvailable then
  3157. +    if TRecycleBinManager.RecyclerQueryFunctionAvailable then
  3158.      begin
  3159. -      outputMemo.Lines.Add('GLOBAL Empty = ' + _BoolToYesNo(RecyclerIsEmpty));
  3160. -      outputMemo.Lines.Add('GLOBAL Number of items = ' + IntToStr(RecyclerGetNumItems));
  3161. -      outputMemo.Lines.Add('GLOBAL Size = ' + IntToStr(RecyclerGetSize) + ' Bytes');
  3162. +      outputMemo.Lines.Add('GLOBAL Empty = ' + _BoolToYesNo(TRecycleBinManager.RecyclerIsEmpty));
  3163. +      outputMemo.Lines.Add('GLOBAL Number of items = ' + IntToStr(TRecycleBinManager.RecyclerGetNumItems));
  3164. +      outputMemo.Lines.Add('GLOBAL Size = ' + IntToStr(TRecycleBinManager.RecyclerGetSize) + ' Bytes');
  3165.        for d := 'A' to 'Z' do
  3166.        begin
  3167. -        if not RecyclerIsPossible(d) then Continue; // Important since Windows Vista throws Exceptions!
  3168. -        outputMemo.Lines.Add('Drive '+d+' Empty = ' + _BoolToYesNo(RecyclerIsEmpty(d)));
  3169. -        outputMemo.Lines.Add('Drive '+d+' Number of items = ' + IntToStr(RecyclerGetNumItems(d)));
  3170. -        outputMemo.Lines.Add('Drive '+d+' Size = ' + IntToStr(RecyclerGetSize(d)) + ' Bytes');
  3171. +        if not TRecycleBinManager.RecyclerIsPossible(d) then Continue; // Important since Windows Vista throws Exceptions!
  3172. +        outputMemo.Lines.Add('Drive '+d+' Empty = ' + _BoolToYesNo(TRecycleBinManager.RecyclerIsEmpty(d)));
  3173. +        outputMemo.Lines.Add('Drive '+d+' Number of items = ' + IntToStr(TRecycleBinManager.RecyclerGetNumItems(d)));
  3174. +        outputMemo.Lines.Add('Drive '+d+' Size = ' + IntToStr(TRecycleBinManager.RecyclerGetSize(d)) + ' Bytes');
  3175.        end;
  3176.      end
  3177.      else
  3178. @@ -293,42 +293,42 @@
  3179.      outputMemo.Lines.Add('= Name and Infotips =');
  3180.      outputMemo.Lines.Add('');
  3181.  
  3182. -    outputMemo.Lines.Add('Name: '+RecyclerGetName());
  3183. -    outputMemo.Lines.Add('Info Tip: '+RecyclerGetInfoTip());
  3184. -    outputMemo.Lines.Add('Intro Text: '+RecyclerGetIntroText());
  3185. -    outputMemo.Lines.Add('Class-ID: '+RecyclerGetCLSID());
  3186. +    outputMemo.Lines.Add('Name: '+TRecycleBinManager.RecyclerGetName());
  3187. +    outputMemo.Lines.Add('Info Tip: '+TRecycleBinManager.RecyclerGetInfoTip());
  3188. +    outputMemo.Lines.Add('Intro Text: '+TRecycleBinManager.RecyclerGetIntroText());
  3189. +    outputMemo.Lines.Add('Class-ID: '+TRecycleBinManager.RecyclerGetCLSID());
  3190.  
  3191.      outputMemo.Lines.Add('');
  3192.      outputMemo.Lines.Add('= Icons =');
  3193.      outputMemo.Lines.Add('');
  3194.  
  3195. -    outputMemo.Lines.Add('Default Icon: '+RecyclerGetDefaultIconString());
  3196. -    if RecyclerQueryFunctionAvailable then
  3197. +    outputMemo.Lines.Add('Default Icon: '+TRecycleBinManager.RecyclerGetDefaultIconString());
  3198. +    if TRecycleBinManager.RecyclerQueryFunctionAvailable then
  3199.      begin
  3200. -      outputMemo.Lines.Add('Current Icon (Empty / Full): '+RecyclerGetCurrentIconString());
  3201. +      outputMemo.Lines.Add('Current Icon (Empty / Full): '+TRecycleBinManager.RecyclerGetCurrentIconString());
  3202.      end
  3203.      else
  3204.      begin
  3205.        outputMemo.Lines.Add('Current Icon (Empty / Full):');
  3206.        outputMemo.Lines.Add('        Functionality not working with your operating system.');
  3207.      end;
  3208. -    outputMemo.Lines.Add('Full Icon: '+RecyclerGetFullIconString());
  3209. -    outputMemo.Lines.Add('Empty Icon: '+RecyclerGetEmptyIconString());
  3210. +    outputMemo.Lines.Add('Full Icon: '+TRecycleBinManager.RecyclerGetFullIconString());
  3211. +    outputMemo.Lines.Add('Empty Icon: '+TRecycleBinManager.RecyclerGetEmptyIconString());
  3212.  
  3213.      outputMemo.Lines.Add('');
  3214.      outputMemo.Lines.Add('= Events =');
  3215.      outputMemo.Lines.Add('');
  3216.  
  3217. -    outputMemo.Lines.Add('Empty Event Name: '+RecyclerEmptyEventGetName());
  3218. -    outputMemo.Lines.Add('Empty Event Current Sound: '+RecyclerEmptyEventGetCurrentSound());
  3219. -    outputMemo.Lines.Add('Empty Event Default Sound: '+RecyclerEmptyEventGetDefaultSound());
  3220. +    outputMemo.Lines.Add('Empty Event Name: '+TRecycleBinManager.RecyclerEmptyEventGetName());
  3221. +    outputMemo.Lines.Add('Empty Event Current Sound: '+TRecycleBinManager.RecyclerEmptyEventGetCurrentSound());
  3222. +    outputMemo.Lines.Add('Empty Event Default Sound: '+TRecycleBinManager.RecyclerEmptyEventGetDefaultSound());
  3223.  
  3224.      sl := TStringList.Create;
  3225.      try
  3226. -      RecyclerEmptyEventGetSoundCategories(sl);
  3227. +      TRecycleBinManager.RecyclerEmptyEventGetSoundCategories(sl);
  3228.        for i := 0 to sl.Count - 1 do
  3229.        begin
  3230. -        outputMemo.Lines.Add(Format('Event "%s" = %s', [sl.Strings[i], RecyclerEmptyEventGetSound(sl.Strings[i])]));
  3231. +        outputMemo.Lines.Add(Format('Event "%s" = %s', [sl.Strings[i], TRecycleBinManager.RecyclerEmptyEventGetSound(sl.Strings[i])]));
  3232.        end;
  3233.      finally
  3234.        sl.Free;
  3235. @@ -338,37 +338,37 @@
  3236.      outputMemo.Lines.Add('= Nuke on Delete =');
  3237.      outputMemo.Lines.Add('');
  3238.  
  3239. -    outputMemo.Lines.Add('Group policy setting: ' + GPBoolToString(RecyclerGroupPolicyNoRecycleFiles));
  3240. -    outputMemo.Lines.Add('Global settings selected: ' + _BoolToYesNo(RecyclerHasGlobalSettings));
  3241. -    outputMemo.Lines.Add('Global setting: ' + _BoolToEnabledDisabled(RecyclerGlobalIsNukeOnDelete()));
  3242. +    outputMemo.Lines.Add('Group policy setting: ' + GPBoolToString(TRecycleBinManager.RecyclerGroupPolicyNoRecycleFiles));
  3243. +    outputMemo.Lines.Add('Global settings selected: ' + _BoolToYesNo(TRecycleBinManager.RecyclerHasGlobalSettings));
  3244. +    outputMemo.Lines.Add('Global setting: ' + _BoolToEnabledDisabled(TRecycleBinManager.RecyclerGlobalIsNukeOnDelete()));
  3245.      for d := 'A' to 'Z' do
  3246.      begin
  3247.        // if not RecyclerIsPossible(d) then Continue;
  3248. -      outputMemo.Lines.Add('Individual setting for drive '+d+': ' + _BoolToEnabledDisabled(RecyclerSpecificIsNukeOnDelete(d)));
  3249. -      outputMemo.Lines.Add('Auto determinated setting for drive '+d+' (includes group policy and global setting): ' + _BoolToEnabledDisabled(RecyclerIsNukeOnDeleteAutoDeterminate(d)));
  3250. +      outputMemo.Lines.Add('Individual setting for drive '+d+': ' + _BoolToEnabledDisabled(TRecycleBinManager.RecyclerSpecificIsNukeOnDelete(d)));
  3251. +      outputMemo.Lines.Add('Auto determinated setting for drive '+d+' (includes group policy and global setting): ' + _BoolToEnabledDisabled(TRecycleBinManager.RecyclerIsNukeOnDeleteAutoDeterminate(d)));
  3252.      end;
  3253.  
  3254.      outputMemo.Lines.Add('');
  3255.      outputMemo.Lines.Add('= Usage Percent =');
  3256.      outputMemo.Lines.Add('');
  3257.  
  3258. -    outputMemo.Lines.Add('Group policy setting: ' + IntToStr(RecyclerGroupPolicyRecycleBinSize));
  3259. -    outputMemo.Lines.Add('Global settings selected: ' + _BoolToYesNo(RecyclerHasGlobalSettings));
  3260. -    outputMemo.Lines.Add('Global setting: ' + IntToStr(RecyclerGlobalGetPercentUsage()));
  3261. +    outputMemo.Lines.Add('Group policy setting: ' + IntToStr(TRecycleBinManager.RecyclerGroupPolicyRecycleBinSize));
  3262. +    outputMemo.Lines.Add('Global settings selected: ' + _BoolToYesNo(TRecycleBinManager.RecyclerHasGlobalSettings));
  3263. +    outputMemo.Lines.Add('Global setting: ' + IntToStr(TRecycleBinManager.RecyclerGlobalGetPercentUsage()));
  3264.      for d := 'A' to 'Z' do
  3265.      begin
  3266.        // if not RecyclerIsPossible(d) then Continue;
  3267. -      outputMemo.Lines.Add('Setting for drive '+d+': ' + IntToStr(RecyclerSpecificGetPercentUsage(d)));
  3268. -      outputMemo.Lines.Add('Auto determinated setting for drive '+d+' (includes group policy and global setting): ' + IntToStr(RecyclerGetPercentUsageAutoDeterminate(d)));
  3269. +      outputMemo.Lines.Add('Setting for drive '+d+': ' + IntToStr(TRecycleBinManager.RecyclerSpecificGetPercentUsage(d)));
  3270. +      outputMemo.Lines.Add('Auto determinated setting for drive '+d+' (includes group policy and global setting): ' + IntToStr(TRecycleBinManager.RecyclerGetPercentUsageAutoDeterminate(d)));
  3271.      end;
  3272.  
  3273.      outputMemo.Lines.Add('');
  3274.      outputMemo.Lines.Add('= Confirmation Dialog =');
  3275.      outputMemo.Lines.Add('');
  3276.  
  3277. -    outputMemo.Lines.Add('Setting in Shell: ' + _BoolToEnabledDisabled(RecyclerShellStateConfirmationDialogEnabled()));
  3278. -    outputMemo.Lines.Add('Setting in Group Policy: ' + GPBoolToString(RecyclerGroupPolicyConfirmFileDelete()));
  3279. -    outputMemo.Lines.Add('Resulting Setting (Group policy before Shell): ' + _BoolToEnabledDisabled(RecyclerConfirmationDialogEnabled()));
  3280. +    outputMemo.Lines.Add('Setting in Shell: ' + _BoolToEnabledDisabled(TRecycleBinManager.RecyclerShellStateConfirmationDialogEnabled()));
  3281. +    outputMemo.Lines.Add('Setting in Group Policy: ' + GPBoolToString(TRecycleBinManager.RecyclerGroupPolicyConfirmFileDelete()));
  3282. +    outputMemo.Lines.Add('Resulting Setting (Group policy before Shell): ' + _BoolToEnabledDisabled(TRecycleBinManager.RecyclerConfirmationDialogEnabled()));
  3283.    finally
  3284.      outputMemo.Visible := true;
  3285.    end;
  3286. Index: RecBinUnit2/RB2Common.pas
  3287. ===================================================================
  3288. --- RecBinUnit2/RB2Common.pas   (revision 0)
  3289. +++ RecBinUnit2/RB2Common.pas   (revision 0)
  3290. @@ -0,0 +1,301 @@
  3291. +unit RB2Common;
  3292. +
  3293. +(*
  3294. + * OBJECT ORIENTED RECYCLE BIN UNIT
  3295. + * VERSION 2.0 ALPHA
  3296. + * Diese Unit soll Funktionen unterscheiden, die Forensisch und
  3297. + * OS-Spezifisch ("alles was ich sehen kann") sind. (TODO)
  3298. + *)
  3299. +
  3300. +interface
  3301. +
  3302. +uses
  3303. +  Windows, SysUtils, Classes, {$IFDEF DEL6UP}DateUtils,{$ENDIF}
  3304. +  ShellApi{$IFNDEF DEL6UP}, FileCtrl{$ENDIF}, Registry,
  3305. +  Messages, BitOps, contnrs;
  3306. +
  3307. +type
  3308. +  TRecycleBinItem = class(TObject)
  3309. +    function exists(): boolean; virtual; abstract;
  3310. +    function removeItem(): boolean; virtual; abstract;
  3311. +  end;
  3312. +
  3313. +  TRecycleBinItemList = class(TObjectList);
  3314. +
  3315. +  TRecycleBin = class(TObject)
  3316. +  private
  3317. +    location: string;
  3318. +  public
  3319. +    function getDrive(): char;
  3320. +    function getLocation(): string;
  3321. +    function getInfoFile(): string; virtual; abstract;
  3322. +    function getItems(): TRecycleBinItemList; virtual; abstract;
  3323. +    function isEmpty(): boolean; virtual; abstract;
  3324. +    constructor Create(location: string);
  3325. +  end;
  3326. +
  3327. +  TRecycleBinList = class(TObjectList);
  3328. +
  3329. +  TSIDRecycleBin = class(TRecycleBin)
  3330. +  public
  3331. +    SID: string;
  3332. +  end;
  3333. +
  3334. +  // X:\RECYCLED\INFO
  3335. +  // Windows 95 without Internet Explorer 4 ShellExtension
  3336. +  TRecycledInfo = class(TRecycleBin)
  3337. +
  3338. +  end;
  3339. +
  3340. +
  3341. +  TRecycledInfoItem = class(TRecycleBinItem)
  3342. +
  3343. +  end;
  3344. +
  3345. +  // X:\RECYCLED\INFO2
  3346. +  // Windows 95 with Internet Explorer 4 ShellExtension
  3347. +  TRecycledInfo2 = class(TRecycleBin)
  3348. +
  3349. +  end;
  3350. +
  3351. +  TRecycledInfo2Item = class(TRecycleBinItem)
  3352. +
  3353. +  end;
  3354. +
  3355. +  // X:\RECYCLER\<SID>\INFO2
  3356. +  // Windows NT with SID
  3357. +  TRecyclerSIDInfo2 = class(TSIDRecycleBin)
  3358. +
  3359. +  end;
  3360. +
  3361. +  TRecyclerInfo2Item = class(TRecycleBinItem)
  3362. +
  3363. +  end;
  3364. +
  3365. +  // X:\$RECYCLE.BIN\<SID>\$I...
  3366. +  // Windows Vista and higher and SID
  3367. +  TRecycleBinSIDVista = class(TSIDRecycleBin)
  3368. +
  3369. +  end;
  3370. +
  3371. +  TRecycleBinSIDVistaItem = class(TRecycleBinItem)
  3372. +
  3373. +  end;
  3374. +
  3375. +  // X:\$RECYCLE.BIN\<SID>\$I...
  3376. +  // Windows Vista and higher without SID (FAT32)
  3377. +  TRecycleBinVista = class(TRecycleBin)
  3378. +
  3379. +  end;
  3380. +
  3381. +  TRecycleBinVistaItem = class(TRecycleBinItem)
  3382. +
  3383. +  end;
  3384. +
  3385. +  TRecycleBinManager = class(TObject)
  3386. +  public
  3387. +    class procedure RecyclerGetAllRecyclerDrives(result: TStringList);
  3388. +    procedure GetAllRecycleBins(drive: Char; result: TRecycleBinItemList); overload;
  3389. +    procedure GetAllRecycleBins(result: TRecycleBinList); overload;
  3390. +    class function RecyclerIsPossible(Drive: Char): boolean;
  3391. +  end;
  3392. +
  3393. +implementation
  3394. +
  3395. +{ TRecycleBinManager }
  3396. +
  3397. +procedure ListAllDirectories (const Path: String;
  3398. +                          List: TStrings) ;
  3399. +var
  3400. +   Res: TSearchRec;
  3401. +   EOFound: Boolean;
  3402. +begin
  3403. +   EOFound:= False;
  3404. +   if FindFirst(Path, faDirectory, Res) < 0 then
  3405. +     exit
  3406. +   else
  3407. +     while not EOFound do begin
  3408. +       List.Add(Res.Name) ;
  3409. +       EOFound:= FindNext(Res) <> 0;
  3410. +     end;
  3411. +   FindClose(Res) ;
  3412. +end;
  3413. +
  3414. +function isValidSID(const sid: string): boolean;
  3415. +begin
  3416. +  result := true; // TODO
  3417. +end;
  3418. +
  3419. +procedure ListAllSIDs(Path: string; Result: TStringList);
  3420. +var
  3421. +  sl: TStringList;
  3422. +  i: integer;
  3423. +  dir, sid: string;
  3424. +begin
  3425. +  Path := IncludeTrailingPathDelimiter(Path);
  3426. +  sl := TStringList.Create;
  3427. +  ListAllDirectories(Path, sl);
  3428. +  try
  3429. +    for i := 0 to sl.Count - 1 do
  3430. +    begin
  3431. +      sid := sl.Strings[i];
  3432. +      dir := Path + sid + PathDelim;
  3433. +      if isValidSID(sid) then
  3434. +      begin
  3435. +        result.Add(dir);
  3436. +      end;
  3437. +    end;
  3438. +  finally
  3439. +    sl.Free;
  3440. +  end;
  3441. +end;
  3442. +
  3443. +// Source: http://www.delphipraxis.net/post2933.html
  3444. +function DriveExists(DriveByte: Byte): Boolean; overload;
  3445. +begin
  3446. +  Result := GetLogicalDrives and (1 shl DriveByte) <> 0;
  3447. +end;
  3448. +
  3449. +function isFAT(drive: char): boolean;
  3450. +var
  3451. +  Dummy2: DWORD;
  3452. +  Dummy3: DWORD;
  3453. +  FileSystem: array[0..MAX_PATH] of char;
  3454. +  VolumeName: array[0..MAX_PATH] of char;
  3455. +  s: string;
  3456. +begin
  3457. +  result := false;
  3458. +  if DriveExists(drive) then
  3459. +  begin
  3460. +    s := drive + DriveDelim + PathDelim; // ohne die Auslagerung in einen String kommt es zu einer AV in ntdll
  3461. +    GetVolumeInformation(PChar(s), VolumeName,
  3462. +      SizeOf(VolumeName), nil, Dummy2, Dummy3, FileSystem, SizeOf(FileSystem));
  3463. +    result := uppercase(copy(FileSystem, 0, 3)) = 'FAT';
  3464. +  end;
  3465. +end;
  3466. +
  3467. +class procedure TRecycleBinManager.RecyclerGetAllRecyclerDrives(result: TStringList);
  3468. +var
  3469. +  Drive: char;
  3470. +begin
  3471. +  for Drive := 'A' to 'Z' do
  3472. +  begin
  3473. +    if RecyclerIsPossible(Drive) (* and RecyclerIsValid(Drive) *) then // TODO: Das ist eine OS und nicht Forensische Analyse
  3474. +    begin
  3475. +      result.Add(Drive);
  3476. +    end;
  3477. +  end;
  3478. +end;
  3479. +
  3480. +procedure TRecycleBinManager.GetAllRecycleBins(drive: Char; result: TRecycleBinItemList);
  3481. +var
  3482. +  dir: string;
  3483. +  sl: TStringList;
  3484. +  i: Integer;
  3485. +  sid: string;
  3486. +begin
  3487. +  // Find recyclers from Windows Vista or higher
  3488. +
  3489. +  // TODO: Unabhängig vom Partitionstyp behandeln?
  3490. +  if isFAT(drive) then
  3491. +  begin
  3492. +    dir := drive + DriveDelim + PathDelim + '$recycle.bin' + PathDelim;
  3493. +    result.Add(TRecycleBinVista.Create(dir));
  3494. +  end
  3495. +  else
  3496. +  begin
  3497. +    dir := drive + DriveDelim + PathDelim + '$recycle.bin' + PathDelim;
  3498. +    sl := TStringList.Create;
  3499. +    try
  3500. +      ListAllSIDs(dir, sl);
  3501. +      for i := 0 to sl.Count - 1 do
  3502. +      begin
  3503. +        sid := sl.Strings[i];
  3504. +        result.Add(TRecycleBinSIDVista.Create(dir+sid+PathDelim));
  3505. +      end;
  3506. +    finally
  3507. +      sl.Free;
  3508. +    end;
  3509. +  end;
  3510. +
  3511. +  // Find recyclers from Windows before Vista
  3512. +
  3513. +  if isFAT(drive) then
  3514. +  begin
  3515. +    dir := drive + DriveDelim + PathDelim + 'Recycled' + PathDelim;
  3516. +
  3517. +    // Both "recycle bins" are possible if you have multiboot
  3518. +    // (but do overwrite themselfes if you empty them)
  3519. +    if fileExists(dir + 'INFO2') then
  3520. +    begin
  3521. +      // Windows 95 with Internet Explorer 4 Extension or higher Windows versions
  3522. +      result.Add(TRecycledInfo2.Create(dir));
  3523. +    end;
  3524. +    if fileExists(dir + 'INFO') then
  3525. +    begin
  3526. +      // Windows 95 native
  3527. +      result.Add(TRecycledInfo.Create(dir));
  3528. +    end;
  3529. +  end
  3530. +  else
  3531. +  begin
  3532. +    dir := drive + DriveDelim + PathDelim + 'Recycler' + PathDelim;
  3533. +    sl := TStringList.Create;
  3534. +    try
  3535. +      ListAllSIDs(dir, sl);
  3536. +      for i := 0 to sl.Count - 1 do
  3537. +      begin
  3538. +        sid := sl.Strings[i];
  3539. +        result.Add(TRecyclerSIDInfo2.Create(dir+sid+PathDelim));
  3540. +      end;
  3541. +    finally
  3542. +      sl.Free;
  3543. +    end;
  3544. +  end;
  3545. +end;
  3546. +
  3547. +procedure TRecycleBinManager.GetAllRecycleBins(result: TRecycleBinList);
  3548. +var
  3549. +  sl: TStringList;
  3550. +  i: Integer;
  3551. +begin
  3552. +  sl := TStringList.Create();
  3553. +  try
  3554. +    RecyclerGetAllRecyclerDrives(sl);
  3555. +    for i := 0 to sl.Count - 1 do
  3556. +    begin
  3557. +      GetAllRecycleBins(sl.Strings[i], result);
  3558. +    end;
  3559. +  finally
  3560. +    sl.Free;
  3561. +  end;
  3562. +end;
  3563. +
  3564. +class function TRecycleBinManager.RecyclerIsPossible(Drive: Char): boolean;
  3565. +var
  3566. +  typ: Integer;
  3567. +begin
  3568. +  typ := GetDriveType(PChar(Drive + ':\'));
  3569. +  result := typ = DRIVE_FIXED;
  3570. +end;
  3571. +
  3572. +{ TRecycleBin }
  3573. +
  3574. +constructor TRecycleBin.Create(location: string);
  3575. +begin
  3576. +  inherited;
  3577. +
  3578. +  self.location := location;
  3579. +end;
  3580. +
  3581. +function TRecycleBin.getDrive: char;
  3582. +begin
  3583. +  result := UpperCase(Copy(location, 1, 1));
  3584. +end;
  3585. +
  3586. +function TRecycleBin.getLocation: string;
  3587. +begin
  3588. +  result := location;
  3589. +end;
  3590. +
  3591. +end.
  3592. Index: Recycler.dpr
  3593. ===================================================================
  3594. --- Recycler.dpr        (revision 35)
  3595. +++ Recycler.dpr        (working copy)
  3596. @@ -3,7 +3,9 @@
  3597.  uses
  3598.    Forms,
  3599.    Main in 'Main.pas' {MainForm},
  3600. -  RecyclerFunctions in 'RecyclerFunctions.pas';
  3601. +  RecyclerFunctions in 'RecyclerFunctions.pas',
  3602. +  RB2Common in 'RecBinUnit2\RB2Common.pas',
  3603. +  RB2RecycledInfo in 'RecBinUnit2\RB2RecycledInfo.pas';
  3604.  
  3605.  {$R *.res}
  3606.  
  3607. Index: Recycler.exe
  3608. ===================================================================
  3609. Cannot display: file marked as a binary type.
  3610. svn:mime-type = application/octet-stream
  3611. Index: RecyclerFunctions.pas
  3612. ===================================================================
  3613. --- RecyclerFunctions.pas       (revision 35)
  3614. +++ RecyclerFunctions.pas       (working copy)
  3615. @@ -1,78 +1,3 @@
  3616. -////////////////////////////////////////////////////////////////////////////////////
  3617. -// RECYCLE-BIN-FUNCTIONS BY DANIEL MARSCHALL                                      //
  3618. -// E-MAIL: info@daniel-marschall.de                                               //
  3619. -// WEB:    www.daniel-marschall.de                                                //
  3620. -////////////////////////////////////////////////////////////////////////////////////
  3621. -// Revision: 05 JUL 2010                                                          //
  3622. -// This unit is freeware, but please link to my website if you are using it!      //
  3623. -////////////////////////////////////////////////////////////////////////////////////
  3624. -// Successful tested with:                                                        //
  3625. -// Windows 95b (without IE4 Shell Extensions)                                     //
  3626. -// Windows 95b (with IE4 Shell Extensions)                                        //
  3627. -// Windows 98-SE                                                                  //
  3628. -// Windows XP-SP3                                                                 //
  3629. -// Windows 2000-SP4                                                               //
  3630. -// Windows 2003 Server EE SP1                                                     //
  3631. -// Windows Vista                                                                  //
  3632. -// Windows 7                                                                      //
  3633. -////////////////////////////////////////////////////////////////////////////////////
  3634. -//                                                                                //
  3635. -//  Needs Delphi 4 or higher. If you are using Delphi 4 or 5, you can not use the //
  3636. -//  RecyclerGetDateTime() functions, because the unit "DateUtils" is missing.     //
  3637. -//  Warning! This is a platform unit.                                             //
  3638. -//                                                                                //
  3639. -//  To do! Can you help?                                                          //
  3640. -//    - WideString-Support (input/output)                                         //
  3641. -//    - GetLoginNameW: Really 255 maximum?                                        //
  3642. -//    - Always do EOF before reading anything?                                    //
  3643. -//    - Is it possible to identify a Vista-file that is not named $Ixxxxxx.ext?   //
  3644. -//    - RecyclerGetInfofiles() check additionally for removable device?           //
  3645. -//      RecyclerIsValid() is false.                                               //
  3646. -//    - Make it possible to empty the recycle bin of one specific drive!          //
  3647. -//                                                                                //
  3648. -//  Unknown! Do you know the answer?                                              //
  3649. -//    - How does Windows 9x/NT manage the daylight saving time (if it does)?      //
  3650. -//    - How does Windows Vista react to a RECYCLER\ folder on a NTFS device?      //
  3651. -//    - How does Windows Vista react to a RECYCLED\ folder on a FAT device?       //
  3652. -//                                                                                //
  3653. -//  Not analyzed yet! Please send me your trash folder contents for analyzing!    //
  3654. -//    - Windows NT                                                                //
  3655. -//    - Windows CE?                                                               //
  3656. -//    - Windows 7                                                                 //
  3657. -//                                                                                //
  3658. -//  Thanks to all these who have helped me solving coding problems.               //
  3659. -//  Thanks to SEBA for sending in the Windows Vista trash structure files.        //
  3660. -//  Thanks to OMATA for testing the unit with Delphi 4.                           //
  3661. -//  Thanks to DEITYSOU for making a bugfix of DriveExists()                       //
  3662. -//                                                                                //
  3663. -////////////////////////////////////////////////////////////////////////////////////
  3664. -
  3665. -(*
  3666. -
  3667. -== TODO LISTE ==
  3668. -
  3669. -Wichtig! Windows XP: InfoTip, IntroText und LocalizedString sind Resourcenangaben und müssen ausgelesen werden!
  3670. -Testen: Wie reagiert Windows, wenn Bitbucket\C existiert, aber kein Wert 'Percent' hat? Mit der Standardeinstellung?
  3671. -Bug: Windows 2000 bei bestehenden Windows 95 Partition: Recycler Filename ist dann Recycled und nicht Recycler!
  3672. -bug? w95 recycled file hat immer selben löschzeitpunkt und größe? war die nicht verschieden?
  3673. -beachtet? bei leerem papierkorb auf fat ist weder info noch info2 vorhanden?
  3674. -testen: auch möglich, einen vista papierkorb offline öffnen?
  3675. -Problem: bei win95(ohne ie4) und win2000 gleichzeitiger installation: es existiert info UND info2!!!
  3676. -Implement SETTER functions to every kind of configuration thing. (percentage etc)
  3677. -Registry CURRENT_USER: Funktionen auch für fremde Benutzer zur Verfügung stellen?
  3678. -Es sollte möglich sein, dass ein Laufwerk mehr als 1 Recycler beinhaltet -- behandeln
  3679. -
  3680. -- Future -
  3681. -
  3682. -Demoapplikation: Dateien statt Text als Explorer-Like?
  3683. -Einzelne Elemente oder alle wiederherstellen oder löschen
  3684. -Konfiguration für Laufwerke ändern etc
  3685. -IconString -> TIcon Convertion functions
  3686. -platzreservierung in mb-angabe berechnen
  3687. -I don't know if there exists any API function which checks the state at any internal way.
  3688. -
  3689. -*)
  3690. -
  3691.  // TODO: Also include BC++ Versions
  3692.  {$IFNDEF BCB}
  3693.  {$DEFINE DEL1UP}
  3694. @@ -136,140 +61,144 @@
  3695.  
  3696.    GPOLICYBOOL = (gpUndefined, gpEnabled, gpDisabled);
  3697.  
  3698. -const
  3699. -  RECYCLER_CLSID = '{645FF040-5081-101B-9F08-00AA002F954E}';
  3700. +  // TODO: $Recycle.Bin at external harddisk with Vista??
  3701.  
  3702. -{$IFDEF DEL6UP}
  3703. -function RecyclerGetDateTime(drive: char; fileid: string): tdatetime; overload;
  3704. -function RecyclerGetDateTime(drive: char; UserSID: string; fileid: string): tdatetime; overload;
  3705. -function RecyclerGetDateTime(InfofileOrRecycleFolder: string): tdatetime; overload;
  3706. -function RecyclerGetDateTime(InfofileOrRecycleFolder: string; id: string): tdatetime; overload;
  3707. -{$ENDIF}
  3708. +  TRecycleBinManager = class(TObject)
  3709. +    class function RecyclerGetCurrentIconString: string;
  3710. +    class function RecyclerGetDefaultIconString: string;
  3711. +    class function RecyclerGetEmptyIconString: string;
  3712. +    class function RecyclerGetFullIconString: string;
  3713.  
  3714. -function RecyclerGetSourceUnicode(drive: char; fileid: string): WideString; overload;
  3715. -function RecyclerGetSourceUnicode(drive: char; UserSID: string; fileid: string): WideString; overload;
  3716. -function RecyclerGetSourceUnicode(InfofileOrRecycleFolder: string): WideString; overload;
  3717. -function RecyclerGetSourceUnicode(InfofileOrRecycleFolder: string; id: string): WideString; overload;
  3718. +    class function RecyclerIsEmpty: boolean; overload;
  3719. +    class function RecyclerIsEmpty(Drive: Char): boolean; overload;
  3720.  
  3721. -function RecyclerGetSource(drive: char; fileid: string): string; overload;
  3722. -function RecyclerGetSource(drive: char; UserSID: string; fileid: string): string; overload;
  3723. -function RecyclerGetSource(InfofileOrRecycleFolder: string): string; overload;
  3724. -function RecyclerGetSource(InfofileOrRecycleFolder: string; id: string): string; overload;
  3725. +    {$IFDEF DEL6UP}
  3726. +    class function RecyclerGetDateTime(drive: char; fileid: string): tdatetime; overload;
  3727. +    class function RecyclerGetDateTime(drive: char; UserSID: string; fileid: string): tdatetime; overload;
  3728. +    class function RecyclerGetDateTime(InfofileOrRecycleFolder: string): tdatetime; overload;
  3729. +    class function RecyclerGetDateTime(InfofileOrRecycleFolder: string; id: string): tdatetime; overload;
  3730. +    {$ENDIF}
  3731.  
  3732. -procedure RecyclerListIndexes(drive: char; result: TStringList); overload;
  3733. -procedure RecyclerListIndexes(drive: char; UserSID: string; result: TStringList); overload;
  3734. -procedure RecyclerListIndexes(InfofileOrRecycleFolder: string; result: TStringList); overload;
  3735. +    class function RecyclerGetSourceUnicode(drive: char; fileid: string): WideString; overload;
  3736. +    class function RecyclerGetSourceUnicode(drive: char; UserSID: string; fileid: string): WideString; overload;
  3737. +    class function RecyclerGetSourceUnicode(InfofileOrRecycleFolder: string): WideString; overload;
  3738. +    class function RecyclerGetSourceUnicode(InfofileOrRecycleFolder: string; id: string): WideString; overload;
  3739.  
  3740. -function RecyclerGetSourceDrive(drive: char; fileid: string): char; overload;
  3741. -function RecyclerGetSourceDrive(drive: char; UserSID: string; fileid: string): char; overload;
  3742. -function RecyclerGetSourceDrive(InfofileOrRecycleFolder: string): char; overload;
  3743. -function RecyclerGetSourceDrive(InfofileOrRecycleFolder: string; id: string): char; overload;
  3744. +    class function RecyclerGetSource(drive: char; fileid: string): string; overload;
  3745. +    class function RecyclerGetSource(drive: char; UserSID: string; fileid: string): string; overload;
  3746. +    class function RecyclerGetSource(InfofileOrRecycleFolder: string): string; overload;
  3747. +    class function RecyclerGetSource(InfofileOrRecycleFolder: string; id: string): string; overload;
  3748.  
  3749. -function RecyclerOriginalSize(drive: char; fileid: string): integer; overload;
  3750. -function RecyclerOriginalSize(drive: char; UserSID: string; fileid: string): integer; overload;
  3751. -function RecyclerOriginalSize(InfofileOrRecycleFolder: string): integer; overload;
  3752. -function RecyclerOriginalSize(InfofileOrRecycleFolder: string; id: string): integer; overload;
  3753. +    class procedure RecyclerListIndexes(drive: char; result: TStringList); overload;
  3754. +    class procedure RecyclerListIndexes(drive: char; UserSID: string; result: TStringList); overload;
  3755. +    class procedure RecyclerListIndexes(InfofileOrRecycleFolder: string; result: TStringList); overload;
  3756.  
  3757. -function RecyclerIsValid(drive: char): boolean; overload;
  3758. -function RecyclerIsValid(drive: char; UserSID: string): boolean; overload;
  3759. -function RecyclerIsValid(InfofileOrRecycleFolder: string): boolean; overload;
  3760. +    class function RecyclerGetSourceDrive(drive: char; fileid: string): char; overload;
  3761. +    class function RecyclerGetSourceDrive(drive: char; UserSID: string; fileid: string): char; overload;
  3762. +    class function RecyclerGetSourceDrive(InfofileOrRecycleFolder: string): char; overload;
  3763. +    class function RecyclerGetSourceDrive(InfofileOrRecycleFolder: string; id: string): char; overload;
  3764.  
  3765. -function RecyclerCurrentFilename(drive: char; fileid: string): string; overload;
  3766. -function RecyclerCurrentFilename(drive: char; UserSID: string; fileid: string): string; overload;
  3767. -function RecyclerCurrentFilename(InfofileOrRecycleFolder: string): string; overload;
  3768. -function RecyclerCurrentFilename(InfofileOrRecycleFolder: string; id: string): string; overload;
  3769. +    class function RecyclerOriginalSize(drive: char; fileid: string): integer; overload;
  3770. +    class function RecyclerOriginalSize(drive: char; UserSID: string; fileid: string): integer; overload;
  3771. +    class function RecyclerOriginalSize(InfofileOrRecycleFolder: string): integer; overload;
  3772. +    class function RecyclerOriginalSize(InfofileOrRecycleFolder: string; id: string): integer; overload;
  3773.  
  3774. -function RecyclerGetPath(drive: char; UserSID: string; IncludeInfofile: boolean; fileid: string): string; overload;
  3775. -function RecyclerGetPath(drive: char; UserSID: string; IncludeInfofile: boolean): string; overload;
  3776. -function RecyclerGetPath(drive: char; IncludeInfofile: boolean): string; overload;
  3777. -function RecyclerGetPath(drive: char; UserSID: string): string; overload;
  3778. -function RecyclerGetPath(drive: char): string; overload;
  3779. +    class function RecyclerIsValid(drive: char): boolean; overload;
  3780. +    class function RecyclerIsValid(drive: char; UserSID: string): boolean; overload;
  3781. +    class function RecyclerIsValid(InfofileOrRecycleFolder: string): boolean; overload;
  3782.  
  3783. -procedure RecyclerGetInfofiles(drive: char; UserSID: string; IncludeInfofile: boolean; fileid: string; result: TStringList); overload;
  3784. -procedure RecyclerGetInfofiles(drive: char; UserSID: string; IncludeInfofile: boolean; result: TStringList); overload;
  3785. -procedure RecyclerGetInfofiles(drive: char; IncludeInfofile: boolean; result: TStringList); overload;
  3786. -procedure RecyclerGetInfofiles(drive: char; UserSID: string; result: TStringList); overload;
  3787. -procedure RecyclerGetInfofiles(drive: char; result: TStringList); overload;
  3788. +    class function RecyclerCurrentFilename(drive: char; fileid: string): string; overload;
  3789. +    class function RecyclerCurrentFilename(drive: char; UserSID: string; fileid: string): string; overload;
  3790. +    class function RecyclerCurrentFilename(InfofileOrRecycleFolder: string): string; overload;
  3791. +    class function RecyclerCurrentFilename(InfofileOrRecycleFolder: string; id: string): string; overload;
  3792.  
  3793. -function RecyclerCurrentFilenameAndPath(drive: char; UserSID: string; fileid: string): string; overload;
  3794. -function RecyclerCurrentFilenameAndPath(drive: char; fileid: string): string; overload;
  3795. -function RecyclerCurrentFilenameAndPath(InfofileOrRecycleFolder: string; id: string): string; overload;
  3796. +    class function RecyclerGetPath(drive: char; UserSID: string; IncludeInfofile: boolean; fileid: string): string; overload;
  3797. +    class function RecyclerGetPath(drive: char; UserSID: string; IncludeInfofile: boolean): string; overload;
  3798. +    class function RecyclerGetPath(drive: char; IncludeInfofile: boolean): string; overload;
  3799. +    class function RecyclerGetPath(drive: char; UserSID: string): string; overload;
  3800. +    class function RecyclerGetPath(drive: char): string; overload;
  3801.  
  3802. -function RecyclerRemoveItem(drive: char; UserSID: string; fileid: string): boolean; overload;
  3803. -function RecyclerRemoveItem(drive: char; fileid: string): boolean; overload;
  3804. -function RecyclerRemoveItem(InfofileOrRecycleFolder: string; id: string): boolean; overload;
  3805. +    class procedure RecyclerGetInfofiles(drive: char; UserSID: string; IncludeInfofile: boolean; fileid: string; result: TStringList); overload;
  3806. +    class procedure RecyclerGetInfofiles(drive: char; UserSID: string; IncludeInfofile: boolean; result: TStringList); overload;
  3807. +    class procedure RecyclerGetInfofiles(drive: char; IncludeInfofile: boolean; result: TStringList); overload;
  3808. +    class procedure RecyclerGetInfofiles(drive: char; UserSID: string; result: TStringList); overload;
  3809. +    class procedure RecyclerGetInfofiles(drive: char; result: TStringList); overload;
  3810.  
  3811. -procedure RecyclerGetAllRecyclerDrives(result: TStringList);
  3812. +    class function RecyclerCurrentFilenameAndPath(drive: char; UserSID: string; fileid: string): string; overload;
  3813. +    class function RecyclerCurrentFilenameAndPath(drive: char; fileid: string): string; overload;
  3814. +    class function RecyclerCurrentFilenameAndPath(InfofileOrRecycleFolder: string; id: string): string; overload;
  3815.  
  3816. -function RecyclerEmptyRecycleBin(flags: cardinal): boolean; overload;
  3817. -function RecyclerEmptyRecycleBin(sound, progress, confirmation: boolean): boolean; overload;
  3818. +    class function RecyclerRemoveItem(drive: char; UserSID: string; fileid: string): boolean; overload;
  3819. +    class function RecyclerRemoveItem(drive: char; fileid: string): boolean; overload;
  3820. +    class function RecyclerRemoveItem(InfofileOrRecycleFolder: string; id: string): boolean; overload;
  3821.  
  3822. -function RecyclerAddFileOrFolder(FileOrFolder: string; confirmation: boolean): boolean; overload;
  3823. -function RecyclerAddFileOrFolder(FileOrFolder: string): boolean; overload;
  3824. +    class procedure RecyclerGetAllRecyclerDrives(result: TStringList);
  3825.  
  3826. -function RecyclerConfirmationDialogEnabled: boolean;
  3827. -function RecyclerShellStateConfirmationDialogEnabled: boolean;
  3828. -procedure RecyclerConfirmationDialogSetEnabled(NewSetting: boolean);
  3829. +    class function RecyclerEmptyRecycleBin(flags: cardinal): boolean; overload;
  3830. +    class function RecyclerEmptyRecycleBin(sound, progress, confirmation: boolean): boolean; overload;
  3831.  
  3832. -function RecyclerGetCurrentIconString: string;
  3833. -function RecyclerGetDefaultIconString: string;
  3834. -function RecyclerGetEmptyIconString: string;
  3835. -function RecyclerGetFullIconString: string;
  3836. +    class function RecyclerAddFileOrFolder(FileOrFolder: string; confirmation: boolean): boolean; overload;
  3837. +    class function RecyclerAddFileOrFolder(FileOrFolder: string): boolean; overload;
  3838.  
  3839. -function RecyclerGetName: string;
  3840. -function RecyclerGetInfoTip: string;
  3841. -function RecyclerGetIntroText: string;
  3842. +    class function RecyclerConfirmationDialogEnabled: boolean;
  3843. +    class function RecyclerShellStateConfirmationDialogEnabled: boolean;
  3844. +    class procedure RecyclerConfirmationDialogSetEnabled(NewSetting: boolean);
  3845.  
  3846. -function RecyclerEmptyEventGetName: string;
  3847. -function RecyclerEmptyEventGetCurrentSound: string;
  3848. -function RecyclerEmptyEventGetDefaultSound: string;
  3849. -procedure RecyclerEmptyEventGetSoundCategories(AStringList: TStringList);
  3850. -function RecyclerEmptyEventGetSound(ACategory: string): string;
  3851. +    class function RecyclerGetName: string;
  3852. +    class function RecyclerGetInfoTip: string;
  3853. +    class function RecyclerGetIntroText: string;
  3854.  
  3855. -function RecyclerGlobalGetPercentUsage: integer;
  3856. -function RecyclerSpecificGetPercentUsage(Drive: Char): integer;
  3857. -function RecyclerGetPercentUsageAutoDeterminate(Drive: Char): integer;
  3858. +    class function RecyclerEmptyEventGetName: string;
  3859. +    class function RecyclerEmptyEventGetCurrentSound: string;
  3860. +    class function RecyclerEmptyEventGetDefaultSound: string;
  3861. +    class procedure RecyclerEmptyEventGetSoundCategories(AStringList: TStringList);
  3862. +    class function RecyclerEmptyEventGetSound(ACategory: string): string;
  3863.  
  3864. -function RecyclerGlobalIsNukeOnDelete: boolean;
  3865. -function RecyclerSpecificIsNukeOnDelete(Drive: Char): boolean;
  3866. -function RecyclerIsNukeOnDeleteAutoDeterminate(Drive: Char): boolean;
  3867. +    class function RecyclerGlobalGetPercentUsage: integer;
  3868. +    class function RecyclerSpecificGetPercentUsage(Drive: Char): integer;
  3869. +    class function RecyclerGetPercentUsageAutoDeterminate(Drive: Char): integer;
  3870.  
  3871. -function RecyclerHasGlobalSettings: boolean;
  3872. +    class function RecyclerGlobalIsNukeOnDelete: boolean;
  3873. +    class function RecyclerSpecificIsNukeOnDelete(Drive: Char): boolean;
  3874. +    class function RecyclerIsNukeOnDeleteAutoDeterminate(Drive: Char): boolean;
  3875.  
  3876. -function RecyclerIsEmpty: boolean; overload;
  3877. -function RecyclerIsEmpty(Drive: Char): boolean; overload;
  3878. +    class function RecyclerHasGlobalSettings: boolean;
  3879.  
  3880. -function RecyclerGetNumItems: int64; overload;
  3881. -function RecyclerGetNumItems(Drive: Char): int64; overload;
  3882. +    class function RecyclerGetNumItems: int64; overload;
  3883. +    class function RecyclerGetNumItems(Drive: Char): int64; overload;
  3884.  
  3885. -function RecyclerGetSize: int64; overload;
  3886. -function RecyclerGetSize(Drive: Char): int64; overload;
  3887. +    class function RecyclerGetSize: int64; overload;
  3888. +    class function RecyclerGetSize(Drive: Char): int64; overload;
  3889.  
  3890. -function RecyclerGetAPIInfo(Drive: Char): TSHQueryRBInfo; overload;
  3891. -function RecyclerGetAPIInfo(Path: String): TSHQueryRBInfo; overload;
  3892. +    class function RecyclerGetAPIInfo(Drive: Char): TSHQueryRBInfo; overload;
  3893. +    class function RecyclerGetAPIInfo(Path: String): TSHQueryRBInfo; overload;
  3894.  
  3895. -function RecyclerGetCLSID: string;
  3896. +    class function RecyclerGetCLSID: string;
  3897.  
  3898. -// Diese Funktion ist false, wenn sie z.B. unter Windows 95 ohne Internet Explorer
  3899. -// 4.0 Shell Extension ausgeführt wird. Wenn abwärtskompatibler Code geschrieben
  3900. -// werden soll, sollte RecyclerQueryFunctionAvailable() verwendet werden, da
  3901. -// unter Windows 95 folgende Funktionalitäten NICHT vorhanden sind:
  3902. -// - RecyclerIsEmpty
  3903. -// - RecyclerGetNumItems
  3904. -// - RecyclerGetSize
  3905. -// - RecyclerGetAPIInfo
  3906. -function RecyclerQueryFunctionAvailable: boolean;
  3907. +    // Diese Funktion ist false, wenn sie z.B. unter Windows 95 ohne Internet Explorer
  3908. +    // 4.0 Shell Extension ausgeführt wird. Wenn abwärtskompatibler Code geschrieben
  3909. +    // werden soll, sollte RecyclerQueryFunctionAvailable() verwendet werden, da
  3910. +    // unter Windows 95 folgende Funktionalitäten NICHT vorhanden sind:
  3911. +    // - RecyclerIsEmpty
  3912. +    // - RecyclerGetNumItems
  3913. +    // - RecyclerGetSize
  3914. +    // - RecyclerGetAPIInfo
  3915. +    class function RecyclerQueryFunctionAvailable: boolean;
  3916.  
  3917. -function RecyclerGroupPolicyNoRecycleFiles: GPOLICYBOOL;
  3918. -function RecyclerGroupPolicyConfirmFileDelete: GPOLICYBOOL;
  3919. -function RecyclerGroupPolicyRecycleBinSize: integer;
  3920. +    class function RecyclerGroupPolicyNoRecycleFiles: GPOLICYBOOL;
  3921. +    class function RecyclerGroupPolicyConfirmFileDelete: GPOLICYBOOL;
  3922. +    class function RecyclerGroupPolicyRecycleBinSize: integer;
  3923.  
  3924. -function GPBoolToString(value: GPOLICYBOOL): String;
  3925. +    class function RecyclerIsPossible(Drive: Char): boolean;
  3926.  
  3927. -function RecyclerIsPossible(Drive: Char): boolean;
  3928. +    class function RecyclerLibraryVersion: string;
  3929. +  end;
  3930.  
  3931. -function RecyclerLibraryVersion: string;
  3932. +  function GPBoolToString(value: GPOLICYBOOL): String;
  3933.  
  3934. +const
  3935. +  RECYCLER_CLSID = '{645FF040-5081-101B-9F08-00AA002F954E}';
  3936. +
  3937.  implementation
  3938.  
  3939.  type
  3940. @@ -964,17 +893,17 @@
  3941.  
  3942.  {$IFDEF DEL6UP}
  3943.  
  3944. -function RecyclerGetDateTime(InfofileOrRecycleFolder: string): tdatetime; overload;
  3945. +class function TRecycleBinManager.RecyclerGetDateTime(InfofileOrRecycleFolder: string): tdatetime;
  3946.  begin
  3947.    result := RecyclerGetDateTime(InfofileOrRecycleFolder, '');
  3948.  end;
  3949.  
  3950. -function RecyclerGetDateTime(drive: char; fileid: string): tdatetime; overload;
  3951. +class function TRecycleBinManager.RecyclerGetDateTime(drive: char; fileid: string): tdatetime;
  3952.  begin
  3953.    result := RecyclerGetDateTime(drive, '', fileid);
  3954.  end;
  3955.  
  3956. -function RecyclerGetDateTime(drive: char; UserSID: string; fileid: string): tdatetime; overload;
  3957. +class function TRecycleBinManager.RecyclerGetDateTime(drive: char; UserSID: string; fileid: string): tdatetime;
  3958.  var
  3959.    infofile: string;
  3960.  begin
  3961. @@ -982,7 +911,7 @@
  3962.    result := RecyclerGetDateTime(infofile, fileid);
  3963.  end;
  3964.  
  3965. -function RecyclerGetDateTime(InfofileOrRecycleFolder: string; id: string): tdatetime; overload;
  3966. +class function TRecycleBinManager.RecyclerGetDateTime(InfofileOrRecycleFolder: string; id: string): tdatetime;
  3967.  var
  3968.    fs: TFileStream;
  3969.    i, record_length: integer;
  3970. @@ -1055,17 +984,105 @@
  3971.  
  3972.  ////////////////////////////////////////////////////////////////////////////////
  3973.  
  3974. -function RecyclerGetSourceUnicode(InfofileOrRecycleFolder: string): WideString; overload;
  3975. +{ TRecycleBinManager }
  3976. +
  3977. +class function TRecycleBinManager.RecyclerGetCurrentIconString: string;
  3978.  begin
  3979. +  if TRecycleBinManager.RecyclerIsEmpty then
  3980. +    result := RecyclerGetEmptyIconString
  3981. +  else
  3982. +    result := RecyclerGetFullIconString;
  3983. +end;
  3984. +
  3985. +class function TRecycleBinManager.RecyclerGetDefaultIconString: string;
  3986. +var
  3987. +  reg: TRegistry;
  3988. +begin
  3989. +  // Please note: The "default" icon is not always the icon of the
  3990. +  // current recycle bin in its current state (full, empty)
  3991. +  // At Windows 95b, the registry value actually did change every time the
  3992. +  // recycle bin state did change, but at Windows 2000 I could not see any
  3993. +  // update, even after reboot. So, the registry value is possible fixed as
  3994. +  // default = empty on newer OS versions.
  3995. +
  3996. +  reg := TRegistry.Create;
  3997. +  try
  3998. +    reg.RootKey := HKEY_CLASSES_ROOT;
  3999. +    if reg.OpenKeyReadOnly('CLSID\'+RECYCLER_CLSID+'\DefaultIcon') then
  4000. +    begin
  4001. +      result := reg.ReadString('');
  4002. +      reg.CloseKey;
  4003. +    end;
  4004. +  finally
  4005. +    reg.Free;
  4006. +  end;
  4007. +end;
  4008. +
  4009. +class function TRecycleBinManager.RecyclerGetEmptyIconString: string;
  4010. +var
  4011. +  reg: TRegistry;
  4012. +begin
  4013. +  reg := TRegistry.Create;
  4014. +  try
  4015. +    reg.RootKey := HKEY_CLASSES_ROOT;
  4016. +    if reg.OpenKeyReadOnly('CLSID\'+RECYCLER_CLSID+'\DefaultIcon') then
  4017. +    begin
  4018. +      result := reg.ReadString('Empty');
  4019. +      reg.CloseKey;
  4020. +    end;
  4021. +  finally
  4022. +    reg.Free;
  4023. +  end;
  4024. +end;
  4025. +
  4026. +class function TRecycleBinManager.RecyclerGetFullIconString: string;
  4027. +var
  4028. +  reg: TRegistry;
  4029. +begin
  4030. +  reg := TRegistry.Create;
  4031. +  try
  4032. +    reg.RootKey := HKEY_CLASSES_ROOT;
  4033. +    if reg.OpenKeyReadOnly('CLSID\'+RECYCLER_CLSID+'\DefaultIcon') then
  4034. +    begin
  4035. +      result := reg.ReadString('Full');
  4036. +      reg.CloseKey;
  4037. +    end;
  4038. +  finally
  4039. +    reg.Free;
  4040. +  end;
  4041. +end;
  4042. +
  4043. +class function TRecycleBinManager.RecyclerIsEmpty: boolean;
  4044. +var
  4045. +  Drive: Char;
  4046. +begin
  4047. +  result := true;
  4048. +  for Drive := 'A' to 'Z' do
  4049. +  begin
  4050. +    if RecyclerIsPossible(Drive) and not RecyclerIsEmpty(Drive) then
  4051. +    begin
  4052. +      result := false;
  4053. +      exit;
  4054. +    end;
  4055. +  end;
  4056. +end;
  4057. +
  4058. +class function TRecycleBinManager.RecyclerIsEmpty(Drive: Char): boolean;
  4059. +begin
  4060. +  result := RecyclerGetAPIInfo(Drive).i64NumItems = 0;
  4061. +end;
  4062. +
  4063. +class function TRecycleBinManager.RecyclerGetSourceUnicode(InfofileOrRecycleFolder: string): WideString;
  4064. +begin
  4065.    result := RecyclerGetSourceUnicode(InfofileOrRecycleFolder, '');
  4066.  end;
  4067.  
  4068. -function RecyclerGetSourceUnicode(drive: char; fileid: string): WideString; overload;
  4069. +class function TRecycleBinManager.RecyclerGetSourceUnicode(drive: char; fileid: string): WideString;
  4070.  begin
  4071.    result := RecyclerGetSourceUnicode(drive, '', fileid);
  4072.  end;
  4073.  
  4074. -function RecyclerGetSourceUnicode(drive: char; UserSID: string; fileid: string): WideString; overload;
  4075. +class function TRecycleBinManager.RecyclerGetSourceUnicode(drive: char; UserSID: string; fileid: string): WideString;
  4076.  var
  4077.    infofile: string;
  4078.  begin
  4079. @@ -1081,7 +1098,7 @@
  4080.    end;
  4081.  end;
  4082.  
  4083. -function RecyclerGetSourceUnicode(InfofileOrRecycleFolder: string; id: string): WideString; overload;
  4084. +class function TRecycleBinManager.RecyclerGetSourceUnicode(InfofileOrRecycleFolder: string; id: string): WideString;
  4085.  var
  4086.    fs: TFileStream;
  4087.    i, record_length: integer;
  4088. @@ -1163,17 +1180,17 @@
  4089.  
  4090.  ////////////////////////////////////////////////////////////////////////////////
  4091.  
  4092. -function RecyclerGetSource(InfofileOrRecycleFolder: string): string; overload;
  4093. +class function TRecycleBinManager.RecyclerGetSource(InfofileOrRecycleFolder: string): string;
  4094.  begin
  4095.    result := RecyclerGetSource(InfofileOrRecycleFolder, '');
  4096.  end;
  4097.  
  4098. -function RecyclerGetSource(drive: char; fileid: string): string; overload;
  4099. +class function TRecycleBinManager.RecyclerGetSource(drive: char; fileid: string): string;
  4100.  begin
  4101.    result := RecyclerGetSource(drive, '', fileid);
  4102.  end;
  4103.  
  4104. -function RecyclerGetSource(drive: char; UserSID: string; fileid: string): string; overload;
  4105. +class function TRecycleBinManager.RecyclerGetSource(drive: char; UserSID: string; fileid: string): string;
  4106.  var
  4107.    infofile: string;
  4108.  begin
  4109. @@ -1181,7 +1198,7 @@
  4110.    result := RecyclerGetSource(infofile, fileid);
  4111.  end;
  4112.  
  4113. -function RecyclerGetSource(InfofileOrRecycleFolder: string; id: string): string; overload;
  4114. +class function TRecycleBinManager.RecyclerGetSource(InfofileOrRecycleFolder: string; id: string): string;
  4115.  var
  4116.    fs: TFileStream;
  4117.    i, record_length: integer;
  4118. @@ -1272,12 +1289,12 @@
  4119.  
  4120.  ////////////////////////////////////////////////////////////////////////////////
  4121.  
  4122. -procedure RecyclerListIndexes(drive: char; result: TStringList); overload;
  4123. +class procedure TRecycleBinManager.RecyclerListIndexes(drive: char; result: TStringList);
  4124.  begin
  4125.    RecyclerListIndexes(drive, '', result);
  4126.  end;
  4127.  
  4128. -procedure RecyclerListIndexes(drive: char; UserSID: string; result: TStringList); overload;
  4129. +class procedure TRecycleBinManager.RecyclerListIndexes(drive: char; UserSID: string; result: TStringList);
  4130.  var
  4131.    infofile: string;
  4132.  begin
  4133. @@ -1285,7 +1302,7 @@
  4134.    RecyclerListIndexes(infofile, result);
  4135.  end;
  4136.  
  4137. -procedure RecyclerListIndexes(InfofileOrRecycleFolder: string; result: TStringList); overload;
  4138. +class procedure TRecycleBinManager.RecyclerListIndexes(InfofileOrRecycleFolder: string; result: TStringList);
  4139.  var
  4140.    fs: TFileStream;
  4141.    i, record_length: integer;
  4142. @@ -1349,17 +1366,17 @@
  4143.  
  4144.  ////////////////////////////////////////////////////////////////////////////////
  4145.  
  4146. -function RecyclerGetSourceDrive(InfofileOrRecycleFolder: string): char; overload;
  4147. +class function TRecycleBinManager.RecyclerGetSourceDrive(InfofileOrRecycleFolder: string): char;
  4148.  begin
  4149.    result := RecyclerGetSourceDrive(InfofileOrRecycleFolder, '');
  4150.  end;
  4151.  
  4152. -function RecyclerGetSourceDrive(drive: char; fileid: string): char; overload;
  4153. +class function TRecycleBinManager.RecyclerGetSourceDrive(drive: char; fileid: string): char;
  4154.  begin
  4155.    result := RecyclerGetSourceDrive(drive, '', fileid);
  4156.  end;
  4157.  
  4158. -function RecyclerGetSourceDrive(drive: char; UserSID: string; fileid: string): char; overload;
  4159. +class function TRecycleBinManager.RecyclerGetSourceDrive(drive: char; UserSID: string; fileid: string): char;
  4160.  var
  4161.    infofile: string;
  4162.  begin
  4163. @@ -1367,7 +1384,7 @@
  4164.    result := RecyclerGetSourceDrive(infofile, fileid);
  4165.  end;
  4166.  
  4167. -function RecyclerGetSourceDrive(InfofileOrRecycleFolder: string; id: string): char; overload;
  4168. +class function TRecycleBinManager.RecyclerGetSourceDrive(InfofileOrRecycleFolder: string; id: string): char;
  4169.  var
  4170.    fs: TFileStream;
  4171.    i, record_length: integer;
  4172. @@ -1437,17 +1454,17 @@
  4173.  
  4174.  ////////////////////////////////////////////////////////////////////////////////
  4175.  
  4176. -function RecyclerOriginalSize(InfofileOrRecycleFolder: string): integer; overload;
  4177. +class function TRecycleBinManager.RecyclerOriginalSize(InfofileOrRecycleFolder: string): integer;
  4178.  begin
  4179.    result := RecyclerOriginalSize(InfofileOrRecycleFolder, '');
  4180.  end;
  4181.  
  4182. -function RecyclerOriginalSize(drive: char; fileid: string): integer; overload;
  4183. +class function TRecycleBinManager.RecyclerOriginalSize(drive: char; fileid: string): integer;
  4184.  begin
  4185.    result := RecyclerOriginalSize(drive, '', fileid);
  4186.  end;
  4187.  
  4188. -function RecyclerOriginalSize(drive: char; UserSID: string; fileid: string): integer; overload;
  4189. +class function TRecycleBinManager.RecyclerOriginalSize(drive: char; UserSID: string; fileid: string): integer;
  4190.  var
  4191.    infofile: string;
  4192.  begin
  4193. @@ -1455,7 +1472,7 @@
  4194.    result := RecyclerOriginalSize(infofile, fileid);
  4195.  end;
  4196.  
  4197. -function RecyclerOriginalSize(InfofileOrRecycleFolder: string; id: string): integer; overload;
  4198. +class function TRecycleBinManager.RecyclerOriginalSize(InfofileOrRecycleFolder: string; id: string): integer;
  4199.  var
  4200.    fs: TFileStream;
  4201.    i, record_length: integer;
  4202. @@ -1525,7 +1542,7 @@
  4203.  
  4204.  ////////////////////////////////////////////////////////////////////////////////
  4205.  
  4206. -function RecyclerIsValid(drive: char): boolean; overload;
  4207. +class function TRecycleBinManager.RecyclerIsValid(drive: char): boolean;
  4208.  begin
  4209.    // Bei Vista und W2k3 (VM) erhalte ich bei LW A: die Meldung
  4210.    // "c0000013 Kein Datenträger". Exception Abfangen geht nicht.
  4211. @@ -1536,7 +1553,7 @@
  4212.    result := RecyclerIsValid(drive, '');
  4213.  end;
  4214.  
  4215. -function RecyclerIsValid(drive: char; UserSID: string): boolean; overload;
  4216. +class function TRecycleBinManager.RecyclerIsValid(drive: char; UserSID: string): boolean;
  4217.  var
  4218.    infofile: string;
  4219.  begin
  4220. @@ -1548,7 +1565,7 @@
  4221.    result := RecyclerIsValid(infofile);
  4222.  end;
  4223.  
  4224. -function RecyclerIsValid(InfofileOrRecycleFolder: string): boolean; overload;
  4225. +class function TRecycleBinManager.RecyclerIsValid(InfofileOrRecycleFolder: string): boolean;
  4226.  var
  4227.    tmp: string;
  4228.    x: TStringList;
  4229. @@ -1617,17 +1634,17 @@
  4230.  
  4231.  ////////////////////////////////////////////////////////////////////////////////
  4232.  
  4233. -function RecyclerCurrentFilename(InfofileOrRecycleFolder: string): string; overload;
  4234. +class function TRecycleBinManager.RecyclerCurrentFilename(InfofileOrRecycleFolder: string): string;
  4235.  begin
  4236.    result := RecyclerCurrentFilename(InfofileOrRecycleFolder, '');
  4237.  end;
  4238.  
  4239. -function RecyclerCurrentFilename(drive: char; fileid: string): string; overload;
  4240. +class function TRecycleBinManager.RecyclerCurrentFilename(drive: char; fileid: string): string;
  4241.  begin
  4242.    result := RecyclerCurrentFilename(drive, '', fileid);
  4243.  end;
  4244.  
  4245. -function RecyclerCurrentFilename(drive: char; UserSID: string; fileid: string): string; overload;
  4246. +class function TRecycleBinManager.RecyclerCurrentFilename(drive: char; UserSID: string; fileid: string): string;
  4247.  var
  4248.    infofile: string;
  4249.  begin
  4250. @@ -1635,7 +1652,7 @@
  4251.    result := RecyclerCurrentFilename(infofile, fileid);
  4252.  end;
  4253.  
  4254. -function RecyclerCurrentFilename(InfofileOrRecycleFolder: string; id: string): string; overload;
  4255. +class function TRecycleBinManager.RecyclerCurrentFilename(InfofileOrRecycleFolder: string; id: string): string;
  4256.  var
  4257.    a, c: string;
  4258.    tmp: string;
  4259. @@ -1683,7 +1700,7 @@
  4260.  
  4261.  ////////////////////////////////////////////////////////////////////////////////
  4262.  
  4263. -function RecyclerGetPath(drive: char; UserSID: string; IncludeInfofile: boolean; fileid: string): string; overload;
  4264. +class function TRecycleBinManager.RecyclerGetPath(drive: char; UserSID: string; IncludeInfofile: boolean; fileid: string): string;
  4265.  var
  4266.    sl: TStringList;
  4267.  begin
  4268. @@ -1699,7 +1716,7 @@
  4269.    end;
  4270.  end;
  4271.  
  4272. -function RecyclerGetPath(drive: char; UserSID: string; IncludeInfofile: boolean): string; overload;
  4273. +class function TRecycleBinManager.RecyclerGetPath(drive: char; UserSID: string; IncludeInfofile: boolean): string;
  4274.  var
  4275.    sl: TStringList;
  4276.  begin
  4277. @@ -1715,7 +1732,7 @@
  4278.    end;
  4279.  end;
  4280.  
  4281. -function RecyclerGetPath(drive: char; IncludeInfofile: boolean): string; overload;
  4282. +class function TRecycleBinManager.RecyclerGetPath(drive: char; IncludeInfofile: boolean): string;
  4283.  var
  4284.    sl: TStringList;
  4285.  begin
  4286. @@ -1731,7 +1748,7 @@
  4287.    end;
  4288.  end;
  4289.  
  4290. -function RecyclerGetPath(drive: char; UserSID: string): string; overload;
  4291. +class function TRecycleBinManager.RecyclerGetPath(drive: char; UserSID: string): string;
  4292.  var
  4293.    sl: TStringList;
  4294.  begin
  4295. @@ -1747,7 +1764,7 @@
  4296.    end;
  4297.  end;
  4298.  
  4299. -function RecyclerGetPath(drive: char): string; overload;
  4300. +class function TRecycleBinManager.RecyclerGetPath(drive: char): string;
  4301.  var
  4302.    sl: TStringList;
  4303.  begin
  4304. @@ -1765,7 +1782,7 @@
  4305.  
  4306.  ////////////////////////////////////////////////////////////////////////////////
  4307.  
  4308. -procedure RecyclerGetInfofiles(drive: char; UserSID: string; IncludeInfofile: boolean; fileid: string; result: TStringList); overload;
  4309. +class procedure TRecycleBinManager.RecyclerGetInfofiles(drive: char; UserSID: string; IncludeInfofile: boolean; fileid: string; result: TStringList);
  4310.  var
  4311.    dir: string;
  4312.  begin
  4313. @@ -1881,40 +1898,40 @@
  4314.    end;
  4315.  end;
  4316.  
  4317. -procedure RecyclerGetInfofiles(drive: char; UserSID: string; IncludeInfofile: boolean; result: TStringList); overload;
  4318. +class procedure TRecycleBinManager.RecyclerGetInfofiles(drive: char; UserSID: string; IncludeInfofile: boolean; result: TStringList);
  4319.  begin
  4320.    RecyclerGetInfofiles(drive, UserSID, IncludeInfofile, '', result);
  4321.  end;
  4322.  
  4323. -procedure RecyclerGetInfofiles(drive: char; IncludeInfofile: boolean; result: TStringList); overload;
  4324. +class procedure TRecycleBinManager.RecyclerGetInfofiles(drive: char; IncludeInfofile: boolean; result: TStringList);
  4325.  begin
  4326.    RecyclerGetInfofiles(drive, '', IncludeInfofile, '', result);
  4327.  end;
  4328.  
  4329. -procedure RecyclerGetInfofiles(drive: char; UserSID: string; result: TStringList); overload;
  4330. +class procedure TRecycleBinManager.RecyclerGetInfofiles(drive: char; UserSID: string; result: TStringList);
  4331.  begin
  4332.    RecyclerGetInfofiles(drive, UserSID, false, '', result);
  4333.  end;
  4334.  
  4335. -procedure RecyclerGetInfofiles(drive: char; result: TStringList); overload;
  4336. +class procedure TRecycleBinManager.RecyclerGetInfofiles(drive: char; result: TStringList);
  4337.  begin
  4338.    RecyclerGetInfofiles(drive, '', false, '', result);
  4339.  end;
  4340.  
  4341.  ////////////////////////////////////////////////////////////////////////////////
  4342.  
  4343. -function RecyclerCurrentFilenameAndPath(drive: char; UserSID: string; fileid: string): string; overload;
  4344. +class function TRecycleBinManager.RecyclerCurrentFilenameAndPath(drive: char; UserSID: string; fileid: string): string;
  4345.  begin
  4346.    result := RecyclerGetPath(drive, UserSID, false, fileid) +
  4347.      RecyclerCurrentFilename(drive, UserSID, fileid);
  4348.  end;
  4349.  
  4350. -function RecyclerCurrentFilenameAndPath(drive: char; fileid: string): string; overload;
  4351. +class function TRecycleBinManager.RecyclerCurrentFilenameAndPath(drive: char; fileid: string): string;
  4352.  begin
  4353.    result := RecyclerCurrentFilenameAndPath(drive, '', fileid);
  4354.  end;
  4355.  
  4356. -function RecyclerCurrentFilenameAndPath(InfofileOrRecycleFolder: string; id: string): string; overload;
  4357. +class function TRecycleBinManager.RecyclerCurrentFilenameAndPath(InfofileOrRecycleFolder: string; id: string): string;
  4358.  begin
  4359.    if RecyclerIsValid(InfofileOrRecycleFolder) then
  4360.    begin
  4361. @@ -1927,7 +1944,7 @@
  4362.  
  4363.  ////////////////////////////////////////////////////////////////////////////////
  4364.  
  4365. -function RecyclerRemoveItem(drive: char; UserSID: string; fileid: string): boolean; overload;
  4366. +class function TRecycleBinManager.RecyclerRemoveItem(drive: char; UserSID: string; fileid: string): boolean;
  4367.  var
  4368.    tmp: string;
  4369.  begin
  4370. @@ -1944,12 +1961,12 @@
  4371.    end;
  4372.  end;
  4373.  
  4374. -function RecyclerRemoveItem(drive: char; fileid: string): boolean; overload;
  4375. +class function TRecycleBinManager.RecyclerRemoveItem(drive: char; fileid: string): boolean;
  4376.  begin
  4377.    result := RecyclerRemoveItem(drive, '', fileid);
  4378.  end;
  4379.  
  4380. -function RecyclerRemoveItem(InfofileOrRecycleFolder: string; id: string): boolean; overload;
  4381. +class function TRecycleBinManager.RecyclerRemoveItem(InfofileOrRecycleFolder: string; id: string): boolean;
  4382.  var
  4383.    tmp: string;
  4384.  begin
  4385. @@ -1966,7 +1983,7 @@
  4386.    end;
  4387.  end;
  4388.  
  4389. -procedure RecyclerGetAllRecyclerDrives(result: TStringList);
  4390. +class procedure TRecycleBinManager.RecyclerGetAllRecyclerDrives(result: TStringList);
  4391.  var
  4392.    Drive: char;
  4393.  begin
  4394. @@ -1982,7 +1999,7 @@
  4395.  ////////////////////////////////////////////////////////////////////////////////
  4396.  
  4397.  // http://www.dsdt.info/tipps/?id=176
  4398. -function RecyclerEmptyRecycleBin(flags: cardinal): boolean; overload;
  4399. +class function TRecycleBinManager.RecyclerEmptyRecycleBin(flags: cardinal): boolean;
  4400.  type
  4401.    TSHEmptyRecycleBin = function (Wnd: HWND;
  4402.                                   pszRootPath: PChar;
  4403. @@ -2015,7 +2032,7 @@
  4404.    end;
  4405.  end;
  4406.  
  4407. -function RecyclerEmptyRecycleBin(sound, progress, confirmation: boolean): boolean; overload;
  4408. +class function TRecycleBinManager.RecyclerEmptyRecycleBin(sound, progress, confirmation: boolean): boolean;
  4409.  const
  4410.    SHERB_NOCONFIRMATION = $00000001;
  4411.    SHERB_NOPROGRESSUI   = $00000002;
  4412. @@ -2039,7 +2056,7 @@
  4413.  
  4414.  // Template
  4415.  // http://www.dsdt.info/tipps/?id=116
  4416. -function RecyclerAddFileOrFolder(FileOrFolder: string; confirmation: boolean): boolean; overload;
  4417. +class function TRecycleBinManager.RecyclerAddFileOrFolder(FileOrFolder: string; confirmation: boolean): boolean;
  4418.  var
  4419.    Operation: TSHFileOpStruct;
  4420.  begin
  4421. @@ -2055,12 +2072,12 @@
  4422.    Result := SHFileOperation(Operation) = 0;
  4423.  end;
  4424.  
  4425. -function RecyclerAddFileOrFolder(FileOrFolder: string): boolean; overload;
  4426. +class function TRecycleBinManager.RecyclerAddFileOrFolder(FileOrFolder: string): boolean;
  4427.  begin
  4428.    result := RecyclerAddFileOrFolder(FileOrFolder, false);
  4429.  end;
  4430.  
  4431. -function RecyclerConfirmationDialogEnabled: boolean;
  4432. +class function TRecycleBinManager.RecyclerConfirmationDialogEnabled: boolean;
  4433.  var
  4434.    gp: GPOLICYBOOL;
  4435.  begin
  4436. @@ -2075,7 +2092,7 @@
  4437.    end;
  4438.  end;
  4439.  
  4440. -function RecyclerShellStateConfirmationDialogEnabled: boolean;
  4441. +class function TRecycleBinManager.RecyclerShellStateConfirmationDialogEnabled: boolean;
  4442.  type
  4443.    TSHGetSettings = procedure (var lpss: SHELLSTATE; dwMask: DWORD) stdcall;
  4444.  const
  4445. @@ -2147,7 +2164,7 @@
  4446.    if (RBHandle <> 0) then FreeLibrary(RBHandle);
  4447.  end;
  4448.  
  4449. -procedure RecyclerConfirmationDialogSetEnabled(NewSetting: boolean);
  4450. +class procedure TRecycleBinManager.RecyclerConfirmationDialogSetEnabled(NewSetting: boolean);
  4451.  type
  4452.    TSHGetSetSettings = procedure (var lpss: SHELLSTATE; dwMask: DWORD; bSet: BOOL) stdcall;
  4453.  const
  4454. @@ -2226,76 +2243,11 @@
  4455.    if (RBHandle <> 0) then FreeLibrary(RBHandle);
  4456.  end;
  4457.  
  4458. -function RecyclerGetCurrentIconString: string;
  4459. -begin
  4460. -  if RecyclerIsEmpty then
  4461. -    result := RecyclerGetEmptyIconString
  4462. -  else
  4463. -    result := RecyclerGetFullIconString;
  4464. -end;
  4465.  
  4466. -function RecyclerGetDefaultIconString: string;
  4467. +class function TRecycleBinManager.RecyclerGetName: string;
  4468.  var
  4469.    reg: TRegistry;
  4470.  begin
  4471. -  // Please note: The "default" icon is not always the icon of the
  4472. -  // current recycle bin in its current state (full, empty)
  4473. -  // At Windows 95b, the registry value actually did change every time the
  4474. -  // recycle bin state did change, but at Windows 2000 I could not see any
  4475. -  // update, even after reboot. So, the registry value is possible fixed as
  4476. -  // default = empty on newer OS versions.
  4477. -
  4478. -  reg := TRegistry.Create;
  4479. -  try
  4480. -    reg.RootKey := HKEY_CLASSES_ROOT;
  4481. -    if reg.OpenKeyReadOnly('CLSID\'+RECYCLER_CLSID+'\DefaultIcon') then
  4482. -    begin
  4483. -      result := reg.ReadString('');
  4484. -      reg.CloseKey;
  4485. -    end;
  4486. -  finally
  4487. -    reg.Free;
  4488. -  end;
  4489. -end;
  4490. -
  4491. -function RecyclerGetEmptyIconString: string;
  4492. -var
  4493. -  reg: TRegistry;
  4494. -begin
  4495. -  reg := TRegistry.Create;
  4496. -  try
  4497. -    reg.RootKey := HKEY_CLASSES_ROOT;
  4498. -    if reg.OpenKeyReadOnly('CLSID\'+RECYCLER_CLSID+'\DefaultIcon') then
  4499. -    begin
  4500. -      result := reg.ReadString('Empty');
  4501. -      reg.CloseKey;
  4502. -    end;
  4503. -  finally
  4504. -    reg.Free;
  4505. -  end;
  4506. -end;
  4507. -
  4508. -function RecyclerGetFullIconString: string;
  4509. -var
  4510. -  reg: TRegistry;
  4511. -begin
  4512. -  reg := TRegistry.Create;
  4513. -  try
  4514. -    reg.RootKey := HKEY_CLASSES_ROOT;
  4515. -    if reg.OpenKeyReadOnly('CLSID\'+RECYCLER_CLSID+'\DefaultIcon') then
  4516. -    begin
  4517. -      result := reg.ReadString('Full');
  4518. -      reg.CloseKey;
  4519. -    end;
  4520. -  finally
  4521. -    reg.Free;
  4522. -  end;
  4523. -end;
  4524. -
  4525. -function RecyclerGetName: string;
  4526. -var
  4527. -  reg: TRegistry;
  4528. -begin
  4529.    // Windows 95b:
  4530.    // Change of CLSID\{645FF040-5081-101B-9F08-00AA002F954E} will change the desktop name of the recycle bin.
  4531.  
  4532. @@ -2324,7 +2276,7 @@
  4533.    end;
  4534.  end;
  4535.  
  4536. -function RecyclerGetInfoTip: string;
  4537. +class function TRecycleBinManager.RecyclerGetInfoTip: string;
  4538.  var
  4539.    reg: TRegistry;
  4540.  begin
  4541. @@ -2345,7 +2297,7 @@
  4542.    end;
  4543.  end;
  4544.  
  4545. -function RecyclerGetIntroText: string;
  4546. +class function TRecycleBinManager.RecyclerGetIntroText: string;
  4547.  var
  4548.    reg: TRegistry;
  4549.  begin
  4550. @@ -2366,7 +2318,7 @@
  4551.    end;
  4552.  end;
  4553.  
  4554. -function RecyclerEmptyEventGetName: string;
  4555. +class function TRecycleBinManager.RecyclerEmptyEventGetName: string;
  4556.  var
  4557.    reg: TRegistry;
  4558.  begin
  4559. @@ -2383,17 +2335,17 @@
  4560.    end;
  4561.  end;
  4562.  
  4563. -function RecyclerEmptyEventGetCurrentSound: string;
  4564. +class function TRecycleBinManager.RecyclerEmptyEventGetCurrentSound: string;
  4565.  begin
  4566.    result := RecyclerEmptyEventGetSound('.Current');
  4567.  end;
  4568.  
  4569. -function RecyclerEmptyEventGetDefaultSound: string;
  4570. +class function TRecycleBinManager.RecyclerEmptyEventGetDefaultSound: string;
  4571.  begin
  4572.    result := RecyclerEmptyEventGetSound('.Default');
  4573.  end;
  4574.  
  4575. -procedure RecyclerEmptyEventGetSoundCategories(AStringList: TStringList);
  4576. +class procedure TRecycleBinManager.RecyclerEmptyEventGetSoundCategories(AStringList: TStringList);
  4577.  var
  4578.    reg: TRegistry;
  4579.  begin
  4580. @@ -2410,7 +2362,7 @@
  4581.    end;
  4582.  end;
  4583.  
  4584. -function RecyclerEmptyEventGetSound(ACategory: string): string;
  4585. +class function TRecycleBinManager.RecyclerEmptyEventGetSound(ACategory: string): string;
  4586.  var
  4587.    reg: TRegistry;
  4588.  resourcestring
  4589. @@ -2437,7 +2389,7 @@
  4590.    end;
  4591.  end;
  4592.  
  4593. -function RecyclerGlobalGetPercentUsage: integer;
  4594. +class function TRecycleBinManager.RecyclerGlobalGetPercentUsage: integer;
  4595.  var
  4596.    reg: TRegistry;
  4597.    dump: string;
  4598. @@ -2479,7 +2431,7 @@
  4599.    end;
  4600.  end;
  4601.  
  4602. -function RecyclerSpecificGetPercentUsage(Drive: Char): integer;
  4603. +class function TRecycleBinManager.RecyclerSpecificGetPercentUsage(Drive: Char): integer;
  4604.  var
  4605.    reg: TRegistry;
  4606.    dump: string;
  4607. @@ -2540,7 +2492,7 @@
  4608.    end;
  4609.  end;
  4610.  
  4611. -function RecyclerGetPercentUsageAutoDeterminate(Drive: Char): integer;
  4612. +class function TRecycleBinManager.RecyclerGetPercentUsageAutoDeterminate(Drive: Char): integer;
  4613.  var
  4614.    gpSetting: integer;
  4615.  begin
  4616. @@ -2553,7 +2505,7 @@
  4617.      result := RecyclerSpecificGetPercentUsage(Drive);
  4618.  end;
  4619.  
  4620. -function RecyclerGlobalIsNukeOnDelete: boolean;
  4621. +class function TRecycleBinManager.RecyclerGlobalIsNukeOnDelete: boolean;
  4622.  var
  4623.    reg: TRegistry;
  4624.    dump: string;
  4625. @@ -2597,7 +2549,7 @@
  4626.    end;
  4627.  end;
  4628.  
  4629. -function RecyclerSpecificIsNukeOnDelete(Drive: Char): boolean;
  4630. +class function TRecycleBinManager.RecyclerSpecificIsNukeOnDelete(Drive: Char): boolean;
  4631.  var
  4632.    reg: TRegistry;
  4633.    dump: string;
  4634. @@ -2663,7 +2615,7 @@
  4635.    end;
  4636.  end;
  4637.  
  4638. -function RecyclerIsNukeOnDeleteAutoDeterminate(Drive: Char): boolean;
  4639. +class function TRecycleBinManager.RecyclerIsNukeOnDeleteAutoDeterminate(Drive: Char): boolean;
  4640.  begin
  4641.    if RecyclerGroupPolicyNoRecycleFiles = gpEnabled then
  4642.      result := true
  4643. @@ -2673,7 +2625,7 @@
  4644.      result := RecyclerSpecificIsNukeOnDelete(Drive);
  4645.  end;
  4646.  
  4647. -function RecyclerHasGlobalSettings: boolean;
  4648. +class function TRecycleBinManager.RecyclerHasGlobalSettings: boolean;
  4649.  var
  4650.    reg: TRegistry;
  4651.    dump: string;
  4652. @@ -2720,27 +2672,8 @@
  4653.    end;
  4654.  end;
  4655.  
  4656. -function RecyclerIsEmpty: boolean;
  4657. -var
  4658. -  Drive: Char;
  4659. -begin
  4660. -  result := true;
  4661. -  for Drive := 'A' to 'Z' do
  4662. -  begin
  4663. -    if RecyclerIsPossible(Drive) and not RecyclerIsEmpty(Drive) then
  4664. -    begin
  4665. -      result := false;
  4666. -      exit;
  4667. -    end;
  4668. -  end;
  4669. -end;
  4670.  
  4671. -function RecyclerIsEmpty(Drive: Char): boolean;
  4672. -begin
  4673. -  result := RecyclerGetAPIInfo(Drive).i64NumItems = 0;
  4674. -end;
  4675. -
  4676. -function RecyclerGetNumItems: int64;
  4677. +class function TRecycleBinManager.RecyclerGetNumItems: int64;
  4678.  var
  4679.    Drive: Char;
  4680.  begin
  4681. @@ -2754,12 +2687,12 @@
  4682.    end;
  4683.  end;
  4684.  
  4685. -function RecyclerGetNumItems(Drive: Char): int64;
  4686. +class function TRecycleBinManager.RecyclerGetNumItems(Drive: Char): int64;
  4687.  begin
  4688.    result := RecyclerGetAPIInfo(Drive).i64NumItems;
  4689.  end;
  4690.  
  4691. -function RecyclerGetSize: int64;
  4692. +class function TRecycleBinManager.RecyclerGetSize: int64;
  4693.  var
  4694.    Drive: Char;
  4695.  begin
  4696. @@ -2773,12 +2706,12 @@
  4697.    end;
  4698.  end;
  4699.  
  4700. -function RecyclerGetSize(Drive: Char): int64;
  4701. +class function TRecycleBinManager.RecyclerGetSize(Drive: Char): int64;
  4702.  begin
  4703.    result := RecyclerGetAPIInfo(Drive).i64Size;
  4704.  end;
  4705.  
  4706. -function RecyclerGetAPIInfo(Drive: Char): TSHQueryRBInfo;
  4707. +class function TRecycleBinManager.RecyclerGetAPIInfo(Drive: Char): TSHQueryRBInfo;
  4708.  begin
  4709.    result := RecyclerGetAPIInfo(Drive + ':\');
  4710.  end;
  4711. @@ -2790,7 +2723,7 @@
  4712.    TSHQueryRecycleBin = function(pszRootPath: LPCTSTR;
  4713.      var pSHQueryRBInfo: TSHQueryRBInfo): HRESULT; stdcall;
  4714.  
  4715. -function RecyclerGetAPIInfo(Path: String): TSHQueryRBInfo;
  4716. +class function TRecycleBinManager.RecyclerGetAPIInfo(Path: String): TSHQueryRBInfo;
  4717.  var
  4718.    PSHQueryRecycleBin: TSHQueryRecycleBin;
  4719.    RBHandle: THandle;
  4720. @@ -2835,13 +2768,13 @@
  4721.    if (RBHandle <> 0) then FreeLibrary(RBHandle);
  4722.  end;
  4723.  
  4724. -function RecyclerGetCLSID: string;
  4725. +class function TRecycleBinManager.RecyclerGetCLSID: string;
  4726.  begin
  4727.    result := RECYCLER_CLSID;
  4728.  end;
  4729.  
  4730.  // Windows 95 without Internet Explorer 4 has no SHQueryRecycleBinA.
  4731. -function RecyclerQueryFunctionAvailable: boolean;
  4732. +class function TRecycleBinManager.RecyclerQueryFunctionAvailable: boolean;
  4733.  var
  4734.    RBHandle: THandle;
  4735.    SHQueryRecycleBin: TSHQueryRecycleBin;
  4736. @@ -2865,7 +2798,7 @@
  4737.  
  4738.  // TODO: In future also detect for other users
  4739.  // TODO: Also make a setter (inkl. Message to Windows Explorer?)
  4740. -function RecyclerGroupPolicyNoRecycleFiles: GPOLICYBOOL;
  4741. +class function TRecycleBinManager.RecyclerGroupPolicyNoRecycleFiles: GPOLICYBOOL;
  4742.  var
  4743.    reg: TRegistry;
  4744.  begin
  4745. @@ -2911,7 +2844,7 @@
  4746.  
  4747.  // TODO: In future also detect for other users
  4748.  // TODO: Also make a setter (inkl. Message to Windows Explorer?)
  4749. -function RecyclerGroupPolicyConfirmFileDelete: GPOLICYBOOL;
  4750. +class function TRecycleBinManager.RecyclerGroupPolicyConfirmFileDelete: GPOLICYBOOL;
  4751.  var
  4752.    reg: TRegistry;
  4753.  begin
  4754. @@ -2957,7 +2890,7 @@
  4755.  
  4756.  // TODO: In future also detect for other users
  4757.  // TODO: Also make a setter (inkl. Message to Windows Explorer?)
  4758. -function RecyclerGroupPolicyRecycleBinSize: integer;
  4759. +class function TRecycleBinManager.RecyclerGroupPolicyRecycleBinSize: integer;
  4760.  var
  4761.    reg: TRegistry;
  4762.  begin
  4763. @@ -3003,7 +2936,7 @@
  4764.    end;
  4765.  end;
  4766.  
  4767. -function RecyclerIsPossible(Drive: Char): boolean;
  4768. +class function TRecycleBinManager.RecyclerIsPossible(Drive: Char): boolean;
  4769.  var
  4770.    typ: Integer;
  4771.  begin
  4772. @@ -3011,9 +2944,10 @@
  4773.    result := typ = DRIVE_FIXED;
  4774.  end;
  4775.  
  4776. -function RecyclerLibraryVersion: string;
  4777. +class function TRecycleBinManager.RecyclerLibraryVersion: string;
  4778.  begin
  4779.    result := 'ViaThinkSoft Recycle Bin Unit [05 JUL 2010]';
  4780.  end;
  4781.  
  4782.  end.
  4783. +
  4784. Index: Windows 95 Bit Bucket Reader/BitBucketReader.exe
  4785. ===================================================================
  4786. Cannot display: file marked as a binary type.
  4787. svn:mime-type = application/octet-stream
  4788.