doublecmd/src/uwfxmodule.pas
Denis Bisson b3143b2aca CHG: Few modifications regarding plugins configuration.
ADD: Warn the user when attempting to quit the plugin configuration without having saved possible unsaved modification.
ADD: In the plugin configuration table, if a text is too large to fit in a column, a tooltip is displayed showing the complete text.
ADD: Individual configuration pages for DSX, WCX, WDX, WFX and WLX plugins.
ADD: Plugin tweak dialog windows now remember their dimensions from a session to another.
ADD: Double-click on an item in the list of plugins in the configuration now trigs the tweak window for selected plugin.
ADD: When we just add a plugin, it is now the selected one in the list.
ADD: Add an option to go to tweak dialog window right after a plugin in added.
CHG: The path to the plugin is now *loaded*, *displayed* and *saved* as what the user sees.
CHG: The path for the plugin files may now be defined with full relative path based on either windows special folders, environment variables or full complete path. It is not simply on a path deeper than %COMMANDERPATH% like it was before.
ADD: In the plugin tweak dialog window, we now have an actual "TFileNameEdit" with a button and the file requester to select our plugin location.
ADD: In the plugin tweak dialog window, we now have a button with a popup menu to help to adapt the path of the plugin location like to make it relative to a specified location.
ADD: There is now an option to make DC automatically use relative path to what we want when we add a plugin file. We may also apply that retro-active.
ADD: In the plugin configuration, do not display a column if not pertinent (like column 2 in WFX).
ADD: In the WCX plugin configuration window, we may display plugins grouped by plugin file or by file extension as they appear in config file AND how they are actually used when searching for a qualified one.
ADD: Add the internal command "cm_ConfigPlugins".
FIX: Added WCX plugin associated with an empty extension was not displayed at first in the grid and needed to close and reopen the configuration window. This is fixed.
FIX: Adding a file extension associated with a WCX plugin in the tweaking window from a WCX where previously *just one* extension was associated was not switching enabled the "Remove" button. This is fixed.
UPD: Languages files have been modified, but efforts have been made to re-use existing translations and to avoid "fuzzy" attributes.
2018-11-03 20:17:43 +00:00

