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
23 class CDesktopThread
24 {
25 private:
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
34 public:
35 CDesktopThread();
36 ~CDesktopThread();
37
38 HRESULT Initialize(ITrayWindow* pTray);
39 void Destroy();
40 };
41
42 /*******************************************************************/
43
CDesktopThread()44 CDesktopThread::CDesktopThread():
45 m_Tray(NULL),
46 m_hInitEvent(NULL),
47 m_hThread(NULL),
48 m_ThreadId(0)
49 {
50 }
51
~CDesktopThread()52 CDesktopThread::~CDesktopThread()
53 {
54 Destroy();
55 }
56
Initialize(ITrayWindow * pTray)57 HRESULT 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
Destroy()117 void 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
DesktopThreadProc()143 DWORD 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
174 Cleanup:
175 OleUninitialize();
176 return dwResult;
177 }
178
s_DesktopThreadProc(LPVOID lpParameter)179 DWORD WINAPI CDesktopThread::s_DesktopThreadProc(LPVOID lpParameter)
180 {
181 CDesktopThread* pDesktopThread = static_cast<CDesktopThread*>(lpParameter);
182 return pDesktopThread->DesktopThreadProc();
183 }
184
185 /*******************************************************************/
186
187 HANDLE
DesktopCreateWindow(IN OUT ITrayWindow * Tray)188 DesktopCreateWindow(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
202 VOID
DesktopDestroyShellWindow(IN HANDLE hDesktop)203 DesktopDestroyShellWindow(IN HANDLE hDesktop)
204 {
205 CDesktopThread* pDesktopThread = reinterpret_cast<CDesktopThread*>(hDesktop);
206 delete pDesktopThread;
207 }
208