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