- Merge aicom-network-fixes up to r36740
[reactos.git] / reactos / subsystems / win32 / csrss / win32csr / desktopbg.c
1 /* $Id$
2 *
3 * reactos/subsys/csrss/win32csr/desktopbg.c
4 *
5 * Desktop background window functions
6 *
7 * ReactOS Operating System
8 */
9
10 #include "w32csr.h"
11
12 #define NDEBUG
13 #include <debug.h>
14
15 #define DESKTOP_WINDOW_ATOM 32880
16
17 #define PM_SHOW_DESKTOP 1
18 #define PM_HIDE_DESKTOP 2
19
20 typedef struct tagDTBG_THREAD_DATA
21 {
22 HDESK Desktop;
23 HANDLE Event;
24 NTSTATUS Status;
25 } DTBG_THREAD_DATA, *PDTBG_THREAD_DATA;
26
27 typedef struct tagPRIVATE_NOTIFY_DESKTOP
28 {
29 NMHDR hdr;
30 union
31 {
32 struct /* PM_SHOW_DESKTOP */
33 {
34 int Width;
35 int Height;
36 } ShowDesktop;
37 };
38 } PRIVATE_NOTIFY_DESKTOP, *PPRIVATE_NOTIFY_DESKTOP;
39
40 static BOOL BgInitialized = FALSE;
41 static HWND VisibleDesktopWindow = NULL;
42
43 static LRESULT CALLBACK
44 DtbgWindowProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)
45 {
46 switch(Msg)
47 {
48 case WM_ERASEBKGND:
49 return 1;
50
51 case WM_PAINT:
52 {
53 PAINTSTRUCT PS;
54 RECT rc;
55 HDC hDC;
56
57 if(GetUpdateRect(Wnd, &rc, FALSE) &&
58 (hDC = BeginPaint(Wnd, &PS)))
59 {
60 PaintDesktop(hDC);
61 EndPaint(Wnd, &PS);
62 }
63 return 0;
64 }
65
66 case WM_SETCURSOR:
67 return (LRESULT) SetCursor(LoadCursorW(0, (LPCWSTR)IDC_ARROW));
68
69 case WM_NCCREATE:
70 return (LRESULT) TRUE;
71
72 case WM_CREATE:
73 return 0;
74
75 case WM_NOTIFY:
76 {
77 PPRIVATE_NOTIFY_DESKTOP nmh = (PPRIVATE_NOTIFY_DESKTOP)lParam;
78
79 /* Use WM_NOTIFY for private messages since it can't be sent between
80 processes! */
81 switch(nmh->hdr.code)
82 {
83 case PM_SHOW_DESKTOP:
84 {
85 LRESULT Result;
86
87 Result = ! SetWindowPos(Wnd,
88 NULL, 0, 0,
89 nmh->ShowDesktop.Width,
90 nmh->ShowDesktop.Height,
91 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW);
92 UpdateWindow(Wnd);
93 VisibleDesktopWindow = Wnd;
94 return Result;
95 }
96
97 case PM_HIDE_DESKTOP:
98 {
99 LRESULT Result;
100
101 Result = ! SetWindowPos(Wnd,
102 NULL, 0, 0, 0, 0,
103 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE |
104 SWP_HIDEWINDOW);
105 UpdateWindow(Wnd);
106 VisibleDesktopWindow = NULL;
107 return Result;
108 }
109
110 default:
111 DPRINT("Unknown notification code 0x%x sent to the desktop window!\n", nmh->hdr.code);
112 return 0;
113 }
114 }
115 }
116
117 return 0;
118 }
119
120 static BOOL FASTCALL
121 DtbgInit()
122 {
123 WNDCLASSEXW Class;
124 ATOM ClassAtom;
125
126 /*
127 * Create the desktop window class
128 */
129 Class.cbSize = sizeof(WNDCLASSEXW);
130 Class.style = 0;
131 Class.lpfnWndProc = DtbgWindowProc;
132 Class.cbClsExtra = 0;
133 Class.cbWndExtra = 0;
134 Class.hInstance = (HINSTANCE) GetModuleHandleW(NULL);
135 Class.hIcon = NULL;
136 Class.hCursor = NULL;
137 Class.hbrBackground = GetSysColorBrush(COLOR_BACKGROUND);
138 Class.lpszMenuName = NULL;
139 Class.lpszClassName = (LPCWSTR) DESKTOP_WINDOW_ATOM;
140 ClassAtom = RegisterClassExW(&Class);
141 if ((ATOM) 0 == ClassAtom)
142 {
143 DPRINT1("Unable to register desktop background class (error %d)\n",
144 GetLastError());
145 return FALSE;
146 }
147 VisibleDesktopWindow = NULL;
148
149 return TRUE;
150 }
151
152 static DWORD STDCALL
153 DtbgDesktopThread(PVOID Data)
154 {
155 HWND BackgroundWnd;
156 MSG msg;
157 PDTBG_THREAD_DATA ThreadData = (PDTBG_THREAD_DATA) Data;
158
159 if (! SetThreadDesktop(ThreadData->Desktop))
160 {
161 DPRINT1("Failed to set thread desktop\n");
162 ThreadData->Status = STATUS_UNSUCCESSFUL;
163 SetEvent(ThreadData->Event);
164 return 1;
165 }
166 BackgroundWnd = CreateWindowW((LPCWSTR) DESKTOP_WINDOW_ATOM,
167 L"",
168 WS_POPUP | WS_CLIPCHILDREN,
169 0,
170 0,
171 0,
172 0,
173 NULL,
174 NULL,
175 (HINSTANCE) GetModuleHandleW(NULL),
176 NULL);
177 if (NULL == BackgroundWnd)
178 {
179 DPRINT1("Failed to create desktop background window\n");
180 ThreadData->Status = STATUS_UNSUCCESSFUL;
181 SetEvent(ThreadData->Event);
182 return 1;
183 }
184
185 ThreadData->Status = STATUS_SUCCESS;
186 SetEvent(ThreadData->Event);
187
188 while (GetMessageW(&msg, NULL, 0, 0))
189 {
190 TranslateMessage(&msg);
191 DispatchMessageW(&msg);
192 }
193
194 return 1;
195 }
196
197 CSR_API(CsrCreateDesktop)
198 {
199 DTBG_THREAD_DATA ThreadData;
200 HANDLE ThreadHandle;
201
202 DPRINT("CsrCreateDesktop\n");
203
204 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
205 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
206
207 if (! BgInitialized)
208 {
209 BgInitialized = TRUE;
210 if (! DtbgInit())
211 {
212 return STATUS_UNSUCCESSFUL;
213 }
214 }
215
216 /*
217 * the desktop handle we got from win32k is in the scope of CSRSS so we can just use it
218 */
219 ThreadData.Desktop = Request->Data.CreateDesktopRequest.DesktopHandle;
220
221 ThreadData.Event = CreateEventW(NULL, FALSE, FALSE, NULL);
222 if (NULL == ThreadData.Event)
223 {
224 DPRINT1("Failed to create event (error %d)\n", GetLastError());
225 return STATUS_UNSUCCESSFUL;
226 }
227 ThreadHandle = CreateThread(NULL,
228 0,
229 DtbgDesktopThread,
230 (PVOID) &ThreadData,
231 0,
232 NULL);
233 if (NULL == ThreadHandle)
234 {
235 CloseHandle(ThreadData.Event);
236 DPRINT1("Failed to create desktop window thread.\n");
237 return STATUS_UNSUCCESSFUL;
238 }
239 CloseHandle(ThreadHandle);
240
241 WaitForSingleObject(ThreadData.Event, INFINITE);
242 CloseHandle(ThreadData.Event);
243
244 return ThreadData.Status;
245 }
246
247 CSR_API(CsrShowDesktop)
248 {
249 PRIVATE_NOTIFY_DESKTOP nmh;
250 DPRINT("CsrShowDesktop\n");
251
252 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
253 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
254
255 nmh.hdr.hwndFrom = Request->Data.ShowDesktopRequest.DesktopWindow;
256 nmh.hdr.idFrom = 0;
257 nmh.hdr.code = PM_SHOW_DESKTOP;
258
259 nmh.ShowDesktop.Width = (int)Request->Data.ShowDesktopRequest.Width;
260 nmh.ShowDesktop.Height = (int)Request->Data.ShowDesktopRequest.Height;
261
262 return SendMessageW(Request->Data.ShowDesktopRequest.DesktopWindow,
263 WM_NOTIFY,
264 (WPARAM)nmh.hdr.hwndFrom,
265 (LPARAM)&nmh)
266 ? STATUS_UNSUCCESSFUL : STATUS_SUCCESS;
267 }
268
269 CSR_API(CsrHideDesktop)
270 {
271 PRIVATE_NOTIFY_DESKTOP nmh;
272 DPRINT("CsrHideDesktop\n");
273
274 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
275 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
276
277 nmh.hdr.hwndFrom = Request->Data.ShowDesktopRequest.DesktopWindow;
278 nmh.hdr.idFrom = 0;
279 nmh.hdr.code = PM_HIDE_DESKTOP;
280
281 return SendMessageW(Request->Data.ShowDesktopRequest.DesktopWindow,
282 WM_NOTIFY,
283 (WPARAM)nmh.hdr.hwndFrom,
284 (LPARAM)&nmh)
285 ? STATUS_UNSUCCESSFUL : STATUS_SUCCESS;
286 }
287
288 BOOL FASTCALL
289 DtbgIsDesktopVisible(VOID)
290 {
291 if (NULL != VisibleDesktopWindow && ! IsWindowVisible(VisibleDesktopWindow))
292 {
293 VisibleDesktopWindow = NULL;
294 }
295
296 return NULL != VisibleDesktopWindow;
297 }
298
299 /* EOF */