home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 October / Chip_2001-10_cd1.bin / zkuste / delphi / kolekce / d456 / DCSLIB25.ZIP / DCIniStream.pas < prev    next >
Pascal/Delphi Source File  |  2001-01-20  |  35KB  |  1,312 lines

  1. unit DCIniStream;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Classes, SysUtils, DCRecordStream;
  7.  
  8. resourcestring 
  9.   RES_IKEY_ERR_INVALIDKEY = '═σΩε≡≡σΩ≥φ√Θ ≥Φ∩ Σδ  ''%s''';
  10.   RES_IKEY_ERR_DUPNAME    = '╨ατΣσδ ''%s'' ≤µσ ±≤∙σ±≥Γ≤σ≥. ┬√ßσ≡Φ≥σ Σ≡≤πεσ Φ∞ ';
  11.  
  12. const
  13.   HashTableSize     = 64;
  14.  
  15.   INIKEY_ROOT_NAME  = 'HIKSV';
  16.  
  17.   // Roots HashCodes
  18.   INIKEY_LOCAL_MACHINE = $1;
  19.   INIKEY_USERS         = $2;
  20.  
  21.   INIKEY_FLAG_READONLY = $01;
  22.   INIKEY_FLAG_NOTVALUE = $02;
  23.   INIKEY_FLAG_NOTSKEYS = $04;
  24.  
  25.   INIDAT_HEADER_SIZE   = $08;   // 8 Byte
  26.  
  27.   INIDAT_FLAG_READONLY = $01;
  28.   INIDAT_FLAG_NOTEDIT  = $02;
  29.   INIDAT_FLAG_DEFAULT  = $04;
  30.   INIDAT_FLAG_EMPTY    = $08;
  31.  
  32.   SystemIniKeyNames: array[$1..$2] of string = (
  33.     'INIKEY_LOCAL_MACHINE',
  34.     'INIKEY_USERS');
  35.  
  36. type
  37.   HIniRootKey     = 0..HashTableSize-1;
  38.   HIniKey         = Longint;
  39.  
  40.   TKeyName        = string[40];
  41.   THashTableType  = array[0..HashTableSize-1] of HIniKey;
  42.   TIniDataType    = (idUnknown, idString, idInteger, idBinary);
  43.  
  44.   PIniKeyType_tag = ^TIniKeyType;
  45.   TIniKeyType = packed record
  46.     Flags     : WORD;           // 02
  47.     Name      : TKeyName;       // 40
  48.     ParentKey : Longint;        // 04
  49.     HashCode  : WORD;           // 02
  50.     HashNext  : Longint;        // 04
  51.     HashPrev  : Longint;        // 04
  52.     HashTable : THashTableType; // 04*64(HashTableSize)
  53.     Data      : Longint;        // 04
  54.     NumSubKeys: WORD;           // 02
  55.     NumValues : WORD;           // 02
  56.   end;
  57.  
  58.   PIniKeyData_tag = ^TIniKeyDataType;
  59.   TIniKeyDataType = packed record
  60.     Flags     : WORD;           // 02
  61.     DataType  : SmallInt;       // 02
  62.     NameLen   : WORD;           // 02
  63.     DataLen   : WORD;           // 02
  64.     NameValue : PChar;          // 01
  65.     DataValue : Pointer;        // 01
  66.   end;
  67.  
  68.   EIniKeyException = class(Exception);
  69.  
  70.   TValueList = class(TStringList)
  71.   private
  72.     FBuffer: Pointer;
  73.     FFlags: WORD;
  74.     function GetKeyValue(Index: Integer): PIniKeyData_tag;
  75.     procedure SetKeyValue(Index: Integer; const Value: PIniKeyData_tag);
  76.     function GetDataSize: Integer;
  77.     procedure DestroyValue(pValue: PIniKeyData_tag);
  78.   protected
  79.     procedure PutData(const Name: string; Buffer: Pointer; ASize: Integer;
  80.       AType: TIniDataType);
  81.     function GetData(const Name: string; var Buffer: Pointer; var AType: TIniDataType): Integer;
  82.   public
  83.     constructor Create;
  84.     procedure Delete(Index: Integer); override;
  85.     procedure LoadValues(ABuffer: Pointer; ADataSize: Integer);
  86.     function GetBuffer(var ABuffer: Pointer): Integer;
  87.     procedure Clear; override;
  88.     function DeleteValue(const Name: string): boolean;
  89.     function RenameValue(const OldName, NewName: string): DWORD;
  90.     function ReadCurrency(const Name: string): Currency;
  91.     function ReadBinaryData(const Name: string; var Buffer; ASize: Integer): Integer;
  92.     function ReadBool(const Name: string): Boolean;
  93.     function ReadDateTime(const Name: string): TDateTime;
  94.     function ReadFloat(const Name: string): Double;
  95.     function ReadInteger(const Name: string): Longint;
  96.     function ReadString(const Name: string): string;
  97.     function ReadTime(const Name: string): TDateTime;
  98.     procedure WriteCurrency(const Name: string; Value: Currency);
  99.     procedure WriteBinaryData(const Name: string; var Buffer; ASize: Integer);
  100.     procedure WriteBool(const Name: string; Value: Boolean);
  101.     procedure WriteDate(const Name: string; Value: TDateTime);
  102.     procedure WriteDateTime(const Name: string; Value: TDateTime);
  103.     procedure WriteFloat(const Name: string; Value: Double);
  104.     procedure WriteInteger(const Name: string; Value: Longint);
  105.     procedure WriteString(const Name, Value: string);
  106.     procedure WriteTime(const Name: string; Value: TDateTime);
  107.     property KeyValue[Index: Integer]: PIniKeyData_tag read GetKeyValue write SetKeyValue;
  108.     property Buffer: Pointer read FBuffer write FBuffer;
  109.     property DataSize: Integer read GetDataSize;
  110.     property Flags: WORD read FFlags write FFlags;
  111.   end;
  112.  
  113.   TIniKeyStream = class(TRecordStream)
  114.   private
  115.     FRootKey: HIniRootKey;
  116.     FValues: TValueList;
  117.     FCurrentKey: HIniKey;
  118.     FCurrentPath: string;
  119.     procedure SetRootKey(const Value: HIniRootKey);
  120.     function ClearKey(var AKey: TIniKeyType; AName: TKeyName = ''): PIniKeyType_tag;
  121.     function GetBaseKey(Relative: Boolean): HIniKey;
  122.     procedure CreateSystemKeys(var RootKey: TIniKeyType);
  123.     function CreateDefaultValue: HIniKey;
  124.   protected
  125.     procedure GetRootData(AData: Pointer); override;
  126.     function CreateKeyEx(hKey: HIniKey; AKey: string; var hResult: HIniKey): DWORD;
  127.     function DeleteKeyEx(hKey: HIniKey; AKey: string = ''): DWORD;
  128.     function OpenKeyEx(hKey: HIniKey; AKey: string; var hResult: HIniKey): DWORD;
  129.     function GetKeyValuesEx(hKey: HIniKey; ValueList: TValueList): Integer;
  130.     procedure CloseKeyEx(hKey: HIniKey; ValueList: TValueList);
  131.     function Append(AData: Pointer): Integer;
  132.     procedure WriteData(AData: TIniKeyType);
  133.     procedure ReadData(var AData: PIniKeyType_tag);
  134.     procedure ChangeKey(Value: HIniKey; const Path: string);
  135.     function GetFlagsBit(AKeyInfo: TIniKeyType; AOffset: Byte): boolean;
  136.     procedure SetFlagsBit(var AKeyInfo: TIniKeyType; AOffset: Byte;
  137.       Value: Boolean);
  138.     procedure LoadValuesEx;
  139.   public
  140.     constructor Create(AName: string);
  141.     destructor Destroy; override;
  142.     procedure CloseKey;
  143.     function CreateKey(const Key: String): Boolean;
  144.     function DeleteKey(const Key: string): Boolean;
  145.     function OpenKey(const Key: String; CanCreate: Boolean): Boolean;
  146.     function GetKeyInfo(var AKeyInfo: PIniKeyType_tag): boolean;
  147.     procedure RenameValue(const OldName, NewName: string);
  148.     function ReadCurrency(const Name: string): Currency;
  149.     function ReadBinaryData(const Name: string; var Buffer; ASize: Integer): Integer;
  150.     function ReadBool(const Name: string): Boolean;
  151.     function ReadDateTime(const Name: string): TDateTime;
  152.     function ReadFloat(const Name: string): Double;
  153.     function ReadInteger(const Name: string): Longint;
  154.     function ReadString(const Name: string): string;
  155.     function ReadTime(const Name: string): TDateTime;
  156.     procedure WriteCurrency(const Name: string; Value: Currency);
  157.     procedure WriteBinaryData(const Name: string; var Buffer; ASize: Integer);
  158.     procedure WriteBool(const Name: string; Value: Boolean);
  159.     procedure WriteDate(const Name: string; Value: TDateTime);
  160.     procedure WriteDateTime(const Name: string; Value: TDateTime);
  161.     procedure WriteFloat(const Name: string; Value: Double);
  162.     procedure WriteInteger(const Name: string; Value: Longint);
  163.     procedure WriteString(const Name, Value: string);
  164.     procedure WriteTime(const Name: string; Value: TDateTime);
  165.     function GetDataInfo(const ValueName: string; var Value: TIniDataType): boolean;
  166.     function GetDataSize(const ValueName: string): integer;
  167.     procedure GetKeyNames(Strings: TStrings; AKey: boolean = False);
  168.     procedure GetValueNames(Strings: TStrings);
  169.     function RestoreKey(const Key, FileName: string): boolean;
  170.     function SaveKey(const Key, FileName: string): boolean;
  171.     property CurrentKey: HIniKey read FCurrentKey;
  172.     property CurrentPath: string read FCurrentPath;
  173.     property RootKey: HIniRootKey read FRootKey write SetRootKey;
  174.   end;
  175.  
  176.   TRegKeyFile = class(TIniKeyStream)
  177.   end;
  178.  
  179. function GetHashCode(Value: PChar; HashTableSize: Byte): Byte;
  180.  
  181. implementation
  182.  
  183. procedure ReadError(const Name: string);
  184. begin
  185.   raise EIniKeyException.CreateFmt(RES_IKEY_ERR_INVALIDKEY, [Name]);
  186. end;
  187.  
  188. function IsRelative(const Value: string; var AValue: string): Boolean;
  189. begin
  190.   AValue := Value;
  191.   Result := not ((Value <> '') and (Value[1] = '\'));
  192.   if not Result then System.Delete(AValue, 1, 1);
  193. end;
  194.  
  195. function GetSubKey(var Value: string): string;
  196.  var
  197.   nPos: Integer;
  198. begin
  199.   nPos   := Pos('\', Value);
  200.   if nPos <> 0 then
  201.   begin
  202.     Result := Copy(Value, 1, nPos-1);
  203.     Value  := Copy(Value, nPos+1, Length(Value)-nPos);
  204.   end
  205.   else begin
  206.     Result := Value;
  207.     Value  := '';
  208.   end;
  209. end;
  210.  
  211. function GetHashCode(Value: PChar; HashTableSize: Byte): Byte;
  212.  var
  213.   CharSum: longint;
  214. begin
  215.   CharSum := 0;
  216.   while Value^ <> #0 do
  217.   begin
  218.     CharSum := CharSum + Byte(Value^);
  219.     Inc(Value);
  220.   end;
  221.   Result := CharSum mod HashTableSize;
  222. end;
  223.  
  224. { TRecordStream }
  225.  
  226. function TIniKeyStream.Append(AData: Pointer): Integer;
  227. begin
  228.   Result := inherited Append(AData, SizeOf(TIniKeyType));
  229. end;
  230.  
  231. procedure TIniKeyStream.ChangeKey(Value: HIniKey; const Path: string);
  232. begin
  233.   CloseKey;
  234.   FCurrentKey := Value;
  235.   FCurrentPath := Path;
  236. end;
  237.  
  238. function TIniKeyStream.ClearKey(var AKey: TIniKeyType; AName: TKeyName): PIniKeyType_tag;
  239. begin
  240.   FillChar(AKey, SizeOf(TIniKeyType), 0);
  241.   if AName <> '' then AKey.Name := AName;
  242.   Result := @AKey;
  243. end;
  244.  
  245. procedure TIniKeyStream.CloseKey;
  246. begin
  247.   if CurrentKey <> 0 then
  248.   begin
  249.     CloseKeyEx(FCurrentKey, FValues);
  250.     FCurrentKey  := 0;
  251.     FCurrentPath := '';
  252.   end;
  253. end;
  254.  
  255. procedure TIniKeyStream.CloseKeyEx(hKey: HIniKey; ValueList: TValueList);
  256.  var
  257.   pKeyInfo: PIniKeyType_tag;
  258.   Buffer: Pointer;
  259.   DataSize: Integer;
  260. begin
  261.   {±ε⌡≡αφσφΦσ Σαφφ√⌡ Ωδ■≈α}
  262.   GetMem(pKeyInfo, SizeOf(TIniKeyType));
  263.   try
  264.    LockRecord(0);
  265.    RecNo := hKey;
  266.    GetKeyInfo(pKeyInfo);
  267.    with pKeyInfo^ do
  268.    begin
  269.      NumValues := ValueList.Count;
  270.      WriteData(pKeyInfo^);
  271.      DataSize  := ValueList.GetBuffer(Buffer);
  272.      RecNo     := Data;
  273.      inherited WriteData(Buffer, DataSize);
  274.    end;
  275.    if DataSize > 0 then FreeMem(Buffer, DataSize);
  276.    ValueList.Clear;
  277.   finally
  278.     FreeMem(pKeyInfo);
  279.     UnlockRecord(0);
  280.   end;
  281. end;
  282.  
  283. constructor TIniKeyStream.Create(AName: string);
  284. begin
  285.   inherited Create(Format('%s.key',[AName]), SizeOf(TIniKeyType));
  286.   FRootKey := INIKEY_LOCAL_MACHINE;
  287.   FValues  := TValueList.Create;
  288. end;
  289.  
  290. function TIniKeyStream.CreateDefaultValue: HIniKey;
  291.  var
  292.   Buffer: Pointer;
  293.   DataSize: Integer;
  294.   ValueList: TValueList;
  295. begin
  296.   ValueList := TValueList.Create;
  297.   try
  298.     ValueList.Flags := INIDAT_FLAG_READONLY or INIDAT_FLAG_DEFAULT or INIDAT_FLAG_EMPTY;
  299.     ValueList.WriteString('', '');
  300.     DataSize := ValueList.GetBuffer(Buffer);
  301.   finally
  302.     ValueList.Free;
  303.   end;
  304.   if DataSize > 0 then
  305.     Result := inherited Append(Buffer, DataSize)
  306.   else
  307.     Result := 0;
  308.     
  309.   if DataSize > 0 then FreeMem(Buffer, DataSize);
  310. end;
  311.  
  312. function TIniKeyStream.CreateKey(const Key: String): Boolean;
  313.  var
  314.   TempKey: HIniKey;
  315.   S: string;
  316.   Relative: boolean;
  317. begin
  318.   Relative := IsRelative(Key, S);
  319.   Result   := CreateKeyEx(GetBaseKey(Relative), Key, TempKey) = ERROR_SUCCESS;
  320. end;
  321.  
  322. function TIniKeyStream.CreateKeyEx(hKey: HIniKey; AKey: string;
  323.   var hResult: HIniKey): DWORD;
  324.  var
  325.   SubKey: string;
  326.   PKeyInfo, SKeyInfo: PIniKeyType_tag;
  327.   hCode: Byte;
  328.   HParentKey: HIniKey;
  329. begin
  330.   GetMem(PKeyInfo, SizeOf(TIniKeyType));
  331.   GetMem(SKeyInfo, SizeOf(TIniKeyType));
  332.  
  333.   LockRecord(0);
  334.   SeekRecord(hKey, 0);
  335.  
  336.   Result := ERROR_BAD_LENGTH;
  337.   try
  338.     while AKey <> '' do
  339.     begin
  340.       SubKey  := GetSubKey(AKey);
  341.       hCode   := GetHashCode(PChar(AnsiUpperCase(SubKey)), HashTableSize);
  342.       GetKeyInfo(PKeyInfo);
  343.       if PKeyInfo^.HashTable[hCode] = 0 then
  344.       begin
  345.         {═αΣε ±ετΣα≥ⁿ}
  346.         ClearKey(SKeyInfo^);
  347.         with SKeyInfo^ do
  348.         begin
  349.           Name      := SubKey;
  350.           HashCode  := hCode;
  351.           HashPrev  := 0;
  352.           ParentKey := RecNo;
  353.           NumValues := 1;
  354.           Data      := CreateDefaultValue;
  355.         end;
  356.         with PKeyInfo^ do
  357.         begin
  358.           Inc(NumSubKeys);
  359.           HashTable[hCode] := Append(SKeyInfo);
  360.           hResult := HashTable[hCode];
  361.         end;
  362.         RecNo := SKeyInfo^.ParentKey;
  363.         WriteData(PKeyInfo^);
  364.         Result := ERROR_SUCCESS;
  365.       end
  366.       else begin
  367.  
  368.         HParentKey := RecNo;
  369.         RecNo      := PKeyInfo^.HashTable[hCode];
  370.         GetKeyInfo(PKeyInfo);
  371.  
  372.         while (AnsiCompareText(PKeyInfo^.Name, SubKey) <> 0) and
  373.               (PKeyInfo^.HashNext <> 0)
  374.         do begin
  375.           RecNo := PKeyInfo^.HashNext;
  376.           GetKeyInfo(PKeyInfo);
  377.         end;
  378.  
  379.         if AnsiCompareStr(PKeyInfo^.Name, SubKey) <> 0 then
  380.         begin
  381.           ClearKey(SKeyInfo^);
  382.           with SKeyInfo^ do
  383.           begin
  384.             Name      := SubKey;
  385.             HashCode  := hCode;
  386.             HashPrev  := RecNo;
  387.             ParentKey := HParentKey;
  388.             NumValues := 1;
  389.             Data      := CreateDefaultValue;
  390.           end;
  391.           with PKeyInfo^ do
  392.           begin
  393.             Inc(NumSubKeys);
  394.             HashTable[hCode] := Append(SKeyInfo);
  395.             hResult := HashTable[hCode];
  396.           end;
  397.           RecNo := SKeyInfo^.ParentKey;
  398.           WriteData(PKeyInfo^);
  399.           Append(SKeyInfo);
  400.           Result := ERROR_SUCCESS;
  401.         end
  402.         else begin
  403.           {╥αΩεΘ ≤µσ σ±≥ⁿ, ∩σ≡σΩδ■≈ασ∞±  φα ±δσΣ. SubKey}
  404.           Result := ERROR_DUP_NAME;
  405.           hResult:= RecNo;
  406.         end;
  407.       end;
  408.     end;
  409.   finally
  410.     FreeMem(PKeyInfo);
  411.     FreeMem(SKeyInfo);
  412.     UnlockRecord(0);
  413.   end;
  414. end;
  415.  
  416. procedure TIniKeyStream.CreateSystemKeys(var RootKey: TIniKeyType);
  417.  var
  418.   i: Integer;
  419.   PKeyValue: PIniKeyType_tag;
  420.   DataKey: HIniKey;
  421. begin
  422.   GetMem(PKeyValue, SizeOf(TIniKeyType));
  423.   LockRecord(0);
  424.   try
  425.     for i := Low(SystemIniKeyNames) to High(SystemIniKeyNames) do
  426.     begin
  427.       ClearKey(PKeyValue^, SystemIniKeyNames[i]);
  428.       SetFlagsBit(PKeyValue^, INIKEY_FLAG_READONLY, True);
  429.       RootKey.HashTable[i] := Append(PKeyValue);
  430.     end;
  431.     for i := Low(SystemIniKeyNames) to High(SystemIniKeyNames) do
  432.     begin
  433.       DataKey := CreateDefaultValue;
  434.       RecNo   := RootKey.HashTable[i];
  435.       GetKeyInfo(PKeyValue);
  436.       PKeyValue^.Data      := DataKey;
  437.       PKeyValue^.NumValues := 1;
  438.       WriteData(PKeyValue^);
  439.     end;
  440.   finally
  441.     UnlockRecord(0);
  442.   end;
  443. end;
  444.  
  445. function TIniKeyStream.DeleteKey(const Key: string): Boolean;
  446.  var
  447.   Relative: Boolean;
  448.   KeyPath, S: string;
  449. begin
  450.   Relative := IsRelative(Key, S);
  451.   KeyPath  := CurrentPath;
  452.   if CurrentKey <> 0 then
  453.   begin
  454.     CloseKey;
  455.     Result := DeleteKeyEx(GetBaseKey(Relative), S) = ERROR_SUCCESS;
  456.     Result := Result and OpenKey(KeyPath, True);
  457.   end
  458.   else
  459.     Result := DeleteKeyEx(GetBaseKey(Relative), S) = ERROR_SUCCESS;
  460. end;
  461.  
  462. function TIniKeyStream.DeleteKeyEx(hKey: HIniKey; AKey: string): DWORD;
  463.  var
  464.   hTempKey: HIniKey;
  465.   pKeyInfo: PIniKeyType_tag;
  466.  
  467.   function DeleteSubKeyEx(hSubKey: HIniKey; MainKey: boolean): DWORD; forward;
  468.  
  469.   function DeleteHashKeys(hSubKey: HIniKey): DWORD;
  470.   begin
  471.     Result := ERROR_SUCCESS;
  472.     RecNo  := hSubKey;
  473.     GetKeyInfo(PKeyInfo);
  474.     if PKeyInfo^.HashNext <>0 then Result := DeleteHashKeys(PKeyInfo^.HashNext);
  475.     if Result = ERROR_SUCCESS then Result := DeleteSubKeyEx(hSubKey, False);
  476.   end;
  477.  
  478.   function DeleteSubKeyEx(hSubKey: HIniKey; MainKey: boolean): DWORD;
  479.    var
  480.     i: Integer;
  481.     AParentKey, AHashPrev, AHashNext: HIniKey;
  482.     AHashCode: WORD;
  483.   begin
  484.     GetKeyInfo(PKeyInfo);
  485.     with PKeyInfo^ do
  486.     begin
  487.       AParentKey := ParentKey;
  488.       AHashPrev  := HashPrev;
  489.       AHashNext  := HashNext;
  490.       AHashCode  := HashCode;
  491.       {╙Σαδ σ∞ Σαφφ√σ πδαΓφεπε Ωδ■≈α}
  492.       if Data <> 0 then Delete(Data);
  493.       {
  494.         ╙Σαδ σ∞ ∩εΣΩδ■≈Φ:
  495.          ╬ß⌡εΣΦ∞ ≥αßδΦ÷≤ HashTable, Σδ  ΩαµΣεΘ φσφ≤δσΓεΘ τα∩Φ±Φ,
  496.          Γ√Σσδ σ∞ ÷σ∩ε≈Ω≤ Ωδ■≈σΘ(HashNext) Φ ≤Σαδ σ∞ Φ⌡ Γ εß≡α≥φε∞ ∩ε≡ ΣΩσ
  497.        }
  498.       if NumSubKeys > 0 then
  499.       begin
  500.         for i := Low(HashTable) to High(HashTable) do
  501.           if HashTable[i] <> 0 then DeleteHashKeys(HashTable[i]);
  502.       end;
  503.     end;
  504.     {╙Σαδ σ∞ πδαΓφ√Θ Ωδ■≈}
  505.     if MainKey then
  506.     begin
  507.       if AHashPrev <> 0 then
  508.       begin
  509.         RecNo := AHashPrev;
  510.         GetKeyInfo(PKeyInfo);
  511.         PKeyInfo^.HashNext := AHashNext;
  512.         WriteData(PKeyInfo^);
  513.  
  514.         RecNo := AParentKey;
  515.         GetKeyInfo(PKeyInfo);
  516.         Dec(PKeyInfo^.NumSubKeys);
  517.         WriteData(PKeyInfo^);
  518.       end
  519.       else begin
  520.         RecNo := AParentKey;
  521.         GetKeyInfo(PKeyInfo);
  522.         PKeyInfo^.HashTable[AHashCode] := AHashNext;
  523.         Dec(PKeyInfo^.NumSubKeys);
  524.         WriteData(PKeyInfo^);
  525.       end;
  526.     end;
  527.     Delete(hSubKey);
  528.     Result := ERROR_SUCCESS
  529.   end;
  530.  
  531. begin
  532.   if AKey <> '' then
  533.     Result := OpenKeyEx(hKey, AKey, hTempKey)
  534.   else begin
  535.     Result   := ERROR_SUCCESS;
  536.     hTempKey := hKey
  537.   end;
  538.   if Result = ERROR_SUCCESS then
  539.   begin
  540.     LockRecord(0);
  541.     SeekRecord(hTempKey, 0);
  542.     GetMem(PKeyInfo, SizeOf(TIniKeyType));
  543.     try
  544.       Result := DeleteSubKeyEx(hTempKey, True);
  545.     finally
  546.       FreeMem(PKeyInfo);
  547.       UnlockRecord(0);
  548.     end;
  549.   end;
  550. end;
  551.  
  552. destructor TIniKeyStream.Destroy;
  553. begin
  554.   FValues.Free;
  555.   inherited;
  556. end;
  557.  
  558. function TIniKeyStream.GetBaseKey(Relative: Boolean): HIniKey;
  559. begin
  560.   if (CurrentKey = 0) or not Relative then
  561.     Result := PIniKeyType_tag(RootData)^.HashTable[FRootKey]
  562.   else
  563.     Result := CurrentKey;
  564. end;
  565.  
  566. function TIniKeyStream.GetDataInfo(const ValueName: string;
  567.   var Value: TIniDataType): boolean;
  568.  var
  569.   Buffer: Pointer;
  570. begin
  571.   Result := FValues.GetData(ValueName, Buffer, Value) <> 0;
  572. end;
  573.  
  574. function TIniKeyStream.GetDataSize(const ValueName: string): integer;
  575.  var
  576.   Buffer: Pointer;
  577.   ADataType: TIniDataType;
  578. begin
  579.   if FValues.GetData(ValueName, Buffer, ADataType) <> 0 then
  580.     Result := PIniKeyData_tag(Buffer)^.DataLen
  581.   else
  582.     Result := -1;
  583. end;
  584.  
  585. function TIniKeyStream.GetFlagsBit(AKeyInfo: TIniKeyType;
  586.   AOffset: Byte): boolean;
  587. begin
  588.   if AKeyInfo.Flags and AOffset = 0 then
  589.     Result := False
  590.   else
  591.     Result := True
  592. end;
  593.  
  594. function TIniKeyStream.GetKeyInfo(var AKeyInfo: PIniKeyType_tag): boolean;
  595. begin
  596.   Result := True;
  597.   ClearKey(AKeyInfo^);
  598.   ReadData(AKeyInfo);
  599. end;
  600.  
  601. procedure TIniKeyStream.GetKeyNames(Strings: TStrings; AKey: boolean = False);
  602.  var
  603.   hKey: HIniKey;
  604.   PKeyInfo, PSubKeyInfo: PIniKeyType_tag;
  605.   i: integer;
  606.  
  607.   procedure AddKeyName(hSubKey: HIniKey);
  608.    var
  609.     pKey: ^integer;
  610.   begin
  611.     SeekRecord(hSubKey, 0);
  612.     GetKeyInfo(PSubKeyInfo);
  613.     if AKey then
  614.     begin
  615.       GetMem(pKey, Sizeof(Integer));
  616.       pKey^ := hSubKey;
  617.       Strings.AddObject(PSubKeyInfo^.Name, TObject(pKey));
  618.     end
  619.     else
  620.       Strings.Add(PSubKeyInfo^.Name);
  621.     if PSubKeyInfo^.HashNext <> 0 then AddKeyName(PSubKeyInfo^.HashNext);
  622.   end;
  623.  
  624. begin
  625.   Strings.Clear;
  626.   hKey := CurrentKey;
  627.   SeekRecord(hKey, 0);
  628.   GetMem(PKeyInfo, SizeOf(TIniKeyType));
  629.   GetMem(PSubKeyInfo, SizeOf(TIniKeyType));
  630.   try
  631.     GetKeyInfo(PKeyInfo);
  632.     with PKeyInfo^ do
  633.     begin
  634.       if NumSubKeys > 0 then
  635.       begin
  636.         for i := Low(HashTable) to High(HashTable) do
  637.           if HashTable[i] <> 0 then AddKeyName(HashTable[i]);
  638.       end;
  639.     end;
  640.   finally
  641.     FreeMem(PKeyInfo);
  642.     FreeMem(PSubKeyInfo);
  643.     SeekRecord(hKey, 0);
  644.   end;
  645. end;
  646.  
  647. function TIniKeyStream.GetKeyValuesEx(hKey: HIniKey;
  648.   ValueList: TValueList): Integer;
  649.  var
  650.   pKeyInfo: PIniKeyType_tag;
  651.   ABuffer: Pointer;
  652.   DataSize: Integer;
  653. begin
  654.   RecNo := hKey;
  655.   GetMem(pKeyInfo, SizeOf(TIniKeyType));
  656.   try
  657.     GetKeyInfo(PKeyInfo);
  658.     if PKeyInfo^.Data > 0 then
  659.     begin
  660.       RecNo   := PKeyInfo^.Data;
  661.       ABuffer := AllocMem(1);
  662.       inherited ReadData(ABuffer, DataSize);
  663.       ValueList.LoadValues(ABuffer, DataSize);
  664.       FreeMem(ABuffer, DataSize);
  665.     end
  666.     else
  667.       ValueList.Clear;
  668.     Result := ValueList.Count;
  669.   finally
  670.     FreeMem(pKeyInfo);
  671.   end;
  672. end;
  673.  
  674. procedure TIniKeyStream.GetRootData(AData: Pointer);
  675. begin
  676.   with PIniKeyType_tag(AData)^ do
  677.   begin
  678.     Name := Format('%s %s',[INIKEY_ROOT_NAME,
  679.                    FormatDateTime('dd.mm.yyyy hh:nn:ss', Now)]);
  680.     HashCode   := 0;
  681.     HashNext   := 0;
  682.     Data       := 0;
  683.     NumSubKeys := 2;
  684.     NumValues  := 0;
  685.  
  686.     SetFlagsBit(PIniKeyType_tag(AData)^, INIKEY_FLAG_READONLY, True);
  687.     SetFlagsBit(PIniKeyType_tag(AData)^, INIKEY_FLAG_NOTVALUE, True);
  688.     SetFlagsBit(PIniKeyType_tag(AData)^, INIKEY_FLAG_NOTSKEYS, True);
  689.  
  690.  
  691.   end;
  692.   {
  693.     ╬∩≡σΣσδ σ∞
  694.       INIKEY_LOCAL_MACHINE
  695.       INIKEY_USERS
  696.   }
  697.   CreateSystemKeys(PIniKeyType_tag(AData)^);
  698.  
  699. end;
  700.  
  701. procedure TIniKeyStream.GetValueNames(Strings: TStrings);
  702.  var
  703.   i: integer;
  704.   Value: PIniKeyData_tag;
  705. begin
  706.   Strings.Clear;
  707.   for i := 0 to FValues.Count-1 do
  708.   begin
  709.     Value := FValues.KeyValue[i];
  710.     if Trim(Value^.NameValue) <> '' then Strings.Add(Value^.NameValue);
  711.   end;
  712. end;
  713.  
  714. procedure TIniKeyStream.LoadValuesEx;
  715. begin
  716.   GetKeyValuesEx(CurrentKey, FValues);
  717. end;
  718.  
  719. function TIniKeyStream.OpenKey(const Key: String;
  720.   CanCreate: Boolean): Boolean;
  721. var
  722.   TempKey: HIniKey;
  723.   S: string;
  724.   Relative: Boolean;
  725.   Value: integer;
  726. begin
  727.   Relative := IsRelative(Key, S);
  728.   TempKey  := 0;
  729.   if not CanCreate or (S = '') then
  730.     Result := OpenKeyEx(GetBaseKey(Relative), S, TempKey) = ERROR_SUCCESS
  731.   else begin
  732.     Value  := CreateKeyEx(GetBaseKey(Relative), S, TempKey);
  733.     Result := (Value = ERROR_SUCCESS) or (Value = ERROR_DUP_NAME);
  734.   end;
  735.   if Result then
  736.   begin
  737.     if (CurrentKey <> 0) and Relative then S := CurrentPath + '\' + S;
  738.     ChangeKey(TempKey, S);
  739.     GetKeyValuesEx(CurrentKey, FValues);
  740.   end;
  741. end;
  742.  
  743. function TIniKeyStream.OpenKeyEx(hKey: HIniKey; AKey: string;
  744.   var hResult: HIniKey): DWORD;
  745.  var
  746.   SubKey: string;
  747.   PKeyInfo: PIniKeyType_tag;
  748.   hCode: Byte;
  749. begin
  750.   GetMem(PKeyInfo, SizeOf(TIniKeyType));
  751.  
  752.   LockRecord(0);
  753.   SeekRecord(hKey, 0);
  754.  
  755.   Result  := ERROR_SUCCESS;
  756.   hResult := 0;
  757.  
  758.   try
  759.     while (AKey <> '') and (Result = ERROR_SUCCESS) do
  760.     begin
  761.       SubKey  := GetSubKey(AKey);
  762.       hCode   := GetHashCode(PChar(AnsiUpperCase(SubKey)), HashTableSize);
  763.       GetKeyInfo(PKeyInfo);
  764.  
  765.       if AnsiCompareText(PKeyInfo^.Name, SubKey) = 0 then Break;
  766.  
  767.       if PKeyInfo^.HashTable[hCode] = 0 then
  768.       begin
  769.         Result := ERROR_BADKEY
  770.       end
  771.       else begin
  772.  
  773.         RecNo := PKeyInfo^.HashTable[hCode];
  774.         GetKeyInfo(PKeyInfo);
  775.  
  776.         while (AnsiCompareText(PKeyInfo^.Name, SubKey) <> 0) and
  777.               (PKeyInfo^.HashNext <> 0)
  778.         do begin
  779.           RecNo := PKeyInfo^.HashNext;
  780.           GetKeyInfo(PKeyInfo);
  781.         end;
  782.  
  783.         if AnsiCompareStr(PKeyInfo^.Name, SubKey) <> 0 then
  784.         begin
  785.           Result := ERROR_BADKEY
  786.         end
  787.         else
  788.           {╥αΩεΘ ≤µσ σ±≥ⁿ, ∩σ≡σΩδ■≈ασ∞±  φα ±δσΣ. SubKey}
  789.           ;
  790.       end;
  791.     end;
  792.   finally
  793.     UnlockRecord(0);
  794.     FreeMem(PKeyInfo);
  795.     if Result = ERROR_SUCCESS then hResult := RecNo;
  796.   end;
  797. end;
  798.  
  799. function TIniKeyStream.ReadBinaryData(const Name: string; var Buffer;
  800.   ASize: Integer): Integer;
  801. begin
  802.   Result := FValues.ReadBinaryData(Name, Buffer, ASize);
  803. end;
  804.  
  805. function TIniKeyStream.ReadBool(const Name: string): Boolean;
  806. begin
  807.   Result := FValues.ReadBool(Name);
  808. end;
  809.  
  810. function TIniKeyStream.ReadCurrency(const Name: string): Currency;
  811. begin
  812.   Result := FValues.ReadCurrency(Name);
  813. end;
  814.  
  815. procedure TIniKeyStream.ReadData(var AData: PIniKeyType_tag);
  816.  var
  817.   ADataSize: Integer;
  818. begin
  819.   inherited ReadData(Pointer(AData), ADataSize);
  820. end;
  821.  
  822. function TIniKeyStream.ReadDateTime(const Name: string): TDateTime;
  823. begin
  824.   Result := FValues.ReadDateTime(Name);
  825. end;
  826.  
  827. function TIniKeyStream.ReadFloat(const Name: string): Double;
  828. begin
  829.   Result := FValues.ReadFloat(Name);
  830. end;
  831.  
  832. function TIniKeyStream.ReadInteger(const Name: string): LongInt;
  833. begin
  834.   Result := FValues.ReadInteger(Name);
  835. end;
  836.  
  837. function TIniKeyStream.ReadString(const Name: string): string;
  838. begin
  839.   Result := FValues.ReadString(Name);
  840. end;
  841.  
  842. function TIniKeyStream.ReadTime(const Name: string): TDateTime;
  843. begin
  844.   Result := ReadDateTime(Name);
  845. end;
  846.  
  847. procedure TIniKeyStream.RenameValue(const OldName, NewName: string);
  848. begin
  849.   FValues.RenameValue(OldName, NewName)
  850. end;
  851.  
  852. function TIniKeyStream.RestoreKey(const Key, FileName: string): boolean;
  853. begin
  854.   Result := True;
  855. end;
  856.  
  857. function TIniKeyStream.SaveKey(const Key, FileName: string): boolean;
  858. begin
  859.   Result := True;
  860. end;
  861.  
  862. procedure TIniKeyStream.SetFlagsBit(var AKeyInfo: TIniKeyType;
  863.   AOffset: Byte; Value: Boolean);
  864. begin
  865.   if Value then
  866.     AKeyInfo.Flags := AKeyInfo.Flags or AOffset
  867.   else
  868.     AKeyInfo.Flags := AKeyInfo.Flags and (AOffset xor $FF)
  869. end;
  870.  
  871. procedure TIniKeyStream.SetRootKey(const Value: HIniRootKey);
  872. begin
  873.   if RootKey <> Value then
  874.   begin
  875.     FRootKey := Value;
  876.     CloseKey;
  877.   end;
  878. end;
  879.  
  880. procedure TIniKeyStream.WriteBinaryData(const Name: string; var Buffer;
  881.   ASize: Integer);
  882. begin
  883.   FValues.WriteBinaryData(Name, Buffer, ASize);
  884. end;
  885.  
  886. procedure TIniKeyStream.WriteBool(const Name: string; Value: Boolean);
  887. begin
  888.   FValues.WriteBool(Name, Value);
  889. end;
  890.  
  891. procedure TIniKeyStream.WriteCurrency(const Name: string; Value: Currency);
  892. begin
  893.   FValues.WriteCurrency(Name, Value);
  894. end;
  895.  
  896. procedure TIniKeyStream.WriteData(AData: TIniKeyType);
  897. begin
  898.   inherited WriteData(@AData, SizeOf(TIniKeyType))
  899. end;
  900.  
  901. procedure TIniKeyStream.WriteDate(const Name: string; Value: TDateTime);
  902. begin
  903.   WriteDateTime(Name, Value);
  904. end;
  905.  
  906. procedure TIniKeyStream.WriteDateTime(const Name: string;
  907.   Value: TDateTime);
  908. begin
  909.   FValues.WriteDateTime(Name, Value);
  910. end;
  911.  
  912. procedure TIniKeyStream.WriteFloat(const Name: string; Value: Double);
  913. begin
  914.   FValues.WriteFloat(Name, Value);
  915. end;
  916.  
  917. procedure TIniKeyStream.WriteInteger(const Name: string; Value: Longint);
  918. begin
  919.   FValues.WriteInteger(Name, Value);
  920. end;
  921.  
  922. procedure TIniKeyStream.WriteString(const Name, Value: string);
  923. begin
  924.   FValues.WriteString(Name, Value);
  925. end;
  926.  
  927. procedure TIniKeyStream.WriteTime(const Name: string; Value: TDateTime);
  928. begin
  929.   WriteDateTime(Name, Value);
  930. end;
  931.  
  932. { TValueList }
  933.  
  934. procedure TValueList.Clear;
  935.  var
  936.   i: Integer;
  937. begin
  938.   FFlags := 0;
  939.   for i := 0 to Count-1 do DestroyValue(KeyValue[i]);
  940.   inherited;
  941. end;
  942.  
  943. constructor TValueList.Create;
  944. begin
  945.   inherited;
  946.   FFlags := 0;
  947. end;
  948.  
  949. function TValueList.GetDataSize: Integer;
  950.  var
  951.   i: Integer;
  952.   pKeyData: PIniKeyData_tag;
  953. begin
  954.   Result := 0;
  955.   for i := 0 to Count-1 do
  956.   begin
  957.     pKeyData := KeyValue[i];
  958.     with pKeyData^ do  Inc(Result, INIDAT_HEADER_SIZE + NameLen + DataLen);
  959.   end;
  960. end;
  961.  
  962. function TValueList.GetBuffer(var ABuffer: Pointer): Integer;
  963.  var
  964.   Offset: DWORD;
  965.   i: Integer;
  966.   pKeyData: PIniKeyData_tag;
  967. begin
  968.   Offset := 0;
  969.   Result := DataSize;
  970.   GetMem(ABuffer, DataSize);
  971.   for i := 0 to Count-1 do
  972.   begin
  973.     pKeyData := KeyValue[i];
  974.     System.Move(pKeyData^, (PChar(ABuffer)+Offset)^, INIDAT_HEADER_SIZE);
  975.     Inc(Offset, INIDAT_HEADER_SIZE);
  976.     with pKeyData^ do
  977.     begin
  978.       System.Move(NameValue^, (PChar(ABuffer)+Offset)^, NameLen);
  979.       Inc(Offset, NameLen);
  980.       System.Move(DataValue^, (PChar(ABuffer)+Offset)^, DataLen);
  981.       Inc(Offset, DataLen);
  982.     end;
  983.   end;
  984. end;
  985.  
  986. function TValueList.GetData(const Name: string; var Buffer: Pointer;
  987.   var AType: TIniDataType): Integer;
  988.  var
  989.   i: Integer;
  990.   pKeyData: PIniKeyData_tag;
  991. begin
  992.   i := IndexOf(Name);
  993.   if i > -1 then
  994.   begin
  995.     pKeyData   := KeyValue[i];
  996.     with pKeyData^ do
  997.     begin
  998.       Buffer := DataValue;
  999.       AType  := TIniDataType(DataType);
  1000.       Result := DataLen;
  1001.     end;
  1002.   end
  1003.   else
  1004.     Result := 0;
  1005. end;
  1006.  
  1007. function TValueList.GetKeyValue(Index: Integer): PIniKeyData_tag;
  1008. begin
  1009.   Result := PIniKeyData_tag(GetObject(Index));
  1010. end;
  1011.  
  1012. procedure TValueList.LoadValues(ABuffer: Pointer; ADataSize: Integer);
  1013.  var
  1014.   Offset: Integer;
  1015.   pKeyData: PIniKeyData_tag;
  1016. begin
  1017.   Buffer := ABuffer;
  1018.   Clear;
  1019.   Offset := 0;
  1020.   while Offset < ADataSize do
  1021.   begin
  1022.     GetMem(pKeyData, SizeOf(TIniKeyDataType));
  1023.  
  1024.     System.Move((PChar(Buffer)+Offset)^, pKeyData^, INIDAT_HEADER_SIZE);
  1025.     Inc(Offset, INIDAT_HEADER_SIZE);
  1026.  
  1027.     with pKeyData^ do
  1028.     begin
  1029.       GetMem(NameValue, NameLen);
  1030.       System.Move((PChar(Buffer)+Offset)^, NameValue^, NameLen);
  1031.       Inc(Offset, NameLen);
  1032.  
  1033.       if DataLen > 0 then
  1034.       begin
  1035.         GetMem(DataValue, DataLen);
  1036.         System.Move((PChar(Buffer)+Offset)^, DataValue^, DataLen);
  1037.       end;
  1038.       Inc(Offset, DataLen);
  1039.  
  1040.       AddObject(NameValue, TObject(pKeyData))
  1041.     end;
  1042.   end;
  1043.   Sort;
  1044. end;
  1045.  
  1046. procedure TValueList.PutData(const Name: string; Buffer: Pointer;
  1047.  ASize: Integer; AType: TIniDataType);
  1048.  var
  1049.   i: Integer;
  1050.   pKeyData: PIniKeyData_tag;
  1051. begin
  1052.   i := IndexOf(Name);
  1053.  
  1054.   if i > -1 then
  1055.   begin
  1056.     pKeyData   := KeyValue[i];
  1057.     with pKeyData^ do
  1058.     begin
  1059.       ReallocMem(DataValue, ASize);
  1060.     end;
  1061.   end else
  1062.   begin
  1063.     GetMem(pKeyData, SizeOf(TIniKeyDataType));
  1064.     with pKeyData^ do
  1065.     begin
  1066.       Flags     := FFlags;
  1067.       NameLen   := Length(Name)+1;
  1068.  
  1069.       GetMem(NameValue, NameLen);
  1070.       StrLCopy(NameValue, PChar(Name), NameLen);
  1071.  
  1072.       GetMem(DataValue, ASize);
  1073.     end;
  1074.     AddObject(Name, TObject(pKeyData));
  1075.   end;
  1076.  
  1077.   with pKeyData^ do
  1078.   begin
  1079.     DataType := Ord(AType);
  1080.     DataLen  := ASize;
  1081.     System.Move(Buffer^, DataValue^, DataLen);
  1082.   end;
  1083. end;
  1084.  
  1085. function TValueList.ReadCurrency(const Name: string): Currency;
  1086.  var
  1087.   DataLen  : Integer;
  1088.   DataType : TIniDataType;
  1089.   DataValue: Pointer;
  1090. begin
  1091.   DataLen := GetData(Name, DataValue, DataType);
  1092.   Result  := 0;
  1093.   if DataLen > 0 then
  1094.   begin
  1095.     if (DataType = idBinary) and (DataLen = SizeOf(Currency)) then
  1096.       System.Move(DataValue^, Result, DataLen)
  1097.     else
  1098.       ReadError(Name);
  1099.   end;
  1100. end;
  1101.  
  1102. function TValueList.ReadBinaryData(const Name: string; var Buffer;
  1103.   ASize: Integer): Integer;
  1104.  var
  1105.   DataLen  : Integer;
  1106.   DataType : TIniDataType;
  1107.   DataValue: Pointer;
  1108. begin
  1109.   DataLen := GetData(Name, DataValue, DataType);
  1110.   Result  := 0;
  1111.   if DataLen > 0 then
  1112.   begin
  1113.     if (DataType = idBinary) and (ASize >= DataLen) then
  1114.     begin
  1115.       System.Move(DataValue^, Buffer, DataLen);
  1116.       Result := DataLen;
  1117.     end
  1118.     else
  1119.       ReadError(Name);
  1120.   end
  1121. end;
  1122.  
  1123. function TValueList.ReadBool(const Name: string): Boolean;
  1124. begin
  1125.   Result := ReadInteger(Name) <> 0;
  1126. end;
  1127.  
  1128. function TValueList.ReadDateTime(const Name: string): TDateTime;
  1129.  var
  1130.   DataLen  : Integer;
  1131.   DataType : TIniDataType;
  1132.   DataValue: Pointer;
  1133. begin
  1134.   DataLen := GetData(Name, DataValue, DataType);
  1135.   Result  := 0;
  1136.   if DataLen > 0 then
  1137.   begin
  1138.     if (DataType = idBinary) and (DataLen = SizeOf(TDateTime)) then
  1139.       System.Move(DataValue^, Result, DataLen)
  1140.     else
  1141.       ReadError(Name);
  1142.   end;
  1143. end;
  1144.  
  1145. function TValueList.ReadInteger(const Name: string): LongInt;
  1146.  var
  1147.   DataLen  : Integer;
  1148.   DataType : TIniDataType;
  1149.   DataValue: Pointer;
  1150. begin
  1151.   DataLen := GetData(Name, DataValue, DataType);
  1152.   Result  := 0;
  1153.   if DataLen > 0 then
  1154.   begin
  1155.     if DataType = idInteger then
  1156.       System.Move(DataValue^, Result, DataLen)
  1157.     else
  1158.       ReadError(Name);
  1159.   end;
  1160. end;
  1161.  
  1162. function TValueList.ReadFloat(const Name: string): Double;
  1163.  var
  1164.   DataLen  : Integer;
  1165.   DataType : TIniDataType;
  1166.   DataValue: Pointer;
  1167. begin
  1168.   DataLen := GetData(Name, DataValue, DataType);
  1169.   Result  := 0;
  1170.   if DataLen > 0 then
  1171.   begin
  1172.     if (DataType = idBinary) and (DataLen = SizeOf(Double)) then
  1173.       System.Move(DataValue^, Result, DataLen)
  1174.     else
  1175.       ReadError(Name);
  1176.   end;
  1177. end;
  1178.  
  1179. function TValueList.ReadString(const Name: string): string;
  1180.  var
  1181.   DataLen  : Integer;
  1182.   DataType : TIniDataType;
  1183.   DataValue: Pointer;
  1184. begin
  1185.   DataLen := GetData(Name, DataValue, DataType);
  1186.   if DataLen > 0 then
  1187.   begin
  1188.     if DataType = idString then
  1189.       SetString(Result, PChar(DataValue), DataLen-1)
  1190.     else
  1191.       ReadError(Name);
  1192.   end
  1193.   else
  1194.     Result := '';
  1195. end;
  1196.  
  1197. function TValueList.ReadTime(const Name: string): TDateTime;
  1198. begin
  1199.   Result := ReadDateTime(Name);
  1200. end;
  1201.  
  1202. function TValueList.RenameValue(const OldName, NewName: string): DWORD;
  1203.  var
  1204.   i, j: Integer;
  1205.   pKeyData: PIniKeyData_tag;
  1206. begin
  1207.   i := IndexOf(OldName);
  1208.   j := IndexOf(NewName);
  1209.  
  1210.   if (j > -1) and (i <> j) then
  1211.   begin
  1212.     Result := ERROR_DUP_NAME;
  1213.     Exit;
  1214.   end;
  1215.  
  1216.   if (i > -1) and (i <> j) then
  1217.   begin
  1218.     Strings[i] := NewName;
  1219.     pKeyData   := KeyValue[i];
  1220.     with pKeyData^ do
  1221.     begin
  1222.       NameLen := Length(NewName);
  1223.       ReallocMem(NameValue, NameLen+1);
  1224.       StrPCopy(NameValue, NewName);
  1225.     end;
  1226.   end;
  1227.  
  1228.   Result := ERROR_SUCCESS;
  1229. end;
  1230.  
  1231. procedure TValueList.SetKeyValue(Index: Integer;
  1232.   const Value: PIniKeyData_tag);
  1233. begin
  1234.   PutObject(Index, TObject(Value));
  1235. end;
  1236.  
  1237. procedure TValueList.WriteBinaryData(const Name: string; var Buffer;
  1238.   ASize: Integer);
  1239. begin
  1240.   PutData(Name, @Buffer, ASize, idBinary);
  1241. end;
  1242.  
  1243. procedure TValueList.WriteBool(const Name: string; Value: Boolean);
  1244. begin
  1245.   WriteInteger(Name, Ord(Value));
  1246. end;
  1247.  
  1248. procedure TValueList.WriteCurrency(const Name: string; Value: Currency);
  1249. begin
  1250.   PutData(Name, @Value, SizeOf(Currency), idBinary);
  1251. end;
  1252.  
  1253. procedure TValueList.WriteDate(const Name: string; Value: TDateTime);
  1254. begin
  1255.   WriteDateTime(Name, Value);
  1256. end;
  1257.  
  1258. procedure TValueList.WriteDateTime(const Name: string; Value: TDateTime);
  1259. begin
  1260.   PutData(Name, @Value, SizeOf(TDateTime), idBinary);
  1261. end;
  1262.  
  1263. procedure TValueList.WriteInteger(const Name: string; Value: LongInt);
  1264. begin
  1265.   PutData(Name, @Value, SizeOf(LongInt), idInteger);
  1266. end;
  1267.  
  1268. procedure TValueList.WriteFloat(const Name: string; Value: Double);
  1269. begin
  1270.   PutData(Name, @Value, SizeOf(Double), idBinary);
  1271. end;
  1272.  
  1273. procedure TValueList.WriteString(const Name, Value: string);
  1274. begin
  1275.   PutData(Name, PChar(Value), Length(Value)+1, idString);
  1276. end;
  1277.  
  1278. procedure TValueList.WriteTime(const Name: string; Value: TDateTime);
  1279. begin
  1280.   WriteDateTime(Name, Value);
  1281. end;
  1282.  
  1283. procedure TValueList.Delete(Index: Integer);
  1284. begin
  1285.   DestroyValue(KeyValue[Index]);
  1286.   inherited;
  1287. end;
  1288.  
  1289. procedure TValueList.DestroyValue(pValue: PIniKeyData_tag);
  1290. begin
  1291.   with pValue^ do
  1292.   begin
  1293.     FreeMem(NameValue, NameLen);
  1294.     if DataLen <> 0 then  FreeMem(DataValue, DataLen);
  1295.   end;
  1296.   FreeMem(pValue);
  1297. end;
  1298.  
  1299. function TValueList.DeleteValue(const Name: string): boolean;
  1300.  var
  1301.   Index: integer;
  1302. begin
  1303.   Result := True;
  1304.   Index  := IndexOf(Name);
  1305.   if Index > -1 then
  1306.     Delete(Index)
  1307.   else
  1308.     Result := False;
  1309. end;
  1310.  
  1311. end.
  1312.