ADD: Start to implement Wfx file source

This commit is contained in:
Alexander Koblov 2009-10-06 11:11:02 +00:00
commit 8b1d509591
7 changed files with 1909 additions and 1079 deletions

View file

@ -16,7 +16,7 @@ implementation
uses
uFileSystemFileSource, uGlobs, uShellExecute, uOSUtils,
uFileSourceOperation, uFileSourceExecuteOperation, uFileSourceMoveOperation,
uWcxArchiveFileSource, uFileSourceOperationTypes, LCLProc;
uVfsFileSource, uWcxArchiveFileSource, uWfxPluginFileSource, uFileSourceOperationTypes, LCLProc;
procedure ChooseFile(aFileView: TFileView; aFile: TFile);
var
@ -55,6 +55,18 @@ begin
end;
end;
// Work only for TVfsFileSource.
if aFileView.FileSource is TVfsFileSource then
begin
// Check if it is registered plugin by file system root name.
FileSource := TWfxPluginFileSource.CreateByRootName(aFile.Name);
if Assigned(FileSource) then
begin
aFileView.AddFileSource(FileSource);
Exit;
end;
end;
if (fsoExecute in aFileView.FileSource.GetOperationsTypes) then
begin
Operation := aFileView.FileSource.CreateExecuteOperation(aFile.Name, 'open') as TFileSourceExecuteOperation;

View file

@ -0,0 +1,71 @@
unit uWfxPluginCreateDirectoryOperation;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils,
uFileSourceCreateDirectoryOperation,
uFileSource, uWfxPluginFileSource;
type
TWfxPluginCreateDirectoryOperation = class(TFileSourceCreateDirectoryOperation)
private
FWfxPluginFileSource: TWfxPluginFileSource;
public
constructor Create(var aTargetFileSource: TFileSource;
aDirectoryPath: String); override;
procedure Initialize; override;
procedure MainExecute; override;
procedure Finalize; override;
end;
implementation
uses
uFileSourceOperationUI, uWfxPluginFile, uFileProcs, uLog, uLng, uGlobs, uOSUtils, ufsplugin;
constructor TWfxPluginCreateDirectoryOperation.Create(
var aTargetFileSource: TFileSource;
aDirectoryPath: String);
begin
FWfxPluginFileSource := aTargetFileSource as TWfxPluginFileSource;
inherited Create(aTargetFileSource, aDirectoryPath);
end;
procedure TWfxPluginCreateDirectoryOperation.Initialize;
begin
end;
procedure TWfxPluginCreateDirectoryOperation.MainExecute;
begin
with FWfxPluginFileSource do
begin
case WfxMkDir(AbsolutePath) of
WFX_NOTSUPPORTED:
AskQuestion(rsMsgErrNotSupported, '', [fsourOk], fsourOk, fsourOk);
WFX_SUCCESS:
begin
// write log success
if (log_vfs_op in gLogOptions) and (log_success in gLogOptions) then
logWrite(Thread, Format(rsMsgLogSuccess+rsMsgLogMkDir, [AbsolutePath]), lmtSuccess)
end;
else
begin
// write log error
if (log_vfs_op in gLogOptions) and (log_errors in gLogOptions) then
logWrite(Thread, Format(rsMsgLogError+rsMsgLogMkDir, [AbsolutePath]), lmtError);
end;
end; // case
end; // with
end;
procedure TWfxPluginCreateDirectoryOperation.Finalize;
begin
end;
end.

View file

