//--------------------------------------------------------------------- #include #pragma hdrstop #include #include "About.h" // must be included before WebBrowserEx.hpp to avoid ambiguity of tagLOGFONTW #include #include #include #include #include #include #include //--------------------------------------------------------------------- #pragma link "SHDocVw_OCX" #pragma resource "*.dfm" //--------------------------------------------------------------------------- static void __fastcall DoAboutDialog(TConfiguration * Configuration, bool AllowLicense, TRegistration * Registration, bool LoadThirdParty) { TAboutDialog * AboutDialog = NULL; try { AboutDialog = new TAboutDialog(Application, Configuration, AllowLicense, Registration, LoadThirdParty); AboutDialog->ShowModal(); } __finally { delete AboutDialog; } } //--------------------------------------------------------------------------- void __fastcall DoAboutDialog(TConfiguration * Configuration, bool AllowLicense, TRegistration * Registration) { try { DoAboutDialog(Configuration, AllowLicense, Registration, true); } catch (EOleException &) { // This happens particularly on Wine that does not support some // functionality of embedded IE we need. DoAboutDialog(Configuration, AllowLicense, Registration, false); } } //--------------------------------------------------------------------------- __fastcall TAboutDialog::TAboutDialog(TComponent * AOwner, TConfiguration * Configuration, bool AllowLicense, TRegistration * Registration, bool ALoadThirdParty) : TForm(AOwner) { FConfiguration = Configuration; UseSystemSettings(this); LinkLabel(HomepageLabel, LoadStr(HOMEPAGE_URL)); LinkLabel(ForumUrlLabel, LoadStr(FORUM_URL)); ApplicationLabel->Caption = AppName; TColor MainInstructionColor; HFONT MainInstructionFont; HFONT InstructionFont; GetInstrutionsTheme(MainInstructionColor, MainInstructionFont, InstructionFont); if (MainInstructionFont != 0) { int PrevHeight = ApplicationLabel->Height; ApplicationLabel->Font->Handle = MainInstructionFont; if (MainInstructionColor != Graphics::clNone) { ApplicationLabel->Font->Color = MainInstructionColor; } ShiftControls(ApplicationLabel->Top + 1, (ApplicationLabel->Height - PrevHeight)); } else { ApplicationLabel->ParentFont = true; ApplicationLabel->Font->Style = ApplicationLabel->Font->Style << fsBold; } WinSCPCopyrightLabel->Caption = LoadStr(WINSCP_COPYRIGHT); if (Registration == NULL) { RegistrationLabel->Visible = false; RegistrationBox->Visible = false; ShiftControls(RegistrationLabel->Top, (RegistrationBox->Top - ThirdPartyPanel->Top)); } else { RegistrationSubjectLabel->Caption = Registration->Subject; if (Registration->Registered) { UnicodeString Text; Text = FORMAT(LoadStrPart(ABOUT_REGISTRATION_LICENSES, 1), (Registration->Licenses >= 0 ? IntToStr(Registration->Licenses) : UnicodeString(LoadStrPart(ABOUT_REGISTRATION_LICENSES, 2)))); if (!Registration->NeverExpires) { Text = FMTLOAD(ABOUT_REGISTRATION_EXPIRES, (Text, FormatDateTime(L"ddddd", Registration->Expiration))); } RegistrationLicensesLabel->Caption = Text; Text = FMTLOAD(ABOUT_REGISTRATION_PRODUCTID, (Registration->ProductId)); if (Registration->EduLicense) { Text = FMTLOAD(ABOUT_REGISTRATION_EDULICENSE, (Text)); } RegistrationProductIdLabel->Caption = Text; RegistrationProductIdLabel->Font->Style = RegistrationProductIdLabel->Font->Style << fsBold; } else { RegistrationLicensesLabel->Visible = false; FOnRegistrationLink = Registration->OnRegistrationLink; RegistrationProductIdLabel->Caption = LoadStr(ABOUT_REGISTRATION_LINK); LinkLabel(RegistrationProductIdLabel, L""); } } LicenseButton->Visible = AllowLicense; LoadData(); if (ALoadThirdParty) { LoadThirdParty(); } else { CreateLabelPanel(ThirdPartyPanel, LoadStr(MESSAGE_DISPLAY_ERROR)); } int IconSize = ScaleByPixelsPerInch(48, this); FIconHandle = static_cast(LoadImage(MainInstance, L"MAINICON", IMAGE_ICON, IconSize, IconSize, 0)); IconPaintBox->Width = IconSize; IconPaintBox->Height = IconSize; } //--------------------------------------------------------------------------- __fastcall TAboutDialog::~TAboutDialog() { DestroyIcon(FIconHandle); } //--------------------------------------------------------------------------- void __fastcall TAboutDialog::ShiftControls(int From, int Diff) { for (int Index = 0; Index < Panel->ControlCount; Index++) { if (Panel->Controls[Index]->Top > From) { Panel->Controls[Index]->Top = Panel->Controls[Index]->Top + Diff; } } ClientHeight = ClientHeight + Diff; } //--------------------------------------------------------------------------- void __fastcall TAboutDialog::LoadData() { UnicodeString Version = FConfiguration->VersionStr; if (!FConfiguration->ProductName.IsEmpty() && (FConfiguration->Version != FConfiguration->ProductVersion)) { Version = FMTLOAD(ABOUT_BASED_ON_PRODUCT, (Version, FConfiguration->ProductName, FConfiguration->ProductVersion)); } VersionLabel->Caption = Version; } //--------------------------------------------------------------------------- void __fastcall TAboutDialog::LoadThirdParty() { FThirdPartyWebBrowser = CreateBrowserViewer(ThirdPartyPanel, L""); reinterpret_cast(FThirdPartyWebBrowser)->Color = ThirdPartyPanel->Color; ReadyBrowserForStreaming(FThirdPartyWebBrowser); DoLoadThirdParty(); } //--------------------------------------------------------------------------- static UnicodeString ExpatLicenseUrl = L"license:expat"; static UnicodeString HtmlBr = "
\n"; UnicodeString TAboutDialog::GenerateThirdParty(bool Html) { UnicodeString ThirdParty; UnicodeString Br = Html ? HtmlBr : L"\n"; if (!GUIConfiguration->UsingInternalTranslation()) { UnicodeString TranslatorUrl = LoadStr(TRANSLATOR_URL); UnicodeString TranslatorInfo = LoadStr(TRANSLATOR_INFO2); wchar_t LocaleNameStr[255]; GetLocaleInfo( GUIConfiguration->AppliedLocale, LOCALE_SLOCALIZEDLANGUAGENAME, LocaleNameStr, std::size(LocaleNameStr)); UnicodeString LocaleName(LocaleNameStr); // The {language} should be present only if we are using an untranslated // (=english) string UnicodeString TranslationHeader = ReplaceStr(LoadStr(ABOUT_TRANSLATIONS_HEADER), L"{language}", LocaleName); AddPara( Html, ThirdParty, TranslationHeader + Br + FMTLOAD(ABOUT_TRANSLATIONS_COPYRIGHT, (GUIConfiguration->AppliedLocaleCopyright())) + Br + (!TranslatorInfo.IsEmpty() ? TranslatorInfo + Br : EmptyStr) + (!TranslatorUrl.IsEmpty() ? CreateLink(Html, TranslatorUrl) : EmptyStr)); } AddPara(Html, ThirdParty, LoadStr(ABOUT_THIRDPARTY_HEADER)); AddPara( Html, ThirdParty, FMTLOAD(PUTTY_BASED_ON, (GetPuTTYVersion())) + Br + LoadStr(PUTTY_COPYRIGHT) + Br + CreateLicenseLinkLine(Html, LoadStr(PUTTY_LICENSE_URL)) + CreateLink(Html, LoadStr(PUTTY_URL))); UnicodeString OpenSSLVersionText = GetOpenSSLVersionText(); CutToChar(OpenSSLVersionText, L' ', true); // "OpenSSL" UnicodeString OpenSSLVersion = CutToChar(OpenSSLVersionText, L' ', true); CutToChar(OpenSSLVersionText, L' ', true); // day CutToChar(OpenSSLVersionText, L' ', true); // month UnicodeString OpenSSLYear = CutToChar(OpenSSLVersionText, L' ', true); AddPara( Html, ThirdParty, FMTLOAD(OPENSSL_BASED_ON, (OpenSSLVersion)) + Br + FMTLOAD(OPENSSL_COPYRIGHT2, (OpenSSLYear)) + Br + CreateLink(Html, LoadStr(OPENSSL_URL))); AddPara( Html, ThirdParty, LoadStr(FILEZILLA_BASED_ON2) + Br + LoadStr(FILEZILLA_COPYRIGHT2) + Br + CreateLink(Html, LoadStr(FILEZILLA_URL))); AddPara( Html, ThirdParty, FMTLOAD(NEON_BASED_ON2, (NeonVersion())) + Br + LoadStr(NEON_COPYRIGHT) + Br + CreateLink(Html, LoadStr(NEON_URL))); AddPara( Html, ThirdParty, FMTLOAD(S3_BASED_ON, (S3LibVersion())) + Br + LoadStr(S3_COPYRIGHT) + Br + CreateLicenseLinkLine(Html, LoadStr(S3_LICENSE_URL)) + CreateLink(Html, LoadStr(S3_URL))); AddPara( Html, ThirdParty, FMTLOAD(EXPAT_BASED_ON, (ExpatVersion())) + Br + CreateLicenseLinkLine(Html, ExpatLicenseUrl) + CreateLink(Html, LoadStr(EXPAT_URL))); AddPara( Html, ThirdParty, FMTLOAD(ABOUT_TOOLBAR2000, (Toolbar2000Version)) + Br + LoadStr(ABOUT_TOOLBAR2000_COPYRIGHT) + Br + CreateLink(Html, LoadStr(ABOUT_TOOLBAR2000_URL))); AddPara( Html, ThirdParty, FMTLOAD(ABOUT_TBX, (TBXVersionString)) + Br + LoadStr(ABOUT_TBX_COPYRIGHT) + Br + CreateLink(Html, LoadStr(ABOUT_TBX_URL))); AddPara( Html, ThirdParty, LoadStr(ABOUT_FILEMANAGER) + Br + LoadStr(ABOUT_FILEMANAGER_COPYRIGHT)); UnicodeString JclVersion = FormatVersion(JclVersionMajor, JclVersionMinor, JclVersionRelease) + L" " + JclCommit; AddPara( Html, ThirdParty, FMTLOAD(ABOUT_JCL, (JclVersion)) + Br + CreateLink(Html, LoadStr(ABOUT_JCL_URL))); AddPara( Html, ThirdParty, LoadStr(ABOUT_PNG) + Br + LoadStr(ABOUT_PNG_COPYRIGHT) + Br + CreateLink(Html, LoadStr(ABOUT_PNG_URL))); return ThirdParty; } //--------------------------------------------------------------------------- void __fastcall TAboutDialog::DoLoadThirdParty() { WaitBrowserToIdle(FThirdPartyWebBrowser); AddBrowserLinkHandler(FThirdPartyWebBrowser, ExpatLicenseUrl, ExpatLicenceHandler); UnicodeString ThirdParty = GenerateThirdParty(true); ThirdParty = GenerateAppHtmlPage(Font, ThirdPartyPanel, ThirdParty, false); LoadBrowserDocument(FThirdPartyWebBrowser, ThirdParty); } //--------------------------------------------------------------------------- void TAboutDialog::AddPara(bool Html, UnicodeString & Text, const UnicodeString & S) { UnicodeString Para = S; if (Html) { Para = L"

