{ 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 . } 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.