BaseUtils.pas 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  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;
  22. function CheckFileExists(FileName: string): Boolean;
  23. function DirExists(Dir: string): Boolean; overload;
  24. function DirExists(Dir: string; var Attrs: Integer): Boolean; overload;
  25. function DiskSize(Drive: Byte): Int64;
  26. function ExtractFileNameOnly(Name: string): string;
  27. function FileOrDirExists(FileName: string): Boolean;
  28. function FormatSize(Size: Integer): string; overload;
  29. function FormatSize(Size: Cardinal): string; overload;
  30. function FormatSize(Size: Int64): string; overload;
  31. procedure FreePIDL(var PIDL: PItemIDList);
  32. function StrContains(Str1, Str2: string): Boolean;
  33. procedure StrTranslate(var Str: string; Code: string);
  34. function IsUncPath(Path: string): Boolean;
  35. function AnyValidPath: string;
  36. procedure UnifyDateTimePrecision(var DateTime1: TDateTime; var DateTime2: TDateTime);
  37. //from math.pas of VCL
  38. {function Min(const A, B: Integer): Integer; overload;
  39. function Min(const A, B: Int64): Int64; overload;
  40. function Min(const A, B: Single): Single; overload;
  41. function Min(const A, B: Double): Double; overload;
  42. function Min(const A, B: Extended): Extended; overload;
  43. function Max(const A, B: Integer): Integer; overload;
  44. function Max(const A, B: Int64): Int64; overload;
  45. function Max(const A, B: Single): Single; overload;
  46. function Max(const A, B: Double): Double; overload;
  47. function Max(const A, B: Extended): Extended; overload;}
  48. resourcestring
  49. SNoValidPath = 'Can''t find any valid path.';
  50. SUcpPathsNotSupported = 'UNC paths are not supported.';
  51. implementation
  52. uses
  53. IEDriveInfo, DateUtils;
  54. var
  55. GetDiskFreeSpaceEx: function (Directory: PChar;
  56. var FreeAvailable, TotalSpace: TLargeInteger; TotalFree: PLargeInteger): Bool stdcall = nil;
  57. function AnyValidPath: string;
  58. var
  59. Drive: TDrive;
  60. begin
  61. for Drive := 'C' to 'Z' do
  62. if (DriveInfo[Drive].DriveType = DRIVE_FIXED) and
  63. DirectoryExists(Drive + ':\') then
  64. begin
  65. Result := Drive + ':\';
  66. Exit;
  67. end;
  68. for Drive := 'C' to 'Z' do
  69. if (DriveInfo[Drive].DriveType = DRIVE_REMOTE) and
  70. DirectoryExists(Drive + ':\') then
  71. begin
  72. Result := Drive + ':\';
  73. Exit;
  74. end;
  75. raise Exception.Create(SNoValidPath);
  76. end;
  77. function IsUncPath(Path: string): Boolean;
  78. begin
  79. Result := (Copy(Path, 1, 2) = '\\') or (Copy(Path, 1, 2) = '//');
  80. end;
  81. procedure StrTranslate(var Str: string; Code: string);
  82. var
  83. Index: Integer;
  84. begin
  85. if (Length(Code) > 0) and (Length(Code) mod 2 = 0) then
  86. for Index := 1 to Length(Code) div 2 do
  87. while Pos(Code[Index*2-1], Str) <> 0 do
  88. Str[Pos(Code[Index*2-1], Str)] := Code[Index*2];
  89. end; {StrTranslate}
  90. function StrContains(Str1, Str2: string): Boolean;
  91. var
  92. Index: Integer;
  93. begin
  94. for Index := 1 to Length(Str1) do
  95. if Pos(Str1[Index], Str2) <> 0 then
  96. begin
  97. Result := True;
  98. Exit;
  99. end;
  100. Result := False;
  101. end; {StringCountains}
  102. function FileOrDirExists(FileName: string): Boolean;
  103. var
  104. SRec : TSearchRec;
  105. begin
  106. if Length(FileName) = 0 then Result := False
  107. else
  108. begin
  109. Result := (FindFirst(FileName, faAnyFile, SRec) = 0);
  110. SysUtils.FindCLose(SRec);
  111. end;
  112. end; {FileOrDirExists}
  113. function CheckFileExists(FileName: string): Boolean;
  114. var
  115. SaveFileMode : Integer;
  116. F: file;
  117. begin
  118. SaveFileMode := System.FileMode;
  119. System.FileMode := 0;
  120. try
  121. AssignFile(F, FileName);
  122. Reset(F, 1);
  123. Result := IOResult = 0;
  124. if Result then
  125. CloseFile(F);
  126. finally
  127. System.FileMode := SaveFileMode;
  128. end;
  129. end; {CheckFileExists}
  130. function DirExists(Dir: string; var Attrs: Integer): Boolean;
  131. var
  132. SRec: TSearchRec;
  133. begin
  134. Result := ((Length(Dir) <= 3) and (Length(Dir) >= 2)) and (Dir[2] = ':');
  135. if Result then Attrs := 0
  136. else
  137. begin
  138. if FindFirst(Dir, faAnyFile, SRec) = 0 then
  139. begin
  140. Result := (SRec.Attr and faDirectory <> 0);
  141. Attrs := SRec.Attr;
  142. end;
  143. SysUtils.FindClose(SRec);
  144. end;
  145. end; {DirExists}
  146. function DirExists(Dir: string): Boolean;
  147. var
  148. Dummy: Integer;
  149. begin
  150. Result := DirExists(Dir, Dummy);
  151. end; {DirExists}
  152. function ExtractFileNameOnly(Name: string): string;
  153. var
  154. Ext: string;
  155. begin
  156. Result := ExtractFileName(Name);
  157. Ext := ExtractFileExt(Name);
  158. if Ext <> '' then
  159. Delete(Result, Length(Result)-Length(Ext)+1, Length(Ext));
  160. end; {ExtractFileNameOnly}
  161. function FormatSize(Size: Integer): string;
  162. begin
  163. Result := FormatSize(Cardinal(Abs(Size)));
  164. end; {FormatSize}
  165. function FormatSize(Size: Cardinal): string;
  166. var
  167. i: Integer;
  168. p: Integer;
  169. begin
  170. p := 0;
  171. i := 3;
  172. Result := IntToStr(Size);
  173. while i + p < Length(Result) do
  174. begin
  175. Insert(ThousandSeparator, Result, Length(Result) - (i + p)+ 1);
  176. Inc(p);
  177. INC(i, 3);
  178. end;
  179. end; {FormatSize}
  180. function FormatSize(Size: Int64): String;
  181. var
  182. i: Integer;
  183. p: Integer;
  184. begin
  185. p := 0;
  186. i := 3;
  187. Result := IntToStr(Size);
  188. while i + p < Length(Result) do
  189. begin
  190. Insert(ThousandSeparator, Result, Length(Result) - (i + p)+ 1);
  191. Inc(p);
  192. Inc(i, 3);
  193. end;
  194. end; {FormatSize}
  195. procedure FreePIDL(var PIDL: PItemIDList);
  196. begin
  197. if PIDL <> nil then
  198. begin
  199. try
  200. ShellMalloc.Free(PIDL);
  201. PIDL := NIL;
  202. except
  203. PIDL := NIL;
  204. end;
  205. end;
  206. end; {FreePIDL}
  207. function InternalGetDiskSpace(Drive: Byte;
  208. var TotalSpace, FreeSpaceAvailable: Int64): Bool;
  209. var
  210. RootPath: array[0..4] of Char;
  211. RootPtr: PChar;
  212. begin
  213. RootPtr := nil;
  214. if Drive > 0 then
  215. begin
  216. RootPath[0] := Char(Drive + $40);
  217. RootPath[1] := ':';
  218. RootPath[2] := '\';
  219. RootPath[3] := #0;
  220. RootPtr := RootPath;
  221. end;
  222. Result := GetDiskFreeSpaceEx(RootPtr, FreeSpaceAvailable, TotalSpace, nil);
  223. end;
  224. // This function is used if the OS doesn't support GetDiskFreeSpaceEx
  225. function BackfillGetDiskFreeSpaceEx(Directory: PChar; var FreeAvailable,
  226. TotalSpace: TLargeInteger; TotalFree: PLargeInteger): Bool; stdcall;
  227. var
  228. SectorsPerCluster, BytesPerSector, FreeClusters, TotalClusters: LongWord;
  229. Temp: Int64;
  230. Dir: PChar;
  231. begin
  232. if Directory <> nil then
  233. Dir := Directory
  234. else
  235. Dir := nil;
  236. Result := GetDiskFreeSpaceA(Dir, SectorsPerCluster, BytesPerSector,
  237. FreeClusters, TotalClusters);
  238. Temp := SectorsPerCluster * BytesPerSector;
  239. FreeAvailable := Temp * FreeClusters;
  240. TotalSpace := Temp * TotalClusters;
  241. end;
  242. function DiskSize(Drive: Byte): Int64;
  243. var
  244. FreeSpace: Int64;
  245. begin
  246. if not InternalGetDiskSpace(Drive, Result, FreeSpace) then
  247. Result := -1;
  248. end;
  249. procedure InitDriveSpacePtr;
  250. var
  251. Kernel: THandle;
  252. begin
  253. Kernel := GetModuleHandle(Windows.Kernel32);
  254. if Kernel <> 0 then
  255. @GetDiskFreeSpaceEx := GetProcAddress(Kernel, 'GetDiskFreeSpaceExA');
  256. if not Assigned(GetDiskFreeSpaceEx) then
  257. GetDiskFreeSpaceEx := @BackfillGetDiskFreeSpaceEx;
  258. end;
  259. procedure UnifyDateTimePrecision(var DateTime1: TDateTime; var DateTime2: TDateTime);
  260. function Unify(var V1, V2: Word): Boolean;
  261. begin
  262. Result := (V1 = 0) or (V2 = 0);
  263. if Result then
  264. begin
  265. V1 := 0;
  266. V2 := 0;
  267. end;
  268. end;
  269. var
  270. Y1, M1, D1, H1, N1, S1, MS1: Word;
  271. Y2, M2, D2, H2, N2, S2, MS2: Word;
  272. Changed: Boolean;
  273. begin
  274. if DateTime1 <> DateTime2 then
  275. begin
  276. DecodeDateTime(DateTime1, Y1, M1, D1, H1, N1, S1, MS1);
  277. DecodeDateTime(DateTime2, Y2, M2, D2, H2, N2, S2, MS2);
  278. Changed := Unify(MS1, MS2);
  279. if Changed and Unify(S1, S2) and Unify(N1, N2) and Unify(H1, H2) and
  280. Unify(D1, D2) and Unify(M1, M2) then Unify(Y1, Y2);
  281. if Changed then
  282. begin
  283. DateTime1 := EncodeDate(Y1, M1, D1) + EncodeTime(H1, N1, S1, MS1);
  284. DateTime2 := EncodeDate(Y2, M2, D2) + EncodeTime(H2, N2, S2, MS2);
  285. end;
  286. end;
  287. end;
  288. {function Min(const A, B: Integer): Integer;
  289. begin
  290. if A < B then
  291. Result := A
  292. else
  293. Result := B;
  294. end;
  295. function Min(const A, B: Int64): Int64;
  296. begin
  297. if A < B then
  298. Result := A
  299. else
  300. Result := B;
  301. end;
  302. function Min(const A, B: Single): Single;
  303. begin
  304. if A < B then
  305. Result := A
  306. else
  307. Result := B;
  308. end;
  309. function Min(const A, B: Double): Double;
  310. begin
  311. if A < B then
  312. Result := A
  313. else
  314. Result := B;
  315. end;
  316. function Min(const A, B: Extended): Extended;
  317. begin
  318. if A < B then
  319. Result := A
  320. else
  321. Result := B;
  322. end;
  323. function Max(const A, B: Integer): Integer;
  324. begin
  325. if A > B then
  326. Result := A
  327. else
  328. Result := B;
  329. end;
  330. function Max(const A, B: Int64): Int64;
  331. begin
  332. if A > B then
  333. Result := A
  334. else
  335. Result := B;
  336. end;
  337. function Max(const A, B: Single): Single;
  338. begin
  339. if A > B then
  340. Result := A
  341. else
  342. Result := B;
  343. end;
  344. function Max(const A, B: Double): Double;
  345. begin
  346. if A > B then
  347. Result := A
  348. else
  349. Result := B;
  350. end;
  351. function Max(const A, B: Extended): Extended;
  352. begin
  353. if A > B then
  354. Result := A
  355. else
  356. Result := B;
  357. end;
  358. }
  359. initialization
  360. InitDriveSpacePtr;
  361. end.