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 30 DWORD DesktopThreadProc(); 31 static DWORD WINAPI s_DesktopThreadProc(LPVOID lpParameter); 32 33 public: 34 CDesktopThread(); 35 ~CDesktopThread(); 36 37 HRESULT Initialize(ITrayWindow* pTray); 38 void Destroy(); 39 }; 40 41 /*******************************************************************/ 42 43 CDesktopThread::CDesktopThread(): 44 m_Tray(NULL), 45 m_hInitEvent(NULL), 46 m_hThread(NULL) 47 { 48 } 49 50 CDesktopThread::~CDesktopThread() 51 { 52 Destroy(); 53 } 54 55 HRESULT CDesktopThread::Initialize(ITrayWindow* pTray) 56 { 57 HANDLE Handles[2]; 58 59 if (!pTray || m_Tray) 60 { 61 return E_FAIL; 62 } 63 64 m_hInitEvent = CreateEventW(NULL, FALSE, FALSE, NULL); 65 if (!m_hInitEvent) 66 { 67 return E_FAIL; 68 } 69 70 m_Tray = pTray; 71 m_hThread = CreateThread(NULL, 0, s_DesktopThreadProc, (LPVOID)this, 0, NULL); 72 73 if (!m_hThread) 74 { 75 CloseHandle(m_hInitEvent); 76 m_hInitEvent = NULL; 77 78 m_Tray = NULL; 79 80 return E_FAIL; 81 } 82 83 Handles[0] = m_hThread; 84 Handles[1] = m_hInitEvent; 85 86 for (;;) 87 { 88 DWORD WaitResult = MsgWaitForMultipleObjects(_countof(Handles), Handles, FALSE, INFINITE, QS_ALLEVENTS); 89 90 if (WaitResult == WAIT_OBJECT_0 + _countof(Handles)) 91 { 92 TrayProcessMessages(m_Tray); 93 } 94 else if (WaitResult != WAIT_FAILED && WaitResult != WAIT_OBJECT_0) 95 { 96 break; 97 } 98 else 99 { 100 CloseHandle(m_hThread); 101 m_hThread = NULL; 102 103 CloseHandle(m_hInitEvent); 104 m_hInitEvent = NULL; 105 106 m_Tray = NULL; 107 108 return E_FAIL; 109 } 110 } 111 return S_OK; 112 } 113 114 void CDesktopThread::Destroy() 115 { 116 if (m_hThread) 117 { 118 DWORD WaitResult = WaitForSingleObject(m_hThread, 0); 119 if (WaitResult == WAIT_TIMEOUT) 120 { 121 /* Send WM_QUIT message to the thread and wait for it to terminate */ 122 PostThreadMessageW(GetThreadId(m_hThread), WM_QUIT, 0, 0); 123 WaitForSingleObject(m_hThread, INFINITE); 124 } 125 126 CloseHandle(m_hThread); 127 m_hThread = NULL; 128 } 129 130 if (m_hInitEvent) 131 { 132 CloseHandle(m_hInitEvent); 133 m_hInitEvent = NULL; 134 } 135 136 m_Tray = NULL; 137 } 138 139 DWORD CDesktopThread::DesktopThreadProc() 140 { 141 CComPtr<IShellDesktopTray> pSdt; 142 HANDLE hDesktop; 143 HRESULT hRet; 144 DWORD dwResult = 1; 145 146 OleInitialize(NULL); 147 148 hRet = m_Tray->QueryInterface(IID_PPV_ARG(IShellDesktopTray, &pSdt)); 149 if (!SUCCEEDED(hRet)) 150 { 151 goto Cleanup; 152 } 153 154 hDesktop = _SHCreateDesktop(pSdt); 155 if (!hDesktop) 156 { 157 goto Cleanup; 158 } 159 160 if (!SetEvent(m_hInitEvent)) 161 { 162 /* Failed to notify that we initialized successfully, kill ourselves 163 * to make the main thread wake up! */ 164 goto Cleanup; 165 } 166 167 _SHDesktopMessageLoop(hDesktop); 168 dwResult = 0; 169 170 Cleanup: 171 OleUninitialize(); 172 return dwResult; 173 } 174 175 DWORD WINAPI CDesktopThread::s_DesktopThreadProc(LPVOID lpParameter) 176 { 177 CDesktopThread* pDesktopThread = static_cast<CDesktopThread*>(lpParameter); 178 return pDesktopThread->DesktopThreadProc(); 179 } 180 181 /*******************************************************************/ 182 183 HANDLE 184 DesktopCreateWindow(IN OUT ITrayWindow *Tray) 185 { 186 CDesktopThread* pDesktopThread = new CDesktopThread(); 187 188 HRESULT hres = pDesktopThread->Initialize(Tray); 189 if (FAILED_UNEXPECTEDLY(hres)) 190 { 191 delete pDesktopThread; 192 return NULL; 193 } 194 195 return pDesktopThread; 196 } 197 198 VOID 199 DesktopDestroyShellWindow(IN HANDLE hDesktop) 200 { 201 CDesktopThread* pDesktopThread = reinterpret_cast<CDesktopThread*>(hDesktop); 202 delete pDesktopThread; 203 } 204