[Win32SS]
[reactos.git] / reactos / win32ss / user / user32 / windows / defwnd.c
1 /*
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS user32.dll
5 * FILE: win32ss/user/user32/windows/defwnd.c
6 * PURPOSE: Window management
7 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * UPDATE HISTORY:
9 * 06-06-2001 CSH Created
10 */
11
12 /* INCLUDES ******************************************************************/
13
14 #include <user32.h>
15
16 #include <wine/debug.h>
17 WINE_DEFAULT_DEBUG_CHANNEL(user32);
18
19 LRESULT DefWndNCHitTest(HWND hWnd, POINT Point);
20
21 /* GLOBALS *******************************************************************/
22
23 /* FUNCTIONS *****************************************************************/
24
25 /*
26 * @implemented
27 */
28 DWORD
29 WINAPI
30 DECLSPEC_HOTPATCH
31 GetSysColor(int nIndex)
32 {
33 if(nIndex >= 0 && nIndex < NUM_SYSCOLORS)
34 {
35 return gpsi->argbSystem[nIndex];
36 }
37
38 SetLastError(ERROR_INVALID_PARAMETER);
39 return 0;
40 }
41
42 /*
43 * @implemented
44 */
45 HBRUSH
46 WINAPI
47 DECLSPEC_HOTPATCH
48 GetSysColorBrush(int nIndex)
49 {
50 if(nIndex >= 0 && nIndex < NUM_SYSCOLORS)
51 {
52 return gpsi->ahbrSystem[nIndex];
53 }
54
55 SetLastError(ERROR_INVALID_PARAMETER);
56 return NULL;
57 }
58
59 /*
60 * @implemented
61 */
62 BOOL
63 WINAPI
64 SetSysColors(
65 int cElements,
66 CONST INT *lpaElements,
67 CONST COLORREF *lpaRgbValues)
68 {
69 return NtUserSetSysColors(cElements, lpaElements, lpaRgbValues, 0);
70 }
71
72 BOOL
73 FASTCALL
74 DefSetText(HWND hWnd, PCWSTR String, BOOL Ansi)
75 {
76 BOOL Ret;
77 LARGE_STRING lsString;
78
79 if ( String )
80 {
81 if ( Ansi )
82 RtlInitLargeAnsiString((PLARGE_ANSI_STRING)&lsString, (PCSZ)String, 0);
83 else
84 RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&lsString, String, 0);
85 }
86 Ret = NtUserDefSetText(hWnd, (String ? &lsString : NULL));
87
88 return Ret;
89 }
90
91 void
92 UserGetInsideRectNC(PWND Wnd, RECT *rect)
93 {
94 ULONG Style;
95 ULONG ExStyle;
96
97 Style = Wnd->style;
98 ExStyle = Wnd->ExStyle;
99
100 rect->top = rect->left = 0;
101 rect->right = Wnd->rcWindow.right - Wnd->rcWindow.left;
102 rect->bottom = Wnd->rcWindow.bottom - Wnd->rcWindow.top;
103
104 if (Style & WS_ICONIC)
105 {
106 return;
107 }
108
109 /* Remove frame from rectangle */
110 if (UserHasThickFrameStyle(Style, ExStyle ))
111 {
112 InflateRect(rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME));
113 }
114 else
115 {
116 if (UserHasDlgFrameStyle(Style, ExStyle ))
117 {
118 InflateRect(rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
119 /* FIXME: this isn't in NC_AdjustRect? why not? */
120 if (ExStyle & WS_EX_DLGMODALFRAME)
121 InflateRect( rect, -1, 0 );
122 }
123 else
124 {
125 if (UserHasThinFrameStyle(Style, ExStyle))
126 {
127 InflateRect(rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
128 }
129 }
130 }
131 /* We have additional border information if the window
132 * is a child (but not an MDI child) */
133 if ((Style & WS_CHILD) && !(ExStyle & WS_EX_MDICHILD))
134 {
135 if (ExStyle & WS_EX_CLIENTEDGE)
136 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
137 if (ExStyle & WS_EX_STATICEDGE)
138 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
139 }
140 }
141
142 HWND FASTCALL
143 IntFindChildWindowToOwner(HWND hRoot, HWND hOwner)
144 {
145 HWND Ret;
146 PWND Child, OwnerWnd, Root, Owner;
147
148 Root = ValidateHwnd(hRoot);
149 Owner = ValidateHwnd(hOwner);
150
151 for( Child = Root->spwndChild ? DesktopPtrToUser(Root->spwndChild) : NULL;
152 Child;
153 Child = Child->spwndNext ? DesktopPtrToUser(Child->spwndNext) : NULL )
154 {
155 OwnerWnd = Child->spwndOwner ? DesktopPtrToUser(Child->spwndOwner) : NULL;
156 if(!OwnerWnd)
157 continue;
158
159 if (!(Child->style & WS_POPUP) || !(Child->style & WS_VISIBLE))
160 continue;
161
162 if(OwnerWnd == Owner)
163 {
164 Ret = Child->head.h;
165 return Ret;
166 }
167 }
168 ERR("IDCWTO Nothing found\n");
169 return NULL;
170 }
171
172 /***********************************************************************
173 * DefWndTrackScrollBar
174 *
175 * Track a mouse button press on the horizontal or vertical scroll-bar.
176 */
177 static VOID
178 DefWndTrackScrollBar(HWND Wnd, WPARAM wParam, POINT Pt)
179 {
180 INT ScrollBar;
181
182 if (SC_HSCROLL == (wParam & 0xfff0))
183 {
184 if (HTHSCROLL != (wParam & 0x0f))
185 {
186 return;
187 }
188 ScrollBar = SB_HORZ;
189 }
190 else /* SC_VSCROLL */
191 {
192 if (HTVSCROLL != (wParam & 0x0f))
193 {
194 return;
195 }
196 ScrollBar = SB_VERT;
197 }
198 ScrollTrackScrollBar(Wnd, ScrollBar, Pt );
199 }
200
201 LRESULT WINAPI DoAppSwitch( WPARAM wParam, LPARAM lParam);
202
203 LRESULT
204 DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
205 {
206 POINT Pt;
207 LRESULT lResult;
208
209 if (!IsWindowEnabled( hWnd )) return 0;
210
211 switch (wParam & 0xfff0)
212 {
213 case SC_MOVE:
214 case SC_SIZE:
215 // case SC_DEFAULT:
216 case SC_MOUSEMENU:
217 case SC_KEYMENU:
218 case SC_SCREENSAVE:
219 NtUserMessageCall( hWnd, WM_SYSCOMMAND, wParam, lParam, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, FALSE);
220 return 0;
221
222 default:
223 break;
224 }
225
226 if (ISITHOOKED(WH_CBT))
227 {
228 NtUserMessageCall( hWnd, WM_SYSCOMMAND, wParam, lParam, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, FALSE);
229 if (lResult) return 0;
230 }
231
232 switch (wParam & 0xfff0)
233 {
234
235 case SC_MINIMIZE:
236 if (hWnd == GetActiveWindow())
237 ShowOwnedPopups(hWnd,FALSE);
238 ShowWindow( hWnd, SW_MINIMIZE );
239 break;
240
241 case SC_MAXIMIZE:
242 if (IsIconic(hWnd) && hWnd == GetActiveWindow())
243 ShowOwnedPopups(hWnd,TRUE);
244 ShowWindow( hWnd, SW_MAXIMIZE );
245 break;
246
247 case SC_RESTORE:
248 if (IsIconic(hWnd) && hWnd == GetActiveWindow())
249 ShowOwnedPopups(hWnd,TRUE);
250 ShowWindow( hWnd, SW_RESTORE );
251 break;
252
253 case SC_CLOSE:
254 return SendMessageW(hWnd, WM_CLOSE, 0, 0);
255
256 case SC_VSCROLL:
257 case SC_HSCROLL:
258 {
259 Pt.x = (short)LOWORD(lParam);
260 Pt.y = (short)HIWORD(lParam);
261 DefWndTrackScrollBar(hWnd, wParam, Pt);
262 }
263 break;
264
265 case SC_TASKLIST:
266 WinExec( "taskman.exe", SW_SHOWNORMAL );
267 break;
268
269
270 case SC_NEXTWINDOW:
271 case SC_PREVWINDOW:
272 DoAppSwitch( wParam, lParam);
273 break;
274
275 case SC_HOTKEY:
276 {
277 HWND hwnd, hWndLastActive;
278 PWND pWnd;
279
280 hwnd = (HWND)lParam;
281 pWnd = ValidateHwnd(hwnd);
282 if (pWnd)
283 {
284 hWndLastActive = GetLastActivePopup(hwnd);
285 if (hWndLastActive)
286 {
287 hwnd = hWndLastActive;
288 pWnd = ValidateHwnd(hwnd);
289 }
290 SetForegroundWindow(hwnd);
291 if (pWnd->style & WS_MINIMIZE)
292 {
293 PostMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
294 }
295 }
296 }
297 break;
298
299 default:
300 FIXME("Unimplemented DefWndHandleSysCommand wParam 0x%x\n",wParam);
301 break;
302 }
303
304 return(0);
305 }
306
307 /***********************************************************************
308 * DefWndControlColor
309 *
310 * Default colors for control painting.
311 */
312 HBRUSH
313 DefWndControlColor(HDC hDC, UINT ctlType)
314 {
315 if (ctlType == CTLCOLOR_SCROLLBAR)
316 {
317 HBRUSH hb = GetSysColorBrush(COLOR_SCROLLBAR);
318 COLORREF bk = GetSysColor(COLOR_3DHILIGHT);
319 SetTextColor(hDC, GetSysColor(COLOR_3DFACE));
320 SetBkColor(hDC, bk);
321
322 /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
323 * we better use 0x55aa bitmap brush to make scrollbar's background
324 * look different from the window background.
325 */
326 if ( bk == GetSysColor(COLOR_WINDOW))
327 return gpsi->hbrGray;
328
329 UnrealizeObject( hb );
330 return hb;
331 }
332
333 SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
334
335 if ((ctlType == CTLCOLOR_EDIT) || (ctlType == CTLCOLOR_LISTBOX))
336 {
337 SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
338 }
339 else
340 {
341 SetBkColor(hDC, GetSysColor(COLOR_3DFACE));
342 return GetSysColorBrush(COLOR_3DFACE);
343 }
344
345 return GetSysColorBrush(COLOR_WINDOW);
346 }
347
348 static BOOL CALLBACK
349 UserSendUiUpdateMsg(HWND hwnd, LPARAM lParam)
350 {
351 SendMessageW(hwnd, WM_UPDATEUISTATE, (WPARAM)lParam, 0);
352 return TRUE;
353 }
354
355 static void
356 UserPaintCaption(PWND pwnd, INT Flags)
357 {
358 if ( pwnd->style & WS_VISIBLE && (pwnd->style & WS_CAPTION) == WS_CAPTION )
359 {
360 if (pwnd->state & WNDS_HASCAPTION && NtUserQueryWindow(UserHMGetHandle(pwnd), QUERY_WINDOW_FOREGROUND))
361 Flags |= DC_ACTIVE;
362 /*
363 * When themes are not enabled we can go on and paint the non client area.
364 * However if we do that with themes enabled we will draw a classic frame.
365 * This is sovled by sending a themes specific message to notify the themes
366 * engine that the caption needs to be redrawn
367 */
368 if(gpsi->dwSRVIFlags & SRVINFO_APIHOOK)
369 {
370 /*
371 * This will cause uxtheme to either paint the themed caption or call
372 * RealUserDrawCaption in order to draw the classic caption when themes
373 * are disabled but the themes service is enabled
374 */
375 SendMessageW(UserHMGetHandle(pwnd), WM_NCUAHDRAWCAPTION, Flags, 0);
376 }
377 else
378 {
379 RECT rc = {0,0,0,0};
380 HDC hDC = GetDCEx(UserHMGetHandle(pwnd), NULL, DCX_WINDOW|DCX_USESTYLE);
381 NtUserDrawCaption(UserHMGetHandle(pwnd), hDC, &rc, DC_DRAWCAPTIONMD|Flags);
382 ReleaseDC(UserHMGetHandle(pwnd), hDC);
383 }
384 }
385 //NtUserCallTwoParam((DWORD_PTR)UserHMGetHandle(pwnd),Flags,TWOPARAM_ROUTINE_REDRAWTITLE)
386 }
387
388 LRESULT FASTCALL
389 DefWndGetIcon(PWND pWnd, WPARAM wParam, LPARAM lParam)
390 {
391 HICON hIconRet;
392 if ( wParam > ICON_SMALL2 )
393 {
394 SetLastError(ERROR_INVALID_PARAMETER);
395 return 0;
396 }
397 switch(wParam)
398 {
399 case ICON_BIG:
400 hIconRet = UserGetProp(UserHMGetHandle(pWnd), gpsi->atomIconProp);
401 break;
402 case ICON_SMALL:
403 case ICON_SMALL2:
404 hIconRet = UserGetProp(UserHMGetHandle(pWnd), gpsi->atomIconSmProp);
405 break;
406 default:
407 break;
408 }
409 return (LRESULT)hIconRet;
410 }
411
412
413 LRESULT WINAPI
414 User32DefWindowProc(HWND hWnd,
415 UINT Msg,
416 WPARAM wParam,
417 LPARAM lParam,
418 BOOL bUnicode)
419 {
420 PWND pWnd = NULL;
421 if (hWnd)
422 {
423 pWnd = ValidateHwnd(hWnd);
424 if (!pWnd) return 0;
425 }
426
427 switch (Msg)
428 {
429 case WM_POPUPSYSTEMMENU:
430 {
431 /* This is an undocumented message used by the windows taskbar to
432 display the system menu of windows that belong to other processes. */
433 HMENU menu = GetSystemMenu(hWnd, FALSE);
434 ERR("WM_POPUPSYSTEMMENU\n");
435 if (menu)
436 TrackPopupMenu(menu, TPM_LEFTBUTTON|TPM_RIGHTBUTTON|TPM_SYSTEM_MENU,
437 LOWORD(lParam), HIWORD(lParam), 0, hWnd, NULL);
438 return 0;
439 }
440
441 case WM_NCHITTEST:
442 {
443 POINT Point;
444 Point.x = GET_X_LPARAM(lParam);
445 Point.y = GET_Y_LPARAM(lParam);
446 return (DefWndNCHitTest(hWnd, Point));
447 }
448
449 case WM_RBUTTONUP:
450 {
451 POINT Pt;
452 Pt.x = GET_X_LPARAM(lParam);
453 Pt.y = GET_Y_LPARAM(lParam);
454 ClientToScreen(hWnd, &Pt);
455 lParam = MAKELPARAM(Pt.x, Pt.y);
456 if (bUnicode)
457 {
458 SendMessageW(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
459 }
460 else
461 {
462 SendMessageA(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
463 }
464 break;
465 }
466
467 case WM_NCRBUTTONUP:
468 /*
469 * FIXME : we must NOT send WM_CONTEXTMENU on a WM_NCRBUTTONUP (checked
470 * in Windows), but what _should_ we do? According to MSDN :
471 * "If it is appropriate to do so, the system sends the WM_SYSCOMMAND
472 * message to the window". When is it appropriate?
473 */
474 ERR("WM_NCRBUTTONUP\n");
475 break;
476
477 case WM_CONTEXTMENU:
478 {
479 if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CHILD)
480 {
481 if (bUnicode)
482 {
483 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
484 }
485 else
486 {
487 SendMessageA(GetParent(hWnd), WM_CONTEXTMENU, wParam, lParam);
488 }
489 }
490 else
491 {
492 goto GoSS;
493 }
494 break;
495 }
496
497 case WM_CLOSE:
498 DestroyWindow(hWnd);
499 return (0);
500
501 case WM_MOUSEACTIVATE:
502 if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CHILD)
503 {
504 LONG Ret = SendMessageW(GetParent(hWnd), WM_MOUSEACTIVATE, wParam, lParam);
505 if (Ret) return (Ret);
506 }
507 return ( (HIWORD(lParam) == WM_LBUTTONDOWN && LOWORD(lParam) == HTCAPTION) ? MA_NOACTIVATE : MA_ACTIVATE );
508
509 case WM_ACTIVATE:
510 /* The default action in Windows is to set the keyboard focus to
511 * the window, if it's being activated and not minimized */
512 if (LOWORD(wParam) != WA_INACTIVE &&
513 !(GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_MINIMIZE))
514 {
515 //ERR("WM_ACTIVATE %p\n",hWnd);
516 SetFocus(hWnd);
517 }
518 break;
519
520 case WM_MOUSEWHEEL:
521 if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CHILD)
522 return SendMessageW( GetParent(hWnd), WM_MOUSEWHEEL, wParam, lParam);
523 break;
524
525 case WM_ERASEBKGND:
526 case WM_ICONERASEBKGND:
527 {
528 RECT Rect;
529 HBRUSH hBrush = (HBRUSH)GetClassLongPtrW(hWnd, GCL_HBRBACKGROUND);
530
531 if (NULL == hBrush)
532 {
533 return 0;
534 }
535 if (GetClassLongPtrW(hWnd, GCL_STYLE) & CS_PARENTDC)
536 {
537 /* can't use GetClipBox with a parent DC or we fill the whole parent */
538 GetClientRect(hWnd, &Rect);
539 DPtoLP((HDC)wParam, (LPPOINT)&Rect, 2);
540 }
541 else
542 {
543 GetClipBox((HDC)wParam, &Rect);
544 }
545 FillRect((HDC)wParam, &Rect, hBrush);
546 return (1);
547 }
548
549 case WM_CTLCOLORMSGBOX:
550 case WM_CTLCOLOREDIT:
551 case WM_CTLCOLORLISTBOX:
552 case WM_CTLCOLORBTN:
553 case WM_CTLCOLORDLG:
554 case WM_CTLCOLORSTATIC:
555 case WM_CTLCOLORSCROLLBAR:
556 return (LRESULT) DefWndControlColor((HDC)wParam, Msg - WM_CTLCOLORMSGBOX);
557
558 case WM_CTLCOLOR:
559 return (LRESULT) DefWndControlColor((HDC)wParam, HIWORD(lParam));
560
561 case WM_SYSCOMMAND:
562 return (DefWndHandleSysCommand(hWnd, wParam, lParam));
563
564 case WM_VKEYTOITEM:
565 case WM_CHARTOITEM:
566 return (-1);
567 /*
568 case WM_DROPOBJECT:
569 return DRAG_FILE;
570 */
571 case WM_QUERYDROPOBJECT:
572 {
573 if (GetWindowLongPtrW(hWnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES)
574 {
575 return(1);
576 }
577 break;
578 }
579
580 case WM_QUERYDRAGICON:
581 {
582 UINT Len;
583 HICON hIcon;
584
585 hIcon = (HICON)GetClassLongPtrW(hWnd, GCL_HICON);
586 if (hIcon)
587 {
588 return ((LRESULT)hIcon);
589 }
590 for (Len = 1; Len < 64; Len++)
591 {
592 if ((hIcon = LoadIconW(NULL, MAKEINTRESOURCEW(Len))) != NULL)
593 {
594 return((LRESULT)hIcon);
595 }
596 }
597 return ((LRESULT)LoadIconW(0, IDI_APPLICATION));
598 }
599
600 case WM_ISACTIVEICON:
601 {
602 BOOL isai;
603 isai = (pWnd->state & WNDS_ACTIVEFRAME) != 0;
604 return isai;
605 }
606
607 case WM_NOTIFYFORMAT:
608 {
609 if (lParam == NF_QUERY)
610 return IsWindowUnicode(hWnd) ? NFR_UNICODE : NFR_ANSI;
611 break;
612 }
613
614 case WM_GETICON:
615 {
616 return DefWndGetIcon(pWnd, wParam, lParam);
617 }
618
619 case WM_HELP:
620 {
621 if (bUnicode)
622 {
623 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
624 }
625 else
626 {
627 SendMessageA(GetParent(hWnd), Msg, wParam, lParam);
628 }
629 break;
630 }
631
632 case WM_QUERYOPEN:
633 case WM_QUERYENDSESSION:
634 {
635 return (1);
636 }
637
638 case WM_INPUTLANGCHANGEREQUEST:
639 {
640 HKL NewHkl;
641
642 if(wParam & INPUTLANGCHANGE_BACKWARD
643 && wParam & INPUTLANGCHANGE_FORWARD)
644 {
645 return FALSE;
646 }
647
648 //FIXME: What to do with INPUTLANGCHANGE_SYSCHARSET ?
649
650 if(wParam & INPUTLANGCHANGE_BACKWARD) NewHkl = (HKL) HKL_PREV;
651 else if(wParam & INPUTLANGCHANGE_FORWARD) NewHkl = (HKL) HKL_NEXT;
652 else NewHkl = (HKL) lParam;
653
654 NtUserActivateKeyboardLayout(NewHkl, 0);
655
656 return TRUE;
657 }
658
659 case WM_INPUTLANGCHANGE:
660 {
661 int count = 0;
662 HWND *win_array = WIN_ListChildren( hWnd );
663
664 if (!win_array)
665 break;
666 while (win_array[count])
667 SendMessageW( win_array[count++], WM_INPUTLANGCHANGE, wParam, lParam);
668 HeapFree(GetProcessHeap(),0,win_array);
669 break;
670 }
671
672 case WM_QUERYUISTATE:
673 {
674 LRESULT Ret = 0;
675 PWND Wnd = ValidateHwnd(hWnd);
676 if (Wnd != NULL)
677 {
678 if (Wnd->HideFocus)
679 Ret |= UISF_HIDEFOCUS;
680 if (Wnd->HideAccel)
681 Ret |= UISF_HIDEACCEL;
682 }
683 return Ret;
684 }
685
686 case WM_CHANGEUISTATE:
687 {
688 BOOL AlwaysShowCues = FALSE;
689 WORD Action = LOWORD(wParam);
690 WORD Flags = HIWORD(wParam);
691 PWND Wnd;
692
693 SystemParametersInfoW(SPI_GETKEYBOARDCUES, 0, &AlwaysShowCues, 0);
694 if (AlwaysShowCues)
695 break;
696
697 Wnd= ValidateHwnd(hWnd);
698 if (!Wnd || lParam != 0)
699 break;
700
701 if (Flags & ~(UISF_HIDEFOCUS | UISF_HIDEACCEL | UISF_ACTIVE))
702 break;
703
704 if (Flags & UISF_ACTIVE)
705 {
706 WARN("WM_CHANGEUISTATE does not yet support UISF_ACTIVE!\n");
707 }
708
709 if (Action == UIS_INITIALIZE)
710 {
711 PDESKTOPINFO Desk = GetThreadDesktopInfo();
712 if (Desk == NULL)
713 break;
714
715 Action = Desk->LastInputWasKbd ? UIS_CLEAR : UIS_SET;
716 Flags = UISF_HIDEFOCUS | UISF_HIDEACCEL;
717
718 /* We need to update wParam in case we need to send out messages */
719 wParam = MAKEWPARAM(Action, Flags);
720 }
721
722 switch (Action)
723 {
724 case UIS_SET:
725 /* See if we actually need to change something */
726 if ((Flags & UISF_HIDEFOCUS) && !Wnd->HideFocus)
727 break;
728 if ((Flags & UISF_HIDEACCEL) && !Wnd->HideAccel)
729 break;
730
731 /* Don't need to do anything... */
732 return 0;
733
734 case UIS_CLEAR:
735 /* See if we actually need to change something */
736 if ((Flags & UISF_HIDEFOCUS) && Wnd->HideFocus)
737 break;
738 if ((Flags & UISF_HIDEACCEL) && Wnd->HideAccel)
739 break;
740
741 /* Don't need to do anything... */
742 return 0;
743
744 default:
745 WARN("WM_CHANGEUISTATE: Unsupported Action 0x%x\n", Action);
746 break;
747 }
748
749 if ((Wnd->style & WS_CHILD) && Wnd->spwndParent != NULL)
750 {
751 /* We're a child window and we need to pass this message down until
752 we reach the root */
753 hWnd = UserHMGetHandle((PWND)DesktopPtrToUser(Wnd->spwndParent));
754 }
755 else
756 {
757 /* We're a top level window, we need to change the UI state */
758 Msg = WM_UPDATEUISTATE;
759 }
760
761 if (bUnicode)
762 return SendMessageW(hWnd, Msg, wParam, lParam);
763 else
764 return SendMessageA(hWnd, Msg, wParam, lParam);
765 }
766
767 case WM_UPDATEUISTATE:
768 {
769 BOOL Change = TRUE;
770 BOOL AlwaysShowCues = FALSE;
771 WORD Action = LOWORD(wParam);
772 WORD Flags = HIWORD(wParam);
773 PWND Wnd;
774
775 SystemParametersInfoW(SPI_GETKEYBOARDCUES, 0, &AlwaysShowCues, 0);
776 if (AlwaysShowCues)
777 break;
778
779 Wnd = ValidateHwnd(hWnd);
780 if (!Wnd || lParam != 0)
781 break;
782
783 if (Flags & ~(UISF_HIDEFOCUS | UISF_HIDEACCEL | UISF_ACTIVE))
784 break;
785
786 if (Flags & UISF_ACTIVE)
787 {
788 WARN("WM_UPDATEUISTATE does not yet support UISF_ACTIVE!\n");
789 }
790
791 if (Action == UIS_INITIALIZE)
792 {
793 PDESKTOPINFO Desk = GetThreadDesktopInfo();
794 if (Desk == NULL)
795 break;
796
797 Action = Desk->LastInputWasKbd ? UIS_CLEAR : UIS_SET;
798 Flags = UISF_HIDEFOCUS | UISF_HIDEACCEL;
799
800 /* We need to update wParam for broadcasting the update */
801 wParam = MAKEWPARAM(Action, Flags);
802 }
803
804 switch (Action)
805 {
806 case UIS_SET:
807 /* See if we actually need to change something */
808 if ((Flags & UISF_HIDEFOCUS) && !Wnd->HideFocus)
809 break;
810 if ((Flags & UISF_HIDEACCEL) && !Wnd->HideAccel)
811 break;
812
813 /* Don't need to do anything... */
814 Change = FALSE;
815 break;
816
817 case UIS_CLEAR:
818 /* See if we actually need to change something */
819 if ((Flags & UISF_HIDEFOCUS) && Wnd->HideFocus)
820 break;
821 if ((Flags & UISF_HIDEACCEL) && Wnd->HideAccel)
822 break;
823
824 /* Don't need to do anything... */
825 Change = FALSE;
826 break;
827
828 default:
829 WARN("WM_UPDATEUISTATE: Unsupported Action 0x%x\n", Action);
830 return 0;
831 }
832
833 /* Pack the information and call win32k */
834 if (Change)
835 {
836 if (!NtUserxUpdateUiState(hWnd, Flags | ((DWORD)Action << 3)))
837 break;
838 }
839
840 /* Always broadcast the update to all children */
841 EnumChildWindows(hWnd,
842 UserSendUiUpdateMsg,
843 (LPARAM)wParam);
844
845 break;
846 }
847
848 /* Move to Win32k !*/
849 case WM_SHOWWINDOW:
850 if (!lParam) break; // Call when it is necessary.
851 case WM_LBUTTONDOWN:
852 case WM_RBUTTONDOWN:
853 case WM_MBUTTONDOWN:
854 case WM_NCLBUTTONDOWN:
855 case WM_LBUTTONDBLCLK:
856 case WM_NCLBUTTONDBLCLK:
857 case WM_NCRBUTTONDOWN:
858 case WM_KEYF1:
859 case WM_KEYUP:
860 case WM_SYSKEYUP:
861 case WM_KEYDOWN:
862 case WM_SYSKEYDOWN:
863 case WM_SYSCHAR:
864 case WM_CANCELMODE:
865 case WM_PAINTICON:
866 case WM_PAINT:
867 case WM_PRINT:
868 case WM_SETICON:
869 case WM_SYSCOLORCHANGE:
870 case WM_NCUAHDRAWCAPTION:
871 case WM_NCUAHDRAWFRAME:
872 case WM_NCPAINT:
873 case WM_NCACTIVATE:
874 case WM_NCCALCSIZE:
875 case WM_SYNCPAINT:
876 case WM_SETREDRAW:
877 case WM_CLIENTSHUTDOWN:
878 case WM_GETHOTKEY:
879 case WM_SETHOTKEY:
880 case WM_WINDOWPOSCHANGING:
881 case WM_WINDOWPOSCHANGED:
882 case WM_APPCOMMAND:
883 case WM_SETCURSOR:
884 GoSS:
885 {
886 LRESULT lResult;
887 NtUserMessageCall( hWnd, Msg, wParam, lParam, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, !bUnicode);
888 return lResult;
889 }
890 }
891 return 0;
892 }
893
894
895 /*
896 * helpers for calling IMM32 (from Wine 10/22/2008)
897 *
898 * WM_IME_* messages are generated only by IMM32,
899 * so I assume imm32 is already LoadLibrary-ed.
900 */
901 static HWND
902 DefWndImmGetDefaultIMEWnd(HWND hwnd)
903 {
904 HINSTANCE hInstIMM = GetModuleHandleW(L"imm32\0");
905 HWND (WINAPI *pFunc)(HWND);
906 HWND hwndRet = 0;
907
908 if (!hInstIMM)
909 {
910 ERR("cannot get IMM32 handle\n");
911 return 0;
912 }
913
914 pFunc = (void*) GetProcAddress(hInstIMM, "ImmGetDefaultIMEWnd");
915 if (pFunc != NULL)
916 hwndRet = (*pFunc)(hwnd);
917
918 return hwndRet;
919 }
920
921
922 static BOOL
923 DefWndImmIsUIMessageA(HWND hwndIME, UINT msg, WPARAM wParam, LPARAM lParam)
924 {
925 HINSTANCE hInstIMM = GetModuleHandleW(L"imm32\0");
926 BOOL (WINAPI *pFunc)(HWND,UINT,WPARAM,LPARAM);
927 BOOL fRet = FALSE;
928
929 if (!hInstIMM)
930 {
931 ERR("cannot get IMM32 handle\n");
932 return FALSE;
933 }
934
935 pFunc = (void*) GetProcAddress(hInstIMM, "ImmIsUIMessageA");
936 if (pFunc != NULL)
937 fRet = (*pFunc)(hwndIME, msg, wParam, lParam);
938
939 return fRet;
940 }
941
942
943 static BOOL
944 DefWndImmIsUIMessageW(HWND hwndIME, UINT msg, WPARAM wParam, LPARAM lParam)
945 {
946 HINSTANCE hInstIMM = GetModuleHandleW(L"imm32\0");
947 BOOL (WINAPI *pFunc)(HWND,UINT,WPARAM,LPARAM);
948 BOOL fRet = FALSE;
949
950 if (!hInstIMM)
951 {
952 ERR("cannot get IMM32 handle\n");
953 return FALSE;
954 }
955
956 pFunc = (void*) GetProcAddress(hInstIMM, "ImmIsUIMessageW");
957 if (pFunc != NULL)
958 fRet = (*pFunc)(hwndIME, msg, wParam, lParam);
959
960 return fRet;
961 }
962
963
964 LRESULT WINAPI
965 RealDefWindowProcA(HWND hWnd,
966 UINT Msg,
967 WPARAM wParam,
968 LPARAM lParam)
969 {
970 LRESULT Result = 0;
971 PWND Wnd;
972
973 Wnd = ValidateHwnd(hWnd);
974
975 if ( !Wnd &&
976 Msg != WM_CTLCOLORMSGBOX &&
977 Msg != WM_CTLCOLORBTN &&
978 Msg != WM_CTLCOLORDLG &&
979 Msg != WM_CTLCOLORSTATIC )
980 return 0;
981
982 SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam);
983 switch (Msg)
984 {
985 case WM_NCCREATE:
986 {
987 if ( Wnd &&
988 Wnd->style & (WS_HSCROLL | WS_VSCROLL) )
989 {
990 if (!Wnd->pSBInfo)
991 {
992 SCROLLINFO si = {sizeof si, SIF_ALL, 0, 100, 0, 0, 0};
993 SetScrollInfo( hWnd, SB_HORZ, &si, FALSE );
994 SetScrollInfo( hWnd, SB_VERT, &si, FALSE );
995 }
996 }
997
998 if (lParam)
999 {
1000 LPCREATESTRUCTA cs = (LPCREATESTRUCTA)lParam;
1001 /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
1002 * may have child window IDs instead of window name */
1003 if (HIWORD(cs->lpszName))
1004 {
1005 DefSetText(hWnd, (PCWSTR)cs->lpszName, TRUE);
1006 }
1007 Result = 1;
1008 }
1009 break;
1010 }
1011
1012 case WM_GETTEXTLENGTH:
1013 {
1014 PWSTR buf;
1015 ULONG len;
1016
1017 if (Wnd != NULL && Wnd->strName.Length != 0)
1018 {
1019 buf = DesktopPtrToUser(Wnd->strName.Buffer);
1020 if (buf != NULL &&
1021 NT_SUCCESS(RtlUnicodeToMultiByteSize(&len,
1022 buf,
1023 Wnd->strName.Length)))
1024 {
1025 Result = (LRESULT) len;
1026 }
1027 }
1028 else Result = 0L;
1029
1030 break;
1031 }
1032
1033 case WM_GETTEXT:
1034 {
1035 PWSTR buf = NULL;
1036 PSTR outbuf = (PSTR)lParam;
1037 UINT copy;
1038
1039 if (Wnd != NULL && wParam != 0)
1040 {
1041 if (Wnd->strName.Buffer != NULL)
1042 buf = DesktopPtrToUser(Wnd->strName.Buffer);
1043 else
1044 outbuf[0] = L'\0';
1045
1046 if (buf != NULL)
1047 {
1048 if (Wnd->strName.Length != 0)
1049 {
1050 copy = min(Wnd->strName.Length / sizeof(WCHAR), wParam - 1);
1051 Result = WideCharToMultiByte(CP_ACP,
1052 0,
1053 buf,
1054 copy,
1055 outbuf,
1056 wParam,
1057 NULL,
1058 NULL);
1059 outbuf[Result] = '\0';
1060 }
1061 else
1062 outbuf[0] = '\0';
1063 }
1064 }
1065 break;
1066 }
1067
1068 case WM_SETTEXT:
1069 {
1070 DefSetText(hWnd, (PCWSTR)lParam, TRUE);
1071
1072 if ((GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
1073 {
1074 UserPaintCaption(Wnd, DC_TEXT);
1075 IntNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hWnd, OBJID_WINDOW, CHILDID_SELF, 0);
1076 }
1077 Result = 1;
1078 break;
1079 }
1080
1081 case WM_IME_KEYDOWN:
1082 {
1083 Result = PostMessageA(hWnd, WM_KEYDOWN, wParam, lParam);
1084 break;
1085 }
1086
1087 case WM_IME_KEYUP:
1088 {
1089 Result = PostMessageA(hWnd, WM_KEYUP, wParam, lParam);
1090 break;
1091 }
1092
1093 case WM_IME_CHAR:
1094 {
1095 if (HIBYTE(wParam))
1096 PostMessageA(hWnd, WM_CHAR, HIBYTE(wParam), lParam);
1097 PostMessageA(hWnd, WM_CHAR, LOBYTE(wParam), lParam);
1098 break;
1099 }
1100
1101 case WM_IME_STARTCOMPOSITION:
1102 case WM_IME_COMPOSITION:
1103 case WM_IME_ENDCOMPOSITION:
1104 case WM_IME_SELECT:
1105 case WM_IME_NOTIFY:
1106 case WM_IME_CONTROL:
1107 {
1108 HWND hwndIME;
1109
1110 hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
1111 if (hwndIME)
1112 Result = SendMessageA(hwndIME, Msg, wParam, lParam);
1113 break;
1114 }
1115
1116 case WM_IME_SETCONTEXT:
1117 {
1118 HWND hwndIME;
1119
1120 hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
1121 if (hwndIME)
1122 Result = DefWndImmIsUIMessageA(hwndIME, Msg, wParam, lParam);
1123 break;
1124 }
1125
1126 /* fall through */
1127 default:
1128 Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, FALSE);
1129 }
1130
1131 SPY_ExitMessage(SPY_RESULT_DEFWND, hWnd, Msg, Result, wParam, lParam);
1132 return Result;
1133 }
1134
1135
1136 LRESULT WINAPI
1137 RealDefWindowProcW(HWND hWnd,
1138 UINT Msg,
1139 WPARAM wParam,
1140 LPARAM lParam)
1141 {
1142 LRESULT Result = 0;
1143 PWND Wnd;
1144
1145 Wnd = ValidateHwnd(hWnd);
1146
1147 if ( !Wnd &&
1148 Msg != WM_CTLCOLORMSGBOX &&
1149 Msg != WM_CTLCOLORBTN &&
1150 Msg != WM_CTLCOLORDLG &&
1151 Msg != WM_CTLCOLORSTATIC )
1152 return 0;
1153
1154 SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam);
1155 switch (Msg)
1156 {
1157 case WM_NCCREATE:
1158 {
1159 if ( Wnd &&
1160 Wnd->style & (WS_HSCROLL | WS_VSCROLL) )
1161 {
1162 if (!Wnd->pSBInfo)
1163 {
1164 SCROLLINFO si = {sizeof si, SIF_ALL, 0, 100, 0, 0, 0};
1165 SetScrollInfo( hWnd, SB_HORZ, &si, FALSE );
1166 SetScrollInfo( hWnd, SB_VERT, &si, FALSE );
1167 }
1168 }
1169
1170 if (lParam)
1171 {
1172 LPCREATESTRUCTW cs = (LPCREATESTRUCTW)lParam;
1173 /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
1174 * may have child window IDs instead of window name */
1175 if (HIWORD(cs->lpszName))
1176 {
1177 DefSetText(hWnd, cs->lpszName, FALSE);
1178 }
1179 Result = 1;
1180 }
1181 break;
1182 }
1183
1184 case WM_GETTEXTLENGTH:
1185 {
1186 PWSTR buf;
1187 ULONG len;
1188
1189 if (Wnd != NULL && Wnd->strName.Length != 0)
1190 {
1191 buf = DesktopPtrToUser(Wnd->strName.Buffer);
1192 if (buf != NULL &&
1193 NT_SUCCESS(RtlUnicodeToMultiByteSize(&len,
1194 buf,
1195 Wnd->strName.Length)))
1196 {
1197 Result = (LRESULT) (Wnd->strName.Length / sizeof(WCHAR));
1198 }
1199 }
1200 else Result = 0L;
1201
1202 break;
1203 }
1204
1205 case WM_GETTEXT:
1206 {
1207 PWSTR buf = NULL;
1208 PWSTR outbuf = (PWSTR)lParam;
1209
1210 if (Wnd != NULL && wParam != 0)
1211 {
1212 if (Wnd->strName.Buffer != NULL)
1213 buf = DesktopPtrToUser(Wnd->strName.Buffer);
1214 else
1215 outbuf[0] = L'\0';
1216
1217 if (buf != NULL)
1218 {
1219 if (Wnd->strName.Length != 0)
1220 {
1221 Result = min(Wnd->strName.Length / sizeof(WCHAR), wParam - 1);
1222 RtlCopyMemory(outbuf,
1223 buf,
1224 Result * sizeof(WCHAR));
1225 outbuf[Result] = L'\0';
1226 }
1227 else
1228 outbuf[0] = L'\0';
1229 }
1230 }
1231 break;
1232 }
1233
1234 case WM_SETTEXT:
1235 {
1236 DefSetText(hWnd, (PCWSTR)lParam, FALSE);
1237
1238 if ((GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
1239 UserPaintCaption(Wnd, DC_TEXT);
1240 Result = 1;
1241 break;
1242 }
1243
1244 case WM_IME_CHAR:
1245 {
1246 PostMessageW(hWnd, WM_CHAR, wParam, lParam);
1247 Result = 0;
1248 break;
1249 }
1250
1251 case WM_IME_KEYDOWN:
1252 {
1253 Result = PostMessageW(hWnd, WM_KEYDOWN, wParam, lParam);
1254 break;
1255 }
1256
1257 case WM_IME_KEYUP:
1258 {
1259 Result = PostMessageW(hWnd, WM_KEYUP, wParam, lParam);
1260 break;
1261 }
1262
1263 case WM_IME_STARTCOMPOSITION:
1264 case WM_IME_COMPOSITION:
1265 case WM_IME_ENDCOMPOSITION:
1266 case WM_IME_SELECT:
1267 case WM_IME_NOTIFY:
1268 case WM_IME_CONTROL:
1269 {
1270 HWND hwndIME;
1271
1272 hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
1273 if (hwndIME)
1274 Result = SendMessageW(hwndIME, Msg, wParam, lParam);
1275 break;
1276 }
1277
1278 case WM_IME_SETCONTEXT:
1279 {
1280 HWND hwndIME;
1281
1282 hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
1283 if (hwndIME)
1284 Result = DefWndImmIsUIMessageW(hwndIME, Msg, wParam, lParam);
1285 break;
1286 }
1287
1288 default:
1289 Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, TRUE);
1290 }
1291 SPY_ExitMessage(SPY_RESULT_DEFWND, hWnd, Msg, Result, wParam, lParam);
1292
1293 return Result;
1294 }
1295
1296 LRESULT WINAPI
1297 DefWindowProcA(HWND hWnd,
1298 UINT Msg,
1299 WPARAM wParam,
1300 LPARAM lParam)
1301 {
1302 BOOL Hook, msgOverride = FALSE;
1303 LRESULT Result = 0;
1304
1305 LoadUserApiHook();
1306
1307 Hook = BeginIfHookedUserApiHook();
1308 if (Hook)
1309 {
1310 msgOverride = IsMsgOverride(Msg, &guah.DefWndProcArray);
1311 if(msgOverride == FALSE)
1312 {
1313 EndUserApiHook();
1314 }
1315 }
1316
1317 /* Bypass SEH and go direct. */
1318 if (!Hook || !msgOverride)
1319 return RealDefWindowProcA(hWnd, Msg, wParam, lParam);
1320
1321 _SEH2_TRY
1322 {
1323 Result = guah.DefWindowProcA(hWnd, Msg, wParam, lParam);
1324 }
1325 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1326 {
1327 }
1328 _SEH2_END;
1329
1330 EndUserApiHook();
1331
1332 return Result;
1333 }
1334
1335 LRESULT WINAPI
1336 DefWindowProcW(HWND hWnd,
1337 UINT Msg,
1338 WPARAM wParam,
1339 LPARAM lParam)
1340 {
1341 BOOL Hook, msgOverride = FALSE;
1342 LRESULT Result = 0;
1343
1344 LoadUserApiHook();
1345
1346 Hook = BeginIfHookedUserApiHook();
1347 if (Hook)
1348 {
1349 msgOverride = IsMsgOverride(Msg, &guah.DefWndProcArray);
1350 if(msgOverride == FALSE)
1351 {
1352 EndUserApiHook();
1353 }
1354 }
1355
1356 /* Bypass SEH and go direct. */
1357 if (!Hook || !msgOverride)
1358 return RealDefWindowProcW(hWnd, Msg, wParam, lParam);
1359
1360 _SEH2_TRY
1361 {
1362 Result = guah.DefWindowProcW(hWnd, Msg, wParam, lParam);
1363 }
1364 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1365 {
1366 }
1367 _SEH2_END;
1368
1369 EndUserApiHook();
1370
1371 return Result;
1372 }