static HWND FASTCALL co_IntSetFocusWindow(PWND Window OPTIONAL) { HWND hWndPrev = 0; PTHREADINFO pti; PUSER_MESSAGE_QUEUE ThreadQueue; if (Window) ASSERT_REFS_CO(Window); pti = PsGetCurrentThreadWin32Thread(); ThreadQueue = pti->MessageQueue; ASSERT(ThreadQueue != 0); hWndPrev = ThreadQueue->FocusWindow; if (Window != 0) { if (hWndPrev == Window->head.h) { return hWndPrev; } if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)Window->head.h, (LPARAM)hWndPrev)) { ERR("SetFocusWindow 1 WH_CBT Call Hook return!\n"); return 0; } ThreadQueue->FocusWindow = Window->head.h; TRACE("Focus: %d -> %d\n", hWndPrev, Window->head.h); co_IntSendKillFocusMessages(hWndPrev, Window->head.h); co_IntSendSetFocusMessages(hWndPrev, Window->head.h); } else { ThreadQueue->FocusWindow = 0; if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)0, (LPARAM)hWndPrev)) { ERR("SetFocusWindow 2 WH_CBT Call Hook return!\n"); return 0; } co_IntSendKillFocusMessages(hWndPrev, 0); } return hWndPrev; }
LRESULT FASTCALL DefWndHandleSysCommand(PWND pWnd, WPARAM wParam, LPARAM lParam) { LRESULT lResult = 0; BOOL Hook = FALSE; if (ISITHOOKED(WH_CBT) || (pWnd->head.rpdesk->pDeskInfo->fsHooks & HOOKID_TO_FLAG(WH_CBT))) { Hook = TRUE; lResult = co_HOOK_CallHooks(WH_CBT, HCBT_SYSCOMMAND, wParam, lParam); if (lResult) return lResult; } switch (wParam & 0xfff0) { case SC_SCREENSAVE: ERR("Screensaver Called!\n"); UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_START_SCREENSAVE, 0); // always lParam 0 == not Secure break; default: // We do not support anything else here so we should return normal even when sending a hook. return 0; } return(Hook ? 1 : 0); // Don't call us again from user space. }
HWND FASTCALL co_IntSetActiveWindow(PWND Wnd OPTIONAL) { PTHREADINFO pti; PUSER_MESSAGE_QUEUE ThreadQueue; HWND hWndPrev; HWND hWnd = 0; CBTACTIVATESTRUCT cbt; if (Wnd) ASSERT_REFS_CO(Wnd); pti = PsGetCurrentThreadWin32Thread(); ThreadQueue = pti->MessageQueue; ASSERT(ThreadQueue != 0); if (Wnd != 0) { if ((!(Wnd->style & WS_VISIBLE) && Wnd->head.pti->pEThread->ThreadsProcess != CsrProcess) || (Wnd->style & (WS_POPUP | WS_CHILD)) == WS_CHILD) { return ThreadQueue ? 0 : ThreadQueue->ActiveWindow; } hWnd = Wnd->head.h; } hWndPrev = ThreadQueue->ActiveWindow; if (hWndPrev == hWnd) { return hWndPrev; } /* call CBT hook chain */ cbt.fMouse = FALSE; cbt.hWndActive = hWndPrev; if (co_HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd, (LPARAM)&cbt)) { ERR("SetActiveWindow WH_CBT Call Hook return!\n"); return 0; } ThreadQueue->ActiveWindow = hWnd; co_IntSendDeactivateMessages(hWndPrev, hWnd); co_IntSendActivateMessages(hWndPrev, hWnd, FALSE); /* FIXME */ /* return IntIsWindow(hWndPrev) ? hWndPrev : 0;*/ return hWndPrev; }
HWND FASTCALL co_UserSetFocus(PWND Window) { HWND hWndPrev = 0; PWND pwndTop; PTHREADINFO pti; PUSER_MESSAGE_QUEUE ThreadQueue; if (Window) ASSERT_REFS_CO(Window); pti = PsGetCurrentThreadWin32Thread(); ThreadQueue = pti->MessageQueue; ASSERT(ThreadQueue != 0); TRACE("Enter SetFocus hWnd 0x%p pti 0x%p\n",Window ? UserHMGetHandle(Window) : 0, pti ); hWndPrev = ThreadQueue->spwndFocus ? UserHMGetHandle(ThreadQueue->spwndFocus) : 0; if (Window != 0) { if (hWndPrev == UserHMGetHandle(Window)) { return hWndPrev ? (IntIsWindow(hWndPrev) ? hWndPrev : 0) : 0; /* Nothing to do */ } if (Window->head.pti->MessageQueue != ThreadQueue) { ERR("SetFocus Must have the same Q!\n"); return 0; } /* Check if we can set the focus to this window */ for (pwndTop = Window; pwndTop != NULL; pwndTop = pwndTop->spwndParent) { if (pwndTop->style & (WS_MINIMIZED|WS_DISABLED)) return 0; if ((pwndTop->style & (WS_POPUP|WS_CHILD)) != WS_CHILD) break; } if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)Window->head.h, (LPARAM)hWndPrev)) { ERR("SetFocus 1 WH_CBT Call Hook return!\n"); return 0; } /* Activate pwndTop if needed. */ if (pwndTop != ThreadQueue->spwndActive) { PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue(); // Keep it based on desktop. if (ThreadQueue != ForegroundQueue && IsAllowedFGActive(pti, pwndTop)) // Rule 2 & 3. { //ERR("SetFocus: Set Foreground!\n"); if (!(pwndTop->style & WS_VISIBLE)) { pti->ppi->W32PF_flags |= W32PF_ALLOWFOREGROUNDACTIVATE; } if (!co_IntSetForegroundAndFocusWindow(pwndTop, FALSE)) { ERR("SetFocus: Set Foreground and Focus Failed!\n"); return 0; } } /* Set Active when it is needed. */ if (pwndTop != ThreadQueue->spwndActive) { //ERR("SetFocus: Set Active!\n"); if (!co_IntSetActiveWindow(pwndTop, FALSE, FALSE, FALSE)) { ERR("SetFocus: Set Active Failed!\n"); return 0; } } /* Abort if window destroyed */ if (Window->state2 & WNDS2_INDESTROY) return 0; /* Do not change focus if the window is no longer active */ if (pwndTop != ThreadQueue->spwndActive) { ERR("SetFocus: Top window did not go active!\n"); return 0; } } // Check again! SetActiveWindow could have set the focus via WM_ACTIVATE. hWndPrev = ThreadQueue->spwndFocus ? UserHMGetHandle(ThreadQueue->spwndFocus) : 0; IntSendFocusMessages( pti, Window); TRACE("Focus: %p -> %p\n", hWndPrev, Window->head.h); } else /* NULL hwnd passed in */ { if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)0, (LPARAM)hWndPrev)) { ERR("SetFocus: 2 WH_CBT Call Hook return!\n"); return 0; } /* set the current thread focus window null */ IntSendFocusMessages( pti, NULL); } return hWndPrev ? (IntIsWindow(hWndPrev) ? hWndPrev : 0) : 0; }
BOOL FASTCALL co_IntSetActiveWindow(PWND Wnd OPTIONAL, BOOL bMouse, BOOL bFocus, BOOL Async) { PTHREADINFO pti; PUSER_MESSAGE_QUEUE ThreadQueue; PWND pWndChg, WndPrev; // State changes. HWND hWndPrev; HWND hWnd = 0; BOOL InAAPM; CBTACTIVATESTRUCT cbt; //ERR("co_IntSetActiveWindow 1\n"); if (Wnd) { ASSERT_REFS_CO(Wnd); hWnd = UserHMGetHandle(Wnd); if ((Wnd->style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE; if (Wnd == UserGetDesktopWindow()) return FALSE; //ERR("co_IntSetActiveWindow 1a hWnd 0x%p\n",hWnd); } //ERR("co_IntSetActiveWindow 2\n"); pti = PsGetCurrentThreadWin32Thread(); ThreadQueue = pti->MessageQueue; ASSERT(ThreadQueue != 0); hWndPrev = ThreadQueue->spwndActive ? UserHMGetHandle(ThreadQueue->spwndActive) : NULL; pWndChg = ThreadQueue->spwndActive; // Keep to notify of a preemptive switch. while (Wnd) { BOOL Ret, DoFG, AllowFG; if (Wnd->state & WNDS_BEINGACTIVATED) return TRUE; if (ThreadQueue == Wnd->head.pti->MessageQueue) { if (IsAllowedFGActive(pti, Wnd)) { DoFG = TRUE; } else { //ERR("co_IntSetActiveWindow 3 Go Out!\n"); break; } AllowFG = !pti->cVisWindows; // Nothing is visable. //ERR("co_IntSetActiveWindow 3a DoFG = %d AllowFG = %d\n",DoFG,AllowFG); } else //if (ThreadQueue != Wnd->head.pti->MessageQueue) { //PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue(); // Rule 1 & 4, We are foreground so set this FG window or NULL foreground.... //if (!ForegroundQueue || ForegroundQueue == ThreadQueue) if (!gpqForeground || gpqForeground == ThreadQueue) { DoFG = TRUE; } else DoFG = FALSE; if (DoFG) { if (pti->TIF_flags & TIF_ALLOWFOREGROUNDACTIVATE || pti->cVisWindows) AllowFG = TRUE; else AllowFG = FALSE; } else AllowFG = FALSE; //ERR("co_IntSetActiveWindow 3b DoFG = %d AllowFG = %d\n",DoFG,AllowFG); } Ret = FALSE; if (DoFG) { pti->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE; //ERR("co_IntSetActiveWindow 3c FG set\n"); Ret = co_IntSetForegroundAndFocusWindow(Wnd, bMouse); if (AllowFG) { pti->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE; } else { pti->TIF_flags &= ~TIF_ALLOWFOREGROUNDACTIVATE; } } return Ret; } /* Call CBT hook chain */ cbt.fMouse = bMouse; cbt.hWndActive = hWndPrev; if (co_HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd, (LPARAM)&cbt)) { ERR("SetActiveWindow: WH_CBT Call Hook return!\n"); return FALSE; } if ( ThreadQueue->spwndActive && ThreadQueue->spwndActive->state & WNDS_DESTROYED ) ThreadQueue->spwndActive = NULL; else ThreadQueue->spwndActivePrev = ThreadQueue->spwndActive; WndPrev = ThreadQueue->spwndActive; // Keep to save changing active. if (WndPrev) { if (ThreadQueue == gpqForeground) gpqForegroundPrev = ThreadQueue; if (!co_IntSendDeactivateMessages(UserHMGetHandle(WndPrev), hWnd)) return FALSE; } WndPrev = ThreadQueue->spwndActive; // Again keep to save changing active. // While in calling message proc or hook: // Fail if a preemptive switch was made, current active not made previous, // focus window is dead or no longer the same thread queue. if ( ThreadQueue->spwndActivePrev != ThreadQueue->spwndActive || pWndChg != WndPrev || (Wnd && !VerifyWnd(Wnd)) || ThreadQueue != pti->MessageQueue ) { ERR("SetActiveWindow: Summery ERROR, active state changed!\n"); return FALSE; } if (!WndPrev) ThreadQueue->QF_flags &= ~QF_FOCUSNULLSINCEACTIVE; if (Wnd) Wnd->state |= WNDS_BEINGACTIVATED; IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND, Wnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); //// Breaks Atl-Esc/Tab via User32. ////FindRemoveAsyncMsg(Wnd,(WPARAM)Wnd); // Clear out activate ASYNC messages. /* check if the specified window can be set in the input data of a given queue */ if ( !Wnd || ThreadQueue == Wnd->head.pti->MessageQueue) { /* set the current thread active window */ ThreadQueue->spwndActive = Wnd; } WndPrev = VerifyWnd(ThreadQueue->spwndActivePrev); // Now should be set but verify it again. InAAPM = co_IntSendActivateMessages(WndPrev, Wnd, bMouse, Async); /* now change focus if necessary */ if (bFocus && !(ThreadQueue->QF_flags & QF_FOCUSNULLSINCEACTIVE)) { /* Do not change focus if the window is no longer active */ if (ThreadQueue->spwndActive == Wnd) { if (!ThreadQueue->spwndFocus || !Wnd || UserGetAncestor(ThreadQueue->spwndFocus, GA_ROOT) != Wnd) { co_UserSetFocus(Wnd); } } } if (InAAPM) { pti->TIF_flags &= ~TIF_INACTIVATEAPPMSG; } // FIXME: Used in the menu loop!!! //ThreadQueue->QF_flags |= QF_ACTIVATIONCHANGE; //ERR("co_IntSetActiveWindow Exit\n"); if (Wnd) Wnd->state &= ~WNDS_BEINGACTIVATED; return (ThreadQueue->spwndActive == Wnd); }
/* Win32k counterpart of User DefWindowProc */ LRESULT FASTCALL IntDefWindowProc( PWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL Ansi) { LRESULT lResult = 0; USER_REFERENCE_ENTRY Ref; if (Msg > WM_USER) return 0; switch (Msg) { case WM_SYSCOMMAND: { ERR("hwnd %p WM_SYSCOMMAND %lx %lx\n", Wnd->head.h, wParam, lParam ); lResult = DefWndHandleSysCommand(Wnd, wParam, lParam); break; } case WM_SHOWWINDOW: { if ((Wnd->style & WS_VISIBLE) && wParam) break; if (!(Wnd->style & WS_VISIBLE) && !wParam) break; if (!Wnd->spwndOwner) break; if (LOWORD(lParam)) { if (wParam) { if (!(Wnd->state & WNDS_HIDDENPOPUP)) break; Wnd->state &= ~WNDS_HIDDENPOPUP; } else Wnd->state |= WNDS_HIDDENPOPUP; co_WinPosShowWindow(Wnd, wParam ? SW_SHOWNOACTIVATE : SW_HIDE); } } break; case WM_CLIENTSHUTDOWN: return IntClientShutdown(Wnd, wParam, lParam); case WM_APPCOMMAND: ERR("WM_APPCOMMAND\n"); if ( (Wnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD && Wnd != co_GetDesktopWindow(Wnd) ) { if (!co_HOOK_CallHooks(WH_SHELL, HSHELL_APPCOMMAND, wParam, lParam)) co_IntShellHookNotify(HSHELL_APPCOMMAND, wParam, lParam); break; } UserRefObjectCo(Wnd->spwndParent, &Ref); lResult = co_IntSendMessage(UserHMGetHandle(Wnd->spwndParent), WM_APPCOMMAND, wParam, lParam); UserDerefObjectCo(Wnd->spwndParent); break; case WM_CTLCOLORMSGBOX: case WM_CTLCOLOREDIT: case WM_CTLCOLORLISTBOX: case WM_CTLCOLORBTN: case WM_CTLCOLORDLG: case WM_CTLCOLORSTATIC: case WM_CTLCOLORSCROLLBAR: return (LRESULT) DefWndControlColor((HDC)wParam, Msg - WM_CTLCOLORMSGBOX); case WM_CTLCOLOR: return (LRESULT) DefWndControlColor((HDC)wParam, HIWORD(lParam)); case WM_GETHOTKEY: return DefWndGetHotKey(Wnd); case WM_SETHOTKEY: return DefWndSetHotKey(Wnd, wParam); case WM_NCHITTEST: { POINT Point; Point.x = GET_X_LPARAM(lParam); Point.y = GET_Y_LPARAM(lParam); return GetNCHitEx(Wnd, Point); } case WM_SYNCPAINT: { HRGN hRgn; Wnd->state &= ~WNDS_SYNCPAINTPENDING; ERR("WM_SYNCPAINT\n"); hRgn = IntSysCreateRectRgn(0, 0, 0, 0); if (co_UserGetUpdateRgn(Wnd, hRgn, FALSE) != NULLREGION) { if (!wParam) wParam = (RDW_ERASENOW | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN); co_UserRedrawWindow(Wnd, NULL, hRgn, wParam); } GreDeleteObject(hRgn); return 0; } case WM_SETREDRAW: if (wParam) { if (!(Wnd->style & WS_VISIBLE)) { IntSetStyle( Wnd, WS_VISIBLE, 0 ); Wnd->state |= WNDS_SENDNCPAINT; } } else { if (Wnd->style & WS_VISIBLE) { co_UserRedrawWindow( Wnd, NULL, NULL, RDW_ALLCHILDREN | RDW_VALIDATE ); IntSetStyle( Wnd, 0, WS_VISIBLE ); } } return 0; /* ReactOS only. */ case WM_CBT: { switch (wParam) { case HCBT_MOVESIZE: { RECTL rt; if (lParam) { _SEH2_TRY { ProbeForRead((PVOID)lParam, sizeof(RECT), 1); RtlCopyMemory(&rt, (PVOID)lParam, sizeof(RECT)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { lResult = 1; } _SEH2_END; } if (!lResult) lResult = co_HOOK_CallHooks(WH_CBT, HCBT_MOVESIZE, (WPARAM)Wnd->head.h, lParam ? (LPARAM)&rt : 0); } break; } break; } break; } return lResult; }
BOOL FASTCALL co_IntSetActiveWindow(PWND Wnd OPTIONAL, HWND * Prev, BOOL bMouse, BOOL bFocus, BOOL Async) { PTHREADINFO pti; PUSER_MESSAGE_QUEUE ThreadQueue; PWND pWndChg, WndPrev; // State changes. HWND hWndPrev; HWND hWnd = 0; BOOL InAAPM; CBTACTIVATESTRUCT cbt; if (Wnd) { ASSERT_REFS_CO(Wnd); hWnd = UserHMGetHandle(Wnd); if ((Wnd->style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE; if (Wnd == UserGetDesktopWindow()) return FALSE; } pti = PsGetCurrentThreadWin32Thread(); ThreadQueue = pti->MessageQueue; ASSERT(ThreadQueue != 0); hWndPrev = ThreadQueue->spwndActive ? UserHMGetHandle(ThreadQueue->spwndActive) : NULL; if (Prev) *Prev = hWndPrev; if (hWndPrev == hWnd) return TRUE; pWndChg = ThreadQueue->spwndActive; // Keep to notify of a preemptive switch. if (Wnd) { if (ThreadQueue != Wnd->head.pti->MessageQueue) { PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue(); // Rule 1 & 4, We are foreground so set this FG window or NULL foreground.... if (!ForegroundQueue || ForegroundQueue == ThreadQueue) { return co_IntSetForegroundAndFocusWindow(Wnd, bMouse); } } if (Wnd->state & WNDS_BEINGACTIVATED) return TRUE; } /* Call CBT hook chain */ cbt.fMouse = bMouse; cbt.hWndActive = hWndPrev; if (co_HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd, (LPARAM)&cbt)) { ERR("SetActiveWindow: WH_CBT Call Hook return!\n"); return FALSE; } if ( ThreadQueue->spwndActive && ThreadQueue->spwndActive->state & WNDS_DESTROYED ) ThreadQueue->spwndActive = NULL; else ThreadQueue->spwndActivePrev = ThreadQueue->spwndActive; WndPrev = ThreadQueue->spwndActive; // Keep to save changing active. if (WndPrev) { if (ThreadQueue == gpqForeground) gpqForegroundPrev = ThreadQueue; if (!co_IntSendDeactivateMessages(hWndPrev, hWnd)) return FALSE; } // While in calling message proc or hook: // Fail if a preemptive switch was made, current active not made previous, // focus window is dead or no longer the same thread queue. if ( ThreadQueue->spwndActivePrev != ThreadQueue->spwndActive || pWndChg != ThreadQueue->spwndActive || (Wnd && !VerifyWnd(Wnd)) || ThreadQueue != pti->MessageQueue ) { ERR("SetActiveWindow: Summery ERROR, active state changed!\n"); return FALSE; } if (!WndPrev) ThreadQueue->QF_flags &= ~QF_FOCUSNULLSINCEACTIVE; if (Wnd) Wnd->state |= WNDS_BEINGACTIVATED; IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND, Wnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); /* check if the specified window can be set in the input data of a given queue */ if ( !Wnd || ThreadQueue == Wnd->head.pti->MessageQueue) { /* set the current thread active window */ ThreadQueue->spwndActive = Wnd; } InAAPM = co_IntSendActivateMessages(WndPrev, Wnd, bMouse, Async); /* now change focus if necessary */ if (bFocus && !(ThreadQueue->QF_flags & QF_FOCUSNULLSINCEACTIVE)) { /* Do not change focus if the window is no longer active */ if (ThreadQueue->spwndActive == Wnd) { if (!ThreadQueue->spwndFocus || !Wnd || UserGetAncestor(ThreadQueue->spwndFocus, GA_ROOT) != Wnd) { co_UserSetFocus(Wnd); } } } if (InAAPM) { pti->TIF_flags &= ~TIF_INACTIVATEAPPMSG; pti->pClientInfo->dwTIFlags = pti->TIF_flags; } // FIXME: Used in the menu loop!!! //ThreadQueue->QF_flags |= QF_ACTIVATIONCHANGE; if (Wnd) Wnd->state &= ~WNDS_BEINGACTIVATED; return (ThreadQueue->spwndActive == Wnd); }