From a061f0a81f6b3d86b59013221315fabd9e83c14e Mon Sep 17 00:00:00 2001 From: DarkCoderSc Date: Mon, 29 Sep 2025 15:05:18 +0200 Subject: [PATCH 1/6] Progress day: 29 Sept 2025 : Start Working on Registry Manager --- Client/Client_OpenSSL.dpr | 4 +- Client/Client_OpenSSL.dproj | 16 +- Server/OptixGate_OpenSSL.dpr | 3 +- Server/OptixGate_OpenSSL.dproj | 20 +- .../Forms/Control/uControlFormFileManager.dfm | 8 +- .../Control/uControlFormRegistryManager.dfm | 143 +++++++++++ .../Control/uControlFormRegistryManager.pas | 179 +++++++++++++ Server/Units/Forms/uFormMain.dfm | 3 + Server/Units/Forms/uFormMain.pas | 26 +- .../Optix.Func.Commands.Registry.pas | 76 ++++++ Shared/Optix.FileSystem.Helper.pas | 88 +++---- Shared/Optix.Protocol.Preflight.pas | 2 +- Shared/Optix.Registry.Helper.pas | 240 ++++++++++++++++++ Shared/Optix.System.Helper.pas | 48 +++- 14 files changed, 784 insertions(+), 72 deletions(-) create mode 100644 Server/Units/Forms/Control/uControlFormRegistryManager.dfm create mode 100644 Server/Units/Forms/Control/uControlFormRegistryManager.pas create mode 100644 Shared/Functions/Optix.Func.Commands.Registry.pas create mode 100644 Shared/Optix.Registry.Helper.pas diff --git a/Client/Client_OpenSSL.dpr b/Client/Client_OpenSSL.dpr index f45c5e4..8077f6e 100644 --- a/Client/Client_OpenSSL.dpr +++ b/Client/Client_OpenSSL.dpr @@ -95,7 +95,9 @@ uses Optix.ClassesRegistry in '..\Shared\Optix.ClassesRegistry.pas', Optix.Func.Commands.FileSystem in '..\Shared\Functions\Optix.Func.Commands.FileSystem.pas', Optix.Func.Commands.Process in '..\Shared\Functions\Optix.Func.Commands.Process.pas', - Optix.Func.Commands.Shell in '..\Shared\Functions\Optix.Func.Commands.Shell.pas'; + Optix.Func.Commands.Shell in '..\Shared\Functions\Optix.Func.Commands.Shell.pas', + Optix.Func.Commands.Registry in '..\Shared\Functions\Optix.Func.Commands.Registry.pas', + Optix.Registry.Helper in '..\Shared\Optix.Registry.Helper.pas'; begin IsMultiThread := True; diff --git a/Client/Client_OpenSSL.dproj b/Client/Client_OpenSSL.dproj index 631eb4f..cffa328 100644 --- a/Client/Client_OpenSSL.dproj +++ b/Client/Client_OpenSSL.dproj @@ -4,7 +4,7 @@ 20.3 None True - Release + Debug Win64 Client_OpenSSL 3 @@ -177,6 +177,8 @@ + + Base @@ -220,7 +222,19 @@ + + + Client_OpenSSL.exe + true + + + + + Client_OpenSSL.rsm + true + + 1 diff --git a/Server/OptixGate_OpenSSL.dpr b/Server/OptixGate_OpenSSL.dpr index 311ec9d..5424e87 100644 --- a/Server/OptixGate_OpenSSL.dpr +++ b/Server/OptixGate_OpenSSL.dpr @@ -113,7 +113,8 @@ uses Optix.ClassesRegistry in '..\Shared\Optix.ClassesRegistry.pas', Optix.Func.Commands.FileSystem in '..\Shared\Functions\Optix.Func.Commands.FileSystem.pas', Optix.Func.Commands.Process in '..\Shared\Functions\Optix.Func.Commands.Process.pas', - Optix.Func.Commands.Shell in '..\Shared\Functions\Optix.Func.Commands.Shell.pas'; + Optix.Func.Commands.Shell in '..\Shared\Functions\Optix.Func.Commands.Shell.pas', + uControlFormRegistryManager in 'Units\Forms\Control\uControlFormRegistryManager.pas' {ControlFormRegistryManager}; {$R *.res} {$R data.res} diff --git a/Server/OptixGate_OpenSSL.dproj b/Server/OptixGate_OpenSSL.dproj index 38c1368..8693a88 100644 --- a/Server/OptixGate_OpenSSL.dproj +++ b/Server/OptixGate_OpenSSL.dproj @@ -4,7 +4,7 @@ 20.3 VCL True - Release + Debug Win32 OptixGate_OpenSSL 3 @@ -251,6 +251,10 @@ + +
ControlFormRegistryManager
+ dfm +
Base @@ -279,10 +283,20 @@ - - + + + .\ + true + + + + + OptixGate_OpenSSL.exe + true + + diff --git a/Server/Units/Forms/Control/uControlFormFileManager.dfm b/Server/Units/Forms/Control/uControlFormFileManager.dfm index 61dc3e7..2d57a57 100644 --- a/Server/Units/Forms/Control/uControlFormFileManager.dfm +++ b/Server/Units/Forms/Control/uControlFormFileManager.dfm @@ -26,6 +26,7 @@ object ControlFormFileManager: TControlFormFileManager Align = alTop ReadOnly = True TabOrder = 0 + ExplicitWidth = 638 end object PanelActions: TPanel AlignWithMargins = True @@ -40,6 +41,7 @@ object ControlFormFileManager: TControlFormFileManager Align = alTop BevelOuter = bvNone TabOrder = 1 + ExplicitWidth = 638 object ButtonHome: TSpeedButton AlignWithMargins = True Left = 0 @@ -117,7 +119,7 @@ object ControlFormFileManager: TControlFormFileManager Left = 619 Top = 10 Width = 21 - Height = 15 + Height = 20 Margins.Left = 8 Margins.Top = 10 Margins.Right = 8 @@ -131,6 +133,7 @@ object ControlFormFileManager: TControlFormFileManager Font.Style = [] ParentFont = False Visible = False + ExplicitHeight = 15 end object ButtonBack: TSpeedButton AlignWithMargins = True @@ -204,7 +207,8 @@ object ControlFormFileManager: TControlFormFileManager MinPosition = 0.020000000000000000 Align = alClient TabOrder = 2 - ExplicitWidth = 666 + ExplicitWidth = 646 + ExplicitHeight = 348 DesignSize = ( 656 380) diff --git a/Server/Units/Forms/Control/uControlFormRegistryManager.dfm b/Server/Units/Forms/Control/uControlFormRegistryManager.dfm new file mode 100644 index 0000000..18a5a73 --- /dev/null +++ b/Server/Units/Forms/Control/uControlFormRegistryManager.dfm @@ -0,0 +1,143 @@ +object ControlFormRegistryManager: TControlFormRegistryManager + Left = 0 + Top = 0 + Caption = 'Registry Manager' + ClientHeight = 431 + ClientWidth = 711 + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -12 + Font.Name = 'Segoe UI' + Font.Style = [] + Position = poOwnerFormCenter + OnCreate = FormCreate + TextHeight = 15 + object OMultiPanel: TOMultiPanel + Left = 0 + Top = 31 + Width = 711 + Height = 400 + PanelCollection = < + item + Control = VSTKeys + Position = 0.333333333333333300 + Visible = True + Index = 0 + end + item + Control = VSTValues + Position = 1.000000000000000000 + Visible = True + Index = 1 + end> + MinPosition = 0.020000000000000000 + Align = alClient + TabOrder = 0 + ExplicitTop = 0 + ExplicitWidth = 701 + ExplicitHeight = 399 + DesignSize = ( + 711 + 400) + object VSTKeys: TVirtualStringTree + Left = 0 + Top = 0 + Width = 237 + Height = 400 + Margins.Left = 2 + Margins.Top = 2 + Margins.Right = 2 + Margins.Bottom = 2 + Anchors = [] + BackGroundImageTransparent = True + BorderStyle = bsNone + Color = clWhite + Colors.UnfocusedColor = clWindowText + DefaultNodeHeight = 19 + Header.AutoSizeIndex = 0 + Header.DefaultHeight = 25 + Header.Options = [hoAutoResize, hoColumnResize, hoDrag, hoShowSortGlyphs, hoHeaderClickAutoSort] + Header.SortColumn = 0 + Images = FormMain.ImageSystem + StateImages = FormMain.VirtualImageList + TabOrder = 0 + TreeOptions.PaintOptions = [toHideFocusRect, toShowButtons, toShowDropmark, toShowRoot, toShowTreeLines, toShowVertGridLines, toThemeAware, toUseBlendedImages, toFullVertGridLines] + TreeOptions.SelectionOptions = [toFullRowSelect, toRightClickSelect, toSelectNextNodeOnRemoval] + OnChange = VSTKeysChange + OnFocusChanged = VSTKeysFocusChanged + OnGetText = VSTKeysGetText + OnGetImageIndex = VSTKeysGetImageIndex + OnGetNodeDataSize = VSTKeysGetNodeDataSize + Touch.InteractiveGestures = [igPan, igPressAndTap] + Touch.InteractiveGestureOptions = [igoPanSingleFingerHorizontal, igoPanSingleFingerVertical, igoPanInertia, igoPanGutter, igoParentPassthrough] + Columns = < + item + Position = 0 + Text = 'Name' + Width = 237 + end> + end + object VSTValues: TVirtualStringTree + Left = 240 + Top = 0 + Width = 471 + Height = 400 + Margins.Left = 2 + Margins.Top = 2 + Margins.Right = 2 + Margins.Bottom = 2 + Anchors = [] + BackGroundImageTransparent = True + BorderStyle = bsNone + Color = clWhite + Colors.UnfocusedColor = clWindowText + DefaultNodeHeight = 19 + Header.AutoSizeIndex = -1 + Header.DefaultHeight = 25 + Header.Options = [hoColumnResize, hoDrag, hoShowSortGlyphs, hoVisible, hoHeaderClickAutoSort] + Header.SortColumn = 0 + Images = FormMain.ImageSystem + StateImages = FormMain.VirtualImageList + TabOrder = 1 + TreeOptions.PaintOptions = [toHideFocusRect, toShowButtons, toShowDropmark, toShowTreeLines, toShowVertGridLines, toThemeAware, toUseBlendedImages, toFullVertGridLines] + TreeOptions.SelectionOptions = [toFullRowSelect, toRightClickSelect, toSelectNextNodeOnRemoval] + Touch.InteractiveGestures = [igPan, igPressAndTap] + Touch.InteractiveGestureOptions = [igoPanSingleFingerHorizontal, igoPanSingleFingerVertical, igoPanInertia, igoPanGutter, igoParentPassthrough] + Columns = < + item + Position = 0 + Text = 'Name' + Width = 150 + end + item + Position = 1 + Text = 'Type' + Width = 120 + end + item + Position = 2 + Text = 'Data' + Width = 200 + end> + end + end + object EditPath: TEdit + AlignWithMargins = True + Left = 4 + Top = 4 + Width = 703 + Height = 23 + Margins.Left = 4 + Margins.Top = 4 + Margins.Right = 4 + Margins.Bottom = 4 + Align = alTop + BevelOuter = bvRaised + ReadOnly = True + TabOrder = 1 + ExplicitLeft = -2 + ExplicitTop = 8 + ExplicitWidth = 705 + end +end diff --git a/Server/Units/Forms/Control/uControlFormRegistryManager.pas b/Server/Units/Forms/Control/uControlFormRegistryManager.pas new file mode 100644 index 0000000..865da8e --- /dev/null +++ b/Server/Units/Forms/Control/uControlFormRegistryManager.pas @@ -0,0 +1,179 @@ +{******************************************************************************} +{ } +{ ____ _ ____ _ ____ } +{ | _ \ __ _ _ __| | __/ ___|___ __| | ___ _ __/ ___| ___ } +{ | | | |/ _` | '__| |/ / | / _ \ / _` |/ _ \ '__\___ \ / __| } +{ | |_| | (_| | | | <| |__| (_) | (_| | __/ | ___) | (__ } +{ |____/ \__,_|_| |_|\_\\____\___/ \__,_|\___|_| |____/ \___| } +{ Project: Optix Gate } +{ } +{ } +{ Author: DarkCoderSc (Jean-Pierre LESUEUR) } +{ https://www.twitter.com/darkcodersc } +{ https://bsky.app/profile/darkcodersc.bsky.social } +{ https://github.com/darkcodersc } +{ License: GPL v3 } +{ } +{ } +{ } +{ Disclaimer: } +{ ----------- } +{ We are doing our best to prepare the content of this app and/or code. } +{ However, The author cannot warranty the expressions and suggestions } +{ of the contents, as well as its accuracy. In addition, to the extent } +{ permitted by the law, author shall not be responsible for any losses } +{ and/or damages due to the usage of the information on our app and/or } +{ code. } +{ } +{ By using our app and/or code, you hereby consent to our disclaimer } +{ and agree to its terms. } +{ } +{ Any links contained in our app may lead to external sites are provided } +{ for convenience only. } +{ Any information or statements that appeared in these sites or app or } +{ files are not sponsored, endorsed, or otherwise approved by the author. } +{ For these external sites, the author cannot be held liable for the } +{ availability of, or the content located on or through it. } +{ Plus, any losses or damages occurred from using these contents or the } +{ internet generally. } +{ } +{ } +{ } +{******************************************************************************} + +unit uControlFormRegistryManager; + +interface + +// --------------------------------------------------------------------------------------------------------------------- +uses + System.SysUtils, System.Variants, System.Classes, + + Winapi.Windows, Winapi.Messages, + + Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, + + VirtualTrees.AncestorVCL, VirtualTrees, VirtualTrees.BaseAncestorVCL, VirtualTrees.BaseTree, VirtualTrees.Types, + OMultiPanel, + + __uBaseFormControl__, Vcl.StdCtrls; +// --------------------------------------------------------------------------------------------------------------------- + +type + TKeysTreeData = record + Name : String; + Path : String; + ImageIndex : Integer; + end; + PKeysTreeData = ^TKeysTreeData; + + TControlFormRegistryManager = class(TBaseFormControl) + OMultiPanel: TOMultiPanel; + VSTKeys: TVirtualStringTree; + VSTValues: TVirtualStringTree; + EditPath: TEdit; + procedure VSTKeysGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer); + procedure VSTKeysGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; + var CellText: string); + procedure VSTKeysFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex); + procedure VSTKeysChange(Sender: TBaseVirtualTree; Node: PVirtualNode); + procedure FormCreate(Sender: TObject); + procedure VSTKeysGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; + Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: TImageIndex); + private + {@M} + procedure InsertKey(const AKeyName : String; const AKeyPath : String = ''); + procedure BrowsePath(const ARegistryHive : HKEY; const AKeyPath : String); + public + { Public declarations } + end; + +var + ControlFormRegistryManager: TControlFormRegistryManager; + +implementation + +// --------------------------------------------------------------------------------------------------------------------- +uses + uFormMain, + + Optix.Helper; +// --------------------------------------------------------------------------------------------------------------------- + +{$R *.dfm} + +procedure TControlFormRegistryManager.BrowsePath(const ARegistryHive : HKEY; const AKeyPath : String); +begin + /// +end; + +procedure TControlFormRegistryManager.FormCreate(Sender: TObject); +begin + // TODO: Receive them from remote probing for permission + InsertKey('HKEY_CLASSES_ROOT'); + InsertKey('HKEY_CURRENT_USER'); + InsertKey('HKEY_LOCAL_MACHINE'); + InsertKey('HKEY_USERS'); + InsertKey('HKEY_PERFORMANCE_DATA'); + InsertKey('HKEY_CURRENT_CONFIG'); + InsertKey('HKEY_DYN_DATA'); +end; + +procedure TControlFormRegistryManager.InsertKey(const AKeyName : String; const AKeyPath : String = ''); +begin + VSTKeys.BeginUpdate(); + try + var pNode := VSTKeys.AddChild(nil); + var pData := PKeysTreeData(pNode.GetData); + + pData^.Name := AKeyName; + pData^.Path := AKeyPath; + pData^.ImageIndex := SystemFolderIcon(); + finally + VSTKeys.EndUpdate(); + end; +end; + +procedure TControlFormRegistryManager.VSTKeysChange(Sender: TBaseVirtualTree; Node: PVirtualNode); +begin + TVirtualStringTree(Sender).Refresh(); +end; + +procedure TControlFormRegistryManager.VSTKeysFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; + Column: TColumnIndex); +begin + TVirtualStringTree(Sender).Refresh(); +end; + +procedure TControlFormRegistryManager.VSTKeysGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; + Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: TImageIndex); +begin + if (Column <> 0) or ((Kind <> ikNormal) and (Kind <> ikSelected)) then + Exit(); + /// + + var pData := PKeysTreeData(Node.GetData); + if not Assigned(pData) then + Exit(); + /// + + ImageIndex := pData^.ImageIndex; +end; + +procedure TControlFormRegistryManager.VSTKeysGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer); +begin + NodeDataSize := SizeOf(TKeysTreeData); +end; + +procedure TControlFormRegistryManager.VSTKeysGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; + TextType: TVSTTextType; var CellText: string); +begin + var pData := PKeysTreeData(Node.GetData); + if not Assigned(pData) or (Column <> 0) then + Exit(); + /// + + CellText := pData^.Name; +end; + +end. diff --git a/Server/Units/Forms/uFormMain.dfm b/Server/Units/Forms/uFormMain.dfm index 9b6807d..2b1f83c 100644 --- a/Server/Units/Forms/uFormMain.dfm +++ b/Server/Units/Forms/uFormMain.dfm @@ -52,6 +52,8 @@ object FormMain: TFormMain OnMouseDown = VSTMouseDown Touch.InteractiveGestures = [igPan, igPressAndTap] Touch.InteractiveGestureOptions = [igoPanSingleFingerHorizontal, igoPanSingleFingerVertical, igoPanInertia, igoPanGutter, igoParentPassthrough] + ExplicitLeft = -7 + ExplicitTop = -7 Columns = < item Position = 0 @@ -162,6 +164,7 @@ object FormMain: TFormMain end object RegistryManager1: TMenuItem Caption = 'Registry Manager' + OnClick = RegistryManager1Click end object RegistrySearch1: TMenuItem Caption = 'Registry Search' diff --git a/Server/Units/Forms/uFormMain.pas b/Server/Units/Forms/uFormMain.pas index acafd8d..4420ae0 100644 --- a/Server/Units/Forms/uFormMain.pas +++ b/Server/Units/Forms/uFormMain.pas @@ -150,6 +150,7 @@ TFormMain = class(TForm) procedure Server1Click(Sender: TObject); procedure VSTMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure FormDestroy(Sender: TObject); + procedure RegistryManager1Click(Sender: TObject); private FFileInfo : TSHFileInfo; @@ -187,7 +188,8 @@ implementation System.DateUtils, System.Rtti, uControlFormProcessManager, uControlFormLogs, uFormAbout, uControlFormTransfers, uControlFormControlForms, - uControlFormFileManager, uFormDebugThreads, uControlFormTasks, uControlFormRemoteShell, uFormListen, uFormServers + uControlFormFileManager, uFormDebugThreads, uControlFormTasks, uControlFormRemoteShell, uFormListen, uFormServers, + uControlFormRegistryManager {$IFDEF USETLS}, uFormCertificatesStore, uFormTrustedCertificates{$ENDIF}, Optix.Protocol.Packet, Optix.Helper, Optix.VCL.Helper, Optix.Constants, Optix.Process.Helper, @@ -477,6 +479,11 @@ procedure TFormMain.RegisterSession(const AHandler : TOptixSessionHandlerThread; end; end; +procedure TFormMain.RegistryManager1Click(Sender: TObject); +begin + CreateNewControlForm(VST.FocusedNode, TControlFormRegistryManager); +end; + procedure TFormMain.RemoteShell1Click(Sender: TObject); begin CreateNewControlForm(VST.FocusedNode, TControlFormRemoteShell); @@ -682,14 +689,15 @@ procedure TFormMain.PopupMenuPopup(Sender: TObject); var AVisible := VST.FocusedNode <> nil; - erminate1.Visible := AVisible; - ProcessManager1.Visible := AVisible; - Logs1.Visible := AVisible; - FileManager1.Visible := AVisible; - ControlForms1.Visible := AVisible; - transfers1.Visible := AVisible; - asks1.Visible := AVisible; - RemoteShell1.Visible := AVisible; + erminate1.Visible := AVisible; + ProcessManager1.Visible := AVisible; + Logs1.Visible := AVisible; + FileManager1.Visible := AVisible; + ControlForms1.Visible := AVisible; + transfers1.Visible := AVisible; + asks1.Visible := AVisible; + RemoteShell1.Visible := AVisible; + RegistryManager1.Visible := AVisible; end; procedure TFormMain.ProcessManager1Click(Sender: TObject); diff --git a/Shared/Functions/Optix.Func.Commands.Registry.pas b/Shared/Functions/Optix.Func.Commands.Registry.pas new file mode 100644 index 0000000..f842e3d --- /dev/null +++ b/Shared/Functions/Optix.Func.Commands.Registry.pas @@ -0,0 +1,76 @@ +{******************************************************************************} +{ } +{ ____ _ ____ _ ____ } +{ | _ \ __ _ _ __| | __/ ___|___ __| | ___ _ __/ ___| ___ } +{ | | | |/ _` | '__| |/ / | / _ \ / _` |/ _ \ '__\___ \ / __| } +{ | |_| | (_| | | | <| |__| (_) | (_| | __/ | ___) | (__ } +{ |____/ \__,_|_| |_|\_\\____\___/ \__,_|\___|_| |____/ \___| } +{ Project: Optix Gate } +{ } +{ } +{ Author: DarkCoderSc (Jean-Pierre LESUEUR) } +{ https://www.twitter.com/darkcodersc } +{ https://bsky.app/profile/darkcodersc.bsky.social } +{ https://github.com/darkcodersc } +{ License: GPL v3 } +{ } +{ } +{ } +{ Disclaimer: } +{ ----------- } +{ We are doing our best to prepare the content of this app and/or code. } +{ However, The author cannot warranty the expressions and suggestions } +{ of the contents, as well as its accuracy. In addition, to the extent } +{ permitted by the law, author shall not be responsible for any losses } +{ and/or damages due to the usage of the information on our app and/or } +{ code. } +{ } +{ By using our app and/or code, you hereby consent to our disclaimer } +{ and agree to its terms. } +{ } +{ Any links contained in our app may lead to external sites are provided } +{ for convenience only. } +{ Any information or statements that appeared in these sites or app or } +{ files are not sponsored, endorsed, or otherwise approved by the author. } +{ For these external sites, the author cannot be held liable for the } +{ availability of, or the content located on or through it. } +{ Plus, any losses or damages occurred from using these contents or the } +{ internet generally. } +{ } +{ } +{ } +{******************************************************************************} + +unit Optix.Func.Commands.Registry; + +interface + +// --------------------------------------------------------------------------------------------------------------------- +uses + System.Classes, System.SysUtils, + + Optix.Shared.Classes, Optix.Func.Commands.Base; +// --------------------------------------------------------------------------------------------------------------------- + +type + TOptixGetRegistryHives = class(TOptixCommandActionResponse) + public + {@M} + procedure DoAction(); override; + end; + +implementation + +(*********************************************************************************************************************** + + TOptixGetRegistryHives + +***********************************************************************************************************************) + +{ TOptixGetRegistryHives.DoAction } +procedure TOptixGetRegistryHives.DoAction(); +begin + /// +end; + +end. diff --git a/Shared/Optix.FileSystem.Helper.pas b/Shared/Optix.FileSystem.Helper.pas index 721cfae..17b05e1 100644 --- a/Shared/Optix.FileSystem.Helper.pas +++ b/Shared/Optix.FileSystem.Helper.pas @@ -45,7 +45,10 @@ interface -uses System.Classes; +// --------------------------------------------------------------------------------------------------------------------- +uses + System.Classes; +// --------------------------------------------------------------------------------------------------------------------- type TDriveType = ( @@ -67,8 +70,10 @@ interface TFileSystemHelper = class public - class function GetDriveInformation(ADriveLetter : String; var AName : String; var AFormat : String; var ADriveType : TDriveType) : Boolean; static; - class function TryGetDriveInformation(ADriveLetter : String; var AName : String; var AFormat : String; var ADriveType : TDriveType) : Boolean; static; + class function GetDriveInformation(ADriveLetter : String; var AName : String; var AFormat : String; + var ADriveType : TDriveType) : Boolean; static; + class function TryGetDriveInformation(ADriveLetter : String; var AName : String; var AFormat : String; + var ADriveType : TDriveType) : Boolean; static; class function GetFileACLString(const AFileName : String) : String; static; class function TryGetFileACLString(const AFileName : String) : String; static; class procedure GetCurrentUserFileAccess(const AFileName : String; var ARead, AWrite, AExecute : Boolean); overload; static; @@ -91,8 +96,14 @@ TFileSystemHelper = class implementation -uses System.SysUtils, Winapi.AccCtrl, Winapi.AclAPI, Winapi.Windows, Optix.Exceptions, Optix.WinApiEx, Winapi.ShellAPI, - Optix.System.Helper, System.IOUtils, System.StrUtils; +// --------------------------------------------------------------------------------------------------------------------- +uses + System.SysUtils, System.IOUtils, System.StrUtils, + + Winapi.AccCtrl, Winapi.AclAPI, Winapi.Windows, Winapi.ShellAPI, + + Optix.Exceptions, Optix.WinApiEx, Optix.System.Helper; +// --------------------------------------------------------------------------------------------------------------------- (* Local *) @@ -155,7 +166,8 @@ function AccessSetToReadableString(const AValue : TFileAccessAttributes) : Strin (* TFileSystemHelper *) { TFileSystemHelper.GetDriveInformation } -class function TFileSystemHelper.GetDriveInformation(ADriveLetter : String; var AName : String; var AFormat : String; var ADriveType : TDriveType) : Boolean; +class function TFileSystemHelper.GetDriveInformation(ADriveLetter : String; var AName : String; var AFormat : String; + var ADriveType : TDriveType) : Boolean; begin var AOldErrorMode := SetErrorMode(SEM_FAILCRITICALERRORS); try @@ -205,7 +217,8 @@ class function TFileSystemHelper.GetDriveInformation(ADriveLetter : String; var end; { TFileSystemHelper.TryGetDriveInformation } -class function TFileSystemHelper.TryGetDriveInformation(ADriveLetter : String; var AName : String; var AFormat : String; var ADriveType : TDriveType) : Boolean; +class function TFileSystemHelper.TryGetDriveInformation(ADriveLetter : String; var AName : String; var AFormat : String; + var ADriveType : TDriveType) : Boolean; begin AName := ''; AFormat := ''; @@ -239,7 +252,7 @@ class function TFileSystemHelper.GetFileACLString(const AFileName : String) : St @ptrSecurityDescriptor ); if AResult <> ERROR_SUCCESS then - raise EWindowsException.Create('GetNamedSecurityInfoW'); + raise EWindowsException.Create('GetNamedSecurityInfoW', AResult); if not ConvertSecurityDescriptorToStringSecurityDescriptorW( ptrSecurityDescriptor, @@ -272,47 +285,15 @@ class function TFileSystemHelper.TryGetFileACLString(const AFileName : String) : end; { TFileSystemHelper.GetCurrentUserFileAccess } -class procedure TFileSystemHelper.GetCurrentUserFileAccess(const AFileName : String; var ARead, AWrite, AExecute : Boolean); -var AMapping : TGenericMapping; - ptrSecurityDescriptor : PSecurityDescriptor; - hToken : THandle; - - function AccessCheck(ADesiredAccess : DWORD) : Boolean; - begin - MapGenericMask(ADesiredAccess, AMapping); - - var APrivilegeSet : TPrivilegeSet; - var APrivilegeSetSize := DWORD(SizeOf(TPrivilegeSet)); - - var AGrantedAccess := DWORD(0); - var AStatus : BOOL; - - if not Winapi.Windows.AccessCheck( - ptrSecurityDescriptor, - hToken, - ADesiredAccess, - AMapping, - APrivilegeSet, - APrivilegeSetSize, - AGrantedAccess, - AStatus - ) then - result := False - else - result := AStatus; - end; - +class procedure TFileSystemHelper.GetCurrentUserFileAccess(const AFileName : String; + var ARead, AWrite, AExecute : Boolean); begin var AImpersonated := False; - ptrSecurityDescriptor := nil; - hToken := 0; + var ptrSecurityDescriptor := PSecurityDescriptor(nil); + var hToken := THandle(0); /// - AMapping.GenericRead := FILE_GENERIC_READ; - AMapping.GenericWrite := FILE_GENERIC_WRITE; - AMapping.GenericExecute := FILE_GENERIC_EXECUTE; - AMapping.GenericAll := FILE_ALL_ACCESS; try AImpersonated := ImpersonateSelf(SecurityImpersonation); @@ -335,17 +316,17 @@ class procedure TFileSystemHelper.GetCurrentUserFileAccess(const AFileName : Str @ptrSecurityDescriptor ); if AResult <> ERROR_SUCCESS then - raise EWindowsException.Create('GetNamedSecurityInfoW'); + raise EWindowsException.Create('GetNamedSecurityInfoW', AResult); /// - if AccessCheck(FILE_ALL_ACCESS) then begin + if TSystemHelper.AccessCheck(FILE_ALL_ACCESS, hToken, ptrSecurityDescriptor) then begin ARead := True; AWrite := True; AExecute := True; end else begin - ARead := AccessCheck(FILE_GENERIC_READ); - AWrite := AccessCheck(FILE_GENERIC_WRITE); - AExecute := AccessCheck(FILE_GENERIC_EXECUTE); + ARead := TSystemHelper.AccessCheck(FILE_GENERIC_READ, hToken, ptrSecurityDescriptor); + AWrite := TSystemHelper.AccessCheck(FILE_GENERIC_WRITE, hToken, ptrSecurityDescriptor); + AExecute := TSystemHelper.AccessCheck(FILE_GENERIC_EXECUTE, hToken, ptrSecurityDescriptor); end; finally if Assigned(ptrSecurityDescriptor) then @@ -379,7 +360,8 @@ class function TFileSystemHelper.GetCurrentUserFileAccess(const AFileName : Stri end; { TFileSystemHelper.TryGetCurrentUserFileAccess } -class procedure TFileSystemHelper.TryGetCurrentUserFileAccess(const AFileName : String; var ARead, AWrite, AExecute : Boolean); +class procedure TFileSystemHelper.TryGetCurrentUserFileAccess(const AFileName : String; + var ARead, AWrite, AExecute : Boolean); begin try GetCurrentUserFileAccess(AFileName, ARead, AWrite, AExecute); @@ -442,7 +424,8 @@ class function TFileSystemHelper.GetFileTypeDescription(const AFileName: String) end; { TFileSystem.Helper.GetFileTime } -class procedure TFileSystemHelper.GetFileTime(const AFileName : String; var ACreate, ALastModified, ALastAccess : TDateTime); +class procedure TFileSystemHelper.GetFileTime(const AFileName : String; + var ACreate, ALastModified, ALastAccess : TDateTime); begin var hFile := CreateFileW( PWideChar(AFileName), @@ -470,7 +453,8 @@ class procedure TFileSystemHelper.GetFileTime(const AFileName : String; var ACre end; { TFileSystem.Helper.TryGetFileTime } -class function TFileSystemHelper.TryGetFileTime(const AFileName : String; var ACreate, ALastModified, ALastAccess : TDateTime) : Boolean; +class function TFileSystemHelper.TryGetFileTime(const AFileName : String; + var ACreate, ALastModified, ALastAccess : TDateTime) : Boolean; begin try GetFileTime(AFileName, ACreate, ALastModified, ALastAccess); diff --git a/Shared/Optix.Protocol.Preflight.pas b/Shared/Optix.Protocol.Preflight.pas index 33a29fb..f781246 100644 --- a/Shared/Optix.Protocol.Preflight.pas +++ b/Shared/Optix.Protocol.Preflight.pas @@ -45,7 +45,7 @@ interface -const OPTIX_PROTOCOL_VERSION = 'v1.1.0' {$IFDEF USETLS} + '+OpenSSL'{$ENDIF}; +const OPTIX_PROTOCOL_VERSION = 'v1.2.0' {$IFDEF USETLS} + '+OpenSSL'{$ENDIF}; type TClientKind = ( diff --git a/Shared/Optix.Registry.Helper.pas b/Shared/Optix.Registry.Helper.pas new file mode 100644 index 0000000..7f23d5f --- /dev/null +++ b/Shared/Optix.Registry.Helper.pas @@ -0,0 +1,240 @@ +{******************************************************************************} +{ } +{ ____ _ ____ _ ____ } +{ | _ \ __ _ _ __| | __/ ___|___ __| | ___ _ __/ ___| ___ } +{ | | | |/ _` | '__| |/ / | / _ \ / _` |/ _ \ '__\___ \ / __| } +{ | |_| | (_| | | | <| |__| (_) | (_| | __/ | ___) | (__ } +{ |____/ \__,_|_| |_|\_\\____\___/ \__,_|\___|_| |____/ \___| } +{ Project: Optix Gate } +{ } +{ } +{ Author: DarkCoderSc (Jean-Pierre LESUEUR) } +{ https://www.twitter.com/darkcodersc } +{ https://bsky.app/profile/darkcodersc.bsky.social } +{ https://github.com/darkcodersc } +{ License: GPL v3 } +{ } +{ } +{ } +{ Disclaimer: } +{ ----------- } +{ We are doing our best to prepare the content of this app and/or code. } +{ However, The author cannot warranty the expressions and suggestions } +{ of the contents, as well as its accuracy. In addition, to the extent } +{ permitted by the law, author shall not be responsible for any losses } +{ and/or damages due to the usage of the information on our app and/or } +{ code. } +{ } +{ By using our app and/or code, you hereby consent to our disclaimer } +{ and agree to its terms. } +{ } +{ Any links contained in our app may lead to external sites are provided } +{ for convenience only. } +{ Any information or statements that appeared in these sites or app or } +{ files are not sponsored, endorsed, or otherwise approved by the author. } +{ For these external sites, the author cannot be held liable for the } +{ availability of, or the content located on or through it. } +{ Plus, any losses or damages occurred from using these contents or the } +{ internet generally. } +{ } +{ } +{ } +{******************************************************************************} + +unit Optix.Registry.Helper; + +interface + +// --------------------------------------------------------------------------------------------------------------------- +uses + Winapi.Windows; +// --------------------------------------------------------------------------------------------------------------------- + +type + TRegistryKeyPermission = ( + rkpRead, + rkpWrite, + rkpExecute, + rkpQueryValue, + rkpSetValue, + rkpCreateSubKey, + rkpEnumerateSubKeys, + rkpNotify, + rkpDelete + ); + + TRegistryKeyPermissions = set of TRegistryKeyPermission; + + TRegistryHelper = class + public + class function GetRegistryACLString(const AHive : HKEY; const AKeyPath : String = '') : String; + class function TryGetFileACLString(const AHive : HKEY; const AKeyPath : String) : String; + class procedure GetCurrentUserRegistryKeyAccess(const AHive : HKEY; const AKeyPath : String; + var ARegistryKeyPermissions : TRegistryKeyPermissions); + class procedure TryGetCurrentUserRegistryKeyAccess(const AHive : HKEY; const AKeyPath : String; + var ARegistryKeyPermissions : TRegistryKeyPermissions); + end; + +implementation + +// --------------------------------------------------------------------------------------------------------------------- +uses + Optix.Exceptions, Optix.WinApiEx, Optix.System.Helper; +// --------------------------------------------------------------------------------------------------------------------- + +{ TRegistryHelper.GetRegistryACLString } +class function TRegistryHelper.GetRegistryACLString(const AHive : HKEY; const AKeyPath : String = '') : String; +begin + var ASecurityDescriptorSize := DWORD(0); + + var ptrSecurityDescriptor := PSecurityDescriptor(nil); + var hToken := THandle(0); + /// + + var AKeyHandle := HKEY(0); + try + var AResult := RegOpenKeyExW(AHive, PWideChar(AKeyPath), 0, READ_CONTROL, AKeyHandle); + if AResult <> ERROR_SUCCESS then + raise EWindowsException.Create('RegOpenKeyW', AResult); + /// + + var AFlags := OWNER_SECURITY_INFORMATION or GROUP_SECURITY_INFORMATION or DACL_SECURITY_INFORMATION; + + AResult := RegGetKeySecurity(AKeyHandle, AFlags, nil, ASecurityDescriptorSize); + if (AResult <> ERROR_SUCCESS) and (AResult <> 122) then + raise EWindowsException.Create('GetNamedSecurityInfoW', AResult); + + GetMem(ptrSecurityDescriptor, ASecurityDescriptorSize); + + AResult := RegGetKeySecurity(AKeyHandle, AFlags, ptrSecurityDescriptor, ASecurityDescriptorSize); + if AResult <> ERROR_SUCCESS then + raise EWindowsException.Create('GetNamedSecurityInfoW', AResult); + + var pSSDL : LPWSTR := nil; + if not ConvertSecurityDescriptorToStringSecurityDescriptorW( + ptrSecurityDescriptor, + SDDL_REVISION_1, + AFlags, + pSSDL, + nil + ) then + raise EWindowsException.Create('ConvertSecurityDescriptorToStringSecurityDescriptorW'); + + /// + result := string(pSSDL); + finally + if AKeyHandle <> 0 then + RegCloseKey(AKeyHandle); + + if Assigned(ptrSecurityDescriptor) then + FreeMem(ptrSecurityDescriptor, ASecurityDescriptorSize); + + if hToken <> 0 then + CloseHandle(hToken); + end; +end; + +{ TRegistryHelper.TryGetFileACLString } +class function TRegistryHelper.TryGetFileACLString(const AHive : HKEY; const AKeyPath : String) : String; +begin + try + result := GetRegistryACLString(AHive, AKeyPath); + except + result := ''; + end; +end; + +{ TRegistryHelper.GetCurrentUserRegistryKeyAccess } +class procedure TRegistryHelper.GetCurrentUserRegistryKeyAccess(const AHive : HKEY; const AKeyPath : String; + var ARegistryKeyPermissions : TRegistryKeyPermissions); +begin + ARegistryKeyPermissions := []; + /// + + var AImpersonated := False; + + var ASecurityDescriptorSize := DWORD(0); + + var ptrSecurityDescriptor := PSecurityDescriptor(nil); + var hToken := THandle(0); + /// + + var AKeyHandle := HKEY(0); + try + var AResult := RegOpenKeyExW(AHive, PWideChar(AKeyPath), 0, READ_CONTROL, AKeyHandle); + if AResult <> ERROR_SUCCESS then + raise EWindowsException.Create('RegOpenKeyW', AResult); + /// + + AImpersonated := ImpersonateSelf(SecurityImpersonation); + + if not OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, False, hToken) then + raise EWindowsException.Create('OpenProcessToken'); + /// + + var AFlags := OWNER_SECURITY_INFORMATION or GROUP_SECURITY_INFORMATION or DACL_SECURITY_INFORMATION; + + AResult := RegGetKeySecurity(AKeyHandle, AFlags, nil, ASecurityDescriptorSize); + if (AResult <> ERROR_SUCCESS) and (AResult <> 122) then + raise EWindowsException.Create('GetNamedSecurityInfoW', AResult); + + GetMem(ptrSecurityDescriptor, ASecurityDescriptorSize); + + AResult := RegGetKeySecurity(AKeyHandle, AFlags, ptrSecurityDescriptor, ASecurityDescriptorSize); + if AResult <> ERROR_SUCCESS then + raise EWindowsException.Create('GetNamedSecurityInfoW', AResult); + + /// + if TSystemHelper.AccessCheck(KEY_READ, hToken, ptrSecurityDescriptor) then + Include(ARegistryKeyPermissions, rkpRead); + + if TSystemHelper.AccessCheck(KEY_WRITE, hToken, ptrSecurityDescriptor) then + Include(ARegistryKeyPermissions, rkpWrite); + + if TSystemHelper.AccessCheck(KEY_EXECUTE, hToken, ptrSecurityDescriptor) then + Include(ARegistryKeyPermissions, rkpExecute); + + if TSystemHelper.AccessCheck(KEY_QUERY_VALUE, hToken, ptrSecurityDescriptor) then + Include(ARegistryKeyPermissions, rkpQueryValue); + + if TSystemHelper.AccessCheck(KEY_SET_VALUE, hToken, ptrSecurityDescriptor) then + Include(ARegistryKeyPermissions, rkpSetValue); + + if TSystemHelper.AccessCheck(KEY_CREATE_SUB_KEY, hToken, ptrSecurityDescriptor) then + Include(ARegistryKeyPermissions, rkpCreateSubKey); + + if TSystemHelper.AccessCheck(KEY_ENUMERATE_SUB_KEYS, hToken, ptrSecurityDescriptor) then + Include(ARegistryKeyPermissions, rkpEnumerateSubKeys); + + if TSystemHelper.AccessCheck(KEY_NOTIFY, hToken, ptrSecurityDescriptor) then + Include(ARegistryKeyPermissions, rkpNotify); + + if TSystemHelper.AccessCheck(_DELETE, hToken, ptrSecurityDescriptor) then + Include(ARegistryKeyPermissions, rkpDelete); + finally + if AKeyHandle <> 0 then + RegCloseKey(AKeyHandle); + + if Assigned(ptrSecurityDescriptor) then + FreeMem(ptrSecurityDescriptor, ASecurityDescriptorSize); + + if hToken <> 0 then + CloseHandle(hToken); + + if AImpersonated then + RevertToSelf(); + end; +end; + +{ TRegistryHelper.TryGetCurrentUserRegistryKeyAccess } +class procedure TRegistryHelper.TryGetCurrentUserRegistryKeyAccess(const AHive : HKEY; const AKeyPath : String; + var ARegistryKeyPermissions : TRegistryKeyPermissions); +begin + try + GetCurrentUserRegistryKeyAccess(AHive, AKeyPath, ARegistryKeyPermissions); + except + ARegistryKeyPermissions := []; + end; +end; + +end. diff --git a/Shared/Optix.System.Helper.pas b/Shared/Optix.System.Helper.pas index 444f972..86eb63c 100644 --- a/Shared/Optix.System.Helper.pas +++ b/Shared/Optix.System.Helper.pas @@ -45,7 +45,10 @@ interface -uses Winapi.Windows; +// --------------------------------------------------------------------------------------------------------------------- +uses + Winapi.Windows; +// --------------------------------------------------------------------------------------------------------------------- type TSystemHelper = class @@ -55,11 +58,18 @@ TSystemHelper = class class function TryFileTimeToDateTime(const AFileTime: TFileTime) : TDateTime; static; class procedure NTSetPrivilege(const APrivilegeName: string; const AEnabled: Boolean); class procedure TryNTSetPrivilege(const APrivilegeName: string; const AEnabled: Boolean); + class function AccessCheck(ADesiredAccess : DWORD; const hToken : THandle; + const ptrSecurityDescriptor : PSecurityDescriptor) : Boolean; end; implementation -uses Optix.Exceptions, System.SysUtils; +// --------------------------------------------------------------------------------------------------------------------- +uses + System.SysUtils, + + Optix.Exceptions; +// --------------------------------------------------------------------------------------------------------------------- { TSystemHelper.NTSetPrivilege } class procedure TSystemHelper.NTSetPrivilege(const APrivilegeName: string; const AEnabled: Boolean); @@ -130,4 +140,38 @@ class function TSystemHelper.TryFileTimeToDateTime(const AFileTime: TFileTime): end; end; +{ TSystemHelper.TryFileTimeToDateTime } +class function TSystemHelper.AccessCheck(ADesiredAccess : DWORD; const hToken : THandle; + const ptrSecurityDescriptor : PSecurityDescriptor) : Boolean; +begin + var AMapping : TGenericMapping; + AMapping.GenericRead := KEY_READ; + AMapping.GenericWrite := KEY_WRITE; + AMapping.GenericExecute := KEY_EXECUTE; + AMapping.GenericAll := KEY_ALL_ACCESS; + /// + + MapGenericMask(ADesiredAccess, AMapping); + + var APrivilegeSet : TPrivilegeSet; + var APrivilegeSetSize := DWORD(SizeOf(TPrivilegeSet)); + + var AGrantedAccess := DWORD(0); + var AStatus : BOOL; + + if not Winapi.Windows.AccessCheck( + ptrSecurityDescriptor, + hToken, + ADesiredAccess, + AMapping, + APrivilegeSet, + APrivilegeSetSize, + AGrantedAccess, + AStatus + ) then + result := False + else + result := AStatus; +end; + end. From ee1bf3c7e0b8173f1bd889d7d123ea11d45788fa Mon Sep 17 00:00:00 2001 From: DarkCoderSc Date: Thu, 2 Oct 2025 19:21:43 +0200 Subject: [PATCH 2/6] Registry Manager Progress --- Client/Client.dpr | 5 +- Client/Client.dproj | 3 + Client/Client_OpenSSL.dpr | 3 +- Client/Client_OpenSSL.dproj | 1 + Server/OptixGate.dpr | 6 +- Server/OptixGate.dproj | 6 + Server/OptixGate_OpenSSL.dpr | 5 +- Server/OptixGate_OpenSSL.dproj | 3 + .../Control/uControlFormRegistryManager.dfm | 25 +- .../Control/uControlFormRegistryManager.pas | 207 +++++++++-- Server/Units/Forms/uFormMain.dfm | 2 - Server/Units/Forms/uFormMain.pas | 9 + Server/Units/Optix.Helper.pas | 18 +- .../Optix.Func.Commands.Registry.pas | 150 +++++++- Shared/Optix.ClassesRegistry.pas | 8 +- Shared/Optix.Registry.Enum.pas | 341 ++++++++++++++++++ Shared/Optix.Registry.Helper.pas | 109 +++++- Shared/Optix.WinApiEx.pas | 13 + 18 files changed, 853 insertions(+), 61 deletions(-) create mode 100644 Shared/Optix.Registry.Enum.pas diff --git a/Client/Client.dpr b/Client/Client.dpr index 74b06b8..9fbdb5f 100644 --- a/Client/Client.dpr +++ b/Client/Client.dpr @@ -89,7 +89,10 @@ uses Optix.ClassesRegistry in '..\Shared\Optix.ClassesRegistry.pas', Optix.Func.Commands.FileSystem in '..\Shared\Functions\Optix.Func.Commands.FileSystem.pas', Optix.Func.Commands.Process in '..\Shared\Functions\Optix.Func.Commands.Process.pas', - Optix.Func.Commands.Shell in '..\Shared\Functions\Optix.Func.Commands.Shell.pas'; + Optix.Func.Commands.Shell in '..\Shared\Functions\Optix.Func.Commands.Shell.pas', + Optix.Func.Commands.Registry in '..\Shared\Functions\Optix.Func.Commands.Registry.pas', + Optix.Registry.Helper in '..\Shared\Optix.Registry.Helper.pas', + Optix.Registry.Enum in '..\Shared\Optix.Registry.Enum.pas'; begin IsMultiThread := True; diff --git a/Client/Client.dproj b/Client/Client.dproj index d63cd5e..86af7a7 100644 --- a/Client/Client.dproj +++ b/Client/Client.dproj @@ -153,6 +153,9 @@ + + + Base diff --git a/Client/Client_OpenSSL.dpr b/Client/Client_OpenSSL.dpr index 8077f6e..6ecd331 100644 --- a/Client/Client_OpenSSL.dpr +++ b/Client/Client_OpenSSL.dpr @@ -97,7 +97,8 @@ uses Optix.Func.Commands.Process in '..\Shared\Functions\Optix.Func.Commands.Process.pas', Optix.Func.Commands.Shell in '..\Shared\Functions\Optix.Func.Commands.Shell.pas', Optix.Func.Commands.Registry in '..\Shared\Functions\Optix.Func.Commands.Registry.pas', - Optix.Registry.Helper in '..\Shared\Optix.Registry.Helper.pas'; + Optix.Registry.Helper in '..\Shared\Optix.Registry.Helper.pas', + Optix.Registry.Enum in '..\Shared\Optix.Registry.Enum.pas'; begin IsMultiThread := True; diff --git a/Client/Client_OpenSSL.dproj b/Client/Client_OpenSSL.dproj index cffa328..83792e9 100644 --- a/Client/Client_OpenSSL.dproj +++ b/Client/Client_OpenSSL.dproj @@ -179,6 +179,7 @@ + Base diff --git a/Server/OptixGate.dpr b/Server/OptixGate.dpr index 8d2d1df..62131cf 100644 --- a/Server/OptixGate.dpr +++ b/Server/OptixGate.dpr @@ -102,7 +102,11 @@ uses Optix.ClassesRegistry in '..\Shared\Optix.ClassesRegistry.pas', Optix.Func.Commands.FileSystem in '..\Shared\Functions\Optix.Func.Commands.FileSystem.pas', Optix.Func.Commands.Process in '..\Shared\Functions\Optix.Func.Commands.Process.pas', - Optix.Func.Commands.Shell in '..\Shared\Functions\Optix.Func.Commands.Shell.pas'; + Optix.Func.Commands.Shell in '..\Shared\Functions\Optix.Func.Commands.Shell.pas', + Optix.Func.Commands.Registry in '..\Shared\Functions\Optix.Func.Commands.Registry.pas', + Optix.Registry.Helper in '..\Shared\Optix.Registry.Helper.pas', + Optix.Registry.Enum in '..\Shared\Optix.Registry.Enum.pas', + uControlFormRegistryManager in 'Units\Forms\Control\uControlFormRegistryManager.pas' {ControlFormRegistryManager}; {$R *.res} {$R data.res} diff --git a/Server/OptixGate.dproj b/Server/OptixGate.dproj index b5086d1..6e7e87f 100644 --- a/Server/OptixGate.dproj +++ b/Server/OptixGate.dproj @@ -231,6 +231,12 @@ + + + + +
ControlFormRegistryManager
+
Base diff --git a/Server/OptixGate_OpenSSL.dpr b/Server/OptixGate_OpenSSL.dpr index 5424e87..ee7a1d5 100644 --- a/Server/OptixGate_OpenSSL.dpr +++ b/Server/OptixGate_OpenSSL.dpr @@ -114,7 +114,10 @@ uses Optix.Func.Commands.FileSystem in '..\Shared\Functions\Optix.Func.Commands.FileSystem.pas', Optix.Func.Commands.Process in '..\Shared\Functions\Optix.Func.Commands.Process.pas', Optix.Func.Commands.Shell in '..\Shared\Functions\Optix.Func.Commands.Shell.pas', - uControlFormRegistryManager in 'Units\Forms\Control\uControlFormRegistryManager.pas' {ControlFormRegistryManager}; + uControlFormRegistryManager in 'Units\Forms\Control\uControlFormRegistryManager.pas' {ControlFormRegistryManager}, + Optix.Func.Commands.Registry in '..\Shared\Functions\Optix.Func.Commands.Registry.pas', + Optix.Registry.Helper in '..\Shared\Optix.Registry.Helper.pas', + Optix.Registry.Enum in '..\Shared\Optix.Registry.Enum.pas'; {$R *.res} {$R data.res} diff --git a/Server/OptixGate_OpenSSL.dproj b/Server/OptixGate_OpenSSL.dproj index 8693a88..bdafc57 100644 --- a/Server/OptixGate_OpenSSL.dproj +++ b/Server/OptixGate_OpenSSL.dproj @@ -255,6 +255,9 @@
ControlFormRegistryManager
dfm
+ + + Base diff --git a/Server/Units/Forms/Control/uControlFormRegistryManager.dfm b/Server/Units/Forms/Control/uControlFormRegistryManager.dfm index 18a5a73..eb00d44 100644 --- a/Server/Units/Forms/Control/uControlFormRegistryManager.dfm +++ b/Server/Units/Forms/Control/uControlFormRegistryManager.dfm @@ -10,8 +10,8 @@ object ControlFormRegistryManager: TControlFormRegistryManager Font.Height = -12 Font.Name = 'Segoe UI' Font.Style = [] + Menu = MainMenu Position = poOwnerFormCenter - OnCreate = FormCreate TextHeight = 15 object OMultiPanel: TOMultiPanel Left = 0 @@ -34,9 +34,8 @@ object ControlFormRegistryManager: TControlFormRegistryManager MinPosition = 0.020000000000000000 Align = alClient TabOrder = 0 - ExplicitTop = 0 ExplicitWidth = 701 - ExplicitHeight = 399 + ExplicitHeight = 368 DesignSize = ( 711 400) @@ -65,7 +64,10 @@ object ControlFormRegistryManager: TControlFormRegistryManager TreeOptions.PaintOptions = [toHideFocusRect, toShowButtons, toShowDropmark, toShowRoot, toShowTreeLines, toShowVertGridLines, toThemeAware, toUseBlendedImages, toFullVertGridLines] TreeOptions.SelectionOptions = [toFullRowSelect, toRightClickSelect, toSelectNextNodeOnRemoval] OnChange = VSTKeysChange + OnCompareNodes = VSTKeysCompareNodes + OnDblClick = VSTKeysDblClick OnFocusChanged = VSTKeysFocusChanged + OnFreeNode = VSTKeysFreeNode OnGetText = VSTKeysGetText OnGetImageIndex = VSTKeysGetImageIndex OnGetNodeDataSize = VSTKeysGetNodeDataSize @@ -136,8 +138,19 @@ object ControlFormRegistryManager: TControlFormRegistryManager BevelOuter = bvRaised ReadOnly = True TabOrder = 1 - ExplicitLeft = -2 - ExplicitTop = 8 - ExplicitWidth = 705 + ExplicitWidth = 693 + end + object MainMenu: TMainMenu + Left = 408 + Top = 191 + object Options1: TMenuItem + Caption = 'Options' + object HideUnenumerableKeys1: TMenuItem + AutoCheck = True + Caption = 'Hide Unenumerable Keys' + Checked = True + OnClick = HideUnenumerableKeys1Click + end + end end end diff --git a/Server/Units/Forms/Control/uControlFormRegistryManager.pas b/Server/Units/Forms/Control/uControlFormRegistryManager.pas index 865da8e..3bc00e9 100644 --- a/Server/Units/Forms/Control/uControlFormRegistryManager.pas +++ b/Server/Units/Forms/Control/uControlFormRegistryManager.pas @@ -51,19 +51,21 @@ interface Winapi.Windows, Winapi.Messages, - Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, + Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls, Vcl.Menus, VirtualTrees.AncestorVCL, VirtualTrees, VirtualTrees.BaseAncestorVCL, VirtualTrees.BaseTree, VirtualTrees.Types, OMultiPanel, - __uBaseFormControl__, Vcl.StdCtrls; + __uBaseFormControl__, + + Optix.Protocol.Packet, Optix.Func.Commands.Registry, Optix.Registry.Enum, Optix.Registry.Helper; // --------------------------------------------------------------------------------------------------------------------- type TKeysTreeData = record - Name : String; - Path : String; - ImageIndex : Integer; + KeyInformation : TRegistryKeyInformation; + ImageIndex : Integer; + Path : String; end; PKeysTreeData = ^TKeysTreeData; @@ -72,20 +74,32 @@ TControlFormRegistryManager = class(TBaseFormControl) VSTKeys: TVirtualStringTree; VSTValues: TVirtualStringTree; EditPath: TEdit; + MainMenu: TMainMenu; + Options1: TMenuItem; + HideUnenumerableKeys1: TMenuItem; procedure VSTKeysGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer); procedure VSTKeysGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string); procedure VSTKeysFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex); procedure VSTKeysChange(Sender: TBaseVirtualTree; Node: PVirtualNode); - procedure FormCreate(Sender: TObject); procedure VSTKeysGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: TImageIndex); + procedure VSTKeysFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); + procedure VSTKeysCompareNodes(Sender: TBaseVirtualTree; Node1, Node2: PVirtualNode; Column: TColumnIndex; + var Result: Integer); + procedure VSTKeysDblClick(Sender: TObject); + procedure HideUnenumerableKeys1Click(Sender: TObject); private {@M} - procedure InsertKey(const AKeyName : String; const AKeyPath : String = ''); - procedure BrowsePath(const ARegistryHive : HKEY; const AKeyPath : String); + procedure BrowsePath(const AKeyFullPath : String); + procedure DisplayKeys(const AList : TOptixRefreshRegistryKeys); + procedure RefreshNodesVisibility(); + protected + {@M} + procedure OnFirstShow(); override; public - { Public declarations } + {@M} + procedure ReceivePacket(const AOptixPacket : TOptixPacket; var AHandleMemory : Boolean); override; end; var @@ -95,6 +109,8 @@ implementation // --------------------------------------------------------------------------------------------------------------------- uses + Generics.Collections, + uFormMain, Optix.Helper; @@ -102,49 +118,182 @@ implementation {$R *.dfm} -procedure TControlFormRegistryManager.BrowsePath(const ARegistryHive : HKEY; const AKeyPath : String); +procedure TControlFormRegistryManager.RefreshNodesVisibility(); begin - /// -end; + VSTKeys.BeginUpdate(); + try + for var pNode in VSTKeys.Nodes do begin + var pData := PKeysTreeData(pNode.GetData); -procedure TControlFormRegistryManager.FormCreate(Sender: TObject); -begin - // TODO: Receive them from remote probing for permission - InsertKey('HKEY_CLASSES_ROOT'); - InsertKey('HKEY_CURRENT_USER'); - InsertKey('HKEY_LOCAL_MACHINE'); - InsertKey('HKEY_USERS'); - InsertKey('HKEY_PERFORMANCE_DATA'); - InsertKey('HKEY_CURRENT_CONFIG'); - InsertKey('HKEY_DYN_DATA'); + // TODO: when Delphi CE is in version 13 replace not (x in y) by x not in y + var AExclude := HideUnenumerableKeys1.Checked and (not Assigned(pData^.KeyInformation) or + not (rkpEnumerateSubKeys in pData^.KeyInformation.Permissions)); + + VSTKeys.IsVisible[pNode] := not AExclude; + end; + finally + VSTKeys.EndUpdate(); + end; end; -procedure TControlFormRegistryManager.InsertKey(const AKeyName : String; const AKeyPath : String = ''); +procedure TControlFormRegistryManager.DisplayKeys(const AList : TOptixRefreshRegistryKeys); + + function GetParentNode(const APath : String) : PVirtualNode; + begin + result := nil; + /// + + for var pNode in VSTKeys.Nodes do begin + var pData := PKeysTreeData(pNode.GetData); + if String.Compare(pData^.Path, APath, True) = 0 then begin + result := pNode; + + break; + end; + end; + end; + + function GetLevelFolder(const AName : String; const pParent : PVirtualNode) : PVirtualNode; + begin + result := nil; + /// + + var pChildNode := VSTKeys.GetFirstChild(pParent); + while Assigned(pChildNode) do begin + var pData := PKeysTreeData(pChildNode.GetData); + if not Assigned(pData^.KeyInformation) then + continue; + /// + + if String.Compare(pData^.KeyInformation.Name, AName, True) = 0 then begin + result := pChildNode; + + break; + end; + + /// + pChildNode := VSTKeys.GetNextSibling(pChildNode); + end; + end; + begin + if not Assigned(AList) then + Exit(); + /// + + var pParentNode := GetParentNode(AList.Path); + VSTKeys.BeginUpdate(); try - var pNode := VSTKeys.AddChild(nil); - var pData := PKeysTreeData(pNode.GetData); + for var AItem in AList.Keys do begin + var pNode := GetLevelFolder(AItem.Name, pParentNode); + if not Assigned(pNode) then + pNode := VSTKeys.AddChild(pParentNode); + + var pData := PKeysTreeData(pNode.GetData); + + pData^.KeyInformation := TRegistryKeyInformation.Create(); + pData^.KeyInformation.Assign(AItem); - pData^.Name := AKeyName; - pData^.Path := AKeyPath; - pData^.ImageIndex := SystemFolderIcon(); + pData^.Path := IncludeTrailingPathDelimiterIfNotEmpty(AList.Path) + AItem.Name; + + pData^.ImageIndex := SystemFolderIcon(); + end; finally + VSTKeys.FullExpand(pParentNode); + + VSTKeys.SortTree(0, TSortDirection.sdAscending); + + RefreshNodesVisibility(); + VSTKeys.EndUpdate(); + + /// + EditPath.Text := AList.Path; end; end; +procedure TControlFormRegistryManager.HideUnenumerableKeys1Click(Sender: TObject); +begin + RefreshNodesVisibility(); +end; + +procedure TControlFormRegistryManager.ReceivePacket(const AOptixPacket : TOptixPacket; var AHandleMemory : Boolean); +begin + inherited; + /// + + // ------------------------------------------------------------------------------------------------------------------- + if AOptixPacket is TOptixRefreshRegistryKeys then + DisplayKeys(TOptixRefreshRegistryKeys(AOptixPacket)); + // ------------------------------------------------------------------------------------------------------------------- +end; + +procedure TControlFormRegistryManager.BrowsePath(const AKeyFullPath : String); +begin + SendCommand(TOptixRefreshRegistrySubKeys.Create(AKeyFullPath)); +end; + +procedure TControlFormRegistryManager.OnFirstShow(); +begin + VSTKeys.Clear(); + VSTValues.Clear(); + + /// + SendCommand(TOptixGetRegistryHives.Create()); +end; + procedure TControlFormRegistryManager.VSTKeysChange(Sender: TBaseVirtualTree; Node: PVirtualNode); begin TVirtualStringTree(Sender).Refresh(); end; +procedure TControlFormRegistryManager.VSTKeysCompareNodes(Sender: TBaseVirtualTree; Node1, Node2: PVirtualNode; + Column: TColumnIndex; var Result: Integer); +begin + var pData1 := PKeysTreeData(Node1.GetData); + var pData2 := PKeysTreeData(Node2.GetData); + /// + + if not Assigned(pData1) or not Assigned(pData2) then + Result := 0 + else if not Assigned(pData1^.KeyInformation) or not Assigned(pData2^.KeyInformation) then + Result := CompareObjectAssigmenet(pData1^.KeyInformation, pData2^.KeyInformation) + else + Result := CompareText(pData1^.KeyInformation.Name, pData2^.KeyInformation.Name); +end; + +procedure TControlFormRegistryManager.VSTKeysDblClick(Sender: TObject); +begin + var pNode := VSTKeys.FocusedNode; + if not Assigned(pNode) then + Exit(); + + var pData := PKeysTreeData(pNode.GetData); + if not Assigned(pData) or not Assigned(pData^.KeyInformation) then + Exit(); + + /// + BrowsePath(pData^.Path); +end; + procedure TControlFormRegistryManager.VSTKeysFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex); begin TVirtualStringTree(Sender).Refresh(); end; +procedure TControlFormRegistryManager.VSTKeysFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); +begin + var pData := PKeysTreeData(Node.GetData); + if not Assigned(pData) then + Exit(); + /// + + if Assigned(pData^.KeyInformation) then + FreeAndNil(pData^.KeyInformation); +end; + procedure TControlFormRegistryManager.VSTKeysGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: TImageIndex); begin @@ -173,7 +322,7 @@ procedure TControlFormRegistryManager.VSTKeysGetText(Sender: TBaseVirtualTree; N Exit(); /// - CellText := pData^.Name; + CellText := pData^.KeyInformation.Name; end; end. diff --git a/Server/Units/Forms/uFormMain.dfm b/Server/Units/Forms/uFormMain.dfm index 2b1f83c..e03c859 100644 --- a/Server/Units/Forms/uFormMain.dfm +++ b/Server/Units/Forms/uFormMain.dfm @@ -52,8 +52,6 @@ object FormMain: TFormMain OnMouseDown = VSTMouseDown Touch.InteractiveGestures = [igPan, igPressAndTap] Touch.InteractiveGestureOptions = [igoPanSingleFingerHorizontal, igoPanSingleFingerVertical, igoPanInertia, igoPanGutter, igoParentPassthrough] - ExplicitLeft = -7 - ExplicitTop = -7 Columns = < item Position = 0 diff --git a/Server/Units/Forms/uFormMain.pas b/Server/Units/Forms/uFormMain.pas index 4420ae0..a038c5e 100644 --- a/Server/Units/Forms/uFormMain.pas +++ b/Server/Units/Forms/uFormMain.pas @@ -41,6 +41,15 @@ { } {******************************************************************************} +(* + Current Release Changelog: + - N/A + + When Delphi 13 in Community Edition (Code Improvements): + - Replace "not (x in y)" by "x not in y" + - Ternary operator +*) + unit uFormMain; interface diff --git a/Server/Units/Optix.Helper.pas b/Server/Units/Optix.Helper.pas index 5e5deab..3a4238e 100644 --- a/Server/Units/Optix.Helper.pas +++ b/Server/Units/Optix.Helper.pas @@ -44,7 +44,9 @@ function ReadResourceString(const AResourceName : String) : String; function TryReadResourceString(const AResourceName : String) : String; function FormatFileSize(const ASize : Int64) : string; -procedure InitializeSystemIcons(var AImages : TImageList; var AFileInfo : TSHFileInfo; const ALargeIcon : Boolean = False); +procedure InitializeSystemIcons(var AImages : TImageList; var AFileInfo : TSHFileInfo; + const ALargeIcon : Boolean = False); + function SystemFileIcon(const AFileName : string; AExtensionMode : Boolean = False) : Integer; function SystemFolderIcon(APath : String = '') : Integer; function GetWindowsDirectory() : string; @@ -54,7 +56,10 @@ procedure Open(const ACommand : String); procedure CheckCertificateFingerprint(const AValue : String); function CompareObjectAssigmenet(const AObject1, AObject2 : TObject) : Integer; -function CompareDateTimeEx(const ADate1 : TDateTime; const ADate1IsSet : Boolean; const ADate2 : TDateTime; const ADate2IsSet : Boolean) : Integer; +function CompareDateTimeEx(const ADate1 : TDateTime; const ADate1IsSet : Boolean; const ADate2 : TDateTime; + const ADate2IsSet : Boolean) : Integer; + +function IncludeTrailingPathDelimiterIfNotEmpty(const AValue : String) : String; implementation @@ -64,6 +69,15 @@ implementation Winapi.Windows; // --------------------------------------------------------------------------------------------------------------------- +{ _.IncludeTrailingPathDelimiterIfNotEmpty } +function IncludeTrailingPathDelimiterIfNotEmpty(const AValue : String) : String; +begin + if not String.IsNullOrWhiteSpace(AValue) then + result := IncludeTrailingPathDelimiter(AValue) + else + result := AValue; +end; + { _.CompareDateTimeEx } function CompareDateTimeEx(const ADate1 : TDateTime; const ADate1IsSet : Boolean; const ADate2 : TDateTime; const ADate2IsSet : Boolean) : Integer; begin diff --git a/Shared/Functions/Optix.Func.Commands.Registry.pas b/Shared/Functions/Optix.Func.Commands.Registry.pas index f842e3d..58ba0a7 100644 --- a/Shared/Functions/Optix.Func.Commands.Registry.pas +++ b/Shared/Functions/Optix.Func.Commands.Registry.pas @@ -49,11 +49,56 @@ interface uses System.Classes, System.SysUtils, - Optix.Shared.Classes, Optix.Func.Commands.Base; + Generics.Collections, + + Winapi.Windows, + + XSuperObject, + + Optix.Shared.Classes, Optix.Func.Commands.Base, Optix.Registry.Enum, Optix.Registry.Helper; // --------------------------------------------------------------------------------------------------------------------- type - TOptixGetRegistryHives = class(TOptixCommandActionResponse) + TOptixRefreshRegistryKeys = class(TOptixCommandActionResponse) + private + [OptixSerializableAttribute] + FPath : String; + + [OptixSerializableAttribute] + FPermissions : TRegistryKeyPermissions; + + FKeys : TObjectList; + FValues : TObjectList; + + {@M} + function GetIsRoot() : Boolean; + protected + {@M} + procedure DeSerialize(const ASerializedObject : ISuperObject); override; + public + {@M} + function Serialize() : ISuperObject; override; + + {@C} + constructor Create(); override; + constructor Create(const APath : String); overload; + destructor Destroy(); override; + + {@G} + property IsRoot : Boolean read GetIsRoot; + property Path : String read FPath; + property Keys : TObjectList read FKeys; + property Values : TObjectList read FValues; + property Permissions : TRegistryKeyPermissions read FPermissions; + end; + + TOptixGetRegistryHives = class(TOptixRefreshRegistryKeys) + public + {@M} + procedure DoAction(); override; + end; + + TOptixRefreshRegistrySubKeys = class(TOptixRefreshRegistryKeys) public {@M} procedure DoAction(); override; @@ -61,6 +106,92 @@ TOptixGetRegistryHives = class(TOptixCommandActionResponse) implementation +(*********************************************************************************************************************** + + TOptixRefreshRegistryKeys + +***********************************************************************************************************************) + +{ TOptixRefreshRegistryKeys.DeSerialize } +procedure TOptixRefreshRegistryKeys.DeSerialize(const ASerializedObject : ISuperObject); +begin + inherited; + /// + + FKeys.Clear(); + for var I := 0 to ASerializedObject.A['Keys'].Length -1 do + FKeys.Add(TRegistryKeyInformation.Create(ASerializedObject.A['Keys'].O[I])); + + FValues.Clear(); + for var I := 0 to ASerializedObject.A['Values'].Length -1 do + FValues.Add(TRegistryValueInformation.Create(ASerializedObject.A['Values'].O[I])); +end; + +{ TOptixRefreshRegistryKeys.Serialize } +function TOptixRefreshRegistryKeys.Serialize() : ISuperObject; +begin + result := inherited; + /// + + var AJsonArray := TSuperArray.Create(); + + for var AItem in FKeys do + AJsonArray.Add(AItem.Serialize); + + result.A['Keys'] := AJsonArray; + + /// + + AJsonArray := TSuperArray.Create(); + + for var AItem in FValues do + AJsonArray.Add(AItem.Serialize); + + result.A['Values'] := AJsonArray; +end; + +{ TOptixRefreshRegistryKeys.Create } +constructor TOptixRefreshRegistryKeys.Create(); +begin + inherited Create(); + /// + + FKeys := TObjectList.Create(True); + FValues := TObjectList.Create(True); + + FPath := ''; + FPermissions := []; +end; + +{ TOptixRefreshRegistryKeys.Create } +constructor TOptixRefreshRegistryKeys.Create(const APath : String); +begin + Create(); + /// + + FPath := APath; + TRegistryHelper.TryGetCurrentUserRegistryKeyAccess(FPath, FPermissions); +end; + +{ TOptixRefreshRegistryKeys.Destroy } +destructor TOptixRefreshRegistryKeys.Destroy(); +begin + if Assigned(FKeys) then + FreeAndNil(FKeys); + + if Assigned(FValues) then + FreeAndNil(FValues); + + /// + inherited; +end; + +{ TOptixRefreshRegistryKeys.GetIsRoot } +function TOptixRefreshRegistryKeys.GetIsRoot() : Boolean; +begin + result := String.IsNullOrWhiteSpace(FPath); +end; + (*********************************************************************************************************************** TOptixGetRegistryHives @@ -70,7 +201,20 @@ implementation { TOptixGetRegistryHives.DoAction } procedure TOptixGetRegistryHives.DoAction(); begin - /// + for var AHive in TRegistryHelper.RegistryHives.Keys do + FKeys.Add(TRegistryKeyInformation.Create(AHive, AHive)); +end; + +(*********************************************************************************************************************** + + TOptixRefreshRegistrySubKeys + +***********************************************************************************************************************) + +{ TOptixRefreshRegistrySubKeys.DoAction } +procedure TOptixRefreshRegistrySubKeys.DoAction(); +begin + TOptixEnumRegistry.Enum(FPath, FKeys, FValues); end; end. diff --git a/Shared/Optix.ClassesRegistry.pas b/Shared/Optix.ClassesRegistry.pas index 2dad431..1eba42b 100644 --- a/Shared/Optix.ClassesRegistry.pas +++ b/Shared/Optix.ClassesRegistry.pas @@ -63,7 +63,7 @@ TClassesRegistry = class {@M} class function CreateInstance(const AClassName: String; const AParams: array of TValue) : TObject; static; - class procedure RegisterClass(const AClass : TClass); + class procedure RegisterClass(const AClass : TClass); static; end; implementation @@ -71,7 +71,8 @@ implementation // --------------------------------------------------------------------------------------------------------------------- uses Optix.Func.Commands.FileSystem, Optix.Func.Commands.Process, Optix.Func.Commands, Optix.Func.Commands.Shell, - Optix.Task.ProcessDump, Optix.Func.Commands.Base, Optix.Func.SessionInformation, Optix.Func.LogNotifier; + Optix.Task.ProcessDump, Optix.Func.Commands.Base, Optix.Func.SessionInformation, Optix.Func.LogNotifier, + Optix.Func.Commands.Registry; // --------------------------------------------------------------------------------------------------------------------- { TClassesRegistry.Create } @@ -165,6 +166,9 @@ initialization TClassesRegistry.RegisterClass(TLogNotifier); TClassesRegistry.RegisterClass(TLogTransferException); + // Registry Manager + TClassesRegistry.RegisterClass(TOptixGetRegistryHives); + TClassesRegistry.RegisterClass(TOptixRefreshRegistrySubKeys); (* Tasks *) TClassesRegistry.RegisterClass(TOptixTaskResult); diff --git a/Shared/Optix.Registry.Enum.pas b/Shared/Optix.Registry.Enum.pas new file mode 100644 index 0000000..a3393df --- /dev/null +++ b/Shared/Optix.Registry.Enum.pas @@ -0,0 +1,341 @@ +{******************************************************************************} +{ } +{ ____ _ ____ _ ____ } +{ | _ \ __ _ _ __| | __/ ___|___ __| | ___ _ __/ ___| ___ } +{ | | | |/ _` | '__| |/ / | / _ \ / _` |/ _ \ '__\___ \ / __| } +{ | |_| | (_| | | | <| |__| (_) | (_| | __/ | ___) | (__ } +{ |____/ \__,_|_| |_|\_\\____\___/ \__,_|\___|_| |____/ \___| } +{ Project: Optix Gate } +{ } +{ } +{ Author: DarkCoderSc (Jean-Pierre LESUEUR) } +{ https://www.twitter.com/darkcodersc } +{ https://bsky.app/profile/darkcodersc.bsky.social } +{ https://github.com/darkcodersc } +{ License: GPL v3 } +{ } +{ } +{ } +{ Disclaimer: } +{ ----------- } +{ We are doing our best to prepare the content of this app and/or code. } +{ However, The author cannot warranty the expressions and suggestions } +{ of the contents, as well as its accuracy. In addition, to the extent } +{ permitted by the law, author shall not be responsible for any losses } +{ and/or damages due to the usage of the information on our app and/or } +{ code. } +{ } +{ By using our app and/or code, you hereby consent to our disclaimer } +{ and agree to its terms. } +{ } +{ Any links contained in our app may lead to external sites are provided } +{ for convenience only. } +{ Any information or statements that appeared in these sites or app or } +{ files are not sponsored, endorsed, or otherwise approved by the author. } +{ For these external sites, the author cannot be held liable for the } +{ availability of, or the content located on or through it. } +{ Plus, any losses or damages occurred from using these contents or the } +{ internet generally. } +{ } +{ } +{ } +{******************************************************************************} + +unit Optix.Registry.Enum; + +interface + +// --------------------------------------------------------------------------------------------------------------------- +uses + System.Classes, + + Generics.Collections, + + Winapi.Windows, + + Optix.Shared.Classes, Optix.Registry.Helper; +// --------------------------------------------------------------------------------------------------------------------- + +type + TRegistryKeyInformation = class(TOptixSerializableObject) + private + [OptixSerializableAttribute] + FName : String; + + [OptixSerializableAttribute] + FACL_SSDL : String; + + [OptixSerializableAttribute] + FPermissions : TRegistryKeyPermissions; + public + {@C} + constructor Create(const AName : String; const APath : String = ''); overload; + + {@M} + procedure Assign(ASource : TPersistent); override; + + {@G} + property Name : String read FName; + property ACL_SSDL : String read FACL_SSDL; + property Permissions : TRegistryKeyPermissions read FPermissions; + end; + + TRegistryValueInformation = class(TOptixSerializableObject) + private + [OptixSerializableAttribute] + FName : String; + + [OptixSerializableAttribute] + FValue : String; + + [OptixSerializableAttribute] + FType : DWORD; + public + {@C} + constructor Create(const AHive : HKEY; const APath : String; const AName, AValue : String; AType : DWORD); overload; + + {@M} + procedure Assign(ASource : TPersistent); override; + + {@G} + property Name : String read FName; + property Value : String read FValue; + property _Type : DWORD read FType; + end; + + TOptixEnumRegistry = class + public + class procedure Enum(const AKeyFullPath : String; var AKeys : TObjectList; + var AValues : TObjectList); static; + end; + +implementation + +// --------------------------------------------------------------------------------------------------------------------- +uses + System.SysUtils, + + Optix.Exceptions, Optix.WinApiEx; +// --------------------------------------------------------------------------------------------------------------------- + +(*********************************************************************************************************************** + + TRegistryKeyInformation + +***********************************************************************************************************************) + +{ TRegistryKeyInformation.Create } +constructor TRegistryKeyInformation.Create(const AName : String; const APath : String = ''); +begin + inherited Create(); + /// + + FName := AName; + FACL_SSDL := TRegistryHelper.TryGetFileACLString(APath); + + TRegistryHelper.TryGetCurrentUserRegistryKeyAccess(APath, FPermissions); +end; + +{ TRegistryKeyInformation.Assign } +procedure TRegistryKeyInformation.Assign(ASource : TPersistent); +begin + if ASource is TRegistryKeyInformation then begin + FName := TRegistryKeyInformation(ASource).FName; + FACL_SSDL := TRegistryKeyInformation(ASource).FACL_SSDL; + FPermissions := TRegistryKeyInformation(ASource).FPermissions; + end else + inherited; +end; + +(*********************************************************************************************************************** + + TRegistryValueInformation + +***********************************************************************************************************************) + +{ TRegistryValueInformation.Create } +constructor TRegistryValueInformation.Create(const AHive : HKEY; const APath : String; const AName, AValue : String; AType : DWORD); +begin + inherited Create(); + /// + + FName := AName; + FValue := AValue; + FType := AType; +end; + + +{ TRegistryValueInformation.Assign } +procedure TRegistryValueInformation.Assign(ASource : TPersistent); +begin + if ASource is TRegistryValueInformation then begin + FName := TRegistryValueInformation(ASource).FName; + FValue := TRegistryValueInformation(ASource).FValue; + FType := TRegistryValueInformation(ASource).FType; + end else + inherited; +end; + +(*********************************************************************************************************************** + + TOptixEnumRegistry + +***********************************************************************************************************************) + +{ TOptixEnumRegistry.Enum } +class procedure TOptixEnumRegistry.Enum(const AKeyFullPath : String; var AKeys : TObjectList; + var AValues : TObjectList); +begin + var hOpenedKey : HKEY; + var ACloseKey := False; + + if not Assigned(AKeys) then + AKeys := TObjectList.Create(True) + else + AKeys.Clear(); + + if not Assigned(AValues) then + AValues := TObjectList.Create(True) + else + AValues.Clear(); + + var AHive : HKEY; + var AKeyPath := ''; + TRegistryHelper.ExtractKeyPathInformation(AKeyFullPath, AHive, AKeyPath); + + if not String.IsNullOrWhiteSpace(AKeyPath) then begin + var ARet := RegOpenKeyEx( + AHive, + PWideChar(AKeyPath), + 0, + KEY_READ, + hOpenedKey + ); + + if ARet <> ERROR_SUCCESS then + raise EWindowsException.Create('RegOpenKeyEx', ARet); + + ACloseKey := True; + end else + hOpenedKey := AHive; + try + var ASubKeysCount : DWORD; + var AMaxKeyNameLength : DWORD; + + var AValuesCount : DWORD; + var AMaxValueNameLength : DWORD; + + var ARet := RegQueryInfoKeyW( + hOpenedKey, + nil, + nil, + nil, + @ASubKeysCount, + @AMaxKeyNameLength, + nil, + @AValuesCount, + @AMaxValueNameLength, + nil, + nil, + nil + ); + + if ARet <> ERROR_SUCCESS then + raise EWindowsException.Create('RegQueryInfoKeyW', ARet); + + if (ASubKeysCount = 0) and (AValuesCount = 0) then + Exit(); + + // Include terminating NULL characters + Inc(AMaxKeyNameLength); + Inc(AMaxValueNameLength); + + var ABufferSize := 0; + if AMaxKeyNameLength > AMaxValueNameLength then + ABufferSize := AMaxKeyNameLength * SizeOf(WideChar) + else + ABufferSize := AMaxValueNameLength * SizeOf(WideChar); + + var pNameBuffer : PWideChar := nil; + GetMem(pNameBuffer, ABufferSize); + try + // Enumerate SubKeys + if ASubKeysCount > 0 then begin + for var I := 0 to ASubKeysCount -1 do begin + ZeroMemory(pNameBuffer, AMaxKeyNameLength * SizeOf(WideChar)); + + var AKeyLength := AMaxKeyNameLength; + + ARet := RegEnumKeyExW(hOpenedKey, I, pNameBuffer, AKeyLength, nil, nil, nil, nil); + if ARet <> ERROR_SUCCESS then + continue; + + var AKeyName := String(pNameBuffer); + + /// + AKeys.Add(TRegistryKeyInformation.Create(AKeyName, IncludeTrailingPathDelimiter(AKeyFullPath) + AKeyName)); + end; + end; + + // Enumerate Key-Values + if AValuesCount > 0 then begin + for var I := 0 to AValuesCount -1 do begin + ZeroMemory(pNameBuffer, AMaxKeyNameLength * SizeOf(WideChar)); + + var AValueNameLength := AMaxValueNameLength; + + ARet := RegEnumValueW(hOpenedKey, I, pNameBuffer, AValueNameLength, nil, nil, nil, nil); + if ARet <> ERROR_SUCCESS then + continue; + + /// + var AValueName := String(pNameBuffer); + var AValueType : DWORD; + var AValueDataSize : DWORD; + var AData : String; + + ARet := RegGetValueW(hOpenedKey, nil, PWideChar(AValueName), RRF_RT_ANY, AValueType, nil, AValueDataSize); + if ARet = ERROR_SUCCESS then begin + var pData : Pointer; + GetMem(pData, AValueDataSize * SizeOf(WideChar)); + try + RegGetValueW( + hOpenedKey, + nil, + PWideChar(AValueName), + RRF_RT_ANY, + AValueType, + pData, + AValueDataSize + ); + + case AValueType of + REG_SZ : begin + AData := String(PWideChar(pData)); + end; + + REG_DWORD : AData := IntToStr(PDWORD(pData)^); + REG_QWORD : AData := IntToStr(PUInt64(pData)^); + + // TODO: ... handle other value types ... // + end; + + /// + //AValues.Add(TRegistryValueInformation.Create(AHive, APath, AValueName, AData, AValueType)); + finally + FreeMem(pData, AValueDataSize); + end; + end else + AData := ''; + end; + end; + finally + FreeMem(pNameBuffer, ABufferSize); + end; + finally + if ACloseKey then + RegCloseKey(hOpenedKey); + end; +end; + +end. diff --git a/Shared/Optix.Registry.Helper.pas b/Shared/Optix.Registry.Helper.pas index 7f23d5f..8d273b0 100644 --- a/Shared/Optix.Registry.Helper.pas +++ b/Shared/Optix.Registry.Helper.pas @@ -47,6 +47,8 @@ interface // --------------------------------------------------------------------------------------------------------------------- uses + Generics.Collections, + Winapi.Windows; // --------------------------------------------------------------------------------------------------------------------- @@ -66,25 +68,90 @@ interface TRegistryKeyPermissions = set of TRegistryKeyPermission; TRegistryHelper = class - public - class function GetRegistryACLString(const AHive : HKEY; const AKeyPath : String = '') : String; - class function TryGetFileACLString(const AHive : HKEY; const AKeyPath : String) : String; - class procedure GetCurrentUserRegistryKeyAccess(const AHive : HKEY; const AKeyPath : String; - var ARegistryKeyPermissions : TRegistryKeyPermissions); - class procedure TryGetCurrentUserRegistryKeyAccess(const AHive : HKEY; const AKeyPath : String; - var ARegistryKeyPermissions : TRegistryKeyPermissions); + private + class var FRegistryHives : TDictionary; + public + {@C} + class constructor Create(); + class destructor Destroy(); + + {@M} + class procedure ExtractKeyPathInformation(const AFullPath: String; var AHive: HKEY; var APath: String); static; + class function GetRegistryACLString(const AKeyFullPath : String = '') : String; static; + class function TryGetFileACLString(const AKeyFullPath : String) : String; static; + class procedure GetCurrentUserRegistryKeyAccess(const AKeyFullPath : String; + var ARegistryKeyPermissions : TRegistryKeyPermissions); static; + class procedure TryGetCurrentUserRegistryKeyAccess(const AKeyFullPath : String; + var ARegistryKeyPermissions : TRegistryKeyPermissions); static; + class function HiveToString(const AHive : HKEY) : String; static; + + {@G} + class property RegistryHives : TDictionary read FRegistryHives; end; implementation // --------------------------------------------------------------------------------------------------------------------- uses + System.SysUtils, + Optix.Exceptions, Optix.WinApiEx, Optix.System.Helper; // --------------------------------------------------------------------------------------------------------------------- +{ TRegistryHelper.Create } +class constructor TRegistryHelper.Create(); +begin + FRegistryHives := TDictionary.Create(); + /// + + FRegistryHives.Add('HKEY_CLASSES_ROOT', HKEY_CLASSES_ROOT); + FRegistryHives.Add('HKEY_CURRENT_USER', HKEY_CURRENT_USER); + FRegistryHives.Add('HKEY_LOCAL_MACHINE', HKEY_LOCAL_MACHINE); + FRegistryHives.Add('HKEY_USERS', HKEY_USERS); + FRegistryHives.Add('HKEY_PERFORMANCE_DATA', HKEY_PERFORMANCE_DATA); + FRegistryHives.Add('HKEY_CURRENT_CONFIG', HKEY_CURRENT_CONFIG); + FRegistryHives.Add('HKEY_DYN_DATA', HKEY_DYN_DATA); +end; + +{ TRegistryHelper.Destroy } +class destructor TRegistryHelper.Destroy(); +begin + if Assigned(FRegistryHives) then + FreeAndNil(FRegistryHives); +end; + +{ TRegistryHelper.ExtractKeyPathInformation } +class procedure TRegistryHelper.ExtractKeyPathInformation(const AFullPath: String; var AHive: HKEY; var APath: String); +begin + AHive := 0; + APath := ''; + + var APosSlash := Pos('\', AFullPath); + var AHiveName := ''; + + if APosSlash > 0 then begin + AHiveName := Copy(AFullPath, 1, APosSlash - 1); + + APath := ExcludeTrailingPathDelimiter(Copy(AFullPath, APosSlash + 1, MaxInt)); + end else + AHiveName := AFullPath; + + /// + if not Assigned(FRegistryHives) or not FRegistryHives.TryGetValue(AHiveName, AHive) then + raise Exception.Create(Format('Registry hive "%s" is not valid.', [AHiveName])); +end; + { TRegistryHelper.GetRegistryACLString } -class function TRegistryHelper.GetRegistryACLString(const AHive : HKEY; const AKeyPath : String = '') : String; +class function TRegistryHelper.GetRegistryACLString(const AKeyFullPath : String = '') : String; begin + result := ''; + /// + + var AHive : HKEY; + var AKeyPath : String; + + ExtractKeyPathInformation(AKeyFullPath, AHive, AKeyPath); + var ASecurityDescriptorSize := DWORD(0); var ptrSecurityDescriptor := PSecurityDescriptor(nil); @@ -135,22 +202,27 @@ class function TRegistryHelper.GetRegistryACLString(const AHive : HKEY; const AK end; { TRegistryHelper.TryGetFileACLString } -class function TRegistryHelper.TryGetFileACLString(const AHive : HKEY; const AKeyPath : String) : String; +class function TRegistryHelper.TryGetFileACLString(const AKeyFullPath : String) : String; begin try - result := GetRegistryACLString(AHive, AKeyPath); + result := GetRegistryACLString(AKeyFullPath); except result := ''; end; end; { TRegistryHelper.GetCurrentUserRegistryKeyAccess } -class procedure TRegistryHelper.GetCurrentUserRegistryKeyAccess(const AHive : HKEY; const AKeyPath : String; +class procedure TRegistryHelper.GetCurrentUserRegistryKeyAccess(const AKeyFullPath : String; var ARegistryKeyPermissions : TRegistryKeyPermissions); begin ARegistryKeyPermissions := []; /// + var AHive : HKEY; + var AKeyPath := ''; + + ExtractKeyPathInformation(AKeyFullPath, AHive, AKeyPath); + var AImpersonated := False; var ASecurityDescriptorSize := DWORD(0); @@ -227,14 +299,25 @@ class procedure TRegistryHelper.GetCurrentUserRegistryKeyAccess(const AHive : HK end; { TRegistryHelper.TryGetCurrentUserRegistryKeyAccess } -class procedure TRegistryHelper.TryGetCurrentUserRegistryKeyAccess(const AHive : HKEY; const AKeyPath : String; +class procedure TRegistryHelper.TryGetCurrentUserRegistryKeyAccess(const AKeyFullPath : String; var ARegistryKeyPermissions : TRegistryKeyPermissions); begin try - GetCurrentUserRegistryKeyAccess(AHive, AKeyPath, ARegistryKeyPermissions); + GetCurrentUserRegistryKeyAccess(AKeyFullPath, ARegistryKeyPermissions); except ARegistryKeyPermissions := []; end; end; +{ TRegistryHelper.HiveToString } +class function TRegistryHelper.HiveToString(const AHive : HKEY) : String; +begin + result := ''; + /// + + for var APair in FRegistryHives do + if APair.Value = AHive then + result := APair.Key; +end; + end. diff --git a/Shared/Optix.WinApiEx.pas b/Shared/Optix.WinApiEx.pas index dd4d083..f01e0c8 100644 --- a/Shared/Optix.WinApiEx.pas +++ b/Shared/Optix.WinApiEx.pas @@ -378,6 +378,9 @@ TSockAddrIn6 = record in6addr_any : TIn6Addr = (Byte: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); NI_MAXHOST = 1025; + (* Advapi32.dll *) + RRF_RT_ANY = $0000FFFF; + //---------------------------------------------------------------------------------------------------------------------- (* Netapi32.dll *) @@ -416,6 +419,16 @@ function ConvertSecurityDescriptorToStringSecurityDescriptorW( StringSecurityDescriptorLen : PULONG ): BOOL; stdcall; external 'Advapi32.dll'; +function RegGetValueW( + hkey : HKEY; + lpSubKey : LPCWSTR; + lpValue : LPCWSTR; + dwFlags : DWORD; + var dwType : DWORD; + pvData : PVOID; + var pcbData : DWORD +) : LONG; stdcall; external 'Advapi32.dll'; + (* NTDLL.dll *) function NtQuerySystemInformation( From 076964210e098e3291000ed55beafbbb63bec26b Mon Sep 17 00:00:00 2001 From: DarkCoderSc Date: Fri, 3 Oct 2025 16:33:50 +0200 Subject: [PATCH 3/6] Registry Manager: Browsing Completed --- .../Control/uControlFormRegistryManager.dfm | 45 +- .../Control/uControlFormRegistryManager.pas | 301 +++++++++-- Server/Units/Forms/uFormMain.dfm | 477 ++++++++++++++++++ Server/Units/Forms/uFormMain.pas | 3 + Server/Units/Optix.Constants.pas | 2 + Server/Units/Optix.Helper.pas | 23 +- Server/Units/Optix.VCL.Helper.pas | 37 +- .../Optix.Func.Commands.Registry.pas | 81 ++- Shared/Optix.Registry.Enum.pas | 99 +++- Shared/Optix.Registry.Helper.pas | 45 +- Shared/Optix.System.Helper.pas | 18 +- 11 files changed, 1050 insertions(+), 81 deletions(-) diff --git a/Server/Units/Forms/Control/uControlFormRegistryManager.dfm b/Server/Units/Forms/Control/uControlFormRegistryManager.dfm index eb00d44..78b1bd7 100644 --- a/Server/Units/Forms/Control/uControlFormRegistryManager.dfm +++ b/Server/Units/Forms/Control/uControlFormRegistryManager.dfm @@ -34,8 +34,6 @@ object ControlFormRegistryManager: TControlFormRegistryManager MinPosition = 0.020000000000000000 Align = alClient TabOrder = 0 - ExplicitWidth = 701 - ExplicitHeight = 368 DesignSize = ( 711 400) @@ -59,6 +57,7 @@ object ControlFormRegistryManager: TControlFormRegistryManager Header.Options = [hoAutoResize, hoColumnResize, hoDrag, hoShowSortGlyphs, hoHeaderClickAutoSort] Header.SortColumn = 0 Images = FormMain.ImageSystem + PopupMenu = PopupKeys StateImages = FormMain.VirtualImageList TabOrder = 0 TreeOptions.PaintOptions = [toHideFocusRect, toShowButtons, toShowDropmark, toShowRoot, toShowTreeLines, toShowVertGridLines, toThemeAware, toUseBlendedImages, toFullVertGridLines] @@ -99,11 +98,17 @@ object ControlFormRegistryManager: TControlFormRegistryManager Header.DefaultHeight = 25 Header.Options = [hoColumnResize, hoDrag, hoShowSortGlyphs, hoVisible, hoHeaderClickAutoSort] Header.SortColumn = 0 - Images = FormMain.ImageSystem - StateImages = FormMain.VirtualImageList + Images = FormMain.VirtualImageList TabOrder = 1 TreeOptions.PaintOptions = [toHideFocusRect, toShowButtons, toShowDropmark, toShowTreeLines, toShowVertGridLines, toThemeAware, toUseBlendedImages, toFullVertGridLines] TreeOptions.SelectionOptions = [toFullRowSelect, toRightClickSelect, toSelectNextNodeOnRemoval] + OnChange = VSTValuesChange + OnCompareNodes = VSTValuesCompareNodes + OnFocusChanged = VSTValuesFocusChanged + OnFreeNode = VSTValuesFreeNode + OnGetText = VSTValuesGetText + OnGetImageIndex = VSTValuesGetImageIndex + OnGetNodeDataSize = VSTValuesGetNodeDataSize Touch.InteractiveGestures = [igPan, igPressAndTap] Touch.InteractiveGestureOptions = [igoPanSingleFingerHorizontal, igoPanSingleFingerVertical, igoPanInertia, igoPanGutter, igoParentPassthrough] Columns = < @@ -138,11 +143,25 @@ object ControlFormRegistryManager: TControlFormRegistryManager BevelOuter = bvRaised ReadOnly = True TabOrder = 1 - ExplicitWidth = 693 end object MainMenu: TMainMenu Left = 408 Top = 191 + object Registry1: TMenuItem + Caption = 'Registry' + object Refresh1: TMenuItem + Caption = 'Refresh' + ShortCut = 16466 + OnClick = Refresh1Click + end + object N1: TMenuItem + Caption = '-' + end + object GoTo1: TMenuItem + Caption = 'Go To' + OnClick = GoTo1Click + end + end object Options1: TMenuItem Caption = 'Options' object HideUnenumerableKeys1: TMenuItem @@ -153,4 +172,20 @@ object ControlFormRegistryManager: TControlFormRegistryManager end end end + object PopupKeys: TPopupMenu + OnPopup = PopupKeysPopup + Left = 64 + Top = 167 + object FullExpand1: TMenuItem + Caption = 'Full Expand' + OnClick = FullExpand1Click + end + object FullCollapse1: TMenuItem + Caption = 'Full Collapse' + OnClick = FullCollapse1Click + end + object FullCollapse2: TMenuItem + Caption = '-' + end + end end diff --git a/Server/Units/Forms/Control/uControlFormRegistryManager.pas b/Server/Units/Forms/Control/uControlFormRegistryManager.pas index 3bc00e9..9e3df53 100644 --- a/Server/Units/Forms/Control/uControlFormRegistryManager.pas +++ b/Server/Units/Forms/Control/uControlFormRegistryManager.pas @@ -69,6 +69,12 @@ TKeysTreeData = record end; PKeysTreeData = ^TKeysTreeData; + TValuesTreeData = record + ValueInformation : TRegistryValueInformation; + ImageIndex : Integer; + end; + PValuesTreeData = ^TValuesTreeData; + TControlFormRegistryManager = class(TBaseFormControl) OMultiPanel: TOMultiPanel; VSTKeys: TVirtualStringTree; @@ -77,6 +83,14 @@ TControlFormRegistryManager = class(TBaseFormControl) MainMenu: TMainMenu; Options1: TMenuItem; HideUnenumerableKeys1: TMenuItem; + PopupKeys: TPopupMenu; + FullExpand1: TMenuItem; + FullCollapse1: TMenuItem; + FullCollapse2: TMenuItem; + Registry1: TMenuItem; + Refresh1: TMenuItem; + N1: TMenuItem; + GoTo1: TMenuItem; procedure VSTKeysGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer); procedure VSTKeysGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string); @@ -89,10 +103,26 @@ TControlFormRegistryManager = class(TBaseFormControl) var Result: Integer); procedure VSTKeysDblClick(Sender: TObject); procedure HideUnenumerableKeys1Click(Sender: TObject); + procedure VSTValuesChange(Sender: TBaseVirtualTree; Node: PVirtualNode); + procedure VSTValuesFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex); + procedure VSTValuesFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); + procedure VSTValuesGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; + TextType: TVSTTextType; var CellText: string); + procedure VSTValuesGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer); + procedure VSTValuesGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; + Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: TImageIndex); + procedure VSTValuesCompareNodes(Sender: TBaseVirtualTree; Node1, Node2: PVirtualNode; Column: TColumnIndex; + var Result: Integer); + procedure FullExpand1Click(Sender: TObject); + procedure FullCollapse1Click(Sender: TObject); + procedure PopupKeysPopup(Sender: TObject); + procedure Refresh1Click(Sender: TObject); + procedure GoTo1Click(Sender: TObject); private {@M} procedure BrowsePath(const AKeyFullPath : String); procedure DisplayKeys(const AList : TOptixRefreshRegistryKeys); + procedure DisplayValues(const AList : TOptixRefreshRegistryKeys); procedure RefreshNodesVisibility(); protected {@M} @@ -109,15 +139,23 @@ implementation // --------------------------------------------------------------------------------------------------------------------- uses + System.Math, + Generics.Collections, uFormMain, - Optix.Helper; + Optix.Helper, Optix.Constants, Optix.System.Helper, Optix.VCL.Helper; // --------------------------------------------------------------------------------------------------------------------- {$R *.dfm} +procedure TControlFormRegistryManager.Refresh1Click(Sender: TObject); +begin + if not String.IsNullOrWhiteSpace(EditPath.Text) then + BrowsePath(EditPath.Text); +end; + procedure TControlFormRegistryManager.RefreshNodesVisibility(); begin VSTKeys.BeginUpdate(); @@ -138,21 +176,6 @@ procedure TControlFormRegistryManager.RefreshNodesVisibility(); procedure TControlFormRegistryManager.DisplayKeys(const AList : TOptixRefreshRegistryKeys); - function GetParentNode(const APath : String) : PVirtualNode; - begin - result := nil; - /// - - for var pNode in VSTKeys.Nodes do begin - var pData := PKeysTreeData(pNode.GetData); - if String.Compare(pData^.Path, APath, True) = 0 then begin - result := pNode; - - break; - end; - end; - end; - function GetLevelFolder(const AName : String; const pParent : PVirtualNode) : PVirtualNode; begin result := nil; @@ -176,31 +199,82 @@ procedure TControlFormRegistryManager.DisplayKeys(const AList : TOptixRefreshReg end; end; + procedure CreateOrUpdateKeyNode(var pNode, pParentNode : PVirtualNode; const AKey : TRegistryKeyInformation); + begin + var pData : PKeysTreeData; + if not Assigned(pNode) then begin + pNode := VSTKeys.AddChild(pParentNode); + + pData := PKeysTreeData(pNode.GetData); + + pData^.KeyInformation := TRegistryKeyInformation.Create(); + + pData^.ImageIndex := SystemFolderIcon(); + + if Assigned(pParentNode) then begin + var pParentData := PKeysTreeData(pParentNode.GetData); + + pData^.Path := TSystemHelper.IncludeTrailingPathDelimiterIfNotEmpty(pParentData^.Path) + AKey.Name; + end else + pData^.Path := AKey.Name; + end else + pData := PKeysTreeData(pNode.GetData); + + /// + if Assigned(pData^.KeyInformation) then + pData^.KeyInformation.Assign(AKey); + end; + begin - if not Assigned(AList) then + if not Assigned(AList) and (AList.SubKeys.Count > 0) then Exit(); /// - var pParentNode := GetParentNode(AList.Path); + var pParentNode := PVirtualNode(nil); + var pNode : PVirtualNode; VSTKeys.BeginUpdate(); try - for var AItem in AList.Keys do begin - var pNode := GetLevelFolder(AItem.Name, pParentNode); - if not Assigned(pNode) then - pNode := VSTKeys.AddChild(pParentNode); + // Generate or Update Parent Keys Tree + for var AItem in AList.ParentKeys do begin + var pChildNode := PVirtualNode(nil); - var pData := PKeysTreeData(pNode.GetData); + pNode := VSTKeys.GetFirstChild(pParentNode); + while Assigned(pNode) do begin + var pData := PKeysTreeData(pNode.GetData); + if not Assigned(pData) or not Assigned(pData^.KeyInformation) then + continue; + /// - pData^.KeyInformation := TRegistryKeyInformation.Create(); - pData^.KeyInformation.Assign(AItem); + if String.Compare(pData^.KeyInformation.Name, AItem.Name, True) = 0 then begin + pChildNode := pNode; - pData^.Path := IncludeTrailingPathDelimiterIfNotEmpty(AList.Path) + AItem.Name; + break; + end; - pData^.ImageIndex := SystemFolderIcon(); + /// + pNode := VSTKeys.GetNextSibling(pNode); + end; + + /// + CreateOrUpdateKeyNode(pChildNode, pParentNode, AItem); + + pParentNode := pChildNode; + end; + + // Generate or Update Sub Keys Tree + for var AItem in AList.SubKeys do begin + pNode := GetLevelFolder(AItem.Name, pParentNode); + + /// + CreateOrUpdateKeyNode(pNode, pParentNode, AItem); end; finally - VSTKeys.FullExpand(pParentNode); + TOptixVirtualTreesHelper.SelectNode(VSTKeys, pParentNode); + + var pRootParent := TOptixVirtualTreesHelper.GetRootParentNode(VSTKeys, pParentNode); + if Assigned(pRootParent) then + VSTKeys.FullExpand(pRootParent); VSTKeys.SortTree(0, TSortDirection.sdAscending); @@ -213,6 +287,60 @@ procedure TControlFormRegistryManager.DisplayKeys(const AList : TOptixRefreshReg end; end; +procedure TControlFormRegistryManager.DisplayValues(const AList : TOptixRefreshRegistryKeys); +begin + VSTValues.Clear(); + /// + + if not Assigned(AList) and (AList.Values.Count > 0) then + Exit(); + /// + + VSTValues.BeginUpdate(); + try + for var AItem in AList.Values do begin + var pNode := VSTValues.AddChild(nil); + var pData := PValuesTreeData(pNode.GetData); + /// + + pData^.ValueInformation := TRegistryValueInformation.Create(); + pData^.ValueInformation.Assign(AItem); + + case pData^.ValueInformation._Type of + REG_SZ, REG_EXPAND_SZ, REG_MULTI_SZ: + pData^.ImageIndex := IMAGE_REG_SZ; + else + pData^.ImageIndex := IMAGE_REG_DATA; + end; + end; + finally + VSTValues.EndUpdate(); + end; +end; + +procedure TControlFormRegistryManager.FullCollapse1Click(Sender: TObject); +begin + VSTKeys.FullCollapse(nil); +end; + +procedure TControlFormRegistryManager.FullExpand1Click(Sender: TObject); +begin + VSTKeys.FullExpand(nil); +end; + +procedure TControlFormRegistryManager.GoTo1Click(Sender: TObject); +begin + var APath := ''; + + if not InputQuery('Go To', 'Key Path:', APath) then + Exit(); + + APath := TRegistryHelper.ExpandHiveShortName(APath); + + if not String.IsNullOrWhiteSpace(APath) then + BrowsePath(APath); +end; + procedure TControlFormRegistryManager.HideUnenumerableKeys1Click(Sender: TObject); begin RefreshNodesVisibility(); @@ -224,8 +352,10 @@ procedure TControlFormRegistryManager.ReceivePacket(const AOptixPacket : TOptixP /// // ------------------------------------------------------------------------------------------------------------------- - if AOptixPacket is TOptixRefreshRegistryKeys then + if AOptixPacket is TOptixRefreshRegistryKeys then begin DisplayKeys(TOptixRefreshRegistryKeys(AOptixPacket)); + DisplayValues(TOptixRefreshRegistryKeys(AOptixPacket)); + end; // ------------------------------------------------------------------------------------------------------------------- end; @@ -243,6 +373,15 @@ procedure TControlFormRegistryManager.OnFirstShow(); SendCommand(TOptixGetRegistryHives.Create()); end; +procedure TControlFormRegistryManager.PopupKeysPopup(Sender: TObject); +begin +// var pData := PKeysTreeData(nil); +// if VSTKeys.FocusedNode <> nil then +// pData := VSTKeys.FocusedNode.GetData; + /// + +end; + procedure TControlFormRegistryManager.VSTKeysChange(Sender: TBaseVirtualTree; Node: PVirtualNode); begin TVirtualStringTree(Sender).Refresh(); @@ -256,7 +395,7 @@ procedure TControlFormRegistryManager.VSTKeysCompareNodes(Sender: TBaseVirtualTr /// if not Assigned(pData1) or not Assigned(pData2) then - Result := 0 + Result := ComparePointerAssigmenet(pData1, pData2) else if not Assigned(pData1^.KeyInformation) or not Assigned(pData2^.KeyInformation) then Result := CompareObjectAssigmenet(pData1^.KeyInformation, pData2^.KeyInformation) else @@ -325,4 +464,106 @@ procedure TControlFormRegistryManager.VSTKeysGetText(Sender: TBaseVirtualTree; N CellText := pData^.KeyInformation.Name; end; +procedure TControlFormRegistryManager.VSTValuesChange(Sender: TBaseVirtualTree; Node: PVirtualNode); +begin + TVirtualStringTree(Sender).Refresh(); +end; + +procedure TControlFormRegistryManager.VSTValuesCompareNodes(Sender: TBaseVirtualTree; Node1, Node2: PVirtualNode; + Column: TColumnIndex; var Result: Integer); +begin + var pData1 := PValuesTreeData(Node1.GetData); + var pData2 := PValuesTreeData(Node2.GetData); + + if not Assigned(pData1) or not Assigned(pData2) then + Result := ComparePointerAssigmenet(pData1, pData2) + else if not Assigned(pData1^.ValueInformation) or not Assigned(pData2^.ValueInformation) then + Result := CompareObjectAssigmenet(pData1^.ValueInformation, pData2^.ValueInformation) + else begin + case Column of + 0 : Result := CompareText(pData1^.ValueInformation.Name, pData2^.ValueInformation.Name); + 1 : Result := CompareValue(pData1^.ValueInformation._Type, pData2^.ValueInformation._Type); + 2 : Result := CompareText(pData1^.ValueInformation.Value, pData2^.ValueInformation.Value); + end; + end; +end; + +procedure TControlFormRegistryManager.VSTValuesFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; + Column: TColumnIndex); +begin + TVirtualStringTree(Sender).Refresh(); +end; + +procedure TControlFormRegistryManager.VSTValuesFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); +begin + var pData := PValuesTreeData(Node.GetData); + if Assigned(pData) and Assigned(pData^.ValueInformation) then + FreeAndNil(pData^.ValueInformation); +end; + +procedure TControlFormRegistryManager.VSTValuesGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; + Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: TImageIndex); +begin + if Column <> 0 then + Exit(); + + var pData := PValuesTreeData(Node.GetData); + if not Assigned(pData) then + Exit(); + + case Kind of + ikNormal, ikSelected : + ImageIndex := pData^.ImageIndex; + + ikState: ; + ikOverlay: ; + end; +end; + +procedure TControlFormRegistryManager.VSTValuesGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer); +begin + NodeDataSize := SizeOf(TValuesTreeData); +end; + +procedure TControlFormRegistryManager.VSTValuesGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; + Column: TColumnIndex; TextType: TVSTTextType; var CellText: string); +begin + CellText := ''; + /// + + var pData := PValuesTreeData(Node.GetData); + if Assigned(pData) and Assigned(pData^.ValueInformation) then begin + case Column of + 0 : begin + // TODO Ternary op when Delphi 13 CE released + if pData^.ValueInformation.IsDefault then + CellText := '(Default)' + else + CellText := pData^.ValueInformation.Name; + end; + + 1 : begin + case pData^.ValueInformation._Type of + REG_SZ : CellText := 'REG_SZ'; + REG_EXPAND_SZ : CellText := 'REG_EXPAND_SZ'; + REG_MULTI_SZ : CellText := 'REG_MULTI_SZ'; + REG_DWORD : CellText := 'REG_DWORD'; + REG_QWORD : CellText := 'REG_QWORD'; + REG_BINARY : CellText := 'REG_BINARY'; + else + CellText := '(unknown)'; + end; + end; + + 2 : begin + // TODO Ternary op when Delphi 13 CE released + if pData^.ValueInformation.IsDefault and pData^.ValueInformation.Value.IsEmpty then + CellText := '(value not set)' + else + CellText := pData^.ValueInformation.Value.Replace(#13#10, '\0', [rfReplaceAll]); + end; + end; + end; +end; + end. diff --git a/Server/Units/Forms/uFormMain.dfm b/Server/Units/Forms/uFormMain.dfm index e03c859..dc4cff4 100644 --- a/Server/Units/Forms/uFormMain.dfm +++ b/Server/Units/Forms/uFormMain.dfm @@ -550,6 +550,16 @@ object FormMain: TFormMain CollectionIndex = 67 CollectionName = 'control-edit' Name = 'control-edit' + end + item + CollectionIndex = 68 + CollectionName = 'file-font' + Name = 'file-font' + end + item + CollectionIndex = 69 + CollectionName = 'file-binary' + Name = 'file-binary' end> ImageCollection = ImageCollectionDark Left = 248 @@ -18561,6 +18571,473 @@ object FormMain: TFormMain D13A6F00C00ADD63050086EFFB701C670D60DD6E3DEA6C369BB64BD068341A8D E63EDE0094A4BF3F257C44DB0000000049454E44AE426082} end> + end + item + Name = 'file-font' + SourceImages = < + item + Image.Data = { + 89504E470D0A1A0A0000000D49484452000000100000001008060000001FF3FF + 610000000473424954080808087C0864880000021649444154388D9592CF8B12 + 7118C69FAFCE98BBCD4E4489ECC662521ED2760C426550FC51370F1DF6921D16 + 82A1C3DEC3B3E7F907044D9620D0432C5D82D45D0C43892E8252205B7A085C33 + AB35C7992519BF5D5A0FEBAED2737A7979F8BCCFFBF212FC533299442412A198 + 234AE91840AC5EAFEF4A92044551C09C36C5E3F17301B22CB38AA2E404418865 + 32995D4992609837F12CA552295655D59C20089B994CE6FF01DD6E17E9749AD5 + 342D2708C2E6CC0A8B24CBF249C9524A7353C06432999A08218846A32897CB18 + 0E87D3FEE9FBC8B2CC4E01AD560BB55A2D0120E1743A110C06311E8F512814E6 + 269ADE60E7551EDFBEF70100A228A2582CC2EBF5C268342E0618B8CB58799AE5 + 0F6F3F089B4C2658AD56944A25743A1DB8DDEEC5002EF81030735BFD9B91F0D1 + B215D96C16BAAEA352A9C0EFF72F001003B8D02300D8668E07EFFA374268B55A + 008066B309B3D90C9BCD763EC0BC110263590F13AAEBD68FAFF787AB2E8C2F70 + F0F97C8846A3D0346D6E0AC3CABD2D1042B601F2E9F8D29ACB34ECE1A7DD8F5E + AF87D1688446A30187C3019EE7CF04304B1BC15500F729217BEA15FB2D93FA0B + 3FEC7E7C79B38776BB0D00E0791EA228229FCFCF262006E313002F8CDD83D8F5 + F7CF5EDA3EECC0FCBB8BC1B53B5353B55A85D7EB05C3CC3E2E0380A39426B5FD + E7609795B714485CEC7FBE7AB47E77893F6C7C35EA7FA0AA2A068381CBE3F11C + 040281C7168B65ED04F017973CC2E02EF35A300000000049454E44AE426082} + end + item + Image.Data = { + 89504E470D0A1A0A0000000D49484452000000140000001408060000008D891D + 0D0000000473424954080808087C086488000002E949444154388DA592DF4B5B + 671CC63FEF496CB393D8986C299AB0B53DDA1FEC6298C48C56BB85228865FEA0 + 30D7C1A0ECA68EF61FE8AE7639A6B7BB71A1F7BB9B375E48ECA981C134134CDD + 14CB32A448A7AC89276D4CD6F4E4E4BCBD58CD0C5349E973F7709EF3E179F8BE + 82570A8542E8BA1E07523421296505B8562E9767C7C7C7595E5E06C07950786A + 6AEA48583018646464C425A59C76BBDDD71289441D7A20706363A39992249349 + D7C0C040035469EACF43A4EB3ABAAEBB8069B7DB3D984824DE0CF8AA25F3F3F3 + 7BD0AB074E6E56939393FBAD4B4AF95303504A8910A2EE5555C5EBF5B2BDBDDD + 00DADADAFADFE1F60ED5002C954A8FD6D6D61E00DD00C3C3C384C36126262628 + 140AF55CA55239F4708EFDA656AB3DCB6432176DDBEE565595B1B131AAD52A8A + A290CD668F9CEFF3F9E8E9E9F9EF28250B52AB1B98550B80582CC6EEEE2E3333 + 33C462315A5A5A8E04EEA90E3C317893EAE7DF9E364E5FEC020887C32C2E2E92 + C964B06D9B4824F21A40C581E7E3EB5455FF377F757F76D97479595F5F676969 + 09CBB248A7D3F4F5F5350F54A38338BC013F705D0AA5B4A37DC4DCDC1CE57219 + 808585050281005D5D5DCD013DFD3710F0A59076AEF5C9C369E34C2FD6BE375F + 2C16595D5D6DAAA5D3193C8BEB6C8F40885BCEE74F7F38F93079EED1A59B3C7D + 374A67F10F86868600686B6B23140AE1F7FB310CE3F086AD57BE4008310068B6 + E3D8AFA6EAF3B5FEBD4EBE334EA1502097CB512C16D9DCDCC4300C7A7B7B8F6E + E8B9FC2908715B08A1D8C73DF71EC76ED43F96DED6989D9DADFB4824C2E8E828 + C96412D3340F6E288EABA7804FA494FDCE72FE9D333F7FFFE3FB335FD3BAF53B + 3B9DF186F0CACA0A9665118D460F9F2C84F80A7820A5BCAFA6EEEE7872D9174E + F31F027FA67816FC00F3ADB67AB856AB914EA7EBB33B3A3AD0340D4DD3080683 + FF4E06B691F23BEBC9262F7E9B479C3F7F57424A31CB382ABBFDC67B1FFE7232 + 7BFFB9625B0821C8E7F32D1E8FE74A341A9D8BC7E377DADBDB2FEC6FF812D537 + 26C4227FA06C0000000049454E44AE426082} + end + item + Image.Data = { + 89504E470D0A1A0A0000000D4948445200000018000000180806000000E0773D + F80000000473424954080808087C0864880000041B4944415448899D945F4C93 + 5718C67FEFF7D102A50CA585023234FD168964ABC6DA45049C9B3331CBB225DC + EDC62C6E341957B864DE1A13B60B6F24D91D72C385375BA29BF362931B2D2B59 + B2CC3F98A664A3F827CE1629A59192AC407977C3D7546B27EEBD7ACEC939E739 + E7F73EDF2794D4E9D3A73979F2E419553D232202A0AAFA225D3A56D51CF02170 + 63747494F3E7CF17CFACA2424D4C4CD887609F59AAEDB165595896E556D59F80 + 8FC2E1F07555656464E4C506AA0AC0B56BD7B474BA824644D4EFF7F3F8F16377 + 5B5BDB15DB0460646404E37903FB86B2599574092A1111191B1B23994CD60357 + 45E448381CE6D4A953E506FFB772B91C636363CCCFCFD7015744E4DD81818172 + 031B916E56256D8FED2980E5E565BD70E1822E2C2CB8811F45E448590F44C46E + E69652B4898873E7CE3DBFAE5E55AF566CF2562B914814F795A6CDB22CFC7EBF + ABCCA05028609AA67D3B1C0E078383839A4EA7B978F122FADC0D128984DA2694 + 24CC4E57590FA6A7A7CF0E0F0FDFB093120804686F6F974020203E9FAF2C4595 + 34200066E9E1B3B3B32C2E2EB2B6B6F629B00BA0BFBF9FF5F57571381C98A6C9 + CCCC8C94EE29ED49A9B62C4BCA5EB0E4F2F1546A510455D51D3B766847470793 + 93937AFBF66D0D0683D4D4D43C93A24ADAC6553410470DCD5F8E93393CF0C68A + D7DA2622120A85249FCF73F3E64D8946A3E2743A098542AF84A868E0EAFE18A3 + AE41724DBBBFBF7FF0F3BD05D3C9A3478FB875EB16F97C9E6432C9DCDC1CDDDD + DD18C6D6BF4F63131EF5EF7C02420F227B0B8E5A963A42DCB973874824525C1C + 8D46F17ABD747676BE9A81735700E7AE00820CA29A36D657FF5CB40EEBEADABA + A6D3E922DB582CC6D2D292F6F6F6AACD784B3D701F3D01820FE8375757C63DF7 + A3C97C7D8BE49A773FC376636383A9A929B12C4B7C3EDF967A5065B81BA90B1E + 47E033C0AC7E9A1A6D9C8B1EC8BE7E80B47518F7FC0CC78E1DA3ABAB0B00A7D3 + 8961181C3A74884B972EBD1C515D4F3F525DEB406400B85E70D6FEAD6695B1FD + C16FBAECEBD2557733F1785CB3D9AC66B3599E3C79A2A9544AF7EFDFAF2E97EB + A588AAEA8F9E40443E007622B4E71BDA16FF7AEF2B272018268BFE5EADBE7B59 + C6C7C78B3FBB9696168686860885421A89445EF853DC44A44695B71DE00BE021 + CA5933BFF2B5E7DED403DFCC2FB8D2B364761EA460563FF3EC542A452291D852 + 640DA013781FF85655871B6726865B62571F34C77FD6B6E91F74C351C3D2CEB7 + CB3044A3516D6C6C64CF9E3DFF8D4844C2C03FAA3ABE7AFF2EAE3F2E63343420 + 22529B7D882B734F17FD7DE299FB1574A388211E8F93C964B4A7A74762B118FB + F6EDD3A6A6263B41EAF7FB05D02A552641E7514DE722DFD92F1B52D56D6BAEED + 3856326FAD7AB6799EB6BE79E3B5544C75A30080D7EB656161A1DBE3F1AC0783 + C1DFFBFAFABE696D6DED2EA1A300FF021F7D52441F3120860000000049454E44 + AE426082} + end + item + Image.Data = { + 89504E470D0A1A0A0000000D4948445200000020000000200806000000737A7A + F40000000473424954080808087C086488000003EB494441545885C5D75D4C5B + 6518C0F1FF39AD95752D45D640570444830831C5186CCBA01130733A7641A246 + 4DBC712E337C5C4124E16A6A02178DC61B12BF0825466388181341C902510723 + 7CC805988A8CC051A2015718DF504A4B5F2F361A90DA695BF049CE4DCFF3BCEF + EFBCE779D3F7484488CACA4A2C164BA494882184C0E3F1D0D4D4C4CECE4ED81C + 75A4012C160BA5A5A52206C00670C16C365FABA9A9098B8808D88BFAFAFAA800 + 4EA753E7F3F9BA1C0E47797373735F38841CD5C8FF215C2E97CEEFF77FE37038 + 1CCDCDCD68349AE305288A426B6BABCEEFF77F1B0E71E4803DC4BE9528DE8F38 + 1600C0CCCC0C2E974B7F67258AF610C706D843B4B5B5E9FD7E7FB7C3E138D3D8 + D81879170483C19827753A9DE17ED60B21BAB3B2B20C52A4E2BABA3A565757AF + 783C9E3763968481B9DD6E29E22B686969C1E3F100505B5B8BCD668BB7E3DFF5 + 407A7A3A269309BBDDFEFF00AC562B939393188D463232328E17909494447E7E + 3EFDFDFD8C8D8D5158581857C0A15DA032A470E2B1A70041F1FD3A2A2ACECB5E + AF97E9E969363737A9AEAEA6B3B393ADADADA301E89FBE88E1FCEB1711F88A32 + 7D9F3D723A58D2DBDB8B1082B9B939E6E7E7292828A0AFAF2F2E8083AF40A546 + E7785E0DBC8DC45B7F6CAB6421308F8E8E8652060707E3DA8C0700DAC7CFA1D2 + 2797030980F1C72571F6EBABBD1D2B2B2BA19CF1F171B45A2DD9D9D9F107E84A + 5E06A4CBC027C0A78B3B547E3F3EB5BD3F271008303A3A1AB7660C01D4299924 + E49EC904CE09213E16427C1094EF29F76A4FA5FFBD68686888DCDC5C12131363 + 06849A50F7E44B4892740918D85DBFF54B707D194D5AF6A0F7BE8C1753177E3E + F4C45B5B5BD86C367A7A7A6202DC5E01951A5DF10B6AE05584F828F0E7AF0416 + 7F07787F25BD40E7F30730994CE4E4E484AEE5E565AC562BB21CDB1FAA1A405B + F02CAAC4531724494A135091F0F013CFDCB9AF099C30B06AB6D0DEDE7E502ECB + 34343490979787DBED8E1A2003E84B5F01B82C84F80E50909843620EC46FB26F + 73E05656F1A1C26030C8C8C848CCCDA8569F7E88841C6B2670167874B5FBC31B + 01CF2C00DA7B35E43E907665D6F65AD1B62E85840DCF81E2E1E161CACACA301A + 8D2C2E2E4607D0153D077009B81E58BE7963E5CB7760370080CA602031A114FD + CD09961E2CC2FCD357078AD7D6D6989898C06EB7D3D5D5151540964F1A005610 + BCB771FD8BD0E4A110418CD3D7907677C30E30303080D7EB8D6A7200F5FA0F9F + 834AF3AE74D2C046DFC1464B4D4D4525CBE817A6D02F4C851D4051141445891E + E09F75B3D4FA46D89B55555524272797747474443DC1DD22E226D6683458ADD6 + 92239B9DBB7C1B4AD2ED33EB3F9C6C8F1E303B3B8BDBED8E78728E251445E12F + 38027CBC900B4CDD0000000049454E44AE426082} + end + item + Image.Data = { + 89504E470D0A1A0A0000000D49484452000000280000002808060000008CFEB8 + 6D0000000473424954080808087C0864880000056F494441545885CDD85F4C53 + 6718C7F1EFDB16A4520BD582DA222838D3F8174E0F501DE924CE192F4DCCFC33 + 93C5645377B58B2D661764377AB199CC8BED46DB64CB329CD18B255BCC8C1A37 + 74D900A90C91E8368C98A16D235AC69F96523C7D778154490B1669C77EB77DF2 + 9C4F9E73DEF79CBE823472F8F0612C164B3AA52F8C9412804824C2F1E3C78944 + 22D3D61BD269BA6DDB36EC76FBCFB3E7258021E05D87C3113A70E0C0B448914E + D3CB972F63B7DBA5CFE7A3BFBF7F56408BC582AAAA4829DB81ADD7AF5F9F1699 + D60427E2F3F9B87BF7EEAC80E5E5E5A8AA8ADFEF576C36DB25A7D3F9BAC7E3E9 + 9F0AA99BD5D56611AFD74B201050804B4EA7D3E2F178983F7F7E52DD9C012391 + 081E8F874020E0042E2A8A52980A396740988454851097269046A3315133A740 + 48425E5414A5D0EBF5262639E74018477ABD5E82C160B510E282A228051393FC + 5F0001C2E1301E8F87603058F3749205478E1C496F9B89C7E319071D3B766CBA + 9F6B006F5151D19B6901A3D128E7CF9FFFC4EFF77F345B98DFEFE7C48913D3D6 + A8AA8AD3E92C823437EAA3478F62B3D9FED0340DA3D1485D5D1D57AE5C21168B + CD18188D465FB8D95754542084400891DE3378E7CE1D344D03405114B66EDD4A + 5555D58C712F93192F92EAEA6A00366EDC98714CAACC0858525282CD66A3ABAB + 0B9BCD46595959B65C89A40DCCC9C9A1BABA9A6834CA993367181818C0E57265 + D306A409349BCD94959551595949474707A3A3A3B4B6B6B27EFDFA942FF84C26 + E52AD699AD14BDF705120912F6974671AF2DCF371A8DB4B5B50170EDDA35B66C + D982AAAA5CBD7A356BC0941334D5ED24CFE1DA60746CBC9DE7709597566D62F1 + E2C53B038100BDBDBD000C0E0E72EBD6ADACDFE6D4C0CD7B010E0A211C428883 + BD233A80E513D39B484B4B0B56AB9555AB56FD77C0BCB56E0CD6927CE02D29E5 + 18B0BFB59F79F7830FBF6A6F6F9F54DBDDDD4D5F5F5F56A7980434B9772184D8 + 2D84304B293F144214750FC6777ACEFEF077AA4FF296961656AF5E4D414141F6 + 813AB395F9CA1B0007A4943EE0732965E728FA437D4F725236F0F97C689A464D + 4D4DF681A6BA9DA0D35702D5203D20014E489DE1D5E882E2F5A91A8C8C8C70E3 + C60D6A6B6BD1E932FFF536699B316DDE8B10E220302C25A7A3777E276FA5D228 + 84F8345AB8EC6D80D2D252CC66F3A42603030398CD66D6AC59C3CD9B37B3037C + 6E71EC05BE95DAD8F0E393EFB3E4E3EF870CE645A70697AE3BA419E661B7DBD9 + B16347CA662E972B7BC0A78B638F10C21C8FC74F0B438EC9FED92F8CEFD5B231 + 9E9377E89F652A6D6DADF4F4F4243572381C6CDFBE1DABD5CAA3478F320BD45B + 96241607804EA76B4A543C77F6F078451D0B7B7E25180C26350A8542D4D7D7E3 + 72B93877EE5C668126F72E84DE5005A852CA9340D7A44391789C9CE8606DB4D0 + BE2FB27005F9A1E409C66231DADBDB5155950B172E3036369621A04E8FC9BD0B + C6A737087C10F6FD181E7BF057A2283FD7C0F2C2DCA1FBCA9E7D8FCBEB520201 + 9A9B9BD9B469131B366CC0E7F36506685CF71A86854B4D8C2F8E5332361A0E7D + DD407CF8D9219161D1224CEE7A16DE6BE1D12BF53CE9FC0E432C9CD4ECE1C387 + F4F4F4E072B93206D4E52E5F07B01B5820A5F484DB2F4EC2250AB5188BEEFD86 + D4E90995D54ED9B0B9B999D2D252EC767B4680060029E519C66F6FC770D3A994 + 8502C88D8458E66B24BFAF7BCA865D5D5D343636A65C482F051CBCF8254F8642 + 43B9656BCFC6A36146FF6C4D2A5AB972257ABD1E4DD3B0F44E7FEB344DA3B3B3 + 33233800831C1922FCD337243F51CFD2D0D0402010A86B6A6A6278783863174F + 2769BD3CF3F2F270BBDDEF14171767DB9394B4FEB84F7C04A8AA4A4545455641 + 307E0A3B91991C0137A9AA9A79CDD4E98034811D1D1D3C78F0A03EBB9EE4DCBE + 7D9B7F01DA5315FBEF4E25A30000000049454E44AE426082} + end + item + Image.Data = { + 89504E470D0A1A0A0000000D49484452000000300000003008060000005702F9 + 870000000473424954080808087C08648800000775494441546881D5997B4C94 + D919C67FEFDC188771909505F1525CAC1B19D9302814C6DD4DD70BA4C67693A6 + 698C9BDDAD51B3DBF84713D3AEB1214D5B4DB741DBA469D234DB15EB3FDBA449 + 93DD0E6AACB48612A64E65BC14C1C0A620142DC50B2AC86D60E6ED1F30380A33 + CC0CA0EC934CF27EDF79CFC979BEE739EF39DF37429C309BCD1C387020DEF4A4 + 110C06397EFC380F1F3E8C2B5FE21DD866B371E9D22544E4C7E17BAA8A88448D + 676A7F3A17E8063E6E6E6ED6BD7BF7C6452261024028DE3E49E297AA7AF0FAF5 + EBBA67CF1EFAFAFA622627A380D6D4D450535383AAAA4C3CCAE9E299DA23E3B2 + B232B66DDB16EEF78B3089999430C44BE059A1AEAE0EE0FB2252B97EFD7AAAAA + AA484B4B8B9A9F30018D40E4F574F14CED4FE52AC0A953A7B4BEBE1EE00740A5 + D3E9E4C48913381C8EB921201188BC9E2E9EA9FDA9DCB09DA5BABA5AEAEBEB11 + 9183225299979727274E9C9856890567A130AAABAB9950E20311F979343B2D38 + 0B450EEFF178D4EBF5021C043E743A9D5455553D61A70567A1C8FB80783C1EF1 + 7ABD88C82111F930BC26C24A2C580B45C2E3F1E0F57A053824223F8BB49329D1 + C1C2F24EA83F699568F14CEDF1C61E8F474504B7DBFD4320E4743A7F54515191 + 3881B0C213DBFF9C6D64E1391F3B762C9EFC0AA0DD6EB7FF3E21022323237474 + 749C6C6B6BDB9D28F199D0D6D616F7D9A9BCBC5C802F01F12B100C06397FFE3C + 4D4D4D27EFDEBDBB1BE0F1839B3DDADBDB696B6B8B97006117C4BD88474646A8 + ACACE4CE9D3B93A56ED7AE5D1C3E7C58AD56EBACCB681231905C194544C466B3 + 497E7E3E56AB555C2ED7ACCB6812717204C270B95C984CE30E2C2D2D9D533B25 + 826409687171B10683415A5B5B353B3B5B737272BE1816321A8D2C5FBE5C56AC + 5821ADADAD9C3B774E0071BBDD5F0C0BA5A7A7535C5C8C88D0D0D040575717B7 + 6EDD223F3F9FD4D4D444879B35621230D8D331A4658EFF1C196CDAB489FCFC7C + 5C2E97F6F5F5694B4B0BAAAA3E9F4FCD6633454545CFDC4251F701596467C5D1 + BF2356BB0540C74603EFACEA625546DAAAD4D454A9ADAD25180CAA88C8D5AB57 + D9B16387969494485D5D1DA15028A99D38D138A602A9256F2256BB5144AE8848 + ADC96C96452FAEC06EB77F27140AA9DFEF9F7C1A2323237AF9F265962E5DAA6B + D7AE5D188B78F196B71191CD401E22A50A1BFF3324002F7776764A4F4FCF138B + CBE7F3A1AAE276BB9FFF22B6E4E4635EB90EE03D000151F8EEE507C2A3C1A1AA + 8686862975BFA7A7871B376E909797C792254BA23D9739C7B404EC9BDF025806 + 7C036851D50E909D977A43E99FD6D4D53536364E915655F1F97C2A225A5252F2 + FC2C2436C7B8FF45768B8855553F023E12117B6F80771BDABB3510084C2B6D73 + 73B3F4F7F74B7171312693E9F95828B57807926213609FAA0E009FA8EA49551D + 0E19CDEF0FA6A4453D338C8D8DD1D0D080C3E1C0E974464B9B534C21607FE32D + 04B602B9C0A7A07781FF019FA918D70D2F5EF6462C692F5EBCA8AA8ADBED7EF6 + FB8025D78525673D88BC8F081A0A7D141A1922F8E036E6ACD5BF15919DC34B56 + EE1311B1582C646464288FBFE74CC6376FDED4DCDC5CC9CACAD2DBB76FCFEB3E + F00401FBEBDF06C806BE8E6A33F08F810B9F31D67383F49D15F540D3E0D2975E + 19B53AB01260FFFEFD582C1626069EF202525252427575754C0BCC16930424C5 + 46AAFB9B88C8BB400AE8712064CECAC1B8F80518FF2AFDBB90C1F4EBDE9C524C + 2D7FE1CC99336467676BC47893715E5E9E6EDCB891B367CF6A201008139B9317 + FCC8789240EAABDF422C5623B06FE2D63211F96091F3B571638C77491311E95D + ED26F3F3BFE2F57AA3CABC79F366D9BE7DBB16141488DFEF9F670B8981C55BDF + 01912D88AC411511C3A1C90E88208F998FDA5EA02FCB89A3FB1AD1E0F7FB292B + 2BA3B4B414BFDF1F356FB63001A4AC29C49CFD6504DE637C8EDF53D5AE70D2A4 + 621AC4F2E86E7EC09E79E45EEE6B38BAAF4595B6BFBF5F9B9A9A70B95CBA72E5 + 4ABABABAE6CF42F62D6F23C832E04DE09AAAFE26D07E4503375B226A0BD84D06 + 32AD630F7A576F924759EB08A46668CAE0BDA8325FB870410B0B0BA5B4B494AE + AEAEF9B190C19E8E6DE3D740D82D221655FD18D07B272B18BDD9F2845CE6AC2C + 16BFBE15098518CC5843EF4BAF92DDEC9946D871747474D0DDDD4D414101A74F + 9F666868286A6EB2302C7AE5AB8839C508EC55D547AAFA87917F5F9E32F9304C + 8101D2FEFB2F350DF7696FCE5708194C31371B9FCFA7168B45376CD8303F6721 + B12C4244560146E04F40EFA3BA3FC6E0AC18426392DEF94F51A39961C7F2A8E7 + 15802B57AEC8D0D090646666CECB59C8141A194443DA81F032600F0DF43178F1 + 54D4E987CDF7E2E77F23B3B506E3D8700CB2303C3CCCD1A347191C1C8C99972C + 4C83BE3FD3DDDD86D5B56D4CCCD607A3B75AD1C054AF1A8D460A0B0B319BCD04 + 020135060600D088CD6BBA4AA1AA3A303030793B566E32B10960B4B389D1CEA6 + 984C5352523872E4083E9FCFE5F7FBE5FEFDFB33568AB9AA36B1AA50429F556C + 361B656565BF2A2A2A4AA4DBBC22A1CFEB068361B20284559C49E6B9B24A4C0B + 25021191F2F272CACBCB178485122600FC24893EF3815A48F00F8EDADA5A809F + CECF7C1247636323FF07E76265E60F5CEA090000000049454E44AE426082} + end> + end + item + Name = 'file-binary' + SourceImages = < + item + Image.Data = { + 89504E470D0A1A0A0000000D49484452000000100000001008060000001FF3FF + 610000000473424954080808087C0864880000018449444154388DAD90BD4B5B + 6114879F9BDC97C4B8542962C58AB482A0F445508AD029D8BF205D843A087790 + 0E2D0E92F982DB8B930E81C43B0A19344570B34BC1DD34E226B4832DA11013F0 + F6DEB6C67B5C14247E8488CF740E1C9E737EC7E2925C2E473A9D16EE4144CE80 + D94AA552721C07DFF7B15B87B2D9EC9D02638CF27DBFA8B59EF53CAFE4380EB1 + FB36DE463E9F57411014B5D619CFF33A1754AB550A85820AC3B0A8B5CEDC88D0 + 0E63CC55A944A4D891A0F53FC618D57184561E4F1045D1830476DFE23A00E5E4 + 73F657565CC0ED48909A782B005F4F7F5B83CD6E6AAFE7097A8649D57F30F06D + 13F5CFA792590540973EDD8C30BEBDB40BF03FD5CBF7371FA655D8E0C5DE1A2A + 6C703C3907C0ABAD8F775E10436417406271223B31D37FB843E24F8DFEC31D4E + FB46DB4688054F06BF5CEBE356740E80159D8365B517549F8E9501100191727D + 680A80FAD014C9C6CFB602BBD68C4B0A8837FFA28293A5E3C9F7F95FFADD4864 + 278F9E1D7CDE10CB92B3AE1E003731F0D25D5E5C70AF0B2E00B75A8A5C74D0DE + AE0000000049454E44AE426082} + end + item + Image.Data = { + 89504E470D0A1A0A0000000D49484452000000140000001408060000008D891D + 0D0000000473424954080808087C0864880000023A49444154388DBDD15F4853 + 7114C0F1EFEFDE6DDE79AFF3CF5CE4EC8F4A494CA2200882202212231909F5D6 + 430F21BE0741F4508F29BD06634FBDF690421488799D8644044962FF0833C85A + 137525B875B7DDDD5F0FBA65B5D950E83C9D1F9CF3F99DDFEF08D6A3B9B919D3 + 344F00E35410524A0BE849A552C3BDBDBD4C4D4D01E02A551C894436C582C120 + E1705893520EE9BADE138D468B6849706E6EAE9221191919D13A3B3B7F43958A + 3ACB84699A98A6A90143BAAE7745A3D1ED81EB53128BC50AE899924FAE340606 + 06361E3529E5E096C0783CFED7E20A8BDA12685956D9C56DFB0FFF2FE838CEB6 + 419771FCFC5A525FC7FCC2F2CB674FC68681AE2D838D976FDF584BE5787FCC9C + 3066A613B6476735B01FC5CE622CBE47716C00927B8E92D3FDB853CB347C7A5E + 1AAC5EFA70C5F235D5389EEA9B0963F744CDBE9362B1FD344807A9BA70FF58A1 + 75F20E55E92456DD2E569A0EE24927CB824ACBD3C8A077E50B524AD20D2DDE44 + E86CB7FFE3241D0FAF117A741D77FA1BF1C31700689ABE5F162A82C271460B07 + A97A0E09A1F877BC1D462051ED0C81D9315603EDC50629E5E6A0650446814255 + 15809ACFFE2AB0B348D50D801062530C4049D5EF4DE4BCB5AFD7EFFF0E90D37C + C5829C568B924DFF132A84EBAB5D85D01B970044DE9E4151DFCC1FB918DAF9EA + 01798F4EA2A39BBACF2F8A0D1BA76C6B6B2BE6C160700D4CE51C0CA12000773A + E9A876A66F35D0DE3F7BEAEA3129A5ADD8997BC6C2BBC78E50908A8B8C1E3867 + 6BBE03B5ADA15B7D7D97EEFE39E14FD862DCDAB48725E20000000049454E44AE + 426082} + end + item + Image.Data = { + 89504E470D0A1A0A0000000D4948445200000018000000180806000000E0773D + F80000000473424954080808087C0864880000031C494441544889AD964B681B + 571486BFA3911CD952522744AA6B37A999A9C8832CD222E8A29B186C5A4A6897 + 2D74530CD6DE14BC6C365DB90B6B596C41B20CDD3549EB60C575B2E88B905571 + ED60BB2F5C0B21D124D6F891C89AD38575E551E44994C70F82FF8E34E7BFE7BF + FF3D48F0616C6C8CE1E1E10BAA7A4144044055753FEE5FABAA0B9C076E4D4E4E + 323131D1A8192600F97CDE14C1D4F473B3761C07C771E2AA7A15F83093C9DC54 + 55B2D9ECFE02AA0AC0CCCC8CFA1F077044446DDB666D6D2DDEDBDB7BC5880064 + B359428F0B981D4A1D41DC67958888E472390A85C241E09A889CCB64328C8E8E + B60A3C2F5CD72597CB512C1663C015111918191969153016691D41DCACCD2380 + 4AA5A25353535A2A95E2C0B72272AEE50C44C41C665B29AA5BC4F8F8F8E3BF3B + A8AAD70253D42E5656561A9DFBD3E6380EB66D7705A6C8674120AF0BA811C197 + 3093AE174E511007047879290AC20B5BF484EF745F0183679945FB71762DD2B0 + 44637B55AD08E572F9E6E2E2E267407F60DFCF80F01B5FCF9BDDF063A7E2CD5E + BEF5E76F77FE6A4BC037F8020554D5338BD52D09DD2EB8C4D4E2417F5AEF1F4B + 53EBE8A2F3DE3F9ABC9BA7C32DA1AA5A3CFD01C593EF03D0B330ADC98569B3C9 + 9633082596E6FE8897971B5B29F7BFCBDFEF0C77FDFBD627528B4425B2F11F0F + FACECAF2C0E7F2F0500F2222F1D292F42C5E6FCAB38F36C734B930FD4DBCBCDC + 90DD48A4D26EF244FAE8D22CA91FBEA2FFE74952B3E3E07914CE7C0440ACB444 + F2F7EF9F6A0F4008AF76437D3750ADC80020C9BB793599EDD8286BF7EA1D7513 + 296383F934A69F8F36862040A81A3BF20B88EB13ED020857B79A5AB7AA5BE259 + 1D7E1BDAB3E851E7E1CD87B1A33FF90476003CB19A5A55B190BD3CB48DD0BA15 + C34DA46EEF55D27980F5D7CE34DAF5C4D2CAABA734BA5EF0DBD09645E1B58D1A + 9DD1433B0DC5EAE67722A195D5F4A76F6EBFD24764EB9EDE3F9696EDEED739FE + EBC5A69B0C68DD17868686CCED0550DBB6776FF2A39A47D4F74674BD5055EBC0 + C7DBDD7D5F144FBE779EDD81583850297E295E75DE0B85116F07377102606EF3 + F0F14BBDA7DFBE3438383807AD7F0EFE073C88E11934C842AE0000000049454E + 44AE426082} + end + item + Image.Data = { + 89504E470D0A1A0A0000000D4948445200000020000000200806000000737A7A + F40000000473424954080808087C0864880000037F494441545885ED965F6C53 + 551CC73FA77F6EB7D275EC4FB7B90865244C9CA3984C16FF70238B983D283399 + 0FC4607CF361733C989819DF48748BA96FA64F46D76631419F4C8CB807128243 + 0C23131E1809CBD28ED211BA1A2864EB68EFEDEEF101DAB0EDF6D2B174F1C1EF + DBFD9DF3FD9DCFBD39DF7B8EC042030303040201AB29969252924AA5181D1D45 + D334D3390EAB068140809E9E1EB9058065E0DDD6D6D63F8686864C212C010A1A + 1E1E7E26806030E8C9E572BFA9AAFA4E28149A3483B03D53E74D281C0E7B745D + 3FA3AAAA1A0A855014657B0162B1186363631E5DD77F3783A8384001E2892F71 + F849886D01008846A384C3E19AC75FE28D02C4B60114202291488DAEEB13AAAA + BE3E3232525E0AB6A260306856AE91524EB4B5B5D55614C02ABEC160D00BDBB8 + 074AE97F80FF3680A6694C4F4F9FAF2480650AC6C7C7F1FBFDE781231503A8ED + 3B896BEF4100A40423739FBBDF7F060E8544DD7E9AECE0CC2F556A7D1CAEBD07 + 71BF7CB478E6EBE96433C296F29DFC8EEA4EF5AD396DF944DEB50365258D6FEE + 1CF5F3171140EA85B749BE740C80BAF9BFD875F52700967CED243BFB7858DBBA + C1630AA02FC6C9DDBC26ECBEDDD8DDDE2480BBAB97EA036FBE2684FCB12176E1 + AA6FEEDCBE6C4D0B0BAF9C400A1B8DB10B34CD9EA569F62C77FDAFB252BF0780 + 4CFD1E12873EE2F92BA7F1A46659EF31932D7DFA4BEE9C3A46F6C6E562D1D57E + 0821F85CE8B92F7626FE9EB21979DC0F16D83D1521B5BF975257A47FDA8FD232 + F32BDEE475CAF598A640385D00FB6CABDA94B272AF58AF5A5EC4B03B311C2ED3 + 66394F13EE747C4DED691EAB18DA917255AC6317522245099B1008B9F15DAD3C + 56000642D8D6B793982F5218351BB1F2980248C3004848BBB323AF788A75AD7A + 2720B1E5B3A6CD9C2B69B2DEE7D6D49EE63105D06FCF22A5FCD670547DB3D4FC + 623B80EEF290E8FA90C6E864C948354627B973E03D1E3E8628C763FA27CC5CFC + 056FEFC7679CBE5DBE85AE0F82C9CE3E0C874243EC4F9A6F4C946805DEE475F2 + 8A87F9C39F809465798A00F9549CDCCD6B2DC6D23D642EC3E2D7C7697AFFD348 + 6776DEEFD032A7EC5A069B91DFD0A0217E8986F8A5E273FDAD29EA6E5D265FE5 + A594C714E0FECF5FAD19584D27A999FC811D1D1D188FF644D912489CD90765CD + B53C0D070707E9EFEF3FB2A9D537294B004551E8EEEEAE2880E5712CC4A3BD5B + E2665B7980783CCECCCC4CA9046D59B1588C7F0180E47C14881EF7A900000000 + 49454E44AE426082} + end + item + Image.Data = { + 89504E470D0A1A0A0000000D49484452000000280000002808060000008CFEB8 + 6D0000000473424954080808087C08648800000541494441545885ED986D6C53 + 5518C77FE7B65B5FE860A5EBC65E1CCB0ACB58A268DB21213831A2488CC688AF + 916834B22F2646E38231D907C9A289FB3020C684B489511213F48341F1054616 + 504294B82D0B090EE718B0B7EEA5ACA35B6FB775BDC70F5B8B4BD7AE30C688F1 + FFADF73CCF737EF7DF7B9F73CF11A4A1BD7BF762B55AD3095D50524A005455A5 + A1A101555553C6EBD329BA63C70E0A0B0B4F2D1E2F0E3802EC292F2F1FA9AEAE + 4E0929D229DAD4D4446161A16C6E6E2610082C0AD06AB5E276BB9152B6028FB5 + B4B4A4844CCBC1989A9B9BE9EAEA5A14606969296EB79BFEFE7E674141C14997 + CBB5DDE3F10492412A8B9A6D11F27ABDF87C3E2770D2E572593D1E0F66B33921 + 6ED9005555C5E3F1E0F3F95C40A3D3E9CC9E0F72D900610EA45B087132066932 + 99E231CB0A0809908D4EA733DBEBF5C69D5C76409881F47ABD0C0C0C540A214E + 389DCE553127EF0A4080502884C7E361606060D3AC93ABEAEAEA6EAECDDC4ED5 + D7D7A71ADE0478ED76FB0B771CB0BFBF9F43870EA58C71BBDDB85C2E3BDC64A3 + BE1D9A989858B0D93B1C0E84100821EE9E673099FE075CACFE1B809AA62D3547 + 52A505A8AA2A478E1CA9E9EEEE5E6A9E04A5D5666A6A6AA8A8A8F0C73ED7EFA4 + F496AA17319655C62FC420025F7F8C361E0045C798CD41446F441F09DF794063 + 592596ADCFED07EEFF17E0F3A3470FF8456412FBBB5F6074DC67E9F17756C592 + 56F82F61BB7C16DDF444BC50B76B3711F38D8D55E9994FE3FB098960B4C849B0 + E05EA219268CD77DD8BACE6050AF2D08187B06DBA494A7A594E78510DB000380 + F5957D98CA2A8BA5DED0A65A8B776786FC6486FC5C2B7D888E47DF67D26C8B17 + 3207AE62F1779219BA46C8BE9ED87647133AAE6CA9A6CFF912CAF414A6D15E42 + 390E3AB67F4030AF626107D5D646A6FDBD5F0A531696EDAF3B743AF13680625E + 8965CB3320382CB468F79A0BC71A6C57CF7D06907FE1185736EFA1A7F2551CBF + EC4700395D670018B7951228D91C9F60A8FC71C2D945AC6FFA0443C83FEB280C + 543C49F7A6D7283F51877E6A3CB9836A6B23A3470F106CFC7CCE4046611928BA + 3221C4C34A64E22DCB7067289E148D50D8F60DEAEA122656E6272D2EA564A464 + 0BB9EDC7E370CC7ABBE6CF9FD04DA98C163D90D2C1A46D46E8F40821D6492943 + 4A74AA3D233C77BB6908F9512261A656E4242DAEE90D4C9B56610EF424D64762 + BADECBA4C57E6B80B3D20311A48622139BB59051A4A24B9E2D9478DCBCC39A16 + 8FB955C065D74280112013A120E7B953A9E811DAFCEEC00DE792B92C151D629E + 7F262D40199D464A79113069FA4CE794297BCE7878653E51BD11C3D860F2E2D1 + 0819EA08215B69C2982674A8D6B5188203B70618E9EB00E465E0472DC3E819CF + 591F7F9AA733CCF43A5F266BE82F8CE3432927B05DFA95C1F22750B38BE2D7A4 + 50E8DFB80BA92864F7B6A6CC4FBA166B6A90D0B91F58F1E0536F2074C77D1B9F + AD1FCFDB0048C6F33690A106B8A7D99BB23880FDEF534CACCCA773DB7B640D5D + 443F3946C8B68E68A68992DFBC7356A3740047A4941F02418091C3B5E873D70E + 9B8A376CB60CB6D72BD1C97700F2CF7F4B764F0BCA3C6F67A61A20AFFD6766DA + F14C3B296EF90A6BF71F04F36796BAD597CFB2FAEAEFE8A74209F94901353548 + F0FB8301605FECB70C8F31F8D12ED66C7D3A526137B4E923A90F1B0132C331C0 + B9CA1AEE206BB863C1FCA480323CC6F5EF0E26466851D64EF663D00A48FEBE2E + 9DD2EA83B5B5B5ECDCB973ABC562596A9E04A50568341AA9AAAA7A33373777A9 + 791294D617B5A2CCDC87DBEDC6E1702C2910CC9CC2C67433270BA7DD6EF7EDA7 + 49AE364813B0ADAD8DBEBEBE4796962751EDEDEDFC032BE00ABBBB09BB8C0000 + 000049454E44AE426082} + end + item + Image.Data = { + 89504E470D0A1A0A0000000D49484452000000300000003008060000005702F9 + 870000000473424954080808087C08648800000721494441546881ED596D6C5B + 67157ECEFDF0C78DF39D344D0B4BD39691385D534651D76D40B435A6C09826F1 + 21A0F0A71542489D46C5A8862AE84AD950954DA23FD03491649A8AF60FB573A2 + 090853438857600BA02CC9E846DC36CD9AD464B61327767CED7B0F3F623B37B1 + DD7BED369391767E58E7BEE7DC73DF739FE73DEFB9AF09164596651C3B76CCAA + 7BD1A2691ABABBBB313F3F6FC99FAC0656140523232320A293E931660611E5D5 + CDECEB7D01CC00F8CDF8F8381F3972C4521205270040B77A4F91F23C331F9F98 + 98E0C3870F636161E196CEC520C0030303181818003333A55E652EDDCC6ED43B + 3B3B71E0C081F47DCFA593304342B09AC0872543434300F023223AD3D6D6869E + 9E1E545656E6F52F38013688F13A976E665FE7CB00D0DFDFCFC3C3C300F02480 + 336EB71BBDBDBDA8A8A8B8330990418CD7B97433FB3ADF349DA9AFAF8F868787 + 4144C789E84C6B6B2BF5F6F6E644A2E4289496BEBE3EA490F83111FD321F9D4A + 8E42C6F05EAF977D3E1F001C07F0ACDBED464F4FCF1A3A951C858CE300C8EBF5 + 92CFE703113D4544CFA6D7441A8992A59051BC5E2F7C3E1F01788A889E31D249 + 2A34581ADE14FA19AAE4D3CDEC5675AFD7CB4484FDFBF7FF0480EE76BB7F7AE2 + C489C21348239CDAFEEFD846969E7357579715FF1300FC2E97EBA58213D82899 + 9C9CB4DC3B793C1E02701780C211D828F1FBFD989C9CB49A00D22CF8BF5903F9 + F49229A345E8C525506AF211853EA2D06D4A41144A2412884422FF0A0683EDA5 + 42A18212080402E8EFEFFFA1DFEF1FA40DD8898BD8B9AD53281A8DE2D0A143E9 + 1D938D6F389F6E66BF4D1D002039F73C0C47CB7DAB33E5CC0F162F5D40626A22 + 6520880DCDD0251B442D61E92D7D1808488E96FB5079F07B9F67E60E5A3D9F01 + 80B3F1AB63E1C4D40484B22AD41E7D118E6DAD085CBB546D8B8690B497C1160D + C375F31DC8EAE21AB412CE2A849AEF0763F53BB17C660C4AF8FA1A3F5D10B158 + 7F37962BB680588312BC0625781504865591525975003869983C98F965006188 + 12363D790EB6A6369B0674053EE9F941062200A2A6F2A689D750FF9F8B19DA24 + 9C55986D3998F66100109717E00C4D65EE5BAAD9C6D73FFD1DC45DF530C62B0B + 5EE18FBF790EB6A539EB8B98884E31F3A91523BE4B8497D330B91EFC1A6C4D6D + 20A25E00DF5282575EBFEBADDF76CAB110E2E59BF966CB1768F69EC7C082C40D + EF0E100028C1ABDC7EFE0962664E3A2AE89D2FFD020032D0C72AB7B2FFC1A324 + C7C2D8F6D76E76052E130B12E6B7ECE6D95D8F92FF738F63E7C5E7598E47CC17 + F1C21F7A70E3E4239879FA2B88F8CE6741A4ECFD2288E86180BE2D24E33FABF5 + FB9EB12FCD41D03538C2D368FADB4BA89C1E41A0F5205467B519E26000EFB77F + 1562228A1D436751716314A2A6424A445173F512B60FFF1A497B396EB61E348D + 050082169A857A6D0CEAB53168F373AB0F4AC1246DBD1B00BE09F01C25E3CF29 + C12B6B2A0258E7CDE3FD9C7E83EBAB506ACE99B184B38AA3B5DB51FFDE459696 + 17B22A8C233CCD55D3FFE0F0C7EE05A74CEB7D8C8FCF5B4633DBF6CA32DC0160 + 5CD0D4B82D1ACADAD6EDD120896A146A595D562B8195759C1953CBEA88417086 + AFE76D139CA1EBA4C90A3459B963AD840D804ABA0E622D77C27A122C88A681D2 + 3EA4E78E938E65F4BD95E4DD893318198E7F53AB086CA81ACCCC585D53ABCC5A + 4BA1F56330B0236F85C913CF5A379AC1C8F8C81543369C866341330A21E39B45 + 899CC78C778A428B002A5910C14236680C40931D1034D53490908C0329FF7CA2 + C90E10602D5E3E4366C5275500FC4F00EDBA646B8C97D5655584A5DA1DAC8B36 + 38C3D3A655C81EB9C9829E44A4C19DBBC2001C6970B36D690E42327EFB55489D + 9A0033BA0140979DDD4B753B9D4638938E727AFF53DF20391646C58D51530A49 + 8918554DBD8960F303B4D8D092458F0FB67F9696EA3F41B59343200B14326DA7 + A323BF8772AF6792991F8720BD1068F1EC6351861C0B61B97C3382CD0F40931D + 687EE34588162007802D6FBF8A584D13AEDCFF7D544FBD05D77F2F830509F38D + BB1169DC858A99B751E7FF8BA558A655287AE902A29F7904CA9E87BAC1FA9426 + 2B5D33F73C56B3D2A8315C8177B971EC5538C2D3D9D529A5AE1F131251ECF8F3 + 599E757F19A1A67D0836ED5BD934E38B6818EFE74DEFBD0EE85ABE78A61F34E7 + 98F99CA1DDC0DC0B4751FDF5E3A8DEFFE81FB7FCFBB57879E0F260D25E063936 + CF522246A959E66CA7E57884769F7F22AB9F1193CBB475F477681CBBC0AA524B + C43A6C4B1F3081F3C65BAF6725B0F8A75EC4FEEECD5C27E752ED6F6219A1577E + 0EFB1BAFA0BA7D178875C8F1C84AEB6D48B418212D09C76200A9C9151C6F4D02 + 5A68165A6836A7A3288AD8D3B213364984AA6A96BF5BCDECB7AB5BFEA4B4DBED + 387DFA343A3A3AF6D4D4D4DCAA3A94EEB18AA228E8ECECFCD5DEBD7B0BB96D43 + A5A0530941104AEE64AEA83F383C1E0F3C1E4F697CD4179A0080A78BB8672364 + 102820014DD33038380800A736663E85CBE8E828FE07E40A8D8C3A7B42960000 + 000049454E44AE426082} + end> end> Left = 152 Top = 80 diff --git a/Server/Units/Forms/uFormMain.pas b/Server/Units/Forms/uFormMain.pas index a038c5e..0fc11da 100644 --- a/Server/Units/Forms/uFormMain.pas +++ b/Server/Units/Forms/uFormMain.pas @@ -50,6 +50,9 @@ - Ternary operator *) +Bug to fix on file manager folder tree with the "Go To" function: do the same thing as for Registry + + unit uFormMain; interface diff --git a/Server/Units/Optix.Constants.pas b/Server/Units/Optix.Constants.pas index 262eeba..95e7b88 100644 --- a/Server/Units/Optix.Constants.pas +++ b/Server/Units/Optix.Constants.pas @@ -109,6 +109,8 @@ interface IMAGE_SERVER_LISTENING = 64; IMAGE_SERVER_ERROR = 65; IMAGE_BUG = 66; + IMAGE_REG_SZ = 68; + IMAGE_REG_DATA = 69; var (* COLORS *) diff --git a/Server/Units/Optix.Helper.pas b/Server/Units/Optix.Helper.pas index 3a4238e..345921c 100644 --- a/Server/Units/Optix.Helper.pas +++ b/Server/Units/Optix.Helper.pas @@ -56,11 +56,10 @@ procedure Open(const ACommand : String); procedure CheckCertificateFingerprint(const AValue : String); function CompareObjectAssigmenet(const AObject1, AObject2 : TObject) : Integer; +function ComparePointerAssigmenet(const pPtr1, pPtr2 : Pointer) : Integer; function CompareDateTimeEx(const ADate1 : TDateTime; const ADate1IsSet : Boolean; const ADate2 : TDateTime; const ADate2IsSet : Boolean) : Integer; -function IncludeTrailingPathDelimiterIfNotEmpty(const AValue : String) : String; - implementation // --------------------------------------------------------------------------------------------------------------------- @@ -69,15 +68,6 @@ implementation Winapi.Windows; // --------------------------------------------------------------------------------------------------------------------- -{ _.IncludeTrailingPathDelimiterIfNotEmpty } -function IncludeTrailingPathDelimiterIfNotEmpty(const AValue : String) : String; -begin - if not String.IsNullOrWhiteSpace(AValue) then - result := IncludeTrailingPathDelimiter(AValue) - else - result := AValue; -end; - { _.CompareDateTimeEx } function CompareDateTimeEx(const ADate1 : TDateTime; const ADate1IsSet : Boolean; const ADate2 : TDateTime; const ADate2IsSet : Boolean) : Integer; begin @@ -102,6 +92,17 @@ function CompareObjectAssigmenet(const AObject1, AObject2 : TObject) : Integer; Result := -1 end; +{ _.ComparePointerAssigmenet } +function ComparePointerAssigmenet(const pPtr1, pPtr2 : Pointer) : Integer; +begin + if (pPtr1 = nil) and (pPtr2 = nil) then + Result := 0 + else if pPtr1 <> nil then + Result := 1 + else + Result := -1 +end; + { _.CheckCertificateFingerprint } procedure CheckCertificateFingerprint(const AValue : String); begin diff --git a/Server/Units/Optix.VCL.Helper.pas b/Server/Units/Optix.VCL.Helper.pas index 9fd1dcb..07f52b7 100644 --- a/Server/Units/Optix.VCL.Helper.pas +++ b/Server/Units/Optix.VCL.Helper.pas @@ -38,7 +38,11 @@ TOptixVirtualTreesHelper = class public class function GetVisibleNodesCount(const AVST : TVirtualStringTree) : UInt64; static; class function GetColumnIndexByName(const AVST : TVirtualStringTree; const AName : String) : Integer; static; - class procedure UpdateColumnVisibility(const AVST : TVirtualStringTree; const AName : String; AVisible : Boolean); static; + class procedure UpdateColumnVisibility(const AVST : TVirtualStringTree; const AName : String; + AVisible : Boolean); static; + class function GetRootParentNode(const AVST : TVirtualStringTree; + const pNode : PVirtualNode) : PVirtualNode; static; + class procedure SelectNode(const AVST : TVirtualStringTree; const pNode : PVirtualNode); static; end; implementation @@ -97,6 +101,37 @@ class procedure TOptixVirtualTreesHelper.UpdateColumnVisibility(const AVST : TVi AColumn.Options := AColumn.Options - [coVisible]; end; +{ TOptixVirtualTreesHelper.GetRootParentNode } +class function TOptixVirtualTreesHelper.GetRootParentNode(const AVST : TVirtualStringTree; + const pNode : PVirtualNode) : PVirtualNode; +begin + result := nil; + /// + + if not Assigned(pNode) or not Assigned(AVST) then + Exit(); + + result := pNode; + + while Assigned(AVST.NodeParent[result]) do + result := AVST.NodeParent[result]; +end; + +{ TOptixVirtualTreesHelper.SelectNode } +class procedure TOptixVirtualTreesHelper.SelectNode(const AVST : TVirtualStringTree; const pNode : PVirtualNode); +begin + if not Assigned(AVST) or not Assigned(pNode) then + Exit(); + /// + + AVST.ClearSelection(); + /// + + AVST.FocusedNode := pNode; + AVST.Selected[pNode] := True; + AVST.ScrollIntoView(pNode, True); +end; + (* TOptixVCLHelper *) { TOptixVCLHelper.UpdatePopupMenuRootItemsVisibility } diff --git a/Shared/Functions/Optix.Func.Commands.Registry.pas b/Shared/Functions/Optix.Func.Commands.Registry.pas index 58ba0a7..2e2b3ca 100644 --- a/Shared/Functions/Optix.Func.Commands.Registry.pas +++ b/Shared/Functions/Optix.Func.Commands.Registry.pas @@ -67,8 +67,9 @@ TOptixRefreshRegistryKeys = class(TOptixCommandActionResponse) [OptixSerializableAttribute] FPermissions : TRegistryKeyPermissions; - FKeys : TObjectList; - FValues : TObjectList; + FParentKeys : TObjectList; + FSubKeys : TObjectList; + FValues : TObjectList; {@M} function GetIsRoot() : Boolean; @@ -87,7 +88,8 @@ TOptixRefreshRegistryKeys = class(TOptixCommandActionResponse) {@G} property IsRoot : Boolean read GetIsRoot; property Path : String read FPath; - property Keys : TObjectList read FKeys; + property ParentKeys : TObjectList read FParentKeys; + property SubKeys : TObjectList read FSubKeys; property Values : TObjectList read FValues; property Permissions : TRegistryKeyPermissions read FPermissions; end; @@ -106,6 +108,11 @@ TOptixRefreshRegistrySubKeys = class(TOptixRefreshRegistryKeys) implementation +// --------------------------------------------------------------------------------------------------------------------- +uses + Optix.System.Helper; +// --------------------------------------------------------------------------------------------------------------------- + (*********************************************************************************************************************** TOptixRefreshRegistryKeys @@ -118,9 +125,13 @@ procedure TOptixRefreshRegistryKeys.DeSerialize(const ASerializedObject : ISuper inherited; /// - FKeys.Clear(); - for var I := 0 to ASerializedObject.A['Keys'].Length -1 do - FKeys.Add(TRegistryKeyInformation.Create(ASerializedObject.A['Keys'].O[I])); + FParentKeys.Clear(); + for var I := 0 to ASerializedObject.A['ParentKeys'].Length -1 do + FParentKeys.Add(TRegistryKeyInformation.Create(ASerializedObject.A['ParentKeys'].O[I])); + + FSubKeys.Clear(); + for var I := 0 to ASerializedObject.A['SubKeys'].Length -1 do + FSubKeys.Add(TRegistryKeyInformation.Create(ASerializedObject.A['SubKeys'].O[I])); FValues.Clear(); for var I := 0 to ASerializedObject.A['Values'].Length -1 do @@ -135,10 +146,19 @@ function TOptixRefreshRegistryKeys.Serialize() : ISuperObject; var AJsonArray := TSuperArray.Create(); - for var AItem in FKeys do + for var AItem in FParentKeys do + AJsonArray.Add(AItem.Serialize); + + result.A['ParentKeys'] := AJsonArray; + + /// + + AJsonArray := TSuperArray.Create(); + + for var AItem in FSubKeys do AJsonArray.Add(AItem.Serialize); - result.A['Keys'] := AJsonArray; + result.A['SubKeys'] := AJsonArray; /// @@ -156,8 +176,9 @@ constructor TOptixRefreshRegistryKeys.Create(); inherited Create(); /// - FKeys := TObjectList.Create(True); - FValues := TObjectList.Create(True); + FParentKeys := TObjectList.Create(True); + FSubKeys := TObjectList.Create(True); + FValues := TObjectList.Create(True); FPath := ''; FPermissions := []; @@ -169,15 +190,18 @@ constructor TOptixRefreshRegistryKeys.Create(const APath : String); Create(); /// - FPath := APath; + FPath := ExcludeTrailingPathDelimiter(APath); TRegistryHelper.TryGetCurrentUserRegistryKeyAccess(FPath, FPermissions); end; { TOptixRefreshRegistryKeys.Destroy } destructor TOptixRefreshRegistryKeys.Destroy(); begin - if Assigned(FKeys) then - FreeAndNil(FKeys); + if Assigned(FParentKeys) then + FreeAndNil(FParentKeys); + + if Assigned(FSubKeys) then + FreeAndNil(FSubKeys); if Assigned(FValues) then FreeAndNil(FValues); @@ -202,7 +226,7 @@ function TOptixRefreshRegistryKeys.GetIsRoot() : Boolean; procedure TOptixGetRegistryHives.DoAction(); begin for var AHive in TRegistryHelper.RegistryHives.Keys do - FKeys.Add(TRegistryKeyInformation.Create(AHive, AHive)); + FSubKeys.Add(TRegistryKeyInformation.Create(AHive, AHive)); end; (*********************************************************************************************************************** @@ -214,7 +238,34 @@ procedure TOptixGetRegistryHives.DoAction(); { TOptixRefreshRegistrySubKeys.DoAction } procedure TOptixRefreshRegistrySubKeys.DoAction(); begin - TOptixEnumRegistry.Enum(FPath, FKeys, FValues); + var ADirectories := TStringList.Create(); + try + TRegistryHelper.CheckRegistryPath(FPath); + /// + + ADirectories.Delimiter := '\'; + ADirectories.DelimitedText := FPath; + + FParentKeys.Clear(); + + var ACurrentPath := ''; + for var ADirectory in ADirectories do begin + if ADirectory.IsEmpty then + continue; + /// + + ACurrentPath := TSystemHelper.IncludeTrailingPathDelimiterIfNotEmpty(ACurrentPath) + ADirectory; + + /// + FParentKeys.Add(TRegistryKeyInformation.Create(ADirectory, ACurrentPath)); + end; + finally + if Assigned(ADirectories) then + FreeAndNil(ADirectories); + end; + + /// + TOptixEnumRegistry.Enum(FPath, FSubKeys, FValues); end; end. diff --git a/Shared/Optix.Registry.Enum.pas b/Shared/Optix.Registry.Enum.pas index a3393df..5e889eb 100644 --- a/Shared/Optix.Registry.Enum.pas +++ b/Shared/Optix.Registry.Enum.pas @@ -90,17 +90,22 @@ TRegistryValueInformation = class(TOptixSerializableObject) [OptixSerializableAttribute] FType : DWORD; + + {@M} + function GetIsDefault() : Boolean; + function GetValue() : String; public {@C} - constructor Create(const AHive : HKEY; const APath : String; const AName, AValue : String; AType : DWORD); overload; + constructor Create(const AName, AValue : String; AType : DWORD); overload; {@M} procedure Assign(ASource : TPersistent); override; {@G} - property Name : String read FName; - property Value : String read FValue; - property _Type : DWORD read FType; + property Name : String read FName; + property Value : String read GetValue; + property _Type : DWORD read FType; + property IsDefault : Boolean read GetIsDefault; end; TOptixEnumRegistry = class @@ -109,6 +114,9 @@ TOptixEnumRegistry = class var AValues : TObjectList); static; end; + const + REG_MSZ_LINE_SEP = '{/\$/\@/\0\n/%\//\!/\}'; + implementation // --------------------------------------------------------------------------------------------------------------------- @@ -154,7 +162,7 @@ procedure TRegistryKeyInformation.Assign(ASource : TPersistent); ***********************************************************************************************************************) { TRegistryValueInformation.Create } -constructor TRegistryValueInformation.Create(const AHive : HKEY; const APath : String; const AName, AValue : String; AType : DWORD); +constructor TRegistryValueInformation.Create(const AName, AValue : String; AType : DWORD); begin inherited Create(); /// @@ -176,6 +184,21 @@ procedure TRegistryValueInformation.Assign(ASource : TPersistent); inherited; end; +{ TRegistryValueInformation.GetIsDefault } +function TRegistryValueInformation.GetIsDefault() : Boolean; +begin + result := FName.IsEmpty(); +end; + +{ TRegistryValueInformation.GetValue } +function TRegistryValueInformation.GetValue() : String; +begin + if FType = REG_MULTI_SZ then + result := FValue.Replace(REG_MSZ_LINE_SEP, #13#10, [rfReplaceAll]) + else + result := FValue; +end; + (*********************************************************************************************************************** TOptixEnumRegistry @@ -250,13 +273,13 @@ class procedure TOptixEnumRegistry.Enum(const AKeyFullPath : String; var AKeys : Inc(AMaxKeyNameLength); Inc(AMaxValueNameLength); - var ABufferSize := 0; + var ABufferSize : DWORD; if AMaxKeyNameLength > AMaxValueNameLength then ABufferSize := AMaxKeyNameLength * SizeOf(WideChar) else ABufferSize := AMaxValueNameLength * SizeOf(WideChar); - var pNameBuffer : PWideChar := nil; + var pNameBuffer : PWideChar; GetMem(pNameBuffer, ABufferSize); try // Enumerate SubKeys @@ -278,6 +301,8 @@ class procedure TOptixEnumRegistry.Enum(const AKeyFullPath : String; var AKeys : end; // Enumerate Key-Values + var ADefaultValueExists := False; + if AValuesCount > 0 then begin for var I := 0 to AValuesCount -1 do begin ZeroMemory(pNameBuffer, AMaxKeyNameLength * SizeOf(WideChar)); @@ -292,14 +317,14 @@ class procedure TOptixEnumRegistry.Enum(const AKeyFullPath : String; var AKeys : var AValueName := String(pNameBuffer); var AValueType : DWORD; var AValueDataSize : DWORD; - var AData : String; + var AData := ''; ARet := RegGetValueW(hOpenedKey, nil, PWideChar(AValueName), RRF_RT_ANY, AValueType, nil, AValueDataSize); if ARet = ERROR_SUCCESS then begin var pData : Pointer; GetMem(pData, AValueDataSize * SizeOf(WideChar)); try - RegGetValueW( + ARet := RegGetValueW( hOpenedKey, nil, PWideChar(AValueName), @@ -308,20 +333,60 @@ class procedure TOptixEnumRegistry.Enum(const AKeyFullPath : String; var AKeys : pData, AValueDataSize ); + if ARet <> ERROR_SUCCESS then + continue; + + if AValueName.IsEmpty then + ADefaultValueExists := True; case AValueType of - REG_SZ : begin + REG_SZ, REG_EXPAND_SZ: AData := String(PWideChar(pData)); - end; - REG_DWORD : AData := IntToStr(PDWORD(pData)^); - REG_QWORD : AData := IntToStr(PUInt64(pData)^); + REG_MULTI_SZ: begin + var AStringList := TStringList.Create(); + try + var p := PWideChar(pData); + while p^ <> #0 do begin + AStringList.Add(String(p)); + + /// + Inc(p, lstrlenW(p) + 1); + end; + + /// + AStringList.LineBreak := REG_MSZ_LINE_SEP; + AData := AStringList.Text; + finally + if Assigned(AStringList) then + FreeAndNil(AStringList); + end; + end; - // TODO: ... handle other value types ... // + REG_DWORD: + AData := Format('0x%.8X (%d)', [PDWORD(pData)^, PDWORD(pData)^]); + + REG_QWORD: + AData := Format('0x%.16X (%d)', [PUInt64(pData)^, PUInt64(pData)^]); + + REG_BINARY: begin + var AStringBuilder := TStringBuilder.Create(AValueDataSize * 3 (* 1 Byte = 2 (Hex) + 1 (Space) *)); + try + for var n := 0 to AValueDataSize -1 do begin + AStringBuilder.AppendFormat('%.2X ', [PByte(NativeUInt(pData) + n)^]); + end; + + /// + AData := AStringBuilder.ToString.TrimRight; + finally + if Assigned(AStringBuilder) then + FreeAndNil(AStringBuilder); + end; + end; end; /// - //AValues.Add(TRegistryValueInformation.Create(AHive, APath, AValueName, AData, AValueType)); + AValues.Add(TRegistryValueInformation.Create(AValueName, AData, AValueType)); finally FreeMem(pData, AValueDataSize); end; @@ -329,6 +394,10 @@ class procedure TOptixEnumRegistry.Enum(const AKeyFullPath : String; var AKeys : AData := ''; end; end; + + /// + if not ADefaultValueExists then + AValues.Add(TRegistryValueInformation.Create('', '', REG_SZ)); finally FreeMem(pNameBuffer, ABufferSize); end; diff --git a/Shared/Optix.Registry.Helper.pas b/Shared/Optix.Registry.Helper.pas index 8d273b0..cfdb306 100644 --- a/Shared/Optix.Registry.Helper.pas +++ b/Shared/Optix.Registry.Helper.pas @@ -84,6 +84,8 @@ TRegistryHelper = class class procedure TryGetCurrentUserRegistryKeyAccess(const AKeyFullPath : String; var ARegistryKeyPermissions : TRegistryKeyPermissions); static; class function HiveToString(const AHive : HKEY) : String; static; + class function ExpandHiveShortName(const AKeyFullPath : String) : String; static; + class procedure CheckRegistryPath(const AKeyFullPath : String); static; {@G} class property RegistryHives : TDictionary read FRegistryHives; @@ -138,7 +140,7 @@ class procedure TRegistryHelper.ExtractKeyPathInformation(const AFullPath: Strin /// if not Assigned(FRegistryHives) or not FRegistryHives.TryGetValue(AHiveName, AHive) then - raise Exception.Create(Format('Registry hive "%s" is not valid.', [AHiveName])); + raise Exception.Create(Format('"%s" is not a valid registry hive.', [AHiveName])); end; { TRegistryHelper.GetRegistryACLString } @@ -320,4 +322,45 @@ class function TRegistryHelper.HiveToString(const AHive : HKEY) : String; result := APair.Key; end; +class function TRegistryHelper.ExpandHiveShortName(const AKeyFullPath : String) : String; +const + HIVES_MAP : array[0..7-1, 0..2-1] of String = ( + ('HKCR\', 'HKEY_CLASSES_ROOT\'), + ('HKCU\', 'HKEY_CURRENT_USER\'), + ('HKLM\', 'HKEY_LOCAL_MACHINE\'), + ('HKU\', 'HKEY_USERS\'), + ('HKPD\', 'HKEY_PERFORMANCE_DATA\'), + ('HKCC\', 'HKEY_CURRENT_CONFIG\'), + ('HKDD\', 'HKEY_DYN_DATA\') + ); +begin + result := AKeyFullPath; + /// + + for var i := 0 to High(HIVES_MAP) do begin + if AKeyFullPath.StartsWith(HIVES_MAP[i, 0]) then begin + Result := HIVES_MAP[i, 1] + Copy(AKeyFullPath, Length(HIVES_MAP[i, 0]) + 1, MaxInt); + + Break; + end; + end; +end; + +{ TRegistryHelper.CheckRegistryPath } +class procedure TRegistryHelper.CheckRegistryPath(const AKeyFullPath : String); +begin + var AHive : HKEY; + var AKeyPath := ''; + + ExtractKeyPathInformation(AKeyFullPath, AHive, AKeyPath); + + var AKeyHandle : HKEY; + + var AResult := RegOpenKeyExW(AHive, PWideChar(AKeyPath), 0, READ_CONTROL, AKeyHandle); + if AResult <> ERROR_SUCCESS then + raise EWindowsException.Create('RegOpenKeyW', AResult); + + RegCloseKey(AKeyHandle); +end; + end. diff --git a/Shared/Optix.System.Helper.pas b/Shared/Optix.System.Helper.pas index 86eb63c..a1d3ba4 100644 --- a/Shared/Optix.System.Helper.pas +++ b/Shared/Optix.System.Helper.pas @@ -50,16 +50,19 @@ interface Winapi.Windows; // --------------------------------------------------------------------------------------------------------------------- +// If you wonder, static keyword in Delphi means cannot change. + type TSystemHelper = class public {@M} class function FileTimeToDateTime(const AFileTime: TFileTime) : TDateTime; static; class function TryFileTimeToDateTime(const AFileTime: TFileTime) : TDateTime; static; - class procedure NTSetPrivilege(const APrivilegeName: string; const AEnabled: Boolean); - class procedure TryNTSetPrivilege(const APrivilegeName: string; const AEnabled: Boolean); + class procedure NTSetPrivilege(const APrivilegeName: string; const AEnabled: Boolean); static; + class procedure TryNTSetPrivilege(const APrivilegeName: string; const AEnabled: Boolean); static; class function AccessCheck(ADesiredAccess : DWORD; const hToken : THandle; - const ptrSecurityDescriptor : PSecurityDescriptor) : Boolean; + const ptrSecurityDescriptor : PSecurityDescriptor) : Boolean; static; + class function IncludeTrailingPathDelimiterIfNotEmpty(const AValue : String) : String; static; end; implementation @@ -174,4 +177,13 @@ class function TSystemHelper.AccessCheck(ADesiredAccess : DWORD; const hToken : result := AStatus; end; +{ TSystemHelper.IncludeTrailingPathDelimiterIfNotEmpty } +class function TSystemHelper.IncludeTrailingPathDelimiterIfNotEmpty(const AValue : String) : String; +begin + if not String.IsNullOrWhiteSpace(AValue) then + result := IncludeTrailingPathDelimiter(AValue) + else + result := AValue; +end; + end. From 34a7afe29558db71921a19b41c0dd3a6c442bae5 Mon Sep 17 00:00:00 2001 From: DarkCoderSc Date: Sat, 4 Oct 2025 10:24:48 +0200 Subject: [PATCH 4/6] Folder Tree Generic Method --- .../Control/uControlFormRegistryManager.dfm | 3 + .../Control/uControlFormRegistryManager.pas | 145 ++++++------------ Server/Units/Forms/uFormMain.pas | 3 +- Server/Units/Optix.VCL.Helper.pas | 116 +++++++++++++- 4 files changed, 166 insertions(+), 101 deletions(-) diff --git a/Server/Units/Forms/Control/uControlFormRegistryManager.dfm b/Server/Units/Forms/Control/uControlFormRegistryManager.dfm index 78b1bd7..af89d11 100644 --- a/Server/Units/Forms/Control/uControlFormRegistryManager.dfm +++ b/Server/Units/Forms/Control/uControlFormRegistryManager.dfm @@ -34,6 +34,8 @@ object ControlFormRegistryManager: TControlFormRegistryManager MinPosition = 0.020000000000000000 Align = alClient TabOrder = 0 + ExplicitWidth = 701 + ExplicitHeight = 368 DesignSize = ( 711 400) @@ -143,6 +145,7 @@ object ControlFormRegistryManager: TControlFormRegistryManager BevelOuter = bvRaised ReadOnly = True TabOrder = 1 + ExplicitWidth = 693 end object MainMenu: TMainMenu Left = 408 diff --git a/Server/Units/Forms/Control/uControlFormRegistryManager.pas b/Server/Units/Forms/Control/uControlFormRegistryManager.pas index 9e3df53..c3e0ac2 100644 --- a/Server/Units/Forms/Control/uControlFormRegistryManager.pas +++ b/Server/Units/Forms/Control/uControlFormRegistryManager.pas @@ -175,113 +175,62 @@ procedure TControlFormRegistryManager.RefreshNodesVisibility(); end; procedure TControlFormRegistryManager.DisplayKeys(const AList : TOptixRefreshRegistryKeys); - - function GetLevelFolder(const AName : String; const pParent : PVirtualNode) : PVirtualNode; - begin - result := nil; - /// - - var pChildNode := VSTKeys.GetFirstChild(pParent); - while Assigned(pChildNode) do begin - var pData := PKeysTreeData(pChildNode.GetData); - if not Assigned(pData^.KeyInformation) then - continue; - /// - - if String.Compare(pData^.KeyInformation.Name, AName, True) = 0 then begin - result := pChildNode; - - break; - end; - - /// - pChildNode := VSTKeys.GetNextSibling(pChildNode); - end; - end; - - procedure CreateOrUpdateKeyNode(var pNode, pParentNode : PVirtualNode; const AKey : TRegistryKeyInformation); - begin - var pData : PKeysTreeData; - if not Assigned(pNode) then begin - pNode := VSTKeys.AddChild(pParentNode); - - pData := PKeysTreeData(pNode.GetData); - - pData^.KeyInformation := TRegistryKeyInformation.Create(); - - pData^.ImageIndex := SystemFolderIcon(); - - if Assigned(pParentNode) then begin - var pParentData := PKeysTreeData(pParentNode.GetData); - - pData^.Path := TSystemHelper.IncludeTrailingPathDelimiterIfNotEmpty(pParentData^.Path) + AKey.Name; - end else - pData^.Path := AKey.Name; - end else - pData := PKeysTreeData(pNode.GetData); - - /// - if Assigned(pData^.KeyInformation) then - pData^.KeyInformation.Assign(AKey); - end; - begin if not Assigned(AList) and (AList.SubKeys.Count > 0) then Exit(); /// - var pParentNode := PVirtualNode(nil); - var pNode : PVirtualNode; - - VSTKeys.BeginUpdate(); try - // Generate or Update Parent Keys Tree - for var AItem in AList.ParentKeys do begin - var pChildNode := PVirtualNode(nil); - - pNode := VSTKeys.GetFirstChild(pParentNode); - while Assigned(pNode) do begin - var pData := PKeysTreeData(pNode.GetData); - if not Assigned(pData) or not Assigned(pData^.KeyInformation) then - continue; - /// - - if String.Compare(pData^.KeyInformation.Name, AItem.Name, True) = 0 then begin - pChildNode := pNode; - - break; - end; - - /// - pNode := VSTKeys.GetNextSibling(pNode); - end; - - /// - CreateOrUpdateKeyNode(pChildNode, pParentNode, AItem); - - pParentNode := pChildNode; - end; - - // Generate or Update Sub Keys Tree - for var AItem in AList.SubKeys do begin - pNode := GetLevelFolder(AItem.Name, pParentNode); - - /// - CreateOrUpdateKeyNode(pNode, pParentNode, AItem); - end; + TOptixVirtualTreesFolderTreeHelper.UpdateTree( + VSTKeys, + AList.ParentKeys, + AList.SubKeys, + ( + function (const pData : Pointer) : String + begin + result := PKeysTreeData(pData)^.KeyInformation.Name; + end + ), + ( + function (const AItem: TRegistryKeyInformation): String + begin + if Assigned(AItem) then + result := AItem.Name + else + result := ''; + end + ), + ( + procedure (var pNode, pParentNode : PVirtualNode; const AItem : TRegistryKeyInformation) + begin + var pData : PKeysTreeData; + if not Assigned(pNode) then begin + pNode := VSTKeys.AddChild(pParentNode); + + pData := PKeysTreeData(pNode.GetData); + + pData^.KeyInformation := TRegistryKeyInformation.Create(); + + pData^.ImageIndex := SystemFolderIcon(); + + if Assigned(pParentNode) then begin + var pParentData := PKeysTreeData(pParentNode.GetData); + + pData^.Path := TSystemHelper.IncludeTrailingPathDelimiterIfNotEmpty(pParentData^.Path) + AItem.Name; + end else + pData^.Path := AItem.Name; + end else + pData := PKeysTreeData(pNode.GetData); + + /// + if Assigned(pData^.KeyInformation) then + pData^.KeyInformation.Assign(AItem); + end + ) + ); finally - TOptixVirtualTreesHelper.SelectNode(VSTKeys, pParentNode); - - var pRootParent := TOptixVirtualTreesHelper.GetRootParentNode(VSTKeys, pParentNode); - if Assigned(pRootParent) then - VSTKeys.FullExpand(pRootParent); - - VSTKeys.SortTree(0, TSortDirection.sdAscending); - RefreshNodesVisibility(); - VSTKeys.EndUpdate(); - /// EditPath.Text := AList.Path; end; diff --git a/Server/Units/Forms/uFormMain.pas b/Server/Units/Forms/uFormMain.pas index 0fc11da..cb2ce92 100644 --- a/Server/Units/Forms/uFormMain.pas +++ b/Server/Units/Forms/uFormMain.pas @@ -50,8 +50,7 @@ - Ternary operator *) -Bug to fix on file manager folder tree with the "Go To" function: do the same thing as for Registry - +// TODO: Implement Generic Folder Tree code to File Manager Folder Tree (Actually a serious bug exists using the "Go To") unit uFormMain; diff --git a/Server/Units/Optix.VCL.Helper.pas b/Server/Units/Optix.VCL.Helper.pas index 07f52b7..6df8215 100644 --- a/Server/Units/Optix.VCL.Helper.pas +++ b/Server/Units/Optix.VCL.Helper.pas @@ -22,7 +22,7 @@ interface -uses VCL.Menus, VirtualTrees, VirtualTrees.Types, VCL.Forms, VirtualTrees.BaseTree; +uses VCL.Menus, VirtualTrees, VirtualTrees.Types, VCL.Forms, VirtualTrees.BaseTree, Generics.Collections; type TOptixVCLHelper = class @@ -45,10 +45,124 @@ TOptixVirtualTreesHelper = class class procedure SelectNode(const AVST : TVirtualStringTree; const pNode : PVirtualNode); static; end; + TOptixVirtualTreesFolderTreeHelper = class + type + TCompareFolderNameCallback = reference to function(const pData : Pointer; const ACompareTo : String) : Boolean; + TGetFolderNameFromItemCallback = reference to function(const AItem: T): String; + TGetFolderNameFromDataCallback = reference to function(const pData: Pointer): String; + TSetupNodeDataCallback = reference to procedure(var pNode, pParentNode : PVirtualNode; const AItem : T); + public + class procedure UpdateTree(const AVST : TVirtualStringTree; const AParentsItems: TEnumerable; + ALevelItems: TEnumerable; const AGetNameFromDataFunc : TGetFolderNameFromDataCallback; + const AGetNameFromItemFunc : TGetFolderNameFromItemCallback; + const ASetupNodeDataFunc : TSetupNodeDataCallback); static; + end; + implementation uses Winapi.Windows, Winapi.Messages, System.SysUtils; +(* TOptixVirtualTreesFolderTreeHelper *) + +{ TOptixVirtualTreesFolderTreeHelper.UpdateTree } +class procedure TOptixVirtualTreesFolderTreeHelper.UpdateTree(const AVST : TVirtualStringTree; + const AParentsItems: TEnumerable; ALevelItems: TEnumerable; + const AGetNameFromDataFunc : TGetFolderNameFromDataCallback; + const AGetNameFromItemFunc : TGetFolderNameFromItemCallback; + const ASetupNodeDataFunc : TSetupNodeDataCallback); +begin + if not Assigned(AVST) then + Exit(); + /// + + var pParentNode := PVirtualNode(nil); + var pChildNode := PVirtualNode(nil); + var pNode := PVirtualNode(nil); + + AVST.BeginUpdate(); + try + // Generate or Update Parent Folder Tree + for var AItem in AParentsItems do begin + pChildNode := nil; + + pNode := AVST.GetFirstChild(pParentNode); + while Assigned(pNode) do begin + if SameText(AGetNameFromDataFunc(pNode.GetData), AGetNameFromitemFunc(AItem)) then begin + pChildNode := pNode; + + break; + end; + + /// + pNode := AVST.GetNextSibling(pNode); + end; + + /// + ASetupNodeDataFunc(pChildNode, pParentNode, AItem); + + pParentNode := pChildNode; + end; + + // Generate Or Update Level Folder + var ALevelNodesCache := TDictionary.Create(); // For Optimization + var ALevelItemsCache := TList.Create(); + try + // Fill Cache with Existing Nodes + pNode := AVST.GetFirstChild(pParentNode); + while Assigned(pNode) do begin + if pNode.GetData <> nil then + ALevelNodesCache.Add(AGetNameFromDataFunc(pNode.GetData), pNode); + + /// + pNode := AVST.GetNextSibling(pNode); + end; + + // Insert or Update Nodes + var AItemName : String; + var ANewNode : Boolean; + + for var AItem in ALevelItems do begin + pNode := nil; + pChildNode := AVST.GetFirstChild(pParentNode); + /// + + AItemName := AGetNameFromItemFunc(AItem); + + ALevelItemsCache.Add(AItemName); + + ANewNode := not ALevelNodesCache.TryGetValue(AItemName, pNode); + + /// + ASetupNodeDataFunc(pNode, pParentNode, AItem); + + if ANewNode then + ALevelNodesCache.Add(AItemName, pNode); + end; + + // Delete Missing Nodes + for var APair in ALevelNodesCache do + if not ALevelItemsCache.Contains(APair.Key) then + AVST.DeleteNode(APair.Value); + finally + if Assigned(ALevelItemsCache) then + FreeAndNil(ALevelItemsCache); + + if Assigned(ALevelNodesCache) then + FreeAndNil(ALevelNodesCache); + end; + finally + if Assigned(pParentNode) then begin + AVST.Expanded[pParentNode] := True; + + TOptixVirtualTreesHelper.SelectNode(AVST, pParentNode); + end; + + AVST.SortTree(0, TSortDirection.sdAscending); + + AVST.EndUpdate(); + end; +end; + (* TOptixVirtualTreesHelper *) { TOptixVirtualTreesHelper.GetVisibleNodesCount } From 1d603e7c736d1cea8af0a4fe3cb2f6985bed9059 Mon Sep 17 00:00:00 2001 From: DarkCoderSc Date: Mon, 6 Oct 2025 14:53:10 +0200 Subject: [PATCH 5/6] File Manager : Generic Folder Tree Implemented (+ Bug Fix) --- Client GUI/ClientGUIGroup.groupproj.local | 4 +- Client GUI/Client_GUI.dpr | 5 +- Client GUI/Client_GUI.dproj | 3 + Client GUI/Client_GUI.res | Bin 227572 -> 227584 bytes Client GUI/Client_GUI_OpenSSL.dpr | 5 +- Client GUI/Client_GUI_OpenSSL.dproj | 3 + Client/Client_OpenSSL.dproj | 2 +- Server/OptixGate_OpenSSL.dproj | 2 +- .../Control/uControlFormControlForms.pas | 2 +- .../Forms/Control/uControlFormFileManager.dfm | 6 +- .../Forms/Control/uControlFormFileManager.pas | 191 +++++++----------- .../Control/uControlFormRegistryManager.pas | 6 +- .../Units/Forms/Control/uControlFormTasks.pas | 2 +- Server/Units/Forms/uFormMain.pas | 9 +- Server/Units/Optix.Helper.pas | 4 +- Server/Units/Optix.VCL.Helper.pas | 31 +-- .../Optix.Func.Commands.FileSystem.pas | 83 ++++++-- .../Optix.Func.Commands.Registry.pas | 40 ++-- Shared/Optix.FileSystem.Enum.pas | 100 +++++++-- Shared/Optix.FileSystem.Helper.pas | 66 ++++++ Shared/Optix.Registry.Helper.pas | 2 +- 21 files changed, 348 insertions(+), 218 deletions(-) diff --git a/Client GUI/ClientGUIGroup.groupproj.local b/Client GUI/ClientGUIGroup.groupproj.local index 677f204..8672c54 100644 --- a/Client GUI/ClientGUIGroup.groupproj.local +++ b/Client GUI/ClientGUIGroup.groupproj.local @@ -1,9 +1,9 @@  - 2025/08/15 09:04:51.000.443,C:\Users\jples\Documents\Embarcadero\Studio\Projects\ProjectGroup1.groupproj=C:\Users\jples\Desktop\OptixGate\Client GUI\ClientGUIGroup.groupproj + 2025/08/15 09:04:51.000.443,C:\Users\jples\Desktop\OptixGate\Client GUI\ClientGUIGroup.groupproj=C:\Users\jples\Documents\Embarcadero\Studio\Projects\ProjectGroup1.groupproj - + diff --git a/Client GUI/Client_GUI.dpr b/Client GUI/Client_GUI.dpr index 5686db2..9b0bccd 100644 --- a/Client GUI/Client_GUI.dpr +++ b/Client GUI/Client_GUI.dpr @@ -92,7 +92,10 @@ uses Optix.Func.Commands.Process in '..\Shared\Functions\Optix.Func.Commands.Process.pas', Optix.Func.Commands.Shell in '..\Shared\Functions\Optix.Func.Commands.Shell.pas', Optix.FileSystem.Enum in '..\Shared\Optix.FileSystem.Enum.pas', - Optix.Process.Enum in '..\Shared\Optix.Process.Enum.pas'; + Optix.Process.Enum in '..\Shared\Optix.Process.Enum.pas', + Optix.Func.Commands.Registry in '..\Shared\Functions\Optix.Func.Commands.Registry.pas', + Optix.Registry.Helper in '..\Shared\Optix.Registry.Helper.pas', + Optix.Registry.Enum in '..\Shared\Optix.Registry.Enum.pas'; {$R *.res} {$R ..\Server\data.res} diff --git a/Client GUI/Client_GUI.dproj b/Client GUI/Client_GUI.dproj index 89965dd..7362243 100644 --- a/Client GUI/Client_GUI.dproj +++ b/Client GUI/Client_GUI.dproj @@ -195,6 +195,9 @@ + + + Base diff --git a/Client GUI/Client_GUI.res b/Client GUI/Client_GUI.res index 539341d19dab5b088f78ccc71eee7d383020f815..22fb0445185d3fc3e40806d905c7d774b44996ff 100644 GIT binary patch delta 54 zcmV-60LlOK@eP3T4Y1JT0T#2-w&jWNm3~X>)XPVRUb^q32rzgZt`- M`|1I=`|1MujrfinuK)l5 delta 43 zcmV+`0M!40@(uLy4Y1JT0SmLyJQ; B6(Ils diff --git a/Client GUI/Client_GUI_OpenSSL.dpr b/Client GUI/Client_GUI_OpenSSL.dpr index 5338407..c445558 100644 --- a/Client GUI/Client_GUI_OpenSSL.dpr +++ b/Client GUI/Client_GUI_OpenSSL.dpr @@ -103,7 +103,10 @@ uses Optix.Func.Commands.Process in '..\Shared\Functions\Optix.Func.Commands.Process.pas', Optix.Func.Commands.Shell in '..\Shared\Functions\Optix.Func.Commands.Shell.pas', Optix.FileSystem.Enum in '..\Shared\Optix.FileSystem.Enum.pas', - Optix.Process.Enum in '..\Shared\Optix.Process.Enum.pas'; + Optix.Process.Enum in '..\Shared\Optix.Process.Enum.pas', + Optix.Func.Commands.Registry in '..\Shared\Functions\Optix.Func.Commands.Registry.pas', + Optix.Registry.Helper in '..\Shared\Optix.Registry.Helper.pas', + Optix.Registry.Enum in '..\Shared\Optix.Registry.Enum.pas'; {$R *.res} {$R ..\Server\data.res} diff --git a/Client GUI/Client_GUI_OpenSSL.dproj b/Client GUI/Client_GUI_OpenSSL.dproj index a8c808e..0a0f21a 100644 --- a/Client GUI/Client_GUI_OpenSSL.dproj +++ b/Client GUI/Client_GUI_OpenSSL.dproj @@ -207,6 +207,9 @@ + + + Base diff --git a/Client/Client_OpenSSL.dproj b/Client/Client_OpenSSL.dproj index 83792e9..40d5dae 100644 --- a/Client/Client_OpenSSL.dproj +++ b/Client/Client_OpenSSL.dproj @@ -4,7 +4,7 @@ 20.3 None True - Debug + Release Win64 Client_OpenSSL 3 diff --git a/Server/OptixGate_OpenSSL.dproj b/Server/OptixGate_OpenSSL.dproj index bdafc57..282e6b2 100644 --- a/Server/OptixGate_OpenSSL.dproj +++ b/Server/OptixGate_OpenSSL.dproj @@ -4,7 +4,7 @@ 20.3 VCL True - Debug + Release Win32 OptixGate_OpenSSL 3 diff --git a/Server/Units/Forms/Control/uControlFormControlForms.pas b/Server/Units/Forms/Control/uControlFormControlForms.pas index 8c4e6fb..493d238 100644 --- a/Server/Units/Forms/Control/uControlFormControlForms.pas +++ b/Server/Units/Forms/Control/uControlFormControlForms.pas @@ -389,7 +389,7 @@ procedure TControlFormControlForms.VSTCompareNodes(Sender: TBaseVirtualTree; Nod Result := 0 else begin if (Column in [2..4, 6]) and (not Assigned(pData1^.FormInformation) or not Assigned(pData2^.FormInformation)) then - Result := CompareObjectAssigmenet(pData1^.FormInformation, pData2^.FormInformation) + Result := CompareObjectAssignement(pData1^.FormInformation, pData2^.FormInformation) else begin case Column of 0 : Result := CompareText(pData1^.Title, pData2^.Title); diff --git a/Server/Units/Forms/Control/uControlFormFileManager.dfm b/Server/Units/Forms/Control/uControlFormFileManager.dfm index 2d57a57..480f5e3 100644 --- a/Server/Units/Forms/Control/uControlFormFileManager.dfm +++ b/Server/Units/Forms/Control/uControlFormFileManager.dfm @@ -319,6 +319,7 @@ object ControlFormFileManager: TControlFormFileManager OnCompareNodes = VSTFoldersCompareNodes OnDblClick = VSTFoldersDblClick OnFocusChanged = VSTFoldersFocusChanged + OnFreeNode = VSTFoldersFreeNode OnGetText = VSTFoldersGetText OnGetImageIndex = VSTFoldersGetImageIndex OnGetNodeDataSize = VSTFoldersGetNodeDataSize @@ -362,11 +363,6 @@ object ControlFormFileManager: TControlFormFileManager Checked = True OnClick = ShowFolderTree1Click end - object AutoExpandFolderTree1: TMenuItem - AutoCheck = True - Caption = 'Auto Expand Folder Tree' - Checked = True - end end object PopupFoldersTree: TPopupMenu Left = 256 diff --git a/Server/Units/Forms/Control/uControlFormFileManager.pas b/Server/Units/Forms/Control/uControlFormFileManager.pas index 42dc359..bf65d05 100644 --- a/Server/Units/Forms/Control/uControlFormFileManager.pas +++ b/Server/Units/Forms/Control/uControlFormFileManager.pas @@ -83,10 +83,8 @@ TFileTreeData = record PFileTreeData = ^TFileTreeData; TFolderTreeData = record - Name : String; - Access : TFileAccessAttributes; - Path : String; - ImageIndex : Integer; + Information : TSimpleFolderInformation; + ImageIndex : Integer; end; PFolderTreeData = ^TFolderTreeData; @@ -119,7 +117,6 @@ TControlFormFileManager = class(TBaseFormControl) PopupFoldersTree: TPopupMenu; FullExpand1: TMenuItem; FullCollapse1: TMenuItem; - AutoExpandFolderTree1: TMenuItem; procedure VSTFilesChange(Sender: TBaseVirtualTree; Node: PVirtualNode); procedure VSTFilesFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex); @@ -163,6 +160,7 @@ TControlFormFileManager = class(TBaseFormControl) procedure VSTFoldersDblClick(Sender: TObject); procedure VSTFoldersCompareNodes(Sender: TBaseVirtualTree; Node1, Node2: PVirtualNode; Column: TColumnIndex; var Result: Integer); + procedure VSTFoldersFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); private FHistoryCursor : Integer; FPathHistory : TList; @@ -172,8 +170,8 @@ TControlFormFileManager = class(TBaseFormControl) procedure BrowseFromCurrentHistoryLocation(); function CanNodeFileBeDownloaded(var pData : PFileTreeData) : Boolean; function CanFileBeUploadedToNodeDirectory(var pData : PFileTreeData) : Boolean; - procedure RegisterFolderInTree(const ABasePath : String; const AFolder : String); - procedure RegisterFoldersInTree(const ABasePath : String; const AFolders : TDictionary); + procedure RegisterFoldersInTree(const AParentFolders : TObjectList; + const AFolders : TObjectList); procedure DisplayDrives(const AList : TOptixCommandRefreshDrives); procedure DisplayFiles(const AList : TOptixCommandRefreshFiles); procedure SetDisplayMode(const AMode : TDisplayMode); @@ -280,8 +278,9 @@ procedure TControlFormFileManager.RegisterNewFile(const APath : String; const AF end; /// - if AFileInformation.IsDirectory then - RegisterFolderInTree(APath, AFileInformation.Name); + if AFileInformation.IsDirectory then begin + // TODO: Support directories (Modify "new file/folder" feedback command to have parent folders list) + end; end; function TControlFormFileManager.GetFolderImageIndex(const AFolderAccess : TFileAccessAttributes) : Integer; @@ -307,108 +306,49 @@ function TControlFormFileManager.GetFolderImageIndex(const AFolderAccess : TFile result := IMAGE_FOLDER_NORMAL; end; -procedure TControlFormFileManager.RegisterFoldersInTree(const ABasePath : String; const AFolders : TDictionary); - - function GetParentNode(const APath : String) : PVirtualNode; - begin - result := nil; - /// - - for var pNode in VSTFolders.Nodes do begin - var pData := PFolderTreeData(pNode.GetData); - if String.Compare(pData^.Path, APath, True) = 0 then begin - result := pNode; - - break; - end; - end; - end; - - function GetLevelFolder(const AName : String; const pParent : PVirtualNode) : PVirtualNode; - begin - result := nil; - /// - - var pChildNode := VSTFolders.GetFirstChild(pParent); - while Assigned(pChildNode) do begin - var pData := PFolderTreeData(pChildNode.GetData); - - if String.Compare(pData^.Name, AName, True) = 0 then begin - result := pChildNode; - - break; - end; - - /// - pChildNode := VSTFolders.GetNextSibling(pChildNode); - end; - end; - +procedure TControlFormFileManager.RegisterFoldersInTree(const AParentFolders : TObjectList; + const AFolders : TObjectList); begin - var pParentNode : PVirtualNode := nil; - - var ARoot := String.IsNullOrWhitespace(ABasePath); - if not ARoot then - pParentNode := GetParentNode(ABasePath); - /// - - VSTFolders.BeginUpdate(); - try - for var AFolder in AFolders do begin - var pNode := GetLevelFolder(AFolder.Key, pParentNode); - if Assigned(pNode) then begin - if ARoot then begin - var pData := PFolderTreeData(pNode.GetData); - - // It might change (e.g. Bitlocker volume unlocked) - pData^.ImageIndex := SystemFileIcon(AFolder.Key); - end; - + TOptixVirtualTreesFolderTreeHelper.UpdateTree( + VSTFolders, + AParentFolders, + AFolders, + ( + function (const pData : Pointer) : String + begin + result := PFolderTreeData(pData)^.Information.Name + end + ), + ( + function (const AItem: TSimpleFolderInformation): String + begin + result := AItem.Name + end + ), + ( + procedure (var pNode, pParentNode : PVirtualNode; const AItem : TSimpleFolderInformation) + begin + var pData : PFolderTreeData; /// - continue; - end; - /// - pNode := VSTFolders.AddChild(pParentNode); - var pData := PFolderTreeData(pNode.GetData); + if not Assigned(pNode) then begin + pNode := VSTFolders.AddChild(pParentNode); - pData^.Name := AFolder.Key; + pData := PFolderTreeData(pNode.GetData); - if ARoot then - pData^.Path := AFolder.Key - else - pData^.Path := IncludeTrailingPathDelimiter(IncludeTrailingPathDelimiter(ABasePath) + AFolder.Key); + pData^.Information := TSimpleFolderInformation.Create(); + end else + pData := PFolderTreeData(pNode.GetData); - pData^.Access := AFolder.Value; + pData^.Information.Assign(AItem); - if ARoot then - pData^.ImageIndex := SystemFileIcon(AFolder.Key) - else - pData^.ImageIndex := SystemFolderIcon(); - end; - finally - if AutoExpandFolderTree1.Checked then - VSTFolders.FullExpand(pParentNode); - - VSTFiles.SortTree(0, TSortDirection.sdAscending); - - /// - VSTFolders.EndUpdate(); - end; -end; - -procedure TControlFormFileManager.RegisterFolderInTree(const ABasePath : String; const AFolder : String); -begin - var AFolders := TDictionary.Create(); - try - AFolders.Add(AFolder, []); - - /// - RegisterFoldersInTree(IncludeTrailingPathDelimiter(ABasePath), AFolders); - finally - if Assigned(AFolders) then - FreeAndNil(AFolders); - end; + if AItem.IsRoot then + pData^.ImageIndex := SystemFileIcon(AItem.Path) + else + pData^.ImageIndex := SystemFolderIcon(); + end + ) + ); end; procedure TControlFormFileManager.BrowseFromCurrentHistoryLocation(); @@ -521,14 +461,6 @@ procedure TControlFormFileManager.SetDisplayMode(const AMode : TDisplayMode); ButtonRefresh.Enabled := AMode = dmFiles; ButtonUpload.Enabled := AMode = dmFiles; -// ButtonBack.Enabled := AMode = dmFiles; -// ButtonForward.Enabled := AMode = dmFiles; - -// if AMode = dmDrives then begin -// FPathHistory.Clear(); -// FHistoryCursor := 0; -// end; - /// RefreshNavButtons(); end; @@ -727,7 +659,6 @@ procedure TControlFormFileManager.VSTFilesCompareNodes(Sender: TBaseVirtualTree; Exit(); // Avoid too many nested blocks of code in this specific case. end; - // File Mode Sorting ------------------------------------------------------------------------------------------------- if Assigned(pData1^.FileInformation) and Assigned(pData2^.FileInformation) then begin case Column of @@ -983,7 +914,7 @@ procedure TControlFormFileManager.VSTFoldersCompareNodes(Sender: TBaseVirtualTre if not Assigned(pData1) or not Assigned(pData2) then Result := 0 else - Result := CompareText(pData1^.Name, pData2^.Name); + Result := CompareText(pData1^.Information.Name, pData2^.Information.Name); end; procedure TControlFormFileManager.VSTFoldersDblClick(Sender: TObject); @@ -996,7 +927,7 @@ procedure TControlFormFileManager.VSTFoldersDblClick(Sender: TObject); var pData := PFolderTreeData(pNode.GetData); /// - BrowsePath(pData^.Path); + BrowsePath(pData^.Information.Path); end; procedure TControlFormFileManager.VSTFoldersFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; @@ -1005,6 +936,13 @@ procedure TControlFormFileManager.VSTFoldersFocusChanged(Sender: TBaseVirtualTre TVirtualStringTree(Sender).Refresh(); end; +procedure TControlFormFileManager.VSTFoldersFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); +begin + var pData := PFolderTreeData(Node.GetData); + if Assigned(pData) and Assigned(pData^.Information) then + FreeAndNil(pData^.Information); +end; + procedure TControlFormFileManager.VSTFoldersGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: TImageIndex); begin @@ -1030,7 +968,7 @@ procedure TControlFormFileManager.VSTFoldersGetText(Sender: TBaseVirtualTree; No if Assigned(pData) then begin case Column of - 0 : CellText := pData^.Name; + 0 : CellText := pData^.Information.Name; end; end; @@ -1060,7 +998,7 @@ procedure TControlFormFileManager.DisplayDrives(const AList : TOptixCommandRefre Exit(); /// - var AFolders := TDictionary.Create(); + var AFolders := TObjectList.Create(True); VSTFiles.BeginUpdate(); try @@ -1075,10 +1013,10 @@ procedure TControlFormFileManager.DisplayDrives(const AList : TOptixCommandRefre pData^.ImageIndex := SystemFileIcon(IncludeTrailingPathDelimiter(ADrive.Letter)); /// - AFolders.Add(IncludeTrailingPathDelimiter(ADrive.Letter), []); + AFolders.Add(TSimpleFolderInformation.Create(ADrive.Letter, ADrive.Letter, [], True)); end; finally - RegisterFoldersInTree('', AFolders); + RegisterFoldersInTree(nil, AFolders); VSTFiles.EndUpdate(); @@ -1101,11 +1039,11 @@ procedure TControlFormFileManager.DisplayFiles(const AList : TOptixCommandRefres ButtonUpload.Enabled := faWrite in AList.Access; - var AFolders := TDictionary.Create(); + var AFolders := TObjectList.Create(True); VSTFiles.BeginUpdate(); try - for var AFile in AList.List do begin + for var AFile in AList.Files do begin var pNode := VSTFiles.AddChild(nil); var pData := PFileTreeData(pNode.GetData); /// @@ -1119,12 +1057,19 @@ procedure TControlFormFileManager.DisplayFiles(const AList : TOptixCommandRefres /// if not MatchStr(pData^.FileInformation.Name, ['.', '..']) then - AFolders.Add(pData^.FileInformation.Name, pData^.FileInformation.Access); + AFolders.Add( + TSimpleFolderInformation.Create( + pData^.FileInformation.Name, + pData^.FileInformation.Path, + pData^.FileInformation.Access, + False + ) + ); end else pData^.ImageIndex := SystemFileIcon(AFile.Name, True); end; finally - RegisterFoldersInTree(IncludeTrailingPathDelimiter(AList.Path), AFolders); + RegisterFoldersInTree(AList.ParentFolders, AFolders); VSTFiles.EndUpdate(); diff --git a/Server/Units/Forms/Control/uControlFormRegistryManager.pas b/Server/Units/Forms/Control/uControlFormRegistryManager.pas index c3e0ac2..1f4932b 100644 --- a/Server/Units/Forms/Control/uControlFormRegistryManager.pas +++ b/Server/Units/Forms/Control/uControlFormRegistryManager.pas @@ -95,7 +95,6 @@ TControlFormRegistryManager = class(TBaseFormControl) procedure VSTKeysGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string); procedure VSTKeysFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex); - procedure VSTKeysChange(Sender: TBaseVirtualTree; Node: PVirtualNode); procedure VSTKeysGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: TImageIndex); procedure VSTKeysFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); @@ -118,6 +117,7 @@ TControlFormRegistryManager = class(TBaseFormControl) procedure PopupKeysPopup(Sender: TObject); procedure Refresh1Click(Sender: TObject); procedure GoTo1Click(Sender: TObject); + procedure VSTKeysChange(Sender: TBaseVirtualTree; Node: PVirtualNode); private {@M} procedure BrowsePath(const AKeyFullPath : String); @@ -346,7 +346,7 @@ procedure TControlFormRegistryManager.VSTKeysCompareNodes(Sender: TBaseVirtualTr if not Assigned(pData1) or not Assigned(pData2) then Result := ComparePointerAssigmenet(pData1, pData2) else if not Assigned(pData1^.KeyInformation) or not Assigned(pData2^.KeyInformation) then - Result := CompareObjectAssigmenet(pData1^.KeyInformation, pData2^.KeyInformation) + Result := CompareObjectAssignement(pData1^.KeyInformation, pData2^.KeyInformation) else Result := CompareText(pData1^.KeyInformation.Name, pData2^.KeyInformation.Name); end; @@ -427,7 +427,7 @@ procedure TControlFormRegistryManager.VSTValuesCompareNodes(Sender: TBaseVirtual if not Assigned(pData1) or not Assigned(pData2) then Result := ComparePointerAssigmenet(pData1, pData2) else if not Assigned(pData1^.ValueInformation) or not Assigned(pData2^.ValueInformation) then - Result := CompareObjectAssigmenet(pData1^.ValueInformation, pData2^.ValueInformation) + Result := CompareObjectAssignement(pData1^.ValueInformation, pData2^.ValueInformation) else begin case Column of 0 : Result := CompareText(pData1^.ValueInformation.Name, pData2^.ValueInformation.Name); diff --git a/Server/Units/Forms/Control/uControlFormTasks.pas b/Server/Units/Forms/Control/uControlFormTasks.pas index 353c3bf..8a9b4ec 100644 --- a/Server/Units/Forms/Control/uControlFormTasks.pas +++ b/Server/Units/Forms/Control/uControlFormTasks.pas @@ -298,7 +298,7 @@ procedure TControlFormTasks.VSTCompareNodes(Sender: TBaseVirtualTree; Node1, Nod 5 : begin if not Assigned(pData1^.TaskCallBack.Result) or not Assigned(pData2^.TaskCallBack.Result) then - Result := CompareObjectAssigmenet(pData1^.TaskCallBack.Result, pData2^.TaskCallBack.Result) + Result := CompareObjectAssignement(pData1^.TaskCallBack.Result, pData2^.TaskCallBack.Result) else Result := CompareText(pData1^.TaskCallBack.Result.Description, pData2^.TaskCallBack.Result.Description); end; diff --git a/Server/Units/Forms/uFormMain.pas b/Server/Units/Forms/uFormMain.pas index cb2ce92..a5944e5 100644 --- a/Server/Units/Forms/uFormMain.pas +++ b/Server/Units/Forms/uFormMain.pas @@ -42,16 +42,11 @@ {******************************************************************************} (* - Current Release Changelog: - - N/A - When Delphi 13 in Community Edition (Code Improvements): - Replace "not (x in y)" by "x not in y" - Ternary operator *) -// TODO: Implement Generic Folder Tree code to File Manager Folder Tree (Actually a serious bug exists using the "Go To") - unit uFormMain; interface @@ -620,9 +615,9 @@ procedure TFormMain.VSTCompareNodes(Sender: TBaseVirtualTree; Node1, Node2: PVir end; if not Assigned(pData1^.SessionInformation) or not Assigned(pData2^.SessionInformation) then - Result := CompareObjectAssigmenet(pData1^.SessionInformation, pData2^.SessionInformation) + Result := CompareObjectAssignement(pData1^.SessionInformation, pData2^.SessionInformation) else if not Assigned(pData1^.Handler) or not Assigned(pData2^.Handler) then - Result := CompareObjectAssigmenet(pData1^.Handler, pData2^.Handler) + Result := CompareObjectAssignement(pData1^.Handler, pData2^.Handler) else begin case Column of 0 : Result := CompareText(pData1^.Handler.PeerAddress, pData2^.Handler.PeerAddress); diff --git a/Server/Units/Optix.Helper.pas b/Server/Units/Optix.Helper.pas index 345921c..d686afe 100644 --- a/Server/Units/Optix.Helper.pas +++ b/Server/Units/Optix.Helper.pas @@ -55,7 +55,7 @@ procedure Open(const ACommand : String); procedure CheckCertificateFingerprint(const AValue : String); -function CompareObjectAssigmenet(const AObject1, AObject2 : TObject) : Integer; +function CompareObjectAssignement(const AObject1, AObject2 : TObject) : Integer; function ComparePointerAssigmenet(const pPtr1, pPtr2 : Pointer) : Integer; function CompareDateTimeEx(const ADate1 : TDateTime; const ADate1IsSet : Boolean; const ADate2 : TDateTime; const ADate2IsSet : Boolean) : Integer; @@ -82,7 +82,7 @@ function CompareDateTimeEx(const ADate1 : TDateTime; const ADate1IsSet : Boolean end; { _.CompareObjectAssignement } -function CompareObjectAssigmenet(const AObject1, AObject2 : TObject) : Integer; +function CompareObjectAssignement(const AObject1, AObject2 : TObject) : Integer; begin if not Assigned(AObject1) and not Assigned(AObject2) then Result := 0 diff --git a/Server/Units/Optix.VCL.Helper.pas b/Server/Units/Optix.VCL.Helper.pas index 6df8215..9443b70 100644 --- a/Server/Units/Optix.VCL.Helper.pas +++ b/Server/Units/Optix.VCL.Helper.pas @@ -75,6 +75,9 @@ class procedure TOptixVirtualTreesFolderTreeHelper.UpdateTree(const AVST : TV Exit(); /// + if not Assigned(ALevelItems) then + Exit(); + var pParentNode := PVirtualNode(nil); var pChildNode := PVirtualNode(nil); var pNode := PVirtualNode(nil); @@ -82,25 +85,27 @@ class procedure TOptixVirtualTreesFolderTreeHelper.UpdateTree(const AVST : TV AVST.BeginUpdate(); try // Generate or Update Parent Folder Tree - for var AItem in AParentsItems do begin - pChildNode := nil; + if Assigned(AParentsItems) then begin + for var AItem in AParentsItems do begin + pChildNode := nil; - pNode := AVST.GetFirstChild(pParentNode); - while Assigned(pNode) do begin - if SameText(AGetNameFromDataFunc(pNode.GetData), AGetNameFromitemFunc(AItem)) then begin - pChildNode := pNode; + pNode := AVST.GetFirstChild(pParentNode); + while Assigned(pNode) do begin + if SameText(AGetNameFromDataFunc(pNode.GetData), AGetNameFromitemFunc(AItem)) then begin + pChildNode := pNode; + + break; + end; - break; + /// + pNode := AVST.GetNextSibling(pNode); end; /// - pNode := AVST.GetNextSibling(pNode); - end; + ASetupNodeDataFunc(pChildNode, pParentNode, AItem); - /// - ASetupNodeDataFunc(pChildNode, pParentNode, AItem); - - pParentNode := pChildNode; + pParentNode := pChildNode; + end; end; // Generate Or Update Level Folder diff --git a/Shared/Functions/Optix.Func.Commands.FileSystem.pas b/Shared/Functions/Optix.Func.Commands.FileSystem.pas index 7f7f1cd..3e3cd9e 100644 --- a/Shared/Functions/Optix.Func.Commands.FileSystem.pas +++ b/Shared/Functions/Optix.Func.Commands.FileSystem.pas @@ -117,7 +117,8 @@ TOptixCommandRefreshFiles = class(TOptixCommandActionResponse) [OptixSerializableAttribute] FIsRoot : Boolean; - FList : TObjectList; + FParentFolders : TObjectList; + FFiles : TObjectList; protected {@M} procedure DeSerialize(const ASerializedObject : ISuperObject); override; @@ -132,10 +133,11 @@ TOptixCommandRefreshFiles = class(TOptixCommandActionResponse) destructor Destroy(); override; {@G} - property Path : String read FPath; - property List : TObjectList read FList; - property Access : TFileAccessAttributes read FAccess; - property IsRoot : Boolean read FIsRoot; + property Path : String read FPath; + property ParentFolders : TObjectList read FParentFolders; + property Files : TObjectList read FFiles; + property Access : TFileAccessAttributes read FAccess; + property IsRoot : Boolean read FIsRoot; end; TOptixCommandTransfer = class(TOptixCommand) @@ -169,6 +171,11 @@ TOptixCommandUploadFile = class(TOptixCommandTransfer) implementation +// --------------------------------------------------------------------------------------------------------------------- +uses + System.IOUtils; +// --------------------------------------------------------------------------------------------------------------------- + (*********************************************************************************************************************** TOptixRequestFileInformation @@ -283,7 +290,34 @@ destructor TOptixCommandRefreshDrives.Destroy(); { TOptixCommandRefreshFiles.DoAction } procedure TOptixCommandRefreshFiles.DoAction(); begin - TOptixEnumFiles.Enum(FPath, FList, FIsRoot, FAccess); + FParentFolders.Clear(); + /// + + FPath := TFileSystemHelper.GetFullPathName(TFileSystemHelper.ExpandPath(FPath)); + + TFileSystemHelper.PathExists(FPath); + + TFileSystemHelper.TraverseDirectories( + FPath, + ( + procedure (const ADirectoryName : String; const AAbsolutePath : String) + begin + var APath := IncludeTrailingPathDelimiter(AAbsolutePath); + var AIsRoot := SameText(APath, TPath.GetPathRoot(APath)); + /// + + var AFileAccess : TFileAccessAttributes := []; + if not AIsRoot then + AFileAccess := TFileSystemHelper.TryGetCurrentUserFileAccess(APath); + + /// + FParentFolders.Add(TSimpleFolderInformation.Create(ADirectoryName, AAbsolutePath, AFileAccess, AIsRoot)); + end + ) + ); + + /// + TOptixEnumFiles.Enum(FPath, FFiles, FIsRoot, FAccess); end; { TOptixCommandRefreshFiles.DeSerialize } @@ -292,10 +326,17 @@ procedure TOptixCommandRefreshFiles.DeSerialize(const ASerializedObject : ISuper inherited; /// - FList.Clear(); + FParentFolders.Clear(); - for var I := 0 to ASerializedObject.A['List'].Length -1 do - FList.Add(TFileInformation.Create(ASerializedObject.A['List'].O[I])); + for var I := 0 to ASerializedObject.A['ParentFolders'].Length -1 do + FParentFolders.Add(TSimpleFolderInformation.Create(ASerializedObject.A['ParentFolders'].O[I])); + + /// + + FFiles.Clear(); + + for var I := 0 to ASerializedObject.A['Files'].Length -1 do + FFiles.Add(TFileInformation.Create(ASerializedObject.A['Files'].O[I])); end; { TOptixCommandRefreshFiles.Serialize } @@ -306,11 +347,21 @@ function TOptixCommandRefreshFiles.Serialize() : ISuperObject; var AJsonArray := TSuperArray.Create(); - for var AItem in FList do + for var AItem in FParentFolders do AJsonArray.Add(AItem.Serialize); /// - result.A['List'] := AJsonArray; + result.A['ParentFolders'] := AJsonArray; + + /// + + AJsonArray := TSuperArray.Create(); + + for var AItem in FFiles do + AJsonArray.Add(AItem.Serialize); + + /// + result.A['Files'] := AJsonArray; end; { TOptixCommandRefreshFiles.Create } @@ -319,7 +370,8 @@ constructor TOptixCommandRefreshFiles.Create(); inherited; /// - FList := TObjectList.Create(True); + FParentFolders := TObjectList.Create(True); + FFiles := TObjectList.Create(True); end; { TOptixCommandRefreshFiles.Create } @@ -336,8 +388,11 @@ constructor TOptixCommandRefreshFiles.Create(const APath : String); { TOptixCommandRefreshFiles.Destroy } destructor TOptixCommandRefreshFiles.Destroy(); begin - if Assigned(FList) then - FreeAndNil(FList); + if Assigned(FFiles) then + FreeAndNil(FFiles); + + if Assigned(FParentFolders) then + FreeAndNil(FParentFolders); /// inherited; diff --git a/Shared/Functions/Optix.Func.Commands.Registry.pas b/Shared/Functions/Optix.Func.Commands.Registry.pas index 2e2b3ca..1fea806 100644 --- a/Shared/Functions/Optix.Func.Commands.Registry.pas +++ b/Shared/Functions/Optix.Func.Commands.Registry.pas @@ -110,7 +110,7 @@ implementation // --------------------------------------------------------------------------------------------------------------------- uses - Optix.System.Helper; + Optix.System.Helper, Optix.FileSystem.Helper; // --------------------------------------------------------------------------------------------------------------------- (*********************************************************************************************************************** @@ -238,31 +238,19 @@ procedure TOptixGetRegistryHives.DoAction(); { TOptixRefreshRegistrySubKeys.DoAction } procedure TOptixRefreshRegistrySubKeys.DoAction(); begin - var ADirectories := TStringList.Create(); - try - TRegistryHelper.CheckRegistryPath(FPath); - /// - - ADirectories.Delimiter := '\'; - ADirectories.DelimitedText := FPath; - - FParentKeys.Clear(); - - var ACurrentPath := ''; - for var ADirectory in ADirectories do begin - if ADirectory.IsEmpty then - continue; - /// - - ACurrentPath := TSystemHelper.IncludeTrailingPathDelimiterIfNotEmpty(ACurrentPath) + ADirectory; - - /// - FParentKeys.Add(TRegistryKeyInformation.Create(ADirectory, ACurrentPath)); - end; - finally - if Assigned(ADirectories) then - FreeAndNil(ADirectories); - end; + TRegistryHelper.CheckRegistryPath(FPath); + FParentKeys.Clear(); + /// + + TFileSystemHelper.TraverseDirectories( + FPath, + ( + procedure (const ADirectoryName : String; const AAbsolutePath : String) + begin + FParentKeys.Add(TRegistryKeyInformation.Create(ADirectoryName, AAbsolutePath)); + end + ) + ); /// TOptixEnumRegistry.Enum(FPath, FSubKeys, FValues); diff --git a/Shared/Optix.FileSystem.Enum.pas b/Shared/Optix.FileSystem.Enum.pas index 83030b1..0ea71b1 100644 --- a/Shared/Optix.FileSystem.Enum.pas +++ b/Shared/Optix.FileSystem.Enum.pas @@ -57,6 +57,35 @@ interface // --------------------------------------------------------------------------------------------------------------------- type + // Folder Information (Simplified) ----------------------------------------------------------------------------------- + TSimpleFolderInformation = class(TOptixSerializableObject) + private + [OptixSerializableAttribute] + FName : String; + + [OptixSerializableAttribute] + FPath : String; + + [OptixSerializableAttribute] + FAccess : TFileAccessAttributes; + + [OptixSerializableAttribute] + FIsRoot : Boolean; + public + {@C} + constructor Create(const AName, APath : String; const AAccess : TFileAccessAttributes; + const AIsRoot : Boolean); overload; + + {@M} + procedure Assign(ASource : TPersistent); override; + + {@G} + property Name : String read FName; + property Path : String read FPath; + property Access : TFileAccessAttributes read FAccess; + property IsRoot : Boolean read FIsRoot; + end; + // Drives ------------------------------------------------------------------------------------------------------------ TDriveInformation = class(TOptixSerializableObject) private @@ -107,6 +136,9 @@ TOptixEnumDrives = class // Files ------------------------------------------------------------------------------------------------------------- TFileInformation = class(TOptixSerializableObject) private + [OptixSerializableAttribute] + FPath : String; + [OptixSerializableAttribute] FName : String; @@ -138,13 +170,14 @@ TFileInformation = class(TOptixSerializableObject) FLastAccessDate : TDateTime; public {@C} - constructor Create(const AFilePath : String; const AIsDirectory : Boolean); overload; + constructor Create(const APath : String; const AIsDirectory : Boolean); overload; {@M} function GetFileTypeDescription() : String; procedure Assign(ASource : TPersistent); override; {@G} + property Path : String read FPath; property Name : String read FName; property IsDirectory : Boolean read FIsDirectory; property ACL_SSDL : String read FACL_SSDL; @@ -159,7 +192,8 @@ TFileInformation = class(TOptixSerializableObject) TOptixEnumFiles = class public - class procedure Enum(APath : String; var AList : TObjectList; var AIsRoot : Boolean; var AAccess : TFileAccessAttributes); static; + class procedure Enum(const APath : String; var AList : TObjectList; var AIsRoot : Boolean; + var AAccess : TFileAccessAttributes); static; end; implementation @@ -173,6 +207,37 @@ implementation Optix.Exceptions; // --------------------------------------------------------------------------------------------------------------------- +(*********************************************************************************************************************** + + TSimpleFolderInformation + +***********************************************************************************************************************) + +{ TSimpleFolderInformation.Create } +constructor TSimpleFolderInformation.Create(const AName, APath : String; const AAccess : TFileAccessAttributes; + const AIsRoot : Boolean); +begin + inherited Create(); + /// + + FName := AName; + FPath := IncludeTrailingPathDelimiter(APath); + FAccess := AAccess; + FIsRoot := AIsRoot; +end; + +{ TSimpleFolderInformation.Assign } +procedure TSimpleFolderInformation.Assign(ASource : TPersistent); +begin + if ASource is TSimpleFolderInformation then begin + FName := TSimpleFolderInformation(ASource).FName; + FPath := TSimpleFolderInformation(ASource).FPath; + FAccess := TSimpleFolderInformation(ASource).FAccess; + FIsRoot := TSimpleFolderInformation(ASource).FIsRoot; + end else + inherited; +end; + (*********************************************************************************************************************** TDriveInformation @@ -285,6 +350,7 @@ function TFileInformation.GetFileTypeDescription() : String; procedure TFileInformation.Assign(ASource : TPersistent); begin if ASource is TFileInformation then begin + FPath := TFileInformation(ASource).FPath; FName := TFileInformation(ASource).FName; FIsDirectory := TFileInformation(ASource).FIsDirectory; FACL_SSDL := TFileInformation(ASource).FACL_SSDL; @@ -300,17 +366,18 @@ procedure TFileInformation.Assign(ASource : TPersistent); end; { TFileInformation.Create } -constructor TFileInformation.Create(const AFilePath : String; const AIsDirectory : Boolean); +constructor TFileInformation.Create(const APath : String; const AIsDirectory : Boolean); begin - FName := ExtractFileName(AFilePath); + FPath := APath; + FName := ExtractFileName(APath); FIsDirectory := AIsDirectory; - FACL_SSDL := TFileSystemHelper.TryGetFileACLString(AFilePath); - FAccess := TFileSystemHelper.TryGetCurrentUserFileAccess(AFilePath); - FDateAreValid := TFileSystemHelper.TryGetFileTime(AFilePath, FCreatedDate, FLastModifiedDate, FLastAccessDate); + FACL_SSDL := TFileSystemHelper.TryGetFileACLString(APath); + FAccess := TFileSystemHelper.TryGetCurrentUserFileAccess(APath); + FDateAreValid := TFileSystemHelper.TryGetFileTime(APath, FCreatedDate, FLastModifiedDate, FLastAccessDate); if not FIsDirectory then begin - FTypeDescription := TFileSystemHelper.GetFileTypeDescription(AFilePath); - FSize := TFileSystemHelper.TryGetFileSize(AFilePath); + FTypeDescription := TFileSystemHelper.GetFileTypeDescription(APath); + FSize := TFileSystemHelper.TryGetFileSize(APath); end else begin FTypeDescription := ''; FSize := 0; @@ -324,7 +391,8 @@ constructor TFileInformation.Create(const AFilePath : String; const AIsDirectory ***********************************************************************************************************************) { TOptixEnumFiles.Enum } -class procedure TOptixEnumFiles.Enum(APath : String; var AList : TObjectList; var AIsRoot : Boolean; var AAccess : TFileAccessAttributes); +class procedure TOptixEnumFiles.Enum(const APath : String; var AList : TObjectList; + var AIsRoot : Boolean; var AAccess : TFileAccessAttributes); begin if not Assigned(AList) then AList := TObjectList.Create(True) @@ -335,8 +403,6 @@ class procedure TOptixEnumFiles.Enum(APath : String; var AList : TObjectList Date: Mon, 6 Oct 2025 15:11:43 +0200 Subject: [PATCH 6/6] Readme Updated for Release --- Assets/sshot-1.png | Bin 112085 -> 66381 bytes Assets/sshot-15.png | Bin 0 -> 168922 bytes README.md | 63 +++++++++++++++++++++++++++++++------------- 3 files changed, 44 insertions(+), 19 deletions(-) create mode 100644 Assets/sshot-15.png diff --git a/Assets/sshot-1.png b/Assets/sshot-1.png index 6e061debef7f01c050d80c6f84b7718c002b42a8..137a6c6992eeedc0bfc31fab4d3cb69640a15ea1 100644 GIT binary patch literal 66381 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 literal 112085 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 diff --git a/Assets/sshot-15.png b/Assets/sshot-15.png new file mode 100644 index 0000000000000000000000000000000000000000..0fc1083141dd135ae987319a371f7dd773bf6cc2 GIT binary patch literal 168922 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

0<8*piOM%12FBO! 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