Synchronize with trunk's revision r57629.
[reactos.git] / win32ss / user / win32csr / desktopbg.c
1 /*
2 * win32ss/user/win32csr/desktopbg.c
3 *
4 * Desktop background window functions
5 *
6 * ReactOS Operating System
7 *
8 * Looks as a hax fix to a problem of not having a proper class window proc support
9 * which ReactOS has now.
10 *
11 * Notes on reason why this is here:
12 * http://www.reactos.org/archives/public/ros-kernel/2003-November/000538.html
13 * http://www.reactos.org/archives/public/ros-kernel/2003-November/000545.html
14 * http://www.reactos.org/archives/public/ros-kernel/2003-November/000586.html
15 * http://www.reactos.org/archives/public/ros-kernel/2003-November/000674.html
16 * Revision 6908 Move desktop window proc from WIN32K to CSRSS
17 * Bugs 42, 48 and 57.
18 *
19 * http://www.reactos.org/archives/public/ros-kernel/2003-December/001186.html
20 *
21
22 Now this is used to start Desktops Threads with TEB support.
23 These first three are Application, Winlogon and ScreenSaver desktops.
24
25 */
26
27 #include "win32csr.h"
28
29 #define NDEBUG
30 #include <debug.h>
31
32 #define DESKTOP_WINDOW_ATOM 32769
33
34 #define PM_SHOW_DESKTOP 1
35 #define PM_HIDE_DESKTOP 2
36
37 typedef struct tagDTBG_THREAD_DATA
38 {
39 HDESK Desktop;
40 HANDLE Event;
41 NTSTATUS Status;
42 } DTBG_THREAD_DATA, *PDTBG_THREAD_DATA;
43
44 typedef struct tagPRIVATE_NOTIFY_DESKTOP
45 {
46 NMHDR hdr;
47 struct /* PM_SHOW_DESKTOP */
48 {
49 int Width;
50 int Height;
51 } ShowDesktop;
52 } PRIVATE_NOTIFY_DESKTOP, *PPRIVATE_NOTIFY_DESKTOP;
53
54 static BOOL BgInitialized = FALSE;
55 static HWND VisibleDesktopWindow = NULL;
56 #if 0
57 static
58 LRESULT
59 CALLBACK
60 DtbgWindowProc(HWND Wnd,
61 UINT Msg,
62 WPARAM wParam,
63 LPARAM lParam)
64 {
65 PAINTSTRUCT PS;
66
67 switch (Msg)
68 {
69 case WM_ERASEBKGND:
70 PaintDesktop((HDC)wParam);
71 return 1;
72
73 case WM_PAINT:
74 if (BeginPaint(Wnd, &PS))
75 EndPaint(Wnd, &PS);
76 return 0;
77
78 case WM_SETCURSOR:
79 return (LRESULT)SetCursor(LoadCursorW(0, (LPCWSTR)IDC_ARROW));
80
81 case WM_NCCREATE:
82 return (LRESULT)TRUE;
83
84 case WM_CREATE:
85 NtUserSetWindowFNID(Wnd, FNID_DESKTOP); // Anti-ReactOS hack!
86 case WM_CLOSE:
87 return 0;
88
89 case WM_DISPLAYCHANGE:
90 MoveWindow(Wnd, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
91 break;
92
93 case WM_NOTIFY:
94 {
95 PPRIVATE_NOTIFY_DESKTOP nmh = (PPRIVATE_NOTIFY_DESKTOP)lParam;
96
97 /* Use WM_NOTIFY for private messages since
98 * it can't be sent between processes!
99 */
100 switch (nmh->hdr.code)
101 {
102 case PM_SHOW_DESKTOP:
103 {
104 LRESULT Result;
105
106 Result = !SetWindowPos(Wnd, NULL, 0, 0,
107 nmh->ShowDesktop.Width,
108 nmh->ShowDesktop.Height,
109 SWP_NOACTIVATE | SWP_NOZORDER |
110 SWP_SHOWWINDOW);
111
112 UpdateWindow(Wnd);
113 VisibleDesktopWindow = Wnd;
114 return Result;
115 }
116
117 case PM_HIDE_DESKTOP:
118 {
119 LRESULT Result;
120
121 Result = !SetWindowPos(Wnd, NULL, 0, 0, 0, 0,
122 SWP_NOACTIVATE | SWP_NOZORDER |
123 SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW);
124
125 UpdateWindow(Wnd);
126 VisibleDesktopWindow = NULL;
127 return Result;
128 }
129
130 default:
131 DPRINT("Unknown notification code 0x%x sent to the desktop window!\n",
132 nmh->hdr.code);
133 return 0;
134 }
135 }
136
137 default:
138 return DefWindowProcW(Wnd, Msg, wParam, lParam);
139 }
140
141 return 0;
142 }
143
144 static
145 BOOL
146 FASTCALL
147 DtbgInit(VOID)
148 {
149 WNDCLASSEXW Class;
150 ATOM ClassAtom;
151
152 /*
153 * Create the desktop window class
154 */
155 Class.cbSize = sizeof(WNDCLASSEXW);
156 Class.style = 0; // Local Class
157 Class.lpfnWndProc = DtbgWindowProc;
158 Class.cbClsExtra = 0;
159 Class.cbWndExtra = 0;
160 Class.hInstance = (HINSTANCE)GetModuleHandleW(NULL);
161 Class.hIcon = NULL;
162 Class.hCursor = NULL;
163 Class.hbrBackground = GetSysColorBrush(COLOR_BACKGROUND);
164 Class.lpszMenuName = NULL;
165 Class.lpszClassName = (LPCWSTR)DESKTOP_WINDOW_ATOM;
166 ClassAtom = RegisterClassExW(&Class);
167
168 if (ClassAtom == INVALID_ATOM)
169 {
170 DPRINT1("Unable to register desktop background class (error %d)\n",
171 GetLastError());
172
173 return FALSE;
174 }
175
176 VisibleDesktopWindow = NULL;
177
178 return TRUE;
179 }
180 #endif
181 static
182 DWORD
183 WINAPI
184 DtbgDesktopThread(PVOID Data)
185 {
186 HWND BackgroundWnd;
187 MSG msg;
188 PDTBG_THREAD_DATA ThreadData = (PDTBG_THREAD_DATA)Data;
189
190 DPRINT("DtbgDesktopThread\n");
191
192 if (!SetThreadDesktop(ThreadData->Desktop))
193 {
194 DPRINT1("Failed to set thread desktop\n");
195 ThreadData->Status = STATUS_UNSUCCESSFUL;
196 SetEvent(ThreadData->Event);
197 return 1;
198 }
199
200 BackgroundWnd = CreateWindowW((LPCWSTR)DESKTOP_WINDOW_ATOM,
201 L"",
202 WS_POPUP | WS_CLIPCHILDREN,
203 GetSystemMetrics(SM_XVIRTUALSCREEN),
204 GetSystemMetrics(SM_YVIRTUALSCREEN),
205 GetSystemMetrics(SM_CXVIRTUALSCREEN),
206 GetSystemMetrics(SM_CYVIRTUALSCREEN),
207 NULL, NULL,
208 (HINSTANCE)GetModuleHandleW(L"user32.dll"), // Run in win32k/user32.
209 NULL);
210
211 if (NULL == BackgroundWnd)
212 {
213 DPRINT1("Failed to create desktop background window\n");
214 ThreadData->Status = STATUS_UNSUCCESSFUL;
215 SetEvent(ThreadData->Event);
216 return 1;
217 }
218
219 DPRINT("BackgroundWnd 0x%p\n",BackgroundWnd);
220
221 ThreadData->Status = STATUS_SUCCESS;
222 SetEvent(ThreadData->Event);
223
224 while (GetMessageW(&msg, NULL, 0, 0))
225 {
226 if (msg.message == WM_QUIT)
227 {
228 DPRINT1("DtbgDesktopThread WM_QUIT\n");
229 }
230 TranslateMessage(&msg);
231 DispatchMessageW(&msg);
232 }
233
234 DPRINT1("DtbgDesktopThread Exit\n");
235 return 1;
236 }
237
238 CSR_API(CsrCreateDesktop)
239 {
240 DTBG_THREAD_DATA ThreadData;
241 HANDLE ThreadHandle;
242
243 DPRINT("CsrCreateDesktop\n");
244
245 if (!BgInitialized)
246 {
247 BgInitialized = TRUE;
248
249 // if (!DtbgInit())
250 // return STATUS_UNSUCCESSFUL;
251 }
252
253 /*
254 * The desktop handle we got from win32k is in
255 * the scope of CSRSS so we can just use it.
256 */
257 ThreadData.Desktop = ApiMessage->Data.CreateDesktopRequest.DesktopHandle;
258
259 ThreadData.Event = CreateEventW(NULL, FALSE, FALSE, NULL);
260
261 if (NULL == ThreadData.Event)
262 {
263 DPRINT1("Failed to create event (error %d)\n", GetLastError());
264 return STATUS_UNSUCCESSFUL;
265 }
266
267 ThreadHandle = CreateThread(NULL,
268 0,
269 DtbgDesktopThread,
270 (PVOID)&ThreadData,
271 0,
272 NULL);
273
274 if (NULL == ThreadHandle)
275 {
276 CloseHandle(ThreadData.Event);
277 DPRINT1("Failed to create desktop window thread.\n");
278 return STATUS_UNSUCCESSFUL;
279 }
280
281 CloseHandle(ThreadHandle);
282
283 WaitForSingleObject(ThreadData.Event, INFINITE);
284 CloseHandle(ThreadData.Event);
285
286 return ThreadData.Status;
287 }
288
289 CSR_API(CsrShowDesktop)
290 {
291 #if 0
292 PRIVATE_NOTIFY_DESKTOP nmh;
293 DPRINT("CsrShowDesktop\n");
294
295 nmh.hdr.hwndFrom = ApiMessage->Data.ShowDesktopRequest.DesktopWindow;
296 nmh.hdr.idFrom = 0;
297 nmh.hdr.code = PM_SHOW_DESKTOP;
298
299 nmh.ShowDesktop.Width = (int)ApiMessage->Data.ShowDesktopRequest.Width;
300 nmh.ShowDesktop.Height = (int)ApiMessage->Data.ShowDesktopRequest.Height;
301
302 if (SendMessageW(ApiMessage->Data.ShowDesktopRequest.DesktopWindow,
303 WM_NOTIFY,
304 (WPARAM)nmh.hdr.hwndFrom,
305 (LPARAM)&nmh))
306 {
307 return STATUS_UNSUCCESSFUL;
308 }
309 #endif
310 return STATUS_SUCCESS;
311 }
312
313 CSR_API(CsrHideDesktop)
314 {
315 #if 0
316 PRIVATE_NOTIFY_DESKTOP nmh;
317 DPRINT("CsrHideDesktop\n");
318
319 nmh.hdr.hwndFrom = ApiMessage->Data.ShowDesktopRequest.DesktopWindow;
320 nmh.hdr.idFrom = 0;
321 nmh.hdr.code = PM_HIDE_DESKTOP;
322
323 if (SendMessageW(ApiMessage->Data.ShowDesktopRequest.DesktopWindow,
324 WM_NOTIFY,
325 (WPARAM)nmh.hdr.hwndFrom,
326 (LPARAM)&nmh))
327 {
328 return STATUS_UNSUCCESSFUL;
329 }
330 #endif
331 return STATUS_SUCCESS;
332 }
333
334 BOOL
335 FASTCALL
336 DtbgIsDesktopVisible(VOID)
337 {
338 VisibleDesktopWindow = GetDesktopWindow(); // DESKTOPWNDPROC
339
340 if (VisibleDesktopWindow != NULL &&
341 !IsWindowVisible(VisibleDesktopWindow))
342 {
343 VisibleDesktopWindow = NULL;
344 }
345
346 return VisibleDesktopWindow != NULL;
347 }
348
349 /* EOF */