https://git.reactos.org/?p=reactos.git;a=commitdiff;h=1aa95f389772901970369a...
commit 1aa95f389772901970369afa3abfb207df6f57f6 Author: Thamatip Chitpong tangaming123456@outlook.com AuthorDate: Tue May 24 18:58:24 2022 +0700 Commit: GitHub noreply@github.com 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 tangaming123456@outlook.com Reviewed-by: Mark Jansen mark.jansen@reactos.org Reviewed-by: Hermès Bélusca-Maïto hermes.belusca-maito@reactos.org Reviewed-by: Stanislav Motylkov x86corez@gmail.com --- 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; }