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 44 CDesktopThread::CDesktopThread(): 45 m_Tray(NULL), 46 m_hInitEvent(NULL), 47 m_hThread(NULL), 48 m_ThreadId(0) 49 { 50 } 51 52 CDesktopThread::~CDesktopThread() 53 { 54 Destroy(); 55 } 56 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 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 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 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 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 203 DesktopDestroyShellWindow(IN HANDLE hDesktop) 204 { 205 CDesktopThread* pDesktopThread = reinterpret_cast<CDesktopThread*>(hDesktop); 206 delete pDesktopThread; 207 } 208