diff --git a/src/interactivity/base/ServiceLocator.cpp b/src/interactivity/base/ServiceLocator.cpp index 3bc691abdc6..49a89e3e81c 100644 --- a/src/interactivity/base/ServiceLocator.cpp +++ b/src/interactivity/base/ServiceLocator.cpp @@ -17,14 +17,13 @@ using namespace Microsoft::Console::Interactivity; std::unique_ptr ServiceLocator::s_interactivityFactory; std::unique_ptr ServiceLocator::s_consoleControl; std::unique_ptr ServiceLocator::s_consoleInputThread; +std::unique_ptr ServiceLocator::s_consoleWindow; std::unique_ptr ServiceLocator::s_windowMetrics; std::unique_ptr ServiceLocator::s_accessibilityNotifier; std::unique_ptr ServiceLocator::s_highDpiApi; std::unique_ptr ServiceLocator::s_systemConfigurationProvider; std::unique_ptr ServiceLocator::s_inputServices; -IConsoleWindow* ServiceLocator::s_consoleWindow = nullptr; - Globals ServiceLocator::s_globals; bool ServiceLocator::s_pseudoWindowInitialized = false; @@ -45,6 +44,10 @@ wil::unique_hwnd ServiceLocator::s_pseudoWindow = nullptr; s_globals.pRender->TriggerTeardown(); } + // By locking the console, we ensure no background tasks are accessing the + // classes we're going to destruct down below (for instance: CursorBlinker). + s_globals.getConsoleInformation().LockConsole(); + // A History Lesson from MSFT: 13576341: // We introduced RundownAndExit to give services that hold onto important handles // an opportunity to let those go when we decide to exit from the console for various reasons. @@ -62,10 +65,9 @@ wil::unique_hwnd ServiceLocator::s_pseudoWindow = nullptr; // TODO: MSFT: 14397093 - Expand graceful rundown beyond just the Hot Bug input services case. - if (s_inputServices.get() != nullptr) - { - s_inputServices.reset(nullptr); - } + delete s_globals.pRender; + s_inputServices.reset(nullptr); + s_consoleWindow.reset(nullptr); ExitProcess(hr); } @@ -154,7 +156,7 @@ wil::unique_hwnd ServiceLocator::s_pseudoWindow = nullptr; } else { - s_consoleWindow = window; + s_consoleWindow.reset(window); } return status; @@ -166,7 +168,7 @@ wil::unique_hwnd ServiceLocator::s_pseudoWindow = nullptr; IConsoleWindow* ServiceLocator::LocateConsoleWindow() { - return s_consoleWindow; + return s_consoleWindow.get(); } IConsoleControl* ServiceLocator::LocateConsoleControl() diff --git a/src/interactivity/inc/ServiceLocator.hpp b/src/interactivity/inc/ServiceLocator.hpp index 41e27bcdf9f..cbcbdd8f0b0 100644 --- a/src/interactivity/inc/ServiceLocator.hpp +++ b/src/interactivity/inc/ServiceLocator.hpp @@ -61,7 +61,7 @@ namespace Microsoft::Console::Interactivity template static T* LocateConsoleWindow() { - return static_cast(s_consoleWindow); + return static_cast(s_consoleWindow.get()); } static IWindowMetrics* LocateWindowMetrics(); @@ -106,7 +106,7 @@ namespace Microsoft::Console::Interactivity // TODO: MSFT 15344939 - some implementations of IConsoleWindow are currently singleton // classes so we can't own a pointer to them here. fix this so s_consoleWindow can follow the // pattern of the rest of the service interface pointers. - static IConsoleWindow* s_consoleWindow; + static std::unique_ptr s_consoleWindow; static std::unique_ptr s_windowMetrics; static std::unique_ptr s_highDpiApi; static std::unique_ptr s_systemConfigurationProvider; diff --git a/src/interactivity/win32/window.cpp b/src/interactivity/win32/window.cpp index e47a2ef03bd..5b72012c706 100644 --- a/src/interactivity/win32/window.cpp +++ b/src/interactivity/win32/window.cpp @@ -51,7 +51,6 @@ using namespace Microsoft::Console::Interactivity; using namespace Microsoft::Console::Render; ATOM Window::s_atomWindowClass = 0; -Window* Window::s_Instance = nullptr; Window::Window() : _fIsInFullscreen(false), @@ -68,10 +67,13 @@ Window::Window() : Window::~Window() { - if (ServiceLocator::LocateGlobals().pRender != nullptr) - { - delete ServiceLocator::LocateGlobals().pRender; - } + delete pGdiEngine; +#if TIL_FEATURE_CONHOSTDXENGINE_ENABLED + delete pDxEngine; +#endif +#if TIL_FEATURE_ATLASENGINE_ENABLED + delete pAtlasEngine; +#endif } // Routine Description: @@ -98,7 +100,6 @@ Window::~Window() if (NT_SUCCESS(status)) { - Window::s_Instance = pNewWindow; LOG_IF_FAILED(ServiceLocator::SetConsoleWindowInstance(pNewWindow)); } } @@ -210,13 +211,6 @@ void Window::_UpdateSystemMetrics() const _UpdateSystemMetrics(); const auto useDx = pSettings->GetUseDx(); - GdiEngine* pGdiEngine = nullptr; -#if TIL_FEATURE_CONHOSTDXENGINE_ENABLED - DxEngine* pDxEngine = nullptr; -#endif -#if TIL_FEATURE_ATLASENGINE_ENABLED - AtlasEngine* pAtlasEngine = nullptr; -#endif try { switch (useDx) diff --git a/src/interactivity/win32/window.hpp b/src/interactivity/win32/window.hpp index 8e1cdef53eb..cb4742aefca 100644 --- a/src/interactivity/win32/window.hpp +++ b/src/interactivity/win32/window.hpp @@ -16,6 +16,13 @@ Author(s): #include "../inc/IConsoleWindow.hpp" +namespace Microsoft::Console::Render +{ + class AtlasEngine; + class DxEngine; + class GdiEngine; +} + namespace Microsoft::Console::Interactivity::Win32 { class WindowUiaProvider; @@ -105,7 +112,14 @@ namespace Microsoft::Console::Interactivity::Win32 Settings* _pSettings; HWND _hWnd; - static Window* s_Instance; + + Render::GdiEngine* pGdiEngine = nullptr; +#if TIL_FEATURE_CONHOSTDXENGINE_ENABLED + Render::DxEngine* pDxEngine = nullptr; +#endif +#if TIL_FEATURE_ATLASENGINE_ENABLED + Render::AtlasEngine* pAtlasEngine = nullptr; +#endif [[nodiscard]] NTSTATUS _InternalSetWindowSize(); void _UpdateWindowSize(const SIZE sizeNew);