| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388 | //---------------------------------------------------------------------------#include <vcl.h>#pragma hdrstop#include <FileInfo.h>#include "Common.h"#include "Exceptions.h"#include "Configuration.h"#include "PuttyIntf.h"#include "TextsCore.h"#include "Interface.h"#include "CoreMain.h"#include "Security.h"#include "FileMasks.h"#include "CopyParam.h"#include <shlobj.h>#include <System.IOUtils.hpp>#include <System.StrUtils.hpp>#include <System.DateUtils.hpp>//---------------------------------------------------------------------------#pragma package(smart_init)//---------------------------------------------------------------------------const wchar_t * AutoSwitchNames = L"On;Off;Auto";const wchar_t * NotAutoSwitchNames = L"Off;On;Auto";//---------------------------------------------------------------------------// See https://www.iana.org/assignments/hash-function-text-names/hash-function-text-names.xhtmlconst UnicodeString Sha1ChecksumAlg(L"sha-1");const UnicodeString Sha224ChecksumAlg(L"sha-224");const UnicodeString Sha256ChecksumAlg(L"sha-256");const UnicodeString Sha384ChecksumAlg(L"sha-384");const UnicodeString Sha512ChecksumAlg(L"sha-512");const UnicodeString Md5ChecksumAlg(L"md5");// Not defined by IANAconst UnicodeString Crc32ChecksumAlg(L"crc32");//---------------------------------------------------------------------------const UnicodeString SshFingerprintType(L"ssh");const UnicodeString TlsFingerprintType(L"tls");//---------------------------------------------------------------------------const UnicodeString FtpsCertificateStorageKey(L"FtpsCertificates");const UnicodeString HttpsCertificateStorageKey(L"HttpsCertificates");const UnicodeString LastFingerprintsStorageKey(L"LastFingerprints");const UnicodeString DirectoryStatisticsCacheKey(L"DirectoryStatisticsCache");const UnicodeString SshHostCAsKey(L"SshHostCAs");const UnicodeString CDCacheKey(L"CDCache");const UnicodeString BannersKey(L"Banners");//---------------------------------------------------------------------------const UnicodeString OpensshFolderName(L".ssh");const UnicodeString OpensshAuthorizedKeysFileName(L"authorized_keys");//---------------------------------------------------------------------------const int BelowNormalLogLevels = 1;//---------------------------------------------------------------------------//---------------------------------------------------------------------------TSshHostCA::TSshHostCA(){  PermitRsaSha1 = false;  PermitRsaSha256 = true;  PermitRsaSha512 = true;}//---------------------------------------------------------------------------bool TSshHostCA::Load(THierarchicalStorage * Storage){  PublicKey = DecodeBase64ToStr(Storage->ReadString(L"PublicKey", PublicKey));  ValidityExpression = Storage->ReadString(L"Validity", ValidityExpression);  PermitRsaSha1 = Storage->ReadBool(L"PermitRSASHA1", PermitRsaSha1);  PermitRsaSha256 = Storage->ReadBool(L"PermitRSASHA256", PermitRsaSha256);  PermitRsaSha512 = Storage->ReadBool(L"PermitRSASHA512", PermitRsaSha512);  return !PublicKey.IsEmpty() && !ValidityExpression.IsEmpty();}//---------------------------------------------------------------------------void TSshHostCA::Save(THierarchicalStorage * Storage) const{  Storage->WriteString(L"PublicKey", EncodeStrToBase64(PublicKey));  Storage->WriteString(L"Validity", ValidityExpression);  Storage->WriteBool(L"PermitRSASHA1", PermitRsaSha1);  Storage->WriteBool(L"PermitRSASHA256", PermitRsaSha256);  Storage->WriteBool(L"PermitRSASHA512", PermitRsaSha512);}//---------------------------------------------------------------------------//---------------------------------------------------------------------------TSshHostCAList::TSshHostCAList(){}//---------------------------------------------------------------------------TSshHostCAList::TSshHostCAList(const TSshHostCA::TList & List){  FList = List;}//---------------------------------------------------------------------------void TSshHostCAList::Default(){  FList.clear();}//---------------------------------------------------------------------------void TSshHostCAList::Save(THierarchicalStorage * Storage){  Storage->ClearSubKeys();  TSshHostCA::TList::const_iterator I = FList.begin();  while (I != FList.end())  {    const TSshHostCA & SshHostCA = *I;    if (Storage->OpenSubKey(SshHostCA.Name, true))    {      SshHostCA.Save(Storage);      Storage->CloseSubKey();    }    ++I;  }}//---------------------------------------------------------------------------void TSshHostCAList::Load(THierarchicalStorage * Storage){  FList.clear();  std::unique_ptr<TStrings> SubKeys(new TStringList());  Storage->GetSubKeyNames(SubKeys.get());  for (int Index = 0; Index < SubKeys->Count; Index++)  {    TSshHostCA SshHostCA;    SshHostCA.Name = SubKeys->Strings[Index];    if (Storage->OpenSubKey(SshHostCA.Name, false))    {      if (SshHostCA.Load(Storage))      {        FList.push_back(SshHostCA);      }      Storage->CloseSubKey();    }  }}//---------------------------------------------------------------------------int TSshHostCAList::GetCount() const{  return FList.size();}//---------------------------------------------------------------------------const TSshHostCA * TSshHostCAList::Get(int Index) const{  return &FList[Index];}//---------------------------------------------------------------------------const TSshHostCA * TSshHostCAList::Find(const UnicodeString & Name) const{  TSshHostCA::TList::const_iterator I = FList.begin();  while (I != FList.end())  {    const TSshHostCA & SshHostCA = *I;    if (SameStr(SshHostCA.Name, Name))    {      return &SshHostCA;    }    ++I;  }  return NULL;}//---------------------------------------------------------------------------const TSshHostCA::TList & TSshHostCAList::GetList() const{  return FList;}//---------------------------------------------------------------------------TSshHostCAList & TSshHostCAList::operator =(const TSshHostCAList & other){  FList = other.FList;  return *this;}//---------------------------------------------------------------------------//---------------------------------------------------------------------------__fastcall TConfiguration::TConfiguration(){  FCriticalSection = new TCriticalSection();  FUpdating = 0;  FStorage = stDetect;  FDontSave = false;  FForceSave = false;  FApplicationInfo = NULL;  FUsage = new TUsage(this);  FDefaultCollectUsage = IsUWP();  FScripting = false;  FSshHostCAList.reset(new TSshHostCAList());  UnicodeString RandomSeedPath;  if (!GetEnvironmentVariable(L"APPDATA").IsEmpty())  {    RandomSeedPath = L"%APPDATA%";  }  else  {    RandomSeedPath = GetShellFolderPath(CSIDL_LOCAL_APPDATA);    if (RandomSeedPath.IsEmpty())    {      RandomSeedPath = GetShellFolderPath(CSIDL_APPDATA);    }  }  FDefaultRandomSeedFile = IncludeTrailingBackslash(RandomSeedPath) + L"winscp.rnd";}//---------------------------------------------------------------------------void __fastcall TConfiguration::Default(){  TGuard Guard(FCriticalSection);  FDisablePasswordStoring = false;  FForceBanners = false;  FDisableAcceptingHostKeys = false;  TRegistryStorage * AdminStorage;  AdminStorage = new TRegistryStorage(RegistryStorageKey, HKEY_LOCAL_MACHINE);  try  {    if (AdminStorage->OpenRootKey(false))    {      LoadAdmin(AdminStorage);      AdminStorage->CloseSubKey();    }  }  __finally  {    delete AdminStorage;  }  RandomSeedFile = FDefaultRandomSeedFile;  PuttyRegistryStorageKey = OriginalPuttyRegistryStorageKey;  FConfirmOverwriting = true;  FConfirmResume = true;  FAutoReadDirectoryAfterOp = true;  FSessionReopenAuto = 5000;  FSessionReopenBackground = 2000;  FSessionReopenTimeout = 0;  FSessionReopenAutoStall = 60000;  FTunnelLocalPortNumberLow = 50000;  FTunnelLocalPortNumberHigh = 50099;  FCacheDirectoryChangesMaxSize = 100;  FShowFtpWelcomeMessage = false;  FExternalIpAddress = L"";  FLocalPortNumberMin = 0;  FLocalPortNumberMax = 0;  FTryFtpWhenSshFails = true;  FParallelDurationThreshold = 10;  FMimeTypes = UnicodeString();  FCertificateStorage = EmptyStr;  FAWSAPI = EmptyStr;  FChecksumCommands = EmptyStr;  FDontReloadMoreThanSessions = 1000;  FScriptProgressFileNameLimit = 25;  FQueueTransfersLimit = 2;  FParallelTransferThreshold = -1; // default (currently off), 0 = explicitly off  FKeyVersion = 0;  FSshHostCAList->Default();  RefreshPuttySshHostCAList();  FSshHostCAsFromPuTTY = false;  FHttpsCertificateValidation = 0;  FSynchronizationChecksumAlgs = EmptyStr;  CollectUsage = FDefaultCollectUsage;  FLogging = false;  FPermanentLogging = false;  FLogFileName = DefaultLogFileName;  FPermanentLogFileName = FLogFileName;  FLogFileAppend = true;  FLogSensitive = false;  FPermanentLogSensitive = FLogSensitive;  FLogMaxSize = 0;  FPermanentLogMaxSize = FLogMaxSize;  FLogMaxCount = 0;  FPermanentLogMaxCount = FLogMaxCount;  FLogProtocol = 0;  FPermanentLogProtocol = FLogProtocol;  UpdateActualLogProtocol();  FLogActions = false;  FPermanentLogActions = false;  FLogActionsRequired = false;  FActionsLogFileName = L"%TEMP%\\!S.xml";  FPermanentActionsLogFileName = FActionsLogFileName;  FProgramIniPathWritable = -1;  FCustomIniFileStorageName = LoadCustomIniFileStorageName();  Changed();}//---------------------------------------------------------------------------__fastcall TConfiguration::~TConfiguration(){  DebugAssert(!FUpdating);  if (FApplicationInfo) FreeFileInfo(FApplicationInfo);  delete FCriticalSection;  delete FUsage;}//---------------------------------------------------------------------------void __fastcall TConfiguration::UpdateStaticUsage(){  Usage->Set(L"ConfigurationIniFile", (Storage == stIniFile));  Usage->Set(L"ConfigurationIniFileCustom", !CustomIniFileStorageName.IsEmpty());  Usage->Set("Unofficial", IsUnofficial);  // this is called from here, because we are guarded from calling into  // master password handler here, see TWinConfiguration::UpdateStaticUsage  StoredSessions->UpdateStaticUsage();}//---------------------------------------------------------------------------THierarchicalStorage * TConfiguration::CreateConfigStorage(){  bool SessionList = false;  return CreateScpStorage(SessionList);}//---------------------------------------------------------------------------THierarchicalStorage * TConfiguration::CreateConfigRegistryStorage(){  return new TRegistryStorage(RegistryStorageKey);}//---------------------------------------------------------------------------THierarchicalStorage * TConfiguration::CreateScpStorage(bool & SessionList){  TGuard Guard(FCriticalSection);  THierarchicalStorage * Result;  if (Storage == stRegistry)  {    Result = CreateConfigRegistryStorage();  }  else if (Storage == stNul)  {    Result = TIniFileStorage::CreateNul();  }  else  {    UnicodeString StorageName = IniFileStorageName;    Result = TIniFileStorage::CreateFromPath(StorageName);  }  if ((FOptionsStorage.get() != NULL) && (FOptionsStorage->Count > 0))  {    if (!SessionList)    {      Result = new TOptionsStorage(FOptionsStorage.get(), ConfigurationSubKey, Result);    }    else    {      // cannot reuse session list storage for configuration as for it we need      // the option-override storage above    }  }  else  {    // All the above stores can be reused for configuration,    // if no options-overrides are set    SessionList = false;  }  return Result;}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::PropertyToKey(const UnicodeString & Property){  // no longer useful  int P = Property.LastDelimiter(L".>");  UnicodeString Result = Property.SubString(P + 1, Property.Length() - P);  if ((Result[1] == L'F') && (towupper(Result[2]) == Result[2]))  {    Result.Delete(1, 1);  }  return Result;}//---------------------------------------------------------------------------#define BLOCK(KEY, CANCREATE, BLOCK) \  if (Storage->OpenSubKeyPath(KEY, CANCREATE)) try { BLOCK } __finally { Storage->CloseSubKeyPath(); }#define KEY(TYPE, VAR) KEYEX(TYPE, VAR, PropertyToKey(TEXT(#VAR)))#define REGCONFIG(CANCREATE) \  BLOCK(L"Interface", CANCREATE, \    KEY(String,   RandomSeedFile); \    KEY(String,   PuttyRegistryStorageKey); \    KEY(Bool,     ConfirmOverwriting); \    KEY(Bool,     ConfirmResume); \    KEY(Bool,     AutoReadDirectoryAfterOp); \    KEY(Integer,  SessionReopenAuto); \    KEY(Integer,  SessionReopenBackground); \    KEY(Integer,  SessionReopenTimeout); \    KEY(Integer,  SessionReopenAutoStall); \    KEY(Integer,  TunnelLocalPortNumberLow); \    KEY(Integer,  TunnelLocalPortNumberHigh); \    KEY(Integer,  CacheDirectoryChangesMaxSize); \    KEY(Bool,     ShowFtpWelcomeMessage); \    KEY(String,   ExternalIpAddress); \    KEY(Integer,  LocalPortNumberMin); \    KEY(Integer,  LocalPortNumberMax); \    KEY(Bool,     TryFtpWhenSshFails); \    KEY(Integer,  ParallelDurationThreshold); \    KEY(String,   MimeTypes); \    KEY(Integer,  DontReloadMoreThanSessions); \    KEY(Integer,  ScriptProgressFileNameLimit); \    KEY(Integer,  QueueTransfersLimit); \    KEY(Integer,  ParallelTransferThreshold); \    KEY(Integer,  KeyVersion); \    KEY(Bool,     SshHostCAsFromPuTTY); \    KEY(Integer,  HttpsCertificateValidation); \    KEY(String,   SynchronizationChecksumAlgs); \    KEY(Bool,     CollectUsage); \    KEY(String,   CertificateStorage); \    KEY(String,   AWSAPI); \  ); \  BLOCK(L"Logging", CANCREATE, \    KEYEX(Bool,  PermanentLogging, L"Logging"); \    KEYEX(String,PermanentLogFileName, L"LogFileName"); \    KEY(Bool,    LogFileAppend); \    KEYEX(Bool,  PermanentLogSensitive, L"LogSensitive"); \    KEYEX(Int64, PermanentLogMaxSize, L"LogMaxSize"); \    KEYEX(Integer, PermanentLogMaxCount, L"LogMaxCount"); \    KEYEX(Integer,PermanentLogProtocol, L"LogProtocol"); \    KEYEX(Bool,  PermanentLogActions, L"LogActions"); \    KEYEX(String,PermanentActionsLogFileName, L"ActionsLogFileName"); \  );//---------------------------------------------------------------------------void __fastcall TConfiguration::SaveData(THierarchicalStorage * Storage, bool /*All*/){  #define KEYEX(TYPE, VAR, NAME) Storage->Write ## TYPE(NAME, VAR)  REGCONFIG(true);  #undef KEYEX  if (Storage->OpenSubKey(L"Usage", true))  {    FUsage->Save(Storage);    Storage->CloseSubKey();  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::Save(){  // only modified, implicit  DoSave(false, false);}//---------------------------------------------------------------------------void __fastcall TConfiguration::SaveExplicit(){  // only modified, explicit  DoSave(false, true);}//---------------------------------------------------------------------------void TConfiguration::DoSave(THierarchicalStorage * AStorage, bool All){  if (AStorage->OpenSubKey(ConfigurationSubKey, true))  {    SaveData(AStorage, All);    AStorage->CloseSubKey();  }  if (AStorage->OpenSubKey(SshHostCAsKey, true))  {    FSshHostCAList->Save(AStorage);    AStorage->CloseSubKey();  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::DoSave(bool All, bool Explicit){  if (FDontSave) return;  THierarchicalStorage * AStorage = CreateConfigStorage();  try  {    AStorage->AccessMode = smReadWrite;    AStorage->Explicit = Explicit;    AStorage->ForceSave = FForceSave;    // if saving to TOptionsStorage, make sure we save everything so that    // all configuration is properly transferred to the master storage    bool ConfigAll = All || AStorage->Temporary;    DoSave(AStorage, ConfigAll);  }  __finally  {    delete AStorage;  }  Saved();  if (All)  {    StoredSessions->Save(true, Explicit);  }  // clean up as last, so that if it fails (read only INI), the saving can proceed  if (Storage == stRegistry)  {    CleanupIniFile();  }  SaveCustomIniFileStorageName();}//---------------------------------------------------------------------------void __fastcall TConfiguration::SaveCustomIniFileStorageName(){  // Particularly, not to create an empty "Override" key, unless the custom INI file is ever set  if (CustomIniFileStorageName != LoadCustomIniFileStorageName())  {    std::unique_ptr<TRegistryStorage> RegistryStorage(new TRegistryStorage(GetRegistryStorageOverrideKey()));    RegistryStorage->AccessMode = smReadWrite;    RegistryStorage->Explicit = true;    if (RegistryStorage->OpenRootKey(true))    {      RegistryStorage->WriteString(L"IniFile", CustomIniFileStorageName);      RegistryStorage->CloseSubKey();      AppLogFmt(L"Saved custom INI file path %s", (CustomIniFileStorageName));    }  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::Export(const UnicodeString & FileName){  // not to "append" the export to an existing file  if (FileExists(FileName))  {    DeleteFileChecked(FileName);  }  THierarchicalStorage * Storage = NULL;  THierarchicalStorage * ExportStorage = NULL;  try  {    ExportStorage = TIniFileStorage::CreateFromPath(FileName);    ExportStorage->AccessMode = smReadWrite;    ExportStorage->Explicit = true;    Storage = CreateConfigStorage();    Storage->AccessMode = smRead;    CopyData(Storage, ExportStorage);    DoSave(ExportStorage, true);  }  __finally  {    delete ExportStorage;    delete Storage;  }  StoredSessions->Export(FileName);}//---------------------------------------------------------------------------void __fastcall TConfiguration::Import(const UnicodeString & FileName){  THierarchicalStorage * Storage = NULL;  THierarchicalStorage * ImportStorage = NULL;  try  {    ImportStorage = TIniFileStorage::CreateFromPath(FileName);    ImportStorage->AccessMode = smRead;    Storage = CreateConfigStorage();    Storage->AccessMode = smReadWrite;    Storage->Explicit = true;    CopyData(ImportStorage, Storage);    Default();    LoadFrom(ImportStorage);    Storage->RecursiveDeleteSubKey(Configuration->StoredSessionsSubKey);    if (ImportStorage->OpenSubKey(Configuration->StoredSessionsSubKey, false))    {      StoredSessions->Clear();      StoredSessions->DefaultSettings->Default();      StoredSessions->Load(ImportStorage);    }  }  __finally  {    delete ImportStorage;    delete Storage;  }  // save all and explicit  DoSave(true, true);  FDontSave = true;}//---------------------------------------------------------------------------void __fastcall TConfiguration::LoadData(THierarchicalStorage * Storage){  #define KEYEX(TYPE, VAR, NAME) VAR = Storage->Read ## TYPE(NAME, VAR)  #pragma warn -eas  REGCONFIG(false);  #pragma warn +eas  #undef KEYEX  if (Storage->OpenSubKey(L"Usage", false))  {    FUsage->Load(Storage);    Storage->CloseSubKey();  }  if (FPermanentLogActions && FPermanentActionsLogFileName.IsEmpty() &&      FPermanentLogging && !FPermanentLogFileName.IsEmpty())  {     FPermanentActionsLogFileName = FPermanentLogFileName;     FPermanentLogging = false;     FPermanentLogFileName = L"";  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::LoadAdmin(THierarchicalStorage * Storage){  FDisablePasswordStoring = Storage->ReadBool(L"DisablePasswordStoring", FDisablePasswordStoring);  FForceBanners = Storage->ReadBool(L"ForceBanners", FForceBanners);  FDisableAcceptingHostKeys = Storage->ReadBool(L"DisableAcceptingHostKeys", FDisableAcceptingHostKeys);  FDefaultCollectUsage = Storage->ReadBool(L"DefaultCollectUsage", FDefaultCollectUsage);}//---------------------------------------------------------------------------void TConfiguration::LoadSshHostCAList(TSshHostCAList * SshHostCAList, THierarchicalStorage * Storage){  if (Storage->OpenSubKey(SshHostCAsKey, false))  {    SshHostCAList->Load(Storage);    Storage->CloseSubKey();  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::LoadFrom(THierarchicalStorage * Storage){  if (Storage->OpenSubKey(ConfigurationSubKey, false))  {    LoadData(Storage);    Storage->CloseSubKey();  }  LoadSshHostCAList(FSshHostCAList.get(), Storage);}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetRegistryStorageOverrideKey(){  return GetRegistryStorageKey() + L" Override";}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::LoadCustomIniFileStorageName(){  UnicodeString Result;  std::unique_ptr<TRegistryStorage> RegistryStorage(new TRegistryStorage(GetRegistryStorageOverrideKey()));  if (RegistryStorage->OpenRootKey(false))  {    Result = RegistryStorage->ReadString(L"IniFile", L"");    AppLogFmt(L"Loaded custom INI file path %s", (Result));    RegistryStorage->CloseSubKey();  }  RegistryStorage.reset(NULL);  return Result;}//---------------------------------------------------------------------------void __fastcall TConfiguration::Load(THierarchicalStorage * Storage){  TGuard Guard(FCriticalSection);  TStorageAccessMode StorageAccessMode = Storage->AccessMode;  try  {    Storage->AccessMode = smRead;    LoadFrom(Storage);  }  __finally  {    Storage->AccessMode = StorageAccessMode;  }}//---------------------------------------------------------------------------bool __fastcall TConfiguration::CopySubKey(THierarchicalStorage * Source, THierarchicalStorage * Target, const UnicodeString & Name){  bool Result = Source->OpenSubKey(Name, false);  if (Result)  {    Result = Target->OpenSubKey(Name, true);    if (!Result)    {      Source->CloseSubKey();    }  }  return Result;}//---------------------------------------------------------------------------void __fastcall TConfiguration::CopyAllStringsInSubKey(  THierarchicalStorage * Source, THierarchicalStorage * Target, const UnicodeString & Name){  if (CopySubKey(Source, Target, Name))  {    std::unique_ptr<TStrings> Names(new TStringList());    Source->GetValueNames(Names.get());    for (int Index = 0; Index < Names->Count; Index++)    {      UnicodeString Buf = Source->ReadStringRaw(Names->Strings[Index], UnicodeString());      Target->WriteStringRaw(Names->Strings[Index], Buf);    }    Target->CloseSubKey();    Source->CloseSubKey();  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::CopyData(THierarchicalStorage * Source,  THierarchicalStorage * Target){  if (CopySubKey(Source, Target, ConfigurationSubKey))  {    if (CopySubKey(Source, Target, CDCacheKey))    {      std::unique_ptr<TStrings> Names(new TStringList());      Source->GetValueNames(Names.get());      for (int Index = 0; Index < Names->Count; Index++)      {        Target->WriteBinaryData(Names->Strings[Index], Source->ReadBinaryData(Names->Strings[Index]));      }      Target->CloseSubKey();      Source->CloseSubKey();    }    CopyAllStringsInSubKey(Source, Target, BannersKey);    CopyAllStringsInSubKey(Source, Target, LastFingerprintsStorageKey);    Target->CloseSubKey();    Source->CloseSubKey();  }  CopyAllStringsInSubKey(Source, Target, SshHostKeysSubKey);  CopyAllStringsInSubKey(Source, Target, SshHostCAsKey);  CopyAllStringsInSubKey(Source, Target, FtpsCertificateStorageKey);  CopyAllStringsInSubKey(Source, Target, HttpsCertificateStorageKey);}//---------------------------------------------------------------------------void __fastcall TConfiguration::LoadDirectoryChangesCache(const UnicodeString SessionKey,  TRemoteDirectoryChangesCache * DirectoryChangesCache){  THierarchicalStorage * Storage = CreateConfigStorage();  try  {    Storage->AccessMode = smRead;    if (Storage->OpenSubKey(ConfigurationSubKey, false) &&        Storage->OpenSubKey(CDCacheKey, false) &&        Storage->ValueExists(SessionKey))    {      DirectoryChangesCache->Deserialize(Storage->ReadBinaryData(SessionKey));    }  }  __finally  {    delete Storage;  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::SaveDirectoryChangesCache(const UnicodeString SessionKey,  TRemoteDirectoryChangesCache * DirectoryChangesCache){  THierarchicalStorage * Storage = CreateConfigStorage();  try  {    Storage->AccessMode = smReadWrite;    if (Storage->OpenSubKey(ConfigurationSubKey, true) &&        Storage->OpenSubKey(CDCacheKey, true))    {      UnicodeString Data;      DirectoryChangesCache->Serialize(Data);      Storage->WriteBinaryData(SessionKey, Data);    }  }  __finally  {    delete Storage;  }}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::BannerHash(const UnicodeString & Banner){  RawByteString Result;  Result.SetLength(16);  md5checksum(    reinterpret_cast<const char*>(Banner.c_str()), Banner.Length() * sizeof(wchar_t),    (unsigned char*)Result.c_str());  return BytesToHex(Result);}//---------------------------------------------------------------------------void __fastcall TConfiguration::GetBannerData(  const UnicodeString & SessionKey, UnicodeString & BannerHash, unsigned int & Params){  BannerHash = UnicodeString();  Params = 0;  std::unique_ptr<THierarchicalStorage> Storage(CreateConfigStorage());  Storage->AccessMode = smRead;  if (Storage->OpenSubKey(ConfigurationSubKey, false) &&      Storage->OpenSubKey(BannersKey, false))  {    UnicodeString S = Storage->ReadString(SessionKey, L"");    BannerHash = CutToChar(S, L',', true);    Params = StrToIntDef(L"$" + CutToChar(S, L',', true), 0);  }}//---------------------------------------------------------------------------bool __fastcall TConfiguration::ShowBanner(  const UnicodeString & SessionKey, const UnicodeString & Banner, unsigned int & Params){  UnicodeString StoredBannerHash;  GetBannerData(SessionKey, StoredBannerHash, Params);  bool Result = (StoredBannerHash != BannerHash(Banner));  return Result;}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetBannerData(  const UnicodeString & SessionKey, const UnicodeString & BannerHash, unsigned int Params){  std::unique_ptr<THierarchicalStorage> Storage(CreateConfigStorage());  Storage->AccessMode = smReadWrite;  if (Storage->OpenSubKey(ConfigurationSubKey, true) &&      Storage->OpenSubKey(BannersKey, true))  {    Storage->WriteString(SessionKey, BannerHash + L"," + UIntToStr(Params));  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::NeverShowBanner(const UnicodeString & SessionKey, const UnicodeString & Banner){  UnicodeString DummyBannerHash;  unsigned int Params;  GetBannerData(SessionKey, DummyBannerHash, Params);  SetBannerData(SessionKey, BannerHash(Banner), Params);}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetBannerParams(const UnicodeString & SessionKey, unsigned int Params){  UnicodeString BannerHash;  unsigned int DummyParams;  GetBannerData(SessionKey, BannerHash, DummyParams);  SetBannerData(SessionKey, BannerHash, Params);}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::FormatFingerprintKey(const UnicodeString & SiteKey, const UnicodeString & FingerprintType){  return FORMAT(L"%s:%s", (SiteKey, FingerprintType));}//---------------------------------------------------------------------------void __fastcall TConfiguration::RememberLastFingerprint(const UnicodeString & SiteKey, const UnicodeString & FingerprintType, const UnicodeString & Fingerprint){  std::unique_ptr<THierarchicalStorage> Storage(CreateConfigStorage());  Storage->AccessMode = smReadWrite;  if (Storage->OpenSubKey(ConfigurationSubKey, true) &&      Storage->OpenSubKey(LastFingerprintsStorageKey, true))  {    UnicodeString FingerprintKey = FormatFingerprintKey(SiteKey, FingerprintType);    Storage->WriteString(FingerprintKey, Fingerprint);  }}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::LastFingerprint(const UnicodeString & SiteKey, const UnicodeString & FingerprintType){  UnicodeString Result;  std::unique_ptr<THierarchicalStorage> Storage(CreateConfigStorage());  Storage->AccessMode = smRead;  if (Storage->OpenSubKey(ConfigurationSubKey, false) &&      Storage->OpenSubKey(LastFingerprintsStorageKey, false))  {    UnicodeString FingerprintKey = FormatFingerprintKey(SiteKey, FingerprintType);    Result = Storage->ReadString(FingerprintKey, L"");  }  return Result;}//---------------------------------------------------------------------------void __fastcall TConfiguration::Changed(){  TNotifyEvent AOnChange = NULL;  {    TGuard Guard(FCriticalSection);    if (FUpdating == 0)    {      AOnChange = OnChange;    }    else    {      FChanged = true;    }  }  // No specific reason to call this outside of a guard, just that it is less of a change to a previous unguarded code  if (AOnChange != NULL)  {    AOnChange(this);  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::BeginUpdate(){  FCriticalSection->Enter();  if (FUpdating == 0)  {    FChanged = false;  }  FUpdating++;  // Greater value would probably indicate some nesting problem in code  DebugAssert(FUpdating < 6);}//---------------------------------------------------------------------------void __fastcall TConfiguration::EndUpdate(){  DebugAssert(FUpdating > 0);  FUpdating--;  if ((FUpdating == 0) && FChanged)  {    FChanged = false;    Changed();  }  FCriticalSection->Leave();}//---------------------------------------------------------------------------void __fastcall TConfiguration::CleanupConfiguration(){  try  {    CleanupRegistry(ConfigurationSubKey);    if (Storage == stRegistry)    {      FDontSave = true;    }  }  catch (Exception &E)  {    throw ExtException(&E, LoadStr(CLEANUP_CONFIG_ERROR));  }}//---------------------------------------------------------------------------bool TConfiguration::RegistryPathExists(const UnicodeString & RegistryPath){  std::unique_ptr<TRegistryStorage> Registry(new TRegistryStorage(RegistryStorageKey));  UnicodeString ParentKey = ExtractFileDir(RegistryPath);  UnicodeString SubKey = ExtractFileName(RegistryPath);  return    Registry->OpenRootKey(false) &&    (ParentKey.IsEmpty() ||     Registry->OpenSubKeyPath(ParentKey, false)) &&    Registry->KeyExists(SubKey);}//---------------------------------------------------------------------------void __fastcall TConfiguration::CleanupRegistry(const UnicodeString & RegistryPath){  UnicodeString CompanyKey = GetCompanyRegistryKey();  UnicodeString Prefix = IncludeTrailingBackslash(CompanyKey);  if (DebugAlwaysTrue(SameStr(LeftStr(RegistryStorageKey, Prefix.Length()), Prefix)))  {    UnicodeString CompanyParentKey = ExtractFileDir(CompanyKey);    std::unique_ptr<TRegistryStorage> Registry(new TRegistryStorage(CompanyParentKey));    UnicodeString RegistryStorageSubKey = MidStr(RegistryStorageKey, CompanyParentKey.Length() + 2);    Registry->UnmungedRoot = RegistryStorageSubKey;    AppLogFmt(L"Cleaning up registry key %s", (RegistryPath));    UnicodeString ARegistryPath = CombinePaths(RegistryStorageSubKey, RegistryPath);    UnicodeString Buf = ARegistryPath;    while (!Buf.IsEmpty())    {      UnicodeString ParentKey = ExtractFileDir(Buf);      // Actually can be simplified to Registry->OpenSubKeyPath(ParentKey, false)      if (ParentKey.IsEmpty() ? Registry->OpenRootKey(false) : Registry->OpenSubKeyPath(ParentKey, false))      {        UnicodeString SubKey = ExtractFileName(Buf);        if (Registry->KeyExists(SubKey))        {          bool Recursive = (Buf == ARegistryPath);          if (Registry->DeleteSubKey(SubKey, Recursive))          {            AppLogFmt(L"Deleted registry key %s in %s", (SubKey, ParentKey));          }          else          {            break;          }        }        Registry->CloseSubKeyPath();        Buf = ParentKey;      }      else      {        break;      }    }  }}//---------------------------------------------------------------------------TStrings * TConfiguration::GetCaches(){  std::unique_ptr<TStrings> Result(new TStringList());  Result->Add(SshHostKeysSubKey);  Result->Add(SshHostCAsKey);  Result->Add(FtpsCertificateStorageKey);  Result->Add(HttpsCertificateStorageKey);  Result->Add(DirectoryStatisticsCacheKey);  Result->Add(CombinePaths(ConfigurationSubKey, CDCacheKey));  Result->Add(CombinePaths(ConfigurationSubKey, BannersKey));  Result->Add(CombinePaths(ConfigurationSubKey, LastFingerprintsStorageKey));  return Result.release();}//---------------------------------------------------------------------------bool __fastcall TConfiguration::HasAnyCache(){  bool Result = false;  std::unique_ptr<TStrings> Caches(GetCaches());  for (int Index = 0; Index < Caches->Count; Index++)  {    if (RegistryPathExists(Caches->Strings[Index]))    {      Result = true;      break;    }  }  return Result;}//---------------------------------------------------------------------------void __fastcall TConfiguration::CleanupCaches(){  try  {    std::unique_ptr<TStrings> Caches(GetCaches());    for (int Index = 0; Index < Caches->Count; Index++)    {      CleanupRegistry(Caches->Strings[Index]);    }  }  catch (Exception & E)  {    throw ExtException(&E, LoadStr(CLEANUP_CACHES_ERROR));  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::CleanupRandomSeedFile(){  try  {    DontSaveRandomSeed();    if (FileExists(ApiPath(RandomSeedFileName)))    {      DeleteFileChecked(RandomSeedFileName);    }  }  catch (Exception &E)  {    throw ExtException(&E, LoadStr(CLEANUP_SEEDFILE_ERROR));  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::CleanupIniFile(){  try  {    if (FileExists(ApiPath(IniFileStorageNameForReading)))    {      DeleteFileChecked(IniFileStorageNameForReading);    }    if (Storage == stIniFile)    {      FDontSave = true;    }  }  catch (Exception &E)  {    throw ExtException(&E, LoadStr(CLEANUP_INIFILE_ERROR));  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::DontSave(){  FDontSave = true;}//---------------------------------------------------------------------------RawByteString __fastcall TConfiguration::EncryptPassword(UnicodeString Password, UnicodeString Key){  if (Password.IsEmpty())  {    return RawByteString();  }  else  {    return ::EncryptPassword(Password, Key);  }}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::DecryptPassword(RawByteString Password, UnicodeString Key){  if (Password.IsEmpty())  {    return UnicodeString();  }  else  {    return ::DecryptPassword(Password, Key);  }}//---------------------------------------------------------------------------RawByteString __fastcall TConfiguration::StronglyRecryptPassword(RawByteString Password, UnicodeString /*Key*/){  return Password;}//---------------------------------------------------------------------------TVSFixedFileInfo *__fastcall TConfiguration::GetFixedApplicationInfo(){  return GetFixedFileInfo(ApplicationInfo);}//---------------------------------------------------------------------------int __fastcall TConfiguration::GetCompoundVersion(){  TVSFixedFileInfo * FileInfo = FixedApplicationInfo;  return CalculateCompoundVersion(    HIWORD(FileInfo->dwFileVersionMS), LOWORD(FileInfo->dwFileVersionMS),    HIWORD(FileInfo->dwFileVersionLS));}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::ModuleFileName(){  return ParamStr(0);}//---------------------------------------------------------------------------void * __fastcall TConfiguration::GetFileApplicationInfo(const UnicodeString FileName){  void * Result;  if (FileName.IsEmpty())  {    if (!FApplicationInfo)    {      FApplicationInfo = CreateFileInfo(ModuleFileName());    }    Result = FApplicationInfo;  }  else  {    Result = CreateFileInfo(FileName);  }  return Result;}//---------------------------------------------------------------------------void * __fastcall TConfiguration::GetApplicationInfo(){  return GetFileApplicationInfo("");}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetFileProductName(const UnicodeString FileName){  return GetFileFileInfoString(L"ProductName", FileName);}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetFileCompanyName(const UnicodeString FileName){  // particularly in IDE build, company name is empty  return GetFileFileInfoString(L"CompanyName", FileName, true);}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetProductName(){  return GetFileProductName(L"");}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetCompanyName(){  return GetFileCompanyName(L"");}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetFileProductVersion(const UnicodeString FileName){  return TrimVersion(GetFileFileInfoString(L"ProductVersion", FileName));}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetFileDescription(const UnicodeString & FileName){  return GetFileFileInfoString(L"FileDescription", FileName);}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetProductVersion(){  return GetFileProductVersion(L"");}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetReleaseType(){  return GetFileInfoString(L"ReleaseType");}//---------------------------------------------------------------------------bool __fastcall TConfiguration::GetIsUnofficial(){  #ifdef BUILD_OFFICIAL  return false;  #else  return true;  #endif}//---------------------------------------------------------------------------static TDateTime GetBuildDate(){  UnicodeString BuildDateStr = __DATE__;  UnicodeString MonthStr = CutToChar(BuildDateStr, L' ', true);  int Month = ParseShortEngMonthName(MonthStr);  int Day = StrToInt(CutToChar(BuildDateStr, L' ', true));  int Year = StrToInt(Trim(BuildDateStr));  TDateTime Result = EncodeDateVerbose(static_cast<Word>(Year), static_cast<Word>(Month), static_cast<Word>(Day));  return Result;}//---------------------------------------------------------------------------UnicodeString TConfiguration::GetFullVersion(){  UnicodeString Result = Version;  UnicodeString AReleaseType = GetReleaseType();  if (DebugAlwaysTrue(!AReleaseType.IsEmpty()) &&      !SameText(AReleaseType, L"stable") &&      !SameText(AReleaseType, L"development"))  {    Result += L" " + AReleaseType;  }  return Result;}//---------------------------------------------------------------------------static UnicodeString GetUnofficialBuildTag(){  DebugAssert(Configuration->IsUnofficial);  UnicodeString Result;  #ifdef _DEBUG  Result = LoadStr(VERSION_DEBUG_BUILD);  #else  Result = LoadStr(VERSION_DEV_BUILD);  #endif  return Result;}//---------------------------------------------------------------------------UnicodeString TConfiguration::GetVersionStrHuman(){  TGuard Guard(FCriticalSection);  try  {    TDateTime BuildDate = GetBuildDate();    UnicodeString FullVersion = GetFullVersion();    if (IsUnofficial)    {      UnicodeString BuildStr = GetUnofficialBuildTag();      FullVersion += L" " + BuildStr;    }    UnicodeString DateStr;    TDateTime ANow = Now();    if (BuildDate < ANow)    {      DateStr = FormatRelativeTime(ANow, BuildDate, true);    }    else    {      DateStr = FormatDateTime(L"ddddd", BuildDate);    }    UnicodeString Result = FORMAT(L"%s (%s)", (FullVersion, DateStr));    return Result;  }  catch (Exception &E)  {    throw ExtException(&E, L"Can't get application version");  }}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetVersionStr(){  TGuard Guard(FCriticalSection);  try  {    UnicodeString BuildStr;    if (!IsUnofficial)    {      BuildStr = LoadStr(VERSION_BUILD);    }    else    {      BuildStr = GetUnofficialBuildTag();    }    UnicodeString FullVersion = GetFullVersion();    int Build = LOWORD(FixedApplicationInfo->dwFileVersionLS);    if (Build > 0)    {      BuildStr += L" " + IntToStr(Build);    }    UnicodeString DateStr = FormatDateTime(L"yyyy-mm-dd", GetBuildDate());    AddToList(BuildStr, DateStr, L" ");    UnicodeString Result = FMTLOAD(VERSION2, (FullVersion, BuildStr));    if (IsUnofficial)    {      Result += L" " + LoadStr(VERSION_DONT_DISTRIBUTE);    }    return Result;  }  catch (Exception &E)  {    throw ExtException(&E, L"Can't get application version");  }}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetFileVersion(const UnicodeString & FileName){  UnicodeString Result;  void * FileInfo = CreateFileInfo(FileName);  try  {    Result = GetFileVersion(GetFixedFileInfo(FileInfo));  }  __finally  {    FreeFileInfo(FileInfo);  }  return Result;}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetFileVersion(TVSFixedFileInfo * Info){  TGuard Guard(FCriticalSection);  try  {    UnicodeString Result =      FormatVersion(        HIWORD(Info->dwFileVersionMS),        LOWORD(Info->dwFileVersionMS),        HIWORD(Info->dwFileVersionLS));    return Result;  }  catch (Exception &E)  {    throw ExtException(&E, L"Can't get file version");  }}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetVersion(){  return GetFileVersion(FixedApplicationInfo);}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetFileFileInfoString(const UnicodeString Key,  const UnicodeString FileName, bool AllowEmpty){  TGuard Guard(FCriticalSection);  UnicodeString Result;  void * Info = GetFileApplicationInfo(FileName);  try  {    if ((Info != NULL) && (GetTranslationCount(Info) > 0))    {      TTranslation Translation;      Translation = GetTranslation(Info, 0);      Result = ::GetFileInfoString(Info, Translation, Key, AllowEmpty);    }    else    {      DebugAssert(!FileName.IsEmpty());    }  }  __finally  {    if (!FileName.IsEmpty())    {      FreeFileInfo(Info);    }  }  return Result;}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetFileInfoString(const UnicodeString Key){  return GetFileFileInfoString(Key, L"");}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetFileMimeType(const UnicodeString & FileName){  UnicodeString Result;  bool Found = false;  if (!MimeTypes.IsEmpty())  {    UnicodeString FileNameOnly = ExtractFileName(FileName);    UnicodeString AMimeTypes = MimeTypes;    while (!Found && !AMimeTypes.IsEmpty())    {      UnicodeString Token = CutToChar(AMimeTypes, L',', true);      UnicodeString MaskStr = CutToChar(Token, L'=', true);      TFileMasks Mask(MaskStr);      if (Mask.MatchesFileName(FileNameOnly))      {        Result = Token.Trim();        Found = true;      }    }  }  if (!Found) // allow an override to "no" Content-Type  {    Result = ::GetFileMimeType(FileName);  }  return Result;}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetRegistryStorageKey(){  return GetRegistryKey();}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetNulStorage(){  FStorage = stNul;}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetExplicitIniFileStorageName(const UnicodeString & FileName){  FIniFileStorageName = FileName;  FStorage = stIniFile;}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetDefaultIniFileExportPath(){  UnicodeString PersonalDirectory = GetPersonalFolder();  UnicodeString FileName = IncludeTrailingBackslash(PersonalDirectory) +    ExtractFileName(ExpandEnvironmentVariables(IniFileStorageName));  return FileName;}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetIniFileStorageNameForReading(){  return GetIniFileStorageName(true);}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetIniFileStorageNameForReadingWriting(){  return GetIniFileStorageName(false);}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetAutomaticIniFileStorageName(bool ReadingOnly){  UnicodeString ProgramPath = ParamStr(0);  UnicodeString ProgramIniPath = ChangeFileExt(ProgramPath, L".ini");  UnicodeString IniPath;  if (FileExists(ApiPath(ProgramIniPath)))  {    IniPath = ProgramIniPath;  }  else  {    UnicodeString AppDataIniPath =      IncludeTrailingBackslash(GetShellFolderPath(CSIDL_APPDATA)) +      ExtractFileName(ProgramIniPath);    if (FileExists(ApiPath(AppDataIniPath)))    {      IniPath = AppDataIniPath;    }    else    {      // avoid expensive test if we are interested in existing files only      if (!ReadingOnly && (FProgramIniPathWritable < 0))      {        UnicodeString ProgramDir = ExtractFilePath(ProgramPath);        FProgramIniPathWritable = IsDirectoryWriteable(ProgramDir) ? 1 : 0;      }      // does not really matter what we return when < 0      IniPath = (FProgramIniPathWritable == 0) ? AppDataIniPath : ProgramIniPath;    }  }  // BACKWARD COMPATIBILITY with 4.x  if (FVirtualIniFileStorageName.IsEmpty() &&      TPath::IsDriveRooted(IniPath))  {    UnicodeString LocalAppDataPath = GetShellFolderPath(CSIDL_LOCAL_APPDATA);    // virtual store for non-system drives have a different virtual store,    // do not bother about them    if (TPath::IsDriveRooted(LocalAppDataPath) &&        SameText(ExtractFileDrive(IniPath), ExtractFileDrive(LocalAppDataPath)))    {      FVirtualIniFileStorageName =        IncludeTrailingBackslash(LocalAppDataPath) +        L"VirtualStore\\" +        IniPath.SubString(4, IniPath.Length() - 3);    }  }  if (!FVirtualIniFileStorageName.IsEmpty() &&      FileExists(ApiPath(FVirtualIniFileStorageName)))  {    return FVirtualIniFileStorageName;  }  else  {    return IniPath;  }}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetIniFileParamValue(){  UnicodeString Result;  if (Storage == stNul)  {    Result = INI_NUL;  }  else if ((Storage == stIniFile) && !FIniFileStorageName.IsEmpty())  {    Result = FIniFileStorageName;  }  return Result;}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetIniFileStorageName(bool ReadingOnly){  UnicodeString Result;  if (!FIniFileStorageName.IsEmpty())  {    Result = FIniFileStorageName;  }  else if (!FCustomIniFileStorageName.IsEmpty())  {    Result = ExpandEnvironmentVariables(FCustomIniFileStorageName);  }  else  {    Result = GetAutomaticIniFileStorageName(ReadingOnly);  }  return Result;}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetOptionsStorage(TStrings * value){  TGuard Guard(FCriticalSection);  if (FOptionsStorage.get() == NULL)  {    FOptionsStorage.reset(new TStringList());  }  FOptionsStorage->AddStrings(value);}//---------------------------------------------------------------------------TStrings * __fastcall TConfiguration::GetOptionsStorage(){  return FOptionsStorage.get();}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetPuttySessionsSubKey(){  return StoredSessionsSubKey;}//---------------------------------------------------------------------------UnicodeString TConfiguration::GetPuttySessionsKey(const UnicodeString & RootKey){  return RootKey + L"\\" + PuttySessionsSubKey;}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::DoGetPuttySessionsKey(){  return GetPuttySessionsKey(PuttyRegistryStorageKey);}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetStoredSessionsSubKey(){  return L"Sessions";}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetSshHostKeysSubKey(){  return L"SshHostKeys";}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetConfigurationSubKey(){  return L"Configuration";}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetRootKeyStr(){  return RootKeyToStr(HKEY_CURRENT_USER);}//---------------------------------------------------------------------------void __fastcall TConfiguration::MoveStorage(TStorage AStorage, const UnicodeString & ACustomIniFileStorageName){  if ((FStorage != AStorage) ||      ((FStorage == stIniFile) && !FIniFileStorageName.IsEmpty()) ||      // Not expanding, as we want to allow change from explicit path to path with variables and vice versa      !IsPathToSameFile(FCustomIniFileStorageName, ACustomIniFileStorageName))  {    TStorage StorageBak = FStorage;    UnicodeString CustomIniFileStorageNameBak = FCustomIniFileStorageName;    UnicodeString IniFileStorageNameBak = FIniFileStorageName;    try    {      THierarchicalStorage * SourceStorage = NULL;      THierarchicalStorage * TargetStorage = NULL;      try      {        SourceStorage = CreateConfigStorage();        SourceStorage->AccessMode = smRead;        FStorage = AStorage;        FCustomIniFileStorageName = ACustomIniFileStorageName;        FIniFileStorageName = UnicodeString();        TargetStorage = CreateConfigStorage();        TargetStorage->AccessMode = smReadWrite;        TargetStorage->Explicit = true;        // copy before save as it removes the ini file,        // when switching from ini to registry        CopyData(SourceStorage, TargetStorage);      }      __finally      {        delete SourceStorage;        delete TargetStorage;      }      // save all and explicit,      // this also removes an INI file, when switching to registry storage      DoSave(true, true);    }    catch (...)    {      // If this fails, do not pretend that storage was switched.      // For instance:      // - When writing to an INI file fails (unlikely, as we fallback to user profile)      // - When removing INI file fails, when switching to registry      //   (possible, when the INI file is in Program Files folder)      FStorage = StorageBak;      FCustomIniFileStorageName = CustomIniFileStorageNameBak;      FIniFileStorageName = IniFileStorageNameBak;      throw;    }  }}//---------------------------------------------------------------------------void __fastcall TConfiguration::ScheduleCustomIniFileStorageUse(const UnicodeString & ACustomIniFileStorageName){  FStorage = stIniFile;  FCustomIniFileStorageName = ACustomIniFileStorageName;  SaveCustomIniFileStorageName();}//---------------------------------------------------------------------------void __fastcall TConfiguration::Saved(){  // nothing}//---------------------------------------------------------------------------TStorage __fastcall TConfiguration::GetStorage(){  TGuard Guard(FCriticalSection);  if (FStorage == stDetect)  {    DebugFail(); // This is never called, as the detection is completely overriden by TWinConfiguration    if (FileExists(ApiPath(IniFileStorageNameForReading)))    {      FStorage = stIniFile;    }    else    {      FStorage = stRegistry;    }  }  return FStorage;}//---------------------------------------------------------------------static TStoredSessionList * CreateSessionsForImport(TStoredSessionList * Sessions){  std::unique_ptr<TStoredSessionList> Result(new TStoredSessionList(true));  Result->DefaultSettings = Sessions->DefaultSettings;  return Result.release();}//---------------------------------------------------------------------void TConfiguration::SelectSessionsToImportIfAny(  TStoredSessionList * ImportSessionList, TStoredSessionList * Sessions,  UnicodeString & Error, const UnicodeString & NoSessionsError){  if (ImportSessionList->Count > 0)  {    ImportSessionList->SelectSessionsToImport(Sessions, true);  }  else  {    Error = NoSessionsError;  }}//---------------------------------------------------------------------TStoredSessionList * __fastcall TConfiguration::SelectFilezillaSessionsForImport(  TStoredSessionList * Sessions, UnicodeString & Error){  std::unique_ptr<TStoredSessionList> ImportSessionList(CreateSessionsForImport(Sessions));  UnicodeString AppDataPath = GetShellFolderPath(CSIDL_APPDATA);  UnicodeString FilezillaSiteManagerFile = CombinePaths(AppDataPath, L"FileZilla\\sitemanager.xml");  UnicodeString FilezillaConfigurationFile = CombinePaths(AppDataPath, L"FileZilla\\filezilla.xml");  if (FileExists(ApiPath(FilezillaSiteManagerFile)))  {    ImportSessionList->ImportFromFilezilla(FilezillaSiteManagerFile, FilezillaConfigurationFile);    UnicodeString NoSessionsError = FMTLOAD(FILEZILLA_NO_SITES, (FilezillaSiteManagerFile));    SelectSessionsToImportIfAny(ImportSessionList.get(), Sessions, Error, NoSessionsError);  }  else  {    Error = FMTLOAD(FILEZILLA_SITE_MANAGER_NOT_FOUND, (FilezillaSiteManagerFile));  }  return ImportSessionList.release();}//---------------------------------------------------------------------bool __fastcall TConfiguration::AnyFilezillaSessionForImport(TStoredSessionList * Sessions){  try  {    UnicodeString Error;    std::unique_ptr<TStoredSessionList> SessionsForImport(SelectFilezillaSessionsForImport(Sessions, Error));    return (SessionsForImport->Count > 0);  }  catch (...)  {    return false;  }}//---------------------------------------------------------------------UnicodeString GetOpensshFolder(){  UnicodeString ProfilePath = GetShellFolderPath(CSIDL_PROFILE);  UnicodeString Result = CombinePaths(ProfilePath, OpensshFolderName);  return Result;}//---------------------------------------------------------------------TStoredSessionList * __fastcall TConfiguration::SelectKnownHostsSessionsForImport(  TStoredSessionList * Sessions, UnicodeString & Error){  std::unique_ptr<TStoredSessionList> ImportSessionList(CreateSessionsForImport(Sessions));  UnicodeString KnownHostsFile = CombinePaths(GetOpensshFolder(), L"known_hosts");  try  {    if (FileExists(ApiPath(KnownHostsFile)))    {      std::unique_ptr<TStrings> Lines(new TStringList());      LoadScriptFromFile(KnownHostsFile, Lines.get(), true);      ImportSessionList->ImportFromKnownHosts(Lines.get());    }    else    {      throw Exception(LoadStr(KNOWN_HOSTS_NOT_FOUND));    }  }  catch (Exception & E)  {    Error = FORMAT(L"%s\n(%s)", (E.Message, KnownHostsFile));  }  return ImportSessionList.release();}//---------------------------------------------------------------------TStoredSessionList * __fastcall TConfiguration::SelectKnownHostsSessionsForImport(  TStrings * Lines, TStoredSessionList * Sessions, UnicodeString & Error){  std::unique_ptr<TStoredSessionList> ImportSessionList(CreateSessionsForImport(Sessions));  try  {    ImportSessionList->ImportFromKnownHosts(Lines);  }  catch (Exception & E)  {    Error = E.Message;  }  return ImportSessionList.release();}//---------------------------------------------------------------------------TStoredSessionList * TConfiguration::SelectOpensshSessionsForImport(  TStoredSessionList * Sessions, UnicodeString & Error){  std::unique_ptr<TStoredSessionList> ImportSessionList(CreateSessionsForImport(Sessions));  UnicodeString ConfigFile = CombinePaths(GetOpensshFolder(), L"config");  try  {    if (FileExists(ApiPath(ConfigFile)))    {      std::unique_ptr<TStrings> Lines(new TStringList());      LoadScriptFromFile(ConfigFile, Lines.get(), true);      const UnicodeString OpensshIncludeDirective(L"Include");      for (int Index = 0; Index < Lines->Count; Index++)      {        UnicodeString Line = Lines->Strings[Index];        UnicodeString Directive, Args;        if (ParseOpensshDirective(Line, Directive, Args))        {          if (SameText(Directive, OpensshIncludeDirective))          {            while (!Args.IsEmpty())            {              UnicodeString IncludePath = ConvertPathFromOpenssh(CutOpensshToken(Args));              // If path does not exist, try if it works relatively to .ssh/              if (!FileExists(ApiPath(IncludePath)))              {                IncludePath = CombinePaths(GetOpensshFolder(), IncludePath);              }              if (FileExists(ApiPath(IncludePath)))              {                std::unique_ptr <TStrings> LinesToInclude(new TStringList());                LoadScriptFromFile(IncludePath, LinesToInclude.get(), true);                Lines->Delete(Index); // Not really needed                for (int Index2 = 0; Index2 < LinesToInclude->Count; Index2++)                {                  Lines->Insert(Index + Index2, LinesToInclude->Strings[Index2]);                }                Index--;              }            }          }        }      }      ImportSessionList->ImportFromOpenssh(Lines.get());      UnicodeString NoSessionsError = FORMAT(L"%s\n(%s)", (LoadStr(OPENSSH_CONFIG_NO_SITES), ConfigFile));      SelectSessionsToImportIfAny(ImportSessionList.get(), Sessions, Error, NoSessionsError);    }    else    {      throw Exception(LoadStr(OPENSSH_CONFIG_NOT_FOUND));    }  }  catch (Exception & E)  {    Error = FORMAT(L"%s\n(%s)", (E.Message, ConfigFile));  }  return ImportSessionList.release();}//---------------------------------------------------------------------------TStoredSessionList * TConfiguration::SelectSessionsForImport(  TStoredSessionList * Sessions, const UnicodeString & FileName, UnicodeString & Error){  std::unique_ptr<TStoredSessionList> ImportSessionList(CreateSessionsForImport(Sessions));  try  {    if (FileName.IsEmpty())    {      throw Exception(LoadStr(INI_SELECT));    }    else    {      std::unique_ptr<THierarchicalStorage> ImportStorage(TIniFileStorage::CreateFromPath(FileName));      ImportStorage->AccessMode = smRead;      if (ImportStorage->OpenSubKey(Configuration->StoredSessionsSubKey, false))      {        ImportSessionList->Load(ImportStorage.get());      }      UnicodeString NoSessionsError = FMTLOAD(INI_NO_SITES, (FileName));      SelectSessionsToImportIfAny(ImportSessionList.get(), Sessions, Error, NoSessionsError);    }  }  catch (Exception & E)  {    Error = E.Message;  }  return ImportSessionList.release();}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetRandomSeedFile(UnicodeString value){  if (RandomSeedFile != value)  {    UnicodeString PrevRandomSeedFileName = RandomSeedFileName;    FRandomSeedFile = value;    // never allow empty seed file to avoid Putty trying to reinitialize the path    if (RandomSeedFileName.IsEmpty())    {      FRandomSeedFile = FDefaultRandomSeedFile;    }    if (!PrevRandomSeedFileName.IsEmpty() &&        (PrevRandomSeedFileName != RandomSeedFileName) &&        FileExists(ApiPath(PrevRandomSeedFileName)))    {      // ignore any error      DeleteFile(ApiPath(PrevRandomSeedFileName));    }  }}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetDirectoryStatisticsCacheKey(  const UnicodeString & SessionKey, const UnicodeString & Path, const TCopyParamType & CopyParam){  std::unique_ptr<TStringList> RawOptions(new TStringList());  RawOptions->Add(SessionKey);  RawOptions->Add(UnixExcludeTrailingBackslash(Path));  TCopyParamType Defaults;  TCopyParamType FilterCopyParam;  FilterCopyParam.IncludeFileMask = CopyParam.IncludeFileMask;  FilterCopyParam.ExcludeHiddenFiles = CopyParam.ExcludeHiddenFiles;  FilterCopyParam.ExcludeEmptyDirectories = CopyParam.ExcludeEmptyDirectories;  std::unique_ptr<TOptionsStorage> OptionsStorage(new TOptionsStorage(RawOptions.get(), true));  FilterCopyParam.Save(OptionsStorage.get(), &Defaults);  UTF8String RawOptionsBuf(RawOptions->CommaText.LowerCase());  UnicodeString Result = Sha256(RawOptionsBuf.c_str(), RawOptionsBuf.Length());  return Result;}//---------------------------------------------------------------------------THierarchicalStorage * TConfiguration::OpenDirectoryStatisticsCache(bool CanCreate){  std::unique_ptr<THierarchicalStorage> Storage(Configuration->CreateConfigStorage());  Storage->AccessMode = CanCreate ? smReadWrite : smRead;  if (!Storage->OpenSubKey(DirectoryStatisticsCacheKey, CanCreate))  {    Storage.reset(NULL);  }  return Storage.release();}//---------------------------------------------------------------------------TStrings * __fastcall TConfiguration::LoadDirectoryStatisticsCache(  const UnicodeString & SessionKey, const UnicodeString & Path, const TCopyParamType & CopyParam){  std::unique_ptr<THierarchicalStorage> Storage(OpenDirectoryStatisticsCache(false));  TStrings * Result;  if (Storage.get() != NULL)  {    UnicodeString Key = GetDirectoryStatisticsCacheKey(SessionKey, Path, CopyParam);    UnicodeString Buf = Storage->ReadString(Key, UnicodeString());    Result = CommaTextToStringList(Buf);  }  else  {    Result = new TStringList();  }  return Result;}//---------------------------------------------------------------------------void __fastcall TConfiguration::SaveDirectoryStatisticsCache(  const UnicodeString & SessionKey, const UnicodeString & Path, const TCopyParamType & CopyParam, TStrings * DataList){  std::unique_ptr<THierarchicalStorage> Storage(OpenDirectoryStatisticsCache(true));  if (Storage.get() != NULL)  {    UnicodeString Key = GetDirectoryStatisticsCacheKey(SessionKey, Path, CopyParam);    UnicodeString Buf = DataList->CommaText;    Storage->WriteString(Key, Buf);  }}//---------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetRandomSeedFileName(){  // StripPathQuotes should not be needed as we do not feed quotes anymore  return StripPathQuotes(ExpandEnvironmentVariables(FRandomSeedFile)).Trim();}//---------------------------------------------------------------------void __fastcall TConfiguration::SetExternalIpAddress(UnicodeString value){  SET_CONFIG_PROPERTY(ExternalIpAddress);}//---------------------------------------------------------------------bool TConfiguration::HasLocalPortNumberLimits(){  return (LocalPortNumberMin > 0) && (LocalPortNumberMax >= LocalPortNumberMin);}//---------------------------------------------------------------------void TConfiguration::SetLocalPortNumberMin(int value){  SET_CONFIG_PROPERTY(LocalPortNumberMin);}//---------------------------------------------------------------------void TConfiguration::SetLocalPortNumberMax(int value){  SET_CONFIG_PROPERTY(LocalPortNumberMax);}//---------------------------------------------------------------------void __fastcall TConfiguration::SetMimeTypes(UnicodeString value){  SET_CONFIG_PROPERTY(MimeTypes);}//---------------------------------------------------------------------void TConfiguration::SetCertificateStorage(const UnicodeString & value){  SET_CONFIG_PROPERTY(CertificateStorage);}//---------------------------------------------------------------------UnicodeString TConfiguration::GetCertificateStorageExpanded(){  UnicodeString Result = FCertificateStorage;  if (Result.IsEmpty())  {    UnicodeString DefaultCertificateStorage = CombinePaths(ExtractFilePath(ModuleFileName()), L"cacert.pem");    if (FileExists(DefaultCertificateStorage))    {      Result = DefaultCertificateStorage;    }  }  return Result;}//---------------------------------------------------------------------void TConfiguration::SetAWSAPI(const UnicodeString & value){  SET_CONFIG_PROPERTY(AWSAPI);}//---------------------------------------------------------------------void __fastcall TConfiguration::SetTryFtpWhenSshFails(bool value){  SET_CONFIG_PROPERTY(TryFtpWhenSshFails);}//---------------------------------------------------------------------void __fastcall TConfiguration::SetParallelDurationThreshold(int value){  SET_CONFIG_PROPERTY(ParallelDurationThreshold);}//---------------------------------------------------------------------void __fastcall TConfiguration::SetPuttyRegistryStorageKey(UnicodeString value){  SET_CONFIG_PROPERTY_EX(PuttyRegistryStorageKey,    RefreshPuttySshHostCAList());}//---------------------------------------------------------------------------TEOLType __fastcall TConfiguration::GetLocalEOLType(){  return eolCRLF;}//---------------------------------------------------------------------bool __fastcall TConfiguration::GetCollectUsage(){  return FUsage->Collect;}//---------------------------------------------------------------------void __fastcall TConfiguration::SetCollectUsage(bool value){  FUsage->Collect = value;}//---------------------------------------------------------------------void __fastcall TConfiguration::TemporaryLogging(const UnicodeString ALogFileName){  if (SameText(ExtractFileExt(ALogFileName), L".xml"))  {    TemporaryActionsLogging(ALogFileName);  }  else  {    FLogging = true;    FLogFileName = ALogFileName;    UpdateActualLogProtocol();  }}//---------------------------------------------------------------------void __fastcall TConfiguration::TemporaryActionsLogging(const UnicodeString ALogFileName){  FLogActions = true;  FActionsLogFileName = ALogFileName;}//---------------------------------------------------------------------void __fastcall TConfiguration::TemporaryLogProtocol(int ALogProtocol){  FLogProtocol = ALogProtocol;  UpdateActualLogProtocol();}//---------------------------------------------------------------------void __fastcall TConfiguration::TemporaryLogSensitive(bool ALogSensitive){  FLogSensitive = ALogSensitive;}//---------------------------------------------------------------------void __fastcall TConfiguration::TemporaryLogMaxSize(__int64 ALogMaxSize){  FLogMaxSize = ALogMaxSize;}//---------------------------------------------------------------------void __fastcall TConfiguration::TemporaryLogMaxCount(int ALogMaxCount){  FLogMaxCount = ALogMaxCount;}//---------------------------------------------------------------------void __fastcall TConfiguration::SetLogging(bool value){  TGuard Guard(FCriticalSection);  if (Logging != value)  {    FPermanentLogging = value;    FLogging = value;    UpdateActualLogProtocol();    Changed();  }}//---------------------------------------------------------------------bool __fastcall TConfiguration::GetLogging(){  TGuard Guard(FCriticalSection);  return FPermanentLogging;}//---------------------------------------------------------------------void __fastcall TConfiguration::SetLogFileName(UnicodeString value){  TGuard Guard(FCriticalSection);  if (LogFileName != value)  {    FPermanentLogFileName = value;    FLogFileName = value;    Changed();  }}//---------------------------------------------------------------------UnicodeString  __fastcall TConfiguration::GetLogFileName(){  TGuard Guard(FCriticalSection);  return FPermanentLogFileName;}//---------------------------------------------------------------------void __fastcall TConfiguration::SetActionsLogFileName(UnicodeString value){  TGuard Guard(FCriticalSection);  if (ActionsLogFileName != value)  {    FPermanentActionsLogFileName = value;    FActionsLogFileName = value;    Changed();  }}//---------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetPermanentActionsLogFileName(){  TGuard Guard(FCriticalSection);  return FPermanentActionsLogFileName;}//---------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetActionsLogFileName(){  TGuard Guard(FCriticalSection);  return FActionsLogFileName;}//---------------------------------------------------------------------bool __fastcall TConfiguration::GetLogToFile(){  // guarded within GetLogFileName  return !LogFileName.IsEmpty();}//---------------------------------------------------------------------void __fastcall TConfiguration::UpdateActualLogProtocol(){  FActualLogProtocol = FLogging ? FLogProtocol : (-BelowNormalLogLevels - 1);}//---------------------------------------------------------------------void __fastcall TConfiguration::SetLogProtocol(int value){  TGuard Guard(FCriticalSection);  if (LogProtocol != value)  {    FPermanentLogProtocol = value;    FLogProtocol = value;    Changed();    UpdateActualLogProtocol();  }}//---------------------------------------------------------------------void __fastcall TConfiguration::SetLogActions(bool value){  TGuard Guard(FCriticalSection);  if (LogActions != value)  {    FPermanentLogActions = value;    FLogActions = value;    Changed();  }}//---------------------------------------------------------------------bool __fastcall TConfiguration::GetLogActions(){  TGuard Guard(FCriticalSection);  return FPermanentLogActions;}//---------------------------------------------------------------------void __fastcall TConfiguration::SetLogFileAppend(bool value){  SET_CONFIG_PROPERTY(LogFileAppend);}//---------------------------------------------------------------------void __fastcall TConfiguration::SetLogSensitive(bool value){  if (LogSensitive != value)  {    FPermanentLogSensitive = value;    FLogSensitive = value;    Changed();  }}//---------------------------------------------------------------------void __fastcall TConfiguration::SetLogMaxSize(__int64 value){  TGuard Guard(FCriticalSection);  if (LogMaxSize != value)  {    FPermanentLogMaxSize = value;    FLogMaxSize = value;    Changed();  }}//---------------------------------------------------------------------__int64 __fastcall TConfiguration::GetLogMaxSize(){  TGuard Guard(FCriticalSection);  return FPermanentLogMaxSize;}//---------------------------------------------------------------------void __fastcall TConfiguration::SetLogMaxCount(int value){  if (LogMaxCount != value)  {    FPermanentLogMaxCount = value;    FLogMaxCount = value;    Changed();  }}//---------------------------------------------------------------------int __fastcall TConfiguration::GetLogMaxCount(){  TGuard Guard(FCriticalSection);  return FPermanentLogMaxCount;}//---------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetDefaultLogFileName(){  return L"%TEMP%\\!S.log";}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetConfirmOverwriting(bool value){  TGuard Guard(FCriticalSection);  SET_CONFIG_PROPERTY(ConfirmOverwriting);}//---------------------------------------------------------------------------bool __fastcall TConfiguration::GetConfirmOverwriting(){  TGuard Guard(FCriticalSection);  return FConfirmOverwriting;}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetConfirmResume(bool value){  TGuard Guard(FCriticalSection);  SET_CONFIG_PROPERTY(ConfirmResume);}//---------------------------------------------------------------------------bool __fastcall TConfiguration::GetConfirmResume(){  TGuard Guard(FCriticalSection);  return FConfirmResume;}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetAutoReadDirectoryAfterOp(bool value){  TGuard Guard(FCriticalSection);  SET_CONFIG_PROPERTY(AutoReadDirectoryAfterOp);}//---------------------------------------------------------------------------bool __fastcall TConfiguration::GetAutoReadDirectoryAfterOp(){  TGuard Guard(FCriticalSection);  return FAutoReadDirectoryAfterOp;}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetTimeFormat(){  return L"h:nn:ss";}//---------------------------------------------------------------------------UnicodeString __fastcall TConfiguration::GetDefaultKeyFile(){  return L"";}//---------------------------------------------------------------------------bool __fastcall TConfiguration::GetRememberPassword(){  return false;}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetSessionReopenAuto(int value){  SET_CONFIG_PROPERTY(SessionReopenAuto);}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetSessionReopenBackground(int value){  SET_CONFIG_PROPERTY(SessionReopenBackground);}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetSessionReopenTimeout(int value){  SET_CONFIG_PROPERTY(SessionReopenTimeout);}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetSessionReopenAutoStall(int value){  SET_CONFIG_PROPERTY(SessionReopenAutoStall);}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetTunnelLocalPortNumberLow(int value){  SET_CONFIG_PROPERTY(TunnelLocalPortNumberLow);}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetTunnelLocalPortNumberHigh(int value){  SET_CONFIG_PROPERTY(TunnelLocalPortNumberHigh);}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetCacheDirectoryChangesMaxSize(int value){  SET_CONFIG_PROPERTY(CacheDirectoryChangesMaxSize);}//---------------------------------------------------------------------------void __fastcall TConfiguration::SetShowFtpWelcomeMessage(bool value){  SET_CONFIG_PROPERTY(ShowFtpWelcomeMessage);}//---------------------------------------------------------------------------void TConfiguration::SetQueueTransfersLimit(int value){  SET_CONFIG_PROPERTY(QueueTransfersLimit);}//---------------------------------------------------------------------------const TSshHostCAList * TConfiguration::GetSshHostCAList(){  return FSshHostCAList.get();}//---------------------------------------------------------------------------void TConfiguration::SetSshHostCAList(const TSshHostCAList * value){  *FSshHostCAList = *value;}//---------------------------------------------------------------------------const TSshHostCAList * TConfiguration::GetPuttySshHostCAList(){  if (FPuttySshHostCAList.get() == NULL)  {    std::unique_ptr<TRegistryStorage> Storage(new TRegistryStorage(PuttyRegistryStorageKey));    Storage->ConfigureForPutty();    FPuttySshHostCAList.reset(new TSshHostCAList());    LoadSshHostCAList(FPuttySshHostCAList.get(), Storage.get());  }  return FPuttySshHostCAList.get();}//---------------------------------------------------------------------------void TConfiguration::RefreshPuttySshHostCAList(){  FPuttySshHostCAList.reset(NULL);}//---------------------------------------------------------------------------const TSshHostCAList * TConfiguration::GetActiveSshHostCAList(){  return FSshHostCAsFromPuTTY ? PuttySshHostCAList : SshHostCAList;}//---------------------------------------------------------------------------bool __fastcall TConfiguration::GetPersistent(){  return (Storage != stNul) && !FDontSave;}//---------------------------------------------------------------------------//---------------------------------------------------------------------------void __fastcall TShortCuts::Add(TShortCut ShortCut){  FShortCuts.insert(ShortCut);}//---------------------------------------------------------------------------bool __fastcall TShortCuts::Has(TShortCut ShortCut) const{  return (FShortCuts.count(ShortCut) != 0);}
 |