Browse Source

* Patch from Bart Broersma to make TRegistry unicode-capable

git-svn-id: trunk@41784 -
michael 6 years ago
parent
commit
79bf26ac4b

+ 1 - 1
packages/fcl-registry/src/regdef.inc

@@ -2,7 +2,7 @@ Type
   HKEY = THandle;
   PHKEY = ^HKEY;
   
-{$ifdef windows}
+{$if defined(windows) and not defined(XMLREG)}
 
 { Direct mapping to constants in Windows unit }
 

+ 526 - 105
packages/fcl-registry/src/registry.pp

@@ -39,6 +39,8 @@ type
     DataSize: Integer;
   end;
 
+  TUnicodeStringArray = Array of UnicodeString;
+
 { ---------------------------------------------------------------------
     TRegistry
   ---------------------------------------------------------------------}
@@ -54,21 +56,30 @@ type
     fCurrentKey: HKEY;
     fRootKey: HKEY;
     fLazyWrite: Boolean;
-    fCurrentPath: string;
+    fCurrentPath: UnicodeString;
     function GetLastErrorMsg: string;
+    function RegMultiSzDataToUnicodeStringArray(U: UnicodeString): TUnicodeStringArray;
+    function ListToArray(List: TStrings; IsUtf8: Boolean): TUnicodeStringArray;
+    procedure ArrayToList(const Arr: TUnicodeStringArray; List: TStrings; ForceUtf8: Boolean);
     procedure SetRootKey(Value: HKEY);
     Procedure SysRegCreate;
     Procedure SysRegFree;
-    Function  SysGetData(const Name: String; Buffer: Pointer; BufSize: Integer; Out RegData: TRegDataType): Integer;
-    Function  SysPutData(const Name: string; Buffer: Pointer; BufSize: Integer; RegData: TRegDataType) : Boolean;
-    Function  SysCreateKey(const Key: String): Boolean;
+    Function  SysGetData(const Name: UnicodeString; Buffer: Pointer; BufSize: Integer; Out RegData: TRegDataType): Integer;
+    Function  SysPutData(const Name: UnicodeString; Buffer: Pointer; BufSize: Integer; RegData: TRegDataType) : Boolean;
+    Function  SysCreateKey(Key: UnicodeString): Boolean;
   protected
     function GetBaseKey(Relative: Boolean): HKey;
