mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 01:39:35 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			748 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			748 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{$mode objfpc}
 | 
						|
{$h+}
 | 
						|
 | 
						|
unit xmlreg;
 | 
						|
 | 
						|
Interface
 | 
						|
 | 
						|
uses
 | 
						|
  sysutils,classes,dom,xmlread,xmlwrite;
 | 
						|
 | 
						|
Type
 | 
						|
 | 
						|
  TDataType = (dtUnknown,dtDWORD,dtString,dtBinary);
 | 
						|
  TDataInfo = record
 | 
						|
    DataType : TDataType;
 | 
						|
    DataSize : Integer;
 | 
						|
  end;
 | 
						|
 | 
						|
  TKeyInfo = record
 | 
						|
    SubKeys,
 | 
						|
    SubKeyLen,
 | 
						|
    Values,
 | 
						|
    ValueLen,
 | 
						|
    DataLen   : Integer;
 | 
						|
    FTime     : TDateTime;
 | 
						|
  end;
 | 
						|
 | 
						|
 | 
						|
  TXmlRegistry = Class(TObject)
 | 
						|
  Private
 | 
						|
    FAutoFlush,
 | 
						|
    FDirty : Boolean;
 | 
						|
    FFileName : String;
 | 
						|
    FRootKey : String;
 | 
						|
    FDocument : TXMLDocument;
 | 
						|
    FCurrentElement : TDomElement;
 | 
						|
    FCurrentKey : String;
 | 
						|
    Procedure SetFileName(Value : String);
 | 
						|
  Protected
 | 
						|
    Procedure LoadFromStream(S : TStream);
 | 
						|
    Function  NormalizeKey(KeyPath : String) : String;
 | 
						|
    Procedure CreateEmptyDoc;
 | 
						|
    Function  FindKey (S : String) : TDomElement;
 | 
						|
    Function  FindSubKey (S : String; N : TDomElement) : TDomElement;
 | 
						|
    Function  CreateSubKey (S : String; N : TDomElement) : TDomElement;
 | 
						|
    Function  FindValueKey (S : String) : TDomElement;
 | 
						|
    Function  CreateValueKey (S : String) : TDomElement;
 | 
						|
    Function  BufToHex(Const Buf; Len : Integer) : String;
 | 
						|
    Function  hexToBuf(Const Str : String; Var Buf; Var Len : Integer ) : Integer;
 | 
						|
    Procedure MaybeFlush;
 | 
						|
    Property  Document : TXMLDocument Read FDocument;
 | 
						|
    Property  Dirty : Boolean Read FDirty write FDirty;
 | 
						|
  Public
 | 
						|
    Constructor Create(AFileName : String);
 | 
						|
    Function  SetKey(KeyPath : String; AllowCreate : Boolean) : Boolean ;
 | 
						|
    Procedure SetRootKey(Value : String);
 | 
						|
    Function  DeleteKey(KeyPath : String) : Boolean;
 | 
						|
    Function  CreateKey(KeyPath : String) : Boolean;
 | 
						|
    Function  GetValueSize(Name : String) : Integer;
 | 
						|
    Function  GetValueType(Name : String) : TDataType;
 | 
						|
    Function  GetValueInfo(Name : String; Var Info : TDataInfo) : Boolean;
 | 
						|
    Function  GetKeyInfo(Var Info : TKeyInfo) : Boolean;
 | 
						|
    Function  EnumSubKeys(List : TStrings) : Integer;
 | 
						|
    Function  EnumValues(List : TStrings) : Integer;
 | 
						|
    Function  KeyExists(KeyPath : String) : Boolean;
 | 
						|
    Function  ValueExists(ValueName : String) : Boolean;
 | 
						|
    Function  RenameValue(Const OldName,NewName : String) : Boolean;
 | 
						|
    Function  DeleteValue(S : String) : Boolean;
 | 
						|
    Procedure Flush;
 | 
						|
    Procedure Load;
 | 
						|
    Function GetValueData(Name : String; Var DataType : TDataType; Var Data; Var DataSize : Integer) : Boolean;
 | 
						|
    Function SetValueData(Name : String; DataType : TDataType; Const Data; DataSize : Integer) : Boolean;
 | 
						|
    Property FileName : String Read FFileName Write SetFileName;
 | 
						|
    Property RootKey : String Read FRootKey Write SetRootkey;
 | 
						|
    Property AutoFlush : Boolean Read FAutoFlush Write FAutoFlush;
 | 
						|
  end;
 | 
						|
 | 
						|
