Reactos
1/*
2 * ReactOS Explorer
3 *
4 * Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "precomp.h"
22
23class CDesktopThread
24{
25private:
26 CComPtr<ITrayWindow> m_Tray;
27 HANDLE m_hInitEvent;
28 HANDLE m_hThread;
29 DWORD m_ThreadId;
30
31 DWORD DesktopThreadProc();
32 static DWORD WINAPI s_DesktopThreadProc(LPVOID lpParameter);
33
34public:
35 CDesktopThread();
36 ~CDesktopThread();
37
38 HRESULT Initialize(ITrayWindow* pTray);
39 void Destroy();
40};
41
42/*******************************************************************/
43
44CDesktopThread::CDesktopThread():
45 m_Tray(NULL),
46 m_hInitEvent(NULL),
47 m_hThread(NULL),
48 m_ThreadId(0)
49{
50}
51
52CDesktopThread::~CDesktopThread()
53{
54 Destroy();
55}
56
57HRESULT CDesktopThread::Initialize(ITrayWindow* pTray)
58{
59 HANDLE Handles[2];
60
61 if (!pTray || m_Tray)
62 {
63 return E_FAIL;
64 }
65
66 m_hInitEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
67 if (!m_hInitEvent)
68 {
69 return E_FAIL;
70 }
71
72 m_Tray = pTray;
73 m_hThread = CreateThread(NULL, 0, s_DesktopThreadProc, (LPVOID)this, 0, &m_ThreadId);
74
75 if (!m_hThread)
76 {
77 CloseHandle(m_hInitEvent);
78 m_hInitEvent = NULL;
79
80 m_Tray = NULL;
81
82 return E_FAIL;
83 }
84
85 Handles[0] = m_hThread;
86 Handles[1] = m_hInitEvent;
87
88 for (;;)
89 {
90 DWORD WaitResult = MsgWaitForMultipleObjects(_countof(Handles), Handles, FALSE, INFINITE, QS_ALLEVENTS);
91
92 if (WaitResult == WAIT_OBJECT_0 + _countof(Handles))
93 {
94 TrayProcessMessages(m_Tray);
95 }
96 else if (WaitResult != WAIT_FAILED && WaitResult != WAIT_OBJECT_0)
97 {
98 break;
99 }
100 else
101 {
102 CloseHandle(m_hThread);
103 m_hThread = NULL;
104 m_ThreadId = 0;
105
106 CloseHandle(m_hInitEvent);
107 m_hInitEvent = NULL;
108
109 m_Tray = NULL;
110
111 return E_FAIL;
112 }
113 }
114 return S_OK;
115}
116
117void CDesktopThread::Destroy()
118{
119 if (m_hThread)
120 {
121 DWORD WaitResult = WaitForSingleObject(m_hThread, 0);
122 if (WaitResult == WAIT_TIMEOUT)
123 {
124 /* Send WM_QUIT message to the thread and wait for it to terminate */
125 PostThreadMessageW(m_ThreadId, WM_QUIT, 0, 0);
126 WaitForSingleObject(m_hThread, INFINITE);
127 }
128
129 CloseHandle(m_hThread);
130 m_hThread = NULL;
131 m_ThreadId = 0;
132 }
133
134 if (m_hInitEvent)
135 {
136 CloseHandle(m_hInitEvent);
137 m_hInitEvent = NULL;
138 }
139
140 m_Tray = NULL;
141}
142
143DWORD CDesktopThread::DesktopThreadProc()
144{
145 CComPtr<IShellDesktopTray> pSdt;
146 HANDLE hDesktop;
147 HRESULT hRet;
148 DWORD dwResult = 1;
149
150 OleInitialize(NULL);
151
152 hRet = m_Tray->QueryInterface(IID_PPV_ARG(IShellDesktopTray, &pSdt));
153 if (!SUCCEEDED(hRet))
154 {
155 goto Cleanup;
156 }
157
158 hDesktop = _SHCreateDesktop(pSdt);
159 if (!hDesktop)
160 {
161 goto Cleanup;
162 }
163
164 if (!SetEvent(m_hInitEvent))
165 {
166 /* Failed to notify that we initialized successfully, kill ourselves
167 * to make the main thread wake up! */
168 goto Cleanup;
169 }
170
171 _SHDesktopMessageLoop(hDesktop);
172 dwResult = 0;
173
174Cleanup:
175 OleUninitialize();
176 return dwResult;
177}
178
179DWORD WINAPI CDesktopThread::s_DesktopThreadProc(LPVOID lpParameter)
180{
181 CDesktopThread* pDesktopThread = static_cast<CDesktopThread*>(lpParameter);
182 return pDesktopThread->DesktopThreadProc();
183}
184
185/*******************************************************************/
186
187HANDLE
188DesktopCreateWindow(IN OUT ITrayWindow *Tray)
189{
190 CDesktopThread* pDesktopThread = new CDesktopThread();
191
192 HRESULT hres = pDesktopThread->Initialize(Tray);
193 if (FAILED_UNEXPECTEDLY(hres))
194 {
195 delete pDesktopThread;
196 return NULL;
197 }
198
199 return pDesktopThread;
200}
201
202VOID
203DesktopDestroyShellWindow(IN HANDLE hDesktop)
204{
205 CDesktopThread* pDesktopThread = reinterpret_cast<CDesktopThread*>(hDesktop);
206 delete pDesktopThread;
207}