xref: /reactos/base/shell/explorer/desktop.cpp (revision 84ccccab)
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     HANDLE m_hEvent;
26     CComPtr<ITrayWindow> m_Tray;
27 
28     DWORD DesktopThreadProc()
29     {
30         CComPtr<IShellDesktopTray> pSdt;
31         HANDLE hDesktop;
32         HRESULT hRet;
33 
34         OleInitialize(NULL);
35 
36         hRet = m_Tray->QueryInterface(IID_PPV_ARG(IShellDesktopTray, &pSdt));
37         if (!SUCCEEDED(hRet))
38             return 1;
39 
40         hDesktop = _SHCreateDesktop(pSdt);
41         if (hDesktop == NULL)
42             return 1;
43 
44         if (!SetEvent(m_hEvent))
45         {
46             /* Failed to notify that we initialized successfully, kill ourselves
47             to make the main thread wake up! */
48             return 1;
49         }
50 
51         _SHDesktopMessageLoop(hDesktop);
52 
53         /* FIXME: Properly rundown the main thread! */
54         ExitProcess(0);
55 
56         return 0;
57     }
58 
59     static DWORD CALLBACK s_DesktopThreadProc(IN OUT LPVOID lpParameter)
60     {
61         return reinterpret_cast<CDesktopThread*>(lpParameter)->DesktopThreadProc();
62     }
63 
64 public:
65     CDesktopThread() :
66         m_hEvent(NULL),
67         m_Tray(NULL)
68     {
69     }
70 
71     HRESULT Initialize(IN OUT ITrayWindow *pTray)
72     {
73         HANDLE hThread;
74         HANDLE Handles[2];
75 
76         m_Tray = pTray;
77 
78         m_hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
79         if (!m_hEvent)
80             return E_FAIL;
81 
82         hThread = CreateThread(NULL, 0, s_DesktopThreadProc, (PVOID)this, 0, NULL);
83         if (!hThread)
84         {
85             CloseHandle(m_hEvent);
86             return E_FAIL;
87         }
88 
89         Handles[0] = hThread;
90         Handles[1] = m_hEvent;
91 
92         for (;;)
93         {
94             DWORD WaitResult = MsgWaitForMultipleObjects(_countof(Handles), Handles, FALSE, INFINITE, QS_ALLEVENTS);
95             if (WaitResult == WAIT_OBJECT_0 + _countof(Handles))
96             {
97                 TrayProcessMessages(m_Tray);
98             }
99             else if (WaitResult != WAIT_FAILED && WaitResult != WAIT_OBJECT_0)
100             {
101                 break;
102             }
103         }
104 
105         CloseHandle(hThread);
106         CloseHandle(m_hEvent);
107 
108         return S_OK;
109     }
110 
111     void Destroy()
112     {
113         return;
114     }
115 };
116 
117 HANDLE
118 DesktopCreateWindow(IN OUT ITrayWindow *Tray)
119 {
120     CDesktopThread* pDesktopThread = new CDesktopThread();
121 
122     HRESULT hres = pDesktopThread->Initialize(Tray);
123     if (FAILED_UNEXPECTEDLY(hres))
124     {
125         delete pDesktopThread;
126         return NULL;
127     }
128 
129     return pDesktopThread;
130 }
131 
132 VOID
133 DesktopDestroyShellWindow(IN HANDLE hDesktop)
134 {
135     CDesktopThread* pDesktopThread = reinterpret_cast<CDesktopThread*>(hDesktop);
136     pDesktopThread->Destroy();
137 }
138