home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2001 September
/
Chip_2001-09_cd1.bin
/
zkuste
/
delphi
/
kolekce
/
d6
/
RX275D6.ZIP
/
Units
/
FileUtil.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
2001-06-24
|
38KB
|
1,235 lines
{*******************************************************}
{ }
{ Delphi VCL Extensions (RX) }
{ }
{ Copyright (c) 1995, 1996 AO ROSNO }
{ Copyright (c) 1997 Master-Bank }
{ }
{*******************************************************}
unit FileUtil;
{$I RX.INC}
{$I-,R-}
interface
uses Windows, RTLConsts, Messages, SysUtils, Classes, Consts, Controls;
procedure CopyFile(const FileName, DestName: string;
ProgressControl: TControl);
procedure CopyFileEx(const FileName, DestName: string;
OverwriteReadOnly, ShellDialog: Boolean; ProgressControl: TControl);
procedure MoveFile(const FileName, DestName: TFileName);
procedure MoveFileEx(const FileName, DestName: TFileName; ShellDialog: Boolean);
{$IFDEF RX_D4}
function GetFileSize(const FileName: string): Int64;
{$ELSE}
function GetFileSize(const FileName: string): Longint;
{$ENDIF}
function FileDateTime(const FileName: string): TDateTime;
function HasAttr(const FileName: string; Attr: Integer): Boolean;
function DeleteFiles(const FileMask: string): Boolean;
function DeleteFilesEx(const FileMasks: array of string): Boolean;
function ClearDir(const Path: string; Delete: Boolean): Boolean;
function NormalDir(const DirName: string): string;
function RemoveBackSlash(const DirName: string): string;
function ValidFileName(const FileName: string): Boolean;
function DirExists(Name: string): Boolean;
procedure ForceDirectories(Dir: string);
function FileLock(Handle: Integer; Offset, LockSize: Longint): Integer;
{$IFDEF RX_D4} overload; {$ENDIF}
{$IFDEF RX_D4}
function FileLock(Handle: Integer; Offset, LockSize: Int64): Integer; overload;
{$ENDIF}
function FileUnlock(Handle: Integer; Offset, LockSize: Longint): Integer;
{$IFDEF RX_D4} overload; {$ENDIF}
{$IFDEF RX_D4}
function FileUnlock(Handle: Integer; Offset, LockSize: Int64): Integer; overload;
{$ENDIF}
function GetTempDir: string;
function GetWindowsDir: string;
function GetSystemDir: string;
function BrowseDirectory(var AFolderName: string; const DlgText: string;
AHelpContext: THelpContext): Boolean;
{$IFDEF WIN32}
function BrowseComputer(var ComputerName: string; const DlgText: string;
AHelpContext: THelpContext): Boolean;
function ShortToLongFileName(const ShortName: string): string;
function ShortToLongPath(const ShortName: string): string;
function LongToShortFileName(const LongName: string): string;
function LongToShortPath(const LongName: string): string;
procedure CreateFileLink(const FileName, DisplayName: string; Folder: Integer);
procedure DeleteFileLink(const DisplayName: string; Folder: Integer);
{$ENDIF WIN32}
{$IFNDEF RX_D3}
function IsPathDelimiter(const S: string; Index: Integer): Boolean;
{$ENDIF}
implementation
uses {$IFDEF WIN32} {$IFDEF RX_D3} ActiveX, ComObj, ShlObj, {$ELSE} Ole2,
OleAuto, {$ENDIF} {$ENDIF} DateUtil, ShellAPI, FileCtrl, Forms, VCLUtils,
RxPrgrss;
{$IFDEF WIN32}
{$IFNDEF RX_D3}
type
{ TSHItemID -- Item ID }
PSHItemID = ^TSHItemID;
TSHItemID = packed record { mkid }
cb: Word; { Size of the ID (including cb itself) }
abID: array[0..0] of Byte; { The item ID (variable length) }
end;
{ TItemIDList -- List if item IDs (combined with 0-terminator) }
PItemIDList = ^TItemIDList;
TItemIDList = packed record { idl }
mkid: TSHItemID;
end;
TFNBFFCallBack = function(Wnd: HWND; uMsg: UINT; lParam, lpData: LPARAM): Integer stdcall;
PBrowseInfo = ^TBrowseInfo;
TBrowseInfo = packed record
hwndOwner: HWND;
pidlRoot: PItemIDList;
pszDisplayName: LPSTR; { Return display name of item selected. }
lpszTitle: LPCSTR; { text to go in the banner over the tree. }
ulFlags: UINT; { Flags that control the return stuff }
lpfn: TFNBFFCallBack;
lParam: LPARAM; { extra info that's passed back in callbacks }
iImage: Integer; { output var: where to return the Image index. }
end;
const
{ Browsing for directory }
BIF_RETURNONLYFSDIRS = $0001; { For finding a folder to start document searching }
BIF_DONTGOBELOWDOMAIN = $0002; { For starting the Find Computer }
BIF_STATUSTEXT = $0004;
BIF_RETURNFSANCESTORS = $0008;
BIF_BROWSEFORCOMPUTER = $1000; { Browsing for Computers }
BIF_BROWSEFORPRINTER = $2000; { Browsing for Printers }
BIF_BROWSEINCLUDEFILES = $4000; { Browsing for Everything }
{ message from browser }
BFFM_INITIALIZED = 1;
BFFM_SELCHANGED = 2;
{ messages to browser }
BFFM_SETSTATUSTEXT = (WM_USER + 100);
BFFM_ENABLEOK = (WM_USER + 101);
BFFM_SETSELECTION = (WM_USER + 102);
const
CSIDL_DRIVES = $0011;
CSIDL_NETWORK = $0012;
function SHBrowseForFolder(var lpbi: TBrowseInfo): PItemIDList; stdcall;
far; external Shell32 name 'SHBrowseForFolder';
function SHGetPathFromIDList(pidl: PItemIDList; pszPath: LPSTR): BOOL; stdcall;
far; external Shell32 name 'SHGetPathFromIDList';
function SHGetSpecialFolderLocation(hwndOwner: HWND; nFolder: Integer;
var ppidl: PItemIDList): HResult; stdcall; far; external Shell32
name 'SHGetSpecialFolderLocation';
{$ENDIF RX_D3}
{ TBrowseFolderDlg }
type
TBrowseKind = (bfFolders, bfComputers);
TDialogPosition = (dpDefault, dpScreenCenter);
TBrowseFolderDlg = class(TComponent)
private
FDefWndProc: Pointer;
FHelpContext: THelpContext;
FHandle: HWnd;
FObjectInstance: Pointer;
FDesktopRoot: Boolean;
FBrowseKind: TBrowseKind;
FPosition: TDialogPosition;
FText: string;
FDisplayName: string;
FSelectedName: string;
FFolderName: string;
FImageIndex: Integer;
FOnInitialized: TNotifyEvent;
FOnSelChanged: TNotifyEvent;
procedure SetSelPath(const Path: string);
procedure SetOkEnable(Value: Boolean);
procedure DoInitialized;
procedure DoSelChanged(Param: PItemIDList);
procedure WMNCDestroy(var Message: TWMNCDestroy); message WM_NCDESTROY;
procedure WMCommand(var Message: TMessage); message WM_COMMAND;
protected
procedure DefaultHandler(var Message); override;
procedure WndProc(var Message: TMessage); virtual;
function TaskModalDialog(var Info: TBrowseInfo): PItemIDList;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function Execute: Boolean;
property Handle: HWnd read FHandle;
property DisplayName: string read FDisplayName;
property SelectedName: string read FSelectedName write FSelectedName;
property ImageIndex: Integer read FImageIndex;
published
property BrowseKind: TBrowseKind read FBrowseKind write FBrowseKind default bfFolders;
property DesktopRoot: Boolean read FDesktopRoot write FDesktopRoot default True;
property DialogText: string read FText write FText;
property FolderName: string read FFolderName write FFolderName;
property HelpContext: THelpContext read FHelpContext write FHelpContext default 0;
property Position: TDialogPosition read FPosition write FPosition default dpScreenCenter;
property OnInitialized: TNotifyEvent read FOnInitialized write FOnInitialized;
property OnSelChanged: TNotifyEvent read FOnSelChanged write FOnSelChanged;
end;
function ExplorerHook(Wnd: HWnd; Msg: UINT; LParam: LPARAM; Data: LPARAM): Integer; stdcall;
begin
Result := 0;
if Msg = BFFM_INITIALIZED then begin
if TBrowseFolderDlg(Data).Position = dpScreenCenter then
CenterWindow(Wnd);
TBrowseFolderDlg(Data).FHandle := Wnd;
TBrowseFolderDlg(Data).FDefWndProc := Pointer(SetWindowLong(Wnd, GWL_WNDPROC,
Longint(TBrowseFolderDlg(Data).FObjectInstance)));
TBrowseFolderDlg(Data).DoInitialized;
end
else if Msg = BFFM_SELCHANGED then begin
TBrowseFolderDlg(Data).FHandle := Wnd;
TBrowseFolderDlg(Data).DoSelChanged(PItemIDList(LParam));
end;
end;
const
HelpButtonId = $FFFF;
constructor TBrowseFolderDlg.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FObjectInstance := MakeObjectInstance(WndProc);
FDesktopRoot := True;
FBrowseKind := bfFolders;
FPosition := dpScreenCenter;
SetLength(FDisplayName, MAX_PATH);
end;
destructor TBrowseFolderDlg.Destroy;
begin
if FObjectInstance <> nil then FreeObjectInstance(FObjectInstance);
inherited Destroy;
end;
procedure TBrowseFolderDlg.DoInitialized;
const
SBtn = 'BUTTON';
var
BtnHandle, HelpBtn, BtnFont: THandle;
BtnSize: TRect;
begin
if (FBrowseKind = bfComputers) or DirExists(FFolderName) then
SetSelPath(FFolderName);
if FHelpContext <> 0 then begin
BtnHandle := FindWindowEx(FHandle, 0, SBtn, nil);
if (BtnHandle <> 0) then begin
GetWindowRect(BtnHandle, BtnSize);
ScreenToClient(FHandle, BtnSize.TopLeft);
ScreenToClient(FHandle, BtnSize.BottomRight);
BtnFont := SendMessage(FHandle, WM_GETFONT, 0, 0);
HelpBtn := CreateWindow(SBtn, PChar(ResStr(SHelpButton)),
WS_CHILD or WS_CLIPSIBLINGS or WS_VISIBLE or BS_PUSHBUTTON or WS_TABSTOP,
12, BtnSize.Top, BtnSize.Right - BtnSize.Left, BtnSize.Bottom - BtnSize.Top,
FHandle, HelpButtonId, HInstance, nil);
if BtnFont <> 0 then
SendMessage(HelpBtn, WM_SETFONT, BtnFont, MakeLParam(1, 0));
UpdateWindow(FHandle);
end;
end;
if Assigned(FOnInitialized) then FOnInitialized(Self);
end;
procedure TBrowseFolderDlg.DoSelChanged(Param: PItemIDList);
var
Temp: array[0..MAX_PATH] of Char;
begin
if (FBrowseKind = bfComputers) then begin
FSelectedName := DisplayName;
end
else begin
if SHGetPathFromIDList(Param, Temp) then begin
FSelectedName := StrPas(Temp);
SetOkEnable(DirExists(FSelectedName));
end
else begin
FSelectedName := '';
SetOkEnable(False);
end;
end;
if Assigned(FOnSelChanged) then FOnSelChanged(Self);
end;
procedure TBrowseFolderDlg.SetSelPath(const Path: string);
begin
if FHandle <> 0 then
SendMessage(FHandle, BFFM_SETSELECTION, 1, Longint(PChar(Path)));
end;
procedure TBrowseFolderDlg.SetOkEnable(Value: Boolean);
begin
if FHandle <> 0 then SendMessage(FHandle, BFFM_ENABLEOK, 0, Ord(Value));
end;
procedure TBrowseFolderDlg.DefaultHandler(var Message);
begin
if FHandle <> 0 then
with TMessage(Message) do
Result := CallWindowProc(FDefWndProc, FHandle, Msg, WParam, LParam)
else inherited DefaultHandler(Message);
end;
procedure TBrowseFolderDlg.WndProc(var Message: TMessage);
begin
Dispatch(Message);
end;
procedure TBrowseFolderDlg.WMCommand(var Message: TMessage);
begin
if (Message.wParam = HelpButtonId) and (LongRec(Message.lParam).Hi =
BN_CLICKED) and (FHelpContext <> 0) then
begin
Application.HelpContext(FHelpContext);
end
else inherited;
end;
procedure TBrowseFolderDlg.WMNCDestroy(var Message: TWMNCDestroy);
begin
inherited;
FHandle := 0;
end;
function TBrowseFolderDlg.Execute: Boolean;
var
BrowseInfo: TBrowseInfo;
ItemIDList: PItemIDList;
Temp: array[0..MAX_PATH] of Char;
begin
if FDesktopRoot and (FBrowseKind = bfFolders) then
BrowseInfo.pidlRoot := nil
else begin
if FBrowseKind = bfComputers then { root - Network }
OleCheck(SHGetSpecialFolderLocation(0, CSIDL_NETWORK,
BrowseInfo.pidlRoot))
else { root - MyComputer }
OleCheck(SHGetSpecialFolderLocation(0, CSIDL_DRIVES,
BrowseInfo.pidlRoot));
end;
try
SetLength(FDisplayName, MAX_PATH);
with BrowseInfo do begin
pszDisplayName := PChar(DisplayName);
if DialogText <> '' then lpszTitle := PChar(DialogText)
else lpszTitle := nil;
if FBrowseKind = bfComputers then
ulFlags := BIF_BROWSEFORCOMPUTER
else
ulFlags := BIF_RETURNONLYFSDIRS or BIF_RETURNFSANCESTORS;
lpfn := ExplorerHook;
lParam := Longint(Self);
hWndOwner := Application.Handle;
iImage := 0;
end;
ItemIDList := TaskModalDialog(BrowseInfo);
Result := ItemIDList <> nil;
if Result then
try
if FBrowseKind = bfFolders then begin
Win32Check(SHGetPathFromIDList(ItemIDList, Temp));
FFolderName := RemoveBackSlash(StrPas(Temp));
end
else begin
FFolderName := DisplayName;
end;
FSelectedName := FFolderName;
FImageIndex := BrowseInfo.iImage;
finally
CoTaskMemFree(ItemIDList);
end;
finally
if BrowseInfo.pidlRoot <> nil then CoTaskMemFree(BrowseInfo.pidlRoot);
end;
end;
function TBrowseFolderDlg.TaskModalDialog(var Info: TBrowseInfo): PItemIDList;
var
ActiveWindow: HWnd;
WindowList: Pointer;
begin
ActiveWindow := GetActiveWindow;
WindowList := DisableTaskWindows(0);
try
try
Result := SHBrowseForFolder(Info);
finally
FHandle := 0;
FDefWndProc := nil;
end;
finally
EnableTaskWindows(WindowList);
SetActiveWindow(ActiveWindow);
end;
end;
function BrowseDirectory(var AFolderName: string; const DlgText: string;
AHelpContext: THelpContext): Boolean;
begin
if NewStyleControls then begin
with TBrowseFolderDlg.Create(Application) do
try
DialogText := DlgText;
FolderName := AFolderName;
HelpContext := AHelpContext;
Result := Execute;
if Result then AFolderName := FolderName;
finally
Free;
end;
end
else Result := SelectDirectory(AFolderName, [], AHelpContext);
end;
function BrowseComputer(var ComputerName: string; const DlgText: string;
AHelpContext: THelpContext): Boolean;
begin
with TBrowseFolderDlg.Create(Application) do
try
BrowseKind := bfComputers;
DialogText := DlgText;
FolderName := ComputerName;
HelpContext := AHelpContext;
Result := Execute;
if Result then ComputerName := FolderName;
finally
Free;
end;
end;
{ TRxFileOperator }
type
TFileOperation = (foCopy, foDelete, foMove, foRename);
TFileOperFlag = (flAllowUndo, flConfirmMouse, flFilesOnly, flMultiDest,
flNoConfirmation, flNoConfirmMkDir, flRenameOnCollision, flSilent,
flSimpleProgress, flNoErrorUI);
TFileOperFlags = set of TFileOperFlag;
TRxFileOperator = class(TComponent)
private
FAborted: Boolean;
FOperation: TFileOperation;
FOptions: TFileOperFlags;
FProgressTitle: string;
FSource: string;
FDestination: string;
function TaskModalDialog(DialogFunc: Pointer; var DialogData): Boolean;
public
constructor Create(AOwner: TComponent); override;
function Execute: Boolean; virtual;
property Aborted: Boolean read FAborted;
published
property Destination: string read FDestination write FDestination;
property Operation: TFileOperation read FOperation write FOperation
default foCopy;
property Options: TFileOperFlags read FOptions write FOptions
default [flAllowUndo, flNoConfirmMkDir];
property ProgressTitle: string read FProgressTitle write FProgressTitle;
property Source: string read FSource write FSource;
end;
{$IFNDEF RX_D3}
const
FOF_NOERRORUI = $0400;
{$ENDIF}
constructor TRxFileOperator.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FOptions := [flAllowUndo, flNoConfirmMkDir];
end;
function TRxFileOperator.TaskModalDialog(DialogFunc: Pointer; var DialogData): Boolean;
type
TDialogFunc = function(var DialogData): Integer stdcall;
var
ActiveWindow: HWnd;
WindowList: Pointer;
begin
ActiveWindow := GetActiveWindow;
WindowList := DisableTaskWindows(0);
try
Result := TDialogFunc(DialogFunc)(DialogData) = 0;
finally
EnableTaskWindows(WindowList);
SetActiveWindow(ActiveWindow);
end;
end;
function TRxFileOperator.Execute: Boolean;
const
OperTypes: array[TFileOperation] of UINT = (
FO_COPY, FO_DELETE, FO_MOVE, FO_RENAME);
OperOptions: array[TFileOperFlag] of FILEOP_FLAGS = (
FOF_ALLOWUNDO, FOF_CONFIRMMOUSE, FOF_FILESONLY, FOF_MULTIDESTFILES,
FOF_NOCONFIRMATION, FOF_NOCONFIRMMKDIR, FOF_RENAMEONCOLLISION,
FOF_SILENT, FOF_SIMPLEPROGRESS, FOF_NOERRORUI);
var
OpStruct: TSHFileOpStruct;
Flag: TFileOperFlag;
function AllocFileStr(const S: string): PChar;
var
P: PChar;
begin
Result := nil;
if S <> '' then begin
Result := StrCopy(StrAlloc(Length(S) + 2), PChar(S));
P := Result;
while P^ <> #0 do begin
if (P^ = ';') or (P^ = '|') then P^ := #0;
Inc(P);
end;
Inc(P);
P^ := #0;
end;
end;
begin
FAborted := False;
FillChar(OpStruct, SizeOf(OpStruct), 0);
with OpStruct do
try
if (Application.MainForm <> nil) and
Application.MainForm.HandleAllocated then
Wnd := Application.MainForm.Handle
else Wnd := Application.Handle;
wFunc := OperTypes[Operation];
pFrom := AllocFileStr(FSource);
pTo := AllocFileStr(FDestination);
fFlags := 0;
for Flag := Low(Flag) to High(Flag) do
if Flag in FOptions then fFlags := fFlags or OperOptions[Flag];
lpszProgressTitle := PChar(FProgressTitle);
Result := TaskModalDialog(@SHFileOperation, OpStruct);
FAborted := fAnyOperationsAborted;
finally
if pFrom <> nil then StrDispose(pFrom);
if pTo <> nil then StrDispose(pTo);
end;
end;
{$ELSE}
function BrowseDirectory(var AFolderName: string; const DlgText: string;
AHelpContext: THelpContext): Boolean;
begin
Result := SelectDirectory(AFolderName, [], AHelpContext);
end;
{$ENDIF WIN32}
function NormalDir(const DirName: string): string;
begin
Result := DirName;
if (Result <> '') and
{$IFDEF RX_D3}
not (AnsiLastChar(Result)^ in [':', '\']) then
{$ELSE}
not (Result[Length(Result)] in [':', '\']) then
{$ENDIF}
begin
if (Length(Result) = 1) and (UpCase(Result[1]) in ['A'..'Z']) then
Result := Result + ':\'
else Result := Result + '\';
end;
end;
function RemoveBackSlash(const DirName: string): string;
begin
Result := DirName;
if (Length(Result) > 1) and
{$IFDEF RX_D3}
(AnsiLastChar(Result)^ = '\') then
{$ELSE}
(Result[Length(Result)] = '\') then
{$ENDIF}
begin
if not ((Length(Result) = 3) and (UpCase(Result[1]) in ['A'..'Z']) and
(Result[2] = ':')) then
Delete(Result, Length(Result), 1);
end;
end;
function DirExists(Name: string): Boolean;
{$IFDEF WIN32}
var
Code: Integer;
begin
Code := GetFileAttributes(PChar(Name));
Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
end;
{$ELSE}
var
SR: TSearchRec;
begin
if Name[Length(Name)] = '\' then Dec(Name[0]);
if (Length(Name) = 2) and (Name[2] = ':') then
Name := Name + '\*.*';
Result := FindFirst(Name, faDirectory, SR) = 0;
Result := Result and (SR.Attr and faDirectory <> 0);
end;
{$ENDIF}
procedure ForceDirectories(Dir: string);
begin
if Length(Dir) = 0 then Exit;
{$IFDEF RX_D3}
if (AnsiLastChar(Dir) <> nil) and (AnsiLastChar(Dir)^ = '\') then
{$ELSE}
if Dir[Length(Dir)] = '\' then
{$ENDIF}
Delete(Dir, Length(Dir), 1);
if (Length(Dir) < 3) or DirectoryExists(Dir) or
(ExtractFilePath(Dir) = Dir) then Exit;
ForceDirectories(ExtractFilePath(Dir));
{$IFDEF WIN32}
CreateDir(Dir);
{$ELSE}
MkDir(Dir);
{$ENDIF}
end;
{$IFDEF WIN32}
procedure CopyMoveFileShell(const FileName, DestName: string; Confirmation,
AllowUndo, MoveFile: Boolean);
begin
with TRxFileOperator.Create(nil) do
try
Source := FileName;
Destination := DestName;
if MoveFile then begin
if AnsiCompareText(ExtractFilePath(FileName),
ExtractFilePath(DestName)) = 0 then
Operation := foRename
else Operation := foMove;
end
else Operation := foCopy;
if not AllowUndo then
Options := Options - [flAllowUndo];
if not Confirmation then
Options := Options + [flNoConfirmation];
if not Execute or Aborted then SysUtils.Abort;
finally
Free;
end;
end;
{$ENDIF}
procedure CopyFile(const FileName, DestName: string;
ProgressControl: TControl);
begin
CopyFileEx(FileName, DestName, False, False, ProgressControl);
end;
procedure CopyFileEx(const FileName, DestName: string;
OverwriteReadOnly, ShellDialog: Boolean; ProgressControl: TControl);
var
CopyBuffer: Pointer;
Source, Dest: Integer;
Destination: TFileName;
FSize, BytesCopied, TotalCopied: Longint;
Attr: Integer;
const
ChunkSize: Longint = 8192;
begin
{$IFDEF WIN32}
if NewStyleControls and ShellDialog then begin
CopyMoveFileShell(FileName, DestName, not OverwriteReadOnly,
False, False);
Exit;
end;
{$ENDIF}
Destination := DestName;
if HasAttr(Destination, faDirectory) then
Destination := NormalDir(Destination) + ExtractFileName(FileName);
GetMem(CopyBuffer, ChunkSize);
try
TotalCopied := 0;
FSize := GetFileSize(FileName);
Source := FileOpen(FileName, fmShareDenyWrite);
if Source < 0 then
raise EFOpenError.CreateFmt(ResStr(SFOpenError), [FileName]);
try
if ProgressControl <> nil then begin
SetProgressMax(ProgressControl, FSize);
SetProgressMin(ProgressControl, 0);
SetProgressValue(ProgressControl, 0);
end;
ForceDirectories(ExtractFilePath(Destination));
if OverwriteReadOnly then begin
Attr := FileGetAttr(Destination);
if (Attr >= 0) and ((Attr and faReadOnly) <> 0) then
FileSetAttr(Destination, Attr and not faReadOnly);
end;
Dest := FileCreate(Destination);
if Dest < 0 then
raise EFCreateError.CreateFmt(ResStr(SFCreateError), [Destination]);
try
repeat
BytesCopied := FileRead(Source, CopyBuffer^, ChunkSize);
if BytesCopied = -1 then
raise EReadError.Create(ResStr(SReadError));
TotalCopied := TotalCopied + BytesCopied;
if BytesCopied > 0 then begin
if FileWrite(Dest, CopyBuffer^, BytesCopied) = -1 then
raise EWriteError.Create(ResStr(SWriteError));
end;
if ProgressControl <> nil then
SetProgressValue(ProgressControl, TotalCopied);
until BytesCopied < ChunkSize;
FileSetDate(Dest, FileGetDate(Source));
finally
FileClose(Dest);
end;
finally
FileClose(Source);
end;
finally
FreeMem(CopyBuffer, ChunkSize);
if ProgressControl <> nil then
SetProgressValue(ProgressControl, 0);
end;
end;
procedure MoveFile(const FileName, DestName: TFileName);
var
Destination: TFileName;
Attr: Integer;
begin
Destination := ExpandFileName(DestName);
if not RenameFile(FileName, Destination) then begin
Attr := FileGetAttr(FileName);
if Attr < 0 then Exit;
if (Attr and faReadOnly) <> 0 then
FileSetAttr(FileName, Attr and not faReadOnly);
CopyFile(FileName, Destination, nil);
DeleteFile(FileName);
end;
end;
procedure MoveFileEx(const FileName, DestName: TFileName;
ShellDialog: Boolean);
begin
{$IFDEF WIN32}
if NewStyleControls and ShellDialog then
CopyMoveFileShell(FileName, DestName, False, False, True)
else
{$ENDIF}
MoveFile(FileName, DestName);
end;
{$IFDEF RX_D4}
function GetFileSize(const FileName: string): Int64;
var
Handle: THandle;
FindData: TWin32FindData;
begin
Handle := FindFirstFile(PChar(FileName), FindData);
if Handle <> INVALID_HANDLE_VALUE then begin
Windows.FindClose(Handle);
if (FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
begin
Int64Rec(Result).Lo := FindData.nFileSizeLow;
Int64Rec(Result).Hi := FindData.nFileSizeHigh;
Exit;
end;
end;
Result := -1;
end;
{$ELSE}
function GetFileSize(const FileName: string): Longint;
var
SearchRec: TSearchRec;
begin
if FindFirst(ExpandFileName(FileName), faAnyFile, SearchRec) = 0 then
Result := SearchRec.Size
else Result := -1;
FindClose(SearchRec);
end;
{$ENDIF RX_D4}
function FileDateTime(const FileName: string): System.TDateTime;
var
Age: Longint;
begin
Age := FileAge(FileName);
if Age = -1 then
Result := NullDate
else
Result := FileDateToDateTime(Age);
end;
function HasAttr(const FileName: string; Attr: Integer): Boolean;
var
FileAttr: Integer;
begin
FileAttr := FileGetAttr(FileName);
Result := (FileAttr >= 0) and (FileAttr and Attr = Attr);
end;
function DeleteFiles(const FileMask: string): Boolean;
var
SearchRec: TSearchRec;
begin
Result := FindFirst(ExpandFileName(FileMask), faAnyFile, SearchRec) = 0;
try
if Result then
repeat
// if (SearchRec.Name[1] <> '.') and
// !!! BUG !!!
if (SearchRec.Name <> '.') and
(SearchRec.Attr and faVolumeID <> faVolumeID) and
(SearchRec.Attr and faDirectory <> faDirectory) then
begin
Result := DeleteFile(ExtractFilePath(FileMask) + SearchRec.Name);
if not Result then Break;
end;
until FindNext(SearchRec) <> 0;
finally
FindClose(SearchRec);
end;
end;
function DeleteFilesEx(const FileMasks: array of string): Boolean;
var
I: Integer;
begin
Result := True;
for I := Low(FileMasks) to High(FileMasks) do
Result := Result and DeleteFiles(FileMasks[I]);
end;
function ClearDir(const Path: string; Delete: Boolean): Boolean;
const
{$IFDEF WIN32}
FileNotFound = 18;
{$ELSE}
FileNotFound = -18;
{$ENDIF}
var
FileInfo: TSearchRec;
DosCode: Integer;
begin
Result := DirExists(Path);
if not Result then Exit;
DosCode := FindFirst(NormalDir(Path) + '*.*', faAnyFile, FileInfo);
try
while DosCode = 0 do begin
// if (FileInfo.Name[1] <> '.') and (FileInfo.Attr <> faVolumeID) then
// !!! BUG !!!
if (FileInfo.Name <> '.') and (FileInfo.Name <> '..') and (FileInfo.Attr <> faVolumeID) then
begin
if (FileInfo.Attr and faDirectory = faDirectory) then
Result := ClearDir(NormalDir(Path) + FileInfo.Name, Delete) and Result
else if (FileInfo.Attr and faVolumeID <> faVolumeID) then begin
if (FileInfo.Attr and faReadOnly = faReadOnly) then
FileSetAttr(NormalDir(Path) + FileInfo.Name, faArchive);
Result := DeleteFile(NormalDir(Path) + FileInfo.Name) and Result;
end;
end;
DosCode := FindNext(FileInfo);
end;
finally
FindClose(FileInfo);
end;
if Delete and Result and (DosCode = FileNotFound) and
not ((Length(Path) = 2) and (Path[2] = ':')) then
begin
RmDir(Path);
Result := (IOResult = 0) and Result;
end;
end;
function GetTempDir: string;
{$IFDEF WIN32}
var
Buffer: array[0..1023] of Char;
begin
SetString(Result, Buffer, GetTempPath(SizeOf(Buffer), Buffer));
{$ELSE}
var
Buffer: array[0..255] of Char;
begin
GetTempFileName(GetTempDrive(#0), '$', 1, Buffer);
Result := ExtractFilePath(StrPas(Buffer));
{$ENDIF}
end;
function GetWindowsDir: string;
{$IFDEF WIN32}
var
Buffer: array[0..1023] of Char;
begin
SetString(Result, Buffer, GetWindowsDirectory(Buffer, SizeOf(Buffer)));
{$ELSE}
begin
Result[0] := Char(GetWindowsDirectory(@Result[1], 254));
{$ENDIF}
end;
function GetSystemDir: string;
{$IFDEF WIN32}
var
Buffer: array[0..1023] of Char;
begin
SetString(Result, Buffer, GetSystemDirectory(Buffer, SizeOf(Buffer)));
{$ELSE}
begin
Result[0] := Char(GetSystemDirectory(@Result[1], 254));
{$ENDIF}
end;
{$IFDEF WIN32}
function ValidFileName(const FileName: string): Boolean;
function HasAny(const Str, Substr: string): Boolean;
var
I: Integer;
begin
Result := False;
for I := 1 to Length(Substr) do begin
if Pos(Substr[I], Str) > 0 then begin
Result := True;
Break;
end;
end;
end;
begin
Result := (FileName <> '') and (not HasAny(FileName, '<>"[]|'));
if Result then Result := Pos('\', ExtractFileName(FileName)) = 0;
end;
function FileLock(Handle: Integer; Offset, LockSize: Longint): Integer;
begin
if LockFile(Handle, Offset, 0, LockSize, 0) then
Result := 0
else
Result := GetLastError;
end;
function FileUnlock(Handle: Integer; Offset, LockSize: Longint): Integer;
begin
if UnlockFile(Handle, Offset, 0, LockSize, 0) then
Result := 0
else
Result := GetLastError;
end;
{$IFDEF RX_D4}
function FileLock(Handle: Integer; Offset, LockSize: Int64): Integer;
begin
if LockFile(Handle, Int64Rec(Offset).Lo, Int64Rec(Offset).Hi,
Int64Rec(LockSize).Lo, Int64Rec(LockSize).Hi) then Result := 0
else
Result := GetLastError;
end;
function FileUnlock(Handle: Integer; Offset, LockSize: Int64): Integer;
begin
if UnlockFile(Handle, Int64Rec(Offset).Lo, Int64Rec(Offset).Hi,
Int64Rec(LockSize).Lo, Int64Rec(LockSize).Hi) then Result := 0
else
Result := GetLastError;
end;
{$ENDIF RX_D4}
{$ELSE}
function ValidFileName(const FileName: string): Boolean;
const
MaxNameLen = 12; { file name and extension }
MaxExtLen = 4; { extension with point }
MaxPathLen = 79; { full file path in DOS }
var
Dir, Name, Ext: TFileName;
function HasAny(Str, SubStr: string): Boolean; near; assembler;
asm
PUSH DS
CLD
LDS SI,Str
LES DI,SubStr
INC DI
MOV DX,DI
XOR AH,AH
LODSB
MOV BX,AX
OR BX,BX
JZ @@2
MOV AL,ES:[DI-1]
XCHG AX,CX
@@1: PUSH CX
MOV DI,DX
LODSB
REPNE SCASB
POP CX
JE @@3
DEC BX
JNZ @@1
@@2: XOR AL,AL
JMP @@4
@@3: MOV AL,1
@@4: POP DS
end;
begin
Result := True;
Dir := Copy(ExtractFilePath(FileName), 1, MaxPathLen);
Name := Copy(ExtractFileName(FileName), 1, MaxNameLen);
Ext := Copy(ExtractFileExt(FileName), 1, MaxExtLen);
if (Dir + Name <> FileName) or HasAny(Name, ';,=+<>|"[] \') or
HasAny(Copy(Ext, 2, 255), ';,=+<>|"[] \.') then Result := False;
end;
function LockFile(Handle: Integer; StartPos, Length: Longint;
Unlock: Boolean): Integer; assembler;
asm
PUSH DS
MOV AH,5CH
MOV AL,Unlock
MOV BX,Handle
MOV DX,StartPos.Word[0]
MOV CX,StartPos.Word[2]
MOV DI,Length.Word[0]
MOV SI,Length.Word[2]
INT 21H
JNC @@1
NEG AX
JMP @@2
@@1: MOV AX,0
@@2: POP DS
end;
function FileLock(Handle: Integer; Offset, LockSize: Longint): Integer;
begin
Result := LockFile(Handle, Offset, LockSize, False);
end;
function FileUnlock(Handle: Integer; Offset, LockSize: Longint): Integer;
begin
Result := LockFile(Handle, Offset, LockSize, True);
end;
{$ENDIF WIN32}
{$IFDEF WIN32}
function ShortToLongFileName(const ShortName: string): string;
var
Temp: TWin32FindData;
SearchHandle: THandle;
begin
SearchHandle := FindFirstFile(PChar(ShortName), Temp);
if SearchHandle <> INVALID_HANDLE_VALUE then begin
Result := string(Temp.cFileName);
if Result = '' then Result := string(Temp.cAlternateFileName);
end
else Result := '';
Windows.FindClose(SearchHandle);
end;
function LongToShortFileName(const LongName: string): string;
var
Temp: TWin32FindData;
SearchHandle: THandle;
begin
SearchHandle := FindFirstFile(PChar(LongName), Temp);
if SearchHandle <> INVALID_HANDLE_VALUE then begin
Result := string(Temp.cAlternateFileName);
if Result = '' then Result := string(Temp.cFileName);
end
else Result := '';
Windows.FindClose(SearchHandle);
end;
function ShortToLongPath(const ShortName: string): string;
var
LastSlash: PChar;
TempPathPtr: PChar;
begin
Result := '';
TempPathPtr := PChar(ShortName);
LastSlash := StrRScan(TempPathPtr, '\');
while LastSlash <> nil do begin
Result := '\' + ShortToLongFileName(TempPathPtr) + Result;
if LastSlash <> nil then begin
LastSlash^ := char(0);
LastSlash := StrRScan(TempPathPtr, '\');
end;
end;
Result := TempPathPtr + Result;
end;
function LongToShortPath(const LongName: string): string;
var
LastSlash: PChar;
TempPathPtr: PChar;
begin
Result := '';
TempPathPtr := PChar(LongName);
LastSlash := StrRScan(TempPathPtr, '\');
while LastSlash <> nil do begin
Result := '\' + LongToShortFileName(TempPathPtr) + Result;
if LastSlash <> nil then begin
LastSlash^ := char(0);
LastSlash := StrRScan(TempPathPtr, '\');
end;
end;
Result := TempPathPtr + Result;
end;
const
IID_IPersistFile: TGUID = (
D1:$0000010B;D2:$0000;D3:$0000;D4:($C0,$00,$00,$00,$00,$00,$00,$46));
{$IFNDEF RX_D3}
const
IID_IShellLinkA: TGUID = (
D1:$000214EE; D2:$0000; D3:$0000; D4:($C0,$00,$00,$00,$00,$00,$00,$46));
CLSID_ShellLink: TGUID = (
D1:$00021401; D2:$0000; D3:$0000; D4:($C0,$00,$00,$00,$00,$00,$00,$46));
type
IShellLink = class(IUnknown) { sl }
function GetPath(pszFile: LPSTR; cchMaxPath: Integer;
var pfd: TWin32FindData; fFlags: DWORD): HResult; virtual; stdcall; abstract;
function GetIDList(var ppidl: PItemIDList): HResult; virtual; stdcall; abstract;
function SetIDList(pidl: PItemIDList): HResult; virtual; stdcall; abstract;
function GetDescription(pszName: LPSTR; cchMaxName: Integer): HResult; virtual; stdcall; abstract;
function SetDescription(pszName: LPSTR): HResult; virtual; stdcall; abstract;
function GetWorkingDirectory(pszDir: LPSTR; cchMaxPath: Integer): HResult; virtual; stdcall; abstract;
function SetWorkingDirectory(pszDir: LPSTR): HResult; virtual; stdcall; abstract;
function GetArguments(pszArgs: LPSTR; cchMaxPath: Integer): HResult; virtual; stdcall; abstract;
function SetArguments(pszArgs: LPSTR): HResult; virtual; stdcall; abstract;
function GetHotkey(var pwHotkey: Word): HResult; virtual; stdcall; abstract;
function SetHotkey(wHotkey: Word): HResult; virtual; stdcall; abstract;
function GetShowCmd(var piShowCmd: Integer): HResult; virtual; stdcall; abstract;
function SetShowCmd(iShowCmd: Integer): HResult; virtual; stdcall; abstract;
function GetIconLocation(pszIconPath: LPSTR; cchIconPath: Integer;
var piIcon: Integer): HResult; virtual; stdcall; abstract;
function SetIconLocation(pszIconPath: LPSTR; iIcon: Integer): HResult; virtual; stdcall; abstract;
function SetRelativePath(pszPathRel: LPSTR; dwReserved: DWORD): HResult; virtual; stdcall; abstract;
function Resolve(Wnd: HWND; fFlags: DWORD): HResult; virtual; stdcall; abstract;
function SetPath(pszFile: LPSTR): HResult; virtual; stdcall; abstract;
end;
{$ENDIF}
const
LinkExt = '.lnk';
procedure CreateFileLink(const FileName, DisplayName: string; Folder: Integer);
var
ShellLink: IShellLink;
PersistFile: IPersistFile;
ItemIDList: PItemIDList;
FileDestPath: array[0..MAX_PATH] of Char;
FileNameW: array[0..MAX_PATH] of WideChar;
begin
CoInitialize(nil);
try
OleCheck(CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_SERVER,
IID_IShellLinkA, ShellLink));
try
OleCheck(ShellLink.QueryInterface(IID_IPersistFile, PersistFile));
try
OleCheck(SHGetSpecialFolderLocation(0, Folder, ItemIDList));
SHGetPathFromIDList(ItemIDList, FileDestPath);
StrCat(FileDestPath, PChar('\' + DisplayName + LinkExt));
ShellLink.SetPath(PChar(FileName));
ShellLink.SetIconLocation(PChar(FileName), 0);
MultiByteToWideChar(CP_ACP, 0, FileDestPath, -1, FileNameW, MAX_PATH);
OleCheck(PersistFile.Save(FileNameW, True));
finally
{$IFDEF RX_D3}
PersistFile := nil;
{$ELSE}
PersistFile.Release;
{$ENDIF}
end;
finally
{$IFDEF RX_D3}
ShellLink := nil;
{$ELSE}
ShellLink.Release;
{$ENDIF}
end;
finally
CoUninitialize;
end;
end;
procedure DeleteFileLink(const DisplayName: string; Folder: Integer);
var
ShellLink: IShellLink;
ItemIDList: PItemIDList;
FileDestPath: array[0..MAX_PATH] of Char;
begin
CoInitialize(nil);
try
OleCheck(CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_SERVER,
IID_IShellLinkA, ShellLink));
try
OleCheck(SHGetSpecialFolderLocation(0, Folder, ItemIDList));
SHGetPathFromIDList(ItemIDList, FileDestPath);
StrCat(FileDestPath, PChar('\' + DisplayName + LinkExt));
DeleteFile(FileDestPath);
finally
{$IFDEF RX_D3}
ShellLink := nil;
{$ELSE}
ShellLink.Release;
{$ENDIF}
end;
finally
CoUninitialize;
end;
end;
{$ENDIF WIN32}
{$IFNDEF RX_D3}
function IsPathDelimiter(const S: string; Index: Integer): Boolean;
begin
Result := (Index > 0) and (Index <= Length(S)) and (S[Index] = '\');
end;
{$ENDIF}
end.