@ -0,0 +1,246 @@
unit uWfxPluginDeleteOperation;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils,
uFileSourceDeleteOperation,
uWfxPluginFileSource,
uFileSource,
uFileSourceOperation,
uFileSourceOperationOptions,
uFileSourceOperationUI,
uFile,
uWfxPluginFile,
uGlobs, uLog;
type
TWfxPluginDeleteOperation = class(TFileSourceDeleteOperation)
private
FWfxPluginFileSource: TWfxPluginFileSource;
FFullFilesTreeToDelete: TFiles; // source files including all files/dirs in subdirectories
FStatistics: TFileSourceDeleteOperationStatistics; // local copy of statistics
// Options.
FSymLinkOption: TFileSourceOperationOptionSymLink;
FSkipErrors: Boolean;
FDeleteReadOnly: TFileSourceOperationOptionGeneral;
protected
function ProcessFile(aFile: TWfxPluginFile): Boolean;
function ShowError(sMessage: String): TFileSourceOperationUIResponse;
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
public
constructor Create(var aTargetFileSource: TFileSource;
var theFilesToDelete: TFiles); override;
destructor Destroy; override;
procedure Initialize; override;
procedure MainExecute; override;
procedure Finalize; override;
end;
implementation
uses
LCLProc, FileUtil, uOSUtils, uLng, ufsplugin;
constructor TWfxPluginDeleteOperation.Create(var aTargetFileSource: TFileSource;
var theFilesToDelete: TFiles);
begin
FSymLinkOption := fsooslNone;
FSkipErrors := False;
FDeleteReadOnly := fsoogNone;
FFullFilesTreeToDelete := nil;
FWfxPluginFileSource:= aTargetFileSource as TWfxPluginFileSource;
inherited Create(aTargetFileSource, theFilesToDelete);
end;
destructor TWfxPluginDeleteOperation.Destroy;
begin
inherited Destroy;
end;
procedure TWfxPluginDeleteOperation.Initialize;
begin
with FWfxPluginFileSource do
WfxStatusInfo(CurrentPath, FS_STATUS_START, FS_STATUS_OP_DELETE);
// Get initialized statistics; then we change only what is needed.
FStatistics := RetrieveStatistics;
FWfxPluginFileSource.FillAndCount(FilesToDelete,
FFullFilesTreeToDelete,
FStatistics.TotalFiles,
FStatistics.TotalBytes); // gets full list of files (recursive)
end;
procedure TWfxPluginDeleteOperation.MainExecute;
var
aFile: TWfxPluginFile;
CurrentFileIndex: Integer;
begin
for CurrentFileIndex := FFullFilesTreeToDelete.Count - 1 downto 0 do
begin
aFile := FFullFilesTreeToDelete[CurrentFileIndex] as TWfxPluginFile;
FStatistics.CurrentFile := aFile.Path + aFile.Name;
UpdateStatistics(FStatistics);
ProcessFile(aFile);
with FStatistics do
begin
DoneFiles := DoneFiles + 1;
DoneBytes := DoneBytes + aFile.Size;
UpdateStatistics(FStatistics);
end;
CheckOperationState;
end;
end;
procedure TWfxPluginDeleteOperation.Finalize;
begin
with FWfxPluginFileSource do
WfxStatusInfo(CurrentPath, FS_STATUS_END, FS_STATUS_OP_DELETE);
end;
function TWfxPluginDeleteOperation.ProcessFile(aFile: TWfxPluginFile): Boolean;
var
FileName: String;
bRetry: Boolean;
sMessage, sQuestion: String;
logOptions: TLogOptions;
begin
Result := False;
FileName := aFile.Path + aFile.Name;
if FileIsReadOnly(aFile.Attributes) then
begin
case FDeleteReadOnly of
fsoogNone:
case AskQuestion(Format(rsMsgFileReadOnly, [FileName]), '',
[fsourYes, fsourAll, fsourSkip, fsourSkipAll],
fsourYes, fsourSkip) of
fsourAll:
FDeleteReadOnly := fsoogYes;
fsourSkip:
Exit;
fsourSkipAll:
begin
FDeleteReadOnly := fsoogNo;
Exit;
end;
end;
fsoogNo:
Exit;
end;
end;
repeat
bRetry := False;
//if FileIsReadOnly(aFile.Attributes) then
// mbFileSetReadOnly(FileName, False);
if aFile.IsDirectory then // directory
begin
Result := FWfxPluginFileSource.WfxRemoveDir(FileName);
end
else
begin // files and other stuff
Result := FWfxPluginFileSource.WfxDeleteFile(FileName);
end;
if Result then
begin // success
if aFile.IsDirectory then
begin
LogMessage(Format(rsMsgLogSuccess + rsMsgLogRmDir, [FileName]), [log_vfs_op], lmtSuccess);
end
else
begin
LogMessage(Format(rsMsgLogSuccess + rsMsgLogDelete, [FileName]), [log_vfs_op], lmtSuccess);
end;
end
else // error
begin
if aFile.IsDirectory then
begin
logOptions := [log_vfs_op];
sMessage := Format(rsMsgLogError + rsMsgLogRmDir, [FileName]);
sQuestion := Format(rsMsgNotDelete, [FileName]);
end
else
begin
logOptions := [log_vfs_op];
sMessage := Format(rsMsgLogError + rsMsgLogDelete, [FileName]);
sQuestion := Format(rsMsgNotDelete, [FileName]);
end;
if gSkipFileOpError or (FSkipErrors = True) then
LogMessage(sMessage, logOptions, lmtError)
else
begin
case AskQuestion(sQuestion, '',
[fsourRetry, fsourSkip, fsourSkipAll, fsourAbort],
fsourRetry, fsourSkip) of
fsourRetry:
bRetry := True;
fsourSkipAll:
FSkipErrors := True;
fsourAbort:
RaiseAbortOperation;
end;
end;
end;
until bRetry = False;
end;
function TWfxPluginDeleteOperation.ShowError(sMessage: String): TFileSourceOperationUIResponse;
begin
if gSkipFileOpError then
begin
if Assigned(Thread) then
logWrite(Thread, sMessage, lmtError, True)
else
logWrite(sMessage, lmtError, True);
Result := fsourSkip;
end
else
begin
Result := AskQuestion(sMessage, '', [fsourSkip, fsourCancel], fsourSkip, fsourCancel);
if Result = fsourCancel then
RaiseAbortOperation;
end;
end;
procedure TWfxPluginDeleteOperation.LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
begin
case logMsgType of
lmtError:
if not (log_errors in gLogOptions) then Exit;
lmtInfo:
if not (log_info in gLogOptions) then Exit;
lmtSuccess:
if not (log_success in gLogOptions) then Exit;
end;
if logOptions <= gLogOptions then
begin
logWrite(Thread, sMessage, logMsgType);
end;
end;
end.

