mirror of
https://github.com/doublecmd/doublecmd.git
synced 2026-06-21 09:58:13 +00:00
878 lines
29 KiB
ObjectPascal
878 lines
29 KiB
ObjectPascal
{
|
|
Double Commander
|
|
-------------------------------------------------------------------------
|
|
Virtual File System - class for manage WFX plugins (Version 1.3)
|
|
|
|
Copyright (C) 2007-2018 Alexander Koblov (alexx2000@mail.ru)
|
|
|
|
Callback functions based on:
|
|
Total Commander filesystem plugins debugger
|
|
Author: Pavel Dubrovsky
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
}
|
|
|
|
unit uWFXmodule;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
SysUtils, Classes, WfxPlugin, uWFXprototypes, LazUTF8Classes,
|
|
dynlibs, DCClassesUtf8, Extension, DCBasicTypes, DCXmlConfig,
|
|
uWdxPrototypes, uWdxModule;
|
|
|
|
const
|
|
WFX_SUCCESS = 0;
|
|
WFX_NOTSUPPORTED = -10;
|
|
WFX_ERROR = -20;
|
|
|
|
type
|
|
|
|
{ TWfxFindData }
|
|
|
|
TWfxFindData = record
|
|
FileAttributes : TFileAttrs;
|
|
CreationTime,
|
|
LastAccessTime,
|
|
LastWriteTime : TDateTime;
|
|
FileSize : Int64;
|
|
Reserved0,
|
|
Reserved1 : LongWord;
|
|
FileName : String;
|
|
AlternateFileName : String;
|
|
case Boolean of
|
|
True: ( FindDataA: TWin32FindData; );
|
|
False: ( FindDataW: TWin32FindDataW; );
|
|
end;
|
|
|
|
{ TWFXModule }
|
|
|
|
TWFXModule = class(TPluginWDX)
|
|
private
|
|
FModuleFileName: String;
|
|
FBackgroundFlags: Integer;
|
|
public
|
|
{ Mandatory }
|
|
FsInit : TFsInit;
|
|
FsFindFirst : TFsFindFirst;
|
|
FsFindNext : TFsFindNext;
|
|
FsFindClose : TFsFindClose;
|
|
{ Optional }
|
|
FsSetCryptCallback: TFsSetCryptCallback;
|
|
FsGetDefRootName : TFsGetDefRootName;
|
|
FsGetFile : TFsGetFile;
|
|
FsPutFile : TFsPutFile;
|
|
FsDeleteFile : TFsDeleteFile;
|
|
FsRemoveDir : TFsRemoveDir;
|
|
FsExecuteFile : TFsExecuteFile;
|
|
FsMkDir : TFsMkDir;
|
|
FsStatusInfo : TFsStatusInfo;
|
|
FsSetDefaultParams : TFsSetDefaultParams;
|
|
//---------------------
|
|
FsSetAttr:TFsSetAttr;
|
|
FsSetTime:TFsSetTime;
|
|
FsExtractCustomIcon:TFsExtractCustomIcon;
|
|
FsRenMovFile:TFsRenMovFile;
|
|
FsDisconnect:TFsDisconnect;
|
|
FsGetPreviewBitmap:TFsGetPreviewBitmap;
|
|
FsLinksToLocalFiles:TFsLinksToLocalFiles;
|
|
FsGetLocalName:TFsGetLocalName;
|
|
//---------------------
|
|
FsGetBackgroundFlags: TFsGetBackgroundFlags;
|
|
//---------------------
|
|
FsContentGetDefaultView:TFsContentGetDefaultView;
|
|
{ Unicode }
|
|
FsInitW: TFsInitW;
|
|
FsFindFirstW: TFsFindFirstW;
|
|
FsFindNextW: TFsFindNextW;
|
|
//---------------------
|
|
FsSetCryptCallbackW: TFsSetCryptCallbackW;
|
|
FsMkDirW: TFsMkDirW;
|
|
FsExecuteFileW: TFsExecuteFileW;
|
|
FsRenMovFileW: TFsRenMovFileW;
|
|
FsGetFileW: TFsGetFileW;
|
|
FsPutFileW: TFsPutFileW;
|
|
FsDeleteFileW: TFsDeleteFileW;
|
|
FsRemoveDirW: TFsRemoveDirW;
|
|
FsDisconnectW: TFsDisconnectW;
|
|
FsSetAttrW: TFsSetAttrW;
|
|
FsSetTimeW: TFsSetTimeW;
|
|
FsStatusInfoW: TFsStatusInfoW;
|
|
FsExtractCustomIconW: TFsExtractCustomIconW;
|
|
FsGetPreviewBitmapW: TFsGetPreviewBitmapW;
|
|
FsGetLocalNameW: TFsGetLocalNameW;
|
|
//-----------------------
|
|
FsContentGetDefaultViewW: TFsContentGetDefaultViewW;
|
|
{ Extension API }
|
|
ExtensionInitialize: TExtensionInitializeProc;
|
|
ExtensionFinalize: TExtensionFinalizeProc;
|
|
public
|
|
function WfxFindFirst(Path: String; var FindData: TWfxFindData): THandle;
|
|
function WfxFindNext(Hdl: THandle; var FindData: TWfxFindData): Boolean;
|
|
procedure WfxStatusInfo(RemoteDir: String; InfoStartEnd, InfoOperation: Integer);
|
|
function WfxExecuteFile(MainWin: HWND; var RemoteName: String; Verb: String): Integer;
|
|
function WfxRenMovFile(OldName, NewName: String; Move, OverWrite: Boolean; RemoteInfo: PRemoteInfo): Integer;
|
|
function WfxGetFile(RemoteName, LocalName: String; CopyFlags: Integer; RemoteInfo: PRemoteInfo): Integer;
|
|
function WfxPutFile(LocalName, RemoteName: String; CopyFlags: Integer): Integer;
|
|
function WfxSetAttr(RemoteName: String; NewAttr: LongInt): Boolean;
|
|
{en
|
|
Each of CreationTime, LastAccessTime, LastWriteTime may be @nil to leave the value unchanged.
|
|
}
|
|
function WfxSetTime(RemoteName: String; pCreationTime, pLastAccessTime, pLastWriteTime: PWfxFileTime): Boolean;
|
|
function WfxMkDir(const sBasePath, sDirName: String): LongInt;
|
|
function WfxRemoveDir(const sDirName: String): Boolean;
|
|
function WfxDeleteFile(const sFileName: String): Boolean;
|
|
function WfxGetLocalName(var sFileName: String): Boolean;
|
|
function WfxDisconnect(const DisconnectRoot: String): Boolean;
|
|
private
|
|
function LoadModule(const sName: String):Boolean; overload; {Load plugin}
|
|
procedure UnloadModule; override;
|
|
public
|
|
constructor Create; override;
|
|
destructor Destroy; override;
|
|
|
|
procedure VFSInit;
|
|
|
|
function VFSConfigure(Parent: HWND):Boolean;
|
|
function VFSRootName: String;
|
|
|
|
function ContentPlugin: Boolean;
|
|
|
|
property BackgroundFlags: Integer read FBackgroundFlags write FBackgroundFlags;
|
|
end;
|
|
|
|
{ TWFXModuleList }
|
|
|
|
TWFXModuleList = class(TStringList)
|
|
private
|
|
FModuleList: TStringListUTF8;
|
|
private
|
|
function GetAEnabled(Index: Integer): Boolean;
|
|
function GetAFileName(Index: Integer): String;
|
|
function GetAName(Index: Integer): String;
|
|
procedure SetAEnabled(Index: Integer; const AValue: Boolean);
|
|
procedure SetAFileName(Index: Integer; const AValue: String);
|
|
procedure SetAName(Index: Integer; const AValue: String);
|
|
public
|
|
constructor Create; reintroduce;
|
|
destructor Destroy; override;
|
|
public
|
|
procedure Load(AConfig: TXmlConfig; ANode: TXmlNode); overload;
|
|
procedure Save(AConfig: TXmlConfig; ANode: TXmlNode); overload;
|
|
function ComputeSignature(seed: dword): dword;
|
|
function Add(Ext: String; FileName: String): Integer; reintroduce;
|
|
function FindFirstEnabledByName(Name: String): Integer;
|
|
function LoadModule(const FileName: String): TWfxModule;
|
|
|
|
property Name[Index: Integer]: String read GetAName write SetAName;
|
|
property FileName[Index: Integer]: String read GetAFileName write SetAFileName;
|
|
property Enabled[Index: Integer]: Boolean read GetAEnabled write SetAEnabled;
|
|
end;
|
|
|
|
function GetErrorMsg(iErrorMsg: LongInt): String;
|
|
|
|
implementation
|
|
|
|
uses
|
|
//Lazarus, Free-Pascal, etc.
|
|
LazUTF8, FileUtil,
|
|
|
|
//DC
|
|
uDCUtils, uLng, uGlobsPaths, uOSUtils, uWfxPluginUtil, fDialogBox, DCOSUtils,
|
|
DCStrUtils, DCConvertEncoding, uComponentsSignature, uOSForms;
|
|
|
|
const
|
|
WfxIniFileName = 'wfx.ini';
|
|
|
|
function GetErrorMsg(iErrorMsg: LongInt): String;
|
|
begin
|
|
case iErrorMsg of
|
|
WFX_ERROR:
|
|
Result:= 'Unknown error!';
|
|
WFX_NOTSUPPORTED,
|
|
FS_FILE_NOTSUPPORTED:
|
|
Result:= rsMsgErrNotSupported;
|
|
FS_FILE_NOTFOUND:
|
|
Result:= 'File not found!';
|
|
FS_FILE_READERROR:
|
|
Result:= rsMsgErrERead;
|
|
FS_FILE_WRITEERROR:
|
|
Result:= rsMsgErrEWrite;
|
|
FS_FILE_USERABORT:
|
|
Result:= rsMsgErrEAborted;
|
|
end;
|
|
end;
|
|
|
|
{ TWfxFindData }
|
|
|
|
procedure ConvertFindData(var FindData: TWfxFindData; AnsiData: Boolean);
|
|
begin
|
|
with FindData do
|
|
begin
|
|
// Convert file attributes
|
|
FileAttributes:= FindDataW.dwFileAttributes;
|
|
CreationTime:= WfxFileTimeToDateTime(FindDataW.ftCreationTime);
|
|
LastAccessTime:= WfxFileTimeToDateTime(FindDataW.ftLastAccessTime);
|
|
LastWriteTime:= WfxFileTimeToDateTime(FindDataW.ftLastWriteTime);
|
|
Int64Rec(FileSize).Lo:= FindDataW.nFileSizeLow;
|
|
Int64Rec(FileSize).Hi:= FindDataW.nFileSizeHigh;
|
|
Reserved0:= FindDataW.dwReserved0;
|
|
Reserved1:= FindDataW.dwReserved1;
|
|
// Convert file name
|
|
if AnsiData then
|
|
begin
|
|
FileName:= CeSysToUtf8(FindDataA.cFileName);
|
|
AlternateFileName:= CeSysToUtf8(FindDataA.cAlternateFileName);
|
|
end
|
|
else
|
|
begin
|
|
FileName:= UTF16ToUTF8(UnicodeString(FindDataW.cFileName));
|
|
AlternateFileName:= UTF16ToUTF8(UnicodeString(FindDataW.cAlternateFileName));
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{ TWFXModule }
|
|
|
|
function TWFXModule.WfxFindFirst(Path: String; var FindData: TWfxFindData): THandle;
|
|
begin
|
|
try
|
|
if Assigned(FsFindFirstW) then
|
|
begin
|
|
Result:= FsFindFirstW(PWideChar(CeUtf8ToUtf16(Path)), FindData.FindDataW);
|
|
if Result <> wfxInvalidHandle then ConvertFindData(FindData, False);
|
|
end
|
|
else if Assigned(FsFindFirst) then
|
|
begin
|
|
Result:= FsFindFirst(PAnsiChar(CeUtf8ToSys(Path)), FindData.FindDataA);
|
|
if Result <> wfxInvalidHandle then ConvertFindData(FindData, True);
|
|
end;
|
|
except
|
|
on E: Exception do
|
|
begin
|
|
Result:= wfxInvalidHandle;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TWFXModule.WfxFindNext(Hdl: THandle; var FindData: TWfxFindData): Boolean;
|
|
begin
|
|
if Assigned(FsFindFirstW) then
|
|
begin
|
|
Result:= FsFindNextW(Hdl, FindData.FindDataW);
|
|
if Result then ConvertFindData(FindData, False);
|
|
end
|
|
else if Assigned(FsFindFirst) then
|
|
begin
|
|
Result:= FsFindNext(Hdl, FindData.FindDataA);
|
|
if Result then ConvertFindData(FindData, True);
|
|
end
|
|
else Result:= False;
|
|
end;
|
|
|
|
procedure TWFXModule.WfxStatusInfo(RemoteDir: String; InfoStartEnd,
|
|
InfoOperation: Integer);
|
|
begin
|
|
if Assigned(FsStatusInfoW) then
|
|
FsStatusInfoW(PWideChar(CeUtf8ToUtf16(RemoteDir)), InfoStartEnd, InfoOperation)
|
|
else if Assigned(FsStatusInfo) then
|
|
FsStatusInfo(PAnsiChar(CeUtf8ToSys(RemoteDir)), InfoStartEnd, InfoOperation);
|
|
end;
|
|
|
|
function TWFXModule.WfxExecuteFile(MainWin: HWND; var RemoteName: String; Verb: String): Integer;
|
|
var
|
|
pacRemoteName: PAnsiChar;
|
|
pwcRemoteName: PWideChar;
|
|
begin
|
|
Result:= WFX_NOTSUPPORTED;
|
|
MainWin:= GetWindowHandle(MainWin);
|
|
if Assigned(FsExecuteFileW) then
|
|
begin
|
|
pwcRemoteName:= GetMem(MAX_PATH * SizeOf(WideChar));
|
|
StrPCopyW(pwcRemoteName, CeUtf8ToUtf16(RemoteName));
|
|
Result:= FsExecuteFileW(MainWin, pwcRemoteName, PWideChar(CeUtf8ToUtf16(Verb)));
|
|
if Result = FS_EXEC_SYMLINK then
|
|
RemoteName:= UTF16ToUTF8(UnicodeString(pwcRemoteName));
|
|
FreeMem(pwcRemoteName);
|
|
end
|
|
else if Assigned(FsExecuteFile) then
|
|
begin
|
|
pacRemoteName:= GetMem(MAX_PATH);
|
|
StrPCopy(pacRemoteName, CeUtf8ToSys(RemoteName));
|
|
Result:= FsExecuteFile(MainWin, pacRemoteName, PAnsiChar(CeUtf8ToSys(Verb)));
|
|
if Result = FS_EXEC_SYMLINK then
|
|
RemoteName:= CeSysToUtf8(StrPas(pacRemoteName));
|
|
FreeMem(pacRemoteName);
|
|
end;
|
|
end;
|
|
|
|
function TWFXModule.WfxRenMovFile(OldName, NewName: String; Move,
|
|
OverWrite: Boolean; RemoteInfo: PRemoteInfo): Integer;
|
|
begin
|
|
Result:= FS_FILE_NOTSUPPORTED;
|
|
if Assigned(FsRenMovFileW) then
|
|
Result:= FsRenMovFileW(PWideChar(CeUtf8ToUtf16(OldName)), PWideChar(CeUtf8ToUtf16(NewName)), Move, OverWrite, RemoteInfo)
|
|
else if Assigned(FsRenMovFile) then
|
|
Result:= FsRenMovFile(PAnsiChar(CeUtf8ToSys(OldName)), PAnsiChar(CeUtf8ToSys(NewName)), Move, OverWrite, RemoteInfo);
|
|
end;
|
|
|
|
function TWFXModule.WfxGetFile(RemoteName, LocalName: String;
|
|
CopyFlags: Integer; RemoteInfo: PRemoteInfo): Integer;
|
|
begin
|
|
Result:= FS_FILE_NOTSUPPORTED;
|
|
if Assigned(FsGetFileW) then
|
|
Result:= FsGetFileW(PWideChar(CeUtf8ToUtf16(RemoteName)), PWideChar(CeUtf8ToUtf16(LocalName)), CopyFlags, RemoteInfo)
|
|
else if Assigned(FsGetFile) then
|
|
Result:= FsGetFile(PAnsiChar(CeUtf8ToSys(RemoteName)), PAnsiChar(CeUtf8ToSys(LocalName)), CopyFlags, RemoteInfo);
|
|
end;
|
|
|
|
function TWFXModule.WfxPutFile(LocalName, RemoteName: String; CopyFlags: Integer): Integer;
|
|
begin
|
|
Result:= FS_FILE_NOTSUPPORTED;
|
|
if Assigned(FsPutFileW) then
|
|
Result:= FsPutFileW(PWideChar(CeUtf8ToUtf16(LocalName)), PWideChar(CeUtf8ToUtf16(RemoteName)), CopyFlags)
|
|
else if Assigned(FsPutFile) then
|
|
Result:= FsPutFile(PAnsiChar(CeUtf8ToSys(LocalName)), PAnsiChar(CeUtf8ToSys(RemoteName)), CopyFlags);
|
|
end;
|
|
|
|
function TWFXModule.WfxSetAttr(RemoteName: String; NewAttr: LongInt): Boolean;
|
|
begin
|
|
Result:= False;
|
|
if Assigned(FsSetAttrW) then
|
|
Result:= FsSetAttrW(PWideChar(CeUtf8ToUtf16(RemoteName)), NewAttr)
|
|
else if Assigned(FsSetAttr) then
|
|
Result:= FsSetAttr(PAnsiChar(CeUtf8ToSys(RemoteName)), NewAttr);
|
|
end;
|
|
|
|
function TWFXModule.WfxSetTime(RemoteName: String; pCreationTime,
|
|
pLastAccessTime, pLastWriteTime: PWfxFileTime): Boolean;
|
|
begin
|
|
Result:= False;
|
|
if Assigned(FsSetTimeW) then
|
|
Result:= FsSetTimeW(PWideChar(CeUtf8ToUtf16(RemoteName)), pCreationTime, pLastAccessTime, pLastWriteTime)
|
|
else if Assigned(FsSetTime) then
|
|
Result:= FsSetTime(PAnsiChar(CeUtf8ToSys(RemoteName)), pCreationTime, pLastAccessTime, pLastWriteTime);
|
|
end;
|
|
|
|
function TWFXModule.WfxMkDir(const sBasePath, sDirName: String): LongInt;
|
|
begin
|
|
Result:= WFX_NOTSUPPORTED;
|
|
if Assigned(FsMkDirW) then
|
|
begin
|
|
WfxStatusInfo(sBasePath, FS_STATUS_START, FS_STATUS_OP_MKDIR);
|
|
if FsMkDirW(PWideChar(CeUtf8ToUtf16(sDirName))) then
|
|
Result:= WFX_SUCCESS
|
|
else
|
|
Result:= WFX_ERROR;
|
|
WfxStatusInfo(sBasePath, FS_STATUS_END, FS_STATUS_OP_MKDIR);
|
|
end
|
|
else if Assigned(FsMkDir) then
|
|
begin
|
|
WfxStatusInfo(sBasePath, FS_STATUS_START, FS_STATUS_OP_MKDIR);
|
|
if FsMkDir(PAnsiChar(CeUtf8ToSys(sDirName))) then
|
|
Result:= WFX_SUCCESS
|
|
else
|
|
Result:= WFX_ERROR;
|
|
WfxStatusInfo(sBasePath, FS_STATUS_END, FS_STATUS_OP_MKDIR);
|
|
end;
|
|
end;
|
|
|
|
function TWFXModule.WfxRemoveDir(const sDirName: String): Boolean;
|
|
begin
|
|
Result:= False;
|
|
if Assigned(FsRemoveDirW) then
|
|
Result:= FsRemoveDirW(PWideChar(CeUtf8ToUtf16(sDirName)))
|
|
else if Assigned(FsRemoveDir) then
|
|
Result:= FsRemoveDir(PAnsiChar(CeUtf8ToSys(sDirName)));
|
|
end;
|
|
|
|
function TWFXModule.WfxDeleteFile(const sFileName: String): Boolean;
|
|
begin
|
|
Result:= False;
|
|
if Assigned(FsDeleteFileW) then
|
|
Result:= FsDeleteFileW(PWideChar(CeUtf8ToUtf16(sFileName)))
|
|
else if Assigned(FsDeleteFile) then
|
|
Result:= FsDeleteFile(PAnsiChar(CeUtf8ToSys(sFileName)));
|
|
end;
|
|
|
|
function TWFXModule.WfxGetLocalName(var sFileName: String): Boolean;
|
|
var
|
|
pacRemoteName: PAnsiChar;
|
|
pwcRemoteName: PWideChar;
|
|
begin
|
|
Result:= False;
|
|
if Assigned(FsGetLocalNameW) then
|
|
begin
|
|
pwcRemoteName:= GetMem(MAX_PATH * SizeOf(WideChar));
|
|
StrPCopyW(pwcRemoteName, CeUtf8ToUtf16(sFileName));
|
|
Result:= FsGetLocalNameW(pwcRemoteName, MAX_PATH);
|
|
if Result = True then
|
|
sFileName:= UTF16ToUTF8(UnicodeString(pwcRemoteName));
|
|
FreeMem(pwcRemoteName);
|
|
end
|
|
else if Assigned(FsGetLocalName) then
|
|
begin
|
|
pacRemoteName:= GetMem(MAX_PATH);
|
|
StrPCopy(pacRemoteName, CeUtf8ToSys(sFileName));
|
|
Result:= FsGetLocalName(pacRemoteName, MAX_PATH);
|
|
if Result = True then
|
|
sFileName:= CeSysToUtf8(StrPas(pacRemoteName));
|
|
FreeMem(pacRemoteName);
|
|
end;
|
|
end;
|
|
|
|
function TWFXModule.WfxDisconnect(const DisconnectRoot: String): Boolean;
|
|
begin
|
|
if Assigned(FsDisconnectW) then
|
|
Result:= FsDisconnectW(PWideChar(CeUtf8ToUtf16(DisconnectRoot)))
|
|
else if Assigned(FsDisconnect) then
|
|
Result:= FsDisconnect(PAnsiChar(CeUtf8ToSys(DisconnectRoot)))
|
|
else
|
|
Result:= False;
|
|
end;
|
|
|
|
constructor TWFXModule.Create;
|
|
begin
|
|
inherited;
|
|
FName:= 'FS';
|
|
end;
|
|
|
|
destructor TWFXModule.Destroy;
|
|
begin
|
|
if IsLoaded then
|
|
begin
|
|
if Assigned(ContentPluginUnloading) then
|
|
ContentPluginUnloading;
|
|
if Assigned(ExtensionFinalize) then
|
|
ExtensionFinalize(nil);
|
|
end;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TWFXModule.LoadModule(const sName: String): Boolean;
|
|
var
|
|
AHandle: TLibHandle;
|
|
begin
|
|
EnterCriticalSection(FMutex);
|
|
try
|
|
if FModuleHandle <> NilHandle then Exit(True);
|
|
AHandle := mbLoadLibrary(mbExpandFileName(sName));
|
|
Result := AHandle <> NilHandle;
|
|
if not Result then Exit;
|
|
|
|
FModuleFileName:= sName;
|
|
{ Mandatory }
|
|
FsInit := TFsInit(GetProcAddress(AHandle,'FsInit'));
|
|
FsFindFirst := TFsFindFirst(GetProcAddress(AHandle,'FsFindFirst'));
|
|
FsFindNext := TFsFindNext(GetProcAddress(AHandle,'FsFindNext'));
|
|
FsFindClose := TFsFindClose(GetProcAddress(AHandle,'FsFindClose'));
|
|
{ Unicode }
|
|
FsInitW := TFsInitW(GetProcAddress(AHandle,'FsInitW'));
|
|
FsFindFirstW := TFsFindFirstW(GetProcAddress(AHandle,'FsFindFirstW'));
|
|
FsFindNextW := TFsFindNextW(GetProcAddress(AHandle,'FsFindNextW'));
|
|
|
|
Result:= (FsInit <> nil) and (FsFindFirst <> nil) and (FsFindNext <> nil);
|
|
if (Result = False) then
|
|
begin
|
|
FsInit:= nil;
|
|
FsFindFirst:= nil;
|
|
FsFindNext:= nil;
|
|
Result:= (FsInitW <> nil) and (FsFindFirstW <> nil) and (FsFindNextW <> nil);
|
|
end;
|
|
|
|
if (Result = False) or (FsFindClose = nil) then
|
|
begin
|
|
FsInitW:= nil;
|
|
FsFindFirstW:= nil;
|
|
FsFindNextW:= nil;
|
|
FsFindClose:= nil;
|
|
FreeLibrary(AHandle);
|
|
Exit(False);
|
|
end;
|
|
|
|
{ Optional }
|
|
FsSetCryptCallback:= TFsSetCryptCallback(GetProcAddress(AHandle,'FsSetCryptCallback'));
|
|
FsGetDefRootName := TFsGetDefRootName(GetProcAddress(AHandle,'FsGetDefRootName'));
|
|
FsExecuteFile := TFsExecuteFile(GetProcAddress(AHandle,'FsExecuteFile'));
|
|
FsGetFile := TFsGetFile(GetProcAddress(AHandle,'FsGetFile'));
|
|
FsPutFile := TFsPutFile(GetProcAddress(AHandle,'FsPutFile'));
|
|
FsDeleteFile := TFsDeleteFile(GetProcAddress(AHandle,'FsDeleteFile'));
|
|
FsMkDir := TFsMkDir(GetProcAddress(AHandle,'FsMkDir'));
|
|
FsRemoveDir := TFsRemoveDir(GetProcAddress(AHandle,'FsRemoveDir'));
|
|
FsStatusInfo := TFsStatusInfo(GetProcAddress(AHandle,'FsStatusInfo'));
|
|
FsSetDefaultParams := TFsSetDefaultParams(GetProcAddress(AHandle,'FsSetDefaultParams'));
|
|
//---------------------
|
|
FsSetAttr := TFsSetAttr (GetProcAddress(AHandle,'FsSetAttr'));
|
|
FsSetTime := TFsSetTime (GetProcAddress(AHandle,'FsSetTime'));
|
|
FsExtractCustomIcon := TFsExtractCustomIcon (GetProcAddress(AHandle,'FsExtractCustomIcon'));
|
|
FsRenMovFile := TFsRenMovFile (GetProcAddress(AHandle,'FsRenMovFile'));
|
|
FsDisconnect := TFsDisconnect (GetProcAddress(AHandle,'FsDisconnect'));
|
|
FsGetPreviewBitmap := TFsGetPreviewBitmap (GetProcAddress(AHandle,'FsGetPreviewBitmap'));
|
|
FsLinksToLocalFiles := TFsLinksToLocalFiles (GetProcAddress(AHandle,'FsLinksToLocalFiles'));
|
|
FsGetLocalName := TFsGetLocalName (GetProcAddress(AHandle,'FsGetLocalName'));
|
|
//---------------------
|
|
FsGetBackgroundFlags := TFsGetBackgroundFlags (GetProcAddress(AHandle,'FsGetBackgroundFlags'));
|
|
//---------------------
|
|
FsContentGetDefaultView := TFsContentGetDefaultView (GetProcAddress(AHandle,'FsContentGetDefaultView'));
|
|
ContentSetDefaultParams := TContentSetDefaultParams (GetProcAddress(AHandle,'FsContentSetDefaultParams'));
|
|
ContentGetDetectString := TFsContentGetDetectString (GetProcAddress(AHandle,'FsContentGetDetectString'));
|
|
ContentGetSupportedField := TFsContentGetSupportedField (GetProcAddress(AHandle,'FsContentGetSupportedField'));
|
|
ContentGetValue := TFsContentGetValue (GetProcAddress(AHandle,'FsContentGetValue'));
|
|
ContentStopGetValue := TFsContentStopGetValue (GetProcAddress(AHandle,'FsContentStopGetValue'));
|
|
ContentGetDefaultSortOrder := TFsContentGetDefaultSortOrder (GetProcAddress(AHandle,'FsContentGetDefaultSortOrder'));
|
|
ContentGetSupportedFieldFlags := TFsContentGetSupportedFieldFlags (GetProcAddress(AHandle,'FsContentGetSupportedFieldFlags'));
|
|
ContentSetValue := TFsContentSetValue (GetProcAddress(AHandle,'FsContentSetValue'));
|
|
ContentPluginUnloading := TFsContentPluginUnloading(GetProcAddress(AHandle,'FsContentPluginUnloading'));
|
|
{ Unicode }
|
|
FsSetCryptCallbackW:= TFsSetCryptCallbackW(GetProcAddress(AHandle,'FsSetCryptCallbackW'));
|
|
FsMkDirW := TFsMkDirW(GetProcAddress(AHandle,'FsMkDirW'));
|
|
FsExecuteFileW := TFsExecuteFileW(GetProcAddress(AHandle,'FsExecuteFileW'));
|
|
FsRenMovFileW := TFsRenMovFileW(GetProcAddress(AHandle,'FsRenMovFileW'));
|
|
FsGetFileW := TFsGetFileW(GetProcAddress(AHandle,'FsGetFileW'));
|
|
FsPutFileW := TFsPutFileW(GetProcAddress(AHandle,'FsPutFileW'));
|
|
FsDeleteFileW := TFsDeleteFileW(GetProcAddress(AHandle,'FsDeleteFileW'));
|
|
FsRemoveDirW := TFsRemoveDirW(GetProcAddress(AHandle,'FsRemoveDirW'));
|
|
FsDisconnectW := TFsDisconnectW(GetProcAddress(AHandle,'FsDisconnectW'));
|
|
FsSetAttrW := TFsSetAttrW (GetProcAddress(AHandle,'FsSetAttrW'));
|
|
FsSetTimeW := TFsSetTimeW (GetProcAddress(AHandle,'FsSetTimeW'));
|
|
FsStatusInfoW := TFsStatusInfoW(GetProcAddress(AHandle,'FsStatusInfoW'));
|
|
FsExtractCustomIconW := TFsExtractCustomIconW(GetProcAddress(AHandle,'FsExtractCustomIconW'));
|
|
FsGetLocalNameW := TFsGetLocalNameW(GetProcAddress(AHandle,'FsGetLocalNameW'));
|
|
//--------------------------
|
|
FsContentGetDefaultViewW := TFsContentGetDefaultViewW(GetProcAddress(AHandle,'FsContentGetDefaultViewW'));
|
|
ContentGetValueW := TFsContentGetValueW(GetProcAddress(AHandle, 'FsContentGetValueW'));
|
|
ContentStopGetValueW := TFsContentStopGetValueW(GetProcAddress(AHandle, 'FsContentStopGetValueW'));
|
|
ContentSetValueW := TFsContentSetValueW(GetProcAddress(AHandle, 'FsContentSetValueW'));
|
|
{ Extension API }
|
|
ExtensionInitialize:= TExtensionInitializeProc(GetProcAddress(AHandle,'ExtensionInitialize'));
|
|
ExtensionFinalize:= TExtensionFinalizeProc(GetProcAddress(AHandle,'ExtensionFinalize'));
|
|
|
|
VFSInit;
|
|
|
|
FModuleHandle := AHandle;
|
|
finally
|
|
LeaveCriticalSection(FMutex);
|
|
end;
|
|
end;
|
|
|
|
procedure TWFXModule.UnloadModule;
|
|
var
|
|
AHandle: TLibHandle;
|
|
begin
|
|
EnterCriticalSection(FMutex);
|
|
try
|
|
if FModuleHandle <> NilHandle then
|
|
begin
|
|
AHandle:= FModuleHandle;
|
|
FModuleHandle := NilHandle;
|
|
FreeLibrary(AHandle);
|
|
end;
|
|
|
|
{ Mandatory }
|
|
FsInit := nil;
|
|
FsFindFirst := nil;
|
|
FsFindNext := nil;
|
|
FsFindClose := nil;
|
|
{ Optional }
|
|
FsSetCryptCallback := nil;
|
|
FsGetDefRootName := nil;
|
|
FsGetFile := nil;
|
|
FsPutFile := nil;
|
|
FsDeleteFile := nil;
|
|
FsRemoveDir := nil;
|
|
FsExecuteFile := nil;
|
|
FsMkDir := nil;
|
|
FsStatusInfo := nil;
|
|
FsSetDefaultParams:=nil;
|
|
//---------------------
|
|
FsSetAttr := nil;
|
|
FsSetTime := nil;
|
|
FsExtractCustomIcon := nil;
|
|
FsRenMovFile := nil;
|
|
FsDisconnect := nil;
|
|
FsGetPreviewBitmap := nil;
|
|
FsLinksToLocalFiles := nil;
|
|
FsGetLocalName := nil;
|
|
//---------------------
|
|
FsGetBackgroundFlags := nil;
|
|
//---------------------
|
|
FsContentGetDefaultView := nil;
|
|
ContentGetDetectString := nil;
|
|
ContentGetSupportedField := nil;
|
|
ContentGetValue := nil;
|
|
ContentSetDefaultParams := nil;
|
|
ContentStopGetValue := nil;
|
|
ContentGetDefaultSortOrder := nil;
|
|
ContentGetSupportedFieldFlags := nil;
|
|
ContentSetValue := nil;
|
|
ContentPluginUnloading := nil;
|
|
{ Unicode }
|
|
FsInitW := nil;
|
|
FsFindFirstW := nil;
|
|
FsFindNextW := nil;
|
|
//---------------------
|
|
FsSetCryptCallbackW:= nil;
|
|
FsMkDirW := nil;
|
|
FsExecuteFileW := nil;
|
|
FsRenMovFileW := nil;
|
|
FsGetFileW := nil;
|
|
FsPutFileW := nil;
|
|
FsDeleteFileW := nil;
|
|
FsRemoveDirW := nil;
|
|
FsDisconnectW := nil;
|
|
FsSetAttrW := nil;
|
|
FsSetTimeW := nil;
|
|
FsStatusInfoW := nil;
|
|
FsExtractCustomIconW := nil;
|
|
FsGetLocalNameW := nil;
|
|
//---------------------
|
|
FsContentGetDefaultViewW := nil;
|
|
ContentGetValueW := nil;
|
|
ContentStopGetValueW := nil;
|
|
ContentSetValueW := nil;
|
|
// Extension API
|
|
ExtensionInitialize:= nil;
|
|
ExtensionFinalize:= nil;
|
|
finally
|
|
LeaveCriticalSection(FMutex);
|
|
end;
|
|
end;
|
|
|
|
procedure TWFXModule.VFSInit;
|
|
var
|
|
dps: tFsDefaultParamStruct;
|
|
StartupInfo: TExtensionStartupInfo;
|
|
begin
|
|
if Assigned(FsSetDefaultParams) then
|
|
begin
|
|
dps.DefaultIniName := mbFileNameToSysEnc(gpCfgDir + WfxIniFileName);
|
|
dps.PluginInterfaceVersionHi:= 2;
|
|
dps.PluginInterfaceVersionLow:= 0;
|
|
dps.Size:= SizeOf(dps);
|
|
FsSetDefaultParams(@dps);
|
|
end;
|
|
|
|
if not Assigned(FsGetBackgroundFlags) then
|
|
FBackgroundFlags:= 0
|
|
else
|
|
FBackgroundFlags:= FsGetBackgroundFlags();
|
|
|
|
// Extension API
|
|
if Assigned(ExtensionInitialize) then
|
|
begin
|
|
FillByte(StartupInfo, SizeOf(TExtensionStartupInfo), 0);
|
|
|
|
with StartupInfo do
|
|
begin
|
|
StructSize:= SizeOf(TExtensionStartupInfo);
|
|
PluginDir:= ExtractFilePath(mbExpandFileName(FModuleFileName));
|
|
PluginConfDir:= gpCfgDir;
|
|
InputBox:= @fDialogBox.InputBox;
|
|
MessageBox:= @fDialogBox.MessageBox;
|
|
DialogBoxLFM:= @fDialogBox.DialogBoxLFM;
|
|
DialogBoxLRS:= @fDialogBox.DialogBoxLRS;
|
|
DialogBoxLFMFile:= @fDialogBox.DialogBoxLFMFile;
|
|
SendDlgMsg:= @fDialogBox.SendDlgMsg;
|
|
end;
|
|
|
|
ExtensionInitialize(@StartupInfo);
|
|
end;
|
|
|
|
CallContentSetDefaultParams;
|
|
CallContentGetSupportedField;
|
|
if Length(Self.DetectStr) = 0 then
|
|
Self.DetectStr := CallContentGetDetectString;
|
|
end;
|
|
|
|
function TWFXModule.VFSConfigure(Parent: HWND): Boolean;
|
|
var
|
|
RemoteName: String;
|
|
begin
|
|
try
|
|
RemoteName:= PathDelim;
|
|
WFXStatusInfo(PathDelim, FS_STATUS_START, FS_STATUS_OP_EXEC);
|
|
Result:= (WfxExecuteFile(Parent, RemoteName, 'properties') = FS_EXEC_OK);
|
|
WFXStatusInfo(PathDelim, FS_STATUS_END, FS_STATUS_OP_EXEC);
|
|
except
|
|
on E: Exception do
|
|
begin
|
|
Result:= False;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TWFXModule.VFSRootName: String;
|
|
var
|
|
pcRootName : PAnsiChar;
|
|
begin
|
|
Result:= EmptyStr;
|
|
if Assigned(FsGetDefRootName) then
|
|
begin
|
|
pcRootName:= GetMem(MAX_PATH);
|
|
Assert(Assigned(pcRootName));
|
|
try
|
|
FsGetDefRootName(pcRootName, MAX_PATH);
|
|
Result := StrPas(pcRootName);
|
|
finally
|
|
FreeMem(pcRootName);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TWFXModule.ContentPlugin: Boolean;
|
|
begin
|
|
Result:= Assigned(ContentGetValue) or Assigned(ContentGetValueW);
|
|
end;
|
|
|
|
{ TWFXModuleList }
|
|
|
|
function TWFXModuleList.GetAEnabled(Index: Integer): Boolean;
|
|
begin
|
|
Result:= Boolean(PtrInt(Objects[Index]));
|
|
end;
|
|
|
|
function TWFXModuleList.GetAFileName(Index: Integer): String;
|
|
begin
|
|
Result:= ValueFromIndex[Index];
|
|
end;
|
|
|
|
function TWFXModuleList.GetAName(Index: Integer): String;
|
|
begin
|
|
Result:= Names[Index];
|
|
end;
|
|
|
|
procedure TWFXModuleList.SetAEnabled(Index: Integer; const AValue: Boolean);
|
|
begin
|
|
Objects[Index]:= TObject(PtrInt(AValue));
|
|
end;
|
|
|
|
procedure TWFXModuleList.SetAFileName(Index: Integer; const AValue: String);
|
|
begin
|
|
ValueFromIndex[Index]:= AValue;
|
|
end;
|
|
|
|
procedure TWFXModuleList.SetAName(Index: Integer; const AValue: String);
|
|
var
|
|
sValue : String;
|
|
begin
|
|
sValue:= ValueFromIndex[Index];
|
|
Self[Index]:= AValue + '=' + sValue;
|
|
end;
|
|
|
|
constructor TWFXModuleList.Create;
|
|
begin
|
|
FModuleList:= TStringListUTF8.Create;
|
|
FModuleList.Sorted:= True;
|
|
end;
|
|
|
|
destructor TWFXModuleList.Destroy;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I:= 0 to FModuleList.Count - 1 do
|
|
begin
|
|
TWfxModule(FModuleList.Objects[I]).Free;
|
|
end;
|
|
FreeAndNil(FModuleList);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TWFXModuleList.Load(AConfig: TXmlConfig; ANode: TXmlNode);
|
|
var
|
|
I: Integer;
|
|
AName, APath: String;
|
|
begin
|
|
Clear;
|
|
|
|
ANode := ANode.FindNode('WfxPlugins');
|
|
if Assigned(ANode) then
|
|
begin
|
|
ANode := ANode.FirstChild;
|
|
while Assigned(ANode) do
|
|
begin
|
|
if ANode.CompareName('WfxPlugin') = 0 then
|
|
begin
|
|
if AConfig.TryGetValue(ANode, 'Name', AName) and AConfig.TryGetValue(ANode, 'Path', APath) then
|
|
begin
|
|
I := Add(AName, APath);
|
|
Enabled[I] := AConfig.GetAttr(ANode, 'Enabled', True);
|
|
end;
|
|
end;
|
|
ANode := ANode.NextSibling;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TWFXModuleList.Save(AConfig: TXmlConfig; ANode: TXmlNode);
|
|
var
|
|
I: Integer;
|
|
SubNode: TXmlNode;
|
|
begin
|
|
ANode := AConfig.FindNode(ANode, 'WfxPlugins', True);
|
|
AConfig.ClearNode(ANode);
|
|
for I := 0 to Count - 1 do
|
|
begin
|
|
SubNode := AConfig.AddNode(ANode, 'WfxPlugin');
|
|
AConfig.SetAttr(SubNode, 'Enabled', Enabled[I]);
|
|
AConfig.AddValue(SubNode, 'Name', Name[I]);
|
|
AConfig.AddValue(SubNode, 'Path', FileName[I]);
|
|
end;
|
|
end;
|
|
|
|
{ TWFXModuleList.ComputeSignature }
|
|
function TWFXModuleList.ComputeSignature(seed: dword): dword;
|
|
var
|
|
iIndex: integer;
|
|
begin
|
|
result := seed;
|
|
for iIndex := 0 to pred(Count) do
|
|
begin
|
|
result := ComputeSignatureBoolean(result, Enabled[iIndex]);
|
|
result := ComputeSignatureString(result, Name[iIndex]);
|
|
result := ComputeSignatureString(result, FileName[iIndex]);
|
|
end;
|
|
end;
|
|
|
|
function TWFXModuleList.Add(Ext: String; FileName: String): Integer;
|
|
begin
|
|
Result:= AddObject(Ext + '=' + FileName, TObject(True));
|
|
end;
|
|
|
|
function TWFXModuleList.FindFirstEnabledByName(Name: String): Integer;
|
|
begin
|
|
for Result := 0 to Count - 1 do
|
|
if Enabled[Result] and (DoCompareText(Names[Result], Name) = 0) then
|
|
Exit;
|
|
Result := -1;
|
|
end;
|
|
|
|
function TWFXModuleList.LoadModule(const FileName: String): TWfxModule;
|
|
var
|
|
Index: Integer;
|
|
begin
|
|
if FModuleList.Find(FileName, Index) then
|
|
Result := TWfxModule(FModuleList.Objects[Index])
|
|
else begin
|
|
Result := TWfxModule.Create;
|
|
if not Result.LoadModule(FileName) then
|
|
FreeAndNil(Result)
|
|
else begin
|
|
FModuleList.AddObject(FileName, Result);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
end.
|