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