e8cfef6b2fc5169fba1fc66b3334360102f6c242
[reactos.git] / reactos / win32ss / user / 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 ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
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 USER_REFERENCE_ENTRY Ref;
176
177 if (Msg > WM_USER) return 0;
178
179 switch (Msg)
180 {
181 case WM_SYSCOMMAND:
182 {
183 ERR("hwnd %p WM_SYSCOMMAND %lx %lx\n", Wnd->head.h, wParam, lParam );
184 lResult = DefWndHandleSysCommand(Wnd, wParam, lParam);
185 break;
186 }
187 case WM_SHOWWINDOW:
188 {
189 if ((Wnd->style & WS_VISIBLE) && wParam) break;
190 if (!(Wnd->style & WS_VISIBLE) && !wParam) break;
191 if (!Wnd->spwndOwner) break;
192 if (LOWORD(lParam))
193 {
194 if (wParam)
195 {
196 if (!(Wnd->state & WNDS_HIDDENPOPUP)) break;
197 Wnd->state &= ~WNDS_HIDDENPOPUP;
198 }
199 else
200 Wnd->state |= WNDS_HIDDENPOPUP;
201
202 co_WinPosShowWindow(Wnd, wParam ? SW_SHOWNOACTIVATE : SW_HIDE);
203 }
204 }
205 break;
206 case WM_CLIENTSHUTDOWN:
207 return IntClientShutdown(Wnd, wParam, lParam);
208
209 case WM_APPCOMMAND:
210 ERR("WM_APPCOMMAND\n");
211 if ( (Wnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD &&
212 Wnd != co_GetDesktopWindow(Wnd) )
213 {
214 if (!co_HOOK_CallHooks(WH_SHELL, HSHELL_APPCOMMAND, wParam, lParam))
215 co_IntShellHookNotify(HSHELL_APPCOMMAND, wParam, lParam);
216 break;
217 }
218 UserRefObjectCo(Wnd->spwndParent, &Ref);
219 lResult = co_IntSendMessage(UserHMGetHandle(Wnd->spwndParent), WM_APPCOMMAND, wParam, lParam);
220 UserDerefObjectCo(Wnd->spwndParent);
221 break;
222
223 case WM_CTLCOLORMSGBOX:
224 case WM_CTLCOLOREDIT:
225 case WM_CTLCOLORLISTBOX:
226 case WM_CTLCOLORBTN:
227 case WM_CTLCOLORDLG:
228 case WM_CTLCOLORSTATIC:
229 case WM_CTLCOLORSCROLLBAR:
230 return (LRESULT) DefWndControlColor((HDC)wParam, Msg - WM_CTLCOLORMSGBOX);
231
232 case WM_CTLCOLOR:
233 return (LRESULT) DefWndControlColor((HDC)wParam, HIWORD(lParam));
234
235 case WM_GETHOTKEY:
236 return DefWndGetHotKey(Wnd);
237 case WM_SETHOTKEY:
238 return DefWndSetHotKey(Wnd, wParam);
239
240 case WM_NCHITTEST:
241 {
242 POINT Point;
243 Point.x = GET_X_LPARAM(lParam);
244 Point.y = GET_Y_LPARAM(lParam);
245 return GetNCHitEx(Wnd, Point);
246 }
247
248 case WM_SYNCPAINT:
249 {
250 HRGN hRgn;
251 Wnd->state &= ~WNDS_SYNCPAINTPENDING;
252 ERR("WM_SYNCPAINT\n");
253 hRgn = IntSysCreateRectRgn(0, 0, 0, 0);
254 if (co_UserGetUpdateRgn(Wnd, hRgn, FALSE) != NULLREGION)
255 {
256 if (!wParam) wParam = (RDW_ERASENOW | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN);
257 co_UserRedrawWindow(Wnd, NULL, hRgn, wParam);
258 }
259 GreDeleteObject(hRgn);
260 return 0;
261 }
262
263 case WM_SETREDRAW:
264 if (wParam)
265 {
266 if (!(Wnd->style & WS_VISIBLE))
267 {
268 IntSetStyle( Wnd, WS_VISIBLE, 0 );
269 Wnd->state |= WNDS_SENDNCPAINT;
270 }
271 }
272 else
273 {
274 if (Wnd->style & WS_VISIBLE)
275 {
276 co_UserRedrawWindow( Wnd, NULL, NULL, RDW_ALLCHILDREN | RDW_VALIDATE );
277 IntSetStyle( Wnd, 0, WS_VISIBLE );
278 }
279 }
280 return 0;
281
282 /* ReactOS only. */
283 case WM_CBT:
284 {
285 switch (wParam)
286 {
287 case HCBT_MOVESIZE:
288 {
289 RECTL rt;
290
291 if (lParam)
292 {
293 _SEH2_TRY
294 {
295 ProbeForRead((PVOID)lParam,
296 sizeof(RECT),
297 1);
298
299 RtlCopyMemory(&rt,
300 (PVOID)lParam,
301 sizeof(RECT));
302 }
303 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
304 {
305 lResult = 1;
306 }
307 _SEH2_END;
308 }
309 if (!lResult)
310 lResult = co_HOOK_CallHooks(WH_CBT, HCBT_MOVESIZE, (WPARAM)Wnd->head.h, lParam ? (LPARAM)&rt : 0);
311 }
312 break;
313 }
314 break;
315 }
316 break;
317 }
318 return lResult;
319 }
320
321 HICON FASTCALL NC_IconForWindow( PWND pWnd )
322 {
323 HICON hIcon = 0;
324 // First thing to do, init the Window Logo icons.
325 if (!gpsi->hIconSmWindows) co_IntSetWndIcons();
326
327 if (!hIcon) hIcon = UserGetProp(pWnd, gpsi->atomIconSmProp);
328 if (!hIcon) hIcon = UserGetProp(pWnd, gpsi->atomIconProp);
329 if (!hIcon) hIcon = pWnd->pcls->hIconSm;
330 if (!hIcon) hIcon = pWnd->pcls->hIcon;
331
332 if (!hIcon && pWnd->style & DS_MODALFRAME)
333 {
334 if (!hIcon) hIcon = gpsi->hIconSmWindows; // Both are IDI_WINLOGO Small
335 if (!hIcon) hIcon = gpsi->hIconWindows; // Reg size.
336 hIcon = (HICON)1;
337 }
338 return hIcon;
339 }
340
341 DWORD FASTCALL
342 GetNCHitEx(PWND pWnd, POINT pt)
343 {
344 RECT rcWindow, rcClient;
345 DWORD Style, ExStyle;
346
347 if (!pWnd) return HTNOWHERE;
348
349 if (pWnd == UserGetDesktopWindow()) // pWnd->fnid == FNID_DESKTOP)
350 {
351 rcClient.left = rcClient.top = rcWindow.left = rcWindow.top = 0;
352 rcWindow.right = UserGetSystemMetrics(SM_CXSCREEN);
353 rcWindow.bottom = UserGetSystemMetrics(SM_CYSCREEN);
354 rcClient.right = UserGetSystemMetrics(SM_CXSCREEN);
355 rcClient.bottom = UserGetSystemMetrics(SM_CYSCREEN);
356 }
357 else
358 {
359 rcClient = pWnd->rcClient;
360 rcWindow = pWnd->rcWindow;
361 }
362
363 if (!RECTL_bPointInRect(&rcWindow, pt.x, pt.y)) return HTNOWHERE;
364
365 Style = pWnd->style;
366 ExStyle = pWnd->ExStyle;
367
368 if (Style & WS_MINIMIZE) return HTCAPTION;
369
370 if (RECTL_bPointInRect( &rcClient, pt.x, pt.y )) return HTCLIENT;
371
372 /* Check borders */
373 if (HAS_THICKFRAME( Style, ExStyle ))
374 {
375 RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXFRAME), -UserGetSystemMetrics(SM_CYFRAME) );
376 if (!RECTL_bPointInRect(&rcWindow, pt.x, pt.y ))
377 {
378 /* Check top sizing border */
379 if (pt.y < rcWindow.top)
380 {
381 if (pt.x < rcWindow.left+UserGetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
382 if (pt.x >= rcWindow.right-UserGetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
383 return HTTOP;
384 }
385 /* Check bottom sizing border */
386 if (pt.y >= rcWindow.bottom)
387 {
388 if (pt.x < rcWindow.left+UserGetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
389 if (pt.x >= rcWindow.right-UserGetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
390 return HTBOTTOM;
391 }
392 /* Check left sizing border */
393 if (pt.x < rcWindow.left)
394 {
395 if (pt.y < rcWindow.top+UserGetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
396 if (pt.y >= rcWindow.bottom-UserGetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
397 return HTLEFT;
398 }
399 /* Check right sizing border */
400 if (pt.x >= rcWindow.right)
401 {
402 if (pt.y < rcWindow.top+UserGetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
403 if (pt.y >= rcWindow.bottom-UserGetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
404 return HTRIGHT;
405 }
406 }
407 }
408 else /* No thick frame */
409 {
410 if (HAS_DLGFRAME( Style, ExStyle ))
411 RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXDLGFRAME), -UserGetSystemMetrics(SM_CYDLGFRAME));
412 else if (HAS_THINFRAME( Style, ExStyle ))
413 RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXBORDER), -UserGetSystemMetrics(SM_CYBORDER));
414 if (!RECTL_bPointInRect( &rcWindow, pt.x, pt.y )) return HTBORDER;
415 }
416
417 /* Check caption */
418
419 if ((Style & WS_CAPTION) == WS_CAPTION)
420 {
421 if (ExStyle & WS_EX_TOOLWINDOW)
422 rcWindow.top += UserGetSystemMetrics(SM_CYSMCAPTION) - 1;
423 else
424 rcWindow.top += UserGetSystemMetrics(SM_CYCAPTION) - 1;
425 if (!RECTL_bPointInRect( &rcWindow, pt.x, pt.y ))
426 {
427 BOOL min_or_max_box = (Style & WS_SYSMENU) && (Style & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX));
428 if (ExStyle & WS_EX_LAYOUTRTL)
429 {
430 /* Check system menu */
431 if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW) && NC_IconForWindow(pWnd))
432 {
433 rcWindow.right -= UserGetSystemMetrics(SM_CYCAPTION) - 1;
434 if (pt.x > rcWindow.right) return HTSYSMENU;
435 }
436
437 /* Check close button */
438 if (Style & WS_SYSMENU)
439 {
440 rcWindow.left += UserGetSystemMetrics(SM_CYCAPTION);
441 if (pt.x < rcWindow.left) return HTCLOSE;
442 }
443
444 /* Check maximize box */
445 /* In Win95 there is automatically a Maximize button when there is a minimize one */
446 if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
447 {
448 rcWindow.left += UserGetSystemMetrics(SM_CXSIZE);
449 if (pt.x < rcWindow.left) return HTMAXBUTTON;
450 }
451
452 /* Check minimize box */
453 if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
454 {
455 rcWindow.left += UserGetSystemMetrics(SM_CXSIZE);
456 if (pt.x < rcWindow.left) return HTMINBUTTON;
457 }
458 }
459 else
460 {
461 /* Check system menu */
462 if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW) && NC_IconForWindow(pWnd))
463 {
464 rcWindow.left += UserGetSystemMetrics(SM_CYCAPTION) - 1;
465 if (pt.x < rcWindow.left) return HTSYSMENU;
466 }
467
468 /* Check close button */
469 if (Style & WS_SYSMENU)
470 {
471 rcWindow.right -= UserGetSystemMetrics(SM_CYCAPTION);
472 if (pt.x > rcWindow.right) return HTCLOSE;
473 }
474
475 /* Check maximize box */
476 /* In Win95 there is automatically a Maximize button when there is a minimize one */
477 if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
478 {
479 rcWindow.right -= UserGetSystemMetrics(SM_CXSIZE);
480 if (pt.x > rcWindow.right) return HTMAXBUTTON;
481 }
482
483 /* Check minimize box */
484 if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
485 {
486 rcWindow.right -= UserGetSystemMetrics(SM_CXSIZE);
487 if (pt.x > rcWindow.right) return HTMINBUTTON;
488 }
489 }
490 return HTCAPTION;
491 }
492 }
493
494 /* Check menu bar */
495
496 if (HAS_MENU( pWnd, Style ) && (pt.y < rcClient.top) &&
497 (pt.x >= rcClient.left) && (pt.x < rcClient.right))
498 return HTMENU;
499
500 /* Check vertical scroll bar */
501
502 if (ExStyle & WS_EX_LAYOUTRTL) ExStyle ^= WS_EX_LEFTSCROLLBAR;
503 if (Style & WS_VSCROLL)
504 {
505 if((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
506 rcClient.left -= UserGetSystemMetrics(SM_CXVSCROLL);
507 else
508 rcClient.right += UserGetSystemMetrics(SM_CXVSCROLL);
509 if (RECTL_bPointInRect( &rcClient, pt.x, pt.y )) return HTVSCROLL;
510 }
511
512 /* Check horizontal scroll bar */
513
514 if (Style & WS_HSCROLL)
515 {
516 rcClient.bottom += UserGetSystemMetrics(SM_CYHSCROLL);
517 if (RECTL_bPointInRect( &rcClient, pt.x, pt.y ))
518 {
519 /* Check size box */
520 if ((Style & WS_VSCROLL) &&
521 ((((ExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (pt.x <= rcClient.left + UserGetSystemMetrics(SM_CXVSCROLL))) ||
522 (((ExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (pt.x >= rcClient.right - UserGetSystemMetrics(SM_CXVSCROLL)))))
523 return HTSIZE;
524 return HTHSCROLL;
525 }
526 }
527
528 /* Has to return HTNOWHERE if nothing was found
529 Could happen when a window has a customized non client area */
530 return HTNOWHERE;
531 }
532
533 /* EOF */