1Unit Registry; 2 3{$mode objfpc} 4{$H+} 5 6interface 7 8{$ifndef windows} 9{$define XMLREG} 10{$endif} 11 12Uses 13 {$ifndef XMLREG} 14 Windows, 15 {$endif XMLREG} 16 Classes, 17 SysUtils, 18 inifiles; 19 20{$I regdef.inc} 21 22type 23 ERegistryException = class(Exception); 24 25 TRegKeyInfo = record 26 NumSubKeys: Integer; 27 MaxSubKeyLen: Integer; 28 NumValues: Integer; 29 MaxValueLen: Integer; 30 MaxDataLen: Integer; 31 FileTime: TDateTime; 32 end; 33 34 TRegDataType = (rdUnknown, rdString, rdExpandString, rdBinary, rdInteger, rdIntegerBigEndian, 35 rdLink, rdMultiString, rdResourceList, rdFullResourceDescriptor, rdResourceRequirementList, rdInt64); 36 37 TRegDataInfo = record 38 RegData: TRegDataType; 39 DataSize: Integer; 40 end; 41 42 TUnicodeStringArray = Array of UnicodeString; 43 44{ --------------------------------------------------------------------- 45 TRegistry 46 ---------------------------------------------------------------------} 47 48 { TRegistry } 49 50 TRegistry = class(TObject) 51 private 52 FLastError: Longint; 53 FStringSizeIncludesNull : Boolean; 54 FSysData : Pointer; 55 fAccess: LongWord; 56 fCurrentKey: HKEY; 57 fRootKey: HKEY; 58 fLazyWrite: Boolean; 59 fCurrentPath: UnicodeString; 60 function FixPath(APath: UnicodeString): UnicodeString; 61 function GetLastErrorMsg: string; 62 function RegMultiSzDataToUnicodeStringArray(U: UnicodeString): TUnicodeStringArray; 63 function ListToArray(List: TStrings; IsUtf8: Boolean): TUnicodeStringArray; 64 procedure ArrayToList(const Arr: TUnicodeStringArray; List: TStrings; ForceUtf8: Boolean); 65 procedure SetRootKey(Value: HKEY); 66 Procedure SysRegCreate; 67 Procedure SysRegFree; 68 Function SysGetData(const Name: UnicodeString; Buffer: Pointer; BufSize: Integer; Out RegData: TRegDataType): Integer; 69 Function SysPutData(const Name: UnicodeString; Buffer: Pointer; BufSize: Integer; RegData: TRegDataType) : Boolean; 70 Function SysCreateKey(Key: UnicodeString): Boolean; 71 protected 72 function GetBaseKey(Relative: Boolean): HKey; 73 function GetData(const Name: UnicodeString; Buffer: Pointer; 74 BufSize: Integer; Out RegData: TRegDataType): Integer; 75 function GetData(const Name: String; Buffer: Pointer; 76 BufSize: Integer; Out RegData: TRegDataType): Integer; 77 function GetKey(Key: UnicodeString): HKEY; 78 function GetKey(Key: String): HKEY; 79 procedure ChangeKey(Value: HKey; const Path: UnicodeString); 80 procedure ChangeKey(Value: HKey; const Path: String); 81 procedure PutData(const Name: UnicodeString; Buffer: Pointer; 82 BufSize: Integer; RegData: TRegDataType); 83 procedure PutData(const Name: String; Buffer: Pointer; 84 BufSize: Integer; RegData: TRegDataType); 85 procedure SetCurrentKey(Value: HKEY); 86 public 87 constructor Create; overload; 88 constructor Create(aaccess:longword); overload; 89 destructor Destroy; override; 90 91 function CreateKey(const Key: UnicodeString): Boolean; 92 function CreateKey(const Key: String): Boolean; 93 function DeleteKey(const Key: UnicodeString): Boolean; 94 function DeleteKey(const Key: String): Boolean; 95 function DeleteValue(const Name: UnicodeString): Boolean; 96 function DeleteValue(const Name: String): Boolean; 97 function GetDataInfo(const ValueName: UnicodeString; Out Value: TRegDataInfo): Boolean; 98 function GetDataInfo(const ValueName: String; Out Value: TRegDataInfo): Boolean; 99 function GetDataSize(const ValueName: UnicodeString): Integer; 100 function GetDataSize(const ValueName: String): Integer; 101 function GetDataType(const ValueName: UnicodeString): TRegDataType; 102 function GetDataType(const ValueName: String): TRegDataType; 103 function GetKeyInfo(Out Value: TRegKeyInfo): Boolean; 104 function HasSubKeys: Boolean; 105 function KeyExists(const Key: UnicodeString): Boolean; 106 function KeyExists(const Key: String): Boolean; 107 function LoadKey(const Key, FileName: UnicodeString): Boolean; unimplemented; 108 function LoadKey(const Key, FileName: String): Boolean; unimplemented; 109 function OpenKey(const Key: UnicodeString; CanCreate: Boolean): Boolean; 110 function OpenKey(const Key: String; CanCreate: Boolean): Boolean; 111 function OpenKeyReadOnly(const Key: UnicodeString): Boolean; 112 function OpenKeyReadOnly(const Key: String): Boolean; 113 function ReadCurrency(const Name: UnicodeString): Currency; 114 function ReadCurrency(const Name: String): Currency; 115 function ReadBinaryData(const Name: UnicodeString; var Buffer; BufSize: Integer): Integer; 116 function ReadBinaryData(const Name: String; var Buffer; BufSize: Integer): Integer; 117 function ReadBool(const Name: UnicodeString): Boolean; 118 function ReadBool(const Name: String): Boolean; 119 function ReadDate(const Name: UnicodeString): TDateTime; 120 function ReadDate(const Name: String): TDateTime; 121 function ReadDateTime(const Name: UnicodeString): TDateTime; 122 function ReadDateTime(const Name: String): TDateTime; 123 function ReadFloat(const Name: UnicodeString): Double; 124 function ReadFloat(const Name: String): Double; 125 function ReadInteger(const Name: UnicodeString): Integer; 126 function ReadInteger(const Name: String): Integer; 127 function ReadInt64(const Name: UnicodeString): Int64; 128 function ReadInt64(const Name: String): Int64; 129 function ReadString(const Name: UnicodeString): UnicodeString; 130 function ReadString(const Name: String): string; 131 procedure ReadStringList(const Name: UnicodeString; AList: TStrings; ForceUtf8: Boolean=False); 132 procedure ReadStringList(const Name: String; AList: TStrings); 133 function ReadStringArray(const Name: UnicodeString): TUnicodeStringArray; 134 function ReadStringArray(const Name: String): TStringArray; 135 function ReadTime(const Name: UnicodeString): TDateTime; 136 function ReadTime(const Name: String): TDateTime; 137 function RegistryConnect(const UNCName: UnicodeString): Boolean; 138 function RegistryConnect(const UNCName: String): Boolean; 139 function ReplaceKey(const Key, FileName, BackUpFileName: UnicodeString): Boolean; unimplemented; 140 function ReplaceKey(const Key, FileName, BackUpFileName: String): Boolean; unimplemented; 141 function RestoreKey(const Key, FileName: UnicodeString): Boolean; unimplemented; 142 function RestoreKey(const Key, FileName: String): Boolean; unimplemented; 143 function SaveKey(const Key, FileName: UnicodeString): Boolean; 144 function SaveKey(const Key, FileName: String): Boolean; 145 function UnLoadKey(const Key: UnicodeString): Boolean; 146 function UnLoadKey(const Key: String): Boolean; 147 function ValueExists(const Name: UnicodeString): Boolean; 148 function ValueExists(const Name: String): Boolean; 149 150 procedure CloseKey; 151 procedure CloseKey(key:HKEY); 152 procedure GetKeyNames(Strings: TStrings); 153 function GetKeyNames: TUnicodeStringArray; 154 procedure GetValueNames(Strings: TStrings); 155 //ToDo 156 function GetValueNames: TUnicodeStringArray; 157 procedure MoveKey(const OldName, NewName: UnicodeString; Delete: Boolean); unimplemented; 158 procedure MoveKey(const OldName, NewName: String; Delete: Boolean); unimplemented; 159 procedure RenameValue(const OldName, NewName: UnicodeString); 160 procedure RenameValue(const OldName, NewName: String); 161 procedure WriteCurrency(const Name: UnicodeString; Value: Currency); 162 procedure WriteCurrency(const Name: String; Value: Currency); 163 procedure WriteBinaryData(const Name: UnicodeString; const Buffer; BufSize: Integer); 164 procedure WriteBinaryData(const Name: String; const Buffer; BufSize: Integer); 165 procedure WriteBool(const Name: UnicodeString; Value: Boolean); 166 procedure WriteBool(const Name: String; Value: Boolean); 167 procedure WriteDate(const Name: UnicodeString; Value: TDateTime); 168 procedure WriteDate(const Name: String; Value: TDateTime); 169 procedure WriteDateTime(const Name: UnicodeString; Value: TDateTime); 170 procedure WriteDateTime(const Name: String; Value: TDateTime); 171 procedure WriteFloat(const Name: UnicodeString; Value: Double); 172 procedure WriteFloat(const Name: String; Value: Double); 173 procedure WriteInteger(const Name: UnicodeString; Value: Integer); 174 procedure WriteInteger(const Name: String; Value: Integer); 175 procedure WriteInt64(const Name: UnicodeString; Value: Int64); 176 procedure WriteInt64(const Name: String; Value: Int64); 177 procedure WriteString(const Name, Value: UnicodeString); 178 procedure WriteString(const Name, Value: String); 179 procedure WriteExpandString(const Name, Value: UnicodeString); 180 procedure WriteExpandString(const Name, Value: String); 181 procedure WriteStringList(const Name: UnicodeString; List: TStrings; IsUtf8: Boolean=False); 182 procedure WriteStringArray(const Name: UnicodeString; const Arr: TUnicodeStringArray); 183 procedure WriteStringArray(const Name: String; const Arr: TStringArray); 184 procedure WriteTime(const Name: UnicodeString; Value: TDateTime); 185 procedure WriteTime(const Name: String; Value: TDateTime); 186 187 property Access: LongWord read fAccess write fAccess; 188 property CurrentKey: HKEY read fCurrentKey; 189 property CurrentPath: UnicodeString read fCurrentPath; 190 property LazyWrite: Boolean read fLazyWrite write fLazyWrite; 191 property RootKey: HKEY read fRootKey write SetRootKey; 192 Property StringSizeIncludesNull : Boolean read FStringSizeIncludesNull; 193 property LastError: Longint read FLastError; platform; 194 property LastErrorMsg: string read GetLastErrorMsg; platform; 195 end; 196 197{ --------------------------------------------------------------------- 198 TRegIniFile 199 ---------------------------------------------------------------------} 200 TRegIniFile = class(TRegistry) 201 private 202 fFileName : String; 203 fPath : String; 204 fPreferStringValues: Boolean; 205 function OpenSection(const Section: string; CreateSection : Boolean = false): boolean; 206 procedure CloseSection; 207 public 208 constructor Create(const FN: string); overload; 209 constructor Create(const FN: string;aaccess:longword); overload; 210 function ReadString(const Section, Ident, Default: string): string; 211 function ReadInteger(const Section, Ident: string; Default: Longint): Longint; 212 function ReadBool(const Section, Ident: string; Default: Boolean): Boolean; 213 function ReadDate(const Section, Ident: string; Default: TDateTime):TDateTime; 214 function ReadDateTime(const Section, Ident: string; Default: TDateTime):TDateTime; 215 function ReadTime(const Section, Ident: string; Default: TDateTime):TDateTime; 216 function ReadFloat(const Section, Ident: string; Default: Double): Double; 217 218 procedure WriteString(const Section, Ident, Value: String); 219 procedure WriteInteger(const Section, Ident: string; Value: Longint); 220 procedure WriteBool(const Section, Ident: string; Value: Boolean); 221 procedure WriteDate(const Section, Ident: string; Value: TDateTime); 222 procedure WriteDateTime(const Section, Ident: string; Value: TDateTime); 223 procedure WriteTime(const Section, Ident: string; Value: TDateTime); 224 procedure WriteFloat(const Section, Ident: string; Value: Double); 225 procedure ReadSection(const Section: string; Strings: TStrings); 226 procedure ReadSections(Strings: TStrings); 227 procedure ReadSectionValues(const Section: string; Strings: TStrings); 228 procedure EraseSection(const Section: string); 229 procedure DeleteKey(const Section, Ident: String); 230 231 property FileName: String read fFileName; 232 property PreferStringValues: Boolean read fPreferStringValues 233 write fPreferStringValues; 234 end{$ifdef XMLREG}deprecated 'Use TRegistry instead. Will be removed in 4.0'{$endif} platform; 235 236{ --------------------------------------------------------------------- 237 TRegIniFile 238 ---------------------------------------------------------------------} 239 240 241 TRegistryIniFile = class(TCustomIniFile) 242 private 243 FRegIniFile: TRegIniFile; 244 public 245 constructor Create(const AFileName: string); overload; 246 constructor Create(const AFileName: string; AAccess: LongWord); overload; 247 destructor destroy; override; 248 function ReadDate(const Section, Name: string; Default: TDateTime): TDateTime; override; 249 function ReadDateTime(const Section, Name: string; Default: TDateTime): TDateTime; override; 250 function ReadInteger(const Section, Name: string; Default: Longint): Longint; override; 251 function ReadFloat(const Section, Name: string; Default: Double): Double; override; 252 function ReadString(const Section, Name, Default: string): string; override; 253 function ReadTime(const Section, Name: string; Default: TDateTime): TDateTime; override; 254 function ReadBinaryStream(const Section, Name: string; Value: TStream): Integer; override; unimplemented; 255 procedure WriteDate(const Section, Name: string; Value: TDateTime); override; 256 procedure WriteDateTime(const Section, Name: string; Value: TDateTime); override; 257 procedure WriteFloat(const Section, Name: string; Value: Double); override; 258 procedure WriteInteger(const Section, Name: string; Value: Longint); override; 259 procedure WriteString(const Section, Name, Value: String); override; 260 procedure WriteTime(const Section, Name: string; Value: TDateTime); override; 261 procedure WriteBinaryStream(const Section, Name: string; Value: TStream); override; 262 procedure ReadSection(const Section: string; Strings: TStrings); override; 263 procedure ReadSections(Strings: TStrings); override; 264 procedure ReadSectionValues(const Section: string; Strings: TStrings); override; 265 procedure EraseSection(const Section: string); override; 266 procedure DeleteKey(const Section, Name: String); override; 267 procedure UpdateFile; override; 268 function ValueExists(const Section, Ident: string): Boolean; override; 269 property RegIniFile: TRegIniFile read FRegIniFile; 270 end{$ifdef XMLREG}deprecated 'Use TRegistry instead. Will be removed in 4.0'{$endif} platform; 271 272ResourceString 273 SInvalidRegType = 'Invalid registry data type: "%s"'; 274 SRegCreateFailed = 'Failed to create key: "%s"'; 275 SRegSetDataFailed = 'Failed to set data for value "%s"'; 276 SRegGetDataFailed = 'Failed to get data for value "%s"'; 277 278var 279 GlobalXMLFile : Boolean = False; 280 281implementation 282 283{ --------------------------------------------------------------------- 284 Include implementation-dependent code 285 ---------------------------------------------------------------------} 286 287 288{$ifdef XMLREG} 289{$i xregreg.inc} 290{$else} 291{$i winreg.inc} 292{$endif} 293 294{ --------------------------------------------------------------------- 295 Generic, implementation-independent code. 296 ---------------------------------------------------------------------} 297 298{$ifdef DebugRegistry} 299function DbgS(const S: UnicodeString): String; 300var 301 C: WideChar; 302begin 303 Result := ''; 304 for C in S do Result := Result + IntToHex(Word(C),4) + #32; 305 Result := TrimRight(Result); 306end; 307{$endif} 308 309constructor TRegistry.Create; 310 311begin 312 inherited Create; 313 FAccess := KEY_ALL_ACCESS; 314 FRootKey := HKEY_CURRENT_USER; 315 FLazyWrite := True; 316 FCurrentKey := 0; 317 SysRegCreate; 318end; 319 320constructor TRegistry.Create(aaccess: longword); 321 322begin 323 Create; 324 FAccess := aaccess; 325end; 326 327destructor TRegistry.Destroy; 328begin 329 CloseKey; 330 SysRegFree; 331 inherited Destroy; 332end; 333 334function TRegistry.CreateKey(const Key: UnicodeString): Boolean; 335 336begin 337 Result:=SysCreateKey(Key); 338 If Not Result Then 339 Raise ERegistryException.CreateFmt(SRegCreateFailed, [Key]); 340end; 341 342function TRegistry.CreateKey(const Key: String): Boolean; 343begin 344 Result:=CreateKey(UnicodeString(Key)); 345end; 346 347function TRegistry.DeleteKey(const Key: String): Boolean; 348begin 349 Result:=DeleteKey(UnicodeString(Key)); 350end; 351 352function TRegistry.DeleteValue(const Name: String): Boolean; 353begin 354 Result:=DeleteValue(UnicodeString(Name)); 355end; 356 357function TRegistry.GetDataInfo(const ValueName: String; out Value: TRegDataInfo 358 ): Boolean; 359begin 360 Result:=GetDataInfo(UnicodeString(ValueName), Value); 361end; 362 363function TRegistry.GetBaseKey(Relative: Boolean): HKey; 364begin 365 If Relative and (CurrentKey<>0) Then 366 Result := CurrentKey 367 else 368 Result := RootKey; 369end; 370 371function TRegistry.GetData(const Name: UnicodeString; Buffer: Pointer; BufSize: Integer; out RegData: TRegDataType): Integer; 372begin 373 Result:=SysGetData(Name,Buffer,BufSize,RegData); 374 If (Result=-1) then 375 Raise ERegistryException.CreateFmt(SRegGetDataFailed, [Name]); 376end; 377 378function TRegistry.GetData(const Name: String; Buffer: Pointer; 379 BufSize: Integer; out RegData: TRegDataType): Integer; 380begin 381 Result:=GetData(UnicodeString(Name), Buffer, BufSize, RegData); 382end; 383 384function TRegistry.GetKey(Key: String): HKEY; 385begin 386 Result:=GetKey(UnicodeString(Key)); 387end; 388 389procedure TRegistry.ChangeKey(Value: HKey; const Path: String); 390begin 391 ChangeKey(Value, UnicodeString(Path)); 392end; 393 394 395procedure TRegistry.PutData(const Name: UnicodeString; Buffer: Pointer; 396 BufSize: Integer; RegData: TRegDataType); 397 398begin 399 If Not SysPutData(Name,Buffer,BufSize,RegData) then 400 Raise ERegistryException.CreateFmt(SRegSetDataFailed, [Name]); 401end; 402 403procedure TRegistry.PutData(const Name: String; Buffer: Pointer; 404 BufSize: Integer; RegData: TRegDataType); 405begin 406 PutData(UnicodeString(Name), Buffer, BufSize, RegData); 407end; 408 409 410function TRegistry.GetDataSize(const ValueName: UnicodeString): Integer; 411 412Var 413 Info: TRegDataInfo; 414 415begin 416 If GetDataInfo(ValueName,Info) Then 417 Result := Info.DataSize 418 else 419 Result := -1; 420end; 421 422function TRegistry.GetDataSize(const ValueName: String): Integer; 423begin 424 Result:=GetDataSize(UnicodeString(ValueName)); 425end; 426 427function TRegistry.GetDataType(const ValueName: UnicodeString): TRegDataType; 428 429Var 430 Info: TRegDataInfo; 431 432begin 433 GetDataInfo(ValueName, Info); 434 Result:=Info.RegData; 435end; 436 437function TRegistry.GetDataType(const ValueName: String): TRegDataType; 438begin 439 Result:=GetDataType(UnicodeString(ValueName)); 440end; 441 442 443function TRegistry.KeyExists(const Key: String): Boolean; 444begin 445 Result:=KeyExists(UnicodeString(Key)); 446end; 447 448function TRegistry.LoadKey(const Key, FileName: String): Boolean; 449begin 450 Result:=LoadKey(UnicodeString(Key), UnicodeString(FileName)); 451end; 452 453function TRegistry.OpenKey(const Key: String; CanCreate: Boolean): Boolean; 454begin 455 Result:=OpenKey(UnicodeString(Key), CanCreate); 456end; 457 458function TRegistry.OpenKeyReadOnly(const Key: String): Boolean; 459begin 460 Result:=OpenKeyReadOnly(UnicodeString(Key)); 461end; 462 463function TRegistry.HasSubKeys: Boolean; 464 465Var 466 Info : TRegKeyInfo; 467 468begin 469 Result:=GetKeyInfo(Info); 470 If Result then 471 Result:=(Info.NumSubKeys>0); 472end; 473 474function TRegistry.ReadBinaryData(const Name: UnicodeString; var Buffer; BufSize: Integer): Integer; 475 476Var 477 RegDataType: TRegDataType; 478 479begin 480 Result := GetData(Name, @Buffer, BufSize, RegDataType); 481end; 482 483function TRegistry.ReadBinaryData(const Name: String; var Buffer; 484 BufSize: Integer): Integer; 485begin 486 Result:=ReadBinaryData(UnicodeString(Name), Buffer, BufSize); 487end; 488 489function TRegistry.ReadInteger(const Name: UnicodeString): Integer; 490 491Var 492 RegDataType: TRegDataType; 493 494begin 495 GetData(Name, @Result, SizeOf(Integer), RegDataType); 496 If RegDataType<>rdInteger Then 497 Raise ERegistryException.CreateFmt(SInvalidRegType, [Name]); 498end; 499 500function TRegistry.ReadInteger(const Name: String): Integer; 501begin 502 Result:=ReadInteger(UnicodeString(Name)); 503end; 504 505function TRegistry.ReadInt64(const Name: UnicodeString): Int64; 506 507Var 508 RegDataType: TRegDataType; 509 510begin 511 GetData(Name, @Result, SizeOf(Int64), RegDataType); 512 If RegDataType<>rdInt64 Then 513 Raise ERegistryException.CreateFmt(SInvalidRegType, [Name]); 514end; 515 516function TRegistry.ReadInt64(const Name: String): Int64; 517begin 518 Result:=ReadInt64(UnicodeString(Name)); 519end; 520 521function TRegistry.ReadBool(const Name: UnicodeString): Boolean; 522 523begin 524 Result:=ReadInteger(Name)<>0; 525end; 526 527function TRegistry.ReadBool(const Name: String): Boolean; 528begin 529 Result:=ReadBool(UnicodeString(Name)); 530end; 531 532function TRegistry.ReadCurrency(const Name: UnicodeString): Currency; 533 534begin 535 Result:=Default(Currency); 536 ReadBinaryData(Name, Result, SizeOf(Currency)); 537end; 538 539function TRegistry.ReadCurrency(const Name: String): Currency; 540begin 541 Result:=ReadCurrency(UnicodeString(Name)); 542end; 543 544function TRegistry.ReadDate(const Name: UnicodeString): TDateTime; 545 546begin 547 Result:=Trunc(ReadDateTime(Name)); 548end; 549 550function TRegistry.ReadDate(const Name: String): TDateTime; 551begin 552 Result:=ReadDate(UnicodeString(Name)); 553end; 554 555function TRegistry.ReadDateTime(const Name: UnicodeString): TDateTime; 556 557begin 558 Result:=Default(TDateTime); 559 ReadBinaryData(Name, Result, SizeOf(TDateTime)); 560end; 561 562function TRegistry.ReadDateTime(const Name: String): TDateTime; 563begin 564 Result:=ReadDateTime(UnicodeString(Name)); 565end; 566 567function TRegistry.ReadFloat(const Name: UnicodeString): Double; 568 569begin 570 Result:=Default(Double); 571 ReadBinaryData(Name,Result,SizeOf(Double)); 572end; 573 574function TRegistry.ReadFloat(const Name: String): Double; 575begin 576 Result:=ReadFloat(UnicodeString(Name)); 577end; 578 579function TRegistry.ReadString(const Name: UnicodeString): UnicodeString; 580 581Var 582 Info : TRegDataInfo; 583 ReadDataSize: Integer; 584 u: UnicodeString; 585 586begin 587 Result:=''; 588 GetDataInfo(Name,Info); 589 if info.datasize>0 then 590 begin 591 if Not (Info.RegData in [rdString,rdExpandString]) then 592 Raise ERegistryException.CreateFmt(SInvalidRegType, [Name]); 593 if Odd(Info.DataSize) then 594 SetLength(u,round((Info.DataSize+1)/SizeOf(UnicodeChar))) 595 else 596 SetLength(u,round(Info.DataSize/SizeOf(UnicodeChar))); 597 ReadDataSize := GetData(Name,@u[1],Info.DataSize,Info.RegData); 598 if ReadDataSize > 0 then 599 begin 600 // If the data has the REG_SZ, REG_MULTI_SZ or REG_EXPAND_SZ type, 601 // the size includes any terminating null character or characters 602 // unless the data was stored without them! (RegQueryValueEx @ MSDN) 603 if StringSizeIncludesNull and 604 (u[Length(u)] = WideChar(0)) then 605 SetLength(u,Length(u)-1); 606 Result:=u; 607 end; 608 end; 609end; 610 611function TRegistry.ReadString(const Name: String): string; 612begin 613 Result:=ReadString(UnicodeString(Name)); 614end; 615 616 617procedure TRegistry.ReadStringList(const Name: UnicodeString; AList: TStrings; ForceUtf8: Boolean=False); 618 619Var 620 UArr: TUnicodeStringArray; 621 622begin 623 UArr := ReadStringArray(Name); 624 ArrayToList(UArr, AList, ForceUtf8); 625end; 626 627procedure TRegistry.ReadStringList(const Name: String; AList: TStrings); 628begin 629 ReadStringList(UnicodeString(Name), AList); 630end; 631 632function TRegistry.FixPath(APath: UnicodeString): UnicodeString; 633const 634 Delim={$ifdef XMLREG}'/'{$else}'\'{$endif}; 635begin 636 //At this point we know the path is valid, since this is only called after OpenKey succeeded 637 //Just sanitize it 638 while (Pos(Delim+Delim,APath) > 0) do 639 APath := UnicodeStringReplace(APath, Delim+Delim,Delim,[rfReplaceAll]); 640 if (Length(APath) > 1) and (APath[Length(APath)] = Delim) then 641 System.Delete(APath, Length(APath), 1); 642 Result := APath; 643end; 644 645function TRegistry.RegMultiSzDataToUnicodeStringArray(U: UnicodeString): TUnicodeStringArray; 646var 647 Len, i, p: Integer; 648 Sub: UnicodeString; 649begin 650 Result := nil; 651 if (U = '') then Exit; 652 Len := 1; 653 for i := 1 to Length(U) do if (U[i] = #0) then Inc(Len); 654 SetLength(Result, Len); 655 i := 0; 656 657 while (U <> '') and (i < Length(Result)) do 658 begin 659 p := Pos(#0, U); 660 if (p = 0) then p := Length(U) + 1; 661 Sub := Copy(U, 1, p - 1); 662 Result[i] := Sub; 663 System.Delete(U, 1, p); 664 Inc(i); 665 end; 666end; 667 668function TRegistry.ListToArray(List: TStrings; IsUtf8: Boolean): TUnicodeStringArray; 669var 670 i, curr, Len: Integer; 671 u: UnicodeString; 672begin 673 Result := nil; 674 Len := List.Count; 675 SetLength(Result, Len); 676 //REG_MULTI_SZ data cannot contain empty strings 677 curr := 0; 678 for i := 0 to List.Count - 1 do 679 begin 680 if IsUtf8 then 681 u := Utf8Decode(List[i]) 682 else 683 u := List[i]; 684 if (u>'') then 685 begin 686 Result[curr] := u; 687 inc(curr); 688 end 689 else 690 Dec(Len); 691 end; 692 if (Len <> List.Count) then SetLength(Result, Len); 693end; 694 695procedure TRegistry.ArrayToList(const Arr: TUnicodeStringArray; List: TStrings; ForceUtf8: Boolean); 696var 697 i: Integer; 698begin 699 List.Clear; 700 for i := Low(Arr) to High(Arr) do 701 begin 702 if ForceUtf8 then 703 List.Add(Utf8Encode(Arr[i])) 704 else 705 List.Add(String(Arr[i])); 706 end; 707end; 708 709function TRegistry.ReadStringArray(const Name: UnicodeString): TUnicodeStringArray; 710Var 711 Info : TRegDataInfo; 712 ReadDataSize: Integer; 713 Data: UnicodeString; 714 715begin 716 Result := nil; 717 GetDataInfo(Name,Info); 718 //writeln('TRegistry.ReadStringArray: datasize=',info.datasize); 719 if info.datasize>0 then 720 begin 721 If Not (Info.RegData in [rdMultiString]) then 722 Raise ERegistryException.CreateFmt(SInvalidRegType, [Name]); 723 SetLength(Data,Info.DataSize); 724 ReadDataSize := GetData(Name,PWideChar(Data),Info.DataSize,Info.RegData) div SizeOf(WideChar); 725 //writeln('TRegistry.ReadStringArray: ReadDataSize=',ReadDataSize); 726 if ReadDataSize > 0 then 727 begin 728 // Windows returns the data with or without trailing zero's, so just strip all trailing null characters 729 while (Data[ReadDataSize] = #0) do Dec(ReadDataSize); 730 SetLength(Data, ReadDataSize); 731 //writeln('Data=',dbgs(data)); 732 //Data := UnicodeStringReplace(Data, #0, AList.LineBreak, [rfReplaceAll]); 733 //AList.Text := Data; 734 Result := RegMultiSzDataToUnicodeStringArray(Data); 735 end 736 end 737end; 738 739function TRegistry.ReadStringArray(const Name: String): TStringArray; 740var 741 UArr: TUnicodeStringArray; 742 i: Integer; 743begin 744 Result := nil; 745 UArr := ReadStringArray(UnicodeString(Name)); 746 SetLength(Result, Length(UArr)); 747 for i := Low(UArr) to High(UArr) do Result[i] := UArr[i]; 748end; 749 750function TRegistry.ReadTime(const Name: UnicodeString): TDateTime; 751 752begin 753 Result:=Frac(ReadDateTime(Name)); 754end; 755 756function TRegistry.ReadTime(const Name: String): TDateTime; 757begin 758 Result:=ReadTime(UnicodeString(Name)); 759end; 760 761function TRegistry.RegistryConnect(const UNCName: String): Boolean; 762begin 763 Result:=RegistryConnect(UnicodeString(UNCName)); 764end; 765 766function TRegistry.ReplaceKey(const Key, FileName, BackUpFileName: String): Boolean; 767begin 768 Result:=ReplaceKey(UnicodeString(Key), UnicodeString(FileName), UnicodeString(BackUpFileName)) 769end; 770 771function TRegistry.RestoreKey(const Key, FileName: String): Boolean; 772begin 773 Result:=RestoreKey(UnicodeString(Key), UnicodeString(FileName)); 774end; 775 776function TRegistry.SaveKey(const Key, FileName: String): Boolean; 777begin 778 Result:=SaveKey(UnicodeString(Key), UnicodeString(FileName)); 779end; 780 781function TRegistry.UnLoadKey(const Key: String): Boolean; 782begin 783 Result:=UnloadKey(UnicodeString(Key)); 784end; 785 786function TRegistry.ValueExists(const Name: String): Boolean; 787begin 788 Result:=ValueExists(UnicodeString(Name)); 789end; 790 791procedure TRegistry.WriteBinaryData(const Name: UnicodeString; const Buffer; BufSize: Integer); 792begin 793 PutData(Name, @Buffer, BufSize, rdBinary); 794end; 795 796procedure TRegistry.WriteBinaryData(const Name: String; const Buffer; 797 BufSize: Integer); 798begin 799 WriteBinaryData(UnicodeString(Name), Buffer, BufSize); 800end; 801 802procedure TRegistry.WriteBool(const Name: UnicodeString; Value: Boolean); 803 804begin 805 WriteInteger(Name,Ord(Value)); 806end; 807 808procedure TRegistry.WriteBool(const Name: String; Value: Boolean); 809begin 810 WriteBool(UnicodeString(Name), Value); 811end; 812 813procedure TRegistry.WriteCurrency(const Name: UnicodeString; Value: Currency); 814begin 815 WriteBinaryData(Name, Value, SizeOf(Currency)); 816end; 817 818procedure TRegistry.WriteCurrency(const Name: String; Value: Currency); 819begin 820 WriteCurrency(UnicodeString(Name), Value); 821end; 822 823procedure TRegistry.WriteDate(const Name: UnicodeString; Value: TDateTime); 824begin 825 WriteBinarydata(Name, Value, SizeOf(TDateTime)); 826end; 827 828procedure TRegistry.WriteDate(const Name: String; Value: TDateTime); 829begin 830 WriteDate(UnicodeString(Name), Value); 831end; 832 833procedure TRegistry.WriteTime(const Name: UnicodeString; Value: TDateTime); 834begin 835 WriteBinaryData(Name, Value, SizeOf(TDateTime)); 836end; 837 838procedure TRegistry.WriteTime(const Name: String; Value: TDateTime); 839begin 840 WriteTime(UnicodeString(Name), Value); 841end; 842 843procedure TRegistry.WriteDateTime(const Name: UnicodeString; Value: TDateTime); 844begin 845 WriteBinaryData(Name, Value, SizeOf(TDateTime)); 846end; 847 848procedure TRegistry.WriteDateTime(const Name: String; Value: TDateTime); 849begin 850 WriteDateTime(UnicodeString(Name), Value); 851end; 852 853procedure TRegistry.WriteExpandString(const Name, Value: UnicodeString); 854begin 855 PutData(Name, PWideChar(Value), ByteLength(Value), rdExpandString); 856end; 857 858procedure TRegistry.WriteExpandString(const Name, Value: String); 859begin 860 WriteExpandString(UnicodeString(Name), UnicodeString(Value)); 861end; 862 863 864procedure TRegistry.WriteStringList(const Name: UnicodeString; List: TStrings; IsUtf8: Boolean=False); 865 866Var 867 UArr: TUnicodeStringArray; 868begin 869 UArr := ListToArray(List, IsUtf8); 870 WriteStringArray(Name, UArr); 871end; 872 873procedure TRegistry.WriteStringArray(const Name: UnicodeString; const Arr: TUnicodeStringArray); 874Var 875 Data: UnicodeString; 876 u: UnicodeString; 877 i: Integer; 878begin 879 Data := ''; 880 //REG_MULTI_SZ data cannot contain empty strings 881 for i := Low(Arr) to High(Arr) do 882 begin 883 u := Arr[i]; 884 if (u>'') then 885 begin 886 if (Data>'') then 887 Data := Data + #0 + u 888 else 889 Data := Data + u; 890 end; 891 end; 892 if StringSizeIncludesNull then 893 Data := Data + #0#0; 894 //writeln('Data=',Dbgs(Data)); 895 PutData(Name, PWideChar(Data), ByteLength(Data), rdMultiString); 896end; 897 898procedure TRegistry.WriteStringArray(const Name: String; const Arr: TStringArray); 899var 900 UArr: TUnicodeStringArray; 901 i: Integer; 902begin 903 UArr := nil; 904 SetLength(UArr, Length(Arr)); 905 for i := Low(Arr) to High(Arr) do UArr[i] := Arr[i]; 906 WriteStringArray(UnicodeString(Name), UArr); 907end; 908 909procedure TRegistry.WriteFloat(const Name: UnicodeString; Value: Double); 910begin 911 WriteBinaryData(Name, Value, SizeOf(Double)); 912end; 913 914procedure TRegistry.WriteFloat(const Name: String; Value: Double); 915begin 916 WriteFloat(UnicodeString(Name), Value); 917end; 918 919procedure TRegistry.WriteInteger(const Name: UnicodeString; Value: Integer); 920begin 921 PutData(Name, @Value, SizeOf(Integer), rdInteger); 922end; 923 924procedure TRegistry.WriteInteger(const Name: String; Value: Integer); 925begin 926 WriteInteger(UnicodeString(Name), Value); 927end; 928 929procedure TRegistry.WriteInt64(const Name: UnicodeString; Value: Int64); 930begin 931 PutData(Name, @Value, SizeOf(Int64), rdInt64); 932end; 933 934procedure TRegistry.WriteInt64(const Name: String; Value: Int64); 935begin 936 WriteInt64(UnicodeString(Name), Value); 937end; 938 939procedure TRegistry.WriteString(const Name, Value: UnicodeString); 940begin 941 PutData(Name, PWideChar(Value), ByteLength(Value), rdString); 942end; 943 944procedure TRegistry.WriteString(const Name, Value: String); 945begin 946 WriteString(UnicodeString(Name), UnicodeString(Value)); 947end; 948 949procedure TRegistry.GetKeyNames(Strings: TStrings); 950var 951 UArr: TUnicodeStringArray; 952begin 953 UArr := GetKeyNames; 954 ArrayToList(UArr, Strings, True); 955end; 956 957procedure TRegistry.GetValueNames(Strings: TStrings); 958var 959 UArr: TUnicodeStringArray; 960begin 961 UArr := GetValueNames; 962 ArrayToList(UArr, Strings, True); 963end; 964 965procedure TRegistry.MoveKey(const OldName, NewName: UnicodeString; Delete: Boolean); 966begin 967 968end; 969 970procedure TRegistry.MoveKey(const OldName, NewName: String; Delete: Boolean); 971begin 972 MoveKey(UnicodeString(OldName), UnicodeString(NewName), Delete); 973end; 974 975procedure TRegistry.RenameValue(const OldName, NewName: String); 976begin 977 RenameValue(UnicodeString(OldName), UnicodeString(NewName)); 978end; 979 980{ --------------------------------------------------------------------- 981 Include TRegIniFile implementation 982 ---------------------------------------------------------------------} 983 984{$i regini.inc} 985 986{ TRegistryIniFile } 987 988// interface from 989// http://www.koders.com/delphi/fid65C1FFAEF89B0CDC4B93FF94C1819686CA6141FC.aspx 990constructor TRegistryIniFile.Create(const AFileName: string; 991 AAccess: LongWord); 992begin 993 inherited create(AFilename); 994 FRegInifile:=TreginiFile.Create(AFileName,AAccess); 995end; 996 997constructor TRegistryIniFile.Create(const AFileName: string); 998begin 999 Create(AFileName,KEY_ALL_ACCESS); 1000end; 1001 1002destructor TRegistryIniFile.destroy; 1003 1004begin 1005 FreeAndNil(FRegInifile); 1006 Inherited; 1007end; 1008 1009procedure TRegistryIniFile.DeleteKey(const Section, Name: String); 1010begin 1011 FRegIniFile.Deletekey(section,name); 1012end; 1013 1014procedure TRegistryIniFile.EraseSection(const Section: string); 1015begin 1016 FRegIniFile.EraseSection(section); 1017end; 1018 1019function TRegistryIniFile.ReadBinaryStream(const Section, Name: string; 1020 Value: TStream): Integer; 1021begin 1022 result:=-1; // unimplemented 1023 // 1024end; 1025 1026function TRegistryIniFile.ReadDate(const Section, Name: string; 1027 Default: TDateTime): TDateTime; 1028begin 1029 Result:=FRegInifile.ReadDate(Section,Name,Default); 1030end; 1031 1032function TRegistryIniFile.ReadDateTime(const Section, Name: string; 1033 Default: TDateTime): TDateTime; 1034begin 1035 Result:=FRegInifile.ReadDateTime(Section,Name,Default); 1036end; 1037 1038function TRegistryIniFile.ReadFloat(const Section, Name: string; 1039 Default: Double): Double; 1040begin 1041 Result:=FRegInifile.ReadFloat(Section,Name,Default); 1042end; 1043 1044function TRegistryIniFile.ReadInteger(const Section, Name: string; 1045 Default: Integer): Longint; 1046begin 1047 Result:=FRegInifile.ReadInteger(Section, Name, Default); 1048end; 1049 1050procedure TRegistryIniFile.ReadSection(const Section: string; Strings: TStrings); 1051begin 1052 FRegIniFile.ReadSection(Section,strings); 1053end; 1054 1055procedure TRegistryIniFile.ReadSections(Strings: TStrings); 1056begin 1057 FRegIniFile.ReadSections(strings); 1058end; 1059 1060procedure TRegistryIniFile.ReadSectionValues(const Section: string; 1061 Strings: TStrings); 1062begin 1063 FRegIniFile.ReadSectionValues(Section,strings); 1064end; 1065 1066function TRegistryIniFile.ReadString(const Section, Name, 1067 Default: string): string; 1068begin 1069 Result:=FRegInifile.ReadString(Section, Name, Default); 1070end; 1071 1072function TRegistryIniFile.ReadTime(const Section, Name: string; 1073 Default: TDateTime): TDateTime; 1074begin 1075 Result:=FRegInifile.ReadTime(Section,Name,Default); 1076end; 1077 1078procedure TRegistryIniFile.UpdateFile; 1079begin 1080// FRegIniFile.UpdateFile; ?? 1081end; 1082 1083procedure TRegistryIniFile.WriteBinaryStream(const Section, Name: string; 1084 Value: TStream); 1085begin 1086 // ?? 1087end; 1088 1089procedure TRegistryIniFile.WriteDate(const Section, Name: string; 1090 Value: TDateTime); 1091begin 1092 FRegInifile.WriteDate(Section,Name, Value); 1093end; 1094 1095procedure TRegistryIniFile.WriteDateTime(const Section, Name: string; 1096 Value: TDateTime); 1097begin 1098 FRegInifile.WriteDateTime(Section,Name, Value); 1099end; 1100 1101procedure TRegistryIniFile.WriteFloat(const Section, Name: string; 1102 Value: Double); 1103begin 1104 FRegInifile.WriteFloat(Section,Name, Value); 1105end; 1106 1107procedure TRegistryIniFile.WriteInteger(const Section, Name: string; 1108 Value: Integer); 1109begin 1110 FRegInifile.WriteInteger(Section, Name, Value); 1111end; 1112 1113procedure TRegistryIniFile.WriteString(const Section, Name, Value: String); 1114begin 1115 FRegInifile.WriteString(Section, Name, Value); 1116end; 1117 1118procedure TRegistryIniFile.WriteTime(const Section, Name: string; 1119 Value: TDateTime); 1120begin 1121 FRegInifile.WriteTime(Section,Name, Value); 1122end; 1123 1124function TRegistryIniFile.ValueExists(const Section, Ident: string): Boolean; 1125begin 1126 with FRegInifile do 1127 if OpenSection(Section) then 1128 try 1129 Result:=FRegInifile.ValueExists(Ident); 1130 finally 1131 CloseSection; 1132 end; 1133end; 1134 1135{$ifdef XMLREG} 1136finalization 1137 TXMLRegistryInstance.FreeXMLRegistryCache; 1138{$endif} 1139 1140end. 1141