https://git.reactos.org/?p=reactos.git;a=commitdiff;h=1aa95f389772901970369afa3abfb207df6f57f6
commit 1aa95f389772901970369afa3abfb207df6f57f6 Author: Thamatip Chitpong <[email protected]> AuthorDate: Tue May 24 18:58:24 2022 +0700 Commit: GitHub <[email protected]> CommitDate: Tue May 24 14:58:24 2022 +0300 [EXPLORER] Implement CDesktopThread::Destroy (#4371) Now Explorer exits properly without using ExitProcess hack. Signed-off-by: Thamatip Chitpong <[email protected]> Reviewed-by: Mark Jansen <[email protected]> Reviewed-by: Hermès Bélusca-Maïto <[email protected]> Reviewed-by: Stanislav Motylkov <[email protected]> --- base/shell/explorer/desktop.cpp | 186 +++++++++++++++++++++++++++------------- 1 file changed, 126 insertions(+), 60 deletions(-) diff --git a/base/shell/explorer/desktop.cpp b/base/shell/explorer/desktop.cpp index 94a30ea4cd7..764c9b0f975 100644 --- a/base/shell/explorer/desktop.cpp +++ b/base/shell/explorer/desktop.cpp @@ -22,97 +22,163 @@ class CDesktopThread { - HANDLE m_hEvent; +private: CComPtr<ITrayWindow> m_Tray; + HANDLE m_hInitEvent; + HANDLE m_hThread; - DWORD DesktopThreadProc() - { - CComPtr<IShellDesktopTray> pSdt; - HANDLE hDesktop; - HRESULT hRet; + DWORD DesktopThreadProc(); + static DWORD WINAPI s_DesktopThreadProc(LPVOID lpParameter); - OleInitialize(NULL); +public: + CDesktopThread(); + ~CDesktopThread(); - hRet = m_Tray->QueryInterface(IID_PPV_ARG(IShellDesktopTray, &pSdt)); - if (!SUCCEEDED(hRet)) - return 1; + HRESULT Initialize(ITrayWindow* pTray); + void Destroy(); +}; - hDesktop = _SHCreateDesktop(pSdt); - if (hDesktop == NULL) - return 1; +/*******************************************************************/ - if (!SetEvent(m_hEvent)) - { - /* Failed to notify that we initialized successfully, kill ourselves - to make the main thread wake up! */ - return 1; - } +CDesktopThread::CDesktopThread(): + m_Tray(NULL), + m_hInitEvent(NULL), + m_hThread(NULL) +{ +} - _SHDesktopMessageLoop(hDesktop); +CDesktopThread::~CDesktopThread() +{ + Destroy(); +} - /* FIXME: Properly rundown the main thread! */ - ExitProcess(0); +HRESULT CDesktopThread::Initialize(ITrayWindow* pTray) +{ + HANDLE Handles[2]; - return 0; + if (!pTray || m_Tray) + { + return E_FAIL; } - static DWORD CALLBACK s_DesktopThreadProc(IN OUT LPVOID lpParameter) + m_hInitEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + if (!m_hInitEvent) { - return reinterpret_cast<CDesktopThread*>(lpParameter)->DesktopThreadProc(); + return E_FAIL; } -public: - CDesktopThread() : - m_hEvent(NULL), - m_Tray(NULL) + m_Tray = pTray; + m_hThread = CreateThread(NULL, 0, s_DesktopThreadProc, (LPVOID)this, 0, NULL); + + if (!m_hThread) { + CloseHandle(m_hInitEvent); + m_hInitEvent = NULL; + + m_Tray = NULL; + + return E_FAIL; } - HRESULT Initialize(IN OUT ITrayWindow *pTray) + Handles[0] = m_hThread; + Handles[1] = m_hInitEvent; + + for (;;) { - HANDLE hThread; - HANDLE Handles[2]; + DWORD WaitResult = MsgWaitForMultipleObjects(_countof(Handles), Handles, FALSE, INFINITE, QS_ALLEVENTS); + + if (WaitResult == WAIT_OBJECT_0 + _countof(Handles)) + { + TrayProcessMessages(m_Tray); + } + else if (WaitResult != WAIT_FAILED && WaitResult != WAIT_OBJECT_0) + { + break; + } + else + { + CloseHandle(m_hThread); + m_hThread = NULL; - m_Tray = pTray; + CloseHandle(m_hInitEvent); + m_hInitEvent = NULL; - m_hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); - if (!m_hEvent) - return E_FAIL; + m_Tray = NULL; - hThread = CreateThread(NULL, 0, s_DesktopThreadProc, (PVOID)this, 0, NULL); - if (!hThread) - { - CloseHandle(m_hEvent); return E_FAIL; } + } + return S_OK; +} - Handles[0] = hThread; - Handles[1] = m_hEvent; - - for (;;) +void CDesktopThread::Destroy() +{ + if (m_hThread) + { + DWORD WaitResult = WaitForSingleObject(m_hThread, 0); + if (WaitResult == WAIT_TIMEOUT) { - DWORD WaitResult = MsgWaitForMultipleObjects(_countof(Handles), Handles, FALSE, INFINITE, QS_ALLEVENTS); - if (WaitResult == WAIT_OBJECT_0 + _countof(Handles)) - { - TrayProcessMessages(m_Tray); - } - else if (WaitResult != WAIT_FAILED && WaitResult != WAIT_OBJECT_0) - { - break; - } + /* Send WM_QUIT message to the thread and wait for it to terminate */ + PostThreadMessageW(GetThreadId(m_hThread), WM_QUIT, 0, 0); + WaitForSingleObject(m_hThread, INFINITE); } - CloseHandle(hThread); - CloseHandle(m_hEvent); + CloseHandle(m_hThread); + m_hThread = NULL; + } - return S_OK; + if (m_hInitEvent) + { + CloseHandle(m_hInitEvent); + m_hInitEvent = NULL; } - void Destroy() + m_Tray = NULL; +} + +DWORD CDesktopThread::DesktopThreadProc() +{ + CComPtr<IShellDesktopTray> pSdt; + HANDLE hDesktop; + HRESULT hRet; + DWORD dwResult = 1; + + OleInitialize(NULL); + + hRet = m_Tray->QueryInterface(IID_PPV_ARG(IShellDesktopTray, &pSdt)); + if (!SUCCEEDED(hRet)) { - return; + goto Cleanup; } -}; + + hDesktop = _SHCreateDesktop(pSdt); + if (!hDesktop) + { + goto Cleanup; + } + + if (!SetEvent(m_hInitEvent)) + { + /* Failed to notify that we initialized successfully, kill ourselves + * to make the main thread wake up! */ + goto Cleanup; + } + + _SHDesktopMessageLoop(hDesktop); + dwResult = 0; + +Cleanup: + OleUninitialize(); + return dwResult; +} + +DWORD WINAPI CDesktopThread::s_DesktopThreadProc(LPVOID lpParameter) +{ + CDesktopThread* pDesktopThread = static_cast<CDesktopThread*>(lpParameter); + return pDesktopThread->DesktopThreadProc(); +} + +/*******************************************************************/ HANDLE DesktopCreateWindow(IN OUT ITrayWindow *Tray) @@ -133,5 +199,5 @@ VOID DesktopDestroyShellWindow(IN HANDLE hDesktop) { CDesktopThread* pDesktopThread = reinterpret_cast<CDesktopThread*>(hDesktop); - pDesktopThread->Destroy(); + delete pDesktopThread; }