// used Key types
 | 
						|
 | 
						|
Const
 | 
						|
  SXmlReg = 'XMLReg';
 | 
						|
  SKey    = 'Key';
 | 
						|
  SValue  = 'Value';
 | 
						|
  SName   = 'Name';
 | 
						|
  SType   = 'Type';
 | 
						|
  SData   = 'Data';
 | 
						|
 | 
						|
Implementation
 | 
						|
 | 
						|
 | 
						|
Constructor TXmlRegistry.Create(AFileName : String);
 | 
						|
 | 
						|
begin
 | 
						|
  FFileName:=AFileName;
 | 
						|
  FautoFlush:=True;
 | 
						|
  If (AFileName<>'') then
 | 
						|
    Load
 | 
						|
  else
 | 
						|
    CreateEmptyDoc;
 | 
						|
end;
 | 
						|
 | 
						|
Procedure TXmlRegistry.SetFileName(Value : String);
 | 
						|
 | 
						|
begin
 | 
						|
  If Value<>FFileName then
 | 
						|
    begin
 | 
						|
    FFilename:=Value;
 | 
						|
    Flush;
 | 
						|
    end;
 | 
						|
end;
 | 
						|
 | 
						|
Procedure TXmlRegistry.CreateEmptyDoc;
 | 
						|
 | 
						|
Const
 | 
						|
  template = '<?xml version="1.0" encoding="ISO8859-1"?>'+LineEnding+
 | 
						|
             '<'+SXMLReg+'>'+LineEnding+
 | 
						|
             '</'+SXMLReg+'>'+LineEnding;
 | 
						|
 | 
						|
Var
 | 
						|
  S : TStream;
 | 
						|
 | 
						|
begin
 | 
						|
  S:=TStringStream.Create(Template);
 | 
						|
  S.Seek(0,soFromBeginning);
 | 
						|
  Try
 | 
						|
    LoadFromStream(S);
 | 
						|
  Finally
 | 
						|
    S.Free;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
Function TXmlRegistry.NormalizeKey(KeyPath : String) : String;
 | 
						|
 | 
						|
Var
 | 
						|
  L : Integer;
 | 
						|
 | 
						|
