home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 2000 March / pcp161b.iso / full / delphi / RUNIMAGE / DELPHI30 / SOURCE / VCL / REGISTRY.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1997-08-03  |  26.0 KB  |  997 lines

  1.  
  2. {*******************************************************}
  3. {                                                       }
  4. {       Delphi Visual Component Library                 }
  5. {                                                       }
  6. {       Copyright (c) 1996,97 Borland International     }
  7. {                                                       }
  8. {*******************************************************}
  9.  
  10. unit Registry;
  11.  
  12. {$R-}
  13.  
  14. interface
  15.  
  16. uses Windows, Classes, SysUtils;
  17.  
  18. type
  19.   ERegistryException = class(Exception);
  20.  
  21.   TRegKeyInfo = record
  22.     NumSubKeys: Integer;
  23.     MaxSubKeyLen: Integer;
  24.     NumValues: Integer;
  25.     MaxValueLen: Integer;
  26.     MaxDataLen: Integer;
  27.     FileTime: TFileTime;
  28.   end;
  29.  
  30.   TRegDataType = (rdUnknown, rdString, rdExpandString, rdInteger, rdBinary);
  31.  
  32.   TRegDataInfo = record
  33.     RegData: TRegDataType;
  34.     DataSize: Integer;
  35.   end;
  36.  
  37.   TRegistry = class(TObject)
  38.   private
  39.     FCurrentKey: HKEY;
  40.     FRootKey: HKEY;
  41.     FLazyWrite: Boolean;
  42.     FCurrentPath: string;
  43.     FCloseRootKey: Boolean;
  44.     procedure SetRootKey(Value: HKEY);
  45.   protected
  46.     procedure ChangeKey(Value: HKey; const Path: string);
  47.     function GetBaseKey(Relative: Boolean): HKey;
  48.     function GetData(const Name: string; Buffer: Pointer;
  49.       BufSize: Integer; var RegData: TRegDataType): Integer;
  50.     function GetKey(const Key: string): HKEY;
  51.     procedure PutData(const Name: string; Buffer: Pointer; BufSize: Integer; RegData: TRegDataType);
  52.     procedure SetCurrentKey(Value: HKEY);
  53.   public
  54.     constructor Create;
  55.     destructor Destroy; override;
  56.     procedure CloseKey;
  57.     function CreateKey(const Key: string): Boolean;
  58.     function DeleteKey(const Key: string): Boolean;
  59.     function DeleteValue(const Name: string): Boolean;
  60.     function GetDataInfo(const ValueName: string; var Value: TRegDataInfo): Boolean;
  61.     function GetDataSize(const ValueName: string): Integer;
  62.     function GetDataType(const ValueName: string): TRegDataType;
  63.     function GetKeyInfo(var Value: TRegKeyInfo): Boolean;
  64.     procedure GetKeyNames(Strings: TStrings);
  65.     procedure GetValueNames(Strings: TStrings);
  66.     function HasSubKeys: Boolean;
  67.     function KeyExists(const Key: string): Boolean;
  68.     function LoadKey(const Key, FileName: string): Boolean;
  69.     procedure MoveKey(const OldName, NewName: string; Delete: Boolean);
  70.     function OpenKey(const Key: string; CanCreate: Boolean): Boolean;
  71.     function ReadCurrency(const Name: string): Currency;
  72.     function ReadBinaryData(const Name: string; var Buffer; BufSize: Integer): Integer;
  73.     function ReadBool(const Name: string): Boolean;
  74.     function ReadDate(const Name: string): TDateTime;
  75.     function ReadDateTime(const Name: string): TDateTime;
  76.     function ReadFloat(const Name: string): Double;
  77.     function ReadInteger(const Name: string): Integer;
  78.     function ReadString(const Name: string): string;
  79.     function ReadTime(const Name: string): TDateTime;
  80.     function RegistryConnect(const UNCName: string): Boolean;
  81.     procedure RenameValue(const OldName, NewName: string);
  82.     function ReplaceKey(const Key, FileName, BackUpFileName: string): Boolean;
  83.     function RestoreKey(const Key, FileName: string): Boolean;
  84.     function SaveKey(const Key, FileName: string): Boolean;
  85.     function UnLoadKey(const Key: string): Boolean;
  86.     function ValueExists(const Name: string): Boolean;
  87.     procedure WriteCurrency(const Name: string; Value: Currency);
  88.     procedure WriteBinaryData(const Name: string; var Buffer; BufSize: Integer);
  89.     procedure WriteBool(const Name: string; Value: Boolean);
  90.     procedure WriteDate(const Name: string; Value: TDateTime);
  91.     procedure WriteDateTime(const Name: string; Value: TDateTime);
  92.     procedure WriteFloat(const Name: string; Value: Double);
  93.     procedure WriteInteger(const Name: string; Value: Integer);
  94.     procedure WriteString(const Name, Value: string);
  95.     procedure WriteExpandString(const Name, Value: string);
  96.     procedure WriteTime(const Name: string; Value: TDateTime);
  97.     property CurrentKey: HKEY read FCurrentKey;
  98.     property CurrentPath: string read FCurrentPath;
  99.     property LazyWrite: Boolean read FLazyWrite write FLazyWrite;
  100.     property RootKey: HKEY read FRootKey write SetRootKey;
  101.   end;
  102.  
  103.   TRegIniFile = class(TRegistry)
  104.   private
  105.     FFileName: string;
  106.   public
  107.     constructor Create(const FileName: string);
  108.     function ReadString(const Section, Ident, Default: string): string;
  109.     procedure WriteString(const Section, Ident, Value: String);
  110.     function ReadInteger(const Section, Ident: string;
  111.       Default: Longint): Longint;
  112.     procedure WriteInteger(const Section, Ident: string; Value: Longint);
  113.     function ReadBool(const Section, Ident: string; Default: Boolean): Boolean;
  114.     procedure WriteBool(const Section, Ident: string; Value: Boolean);
  115.     procedure ReadSection(const Section: string; Strings: TStrings);
  116.     procedure ReadSections(Strings: TStrings);
  117.     procedure ReadSectionValues(const Section: string; Strings: TStrings);
  118.     procedure EraseSection(const Section: string);
  119.     procedure DeleteKey(const Section, Ident: String);
  120.     property FileName: string read FFileName;
  121.   end;
  122.  
  123. implementation
  124.  
  125. uses Consts;
  126.  
  127. procedure ReadError(const Name: string);
  128. begin
  129.   raise ERegistryException.CreateFmt(SInvalidRegType, [Name]);
  130. end;
  131.  
  132. function IsRelative(const Value: string): Boolean;
  133. begin
  134.   Result := not ((Value <> '') and (Value[1] = '\'));
  135. end;
  136.  
  137. function DataTypeToRegData(Value: Integer): TRegDataType;
  138. begin
  139.   case Value of
  140.     REG_SZ       : Result := rdString;
  141.     REG_EXPAND_SZ: Result := rdExpandString;
  142.     REG_DWORD    : Result := rdInteger;
  143.     REG_BINARY   : Result := rdBinary;
  144.   else
  145.     Result := rdUnknown;
  146.   end;
  147. end;
  148.  
  149. constructor TRegistry.Create;
  150. begin
  151.   RootKey := HKEY_CURRENT_USER;
  152.   LazyWrite := True;
  153. end;
  154.  
  155. destructor TRegistry.Destroy;
  156. begin
  157.   CloseKey;
  158.   inherited;
  159. end;
  160.  
  161. procedure TRegistry.CloseKey;
  162. begin
  163.   if CurrentKey <> 0 then
  164.   begin
  165.     if LazyWrite then
  166.       RegCloseKey(CurrentKey) else
  167.       RegFlushKey(CurrentKey);
  168.     FCurrentKey := 0;
  169.     FCurrentPath := '';
  170.   end;
  171. end;
  172.  
  173. procedure TRegistry.SetRootKey(Value: HKEY);
  174. begin
  175.   if RootKey <> Value then
  176.   begin
  177.     if FCloseRootKey then
  178.     begin
  179.       RegCloseKey(RootKey);
  180.       FCloseRootKey := False;
  181.     end;
  182.     FRootKey := Value;
  183.     CloseKey;
  184.   end;
  185. end;
  186.  
  187. procedure TRegistry.ChangeKey(Value: HKey; const Path: string);
  188. begin
  189.   CloseKey;
  190.   FCurrentKey := Value;
  191.   FCurrentPath := Path;
  192. end;
  193.  
  194. function TRegistry.GetBaseKey(Relative: Boolean): HKey;
  195. begin
  196.   if (CurrentKey = 0) or not Relative then
  197.     Result := RootKey else
  198.     Result := CurrentKey;
  199. end;
  200.  
  201. procedure TRegistry.SetCurrentKey(Value: HKEY);
  202. begin
  203.   FCurrentKey := Value;
  204. end;
  205.  
  206. function TRegistry.CreateKey(const Key: string): Boolean;
  207. var
  208.   TempKey: HKey;
  209.   S: string;
  210.   Disposition: Integer;
  211.   Relative: Boolean;
  212. begin
  213.   TempKey := 0;
  214.   S := Key;
  215.   Relative := IsRelative(S);
  216.   if not Relative then Delete(S, 1, 1);
  217.   Result := RegCreateKeyEx(GetBaseKey(Relative), PChar(S), 0, nil,
  218.     REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, nil, TempKey, @Disposition) = ERROR_SUCCESS;
  219.   if Result then RegCloseKey(TempKey)
  220.   else raise ERegistryException.CreateFmt(SRegCreateFailed, [Key]);
  221. end;
  222.  
  223. function TRegistry.OpenKey(const Key: string; CanCreate: Boolean): Boolean;
  224. var
  225.   TempKey: HKey;
  226.   S: string;
  227.   Disposition: Integer;
  228.   Relative: Boolean;
  229.   ErrorCode: Integer;
  230. begin
  231.   S := Key;
  232.   Relative := IsRelative(S);
  233.   if not Relative then Delete(S, 1, 1);
  234.   TempKey := 0;
  235.   if not CanCreate or (S = '') then
  236.   begin
  237.     ErrorCode := RegOpenKeyEx(GetBaseKey(Relative), PChar(S), 0,
  238.       KEY_ALL_ACCESS, TempKey);
  239.     if ErrorCode <> ERROR_SUCCESS then
  240.       ErrorCode := RegOpenKeyEx(GetBaseKey(Relative), PChar(S), 0,
  241.       KEY_READ, TempKey);
  242.     Result := ErrorCode = ERROR_SUCCESS;
  243.   end else
  244.     Result := RegCreateKeyEx(GetBaseKey(Relative), PChar(S), 0, nil,
  245.       REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, nil, TempKey, @Disposition) = ERROR_SUCCESS;
  246.   if Result then
  247.   begin
  248.     if (CurrentKey <> 0) and Relative then S := CurrentPath + '\' + S;
  249.     ChangeKey(TempKey, S);
  250.   end;
  251. end;
  252.  
  253. function TRegistry.DeleteKey(const Key: string): Boolean;
  254. var
  255.   I, Len: Integer;
  256.   Relative: Boolean;
  257.   S, KeyName: string;
  258.   OldKey, DeleteKey: HKEY;
  259.   Info: TRegKeyInfo;
  260. begin
  261.   S := Key;
  262.   Relative := IsRelative(S);
  263.   if not Relative then Delete(S, 1, 1);
  264.   OldKey := CurrentKey;
  265.   DeleteKey := GetKey(Key);
  266.   if DeleteKey <> 0 then
  267.   try
  268.     SetCurrentKey(DeleteKey);
  269.     if GetKeyInfo(Info) then
  270.     begin
  271.       SetString(KeyName, nil, Info.MaxSubKeyLen + 1);
  272.       for I := 0 to Info.NumSubKeys - 1 do
  273.       begin
  274.         Len := Info.MaxSubKeyLen + 1;
  275.         if RegEnumKeyEx(DeleteKey, I, PChar(KeyName), Len, nil, nil, nil, nil) = ERROR_SUCCESS then
  276.           Self.DeleteKey(PChar(KeyName));
  277.       end;
  278.     end;
  279.   finally
  280.     SetCurrentKey(OldKey);
  281.     RegCloseKey(DeleteKey);
  282.   end;
  283.   Result := RegDeleteKey(GetBaseKey(Relative), PChar(S)) = ERROR_SUCCESS;
  284. end;
  285.  
  286. function TRegistry.DeleteValue(const Name: string): Boolean;
  287. begin
  288.   Result := RegDeleteValue(CurrentKey, PChar(Name)) = ERROR_SUCCESS;
  289. end;
  290.  
  291. function TRegistry.GetKeyInfo(var Value: TRegKeyInfo): Boolean;
  292. begin
  293.   FillChar(Value, SizeOf(TRegKeyInfo), 0);
  294.   Result := RegQueryInfoKey(CurrentKey, nil, nil, nil, @Value.NumSubKeys,
  295.     @Value.MaxSubKeyLen, nil, @Value.NumValues, @Value.MaxValueLen,
  296.     @Value.MaxDataLen, nil, @Value.FileTime) = ERROR_SUCCESS;
  297.   if SysLocale.FarEast and (Win32Platform = VER_PLATFORM_WIN32_NT) then
  298.     with Value do
  299.     begin
  300.       Inc(MaxSubKeyLen, MaxSubKeyLen);
  301.       Inc(MaxValueLen, MaxValueLen);
  302.     end;
  303. end;
  304.  
  305. procedure TRegistry.GetKeyNames(Strings: TStrings);
  306. var
  307.   I, Len: Integer;
  308.   Info: TRegKeyInfo;
  309.   S: string;
  310. begin
  311.   Strings.Clear;
  312.   if GetKeyInfo(Info) then
  313.   begin
  314.     SetString(S, nil, Info.MaxSubKeyLen + 1);
  315.     for I := 0 to Info.NumSubKeys - 1 do
  316.     begin
  317.       Len := Info.MaxSubKeyLen + 1;
  318.       RegEnumKeyEx(CurrentKey, I, PChar(S), Len, nil, nil, nil, nil);
  319.       Strings.Add(PChar(S));
  320.     end;
  321.   end;
  322. end;
  323.  
  324. procedure TRegistry.GetValueNames(Strings: TStrings);
  325. var
  326.   I, Len: Integer;
  327.   Info: TRegKeyInfo;
  328.   S: string;
  329. begin
  330.   Strings.Clear;
  331.   if GetKeyInfo(Info) then
  332.   begin
  333.     SetString(S, nil, Info.MaxValueLen + 1);
  334.     for I := 0 to Info.NumValues - 1 do
  335.     begin
  336.       Len := Info.MaxValueLen + 1;
  337.       RegEnumValue(CurrentKey, I, PChar(S), Len, nil, nil, nil, nil);
  338.       Strings.Add(PChar(S));
  339.     end;
  340.   end;
  341. end;
  342.  
  343. function TRegistry.GetDataInfo(const ValueName: string; var Value: TRegDataInfo): Boolean;
  344. var
  345.   DataType: Integer;
  346. begin
  347.   FillChar(Value, SizeOf(TRegDataInfo), 0);
  348.   Result := RegQueryValueEx(CurrentKey, PChar(ValueName), nil, @DataType, nil,
  349.     @Value.DataSize) = ERROR_SUCCESS;
  350.   Value.RegData := DataTypeToRegData(DataType);
  351. end;
  352.  
  353. function TRegistry.GetDataSize(const ValueName: string): Integer;
  354. var
  355.   Info: TRegDataInfo;
  356. begin
  357.   if GetDataInfo(ValueName, Info) then
  358.     Result := Info.DataSize else
  359.     Result := -1;
  360. end;
  361.  
  362. function TRegistry.GetDataType(const ValueName: string): TRegDataType;
  363. var
  364.   Info: TRegDataInfo;
  365. begin
  366.   if GetDataInfo(ValueName, Info) then
  367.     Result := Info.RegData else
  368.     Result := rdUnknown;
  369. end;
  370.  
  371. procedure TRegistry.WriteString(const Name, Value: string);
  372. begin
  373.   PutData(Name, PChar(Value), Length(Value)+1, rdString);
  374. end;
  375.  
  376. procedure TRegistry.WriteExpandString(const Name, Value: string);
  377. begin
  378.   PutData(Name, PChar(Value), Length(Value)+1, rdExpandString);
  379. end;
  380.  
  381. function TRegistry.ReadString(const Name: string): string;
  382. var
  383.   Len: Integer;
  384.   RegData: TRegDataType;
  385. begin
  386.   Len := GetDataSize(Name);
  387.   if Len > 0 then
  388.   begin
  389.     SetString(Result, nil, Len);
  390.     GetData(Name, PChar(Result), Len, RegData);
  391.     if (RegData = rdString) or (RegData = rdExpandString) then
  392.       SetLength(Result, StrLen(PChar(Result)))
  393.     else ReadError(Name);
  394.   end
  395.   else Result := '';
  396. end;
  397.  
  398. procedure TRegistry.WriteInteger(const Name: string; Value: Integer);
  399. begin
  400.   PutData(Name, @Value, SizeOf(Integer), rdInteger);
  401. end;
  402.  
  403. function TRegistry.ReadInteger(const Name: string): Integer;
  404. var
  405.   RegData: TRegDataType;
  406. begin
  407.   GetData(Name, @Result, SizeOf(Integer), RegData);
  408.   if RegData <> rdInteger then ReadError(Name);
  409. end;
  410.  
  411. procedure TRegistry.WriteBool(const Name: string; Value: Boolean);
  412. begin
  413.   WriteInteger(Name, Ord(Value));
  414. end;
  415.  
  416. function TRegistry.ReadBool(const Name: string): Boolean;
  417. begin
  418.   Result := ReadInteger(Name) <> 0;
  419. end;
  420.  
  421. procedure TRegistry.WriteFloat(const Name: string; Value: Double);
  422. begin
  423.   PutData(Name, @Value, SizeOf(Double), rdBinary);
  424. end;
  425.  
  426. function TRegistry.ReadFloat(const Name: string): Double;
  427. var
  428.   Len: Integer;
  429.   RegData: TRegDataType;
  430. begin
  431.   Len := GetData(Name, @Result, SizeOf(Double), RegData);
  432.   if (RegData <> rdBinary) or (Len <> SizeOf(Double)) then
  433.     ReadError(Name);
  434. end;
  435.  
  436. procedure TRegistry.WriteCurrency(const Name: string; Value: Currency);
  437. begin
  438.   PutData(Name, @Value, SizeOf(Currency), rdBinary);
  439. end;
  440.  
  441. function TRegistry.ReadCurrency(const Name: string): Currency;
  442. var
  443.   Len: Integer;
  444.   RegData: TRegDataType;
  445. begin
  446.   Len := GetData(Name, @Result, SizeOf(Currency), RegData);
  447.   if (RegData <> rdBinary) or (Len <> SizeOf(Currency)) then
  448.     ReadError(Name);
  449. end;
  450.  
  451. procedure TRegistry.WriteDateTime(const Name: string; Value: TDateTime);
  452. begin
  453.   PutData(Name, @Value, SizeOf(TDateTime), rdBinary);
  454. end;
  455.  
  456. function TRegistry.ReadDateTime(const Name: string): TDateTime;
  457. var
  458.   Len: Integer;
  459.   RegData: TRegDataType;
  460. begin
  461.   Len := GetData(Name, @Result, SizeOf(TDateTime), RegData);
  462.   if (RegData <> rdBinary) or (Len <> SizeOf(TDateTime)) then
  463.     ReadError(Name);
  464. end;
  465.  
  466. procedure TRegistry.WriteDate(const Name: string; Value: TDateTime);
  467. begin
  468.   WriteDateTime(Name, Value);
  469. end;
  470.  
  471. function TRegistry.ReadDate(const Name: string): TDateTime;
  472. begin
  473.   Result := ReadDateTime(Name);
  474. end;
  475.  
  476. procedure TRegistry.WriteTime(const Name: string; Value: TDateTime);
  477. begin
  478.   WriteDateTime(Name, Value);
  479. end;
  480.  
  481. function TRegistry.ReadTime(const Name: string): TDateTime;
  482. begin
  483.   Result := ReadDateTime(Name);
  484. end;
  485.  
  486. procedure TRegistry.WriteBinaryData(const Name: string; var Buffer; BufSize: Integer);
  487. begin
  488.   PutData(Name, @Buffer, BufSize, rdBinary);
  489. end;
  490.  
  491. function TRegistry.ReadBinaryData(const Name: string; var Buffer; BufSize: Integer): Integer;
  492. var
  493.   RegData: TRegDataType;
  494.   Info: TRegDataInfo;
  495. begin
  496.   if GetDataInfo(Name, Info) then
  497.   begin
  498.     Result := Info.DataSize;
  499.     RegData := Info.RegData;
  500.     if (RegData = rdBinary) and (Result <= BufSize) then
  501.       GetData(Name, @Buffer, Result, RegData)
  502.     else ReadError(Name);
  503.   end else
  504.     Result := 0;
  505. end;
  506.  
  507. procedure TRegistry.PutData(const Name: string; Buffer: Pointer;
  508.   BufSize: Integer; RegData: TRegDataType);
  509.  
  510.   procedure Error;
  511.   begin
  512.     raise ERegistryException.CreateFmt(SRegSetDataFailed, [Name]);
  513.   end;
  514.  
  515. const
  516.   RegDataToDataType: array [TRegDataType] of Integer =
  517.     (REG_NONE, REG_SZ, REG_EXPAND_SZ, REG_DWORD, REG_BINARY);
  518.  
  519. begin
  520.   if RegSetValueEx(CurrentKey, PChar(Name), 0, RegDataToDataType[RegData],
  521.     Buffer, BufSize) <> ERROR_SUCCESS then  Error;
  522. end;
  523.  
  524. function TRegistry.GetData(const Name: string; Buffer: Pointer;
  525.   BufSize: Integer; var RegData: TRegDataType): Integer;
  526.  
  527.   procedure Error;
  528.   begin
  529.     raise ERegistryException.CreateFmt(SRegGetDataFailed, [Name]);
  530.   end;
  531.  
  532. var
  533.   DataType: Integer;
  534. begin
  535.   DataType := REG_NONE;
  536.   if RegQueryValueEx(CurrentKey, PChar(Name), nil, @DataType, PByte(Buffer),
  537.     @BufSize) <> ERROR_SUCCESS then Error;
  538.   RegData := DataTypeToRegData(DataType);
  539.   Result := BufSize;
  540. end;
  541.  
  542. function TRegistry.HasSubKeys: Boolean;
  543. var
  544.   Info: TRegKeyInfo;
  545. begin
  546.   Result := GetKeyInfo(Info) and (Info.NumSubKeys > 0);
  547. end;
  548.  
  549. function TRegistry.ValueExists(const Name: string): Boolean;
  550. var
  551.   Info: TRegDataInfo;
  552. begin
  553.   Result := GetDataInfo(Name, Info);
  554. end;
  555.  
  556. function TRegistry.GetKey(const Key: string): HKEY;
  557. var
  558.   S: string;
  559.   Relative: Boolean;
  560. begin
  561.   S := Key;
  562.   Relative := IsRelative(S);
  563.   if not Relative then Delete(S, 1, 1);
  564.   Result := 0;
  565.   if RegOpenKeyEx(GetBaseKey(Relative), PChar(S), 0,
  566.     KEY_ALL_ACCESS, Result) <> ERROR_SUCCESS then
  567.     RegOpenKeyEx(GetBaseKey(Relative), PChar(S), 0, KEY_READ, Result);
  568. end;
  569.  
  570. function TRegistry.RegistryConnect(const UNCName: string): Boolean;
  571. var
  572.   TempKey: HKEY;
  573. begin
  574.   Result := RegConnectRegistry(PChar(UNCname), RootKey, TempKey) = ERROR_SUCCESS;
  575.   if Result then
  576.   begin
  577.     RootKey := TempKey;
  578.     FCloseRootKey := True;
  579.   end;
  580. end;
  581.  
  582. function TRegistry.LoadKey(const Key, FileName: string): Boolean;
  583. var
  584.   S: string;
  585. begin
  586.   S := Key;
  587.   if not IsRelative(S) then Delete(S, 1, 1);
  588.   Result := RegLoadKey(RootKey, PChar(S), PChar(FileName)) = ERROR_SUCCESS;
  589. end;
  590.  
  591. function TRegistry.UnLoadKey(const Key: string): Boolean;
  592. var
  593.   S: string;
  594. begin
  595.   S := Key;
  596.   if not IsRelative(S) then Delete(S, 1, 1);
  597.   Result := RegUnLoadKey(RootKey, PChar(S)) = ERROR_SUCCESS;
  598. end;
  599.  
  600. function TRegistry.RestoreKey(const Key, FileName: string): Boolean;
  601. var
  602.   RestoreKey: HKEY;
  603. begin
  604.   Result := False;
  605.   RestoreKey := GetKey(Key);
  606.   if RestoreKey <> 0 then
  607.   try
  608.     Result := RegRestoreKey(RestoreKey, PChar(FileName), 0) = ERROR_SUCCESS;
  609.   finally
  610.     RegCloseKey(RestoreKey);
  611.   end;
  612. end;
  613.  
  614. function TRegistry.ReplaceKey(const Key, FileName, BackUpFileName: string): Boolean;
  615. var
  616.   S: string;
  617.   Relative: Boolean;
  618. begin
  619.   S := Key;
  620.   Relative := IsRelative(S);
  621.   if not Relative then Delete(S, 1, 1);
  622.   Result := RegReplaceKey(GetBaseKey(Relative), PChar(S),
  623.     PChar(FileName), PChar(BackUpFileName)) = ERROR_SUCCESS;
  624. end;
  625.  
  626. function TRegistry.SaveKey(const Key, FileName: string): Boolean;
  627. var
  628.   SaveKey: HKEY;
  629. begin
  630.   Result := False;
  631.   SaveKey := GetKey(Key);
  632.   if SaveKey <> 0 then
  633.   try
  634.     Result := RegSaveKey(SaveKey, PChar(FileName), nil) = ERROR_SUCCESS;
  635.   finally
  636.     RegCloseKey(SaveKey);
  637.   end;
  638. end;
  639.  
  640. function TRegistry.KeyExists(const Key: string): Boolean;
  641. var
  642.   TempKey: HKEY;
  643. begin
  644.   TempKey := GetKey(Key);
  645.   if TempKey <> 0 then RegCloseKey(TempKey);
  646.   Result := TempKey <> 0;
  647. end;
  648.  
  649. procedure TRegistry.RenameValue(const OldName, NewName: string);
  650. var
  651.   Len: Integer;
  652.   RegData: TRegDataType;
  653.   Buffer: PChar;
  654. begin
  655.   if ValueExists(OldName) and not ValueExists(NewName) then
  656.   begin
  657.     Len := GetDataSize(OldName);
  658.     if Len > 0 then
  659.     begin
  660.       Buffer := AllocMem(Len);
  661.       try
  662.         Len := GetData(OldName, Buffer, Len, RegData);
  663.         DeleteValue(OldName);
  664.         PutData(NewName, Buffer, Len, RegData);
  665.       finally
  666.         FreeMem(Buffer);
  667.       end;
  668.     end;
  669.   end;
  670. end;
  671.  
  672. procedure TRegistry.MoveKey(const OldName, NewName: string; Delete: Boolean);
  673. var
  674.   SrcKey, DestKey: HKEY;
  675.  
  676.   procedure MoveValue(SrcKey, DestKey: HKEY; const Name: string);
  677.   var
  678.     Len: Integer;
  679.     OldKey, PrevKey: HKEY;
  680.     Buffer: PChar;
  681.     RegData: TRegDataType;
  682.   begin
  683.     OldKey := CurrentKey;
  684.     SetCurrentKey(SrcKey);
  685.     try
  686.       Len := GetDataSize(Name);
  687.       if Len > 0 then
  688.       begin
  689.         Buffer := AllocMem(Len);
  690.         try
  691.           Len := GetData(Name, Buffer, Len, RegData);
  692.           PrevKey := CurrentKey;
  693.           SetCurrentKey(DestKey);
  694.           try
  695.             PutData(Name, Buffer, Len, RegData);
  696.           finally
  697.             SetCurrentKey(PrevKey);
  698.           end;
  699.         finally
  700.           FreeMem(Buffer);
  701.         end;
  702.       end;
  703.     finally
  704.       SetCurrentKey(OldKey);
  705.     end;
  706.   end;
  707.  
  708.   procedure CopyValues(SrcKey, DestKey: HKEY);
  709.   var
  710.     I, Len: Integer;
  711.     KeyInfo: TRegKeyInfo;
  712.     S: string;
  713.     OldKey: HKEY;
  714.   begin
  715.     OldKey := CurrentKey;
  716.     SetCurrentKey(SrcKey);
  717.     try
  718.       if GetKeyInfo(KeyInfo) then
  719.       begin
  720.         MoveValue(SrcKey, DestKey, '');
  721.         SetString(S, nil, KeyInfo.MaxValueLen + 1);
  722.         for I := 0 to KeyInfo.NumValues - 1 do
  723.         begin
  724.           Len := KeyInfo.MaxValueLen + 1;
  725.           if RegEnumValue(SrcKey, I, PChar(S), Len, nil, nil, nil, nil) = ERROR_SUCCESS then
  726.             MoveValue(SrcKey, DestKey, PChar(S));
  727.         end;
  728.       end;
  729.     finally
  730.       SetCurrentKey(OldKey);
  731.     end;
  732.   end;
  733.  
  734.   procedure CopyKeys(SrcKey, DestKey: HKEY);
  735.   var
  736.     I, Len: Integer;
  737.     Info: TRegKeyInfo;
  738.     S: string;
  739.     OldKey, PrevKey, NewSrc, NewDest: HKEY;
  740.   begin
  741.     OldKey := CurrentKey;
  742.     SetCurrentKey(SrcKey);
  743.     try
  744.       if GetKeyInfo(Info) then
  745.       begin
  746.         SetString(S, nil, Info.MaxSubKeyLen + 1);
  747.         for I := 0 to Info.NumSubKeys - 1 do
  748.         begin
  749.           Len := Info.MaxSubKeyLen + 1;
  750.           if RegEnumKeyEx(SrcKey, I, PChar(S), Len, nil, nil, nil, nil) = ERROR_SUCCESS then
  751.           begin
  752.             NewSrc := GetKey(PChar(S));
  753.             if NewSrc <> 0 then
  754.             try
  755.               PrevKey := CurrentKey;
  756.               SetCurrentKey(DestKey);
  757.               try
  758.                 CreateKey(PChar(S));
  759.                 NewDest := GetKey(PChar(S));
  760.                 try
  761.                   CopyValues(NewSrc, NewDest);
  762.                   CopyKeys(NewSrc, NewDest);
  763.                 finally
  764.                   RegCloseKey(NewDest);
  765.                 end;
  766.               finally
  767.                 SetCurrentKey(PrevKey);
  768.               end;
  769.             finally
  770.               RegCloseKey(NewSrc);
  771.             end;
  772.           end;
  773.         end;
  774.       end;
  775.     finally
  776.       SetCurrentKey(OldKey);
  777.     end;
  778.   end;
  779.  
  780. begin
  781.   if KeyExists(OldName) and not KeyExists(NewName) then
  782.   begin
  783.     SrcKey := GetKey(OldName);
  784.     if SrcKey <> 0 then
  785.     try
  786.       CreateKey(NewName);
  787.       DestKey := GetKey(NewName);
  788.       if DestKey <> 0 then
  789.       try
  790.         CopyValues(SrcKey, DestKey);
  791.         CopyKeys(SrcKey, DestKey);
  792.         if Delete then DeleteKey(OldName);
  793.       finally
  794.         RegCloseKey(DestKey);
  795.       end;
  796.     finally
  797.       RegCloseKey(SrcKey);
  798.     end;
  799.   end;
  800. end;
  801.  
  802. constructor TRegIniFile.Create(const FileName: string);
  803. begin
  804.   inherited Create;
  805.   FFileName := FileName;
  806.   OpenKey(FileName, True);
  807. end;
  808.  
  809. function TRegIniFile.ReadString(const Section, Ident, Default: string): string;
  810. var
  811.   Key, OldKey: HKEY;
  812. begin
  813.   Key := GetKey(Section);
  814.   if Key <> 0 then
  815.   try
  816.     OldKey := CurrentKey;
  817.     SetCurrentKey(Key);
  818.     try
  819.       if ValueExists(Ident) then
  820.         Result := inherited ReadString(Ident) else
  821.         Result := Default;
  822.     finally
  823.       SetCurrentKey(OldKey);
  824.     end;
  825.   finally
  826.     RegCloseKey(Key);
  827.   end
  828.   else Result := Default;
  829. end;
  830.  
  831. procedure TRegIniFile.WriteString(const Section, Ident, Value: String);
  832. var
  833.   Key, OldKey: HKEY;
  834. begin
  835.   CreateKey(Section);
  836.   Key := GetKey(Section);
  837.   if Key <> 0 then
  838.   try
  839.     OldKey := CurrentKey;
  840.     SetCurrentKey(Key);
  841.     try
  842.       inherited WriteString(Ident, Value);
  843.     finally
  844.       SetCurrentKey(OldKey);
  845.     end;
  846.   finally
  847.     RegCloseKey(Key);
  848.   end;
  849. end;
  850.  
  851. function TRegIniFile.ReadInteger(const Section, Ident: string; Default: LongInt): LongInt;
  852. var
  853.   Key, OldKey: HKEY;
  854.   S: string;
  855. begin
  856.   Key := GetKey(Section);
  857.   if Key <> 0 then
  858.   try
  859.     OldKey := CurrentKey;
  860.     SetCurrentKey(Key);
  861.     try
  862.       if ValueExists(Ident) then
  863.       begin
  864.         S := inherited ReadString(Ident);
  865.         if (Length(S) > 2) and (S[1] = '0') and (UpCase(S[2]) = 'X') then
  866.           S := '$' + Copy(S, 3, Maxint);
  867.         Result := StrToIntDef(S, Default);
  868.       end else
  869.         Result := Default;
  870.     finally
  871.       SetCurrentKey(OldKey);
  872.     end;
  873.   finally
  874.     RegCloseKey(Key);
  875.   end
  876.   else Result := Default;
  877. end;
  878.  
  879. procedure TRegIniFile.WriteInteger(const Section, Ident: string; Value: LongInt);
  880. var
  881.   Key, OldKey: HKEY;
  882. begin
  883.   CreateKey(Section);
  884.   Key := GetKey(Section);
  885.   if Key <> 0 then
  886.   try
  887.     OldKey := CurrentKey;
  888.     SetCurrentKey(Key);
  889.     try
  890.       inherited WriteString(Ident, IntToStr(Value));
  891.     finally
  892.       SetCurrentKey(OldKey);
  893.     end;
  894.   finally
  895.     RegCloseKey(Key);
  896.   end;
  897. end;
  898.  
  899. function TRegIniFile.ReadBool(const Section, Ident: string; Default: Boolean): Boolean;
  900. begin
  901.   Result := ReadInteger(Section, Ident, Ord(Default)) <> 0;
  902. end;
  903.  
  904. procedure TRegIniFile.WriteBool(const Section, Ident: string; Value: Boolean);
  905. const
  906.   Values: array[Boolean] of string = ('0', '1');
  907. var
  908.   Key, OldKey: HKEY;
  909. begin
  910.   CreateKey(Section);
  911.   Key := GetKey(Section);
  912.   if Key <> 0 then
  913.   try
  914.     OldKey := CurrentKey;
  915.     SetCurrentKey(Key);
  916.     try
  917.       inherited WriteString(Ident, Values[Value]);
  918.     finally
  919.       SetCurrentKey(OldKey);
  920.     end;
  921.   finally
  922.     RegCloseKey(Key);
  923.   end;
  924. end;
  925.  
  926. procedure TRegIniFile.ReadSection(const Section: string; Strings: TStrings);
  927. var
  928.   Key, OldKey: HKEY;
  929. begin
  930.   Key := GetKey(Section);
  931.   if Key <> 0 then
  932.   try
  933.     OldKey := CurrentKey;
  934.     SetCurrentKey(Key);
  935.     try
  936.       inherited GetValueNames(Strings);
  937.     finally
  938.       SetCurrentKey(OldKey);
  939.     end;
  940.   finally
  941.     RegCloseKey(Key);
  942.   end;
  943. end;
  944.  
  945. procedure TRegIniFile.ReadSections(Strings: TStrings);
  946. begin
  947.   GetKeyNames(Strings);
  948. end;
  949.  
  950. procedure TRegIniFile.ReadSectionValues(const Section: string; Strings: TStrings);
  951. var
  952.   KeyList: TStringList;
  953.   I: Integer;
  954. begin
  955.   KeyList := TStringList.Create;
  956.   try
  957.     ReadSection(Section, KeyList);
  958.     Strings.BeginUpdate;
  959.     try
  960.       for I := 0 to KeyList.Count - 1 do
  961.         Strings.Values[KeyList[I]] := ReadString(Section, KeyList[I], '');
  962.     finally
  963.       Strings.EndUpdate;
  964.     end;
  965.   finally
  966.     KeyList.Free;
  967.   end;
  968. end;
  969.  
  970. procedure TRegIniFile.EraseSection(const Section: string);
  971. begin
  972.   inherited DeleteKey(Section);
  973. end;
  974.  
  975. procedure TRegIniFile.DeleteKey(const Section, Ident: String);
  976. var
  977.   Key, OldKey: HKEY;
  978. begin
  979.   Key := GetKey(Section);
  980.   if Key <> 0 then
  981.   try
  982.     OldKey := CurrentKey;
  983.     SetCurrentKey(Key);
  984.     try
  985.       inherited DeleteValue(Ident);
  986.     finally
  987.       SetCurrentKey(OldKey);
  988.     end;    
  989.   finally
  990.     RegCloseKey(Key);
  991.   end;
  992. end;
  993.  
  994. end.
  995.  
  996.  
  997.