From dd0b8b2cb611b06db5cf9871f7ae0eb771be3be3 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 29 Oct 2020 05:34:55 -0500 Subject: [PATCH 1/9] This is a scratch sample of checking if the service is enabled --- src/tools/scratch/main.cpp | 77 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/src/tools/scratch/main.cpp b/src/tools/scratch/main.cpp index c6f9cc901a2..34cd676032a 100644 --- a/src/tools/scratch/main.cpp +++ b/src/tools/scratch/main.cpp @@ -2,9 +2,86 @@ // Licensed under the MIT license. #include +#include // This wmain exists for help in writing scratch programs while debugging. int __cdecl wmain(int /*argc*/, WCHAR* /*argv[]*/) { + printf("Getting manager...\n"); + auto hManager = OpenSCManager(nullptr, nullptr, SERVICE_QUERY_CONFIG); + // printf("OpenSCManager returned %d\n", static_cast(hManager)); + if (hManager == 0) + { + auto gle = GetLastError(); + printf("gle: %d", gle); + return gle; + } + + printf("Getting service...\n"); + auto hService = OpenService(hManager, L"TabletInputService", SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS); + // printf("OpenService returned %d\n", static_cast(hService)); + if (hService == 0) + { + auto gle = GetLastError(); + printf("gle: %d", gle); + return gle; + } + + DWORD dwBytesNeeded = 0; + LPQUERY_SERVICE_CONFIG lpsc = nullptr; + + printf("Getting config size...\n"); + if (!QueryServiceConfig(hService, + NULL, + 0, + &dwBytesNeeded)) + { + auto gle = GetLastError(); + if (ERROR_INSUFFICIENT_BUFFER == gle) + { + auto cbBufSize = dwBytesNeeded; + lpsc = (LPQUERY_SERVICE_CONFIG)LocalAlloc(LMEM_FIXED, cbBufSize); + } + else + { + printf("QueryServiceConfig failed (%d)", gle); + return gle; + } + } + + printf("Getting config...\n"); + if (!QueryServiceConfig(hService, + lpsc, + dwBytesNeeded, + &dwBytesNeeded)) + { + auto gle = GetLastError(); + printf("QueryServiceConfig failed (%d)", gle); + return gle; + } + + printf("Succeeded!\n"); + + printf("Start Type: 0x%x\n", lpsc->dwStartType); + + SERVICE_STATUS status{ 0 }; + if (!QueryServiceStatus(hService, &status)) + { + auto gle = GetLastError(); + printf("QueryServiceStatus failed (%d)", gle); + return gle; + } + printf("State: 0x%x\n", status.dwCurrentState); + + auto state = status.dwCurrentState; + if (state != SERVICE_RUNNING && state != SERVICE_START_PENDING) + { + printf("The service is stopped\n"); + } + else + { + printf("The service is running\n"); + } + return 0; } From 3c489d9c6d852c7eee6b1395552fd5a3bdeb41d1 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 29 Oct 2020 07:57:33 -0500 Subject: [PATCH 2/9] Pretty confident this will work, just gotta reboot to make sure --- src/cascadia/TerminalApp/AppLogic.cpp | 75 +++++++++++++++++++ src/cascadia/TerminalApp/AppLogic.h | 2 + .../Resources/en-US/Resources.resw | 60 ++++++++------- 3 files changed, 110 insertions(+), 27 deletions(-) diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index 72d7dae9cf2..3dc6ef8b2dd 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -400,6 +400,30 @@ namespace winrt::TerminalApp::implementation ShowDialog(dialog); } + void AppLogic::_ShowKeyboardServiceDisabledDialog() + { + auto title = RS_(L"KeyboardServiceWarningTitle"); + auto text = RS_(L"KeyboardServiceWarningText"); + auto buttonText = RS_(L"Ok"); + + Controls::TextBlock warningsTextBlock; + // Make sure you can copy-paste + warningsTextBlock.IsTextSelectionEnabled(true); + // Make sure the lines of text wrap + warningsTextBlock.TextWrapping(TextWrapping::Wrap); + + warningsTextBlock.Inlines().Append(_BuildErrorRun(text, Application::Current().as<::winrt::TerminalApp::App>().Resources())); + warningsTextBlock.Inlines().Append(Documents::LineBreak{}); + + Controls::ContentDialog dialog; + dialog.Title(winrt::box_value(title)); + dialog.Content(winrt::box_value(warningsTextBlock)); + dialog.CloseButtonText(buttonText); + dialog.DefaultButton(Controls::ContentDialogButton::Close); + + ShowDialog(dialog); + } + // Method Description: // - Displays a dialog for warnings found while loading or validating the // settings. Displays messages for whatever warnings were found while @@ -470,6 +494,11 @@ namespace winrt::TerminalApp::implementation void AppLogic::_OnLoaded(const IInspectable& /*sender*/, const RoutedEventArgs& /*eventArgs*/) { + const auto keyboardServiceIsDisabled = !_IsKeyboardServiceEnabled(); + if (keyboardServiceIsDisabled) + { + _ShowKeyboardServiceDisabledDialog(); + } if (FAILED(_settingsLoadedResult)) { const winrt::hstring titleKey = USES_RESOURCE(L"InitialJsonParseErrorTitle"); @@ -482,6 +511,52 @@ namespace winrt::TerminalApp::implementation } } + bool AppLogic::_IsKeyboardServiceEnabled() + { + if (IsUwp()) + { + return true; + } + + // If at any point we fail to open the service manager, the service, + // etc, then just quick return true to disable the dialog. We'd rather + // not be noisy with this dialog if we failed for some reason. + + // Open the service manager. This will return 0 if it failed. + wil::unique_schandle hManager{ OpenSCManager(nullptr, nullptr, SERVICE_QUERY_STATUS) }; + + if (LOG_LAST_ERROR_IF(!hManager.is_valid())) + { + return true; + } + + // Get a handle to the keyboard service + wil::unique_schandle hService{ OpenService(hManager.get(), L"TabletInputService", SERVICE_QUERY_STATUS) }; + if (LOG_LAST_ERROR_IF(!hService.is_valid())) + { + return true; + } + + // Get the current state of the service + SERVICE_STATUS status{ 0 }; + if (!LOG_IF_WIN32_BOOL_FALSE(QueryServiceStatus(hService.get(), &status))) + { + return true; + } + + const auto state = status.dwCurrentState; + if (state != SERVICE_RUNNING && state != SERVICE_START_PENDING) + { + // The service is off - return false + return false; + } + else + { + // The service is on - this is good. + return true; + } + } + // Method Description: // - Get the size in pixels of the client area we'll need to launch this // terminal app. This method will use the default profile's settings to do diff --git a/src/cascadia/TerminalApp/AppLogic.h b/src/cascadia/TerminalApp/AppLogic.h index a6dfd3251cd..b5222d7247a 100644 --- a/src/cascadia/TerminalApp/AppLogic.h +++ b/src/cascadia/TerminalApp/AppLogic.h @@ -85,6 +85,8 @@ namespace winrt::TerminalApp::implementation void _ShowLoadErrorsDialog(const winrt::hstring& titleKey, const winrt::hstring& contentKey, HRESULT settingsLoadedResult); void _ShowLoadWarningsDialog(); + bool _IsKeyboardServiceEnabled(); + void _ShowKeyboardServiceDisabledDialog(); fire_and_forget _LoadErrorsDialogRoutine(); fire_and_forget _ShowLoadWarningsDialogRoutine(); diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index c7b08834f56..7887375f036 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -1,17 +1,17 @@  - @@ -149,6 +149,12 @@ Encountered errors while loading user settings + + Warning: + + + The "Touch Keyboard and Handwriting Panel Service" isn't running on your machine. This can prevent the Terminal from receiving keyboard input. + OK From 20cf659305c2b1cd87e0766bfebc88ced7215906 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 29 Oct 2020 08:38:17 -0500 Subject: [PATCH 3/9] cleanup for review --- .../actions/spell-check/dictionary/apis.txt | 1 + src/cascadia/TerminalApp/AppLogic.cpp | 16 +++- src/tools/scratch/main.cpp | 77 ------------------- 3 files changed, 16 insertions(+), 78 deletions(-) diff --git a/.github/actions/spell-check/dictionary/apis.txt b/.github/actions/spell-check/dictionary/apis.txt index fddc4ddb7bf..9b997eef7c7 100644 --- a/.github/actions/spell-check/dictionary/apis.txt +++ b/.github/actions/spell-check/dictionary/apis.txt @@ -50,6 +50,7 @@ rfind roundf RSHIFT rx +schandle serializer SIZENS spsc diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index 3dc6ef8b2dd..ebddf50066c 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -400,6 +400,12 @@ namespace winrt::TerminalApp::implementation ShowDialog(dialog); } + // Method Description: + // - Displays a dialog if the "Touch, Keyboard and Handwriting Panel + // Service" is disabled. If it is, we want to warn the user, because they + // won't be able to type in the Terminal. + // - Only one dialog can be visible at a time. If another dialog is visible + // when this is called, nothing happens. See ShowDialog for details void AppLogic::_ShowKeyboardServiceDisabledDialog() { auto title = RS_(L"KeyboardServiceWarningTitle"); @@ -511,6 +517,14 @@ namespace winrt::TerminalApp::implementation } } + // Method Description: + // - Helper for determining if the "Touch, Keyboard and Handwriting Panel + // Service" is enabled. If it isn't, we want to be able to display a + // warning to the user, because they won't be able to type in the + // Terminal. + // Return Value: + // - true if the service is enabled, or if we fail to query the service. We + // return true in that case, to be less noisy (though, that is unexpected) bool AppLogic::_IsKeyboardServiceEnabled() { if (IsUwp()) @@ -524,7 +538,7 @@ namespace winrt::TerminalApp::implementation // Open the service manager. This will return 0 if it failed. wil::unique_schandle hManager{ OpenSCManager(nullptr, nullptr, SERVICE_QUERY_STATUS) }; - + if (LOG_LAST_ERROR_IF(!hManager.is_valid())) { return true; diff --git a/src/tools/scratch/main.cpp b/src/tools/scratch/main.cpp index 34cd676032a..c6f9cc901a2 100644 --- a/src/tools/scratch/main.cpp +++ b/src/tools/scratch/main.cpp @@ -2,86 +2,9 @@ // Licensed under the MIT license. #include -#include // This wmain exists for help in writing scratch programs while debugging. int __cdecl wmain(int /*argc*/, WCHAR* /*argv[]*/) { - printf("Getting manager...\n"); - auto hManager = OpenSCManager(nullptr, nullptr, SERVICE_QUERY_CONFIG); - // printf("OpenSCManager returned %d\n", static_cast(hManager)); - if (hManager == 0) - { - auto gle = GetLastError(); - printf("gle: %d", gle); - return gle; - } - - printf("Getting service...\n"); - auto hService = OpenService(hManager, L"TabletInputService", SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS); - // printf("OpenService returned %d\n", static_cast(hService)); - if (hService == 0) - { - auto gle = GetLastError(); - printf("gle: %d", gle); - return gle; - } - - DWORD dwBytesNeeded = 0; - LPQUERY_SERVICE_CONFIG lpsc = nullptr; - - printf("Getting config size...\n"); - if (!QueryServiceConfig(hService, - NULL, - 0, - &dwBytesNeeded)) - { - auto gle = GetLastError(); - if (ERROR_INSUFFICIENT_BUFFER == gle) - { - auto cbBufSize = dwBytesNeeded; - lpsc = (LPQUERY_SERVICE_CONFIG)LocalAlloc(LMEM_FIXED, cbBufSize); - } - else - { - printf("QueryServiceConfig failed (%d)", gle); - return gle; - } - } - - printf("Getting config...\n"); - if (!QueryServiceConfig(hService, - lpsc, - dwBytesNeeded, - &dwBytesNeeded)) - { - auto gle = GetLastError(); - printf("QueryServiceConfig failed (%d)", gle); - return gle; - } - - printf("Succeeded!\n"); - - printf("Start Type: 0x%x\n", lpsc->dwStartType); - - SERVICE_STATUS status{ 0 }; - if (!QueryServiceStatus(hService, &status)) - { - auto gle = GetLastError(); - printf("QueryServiceStatus failed (%d)", gle); - return gle; - } - printf("State: 0x%x\n", status.dwCurrentState); - - auto state = status.dwCurrentState; - if (state != SERVICE_RUNNING && state != SERVICE_START_PENDING) - { - printf("The service is stopped\n"); - } - else - { - printf("The service is running\n"); - } - return 0; } From 401956dc19b18171b951e894ca7adb3a40e9d8b7 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 2 Nov 2020 16:55:31 -0600 Subject: [PATCH 4/9] well at least this compiles --- src/cascadia/TerminalApp/AppLogic.cpp | 39 +++++++++++++------ .../Resources/en-US/Resources.resw | 3 +- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index ebddf50066c..ef5999e4277 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -400,6 +400,30 @@ namespace winrt::TerminalApp::implementation ShowDialog(dialog); } + std::wstring _getTabletServiceName() + { + wil::unique_schandle hManager{ OpenSCManager(nullptr, nullptr, 0) }; + + if (LOG_LAST_ERROR_IF(!hManager.is_valid())) + { + return L"TabletInputService"; + } + + DWORD cchBuffer = 0; + GetServiceDisplayName(hManager.get(), L"TabletInputService", nullptr, &cchBuffer); + std::wstring buffer; + buffer.resize(cchBuffer); + + if (LOG_LAST_ERROR_IF(!GetServiceDisplayName(hManager.get(), + L"TabletInputService", + buffer.data(), + &cchBuffer))) + { + return L"TabletInputService"; + } + return buffer; + } + // Method Description: // - Displays a dialog if the "Touch, Keyboard and Handwriting Panel // Service" is disabled. If it is, we want to warn the user, because they @@ -409,7 +433,9 @@ namespace winrt::TerminalApp::implementation void AppLogic::_ShowKeyboardServiceDisabledDialog() { auto title = RS_(L"KeyboardServiceWarningTitle"); - auto text = RS_(L"KeyboardServiceWarningText"); + // auto text = RS_(L"KeyboardServiceWarningText"); + const winrt::hstring serviceName{ _getTabletServiceName() }; + const winrt::hstring text{ fmt::format(std::wstring_view(RS_(L"KeyboardServiceWarningText")), serviceName) }; auto buttonText = RS_(L"Ok"); Controls::TextBlock warningsTextBlock; @@ -559,16 +585,7 @@ namespace winrt::TerminalApp::implementation } const auto state = status.dwCurrentState; - if (state != SERVICE_RUNNING && state != SERVICE_START_PENDING) - { - // The service is off - return false - return false; - } - else - { - // The service is on - this is good. - return true; - } + return (state == SERVICE_RUNNING || state == SERVICE_START_PENDING); } // Method Description: diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index 7887375f036..8932613ce99 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -153,7 +153,8 @@ Warning: - The "Touch Keyboard and Handwriting Panel Service" isn't running on your machine. This can prevent the Terminal from receiving keyboard input. + The "{0}" service isn't running on your machine. This can prevent the Terminal from receiving keyboard input. + {0} will be replaced with the OS-localized name of the TabletInputService OK From 2e502a9f940e71317b2e76575dc52bf4094b682b Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 2 Nov 2020 17:36:38 -0600 Subject: [PATCH 5/9] Make it actually work, silly Win32 APIs not leaving space for a NULL --- src/cascadia/TerminalApp/AppLogic.cpp | 4 +++- src/cascadia/TerminalApp/Resources/en-US/Resources.resw | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index ef5999e4277..463033fb143 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -412,6 +412,7 @@ namespace winrt::TerminalApp::implementation DWORD cchBuffer = 0; GetServiceDisplayName(hManager.get(), L"TabletInputService", nullptr, &cchBuffer); std::wstring buffer; + cchBuffer += 1; // Add space for a null buffer.resize(cchBuffer); if (LOG_LAST_ERROR_IF(!GetServiceDisplayName(hManager.get(), @@ -526,7 +527,8 @@ namespace winrt::TerminalApp::implementation void AppLogic::_OnLoaded(const IInspectable& /*sender*/, const RoutedEventArgs& /*eventArgs*/) { - const auto keyboardServiceIsDisabled = !_IsKeyboardServiceEnabled(); + const auto keyboardServiceIsDisabled = true; + // const auto keyboardServiceIsDisabled = !_IsKeyboardServiceEnabled(); if (keyboardServiceIsDisabled) { _ShowKeyboardServiceDisabledDialog(); diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index 8932613ce99..7ffa21da2b1 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -153,7 +153,7 @@ Warning: - The "{0}" service isn't running on your machine. This can prevent the Terminal from receiving keyboard input. + The "{0}" isn't running on your machine. This can prevent the Terminal from receiving keyboard input. {0} will be replaced with the OS-localized name of the TabletInputService From 5d6b40c1156c29c62a80cfaf20ae336210a99eda Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 2 Nov 2020 18:21:45 -0600 Subject: [PATCH 6/9] You want it in XAML, here it is in XAML --- src/cascadia/TerminalApp/AppLogic.cpp | 62 +---------------- .../Resources/en-US/Resources.resw | 5 +- src/cascadia/TerminalApp/TerminalPage.cpp | 68 +++++++++++++++++++ src/cascadia/TerminalApp/TerminalPage.h | 3 + src/cascadia/TerminalApp/TerminalPage.idl | 2 + src/cascadia/TerminalApp/TerminalPage.xaml | 14 ++++ 6 files changed, 93 insertions(+), 61 deletions(-) diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index 463033fb143..cecdd835930 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -400,63 +400,6 @@ namespace winrt::TerminalApp::implementation ShowDialog(dialog); } - std::wstring _getTabletServiceName() - { - wil::unique_schandle hManager{ OpenSCManager(nullptr, nullptr, 0) }; - - if (LOG_LAST_ERROR_IF(!hManager.is_valid())) - { - return L"TabletInputService"; - } - - DWORD cchBuffer = 0; - GetServiceDisplayName(hManager.get(), L"TabletInputService", nullptr, &cchBuffer); - std::wstring buffer; - cchBuffer += 1; // Add space for a null - buffer.resize(cchBuffer); - - if (LOG_LAST_ERROR_IF(!GetServiceDisplayName(hManager.get(), - L"TabletInputService", - buffer.data(), - &cchBuffer))) - { - return L"TabletInputService"; - } - return buffer; - } - - // Method Description: - // - Displays a dialog if the "Touch, Keyboard and Handwriting Panel - // Service" is disabled. If it is, we want to warn the user, because they - // won't be able to type in the Terminal. - // - Only one dialog can be visible at a time. If another dialog is visible - // when this is called, nothing happens. See ShowDialog for details - void AppLogic::_ShowKeyboardServiceDisabledDialog() - { - auto title = RS_(L"KeyboardServiceWarningTitle"); - // auto text = RS_(L"KeyboardServiceWarningText"); - const winrt::hstring serviceName{ _getTabletServiceName() }; - const winrt::hstring text{ fmt::format(std::wstring_view(RS_(L"KeyboardServiceWarningText")), serviceName) }; - auto buttonText = RS_(L"Ok"); - - Controls::TextBlock warningsTextBlock; - // Make sure you can copy-paste - warningsTextBlock.IsTextSelectionEnabled(true); - // Make sure the lines of text wrap - warningsTextBlock.TextWrapping(TextWrapping::Wrap); - - warningsTextBlock.Inlines().Append(_BuildErrorRun(text, Application::Current().as<::winrt::TerminalApp::App>().Resources())); - warningsTextBlock.Inlines().Append(Documents::LineBreak{}); - - Controls::ContentDialog dialog; - dialog.Title(winrt::box_value(title)); - dialog.Content(winrt::box_value(warningsTextBlock)); - dialog.CloseButtonText(buttonText); - dialog.DefaultButton(Controls::ContentDialogButton::Close); - - ShowDialog(dialog); - } - // Method Description: // - Displays a dialog for warnings found while loading or validating the // settings. Displays messages for whatever warnings were found while @@ -527,11 +470,10 @@ namespace winrt::TerminalApp::implementation void AppLogic::_OnLoaded(const IInspectable& /*sender*/, const RoutedEventArgs& /*eventArgs*/) { - const auto keyboardServiceIsDisabled = true; - // const auto keyboardServiceIsDisabled = !_IsKeyboardServiceEnabled(); + const auto keyboardServiceIsDisabled = !_IsKeyboardServiceEnabled(); if (keyboardServiceIsDisabled) { - _ShowKeyboardServiceDisabledDialog(); + _root->ShowKeyboardServiceWarning(); } if (FAILED(_settingsLoadedResult)) { diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index 7ffa21da2b1..4a6cbdeb511 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -149,7 +149,10 @@ Encountered errors while loading user settings - + + Ok + + Warning: diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 8af85650f71..568776fe8b0 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -2624,6 +2624,74 @@ namespace winrt::TerminalApp::implementation } } + // Method Description: + // - Displays a dialog stating the "Touch, Keyboard and Handwriting Panel + // Service" is disabled. + void TerminalPage::ShowKeyboardServiceWarning() + { + if (auto presenter{ _dialogPresenter.get() }) + { + presenter.ShowDialog(FindName(L"KeyboardServiceDisabledDialog").try_as()); + } + } + + // Function Description: + // - Helper function to get the OS-localized name for the "Touch, Keyboard + // and Handwriting Panel Service". If we can't open up the service for any + // reason, then we'll just return the service's key, "TabletInputService". + // Return Value: + // - The OS-localized name for the TabletInputService + std::wstring _getTabletServiceName() + { + auto isUwp = false; + try + { + isUwp = ::winrt::Windows::UI::Xaml::Application::Current().as<::winrt::TerminalApp::App>().Logic().IsUwp(); + } + CATCH_LOG(); + + if (isUwp) + { + return L"TabletInputService"; + } + + wil::unique_schandle hManager{ OpenSCManager(nullptr, nullptr, 0) }; + + if (LOG_LAST_ERROR_IF(!hManager.is_valid())) + { + return L"TabletInputService"; + } + + DWORD cchBuffer = 0; + GetServiceDisplayName(hManager.get(), L"TabletInputService", nullptr, &cchBuffer); + std::wstring buffer; + cchBuffer += 1; // Add space for a null + buffer.resize(cchBuffer); + + if (LOG_LAST_ERROR_IF(!GetServiceDisplayName(hManager.get(), + L"TabletInputService", + buffer.data(), + &cchBuffer))) + { + return L"TabletInputService"; + } + return buffer; + } + + // Method Description: + // - Return the fully-formed warning message for the + // "KeyboardServiceDisabled" dialog. This dialog is used to warn the user + // if the keyboard service is disabled, and uses the OS localization for + // the service's actual name. It's boud to the dialog in XAML. + // Return Value: + // - The warning message, including the OS-localized service name. + winrt::hstring TerminalPage::KeyboardServiceDisabledText() + { + const winrt::hstring serviceName{ _getTabletServiceName() }; + const winrt::hstring text{ fmt::format(std::wstring_view(RS_(L"KeyboardServiceWarningText")), serviceName) }; + return text; + } + // -------------------------------- WinRT Events --------------------------------- // Winrt events need a method for adding a callback to the event and removing the callback. // These macros will define them both for you. diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 9df26d24285..dd6f101f8f5 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -71,6 +71,9 @@ namespace winrt::TerminalApp::implementation winrt::TerminalApp::IDialogPresenter DialogPresenter() const; void DialogPresenter(winrt::TerminalApp::IDialogPresenter dialogPresenter); + void ShowKeyboardServiceWarning(); + winrt::hstring KeyboardServiceDisabledText(); + // -------------------------------- WinRT Events --------------------------------- DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(TitleChanged, _titleChangeHandlers, winrt::Windows::Foundation::IInspectable, winrt::hstring); DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(LastTabClosed, _lastTabClosedHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::LastTabClosedEventArgs); diff --git a/src/cascadia/TerminalApp/TerminalPage.idl b/src/cascadia/TerminalApp/TerminalPage.idl index 7fb5cb29ac1..affaa1a5d69 100644 --- a/src/cascadia/TerminalApp/TerminalPage.idl +++ b/src/cascadia/TerminalApp/TerminalPage.idl @@ -26,6 +26,8 @@ namespace TerminalApp // that there's only one application-global dialog visible at a time, // and because of GH#5224. IDialogPresenter DialogPresenter; + void ShowKeyboardServiceWarning(); + String KeyboardServiceDisabledText { get; }; event Windows.Foundation.TypedEventHandler TitleChanged; event Windows.Foundation.TypedEventHandler LastTabClosed; diff --git a/src/cascadia/TerminalApp/TerminalPage.xaml b/src/cascadia/TerminalApp/TerminalPage.xaml index b2901440bf4..93fffcc59ff 100644 --- a/src/cascadia/TerminalApp/TerminalPage.xaml +++ b/src/cascadia/TerminalApp/TerminalPage.xaml @@ -82,6 +82,20 @@ the MIT License. See LICENSE in the project root for license information. --> + + + + + + Date: Wed, 4 Nov 2020 10:30:58 -0600 Subject: [PATCH 7/9] Update src/cascadia/TerminalApp/AppLogic.cpp --- src/cascadia/TerminalApp/AppLogic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index a925e51a203..5e3366b92ce 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -507,7 +507,7 @@ namespace winrt::TerminalApp::implementation // not be noisy with this dialog if we failed for some reason. // Open the service manager. This will return 0 if it failed. - wil::unique_schandle hManager{ OpenSCManager(nullptr, nullptr, SERVICE_QUERY_STATUS) }; + wil::unique_schandle hManager{ OpenSCManager(nullptr, nullptr, 0) }; if (LOG_LAST_ERROR_IF(!hManager.is_valid())) { From 93c61176bba59a284bc4c3bc0ee40dc57c707551 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 4 Nov 2020 12:21:20 -0600 Subject: [PATCH 8/9] Make miniksa happy --- src/cascadia/TerminalApp/AppLogic.cpp | 4 ++-- .../TerminalApp/Resources/en-US/Resources.resw | 2 +- src/cascadia/TerminalApp/TerminalPage.cpp | 18 +++++++++--------- src/cascadia/TerminalApp/TerminalPage.h | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index 5e3366b92ce..7418d80ff95 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -488,7 +488,7 @@ namespace winrt::TerminalApp::implementation } // Method Description: - // - Helper for determining if the "Touch, Keyboard and Handwriting Panel + // - Helper for determining if the "Touch Keyboard and Handwriting Panel // Service" is enabled. If it isn't, we want to be able to display a // warning to the user, because they won't be able to type in the // Terminal. @@ -515,7 +515,7 @@ namespace winrt::TerminalApp::implementation } // Get a handle to the keyboard service - wil::unique_schandle hService{ OpenService(hManager.get(), L"TabletInputService", SERVICE_QUERY_STATUS) }; + wil::unique_schandle hService{ OpenService(hManager.get(), TabletInputServiceKey.data(), SERVICE_QUERY_STATUS) }; if (LOG_LAST_ERROR_IF(!hService.is_valid())) { return true; diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index 4a6cbdeb511..9c67c78ebb5 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -150,7 +150,7 @@ Encountered errors while loading user settings - Ok + OK Warning: diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index ceca1385bb7..5cd216af75a 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -2642,7 +2642,7 @@ namespace winrt::TerminalApp::implementation } // Method Description: - // - Displays a dialog stating the "Touch, Keyboard and Handwriting Panel + // - Displays a dialog stating the "Touch Keyboard and Handwriting Panel // Service" is disabled. void TerminalPage::ShowKeyboardServiceWarning() { @@ -2653,12 +2653,12 @@ namespace winrt::TerminalApp::implementation } // Function Description: - // - Helper function to get the OS-localized name for the "Touch, Keyboard + // - Helper function to get the OS-localized name for the "Touch Keyboard // and Handwriting Panel Service". If we can't open up the service for any // reason, then we'll just return the service's key, "TabletInputService". // Return Value: // - The OS-localized name for the TabletInputService - std::wstring _getTabletServiceName() + winrt::hstring _getTabletServiceName() { auto isUwp = false; try @@ -2669,30 +2669,30 @@ namespace winrt::TerminalApp::implementation if (isUwp) { - return L"TabletInputService"; + return winrt::hstring{ TabletInputServiceKey }; } wil::unique_schandle hManager{ OpenSCManager(nullptr, nullptr, 0) }; if (LOG_LAST_ERROR_IF(!hManager.is_valid())) { - return L"TabletInputService"; + return winrt::hstring{ TabletInputServiceKey }; } DWORD cchBuffer = 0; - GetServiceDisplayName(hManager.get(), L"TabletInputService", nullptr, &cchBuffer); + GetServiceDisplayName(hManager.get(), TabletInputServiceKey.data(), nullptr, &cchBuffer); std::wstring buffer; cchBuffer += 1; // Add space for a null buffer.resize(cchBuffer); if (LOG_LAST_ERROR_IF(!GetServiceDisplayName(hManager.get(), - L"TabletInputService", + TabletInputServiceKey.data(), buffer.data(), &cchBuffer))) { - return L"TabletInputService"; + return winrt::hstring{ TabletInputServiceKey }; } - return buffer; + return winrt::hstring{ buffer }; } // Method Description: diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 2e040d37e41..62f398f3e0a 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -13,7 +13,7 @@ #include "AppCommandlineArgs.h" static constexpr uint32_t DefaultRowsToScroll{ 3 }; - +static constexpr std::wstring_view TabletInputServiceKey{ L"TabletInputService" }; // fwdecl unittest classes namespace TerminalAppLocalTests { From 3e15cad4b21d841f7f6d7898ed71a1fccfe3271e Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 4 Nov 2020 15:03:44 -0600 Subject: [PATCH 9/9] Update src/cascadia/TerminalApp/TerminalPage.cpp Co-authored-by: Dustin L. Howett --- src/cascadia/TerminalApp/TerminalPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 5cd216af75a..731e1f06cb2 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -2699,7 +2699,7 @@ namespace winrt::TerminalApp::implementation // - Return the fully-formed warning message for the // "KeyboardServiceDisabled" dialog. This dialog is used to warn the user // if the keyboard service is disabled, and uses the OS localization for - // the service's actual name. It's boud to the dialog in XAML. + // the service's actual name. It's bound to the dialog in XAML. // Return Value: // - The warning message, including the OS-localized service name. winrt::hstring TerminalPage::KeyboardServiceDisabledText()