BaseUtils.pas 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  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 = (tpNone, tpDay, tpMinute, tpSecond, tpMillisecond);
  24. // order choosen so that for previous bool value, false maps to fbNone,
  25. // and true maps to new default fbKilobytes, although functionaly it is fbShort
  26. TFormatBytesStyle = (fbNone, fbKilobytes, fbShort);
  27. function CheckFileExists(FileName: string): Boolean;
  28. function DirExists(Dir: string): Boolean; overload;
  29. function DirExists(Dir: string; var Attrs: Integer): Boolean; overload;
  30. function ExtractFileNameOnly(Name: string): string;
  31. function FileOrDirExists(FileName: string): Boolean;
  32. function FormatBytes(Bytes: Int64; Style: TFormatBytesStyle = fbShort; UseUnitsForBytes: Boolean = True): string;
  33. function FormatPanelBytes(Bytes: Int64; Style: TFormatBytesStyle): string;
  34. procedure FreePIDL(var PIDL: PItemIDList);
  35. function StrContains(Str1, Str2: string): Boolean;
  36. procedure StrTranslate(var Str: string; Code: string);
  37. function IsUncPath(Path: string): Boolean;
  38. function AnyValidPath: string;
  39. procedure ReduceDateTimePrecision(var DateTime: TDateTime;
  40. Precision: TDateTimePrecision);
  41. function SpecialFolderLocation(Folder: Integer; var Path: string;
  42. var PIDL: PItemIDList): Boolean; overload;
  43. function SpecialFolderLocation(Folder: Integer; var Path: string): Boolean; overload;
  44. function ShellImageList(Owner: TComponent; Flags: UINT): TImageList;
  45. function FormatLastOSError(Message: string): string;
  46. resourcestring
  47. SNoValidPath = 'Can''t find any valid path.';
  48. SUcpPathsNotSupported = 'UNC paths are not supported.';
  49. SByte = 'B';
  50. SKiloByte = 'KB';
  51. SMegaByte = 'MB';
  52. SGigaByte = 'GB';
  53. implementation
  54. uses
  55. IEDriveInfo, DateUtils, ShellApi, SysConst, PasTools, Math;
  56. function AnyValidPath: string;
  57. var
  58. Drive: TDrive;
  59. begin
  60. for Drive := 'C' to 'Z' do
  61. if (DriveInfo[Drive].DriveType = DRIVE_FIXED) and
  62. DirectoryExists(ApiPath(Drive + ':\')) then
  63. begin
  64. Result := Drive + ':\';
  65. Exit;
  66. end;
  67. for Drive := 'C' to 'Z' do
  68. if (DriveInfo[Drive].DriveType = DRIVE_REMOTE) and
  69. DirectoryExists(ApiPath(Drive + ':\')) then
  70. begin
  71. Result := Drive + ':\';
  72. Exit;
  73. end;
  74. raise Exception.Create(SNoValidPath);
  75. end;
  76. function IsUncPath(Path: string): Boolean;
  77. begin
  78. Result := (Copy(Path, 1, 2) = '\\') or (Copy(Path, 1, 2) = '//');
  79. end;
  80. procedure StrTranslate(var Str: string; Code: string);
  81. var
  82. Index: Integer;
  83. begin
  84. if (Length(Code) > 0) and (Length(Code) mod 2 = 0) then
  85. for Index := 1 to Length(Code) div 2 do
  86. while Pos(Code[Index*2-1], Str) <> 0 do
  87. Str[Pos(Code[Index*2-1], Str)] := Code[Index*2];
  88. end; {StrTranslate}
  89. function StrContains(Str1, Str2: string): Boolean;
  90. var
  91. Index: Integer;
  92. begin
  93. for Index := 1 to Length(Str1) do
  94. if Pos(Str1[Index], Str2) <> 0 then
  95. begin
  96. Result := True;
  97. Exit;
  98. end;
  99. Result := False;
  100. end; {StringCountains}
  101. function FileOrDirExists(FileName: string): Boolean;
  102. var
  103. SRec : TSearchRec;
  104. begin
  105. if Length(FileName) = 0 then Result := False
  106. else
  107. begin
  108. Result := (FindFirst(ApiPath(FileName), faAnyFile, SRec) = 0);
  109. SysUtils.FindCLose(SRec);
  110. end;
  111. end; {FileOrDirExists}
  112. function CheckFileExists(FileName: string): Boolean;
  113. var
  114. SaveFileMode : Integer;
  115. F: file;
  116. begin
  117. SaveFileMode := System.FileMode;
  118. System.FileMode := 0;
  119. try
  120. AssignFile(F, ApiPath(FileName));
  121. Reset(F, 1);
  122. Result := IOResult = 0;
  123. if Result then
  124. CloseFile(F);
  125. finally
  126. System.FileMode := SaveFileMode;
  127. end;
  128. end; {CheckFileExists}
  129. function DirExists(Dir: string; var Attrs: Integer): Boolean;
  130. var
  131. SRec: TSearchRec;
  132. begin
  133. Result := ((Length(Dir) <= 3) and (Length(Dir) >= 2)) and (Dir[2] = ':');
  134. if Result then Attrs := 0
  135. else
  136. begin
  137. if FindFirst(ApiPath(Dir), faAnyFile, SRec) = 0 then
  138. begin
  139. Result := (SRec.Attr and faDirectory <> 0);
  140. Attrs := SRec.Attr;
  141. end;
  142. SysUtils.FindClose(SRec);
  143. end;
  144. end; {DirExists}
  145. function DirExists(Dir: string): Boolean;
  146. var
  147. Dummy: Integer;
  148. begin
  149. Result := DirExists(Dir, Dummy);
  150. end; {DirExists}
  151. function ExtractFileNameOnly(Name: string): string;
  152. var
  153. Ext: string;
  154. begin
  155. Result := ExtractFileName(Name);
  156. Ext := ExtractFileExt(Name);
  157. if Ext <> '' then
  158. Delete(Result, Length(Result)-Length(Ext)+1, Length(Ext));
  159. end; {ExtractFileNameOnly}
  160. function FormatBytes(Bytes: Int64; Style: TFormatBytesStyle; UseUnitsForBytes: Boolean): string;
  161. var
  162. SizeUnit: string;
  163. Value: Int64;
  164. Order: Int64;
  165. EValue: Extended;
  166. begin
  167. if (Style = fbNone) or ((Style = fbShort) and (Bytes < Int64(100*1024))) then
  168. begin
  169. Order := 1;
  170. if UseUnitsForBytes then
  171. SizeUnit := SByte;
  172. end
  173. else
  174. if (Style = fbKilobytes) or (Bytes < Int64(100*1024*1024)) then
  175. begin
  176. Order := 1024;
  177. SizeUnit := SKiloByte;
  178. end
  179. else
  180. if Bytes < Int64(Int64(100)*1024*1024*1024) then
  181. begin
  182. Order := 1024*1024;
  183. SizeUnit := SMegaByte;
  184. end
  185. else
  186. begin
  187. Order := 1024*1024*1024;
  188. SizeUnit := SGigaByte;
  189. end;
  190. Value := Bytes div Order;
  191. if (Bytes mod Order) > 0 then
  192. Inc(Value);
  193. EValue := Value;
  194. Result := FormatFloat('#,##0', EValue);
  195. if SizeUnit <> '' then
  196. Result := Result + ' ' + SizeUnit;
  197. end;
  198. function FormatPanelBytes(Bytes: Int64; Style: TFormatBytesStyle): string;
  199. begin
  200. Result := FormatBytes(Bytes, Style, (Style <> fbNone));
  201. end;
  202. procedure FreePIDL(var PIDL: PItemIDList);
  203. begin
  204. if PIDL <> nil then
  205. begin
  206. try
  207. ShellMalloc.Free(PIDL);
  208. PIDL := NIL;
  209. except
  210. PIDL := NIL;
  211. end;
  212. end;
  213. end; {FreePIDL}
  214. // duplicated in RemoteFiles.cpp
  215. procedure ReduceDateTimePrecision(var DateTime: TDateTime;
  216. Precision: TDateTimePrecision);
  217. var
  218. Y, M, D, H, N, S, MS: Word;
  219. begin
  220. if Precision = tpNone then DateTime := 0
  221. else
  222. if Precision <> tpMillisecond then
  223. begin
  224. DecodeDateTime(DateTime, Y, M, D, H, N, S, MS);
  225. case Precision of
  226. tpDay:
  227. begin
  228. H := 0;
  229. N := 0;
  230. S := 0;
  231. MS := 0;
  232. end;
  233. tpMinute:
  234. begin
  235. S := 0;
  236. MS := 0;
  237. end;
  238. tpSecond:
  239. begin
  240. MS := 0;
  241. end;
  242. end;
  243. DateTime := EncodeDate(Y, M, D) + EncodeTime(H, N, S, MS);
  244. end;
  245. end;
  246. function SpecialFolderLocation(Folder: Integer; var Path: string;
  247. var PIDL: PItemIDList): Boolean;
  248. begin
  249. SetLength(Path, MAX_PATH);
  250. Result :=
  251. (not Failed(SHGetSpecialFolderLocation(Application.Handle, Folder, PIDL))) and
  252. SHGetPathFromIDList(PIDL, PChar(Path));
  253. if Result then SetLength(Path, StrLen(PChar(Path)));
  254. end;
  255. function SpecialFolderLocation(Folder: Integer; var Path: string): Boolean;
  256. var
  257. PIDL: PItemIDList;
  258. begin
  259. Result := SpecialFolderLocation(Folder, Path, PIDL);
  260. end;
  261. function ShellImageList(Owner: TComponent; Flags: UINT): TImageList;
  262. var
  263. FileInfo: TShFileInfo;
  264. begin
  265. Result := TImageList.Create(Owner);
  266. Result.Handle := SHGetFileInfo('', 0, FileInfo, SizeOf(FileInfo),
  267. SHGFI_SYSICONINDEX or Flags);
  268. Result.ShareImages := True;
  269. end;
  270. function FormatLastOSError(Message: string): string;
  271. var
  272. LastError: Integer;
  273. begin
  274. Result := Message;
  275. LastError := GetLastError;
  276. if LastError <> 0 then
  277. Result := Result + #13#10 + #13#10 + Format(SOSError, [LastError, SysErrorMessage(LastError), '']);
  278. end;
  279. initialization
  280. end.