-    function GetData(const Name: string; Buffer: Pointer;
+    function GetData(const Name: UnicodeString; Buffer: Pointer;
+                  BufSize: Integer; Out RegData: TRegDataType): Integer;
+    function GetData(const Name: String; Buffer: Pointer;
                   BufSize: Integer; Out RegData: TRegDataType): Integer;
-    function GetKey(const Key: string): HKEY;
-    procedure ChangeKey(Value: HKey; const Path: string);
-    procedure PutData(const Name: string; Buffer: Pointer;
+    function GetKey(Key: UnicodeString): HKEY;
+    function GetKey(Key: String): HKEY;
+    procedure ChangeKey(Value: HKey; const Path: UnicodeString);
+    procedure ChangeKey(Value: HKey; const Path: String);
+    procedure PutData(const Name: UnicodeString; Buffer: Pointer;
+                  BufSize: Integer; RegData: TRegDataType);
+    procedure PutData(const Name: String; Buffer: Pointer;
                   BufSize: Integer; RegData: TRegDataType);
     procedure SetCurrentKey(Value: HKEY);
   public
@@ -76,58 +87,105 @@ type
     constructor Create(aaccess:longword); overload;
     destructor Destroy; override;
 
-    function CreateKey(const Key: string): Boolean;
-    function DeleteKey(const Key: string): Boolean;
-    function DeleteValue(const Name: string): Boolean;
-    function GetDataInfo(const ValueName: string; Out Value: TRegDataInfo): Boolean;
-    function GetDataSize(const ValueName: string): Integer;
-    function GetDataType(const ValueName: string): TRegDataType;
+    function CreateKey(const Key: UnicodeString): Boolean;
+    function CreateKey(const Key: String): Boolean;
+    function DeleteKey(const Key: UnicodeString): Boolean;
+    function DeleteKey(const Key: String): Boolean;
+    function DeleteValue(const Name: UnicodeString): Boolean;
+    function DeleteValue(const Name: String): Boolean;
+    function GetDataInfo(const ValueName: UnicodeString; Out Value: TRegDataInfo): Boolean;
+    function GetDataInfo(const ValueName: String; Out Value: TRegDataInfo): Boolean;
+    function GetDataSize(const ValueName: UnicodeString): Integer;
+    function GetDataSize(const ValueName: String): Integer;
+    function GetDataType(const ValueName: UnicodeString): TRegDataType;
+    function GetDataType(const ValueName: String): TRegDataType;
     function GetKeyInfo(Out Value: TRegKeyInfo): Boolean;
     function HasSubKeys: Boolean;
-    function KeyExists(const Key: string): Boolean;
-    function LoadKey(const Key, FileName: string): Boolean;
-    function OpenKey(const Key: string; CanCreate: Boolean): Boolean;
-    function OpenKeyReadOnly(const Key: string): Boolean;
-    function ReadCurrency(const Name: string): Currency;
-    function ReadBinaryData(const Name: string; var Buffer; BufSize: Integer): Integer;
-    function ReadBool(const Name: string): Boolean;
-    function ReadDate(const Name: string): TDateTime;
-    function ReadDateTime(const Name: string): TDateTime;
-    function ReadFloat(const Name: string): Double;
-    function ReadInteger(const Name: string): Integer;
-    function ReadInt64(const Name: string): Int64;
-    function ReadString(const Name: string): string;
-    procedure ReadStringList(const Name: string; AList: TStrings);
-    function ReadTime(const Name: string): TDateTime;
-    function RegistryConnect(const UNCName: string): Boolean;
-    function ReplaceKey(const Key, FileName, BackUpFileName: string): Boolean;
-    function RestoreKey(const Key, FileName: string): Boolean;
-    function SaveKey(const Key, FileName: string): Boolean;
-    function UnLoadKey(const Key: string): Boolean;
-    function ValueExists(const Name: string): Boolean;
+    function KeyExists(const Key: UnicodeString): Boolean;
+    function KeyExists(const Key: String): Boolean;
+    function LoadKey(const Key, FileName: UnicodeString): Boolean;
+    function LoadKey(const Key, FileName: String): Boolean;
+    function OpenKey(const Key: UnicodeString; CanCreate: Boolean): Boolean;
+    function OpenKey(const Key: String; CanCreate: Boolean): Boolean;
+    function OpenKeyReadOnly(const Key: UnicodeString): Boolean;
+    function OpenKeyReadOnly(const Key: String): Boolean;
+    function ReadCurrency(const Name: UnicodeString): Currency;
+    function ReadCurrency(const Name: String): Currency;
+    function ReadBinaryData(const Name: UnicodeString; var Buffer; BufSize: Integer): Integer;
+    function ReadBinaryData(const Name: String; var Buffer; BufSize: Integer): Integer;
+    function ReadBool(const Name: UnicodeString): Boolean;
+    function ReadBool(const Name: String): Boolean;
+    function ReadDate(const Name: UnicodeString): TDateTime;
+    function ReadDate(const Name: String): TDateTime;
+    function ReadDateTime(const Name: UnicodeString): TDateTime;
+    function ReadDateTime(const Name: String): TDateTime;
+    function ReadFloat(const Name: UnicodeString): Double;
+    function ReadFloat(const Name: String): Double;
+    function ReadInteger(const Name: UnicodeString): Integer;
+    function ReadInteger(const Name: String): Integer;
+    function ReadInt64(const Name: UnicodeString): Int64;
+    function ReadInt64(const Name: String): Int64;
+    function ReadString(const Name: UnicodeString): UnicodeString;
+    function ReadString(const Name: String): string;
+    procedure ReadStringList(const Name: UnicodeString; AList: TStrings; ForceUtf8: Boolean=False);
+    procedure ReadStringList(const Name: String; AList: TStrings);
+    function ReadStringArray(const Name: UnicodeString): TUnicodeStringArray;
+    function ReadStringArray(const Name: String): TStringArray;
+    function ReadTime(const Name: UnicodeString): TDateTime;
+    function ReadTime(const Name: String): TDateTime;
+    function RegistryConnect(const UNCName: UnicodeString): Boolean;
+    function RegistryConnect(const UNCName: String): Boolean;
+    function ReplaceKey(const Key, FileName, BackUpFileName: UnicodeString): Boolean;
+    function ReplaceKey(const Key, FileName, BackUpFileName: String): Boolean;
+    function RestoreKey(const Key, FileName: UnicodeString): Boolean;
+    function RestoreKey(const Key, FileName: String): Boolean;
+    function SaveKey(const Key, FileName: UnicodeString): Boolean;
+    function SaveKey(const Key, FileName: String): Boolean;
+    function UnLoadKey(const Key: UnicodeString): Boolean;
+    function UnLoadKey(const Key: String): Boolean;
+    function ValueExists(const Name: UnicodeString): Boolean;
+    function ValueExists(const Name: String): Boolean;
 
     procedure CloseKey;
     procedure CloseKey(key:HKEY);
     procedure GetKeyNames(Strings: TStrings);
+    function GetKeyNames: TUnicodeStringArray;
     procedure GetValueNames(Strings: TStrings);
-    procedure MoveKey(const OldName, NewName: string; Delete: Boolean);
-    procedure RenameValue(const OldName, NewName: string);
-    procedure WriteCurrency(const Name: string; Value: Currency);
-    procedure WriteBinaryData(const Name: string; var Buffer; BufSize: Integer);
-    procedure WriteBool(const Name: string; Value: Boolean);
-    procedure WriteDate(const Name: string; Value: TDateTime);
-    procedure WriteDateTime(const Name: string; Value: TDateTime);
-    procedure WriteFloat(const Name: string; Value: Double);
-    procedure WriteInteger(const Name: string; Value: Integer);
-    procedure WriteInt64(const Name: string; Value: Int64);
-    procedure WriteString(const Name, Value: string);
-    procedure WriteExpandString(const Name, Value: string);
-    procedure WriteStringList(const Name: string; List: TStrings);
-    procedure WriteTime(const Name: string; Value: TDateTime);
+    //ToDo
+    function GetValueNames: TUnicodeStringArray;
+    procedure MoveKey(const OldName, NewName: UnicodeString; Delete: Boolean);
+    procedure MoveKey(const OldName, NewName: String; Delete: Boolean);
+    procedure RenameValue(const OldName, NewName: UnicodeString);
+    procedure RenameValue(const OldName, NewName: String);
+    procedure WriteCurrency(const Name: UnicodeString; Value: Currency);
+    procedure WriteCurrency(const Name: String; Value: Currency);
+    procedure WriteBinaryData(const Name: UnicodeString; var Buffer; BufSize: Integer);
+    procedure WriteBinaryData(const Name: String; var Buffer; BufSize: Integer);
+    procedure WriteBool(const Name: UnicodeString; Value: Boolean);
+    procedure WriteBool(const Name: String; Value: Boolean);
+    procedure WriteDate(const Name: UnicodeString; Value: TDateTime);
+    procedure WriteDate(const Name: String; Value: TDateTime);
+    procedure WriteDateTime(const Name: UnicodeString; Value: TDateTime);
+    procedure WriteDateTime(const Name: String; Value: TDateTime);
+    procedure WriteFloat(const Name: UnicodeString; Value: Double);
+    procedure WriteFloat(const Name: String; Value: Double);
+    procedure WriteInteger(const Name: UnicodeString; Value: Integer);
+    procedure WriteInteger(const Name: String; Value: Integer);
+    procedure WriteInt64(const Name: UnicodeString; Value: Int64);
+    procedure WriteInt64(const Name: String; Value: Int64);
+    procedure WriteString(const Name, Value: UnicodeString);
+    procedure WriteString(const Name, Value: String);
+    procedure WriteExpandString(const Name, Value: UnicodeString);
+    procedure WriteExpandString(const Name, Value: String);
+    procedure WriteStringList(const Name: UnicodeString; List: TStrings; IsUtf8: Boolean=False);
+    procedure WriteStringArray(const Name: UnicodeString; const Arr: TUnicodeStringArray);
+    procedure WriteStringArray(const Name: String; const Arr: TStringArray);
+    procedure WriteTime(const Name: UnicodeString; Value: TDateTime);
+    procedure WriteTime(const Name: String; Value: TDateTime);
 
     property Access: LongWord read fAccess write fAccess;
     property CurrentKey: HKEY read fCurrentKey;
-    property CurrentPath: string read fCurrentPath;
+    property CurrentPath: UnicodeString read fCurrentPath;
     property LazyWrite: Boolean read fLazyWrite write fLazyWrite;
     property RootKey: HKEY read fRootKey write SetRootKey;
     Property StringSizeIncludesNull : Boolean read FStringSizeIncludesNull;
@@ -235,6 +293,16 @@ implementation
     Generic, implementation-independent code.
   ---------------------------------------------------------------------}
 
+{$ifdef DebugRegistry}
+function DbgS(const S: UnicodeString): String;
+var
+  C: WideChar;
+begin
+  Result := '';
+  for C in S do Result := Result + IntToHex(Word(C),4) + #32;
+  Result := TrimRight(Result);
+end;
+{$endif}
 
 constructor TRegistry.Create;
 
@@ -261,7 +329,7 @@ begin
   inherited Destroy;
 end;
 
-function TRegistry.CreateKey(const Key: string): Boolean;
+function TRegistry.CreateKey(const Key: UnicodeString): Boolean;
 
 begin
   Result:=SysCreateKey(Key);
@@ -269,6 +337,27 @@ begin
     Raise ERegistryException.CreateFmt(SRegCreateFailed, [Key]);
 end;
 
+function TRegistry.CreateKey(const Key: String): Boolean;
+begin
+  Result:=CreateKey(UnicodeString(Key));
+end;
+
+function TRegistry.DeleteKey(const Key: String): Boolean;
+begin
+  Result:=DeleteKey(UnicodeString(Key));
+end;
+
+function TRegistry.DeleteValue(const Name: String): Boolean;
+begin
+  Result:=DeleteValue(UnicodeString(Name));
+end;
+
+function TRegistry.GetDataInfo(const ValueName: String; out Value: TRegDataInfo
+  ): Boolean;
+begin
+  Result:=GetDataInfo(UnicodeString(ValueName), Value);
+end;
+
 function TRegistry.GetBaseKey(Relative: Boolean): HKey;
 begin
   If Relative and (CurrentKey<>0) Then
@@ -277,14 +366,31 @@ begin
     Result := RootKey;
 end;
 
-function TRegistry.GetData(const Name: string; Buffer: Pointer; BufSize: Integer; out RegData: TRegDataType): Integer;
+function TRegistry.GetData(const Name: UnicodeString; Buffer: Pointer; BufSize: Integer; out RegData: TRegDataType): Integer;
 begin
   Result:=SysGetData(Name,Buffer,BufSize,RegData);
   If (Result=-1) then
     Raise ERegistryException.CreateFmt(SRegGetDataFailed, [Name]);
 end;
 
-procedure TRegistry.PutData(const Name: string; Buffer: Pointer;
+function TRegistry.GetData(const Name: String; Buffer: Pointer;
+  BufSize: Integer; out RegData: TRegDataType): Integer;
+begin
+  Result:=GetData(UnicodeString(Name), Buffer, BufSize, RegData);
+end;
+
+function TRegistry.GetKey(Key: String): HKEY;
+begin
+  Result:=GetKey(UnicodeString(Key));
+end;
+
+procedure TRegistry.ChangeKey(Value: HKey; const Path: String);
+begin
+  ChangeKey(Value, UnicodeString(Path));
+end;
+
+
+procedure TRegistry.PutData(const Name: UnicodeString; Buffer: Pointer;
   BufSize: Integer; RegData: TRegDataType);
 
 begin
@@ -292,8 +398,14 @@ begin
     Raise ERegistryException.CreateFmt(SRegSetDataFailed, [Name]);
 end;
 
+procedure TRegistry.PutData(const Name: String; Buffer: Pointer;
+  BufSize: Integer; RegData: TRegDataType);
+begin
+  PutData(UnicodeString(Name), Buffer, BufSize, RegData);
+end;
+
 
-function TRegistry.GetDataSize(const ValueName: string): Integer;
+function TRegistry.GetDataSize(const ValueName: UnicodeString): Integer;
 
 Var
   Info: TRegDataInfo;
@@ -305,7 +417,12 @@ begin
     Result := -1;
 end;
 
-function TRegistry.GetDataType(const ValueName: string): TRegDataType;
+function TRegistry.GetDataSize(const ValueName: String): Integer;
+begin
+  Result:=GetDataSize(UnicodeString(ValueName));
+end;
+
+function TRegistry.GetDataType(const ValueName: UnicodeString): TRegDataType;
 
 Var
   Info: TRegDataInfo;
@@ -315,6 +432,32 @@ begin
   Result:=Info.RegData;
 end;
 
+function TRegistry.GetDataType(const ValueName: String): TRegDataType;
+begin
+  Result:=GetDataType(UnicodeString(ValueName));
+end;
+
+
+function TRegistry.KeyExists(const Key: String): Boolean;
+begin
+  Result:=KeyExists(UnicodeString(Key));
+end;
+
+function TRegistry.LoadKey(const Key, FileName: String): Boolean;
+begin
+  Result:=LoadKey(UnicodeString(Key), UnicodeString(FileName));
+end;
+
+function TRegistry.OpenKey(const Key: String; CanCreate: Boolean): Boolean;
+begin
+  Result:=OpenKey(UnicodeString(Key), CanCreate);
+end;
+
+function TRegistry.OpenKeyReadOnly(const Key: String): Boolean;
+begin
+  Result:=OpenKeyReadOnly(UnicodeString(Key));
+end;
+
 function TRegistry.HasSubKeys: Boolean;
 
 Var
@@ -326,7 +469,7 @@ begin
     Result:=(Info.NumSubKeys>0);
 end;
 
-function TRegistry.ReadBinaryData(const Name: string; var Buffer; BufSize: Integer): Integer;
+function TRegistry.ReadBinaryData(const Name: UnicodeString; var Buffer; BufSize: Integer): Integer;
 
 Var
   RegDataType: TRegDataType;
@@ -337,7 +480,13 @@ begin
     Raise ERegistryException.CreateFmt(SInvalidRegType, [Name]);
 end;
 
-function TRegistry.ReadInteger(const Name: string): Integer;
+function TRegistry.ReadBinaryData(const Name: String; var Buffer;
+  BufSize: Integer): Integer;
+begin
+  Result:=ReadBinaryData(UnicodeString(Name), Buffer, BufSize);
+end;
+
+function TRegistry.ReadInteger(const Name: UnicodeString): Integer;
 
 Var
   RegDataType: TRegDataType;
@@ -348,7 +497,12 @@ begin
     Raise ERegistryException.CreateFmt(SInvalidRegType, [Name]);
 end;
 
-function TRegistry.ReadInt64(const Name: string): Int64;
+function TRegistry.ReadInteger(const Name: String): Integer;
+begin
+  Result:=ReadInteger(UnicodeString(Name));
+end;
+
+function TRegistry.ReadInt64(const Name: UnicodeString): Int64;
 
 Var
   RegDataType: TRegDataType;
@@ -359,20 +513,35 @@ begin
     Raise ERegistryException.CreateFmt(SInvalidRegType, [Name]);
 end;
 
-function TRegistry.ReadBool(const Name: string): Boolean;
+function TRegistry.ReadInt64(const Name: String): Int64;
+begin
+  Result:=ReadInt64(UnicodeString(Name));
+end;
+
+function TRegistry.ReadBool(const Name: UnicodeString): Boolean;
 
 begin
   Result:=ReadInteger(Name)<>0;
 end;
 
-function TRegistry.ReadCurrency(const Name: string): Currency;
+function TRegistry.ReadBool(const Name: String): Boolean;
+begin
+  Result:=ReadBool(UnicodeString(Name));
+end;
+
+function TRegistry.ReadCurrency(const Name: UnicodeString): Currency;
 
 begin
   Result:=Default(Currency);
   ReadBinaryData(Name, Result, SizeOf(Currency));
 end;
 
-function TRegistry.ReadDate(const Name: string): TDateTime;
+function TRegistry.ReadCurrency(const Name: String): Currency;
+begin
+  Result:=ReadCurrency(UnicodeString(Name));
+end;
+
+function TRegistry.ReadDate(const Name: UnicodeString): TDateTime;
 
 begin
   Result:=Default(TDateTime);
@@ -380,21 +549,36 @@ begin
   Result:=Trunc(Result);
 end;
 
-function TRegistry.ReadDateTime(const Name: string): TDateTime;
+function TRegistry.ReadDate(const Name: String): TDateTime;
+begin
+  Result:=ReadDate(UnicodeString(Name));
+end;
+
+function TRegistry.ReadDateTime(const Name: UnicodeString): TDateTime;
 
 begin
   Result:=Default(TDateTime);
   ReadBinaryData(Name, Result, SizeOf(TDateTime));
 end;
 
-function TRegistry.ReadFloat(const Name: string): Double;
+function TRegistry.ReadDateTime(const Name: String): TDateTime;
+begin
+  Result:=ReadDateTime(UnicodeString(Name));
+end;
+
+function TRegistry.ReadFloat(const Name: UnicodeString): Double;
 
 begin
   Result:=Default(Double);
   ReadBinaryData(Name,Result,SizeOf(Double));
 end;
 
-function TRegistry.ReadString(const Name: string): string;
+function TRegistry.ReadFloat(const Name: String): Double;
+begin
+  Result:=ReadFloat(UnicodeString(Name));
+end;
+
+function TRegistry.ReadString(const Name: UnicodeString): UnicodeString;
 
 Var
   Info : TRegDataInfo;
@@ -421,46 +605,138 @@ begin
       if StringSizeIncludesNull and
          (u[Length(u)] = WideChar(0)) then
         SetLength(u,Length(u)-1);
-      Result:=UTF8Encode(u);
+      Result:=u;
     end;
   end;
 end;
 
-procedure TRegistry.ReadStringList(const Name: string; AList: TStrings);
+function TRegistry.ReadString(const Name: String): string;
+begin
+  Result:=ReadString(UnicodeString(Name));
+end;
+
+
+procedure TRegistry.ReadStringList(const Name: UnicodeString; AList: TStrings; ForceUtf8: Boolean=False);
+
+Var
+  UArr: TUnicodeStringArray;
+
+begin
+  UArr := ReadStringArray(Name);
+  ArrayToList(UArr, AList, ForceUtf8);
+end;
+
+procedure TRegistry.ReadStringList(const Name: String; AList: TStrings);
+begin
+  ReadStringList(UnicodeString(Name), AList);
+end;
+
+function TRegistry.RegMultiSzDataToUnicodeStringArray(U: UnicodeString): TUnicodeStringArray;
+var
+  Len, i, p: Integer;
+  Sub: UnicodeString;
+begin
+  Result := nil;
+  if (U = '') then Exit;
+  Len := 1;
+  for i := 1 to Length(U) do if (U[i] = #0) then Inc(Len);
+  SetLength(Result, Len);
+  i := 0;
+
+  while (U <> '') and (i < Length(Result)) do
+  begin
+    p := Pos(#0, U);
+    if (p = 0) then p := Length(U) + 1;
+    Sub := Copy(U, 1, p - 1);
+    Result[i] := Sub;
+    System.Delete(U, 1, p);
+    Inc(i);
+  end;
+end;
+
+function TRegistry.ListToArray(List: TStrings; IsUtf8: Boolean): TUnicodeStringArray;
+var
+  i, curr, Len: Integer;
+  u: UnicodeString;
+begin
+  Result := nil;
+  Len := List.Count;
+  SetLength(Result, Len);
+  //REG_MULTI_SZ data cannot contain empty strings
+  curr := 0;
+  for i := 0 to List.Count - 1 do
+  begin
+    if IsUtf8 then
+      u := Utf8Decode(List[i])
+    else
+      u := List[i];
+    if (u>'') then
+    begin
+      Result[curr] := u;
+      inc(curr);
+    end
+    else
+      Dec(Len);
+  end;
+  if (Len <> List.Count) then SetLength(Result, Len);
+end;
+
+procedure TRegistry.ArrayToList(const Arr: TUnicodeStringArray; List: TStrings; ForceUtf8: Boolean);
+var
+  i: Integer;
+begin
+  List.Clear;
+  for i := Low(Arr) to High(Arr) do
+  begin
+    if ForceUtf8 then
+      List.Add(Utf8Encode(Arr[i]))
+    else
+      List.Add(String(Arr[i]));
+  end;
+end;
 
+function TRegistry.ReadStringArray(const Name: UnicodeString): TUnicodeStringArray;
 Var
   Info : TRegDataInfo;
   ReadDataSize: Integer;
-  Data: string;
+  Data: UnicodeString;
 
 begin
-  AList.Clear;
+  Result := nil;
   GetDataInfo(Name,Info);
+  //writeln('TRegistry.ReadStringArray: datasize=',info.datasize);
   if info.datasize>0 then
     begin
      If Not (Info.RegData in [rdMultiString]) then
        Raise ERegistryException.CreateFmt(SInvalidRegType, [Name]);
      SetLength(Data,Info.DataSize);
-     ReadDataSize := GetData(Name,PChar(Data),Info.DataSize,Info.RegData);
+     ReadDataSize := GetData(Name,PWideChar(Data),Info.DataSize,Info.RegData) div SizeOf(WideChar);
+     //writeln('TRegistry.ReadStringArray: ReadDataSize=',ReadDataSize);
      if ReadDataSize > 0 then
      begin
-       // If the data has the REG_SZ, REG_MULTI_SZ or REG_EXPAND_SZ type,
-       // the size includes any terminating null character or characters
-       // unless the data was stored without them! (RegQueryValueEx @ MSDN)
-       if StringSizeIncludesNull then begin
-         if Data[ReadDataSize] = #0 then
-           Dec(ReadDataSize);
-         if Data[ReadDataSize] = #0 then
-           Dec(ReadDataSize);
-       end;
+       // Windows returns the data with or without trailing zero's, so just strip all trailing null characters
+        while (Data[ReadDataSize] = #0) do Dec(ReadDataSize);
        SetLength(Data, ReadDataSize);
-       Data := StringReplace(Data, #0, LineEnding, [rfReplaceAll]);
-       AList.Text := Data;
+       //writeln('Data=',dbgs(data));
+       //Data := UnicodeStringReplace(Data, #0, AList.LineBreak, [rfReplaceAll]);
+       //AList.Text := Data;
+       Result := RegMultiSzDataToUnicodeStringArray(Data);
      end
    end
 end;
 
-function TRegistry.ReadTime(const Name: string): TDateTime;
+function TRegistry.ReadStringArray(const Name: String): TStringArray;
+var
+  UArr: TUnicodeStringArray;
+  i: Integer;
+begin
+  Result := nil;
+  UArr := ReadStringArray(UnicodeString(Name));
+  SetLength(Result, Length(UArr));
+  for i := Low(UArr) to High(UArr) do Result[i] := UArr[i];
+end;
+
+function TRegistry.ReadTime(const Name: UnicodeString): TDateTime;
 
 begin
   Result:=Default(TDateTime);
@@ -468,83 +744,228 @@ begin
   Result:=Frac(Result);
 end;
 
-procedure TRegistry.WriteBinaryData(const Name: string; var Buffer; BufSize: Integer);
+function TRegistry.ReadTime(const Name: String): TDateTime;
+begin
+  Result:=ReadTime(UnicodeString(Name));
+end;
+
+function TRegistry.RegistryConnect(const UNCName: String): Boolean;
+begin
+  Result:=RegistryConnect(UnicodeString(UNCName));
+end;
+
+function TRegistry.ReplaceKey(const Key, FileName, BackUpFileName: String): Boolean;
+begin
+  Result:=ReplaceKey(UnicodeString(Key), UnicodeString(FileName), UnicodeString(BackUpFileName))
+end;
+
+function TRegistry.RestoreKey(const Key, FileName: String): Boolean;
+begin
+  Result:=RestoreKey(UnicodeString(Key), UnicodeString(FileName));
+end;
+
+function TRegistry.SaveKey(const Key, FileName: String): Boolean;
+begin
+  Result:=SaveKey(UnicodeString(Key), UnicodeString(FileName));
+end;
+
+function TRegistry.UnLoadKey(const Key: String): Boolean;
+begin
+  Result:=UnloadKey(UnicodeString(Key));
+end;
+
+function TRegistry.ValueExists(const Name: String): Boolean;
+begin
+  Result:=ValueExists(UnicodeString(Name));
+end;
+
+procedure TRegistry.WriteBinaryData(const Name: UnicodeString; var Buffer; BufSize: Integer);
 begin
   PutData(Name, @Buffer, BufSize, rdBinary);
 end;
 
-procedure TRegistry.WriteBool(const Name: string; Value: Boolean);
+procedure TRegistry.WriteBinaryData(const Name: String; var Buffer;
+  BufSize: Integer);
+begin
+  WriteBinaryData(UnicodeString(Name), Buffer, BufSize);
+end;
+
+procedure TRegistry.WriteBool(const Name: UnicodeString; Value: Boolean);
 
 begin
   WriteInteger(Name,Ord(Value));
 end;
 
-procedure TRegistry.WriteCurrency(const Name: string; Value: Currency);
+procedure TRegistry.WriteBool(const Name: String; Value: Boolean);
+begin
+  WriteBool(UnicodeString(Name), Value);
+end;
+
+procedure TRegistry.WriteCurrency(const Name: UnicodeString; Value: Currency);
 begin
   WriteBinaryData(Name, Value, SizeOf(Currency));
 end;
 
-procedure TRegistry.WriteDate(const Name: string; Value: TDateTime);
+procedure TRegistry.WriteCurrency(const Name: String; Value: Currency);
+begin
+  WriteCurrency(UnicodeString(Name), Value);
+end;
+
+procedure TRegistry.WriteDate(const Name: UnicodeString; Value: TDateTime);
 begin
   WriteBinarydata(Name, Value, SizeOf(TDateTime));
 end;
 
-procedure TRegistry.WriteTime(const Name: string; Value: TDateTime);
+procedure TRegistry.WriteDate(const Name: String; Value: TDateTime);
+begin
+  WriteDate(UnicodeString(Name), Value);
+end;
+
+procedure TRegistry.WriteTime(const Name: UnicodeString; Value: TDateTime);
 begin
   WriteBinaryData(Name, Value, SizeOf(TDateTime));
 end;
 
-procedure TRegistry.WriteDateTime(const Name: string; Value: TDateTime);
+procedure TRegistry.WriteTime(const Name: String; Value: TDateTime);
+begin
+  WriteTime(UnicodeString(Name), Value);
+end;
+
+procedure TRegistry.WriteDateTime(const Name: UnicodeString; Value: TDateTime);
 begin
   WriteBinaryData(Name, Value, SizeOf(TDateTime));
 end;
 
-procedure TRegistry.WriteExpandString(const Name, Value: string);
-var
-  u: UnicodeString;
+procedure TRegistry.WriteDateTime(const Name: String; Value: TDateTime);
+begin
+  WriteDateTime(UnicodeString(Name), Value);
+end;
+
+procedure TRegistry.WriteExpandString(const Name, Value: UnicodeString);
+begin
+  PutData(Name, PWideChar(Value), ByteLength(Value), rdExpandString);
+end;
 
+procedure TRegistry.WriteExpandString(const Name, Value: String);
 begin
-  u:=Value;
-  PutData(Name, PWideChar(u), ByteLength(u), rdExpandString);
+  WriteExpandString(UnicodeString(Name), UnicodeString(Value));
 end;
 
-procedure TRegistry.WriteStringList(const Name: string; List: TStrings);
+
+procedure TRegistry.WriteStringList(const Name: UnicodeString; List: TStrings; IsUtf8: Boolean=False);
 
 Var
-  Data: string;
+  UArr: TUnicodeStringArray;
+begin
+  UArr := ListToArray(List, IsUtf8);
+  WriteStringArray(Name, UArr);
+end;
+
+procedure TRegistry.WriteStringArray(const Name: UnicodeString; const Arr: TUnicodeStringArray);
+Var
+  Data: UnicodeString;
+  u: UnicodeString;
+  i: Integer;
+begin
+  Data := '';
+  //REG_MULTI_SZ data cannot contain empty strings
+  for i := Low(Arr) to High(Arr) do
+  begin
+    u := Arr[i];
+    if (u>'') then
+    begin
+      if (Data>'') then
+        Data := Data + #0 + u
+      else
+        Data := Data + u;
+    end;
+  end;
+  if StringSizeIncludesNull then
+    Data := Data + #0#0;
+  //writeln('Data=',Dbgs(Data));
+  PutData(Name, PWideChar(Data), ByteLength(Data), rdMultiString);
+end;
 
+procedure TRegistry.WriteStringArray(const Name: String; const Arr: TStringArray);
+var
+  UArr: TUnicodeStringArray;
+  i: Integer;
 begin
-  Data := StringReplace(List.Text, LineEnding, #0, [rfReplaceAll]) + #0#0;
-  PutData(Name, PChar(Data), Length(Data),rdMultiString);
+  UArr := nil;
+  SetLength(UArr, Length(Arr));
+  for i := Low(Arr) to High(Arr) do UArr[i] := Arr[i];
+  WriteStringArray(UnicodeString(Name), UArr);
 end;
 
-procedure TRegistry.WriteFloat(const Name: string; Value: Double);
+procedure TRegistry.WriteFloat(const Name: UnicodeString; Value: Double);
 begin
   WriteBinaryData(Name, Value, SizeOf(Double));
 end;
 
-procedure TRegistry.WriteInteger(const Name: string; Value: Integer);
+procedure TRegistry.WriteFloat(const Name: String; Value: Double);
+begin
+  WriteFloat(UnicodeString(Name), Value);
+end;
+
+procedure TRegistry.WriteInteger(const Name: UnicodeString; Value: Integer);
 begin
   PutData(Name, @Value, SizeOf(Integer), rdInteger);
 end;
 
-procedure TRegistry.WriteInt64(const Name: string; Value: Int64);
+procedure TRegistry.WriteInteger(const Name: String; Value: Integer);
+begin
+  WriteInteger(UnicodeString(Name), Value);
+end;
+
+procedure TRegistry.WriteInt64(const Name: UnicodeString; Value: Int64);
 begin
   PutData(Name, @Value, SizeOf(Int64), rdInt64);
 end;
 
-procedure TRegistry.WriteString(const Name, Value: string);
+procedure TRegistry.WriteInt64(const Name: String; Value: Int64);
+begin
+  WriteInt64(UnicodeString(Name), Value);
+end;
+
+procedure TRegistry.WriteString(const Name, Value: UnicodeString);
+begin
+  PutData(Name, PWideChar(Value), ByteLength(Value), rdString);
+end;
+
+procedure TRegistry.WriteString(const Name, Value: String);
+begin
+  WriteString(UnicodeString(Name), UnicodeString(Value));
+end;
+
+procedure TRegistry.GetKeyNames(Strings: TStrings);
 var
-  u: UnicodeString;
+  UArr: TUnicodeStringArray;
+begin
+  UArr := GetKeyNames;
+  ArrayToList(UArr, Strings, True);
+end;
+
+procedure TRegistry.GetValueNames(Strings: TStrings);
+var
+  UArr: TUnicodeStringArray;
+begin
+  UArr := GetValueNames;
+  ArrayToList(UArr, Strings, True);
+end;
 
+procedure TRegistry.MoveKey(const OldName, NewName: UnicodeString; Delete: Boolean);
 begin
-  u:=Value;
-  PutData(Name, PWideChar(u), ByteLength(u), rdString);
+
 end;
 
-procedure TRegistry.MoveKey(const OldName, NewName: string; Delete: Boolean);
+procedure TRegistry.MoveKey(const OldName, NewName: String; Delete: Boolean);
 begin
+  MoveKey(UnicodeString(OldName), UnicodeString(NewName), Delete);
+end;
 
+procedure TRegistry.RenameValue(const OldName, NewName: String);
+begin
+  RenameValue(UnicodeString(OldName), UnicodeString(NewName));
 end;
 
 { ---------------------------------------------------------------------
@@ -583,7 +1004,7 @@ function TRegistryIniFile.ReadBinaryStream(const Section, Name: string;
   Value: TStream): Integer;
 begin
   result:=-1; // unimplemented
- // 
+ //
 end;
 
 function TRegistryIniFile.ReadDate(const Section, Name: string;

+ 62 - 71
packages/fcl-registry/src/winreg.inc

@@ -28,7 +28,7 @@ begin
   Dispose(PWinRegData(FSysData));
 end;
 
-Function PrepKey(Const S : String) : String;
+Function PrepKey(Const S : UnicodeString) : UnicodeString;
 
 begin
   Result := S;
@@ -36,25 +36,24 @@ begin
     System.Delete(Result, 1, 1);
 end;
 
-Function RelativeKey(Const S : String) : Boolean;
+Function RelativeKey(Const S : UnicodeString) : Boolean;
 
 begin
   Result:=(S='') or (S[1]<>'\')
 end;
 
 
-function TRegistry.sysCreateKey(const Key: String): Boolean;
+function TRegistry.sysCreateKey(Key: UnicodeString): Boolean;
 Var
-  u: UnicodeString;
   Disposition: Dword;
   Handle: HKEY;
   SecurityAttributes: Pointer; //LPSECURITY_ATTRIBUTES;
 
 begin
   SecurityAttributes := Nil;
-  u:=PrepKey(Key);
+  Key:=PrepKey(Key);
   FLastError:=RegCreateKeyExW(GetBaseKey(RelativeKey(Key)),
-                              PWideChar(u),
+                              PWideChar(Key),
                               0,
                               '',
                               REG_OPTION_NON_VOLATILE,
@@ -66,7 +65,7 @@ begin
   RegCloseKey(Handle);
 end;
 
-function TRegistry.DeleteKey(const Key: String): Boolean;
+function TRegistry.DeleteKey(const Key: UnicodeString): Boolean;
 
 Var
   u: UnicodeString;
@@ -76,21 +75,21 @@ begin
   Result:=FLastError=ERROR_SUCCESS;
 end;
 
-function TRegistry.DeleteValue(const Name: String): Boolean;
+
+function TRegistry.DeleteValue(const Name: UnicodeString): Boolean;
 begin
-  FLastError:= RegDeleteValueW(fCurrentKey, PWideChar(UnicodeString(Name)));
+  FLastError:= RegDeleteValueW(fCurrentKey, PWideChar(Name));
   Result:=FLastError=ERROR_SUCCESS;
 end;
 
-function TRegistry.SysGetData(const Name: String; Buffer: Pointer;
+
+function TRegistry.SysGetData(const Name: UnicodeString; Buffer: Pointer;
           BufSize: Integer; Out RegData: TRegDataType): Integer;
 Var
-  u: UnicodeString;
   RD : DWord;
 
 begin
-  u := Name;
-  FLastError:=RegQueryValueExW(fCurrentKey,PWideChar(u),Nil,
+  FLastError:=RegQueryValueExW(fCurrentKey,PWideChar(Name),Nil,
                       @RD,Buffer,lpdword(@BufSize));
   if (FLastError<>ERROR_SUCCESS) Then
     Result:=-1
@@ -103,17 +102,15 @@ begin
     end;
 end;
 
-function TRegistry.GetDataInfo(const ValueName: String; out Value: TRegDataInfo): Boolean;
+function TRegistry.GetDataInfo(const ValueName: UnicodeString; out Value: TRegDataInfo): Boolean;
 
 Var
-  u: UnicodeString;
   RD : DWord;
 
 begin
-  u:=ValueName;
   With Value do
     begin
-    FLastError:=RegQueryValueExW(fCurrentKey,PWideChar(u),Nil,lpdword(@RegData),Nil,lpdword(@DataSize));
+    FLastError:=RegQueryValueExW(fCurrentKey,PWideChar(ValueName),Nil,lpdword(@RegData),Nil,lpdword(@DataSize));
     Result:=FLastError=ERROR_SUCCESS;
     if Result then
       begin
@@ -131,24 +128,18 @@ begin
 end;
 
 
-function TRegistry.GetKey(const Key: String): HKEY;
+function TRegistry.GetKey(Key: UnicodeString): HKEY;
 var
-  S : string;
-{$ifndef WinCE}
-  u : UnicodeString;
-{$endif}
   Rel : Boolean;
 begin
   Result:=0;
-  S:=Key;
-  Rel:=RelativeKey(S);
+  Rel:=RelativeKey(Key);
   if not(Rel) then
-    Delete(S,1,1);
+    Delete(Key,1,1);
 {$ifdef WinCE}
-  FLastError:=RegOpenKeyEx(GetBaseKey(Rel),PWideChar(WideString(S)),0,FAccess,Result);
+  FLastError:=RegOpenKeyEx(GetBaseKey(Rel),PWideChar(Key),0,FAccess,Result);
 {$else WinCE}
-  u:=UnicodeString(S);
-  FLastError:=RegOpenKeyExW(GetBaseKey(Rel),PWideChar(u),0,FAccess,Result);
+  FLastError:=RegOpenKeyExW(GetBaseKey(Rel),PWideChar(Key),0,FAccess,Result);
 {$endif WinCE}
 end;
 
@@ -174,7 +165,7 @@ begin
 end;
 
 
-function TRegistry.KeyExists(const Key: string): Boolean;
+function TRegistry.KeyExists(const Key: UnicodeString): Boolean;
 var
   KeyHandle : HKEY;
   OldAccess : LONG;
@@ -196,20 +187,20 @@ begin
 end;
 
 
-function TRegistry.LoadKey(const Key, FileName: string): Boolean;
+function TRegistry.LoadKey(const Key, FileName: UnicodeString): Boolean;
 begin
   Result := False;
 end;
 
 
-function TRegistry.OpenKey(const Key: string; CanCreate: Boolean): Boolean;
+
+function TRegistry.OpenKey(const Key: UnicodeString; CanCreate: Boolean): Boolean;
 
 Var
-  u: UnicodeString;
+  u, S: UnicodeString;
   Handle: HKEY;
   Disposition: Integer;
   SecurityAttributes: Pointer; //LPSECURITY_ATTRIBUTES;
-  S: string;
 begin
   SecurityAttributes := Nil;
   u:=PrepKey(Key);
@@ -232,12 +223,13 @@ begin
     if RelativeKey(Key) then
       S:=CurrentPath + Key
     else
-      S:=UTF8Encode(u);
+      S:=u;
     ChangeKey(Handle, S);
   end;
 end;
 
-function TRegistry.OpenKeyReadOnly(const Key: string): Boolean;
+
+function TRegistry.OpenKeyReadOnly(const Key: UnicodeString): Boolean;
 
 Var
   OldAccess: LongWord;
@@ -251,7 +243,8 @@ begin
   end;
 end;
 
-function TRegistry.RegistryConnect(const UNCName: string): Boolean;
+
+function TRegistry.RegistryConnect(const UNCName: UnicodeString): Boolean;
 {$ifndef WinCE}
 var
   newroot: HKEY;
@@ -260,7 +253,7 @@ begin
 {$ifdef WinCE}
   Result:=False;
 {$else}
-  FLastError:=RegConnectRegistryW(PWideChar(UnicodeString(UNCName)),RootKey,newroot);
+  FLastError:=RegConnectRegistryW(PWideChar(UNCName),RootKey,newroot);
   Result:=FLastError=ERROR_SUCCESS;
   if Result then begin
     RootKey:=newroot;
@@ -269,27 +262,32 @@ begin
 {$endif}
 end;
 
-function TRegistry.ReplaceKey(const Key, FileName, BackUpFileName: string): Boolean;
+
+function TRegistry.ReplaceKey(const Key, FileName, BackUpFileName: UnicodeString): Boolean;
 begin
   Result := False;
 end;
 
-function TRegistry.RestoreKey(const Key, FileName: string): Boolean;
+
+function TRegistry.RestoreKey(const Key, FileName: UnicodeString): Boolean;
 begin
   Result := False;
 end;
 
-function TRegistry.SaveKey(const Key, FileName: string): Boolean;
+
+function TRegistry.SaveKey(const Key, FileName: UnicodeString): Boolean;
 begin
   Result := False;
 end;
 
-function TRegistry.UnLoadKey(const Key: string): Boolean;
+
+function TRegistry.UnLoadKey(const Key: UnicodeString): Boolean;
 begin
   Result := false;
 end;
 
-function TRegistry.ValueExists(const Name: string): Boolean;
+
+function TRegistry.ValueExists(const Name: UnicodeString): Boolean;
 
 var
   Info : TRegDataInfo;
@@ -298,6 +296,7 @@ begin
   Result:=GetDataInfo(Name,Info);
 end;
 
+
 procedure TRegistry.CloseKey;
 begin
   If (CurrentKey<>0) then
@@ -316,14 +315,15 @@ begin
   RegCloseKey(key);
 end;
 
-procedure TRegistry.ChangeKey(Value: HKey; const Path: String);
+procedure TRegistry.ChangeKey(Value: HKey; const Path: UnicodeString);
 begin
   CloseKey;
   FCurrentKey:=Value;
   FCurrentPath:=Path;
 end;
 
-procedure TRegistry.GetKeyNames(Strings: TStrings);
+
+function TRegistry.GetKeyNames: TUnicodeStringArray;
 
 var
   Info:    TRegKeyInfo;
@@ -331,15 +331,17 @@ var
   lpName:  LPWSTR;
   dwIndex: DWORD;
   lResult: LONGINT;
-  s:       string;
+  u:       UnicodeString;
 
 begin
-  Strings.Clear;
+  Result:=nil;
   if GetKeyInfo(Info) then
   begin
     dwLen:=Info.MaxSubKeyLen+1;
     GetMem(lpName,dwLen*SizeOf(WideChar));
     try
+      //writeln('TRegistry.GetKeyNames: Info.NumSubKeys=',Info.NumSubKeys);
+      SetLength(Result, Info.NumSubKeys);
       for dwIndex:=0 to Info.NumSubKeys-1 do
       begin
         dwLen:=Info.MaxSubKeyLen+1;
@@ -347,26 +349,21 @@ begin
         if lResult<>ERROR_SUCCESS then
           raise ERegistryException.Create(SysErrorMessage(lResult));
         if dwLen=0 then
-          s:=''
+          u:=''
         else
         begin           // dwLen>0
-          SetLength(s,dwLen*3);
-          dwLen:=UnicodeToUTF8(PChar(s),Length(s)+1,lpName,dwLen);
-          if dwLen<=1 then
-            s:=''
-          else          // dwLen>1
-            SetLength(s,dwLen-1);
+          u:=lpName;
         end;            // if dwLen=0
-        Strings.Add(s);
+        Result[dwIndex]:=u;
       end;              // for dwIndex:=0 ...
-
     finally
       FreeMem(lpName);
     end;
   end;
 end;
 
-procedure TRegistry.GetValueNames(Strings: TStrings);
+
+Function TRegistry.GetValueNames: TUnicodeStringArray;
 
 var
   Info:    TRegKeyInfo;
@@ -374,15 +371,16 @@ var
   lpName:  LPWSTR;
   dwIndex: DWORD;
   lResult: LONGINT;
-  s:       string;
+  u:       UnicodeString;
 
 begin
-   Strings.Clear;
+  Result:=nil;
   if GetKeyInfo(Info) then
   begin
     dwLen:=Info.MaxValueLen+1;
     GetMem(lpName,dwLen*SizeOf(WideChar));
     try
+      SetLength(Result, Info.NumValues);
       for dwIndex:=0 to Info.NumValues-1 do
       begin
         dwLen:=Info.MaxValueLen+1;
@@ -390,17 +388,12 @@ begin
         if lResult<>ERROR_SUCCESS then
           raise ERegistryException.Create(SysErrorMessage(lResult));
         if dwLen=0 then
-          s:=''
+          u:=''
         else
         begin           // dwLen>0
-          SetLength(s,dwLen*3);
-          dwLen:=UnicodeToUTF8(PChar(s),Length(s)+1,lpName,dwLen);
-          if dwLen<=1 then
-            s:=''
-          else          // dwLen>1
-            SetLength(s,dwLen-1);
+          u:=lpName;
         end;            // if dwLen=0
-        Strings.Add(s);
+        Result[dwIndex]:=u;
       end;              // for dwIndex:=0 ...
 
     finally
@@ -410,24 +403,22 @@ begin
 end;
 
 
-Function TRegistry.SysPutData(const Name: string; Buffer: Pointer;
+Function TRegistry.SysPutData(const Name: UnicodeString; Buffer: Pointer;
   BufSize: Integer; RegData: TRegDataType) : Boolean;
 
 
 Var
-  u: UnicodeString;
   RegDataType: DWORD;
   B : Pchar;
   S : String;
 
 begin
   RegDataType:=RegDataWords[RegData];
-  u:=UnicodeString(Name);
-  FLastError:=RegSetValueExW(fCurrentKey,PWideChar(u),0,RegDataType,Buffer,BufSize);
+  FLastError:=RegSetValueExW(fCurrentKey,PWideChar(Name),0,RegDataType,Buffer,BufSize);
   Result:=FLastError=ERROR_SUCCESS;
 end;
 
-procedure TRegistry.RenameValue(const OldName, NewName: string);
+procedure TRegistry.RenameValue(const OldName, NewName: UnicodeString);
 
 var
   L: Integer;

+ 160 - 77
packages/fcl-registry/src/xmlreg.pp

@@ -25,6 +25,7 @@ Type
     FTime     : TDateTime;
   end;
 
+  TUnicodeStringArray = Array of UnicodeString;
 
   { TXmlRegistry }
 
@@ -33,53 +34,55 @@ Type
     FAutoFlush,
     FDirty : Boolean;
     FFileName : String;
-    FRootKey : String;
+    FRootKey : UnicodeString;
     FDocument : TXMLDocument;
     FCurrentElement : TDomElement;
-    FCurrentKey : String;
+    FCurrentKey : UnicodeString;
     Procedure SetFileName(Value : String);
   Protected
-    function DoGetValueData(Name: String; out DataType: TDataType; Var Data; Var DataSize: Integer; IsUnicode: Boolean): Boolean; virtual;
-    function DoSetValueData(Name: String; DataType: TDataType; const Data; DataSize: Integer; IsUnicode: Boolean): Boolean; virtual;
+    function DoGetValueData(Name: UnicodeString; out DataType: TDataType; Var Data; Var DataSize: Integer; IsUnicode: Boolean): Boolean; virtual;
+    function DoSetValueData(Name: UnicodeString; DataType: TDataType; const Data; DataSize: Integer; IsUnicode: Boolean): Boolean; virtual;
     Procedure LoadFromStream(S : TStream);
-    Function  NormalizeKey(KeyPath : String) : String;
+    Function  NormalizeKey(KeyPath : UnicodeString) : UnicodeString;
     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  FindKey (S : UnicodeString) : TDomElement;
+    Function  FindSubKey (S : UnicodeString; N : TDomElement) : TDomElement;
+    Function  CreateSubKey (S : UnicodeString; N : TDomElement) : TDomElement;
+    Function  FindValueKey (S : UnicodeString) : TDomElement;
+    Function  CreateValueKey (S : UnicodeString) : TDomElement;
     Function  BufToHex(Const Buf; Len : Integer) : String;
-    Function  hexToBuf(Const Str : String; Var Buf; Var Len : Integer ) : Integer;
+    Function  HexToBuf(Const Str : UnicodeString; 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);
     Destructor  Destroy;override;
-    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; Out Info : TDataInfo; AsUnicode : Boolean = False) : Boolean;
+    Function  SetKey(KeyPath : UnicodeString; AllowCreate : Boolean) : Boolean ;
+    Procedure SetRootKey(Value : UnicodeString);
+    Function  DeleteKey(KeyPath : UnicodeString) : Boolean;
+    Function  CreateKey(KeyPath : UnicodeString) : Boolean;
+    Function  GetValueSize(Name : UnicodeString) : Integer;
+    Function  GetValueType(Name : UnicodeString) : TDataType;
+    Function  GetValueInfo(Name : UnicodeString; Out Info : TDataInfo; AsUnicode : Boolean = False) : Boolean;
     Function  GetKeyInfo(Out Info : TKeyInfo) : Boolean;
     Function  EnumSubKeys(List : TStrings) : Integer;
+    Function  EnumSubKeys: TUnicodeStringArray;
     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;
+    Function  EnumValues: TUnicodeStringArray;
+    Function  KeyExists(KeyPath : UnicodeString) : Boolean;
+    Function  ValueExists(ValueName : UnicodeString) : Boolean;
+    Function  RenameValue(Const OldName,NewName : UnicodeString) : Boolean;
+    Function  DeleteValue(S : UnicodeString) : Boolean;
     Procedure Flush;
     Procedure Load;
-    Function GetValueData(Name : String; Out DataType : TDataType; Var Data; Var DataSize : Integer) : Boolean;
-    Function SetValueData(Name : String; DataType : TDataType; Const Data; DataSize : Integer) : Boolean;
+    Function GetValueData(Name : UnicodeString; Out DataType : TDataType; Var Data; Var DataSize : Integer) : Boolean;
+    Function SetValueData(Name : UnicodeString; DataType : TDataType; Const Data; DataSize : Integer) : Boolean;
     // These interpret the Data buffer as unicode data
-    Function GetValueDataUnicode(Name : String; Out DataType : TDataType; Var Data; Var DataSize : Integer) : Boolean;
-    Function SetValueDataUnicode(Name : String; DataType : TDataType; Const Data; DataSize : Integer) : Boolean;
+    Function GetValueDataUnicode(Name : UnicodeString; Out DataType : TDataType; Var Data; Var DataSize : Integer) : Boolean;
+    Function SetValueDataUnicode(Name : UnicodeString; DataType : TDataType; Const Data; DataSize : Integer) : Boolean;
     Property FileName : String Read FFileName Write SetFileName;
-    Property RootKey : String Read FRootKey Write SetRootkey;
+    Property RootKey : UnicodeString Read FRootKey Write SetRootkey;
     Property AutoFlush : Boolean Read FAutoFlush Write FAutoFlush;
   end;
 
@@ -143,13 +146,13 @@ begin
   end;
 end;
 
-Function TXmlRegistry.NormalizeKey(KeyPath : String) : String;
+Function TXmlRegistry.NormalizeKey(KeyPath : UnicodeString) : UnicodeString;
 
 Var
   L : Integer;
 
 begin
-  Result:=StringReplace(KeyPath,'\','/',[rfReplaceAll]);
+  Result:=UnicodeStringReplace(KeyPath,'\','/',[rfReplaceAll]);
   L:=Length(Result);
   If (L>0) and (Result[L]<>'/') then
     Result:=Result+'/';
@@ -157,10 +160,10 @@ begin
     Result:='/' + Result;
 end;
 
-Function TXmlRegistry.SetKey(KeyPath : String; AllowCreate : Boolean) : boolean;
+Function TXmlRegistry.SetKey(KeyPath : UnicodeString; AllowCreate : Boolean) : boolean;
 
 Var
-  SubKey,ResultKey : String;
+  SubKey,ResultKey : UnicodeString;
   P : Integer;
   Node,Node2 : TDomElement;
 
@@ -218,7 +221,7 @@ begin
   MaybeFlush;
 end;
 
-Procedure TXmlRegistry.SetRootKey(Value : String);
+Procedure TXmlRegistry.SetRootKey(Value : UnicodeString);
 
 begin
   FRootKey:=NormalizeKey(Value);
@@ -228,7 +231,7 @@ begin
   FCurrentElement:=Nil;
 end;
 
-Function TXmlRegistry.DeleteKey(KeyPath : String) : Boolean;
+Function TXmlRegistry.DeleteKey(KeyPath : UnicodeString) : Boolean;
 
 Var
   N : TDomElement;
@@ -244,10 +247,10 @@ begin
    end;
 end;
 
-Function TXmlRegistry.CreateKey(KeyPath : String) : Boolean;
+Function TXmlRegistry.CreateKey(KeyPath : UnicodeString) : Boolean;
 
 Var
-  SubKey : String;
+  SubKey : UnicodeString;
   P : Integer;
   Node,Node2 : TDomElement;
 
@@ -290,7 +293,7 @@ begin
   MaybeFlush;
 end;
 
-Function TXmlRegistry.DoGetValueData(Name : String; Out DataType : TDataType; Var Data; Var DataSize : Integer; IsUnicode : Boolean) : Boolean;
+Function TXmlRegistry.DoGetValueData(Name : UnicodeString; Out DataType : TDataType; Var Data; Var DataSize : Integer; IsUnicode : Boolean) : Boolean;
 
 Type
   PCardinal = ^Cardinal;
@@ -305,22 +308,27 @@ Var
   D : DWord;
   
 begin
+  //writeln('TXmlRegistry.DoGetValueData: Name=',Name,' IsUnicode=',IsUnicode);
   Node:=FindValueKey(Name);
   Result:=Node<>Nil;
   If Result then
     begin
+    //writeln('TXmlRegistry.DoGetValueData: Node<>nil');
     DataNode:=Node.FirstChild;
     HasData:=Assigned(DataNode) and (DataNode.NodeType=TEXT_NODE);
-    ND:=StrToIntDef(Node[Stype],0);
+    //writeln('TXmlRegistry.DoGetValueData: HasData=',hasdata);
+    ND:=StrToIntDef(String(Node[Stype]),0);
+    //writeln('TXmlRegistry.DoGetValueData: ND=',ND);
     Result:=ND<=Ord(High(TDataType));
     If Result then
       begin
       DataType:=TDataType(ND);
+      //writeln('TXmlRegistry.DoGetValueData: DataType=',DataType);
       NS:=0; // Initialize, for optional nodes.
       Case DataType of
         dtDWORD : begin   // DataNode is required
                   NS:=SizeOf(Cardinal);
-                  Result:=HasData and TryStrToDWord(DataNode.NodeValue,D) and (DataSize>=NS);
+                  Result:=HasData and TryStrToDWord(String(DataNode.NodeValue),D) and (DataSize>=NS);
                   if Result then
                     PCardinal(@Data)^:=D;
                   end;
@@ -329,7 +337,7 @@ begin
                      begin
                      if not IsUnicode then
                        begin
-                       S:=UTF8Encode(DataNode.NodeValue); // Convert to ansistring
+                       S:=DataNode.NodeValue; // Convert to ansistring
                        NS:=Length(S);
                        Result:=(DataSize>=NS);
                        if Result then
@@ -350,8 +358,10 @@ begin
                    if HasData then
                      begin
                      BL:=Length(DataNode.NodeValue);
+                     //writeln('TXmlRegistry.DoGetValueData: BL=',BL);
                      NS:=BL div 2;
                      Result:=DataSize>=NS;
+                     //writeln('TXmlRegistry.DoGetValueData: Result=',Result);
                      If Result then
                        // No need to check for -1, We checked NS before calling.
                        NS:=HexToBuf(DataNode.NodeValue,Data,BL);
@@ -363,7 +373,7 @@ begin
     end;
 end;
 
-Function TXmlRegistry.DoSetValueData(Name : String; DataType : TDataType; Const Data; DataSize : Integer; IsUnicode : Boolean) : Boolean;
+Function TXmlRegistry.DoSetValueData(Name : UnicodeString; DataType : TDataType; Const Data; DataSize : Integer; IsUnicode : Boolean) : Boolean;
 
 Type
   PCardinal = ^Cardinal;
@@ -374,26 +384,27 @@ Var
   SW : UnicodeString;
 
 begin
+  //writeln('TXmlRegistry.DoSetValueData A: Name=',Name,', DataType=',DataType,', DataSize=',DataSize,', IsUnicode=',IsUnicode);
   Node:=FindValueKey(Name);
   If Node=Nil then
     Node:=CreateValueKey(Name);
   Result:=(Node<>Nil);
   If Result then
     begin
-    Node[SType]:=IntToStr(Ord(DataType));
+    Node[SType]:=UnicodeString(IntToStr(Ord(DataType)));
     DataNode:=Node.FirstChild;
 
     Case DataType of
-      dtDWORD : SW:=IntToStr(PCardinal(@Data)^);
+      dtDWORD : SW:=UnicodeString(IntToStr(PCardinal(@Data)^));
       dtString : begin
                  if IsUnicode then
                    SW:=UnicodeString(PUnicodeChar(@Data))
                  else
                    SW:=UnicodeString(PAnsiChar(@Data));
-                   //S:=UTF8Encode(SW);
+                   //S:=SW;
                  end;
-      dtBinary : SW:=BufToHex(Data,DataSize);
-      dtStrings : SW:=BufToHex(Data,DataSize);
+      dtBinary : SW:=UnicodeString(BufToHex(Data,DataSize));
+      dtStrings : SW:=UnicodeString(BufToHex(Data,DataSize));
     else
       sw:='';
     end;
@@ -416,29 +427,29 @@ begin
     end;
 end;
 
-Function TXmlRegistry.SetValueData(Name : String; DataType : TDataType; Const Data; DataSize : Integer) : Boolean;
+Function TXmlRegistry.SetValueData(Name : UnicodeString; DataType : TDataType; Const Data; DataSize : Integer) : Boolean;
 
 begin
   Result:=DoSetValueData(Name,DataType,Data,DataSize,False);
 end;
 
-Function TXmlRegistry.GetValueData(Name : String; Out DataType : TDataType; Var Data; Var DataSize : Integer) : Boolean;
+Function TXmlRegistry.GetValueData(Name : UnicodeString; Out DataType : TDataType; Var Data; Var DataSize : Integer) : Boolean;
 
 begin
   Result:=DoGetValueData(Name,DataType,Data,DataSize,False);
 end;
 
-function TXmlRegistry.GetValueDataUnicode(Name: String; out DataType: TDataType; Var Data; Var DataSize: Integer): Boolean;
+function TXmlRegistry.GetValueDataUnicode(Name: UnicodeString; out DataType: TDataType; Var Data; Var DataSize: Integer): Boolean;
 begin
   Result:=DoGetValueData(Name,DataType,Data,DataSize,True);
 end;
 
-function TXmlRegistry.SetValueDataUnicode(Name: String; DataType: TDataType; const Data; DataSize: Integer): Boolean;
+function TXmlRegistry.SetValueDataUnicode(Name: UnicodeString; DataType: TDataType; const Data; DataSize: Integer): Boolean;
 begin
   Result:=DoSetValueData(Name,DataType,Data,DataSize,True)
 end;
 
-Function TXmlRegistry.FindSubKey (S : String; N : TDomElement) : TDomElement;
+Function TXmlRegistry.FindSubKey (S : UnicodeString; N : TDomElement) : TDomElement;
 
 Var
   Node : TDOMNode;
@@ -451,14 +462,14 @@ begin
     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
+        If UnicodeCompareText(TDomElement(Node)[SName],S)=0 then
           Result:=TDomElement(Node);
       Node:=Node.NextSibling;
       end;
     end;
 end;
 
-Function TXmlRegistry.CreateSubKey (S : String; N : TDomElement) : TDomElement;
+Function TXmlRegistry.CreateSubKey (S : UnicodeString; N : TDomElement) : TDomElement;
 
 begin
   Result:=FDocument.CreateElement(SKey);
@@ -468,7 +479,7 @@ begin
   FDirty:=True;
 end;
 
-Function  TXmlRegistry.FindValueKey (S : String) : TDomElement;
+Function  TXmlRegistry.FindValueKey (S : UnicodeString) : TDomElement;
 
 Var
   Node : TDOMNode;
@@ -481,14 +492,14 @@ begin
     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
+        If UnicodeCompareText(TDomElement(Node)[SName],S)=0 then
           Result:=TDomElement(Node);
       Node:=Node.NextSibling;
       end;
     end;
 end;
 
-Function  TXmlRegistry.CreateValueKey (S : String) : TDomElement;
+Function  TXmlRegistry.CreateValueKey (S : UnicodeString) : TDomElement;
 
 begin
   If Assigned(FCurrentElement) then
@@ -581,38 +592,47 @@ begin
     end;
 end;
 
-Function TXMLRegistry.hexToBuf(Const Str : String; Var Buf; Var Len : Integer ) : Integer;
+Function TXMLRegistry.HexToBuf(Const Str : UnicodeString; Var Buf; Var Len : Integer ) : Integer;
 
 Var
   NLeN,I : Integer;
   P : PByte;
-  S : String;
+  S : UnicodeString;
   B : Byte;
   Code : Integer;
 
 begin
+  //writeln('TXMLRegistry.HexToBuf A: Str=',Str,', Len=',Len);
   Result:=0;
   P:=@Buf;
+  //writeln('TXMLRegistry.HexToBuf B: (p=nil)=',p=nil);
   NLen:= Length(Str) div 2;
+  //writeln('TXMLRegistry.HexToBuf C: NLen=',NLen,', SizeOf(TDateTime)=',SizeOf(TDateTime));
   If (NLen>Len) then
     begin
     Len:=NLen;
     Exit(-1);
     end;
-  For I:=0 to Len-1 do
+  For I:=0 to NLen-1 do
     begin
+    //write('TXMLRegistry.HexToBuf: i=',i);
     S:='$'+Copy(Str,(I*2)+1,2);
+    //write(', S=',S);
     Val(S,B,Code);
+    //writeln(', Code=',Code);
     If Code<>0 then
-      begin
-      Inc(Result);
-      B:=0;
+      begin    //This means invalid data in the registry, why continue and increment result? Why not Exit(-1)?
+      //Inc(Result);   //the whole function only worked because this was called as often as when Code=0, so by change
+      //B:=0;          //it causes AV's
+      Exit(-1);
       end;
+    Inc(Result);
     P[I]:=B;
     end;
+  //writeln('TXMLRegistry.HexToBuf End: Result=',Result);
 end;
 
-Function TXMLRegistry.DeleteValue(S : String) : Boolean;
+Function TXMLRegistry.DeleteValue(S : UnicodeString) : Boolean;
 
 Var
   N : TDomElement;
@@ -628,31 +648,31 @@ begin
     end;
 end;
 
-Function TXMLRegistry.GetValueSize(Name : String) : Integer;
+Function TXMLRegistry.GetValueSize(Name : UnicodeString) : Integer;
 
 Var
   Info : TDataInfo;
 
 begin
-  If GetValueInfo(Name,Info) then
+  If GetValueInfo(Name,Info,True) then
     Result:=Info.DataSize
   else
     Result:=-1;
 end;
 
-Function TXMLRegistry.GetValueType(Name : String) : TDataType;
+Function TXMLRegistry.GetValueType(Name : UnicodeString) : TDataType;
 
 Var
   Info : TDataInfo;
 
 begin
-  If GetValueInfo(Name,Info) then
+  If GetValueInfo(Name,Info,True) then
     Result:=Info.DataType
   else
     Result:=dtUnknown;
 end;
 
-function TXmlRegistry.GetValueInfo(Name: String; out Info: TDataInfo; AsUnicode: Boolean): Boolean;
+function TXmlRegistry.GetValueInfo(Name: UnicodeString; out Info: TDataInfo; AsUnicode: Boolean): Boolean;
 
 Var
   N  : TDomElement;
@@ -671,7 +691,7 @@ begin
         L:=Length(DN.NodeValue)*SizeOf(UnicodeChar)
       else
         begin
-        S := UTF8Encode(DN.NodeValue);
+        S := DN.NodeValue;
         L:=Length(S);
         end
       end
@@ -679,7 +699,7 @@ begin
       L:=0;
     With Info do
       begin
-      DataType:=TDataType(StrToIntDef(N[SType],0));
+      DataType:=TDataType(StrToIntDef(String(N[SType]),0));
       Case DataType of
         dtUnknown : DataSize:=0;
         dtDword   : Datasize:=SizeOf(Cardinal);
@@ -724,10 +744,10 @@ begin
               ValueLen:=L;
             DataNode:=TDomElement(Node).FirstChild;
             If (DataNode<>Nil) and (DataNode is TDomText) then
-              Case TDataType(StrToIntDef(TDomElement(Node)[SType],0)) of
+              Case TDataType(StrToIntDef(String(TDomElement(Node)[SType]),0)) of
                 dtUnknown : L:=0;
                 dtDWord   : L:=4;
-                DtString  : L:=Length(UTF8Encode(DataNode.NodeValue));
+                DtString  : L:=Length(String(DataNode.NodeValue));
                 dtBinary  : L:=Length(DataNode.NodeValue) div 2;
               end
             else
@@ -761,6 +781,37 @@ begin
     end;
 end;
 
+function TXmlRegistry.EnumSubKeys: TUnicodeStringArray;
+
+Var
+  Node : TDOMNode;
+  Len, Count: Integer;
+
+begin
+  Result:=nil;
+  If FCurrentElement<>Nil then
+    begin
+    Node:=FCurrentElement.FirstChild;
+    Len:=0;
+    Count:=0;
+    While Assigned(Node) do
+      begin
+      If (Node.NodeType=ELEMENT_NODE) and (Node.NodeName=SKey) then
+        begin
+        Inc(Count);
+        if (Count>Len) then
+          begin
+          Inc(Len,10); //avoid calling SetLength on each addition
+          SetLength(Result,Len);
+          end;
+        Result[Count-1]:=TDomElement(Node)[SName];
+        end;
+      Node:=Node.NextSibling;
+      end;
+    SetLength(Result,Count);
+    end;
+end;
+
 Function TXMLRegistry.EnumValues(List : TStrings) : Integer;
 
 Var
@@ -775,20 +826,52 @@ begin
     While Assigned(Node) do
       begin
       If (Node.NodeType=ELEMENT_NODE) and (Node.NodeName=SValue) then
-        List.Add(TDomElement(Node)[SName]);
+        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;
+Function TXMLRegistry.EnumValues: TUnicodeStringArray;
+
+Var
+  Node : TDOMNode;
+  Len, Count: Integer;
+begin
+  Result:=nil;
+  If FCurrentElement<>Nil then
+    begin
+    Node:=FCurrentElement.FirstChild;
+    Count:=0;
+    Len:=0;
+    While Assigned(Node) do
+      begin
+      If (Node.NodeType=ELEMENT_NODE) and (Node.NodeName=SValue) then
+        begin
+        Inc(Count);
+        if (Count>Len) then
+          begin
+          Inc(Len,10); //avoid calling SetLength on each addition
+          SetLength(Result,Len);
+          end;
+        Result[Count-1]:=TDomElement(Node)[SName];
+        end;
+      Node:=Node.NextSibling;
+      end;
+    SetLength(Result,Count);
+    end;
+end;
+
+
+Function TXMLRegistry.KeyExists(KeyPath : UnicodeString) : Boolean;
 
 begin
   Result:=FindKey(KeyPath)<>Nil;
 end;
 
-Function TXMLRegistry.RenameValue(Const OldName,NewName : String) : Boolean;
+Function TXMLRegistry.RenameValue(Const OldName,NewName : UnicodeString) : Boolean;
 
 Var
   N : TDomElement;
@@ -804,10 +887,10 @@ begin
     end;
 end;
 
-Function TXMLRegistry.FindKey (S : String) : TDomElement;
+Function TXMLRegistry.FindKey (S : UnicodeString) : TDomElement;
 
 Var
-  SubKey : String;
+  SubKey : UnicodeString;
   P : Integer;
   Node : TDomElement;
 
@@ -840,7 +923,7 @@ begin
   Until (Result=Nil) or (Length(S)=0);
 end;
 
-Function  TXmlRegistry.ValueExists(ValueName : String) : Boolean;
+Function  TXmlRegistry.ValueExists(ValueName : UnicodeString) : Boolean;
 
 begin
   Result:=FindValueKey(ValueName)<>Nil;

+ 33 - 24
packages/fcl-registry/src/xregreg.inc

@@ -116,7 +116,11 @@ end;
 procedure TRegistry.SysRegCreate;
 var s : string;
 begin
+  FStringSizeIncludesNull:=False;
   s:=includetrailingpathdelimiter(GetAppConfigDir(GlobalXMLFile));
+  {$ifdef XMLRegfile_in_CurDir}
+  s:='.' + PathDelim;
+  {$endif}
   ForceDirectories(s);
   FSysData:=TXMLRegistryInstance.GetXMLRegistry(s+XFileName);
   TXmlRegistry(FSysData).AutoFlush:=False;
@@ -130,24 +134,24 @@ begin
   TXMLRegistryInstance.FreeXMLRegistry(TXMLRegistry(FSysData));
 end;
 
-function TRegistry.SysCreateKey(const Key: String): Boolean;
+function TRegistry.SysCreateKey(Key: UnicodeString): Boolean;
 
 begin
   Result:=TXmlRegistry(FSysData).CreateKey(Key);
 end;
 
-function TRegistry.DeleteKey(const Key: string): Boolean;
+function TRegistry.DeleteKey(const Key: UnicodeString): Boolean;
 
 begin
   Result:=TXMLRegistry(FSysData).DeleteKey(Key);
 end;
 
-function TRegistry.DeleteValue(const Name: string): Boolean;
+function TRegistry.DeleteValue(const Name: UnicodeString): Boolean;
 begin
   Result:=TXmlRegistry(FSysData).DeleteValue(Name);
 end;
 
-function TRegistry.SysGetData(const Name: String; Buffer: Pointer;
+function TRegistry.SysGetData(const Name: UnicodeString; Buffer: Pointer;
           BufSize: Integer; Out RegData: TRegDataType): Integer;
 
 Var
@@ -160,7 +164,7 @@ begin
     Result:=-1;
 end;
 
-function TRegistry.GetDataInfo(const ValueName: string; out Value: TRegDataInfo): Boolean;
+function TRegistry.GetDataInfo(const ValueName: UnicodeString; out Value: TRegDataInfo): Boolean;
 
 Var
   Info : TDataInfo;
@@ -181,7 +185,7 @@ begin
       end;
 end;
 
-function TRegistry.GetKey(const Key: string): HKEY;
+function TRegistry.GetKey(Key: UnicodeString): HKEY;
 begin
   Result := 0;
 end;
@@ -205,91 +209,94 @@ begin
       end;
 end;
 
-function TRegistry.KeyExists(const Key: string): Boolean;
+function TRegistry.KeyExists(const Key: UnicodeString): Boolean;
 begin
   Result:=TXmlRegistry(FSysData).KeyExists(Key);
 end;
 
-function TRegistry.LoadKey(const Key, FileName: string): Boolean;
+function TRegistry.LoadKey(const Key, FileName: UnicodeString): Boolean;
 begin
   Result := False;
 end;
 
-function TRegistry.OpenKey(const Key: string; CanCreate: Boolean): Boolean;
+function TRegistry.OpenKey(const Key: UnicodeString; CanCreate: Boolean): Boolean;
 
 begin
   Result:=TXmlRegistry(FSysData).SetKey(Key,CanCreate);
   FCurrentKey:=1;
 end;
 
-function TRegistry.OpenKeyReadOnly(const Key: string): Boolean;
+function TRegistry.OpenKeyReadOnly(const Key: UnicodeString): Boolean;
 
 begin
   Result:=TXmlRegistry(FSysData).SetKey(Key,False);
 end;
 
-function TRegistry.RegistryConnect(const UNCName: string): Boolean;
+function TRegistry.RegistryConnect(const UNCName: UnicodeString): Boolean;
 begin
   Result := True;
 end;
 
-function TRegistry.ReplaceKey(const Key, FileName, BackUpFileName: string): Boolean;
+function TRegistry.ReplaceKey(const Key, FileName, BackUpFileName: UnicodeString): Boolean;
 begin
   Result := False;
 end;
 
-function TRegistry.RestoreKey(const Key, FileName: string): Boolean;
+function TRegistry.RestoreKey(const Key, FileName: UnicodeString): Boolean;
 begin
   Result := False;
 end;
 
-function TRegistry.SaveKey(const Key, FileName: string): Boolean;
+function TRegistry.SaveKey(const Key, FileName: UnicodeString): Boolean;
 begin
   Result := False;
 end;
 
-function TRegistry.UnLoadKey(const Key: string): Boolean;
+function TRegistry.UnLoadKey(const Key: UnicodeString): Boolean;
 begin
   Result := False;
 end;
 
-function TRegistry.ValueExists(const Name: string): Boolean;
+function TRegistry.ValueExists(const Name: UnicodeString): Boolean;
 begin
   Result := TXmlRegistry(FSysData).ValueExists(Name);
 end;
 
-procedure TRegistry.ChangeKey(Value: HKey; const Path: string);
+procedure TRegistry.ChangeKey(Value: HKey; const Path: UnicodeString);
 begin
 
 end;
 
-procedure TRegistry.GetKeyNames(Strings: TStrings);
+function TRegistry.GetKeyNames: TUnicodeStringArray;
 begin
-  TXmlRegistry(FSysData).EnumSubKeys(Strings);
+  Result:=TXmlRegistry(FSysData).EnumSubKeys;
 end;
 
-procedure TRegistry.GetValueNames(Strings: TStrings);
+function TRegistry.GetValueNames: TUnicodeStringArray;
 begin
-  TXmlRegistry(FSysData).EnumValues(Strings);
+  Result := TXmlRegistry(FSysData).EnumValues;
 end;
 
 
-function TRegistry.SysPutData(const Name: string; Buffer: Pointer;
+function TRegistry.SysPutData(const Name: UnicodeString; Buffer: Pointer;
   BufSize: Integer; RegData: TRegDataType): Boolean;
 
 Var
   DataType : TDataType;
 
 begin
+  //writeln('TRegistry.SysPutData: Name=',Name,', RegData=',RegData,', BufSize=',BufSize);
   DataType:=RegDataTypeToXmlDataType(RegData);
+
   Result:=TXMLRegistry(FSysData).SetValueDataUnicode(Name,DataType,Buffer^,BufSize);
 end;
 
-procedure TRegistry.RenameValue(const OldName, NewName: string);
+procedure TRegistry.RenameValue(const OldName, NewName: UnicodeString);
 begin
   TXMLRegistry(FSysData).RenameValue(OldName,NewName);
 end;
 
+
 procedure TRegistry.SetCurrentKey(Value: HKEY);
 begin
   fCurrentKey := Value;
@@ -298,7 +305,7 @@ end;
 procedure TRegistry.SetRootKey(Value: HKEY);
 
 Var
-  S: String;
+  S: UnicodeString;
 
 begin
   If (Value=HKEY_CLASSES_ROOT) then
@@ -347,3 +354,5 @@ begin
     TXMLRegistry(FSysData).SetRootKey(TXMLRegistry(FSysData).RootKey);
   end;
 end;
+
+