HierarchicalStorage.cpp 28 KB

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