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