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