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