From 071760b7f4c28a131651233da47df8899c101b1f Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 19 Apr 2020 16:59:59 +0200 Subject: [PATCH 1/4] Move OLE initialization to a module Previously this was done in wxMSW-specific wxApp version, which meant that initialization was done after the modules initialization and, especially problematically, uninitialization was done before modules uninitialization, which resulted in problems when doing anything using OLE from the modules OnExit(). This commit doesn't solve these problems yet, because it leaves modules initialization order undefined, but the upcoming commits using it will. --- src/msw/app.cpp | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/msw/app.cpp b/src/msw/app.cpp index 027a075fd0..be4bc5e9dc 100644 --- a/src/msw/app.cpp +++ b/src/msw/app.cpp @@ -145,6 +145,33 @@ wxVector gs_regClassesInfo; LRESULT WXDLLEXPORT APIENTRY wxWndProc(HWND, UINT, WPARAM, LPARAM); +// ---------------------------------------------------------------------------- +// Module for OLE initialization and cleanup +// ---------------------------------------------------------------------------- + +class wxOleInitModule : public wxModule +{ +public: + wxOleInitModule() + { + } + + virtual bool OnInit() wxOVERRIDE + { + return wxOleInitialize(); + } + + virtual void OnExit() wxOVERRIDE + { + wxOleUninitialize(); + } + +private: + wxDECLARE_DYNAMIC_CLASS(wxOleInitModule); +}; + +wxIMPLEMENT_DYNAMIC_CLASS(wxOleInitModule, wxModule); + // =========================================================================== // wxGUIAppTraits implementation // =========================================================================== @@ -622,8 +649,6 @@ bool wxApp::Initialize(int& argc_, wxChar **argv_) InitCommonControls(); - wxOleInitialize(); - wxSetKeyboardHook(true); callBaseCleanup.Dismiss(); @@ -739,8 +764,6 @@ void wxApp::CleanUp() wxSetKeyboardHook(false); - wxOleUninitialize(); - // for an EXE the classes are unregistered when it terminates but DLL may // be loaded several times (load/unload/load) into the same process in // which case the registration will fail after the first time if we don't From 05059b64f16dc0a5ea0fa7fbad76b9b4758a4775 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 19 Apr 2020 17:02:32 +0200 Subject: [PATCH 2/4] Remove unneeded wxOleInitialize() from wxClipboard code There is no need to do it here when it had been already done on startup. No real changes, just cleanup. --- src/msw/clipbrd.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/msw/clipbrd.cpp b/src/msw/clipbrd.cpp index 8d4ad6ae9f..ea77bd4182 100644 --- a/src/msw/clipbrd.cpp +++ b/src/msw/clipbrd.cpp @@ -458,10 +458,6 @@ wxIMPLEMENT_DYNAMIC_CLASS(wxClipboard, wxObject); wxClipboard::wxClipboard() { -#if wxUSE_OLE_CLIPBOARD - wxOleInitialize(); -#endif - m_lastDataObject = NULL; m_isOpened = false; } @@ -472,10 +468,6 @@ wxClipboard::~wxClipboard() { Clear(); } - -#if wxUSE_OLE_CLIPBOARD - wxOleUninitialize(); -#endif } void wxClipboard::Clear() From 893f3a6c00028df54289b62ca3b7413a5389a865 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 19 Apr 2020 17:04:36 +0200 Subject: [PATCH 3/4] Add wxDirect2DModule dependency on wxOleInitModule This avoids the need for calling CoInitializeEx() and CoUninitialize() in this module itself, it's enough to ensure that wxOleInitModule does it before, or after, before this one is initialized, or uninitialized, respectively. This replaces the earlier fix of 450019dc21 (Ensure COM is still active when Direct2D renderer is in use, 2015-12-30). See #17308. --- src/msw/graphicsd2d.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/msw/graphicsd2d.cpp b/src/msw/graphicsd2d.cpp index 7ad74fc4e2..9231d36d6c 100644 --- a/src/msw/graphicsd2d.cpp +++ b/src/msw/graphicsd2d.cpp @@ -5247,14 +5247,14 @@ class wxDirect2DModule : public wxModule public: wxDirect2DModule() { + // Using Direct2D requires OLE and, importantly, we must ensure our + // OnExit() runs before it is uninitialized. + AddDependency("wxOleInitModule"); } virtual bool OnInit() wxOVERRIDE { - HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); - // RPC_E_CHANGED_MODE is not considered as an error - // - see remarks for wxOleInitialize(). - return SUCCEEDED(hr) || hr == RPC_E_CHANGED_MODE; + return true; } virtual void OnExit() wxOVERRIDE @@ -5289,8 +5289,6 @@ public: gs_ID2D1Factory->Release(); gs_ID2D1Factory = NULL; } - - ::CoUninitialize(); } private: From 5ecc553afb50b2ee503a3eba76f8a9d87f48c576 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 19 Apr 2020 17:07:04 +0200 Subject: [PATCH 4/4] Add wxToastNotifMsgModule dependency on wxOleInitModule This ensures that OLE is still initialized when this module cleanup occurs, as it must be when IToastNotificationManagerStatics COM pointer is destroyed. Closes #18730. --- src/msw/rt/notifmsgrt.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/msw/rt/notifmsgrt.cpp b/src/msw/rt/notifmsgrt.cpp index 3b9ba571ce..d91e64454b 100644 --- a/src/msw/rt/notifmsgrt.cpp +++ b/src/msw/rt/notifmsgrt.cpp @@ -463,6 +463,9 @@ class wxToastNotifMsgModule : public wxModule public: wxToastNotifMsgModule() { + // Using RT API requires OLE and, importantly, we must ensure our + // OnExit() runs before it is uninitialized. + AddDependency("wxOleInitModule"); } virtual bool OnInit() wxOVERRIDE