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