861 lines
28 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;
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(UTF8Decode(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(UTF8Decode(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;
if Assigned(FsExecuteFileW) then
begin
pwcRemoteName:= GetMem(MAX_PATH * SizeOf(WideChar));
StrPCopyW(pwcRemoteName, UTF8Decode(RemoteName));
Result:= FsExecuteFileW(MainWin, pwcRemoteName, PWideChar(UTF8Decode(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(UTF8Decode(OldName)), PWideChar(UTF8Decode(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(UTF8Decode(RemoteName)), PWideChar(UTF8Decode(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(UTF8Decode(LocalName)), PWideChar(UTF8Decode(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(UTF8Decode(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(UTF8Decode(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(UTF8Decode(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(UTF8Decode(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(UTF8Decode(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, UTF8Decode(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(UTF8Decode(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);
//------------------------------------------------------
UnloadModule;
end;
inherited;
end;
function TWFXModule.LoadModule(const sName: String): Boolean;
begin
FModuleHandle := mbLoadLibrary(mbExpandFileName(sName));
if FModuleHandle = 0 then
begin
Exit(False);
end;
FModuleFileName:= sName;
{ Mandatory }
FsInit := TFsInit(GetProcAddress(FModuleHandle,'FsInit'));
FsFindFirst := TFsFindFirst(GetProcAddress(FModuleHandle,'FsFindFirst'));
FsFindNext := TFsFindNext(GetProcAddress(FModuleHandle,'FsFindNext'));
FsFindClose := TFsFindClose(GetProcAddress(FModuleHandle,'FsFindClose'));
{ Unicode }
FsInitW := TFsInitW(GetProcAddress(FModuleHandle,'FsInitW'));
FsFindFirstW := TFsFindFirstW(GetProcAddress(FModuleHandle,'FsFindFirstW'));
FsFindNextW := TFsFindNextW(GetProcAddress(FModuleHandle,'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;
Exit(False);
end;
{ Optional }
FsSetCryptCallback:= TFsSetCryptCallback(GetProcAddress(FModuleHandle,'FsSetCryptCallback'));
FsGetDefRootName := TFsGetDefRootName(GetProcAddress(FModuleHandle,'FsGetDefRootName'));
FsExecuteFile := TFsExecuteFile(GetProcAddress(FModuleHandle,'FsExecuteFile'));
FsGetFile := TFsGetFile(GetProcAddress(FModuleHandle,'FsGetFile'));
FsPutFile := TFsPutFile(GetProcAddress(FModuleHandle,'FsPutFile'));
FsDeleteFile := TFsDeleteFile(GetProcAddress(FModuleHandle,'FsDeleteFile'));
FsMkDir := TFsMkDir(GetProcAddress(FModuleHandle,'FsMkDir'));
FsRemoveDir := TFsRemoveDir(GetProcAddress(FModuleHandle,'FsRemoveDir'));
FsStatusInfo := TFsStatusInfo(GetProcAddress(FModuleHandle,'FsStatusInfo'));
FsSetDefaultParams := TFsSetDefaultParams(GetProcAddress(FModuleHandle,'FsSetDefaultParams'));
//---------------------
FsSetAttr := TFsSetAttr (GetProcAddress(FModuleHandle,'FsSetAttr'));
FsSetTime := TFsSetTime (GetProcAddress(FModuleHandle,'FsSetTime'));
FsExtractCustomIcon := TFsExtractCustomIcon (GetProcAddress(FModuleHandle,'FsExtractCustomIcon'));
FsRenMovFile := TFsRenMovFile (GetProcAddress(FModuleHandle,'FsRenMovFile'));
FsDisconnect := TFsDisconnect (GetProcAddress(FModuleHandle,'FsDisconnect'));
FsGetPreviewBitmap := TFsGetPreviewBitmap (GetProcAddress(FModuleHandle,'FsGetPreviewBitmap'));
FsLinksToLocalFiles := TFsLinksToLocalFiles (GetProcAddress(FModuleHandle,'FsLinksToLocalFiles'));
FsGetLocalName := TFsGetLocalName (GetProcAddress(FModuleHandle,'FsGetLocalName'));
//---------------------
FsGetBackgroundFlags := TFsGetBackgroundFlags (GetProcAddress(FModuleHandle,'FsGetBackgroundFlags'));
//---------------------
FsContentGetDefaultView := TFsContentGetDefaultView (GetProcAddress(FModuleHandle,'FsContentGetDefaultView'));
ContentSetDefaultParams := TContentSetDefaultParams (GetProcAddress(FModuleHandle,'FsContentSetDefaultParams'));
ContentGetDetectString := TFsContentGetDetectString (GetProcAddress(FModuleHandle,'FsContentGetDetectString'));
ContentGetSupportedField := TFsContentGetSupportedField (GetProcAddress(FModuleHandle,'FsContentGetSupportedField'));
ContentGetValue := TFsContentGetValue (GetProcAddress(FModuleHandle,'FsContentGetValue'));
ContentStopGetValue := TFsContentStopGetValue (GetProcAddress(FModuleHandle,'FsContentStopGetValue'));
ContentGetDefaultSortOrder := TFsContentGetDefaultSortOrder (GetProcAddress(FModuleHandle,'FsContentGetDefaultSortOrder'));
ContentGetSupportedFieldFlags := TFsContentGetSupportedFieldFlags (GetProcAddress(FModuleHandle,'FsContentGetSupportedFieldFlags'));
ContentSetValue := TFsContentSetValue (GetProcAddress(FModuleHandle,'FsContentSetValue'));
ContentPluginUnloading := TFsContentPluginUnloading(GetProcAddress(FModuleHandle,'FsContentPluginUnloading'));
{ Unicode }
FsSetCryptCallbackW:= TFsSetCryptCallbackW(GetProcAddress(FModuleHandle,'FsSetCryptCallbackW'));
FsMkDirW := TFsMkDirW(GetProcAddress(FModuleHandle,'FsMkDirW'));
FsExecuteFileW := TFsExecuteFileW(GetProcAddress(FModuleHandle,'FsExecuteFileW'));
FsRenMovFileW := TFsRenMovFileW(GetProcAddress(FModuleHandle,'FsRenMovFileW'));
FsGetFileW := TFsGetFileW(GetProcAddress(FModuleHandle,'FsGetFileW'));
FsPutFileW := TFsPutFileW(GetProcAddress(FModuleHandle,'FsPutFileW'));
FsDeleteFileW := TFsDeleteFileW(GetProcAddress(FModuleHandle,'FsDeleteFileW'));
FsRemoveDirW := TFsRemoveDirW(GetProcAddress(FModuleHandle,'FsRemoveDirW'));
FsDisconnectW := TFsDisconnectW(GetProcAddress(FModuleHandle,'FsDisconnectW'));
FsSetAttrW := TFsSetAttrW (GetProcAddress(FModuleHandle,'FsSetAttrW'));
FsSetTimeW := TFsSetTimeW (GetProcAddress(FModuleHandle,'FsSetTimeW'));
FsStatusInfoW := TFsStatusInfoW(GetProcAddress(FModuleHandle,'FsStatusInfoW'));
FsExtractCustomIconW := TFsExtractCustomIconW(GetProcAddress(FModuleHandle,'FsExtractCustomIconW'));
FsGetLocalNameW := TFsGetLocalNameW(GetProcAddress(FModuleHandle,'FsGetLocalNameW'));
//--------------------------
FsContentGetDefaultViewW := TFsContentGetDefaultViewW(GetProcAddress(FModuleHandle,'FsContentGetDefaultViewW'));
ContentGetValueW := TFsContentGetValueW(GetProcAddress(FModuleHandle, 'FsContentGetValueW'));
ContentStopGetValueW := TFsContentStopGetValueW(GetProcAddress(FModuleHandle, 'FsContentStopGetValueW'));
ContentSetValueW := TFsContentSetValueW(GetProcAddress(FModuleHandle, 'FsContentSetValueW'));
{ Extension API }
ExtensionInitialize:= TExtensionInitializeProc(GetProcAddress(FModuleHandle,'ExtensionInitialize'));
ExtensionFinalize:= TExtensionFinalizeProc(GetProcAddress(FModuleHandle,'ExtensionFinalize'));
VFSInit;
end;
procedure TWFXModule.UnloadModule;
begin
{$IF (not DEFINED(LINUX)) or ((FPC_VERSION > 2) or ((FPC_VERSION=2) and (FPC_RELEASE >= 5)))}
if FModuleHandle <> 0 then
FreeLibrary(FModuleHandle);
{$ENDIF}
FModuleHandle := 0;
{ 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;
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(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.