HierarchicalStorage.cpp 27 KB

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