HierarchicalStorage.cpp 29 KB

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