View file

@ -0,0 +1,169 @@
unit uWfxPluginFile;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils,
uFile,
uFileProperty,
ufsplugin,
uOSUtils;
type
TWfxPluginFile = class(TFile)
private
FSize: TFileSizeProperty;
FAttributes: TFileAttributesProperty;
FModificationTime: TFileModificationDateTimeProperty;
FIsLinkToDirectory: Boolean;
procedure AssignProperties;
protected
function GetAttributes: Cardinal; virtual;
procedure SetAttributes(NewAttributes: Cardinal); virtual;
function GetSize: Int64; virtual;
procedure SetSize(NewSize: Int64); virtual;
function GetModificationTime: TDateTime; virtual;
procedure SetModificationTime(NewTime: TDateTime); virtual;
public
constructor Create; override;
constructor Create(FindData: TWin32FindData); overload;
destructor Destroy; override;
{en
Creates an identical copy of the object (as far as object data is concerned).
}
function Clone: TWfxPluginFile; override;
procedure CloneTo(AFile: TFile); override;
class function GetSupportedProperties: TFilePropertiesTypes; override;
function IsLinkToDirectory: Boolean; override;
property Size: Int64 read GetSize write SetSize;
property Attributes: Cardinal read GetAttributes write SetAttributes;
property ModificationTime: TDateTime read GetModificationTime write SetModificationTime;
end;
implementation
uses
LCLProc, FileUtil;
constructor TWfxPluginFile.Create;
begin
inherited Create;
FSize := TFileSizeProperty.Create;
FAttributes := TNtfsFileAttributesProperty.Create;
FModificationTime := TFileModificationDateTimeProperty.Create;
FIsLinkToDirectory := False;
AssignProperties;
// Set name after assigning Attributes property, because it is used to get extension.
Name := '';
end;
constructor TWfxPluginFile.Create(FindData: TWin32FindData);
begin
inherited Create;
FAttributes := TNtfsFileAttributesProperty.Create(FindData.dwFileAttributes);
FSize := TFileSizeProperty.Create((Int64(FindData.nFileSizeHigh) * MAXDWORD) + FindData.nFileSizeLow);
FModificationTime := TFileModificationDateTimeProperty.Create(FileTimeToDateTime(FindData.ftLastWriteTime));
FIsLinkToDirectory := FPS_ISLNK(FindData.dwFileAttributes);
AssignProperties;
// Set name after assigning Attributes property, because it is used to get extension.
Name := SysToUTF8(FindData.cFileName);
end;
destructor TWfxPluginFile.Destroy;
begin
if Assigned(FAttributes) then
FreeAndNil(FAttributes);
if Assigned(FSize) then
FreeAndNil(FSize);
if Assigned(FModificationTime) then
FreeAndNil(FModificationTime);
inherited Destroy;
end;
function TWfxPluginFile.Clone: TWfxPluginFile;
begin
Result := TWfxPluginFile.Create;
CloneTo(Result);
end;
procedure TWfxPluginFile.CloneTo(AFile: TFile);
begin
if Assigned(AFile) then
begin
inherited CloneTo(AFile);
// All properties are cloned in base class.
with AFile as TWfxPluginFile do
begin
FIsLinkToDirectory := Self.FIsLinkToDirectory;
end;
end;
end;
procedure TWfxPluginFile.AssignProperties;
begin
FProperties[fpSize] := FSize;
FProperties[fpAttributes] := FAttributes;
FProperties[fpModificationTime] := FModificationTime;
end;
class function TWfxPluginFile.GetSupportedProperties: TFilePropertiesTypes;
begin
Result := [{fpName, }fpSize, fpAttributes, fpModificationTime];
end;
function TWfxPluginFile.GetAttributes: Cardinal;
begin
Result := FAttributes.Value;
end;
procedure TWfxPluginFile.SetAttributes(NewAttributes: Cardinal);
begin
FAttributes.Value := NewAttributes;
end;
function TWfxPluginFile.GetSize: Int64;
begin
Result := FSize.Value;
end;
procedure TWfxPluginFile.SetSize(NewSize: Int64);
begin
FSize.Value := NewSize;
end;
function TWfxPluginFile.GetModificationTime: TDateTime;
begin
Result := FModificationTime.Value;
end;
procedure TWfxPluginFile.SetModificationTime(NewTime: TDateTime);
begin
FModificationTime.Value := NewTime;
end;
function TWfxPluginFile.IsLinkToDirectory: Boolean;
begin
Result := FIsLinkToDirectory;
end;
end.

