BaseUtils.pas 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. unit BaseUtils;
  2. {==================================================================
  3. Basic file handling utilities / Version 1.2 / 11.1999
  4. ========================================================
  5. Description:
  6. ============
  7. Basic utilities useful for handling files or directories.
  8. Used by the components TDriveView and TDirView.
  9. Author:
  10. =======
  11. (c) Ingo Eckel 5/1998
  12. Sodener Weg 38
  13. 65812 Bad Soden
  14. Germany
  15. Modifications (for WinSCP):
  16. ===========================
  17. (c) Martin Prikryl 2001, 2002
  18. {==================================================================}
  19. interface
  20. uses
  21. SysUtils, Windows, Forms, ShlObj, PIDL, Classes, Controls;
  22. type
  23. TDateTimePrecision = (tpDay, tpMinute, tpSecond, tpMillisecond);
  24. function CheckFileExists(FileName: string): Boolean;
  25. function DirExists(Dir: string): Boolean; overload;
  26. function DirExists(Dir: string; var Attrs: Integer): Boolean; overload;
  27. function DiskSize(Drive: Byte): Int64;
  28. function ExtractFileNameOnly(Name: string): string;
  29. function FileOrDirExists(FileName: string): Boolean;
  30. function FormatSize(Size: Integer): string; overload;
  31. function FormatSize(Size: Cardinal): string; overload;
  32. function FormatSize(Size: Int64): string; overload;
  33. procedure FreePIDL(var PIDL: PItemIDList);
  34. function StrContains(Str1, Str2: string): Boolean;
  35. procedure StrTranslate(var Str: string; Code: string);
  36. function IsUncPath(Path: string): Boolean;
  37. function AnyValidPath: string;
  38. procedure ReduceDateTimePrecision(var DateTime: TDateTime;
  39. Precision: TDateTimePrecision);
  40. function SpecialFolderLocation(Folder: Integer; var Path: string;
  41. var PIDL: PItemIDList): Boolean; overload;
  42. function SpecialFolderLocation(Folder: Integer; var Path: string): Boolean; overload;
  43. function ShellImageList(Owner: TComponent; Flags: UINT): TImageList;
  44. resourcestring
  45. SNoValidPath = 'Can''t find any valid path.';
  46. SUcpPathsNotSupported = 'UNC paths are not supported.';
  47. implementation
  48. uses
  49. IEDriveInfo, DateUtils, ShellApi;
  50. var
  51. GetDiskFreeSpaceEx: function (Directory: PChar;
  52. var FreeAvailable, TotalSpace: TLargeInteger; TotalFree: PLargeInteger): Bool stdcall = nil;
  53. function AnyValidPath: string;
  54. var
  55. Drive: TDrive;
  56. begin
  57. for Drive := 'C' to 'Z' do
  58. if (DriveInfo[Drive].DriveType = DRIVE_FIXED) and
  59. DirectoryExists(Drive + ':\') then
  60. begin
  61. Result := Drive + ':\';
  62. Exit;
  63. end;
  64. for Drive := 'C' to 'Z' do
  65. if (DriveInfo[Drive].DriveType = DRIVE_REMOTE) and
  66. DirectoryExists(Drive + ':\') then
  67. begin
  68. Result := Drive + ':\';
  69. Exit;
  70. end;
  71. raise Exception.Create(SNoValidPath);
  72. end;
  73. function IsUncPath(Path: string): Boolean;
  74. begin
  75. Result := (Copy(Path, 1, 2) = '\\') or (Copy(Path, 1, 2) = '//');
  76. end;
  77. procedure StrTranslate(var Str: string; Code: string);
  78. var
  79. Index: Integer;
  80. begin
  81. if (Length(Code) > 0) and (Length(Code) mod 2 = 0) then
  82. for Index := 1 to Length(Code) div 2 do
  83. while Pos(Code[Index*2-1], Str) <> 0 do
  84. Str[Pos(Code[Index*2-1], Str)] := Code[Index*2];
  85. end; {StrTranslate}
  86. function StrContains(Str1, Str2: string): Boolean;
  87. var
  88. Index: Integer;
  89. begin
  90. for Index := 1 to Length(Str1) do
  91. if Pos(Str1[Index], Str2) <> 0 then
  92. begin
  93. Result := True;
  94. Exit;
  95. end;
  96. Result := False;
  97. end; {StringCountains}
  98. function FileOrDirExists(FileName: string): Boolean;
  99. var
  100. SRec : TSearchRec;
  101. begin
  102. if Length(FileName) = 0 then Result := False
  103. else
  104. begin
  105. Result := (FindFirst(FileName, faAnyFile, SRec) = 0);
  106. SysUtils.FindCLose(SRec);
  107. end;
  108. end; {FileOrDirExists}
  109. function CheckFileExists(FileName: string): Boolean;
  110. var
  111. SaveFileMode : Integer;
  112. F: file;
  113. begin
  114. SaveFileMode := System.FileMode;
  115. System.FileMode := 0;
  116. try
  117. AssignFile(F, FileName);
  118. Reset(F, 1);
  119. Result := IOResult = 0;
  120. if Result then
  121. CloseFile(F);
  122. finally
  123. System.FileMode := SaveFileMode;
  124. end;
  125. end; {CheckFileExists}
  126. function DirExists(Dir: string; var Attrs: Integer): Boolean;
  127. var
  128. SRec: TSearchRec;
  129. begin
  130. Result := ((Length(Dir) <= 3) and (Length(Dir) >= 2)) and (Dir[2] = ':');
  131. if Result then Attrs := 0
  132. else
  133. begin
  134. if FindFirst(Dir, faAnyFile, SRec) = 0 then
  135. begin
  136. Result := (SRec.Attr and faDirectory <> 0);
  137. Attrs := SRec.Attr;
  138. end;
  139. SysUtils.FindClose(SRec);
  140. end;
  141. end; {DirExists}
  142. function DirExists(Dir: string): Boolean;
  143. var
  144. Dummy: Integer;
  145. begin
  146. Result := DirExists(Dir, Dummy);
  147. end; {DirExists}
  148. function ExtractFileNameOnly(Name: string): string;
  149. var
  150. Ext: string;
  151. begin
  152. Result := ExtractFileName(Name);
  153. Ext := ExtractFileExt(Name);
  154. if Ext <> '' then
  155. Delete(Result, Length(Result)-Length(Ext)+1, Length(Ext));
  156. end; {ExtractFileNameOnly}
  157. function FormatSize(Size: Integer): string;
  158. begin
  159. Result := FormatSize(Cardinal(Abs(Size)));
  160. end; {FormatSize}
  161. function FormatSize(Size: Cardinal): string;
  162. var
  163. i: Integer;
  164. p: Integer;
  165. begin
  166. p := 0;
  167. i := 3;
  168. Result := IntToStr(Size);
  169. while i + p < Length(Result) do
  170. begin
  171. Insert(ThousandSeparator, Result, Length(Result) - (i + p)+ 1);
  172. Inc(p);
  173. INC(i, 3);
  174. end;
  175. end; {FormatSize}
  176. function FormatSize(Size: Int64): String;
  177. var
  178. i: Integer;
  179. p: Integer;
  180. begin
  181. p := 0;
  182. i := 3;
  183. Result := IntToStr(Size);
  184. while i + p < Length(Result) do
  185. begin
  186. Insert(ThousandSeparator, Result, Length(Result) - (i + p)+ 1);
  187. Inc(p);
  188. Inc(i, 3);
  189. end;
  190. end; {FormatSize}
  191. procedure FreePIDL(var PIDL: PItemIDList);
  192. begin
  193. if PIDL <> nil then
  194. begin
  195. try
  196. ShellMalloc.Free(PIDL);
  197. PIDL := NIL;
  198. except
  199. PIDL := NIL;
  200. end;
  201. end;
  202. end; {FreePIDL}
  203. function InternalGetDiskSpace(Drive: Byte;
  204. var TotalSpace, FreeSpaceAvailable: Int64): Bool;
  205. var
  206. RootPath: array[0..4] of Char;
  207. RootPtr: PChar;
  208. begin
  209. RootPtr := nil;
  210. if Drive > 0 then
  211. begin
  212. RootPath[0] := Char(Drive + $40);
  213. RootPath[1] := ':';
  214. RootPath[2] := '\';
  215. RootPath[3] := #0;
  216. RootPtr := RootPath;
  217. end;
  218. Result := GetDiskFreeSpaceEx(RootPtr, FreeSpaceAvailable, TotalSpace, nil);
  219. end;
  220. // This function is used if the OS doesn't support GetDiskFreeSpaceEx
  221. function BackfillGetDiskFreeSpaceEx(Directory: PChar; var FreeAvailable,
  222. TotalSpace: TLargeInteger; TotalFree: PLargeInteger): Bool; stdcall;
  223. var
  224. SectorsPerCluster, BytesPerSector, FreeClusters, TotalClusters: LongWord;
  225. Temp: Int64;
  226. Dir: PChar;
  227. begin
  228. if Directory <> nil then
  229. Dir := Directory
  230. else
  231. Dir := nil;
  232. Result := GetDiskFreeSpaceA(Dir, SectorsPerCluster, BytesPerSector,
  233. FreeClusters, TotalClusters);
  234. Temp := SectorsPerCluster * BytesPerSector;
  235. FreeAvailable := Temp * FreeClusters;
  236. TotalSpace := Temp * TotalClusters;
  237. end;
  238. function DiskSize(Drive: Byte): Int64;
  239. var
  240. FreeSpace: Int64;
  241. begin
  242. if not InternalGetDiskSpace(Drive, Result, FreeSpace) then
  243. Result := -1;
  244. end;
  245. procedure InitDriveSpacePtr;
  246. var
  247. Kernel: THandle;
  248. begin
  249. Kernel := GetModuleHandle(Windows.Kernel32);
  250. if Kernel <> 0 then
  251. @GetDiskFreeSpaceEx := GetProcAddress(Kernel, 'GetDiskFreeSpaceExA');
  252. if not Assigned(GetDiskFreeSpaceEx) then
  253. GetDiskFreeSpaceEx := @BackfillGetDiskFreeSpaceEx;
  254. end;
  255. procedure ReduceDateTimePrecision(var DateTime: TDateTime;
  256. Precision: TDateTimePrecision);
  257. var
  258. Y, M, D, H, N, S, MS: Word;
  259. begin
  260. if Precision <> tpMillisecond then
  261. begin
  262. DecodeDateTime(DateTime, Y, M, D, H, N, S, MS);
  263. case Precision of
  264. tpDay:
  265. begin
  266. H := 0;
  267. N := 0;
  268. S := 0;
  269. MS := 0;
  270. end;
  271. tpMinute:
  272. begin
  273. S := 0;
  274. MS := 0;
  275. end;
  276. tpSecond:
  277. begin
  278. MS := 0;
  279. end;
  280. end;
  281. DateTime := EncodeDate(Y, M, D) + EncodeTime(H, N, S, MS);
  282. end;
  283. end;
  284. function SpecialFolderLocation(Folder: Integer; var Path: string;
  285. var PIDL: PItemIDList): Boolean;
  286. begin
  287. SetLength(Path, MAX_PATH);
  288. Result :=
  289. (not Failed(SHGetSpecialFolderLocation(Application.Handle, Folder, PIDL))) and
  290. SHGetPathFromIDList(PIDL, PChar(Path));
  291. if Result then SetLength(Path, StrLen(PChar(Path)));
  292. end;
  293. function SpecialFolderLocation(Folder: Integer; var Path: string): Boolean;
  294. var
  295. PIDL: PItemIDList;
  296. begin
  297. Result := SpecialFolderLocation(Folder, Path, PIDL);
  298. end;
  299. function ShellImageList(Owner: TComponent; Flags: UINT): TImageList;
  300. var
  301. FileInfo: TShFileInfo;
  302. begin
  303. Result := TImageList.Create(Owner);
  304. Result.Handle := SHGetFileInfo('', 0, FileInfo, SizeOf(FileInfo),
  305. SHGFI_SYSICONINDEX or Flags);
  306. Result.ShareImages := True;
  307. end;
  308. initialization
  309. InitDriveSpacePtr;
  310. end.