" + Para + L"

\n"; } else { Para += L"\n\n"; } Text += Para; } //--------------------------------------------------------------------------- UnicodeString TAboutDialog::CreateLicenseLinkLine(bool Html, const UnicodeString & URL) { return Html ? (CreateLink(true, URL, LoadStr(ABOUT_THIRDPARTY_LICENSE)) + HtmlBr) : EmptyStr; } //--------------------------------------------------------------------------- UnicodeString TAboutDialog::CreateLink(bool Html, const UnicodeString & URL, const UnicodeString & Title) { if (Html) { return FORMAT(L"%s", (URL, Title.IsEmpty() ? URL : Title)); } else { DebugAssert(Title.IsEmpty()); return URL; } } //--------------------------------------------------------------------------- void __fastcall TAboutDialog::LicenseButtonClick(TObject * /*Sender*/) { DoProductLicense(); } //--------------------------------------------------------------------------- void __fastcall TAboutDialog::HelpButtonClick(TObject * /*Sender*/) { FormHelp(this); } //--------------------------------------------------------------------------- void __fastcall TAboutDialog::RegistrationProductIdLabelClick( TObject * /*Sender*/) { if (FOnRegistrationLink != NULL) { FOnRegistrationLink(this); } } //--------------------------------------------------------------------------- void __fastcall TAboutDialog::OKButtonMouseDown(TObject * /*Sender*/, TMouseButton Button, TShiftState Shift, int /*X*/, int /*Y*/) { if (Button == mbRight) { if (Shift.Contains(ssAlt)) { AccessViolationTest(); } else if (Shift.Contains(ssShift)) { InternalExceptionTest(); } else if (Shift.Contains(ssCtrl)) { LookupAddress(); } } } //--------------------------------------------------------------------------- void __fastcall TAboutDialog::LookupAddress() { UnicodeString S; if (InputQuery(L"Address lookup", L"&Address:", S)) { void * Address = reinterpret_cast(StrToInt(L"$" + S)); ShowMessage(GetLocationInfoStr(Address, true, true, true, true)); } } //--------------------------------------------------------------------------- #ifdef _WIN64 static thread_local EXCEPTION_RECORD ExceptionRecord; static thread_local bool ExceptionCaptured = false; //--------------------------------------------------------------------------- LONG WINAPI CaptureException(EXCEPTION_POINTERS * ExceptionInfo) { if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { ExceptionRecord = *(ExceptionInfo->ExceptionRecord); ExceptionCaptured = true; } return EXCEPTION_CONTINUE_SEARCH; // Let the local __except block catch it } #endif //--------------------------------------------------------------------------- [[noreturn]] static void RaiseInternalError(Exception * E) { throw ExtException(E, MainInstructions(L"Internal error test.")); } //--------------------------------------------------------------------------- #ifdef _WIN64 [[noreturn]] #endif void TAboutDialog::AccessViolationTest() { #ifdef _WIN64 PVOID ExceptionHandler = AddVectoredExceptionHandler(1, CaptureException); ExceptionCaptured = false; __try { ACCESS_VIOLATION_TEST; } #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunreachable-code" __except (EXCEPTION_EXECUTE_HANDLER) #pragma clang diagnostic pop { RemoveVectoredExceptionHandler(ExceptionHandler); if (ExceptionCaptured) { auto VclExceptionRecord = reinterpret_cast(&ExceptionRecord); Exception * E = static_cast(reinterpret_cast(ExceptObjProc)(VclExceptionRecord)); RaiseInternalError(E); } throw Exception(L"Unknown hardware exception occurred."); } #else try { ACCESS_VIOLATION_TEST; } catch (Exception & E) { RaiseInternalError(&E); } #endif } //--------------------------------------------------------------------------- void TAboutDialog::InternalExceptionTest() { try { (new TList())->Error(L"List error", 0); } catch (Exception & E) { RaiseInternalError(&E); } } //--------------------------------------------------------------------------- void __fastcall TAboutDialog::ExpatLicenceHandler(TObject * /*Sender*/) { DoLicenseDialog(lcExpat); } //--------------------------------------------------------------------------- void __fastcall TAboutDialog::IconPaintBoxPaint(TObject * /*Sender*/) { DrawIconEx(IconPaintBox->Canvas->Handle, 0, 0, FIconHandle, IconPaintBox->Width, IconPaintBox->Height, 0, NULL, DI_NORMAL); } //--------------------------------------------------------------------------- void __fastcall TAboutDialog::FormAfterMonitorDpiChanged(TObject *, int OldDPI, int NewDPI) { DebugUsedParam2(OldDPI, NewDPI); if (FThirdPartyWebBrowser != NULL) { DoLoadThirdParty(); } } //--------------------------------------------------------------------------- void __fastcall TAboutDialog::FormKeyDown(TObject *, WORD & Key, TShiftState Shift) { if ((Key == L'C') && Shift.Contains(ssCtrl)) { if ((FThirdPartyWebBrowser != NULL) && FThirdPartyWebBrowser->Focused() && (FThirdPartyWebBrowser->SelLength() > 0)) { // Let the browser handle the Ctrl+C } else { UnicodeString Text = ApplicationLabel->Caption + sLineBreak + VersionLabel->Caption + sLineBreak + sLineBreak + WinSCPCopyrightLabel->Caption + sLineBreak + HomepageLabel->Caption + sLineBreak + sLineBreak + ProductSpecificMessageLabel->Caption + sLineBreak + ForumUrlLabel->Caption + sLineBreak; Text += sLineBreak + GetDividerLine() + sLineBreak + Label3->Caption + sLineBreak + TrimRight(GenerateThirdParty(false)) + sLineBreak; TInstantOperationVisualizer Visualizer; CopyToClipboard(Text); Key = 0; } } } //---------------------------------------------------------------------------