begin
 | 
						|
  Result:=StringReplace(KeyPath,'\','/',[rfReplaceAll]);
 | 
						|
  L:=Length(Result);
 | 
						|
  If (L>0) and (Result[L]<>'/') then
 | 
						|
    Result:=Result+'/';
 | 
						|
end;
 | 
						|
 | 
						|
Function TXmlRegistry.SetKey(KeyPath : String; AllowCreate : Boolean) : boolean;
 | 
						|
 | 
						|
Var
 | 
						|
  SubKey,ResultKey : String;
 | 
						|
  P : Integer;
 | 
						|
  Node,Node2 : TDomElement;
 | 
						|
 | 
						|
begin
 | 
						|
  Result:=(Length(KeyPath)>0);
 | 
						|
  If Not Result then
 | 
						|
    Exit;
 | 
						|
  KeyPath:=NormalizeKey(KeyPath);
 | 
						|
  If (KeyPath[1]<>'/') then
 | 
						|
    begin
 | 
						|
    Node:=FCurrentElement;
 | 
						|
    Resultkey:=FCurrentKey;
 | 
						|
    end
 | 
						|
  else
 | 
						|
    begin
 | 
						|
    Delete(Keypath,1,1);
 | 
						|
    Node:=FDocument.DocumentElement;
 | 
						|
    If (FRootKey<>'') then
 | 
						|
      KeyPath:=FRootKey+KeyPath;
 | 
						|
    ResultKey:='';
 | 
						|
    end;
 | 
						|
  Result:=True;
 | 
						|
  repeat
 | 
						|
    P:=Pos('/',KeyPath);
 | 
						|
    If (P<>0) then
 | 
						|
      begin
 | 
						|
      SubKey:=Copy(KeyPath,1,P-1);
 | 
						|
      Delete(KeyPath,1,P);
 | 
						|
      Node2:=FindSubKey(SubKey,Node);
 | 
						|
      Result:=(Node2<>Nil);
 | 
						|
      If Result then
 | 
						|
        Node:=Node2
 | 
						|
      else
 | 
						|
        begin
 | 
						|
        If AllowCreate then
 | 
						|
          Begin
 | 
						|
          Node2:=CreateSubKey(SubKey,Node);
 | 
						|
          Result:=Node2<>Nil;
 | 
						|
          If Result Then
 | 
						|
            Node:=Node2;
 | 
						|
          end;
 | 
						|
        end;
 | 
						|
      If Result then
 | 
						|
        ResultKey:=ResultKey+SubKey+'/';
 | 
						|
      end;
 | 
						|
  Until (Not Result) or (Length(KeyPath)=0);
 | 
						|
  If Result then
 | 
						|
    begin
 | 
						|
    FCurrentkey:=ResultKey;
 | 
						|
    FCurrentElement:=Node;
 | 
						|
    end;
 | 
						|
  MaybeFlush;
 | 
						|
end;
 | 
						|
 | 
						|
Procedure TXmlRegistry.SetRootKey(Value : String);
 | 
						|
 | 
						|
begin
 | 
						|
  FRootKey:=NormalizeKey(Value);
 | 
						|
  If (Length(FRootKey)>1) and (FRootKey[1]='/') then
 | 
						|
    Delete(FRootKey,1,1);
 | 
						|
  FCurrentKey:='';
 | 
						|
  FCurrentElement:=Nil;
 | 
						|
end;
 | 
						|
 | 
						|
Function TXmlRegistry.DeleteKey(KeyPath : String) : Boolean;
 | 
						|
 | 
						|
Var
 | 
						|
  N : TDomElement;
 | 
						|
 | 
						|
begin
 | 
						|
 N:=FindKey(KeyPath);
 | 
						|
 Result:=(N<>Nil);
 | 
						|
 If Result then
 | 
						|
   begin
 | 
						|
   (N.ParentNode as TDomElement).RemoveChild(N);
 | 
						|
   FDirty:=True;
 | 
						|
   MaybeFlush;
 | 
						|
   end;
 | 
						|
end;
 | 
						|
 | 
						|
Function TXmlRegistry.CreateKey(KeyPath : String) : Boolean;
 | 
						|
 | 
						|
Var
 | 
						|
  SubKey : String;
 | 
						|
  P : Integer;
 | 
						|
  Node,Node2 : TDomElement;
 | 
						|
 | 
						|
begin
 | 
						|
  Result:=(Length(KeyPath)>0);
 | 
						|
  If Not Result then
 | 
						|
    Exit;
 | 
						|
  KeyPath:=NormalizeKey(KeyPath);
 | 
						|
  If (KeyPath[1]<>'/') then
 | 
						|
    Node:=FCurrentElement
 | 
						|
  else
 | 
						|
    begin
 | 
						|
    Delete(Keypath,1,1);
 | 
						|
    Node:=FDocument.DocumentElement;
 | 
						|
    If (FRootKey<>'') then
 | 
						|
      KeyPath:=FRootKey+KeyPath;
 | 
						|
    end;
 | 
						|
  Result:=True;
 | 
						|
  repeat
 | 
						|
    P:=Pos('/',KeyPath);
 | 
						|
    If (P<>0) then
 | 
						|
      begin
 | 
						|
      SubKey:=Copy(KeyPath,1,P-1);
 | 
						|
      Delete(KeyPath,1,P);
 | 
						|
      Node2:=FindSubKey(SubKey,Node);
 | 
						|
      Result:=(Node2<>Nil);
 | 
						|
      If Result then
 | 
						|
        Node:=Node2
 | 
						|
      else
 | 
						|
        begin
 | 
						|
        Node2:=CreateSubKey(SubKey,Node);
 | 
						|
        Result:=Node2<>Nil;
 | 
						|
        Node:=Node2
 | 
						|
        end;
 | 
						|
      end;
 | 
						|
  Until (Not Result) or (Length(KeyPath)=0);
 | 
						|
  MaybeFlush;
 | 
						|
end;
 | 
						|
 | 
						|
Function TXmlRegistry.GetValueData(Name : String; Var DataType : TDataType; Var Data; Var DataSize : Integer) : Boolean;
 | 
						|
 | 
						|
Type
 | 
						|
  PCardinal = ^Cardinal;
 | 
						|
 | 
						|
Var
 | 
						|
  Node  : TDomElement;
 | 
						|
  DataNode : TDomNode;
 | 
						|
  ND : Integer;
 | 
						|
  Dt : TDataType;
 | 
						|
  S : AnsiString;
 | 
						|
 | 
						|
begin
 | 
						|
  Node:=FindValueKey(Name);
 | 
						|
  Result:=Node<>Nil;
 | 
						|
  If Result then
 | 
						|
    begin
 | 
						|
    DataNode:=Node.FirstChild;
 | 
						|
    Result:=(DataNode<>Nil) and (DataNode is TDomText);
 | 
						|
    If Result then
 | 
						|
      begin
 | 
						|
      ND:=StrToIntDef(Node[Stype],0);
 | 
						|
      Result:=ND<=Ord(High(TDataType));
 | 
						|
      If Result then
 | 
						|
        begin
 | 
						|
        DataType:=TDataType(StrToIntDef(Node[Stype],0));
 | 
						|
        Case DataType of
 | 
						|
          dtDWORD : begin
 | 
						|
                    PCardinal(@Data)^:=StrToIntDef(DataNode.NodeValue,0);
 | 
						|
                    DataSize:=SizeOf(Cardinal);
 | 
						|
                    end;
 | 
						|
          dtString : begin
 | 
						|
                     S:=DataNode.NodeValue; // Convert to ansistring
 | 
						|
                     DataSize:=Length(S);
 | 
						|
                     If (DataSize>0) then
 | 
						|
                       Move(S[1],Data,DataSize);
 | 
						|
                     end;
 | 
						|
          dtBinary : begin
 | 
						|
                     DataSize:=Length(DataNode.NodeValue);
 | 
						|
                     If (DataSize>0) then
 | 
						|
                       HexToBuf(DataNode.NodeValue,Data,DataSize);
 | 
						|
                     end;
 | 
						|
        end;
 | 
						|
        end;
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
end;
 | 
						|
 | 
						|
Function TXmlRegistry.SetValueData(Name : String; DataType : TDataType; Const Data; DataSize : Integer) : Boolean;
 | 
						|
 | 
						|
Type
 | 
						|
  PCardinal = ^Cardinal;
 | 
						|
 | 
						|
Var
 | 
						|
  Node  : TDomElement;
 | 
						|
  DataNode : TDomNode;
 | 
						|
  ND : Integer;
 | 
						|
  Dt : TDataType;
 | 
						|
  S : String;
 | 
						|
 | 
						|
begin
 | 
						|
  Node:=FindValueKey(Name);
 | 
						|
  If Node=Nil then
 | 
						|
    Node:=CreateValueKey(Name);
 | 
						|
  Result:=(Node<>Nil);
 | 
						|
  If Result then
 | 
						|
    begin
 | 
						|
    Node[SType]:=IntToStr(Ord(DataType));
 | 
						|
    DataNode:=Node.FirstChild;
 | 
						|
    Case DataType of
 | 
						|
      dtDWORD : DataNode.NodeValue:=IntToStr(PCardinal(@Data)^);
 | 
						|
      dtString : begin
 | 
						|
                 SetLength(S,DataSize);
 | 
						|
                 If (DataSize>0) then
 | 
						|
                   Move(Data,S[1],DataSize);
 | 
						|
                 DataNode.NodeValue:=S;
 | 
						|
                 end;
 | 
						|
      dtBinary : begin
 | 
						|
                 S:=BufToHex(Data,DataSize);
 | 
						|
                 DataNode.NodeValue:=S;
 | 
						|
                 end;
 | 
						|
    end;
 | 
						|
    end;
 | 
						|
  If Result then
 | 
						|
    begin
 | 
						|
    FDirty:=True;
 | 
						|
    MaybeFlush;
 | 
						|
    end;
 | 
						|
end;
 | 
						|
 | 
						|
Function TXmlRegistry.FindSubKey (S : String; N : TDomElement) : TDomElement;
 | 
						|
 | 
						|
Var
 | 
						|
  Node : TDOMNode;
 | 
						|
 | 
						|
begin
 | 
						|
  Result:=Nil;
 | 
						|
  If N<>Nil then
 | 
						|
    begin
 | 
						|
    Node:=N.FirstChild;
 | 
						|
    While (Result=Nil) and (Assigned(Node)) do
 | 
						|
      begin
 | 
						|
      If (Node.NodeType=ELEMENT_NODE) and (Node.NodeName=SKey) then
 | 
						|
        If CompareText(TDomElement(Node)[SName],S)=0 then
 | 
						|
          Result:=TDomElement(Node);
 | 
						|
      Node:=Node.NextSibling;
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
end;
 | 
						|
 | 
						|
Function TXmlRegistry.CreateSubKey (S : String; N : TDomElement) : TDomElement;
 | 
						|
 | 
						|
begin
 | 
						|
  Result:=FDocument.CreateElement(SKey);
 | 
						|
  Result[SName]:=S;
 | 
						|
  N.AppendChild(Result);
 | 
						|
  FDirty:=True;
 | 
						|
end;
 | 
						|
 | 
						|
Function  TXmlRegistry.FindValueKey (S : String) : TDomElement;
 | 
						|
 | 
						|
Var
 | 
						|
  Node : TDOMNode;
 | 
						|
 | 
						|
begin
 | 
						|
  If FCurrentElement<>Nil then
 | 
						|
    begin
 | 
						|
    Node:=FCurrentElement.FirstChild;
 | 
						|
    Result:=Nil;
 | 
						|
    While (Result=Nil) and (Assigned(Node)) do
 | 
						|
      begin
 | 
						|
      If (Node.NodeType=ELEMENT_NODE) and (Node.NodeName=SValue) then
 | 
						|
        If CompareText(TDomElement(Node)[SName],S)=0 then
 | 
						|
          Result:=TDomElement(Node);
 | 
						|
      Node:=Node.NextSibling;
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
end;
 | 
						|
 | 
						|
Function  TXmlRegistry.CreateValueKey (S : String) : TDomElement;
 | 
						|
 | 
						|
begin
 | 
						|
  If Assigned(FCurrentElement) then
 | 
						|
    begin
 | 
						|
    Result:=FDocument.CreateElement(SValue);
 | 
						|
    Result[SName]:=S;
 | 
						|
    // textnode to hold the value;
 | 
						|
    Result.AppendChild(FDocument.CreateTextNode(''));
 | 
						|
    FCurrentElement.AppendChild(Result);
 | 
						|
    FDirty:=True;
 | 
						|
    end
 | 
						|
  else
 | 
						|
    Result:=Nil;
 | 
						|
end;
 | 
						|
 | 
						|
Procedure TXMLregistry.MaybeFlush;
 | 
						|
 | 
						|
begin
 | 
						|
  If FAutoFlush then
 | 
						|
    Flush;
 | 
						|
end;
 | 
						|
 | 
						|
Procedure TXmlRegistry.Flush;
 | 
						|
 | 
						|
Var
 | 
						|
  S : TStream;
 | 
						|
 | 
						|
begin
 | 
						|
  If FDirty then
 | 
						|
    begin
 | 
						|
    S:=TFileStream.Create(FFileName,fmCreate);
 | 
						|
    Try
 | 
						|
      WriteXMLFile(FDocument,S);
 | 
						|
      FDirty:=False;
 | 
						|
    finally
 | 
						|
      S.Free;
 | 
						|
    end;
 | 
						|
    end;
 | 
						|
end;
 | 
						|
 | 
						|
Procedure TXmlRegistry.Load;
 | 
						|
 | 
						|
Var
 | 
						|
  S : TStream;
 | 
						|
 | 
						|
begin
 | 
						|
  If Not FileExists(FFileName) then
 | 
						|
    CreateEmptyDoc
 | 
						|
  else
 | 
						|
    begin
 | 
						|
    S:=TFileStream.Create(FFileName,fmOpenReadWrite);
 | 
						|
    try
 | 
						|
      LoadFromStream(S);
 | 
						|
    finally
 | 
						|
      S.Free;
 | 
						|
    end;
 | 
						|
    end;
 | 
						|
end;
 | 
						|
 | 
						|
Procedure TXmlRegistry.LoadFromStream(S : TStream);
 | 
						|
 | 
						|
begin
 | 
						|
  If Assigned(FDocument) then
 | 
						|
    begin
 | 
						|
    FDocument.Free;
 | 
						|
    FDocument:=Nil;
 | 
						|
    end;
 | 
						|
  ReadXMLFile(FDocument,S);
 | 
						|
  if (FDocument=Nil) then
 | 
						|
    CreateEmptyDoc;
 | 
						|
  FCurrentElement:=Nil;
 | 
						|
  FCurrentKey:='';
 | 
						|
  FRootKey:='';
 | 
						|
  FDirty:=False;
 | 
						|
end;
 | 
						|
 | 
						|
Function TXmlRegistry.BufToHex(Const Buf; Len : Integer) : String;
 | 
						|
 | 
						|
Var
 | 
						|
  P : PByte;
 | 
						|
  S : String;
 | 
						|
  I : Integer;
 | 
						|
 | 
						|
begin
 | 
						|
  SetLength(Result,Len*2);
 | 
						|
  P:=@Buf;
 | 
						|
  For I:=0 to Len-1 do
 | 
						|
    begin
 | 
						|
    S:=HexStr(P[I],2);
 | 
						|
    Move(S[1],Result[I*2+1],2);
 | 
						|
    end;
 | 
						|
end;
 | 
						|
 | 
						|
Function TXMLRegistry.hexToBuf(Const Str : String; Var Buf; Var Len : Integer ) : Integer;
 | 
						|
 | 
						|
Var
 | 
						|
  I : Integer;
 | 
						|
  P : PByte;
 | 
						|
  S : String;
 | 
						|
  B : Byte;
 | 
						|
  Code : Integer;
 | 
						|
 | 
						|
begin
 | 
						|
  P:=@Buf;
 | 
						|
  Len:= Length(Str) div 2;
 | 
						|
  For I:=0 to Len-1 do
 | 
						|
    begin
 | 
						|
    S:='$'+Copy(Str,(I*2)+1,2);
 | 
						|
    Val(S,B,Code);
 | 
						|
    If Code<>0 then
 | 
						|
      begin
 | 
						|
      Inc(Result);
 | 
						|
      B:=0;
 | 
						|
      end;
 | 
						|
    P[I]:=B;
 | 
						|
    end;
 | 
						|
end;
 | 
						|
 | 
						|
Function TXMLRegistry.DeleteValue(S : String) : Boolean;
 | 
						|
 | 
						|
Var
 | 
						|
  N : TDomElement;
 | 
						|
 | 
						|
begin
 | 
						|
  N:=FindValueKey(S);
 | 
						|
  Result:=(N<>Nil);
 | 
						|
  If Result then
 | 
						|
    begin
 | 
						|
    FCurrentElement.RemoveChild(N);
 | 
						|
    FDirty:=True;
 | 
						|
    MaybeFlush;
 | 
						|
    end;
 | 
						|
end;
 | 
						|
 | 
						|
Function TXMLRegistry.GetValueSize(Name : String) : Integer;
 | 
						|
 | 
						|
Var
 | 
						|
  Info : TDataInfo;
 | 
						|
 | 
						|
begin
 | 
						|
  If GetValueInfo(Name,Info) then
 | 
						|
    Result:=Info.DataSize
 | 
						|
  else
 | 
						|
    Result:=-1;
 | 
						|
end;
 | 
						|
 | 
						|
Function TXMLRegistry.GetValueType(Name : String) : TDataType;
 | 
						|
 | 
						|
Var
 | 
						|
  Info : TDataInfo;
 | 
						|
 | 
						|
begin
 | 
						|
  If GetValueInfo(Name,Info) then
 | 
						|
    Result:=Info.DataType
 | 
						|
  else
 | 
						|
    Result:=dtUnknown;
 | 
						|
end;
 | 
						|
 | 
						|
Function TXMLRegistry.GetValueInfo(Name : String; Var Info : TDataInfo) : Boolean;
 | 
						|
 | 
						|
Var
 | 
						|
  N  : TDomElement;
 | 
						|
  DN : TDomNode;
 | 
						|
begin
 | 
						|
  N:=FindValueKey(Name);
 | 
						|
  Result:=(N<>Nil);
 | 
						|
  If Result then
 | 
						|
    begin
 | 
						|
    DN:=N.FirstChild;
 | 
						|
    Result:=DN<>Nil;
 | 
						|
    If Result then
 | 
						|
    With Info do
 | 
						|
      begin
 | 
						|
      DataType:=TDataType(StrToIntDef(N[SType],0));
 | 
						|
      Case DataType of
 | 
						|
        dtUnknown : DataSize:=0;
 | 
						|
        dtDword   : Datasize:=SizeOf(Cardinal);
 | 
						|
        dtString  : DataSize:=Length(DN.NodeValue);
 | 
						|
        dtBinary  : DataSize:=Length(DN.NodeValue) div 2;
 | 
						|
      end;
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
end;
 | 
						|
 | 
						|
Function  TXMLRegistry.GetKeyInfo(Var Info : TKeyInfo) : Boolean;
 | 
						|
 | 
						|
Var
 | 
						|
  Node,DataNode : TDOMNode;
 | 
						|
  L    : Integer;
 | 
						|
 | 
						|
begin
 | 
						|
  FillChar(Info,SizeOf(Info),0);
 | 
						|
  Result:=FCurrentElement<>Nil;
 | 
						|
  If Result then
 | 
						|
    With Info do
 | 
						|
      begin
 | 
						|
      If (FFileName<>'') Then
 | 
						|
        FTime:=FileAge(FFileName);
 | 
						|
      Node:=FCurrentElement.FirstChild;
 | 
						|
      While Assigned(Node) do
 | 
						|
        begin
 | 
						|
        If (Node.NodeType=ELEMENT_NODE) then
 | 
						|
          If (Node.NodeName=SKey) then
 | 
						|
            begin
 | 
						|
            Inc(SubKeys);
 | 
						|
            L:=Length(TDomElement(Node)[SName]);
 | 
						|
            If (L>SubKeyLen) then
 | 
						|
              SubKeyLen:=L;
 | 
						|
            end
 | 
						|
          else if (Node.NodeName=SValue) then
 | 
						|
            begin
 | 
						|
            Inc(Values);
 | 
						|
            L:=Length(TDomElement(Node)[SName]);
 | 
						|
            If (L>ValueLen) then
 | 
						|
              ValueLen:=L;
 | 
						|
            DataNode:=TDomElement(Node).FirstChild;
 | 
						|
            If (DataNode<>Nil) and (DataNode is TDomText) then
 | 
						|
              Case TDataType(StrToIntDef(TDomElement(Node)[SType],0)) of
 | 
						|
                dtUnknown : L:=0;
 | 
						|
                dtDWord   : L:=4;
 | 
						|
                DtString  : L:=Length(DataNode.NodeValue);
 | 
						|
                dtBinary  : L:=Length(DataNode.NodeValue) div 2;
 | 
						|
              end
 | 
						|
            else
 | 
						|
              L:=0;
 | 
						|
            If (L>DataLen) Then
 | 
						|
              DataLen:=L;
 | 
						|
            end;
 | 
						|
        Node:=Node.NextSibling;
 | 
						|
        end;
 | 
						|
      end;
 | 
						|
end;
 | 
						|
 | 
						|
Function TXMLRegistry.EnumSubKeys(List : TStrings) : Integer;
 | 
						|
 | 
						|
Var
 | 
						|
  Node : TDOMNode;
 | 
						|
 | 
						|
begin
 | 
						|
  List.Clear;
 | 
						|
  Result:=0;
 | 
						|
  If FCurrentElement<>Nil then
 | 
						|
    begin
 | 
						|
    Node:=FCurrentElement.FirstChild;
 | 
						|
    While Assigned(Node) do
 | 
						|
      begin
 | 
						|
      If (Node.NodeType=ELEMENT_NODE) and (Node.NodeName=SKey) then
 | 
						|
        List.Add(TDomElement(Node)[SName]);
 | 
						|
      Node:=Node.NextSibling;
 | 
						|
      end;
 | 
						|
    Result:=List.Count;
 | 
						|
    end;
 | 
						|
end;
 | 
						|
 | 
						|
Function TXMLRegistry.EnumValues(List : TStrings) : Integer;
 | 
						|
 | 
						|
Var
 | 
						|
  Node : TDOMNode;
 | 
						|
 | 
						|
begin
 | 
						|
  List.Clear;
 | 
						|
  Result:=0;
 | 
						|
  If FCurrentElement<>Nil then
 | 
						|
    begin
 | 
						|
    Node:=FCurrentElement.FirstChild;
 | 
						|
    While Assigned(Node) do
 | 
						|
      begin
 | 
						|
      If (Node.NodeType=ELEMENT_NODE) and (Node.NodeName=SValue) then
 | 
						|
        List.Add(TDomElement(Node)[SName]);
 | 
						|
      Node:=Node.NextSibling;
 | 
						|
      end;
 | 
						|
    Result:=List.Count;
 | 
						|
    end;
 | 
						|
end;
 | 
						|
 | 
						|
Function TXMLRegistry.KeyExists(KeyPath : String) : Boolean;
 | 
						|
 | 
						|
begin
 | 
						|
  Result:=FindKey(KeyPath)<>Nil;
 | 
						|
end;
 | 
						|
 | 
						|
Function TXMLRegistry.RenameValue(Const OldName,NewName : String) : Boolean;
 | 
						|
 | 
						|
Var
 | 
						|
  N : TDomElement;
 | 
						|
 | 
						|
begin
 | 
						|
  N:=FindValueKey(OldName);
 | 
						|
  If (N<>Nil) then
 | 
						|
    begin
 | 
						|
    N[SName]:=NewName;
 | 
						|
    FDirty:=True;
 | 
						|
    MaybeFlush;
 | 
						|
    end;
 | 
						|
end;
 | 
						|
 | 
						|
Function TXMLRegistry.FindKey (S : String) : TDomElement;
 | 
						|
 | 
						|
Var
 | 
						|
  SubKey : String;
 | 
						|
  P : Integer;
 | 
						|
  Node : TDomElement;
 | 
						|
 | 
						|
begin
 | 
						|
  Result:=Nil;
 | 
						|
  If (Length(S)=0) then
 | 
						|
    Exit;
 | 
						|
  S:=NormalizeKey(S);
 | 
						|
  If (S[1]<>'/') then
 | 
						|
    Node:=FCurrentElement
 | 
						|
  else
 | 
						|
    begin
 | 
						|
    Delete(S,1,1);
 | 
						|
    Node:=FDocument.DocumentElement;
 | 
						|
    If (FRootKey<>'') then
 | 
						|
      S:=FRootKey+S;
 | 
						|
    end;
 | 
						|
  repeat
 | 
						|
    P:=Pos('/',S);
 | 
						|
    If (P<>0) then
 | 
						|
      begin
 | 
						|
      SubKey:=Copy(S,1,P-1);
 | 
						|
      Delete(S,1,P);
 | 
						|
      Result:=FindSubKey(SubKey,Node);
 | 
						|
      Node:=Result;
 | 
						|
      end;
 | 
						|
  Until (Result=Nil) or (Length(S)=0);
 | 
						|
end;
 | 
						|
 | 
						|
Function  TXmlRegistry.ValueExists(ValueName : String) : Boolean;
 | 
						|
 | 
						|
begin
 | 
						|
  Result:=FindValueKey(ValueName)<>Nil;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
end.
 |