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