diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index 106da0fbd..6b5b07bd0 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -189,7 +189,7 @@ namespace winrt::TerminalApp::implementation } AppLogic::AppLogic() : - _reloadState{ std::chrono::milliseconds(100), []() { ApplicationState::SharedInstance().Reload(); } } + _reloadState{ std::chrono::milliseconds(100), []() { ApplicationState::SharedInstance().Reload(); ElevatedState::SharedInstance().Reload(); } } { // For your own sanity, it's better to do setup outside the ctor. // If you do any setup in the ctor that ends up throwing an exception, @@ -870,6 +870,7 @@ namespace winrt::TerminalApp::implementation { const std::filesystem::path settingsPath{ std::wstring_view{ CascadiaSettings::SettingsPath() } }; const std::filesystem::path statePath{ std::wstring_view{ ApplicationState::SharedInstance().FilePath() } }; + // const std::filesystem::path elevatedStatePath{ std::wstring_view{ ElevatedState::SharedInstance().FilePath() } }; _reader.create( settingsPath.parent_path().c_str(), @@ -879,14 +880,14 @@ namespace winrt::TerminalApp::implementation // editors, who will write a temp file, then rename it to be the // actual file you wrote. So listen for that too. wil::FolderChangeEvents::FileName | wil::FolderChangeEvents::LastWriteTime, - [this, settingsBasename = settingsPath.filename(), stateBasename = statePath.filename()](wil::FolderChangeEvent, PCWSTR fileModified) { + [=](wil::FolderChangeEvent, PCWSTR fileModified) { const auto modifiedBasename = std::filesystem::path{ fileModified }.filename(); - if (modifiedBasename == settingsBasename) + if (modifiedBasename == settingsPath.filename()) { _reloadSettings->Run(); } - else if (modifiedBasename == stateBasename) + else if (modifiedBasename == statePath.filename() /*|| modifiedBasename == elevatedStatePath.filename()*/) { _reloadState(); } diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index f9e8cbf12..ad38d7a9b 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -486,6 +486,18 @@ Warning + + Cancel + + + You are about t execute the following commandline. {TODO! format this}. Do you wish to continue? + + + Allow Commandline + + + Warning + Type a command name... diff --git a/src/cascadia/TerminalApp/TabManagement.cpp b/src/cascadia/TerminalApp/TabManagement.cpp index 849bfcc69..ed1f40d3a 100644 --- a/src/cascadia/TerminalApp/TabManagement.cpp +++ b/src/cascadia/TerminalApp/TabManagement.cpp @@ -235,8 +235,44 @@ namespace winrt::TerminalApp::implementation // - profile: profile settings for this connection // - settings: the TerminalSettings object to use to create the TerminalControl with. // - existingConnection: optionally receives a connection from the outside world instead of attempting to create one - void TerminalPage::_CreateNewTabWithProfileAndSettings(const Profile& profile, const TerminalSettingsCreateResult& settings, TerminalConnection::ITerminalConnection existingConnection) + winrt::fire_and_forget TerminalPage::_CreateNewTabWithProfileAndSettings(Microsoft::Terminal::Settings::Model::Profile profile, Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult settings, TerminalConnection::ITerminalConnection existingConnection) { + if (_isElevated()) + { + auto cmdline{ settings.DefaultSettings().Commandline() }; + auto allowedCommandlines{ ElevatedState::SharedInstance().AllowedCommandlines() }; + bool commandlineWasAllowed = false; + + if (allowedCommandlines) + { + for (const auto& approved : allowedCommandlines) + { + if (approved == cmdline) + { + commandlineWasAllowed = true; + break; + } + } + } + else + { + allowedCommandlines = winrt::single_threaded_vector(); + } + if (!commandlineWasAllowed) + { + ContentDialogResult warningResult = co_await _ShowCommandlineApproveWarning(); + if (warningResult != ContentDialogResult::Primary) + { + co_return; + } + else + { + allowedCommandlines.Append(cmdline); + } + ElevatedState::SharedInstance().AllowedCommandlines(allowedCommandlines); + } + } + // Initialize the new tab // Create a connection based on the values in our settings object if we weren't given one. auto connection = existingConnection ? existingConnection : _CreateConnectionFromSettings(profile, settings.DefaultSettings()); diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 8ae486548..1f0f0d35f 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -49,6 +49,23 @@ namespace winrt namespace winrt::TerminalApp::implementation { + bool TerminalPage::_isElevated() const noexcept + { + // GH#2455 - Make sure to try/catch calls to Application::Current, + // because that _won't_ be an instance of TerminalApp::App in the + // LocalTests + try + { + // GH#3581 - There's a platform limitation that causes us to crash when we rearrange tabs. + // Xaml tries to send a drag visual (to wit: a screenshot) to the drag hosting process, + // but that process is running at a different IL than us. + // For now, we're disabling elevated drag. + return ::winrt::Windows::UI::Xaml::Application::Current().as<::winrt::TerminalApp::App>().Logic().IsElevated(); + } + CATCH_LOG(); + return false; + } + TerminalPage::TerminalPage() : _tabs{ winrt::single_threaded_observable_vector() }, _mruTabs{ winrt::single_threaded_observable_vector() }, @@ -128,19 +145,7 @@ namespace winrt::TerminalApp::implementation _tabView = _tabRow.TabView(); _rearranging = false; - // GH#2455 - Make sure to try/catch calls to Application::Current, - // because that _won't_ be an instance of TerminalApp::App in the - // LocalTests - auto isElevated = false; - try - { - // GH#3581 - There's a platform limitation that causes us to crash when we rearrange tabs. - // Xaml tries to send a drag visual (to wit: a screenshot) to the drag hosting process, - // but that process is running at a different IL than us. - // For now, we're disabling elevated drag. - isElevated = ::winrt::Windows::UI::Xaml::Application::Current().as<::winrt::TerminalApp::App>().Logic().IsElevated(); - } - CATCH_LOG(); + const auto isElevated = _isElevated(); if (_settings.GlobalSettings().UseAcrylicInTabRow()) { @@ -574,6 +579,15 @@ namespace winrt::TerminalApp::implementation co_return ContentDialogResult::None; } + winrt::Windows::Foundation::IAsyncOperation TerminalPage::_ShowCommandlineApproveWarning() + { + if (auto presenter{ _dialogPresenter.get() }) + { + co_return co_await presenter.ShowDialog(FindName(L"ApproveCommandlineWarning").try_as()); + } + co_return ContentDialogResult::None; + } + // Method Description: // - Builds the flyout (dropdown) attached to the new tab button, and // attaches it to the button. Populates the flyout with one entry per diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 0bdcf4aae..4c3ae8f8e 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -179,17 +179,19 @@ namespace winrt::TerminalApp::implementation std::shared_ptr _windowIdToast{ nullptr }; std::shared_ptr _windowRenameFailedToast{ nullptr }; + bool _isElevated() const noexcept; void _ShowAboutDialog(); winrt::Windows::Foundation::IAsyncOperation _ShowCloseWarningDialog(); winrt::Windows::Foundation::IAsyncOperation _ShowCloseReadOnlyDialog(); winrt::Windows::Foundation::IAsyncOperation _ShowMultiLinePasteWarningDialog(); winrt::Windows::Foundation::IAsyncOperation _ShowLargePasteWarningDialog(); + winrt::Windows::Foundation::IAsyncOperation _ShowCommandlineApproveWarning(); void _CreateNewTabFlyout(); void _OpenNewTabDropdown(); HRESULT _OpenNewTab(const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr); void _CreateNewTabFromPane(std::shared_ptr pane); - void _CreateNewTabWithProfileAndSettings(const Microsoft::Terminal::Settings::Model::Profile& profile, const Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr); + winrt::fire_and_forget _CreateNewTabWithProfileAndSettings(Microsoft::Terminal::Settings::Model::Profile profile, Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult settings, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr); winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection _CreateConnectionFromSettings(Microsoft::Terminal::Settings::Model::Profile profile, Microsoft::Terminal::Settings::Model::TerminalSettings settings); winrt::fire_and_forget _OpenNewWindow(const bool elevate, const Microsoft::Terminal::Settings::Model::NewTerminalArgs newTerminalArgs); diff --git a/src/cascadia/TerminalApp/TerminalPage.xaml b/src/cascadia/TerminalApp/TerminalPage.xaml index 35ac1807d..d7c37a70b 100644 --- a/src/cascadia/TerminalApp/TerminalPage.xaml +++ b/src/cascadia/TerminalApp/TerminalPage.xaml @@ -103,6 +103,11 @@ + +