mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 00:45:43 +00:00
[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>
This commit is contained in:
parent
4900dd3d87
commit
1aa95f3897
1 changed files with 152 additions and 86 deletions
|
@ -22,98 +22,164 @@
|
||||||
|
|
||||||
class CDesktopThread
|
class CDesktopThread
|
||||||
{
|
{
|
||||||
HANDLE m_hEvent;
|
private:
|
||||||
CComPtr<ITrayWindow> m_Tray;
|
CComPtr<ITrayWindow> m_Tray;
|
||||||
|
HANDLE m_hInitEvent;
|
||||||
|
HANDLE m_hThread;
|
||||||
|
|
||||||
DWORD DesktopThreadProc()
|
DWORD DesktopThreadProc();
|
||||||
{
|
static DWORD WINAPI s_DesktopThreadProc(LPVOID lpParameter);
|
||||||
CComPtr<IShellDesktopTray> pSdt;
|
|
||||||
HANDLE hDesktop;
|
|
||||||
HRESULT hRet;
|
|
||||||
|
|
||||||
OleInitialize(NULL);
|
|
||||||
|
|
||||||
hRet = m_Tray->QueryInterface(IID_PPV_ARG(IShellDesktopTray, &pSdt));
|
|
||||||
if (!SUCCEEDED(hRet))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
_SHDesktopMessageLoop(hDesktop);
|
|
||||||
|
|
||||||
/* FIXME: Properly rundown the main thread! */
|
|
||||||
ExitProcess(0);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static DWORD CALLBACK s_DesktopThreadProc(IN OUT LPVOID lpParameter)
|
|
||||||
{
|
|
||||||
return reinterpret_cast<CDesktopThread*>(lpParameter)->DesktopThreadProc();
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDesktopThread() :
|
CDesktopThread();
|
||||||
m_hEvent(NULL),
|
~CDesktopThread();
|
||||||
m_Tray(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT Initialize(IN OUT ITrayWindow *pTray)
|
HRESULT Initialize(ITrayWindow* pTray);
|
||||||
{
|
void Destroy();
|
||||||
HANDLE hThread;
|
|
||||||
HANDLE Handles[2];
|
|
||||||
|
|
||||||
m_Tray = pTray;
|
|
||||||
|
|
||||||
m_hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
|
|
||||||
if (!m_hEvent)
|
|
||||||
return E_FAIL;
|
|
||||||
|
|
||||||
hThread = CreateThread(NULL, 0, s_DesktopThreadProc, (PVOID)this, 0, NULL);
|
|
||||||
if (!hThread)
|
|
||||||
{
|
|
||||||
CloseHandle(m_hEvent);
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Handles[0] = hThread;
|
|
||||||
Handles[1] = m_hEvent;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(hThread);
|
|
||||||
CloseHandle(m_hEvent);
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Destroy()
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
|
||||||
|
CDesktopThread::CDesktopThread():
|
||||||
|
m_Tray(NULL),
|
||||||
|
m_hInitEvent(NULL),
|
||||||
|
m_hThread(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CDesktopThread::~CDesktopThread()
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT CDesktopThread::Initialize(ITrayWindow* pTray)
|
||||||
|
{
|
||||||
|
HANDLE Handles[2];
|
||||||
|
|
||||||
|
if (!pTray || m_Tray)
|
||||||
|
{
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_hInitEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||||
|
if (!m_hInitEvent)
|
||||||
|
{
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
Handles[0] = m_hThread;
|
||||||
|
Handles[1] = m_hInitEvent;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
CloseHandle(m_hInitEvent);
|
||||||
|
m_hInitEvent = NULL;
|
||||||
|
|
||||||
|
m_Tray = NULL;
|
||||||
|
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDesktopThread::Destroy()
|
||||||
|
{
|
||||||
|
if (m_hThread)
|
||||||
|
{
|
||||||
|
DWORD WaitResult = WaitForSingleObject(m_hThread, 0);
|
||||||
|
if (WaitResult == WAIT_TIMEOUT)
|
||||||
|
{
|
||||||
|
/* 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(m_hThread);
|
||||||
|
m_hThread = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_hInitEvent)
|
||||||
|
{
|
||||||
|
CloseHandle(m_hInitEvent);
|
||||||
|
m_hInitEvent = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
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
|
HANDLE
|
||||||
DesktopCreateWindow(IN OUT ITrayWindow *Tray)
|
DesktopCreateWindow(IN OUT ITrayWindow *Tray)
|
||||||
{
|
{
|
||||||
|
@ -133,5 +199,5 @@ VOID
|
||||||
DesktopDestroyShellWindow(IN HANDLE hDesktop)
|
DesktopDestroyShellWindow(IN HANDLE hDesktop)
|
||||||
{
|
{
|
||||||
CDesktopThread* pDesktopThread = reinterpret_cast<CDesktopThread*>(hDesktop);
|
CDesktopThread* pDesktopThread = reinterpret_cast<CDesktopThread*>(hDesktop);
|
||||||
pDesktopThread->Destroy();
|
delete pDesktopThread;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue