[WIN32SS]
[reactos.git] / reactos / subsystems / win32 / win32k / ntuser / defwnd.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Miscellaneous User functions
5 * FILE: subsystems/win32/win32k/ntuser/defwnd.c
6 * PROGRAMER:
7 */
8
9 #include <win32k.h>
10 DBG_DEFAULT_CHANNEL(UserDefwnd);
11
12 // Client Shutdown messages
13 #define MCS_SHUTDOWNTIMERS 1
14 #define MCS_QUERYENDSESSION 2
15 // Client Shutdown returns
16 #define MCSR_GOODFORSHUTDOWN 1
17 #define MCSR_SHUTDOWNFINISHED 2
18 #define MCSR_DONOTSHUTDOWN 3
19
20 /*
21 * Based on CSRSS and described in pages 1115 - 1118 "Windows Internals, Fifth Edition".
22 * Apparently CSRSS sends out messages to do this w/o going into win32k internals.
23 */
24 static
25 LRESULT FASTCALL
26 IntClientShutdown(
27 PWND pWindow,
28 WPARAM wParam,
29 LPARAM lParam
30 )
31 {
32 LPARAM lParams;
33 BOOL KillTimers;
34 INT i;
35 LRESULT lResult = MCSR_GOODFORSHUTDOWN;
36 HWND *List;
37
38 lParams = wParam & (ENDSESSION_LOGOFF|ENDSESSION_CRITICAL|ENDSESSION_CLOSEAPP);
39 KillTimers = wParam & MCS_SHUTDOWNTIMERS ? TRUE : FALSE;
40 /*
41 First, send end sessions to children.
42 */
43 List = IntWinListChildren(pWindow);
44
45 if (List)
46 {
47 for (i = 0; List[i]; i++)
48 {
49 PWND WndChild;
50
51 if (!(WndChild = UserGetWindowObject(List[i])))
52 continue;
53
54 if (wParam & MCS_QUERYENDSESSION)
55 {
56 if (!co_IntSendMessage(WndChild->head.h, WM_QUERYENDSESSION, 0, lParams))
57 {
58 lResult = MCSR_DONOTSHUTDOWN;
59 break;
60 }
61 }
62 else
63 {
64 co_IntSendMessage(WndChild->head.h, WM_ENDSESSION, KillTimers, lParams);
65 if (KillTimers)
66 {
67 DestroyTimersForWindow(WndChild->head.pti, WndChild);
68 }
69 lResult = MCSR_SHUTDOWNFINISHED;
70 }
71 }
72 ExFreePool(List);
73 }
74 if (List && (lResult == MCSR_DONOTSHUTDOWN)) return lResult;
75 /*
76 Send to the caller.
77 */
78 if (wParam & MCS_QUERYENDSESSION)
79 {
80 if (!co_IntSendMessage(pWindow->head.h, WM_QUERYENDSESSION, 0, lParams))
81 {
82 lResult = MCSR_DONOTSHUTDOWN;
83 }
84 }
85 else
86 {
87 co_IntSendMessage(pWindow->head.h, WM_ENDSESSION, KillTimers, lParams);
88 if (KillTimers)
89 {
90 DestroyTimersForWindow(pWindow->head.pti, pWindow);
91 }
92 lResult = MCSR_SHUTDOWNFINISHED;
93 }
94 return lResult;
95 }
96
97 HBRUSH FASTCALL
98 DefWndControlColor(HDC hDC, UINT ctlType)
99 {
100 if (ctlType == CTLCOLOR_SCROLLBAR)
101 {
102 HBRUSH hb = IntGetSysColorBrush(COLOR_SCROLLBAR);
103 COLORREF bk = IntGetSysColor(COLOR_3DHILIGHT);
104 IntGdiSetTextColor(hDC, IntGetSysColor(COLOR_3DFACE));
105 IntGdiSetBkColor(hDC, bk);
106
107 /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
108 * we better use 0x55aa bitmap brush to make scrollbar's background
109 * look different from the window background.
110 */
111 if ( bk == IntGetSysColor(COLOR_WINDOW))
112 return gpsi->hbrGray;
113
114 NtGdiUnrealizeObject( hb );
115 return hb;
116 }
117
118 IntGdiSetTextColor(hDC, IntGetSysColor(COLOR_WINDOWTEXT));
119
120 if ((ctlType == CTLCOLOR_EDIT) || (ctlType == CTLCOLOR_LISTBOX))
121 {
122 IntGdiSetBkColor(hDC, IntGetSysColor(COLOR_WINDOW));
123 }
124 else
125 {
126 IntGdiSetBkColor(hDC, IntGetSysColor(COLOR_3DFACE));
127 return IntGetSysColorBrush(COLOR_3DFACE);
128 }
129
130 return IntGetSysColorBrush(COLOR_WINDOW);
131 }
132
133
134 LRESULT FASTCALL
135 DefWndHandleSysCommand(PWND pWnd, WPARAM wParam, LPARAM lParam)
136 {
137 LRESULT lResult = 0;
138 BOOL Hook = FALSE;
139
140 if (ISITHOOKED(WH_CBT) || (pWnd->head.rpdesk->pDeskInfo->fsHooks & HOOKID_TO_FLAG(WH_CBT)))
141 {
142 Hook = TRUE;
143 lResult = co_HOOK_CallHooks(WH_CBT, HCBT_SYSCOMMAND, wParam, lParam);
144
145 if (lResult) return lResult;
146 }
147
148 switch (wParam & 0xfff0)
149 {
150 case SC_SCREENSAVE:
151 ERR("Screensaver Called!\n");
152 UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_START_SCREENSAVE, 0); // always lParam 0 == not Secure
153 break;
154
155 default:
156 // We do not support anything else here so we should return normal even when sending a hook.
157 return 0;
158 }
159
160 return(Hook ? 1 : 0); // Don't call us again from user space.
161 }
162
163 /*
164 Win32k counterpart of User DefWindowProc
165 */
166 LRESULT FASTCALL
167 IntDefWindowProc(
168 PWND Wnd,
169 UINT Msg,
170 WPARAM wParam,
171 LPARAM lParam,
172 BOOL Ansi)
173 {
174 LRESULT lResult = 0;
175
176 if (Msg > WM_USER) return 0;
177
178 switch (Msg)
179 {
180 case WM_SYSCOMMAND:
181 {
182 ERR("hwnd %p WM_SYSCOMMAND %lx %lx\n", Wnd->head.h, wParam, lParam );
183 lResult = DefWndHandleSysCommand(Wnd, wParam, lParam);
184 break;
185 }
186 case WM_SHOWWINDOW:
187 {
188 if ((Wnd->style & WS_VISIBLE) && wParam) break;
189 if (!(Wnd->style & WS_VISIBLE) && !wParam) break;
190 if (!Wnd->spwndOwner) break;
191 if (LOWORD(lParam))
192 {
193 if (wParam)
194 {
195 if (!(Wnd->state & WNDS_HIDDENPOPUP)) break;
196 Wnd->state &= ~WNDS_HIDDENPOPUP;
197 }
198 else
199 Wnd->state |= WNDS_HIDDENPOPUP;
200
201 co_WinPosShowWindow(Wnd, wParam ? SW_SHOWNOACTIVATE : SW_HIDE);
202 }
203 }
204 break;
205 case WM_CLIENTSHUTDOWN:
206 return IntClientShutdown(Wnd, wParam, lParam);
207
208 case WM_CTLCOLORMSGBOX:
209 case WM_CTLCOLOREDIT:
210 case WM_CTLCOLORLISTBOX:
211 case WM_CTLCOLORBTN:
212 case WM_CTLCOLORDLG:
213 case WM_CTLCOLORSTATIC:
214 case WM_CTLCOLORSCROLLBAR:
215 return (LRESULT) DefWndControlColor((HDC)wParam, Msg - WM_CTLCOLORMSGBOX);
216
217 case WM_CTLCOLOR:
218 return (LRESULT) DefWndControlColor((HDC)wParam, HIWORD(lParam));
219
220 case WM_GETHOTKEY:
221 return DefWndGetHotKey(UserHMGetHandle(Wnd));
222 case WM_SETHOTKEY:
223 return DefWndSetHotKey(Wnd, wParam);
224
225 case WM_NCHITTEST:
226 {
227 POINT Point;
228 Point.x = GET_X_LPARAM(lParam);
229 Point.y = GET_Y_LPARAM(lParam);
230 return GetNCHitEx(Wnd, Point);
231 }
232
233 /* ReactOS only. */
234 case WM_CBT:
235 {
236 switch (wParam)
237 {
238 case HCBT_MOVESIZE:
239 {
240 RECTL rt;
241
242 if (lParam)
243 {
244 _SEH2_TRY
245 {
246 ProbeForRead((PVOID)lParam,
247 sizeof(RECT),
248 1);
249
250 RtlCopyMemory(&rt,
251 (PVOID)lParam,
252 sizeof(RECT));
253 }
254 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
255 {
256 lResult = 1;
257 }
258 _SEH2_END;
259 }
260 if (!lResult)
261 lResult = co_HOOK_CallHooks(WH_CBT, HCBT_MOVESIZE, (WPARAM)Wnd->head.h, lParam ? (LPARAM)&rt : 0);
262 }
263 break;
264 }
265 break;
266 }
267 break;
268 }
269 return lResult;
270 }
271
272 static HICON NC_IconForWindow( PWND pWnd )
273 {
274 HICON hIcon = 0;
275
276 if (!pWnd->pcls || pWnd->fnid == FNID_DESKTOP) return hIcon;
277 if (!hIcon) hIcon = pWnd->pcls->hIconSm;
278 if (!hIcon) hIcon = pWnd->pcls->hIcon;
279
280 if (!hIcon && pWnd->style & DS_MODALFRAME)
281 { // Fake it out for now, we use it as a test.
282 hIcon = (HICON)1;
283 /* FIXME: Need to setup Registry System Cursor & Icons via Callbacks at init time! */
284 if (!hIcon) hIcon = gpsi->hIconSmWindows; // Both are IDI_WINLOGO Small
285 if (!hIcon) hIcon = gpsi->hIcoWindows; // Reg size.
286 }
287 return hIcon;
288 }
289
290 DWORD FASTCALL
291 GetNCHitEx(PWND pWnd, POINT pt)
292 {
293 RECT rcWindow, rcClient;
294 DWORD Style, ExStyle;
295
296 if (!pWnd) return HTNOWHERE;
297
298 if (pWnd == UserGetDesktopWindow()) // pWnd->fnid == FNID_DESKTOP)
299 {
300 rcClient.left = rcClient.top = rcWindow.left = rcWindow.top = 0;
301 rcWindow.right = UserGetSystemMetrics(SM_CXSCREEN);
302 rcWindow.bottom = UserGetSystemMetrics(SM_CYSCREEN);
303 rcClient.right = UserGetSystemMetrics(SM_CXSCREEN);
304 rcClient.bottom = UserGetSystemMetrics(SM_CYSCREEN);
305 }
306 else
307 {
308 rcClient = pWnd->rcClient;
309 rcWindow = pWnd->rcWindow;
310 }
311
312 if (!RECTL_bPointInRect(&rcWindow, pt.x, pt.y)) return HTNOWHERE;
313
314 Style = pWnd->style;
315 ExStyle = pWnd->ExStyle;
316
317 if (Style & WS_MINIMIZE) return HTCAPTION;
318
319 if (RECTL_bPointInRect( &rcClient, pt.x, pt.y )) return HTCLIENT;
320
321 /* Check borders */
322 if (HAS_THICKFRAME( Style, ExStyle ))
323 {
324 RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXFRAME), -UserGetSystemMetrics(SM_CYFRAME) );
325 if (!RECTL_bPointInRect(&rcWindow, pt.x, pt.y ))
326 {
327 /* Check top sizing border */
328 if (pt.y < rcWindow.top)
329 {
330 if (pt.x < rcWindow.left+UserGetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
331 if (pt.x >= rcWindow.right-UserGetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
332 return HTTOP;
333 }
334 /* Check bottom sizing border */
335 if (pt.y >= rcWindow.bottom)
336 {
337 if (pt.x < rcWindow.left+UserGetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
338 if (pt.x >= rcWindow.right-UserGetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
339 return HTBOTTOM;
340 }
341 /* Check left sizing border */
342 if (pt.x < rcWindow.left)
343 {
344 if (pt.y < rcWindow.top+UserGetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
345 if (pt.y >= rcWindow.bottom-UserGetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
346 return HTLEFT;
347 }
348 /* Check right sizing border */
349 if (pt.x >= rcWindow.right)
350 {
351 if (pt.y < rcWindow.top+UserGetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
352 if (pt.y >= rcWindow.bottom-UserGetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
353 return HTRIGHT;
354 }
355 }
356 }
357 else /* No thick frame */
358 {
359 if (HAS_DLGFRAME( Style, ExStyle ))
360 RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXDLGFRAME), -UserGetSystemMetrics(SM_CYDLGFRAME));
361 else if (HAS_THINFRAME( Style, ExStyle ))
362 RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXBORDER), -UserGetSystemMetrics(SM_CYBORDER));
363 if (!RECTL_bPointInRect( &rcWindow, pt.x, pt.y )) return HTBORDER;
364 }
365
366 /* Check caption */
367
368 if ((Style & WS_CAPTION) == WS_CAPTION)
369 {
370 if (ExStyle & WS_EX_TOOLWINDOW)
371 rcWindow.top += UserGetSystemMetrics(SM_CYSMCAPTION) - 1;
372 else
373 rcWindow.top += UserGetSystemMetrics(SM_CYCAPTION) - 1;
374 if (!RECTL_bPointInRect( &rcWindow, pt.x, pt.y ))
375 {
376 BOOL min_or_max_box = (Style & WS_MAXIMIZEBOX) ||
377 (Style & WS_MINIMIZEBOX);
378 if (ExStyle & WS_EX_LAYOUTRTL)
379 {
380 /* Check system menu */
381 if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW) && NC_IconForWindow(pWnd))
382 {
383 rcWindow.right -= UserGetSystemMetrics(SM_CYCAPTION) - 1;
384 if (pt.x > rcWindow.right) return HTSYSMENU;
385 }
386
387 /* Check close button */
388 if (Style & WS_SYSMENU)
389 {
390 rcWindow.left += UserGetSystemMetrics(SM_CYCAPTION);
391 if (pt.x < rcWindow.left) return HTCLOSE;
392 }
393
394 /* Check maximize box */
395 /* In Win95 there is automatically a Maximize button when there is a minimize one */
396 if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
397 {
398 rcWindow.left += UserGetSystemMetrics(SM_CXSIZE);
399 if (pt.x < rcWindow.left) return HTMAXBUTTON;
400 }
401
402 /* Check minimize box */
403 if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
404 {
405 rcWindow.left += UserGetSystemMetrics(SM_CXSIZE);
406 if (pt.x < rcWindow.left) return HTMINBUTTON;
407 }
408 }
409 else
410 {
411 /* Check system menu */
412 if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW) && NC_IconForWindow(pWnd))
413 {
414 rcWindow.left += UserGetSystemMetrics(SM_CYCAPTION) - 1;
415 if (pt.x < rcWindow.left) return HTSYSMENU;
416 }
417
418 /* Check close button */
419 if (Style & WS_SYSMENU)
420 {
421 rcWindow.right -= UserGetSystemMetrics(SM_CYCAPTION);
422 if (pt.x > rcWindow.right) return HTCLOSE;
423 }
424
425 /* Check maximize box */
426 /* In Win95 there is automatically a Maximize button when there is a minimize one */
427 if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
428 {
429 rcWindow.right -= UserGetSystemMetrics(SM_CXSIZE);
430 if (pt.x > rcWindow.right) return HTMAXBUTTON;
431 }
432
433 /* Check minimize box */
434 if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
435 {
436 rcWindow.right -= UserGetSystemMetrics(SM_CXSIZE);
437 if (pt.x > rcWindow.right) return HTMINBUTTON;
438 }
439 }
440 return HTCAPTION;
441 }
442 }
443
444 /* Check menu bar */
445
446 if (HAS_MENU( pWnd, Style ) && (pt.y < rcClient.top) &&
447 (pt.x >= rcClient.left) && (pt.x < rcClient.right))
448 return HTMENU;
449
450 /* Check vertical scroll bar */
451
452 if (ExStyle & WS_EX_LAYOUTRTL) ExStyle ^= WS_EX_LEFTSCROLLBAR;
453 if (Style & WS_VSCROLL)
454 {
455 if((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
456 rcClient.left -= UserGetSystemMetrics(SM_CXVSCROLL);
457 else
458 rcClient.right += UserGetSystemMetrics(SM_CXVSCROLL);
459 if (RECTL_bPointInRect( &rcClient, pt.x, pt.y )) return HTVSCROLL;
460 }
461
462 /* Check horizontal scroll bar */
463
464 if (Style & WS_HSCROLL)
465 {
466 rcClient.bottom += UserGetSystemMetrics(SM_CYHSCROLL);
467 if (RECTL_bPointInRect( &rcClient, pt.x, pt.y ))
468 {
469 /* Check size box */
470 if ((Style & WS_VSCROLL) &&
471 ((((ExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (pt.x <= rcClient.left + UserGetSystemMetrics(SM_CXVSCROLL))) ||
472 (((ExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (pt.x >= rcClient.right - UserGetSystemMetrics(SM_CXVSCROLL)))))
473 return HTSIZE;
474 return HTHSCROLL;
475 }
476 }
477
478 /* Has to return HTNOWHERE if nothing was found
479 Could happen when a window has a customized non client area */
480 return HTNOWHERE;
481 }
482
483 /* EOF */