HierarchicalStorage.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include "Common.h"
  5. #include "Exceptions.h"
  6. #include "PuttyIntf.h"
  7. #include "HierarchicalStorage.h"
  8. #include <TextsCore.h>
  9. #include <vector>
  10. //---------------------------------------------------------------------------
  11. #pragma package(smart_init)
  12. //---------------------------------------------------------------------------
  13. #define READ_REGISTRY(Method) \
  14. if (FRegistry->ValueExists(Name)) \
  15. try { return FRegistry->Method(Name); } catch(...) { FFailed++; return Default; } \
  16. else return Default;
  17. #define WRITE_REGISTRY(Method) \
  18. try { FRegistry->Method(Name, Value); } catch(...) { FFailed++; }
  19. //---------------------------------------------------------------------------
  20. AnsiString __fastcall MungeStr(const AnsiString Str)
  21. {
  22. AnsiString Result;
  23. Result.SetLength(Str.Length() * 3 + 1);
  24. putty_mungestr(Str.c_str(), Result.c_str());
  25. PackStr(Result);
  26. return Result;
  27. }
  28. //---------------------------------------------------------------------------
  29. AnsiString __fastcall UnMungeStr(const AnsiString Str)
  30. {
  31. AnsiString Result;
  32. Result.SetLength(Str.Length() * 3 + 1);
  33. putty_unmungestr(Str.c_str(), Result.c_str(), Result.Length());
  34. PackStr(Result);
  35. return Result;
  36. }
  37. //---------------------------------------------------------------------------
  38. AnsiString __fastcall SimpleMungeStr(const AnsiString Str)
  39. {
  40. AnsiString Result = Str;
  41. for (int i = 1; i < Result.Length(); i++)
  42. {
  43. if ((Result[i] == '\\') || (Result[i] == '[') || (Result[i] == ']'))
  44. {
  45. Result[i] = '_';
  46. }
  47. }
  48. return Result;
  49. }
  50. //===========================================================================
  51. __fastcall THierarchicalStorage::THierarchicalStorage(const AnsiString AStorage)
  52. {
  53. FStorage = AStorage;
  54. FKeyHistory = new TStringList();
  55. AccessMode = smRead;
  56. Explicit = false;
  57. }
  58. //---------------------------------------------------------------------------
  59. __fastcall THierarchicalStorage::~THierarchicalStorage()
  60. {
  61. delete FKeyHistory;
  62. }
  63. //---------------------------------------------------------------------------
  64. void __fastcall THierarchicalStorage::SetAccessMode(TStorageAccessMode value)
  65. {
  66. FAccessMode = value;
  67. }
  68. //---------------------------------------------------------------------------
  69. AnsiString __fastcall THierarchicalStorage::GetCurrentSubKey()
  70. {
  71. if (FKeyHistory->Count) return FKeyHistory->Strings[FKeyHistory->Count-1];
  72. else return "";
  73. }
  74. //---------------------------------------------------------------------------
  75. bool __fastcall THierarchicalStorage::OpenRootKey(bool CanCreate)
  76. {
  77. return OpenSubKey("", CanCreate);
  78. }
  79. //---------------------------------------------------------------------------
  80. bool __fastcall THierarchicalStorage::OpenSubKey(const AnsiString SubKey, bool )
  81. {
  82. FKeyHistory->Add(IncludeTrailingBackslash(CurrentSubKey+SubKey));
  83. return true;
  84. }
  85. //---------------------------------------------------------------------------
  86. bool __fastcall THierarchicalStorage::CreateSubKey(const AnsiString SubKey)
  87. {
  88. FKeyHistory->Add(IncludeTrailingBackslash(CurrentSubKey+SubKey));
  89. return true;
  90. }
  91. //---------------------------------------------------------------------------
  92. void __fastcall THierarchicalStorage::CloseSubKey()
  93. {
  94. if (FKeyHistory->Count == 0) throw Exception("");
  95. else FKeyHistory->Delete(FKeyHistory->Count-1);
  96. }
  97. //---------------------------------------------------------------------------
  98. void __fastcall THierarchicalStorage::ClearSubKeys()
  99. {
  100. TStringList *SubKeys = new TStringList();
  101. try
  102. {
  103. GetSubKeyNames(SubKeys);
  104. for (int Index = 0; Index < SubKeys->Count; Index++)
  105. {
  106. RecursiveDeleteSubKey(SubKeys->Strings[Index]);
  107. }
  108. }
  109. __finally
  110. {
  111. delete SubKeys;
  112. }
  113. }
  114. //---------------------------------------------------------------------------
  115. void __fastcall THierarchicalStorage::RecursiveDeleteSubKey(const AnsiString Key)
  116. {
  117. if (OpenSubKey(Key, false))
  118. {
  119. ClearSubKeys();
  120. CloseSubKey();
  121. }
  122. DeleteSubKey(Key);
  123. }
  124. //---------------------------------------------------------------------------
  125. bool __fastcall THierarchicalStorage::HasSubKeys()
  126. {
  127. bool Result;
  128. TStrings * SubKeys = new TStringList();
  129. try
  130. {
  131. GetSubKeyNames(SubKeys);
  132. Result = (SubKeys->Count > 0);
  133. }
  134. __finally
  135. {
  136. delete SubKeys;
  137. }
  138. return Result;
  139. }
  140. //---------------------------------------------------------------------------
  141. void __fastcall THierarchicalStorage::ReadValues(Classes::TStrings* Strings,
  142. bool MaintainKeys)
  143. {
  144. TStrings * Names = new TStringList();
  145. try
  146. {
  147. GetValueNames(Names);
  148. for (int Index = 0; Index < Names->Count; Index++)
  149. {
  150. if (MaintainKeys)
  151. {
  152. Strings->Add(FORMAT("%s=%s", (Names->Strings[Index],
  153. ReadString(Names->Strings[Index], ""))));
  154. }
  155. else
  156. {
  157. Strings->Add(ReadString(Names->Strings[Index], ""));
  158. }
  159. }
  160. }
  161. __finally
  162. {
  163. delete Names;
  164. }
  165. }
  166. //---------------------------------------------------------------------------
  167. void __fastcall THierarchicalStorage::ClearValues()
  168. {
  169. TStrings * Names = new TStringList();
  170. try
  171. {
  172. GetValueNames(Names);
  173. for (int Index = 0; Index < Names->Count; Index++)
  174. {
  175. DeleteValue(Names->Strings[Index]);
  176. }
  177. }
  178. __finally
  179. {
  180. delete Names;
  181. }
  182. }
  183. //---------------------------------------------------------------------------
  184. void __fastcall THierarchicalStorage::WriteValues(Classes::TStrings * Strings,
  185. bool MaintainKeys)
  186. {
  187. ClearValues();
  188. if (Strings)
  189. {
  190. for (int Index = 0; Index < Strings->Count; Index++)
  191. {
  192. if (MaintainKeys)
  193. {
  194. assert(Strings->Strings[Index].Pos("=") > 1);
  195. WriteString(Strings->Names[Index], Strings->Values[Strings->Names[Index]]);
  196. }
  197. else
  198. {
  199. WriteString(IntToStr(Index), Strings->Strings[Index]);
  200. }
  201. }
  202. }
  203. }
  204. //---------------------------------------------------------------------------
  205. AnsiString __fastcall THierarchicalStorage::ReadString(const AnsiString Name, const AnsiString Default)
  206. {
  207. return UnMungeStr(ReadStringRaw(Name, MungeStr(Default)));
  208. }
  209. //---------------------------------------------------------------------------
  210. AnsiString __fastcall THierarchicalStorage::ReadBinaryData(const AnsiString Name)
  211. {
  212. int Size = BinaryDataSize(Name);
  213. AnsiString Value;
  214. Value.SetLength(Size);
  215. ReadBinaryData(Name, Value.c_str(), Size);
  216. return Value;
  217. }
  218. //---------------------------------------------------------------------------
  219. void __fastcall THierarchicalStorage::WriteString(const AnsiString Name, const AnsiString Value)
  220. {
  221. WriteStringRaw(Name, MungeStr(Value));
  222. }
  223. //---------------------------------------------------------------------------
  224. void __fastcall THierarchicalStorage::WriteBinaryData(const AnsiString Name,
  225. const AnsiString Value)
  226. {
  227. WriteBinaryData(Name, Value.c_str(), Value.Length());
  228. }
  229. //---------------------------------------------------------------------------
  230. AnsiString __fastcall THierarchicalStorage::IncludeTrailingBackslash(const AnsiString & S)
  231. {
  232. // expanded from ?: as it caused memory leaks
  233. if (S.IsEmpty())
  234. {
  235. return S;
  236. }
  237. else
  238. {
  239. return ::IncludeTrailingBackslash(S);
  240. }
  241. }
  242. //---------------------------------------------------------------------------
  243. AnsiString __fastcall THierarchicalStorage::ExcludeTrailingBackslash(const AnsiString & S)
  244. {
  245. // expanded from ?: as it caused memory leaks
  246. if (S.IsEmpty())
  247. {
  248. return S;
  249. }
  250. else
  251. {
  252. return ::ExcludeTrailingBackslash(S);
  253. }
  254. }
  255. //===========================================================================
  256. __fastcall TRegistryStorage::TRegistryStorage(const AnsiString AStorage):
  257. THierarchicalStorage(IncludeTrailingBackslash(AStorage))
  258. {
  259. Init();
  260. };
  261. //---------------------------------------------------------------------------
  262. __fastcall TRegistryStorage::TRegistryStorage(const AnsiString AStorage, HKEY ARootKey):
  263. THierarchicalStorage(IncludeTrailingBackslash(AStorage))
  264. {
  265. Init();
  266. FRegistry->RootKey = ARootKey;
  267. }
  268. //---------------------------------------------------------------------------
  269. void __fastcall TRegistryStorage::Init()
  270. {
  271. FFailed = 0;
  272. FRegistry = new TRegistry();
  273. FRegistry->Access = KEY_READ;
  274. }
  275. //---------------------------------------------------------------------------
  276. __fastcall TRegistryStorage::~TRegistryStorage()
  277. {
  278. delete FRegistry;
  279. };
  280. //---------------------------------------------------------------------------
  281. bool __fastcall TRegistryStorage::Copy(TRegistryStorage * Storage)
  282. {
  283. TRegistry * Registry = Storage->FRegistry;
  284. bool Result = true;
  285. TStrings * Names = new TStringList();
  286. try
  287. {
  288. Registry->GetValueNames(Names);
  289. std::vector<unsigned char> Buffer(1024, 0);
  290. int Index = 0;
  291. while ((Index < Names->Count) && Result)
  292. {
  293. AnsiString Name = Names->Strings[Index];
  294. unsigned long Size = Buffer.size();
  295. unsigned long Type;
  296. int RegResult;
  297. do
  298. {
  299. RegResult = RegQueryValueEx(Registry->CurrentKey, Name.c_str(), NULL,
  300. &Type, &Buffer[0], &Size);
  301. if (Result == ERROR_MORE_DATA)
  302. {
  303. Buffer.resize(Size);
  304. }
  305. } while (RegResult == ERROR_MORE_DATA);
  306. Result = (RegResult == ERROR_SUCCESS);
  307. if (Result)
  308. {
  309. RegResult = RegSetValueEx(FRegistry->CurrentKey, Name.c_str(), NULL, Type,
  310. &Buffer[0], Size);
  311. Result = (RegResult == ERROR_SUCCESS);
  312. }
  313. ++Index;
  314. }
  315. }
  316. __finally
  317. {
  318. delete Names;
  319. }
  320. return Result;
  321. }
  322. //---------------------------------------------------------------------------
  323. void __fastcall TRegistryStorage::SetAccessMode(TStorageAccessMode value)
  324. {
  325. THierarchicalStorage::SetAccessMode(value);
  326. if (FRegistry)
  327. {
  328. switch (AccessMode) {
  329. case smRead:
  330. FRegistry->Access = KEY_READ;
  331. break;
  332. case smReadWrite:
  333. default:
  334. FRegistry->Access = KEY_READ | KEY_WRITE;
  335. break;
  336. }
  337. }
  338. }
  339. //---------------------------------------------------------------------------
  340. bool __fastcall TRegistryStorage::OpenSubKey(const AnsiString SubKey, bool CanCreate)
  341. {
  342. bool Result;
  343. if (FKeyHistory->Count > 0) FRegistry->CloseKey();
  344. Result = FRegistry->OpenKey(
  345. ExcludeTrailingBackslash(Storage + CurrentSubKey + SubKey), CanCreate);
  346. if (Result) Result = THierarchicalStorage::OpenSubKey(SubKey, CanCreate);
  347. return Result;
  348. }
  349. //---------------------------------------------------------------------------
  350. bool __fastcall TRegistryStorage::CreateSubKey(const AnsiString SubKey)
  351. {
  352. bool Result;
  353. if (FKeyHistory->Count) FRegistry->CloseKey();
  354. Result = FRegistry->CreateKey(ExcludeTrailingBackslash(Storage + CurrentSubKey + SubKey));
  355. if (Result) Result = THierarchicalStorage::CreateSubKey(CurrentSubKey + SubKey);
  356. return Result;
  357. }
  358. //---------------------------------------------------------------------------
  359. void __fastcall TRegistryStorage::CloseSubKey()
  360. {
  361. FRegistry->CloseKey();
  362. THierarchicalStorage::CloseSubKey();
  363. if (FKeyHistory->Count)
  364. {
  365. FRegistry->OpenKey(Storage + CurrentSubKey, True);
  366. }
  367. }
  368. //---------------------------------------------------------------------------
  369. bool __fastcall TRegistryStorage::DeleteSubKey(const AnsiString SubKey)
  370. {
  371. AnsiString K;
  372. if (FKeyHistory->Count == 0) K = Storage + CurrentSubKey;
  373. K += SubKey;
  374. return FRegistry->DeleteKey(K);
  375. }
  376. //---------------------------------------------------------------------------
  377. void __fastcall TRegistryStorage::GetSubKeyNames(Classes::TStrings* Strings)
  378. {
  379. FRegistry->GetKeyNames(Strings);
  380. }
  381. //---------------------------------------------------------------------------
  382. void __fastcall TRegistryStorage::GetValueNames(Classes::TStrings* Strings)
  383. {
  384. FRegistry->GetValueNames(Strings);
  385. }
  386. //---------------------------------------------------------------------------
  387. bool __fastcall TRegistryStorage::DeleteValue(const AnsiString Name)
  388. {
  389. return FRegistry->DeleteValue(Name);
  390. }
  391. //---------------------------------------------------------------------------
  392. bool __fastcall TRegistryStorage::KeyExists(const AnsiString SubKey)
  393. {
  394. return FRegistry->KeyExists(SubKey);
  395. }
  396. //---------------------------------------------------------------------------
  397. bool __fastcall TRegistryStorage::ValueExists(const AnsiString Value)
  398. {
  399. return FRegistry->ValueExists(Value);
  400. }
  401. //---------------------------------------------------------------------------
  402. int __fastcall TRegistryStorage::BinaryDataSize(const AnsiString Name)
  403. {
  404. return FRegistry->GetDataSize(Name);
  405. }
  406. //---------------------------------------------------------------------------
  407. bool __fastcall TRegistryStorage::ReadBool(const AnsiString Name, bool Default)
  408. {
  409. READ_REGISTRY(ReadBool);
  410. }
  411. //---------------------------------------------------------------------------
  412. TDateTime __fastcall TRegistryStorage::ReadDateTime(const AnsiString Name, TDateTime Default)
  413. {
  414. READ_REGISTRY(ReadDateTime);
  415. }
  416. //---------------------------------------------------------------------------
  417. double __fastcall TRegistryStorage::ReadFloat(const AnsiString Name, double Default)
  418. {
  419. READ_REGISTRY(ReadFloat);
  420. }
  421. //---------------------------------------------------------------------------
  422. int __fastcall TRegistryStorage::ReadInteger(const AnsiString Name, int Default)
  423. {
  424. READ_REGISTRY(ReadInteger);
  425. }
  426. //---------------------------------------------------------------------------
  427. __int64 __fastcall TRegistryStorage::ReadInt64(const AnsiString Name, __int64 Default)
  428. {
  429. __int64 Result = Default;
  430. if (FRegistry->ValueExists(Name))
  431. {
  432. try
  433. {
  434. FRegistry->ReadBinaryData(Name, &Result, sizeof(Result));
  435. }
  436. catch(...)
  437. {
  438. FFailed++;
  439. }
  440. }
  441. return Result;
  442. }
  443. //---------------------------------------------------------------------------
  444. AnsiString __fastcall TRegistryStorage::ReadStringRaw(const AnsiString Name, const AnsiString Default)
  445. {
  446. READ_REGISTRY(ReadString);
  447. }
  448. //---------------------------------------------------------------------------
  449. int __fastcall TRegistryStorage::ReadBinaryData(const AnsiString Name,
  450. void * Buffer, int Size)
  451. {
  452. int Result;
  453. if (FRegistry->ValueExists(Name))
  454. {
  455. try
  456. {
  457. Result = FRegistry->ReadBinaryData(Name, Buffer, Size);
  458. }
  459. catch(...)
  460. {
  461. Result = 0;
  462. FFailed++;
  463. }
  464. }
  465. else
  466. {
  467. Result = 0;
  468. }
  469. return Result;
  470. }
  471. //---------------------------------------------------------------------------
  472. void __fastcall TRegistryStorage::WriteBool(const AnsiString Name, bool Value)
  473. {
  474. WRITE_REGISTRY(WriteBool);
  475. }
  476. //---------------------------------------------------------------------------
  477. void __fastcall TRegistryStorage::WriteDateTime(const AnsiString Name, TDateTime Value)
  478. {
  479. WRITE_REGISTRY(WriteDateTime);
  480. }
  481. //---------------------------------------------------------------------------
  482. void __fastcall TRegistryStorage::WriteFloat(const AnsiString Name, double Value)
  483. {
  484. WRITE_REGISTRY(WriteFloat);
  485. }
  486. //---------------------------------------------------------------------------
  487. void __fastcall TRegistryStorage::WriteStringRaw(const AnsiString Name, const AnsiString Value)
  488. {
  489. WRITE_REGISTRY(WriteString);
  490. }
  491. //---------------------------------------------------------------------------
  492. void __fastcall TRegistryStorage::WriteInteger(const AnsiString Name, int Value)
  493. {
  494. WRITE_REGISTRY(WriteInteger);
  495. }
  496. //---------------------------------------------------------------------------
  497. void __fastcall TRegistryStorage::WriteInt64(const AnsiString Name, __int64 Value)
  498. {
  499. try
  500. {
  501. FRegistry->WriteBinaryData(Name, &Value, sizeof(Value));
  502. }
  503. catch(...)
  504. {
  505. FFailed++;
  506. }
  507. }
  508. //---------------------------------------------------------------------------
  509. void __fastcall TRegistryStorage::WriteBinaryData(const AnsiString Name,
  510. const void * Buffer, int Size)
  511. {
  512. try
  513. {
  514. FRegistry->WriteBinaryData(Name, const_cast<void *>(Buffer), Size);
  515. }
  516. catch(...)
  517. {
  518. FFailed++;
  519. }
  520. }
  521. //---------------------------------------------------------------------------
  522. int __fastcall TRegistryStorage::GetFailed()
  523. {
  524. int Result = FFailed;
  525. FFailed = 0;
  526. return Result;
  527. }
  528. //===========================================================================
  529. __fastcall TIniFileStorage::TIniFileStorage(const AnsiString AStorage):
  530. THierarchicalStorage(AStorage)
  531. {
  532. FIniFile = new TMemIniFile(Storage);
  533. FOriginal = new TStringList();
  534. FIniFile->GetStrings(FOriginal);
  535. ApplyOverrides();
  536. }
  537. //---------------------------------------------------------------------------
  538. __fastcall TIniFileStorage::~TIniFileStorage()
  539. {
  540. TStrings * Strings = new TStringList;
  541. try
  542. {
  543. FIniFile->GetStrings(Strings);
  544. if (!Strings->Equals(FOriginal))
  545. {
  546. int Attr;
  547. // preserve attributes (especially hidden)
  548. if (FileExists(Storage))
  549. {
  550. Attr = GetFileAttributes(Storage.c_str());
  551. }
  552. else
  553. {
  554. Attr = FILE_ATTRIBUTE_NORMAL;
  555. }
  556. HANDLE Handle = CreateFile(Storage.c_str(), GENERIC_READ | GENERIC_WRITE,
  557. 0, NULL, CREATE_ALWAYS, Attr, 0);
  558. if (Handle == INVALID_HANDLE_VALUE)
  559. {
  560. // "access denied" errors upon implicit saves are ignored
  561. if (Explicit || (GetLastError() != ERROR_ACCESS_DENIED))
  562. {
  563. try
  564. {
  565. RaiseLastOSError();
  566. }
  567. catch(Exception & E)
  568. {
  569. throw ExtException(&E, FMTLOAD(CREATE_FILE_ERROR, (Storage)));
  570. }
  571. }
  572. }
  573. else
  574. {
  575. TStream * Stream = new THandleStream(int(Handle));
  576. try
  577. {
  578. Strings->SaveToStream(Stream);
  579. }
  580. __finally
  581. {
  582. CloseHandle(Handle);
  583. delete Stream;
  584. }
  585. }
  586. }
  587. }
  588. __finally
  589. {
  590. delete FOriginal;
  591. delete Strings;
  592. delete FIniFile;
  593. }
  594. }
  595. //---------------------------------------------------------------------------
  596. AnsiString __fastcall TIniFileStorage::GetCurrentSection()
  597. {
  598. return ExcludeTrailingBackslash(CurrentSubKey);
  599. }
  600. //---------------------------------------------------------------------------
  601. bool __fastcall TIniFileStorage::OpenSubKey(const AnsiString SubKey, bool CanCreate)
  602. {
  603. bool Result = CanCreate;
  604. if (!Result)
  605. {
  606. TStringList * Sections = new TStringList();
  607. try
  608. {
  609. Sections->Sorted = true;
  610. FIniFile->ReadSections(Sections);
  611. AnsiString NewKey = ExcludeTrailingBackslash(CurrentSubKey+SubKey);
  612. int Index = -1;
  613. if (Sections->Count)
  614. {
  615. Result = Sections->Find(NewKey, Index);
  616. if (!Result && Index < Sections->Count &&
  617. Sections->Strings[Index].SubString(1, NewKey.Length()+1) == NewKey + "\\")
  618. {
  619. Result = true;
  620. }
  621. }
  622. }
  623. __finally
  624. {
  625. delete Sections;
  626. }
  627. }
  628. if (Result)
  629. {
  630. Result = THierarchicalStorage::OpenSubKey(SubKey, CanCreate);
  631. }
  632. return Result;
  633. }
  634. //---------------------------------------------------------------------------
  635. bool __fastcall TIniFileStorage::DeleteSubKey(const AnsiString SubKey)
  636. {
  637. bool Result;
  638. try
  639. {
  640. FIniFile->EraseSection(CurrentSubKey + SubKey);
  641. Result = true;
  642. }
  643. catch (...)
  644. {
  645. Result = false;
  646. }
  647. return Result;
  648. }
  649. //---------------------------------------------------------------------------
  650. void __fastcall TIniFileStorage::GetSubKeyNames(Classes::TStrings* Strings)
  651. {
  652. TStrings * Sections = new TStringList();
  653. try
  654. {
  655. Strings->Clear();
  656. FIniFile->ReadSections(Sections);
  657. for (int i = 0; i < Sections->Count; i++)
  658. {
  659. AnsiString Section = Sections->Strings[i];
  660. if (AnsiCompareText(CurrentSubKey,
  661. Section.SubString(1, CurrentSubKey.Length())) == 0)
  662. {
  663. AnsiString SubSection = Section.SubString(CurrentSubKey.Length() + 1,
  664. Section.Length() - CurrentSubKey.Length());
  665. int P = SubSection.Pos("\\");
  666. if (P)
  667. {
  668. SubSection.SetLength(P - 1);
  669. }
  670. if (Strings->IndexOf(SubSection) < 0)
  671. {
  672. Strings->Add(SubSection);
  673. }
  674. }
  675. }
  676. }
  677. __finally
  678. {
  679. delete Sections;
  680. }
  681. }
  682. //---------------------------------------------------------------------------
  683. void __fastcall TIniFileStorage::GetValueNames(Classes::TStrings* Strings)
  684. {
  685. return FIniFile->ReadSection(CurrentSection, Strings);
  686. }
  687. //---------------------------------------------------------------------------
  688. bool __fastcall TIniFileStorage::KeyExists(const AnsiString SubKey)
  689. {
  690. return FIniFile->SectionExists(CurrentSubKey + SubKey);
  691. }
  692. //---------------------------------------------------------------------------
  693. bool __fastcall TIniFileStorage::ValueExists(const AnsiString Value)
  694. {
  695. return FIniFile->ValueExists(CurrentSection, Value);
  696. }
  697. //---------------------------------------------------------------------------
  698. bool __fastcall TIniFileStorage::DeleteValue(const AnsiString Name)
  699. {
  700. FIniFile->DeleteKey(CurrentSection, Name);
  701. return true;
  702. }
  703. //---------------------------------------------------------------------------
  704. int __fastcall TIniFileStorage::BinaryDataSize(const AnsiString Name)
  705. {
  706. return ReadStringRaw(Name, "").Length() / 2;
  707. }
  708. //---------------------------------------------------------------------------
  709. void __fastcall TIniFileStorage::ApplyOverrides()
  710. {
  711. AnsiString OverridesKey = IncludeTrailingBackslash("Override");
  712. TStrings * Sections = new TStringList();
  713. try
  714. {
  715. Sections->Clear();
  716. FIniFile->ReadSections(Sections);
  717. for (int i = 0; i < Sections->Count; i++)
  718. {
  719. AnsiString Section = Sections->Strings[i];
  720. if (AnsiSameText(OverridesKey,
  721. Section.SubString(1, OverridesKey.Length())))
  722. {
  723. AnsiString SubKey = Section.SubString(OverridesKey.Length() + 1,
  724. Section.Length() - OverridesKey.Length());
  725. TStrings * Names = new TStringList;
  726. try
  727. {
  728. FIniFile->ReadSection(Section, Names);
  729. for (int ii = 0; ii < Names->Count; ii++)
  730. {
  731. AnsiString Name = Names->Strings[ii];
  732. AnsiString Value = FIniFile->ReadString(Section, Name, "");
  733. FIniFile->WriteString(SubKey, Name, Value);
  734. }
  735. }
  736. __finally
  737. {
  738. delete Names;
  739. }
  740. FIniFile->EraseSection(Section);
  741. }
  742. }
  743. }
  744. __finally
  745. {
  746. delete Sections;
  747. }
  748. }
  749. //---------------------------------------------------------------------------
  750. bool __fastcall TIniFileStorage::ReadBool(const AnsiString Name, bool Default)
  751. {
  752. return FIniFile->ReadBool(CurrentSection, Name, Default);
  753. }
  754. //---------------------------------------------------------------------------
  755. int __fastcall TIniFileStorage::ReadInteger(const AnsiString Name, int Default)
  756. {
  757. return FIniFile->ReadInteger(CurrentSection, Name, Default);
  758. }
  759. //---------------------------------------------------------------------------
  760. __int64 __fastcall TIniFileStorage::ReadInt64(const AnsiString Name, __int64 Default)
  761. {
  762. __int64 Result = Default;
  763. AnsiString Str;
  764. Str = ReadStringRaw(Name, "");
  765. if (!Str.IsEmpty())
  766. {
  767. Result = StrToInt64Def(Str, Default);
  768. }
  769. return Result;
  770. }
  771. //---------------------------------------------------------------------------
  772. TDateTime __fastcall TIniFileStorage::ReadDateTime(const AnsiString Name, TDateTime Default)
  773. {
  774. TDateTime Result;
  775. AnsiString Value = FIniFile->ReadString(CurrentSection, Name, "");
  776. if (Value.IsEmpty())
  777. {
  778. Result = Default;
  779. }
  780. else
  781. {
  782. try
  783. {
  784. AnsiString Raw = HexToStr(Value);
  785. if (Raw.Length() == sizeof(Result))
  786. {
  787. memcpy(&Result, Raw.c_str(), sizeof(Result));
  788. }
  789. else
  790. {
  791. Result = StrToDateTime(Value);
  792. }
  793. }
  794. catch(...)
  795. {
  796. Result = Default;
  797. }
  798. }
  799. return Result;
  800. }
  801. //---------------------------------------------------------------------------
  802. double __fastcall TIniFileStorage::ReadFloat(const AnsiString Name, double Default)
  803. {
  804. double Result;
  805. AnsiString Value = FIniFile->ReadString(CurrentSection, Name, "");
  806. if (Value.IsEmpty())
  807. {
  808. Result = Default;
  809. }
  810. else
  811. {
  812. try
  813. {
  814. AnsiString Raw = HexToStr(Value);
  815. if (Raw.Length() == sizeof(Result))
  816. {
  817. memcpy(&Result, Raw.c_str(), sizeof(Result));
  818. }
  819. else
  820. {
  821. Result = StrToFloat(Value);
  822. }
  823. }
  824. catch(...)
  825. {
  826. Result = Default;
  827. }
  828. }
  829. return Result;
  830. }
  831. //---------------------------------------------------------------------------
  832. AnsiString __fastcall TIniFileStorage::ReadStringRaw(const AnsiString Name, AnsiString Default)
  833. {
  834. return FIniFile->ReadString(CurrentSection, Name, Default);
  835. }
  836. //---------------------------------------------------------------------------
  837. int __fastcall TIniFileStorage::ReadBinaryData(const AnsiString Name,
  838. void * Buffer, int Size)
  839. {
  840. AnsiString Value = HexToStr(ReadStringRaw(Name, ""));
  841. int Len = Value.Length();
  842. if (Size > Len)
  843. {
  844. Size = Len;
  845. }
  846. assert(Buffer);
  847. memcpy(Buffer, Value.c_str(), Size);
  848. return Size;
  849. }
  850. //---------------------------------------------------------------------------
  851. void __fastcall TIniFileStorage::WriteBool(const AnsiString Name, bool Value)
  852. {
  853. FIniFile->WriteBool(CurrentSection, Name, Value);
  854. }
  855. //---------------------------------------------------------------------------
  856. void __fastcall TIniFileStorage::WriteInteger(const AnsiString Name, int Value)
  857. {
  858. FIniFile->WriteInteger(CurrentSection, Name, Value);
  859. }
  860. //---------------------------------------------------------------------------
  861. void __fastcall TIniFileStorage::WriteInt64(const AnsiString Name, __int64 Value)
  862. {
  863. WriteStringRaw(Name, IntToStr(Value));
  864. }
  865. //---------------------------------------------------------------------------
  866. void __fastcall TIniFileStorage::WriteDateTime(const AnsiString Name, TDateTime Value)
  867. {
  868. WriteBinaryData(Name, &Value, sizeof(Value));
  869. }
  870. //---------------------------------------------------------------------------
  871. void __fastcall TIniFileStorage::WriteFloat(const AnsiString Name, double Value)
  872. {
  873. WriteBinaryData(Name, &Value, sizeof(Value));
  874. }
  875. //---------------------------------------------------------------------------
  876. void __fastcall TIniFileStorage::WriteStringRaw(const AnsiString Name, const AnsiString Value)
  877. {
  878. FIniFile->WriteString(CurrentSection, Name, Value);
  879. }
  880. //---------------------------------------------------------------------------
  881. void __fastcall TIniFileStorage::WriteBinaryData(const AnsiString Name,
  882. const void * Buffer, int Size)
  883. {
  884. WriteStringRaw(Name, StrToHex(AnsiString(static_cast<const char*>(Buffer), Size)));
  885. }