View file

@ -0,0 +1,277 @@
unit uWfxPluginFileSource;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, uWFXModule,
uFile, uFileSourceProperty, uFileSourceOperationTypes,
uFileProperty, uFileSource, uFileSourceOperation;
const
WFX_SUCCESS = 0;
WFX_NOTSUPPORTED = -1;
WFX_ERROR = -2;
type
{ TWfxPluginFileSource }
TWfxPluginFileSource = class(TFileSource)
private
FModuleFileName: UTF8String;
FWFXModule: TWFXModule;
protected
class function GetSupportedFileProperties: TFilePropertiesTypes; override;
function GetCurrentAddress: String; override;
public
procedure FillAndCount(Files: TFiles; out NewFiles: TFiles; out FilesCount: Int64; out FilesSize: Int64);
procedure WfxStatusInfo(RemoteDir: UTF8String; InfoStartEnd, InfoOperation: Integer);
function WfxMkDir(const sDirName: UTF8String): LongInt;
function WfxRemoveDir(const sDirName: UTF8String): Boolean;
function WfxDeleteFile(const sFileName: UTF8String): Boolean;
public
constructor Create(aModuleFileName: UTF8String); reintroduce;
destructor Destroy; override;
function Clone: TWfxPluginFileSource; override;
procedure CloneTo(FileSource: TFileSource); override;
// Retrieve operations permitted on the source. = capabilities?
class function GetOperationsTypes: TFileSourceOperationTypes; override;
// Returns a list of property types supported by this source for each file.
class function GetFilePropertiesDescriptions: TFilePropertiesDescriptions; override;
// Retrieve some properties of the file source.
class function GetProperties: TFileSourceProperties; override;
// These functions create an operation object specific to the file source.
// Each parameter will be owned by the operation (will be freed).
function CreateListOperation: TFileSourceOperation; override;
function CreateDeleteOperation(var FilesToDelete: TFiles): TFileSourceOperation; override;
function CreateCreateDirectoryOperation(DirectoryPath: String): TFileSourceOperation; override;
class function CreateByRootName(aRootName: String): TWfxPluginFileSource;
property WfxModule: TWfxModule read FWfxModule;
end;
implementation
uses
LCLProc, FileUtil, uGlobs, uDCUtils,
uWfxPluginListOperation, uWfxPluginCreateDirectoryOperation, uWfxPluginDeleteOperation,
uWfxPluginFile, ufsplugin;
constructor TWfxPluginFileSource.Create(aModuleFileName: UTF8String);
begin
inherited Create;
CurrentPath:= PathDelim;
FModuleFileName:= aModuleFileName;
FWFXModule:= TWFXModule.Create;
FWFXModule.LoadModule(FModuleFileName);
end;
destructor TWfxPluginFileSource.Destroy;
begin
inherited Destroy;
end;
function TWfxPluginFileSource.Clone: TWfxPluginFileSource;
begin
Result := TWfxPluginFileSource.Create(FModuleFileName);
CloneTo(Result);
end;
procedure TWfxPluginFileSource.CloneTo(FileSource: TFileSource);
begin
if Assigned(FileSource) then
begin
inherited CloneTo(FileSource);
end;
end;
class function TWfxPluginFileSource.GetOperationsTypes: TFileSourceOperationTypes;
begin
Result := [fsoList, fsoDelete, fsoCreateDirectory];
end;
class function TWfxPluginFileSource.GetFilePropertiesDescriptions: TFilePropertiesDescriptions;
begin
Result := nil;
end;
class function TWfxPluginFileSource.GetProperties: TFileSourceProperties;
begin
Result := [];
end;
class function TWfxPluginFileSource.GetSupportedFileProperties: TFilePropertiesTypes;
begin
Result := [];
end;
function TWfxPluginFileSource.GetCurrentAddress: String;
begin
Result:= 'wfx://' + FModuleFileName;
end;
procedure TWfxPluginFileSource.FillAndCount(Files: TFiles; out NewFiles: TFiles; out FilesCount: Int64; out FilesSize: Int64);
procedure FillAndCountRec(const srcPath: UTF8String);
var
FindData: TWin32FindData;
Handle: THandle;
aFile: TWfxPluginFile;
begin
with FWfxModule do
begin
Handle := FsFindFirst(PChar(UTF8ToSys(srcPath)), FindData);
if Handle = feInvalidHandle then Exit;
repeat
if (FindData.cFileName = '.') or (FindData.cFileName = '..') then Continue;
aFile:= TWfxPluginFile.Create(FindData);
aFile.Path:= srcPath;
NewFiles.Add(aFile);
if aFile.IsDirectory then
begin
FillAndCountRec(srcPath + SysToUTF8(FindData.cFileName) + PathDelim);
end
else
begin
Inc(FilesSize, aFile.Size);
Inc(FilesCount);
end;
until not FsFindNext(Handle, FindData);
FsFindClose(Handle);
end;
end;
var
I: Integer;
aFile: TWfxPluginFile;
begin
NewFiles := TFiles.Create;
FilesCount:= 0;
FilesSize:= 0;
for I := 0 to Files.Count - 1 do
begin
aFile := Files[I] as TWfxPluginFile;
NewFiles.Add(aFile.Clone);
if aFile.IsDirectory and (not aFile.IsLinkToDirectory) then
begin
FillAndCountRec(aFile.Path + aFile.Name + DirectorySeparator); // recursive browse child dir
end
else
begin
Inc(FilesCount);
Inc(FilesSize, aFile.Size); // in first level we know file size -> use it
end;
end;
end;
procedure TWfxPluginFileSource.WfxStatusInfo(RemoteDir: UTF8String; InfoStartEnd, InfoOperation: Integer);
begin
with FWfxModule do
begin
if Assigned(FsStatusInfo) then
FsStatusInfo(PChar(UTF8ToSys(RemoteDir)), InfoStartEnd, InfoOperation);
end;
end;
function TWfxPluginFileSource.WfxMkDir(const sDirName: UTF8String): LongInt;
begin
with FWfxModule do
begin
Result:= WFX_NOTSUPPORTED;
if Assigned(FsMkDir) then
begin
WfxStatusInfo(CurrentPath, FS_STATUS_START, FS_STATUS_OP_MKDIR);
if FsMkDir(PChar(UTF8ToSys(sDirName))) then
Result:= WFX_SUCCESS
else
Result:= WFX_ERROR;
WfxStatusInfo(CurrentPath, FS_STATUS_END, FS_STATUS_OP_MKDIR);
end;
end;
end;
function TWfxPluginFileSource.WfxRemoveDir(const sDirName: UTF8String): Boolean;
begin
with FWfxModule do
begin
Result:= False;
if Assigned(FsRemoveDir) then
begin
Result:= FsRemoveDir(PChar(UTF8ToSys(sDirName)));
end;
end;
end;
function TWfxPluginFileSource.WfxDeleteFile(const sFileName: UTF8String): Boolean;
begin
with FWfxModule do
begin
Result:= False;
if Assigned(FsDeleteFile) then
begin
Result:= FsDeleteFile(PChar(UTF8ToSys(sFileName)));
end;
end;
end;
function TWfxPluginFileSource.CreateListOperation: TFileSourceOperation;
var
TargetFileSource: TFileSource;
begin
TargetFileSource := Self.Clone;
Result := TWfxPluginListOperation.Create(TargetFileSource);
end;
function TWfxPluginFileSource.CreateDeleteOperation(var FilesToDelete: TFiles): TFileSourceOperation;
var
TargetFileSource: TFileSource;
begin
TargetFileSource := Self.Clone;
Result := TWfxPluginDeleteOperation.Create(TargetFileSource, FilesToDelete);
end;
function TWfxPluginFileSource.CreateCreateDirectoryOperation(DirectoryPath: String): TFileSourceOperation;
var
TargetFileSource: TFileSource;
begin
TargetFileSource := Self.Clone;
Result := TWfxPluginCreateDirectoryOperation.Create(TargetFileSource, DirectoryPath);
end;
class function TWfxPluginFileSource.CreateByRootName(aRootName: String): TWfxPluginFileSource;
var
I: Integer;
sModuleFileName: UTF8String;
begin
Result:= nil;
if gWFXPlugins.Count = 0 then Exit;
// Check if there is a registered plugin for the name of the file system plugin.
sModuleFileName:= gWFXPlugins.Values[aRootName];
if sModuleFileName <> EmptyStr then
begin
sModuleFileName:= GetCmdDirFromEnvVar(sModuleFileName);
Result:= TWfxPluginFileSource.Create(sModuleFileName);
DebugLn('Registered plugin ' + sModuleFileName + ' for file system ' + aRootName);
end;
end;
end.

