Configuration.cpp 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include <FileInfo.h>
  5. #include "Common.h"
  6. #include "Exceptions.h"
  7. #include "Configuration.h"
  8. #include "PuttyIntf.h"
  9. #include "TextsCore.h"
  10. #include "Interface.h"
  11. #include "CoreMain.h"
  12. #include "Security.h"
  13. #include <shlobj.h>
  14. #include <System.IOUtils.hpp>
  15. //---------------------------------------------------------------------------
  16. #pragma package(smart_init)
  17. //---------------------------------------------------------------------------
  18. __fastcall TConfiguration::TConfiguration()
  19. {
  20. FCriticalSection = new TCriticalSection();
  21. FUpdating = 0;
  22. FStorage = stDetect;
  23. FDontSave = false;
  24. FApplicationInfo = NULL;
  25. FUsage = new TUsage(this);
  26. FDefaultCollectUsage = false;
  27. wchar_t Buf[10];
  28. UnicodeString RandomSeedPath;
  29. if (GetEnvironmentVariable(L"APPDATA", Buf, LENOF(Buf)) > 0)
  30. {
  31. RandomSeedPath = L"%APPDATA%";
  32. }
  33. else
  34. {
  35. RandomSeedPath = GetShellFolderPath(CSIDL_LOCAL_APPDATA);
  36. if (RandomSeedPath.IsEmpty())
  37. {
  38. RandomSeedPath = GetShellFolderPath(CSIDL_APPDATA);
  39. }
  40. }
  41. FDefaultRandomSeedFile = IncludeTrailingBackslash(RandomSeedPath) + L"winscp.rnd";
  42. }
  43. //---------------------------------------------------------------------------
  44. void __fastcall TConfiguration::Default()
  45. {
  46. TGuard Guard(FCriticalSection);
  47. FDisablePasswordStoring = false;
  48. FForceBanners = false;
  49. FDisableAcceptingHostKeys = false;
  50. TRegistryStorage * AdminStorage;
  51. AdminStorage = new TRegistryStorage(RegistryStorageKey, HKEY_LOCAL_MACHINE);
  52. try
  53. {
  54. if (AdminStorage->OpenRootKey(false))
  55. {
  56. LoadAdmin(AdminStorage);
  57. AdminStorage->CloseSubKey();
  58. }
  59. }
  60. __finally
  61. {
  62. delete AdminStorage;
  63. }
  64. RandomSeedFile = FDefaultRandomSeedFile;
  65. PuttyRegistryStorageKey = OriginalPuttyRegistryStorageKey;
  66. FConfirmOverwriting = true;
  67. FConfirmResume = true;
  68. FAutoReadDirectoryAfterOp = true;
  69. FSessionReopenAuto = 5000;
  70. FSessionReopenBackground = 2000;
  71. FSessionReopenTimeout = 0;
  72. FSessionReopenAutoStall = 60000;
  73. FTunnelLocalPortNumberLow = 50000;
  74. FTunnelLocalPortNumberHigh = 50099;
  75. FCacheDirectoryChangesMaxSize = 100;
  76. FShowFtpWelcomeMessage = false;
  77. FExternalIpAddress = L"";
  78. FTryFtpWhenSshFails = true;
  79. CollectUsage = FDefaultCollectUsage;
  80. FLogging = false;
  81. FPermanentLogging = false;
  82. FLogFileName = DefaultLogFileName;
  83. FPermanentLogFileName = FLogFileName;
  84. FLogFileAppend = true;
  85. FLogWindowLines = 100;
  86. FLogProtocol = 0;
  87. UpdateActualLogProtocol();
  88. FLogActions = false;
  89. FPermanentLogActions = false;
  90. FActionsLogFileName = L"%TEMP%\\!S.xml";
  91. FPermanentActionsLogFileName = FActionsLogFileName;
  92. FProgramIniPathWrittable = -1;
  93. Changed();
  94. }
  95. //---------------------------------------------------------------------------
  96. __fastcall TConfiguration::~TConfiguration()
  97. {
  98. assert(!FUpdating);
  99. if (FApplicationInfo) FreeFileInfo(FApplicationInfo);
  100. delete FCriticalSection;
  101. delete FUsage;
  102. }
  103. //---------------------------------------------------------------------------
  104. THierarchicalStorage * TConfiguration::CreateScpStorage(bool /*SessionList*/)
  105. {
  106. if (Storage == stRegistry)
  107. {
  108. return new TRegistryStorage(RegistryStorageKey);
  109. }
  110. else if (Storage == stNul)
  111. {
  112. return new TIniFileStorage(L"nul");
  113. }
  114. else
  115. {
  116. return new TIniFileStorage(IniFileStorageName);
  117. }
  118. }
  119. //---------------------------------------------------------------------------
  120. UnicodeString __fastcall TConfiguration::PropertyToKey(const UnicodeString & Property)
  121. {
  122. // no longer useful
  123. int P = Property.LastDelimiter(L".>");
  124. return Property.SubString(P + 1, Property.Length() - P);
  125. }
  126. //---------------------------------------------------------------------------
  127. #define BLOCK(KEY, CANCREATE, BLOCK) \
  128. if (Storage->OpenSubKey(KEY, CANCREATE, true)) try { BLOCK } __finally { Storage->CloseSubKey(); }
  129. #define KEY(TYPE, VAR) KEYEX(TYPE, VAR, PropertyToKey(TEXT(#VAR)))
  130. #define REGCONFIG(CANCREATE) \
  131. BLOCK(L"Interface", CANCREATE, \
  132. KEY(String, RandomSeedFile); \
  133. KEY(String, PuttyRegistryStorageKey); \
  134. KEY(Bool, ConfirmOverwriting); \
  135. KEY(Bool, ConfirmResume); \
  136. KEY(Bool, AutoReadDirectoryAfterOp); \
  137. KEY(Integer, SessionReopenAuto); \
  138. KEY(Integer, SessionReopenBackground); \
  139. KEY(Integer, SessionReopenTimeout); \
  140. KEY(Integer, SessionReopenAutoStall); \
  141. KEY(Integer, TunnelLocalPortNumberLow); \
  142. KEY(Integer, TunnelLocalPortNumberHigh); \
  143. KEY(Integer, CacheDirectoryChangesMaxSize); \
  144. KEY(Bool, ShowFtpWelcomeMessage); \
  145. KEY(String, ExternalIpAddress); \
  146. KEY(Bool, TryFtpWhenSshFails); \
  147. KEY(Bool, CollectUsage); \
  148. ); \
  149. BLOCK(L"Logging", CANCREATE, \
  150. KEYEX(Bool, PermanentLogging, L"Logging"); \
  151. KEYEX(String,PermanentLogFileName, L"LogFileName"); \
  152. KEY(Bool, LogFileAppend); \
  153. KEY(Integer, LogWindowLines); \
  154. KEY(Integer, LogProtocol); \
  155. KEYEX(Bool, PermanentLogActions, L"LogActions"); \
  156. KEYEX(String,PermanentActionsLogFileName, L"ActionsLogFileName"); \
  157. );
  158. //---------------------------------------------------------------------------
  159. void __fastcall TConfiguration::SaveData(THierarchicalStorage * Storage, bool /*All*/)
  160. {
  161. #define KEYEX(TYPE, VAR, NAME) Storage->Write ## TYPE(NAME, VAR)
  162. REGCONFIG(true);
  163. #undef KEYEX
  164. if (Storage->OpenSubKey(L"Usage", true))
  165. {
  166. FUsage->Save(Storage);
  167. Storage->CloseSubKey();
  168. }
  169. }
  170. //---------------------------------------------------------------------------
  171. void __fastcall TConfiguration::Save()
  172. {
  173. // only modified, implicit
  174. DoSave(false, false);
  175. }
  176. //---------------------------------------------------------------------------
  177. void __fastcall TConfiguration::SaveExplicit()
  178. {
  179. // only modified, explicit
  180. DoSave(false, true);
  181. }
  182. //---------------------------------------------------------------------------
  183. void __fastcall TConfiguration::DoSave(bool All, bool Explicit)
  184. {
  185. if (FDontSave) return;
  186. THierarchicalStorage * AStorage = CreateScpStorage(false);
  187. try
  188. {
  189. AStorage->AccessMode = smReadWrite;
  190. AStorage->Explicit = Explicit;
  191. if (AStorage->OpenSubKey(ConfigurationSubKey, true))
  192. {
  193. SaveData(AStorage, All);
  194. }
  195. }
  196. __finally
  197. {
  198. delete AStorage;
  199. }
  200. Saved();
  201. if (All)
  202. {
  203. StoredSessions->Save(true, Explicit);
  204. }
  205. // clean up as last, so that if it fails (read only INI), the saving can proceed
  206. if (Storage == stRegistry)
  207. {
  208. CleanupIniFile();
  209. }
  210. }
  211. //---------------------------------------------------------------------------
  212. void __fastcall TConfiguration::Export(const UnicodeString & FileName)
  213. {
  214. THierarchicalStorage * Storage = NULL;
  215. THierarchicalStorage * ExportStorage = NULL;
  216. try
  217. {
  218. ExportStorage = new TIniFileStorage(FileName);
  219. ExportStorage->AccessMode = smReadWrite;
  220. ExportStorage->Explicit = true;
  221. Storage = CreateScpStorage(false);
  222. Storage->AccessMode = smRead;
  223. CopyData(Storage, ExportStorage);
  224. if (ExportStorage->OpenSubKey(ConfigurationSubKey, true))
  225. {
  226. SaveData(ExportStorage, true);
  227. }
  228. }
  229. __finally
  230. {
  231. delete ExportStorage;
  232. delete Storage;
  233. }
  234. StoredSessions->Export(FileName);
  235. }
  236. //---------------------------------------------------------------------------
  237. void __fastcall TConfiguration::Import(const UnicodeString & FileName)
  238. {
  239. THierarchicalStorage * Storage = NULL;
  240. THierarchicalStorage * ImportStorage = NULL;
  241. try
  242. {
  243. ImportStorage = new TIniFileStorage(FileName);
  244. ImportStorage->AccessMode = smRead;
  245. Storage = CreateScpStorage(false);
  246. Storage->AccessMode = smReadWrite;
  247. Storage->Explicit = true;
  248. CopyData(ImportStorage, Storage);
  249. Default();
  250. LoadFrom(ImportStorage);
  251. if (ImportStorage->OpenSubKey(Configuration->StoredSessionsSubKey, false))
  252. {
  253. StoredSessions->Clear();
  254. StoredSessions->DefaultSettings->Default();
  255. StoredSessions->Load(ImportStorage);
  256. }
  257. }
  258. __finally
  259. {
  260. delete ImportStorage;
  261. delete Storage;
  262. }
  263. // save all and explicit
  264. DoSave(true, true);
  265. }
  266. //---------------------------------------------------------------------------
  267. void __fastcall TConfiguration::LoadData(THierarchicalStorage * Storage)
  268. {
  269. #define KEYEX(TYPE, VAR, NAME) VAR = Storage->Read ## TYPE(NAME, VAR)
  270. #pragma warn -eas
  271. REGCONFIG(false);
  272. #pragma warn +eas
  273. #undef KEYEX
  274. if (Storage->OpenSubKey(L"Usage", false))
  275. {
  276. FUsage->Load(Storage);
  277. Storage->CloseSubKey();
  278. }
  279. if (FPermanentLogActions && FPermanentActionsLogFileName.IsEmpty() &&
  280. FPermanentLogging && !FPermanentLogFileName.IsEmpty())
  281. {
  282. FPermanentActionsLogFileName = FPermanentLogFileName;
  283. FPermanentLogging = false;
  284. FPermanentLogFileName = L"";
  285. }
  286. }
  287. //---------------------------------------------------------------------------
  288. void __fastcall TConfiguration::LoadAdmin(THierarchicalStorage * Storage)
  289. {
  290. FDisablePasswordStoring = Storage->ReadBool(L"DisablePasswordStoring", FDisablePasswordStoring);
  291. FForceBanners = Storage->ReadBool(L"ForceBanners", FForceBanners);
  292. FDisableAcceptingHostKeys = Storage->ReadBool(L"DisableAcceptingHostKeys", FDisableAcceptingHostKeys);
  293. FDefaultCollectUsage = Storage->ReadBool(L"DefaultCollectUsage", FDefaultCollectUsage);
  294. }
  295. //---------------------------------------------------------------------------
  296. void __fastcall TConfiguration::LoadFrom(THierarchicalStorage * Storage)
  297. {
  298. if (Storage->OpenSubKey(ConfigurationSubKey, false))
  299. {
  300. LoadData(Storage);
  301. Storage->CloseSubKey();
  302. }
  303. }
  304. //---------------------------------------------------------------------------
  305. void __fastcall TConfiguration::Load()
  306. {
  307. TGuard Guard(FCriticalSection);
  308. THierarchicalStorage * Storage = CreateScpStorage(false);
  309. try
  310. {
  311. Storage->AccessMode = smRead;
  312. LoadFrom(Storage);
  313. }
  314. __finally
  315. {
  316. delete Storage;
  317. }
  318. }
  319. //---------------------------------------------------------------------------
  320. void __fastcall TConfiguration::CopyData(THierarchicalStorage * Source,
  321. THierarchicalStorage * Target)
  322. {
  323. TStrings * Names = new TStringList();
  324. try
  325. {
  326. if (Source->OpenSubKey(ConfigurationSubKey, false))
  327. {
  328. if (Target->OpenSubKey(ConfigurationSubKey, true))
  329. {
  330. if (Source->OpenSubKey(L"CDCache", false))
  331. {
  332. if (Target->OpenSubKey(L"CDCache", true))
  333. {
  334. Names->Clear();
  335. Source->GetValueNames(Names);
  336. for (int Index = 0; Index < Names->Count; Index++)
  337. {
  338. Target->WriteBinaryData(Names->Strings[Index],
  339. Source->ReadBinaryData(Names->Strings[Index]));
  340. }
  341. Target->CloseSubKey();
  342. }
  343. Source->CloseSubKey();
  344. }
  345. if (Source->OpenSubKey(L"Banners", false))
  346. {
  347. if (Target->OpenSubKey(L"Banners", true))
  348. {
  349. Names->Clear();
  350. Source->GetValueNames(Names);
  351. for (int Index = 0; Index < Names->Count; Index++)
  352. {
  353. Target->WriteString(Names->Strings[Index],
  354. Source->ReadString(Names->Strings[Index], L""));
  355. }
  356. Target->CloseSubKey();
  357. }
  358. Source->CloseSubKey();
  359. }
  360. Target->CloseSubKey();
  361. }
  362. Source->CloseSubKey();
  363. }
  364. if (Source->OpenSubKey(SshHostKeysSubKey, false))
  365. {
  366. if (Target->OpenSubKey(SshHostKeysSubKey, true))
  367. {
  368. Names->Clear();
  369. Source->GetValueNames(Names);
  370. for (int Index = 0; Index < Names->Count; Index++)
  371. {
  372. Target->WriteStringRaw(Names->Strings[Index],
  373. Source->ReadStringRaw(Names->Strings[Index], L""));
  374. }
  375. Target->CloseSubKey();
  376. }
  377. Source->CloseSubKey();
  378. }
  379. }
  380. __finally
  381. {
  382. delete Names;
  383. }
  384. }
  385. //---------------------------------------------------------------------------
  386. void __fastcall TConfiguration::LoadDirectoryChangesCache(const UnicodeString SessionKey,
  387. TRemoteDirectoryChangesCache * DirectoryChangesCache)
  388. {
  389. THierarchicalStorage * Storage = CreateScpStorage(false);
  390. try
  391. {
  392. Storage->AccessMode = smRead;
  393. if (Storage->OpenSubKey(ConfigurationSubKey, false) &&
  394. Storage->OpenSubKey(L"CDCache", false) &&
  395. Storage->ValueExists(SessionKey))
  396. {
  397. DirectoryChangesCache->Deserialize(Storage->ReadBinaryData(SessionKey));
  398. }
  399. }
  400. __finally
  401. {
  402. delete Storage;
  403. }
  404. }
  405. //---------------------------------------------------------------------------
  406. void __fastcall TConfiguration::SaveDirectoryChangesCache(const UnicodeString SessionKey,
  407. TRemoteDirectoryChangesCache * DirectoryChangesCache)
  408. {
  409. THierarchicalStorage * Storage = CreateScpStorage(false);
  410. try
  411. {
  412. Storage->AccessMode = smReadWrite;
  413. if (Storage->OpenSubKey(ConfigurationSubKey, true) &&
  414. Storage->OpenSubKey(L"CDCache", true))
  415. {
  416. UnicodeString Data;
  417. DirectoryChangesCache->Serialize(Data);
  418. Storage->WriteBinaryData(SessionKey, Data);
  419. }
  420. }
  421. __finally
  422. {
  423. delete Storage;
  424. }
  425. }
  426. //---------------------------------------------------------------------------
  427. UnicodeString __fastcall TConfiguration::BannerHash(const UnicodeString & Banner)
  428. {
  429. RawByteString Result;
  430. Result.SetLength(16);
  431. md5checksum(
  432. reinterpret_cast<const char*>(Banner.c_str()), Banner.Length() * sizeof(wchar_t),
  433. (unsigned char*)Result.c_str());
  434. return BytesToHex(Result);
  435. }
  436. //---------------------------------------------------------------------------
  437. bool __fastcall TConfiguration::ShowBanner(const UnicodeString SessionKey,
  438. const UnicodeString & Banner)
  439. {
  440. bool Result;
  441. THierarchicalStorage * Storage = CreateScpStorage(false);
  442. try
  443. {
  444. Storage->AccessMode = smRead;
  445. Result =
  446. !Storage->OpenSubKey(ConfigurationSubKey, false) ||
  447. !Storage->OpenSubKey(L"Banners", false) ||
  448. !Storage->ValueExists(SessionKey) ||
  449. (Storage->ReadString(SessionKey, L"") != BannerHash(Banner));
  450. }
  451. __finally
  452. {
  453. delete Storage;
  454. }
  455. return Result;
  456. }
  457. //---------------------------------------------------------------------------
  458. void __fastcall TConfiguration::NeverShowBanner(const UnicodeString SessionKey,
  459. const UnicodeString & Banner)
  460. {
  461. THierarchicalStorage * Storage = CreateScpStorage(false);
  462. try
  463. {
  464. Storage->AccessMode = smReadWrite;
  465. if (Storage->OpenSubKey(ConfigurationSubKey, true) &&
  466. Storage->OpenSubKey(L"Banners", true))
  467. {
  468. Storage->WriteString(SessionKey, BannerHash(Banner));
  469. }
  470. }
  471. __finally
  472. {
  473. delete Storage;
  474. }
  475. }
  476. //---------------------------------------------------------------------------
  477. void __fastcall TConfiguration::Changed()
  478. {
  479. if (FUpdating == 0)
  480. {
  481. if (OnChange)
  482. {
  483. OnChange(this);
  484. }
  485. }
  486. else
  487. {
  488. FChanged = true;
  489. }
  490. }
  491. //---------------------------------------------------------------------------
  492. void __fastcall TConfiguration::BeginUpdate()
  493. {
  494. if (FUpdating == 0)
  495. {
  496. FChanged = false;
  497. }
  498. FUpdating++;
  499. // Greater value would probably indicate some nesting problem in code
  500. assert(FUpdating < 6);
  501. }
  502. //---------------------------------------------------------------------------
  503. void __fastcall TConfiguration::EndUpdate()
  504. {
  505. assert(FUpdating > 0);
  506. FUpdating--;
  507. if ((FUpdating == 0) && FChanged)
  508. {
  509. FChanged = false;
  510. Changed();
  511. }
  512. }
  513. //---------------------------------------------------------------------------
  514. void __fastcall TConfiguration::CleanupConfiguration()
  515. {
  516. try
  517. {
  518. CleanupRegistry(ConfigurationSubKey);
  519. if (Storage == stRegistry)
  520. {
  521. FDontSave = true;
  522. }
  523. }
  524. catch (Exception &E)
  525. {
  526. throw ExtException(&E, LoadStr(CLEANUP_CONFIG_ERROR));
  527. }
  528. }
  529. //---------------------------------------------------------------------------
  530. void __fastcall TConfiguration::CleanupRegistry(UnicodeString CleanupSubKey)
  531. {
  532. TRegistryStorage *Registry = new TRegistryStorage(RegistryStorageKey);
  533. try
  534. {
  535. Registry->RecursiveDeleteSubKey(CleanupSubKey);
  536. }
  537. __finally
  538. {
  539. delete Registry;
  540. }
  541. }
  542. //---------------------------------------------------------------------------
  543. void __fastcall TConfiguration::CleanupHostKeys()
  544. {
  545. try
  546. {
  547. CleanupRegistry(SshHostKeysSubKey);
  548. }
  549. catch (Exception &E)
  550. {
  551. throw ExtException(&E, LoadStr(CLEANUP_HOSTKEYS_ERROR));
  552. }
  553. }
  554. //---------------------------------------------------------------------------
  555. void __fastcall TConfiguration::CleanupRandomSeedFile()
  556. {
  557. try
  558. {
  559. DontSaveRandomSeed();
  560. if (FileExists(RandomSeedFileName))
  561. {
  562. DeleteFileChecked(RandomSeedFileName);
  563. }
  564. }
  565. catch (Exception &E)
  566. {
  567. throw ExtException(&E, LoadStr(CLEANUP_SEEDFILE_ERROR));
  568. }
  569. }
  570. //---------------------------------------------------------------------------
  571. void __fastcall TConfiguration::CleanupIniFile()
  572. {
  573. try
  574. {
  575. if (FileExists(IniFileStorageNameForReading))
  576. {
  577. DeleteFileChecked(IniFileStorageNameForReading);
  578. }
  579. if (Storage == stIniFile)
  580. {
  581. FDontSave = true;
  582. }
  583. }
  584. catch (Exception &E)
  585. {
  586. throw ExtException(&E, LoadStr(CLEANUP_INIFILE_ERROR));
  587. }
  588. }
  589. //---------------------------------------------------------------------------
  590. RawByteString __fastcall TConfiguration::EncryptPassword(UnicodeString Password, UnicodeString Key)
  591. {
  592. if (Password.IsEmpty())
  593. {
  594. return RawByteString();
  595. }
  596. else
  597. {
  598. return ::EncryptPassword(Password, Key);
  599. }
  600. }
  601. //---------------------------------------------------------------------------
  602. UnicodeString __fastcall TConfiguration::DecryptPassword(RawByteString Password, UnicodeString Key)
  603. {
  604. if (Password.IsEmpty())
  605. {
  606. return UnicodeString();
  607. }
  608. else
  609. {
  610. return ::DecryptPassword(Password, Key);
  611. }
  612. }
  613. //---------------------------------------------------------------------------
  614. RawByteString __fastcall TConfiguration::StronglyRecryptPassword(RawByteString Password, UnicodeString /*Key*/)
  615. {
  616. return Password;
  617. }
  618. //---------------------------------------------------------------------------
  619. UnicodeString __fastcall TConfiguration::GetOSVersionStr()
  620. {
  621. UnicodeString Result;
  622. OSVERSIONINFO OSVersionInfo;
  623. OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVersionInfo);
  624. if (GetVersionEx(&OSVersionInfo) != 0)
  625. {
  626. Result = FORMAT(L"%d.%d.%d", (int(OSVersionInfo.dwMajorVersion),
  627. int(OSVersionInfo.dwMinorVersion), int(OSVersionInfo.dwBuildNumber)));
  628. UnicodeString CSDVersion = OSVersionInfo.szCSDVersion;
  629. if (!CSDVersion.IsEmpty())
  630. {
  631. Result += L" " + CSDVersion;
  632. }
  633. UnicodeString ProductName = WindowsProductName();
  634. if (!ProductName.IsEmpty())
  635. {
  636. Result += L" - " + ProductName;
  637. }
  638. }
  639. return Result;
  640. }
  641. //---------------------------------------------------------------------------
  642. TVSFixedFileInfo *__fastcall TConfiguration::GetFixedApplicationInfo()
  643. {
  644. return GetFixedFileInfo(ApplicationInfo);
  645. }
  646. //---------------------------------------------------------------------------
  647. int __fastcall TConfiguration::GetCompoundVersion()
  648. {
  649. TVSFixedFileInfo * FileInfo = FixedApplicationInfo;
  650. return CalculateCompoundVersion(
  651. HIWORD(FileInfo->dwFileVersionMS), LOWORD(FileInfo->dwFileVersionMS),
  652. HIWORD(FileInfo->dwFileVersionLS), LOWORD(FileInfo->dwFileVersionLS));
  653. }
  654. //---------------------------------------------------------------------------
  655. UnicodeString __fastcall TConfiguration::ModuleFileName()
  656. {
  657. return ParamStr(0);
  658. }
  659. //---------------------------------------------------------------------------
  660. void * __fastcall TConfiguration::GetFileApplicationInfo(const UnicodeString FileName)
  661. {
  662. void * Result;
  663. if (FileName.IsEmpty())
  664. {
  665. if (!FApplicationInfo)
  666. {
  667. FApplicationInfo = CreateFileInfo(ModuleFileName());
  668. }
  669. Result = FApplicationInfo;
  670. }
  671. else
  672. {
  673. Result = CreateFileInfo(FileName);
  674. }
  675. return Result;
  676. }
  677. //---------------------------------------------------------------------------
  678. void * __fastcall TConfiguration::GetApplicationInfo()
  679. {
  680. return GetFileApplicationInfo("");
  681. }
  682. //---------------------------------------------------------------------------
  683. UnicodeString __fastcall TConfiguration::GetFileProductName(const UnicodeString FileName)
  684. {
  685. return GetFileFileInfoString(L"ProductName", FileName);
  686. }
  687. //---------------------------------------------------------------------------
  688. UnicodeString __fastcall TConfiguration::GetFileCompanyName(const UnicodeString FileName)
  689. {
  690. return GetFileFileInfoString(L"CompanyName", FileName);
  691. }
  692. //---------------------------------------------------------------------------
  693. UnicodeString __fastcall TConfiguration::GetProductName()
  694. {
  695. return GetFileProductName(L"");
  696. }
  697. //---------------------------------------------------------------------------
  698. UnicodeString __fastcall TConfiguration::GetCompanyName()
  699. {
  700. return GetFileCompanyName(L"");
  701. }
  702. //---------------------------------------------------------------------------
  703. UnicodeString __fastcall TConfiguration::GetFileProductVersion(const UnicodeString FileName)
  704. {
  705. return TrimVersion(GetFileFileInfoString(L"ProductVersion", FileName));
  706. }
  707. //---------------------------------------------------------------------------
  708. UnicodeString __fastcall TConfiguration::GetFileDescription(const UnicodeString & FileName)
  709. {
  710. return GetFileFileInfoString(L"FileDescription", FileName);
  711. }
  712. //---------------------------------------------------------------------------
  713. UnicodeString __fastcall TConfiguration::GetProductVersion()
  714. {
  715. return GetFileProductVersion(L"");
  716. }
  717. //---------------------------------------------------------------------------
  718. UnicodeString __fastcall TConfiguration::TrimVersion(UnicodeString Version)
  719. {
  720. while ((Version.Pos(L".") != Version.LastDelimiter(L".")) &&
  721. (Version.SubString(Version.Length() - 1, 2) == L".0"))
  722. {
  723. Version.SetLength(Version.Length() - 2);
  724. }
  725. return Version;
  726. }
  727. //---------------------------------------------------------------------------
  728. UnicodeString __fastcall TConfiguration::GetVersionStr()
  729. {
  730. TGuard Guard(FCriticalSection);
  731. try
  732. {
  733. TVSFixedFileInfo * Info = FixedApplicationInfo;
  734. return FMTLOAD(VERSION, (
  735. HIWORD(Info->dwFileVersionMS),
  736. LOWORD(Info->dwFileVersionMS),
  737. HIWORD(Info->dwFileVersionLS),
  738. LOWORD(Info->dwFileVersionLS)));
  739. }
  740. catch (Exception &E)
  741. {
  742. throw ExtException(&E, L"Can't get application version");
  743. }
  744. }
  745. //---------------------------------------------------------------------------
  746. UnicodeString __fastcall TConfiguration::GetVersion()
  747. {
  748. TGuard Guard(FCriticalSection);
  749. try
  750. {
  751. TVSFixedFileInfo * Info = FixedApplicationInfo;
  752. UnicodeString Result;
  753. Result = TrimVersion(FORMAT(L"%d.%d.%d", (
  754. HIWORD(Info->dwFileVersionMS),
  755. LOWORD(Info->dwFileVersionMS),
  756. HIWORD(Info->dwFileVersionLS))));
  757. return Result;
  758. }
  759. catch (Exception &E)
  760. {
  761. throw ExtException(&E, L"Can't get application version");
  762. }
  763. }
  764. //---------------------------------------------------------------------------
  765. UnicodeString __fastcall TConfiguration::GetFileFileInfoString(const UnicodeString Key,
  766. const UnicodeString FileName)
  767. {
  768. TGuard Guard(FCriticalSection);
  769. UnicodeString Result;
  770. void * Info = GetFileApplicationInfo(FileName);
  771. try
  772. {
  773. if ((Info != NULL) && (GetTranslationCount(Info) > 0))
  774. {
  775. TTranslation Translation;
  776. Translation = GetTranslation(Info, 0);
  777. Result = ::GetFileInfoString(Info, Translation, Key);
  778. }
  779. else
  780. {
  781. assert(!FileName.IsEmpty());
  782. }
  783. }
  784. __finally
  785. {
  786. if (!FileName.IsEmpty())
  787. {
  788. FreeFileInfo(Info);
  789. }
  790. }
  791. return Result;
  792. }
  793. //---------------------------------------------------------------------------
  794. UnicodeString __fastcall TConfiguration::GetFileInfoString(const UnicodeString Key)
  795. {
  796. return GetFileFileInfoString(Key, L"");
  797. }
  798. //---------------------------------------------------------------------------
  799. UnicodeString __fastcall TConfiguration::GetRegistryStorageKey()
  800. {
  801. return GetRegistryKey();
  802. }
  803. //---------------------------------------------------------------------------
  804. void __fastcall TConfiguration::SetNulStorage()
  805. {
  806. FStorage = stNul;
  807. }
  808. //---------------------------------------------------------------------------
  809. void __fastcall TConfiguration::SetDefaultStorage()
  810. {
  811. FStorage = stDetect;
  812. }
  813. //---------------------------------------------------------------------------
  814. void __fastcall TConfiguration::SetIniFileStorageName(UnicodeString value)
  815. {
  816. FIniFileStorageName = value;
  817. FStorage = stIniFile;
  818. }
  819. //---------------------------------------------------------------------------
  820. UnicodeString __fastcall TConfiguration::GetIniFileStorageNameForReading()
  821. {
  822. return GetIniFileStorageName(true);
  823. }
  824. //---------------------------------------------------------------------------
  825. UnicodeString __fastcall TConfiguration::GetIniFileStorageNameForReadingWritting()
  826. {
  827. return GetIniFileStorageName(false);
  828. }
  829. //---------------------------------------------------------------------------
  830. UnicodeString __fastcall TConfiguration::GetIniFileStorageName(bool ReadingOnly)
  831. {
  832. if (FIniFileStorageName.IsEmpty())
  833. {
  834. UnicodeString ProgramPath = ParamStr(0);
  835. UnicodeString ProgramIniPath = ChangeFileExt(ProgramPath, L".ini");
  836. UnicodeString IniPath;
  837. if (FileExists(ProgramIniPath))
  838. {
  839. IniPath = ProgramIniPath;
  840. }
  841. else
  842. {
  843. UnicodeString AppDataIniPath =
  844. IncludeTrailingBackslash(GetShellFolderPath(CSIDL_APPDATA)) +
  845. ExtractFileName(ProgramIniPath);
  846. if (FileExists(AppDataIniPath))
  847. {
  848. IniPath = AppDataIniPath;
  849. }
  850. else
  851. {
  852. // avoid expensive test if we are interested in existing files only
  853. if (!ReadingOnly && (FProgramIniPathWrittable < 0))
  854. {
  855. UnicodeString ProgramDir = ExtractFilePath(ProgramPath);
  856. FProgramIniPathWrittable = IsDirectoryWriteable(ProgramDir) ? 1 : 0;
  857. }
  858. // does not really matter what we return when < 0
  859. IniPath = (FProgramIniPathWrittable == 0) ? AppDataIniPath : ProgramIniPath;
  860. }
  861. }
  862. if (FVirtualIniFileStorageName.IsEmpty() &&
  863. TPath::IsDriveRooted(IniPath))
  864. {
  865. UnicodeString LocalAppDataPath = GetShellFolderPath(CSIDL_LOCAL_APPDATA);
  866. // virtual store for non-system drives have a different virtual store,
  867. // do not bother about them
  868. if (TPath::IsDriveRooted(LocalAppDataPath) &&
  869. SameText(ExtractFileDrive(IniPath), ExtractFileDrive(LocalAppDataPath)))
  870. {
  871. FVirtualIniFileStorageName =
  872. IncludeTrailingBackslash(LocalAppDataPath) +
  873. L"VirtualStore\\" +
  874. IniPath.SubString(4, IniPath.Length() - 3);
  875. }
  876. }
  877. if (!FVirtualIniFileStorageName.IsEmpty() &&
  878. FileExists(FVirtualIniFileStorageName))
  879. {
  880. return FVirtualIniFileStorageName;
  881. }
  882. else
  883. {
  884. return IniPath;
  885. }
  886. }
  887. else
  888. {
  889. return FIniFileStorageName;
  890. }
  891. }
  892. //---------------------------------------------------------------------------
  893. UnicodeString __fastcall TConfiguration::GetPuttySessionsKey()
  894. {
  895. return PuttyRegistryStorageKey + L"\\Sessions";
  896. }
  897. //---------------------------------------------------------------------------
  898. UnicodeString __fastcall TConfiguration::GetStoredSessionsSubKey()
  899. {
  900. return L"Sessions";
  901. }
  902. //---------------------------------------------------------------------------
  903. UnicodeString __fastcall TConfiguration::GetSshHostKeysSubKey()
  904. {
  905. return L"SshHostKeys";
  906. }
  907. //---------------------------------------------------------------------------
  908. UnicodeString __fastcall TConfiguration::GetConfigurationSubKey()
  909. {
  910. return L"Configuration";
  911. }
  912. //---------------------------------------------------------------------------
  913. UnicodeString __fastcall TConfiguration::GetRootKeyStr()
  914. {
  915. return RootKeyToStr(HKEY_CURRENT_USER);
  916. }
  917. //---------------------------------------------------------------------------
  918. void __fastcall TConfiguration::SetStorage(TStorage value)
  919. {
  920. if (FStorage != value)
  921. {
  922. TStorage StorageBak = FStorage;
  923. try
  924. {
  925. THierarchicalStorage * SourceStorage = NULL;
  926. THierarchicalStorage * TargetStorage = NULL;
  927. try
  928. {
  929. SourceStorage = CreateScpStorage(false);
  930. SourceStorage->AccessMode = smRead;
  931. FStorage = value;
  932. TargetStorage = CreateScpStorage(false);
  933. TargetStorage->AccessMode = smReadWrite;
  934. TargetStorage->Explicit = true;
  935. // copy before save as it removes the ini file,
  936. // when switching from ini to registry
  937. CopyData(SourceStorage, TargetStorage);
  938. }
  939. __finally
  940. {
  941. delete SourceStorage;
  942. delete TargetStorage;
  943. }
  944. // save all and explicit,
  945. // this also removes an INI file, when switching to registry storage
  946. DoSave(true, true);
  947. }
  948. catch (...)
  949. {
  950. // If this fails, do not pretend that storage was switched.
  951. // For instance:
  952. // - When writting to an IFI file fails (unlikely, as we fallsback to user profile)
  953. // - When removing INI file fails, when switching to registry
  954. // (possible, when the INI file is in Program files folder)
  955. FStorage = StorageBak;
  956. throw;
  957. }
  958. }
  959. }
  960. //---------------------------------------------------------------------------
  961. void __fastcall TConfiguration::Saved()
  962. {
  963. // nothing
  964. }
  965. //---------------------------------------------------------------------------
  966. TStorage __fastcall TConfiguration::GetStorage()
  967. {
  968. if (FStorage == stDetect)
  969. {
  970. if (FileExists(IniFileStorageNameForReading))
  971. {
  972. FStorage = stIniFile;
  973. }
  974. else
  975. {
  976. FStorage = stRegistry;
  977. }
  978. }
  979. return FStorage;
  980. }
  981. //---------------------------------------------------------------------------
  982. void __fastcall TConfiguration::SetRandomSeedFile(UnicodeString value)
  983. {
  984. if (RandomSeedFile != value)
  985. {
  986. UnicodeString PrevRandomSeedFileName = RandomSeedFileName;
  987. FRandomSeedFile = value;
  988. // never allow empty seed file to avoid Putty trying to reinitialize the path
  989. if (RandomSeedFileName.IsEmpty())
  990. {
  991. FRandomSeedFile = FDefaultRandomSeedFile;
  992. }
  993. if (!PrevRandomSeedFileName.IsEmpty() &&
  994. (PrevRandomSeedFileName != RandomSeedFileName) &&
  995. FileExists(PrevRandomSeedFileName))
  996. {
  997. // ignore any error
  998. DeleteFile(PrevRandomSeedFileName);
  999. }
  1000. }
  1001. }
  1002. //---------------------------------------------------------------------
  1003. UnicodeString __fastcall TConfiguration::GetRandomSeedFileName()
  1004. {
  1005. return StripPathQuotes(ExpandEnvironmentVariables(FRandomSeedFile)).Trim();
  1006. }
  1007. //---------------------------------------------------------------------
  1008. void __fastcall TConfiguration::SetExternalIpAddress(UnicodeString value)
  1009. {
  1010. SET_CONFIG_PROPERTY(ExternalIpAddress);
  1011. }
  1012. //---------------------------------------------------------------------
  1013. void __fastcall TConfiguration::SetTryFtpWhenSshFails(bool value)
  1014. {
  1015. SET_CONFIG_PROPERTY(TryFtpWhenSshFails);
  1016. }
  1017. //---------------------------------------------------------------------
  1018. void __fastcall TConfiguration::SetPuttyRegistryStorageKey(UnicodeString value)
  1019. {
  1020. SET_CONFIG_PROPERTY(PuttyRegistryStorageKey);
  1021. }
  1022. //---------------------------------------------------------------------------
  1023. TEOLType __fastcall TConfiguration::GetLocalEOLType()
  1024. {
  1025. return eolCRLF;
  1026. }
  1027. //---------------------------------------------------------------------
  1028. bool __fastcall TConfiguration::GetCollectUsage()
  1029. {
  1030. return FUsage->Collect;
  1031. }
  1032. //---------------------------------------------------------------------
  1033. void __fastcall TConfiguration::SetCollectUsage(bool value)
  1034. {
  1035. FUsage->Collect = value;
  1036. }
  1037. //---------------------------------------------------------------------
  1038. void __fastcall TConfiguration::TemporaryLogging(const UnicodeString ALogFileName)
  1039. {
  1040. if (SameText(ExtractFileExt(ALogFileName), L".xml"))
  1041. {
  1042. TemporaryActionsLogging(ALogFileName);
  1043. }
  1044. else
  1045. {
  1046. FLogging = true;
  1047. FLogFileName = ALogFileName;
  1048. UpdateActualLogProtocol();
  1049. }
  1050. }
  1051. //---------------------------------------------------------------------
  1052. void __fastcall TConfiguration::TemporaryActionsLogging(const UnicodeString ALogFileName)
  1053. {
  1054. FLogActions = true;
  1055. FActionsLogFileName = ALogFileName;
  1056. }
  1057. //---------------------------------------------------------------------
  1058. void __fastcall TConfiguration::SetLogging(bool value)
  1059. {
  1060. if (Logging != value)
  1061. {
  1062. FPermanentLogging = value;
  1063. FLogging = value;
  1064. UpdateActualLogProtocol();
  1065. Changed();
  1066. }
  1067. }
  1068. //---------------------------------------------------------------------
  1069. void __fastcall TConfiguration::SetLogFileName(UnicodeString value)
  1070. {
  1071. if (LogFileName != value)
  1072. {
  1073. FPermanentLogFileName = value;
  1074. FLogFileName = value;
  1075. Changed();
  1076. }
  1077. }
  1078. //---------------------------------------------------------------------
  1079. void __fastcall TConfiguration::SetActionsLogFileName(UnicodeString value)
  1080. {
  1081. if (ActionsLogFileName != value)
  1082. {
  1083. FPermanentActionsLogFileName = value;
  1084. FActionsLogFileName = value;
  1085. Changed();
  1086. }
  1087. }
  1088. //---------------------------------------------------------------------
  1089. bool __fastcall TConfiguration::GetLogToFile()
  1090. {
  1091. return !LogFileName.IsEmpty();
  1092. }
  1093. //---------------------------------------------------------------------
  1094. void __fastcall TConfiguration::UpdateActualLogProtocol()
  1095. {
  1096. FActualLogProtocol = FLogging ? FLogProtocol : 0;
  1097. }
  1098. //---------------------------------------------------------------------
  1099. void __fastcall TConfiguration::SetLogProtocol(int value)
  1100. {
  1101. SET_CONFIG_PROPERTY(LogProtocol);
  1102. UpdateActualLogProtocol();
  1103. }
  1104. //---------------------------------------------------------------------
  1105. void __fastcall TConfiguration::SetLogActions(bool value)
  1106. {
  1107. if (LogActions != value)
  1108. {
  1109. FPermanentLogActions = value;
  1110. FLogActions = value;
  1111. Changed();
  1112. }
  1113. }
  1114. //---------------------------------------------------------------------
  1115. void __fastcall TConfiguration::SetLogFileAppend(bool value)
  1116. {
  1117. SET_CONFIG_PROPERTY(LogFileAppend);
  1118. }
  1119. //---------------------------------------------------------------------
  1120. void __fastcall TConfiguration::SetLogWindowLines(int value)
  1121. {
  1122. SET_CONFIG_PROPERTY(LogWindowLines);
  1123. }
  1124. //---------------------------------------------------------------------
  1125. void __fastcall TConfiguration::SetLogWindowComplete(bool value)
  1126. {
  1127. if (value != LogWindowComplete)
  1128. {
  1129. LogWindowLines = value ? 0 : 50;
  1130. Changed();
  1131. }
  1132. }
  1133. //---------------------------------------------------------------------
  1134. bool __fastcall TConfiguration::GetLogWindowComplete()
  1135. {
  1136. return (bool)(LogWindowLines == 0);
  1137. }
  1138. //---------------------------------------------------------------------
  1139. UnicodeString __fastcall TConfiguration::GetDefaultLogFileName()
  1140. {
  1141. return L"%TEMP%\\!S.log";
  1142. }
  1143. //---------------------------------------------------------------------------
  1144. void __fastcall TConfiguration::SetConfirmOverwriting(bool value)
  1145. {
  1146. TGuard Guard(FCriticalSection);
  1147. SET_CONFIG_PROPERTY(ConfirmOverwriting);
  1148. }
  1149. //---------------------------------------------------------------------------
  1150. bool __fastcall TConfiguration::GetConfirmOverwriting()
  1151. {
  1152. TGuard Guard(FCriticalSection);
  1153. return FConfirmOverwriting;
  1154. }
  1155. //---------------------------------------------------------------------------
  1156. void __fastcall TConfiguration::SetConfirmResume(bool value)
  1157. {
  1158. TGuard Guard(FCriticalSection);
  1159. SET_CONFIG_PROPERTY(ConfirmResume);
  1160. }
  1161. //---------------------------------------------------------------------------
  1162. bool __fastcall TConfiguration::GetConfirmResume()
  1163. {
  1164. TGuard Guard(FCriticalSection);
  1165. return FConfirmResume;
  1166. }
  1167. //---------------------------------------------------------------------------
  1168. void __fastcall TConfiguration::SetAutoReadDirectoryAfterOp(bool value)
  1169. {
  1170. TGuard Guard(FCriticalSection);
  1171. SET_CONFIG_PROPERTY(AutoReadDirectoryAfterOp);
  1172. }
  1173. //---------------------------------------------------------------------------
  1174. bool __fastcall TConfiguration::GetAutoReadDirectoryAfterOp()
  1175. {
  1176. TGuard Guard(FCriticalSection);
  1177. return FAutoReadDirectoryAfterOp;
  1178. }
  1179. //---------------------------------------------------------------------------
  1180. UnicodeString __fastcall TConfiguration::GetTimeFormat()
  1181. {
  1182. return L"h:nn:ss";
  1183. }
  1184. //---------------------------------------------------------------------------
  1185. UnicodeString __fastcall TConfiguration::GetPartialExt() const
  1186. {
  1187. return PARTIAL_EXT;
  1188. }
  1189. //---------------------------------------------------------------------------
  1190. UnicodeString __fastcall TConfiguration::GetDefaultKeyFile()
  1191. {
  1192. return L"";
  1193. }
  1194. //---------------------------------------------------------------------------
  1195. bool __fastcall TConfiguration::GetRememberPassword()
  1196. {
  1197. return false;
  1198. }
  1199. //---------------------------------------------------------------------------
  1200. void __fastcall TConfiguration::SetSessionReopenAuto(int value)
  1201. {
  1202. SET_CONFIG_PROPERTY(SessionReopenAuto);
  1203. }
  1204. //---------------------------------------------------------------------------
  1205. void __fastcall TConfiguration::SetSessionReopenBackground(int value)
  1206. {
  1207. SET_CONFIG_PROPERTY(SessionReopenBackground);
  1208. }
  1209. //---------------------------------------------------------------------------
  1210. void __fastcall TConfiguration::SetSessionReopenTimeout(int value)
  1211. {
  1212. SET_CONFIG_PROPERTY(SessionReopenTimeout);
  1213. }
  1214. //---------------------------------------------------------------------------
  1215. void __fastcall TConfiguration::SetSessionReopenAutoStall(int value)
  1216. {
  1217. SET_CONFIG_PROPERTY(SessionReopenAutoStall);
  1218. }
  1219. //---------------------------------------------------------------------------
  1220. void __fastcall TConfiguration::SetTunnelLocalPortNumberLow(int value)
  1221. {
  1222. SET_CONFIG_PROPERTY(TunnelLocalPortNumberLow);
  1223. }
  1224. //---------------------------------------------------------------------------
  1225. void __fastcall TConfiguration::SetTunnelLocalPortNumberHigh(int value)
  1226. {
  1227. SET_CONFIG_PROPERTY(TunnelLocalPortNumberHigh);
  1228. }
  1229. //---------------------------------------------------------------------------
  1230. void __fastcall TConfiguration::SetCacheDirectoryChangesMaxSize(int value)
  1231. {
  1232. SET_CONFIG_PROPERTY(CacheDirectoryChangesMaxSize);
  1233. }
  1234. //---------------------------------------------------------------------------
  1235. void __fastcall TConfiguration::SetShowFtpWelcomeMessage(bool value)
  1236. {
  1237. SET_CONFIG_PROPERTY(ShowFtpWelcomeMessage);
  1238. }
  1239. //---------------------------------------------------------------------------
  1240. //---------------------------------------------------------------------------
  1241. void __fastcall TShortCuts::Add(TShortCut ShortCut)
  1242. {
  1243. FShortCuts.insert(ShortCut);
  1244. }
  1245. //---------------------------------------------------------------------------
  1246. bool __fastcall TShortCuts::Has(TShortCut ShortCut) const
  1247. {
  1248. return (FShortCuts.count(ShortCut) != 0);
  1249. }