HierarchicalStorage.cpp 29 KB

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