BaseUtils.pas 8.2 KB

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