mirror of
https://github.com/winscp/winscp.git
synced 2026-10-24 02:28:55 +03:00
Raw site settings editor
Source commit: caf055e335fef5e08a1685b4fb7a52986f3043cf
This commit is contained in:
@@ -116,7 +116,7 @@ TSessionData * __fastcall TSessionData::Clone()
|
||||
return Data.release();
|
||||
}
|
||||
//---------------------------------------------------------------------
|
||||
void __fastcall TSessionData::Default()
|
||||
void __fastcall TSessionData::DefaultSettings()
|
||||
{
|
||||
HostName = L"";
|
||||
PortNumber = SshPortNumber;
|
||||
@@ -275,6 +275,11 @@ void __fastcall TSessionData::Default()
|
||||
|
||||
CustomParam1 = L"";
|
||||
CustomParam2 = L"";
|
||||
}
|
||||
//---------------------------------------------------------------------
|
||||
void __fastcall TSessionData::Default()
|
||||
{
|
||||
DefaultSettings();
|
||||
|
||||
IsWorkspace = false;
|
||||
Link = L"";
|
||||
@@ -1176,7 +1181,12 @@ void __fastcall TSessionData::DoSave(THierarchicalStorage * Storage,
|
||||
WRITE_DATA(String, CustomParam2);
|
||||
}
|
||||
|
||||
SavePasswords(Storage, PuttyExport, DoNotEncryptPasswords);
|
||||
// This is for collecting all keys for TSiteRawDialog::AddButtonClick.
|
||||
// It should be enough to test for (Default == NULL),
|
||||
// the DoNotEncryptPasswords and PuttyExport were added to limit a possible unintended impact.
|
||||
bool SaveAll = (Default == NULL) && DoNotEncryptPasswords && !PuttyExport;
|
||||
|
||||
SavePasswords(Storage, PuttyExport, DoNotEncryptPasswords, SaveAll);
|
||||
}
|
||||
//---------------------------------------------------------------------
|
||||
TStrings * __fastcall TSessionData::SaveToOptions(const TSessionData * Default, bool SaveName)
|
||||
@@ -1486,21 +1496,26 @@ void __fastcall TSessionData::ImportFromFilezilla(
|
||||
|
||||
}
|
||||
//---------------------------------------------------------------------
|
||||
void __fastcall TSessionData::SavePasswords(THierarchicalStorage * Storage, bool PuttyExport, bool DoNotEncryptPasswords)
|
||||
void __fastcall TSessionData::SavePasswords(THierarchicalStorage * Storage, bool PuttyExport, bool DoNotEncryptPasswords, bool SaveAll)
|
||||
{
|
||||
if (!Configuration->DisablePasswordStoring && !PuttyExport && !FPassword.IsEmpty())
|
||||
if (!Configuration->DisablePasswordStoring && !PuttyExport && (!FPassword.IsEmpty() || SaveAll))
|
||||
{
|
||||
// DoNotEncryptPasswords is set when called from GenerateOpenCommandArgs only
|
||||
// and it never saves session password
|
||||
DebugAssert(!DoNotEncryptPasswords);
|
||||
|
||||
Storage->WriteBinaryDataAsString(L"Password", StronglyRecryptPassword(FPassword, UserName+HostName));
|
||||
if (DoNotEncryptPasswords)
|
||||
{
|
||||
Storage->WriteString(L"PasswordPlain", Password);
|
||||
Storage->DeleteValue(L"Password");
|
||||
}
|
||||
else
|
||||
{
|
||||
Storage->WriteBinaryDataAsString(L"Password", StronglyRecryptPassword(FPassword, UserName+HostName));
|
||||
Storage->DeleteValue(L"PasswordPlain");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Storage->DeleteValue(L"Password");
|
||||
Storage->DeleteValue(L"PasswordPlain");
|
||||
}
|
||||
Storage->DeleteValue(L"PasswordPlain");
|
||||
|
||||
if (PuttyExport)
|
||||
{
|
||||
@@ -1511,7 +1526,7 @@ void __fastcall TSessionData::SavePasswords(THierarchicalStorage * Storage, bool
|
||||
{
|
||||
if (DoNotEncryptPasswords)
|
||||
{
|
||||
if (!FProxyPassword.IsEmpty())
|
||||
if (!FProxyPassword.IsEmpty() || SaveAll)
|
||||
{
|
||||
Storage->WriteString(L"ProxyPassword", ProxyPassword);
|
||||
}
|
||||
@@ -1524,7 +1539,7 @@ void __fastcall TSessionData::SavePasswords(THierarchicalStorage * Storage, bool
|
||||
else
|
||||
{
|
||||
// save password encrypted
|
||||
if (!FProxyPassword.IsEmpty())
|
||||
if (!FProxyPassword.IsEmpty() || SaveAll)
|
||||
{
|
||||
Storage->WriteBinaryDataAsString(L"ProxyPasswordEnc", StronglyRecryptPassword(FProxyPassword, ProxyUsername+ProxyHost));
|
||||
}
|
||||
@@ -1537,7 +1552,7 @@ void __fastcall TSessionData::SavePasswords(THierarchicalStorage * Storage, bool
|
||||
|
||||
if (DoNotEncryptPasswords)
|
||||
{
|
||||
if (!FTunnelPassword.IsEmpty())
|
||||
if (!FTunnelPassword.IsEmpty() || SaveAll)
|
||||
{
|
||||
Storage->WriteString(L"TunnelPasswordPlain", TunnelPassword);
|
||||
}
|
||||
@@ -1548,7 +1563,7 @@ void __fastcall TSessionData::SavePasswords(THierarchicalStorage * Storage, bool
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Configuration->DisablePasswordStoring && !FTunnelPassword.IsEmpty())
|
||||
if (!Configuration->DisablePasswordStoring && (!FTunnelPassword.IsEmpty() || SaveAll))
|
||||
{
|
||||
Storage->WriteBinaryDataAsString(L"TunnelPassword", StronglyRecryptPassword(FTunnelPassword, TunnelUserName+TunnelHostName));
|
||||
}
|
||||
@@ -1560,7 +1575,7 @@ void __fastcall TSessionData::SavePasswords(THierarchicalStorage * Storage, bool
|
||||
|
||||
if (DoNotEncryptPasswords)
|
||||
{
|
||||
if (!FEncryptKey.IsEmpty())
|
||||
if (!FEncryptKey.IsEmpty() || SaveAll)
|
||||
{
|
||||
Storage->WriteString(L"EncryptKeyPlain", EncryptKey);
|
||||
}
|
||||
@@ -1572,7 +1587,7 @@ void __fastcall TSessionData::SavePasswords(THierarchicalStorage * Storage, bool
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!FEncryptKey.IsEmpty())
|
||||
if (!FEncryptKey.IsEmpty() || SaveAll)
|
||||
{
|
||||
Storage->WriteBinaryDataAsString(L"EncryptKey", StronglyRecryptPassword(FEncryptKey, UserName+HostName));
|
||||
}
|
||||
@@ -1664,7 +1679,7 @@ void __fastcall TSessionData::SaveRecryptedPasswords(THierarchicalStorage * Stor
|
||||
{
|
||||
RecryptPasswords();
|
||||
|
||||
SavePasswords(Storage, false, false);
|
||||
SavePasswords(Storage, false, false, false);
|
||||
}
|
||||
__finally
|
||||
{
|
||||
|
||||
@@ -403,7 +403,7 @@ private:
|
||||
void __fastcall SetEncryptKey(UnicodeString value);
|
||||
|
||||
TDateTime __fastcall GetTimeoutDT();
|
||||
void __fastcall SavePasswords(THierarchicalStorage * Storage, bool PuttyExport, bool DoNotEncryptPasswords);
|
||||
void __fastcall SavePasswords(THierarchicalStorage * Storage, bool PuttyExport, bool DoNotEncryptPasswords, bool SaveAll);
|
||||
UnicodeString __fastcall GetLocalName();
|
||||
UnicodeString __fastcall GetFolderName();
|
||||
void __fastcall Modify();
|
||||
@@ -444,8 +444,6 @@ private:
|
||||
void __fastcall AddAssemblyProperty(
|
||||
UnicodeString & Result, TAssemblyLanguage Language,
|
||||
const UnicodeString & Name, bool Value);
|
||||
TStrings * __fastcall SaveToOptions(const TSessionData * Default, bool SaveName);
|
||||
void __fastcall ApplyRawSettings(TStrings * RawSettings);
|
||||
TStrings * __fastcall GetRawSettingsForUrl();
|
||||
void __fastcall DoCopyData(TSessionData * SourceData, bool NoRecrypt);
|
||||
template<class AlgoT>
|
||||
@@ -460,8 +458,10 @@ public:
|
||||
virtual __fastcall ~TSessionData();
|
||||
TSessionData * __fastcall Clone();
|
||||
void __fastcall Default();
|
||||
void __fastcall DefaultSettings();
|
||||
void __fastcall NonPersistant();
|
||||
void __fastcall Load(THierarchicalStorage * Storage, bool PuttyImport);
|
||||
void __fastcall ApplyRawSettings(TStrings * RawSettings);
|
||||
void __fastcall ApplyRawSettings(THierarchicalStorage * Storage);
|
||||
void __fastcall ImportFromFilezilla(_di_IXMLNode Node, const UnicodeString & Path, _di_IXMLNode SettingsNode);
|
||||
void __fastcall Save(THierarchicalStorage * Storage, bool PuttyExport,
|
||||
@@ -483,6 +483,7 @@ public:
|
||||
bool __fastcall ParseUrl(UnicodeString Url, TOptions * Options,
|
||||
TStoredSessionList * StoredSessions, bool & DefaultsOnly,
|
||||
UnicodeString * FileName, bool * AProtocolDefined, UnicodeString * MaskedUrl, int Flags);
|
||||
TStrings * __fastcall SaveToOptions(const TSessionData * Default, bool SaveName);
|
||||
void __fastcall ConfigureTunnel(int PortNumber);
|
||||
void __fastcall RollbackTunnel();
|
||||
void __fastcall ExpandEnvironmentVariables();
|
||||
|
||||
@@ -1443,3 +1443,165 @@ void __fastcall DoUsageStatisticsDialog()
|
||||
std::unique_ptr<TUsageStatisticsDialog> Dialog(new TUsageStatisticsDialog());
|
||||
Dialog->Execute();
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
//---------------------------------------------------------------------------
|
||||
class TSiteRawDialog : public TCustomDialog
|
||||
{
|
||||
public:
|
||||
__fastcall TSiteRawDialog();
|
||||
|
||||
bool __fastcall Execute(TSessionData * Data);
|
||||
|
||||
protected:
|
||||
// virtual void __fastcall DoChange(bool & CanSubmit);
|
||||
|
||||
private:
|
||||
TMemo * SettingsMemo;
|
||||
TButton * AdddButton;
|
||||
|
||||
void __fastcall AddButtonClick(TObject * Sender);
|
||||
void __fastcall SettingsMemoKeyDown(TObject * Sender, WORD & Key, TShiftState Shift);
|
||||
|
||||
void DeleteNames(TStrings * Names, TStrings * Options);
|
||||
};
|
||||
//---------------------------------------------------------------------------
|
||||
__fastcall TSiteRawDialog::TSiteRawDialog() :
|
||||
TCustomDialog(HELP_SITE_RAW)
|
||||
{
|
||||
Caption = LoadStr(SITE_RAW_CAPTION);
|
||||
Width = ScaleByTextHeight(this, 400);
|
||||
|
||||
SettingsMemo = new TMemo(this);
|
||||
SettingsMemo->Height = ScaleByTextHeight(this, 300);
|
||||
SettingsMemo->OnKeyDown = SettingsMemoKeyDown;
|
||||
AddEdit(SettingsMemo, NULL);
|
||||
|
||||
AdddButton = new TButton(this);
|
||||
AdddButton->Caption = LoadStr(SITE_RAW_ADD);
|
||||
AdddButton->Width = OKButton->Width;
|
||||
AdddButton->OnClick = AddButtonClick;
|
||||
AddDialogButton(AdddButton);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
bool __fastcall TSiteRawDialog::Execute(TSessionData * Data)
|
||||
{
|
||||
std::unique_ptr<TSessionData> FactoryDefaults(new TSessionData(L""));
|
||||
std::unique_ptr<TSessionData> RawData(new TSessionData(L""));
|
||||
RawData->Assign(Data);
|
||||
// SFTP-only is not reflected by the protocol prefix, we have to use rawsettings for that
|
||||
if (RawData->FSProtocol != fsSFTPonly)
|
||||
{
|
||||
RawData->FSProtocol = FactoryDefaults->FSProtocol;
|
||||
}
|
||||
RawData->HostName = FactoryDefaults->HostName;
|
||||
RawData->PortNumber = FactoryDefaults->PortNumber;
|
||||
RawData->UserName = FactoryDefaults->UserName;
|
||||
RawData->Password = FactoryDefaults->Password;
|
||||
RawData->Ftps = FactoryDefaults->Ftps;
|
||||
|
||||
std::unique_ptr<TStrings> Options(RawData->SaveToOptions(FactoryDefaults.get(), false));
|
||||
|
||||
SettingsMemo->Lines = Options.get();
|
||||
|
||||
bool Result = TCustomDialog::Execute();
|
||||
if (Result)
|
||||
{
|
||||
std::unique_ptr<TSessionData> BackupData(new TSessionData(L""));
|
||||
BackupData->Assign(Data);
|
||||
Data->DefaultSettings();
|
||||
|
||||
Data->FSProtocol = BackupData->FSProtocol;
|
||||
Data->HostName = BackupData->HostName;
|
||||
Data->PortNumber = BackupData->PortNumber;
|
||||
Data->UserName = BackupData->UserName;
|
||||
Data->Password = BackupData->Password;
|
||||
Data->Ftps = BackupData->Ftps;
|
||||
|
||||
Data->ApplyRawSettings(SettingsMemo->Lines);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall TSiteRawDialog::SettingsMemoKeyDown(TObject * Sender, WORD & Key, TShiftState Shift)
|
||||
{
|
||||
MemoKeyDown(Sender, Key, Shift);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall TSiteRawDialog::AddButtonClick(TObject *)
|
||||
{
|
||||
std::unique_ptr<TSessionData> FactoryDefaults(new TSessionData(L""));
|
||||
std::unique_ptr<TSessionData> BasicData(new TSessionData(L""));
|
||||
BasicData->FSProtocol = TFSProtocol(FactoryDefaults->FSProtocol + 1);
|
||||
UnicodeString RandomAppendix(L"_");
|
||||
BasicData->HostName = FactoryDefaults->HostName + RandomAppendix;
|
||||
BasicData->Ftps = TFtps(FactoryDefaults->Ftps + 1);
|
||||
BasicData->PortNumber = DefaultPort(BasicData->FSProtocol, BasicData->Ftps) + 1;
|
||||
BasicData->UserName = FactoryDefaults->UserName + RandomAppendix;
|
||||
BasicData->Password = FactoryDefaults->Password + RandomAppendix;
|
||||
|
||||
std::unique_ptr<TStrings> BasicOptions(BasicData->SaveToOptions(FactoryDefaults.get(), false));
|
||||
|
||||
std::unique_ptr<TStrings> AllOptions(FactoryDefaults->SaveToOptions(NULL, false));
|
||||
|
||||
std::unique_ptr<TStrings> Names(CreateSortedStringList());
|
||||
for (int Index = 0; Index < AllOptions->Count; Index++)
|
||||
{
|
||||
Names->Add(AllOptions->Names[Index]);
|
||||
}
|
||||
DeleteNames(Names.get(), BasicOptions.get());
|
||||
DeleteNames(Names.get(), SettingsMemo->Lines);
|
||||
|
||||
std::unique_ptr<TCustomDialog> AddDialog(new TCustomDialog(HelpKeyword));
|
||||
AddDialog->Caption = LoadStr(SITE_RAW_ADD_CAPTION);
|
||||
TComboBox * AddComboBox = new TComboBox(AddDialog.get());
|
||||
AddComboBox->Style = csDropDownList;
|
||||
AddComboBox->DropDownCount = Max(AddComboBox->DropDownCount, 16);
|
||||
AddDialog->AddComboBox(AddComboBox, CreateLabel(LoadStr(SITE_RAW_ADD_LABEL)), Names.get(), true);
|
||||
AddComboBox->ItemIndex = 0;
|
||||
if (AddDialog->Execute())
|
||||
{
|
||||
UnicodeString Name = AddComboBox->Items->Strings[AddComboBox->ItemIndex];
|
||||
UnicodeString Value = AllOptions->Values[Name];
|
||||
UnicodeString NameAndSeparator = Name + SettingsMemo->Lines->NameValueSeparator;
|
||||
int Start = (SettingsMemo->Lines->Text + NameAndSeparator).Length();
|
||||
SettingsMemo->Lines->Add(NameAndSeparator + Value);
|
||||
SettingsMemo->SetFocus();
|
||||
SettingsMemo->SelStart = Start;
|
||||
SettingsMemo->SelLength = Value.Length();
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void TSiteRawDialog::DeleteNames(TStrings * Names, TStrings * Options)
|
||||
{
|
||||
for (int Index = 0; Index < Options->Count; Index++)
|
||||
{
|
||||
UnicodeString Name = Options->Names[Index];
|
||||
if (!Name.IsEmpty())
|
||||
{
|
||||
int I = Names->IndexOf(Name);
|
||||
if (I >= 0)
|
||||
{
|
||||
Names->Delete(I);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
/*void __fastcall TUsageStatisticsDialog::DoChange(bool & CanSubmit)
|
||||
{
|
||||
TCustomDialog::DoChange(CanSubmit);
|
||||
UnicodeString Text = Configuration->Usage->Serialize(L"\n", FilterEdit->Text);
|
||||
bool NoUsage = Text.IsEmpty();
|
||||
ClipboardButton->Enabled = !NoUsage;
|
||||
if (NoUsage)
|
||||
{
|
||||
Text = LoadStr(USAGE_DATA_NONE2);
|
||||
}
|
||||
UsageMemo->Lines->Text = Text;
|
||||
} */
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall DoSiteRawDialog(TSessionData * Data)
|
||||
{
|
||||
std::unique_ptr<TSiteRawDialog> Dialog(new TSiteRawDialog());
|
||||
Dialog->Execute(Data);
|
||||
}
|
||||
|
||||
@@ -1182,6 +1182,10 @@ void __fastcall TLoginDialog::ActionListUpdate(TBasicAction * BasicAction,
|
||||
{
|
||||
SessionAdvancedAction->Enabled = Editable;
|
||||
}
|
||||
else if (Action == SessionRawAction)
|
||||
{
|
||||
SessionRawAction->Enabled = Editable;
|
||||
}
|
||||
else if (Action == SaveAsSessionAction)
|
||||
{
|
||||
// Save as is needed for new site only when !SupportsSplitButton()
|
||||
@@ -2773,7 +2777,7 @@ void __fastcall TLoginDialog::PersistNewSiteIfNeeded()
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall TLoginDialog::SessionAdvancedActionExecute(TObject * /*Sender*/)
|
||||
void __fastcall TLoginDialog::SessionAdvancedActionExecute(TObject * Sender)
|
||||
{
|
||||
// If we ever allow showing advanced settings, while read-only,
|
||||
// we must make sure that FSessionData actually holds the advanced settings,
|
||||
@@ -2789,7 +2793,14 @@ void __fastcall TLoginDialog::SessionAdvancedActionExecute(TObject * /*Sender*/)
|
||||
ParseHostName();
|
||||
|
||||
SaveSession(FSessionData);
|
||||
DoSiteAdvancedDialog(FSessionData);
|
||||
if (Sender == SessionAdvancedAction)
|
||||
{
|
||||
DoSiteAdvancedDialog(FSessionData);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoSiteRawDialog(FSessionData);
|
||||
}
|
||||
// Needed only for Note.
|
||||
// The only other property visible on Login dialog that Advanced site dialog
|
||||
// can change is protocol (between fsSFTP and fsSFTPonly),
|
||||
|
||||
@@ -682,6 +682,11 @@ object LoginDialog: TLoginDialog
|
||||
Caption = 'Close and Do Not Show Automatically Again'
|
||||
OnExecute = NeverShowAgainActionExecute
|
||||
end
|
||||
object SessionRawAction: TAction
|
||||
Category = 'Session'
|
||||
Caption = 'Edit &Raw Settings...'
|
||||
OnExecute = SessionAdvancedActionExecute
|
||||
end
|
||||
end
|
||||
object ToolsPopupMenu: TPopupMenu
|
||||
Left = 144
|
||||
@@ -1387,6 +1392,9 @@ object LoginDialog: TLoginDialog
|
||||
Action = SessionAdvancedAction
|
||||
Default = True
|
||||
end
|
||||
object EditRawSettings1: TMenuItem
|
||||
Action = SessionRawAction
|
||||
end
|
||||
object TransferSettingsRule1: TMenuItem
|
||||
Action = CopyParamRuleAction
|
||||
end
|
||||
|
||||
@@ -211,6 +211,8 @@ __published:
|
||||
TMenuItem *MenuItem20;
|
||||
TAction *CloseAction;
|
||||
TAction *NeverShowAgainAction;
|
||||
TAction *SessionRawAction;
|
||||
TMenuItem *EditRawSettings1;
|
||||
void __fastcall DataChange(TObject *Sender);
|
||||
void __fastcall FormShow(TObject *Sender);
|
||||
void __fastcall SessionTreeDblClick(TObject *Sender);
|
||||
|
||||
@@ -65,5 +65,6 @@
|
||||
#define HELP_DD_TARGET_UNKNOWN "ui_pref_dragdrop#fake_file"
|
||||
#define HELP_FILE_COLORS "ui_file_color"
|
||||
#define HELP_AUTOMATIC_UPDATE "updates#automatic_upgrade"
|
||||
#define HELP_SITE_RAW "ui_login_raw"
|
||||
|
||||
#endif // TextsWin
|
||||
|
||||
@@ -620,6 +620,10 @@
|
||||
#define UPDATES_DONATE_HTML 6020
|
||||
#define EDITOR_NEW 6021
|
||||
#define PREFERENCES_STATISTICS_CAPTION 6022
|
||||
#define SITE_RAW_CAPTION 6023
|
||||
#define SITE_RAW_ADD 6024
|
||||
#define SITE_RAW_ADD_CAPTION 6025
|
||||
#define SITE_RAW_ADD_LABEL 6026
|
||||
|
||||
// 2xxx is reserved for TextsFileZilla.h
|
||||
|
||||
|
||||
@@ -625,6 +625,10 @@ BEGIN
|
||||
UPDATES_DONATE_HTML, "To enable automatic updates, please <a href=\"%DONATE_URL%\">donate to WinSCP development</a> or %GET_IMG% WinSCP from <a href=\"%STORE_URL%\">Microsoft Store</a>."
|
||||
EDITOR_NEW, "New"
|
||||
PREFERENCES_STATISTICS_CAPTION, "Statistics"
|
||||
SITE_RAW_CAPTION, "Raw Site Settings"
|
||||
SITE_RAW_ADD, "&Add..."
|
||||
SITE_RAW_ADD_CAPTION, "Add Raw Site Setting"
|
||||
SITE_RAW_ADD_LABEL, "&Site Setting:"
|
||||
|
||||
WIN_VARIABLE_STRINGS, "WIN_VARIABLE"
|
||||
WINSCP_COPYRIGHT, "Copyright © 2000-2019 Martin Prikryl"
|
||||
|
||||
@@ -150,6 +150,7 @@ bool __fastcall DoCustomCommandOptionsDialog(
|
||||
const TCustomCommandType * Command, TStrings * CustomCommandOptions, TShortCut * ShortCut, unsigned int Flags,
|
||||
TCustomCommand * CustomCommandForOptions, const UnicodeString & Site, const TShortCuts * ShortCuts);
|
||||
void __fastcall DoUsageStatisticsDialog();
|
||||
void __fastcall DoSiteRawDialog(TSessionData * Data);
|
||||
|
||||
// windows\UserInterface.cpp
|
||||
bool __fastcall DoMasterPasswordDialog();
|
||||
|
||||
Reference in New Issue
Block a user