View file

@ -0,0 +1,76 @@
unit uWfxPluginListOperation;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils,
uFileSourceListOperation,
uWfxPluginFileSource,
uFileSource;
type
TWfxPluginListOperation = class(TFileSourceListOperation)
private
FWfxPluginFileSource: TWfxPluginFileSource;
public
constructor Create(var aFileSource: TFileSource); reintroduce;
procedure MainExecute; override;
end;
implementation
uses
LCLProc, FileUtil, uOSUtils, uDCUtils, uWfxPluginFile, uFile, ufsplugin;
constructor TWfxPluginListOperation.Create(var aFileSource: TFileSource);
begin
FFiles := TFiles.Create;
FWfxPluginFileSource := aFileSource as TWfxPluginFileSource;
inherited Create(aFileSource);
end;
procedure TWfxPluginListOperation.MainExecute;
var
FindData : TWIN32FINDDATA;
Handle: THandle;
aFile: TWfxPluginFile;
sPath : UTF8String;
begin
with FWfxPluginFileSource.WFXModule do
begin
sPath:= FileSource.CurrentPath;
WFXStatusInfo(sPath, FS_STATUS_START, FS_STATUS_OP_LIST);
FFiles.Clear;
FFiles.Path := IncludeTrailingPathDelimiter(sPath);
if not FileSource.IsAtRootPath then
begin
aFile := TWfxPluginFile.Create;
aFile.Path := sPath;
aFile.Name := '..';
aFile.Attributes := faFolder;
FFiles.Add(aFile);
end;
Handle := FsFindFirst(PChar(UTF8ToSys(sPath)), FindData);
if Handle = feInvalidHandle then Exit;
repeat
if (FindData.cFileName = '.') or (FindData.cFileName = '..') then Continue;
aFile := TWfxPluginFile.Create(FindData);
aFile.Path := sPath;
FFiles.Add(aFile);
until (not FsFindNext(Handle, FindData));
FsFindClose(Handle);
WFXStatusInfo(sPath, FS_STATUS_END, FS_STATUS_OP_LIST);
end; // with
end;
end.

File diff suppressed because it is too large Load diff