Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

input.c File Reference

#include "precomp.h"

Go to the source code of this file.

Defines

#define CANCEL_ACTIVESTATE   0
#define CANCEL_FOCUSSTATE   1
#define CANCEL_CAPTURESTATE   2
#define KEYSTATESIZE   (CBKEYSTATE + CBKEYSTATERECENTDOWN)
#define PQMSG_PLAYBACK   ((PQMSG)1)
#define PATHTAKEN(x)
#define DUMPPATHTAKEN()
#define MA_PASSTHRU   0
#define MA_SKIP   1
#define MA_REHITTEST   2
#define PATHTAKEN(x)
#define PATHTAKEN2(x)
#define PATHTAKEN3(x)
#define DUMPPATHTAKEN()
#define DUMPSUBPATHTAKEN(p, x)
#define CTS_DONOTHING   0
#define CTS_CANCELOLD   1
#define CTS_TRANSFER   2

Functions

BOOL xxxScanSysQueue (PTHREADINFO ptiCurrent, LPMSG lpMsg, PWND pwndFilter, UINT msgMinFilter, UINT msgMaxFilter, DWORD flags, DWORD fsReason)
BOOL xxxReadPostMessage (PTHREADINFO pti, LPMSG lpMsg, PWND pwndFilter, UINT msgMin, UINT msgMax, BOOL fRemoveMsg)
void CleanEventMessage (PQMSG pqmsg)
BOOL xxxWaitMessage (VOID)
void CheckProcessForeground (PTHREADINFO pti)
BOOL xxxInternalGetMessage (LPMSG lpMsg, HWND hwndFilter, UINT msgMin, UINT msgMax, UINT flags, BOOL fGetMessage)
LRESULT xxxDispatchMessage (LPMSG pmsg)
void AdjustForCoalescing (PMLIST pml, HWND hwnd, UINT message)
BOOL _PostMessage (PWND pwnd, UINT message, WPARAM wParam, LPARAM lParam)
BOOL IPostQuitMessage (PTHREADINFO pti, int nExitCode)
BOOL _PostQuitMessage (int nExitCode)
BOOL _PostThreadMessage (PTHREADINFO pti, UINT message, WPARAM wParam, LPARAM lParam)
DWORD _GetMessagePos (VOID)
VOID PostMove (PQ pq)
VOID zzzSetFMouseMoved ()
void CancelForegroundActivate ()
void RestoreForegroundActivate ()
void PostInputMessage (PQ pq, PWND pwnd, UINT message, WPARAM wParam, LPARAM lParam, DWORD time, ULONG_PTR dwExtraInfo)
void WakeSomeone (PQ pq, UINT message, PQMSG pqmsg)
void PostUpdateKeyStateEvent (PQ pq)
void ProcessUpdateKeyStateEvent (PQ pq, CONST PBYTE pbKeyState, CONST PBYTE pbRecentDown)
BOOL PostEventMessage (PTHREADINFO pti, PQ pq, DWORD dwQEvent, PWND pwnd, UINT message, WPARAM wParam, LPARAM lParam)
BOOL CheckOnTop (PTHREADINFO pti, PWND pwndTop, UINT message)
void zzzActiveCursorTracking (PWND pwnd)
PWND GetActiveTrackPwnd (PWND pwnd, Q **ppq)
int xxxActiveWindowTracking (PWND pwnd, UINT uMsg, int iHitTest)
int xxxMouseActivate (PTHREADINFO pti, PWND pwnd, UINT message, WPARAM wParam, LPPOINT lppt, int ht)
void ResetMouseHover (PDESKTOP pdesk, POINT pt)
BOOL QueryTrackMouseEvent (LPTRACKMOUSEEVENT lpTME)
BOOL TrackMouseEvent (LPTRACKMOUSEEVENT lpTME)
PQMSG xxxGetNextSysMsg (PTHREADINFO pti, PQMSG pqmsgPrev, PQMSG pqmsg)
void UpdateKeyState (PQ pq, UINT vk, BOOL fDown)
BOOL EqualMsg (PQMSG pqmsg1, PQMSG pqmsg2)
void xxxSkipSysMsg (PTHREADINFO pti, PQMSG pqmsg)
UINT GetMouseKeyFlags (PQ pq)
VOID IdleTimerProc (VOID)
void zzzWakeInputIdle (PTHREADINFO pti)
void SleepInputIdle (PTHREADINFO pti)
void zzzAddAttachment (PTHREADINFO pti, PQ pqAttach, LPBOOL pfChanged)
void zzzRecalc2 (PQ pqAttach)
void zzzRecalcThreadAttachment ()
void RedistributeInput (PQMSG pqmsgS, PQ pqRedist)
VOID CancelInputState (PTHREADINFO pti, DWORD cmd)
DWORD CheckTransferState (PTHREADINFO pti, PQ pqAttach, LONG offset, BOOL fJoiningForeground)
void zzzAttachToQueue (PTHREADINFO pti, PQ pqAttach, PQ pqJournal, BOOL fJoiningForeground)
BOOL zzzReattachThreads (BOOL fJournalAttach)
BOOL zzzAttachThreadInput (PTHREADINFO ptiAttach, PTHREADINFO ptiAttachTo, BOOL fAttach)
LONG_PTR _SetMessageExtraInfo (LONG_PTR lData)


Define Documentation

#define CANCEL_ACTIVESTATE   0
 

Definition at line 84 of file ntuser/kernel/input.c.

Referenced by CancelInputState(), and zzzAttachToQueue().

#define CANCEL_CAPTURESTATE   2
 

Definition at line 86 of file ntuser/kernel/input.c.

Referenced by CancelInputState(), and zzzAttachToQueue().

#define CANCEL_FOCUSSTATE   1
 

Definition at line 85 of file ntuser/kernel/input.c.

Referenced by CancelInputState(), and zzzAttachToQueue().

#define CTS_CANCELOLD   1
 

Definition at line 5887 of file ntuser/kernel/input.c.

Referenced by CheckTransferState(), and zzzAttachToQueue().

#define CTS_DONOTHING   0
 

Definition at line 5886 of file ntuser/kernel/input.c.

Referenced by CheckTransferState(), and zzzAttachToQueue().

#define CTS_TRANSFER   2
 

Definition at line 5888 of file ntuser/kernel/input.c.

Referenced by CheckTransferState(), and zzzAttachToQueue().

 
#define DUMPPATHTAKEN  ) 
 

 
#define DUMPPATHTAKEN  ) 
 

Referenced by xxxInternalGetMessage(), and xxxScanSysQueue().

#define DUMPSUBPATHTAKEN p,
 ) 
 

Referenced by xxxScanSysQueue().

#define KEYSTATESIZE   (CBKEYSTATE + CBKEYSTATERECENTDOWN)
 

Definition at line 88 of file ntuser/kernel/input.c.

Referenced by PostUpdateKeyStateEvent().

#define MA_PASSTHRU   0
 

Definition at line 2171 of file ntuser/kernel/input.c.

Referenced by xxxActiveWindowTracking(), and xxxMouseActivate().

#define MA_REHITTEST   2
 

Definition at line 2173 of file ntuser/kernel/input.c.

Referenced by xxxMouseActivate(), and xxxScanSysQueue().

#define MA_SKIP   1
 

Definition at line 2172 of file ntuser/kernel/input.c.

Referenced by xxxActiveWindowTracking(), xxxMouseActivate(), and xxxScanSysQueue().

#define PATHTAKEN  ) 
 

#define PATHTAKEN  ) 
 

Referenced by xxxInternalGetMessage(), and xxxScanSysQueue().

#define PATHTAKEN2  ) 
 

Referenced by xxxScanSysQueue().

#define PATHTAKEN3  ) 
 

Referenced by xxxScanSysQueue().

#define PQMSG_PLAYBACK   ((PQMSG)1)
 

Definition at line 94 of file ntuser/kernel/input.c.

Referenced by xxxGetNextSysMsg(), xxxScanSysQueue(), and xxxSkipSysMsg().


Function Documentation

DWORD _GetMessagePos VOID   ) 
 

Definition at line 1205 of file ntuser/kernel/input.c.

References DWORD, PtiCurrent, tagTHREADINFO::ptLast, and SHORT.

Referenced by xxxContScroll(), xxxEndScroll(), xxxMS_TrackMove(), xxxSendHelpMessage(), and xxxSysCommand().

01206 { 01207 PTHREADINFO pti; 01208 01209 pti = PtiCurrent(); 01210 01211 return MAKELONG((SHORT)pti->ptLast.x, (SHORT)pti->ptLast.y); 01212 }

BOOL _PostMessage PWND  pwnd,
UINT  message,
WPARAM  wParam,
LPARAM  lParam
 

Definition at line 981 of file ntuser/kernel/input.c.

References _PostThreadMessage(), AdjustForCoalescing(), AllocQEntry(), BMSG_POSTMSG, BOOL, DO_POST, DWORD, FALSE, GETPTI, HWq, tagQ::idSysLock, tagTHREADINFO::mlPost, NULL, PostUpdateKeyStateEvent(), tagTHREADINFO::pq, PtiCurrent, tagQ::ptiSysLock, PWND_BROADCAST, SetWakeBit(), StoreQMessage(), TESTSYNCONLYMESSAGE, ThreadLockAlwaysWithPti, ThreadUnlock, TRUE, xxxBroadcastMessage(), and xxxDDETrackPostHook().

Referenced by _LockWorkStation(), AbnormalDDEPost(), DestroyTask(), FreeDdeConv(), HighContrastHotKey(), IdleTimerProc(), NotifyLogon(), NtUserEndMenu(), NtUserPostMessage(), PlayEventSound(), PostAccessNotification(), PostShellHookMessages(), RemoteLogoff(), RemoteNtSecurity(), StartScreenSaver(), TrackMouseEvent(), xxxAccessTimeOutTimer(), xxxButtonEvent(), xxxCancelMouseMoveTracking(), xxxCancelTrackingForThread(), xxxDDETrackSendHook(), xxxDDETrackWindowDying(), xxxDefWindowProc(), xxxDestroyThreadInfo(), xxxDoHotKeyStuff(), xxxDWP_ProcessVirtKey(), xxxFlashWindow(), xxxHandleMenuMessages(), xxxImmProcessKey(), xxxMenuWindowProc(), xxxMessageBeep(), xxxMinMaximize(), xxxMNCancel(), xxxMNLoop(), xxxMNStartMenuState(), xxxNextWindow(), xxxOldNextWindow(), xxxProcessEventMessage(), xxxRemoteDisconnect(), xxxRemoteReconnect(), xxxScanSysQueue(), xxxSendBSMtoDesktop(), xxxSysCommand(), xxxSystemParametersInfo(), xxxSystemTimerProc(), xxxTranslateMessage(), and xxxUserPowerEventCalloutWorker().

00986 { 00987 PQMSG pqmsg; 00988 BOOL fPwndUnlock; 00989 BOOL fRet; 00990 DWORD dwPostCode; 00991 TL tlpwnd; 00992 PTHREADINFO pti; 00993 00994 /* 00995 * First check to see if this message takes DWORDs only. If it does not, 00996 * fail the post. Cannot allow an app to post a message with pointers or 00997 * handles in it - this can cause the server to fault and cause other 00998 * problems - such as causing apps in separate address spaces to fault. 00999 * (or even an app in the same address space to fault!) 01000 */ 01001 if (TESTSYNCONLYMESSAGE(message, wParam)) { 01002 RIPERR1(ERROR_MESSAGE_SYNC_ONLY, 01003 RIP_WARNING, 01004 "Invalid parameter \"message\" (%ld) to _PostMessage", 01005 message); 01006 01007 return FALSE; 01008 } 01009 01010 /* 01011 * Is this a BroadcastMsg()? 01012 */ 01013 if (pwnd == PWND_BROADCAST) { 01014 xxxBroadcastMessage(NULL, message, wParam, lParam, BMSG_POSTMSG, NULL); 01015 return TRUE; 01016 } 01017 01018 pti = PtiCurrent(); 01019 01020 /* 01021 * Is this posting to the current thread info? 01022 */ 01023 if (pwnd == NULL) { 01024 return _PostThreadMessage(pti, message, wParam, lParam); 01025 } 01026 01027 fPwndUnlock = FALSE; 01028 if (message >= WM_DDE_FIRST && message <= WM_DDE_LAST) { 01029 ThreadLockAlwaysWithPti(pti, pwnd, &tlpwnd); 01030 dwPostCode = xxxDDETrackPostHook(&message, pwnd, wParam, &lParam, FALSE); 01031 01032 if (dwPostCode != DO_POST) { 01033 ThreadUnlock(&tlpwnd); 01034 return (BOOL)dwPostCode; 01035 } 01036 01037 fPwndUnlock = TRUE; 01038 } 01039 01040 pti = GETPTI(pwnd); 01041 01042 /* 01043 * Check to see if this message is in the multimedia coalescing range. 01044 * If so, see if it can be coalesced with the previous message. 01045 */ 01046 AdjustForCoalescing(&pti->mlPost, HWq(pwnd), message); 01047 01048 /* 01049 * Allocate a key state update event if needed. 01050 */ 01051 if (message >= WM_KEYFIRST && message <= WM_KEYLAST) { 01052 PostUpdateKeyStateEvent(pti->pq); 01053 } 01054 01055 /* 01056 * Put this message on the 'post' list. 01057 */ 01058 fRet = FALSE; 01059 if ((pqmsg = AllocQEntry(&pti->mlPost)) != NULL) { 01060 /* 01061 * Set the QS_POSTMESSAGE bit so the thread knows it has a message. 01062 */ 01063 StoreQMessage(pqmsg, pwnd, message, wParam, lParam, 0, 0, 0); 01064 SetWakeBit(pti, QS_POSTMESSAGE | QS_ALLPOSTMESSAGE); 01065 01066 /* 01067 * If it's a hotkey, set the QS_HOTKEY bit since we have a separate 01068 * bit for those messages. 01069 */ 01070 if (message == WM_HOTKEY) 01071 SetWakeBit(pti, QS_HOTKEY); 01072 01073 fRet = TRUE; 01074 } else { 01075 RIPMSG1(RIP_WARNING, "_PostMessage: Failed to alloc Q entry: target pti=0x%p", 01076 pti); 01077 } 01078 01079 /* 01080 * Are we posting to the thread currently reading from the input queue? 01081 * If so, update idSysLock with this pqmsg so that the input queue will 01082 * not be unlocked until this message is read. 01083 */ 01084 if (pti == pti->pq->ptiSysLock) 01085 pti->pq->idSysLock = (ULONG_PTR)pqmsg; 01086 01087 if (fPwndUnlock) 01088 ThreadUnlock(&tlpwnd); 01089 01090 return fRet; 01091 }

BOOL _PostQuitMessage int  nExitCode  ) 
 

Definition at line 1109 of file ntuser/kernel/input.c.

References BOOL, IPostQuitMessage(), and PtiCurrent.

Referenced by xxxFreeWindow().

01110 { 01111 return IPostQuitMessage(PtiCurrent(), nExitCode); 01112 }

BOOL _PostThreadMessage PTHREADINFO  pti,
UINT  message,
WPARAM  wParam,
LPARAM  lParam
 

Definition at line 1123 of file ntuser/kernel/input.c.

References AdjustForCoalescing(), AllocQEntry(), BOOL, FALSE, tagQ::idSysLock, tagTHREADINFO::mlPost, NULL, tagTHREADINFO::pq, tagQ::ptiSysLock, SetWakeBit(), StoreQMessage(), TESTSYNCONLYMESSAGE, tagTHREADINFO::TIF_flags, TIF_GUITHREADINITIALIZED, TIF_INCLEANUP, and TRUE.

Referenced by _PostMessage(), EndShutdown(), InitiateWin32kCleanup(), NtUserPostThreadMessage(), TerminateConsole(), xxxDoHotKeyStuff(), xxxSysCommand(), and zzzCancelJournalling().

01128 { 01129 PQMSG pqmsg; 01130 01131 if ((pti == NULL) || 01132 !(pti->TIF_flags & TIF_GUITHREADINITIALIZED) || 01133 (pti->TIF_flags & TIF_INCLEANUP)) { 01134 01135 RIPERR0(ERROR_INVALID_THREAD_ID, RIP_VERBOSE, ""); 01136 return FALSE; 01137 } 01138 01139 /* 01140 * First check to see if this message takes DWORDs only. If it does not, 01141 * fail the post. Cannot allow an app to post a message with pointers or 01142 * handles in it - this can cause the server to fault and cause other 01143 * problems - such as causing apps in separate address spaces to fault. 01144 * (or even an app in the same address space to fault!) 01145 */ 01146 if (TESTSYNCONLYMESSAGE(message, wParam)) { 01147 RIPERR1(ERROR_MESSAGE_SYNC_ONLY, 01148 RIP_WARNING, 01149 "Invalid parameter \"message\" (%ld) to _PostThreadMessage", 01150 message); 01151 01152 return FALSE; 01153 } 01154 01155 /* 01156 * Check to see if this message is in the multimedia coalescing range. 01157 * If so, see if it can be coalesced with the previous message. 01158 */ 01159 AdjustForCoalescing(&pti->mlPost, NULL, message); 01160 01161 /* 01162 * Put this message on the 'post' list. 01163 */ 01164 if ((pqmsg = AllocQEntry(&pti->mlPost)) == NULL) { 01165 RIPMSG1(RIP_WARNING, "_PostThreadMessage: Failed to alloc Q entry: Target pti=0x%p", 01166 pti); 01167 return FALSE; 01168 } 01169 01170 /* 01171 * Set the QS_POSTMESSAGE bit so the thread knows it has a message. 01172 */ 01173 StoreQMessage(pqmsg, NULL, message, wParam, lParam, 0, 0, 0); 01174 SetWakeBit(pti, QS_POSTMESSAGE | QS_ALLPOSTMESSAGE); 01175 01176 /* 01177 * If it's a hotkey, set the QS_HOTKEY bit since we have a separate 01178 * bit for those messages. 01179 */ 01180 if (message == WM_HOTKEY) 01181 SetWakeBit(pti, QS_HOTKEY); 01182 01183 /* 01184 * Are we posting to the thread currently reading from the input queue? 01185 * If so, update idSysLock with this pqmsg so that the input queue will 01186 * not be unlocked until this message is read. 01187 */ 01188 if (pti == pti->pq->ptiSysLock) 01189 pti->pq->idSysLock = (ULONG_PTR)pqmsg; 01190 01191 return TRUE; 01192 }

LONG_PTR _SetMessageExtraInfo LONG_PTR  lData  ) 
 

Definition at line 6485 of file ntuser/kernel/input.c.

References tagQ::ExtraInfo, tagTHREADINFO::pq, and PtiCurrent.

06486 { 06487 LONG_PTR lRet; 06488 PTHREADINFO pti = PtiCurrent(); 06489 06490 lRet = pti->pq->ExtraInfo; 06491 pti->pq->ExtraInfo = lData; 06492 return lRet; 06493 }

void AdjustForCoalescing PMLIST  pml,
HWND  hwnd,
UINT  message
 

Definition at line 943 of file ntuser/kernel/input.c.

References CheckMsgFilter, DelQEntry(), tagQMSG::msg, NULL, PMLIST, and tagMLIST::pqmsgWriteLast.

Referenced by _PostMessage(), and _PostThreadMessage().

00947 { 00948 /* 00949 * First see if this message is in that range. 00950 */ 00951 if (!CheckMsgFilter(message, WM_COALESCE_FIRST, WM_COALESCE_LAST) && 00952 (message != WM_TIMECHANGE)) 00953 return; 00954 00955 if (pml->pqmsgWriteLast == NULL) 00956 return; 00957 00958 if (pml->pqmsgWriteLast->msg.message != message) 00959 return; 00960 00961 if (pml->pqmsgWriteLast->msg.hwnd != hwnd) 00962 return; 00963 00964 /* 00965 * The message and hwnd are the same, so delete this message and 00966 * the new one will added later. 00967 */ 00968 DelQEntry(pml, pml->pqmsgWriteLast); 00969 }

void CancelForegroundActivate  ) 
 

Definition at line 1515 of file ntuser/kernel/input.c.

References CLEAR_PUDF, gppiStarting, NULL, tagPROCESSINFO::ppiNext, PUDF_ALLOWFOREGROUNDACTIVATE, and TEST_PUDF.

Referenced by WakeSomeone().

01516 { 01517 PPROCESSINFO ppiT; 01518 01519 if (TEST_PUDF(PUDF_ALLOWFOREGROUNDACTIVATE)) { 01520 01521 for (ppiT = gppiStarting; ppiT != NULL; ppiT = ppiT->ppiNext) { 01522 /* 01523 * Don't cancel activation if the app is being debugged - if 01524 * the debugger stops the application before it has created and 01525 * activated its first window, the app will come up behind all 01526 * others - not what you want when being debugged. 01527 */ 01528 if (!ppiT->Process->DebugPort) { 01529 ppiT->W32PF_Flags &= ~W32PF_ALLOWFOREGROUNDACTIVATE; 01530 TAGMSG1(DBGTAG_FOREGROUND, "CancelForegroundActivate clear W32PF %#p", ppiT); 01531 } 01532 } 01533 01534 CLEAR_PUDF(PUDF_ALLOWFOREGROUNDACTIVATE); 01535 TAGMSG0(DBGTAG_FOREGROUND, "CancelForegroundActivate clear PUDF"); 01536 } 01537 }

VOID CancelInputState PTHREADINFO  pti,
DWORD  cmd
 

Definition at line 5671 of file ntuser/kernel/input.c.

References BWL_ENUMLIST, CANCEL_ACTIVESTATE, CANCEL_CAPTURESTATE, CANCEL_FOCUSSTATE, tagAAS::fActivating, FALSE, tagMENUSTATE::fInDoDragDrop, tagMENUSTATE::fModelessMenu, tagAAS::fQueueNotify, GETPTI, IS_IME_ENABLED, NULL, tagTHREADINFO::pMenuState, tagTHREADINFO::pq, PtiCurrent, tagAAS::ptiNotify, QF_CAPTURELOCKED, tagQ::QF_flags, QueueNotifyMessage(), tagQ::spwndActive, tagQ::spwndCapture, tagQ::spwndFocus, TestWF, ThreadLockWithPti, ThreadUnlock, tagAAS::tidActDeact, TIDq, TRUE, Unlock, UnlockCaptureWindow(), VOID(), WFMINIMIZED, WNDENUMPROC_PWND, xxxActivateApp(), xxxFocusSetInputContext(), and xxxInternalEnumWindow().

Referenced by zzzAttachToQueue().

05674 { 05675 PTHREADINFO ptiCurrent = PtiCurrent(); 05676 PWND pwndT; 05677 TL tlpwndT; 05678 TL tlpwndChild; 05679 AAS aas; 05680 05681 /* 05682 * In all cases, do not leave do any send messages or any callbacks! 05683 * This is because this code is called from 05684 * SetWindowsHook(WH_JOURNALPLAYBACK | WH_JOURNALRECORD). No app currently 05685 * calling this routine expects to be called before this routine returns. 05686 * (If you do callback before it returns, you'll break at least Access 05687 * for Windows). - scottlu 05688 */ 05689 switch (cmd) { 05690 case CANCEL_ACTIVESTATE: 05691 /* 05692 * Active state. 05693 */ 05694 pwndT = pti->pq->spwndActive; 05695 ThreadLockWithPti(ptiCurrent, pwndT, &tlpwndT); 05696 05697 QueueNotifyMessage(pwndT, WM_NCACTIVATE, FALSE, 0); 05698 QueueNotifyMessage(pwndT, WM_ACTIVATE, 05699 MAKELONG(WA_INACTIVE, TestWF(pwndT, WFMINIMIZED)), 05700 0); 05701 05702 if (pwndT == pti->pq->spwndActive) 05703 Unlock(&pti->pq->spwndActive); 05704 05705 aas.ptiNotify = GETPTI(pwndT); 05706 aas.tidActDeact = TIDq(GETPTI(pwndT)); 05707 aas.fActivating = FALSE; 05708 aas.fQueueNotify = TRUE; 05709 05710 /* 05711 * Even though this in an xxx call, it does NOT leave any critical 05712 * sections (because fQueueNotify is TRUE). 05713 */ 05714 ThreadLockWithPti(ptiCurrent, GETPTI(pwndT)->rpdesk->pDeskInfo->spwnd->spwndChild, &tlpwndChild); 05715 xxxInternalEnumWindow(GETPTI(pwndT)->rpdesk->pDeskInfo->spwnd->spwndChild, 05716 (WNDENUMPROC_PWND)xxxActivateApp, (LPARAM)&aas, BWL_ENUMLIST); 05717 ThreadUnlock(&tlpwndChild); 05718 05719 ThreadUnlock(&tlpwndT); 05720 break; 05721 05722 case CANCEL_FOCUSSTATE: 05723 /* 05724 * Focus state. 05725 */ 05726 pwndT = pti->pq->spwndFocus; 05727 ThreadLockWithPti(ptiCurrent, pwndT, &tlpwndT); 05728 05729 QueueNotifyMessage(pwndT, WM_KILLFOCUS, 0, 0); 05730 #ifdef FE_IME 05731 if (IS_IME_ENABLED()) { 05732 /* 05733 * Even though this in an xxx call, it does NOT leave any 05734 * critical section (because fQueueMsg is TRUE). 05735 */ 05736 xxxFocusSetInputContext(pwndT, FALSE, TRUE); 05737 } 05738 #endif 05739 if (pwndT == pti->pq->spwndFocus) 05740 Unlock(&pti->pq->spwndFocus); 05741 05742 ThreadUnlock(&tlpwndT); 05743 break; 05744 05745 case CANCEL_CAPTURESTATE: 05746 /* 05747 * Capture state. 05748 */ 05749 05750 /* 05751 * We shouldn't be nuking the capture of a modal menu mode. 05752 */ 05753 UserAssert((pti->pMenuState == NULL) 05754 || pti->pMenuState->fModelessMenu 05755 || pti->pMenuState->fInDoDragDrop); 05756 05757 pti->pq->QF_flags &= ~QF_CAPTURELOCKED; 05758 pwndT = pti->pq->spwndCapture; 05759 ThreadLockWithPti(ptiCurrent, pwndT, &tlpwndT); 05760 05761 QueueNotifyMessage(pwndT, WM_CANCELMODE, 0, 0); 05762 if (pwndT == pti->pq->spwndCapture) 05763 UnlockCaptureWindow(pti->pq); 05764 05765 ThreadUnlock(&tlpwndT); 05766 break; 05767 } 05768 05769 return; 05770 }

BOOL CheckOnTop PTHREADINFO  pti,
PWND  pwndTop,
UINT  message
 

Definition at line 2148 of file ntuser/kernel/input.c.

References _GetWindow(), BOOL, CalcForegroundInsertAfter(), FALSE, tagTHREADINFO::pq, PWND_TOP, tagQ::spwndActive, TestWF, WEFTOPMOST, and xxxSetWindowPos().

Referenced by xxxMouseActivate().

02149 { 02150 if (pwndTop != pti->pq->spwndActive) 02151 return FALSE; 02152 02153 switch (message) { 02154 case WM_LBUTTONDOWN: 02155 case WM_RBUTTONDOWN: 02156 case WM_MBUTTONDOWN: 02157 case WM_XBUTTONDOWN: 02158 if ( TestWF(pwndTop, WEFTOPMOST) 02159 || (_GetWindow(pwndTop, GW_HWNDPREV) != CalcForegroundInsertAfter(pwndTop))) { 02160 02161 return xxxSetWindowPos(pwndTop, PWND_TOP, 0, 0, 0, 0, 02162 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); 02163 } 02164 break; 02165 } 02166 02167 return FALSE; 02168 }

void CheckProcessForeground PTHREADINFO  pti  ) 
 

Definition at line 155 of file ntuser/kernel/input.c.

References _CLIENTINFO::cSpins, _CLIENTINFO::dwTIFlags, gppiWantForegroundPriority, NULL, tagTHREADINFO::pClientInfo, tagTHREADINFO::ppi, tagPROCESSINFO::ptiList, tagTHREADINFO::ptiSibling, SetForegroundPriority(), tagTHREADINFO::TIF_flags, TIF_SPINNING, and TRUE.

Referenced by xxxGetInputEvent(), xxxMsgWaitForMultipleObjects(), xxxReadPostMessage(), xxxScanSysQueue(), and xxxSleepThread().

00157 { 00158 PTHREADINFO ptiT; 00159 00160 /* 00161 * Check to see if we need to move this process into foreground 00162 * priority. 00163 */ 00164 pti->pClientInfo->cSpins = 0; 00165 pti->TIF_flags &= ~TIF_SPINNING; 00166 pti->pClientInfo->dwTIFlags = pti->TIF_flags; 00167 00168 if (pti->ppi->W32PF_Flags & W32PF_FORCEBACKGROUNDPRIORITY) { 00169 /* 00170 * See if any thread of this process is spinning. If none 00171 * are, we can remove the force to background. 00172 */ 00173 for (ptiT = pti->ppi->ptiList; ptiT != NULL; ptiT = ptiT->ptiSibling) { 00174 if (ptiT->TIF_flags & TIF_SPINNING) 00175 return; 00176 } 00177 00178 pti->ppi->W32PF_Flags &= ~W32PF_FORCEBACKGROUNDPRIORITY; 00179 if (pti->ppi == gppiWantForegroundPriority) { 00180 SetForegroundPriority(pti, TRUE); 00181 } 00182 } 00183 }

DWORD CheckTransferState PTHREADINFO  pti,
PQ  pqAttach,
LONG  offset,
BOOL  fJoiningForeground
 

Definition at line 5890 of file ntuser/kernel/input.c.

References BYTE, CTS_CANCELOLD, CTS_DONOTHING, CTS_TRANSFER, DWORD, GETPTI, gpqForeground, NULL, and tagTHREADINFO::pq.

Referenced by zzzAttachToQueue().

05895 { 05896 PWND pwndOld, pwndNew, pwndForegroundState; 05897 05898 /* 05899 * return 0: do nothing. 05900 * return 1: cancel the old state. 05901 * return 2: transfer the old state to the new state 05902 */ 05903 pwndOld = *(PWND *)(((BYTE *)pti->pq) + offset); 05904 pwndNew = *(PWND *)(((BYTE *)pqAttach) + offset); 05905 05906 /* 05907 * Make sure the old state even exists, and that the old state is 05908 * owned by this thread. If not, nothing happens. 05909 */ 05910 if (pwndOld == NULL || GETPTI(pwndOld) != pti) 05911 return CTS_DONOTHING; 05912 05913 /* 05914 * If the new state already exists, cancel the old state. 05915 */ 05916 if (pwndNew != NULL) 05917 return CTS_CANCELOLD; 05918 05919 /* 05920 * Transfer this old state if this thread is not joining the foreground. 05921 */ 05922 if (gpqForeground == NULL || !fJoiningForeground) 05923 return CTS_TRANSFER; 05924 05925 /* 05926 * We're joining the foreground - only transfer the old state if we own 05927 * that foreground state or if there is no foreground state. 05928 */ 05929 pwndForegroundState = *(PWND *)(((BYTE *)gpqForeground) + offset); 05930 if (pwndForegroundState == NULL || pwndOld == pwndForegroundState) 05931 return CTS_TRANSFER; 05932 05933 /* 05934 * We're joining the foreground but we didn't set that foreground state. 05935 * Don't allow the transfer of that state. 05936 */ 05937 return CTS_CANCELOLD; 05938 }

void CleanEventMessage PQMSG  pqmsg  ) 
 

Definition at line 3068 of file queue.c.

References DestroyNotify(), tagQMSG::dwQEvent, tagASYNCSENDMSG::lParam, tagQMSG::msg, PASYNCSENDMSG, PBYTE, QEVENT_ASYNCSENDMSG, QEVENT_NOTIFYWINEVENT, QEVENT_SETWINDOWPOS, QEVENT_UPDATEKEYSTATE, and UserDeleteAtom().

Referenced by DestroyThreadsMessages(), FreeMessageList(), RedistributeInput(), xxxProcessEventMessage(), and xxxScanSysQueue().

03070 { 03071 PASYNCSENDMSG pmsg; 03072 03073 /* 03074 * Certain special messages on the INPUT queue have associated 03075 * bits of memory that need to be freed. 03076 */ 03077 switch (pqmsg->dwQEvent) { 03078 case QEVENT_SETWINDOWPOS: 03079 UserFreePool((PSMWP)pqmsg->msg.wParam); 03080 break; 03081 03082 case QEVENT_UPDATEKEYSTATE: 03083 UserFreePool((PBYTE)pqmsg->msg.wParam); 03084 break; 03085 03086 case QEVENT_NOTIFYWINEVENT: 03087 DestroyNotify((PNOTIFY)pqmsg->msg.lParam); 03088 break; 03089 03090 case QEVENT_ASYNCSENDMSG: 03091 pmsg = (PASYNCSENDMSG)pqmsg->msg.wParam; 03092 UserDeleteAtom((ATOM)pmsg->lParam); 03093 UserFreePool(pmsg); 03094 break; 03095 } 03096 }

BOOL EqualMsg PQMSG  pqmsg1,
PQMSG  pqmsg2
 

Definition at line 2953 of file ntuser/kernel/input.c.

References BOOL, FALSE, tagQMSG::msg, tagQMSG::pti, and TRUE.

Referenced by xxxSkipSysMsg().

02954 { 02955 if (pqmsg1->msg.hwnd != pqmsg2->msg.hwnd || 02956 pqmsg1->msg.message != pqmsg2->msg.message) 02957 return FALSE; 02958 02959 /* 02960 * This might be a coalesced WM_MOUSEMOVE 02961 */ 02962 if (pqmsg1->msg.message == WM_MOUSEMOVE) 02963 return TRUE; 02964 02965 if (pqmsg1->pti != pqmsg2->pti || 02966 pqmsg1->msg.time != pqmsg2->msg.time) 02967 return FALSE; 02968 02969 return TRUE; 02970 }

PWND GetActiveTrackPwnd PWND  pwnd,
Q **  ppq
 

Definition at line 2251 of file ntuser/kernel/input.c.

References CheckCritIn, DWP_GetEnabledPopup(), GETPTI, gpqForeground, tagWND::head, IsModelessMenuNotificationWindow(), NULL, tagQ::spwndActive, tagWND::spwndParent, TestWF, TestwndChild, WFDISABLED, and WFVISIBLE.

Referenced by xxxActiveWindowTracking(), xxxSystemTimerProc(), xxxTrackMouseMove(), and zzzActiveCursorTracking().

02252 { 02253 PWND pwndActivate; 02254 Q *pq; 02255 02256 CheckCritIn(); 02257 pwndActivate = pwnd; 02258 02259 /* 02260 * Find the top parent 02261 */ 02262 while (TestwndChild(pwndActivate)) { 02263 pwndActivate = pwndActivate->spwndParent; 02264 } 02265 02266 /* 02267 * If disabled, get a enabled popup owned by it. 02268 */ 02269 if (TestWF(pwndActivate, WFDISABLED)) { 02270 /* 02271 * This is what we do elsewhere when someone clicks on a 02272 * disabled non-active window. It might be cheaper to check 02273 * pwnd->spwndLastActive first (we might need to walk up 02274 * the owner chain though, as this is where we set spwndLastAcitve 02275 * when activating a new window. see xxxActivateThisWindow). 02276 * But let's do the same here; this should be fixed/improved 02277 * in DWP_GetEnabledPopup anyway. There might be a reason 02278 * why we don't grab spwndLastActive if OK.... perhaps it has 02279 * something to do with nested owner windows 02280 */ 02281 pwndActivate = DWP_GetEnabledPopup(pwndActivate); 02282 } 02283 02284 /* 02285 * Bail if we didn't find a visible window 02286 */ 02287 if ((pwndActivate == NULL) || !TestWF(pwndActivate, WFVISIBLE)) { 02288 return NULL; 02289 } 02290 02291 /* 02292 * If already active in the foreground queue, nothing to do 02293 * Don't activate the modeless menu notification window (it would 02294 * dismiss the menu) 02295 */ 02296 pq = GETPTI(pwndActivate)->pq; 02297 if ((pq == gpqForeground) 02298 && ((pwndActivate == pq->spwndActive) 02299 || IsModelessMenuNotificationWindow(pwndActivate))) { 02300 02301 return NULL; 02302 } 02303 02304 /* 02305 * Don't activate the shell window. 02306 */ 02307 if (pwndActivate == pwndActivate->head.rpdesk->pDeskInfo->spwndShell) { 02308 return NULL; 02309 } 02310 02311 /* 02312 * Return the queue if requested 02313 */ 02314 if (ppq != NULL) { 02315 *ppq = pq; 02316 } 02317 02318 return pwndActivate; 02319 }

UINT GetMouseKeyFlags PQ  pq  ) 
 

Definition at line 3267 of file ntuser/kernel/input.c.

References TestKeyStateDown, and UINT.

Referenced by xxxDefWindowProc(), xxxProcessEventMessage(), xxxScanSysQueue(), and xxxSystemTimerProc().

03269 { 03270 UINT wParam = 0; 03271 03272 if (TestKeyStateDown(pq, VK_LBUTTON)) 03273 wParam |= MK_LBUTTON; 03274 if (TestKeyStateDown(pq, VK_RBUTTON)) 03275 wParam |= MK_RBUTTON; 03276 if (TestKeyStateDown(pq, VK_MBUTTON)) 03277 wParam |= MK_MBUTTON; 03278 if (TestKeyStateDown(pq, VK_XBUTTON1)) 03279 wParam |= MK_XBUTTON1; 03280 if (TestKeyStateDown(pq, VK_XBUTTON2)) 03281 wParam |= MK_XBUTTON2; 03282 if (TestKeyStateDown(pq, VK_SHIFT)) 03283 wParam |= MK_SHIFT; 03284 if (TestKeyStateDown(pq, VK_CONTROL)) 03285 wParam |= MK_CONTROL; 03286 03287 return wParam; 03288 }

VOID IdleTimerProc VOID   ) 
 

Definition at line 5120 of file ntuser/kernel/input.c.

References _PostMessage(), CheckCritIn, CMSHUNGAPPTIMEOUT, tagLASTINPUT::dwFlags, DWORD, FALSE, FHungApp(), GETPTI, giLowPowerTimeOutMs, giPowerOffTimeOutMs, giScreenSaveTimeOutMs, glinp, gppiScreenSaver, gpqForeground, IsTimeFromLastInput(), L, LINP_LOWPOWER, LINP_POWEROFF, LOWPOWER_PHASE, NULL, POWEROFF_PHASE, tagPROCESSINFO::ptiMainThread, SetForegroundPriorityProcess(), tagQ::spwndActive, StartScreenSaver(), TestAsyncKeyStateDown, TRUE, and VOID().

Referenced by xxxHungAppDemon().

05121 { 05122 05123 CheckCritIn(); 05124 05125 if ( (TestAsyncKeyStateDown(VK_LBUTTON)) || 05126 (TestAsyncKeyStateDown(VK_RBUTTON)) || 05127 (TestAsyncKeyStateDown(VK_MBUTTON)) || 05128 (TestAsyncKeyStateDown(VK_XBUTTON1)) || 05129 (TestAsyncKeyStateDown(VK_XBUTTON2))) { 05130 05131 return; 05132 } 05133 05134 05135 if (giScreenSaveTimeOutMs > 0) { 05136 05137 if (IsTimeFromLastInput((DWORD)(giScreenSaveTimeOutMs))) { 05138 05139 if (gppiScreenSaver != NULL) { 05140 05141 if (!(gppiScreenSaver->W32PF_Flags & W32PF_IDLESCREENSAVER)) { 05142 /* 05143 * Bump the priority of the screen saver down to idle. 05144 */ 05145 gppiScreenSaver->W32PF_Flags |= W32PF_IDLESCREENSAVER; 05146 SetForegroundPriorityProcess(gppiScreenSaver, gppiScreenSaver->ptiMainThread, TRUE); 05147 } 05148 } else { 05149 /* 05150 * Tell the system that it needs to bring up a screen saver. 05151 * 05152 * Carefull with the case when the active window is hung. If this 05153 * is the case the screen saver won't be started by winlogon because 05154 * DefWindowProc won't call StartScreenSaver(FALSE). 05155 */ 05156 if ((gpqForeground != NULL) && 05157 (gpqForeground->spwndActive != NULL) && 05158 !FHungApp(GETPTI(gpqForeground->spwndActive), CMSHUNGAPPTIMEOUT)) { 05159 05160 /* 05161 * Tell winlogon to start the screen saver if we have a secure 05162 * screen saver. In case we do have a secure one, the next PostMessage 05163 * will be ignored in winlogon. 05164 */ 05165 StartScreenSaver(TRUE); 05166 _PostMessage(gpqForeground->spwndActive, WM_SYSCOMMAND, SC_SCREENSAVE, 0L); 05167 } else { 05168 StartScreenSaver(FALSE); 05169 } 05170 } 05171 } 05172 } 05173 05174 if ((giLowPowerTimeOutMs > 0) && ((glinp.dwFlags & LINP_LOWPOWER) == 0)) { 05175 if (IsTimeFromLastInput((DWORD)(giLowPowerTimeOutMs))) { 05176 if ((gpqForeground != NULL) && (gpqForeground->spwndActive != NULL)) { 05177 _PostMessage(gpqForeground->spwndActive, WM_SYSCOMMAND, SC_MONITORPOWER, LOWPOWER_PHASE); 05178 } 05179 } 05180 } 05181 05182 if ((giPowerOffTimeOutMs > 0) && ((glinp.dwFlags & LINP_POWEROFF) == 0)) { 05183 if (IsTimeFromLastInput((DWORD)(giPowerOffTimeOutMs))) { 05184 if ((gpqForeground != NULL) && (gpqForeground->spwndActive != NULL)) { 05185 _PostMessage(gpqForeground->spwndActive, WM_SYSCOMMAND, SC_MONITORPOWER, POWEROFF_PHASE); 05186 } 05187 } 05188 } 05189 05190 }

BOOL IPostQuitMessage PTHREADINFO  pti,
int  nExitCode
 

Definition at line 1102 of file ntuser/kernel/input.c.

References BOOL, tagTHREADINFO::cQuit, tagTHREADINFO::exitCode, SetWakeBit(), and TRUE.

Referenced by _PostQuitMessage(), and xxxSwitchDesktop().

01103 { 01104 pti->cQuit = 1; 01105 pti->exitCode = nExitCode; 01106 SetWakeBit(pti, QS_POSTMESSAGE | QS_ALLPOSTMESSAGE); 01107 return TRUE; 01108 }

BOOL PostEventMessage PTHREADINFO  pti,
PQ  pq,
DWORD  dwQEvent,
PWND  pwnd,
UINT  message,
WPARAM  wParam,
LPARAM  lParam
 

Definition at line 2068 of file ntuser/kernel/input.c.

References AllocQEntry(), BOOL, CheckCritIn, FALSE, tagQ::mlInput, NULL, tagQ::ptiKeyboard, tagQ::ptiMouse, SetWakeBit(), StoreQMessage(), StoreQMessagePti(), tagTHREADINFO::TIF_flags, TIF_INCLEANUP, and TRUE.

Referenced by _ShowWindowAsync(), AsyncWindowPos(), FKActivationTimer(), PostAccessibility(), PostRitSound(), PostUpdateKeyStateEvent(), xxxButtonEvent(), xxxFW_DestroyAllChildren(), xxxKeyEvent(), xxxMinimizeHungWindow(), xxxProcessEventMessage(), xxxProcessNotifyWinEvent(), xxxSetForegroundWindow(), xxxSwitchToThisWindow(), xxxTrackMouseMove(), zzzReattachThreads(), and zzzSetFMouseMoved().

02076 { 02077 PQMSG pqmsgEvent; 02078 02079 CheckCritIn(); 02080 02081 /* 02082 * If the thread is in cleanup, then it's possible the queue has 02083 * already been removed for this thread. If this is the case, then 02084 * we should fail to post the event to a dying thread. 02085 */ 02086 if (pti && (pti->TIF_flags & TIF_INCLEANUP)) 02087 return FALSE; 02088 02089 if ((pqmsgEvent = AllocQEntry(&pq->mlInput)) == NULL) 02090 return FALSE; 02091 02092 StoreQMessage(pqmsgEvent, pwnd, message, wParam, lParam, 0, dwQEvent, 0); 02093 02094 StoreQMessagePti(pqmsgEvent, pti); 02095 02096 /* 02097 * Let this thread know it has an event message to process. 02098 */ 02099 if (pti == NULL) { 02100 UserAssert(pti); 02101 SetWakeBit(pq->ptiMouse, QS_EVENTSET); 02102 SetWakeBit(pq->ptiKeyboard, QS_EVENTSET); 02103 } else { 02104 SetWakeBit(pti, QS_EVENTSET); 02105 } 02106 02107 return TRUE; 02108 }

void PostInputMessage PQ  pq,
PWND  pwnd,
UINT  message,
WPARAM  wParam,
LPARAM  lParam,
DWORD  time,
ULONG_PTR  dwExtraInfo
 

Definition at line 1575 of file ntuser/kernel/input.c.

References AllocQEntry(), DelQEntry(), tagQ::idSysPeek, tagQ::mlInput, tagQMSG::msg, NULL, PostUpdateKeyStateEvent(), tagMLIST::pqmsgWriteLast, tagQ::QF_flags, QF_UPDATEKEYSTATE, StoreQMessage(), and WakeSomeone().

Referenced by PostMove(), xxxButtonEvent(), xxxDoButtonEvent(), and xxxKeyEvent().

01583 { 01584 PQMSG pqmsgInput, pqmsgPrev; 01585 short sWheelDelta; 01586 01587 /* 01588 * Grab the last written message before we start allocing new ones, 01589 * so we're sure to point to the correct message. 01590 */ 01591 pqmsgPrev = pq->mlInput.pqmsgWriteLast; 01592 01593 /* 01594 * Allocate a key state update event if needed. 01595 */ 01596 if (pq->QF_flags & QF_UPDATEKEYSTATE) { 01597 PostUpdateKeyStateEvent(pq); 01598 } 01599 01600 /* 01601 * We want to coalesce sequential WM_MOUSEMOVE and WM_MOUSEWHEEL. 01602 * WM_MOUSEMOVEs are coalesced by just storing the most recent 01603 * event over the last one. 01604 * WM_MOUSEWHEELs also add up the wheel rolls. 01605 */ 01606 if (pqmsgPrev != NULL && 01607 pqmsgPrev->msg.message == message && 01608 (message == WM_MOUSEMOVE || message == WM_MOUSEWHEEL)) { 01609 01610 if (message == WM_MOUSEWHEEL) { 01611 sWheelDelta = (short)HIWORD(wParam) + (short)HIWORD(pqmsgPrev->msg.wParam); 01612 01613 #if 0 01614 /* 01615 * LATER: We can't remove a wheel message with zero delta 01616 * unless we know it hasn't been peeked. Ideally, 01617 * we would check idsyspeek for this, but we're too close 01618 * to ship and idsyspeek is too fragile. Consider also 01619 * checking to see if mouse move messages have been peeked. 01620 */ 01621 01622 if (sWheelDelta == 0) { 01623 if ((PQMSG)pq->idSysPeek == pqmsgPrev) { 01624 RIPMSG0(RIP_VERBOSE, 01625 "Coalescing of mouse wheel messages causing " 01626 "idSysPeek to be reset to 0"); 01627 01628 pq->idSysPeek = 0; 01629 } 01630 01631 DelQEntry(&pq->mlInput, pqmsgPrev); 01632 return; 01633 } 01634 #endif 01635 01636 wParam = MAKEWPARAM(LOWORD(wParam), sWheelDelta); 01637 } 01638 01639 StoreQMessage(pqmsgPrev, pwnd, message, wParam, lParam, time, 0, dwExtraInfo); 01640 WakeSomeone(pq, message, pqmsgPrev); 01641 01642 return; 01643 } 01644 01645 /* 01646 * Fill in pqmsgInput. 01647 */ 01648 pqmsgInput = AllocQEntry(&pq->mlInput); 01649 if (pqmsgInput != NULL) { 01650 StoreQMessage(pqmsgInput, pwnd, message, wParam, lParam, time, 0, dwExtraInfo); 01651 WakeSomeone(pq, message, pqmsgInput); 01652 } 01653 }

VOID PostMove PQ  pq  ) 
 

Definition at line 1254 of file ntuser/kernel/input.c.

References CheckCritIn, gdwMouseMoveExtraInfo, gdwMouseMoveTimeStamp, gpsi, NtGetTickCount(), NULL, PostInputMessage(), tagQ::QF_flags, QF_MOUSEMOVED, SHORT, and VOID().

Referenced by xxxButtonEvent(), xxxGetNextSysMsg(), and xxxKeyEvent().

01256 { 01257 #ifdef REDIRECTION 01258 POINT pt; 01259 #endif // REDIRECTION 01260 01261 CheckCritIn(); 01262 01263 /* 01264 * set gdwMouseMoveTimeStamp to 0 after posting the move so 01265 * subsequent calls to SetFMouseMove doesn't use the same value 01266 * of gdwMouseMoveTimeStamp. Bug 74508. 01267 */ 01268 if (gdwMouseMoveTimeStamp == 0) { 01269 gdwMouseMoveTimeStamp = NtGetTickCount(); 01270 } 01271 01272 #ifdef REDIRECTION 01273 01274 PopMouseMove(pq, &pt); 01275 01276 PostInputMessage(pq, NULL, WM_MOUSEMOVE, 0, 01277 MAKELONG((SHORT)pt.x, (SHORT)pt.y), 01278 gdwMouseMoveTimeStamp, gdwMouseMoveExtraInfo); 01279 #else 01280 PostInputMessage(pq, NULL, WM_MOUSEMOVE, 0, 01281 MAKELONG((SHORT)gpsi->ptCursor.x, (SHORT)gpsi->ptCursor.y), 01282 gdwMouseMoveTimeStamp, gdwMouseMoveExtraInfo); 01283 #endif // REDIRECTION 01284 01285 gdwMouseMoveTimeStamp = 0; 01286 01287 pq->QF_flags &= ~QF_MOUSEMOVED; 01288 }

void PostUpdateKeyStateEvent PQ  pq  ) 
 

Definition at line 1874 of file ntuser/kernel/input.c.

References tagQ::afKeyRecentDown, BYTE, CBKEYSTATE, CBKEYSTATERECENTDOWN, tagMLIST::cMsgs, DWORD, tagQMSG::dwQEvent, tagCLIENTTHREADINFO::fsWakeBits, gafAsyncKeyState, gptiRit, KEYSTATESIZE, tagQ::mlInput, tagQMSG::msg, NULL, PBYTE, tagTHREADINFO::pcti, PostEventMessage(), tagQMSG::pqmsgNext, tagMLIST::pqmsgRead, tagMLIST::pqmsgWriteLast, ProcessUpdateKeyStateEvent(), tagQ::ptiKeyboard, tagQ::ptiMouse, QEVENT_UPDATEKEYSTATE, tagQ::QF_flags, QF_UPDATEKEYSTATE, and SetWakeBit().

Referenced by _PostMessage(), NtUserGetKeyState(), PostInputMessage(), UpdateAsyncKeyState(), and xxxSwitchDesktop().

01876 { 01877 BYTE *pb; 01878 PQMSG pqmsg; 01879 01880 if (!(pq->QF_flags & QF_UPDATEKEYSTATE)) 01881 return; 01882 01883 /* 01884 * Exclude the RIT - it's queue is never read, so don't waste memory 01885 */ 01886 if (pq->ptiKeyboard == gptiRit) { 01887 return; 01888 } 01889 01890 /* 01891 * If there's no mousebutton or keystroke input pending, process the 01892 * UpdateKeyState Event now: thus saving memory allocation and giving 01893 * applications the correct KeyState immediately. 01894 * NOTE: There may be event/activation msgs in pq->mlInput that don't 01895 * affect keystate, so I'd like to just test QS_KEY | QS_MOUSEBUTTON 01896 * specifically, instead of the cMsgss. However, sometimes there are 01897 * keystroke or mousebutton msgs in the q without those bits set! - IanJa 01898 */ 01899 if (pq->mlInput.cMsgs == 0) { 01900 ProcessUpdateKeyStateEvent(pq, gafAsyncKeyState, pq->afKeyRecentDown); 01901 goto SyncQueue; 01902 } 01903 #if DBG 01904 else if ((!pq->ptiKeyboard || !(pq->ptiKeyboard->pcti->fsWakeBits & QS_KEY)) && 01905 (!pq->ptiMouse || !(pq->ptiMouse->pcti->fsWakeBits & QS_MOUSEBUTTON))) { 01906 /* 01907 * See if there are any key or mousebutton messages that aren't 01908 * indicated by QS_KEY or QS_MOUSEBUTTON bits. 01909 */ 01910 PQMSG pqmsgT; 01911 for (pqmsgT = pq->mlInput.pqmsgRead; pqmsgT; pqmsgT = pqmsgT->pqmsgNext) { 01912 if (pqmsgT->msg.message >= WM_KEYFIRST && pqmsgT->msg.message <= WM_KEYLAST) { 01913 TAGMSG1(DBGTAG_InputWithoutQS, 01914 "PostUpdateKeyStateEvent() pushing in front of a keystroke: Q %#p", pq); 01915 } else if (pqmsgT->msg.message >= WM_LBUTTONDOWN && pqmsgT->msg.message <= WM_XBUTTONDBLCLK) { 01916 TAGMSG1(DBGTAG_InputWithoutQS, 01917 "PostUpdateKeyStateEvent() pushing in front of a mousebutton: Q %#p", pq); 01918 } 01919 } 01920 } 01921 #endif 01922 01923 UserAssert(pq->mlInput.pqmsgWriteLast != NULL); 01924 01925 /* 01926 * If the last input message is an UPDATEKEYSTATE event, coalesce with it. 01927 * (Prevents big memory leaks on apps that don't read input messages) 01928 */ 01929 pqmsg = pq->mlInput.pqmsgWriteLast; 01930 if (pqmsg->dwQEvent == QEVENT_UPDATEKEYSTATE) { 01931 int i; 01932 DWORD *pdw; 01933 01934 pb = (PBYTE)(pqmsg->msg.wParam); 01935 pdw = (DWORD *) (pb + CBKEYSTATE); 01936 01937 /* 01938 * Copy in the new key state 01939 */ 01940 RtlCopyMemory(pb, gafAsyncKeyState, CBKEYSTATE); 01941 01942 /* 01943 * Or in the recent key down state (DWORD at a time) 01944 */ 01945 #if (CBKEYSTATERECENTDOWN % 4) != 0 01946 #error "CBKEYSTATERECENTDOWN assumed to be an integral number of DWORDs" 01947 #endif 01948 for (i = 0; i < CBKEYSTATERECENTDOWN / sizeof(*pdw); i++) { 01949 *pdw++ |= ((DWORD *)(pq->afKeyRecentDown))[i]; 01950 } 01951 01952 /* 01953 * Set QS_EVENTSET as in PostEventMessage, although this is 01954 * usually, but not always already set 01955 */ 01956 SetWakeBit(pq->ptiKeyboard, QS_EVENTSET); 01957 goto SyncQueue; 01958 } 01959 01960 /* 01961 * Make a copy of the async key state buffer, point to it, and add an 01962 * event to the end of the input queue. 01963 */ 01964 if ((pb = UserAllocPool(KEYSTATESIZE, TAG_KBDSTATE)) == NULL) { 01965 return; 01966 } 01967 01968 RtlCopyMemory(pb, gafAsyncKeyState, CBKEYSTATE); 01969 RtlCopyMemory(pb + CBKEYSTATE, pq->afKeyRecentDown, CBKEYSTATERECENTDOWN); 01970 01971 if (!PostEventMessage(pq->ptiKeyboard, pq, QEVENT_UPDATEKEYSTATE, 01972 NULL, 0 , (WPARAM)pb, 0)) { 01973 UserFreePool(pb); 01974 return; 01975 } 01976 01977 /* 01978 * The key state of the queue is input-synchronized with the user. Erase 01979 * all 'recent down' flags. 01980 */ 01981 SyncQueue: 01982 RtlZeroMemory(pq->afKeyRecentDown, CBKEYSTATERECENTDOWN); 01983 pq->QF_flags &= ~QF_UPDATEKEYSTATE; 01984 }

void ProcessUpdateKeyStateEvent PQ  pq,
CONST PBYTE  pbKeyState,
CONST PBYTE  pbRecentDown
 

Definition at line 1996 of file ntuser/kernel/input.c.

References BYTE, CBKEYSTATERECENTDOWN, ClearKeyStateDown, ClearKeyStateToggle, gafAsyncKeyState, gpsi, SetKeyStateDown, SetKeyStateToggle, TestKeyDownBit, TestKeyRecentDownBit, and TestKeyToggleBit.

Referenced by PostUpdateKeyStateEvent(), and xxxProcessEventMessage().

02000 { 02001 int i, j; 02002 BYTE *pbChange; 02003 int vk; 02004 02005 pbChange = pbRecentDown; 02006 for (i = 0; i < CBKEYSTATERECENTDOWN; i++, pbChange++) { 02007 02008 /* 02009 * Find some keys that have changed. 02010 */ 02011 if (*pbChange == 0) 02012 continue; 02013 02014 /* 02015 * Some keys have changed in this byte. find out which key it is. 02016 */ 02017 for (j = 0; j < 8; j++) { 02018 02019 /* 02020 * Convert our counts to a virtual key index and check to see 02021 * if this key has changed. 02022 */ 02023 vk = (i << 3) + j; 02024 if (!TestKeyRecentDownBit(pbRecentDown, vk)) 02025 continue; 02026 02027 /* 02028 * This key has changed. Update it's state in the thread key 02029 * state table. 02030 */ 02031 02032 if (TestKeyDownBit(pbKeyState, vk)) { 02033 SetKeyStateDown(pq, vk); 02034 } else { 02035 ClearKeyStateDown(pq, vk); 02036 } 02037 02038 if (TestKeyToggleBit(pbKeyState, vk)) { 02039 SetKeyStateToggle(pq, vk); 02040 } else { 02041 ClearKeyStateToggle(pq, vk); 02042 } 02043 } 02044 } 02045 02046 /* 02047 * Update the key cache index. 02048 */ 02049 gpsi->dwKeyCache++; 02050 02051 /* 02052 * All updated. Free the key state table if it was posted as an Event Message 02053 */ 02054 if (pbKeyState != gafAsyncKeyState) { 02055 UserFreePool(pbKeyState); 02056 } 02057 }

BOOL QueryTrackMouseEvent LPTRACKMOUSEEVENT  lpTME  ) 
 

Definition at line 2679 of file ntuser/kernel/input.c.

References BOOL, DF_TRACKMOUSEEVENT, DF_TRACKMOUSEHOVER, DF_TRACKMOUSELEAVE, tagDESKTOP::dwDTFlags, tagDESKTOP::dwMouseHoverTime, GETPTI, tagDESKTOP::htEx, HWq, tagTHREADINFO::pq, PtiCurrent, tagTHREADINFO::rpdesk, tagDESKTOP::spwndTrack, and TRUE.

Referenced by NtUserTrackMouseEvent().

02681 { 02682 PTHREADINFO ptiCurrent = PtiCurrent(); 02683 PDESKTOP pdesk = ptiCurrent->rpdesk; 02684 02685 /* 02686 * initialize the struct 02687 */ 02688 RtlZeroMemory(lpTME, sizeof(*lpTME)); 02689 lpTME->cbSize = sizeof(*lpTME); 02690 /* 02691 * Bail if not tracking any mouse event 02692 * or if the current thread is not in spwndTrack's queue 02693 */ 02694 if (!(pdesk->dwDTFlags & DF_TRACKMOUSEEVENT) 02695 || (ptiCurrent->pq != GETPTI(pdesk->spwndTrack)->pq)) { 02696 return TRUE; 02697 } 02698 /* 02699 * fill in the requested information 02700 */ 02701 if (pdesk->htEx != HTCLIENT) { 02702 lpTME->dwFlags |= TME_NONCLIENT; 02703 } 02704 if (pdesk->dwDTFlags & DF_TRACKMOUSELEAVE) { 02705 lpTME->dwFlags |= TME_LEAVE; 02706 } 02707 if (pdesk->dwDTFlags & DF_TRACKMOUSEHOVER) { 02708 lpTME->dwFlags |= TME_HOVER; 02709 lpTME->dwHoverTime = pdesk->dwMouseHoverTime; 02710 } 02711 02712 lpTME->hwndTrack = HWq(pdesk->spwndTrack); 02713 02714 return TRUE; 02715 }

void RedistributeInput PQMSG  pqmsgS,
PQ  pqRedist
 

Definition at line 5470 of file ntuser/kernel/input.c.

References CheckPtiSysPeek, CheckSysLock, CleanEventMessage(), tagMLIST::cMsgs, tagQMSG::dwQEvent, FreeQEntry(), tagQ::idSysPeek, tagQMSG::msg, NULL, tagTHREADINFO::pq, tagQMSG::pqmsgNext, tagQMSG::pqmsgPrev, tagMLIST::pqmsgWriteLast, tagQMSG::pti, tagQ::ptiSysLock, QEVENT_UPDATEKEYSTATE, and SetWakeBit().

Referenced by zzzAttachToQueue(), and zzzReattachThreads().

05473 { 05474 PTHREADINFO ptiSave; 05475 PTHREADINFO ptiT; 05476 PQMSG *ppqmsgD; 05477 PQMSG pqmsgT; 05478 PMLIST pmlInput; 05479 05480 /* 05481 * Since the thread attaching or unattaching may have left a queue 05482 * shared by other threads, the messages we are going to requeue 05483 * may have multiple destinations. On top of this, once we find 05484 * a home queue for a message, it needs to be inserted in the 05485 * list ordered by its time stamp (older messages go at the end). 05486 */ 05487 05488 /* 05489 * Loop through a given dest's messages to find where to insert 05490 * the source messages, based on message time stamp. Be sure 05491 * to deal with empty message lists (meaning, check for NULL). 05492 */ 05493 05494 ptiT = NULL; 05495 ppqmsgD = NULL; 05496 pmlInput = NULL; 05497 05498 while (pqmsgS != NULL) { 05499 05500 /* 05501 * Find out where this message should go. 05502 */ 05503 ptiSave = ptiT; 05504 ptiT = pqmsgS->pti; 05505 05506 /* 05507 * Get rid of some event messages. 05508 * 05509 * QEVENT_UPDATEKEYSTATE: key state already up to date 05510 */ 05511 if (pqmsgS->dwQEvent == QEVENT_UPDATEKEYSTATE) { 05512 ptiT = NULL; 05513 } 05514 05515 if (ptiT == NULL) { 05516 /* 05517 * Unlink it. pqmsgS should be the first in the list 05518 */ 05519 05520 UserAssert(!pqmsgS->pqmsgPrev); 05521 if (pqmsgS->pqmsgNext != NULL) { 05522 pqmsgS->pqmsgNext->pqmsgPrev = NULL; 05523 } 05524 05525 pqmsgT = pqmsgS; 05526 pqmsgS = pqmsgS->pqmsgNext; 05527 05528 /* 05529 * Clean it / free it. 05530 */ 05531 CleanEventMessage(pqmsgT); 05532 FreeQEntry(pqmsgT); 05533 05534 ptiT = ptiSave; 05535 continue; 05536 } 05537 05538 /* 05539 * Point to the pointer that points to the first message 05540 * that this message should go to, so that pointer is easy to 05541 * update, no matter where it is. 05542 */ 05543 if (ppqmsgD == NULL || ptiSave != ptiT) { 05544 05545 /* 05546 * If the source is younger than the last message in the 05547 * destination, go to the end. Otherwise, start at the 05548 * head of the desination list and find a place to insert 05549 * the message. 05550 */ 05551 if (ptiT->pq->mlInput.pqmsgWriteLast != NULL && 05552 pqmsgS->msg.time >= ptiT->pq->mlInput.pqmsgWriteLast->msg.time) { 05553 ppqmsgD = &ptiT->pq->mlInput.pqmsgWriteLast->pqmsgNext; 05554 } else { 05555 ppqmsgD = &ptiT->pq->mlInput.pqmsgRead; 05556 } 05557 05558 pmlInput = &ptiT->pq->mlInput; 05559 } 05560 05561 /* 05562 * If we're not at the end of the destination AND the destination 05563 * message time is younger than the source time, go on to 05564 * the next message. 05565 */ 05566 while (*ppqmsgD != NULL && ((*ppqmsgD)->msg.time <= pqmsgS->msg.time)) { 05567 ppqmsgD = &((*ppqmsgD)->pqmsgNext); 05568 } 05569 05570 /* 05571 * Link in the source before the dest message. Update 05572 * it's next and prev pointers. Update the dest prev 05573 * pointer. 05574 */ 05575 pqmsgT = pqmsgS; 05576 pqmsgS = pqmsgS->pqmsgNext; 05577 pqmsgT->pqmsgNext = *ppqmsgD; 05578 05579 if (*ppqmsgD != NULL) { 05580 pqmsgT->pqmsgPrev = (*ppqmsgD)->pqmsgPrev; 05581 (*ppqmsgD)->pqmsgPrev = pqmsgT; 05582 } else { 05583 pqmsgT->pqmsgPrev = pmlInput->pqmsgWriteLast; 05584 pmlInput->pqmsgWriteLast = pqmsgT; 05585 } 05586 *ppqmsgD = pqmsgT; 05587 ppqmsgD = &pqmsgT->pqmsgNext; 05588 pmlInput->cMsgs++; 05589 05590 /* 05591 * If the thread has an event message, make sure it's going to wake 05592 * up to process it. The QS_EVENT flag might not be set if the thread 05593 * previously found an event message for another thread and passed 05594 * control over to him. 05595 */ 05596 if (pqmsgT->dwQEvent != 0 && !(ptiT->pcti->fsWakeBits & QS_EVENT)) { 05597 SetWakeBit(ptiT, QS_EVENTSET); 05598 } 05599 05600 /* 05601 * Preserve the 'idSysPeek' from the old queue. 05602 * Carefull if the redistributed queue is the same as ptiT->pq. 05603 */ 05604 if (pqmsgT == (PQMSG)(pqRedist->idSysPeek) && (pqRedist != ptiT->pq)) { 05605 05606 if (ptiT->pq->idSysPeek == 0) { 05607 CheckPtiSysPeek(6, ptiT->pq, pqRedist->idSysPeek); 05608 ptiT->pq->idSysPeek = pqRedist->idSysPeek; 05609 } 05610 05611 #if DEBUGTAGS 05612 else { 05613 TAGMSG2(DBGTAG_SysPeek, 05614 "idSysPeek %#p already set in pq %#p", 05615 ptiT->pq->idSysPeek, ptiT->pq); 05616 05617 } 05618 #endif 05619 /* 05620 * Set the 'idSysPeek' of this queue to 0 since 05621 * we moved the idSysPeek to other queue 05622 */ 05623 CheckPtiSysPeek(7, pqRedist, 0); 05624 pqRedist->idSysPeek = 0; 05625 05626 /* 05627 * Preserve also 'ptiSysLock'. 05628 * Set ptiSysLock to the ptiT->pq only if it points to 05629 * that queue. 05630 */ 05631 if (ptiT->pq->ptiSysLock == NULL && 05632 pqRedist->ptiSysLock != NULL && 05633 pqRedist->ptiSysLock->pq == ptiT->pq) { 05634 05635 CheckSysLock(4, ptiT->pq, pqRedist->ptiSysLock); 05636 ptiT->pq->ptiSysLock = pqRedist->ptiSysLock; 05637 05638 CheckSysLock(5, pqRedist, NULL); 05639 pqRedist->ptiSysLock = NULL; 05640 } 05641 #if DEBUGTAGS 05642 else { 05643 TAGMSG2(DBGTAG_SysPeek, 05644 "ptiSysLock %#p already set in pq %#p\n", 05645 ptiT->pq->ptiSysLock, ptiT->pq); 05646 } 05647 #endif 05648 } 05649 05650 /* 05651 * Don't want the prev pointer on our message list to point 05652 * to this message which is on a different list (doesn't 05653 * really matter because we're about to link it anyway, 05654 * but completeness shouldn't hurt). 05655 */ 05656 if (pqmsgS != NULL) { 05657 pqmsgS->pqmsgPrev = NULL; 05658 } 05659 } 05660 }

void ResetMouseHover PDESKTOP  pdesk,
POINT  pt
 

Definition at line 2653 of file ntuser/kernel/input.c.

References tagDESKTOP::dwMouseHoverTime, gcxMouseHover, gcyMouseHover, IDSYS_MOUSEHOVER, InternalSetTimer(), tagDESKTOP::rcMouseHover, SetRect(), tagDESKTOP::spwndTrack, and xxxSystemTimerProc().

Referenced by TrackMouseEvent(), and xxxScanSysQueue().

02654 { 02655 /* 02656 * Reset the timer and hover rect 02657 */ 02658 InternalSetTimer(pdesk->spwndTrack, IDSYS_MOUSEHOVER, 02659 pdesk->dwMouseHoverTime, 02660 xxxSystemTimerProc, TMRF_SYSTEM); 02661 02662 SetRect(&pdesk->rcMouseHover, 02663 pt.x - gcxMouseHover / 2, 02664 pt.y - gcyMouseHover / 2, 02665 pt.x + gcxMouseHover / 2, 02666 pt.y + gcyMouseHover / 2); 02667 02668 }

void RestoreForegroundActivate  ) 
 

Definition at line 1549 of file ntuser/kernel/input.c.

References gppiStarting, NULL, tagPROCESSINFO::ppiNext, PUDF_ALLOWFOREGROUNDACTIVATE, and SET_PUDF.

Referenced by xxxEndDeferWindowPosEx(), and xxxMinMaximize().

01550 { 01551 PPROCESSINFO ppiT; 01552 01553 for (ppiT = gppiStarting; ppiT != NULL; ppiT = ppiT->ppiNext) { 01554 if (ppiT->W32PF_Flags & W32PF_APPSTARTING) { 01555 ppiT->W32PF_Flags |= W32PF_ALLOWFOREGROUNDACTIVATE; 01556 TAGMSG1(DBGTAG_FOREGROUND, "RestoreForegroundActivate set W32PF %#p", ppiT); 01557 SET_PUDF(PUDF_ALLOWFOREGROUNDACTIVATE); 01558 TAGMSG0(DBGTAG_FOREGROUND, "RestoreForegroundActivate set PUDF"); 01559 } 01560 } 01561 }

void SleepInputIdle PTHREADINFO  pti  ) 
 

Definition at line 5249 of file ntuser/kernel/input.c.

References NULL, tagWOWTHREADINFO::pIdleEvent, tagTHREADINFO::ppi, tagTHREADINFO::ptdb, tagPROCESSINFO::ptiMainThread, tagTDB::pwti, RESET_PSEUDO_EVENT, TIF_16BIT, tagTHREADINFO::TIF_flags, and TIF_SHAREDWOW.

Referenced by xxxMsgWaitForMultipleObjects(), and xxxSleepThread().

05251 { 05252 PW32PROCESS W32Process; 05253 05254 /* 05255 * Shared Wow Apps use the per thread idle event for synchronization. 05256 * Separate Wow VDMs use the regular mechanism. 05257 */ 05258 if (pti->TIF_flags & TIF_SHAREDWOW) { 05259 UserAssert(pti->TIF_flags & TIF_16BIT); 05260 if (pti->ptdb->pwti) { 05261 RESET_PSEUDO_EVENT(&pti->ptdb->pwti->pIdleEvent); 05262 } 05263 } else { 05264 /* 05265 * If the main thread is NULL, set it to this queue: it is calling 05266 * GetMessage(). 05267 */ 05268 if (pti->ppi->ptiMainThread == NULL) 05269 pti->ppi->ptiMainThread = pti; 05270 05271 /* 05272 * Put to sleep up anyone waiting on this event. 05273 */ 05274 if (pti->ppi->ptiMainThread == pti) { 05275 W32Process = W32GetCurrentProcess(); 05276 RESET_PSEUDO_EVENT(&W32Process->InputIdleEvent); 05277 } 05278 } 05279 }

BOOL TrackMouseEvent LPTRACKMOUSEEVENT  lpTME  ) 
 

Definition at line 2725 of file ntuser/kernel/input.c.

References _KillSystemTimer(), _PostMessage(), BOOL, DF_TRACKMOUSEHOVER, DF_TRACKMOUSELEAVE, tagDESKTOP::dwDTFlags, tagDESKTOP::dwMouseHoverTime, FALSE, gdtMouseHover, GETPTI, tagDESKTOP::htEx, IDSYS_MOUSEHOVER, NULL, PtiCurrent, ResetMouseHover(), tagDESKTOP::spwndTrack, TRUE, and ValidateHwnd.

Referenced by NtUserTrackMouseEvent(), xxxMNMouseMove(), and xxxSBWndProc().

02727 { 02728 PDESKTOP pdesk = PtiCurrent()->rpdesk; 02729 PWND pwnd; 02730 02731 /* 02732 * Validate hwndTrack 02733 */ 02734 pwnd = ValidateHwnd(lpTME->hwndTrack); 02735 if (pwnd == NULL) { 02736 return FALSE; 02737 } 02738 /* 02739 * If we're not tracking this window or not in correct hittest, bail 02740 */ 02741 if ((pwnd != pdesk->spwndTrack) 02742 || (!!(lpTME->dwFlags & TME_NONCLIENT) ^ (pdesk->htEx != HTCLIENT))) { 02743 02744 if ((lpTME->dwFlags & TME_LEAVE) && !(lpTME->dwFlags & TME_CANCEL)) { 02745 _PostMessage(pwnd, 02746 ((lpTME->dwFlags & TME_NONCLIENT) ? WM_NCMOUSELEAVE : WM_MOUSELEAVE), 02747 0, 0); 02748 } 02749 return TRUE; 02750 } 02751 02752 /* 02753 * Process cancel request 02754 */ 02755 if (lpTME->dwFlags & TME_CANCEL) { 02756 if (lpTME->dwFlags & TME_LEAVE) { 02757 pdesk->dwDTFlags &= ~DF_TRACKMOUSELEAVE; 02758 } 02759 if (lpTME->dwFlags & TME_HOVER) { 02760 if (pdesk->dwDTFlags & DF_TRACKMOUSEHOVER) { 02761 _KillSystemTimer(pwnd, IDSYS_MOUSEHOVER); 02762 pdesk->dwDTFlags &= ~DF_TRACKMOUSEHOVER; 02763 } 02764 } 02765 return TRUE; 02766 } 02767 02768 /* 02769 * Track mouse leave 02770 */ 02771 if (lpTME->dwFlags & TME_LEAVE) { 02772 pdesk->dwDTFlags |= DF_TRACKMOUSELEAVE; 02773 } 02774 /* 02775 * Track mouse hover 02776 */ 02777 if (lpTME->dwFlags & TME_HOVER) { 02778 pdesk->dwDTFlags |= DF_TRACKMOUSEHOVER; 02779 02780 pdesk->dwMouseHoverTime = lpTME->dwHoverTime; 02781 if ((pdesk->dwMouseHoverTime == 0) || (pdesk->dwMouseHoverTime == HOVER_DEFAULT)) { 02782 pdesk->dwMouseHoverTime = gdtMouseHover; 02783 } 02784 02785 ResetMouseHover(pdesk, GETPTI(pwnd)->ptLast); 02786 } 02787 02788 return TRUE; 02789 }

void UpdateKeyState PQ  pq,
UINT  vk,
BOOL  fDown
 

Definition at line 2908 of file ntuser/kernel/input.c.

References ClearKeyStateDown, ClearKeyStateToggle, CVKKEYCACHE, gpsi, SetKeyStateDown, SetKeyStateToggle, TestKeyStateDown, and TestKeyStateToggle.

Referenced by xxxSkipSysMsg().

02912 { 02913 if (vk != 0) { 02914 /* 02915 * If we're going down, toggle only if the key isn't 02916 * already down. 02917 */ 02918 if (fDown && !TestKeyStateDown(pq, vk)) { 02919 if (TestKeyStateToggle(pq, vk)) { 02920 ClearKeyStateToggle(pq, vk); 02921 } else { 02922 SetKeyStateToggle(pq, vk); 02923 } 02924 } 02925 02926 /* 02927 * Now set/clear the key down state. 02928 */ 02929 if (fDown) { 02930 SetKeyStateDown(pq, vk); 02931 } else { 02932 ClearKeyStateDown(pq, vk); 02933 } 02934 02935 /* 02936 * If this is one of the keys we cache, update the key cache index. 02937 */ 02938 if (vk < CVKKEYCACHE) { 02939 gpsi->dwKeyCache++; 02940 } 02941 } 02942 }

void WakeSomeone PQ  pq,
UINT  message,
PQMSG  pqmsg
 

Definition at line 1664 of file ntuser/kernel/input.c.

References BOOL, CancelForegroundActivate(), FALSE, GETPTI, glinp, tagQMSG::msg, NULL, tagQ::ptiKeyboard, tagLASTINPUT::ptiLastWoken, tagQ::ptiMouse, SetWakeBit(), tagQ::spwndActive, tagQ::spwndCapture, StoreQMessagePti(), TestKeyStateDown, tagTHREADINFO::TIF_flags, TIF_INCLEANUP, and TRUE.

Referenced by JournalTimer(), PostInputMessage(), xxxGetNextSysMsg(), xxxKeyEvent(), and zzzSetFMouseMoved().

01668 { 01669 BOOL fSetLastWoken = FALSE; 01670 PTHREADINFO ptiT; 01671 01672 /* 01673 * Set the appropriate wakebits for this queue. 01674 */ 01675 ptiT = NULL; 01676 switch (message) { 01677 01678 case WM_SYSKEYDOWN: 01679 case WM_KEYDOWN: 01680 /* 01681 * Don't change input ownership if the user is holding down 01682 * a modifier key. When doing a ctrl-drag operation for example, 01683 * the ctrl key must be down when the user drops the object (ie, mouse up). 01684 * On mouse up the RIT gives input ownership to the target; but since 01685 * ctrl is down, on the next repeat key we used to give input ownership 01686 * to the focus window (usually the drag source). Hence the target 01687 * would lose owenerhip and couldn't take the foreground. 01688 */ 01689 if (pqmsg != NULL) { 01690 switch (pqmsg->msg.wParam) { 01691 case VK_SHIFT: 01692 case VK_CONTROL: 01693 case VK_MENU: 01694 if (TestKeyStateDown(pq, pqmsg->msg.wParam)) { 01695 break; 01696 } 01697 /* Fall through */ 01698 01699 default: 01700 fSetLastWoken = TRUE; 01701 break; 01702 } 01703 } else { 01704 fSetLastWoken = TRUE; 01705 } 01706 /* fall through */ 01707 01708 case WM_SYSCHAR: 01709 case WM_CHAR: 01710 /* Freelance graphics seems to pass in WM_SYSCHARs and WM_CHARs into 01711 * the journal playback hook, so we need to set an input bit for 01712 * this case since that is what win3.1 does. VB2 "learning" demo does 01713 * the same, as does Excel intro. 01714 * 01715 * On win3.1, the WM_CHAR would by default set the QS_MOUSEBUTTON bit. 01716 * On NT, the WM_CHAR sets the QS_KEY bit. This is because 01717 * ScanSysQueue() calls TransferWakeBit() with the QS_KEY bit when 01718 * a WM_CHAR message is passed in. By using the QS_KEY bit on NT, 01719 * we're more compatible with what win3.1 wants to be. 01720 * 01721 * This fixes a case where the mouse was over progman, the WM_CHAR 01722 * would come in via journal playback, wakesomeone would be called, 01723 * and set the mouse bit in progman. Progman would then get into 01724 * ScanSysQueue(), callback the journal playback hook, get the WM_CHAR, 01725 * and do it again, looping. This caught VB2 in a loop. 01726 */ 01727 01728 CancelForegroundActivate(); 01729 01730 /* fall through */ 01731 01732 case WM_KEYUP: 01733 case WM_SYSKEYUP: 01734 case WM_MOUSEWHEEL: 01735 /* 01736 * Win3.1 first looks at what thread has the active status. This 01737 * means that we don't depend on the thread owning ptiKeyboard 01738 * to wake up and process this key in order to give it to the 01739 * active window, which is potentially newly active. Case in 01740 * point: excel bringing up CBT, cbt has an error, brings up 01741 * a message box: since excel is filtering for CBT messages only, 01742 * ptiKeyboard never gets reassigned to CBT so CBT doesn't get 01743 * any key messages and appears hung. 01744 */ 01745 ptiT = pq->ptiKeyboard; 01746 if (pq->spwndActive != NULL) 01747 ptiT = GETPTI(pq->spwndActive); 01748 01749 SetWakeBit(ptiT, message == WM_MOUSEWHEEL ? QS_MOUSEBUTTON : QS_KEY); 01750 break; 01751 01752 case WM_MOUSEMOVE: 01753 /* 01754 * Make sure we wake up the thread with the capture, if there is 01755 * one. This fixes PC Tools screen capture program, which sets 01756 * capture and then loops trying to remove messages from the 01757 * queue. 01758 */ 01759 if (pq->spwndCapture != NULL) 01760 ptiT = GETPTI(pq->spwndCapture); 01761 else 01762 ptiT = pq->ptiMouse; 01763 SetWakeBit(ptiT, QS_MOUSEMOVE); 01764 break; 01765 01766 01767 case WM_LBUTTONDOWN: 01768 case WM_LBUTTONDBLCLK: 01769 case WM_RBUTTONDOWN: 01770 case WM_RBUTTONDBLCLK: 01771 case WM_MBUTTONDOWN: 01772 case WM_MBUTTONDBLCLK: 01773 case WM_XBUTTONDOWN: 01774 case WM_XBUTTONDBLCLK: 01775 fSetLastWoken = TRUE; 01776 01777 /* fall through */ 01778 01779 default: 01780 /* 01781 * The default case in Win3.1 for this is QS_MOUSEBUTTON. 01782 */ 01783 01784 CancelForegroundActivate(); 01785 01786 /* fall through */ 01787 01788 case WM_LBUTTONUP: 01789 case WM_RBUTTONUP: 01790 case WM_MBUTTONUP: 01791 case WM_XBUTTONUP: 01792 /* 01793 * Make sure we wake up the thread with the capture, if there is 01794 * one. This fixes PC Tools screen capture program, which sets 01795 * capture and then loops trying to remove messages from the 01796 * queue. 01797 */ 01798 if (pq->spwndCapture != NULL && 01799 message >= WM_MOUSEFIRST && message <= WM_MOUSELAST) 01800 ptiT = GETPTI(pq->spwndCapture); 01801 else 01802 ptiT = pq->ptiMouse; 01803 SetWakeBit(ptiT, QS_MOUSEBUTTON); 01804 break; 01805 } 01806 01807 /* 01808 * If a messaged was passed in, remember in it who we woke up for this 01809 * message. We do this so each message is ownership marked. This way 01810 * we can merge/unmerge message streams when zzzAttachThreadInput() is 01811 * called. 01812 */ 01813 if (ptiT != NULL) { 01814 if (pqmsg != NULL) { 01815 01816 StoreQMessagePti(pqmsg, ptiT); 01817 01818 UserAssert(!(ptiT->TIF_flags & TIF_INCLEANUP)); 01819 } 01820 01821 /* 01822 * Remember who got the last key/click down. 01823 */ 01824 if (fSetLastWoken) { 01825 glinp.ptiLastWoken = ptiT; 01826 } 01827 } 01828 01829 }

int xxxActiveWindowTracking PWND  pwnd,
UINT  uMsg,
int  iHitTest
 

Definition at line 2327 of file ntuser/kernel/input.c.

References ATW_NOZORDER, BOOL, CheckLock, GetActiveTrackPwnd(), GETPTI, gpqForeground, HWq, IsForegroundLocked(), MA_PASSTHRU, MA_SKIP, NULL, QF_ACTIVEWNDTRACKING, tagQ::QF_flags, SFW_NOZORDER, SFW_SWITCH, SHORT, TestUP, ThreadLockAlways, ThreadUnlock, xxxActivateThisWindow(), xxxSendMessage(), and xxxSetForegroundWindow2().

Referenced by xxxDWP_SetCursor(), and xxxMouseActivate().

02331 { 02332 02333 BOOL fSuccess; 02334 int iRet; 02335 PWND pwndActivate; 02336 Q *pq; 02337 TL tlpwndActivate; 02338 02339 CheckLock(pwnd); 02340 UserAssert(TestUP(ACTIVEWINDOWTRACKING)); 02341 02342 /* 02343 * If the mouse hasn't been long enough on this queue, bail. 02344 */ 02345 pq = GETPTI(pwnd)->pq; 02346 if (!(pq->QF_flags & QF_ACTIVEWNDTRACKING)) { 02347 return MA_PASSTHRU; 02348 } 02349 pq->QF_flags &= ~QF_ACTIVEWNDTRACKING; 02350 02351 /* 02352 * If the foreground is locked, bail 02353 */ 02354 if (IsForegroundLocked()) { 02355 return MA_PASSTHRU; 02356 } 02357 02358 /* 02359 * Get the window we need to activate. If none, bail. 02360 */ 02361 pwndActivate = GetActiveTrackPwnd(pwnd, &pq); 02362 if (pwndActivate == NULL) { 02363 return MA_PASSTHRU; 02364 } 02365 02366 /* 02367 * Lock if needed because we're about to callback 02368 */ 02369 if (pwnd != pwndActivate) { 02370 ThreadLockAlways(pwndActivate, &tlpwndActivate); 02371 } 02372 02373 /* 02374 * Let's ask if it's OK to do this 02375 * 02376 * This message is supposed to go to the window the mouse is on. 02377 * This could be a child window which might return MA_NOACTIVATE*. 02378 * For mouse clicks (which is what we want to emulate here) 02379 * xxxButtonEvent calls xxxSetForegroundWindow2 so their 02380 * pwndActivate gets brought to the foreground regardless. 02381 * So we send the message to pwndActivate instead. 02382 */ 02383 iRet = (int)xxxSendMessage(pwndActivate, WM_MOUSEACTIVATE, 02384 (WPARAM)(HWq(pwndActivate)), MAKELONG((SHORT)iHitTest, uMsg)); 02385 02386 02387 switch (iRet) { 02388 case MA_ACTIVATE: 02389 case MA_ACTIVATEANDEAT: 02390 if (pq == gpqForeground) { 02391 fSuccess = xxxActivateThisWindow(pwndActivate, 0, 02392 (TestUP(ACTIVEWNDTRKZORDER) ? 0 : ATW_NOZORDER)); 02393 } else { 02394 fSuccess = xxxSetForegroundWindow2(pwndActivate, NULL, 02395 SFW_SWITCH | (TestUP(ACTIVEWNDTRKZORDER) ? 0 : SFW_NOZORDER)); 02396 } 02397 02398 /* 02399 * Eat the message if activation failed. 02400 */ 02401 if (!fSuccess) { 02402 iRet = MA_SKIP; 02403 } else if (iRet == MA_ACTIVATEANDEAT) { 02404 iRet = MA_SKIP; 02405 } 02406 break; 02407 02408 case MA_NOACTIVATEANDEAT: 02409 iRet = MA_SKIP; 02410 break; 02411 02412 02413 case MA_NOACTIVATE: 02414 default: 02415 iRet = MA_PASSTHRU; 02416 break; 02417 } 02418 02419 if (pwnd != pwndActivate) { 02420 ThreadUnlock(&tlpwndActivate); 02421 } 02422 02423 return iRet; 02424 02425 }

LRESULT xxxDispatchMessage LPMSG  pmsg  ) 
 

Definition at line 762 of file ntuser/kernel/input.c.

References CallClientProcA, CallClientProcW, ClrWF, tagTIMER::flags, gapfnScSendMessage, GETPTI, gptmrFirst, tagMSG_TABLE_ENTRY::iFunction, tagWND::lpfnWndProc, MessageTable, MSGFLAG_WOW_RESERVED, NtGetTickCount(), NULL, tagTIMER::pfn, PtiCurrent, tagTIMER::ptmrNext, RevalidateHwnd, RtlMBMessageWParamCharToWCS(), RtlWCSMessageWParamCharToMB(), SetWF, TESTSYNCONLYMESSAGE, TestWF, ThreadLock, ThreadUnlock, TIF_16BIT, tagTHREADINFO::TIF_flags, TIF_SYSTEMTHREAD, UINT, ValidateHwnd, WFANSIPROC, WFPAINTNOTPROCESSED, WFSERVERSIDEPROC, WFWMPAINTSENT, WM_SYSTIMER, WNDPROC_PWND, and xxxSimpleDoSyncPaint().

Referenced by NtUserDispatchMessage(), xxxDesktopThread(), xxxHelpLoop(), xxxMNLoop(), xxxMoveSize(), xxxOldNextWindow(), xxxRestoreCsrssThreadDesktop(), xxxSBTrackLoop(), and xxxSetCsrssThreadDesktop().

00764 { 00765 LRESULT lRet; 00766 PWND pwnd; 00767 WNDPROC_PWND lpfnWndProc; 00768 TL tlpwnd; 00769 00770 pwnd = NULL; 00771 if (pmsg->hwnd != NULL) { 00772 if ((pwnd = ValidateHwnd(pmsg->hwnd)) == NULL) 00773 return 0; 00774 } 00775 00776 /* 00777 * If this is a synchronous-only message (takes a pointer in wParam or 00778 * lParam), then don't allow this message to go through since those 00779 * parameters have not been thunked, and are pointing into outer-space 00780 * (which would case exceptions to occur). 00781 * 00782 * (This api is only called in the context of a message loop, and you 00783 * don't get synchronous-only messages in a message loop). 00784 */ 00785 if (TESTSYNCONLYMESSAGE(pmsg->message, pmsg->wParam)) { 00786 /* 00787 * Fail if 32 bit app is calling. 00788 */ 00789 if (!(PtiCurrent()->TIF_flags & TIF_16BIT)) { 00790 RIPERR1(ERROR_MESSAGE_SYNC_ONLY, RIP_WARNING, "xxxDispatchMessage: Sync only message 0x%lX", 00791 pmsg->message); 00792 return 0; 00793 } 00794 00795 /* 00796 * For wow apps, allow it to go through (for compatibility). Change 00797 * the message id so our code doesn't understand the message - wow 00798 * will get the message and strip out this bit before dispatching 00799 * the message to the application. 00800 */ 00801 pmsg->message |= MSGFLAG_WOW_RESERVED; 00802 } 00803 00804 ThreadLock(pwnd, &tlpwnd); 00805 00806 /* 00807 * Is this a timer? If there's a proc address, call it, 00808 * otherwise send it to the wndproc. 00809 */ 00810 if ((pmsg->message == WM_TIMER) || (pmsg->message == WM_SYSTIMER)) { 00811 if (pmsg->lParam != 0) { 00812 00813 /* 00814 * System timers must be executed on the server's context. 00815 */ 00816 if (pmsg->message == WM_SYSTIMER) { 00817 00818 /* 00819 * Verify that it's a valid timer proc. If so, 00820 * don't leave the critsect to call server-side procs 00821 * and pass a PWND, not HWND. 00822 */ 00823 PTIMER ptmr; 00824 lRet = 0; 00825 for (ptmr = gptmrFirst; ptmr != NULL; ptmr = ptmr->ptmrNext) { 00826 if ((pmsg->lParam == (LPARAM)ptmr->pfn) && (ptmr->flags & TMRF_SYSTEM)) { 00827 ptmr->pfn(pwnd, WM_SYSTIMER, (UINT)pmsg->wParam, 00828 NtGetTickCount()); 00829 break; 00830 } 00831 } 00832 goto Exit; 00833 } else { 00834 /* 00835 * WM_TIMER is the same for Unicode/ANSI. 00836 */ 00837 PTHREADINFO ptiCurrent = PtiCurrent(); 00838 00839 if (ptiCurrent->TIF_flags & TIF_SYSTEMTHREAD) { 00840 lRet = 0; 00841 goto Exit; 00842 } 00843 00844 lRet = CallClientProcA(pwnd, WM_TIMER, 00845 pmsg->wParam, NtGetTickCount(), pmsg->lParam); 00846 00847 goto Exit; 00848 } 00849 } 00850 } 00851 00852 /* 00853 * Check to see if pwnd is NULL AFTER the timer check. Apps can set 00854 * timers with NULL hwnd's, that's totally legal. But NULL hwnd messages 00855 * don't get dispatched, so check here after the timer case but before 00856 * dispatching - if it's NULL, just return 0. 00857 */ 00858 if (pwnd == NULL) { 00859 lRet = 0; 00860 goto Exit; 00861 } 00862 00863 /* 00864 * If we're dispatching a WM_PAINT message, set a flag to be used to 00865 * determine whether it was processed properly. 00866 */ 00867 if (pmsg->message == WM_PAINT) 00868 SetWF(pwnd, WFPAINTNOTPROCESSED); 00869 00870 /* 00871 * If this window's proc is meant to be executed from the server side 00872 * we'll just stay inside the semaphore and call it directly. Note 00873 * how we don't convert the pwnd into an hwnd before calling the proc. 00874 */ 00875 if (TestWF(pwnd, WFSERVERSIDEPROC)) { 00876 ULONG_PTR fnMessageType; 00877 00878 fnMessageType = pmsg->message >= WM_USER ? (ULONG_PTR)SfnDWORD : 00879 (ULONG_PTR)gapfnScSendMessage[MessageTable[pmsg->message].iFunction]; 00880 00881 /* 00882 * Convert the WM_CHAR from ANSI to UNICODE if the source was ANSI 00883 */ 00884 if (fnMessageType == (ULONG_PTR)SfnINWPARAMCHAR && TestWF(pwnd, WFANSIPROC)) { 00885 UserAssert(PtiCurrent() == GETPTI(pwnd)); // use receiver's codepage 00886 RtlMBMessageWParamCharToWCS(pmsg->message, &pmsg->wParam); 00887 } 00888 00889 lRet = pwnd->lpfnWndProc(pwnd, pmsg->message, pmsg->wParam, 00890 pmsg->lParam); 00891 goto Exit; 00892 } 00893 00894 /* 00895 * Cool people dereference any window structure members before they 00896 * leave the critsect. 00897 */ 00898 lpfnWndProc = pwnd->lpfnWndProc; 00899 00900 { 00901 /* 00902 * If we're dispatching the message to an ANSI wndproc we need to 00903 * convert the character messages from Unicode to Ansi. 00904 */ 00905 if (TestWF(pwnd, WFANSIPROC)) { 00906 UserAssert(PtiCurrent() == GETPTI(pwnd)); // use receiver's codepage 00907 RtlWCSMessageWParamCharToMB(pmsg->message, &pmsg->wParam); 00908 lRet = CallClientProcA(pwnd, pmsg->message, 00909 pmsg->wParam, pmsg->lParam, (ULONG_PTR)lpfnWndProc); 00910 } else { 00911 lRet = CallClientProcW(pwnd, pmsg->message, 00912 pmsg->wParam, pmsg->lParam, (ULONG_PTR)lpfnWndProc); 00913 } 00914 } 00915 00916 /* 00917 * If we dispatched a WM_PAINT message and it wasn't properly 00918 * processed, do the drawing here. 00919 */ 00920 if (pmsg->message == WM_PAINT && RevalidateHwnd(pmsg->hwnd) && 00921 TestWF(pwnd, WFPAINTNOTPROCESSED)) { 00922 //RIPMSG0(RIP_WARNING, 00923 // "Missing BeginPaint or GetUpdateRect/Rgn(fErase == TRUE) in WM_PAINT"); 00924 ClrWF(pwnd, WFWMPAINTSENT); 00925 xxxSimpleDoSyncPaint(pwnd); 00926 } 00927 00928 Exit: 00929 ThreadUnlock(&tlpwnd); 00930 return lRet; 00931 }

PQMSG xxxGetNextSysMsg PTHREADINFO  pti,
PQMSG  pqmsgPrev,
PQMSG  pqmsg
 

Definition at line 2802 of file ntuser/kernel/input.c.

References tagMLIST::cMsgs, dt(), DWORD, tagCLIENTTHREADINFO::fsChangeBits, tagCLIENTTHREADINFO::fsWakeBits, grpdeskRitInput, tagQ::idSysPeek, tagQ::mlInput, tagQMSG::msg, NULL, tagTHREADINFO::pcti, PhkFirstGlobalValid(), PostMove(), tagTHREADINFO::pq, PQMSG_PLAYBACK, tagQMSG::pqmsgNext, tagMLIST::pqmsgRead, tagQ::QF_flags, QF_MOUSEMOVED, tagTHREADINFO::rpdesk, SetJournalTimer(), WakeSomeone(), and xxxCallJournalPlaybackHook().

Referenced by xxxScanSysQueue().

02806 { 02807 DWORD dt; 02808 PMLIST pml; 02809 PQMSG pqmsgT; 02810 02811 /* 02812 * If there is a journal playback hook, call it to get the next message. 02813 */ 02814 if ((PhkFirstGlobalValid(pti, WH_JOURNALPLAYBACK) != NULL) 02815 && (pti->rpdesk == grpdeskRitInput)) { 02816 /* 02817 * We can't search through journal messages: we only get the current 02818 * journal message. So if the caller has already called us once 02819 * before, then exit with no messages. 02820 */ 02821 if (pqmsgPrev != 0) 02822 return NULL; 02823 02824 /* 02825 * Tell the journal playback hook that we're done 02826 * with this message now. 02827 */ 02828 dt = xxxCallJournalPlaybackHook(pqmsg); 02829 if (dt == 0xFFFFFFFF) 02830 return NULL; 02831 02832 /* 02833 * If dt == 0, then we don't need to wait: set the right wake 02834 * bits and return this message. 02835 */ 02836 if (dt == 0) { 02837 WakeSomeone(pti->pq, pqmsg->msg.message, NULL); 02838 return PQMSG_PLAYBACK; 02839 } else { 02840 /* 02841 * There is logically no more input in the "queue", so clear the 02842 * bits so that we will sleep when GetMessage is called. 02843 */ 02844 pti->pcti->fsWakeBits &= ~QS_INPUT; 02845 pti->pcti->fsChangeBits &= ~QS_INPUT; 02846 02847 /* 02848 * Need to wait before processing this next message. Set 02849 * a journal timer. 02850 */ 02851 SetJournalTimer(dt, pqmsg->msg.message); 02852 02853 return NULL; 02854 } 02855 } 02856 02857 /* 02858 * No journalling going on... return next message in system queue. 02859 */ 02860 02861 /* 02862 * Queue up a mouse move if the mouse has moved. 02863 */ 02864 if (pti->pq->QF_flags & QF_MOUSEMOVED) { 02865 PostMove(pti->pq); 02866 } 02867 02868 /* 02869 * If no messages in the input queue, return with 0. 02870 */ 02871 pml = &pti->pq->mlInput; 02872 if (pml->cMsgs == 0) 02873 return NULL; 02874 02875 /* 02876 * If this is the first call to xxxGetNextSysMsg(), return the 02877 * first message. 02878 */ 02879 if (pqmsgPrev == NULL || pti->pq->idSysPeek <= (ULONG_PTR)PQMSG_PLAYBACK) { 02880 pqmsgT = pml->pqmsgRead; 02881 } else { 02882 /* 02883 * Otherwise return the next message in the queue. Index with 02884 * idSysPeek, because that is updated by recursive calls through 02885 * this code. 02886 */ 02887 pqmsgT = ((PQMSG)(pti->pq->idSysPeek))->pqmsgNext; 02888 } 02889 02890 /* 02891 * Fill in the structure passed, and return the pointer to the 02892 * current message in the message list. This will become the new 02893 * pq->idSysPeek. 02894 */ 02895 if (pqmsgT != NULL) 02896 *pqmsg = *pqmsgT; 02897 return pqmsgT; 02898 }

BOOL xxxInternalGetMessage LPMSG  lpMsg,
HWND  hwndFilter,
UINT  msgMin,
UINT  msgMax,
UINT  flags,
BOOL  fGetMessage
 

Definition at line 213 of file ntuser/kernel/input.c.

References BOOL, CalcWakeMask(), CheckCritIn, CheckForClientDeath, CheckSysLock, CSPINBACKGROUND, _CLIENTINFO::cSpins, tagPROCESSINFO::cSysExpunge, tagCLIENTTHREADINFO::CTIF_flags, CTIF_SYSQUEUELOCKED, tagTHREADINFO::cVisWindows, DoPaint(), DoTimer(), DUMPPATHTAKEN, tagPROCESSINFO::dwhmodLibLoadedMask, DWORD, _CLIENTINFO::dwTIFlags, EnterCrit, FALSE, FJOURNALPLAYBACK, FJOURNALRECORD, tagCLIENTTHREADINFO::fsChangeBits, tagTHREADINFO::fsChangeBitsRemoved, tagCLIENTTHREADINFO::fsWakeBits, tagCLIENTTHREADINFO::fsWakeBitsJournal, gbExitInProgress, gcSysExpunge, gdwSysExpungeMask, gpdeskRecalcQueueAttach, gppiWantForegroundPriority, HEVENT_REMOVEME, tagTHREADINFO::idLast, tagQ::idSysLock, IsHooked, IsWinEventNotifyDeferredOK, LeaveCrit, NULL, PATHTAKEN, tagTHREADINFO::pClientInfo, tagTHREADINFO::pcti, PhkFirstGlobalValid(), tagTHREADINFO::ppi, tagTHREADINFO::pq, tagTHREADINFO::psmsCurrent, PtiCurrent, tagQ::ptiSysLock, tagQ::QF_flags, QF_LOCKNOREMOVE, tagTHREADINFO::rpdesk, SET_TIME_LAST_READ, SetForegroundPriority(), ThreadLockAlwaysWithPti, ThreadUnlock, TIF_16BIT, TIF_DELAYEDEVENT, tagTHREADINFO::TIF_flags, TIF_SPINNING, TRUE, UINT, ValidateHwnd, WHF_GETMESSAGE, xxxCallHook(), xxxDirectedYield(), xxxDoSysExpunge(), xxxReadPostMessage(), xxxReceiveMessages, xxxScanSysQueue(), xxxSleepTask(), xxxSleepThread(), xxxUserYield(), zzzCalcStartCursorHide(), zzzReattachThreads(), and zzzWakeInputIdle().

00220 { 00221 UINT fsWakeBits; 00222 UINT fsWakeMask; 00223 UINT fsRemoveBits; 00224 PTHREADINFO ptiCurrent; 00225 PW32PROCESS W32Process; 00226 PWND pwndFilter; 00227 BOOL fLockPwndFilter; 00228 TL tlpwndFilter; 00229 BOOL fRemove; 00230 BOOL fExit; 00231 PQ pq; 00232 #ifdef MARKPATH 00233 DWORD pathTaken = 0; 00234 00235 #define PATHTAKEN(x) pathTaken |= x 00236 #define DUMPPATHTAKEN() if (gfMarkPath) DbgPrint("xxxInternalGetMessage path:%08x\n", pathTaken) 00237 #else 00238 #define PATHTAKEN(x) 00239 #define DUMPPATHTAKEN() 00240 #endif 00241 00242 CheckCritIn(); 00243 UserAssert(IsWinEventNotifyDeferredOK()); 00244 00245 ptiCurrent = PtiCurrent(); 00246 00247 /* 00248 * PeekMessage accepts NULL, 0x0000FFFF, and -1 as valid HWNDs. 00249 * If hwndFilter is invalid we can't just return FALSE because that will 00250 * hose existing badly behaved apps who might attempt to dispatch 00251 * the random contents of pmsg. 00252 */ 00253 if ((hwndFilter == (HWND)-1) || (hwndFilter == (HWND)0x0000FFFF)) { 00254 hwndFilter = (HWND)1; 00255 } 00256 00257 if ((hwndFilter != NULL) && (hwndFilter != (HWND)1)) { 00258 if ((pwndFilter = ValidateHwnd(hwndFilter)) == NULL) { 00259 lpMsg->hwnd = NULL; 00260 lpMsg->message = WM_NULL; 00261 PATHTAKEN(1); 00262 DUMPPATHTAKEN(); 00263 if (fGetMessage) 00264 return -1; 00265 else 00266 return 0; 00267 } 00268 00269 ThreadLockAlwaysWithPti(ptiCurrent, pwndFilter, &tlpwndFilter); 00270 fLockPwndFilter = TRUE; 00271 00272 } else { 00273 pwndFilter = (PWND)hwndFilter; 00274 fLockPwndFilter = FALSE; 00275 } 00276 00277 /* 00278 * Add one to our spin count. At this end of this routine we'll check 00279 * to see if the spin count gets >= CSPINBACKGROUND. If so we'll put this 00280 * process into the background. 00281 */ 00282 ptiCurrent->pClientInfo->cSpins++; 00283 00284 /* 00285 * Check to see if the startglass is on, and if so turn it off and update. 00286 */ 00287 W32Process = W32GetCurrentProcess(); 00288 if (W32Process->W32PF_Flags & W32PF_STARTGLASS) { 00289 00290 /* 00291 * This app is no longer in "starting" mode. Recalc when to hide 00292 * the app starting cursor. 00293 */ 00294 W32Process->W32PF_Flags &= ~W32PF_STARTGLASS; 00295 /* 00296 * Don't need DeferWinEventNotify() - xxxDoSysExpunge below doesn't 00297 */ 00298 zzzCalcStartCursorHide(NULL, 0); 00299 } 00300 00301 /* 00302 * Next check to see if any .dlls need freeing in 00303 * the context of this client (used for windows hooks). 00304 */ 00305 if (ptiCurrent->ppi->cSysExpunge != gcSysExpunge) { 00306 ptiCurrent->ppi->cSysExpunge = gcSysExpunge; 00307 if (ptiCurrent->ppi->dwhmodLibLoadedMask & gdwSysExpungeMask) 00308 xxxDoSysExpunge(ptiCurrent); 00309 } 00310 00311 /* 00312 * Set up BOOL fRemove local variable from for ReadMessage() 00313 */ 00314 fRemove = flags & PM_REMOVE; 00315 00316 /* 00317 * Unlock the system queue if it's owned by us. 00318 */ 00319 /* 00320 * If we're currently processing a message, unlock the input queue 00321 * because the sender, who is blocked, might be the owner, and in order 00322 * to reply, the receiver may need to read keyboard / mouse input. 00323 */ 00324 /* 00325 * If this thread has the input queue locked and the last message removed 00326 * is the last message we looked at, then unlock - we're ready for anyone 00327 * to get the next message. 00328 */ 00329 pq = ptiCurrent->pq; 00330 if ( (ptiCurrent->psmsCurrent != NULL) 00331 || (pq->ptiSysLock == ptiCurrent && pq->idSysLock == ptiCurrent->idLast) 00332 ) { 00333 CheckSysLock(1, pq, NULL); 00334 pq->ptiSysLock = NULL; 00335 PATHTAKEN(2); 00336 } else if (pq->ptiSysLock 00337 && (pq->ptiSysLock->cVisWindows == 0) 00338 && (PhkFirstGlobalValid(ptiCurrent, WH_JOURNALPLAYBACK) != NULL)) { 00339 /* 00340 * If the thread that has the system queue lock has no windows visible 00341 * (can happen if it just hid its last window), don't expect it to call 00342 * GetMessage() again! - unlock the system queue. --- ScottLu 00343 * This condition creates a hole by which a second thread attached to 00344 * the same queue as thread 1 can alter pq->idSysPeek during a callback 00345 * made by thread 1 so that thread 1 will delete the wrong message 00346 * (losing keystrokes - causing Shift to appear be stuck down editing a 00347 * Graph5 caption embedded in Word32 document #5032. However, MSTEST 00348 * requires this hole, so allow it if Journal Playback is occurring 00349 * #8850 (yes, a hack) Chicago also has this behavior. --- IanJa 00350 */ 00351 CheckSysLock(2, pq, NULL); 00352 pq->ptiSysLock = NULL; 00353 PATHTAKEN(3); 00354 } 00355 if (pq->ptiSysLock != ptiCurrent) { 00356 ptiCurrent->pcti->CTIF_flags &= ~CTIF_SYSQUEUELOCKED; 00357 } 00358 00359 /* 00360 * If msgMax == 0 then msgMax = -1: that makes our range checking only 00361 * have to deal with msgMin < msgMax. 00362 */ 00363 if (msgMax == 0) 00364 msgMax--; 00365 00366 /* 00367 * Compute the QS* mask that corresponds to the message range 00368 * and the wake mask filter (HIWORD(flags)) 00369 */ 00370 fsWakeMask = CalcWakeMask(msgMin, msgMax, HIWORD(flags)); 00371 ptiCurrent->fsChangeBitsRemoved = 0; 00372 00373 /* 00374 * If we can yield and one or more events were skipped, 00375 * set the wakebits for event 00376 */ 00377 if (!(flags & PM_NOYIELD) && ptiCurrent->TIF_flags & TIF_DELAYEDEVENT) { 00378 ptiCurrent->pcti->fsWakeBits |= QS_EVENT; 00379 ptiCurrent->pcti->fsChangeBits |= QS_EVENT; 00380 ptiCurrent->TIF_flags &= ~TIF_DELAYEDEVENT; 00381 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; 00382 } 00383 00384 while (TRUE) { 00385 00386 /* 00387 * Restore any wake bits saved while journalling 00388 */ 00389 ptiCurrent->pcti->fsWakeBits |= ptiCurrent->pcti->fsWakeBitsJournal; 00390 00391 /* 00392 * If we need to recalc queue attachments, do it here. Do it on the 00393 * right desktop or else the queues will get created in the wrong 00394 * heap. 00395 */ 00396 if (ptiCurrent->rpdesk == gpdeskRecalcQueueAttach) { 00397 gpdeskRecalcQueueAttach = NULL; 00398 00399 if (ptiCurrent->rpdesk != NULL && !FJOURNALRECORD() && !FJOURNALPLAYBACK()) { 00400 /* 00401 * No need to DeferWinEventNotify(): a call to 00402 * xxxReceiveMessages is made just below 00403 */ 00404 zzzReattachThreads(FALSE); 00405 PATHTAKEN(4); 00406 } 00407 } 00408 00409 /* 00410 * Remember what change bits we're clearing. This is important to 00411 * fix a bug in the input model: If an app receives a sent message 00412 * from within SleepThread(), then does PostMessage() (which sets 00413 * QS_POSTMESSAGE), then does a PeekMessage(...) for some different 00414 * posted message (clears QS_POSTMESSAGE in fsChangeBits), then returns 00415 * back into SleepThread(), it won't wake up to retrieve that newly 00416 * posted message because the change bits are cleared. 00417 * 00418 * What we do is remember the change bits that are being cleared. 00419 * Then, when we return to SleepThread(), we put these remembered 00420 * bits back into the change bits that also have corresponding 00421 * bits in the wakebits (so we don't set changebits that represent 00422 * input that isn't there anymore). This way, the app will retrieve 00423 * the newly posted message refered to earlier. 00424 * - scottlu 00425 * 00426 * New for NT5: Since QS_SENDMESSAGE was never set it fsWakeMask before (NT4), 00427 * it was never cleared from fsChangeBits. For compatibility, we won't clear 00428 * it now even if specified in fsWakeMask; hence we won't affect any one 00429 * checking for QS_SENDMESSAGE in pcti->fsChangeBits. 00430 */ 00431 fsRemoveBits = fsWakeMask & ~QS_SENDMESSAGE; 00432 ptiCurrent->fsChangeBitsRemoved |= ptiCurrent->pcti->fsChangeBits & fsRemoveBits; 00433 00434 /* 00435 * Clear the change bits that we're looking at, in order to detect 00436 * incoming events that may occur the last time we checked the wake 00437 * bits. 00438 */ 00439 ptiCurrent->pcti->fsChangeBits &= ~fsRemoveBits; 00440 00441 /* 00442 * Check for sent messages. Check the the actual wake bits (i.e, from pcti) 00443 * so we know for real. 00444 */ 00445 if (ptiCurrent->pcti->fsWakeBits & fsWakeMask & QS_SENDMESSAGE) { 00446 xxxReceiveMessages(ptiCurrent); 00447 } else if (ptiCurrent->pcti->fsWakeBits & QS_SENDMESSAGE) { 00448 RIPMSG2(RIP_WARNING, "xxxInternalGetMessage:(1st test) sendmsgs pending. Bits:%#lx Mask:%#lx", 00449 ptiCurrent->pcti->fsWakeBits, fsWakeMask); 00450 goto NoMessages; 00451 } 00452 00453 /* 00454 * Check to see if we have any input we want. 00455 */ 00456 if ((ptiCurrent->pcti->fsWakeBits & fsWakeMask) == 0) { 00457 PATHTAKEN(8); 00458 goto NoMessages; 00459 } 00460 fsWakeBits = ptiCurrent->pcti->fsWakeBits; 00461 00462 /* 00463 * If the queue lock is != NULL (ptiSysLock) and it is this thread that 00464 * locked it, then go get the message from the system queue. This is 00465 * to prevent messages posted after a PeekMessage/no-remove from being 00466 * seen before the original message from the system queue. (Aldus 00467 * Pagemaker requires this) (bobgu 8/5/87). 00468 */ 00469 if (ptiCurrent->pq->ptiSysLock == ptiCurrent && 00470 (ptiCurrent->pq->QF_flags & QF_LOCKNOREMOVE)) { 00471 /* 00472 * Does the caller want mouse / keyboard? 00473 */ 00474 if (fsWakeBits & fsWakeMask & (QS_INPUT | QS_EVENT)) { 00475 00476 /* 00477 * It should never get here during exit. 00478 */ 00479 UserAssert(gbExitInProgress == FALSE); 00480 00481 if (xxxScanSysQueue(ptiCurrent, lpMsg, pwndFilter, 00482 msgMin, msgMax, flags, 00483 fsWakeBits & fsWakeMask & (QS_INPUT | QS_EVENT))) { 00484 00485 PATHTAKEN(0x10); 00486 break; 00487 } 00488 } else if (fsWakeBits & QS_EVENT) { 00489 RIPMSG2(RIP_WARNING, 00490 "xxxInternalGetMessage:(1st test)events pending. Bits:%#lx Mask:%#lx", 00491 fsWakeBits, fsWakeMask); 00492 goto NoMessages; 00493 } 00494 } 00495 00496 /* 00497 * See if there's a message in the application queue. 00498 */ 00499 if (fsWakeBits & fsWakeMask & QS_POSTMESSAGE) { 00500 if (xxxReadPostMessage(ptiCurrent, lpMsg, pwndFilter, 00501 msgMin, msgMax, fRemove)) { 00502 PATHTAKEN(0x20); 00503 break; 00504 } 00505 } 00506 00507 /* 00508 * Time to scan the raw input queue for input. First check to see 00509 * if the caller wants mouse / keyboard input. 00510 */ 00511 if (fsWakeBits & fsWakeMask & (QS_INPUT | QS_EVENT)) { 00512 00513 /* 00514 * It should never get here during exit. 00515 */ 00516 UserAssert(gbExitInProgress == FALSE); 00517 00518 if (xxxScanSysQueue(ptiCurrent, lpMsg, pwndFilter, 00519 msgMin, msgMax, flags, 00520 fsWakeBits & fsWakeMask & (QS_INPUT | QS_EVENT))) { 00521 PATHTAKEN(0x40); 00522 break; 00523 } 00524 } else if (fsWakeBits & QS_EVENT) { 00525 RIPMSG2(RIP_WARNING, "xxxInternalGetMessage:(2nd test)events pending. Bits:%#lx Mask:%#lx", 00526 fsWakeBits, fsWakeMask); 00527 goto NoMessages; 00528 } 00529 00530 /* 00531 * Check for sent messages. Check the the actual wake bits (i.e, from pcti) 00532 * so we know for real. 00533 */ 00534 if (ptiCurrent->pcti->fsWakeBits & fsWakeMask & QS_SENDMESSAGE) { 00535 xxxReceiveMessages(ptiCurrent); 00536 } else if (ptiCurrent->pcti->fsWakeBits & QS_SENDMESSAGE) { 00537 RIPMSG2(RIP_WARNING, "xxxInternalGetMessage:(2nd test)sendmsgs pending. Bits:%#lx Mask:%#lx", 00538 ptiCurrent->pcti->fsWakeBits, fsWakeMask); 00539 goto NoMessages; 00540 } 00541 00542 /* 00543 * Get new input bits. 00544 */ 00545 if ((ptiCurrent->pcti->fsWakeBits & fsWakeMask) == 0) { 00546 PATHTAKEN(0x80); 00547 goto NoMessages; 00548 } 00549 fsWakeBits = ptiCurrent->pcti->fsWakeBits; 00550 00551 /* 00552 * Does the caller want paint messages? If so, try to find a paint. 00553 */ 00554 if (fsWakeBits & fsWakeMask & QS_PAINT) { 00555 if (DoPaint(pwndFilter, lpMsg)) { 00556 PATHTAKEN(0x100); 00557 break; 00558 } 00559 } 00560 00561 /* 00562 * We must yield for 16 bit apps before checking timers or an app 00563 * that has a fast timer could chew up all the time and never let 00564 * anyone else run. 00565 * 00566 * NOTE: This could cause PeekMessage() to yield TWICE, if the user 00567 * is filtering with a window handle. If the DoTimer() call fails 00568 * then we end up yielding again. 00569 */ 00570 if (!(flags & PM_NOYIELD)) { 00571 /* 00572 * This is the point where windows would yield. Here we wait to wake 00573 * up any threads waiting for this thread to hit "idle state". 00574 */ 00575 zzzWakeInputIdle(ptiCurrent); 00576 00577 /* 00578 * Yield and receive pending messages. 00579 */ 00580 xxxUserYield(ptiCurrent); 00581 00582 /* 00583 * Check new input buts and receive pending messages. 00584 */ 00585 if (ptiCurrent->pcti->fsWakeBits & fsWakeMask & QS_SENDMESSAGE) { 00586 xxxReceiveMessages(ptiCurrent); 00587 } else if (ptiCurrent->pcti->fsWakeBits & QS_SENDMESSAGE) { 00588 RIPMSG2(RIP_WARNING, "xxxInternalGetMessage:(3rd test) sendmsgs pending. Bits:%#lx Mask:%#lx", 00589 ptiCurrent->pcti->fsWakeBits, fsWakeMask); 00590 goto NoMessages; 00591 } 00592 00593 if ((ptiCurrent->pcti->fsWakeBits & fsWakeMask) == 0) { 00594 00595 PATHTAKEN(0x200); 00596 goto NoMessages; 00597 } 00598 fsWakeBits = ptiCurrent->pcti->fsWakeBits; 00599 } 00600 00601 /* 00602 * Does the app want timer messages, and if there one pending? 00603 */ 00604 if (fsWakeBits & fsWakeMask & QS_TIMER) { 00605 if (DoTimer(pwndFilter)) { 00606 /* 00607 * DoTimer() posted the message into the app's queue, 00608 * so start over and we'll grab it from there. 00609 */ 00610 PATHTAKEN(0x400); 00611 continue; 00612 } 00613 } 00614 00615 NoMessages: 00616 /* 00617 * Looks like we have no input. If we're being called from GetMessage() 00618 * then go to sleep until we find something. 00619 */ 00620 if (!fGetMessage) { 00621 /* 00622 * This is one last check for pending sent messages. It also 00623 * yields. Win3.1 does this. 00624 */ 00625 if (!(flags & PM_NOYIELD)) { 00626 /* 00627 * This is the point where windows yields. Here we wait to wake 00628 * up any threads waiting for this thread to hit "idle state". 00629 */ 00630 zzzWakeInputIdle(ptiCurrent); 00631 00632 /* 00633 * Yield and receive pending messages. 00634 */ 00635 xxxUserYield(ptiCurrent); 00636 } 00637 PATHTAKEN(0x800); 00638 goto FalseExit; 00639 } 00640 00641 /* 00642 * This is a getmessage not a peekmessage, so sleep. When we sleep, 00643 * zzzWakeInputIdle() is called to wake up any apps waiting on this 00644 * app to go idle. 00645 */ 00646 if (!xxxSleepThread(fsWakeMask, 0, TRUE)) 00647 goto FalseExit; 00648 } /* while (TRUE) */ 00649 00650 /* 00651 * If we're here then we have input for this queue. Call the 00652 * GetMessage() hook with this input. 00653 */ 00654 if (IsHooked(ptiCurrent, WHF_GETMESSAGE)) 00655 xxxCallHook(HC_ACTION, flags, (LPARAM)lpMsg, WH_GETMESSAGE); 00656 00657 /* 00658 * If called from PeekMessage(), return TRUE. 00659 */ 00660 if (!fGetMessage) { 00661 PATHTAKEN(0x1000); 00662 goto TrueExit; 00663 } 00664 00665 /* 00666 * Being called from GetMessage(): return FALSE if the message is WM_QUIT, 00667 * TRUE otherwise. 00668 */ 00669 if (lpMsg->message == WM_QUIT) { 00670 PATHTAKEN(0x2000); 00671 goto FalseExit; 00672 } 00673 00674 /* 00675 * Fall through to TrueExit... 00676 */ 00677 00678 TrueExit: 00679 /* 00680 * Update timeLastRead. We use this for hung app calculations. 00681 */ 00682 SET_TIME_LAST_READ(ptiCurrent); 00683 fExit = TRUE; 00684 PATHTAKEN(0x4000); 00685 goto Exit; 00686 00687 FalseExit: 00688 fExit = FALSE; 00689 00690 Exit: 00691 if (fLockPwndFilter) 00692 ThreadUnlock(&tlpwndFilter); 00693 00694 /* 00695 * see CheckProcessBackground() comment above 00696 * Check to see if we need to move this process into background 00697 * priority. 00698 */ 00699 if (ptiCurrent->pClientInfo->cSpins >= CSPINBACKGROUND) { 00700 00701 ptiCurrent->pClientInfo->cSpins = 0; 00702 00703 if (!(ptiCurrent->TIF_flags & TIF_SPINNING)) { 00704 00705 ptiCurrent->TIF_flags |= TIF_SPINNING; 00706 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; 00707 00708 if (!(ptiCurrent->ppi->W32PF_Flags & W32PF_FORCEBACKGROUNDPRIORITY)) { 00709 00710 ptiCurrent->ppi->W32PF_Flags |= W32PF_FORCEBACKGROUNDPRIORITY; 00711 00712 if (ptiCurrent->ppi == gppiWantForegroundPriority) { 00713 SetForegroundPriority(ptiCurrent, FALSE); 00714 } 00715 } 00716 } 00717 00718 /* 00719 * For spinning Message loops, we need to take the 16bit-thread out 00720 * of the scheduler temporarily so that other processes can get a chance 00721 * to run. This is appearent in OLE operations where a 16bit foreground 00722 * thread starts an OLE activation on a 32bit process. The 32bit process 00723 * gets starved of CPU while the 16bit thread spins. 00724 */ 00725 if (ptiCurrent->TIF_flags & TIF_16BIT) { 00726 00727 /* 00728 * Take the 16bit thread out of the scheduler. This wakes any 00729 * other 16bit thread needing time, and takes the current thread 00730 * out. We will do a brief sleep so that apps can respond in time. 00731 * When done, we will reschedule the thread. The zzzWakeInputIdle() 00732 * should have been called in the no-messages section, so we have 00733 * already set the Idle-Event. 00734 */ 00735 xxxSleepTask(FALSE, HEVENT_REMOVEME); 00736 00737 LeaveCrit(); 00738 ZwYieldExecution(); 00739 CheckForClientDeath(); 00740 EnterCrit(); 00741 00742 xxxDirectedYield(DY_OLDYIELD); 00743 } 00744 } 00745 00746 PATHTAKEN(0x8000); 00747 DUMPPATHTAKEN(); 00748 return fExit; 00749 }

int xxxMouseActivate PTHREADINFO  pti,
PWND  pwnd,
UINT  message,
WPARAM  wParam,
LPPOINT  lppt,
int  ht
 

Definition at line 2444 of file ntuser/kernel/input.c.

References _GETPDESK, AW_TRY, AW_TRY2, BOOL, CheckLock, CheckOnTop(), tagQ::codeCapture, GETPTI, HW, MA_PASSTHRU, MA_REHITTEST, MA_SKIP, NO_CAP_CLIENT, NULL, tagTHREADINFO::pq, PWNDDESKTOP, QF_EVENTDEACTIVATEREMOVED, tagQ::QF_flags, tagWND::rcClient, SHORT, tagQ::spwndActive, tagQ::spwndCapture, tagWND::spwndParent, TestUP, TestWF, TestwndChild, ThreadLockAlwaysWithPti, ThreadLockWithPti, ThreadUnlock, TIF_CSRSSTHREAD, UINT, WEFNOPARENTNOTIFY, WEFTOPMOST, WFDISABLED, WFWIN40COMPAT, xxxActivateWindow(), xxxActiveWindowTracking(), and xxxSendMessage().

Referenced by xxxScanSysQueue().

02451 { 02452 UINT x, y; 02453 PWND pwndTop; 02454 int result; 02455 TL tlpwndTop; 02456 BOOL fSend; 02457 02458 CheckLock(pwnd); 02459 02460 UserAssert(_GETPDESK(pwnd) != NULL); 02461 02462 /* 02463 * No mouse activation if the mouse is captured. Must check for the capture 02464 * ONLY here. 123W depends on it - create a graph, select Rearrange.. 02465 * flip horizontal, click outside the graph. If this code checks for 02466 * anything beside just capture, 123w will get the below messages and 02467 * get confused. 02468 */ 02469 if (pti->pq->spwndCapture != NULL) { 02470 return MA_PASSTHRU; 02471 } 02472 02473 result = MA_PASSTHRU; 02474 02475 pwndTop = pwnd; 02476 ThreadLockWithPti(pti, pwndTop, &tlpwndTop); 02477 02478 /* 02479 * B#1404 02480 * Don't send WM_PARENTNOTIFY messages if the child has 02481 * WS_EX_NOPARENTNOTIFY style. 02482 * 02483 * Unfortunately, this breaks people who create controls in 02484 * MDI children, like WinMail. They don't get WM_PARENTNOTIFY 02485 * messages, which don't get passed to DefMDIChildProc(), which 02486 * then can't update the active MDI child. Grrr. 02487 */ 02488 02489 fSend = (!TestWF(pwnd, WFWIN40COMPAT) || !TestWF(pwnd, WEFNOPARENTNOTIFY)); 02490 02491 /* 02492 * If it's a buttondown event, send WM_PARENTNOTIFY. 02493 */ 02494 switch (message) { 02495 case WM_LBUTTONDOWN: 02496 case WM_RBUTTONDOWN: 02497 case WM_MBUTTONDOWN: 02498 case WM_XBUTTONDOWN: 02499 while (TestwndChild(pwndTop)) { 02500 pwndTop = pwndTop->spwndParent; 02501 02502 if (fSend) { 02503 ThreadUnlock(&tlpwndTop); 02504 ThreadLockWithPti(pti, pwndTop, &tlpwndTop); 02505 x = (UINT)(lppt->x - pwndTop->rcClient.left); 02506 y = (UINT)(lppt->y - pwndTop->rcClient.top); 02507 02508 /* Get the xbutton from the hiword of wParam */ 02509 UserAssert(message == WM_XBUTTONDOWN || HIWORD(wParam) == 0); 02510 UserAssert(LOWORD(wParam) == 0); 02511 xxxSendMessage(pwndTop, WM_PARENTNOTIFY, (WPARAM)(message | wParam), MAKELPARAM(x, y)); 02512 } 02513 } 02514 02515 if (!fSend) { 02516 ThreadUnlock(&tlpwndTop); 02517 ThreadLockAlwaysWithPti(pti, pwndTop, &tlpwndTop); 02518 } 02519 02520 /* 02521 * NOTE: We break out of this loop with pwndTop locked. 02522 */ 02523 break; 02524 } 02525 02526 /* 02527 * The mouse was moved onto this window: make it foreground 02528 */ 02529 if (TestUP(ACTIVEWINDOWTRACKING) && (message == WM_MOUSEMOVE)) { 02530 result = xxxActiveWindowTracking(pwnd, WM_MOUSEMOVE, ht); 02531 } 02532 02533 /* 02534 * Are we hitting an inactive top-level window WHICH ISN'T THE DESKTOP(!)? 02535 * 02536 * craigc 7-14-89 hitting either inactive top level or any child window, 02537 * to be compatible with 2.X. Apps apparently needs this message. 02538 */ 02539 else if ((pti->pq->spwndActive != pwnd || pti->pq->QF_flags & QF_EVENTDEACTIVATEREMOVED) && 02540 (pwndTop != PWNDDESKTOP(pwndTop))) { 02541 switch (message) { 02542 case WM_LBUTTONDOWN: 02543 case WM_RBUTTONDOWN: 02544 case WM_MBUTTONDOWN: 02545 case WM_XBUTTONDOWN: 02546 02547 /* 02548 * Send the MOUSEACTIVATE message. 02549 */ 02550 result = (int)xxxSendMessage(pwnd, WM_MOUSEACTIVATE, 02551 (WPARAM)(HW(pwndTop)), MAKELONG((SHORT)ht, message)); 02552 02553 switch (result) { 02554 02555 case 0: 02556 case MA_ACTIVATE: 02557 case MA_ACTIVATEANDEAT: 02558 02559 /* 02560 * If activation fails, swallow the message. 02561 */ 02562 if ((pwndTop != pti->pq->spwndActive || 02563 pti->pq->QF_flags & QF_EVENTDEACTIVATEREMOVED) && 02564 !xxxActivateWindow(pwndTop, 02565 (UINT)((pti->pq->codeCapture == NO_CAP_CLIENT) ? 02566 AW_TRY2 : AW_TRY))) { 02567 result = MA_SKIP; 02568 } else if (TestWF(pwndTop, WFDISABLED)) { 02569 #ifdef NEVER 02570 02571 /* 02572 * Althoug this is what win3 does, it is braindead: it 02573 * can easily cause infinite loops. Returning "rehittest" 02574 * means process this event over again - nothing causes 02575 * anything different to happen, and we get an infinite 02576 * loop. This case never gets executed on win3 because if 02577 * the window is disabled, it got the HTERROR hittest 02578 * code. This can only be done on Win32 where input is 02579 * assigned to a window BEFORE process occurs to pull 02580 * it out of the queue. 02581 */ 02582 result = MA_REHITTEST; 02583 #endif 02584 02585 /* 02586 * Someone clicked on a window before it was disabled... 02587 * Since it is disabled now, don't send this message to 02588 * it: instead eat it. 02589 */ 02590 result = MA_SKIP; 02591 } else if (result == MA_ACTIVATEANDEAT) { 02592 result = MA_SKIP; 02593 } else { 02594 result = MA_PASSTHRU; 02595 goto ItsActiveJustCheckOnTop; 02596 } 02597 break; 02598 02599 case MA_NOACTIVATEANDEAT: 02600 result = MA_SKIP; 02601 break; 02602 } 02603 } 02604 } else { 02605 ItsActiveJustCheckOnTop: 02606 /* 02607 * Make sure this active window is on top (see comment 02608 * in CheckOnTop). 02609 */ 02610 if (TestUP(ACTIVEWINDOWTRACKING)) { 02611 if (CheckOnTop(pti, pwndTop, message)) { 02612 /* 02613 * The window was z-ordered to the top. 02614 * If it is a console window, skip the message 02615 * so it won't go into "selecting" mode 02616 * Hard error boxes are created by csrss as well 02617 * If we have topmost console windows someday, this 02618 * will need to change 02619 */ 02620 if ((ht == HTCLIENT) 02621 && (GETPTI(pwndTop)->TIF_flags & TIF_CSRSSTHREAD) 02622 && !(TestWF(pwndTop, WEFTOPMOST))) { 02623 02624 RIPMSG2(RIP_WARNING, "xxxMouseActivate: Skipping msg %#lx for pwnd %#p", 02625 message, pwndTop); 02626 result = MA_SKIP; 02627 } 02628 } 02629 } /* if (TestUP(ACTIVEWINDOWTRACKING)) */ 02630 } 02631 02632 /* 02633 * Now set the cursor shape. 02634 */ 02635 if (pti->pq->spwndCapture == NULL) { 02636 xxxSendMessage(pwnd, WM_SETCURSOR, (WPARAM)HW(pwnd), 02637 MAKELONG((SHORT)ht, message)); 02638 } 02639 02640 ThreadUnlock(&tlpwndTop); 02641 return result; 02642 }

BOOL xxxReadPostMessage PTHREADINFO  pti,
LPMSG  lpMsg,
PWND  pwndFilter,
UINT  msgMin,
UINT  msgMax,
BOOL  fRemoveMsg
 

Definition at line 3499 of file queue.c.

References BOOL, CheckMsgFilter, CheckProcessForeground(), CheckQuitMessage(), CheckRemoveHotkeyBit(), tagMLIST::cMsgs, tagTHREADINFO::cQuit, DelQEntry(), tagQ::ExtraInfo, tagQMSG::ExtraInfo, FALSE, FindQMsg(), tagCLIENTTHREADINFO::fsChangeBits, tagCLIENTTHREADINFO::fsWakeBits, tagTHREADINFO::idLast, tagTHREADINFO::mlPost, tagQMSG::msg, MSGFLAG_DDE_MID_THUNK, NULL, tagTHREADINFO::pcti, tagTHREADINFO::pq, tagMLIST::pqmsgRead, tagTHREADINFO::ptLast, tagTHREADINFO::TIF_flags, TIF_MSGPOSCHANGED, TIF_SPINNING, tagTHREADINFO::timeLast, TraceDdeMsg, TRUE, UINT, and xxxDDETrackGetMessageHook().

Referenced by xxxInternalGetMessage().

03506 { 03507 PQMSG pqmsg; 03508 PMLIST pmlPost; 03509 03510 /* 03511 * Check to see if it is time to generate a quit message. 03512 */ 03513 if (CheckQuitMessage(pti, lpMsg, fRemoveMsg)) 03514 return TRUE; 03515 03516 /* 03517 * Loop through the messages in this list looking for the one that 03518 * fits the passed in filters. 03519 */ 03520 pmlPost = &pti->mlPost; 03521 pqmsg = FindQMsg(pti, pmlPost, pwndFilter, msgMin, msgMax, FALSE); 03522 if (pqmsg == NULL) { 03523 /* 03524 * Check again for quit... FindQMsg deletes some messages 03525 * in some instances, so we may match the conditions 03526 * for quit generation here. 03527 */ 03528 if (CheckQuitMessage(pti, lpMsg, fRemoveMsg)) 03529 return TRUE; 03530 } else { 03531 /* 03532 * Update the thread info fields with the info from this qmsg. 03533 */ 03534 pti->timeLast = pqmsg->msg.time; 03535 if (!RtlEqualMemory(&pti->ptLast, &pqmsg->msg.pt, sizeof(POINT))) { 03536 pti->TIF_flags |= TIF_MSGPOSCHANGED; 03537 } 03538 pti->ptLast = pqmsg->msg.pt; 03539 03540 pti->idLast = (ULONG_PTR)pqmsg; 03541 pti->pq->ExtraInfo = pqmsg->ExtraInfo; 03542 03543 /* 03544 * Are we supposed to yank out the message? If not, stick some 03545 * random id into idLast so we don't unlock the input queue until we 03546 * pull this message from the queue. 03547 */ 03548 *lpMsg = pqmsg->msg; 03549 if (!fRemoveMsg) { 03550 pti->idLast = 1; 03551 } else { 03552 /* 03553 * If we're removing a WM_HOTKEY message, we may need to 03554 * clear the QS_HOTKEY bit, since we have a special bit 03555 * for that message. 03556 */ 03557 if (pmlPost->pqmsgRead->msg.message == WM_HOTKEY) { 03558 CheckRemoveHotkeyBit(pti, pmlPost); 03559 } 03560 03561 03562 /* 03563 * Since we're removing an event from the queue, we 03564 * need to check priority. This resets the TIF_SPINNING 03565 * since we're no longer spinning. 03566 */ 03567 // We disable all MS badapp code and do it our way 03568 if (pti->TIF_flags & TIF_SPINNING) 03569 CheckProcessForeground(pti); 03570 03571 DelQEntry(pmlPost, pqmsg); 03572 } 03573 03574 /* 03575 * See if this is a dde message that needs to be fixed up. 03576 */ 03577 if (CheckMsgFilter(lpMsg->message, 03578 (WM_DDE_FIRST + 1) | MSGFLAG_DDE_MID_THUNK, 03579 WM_DDE_LAST | MSGFLAG_DDE_MID_THUNK)) { 03580 /* 03581 * Fixup the message value. 03582 */ 03583 lpMsg->message &= (UINT)~MSGFLAG_DDE_MID_THUNK; 03584 03585 /* 03586 * Call back the client to allocate the dde data for this message. 03587 */ 03588 xxxDDETrackGetMessageHook(lpMsg); 03589 03590 /* 03591 * Copy these values back into the queue if this message hasn't 03592 * been removed from the queue. Need to search through the 03593 * queue again because the pqmsg may have been removed when 03594 * we left the critical section above. 03595 */ 03596 if (!fRemoveMsg) { 03597 if (pqmsg == FindQMsg(pti, pmlPost, pwndFilter, msgMin, msgMax, FALSE)) { 03598 pqmsg->msg = *lpMsg; 03599 } 03600 } 03601 } 03602 #if DBG 03603 else if (CheckMsgFilter(lpMsg->message, WM_DDE_FIRST, WM_DDE_LAST)) { 03604 if (fRemoveMsg) { 03605 TraceDdeMsg(lpMsg->message, (HWND)lpMsg->wParam, lpMsg->hwnd, MSG_RECV); 03606 } else { 03607 TraceDdeMsg(lpMsg->message, (HWND)lpMsg->wParam, lpMsg->hwnd, MSG_PEEK); 03608 } 03609 } 03610 #endif 03611 } 03612 03613 /* 03614 * If there are no posted messages available, clear the post message 03615 * bit so we don't go looking for them again. 03616 */ 03617 if (pmlPost->cMsgs == 0 && pti->cQuit == 0) { 03618 pti->pcti->fsWakeBits &= ~(QS_POSTMESSAGE | QS_ALLPOSTMESSAGE); 03619 pti->pcti->fsChangeBits &= ~QS_ALLPOSTMESSAGE; 03620 } 03621 03622 return pqmsg != NULL; 03623 }

BOOL xxxScanSysQueue PTHREADINFO  ptiCurrent,
LPMSG  lpMsg,
PWND  pwndFilter,
UINT  msgMinFilter,
UINT  msgMaxFilter,
DWORD  flags,
DWORD  fsReason
 

Definition at line 3305 of file ntuser/kernel/input.c.

References _PostMessage(), BOOL, tagKBDLANGTOGGLE::bScan, tagKBDLANGTOGGLE::bVkey, BYTE, CFDBLCLKS, CheckMsgFilter, CheckProcessForeground(), CheckPtiSysPeek, CheckPwndFilter(), CheckSysLock, CleanEventMessage(), ClearWakeBit(), CLIENT_CAPTURE, tagQ::codeCapture, tagCLIENTTHREADINFO::CTIF_flags, CTIF_SYSQUEUELOCKED, DelQEntry(), DF_TRACKMOUSEHOVER, DUMPPATHTAKEN, DUMPSUBPATHTAKEN, tagDESKTOP::dwDTFlags, tagKL::dwFontSigs, DWORD, tagQMSG::dwQEvent, _CLIENTINFO::dwTIFlags, tagQ::ExtraInfo, tagQMSG::ExtraInfo, FALSE, FindNCHitEx(), tagPOPUPMENU::fIsMenuBar, FJOURNALPLAYBACK, tagMENUSTATE::fModelessMenu, tagCLIENTTHREADINFO::fsChangeBits, tagTHREADINFO::fsReserveKeys, tagCLIENTTHREADINFO::fsWakeBits, tagCLIENTTHREADINFO::fsWakeBitsJournal, FWINABLE, gbClientDoubleClickSupport, gbGraveKeyToggle, gcHotKey, gdtDblClk, GetAppImeCompatFlags(), GetMouseKeyFlags(), GETPTI, gfEnableHexNumpad, gfInNumpadHexInput, gLangToggle, gLangToggleKeyState, gpImeHotKeyListHeader, gpqCursor, gptiRit, gspklBaseLayout, gspwndScreenCapture, gSystemFS, tagKL::hkl, HKLtoPKL(), HotKeyToWindow(), tagDESKTOP::htEx, HW, tagQ::hwndDblClk, HWq, tagKBDLANGTOGGLE::iBitPosition, tagTHREADINFO::idLast, tagQ::idSysLock, tagQ::idSysPeek, IPHK_HOTKEY, IPHK_PROCESSBYIME, IsHooked, IsInsideMenuLoop(), IsMenuStarted(), IsWinEventNotifyDeferredOK, KEYBOARD_MENU, KLT_ALTBOTHSHIFTS, KLT_ALTLEFTSHIFT, KLT_ALTRIGHTSHIFT, KLT_NONE, L, LANGTOGGLEKEYS_SIZE, LOBYTE, MA_REHITTEST, MA_SKIP, tagQ::mlInput, tagQMSG::msg, tagQ::msgDblClk, NO_CAP_CLIENT, NO_CAP_SYS, NULL, NUMPAD_HEXMODE_HL, PATHTAKEN, PATHTAKEN2, PATHTAKEN3, tagTHREADINFO::pClientInfo, tagTHREADINFO::pcti, tagDESKTOP::pDeskInfo, tagMENUSTATE::pGlobalPopupMenu, tagTHREADINFO::pMenuState, tagTHREADINFO::pmsd, tagTHREADINFO::pq, PQMSG_PLAYBACK, tagMLIST::pqmsgRead, tagQ::ptDblClk, tagQMSG::pti, PtInRect(), tagQ::ptiSysLock, tagTHREADINFO::ptl, tagTHREADINFO::ptLast, PtoH, QEVENT_ASYNCSENDMSG, QEVENT_UPDATEKEYSTATE, QF_DIALOGACTIVE, tagQ::QF_flags, QF_FMENUSTATUS, QF_FMENUSTATUSBREAK, QF_LOCKNOREMOVE, QMSG, tagWND::rcClient, tagDESKTOP::rcMouseHover, tagWND::rcWindow, ResetMouseHover(), RevalidateHwnd, tagTHREADINFO::rpdesk, SetWakeBit(), tagTHREADINFO::spklActive, _MOVESIZEDATA::spwnd, tagDESKTOPINFO::spwnd, tagQ::spwndActive, tagQ::spwndCapture, tagQ::spwndFocus, tagPOPUPMENU::spwndNotify, tagDESKTOP::spwndTrack, SYSCUR, SYSMET, TestCF, TestKeyStateDown, TestWF, ThreadLockAlwaysWithPti, ThreadLockExchange(), ThreadLockWithPti, ThreadUnlock, TIF_16BIT, TIF_CSRSSTHREAD, TIF_DELAYEDEVENT, TIF_DISABLEIME, tagTHREADINFO::TIF_flags, TIF_MOVESIZETRACKING, TIF_MSGPOSCHANGED, TIF_SPINNING, tagQ::timeDblClk, tagTHREADINFO::timeLast, TransferWakeBit(), TRUE, UINT, tagTHREADINFO::wchInjected, WHF_CBT, WHF_KEYBOARD, WHF_MOUSE, WHT_IGNOREDISABLED, WINDOW_CAPTURE, tagQ::xbtnDblClk, xxxCallHandleMenuMessages(), xxxCallHook(), xxxCallMouseHook(), xxxGetNextSysMsg(), xxxImmProcessKey(), xxxMouseActivate(), xxxProcessEventMessage(), xxxSendMessage(), xxxSkipSysMsg(), xxxSnapWindow(), xxxTrackMouseMove(), xxxWindowEvent(), xxxWindowHitTest(), and zzzSetCursor().

Referenced by xxxInternalGetMessage().

03313 { 03314 QMSG qmsg; 03315 HWND hwnd; 03316 PWND pwnd; 03317 UINT message; 03318 WPARAM wParam; 03319 LPARAM lParam; 03320 PTHREADINFO ptiKeyWake, ptiMouseWake, ptiEventWake; 03321 POINT pt, ptScreen; 03322 UINT codeMouseDown; 03323 BOOL fMouseHookCalled; 03324 BOOL fKbdHookCalled; 03325 BOOL fOtherApp; 03326 int part; 03327 MOUSEHOOKSTRUCTEX mhs; 03328 PWND pwndT; 03329 BOOL fPrevDown; 03330 BOOL fDown; 03331 BOOL fAlt; 03332 TL tlpwnd; 03333 TL tlpwndT; 03334 BOOL fRemove = (flags & PM_REMOVE); 03335 #ifdef FE_IME 03336 DWORD dwImmRet = 0; 03337 #endif 03338 #ifdef MARKPATH 03339 DWORD pathTaken = 0; 03340 DWORD pathTaken2 = 0; 03341 DWORD pathTaken3 = 0; 03342 03343 #define PATHTAKEN(x) pathTaken |= x 03344 #define PATHTAKEN2(x) pathTaken2 |= x 03345 #define PATHTAKEN3(x) pathTaken3 |= x 03346 #define DUMPPATHTAKEN() if (gfMarkPath) DbgPrint("xxxScanSysQueue path:%08x %08x %08x\n", pathTaken, pathTaken2, pathTaken3) 03347 #define DUMPSUBPATHTAKEN(p, x) if (gfMarkPath && p & x) { DbgPrint(" %08x %08x %08x\n", pathTaken, pathTaken2, pathTaken3); pathTaken = pathTaken2 = pathTaken3 = 0; } 03348 #else 03349 #define PATHTAKEN(x) 03350 #define PATHTAKEN2(x) 03351 #define PATHTAKEN3(x) 03352 #define DUMPPATHTAKEN() 03353 #define DUMPSUBPATHTAKEN(p, x) 03354 #endif 03355 03356 UserAssert(IsWinEventNotifyDeferredOK()); 03357 UserAssert((fsReason & ~(QS_EVENT | QS_INPUT)) == 0 && 03358 (fsReason & (QS_EVENT | QS_INPUT)) != 0); 03359 03360 /* 03361 * If we are looking at a peeked message currently (recursion into this 03362 * routine) and the only reason we got here was because of an event 03363 * message (an app was filtering for a non-input message), then just 03364 * return so we don't screw up idSysPeek. If we do enter this code 03365 * idSysPeek will get set back to 0, and when we return back into 03366 * the previous xxxScanSysQueue(), SkipSysMsg() will do nothing, so the 03367 * message won't get removed. (MS Publisher 2.0 does this). 03368 */ 03369 if (fsReason == QS_EVENT) { 03370 if (ptiCurrent->pq->idSysPeek != 0) { 03371 PATHTAKEN(1); 03372 DUMPPATHTAKEN(); 03373 return FALSE; 03374 } 03375 } 03376 03377 fDown = FALSE; 03378 fMouseHookCalled = FALSE; 03379 fKbdHookCalled = FALSE; 03380 03381 /* 03382 * Lock the queue if it's currently unlocked. 03383 */ 03384 if (ptiCurrent->pq->ptiSysLock == NULL) { 03385 CheckSysLock(3, ptiCurrent->pq, ptiCurrent); 03386 ptiCurrent->pq->ptiSysLock = ptiCurrent; 03387 ptiCurrent->pcti->CTIF_flags |= CTIF_SYSQUEUELOCKED; 03388 } 03389 03390 /* 03391 * Flag to tell if locker was removing messages. If not, then next time 03392 * Get/PeekMessage is called, the input message list is scanned before the 03393 * post msg list. 03394 * 03395 * Under Win3.1, this flag only gets modified for key and mouse messages. 03396 * Since under NT ScanSysQueue() can be called to execute event messages, 03397 * we make this check to be compatible. 03398 */ 03399 if (fsReason & QS_INPUT) { 03400 if (fRemove) { 03401 PATHTAKEN(2); 03402 ptiCurrent->pq->QF_flags &= ~QF_LOCKNOREMOVE; 03403 } else { 03404 PATHTAKEN(4); 03405 ptiCurrent->pq->QF_flags |= QF_LOCKNOREMOVE; 03406 } 03407 } 03408 03409 /* 03410 * Return FALSE if the current thread is not the one that lock this queue. 03411 */ 03412 if (ptiCurrent->pq->ptiSysLock != ptiCurrent) { 03413 PATHTAKEN(8); 03414 DUMPPATHTAKEN(); 03415 return FALSE; 03416 } 03417 03418 ptiEventWake = ptiKeyWake = ptiMouseWake = NULL; 03419 03420 /* 03421 * Initialize the thread lock structure here so we can unlock/lock in 03422 * the main loop. 03423 */ 03424 pwnd = NULL; 03425 ThreadLockWithPti(ptiCurrent, pwnd, &tlpwnd); 03426 03427 RestartScan: 03428 CheckPtiSysPeek(2, ptiCurrent->pq, 0); 03429 ptiCurrent->pq->idSysPeek = 0; 03430 03431 ContinueScan: 03432 while (TRUE) { 03433 ULONG_PTR idSysPeek; 03434 03435 DUMPSUBPATHTAKEN(pathTaken, 0xf0); 03436 /* 03437 * Store idSysPeek in a local which forces pq to be reloaded 03438 * in case it changed during the xxx call (the compiler can 03439 * evaluate the LValue at any time) 03440 */ 03441 idSysPeek = (ULONG_PTR)xxxGetNextSysMsg(ptiCurrent, 03442 (PQMSG)ptiCurrent->pq->idSysPeek, &qmsg); 03443 CheckPtiSysPeek(3, ptiCurrent->pq, idSysPeek); 03444 ptiCurrent->pq->idSysPeek = idSysPeek; 03445 03446 if (ptiCurrent->pq->idSysPeek == 0) { 03447 /* 03448 * If we are only looking for event messages and we didn't 03449 * find any, then clear the QS_EVENT bit 03450 */ 03451 if (fsReason == QS_EVENT) 03452 ClearWakeBit(ptiCurrent, QS_EVENT, FALSE); 03453 PATHTAKEN(0x10); 03454 goto NoMessages; 03455 } 03456 03457 /* 03458 * pwnd should be locked for the duration of this routine. 03459 * For most messages right out of GetNextSysMsg, this is 03460 * NULL. 03461 */ 03462 ThreadUnlock(&tlpwnd); 03463 pwnd = RevalidateHwnd(qmsg.msg.hwnd); 03464 ThreadLockWithPti(ptiCurrent, pwnd, &tlpwnd); 03465 03466 /* 03467 * See if this is an event message. If so, execute it regardless 03468 * of message and window filters, but only if it is the first element 03469 * of the input queue. 03470 */ 03471 if (qmsg.dwQEvent != 0) { 03472 PTHREADINFO pti; 03473 03474 PATHTAKEN(0x20); 03475 /* 03476 * Most event messages can be executed out of order relative to 03477 * its place in the queue. There are some examples were this is 03478 * not allowed, and we check that here. For example, we would not 03479 * want a keystate synchronization event to be processed before 03480 * the keystrokes that came before it in the queue! 03481 * 03482 * We need to have most event messages be able to get processed 03483 * out of order because apps can be filtering for message ranges 03484 * that don't include input (like dde) - those scenarios still 03485 * need to process events such as deactivate event messages even 03486 * if there is input in the input queue. 03487 */ 03488 switch (qmsg.dwQEvent) { 03489 case QEVENT_UPDATEKEYSTATE: 03490 /* 03491 * If the message is not the next message in the queue, don't 03492 * process it. 03493 */ 03494 if (ptiCurrent->pq->idSysPeek != 03495 (ULONG_PTR)ptiCurrent->pq->mlInput.pqmsgRead) { 03496 PATHTAKEN(0x40); 03497 continue; 03498 } 03499 break; 03500 } 03501 03502 /* 03503 * If this event isn't for this thread, wake the thread it is 03504 * for. A NULL qmsg.hti means that any thread can process 03505 * the event. 03506 */ 03507 if (qmsg.pti != NULL && (pti = qmsg.pti) != ptiCurrent) { 03508 03509 /* 03510 * If somehow this event message got into the wrong queue, 03511 * then ignore it. 03512 */ 03513 UserAssert(pti->pq == ptiCurrent->pq); 03514 if (pti->pq != ptiCurrent->pq) { 03515 CleanEventMessage((PQMSG)ptiCurrent->pq->idSysPeek); 03516 DelQEntry(&ptiCurrent->pq->mlInput, 03517 (PQMSG)ptiCurrent->pq->idSysPeek); 03518 PATHTAKEN(0x80); 03519 goto RestartScan; 03520 } 03521 03522 /* 03523 * If ptiEventWake is already set, it means we've already 03524 * found a thread to wake for event. 03525 */ 03526 if (ptiEventWake == NULL) 03527 ptiEventWake = pti; 03528 03529 /* 03530 * Clear idSysPeek so that the targeted thread 03531 * can always get it. Look at the test at the 03532 * start of this routine for more info. 03533 */ 03534 CheckPtiSysPeek(4, ptiCurrent->pq, 0); 03535 ptiCurrent->pq->idSysPeek = 0; 03536 PATHTAKEN(0x100); 03537 goto NoMessages; 03538 } 03539 03540 /* 03541 * If this is called with PM_NOYIELD from a 16-bit app, skip 03542 * processing any event that can generate activation messages. An 03543 * example is printing from PageMaker 5.0. Bug #12662. 03544 */ 03545 if ((flags & PM_NOYIELD) && (ptiCurrent->TIF_flags & TIF_16BIT)) { 03546 PATHTAKEN(0x200); 03547 switch (qmsg.dwQEvent) { 03548 03549 /* 03550 * The following events are safe to process if no yield 03551 * is to occur. 03552 */ 03553 case QEVENT_UPDATEKEYSTATE: 03554 case QEVENT_ASYNCSENDMSG: 03555 break; 03556 03557 /* 03558 * Skip all other events. 03559 */ 03560 default: 03561 ptiCurrent->TIF_flags |= TIF_DELAYEDEVENT; 03562 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; 03563 PATHTAKEN(0x400); 03564 goto ContinueScan; 03565 } 03566 } 03567 03568 /* 03569 * Delete this before it gets processed so there are no 03570 * recursion problems. 03571 */ 03572 DelQEntry(&ptiCurrent->pq->mlInput, 03573 (PQMSG)ptiCurrent->pq->idSysPeek); 03574 03575 /* 03576 * Clear idSysPeek before processing any events messages, because 03577 * they may recurse and want to use idSysPeek. 03578 */ 03579 CheckPtiSysPeek(5, ptiCurrent->pq, 0); 03580 ptiCurrent->pq->idSysPeek = 0; 03581 xxxProcessEventMessage(ptiCurrent, &qmsg); 03582 03583 /* 03584 * Restart the scan from the start so we start with 0 in 03585 * pq->idSysPeek (since that message is now gone!). 03586 */ 03587 PATHTAKEN(0x800); 03588 goto RestartScan; 03589 } 03590 03591 /* 03592 * If the reason we called was just to process event messages, don't 03593 * enumerate any other mouse or key messages! 03594 */ 03595 if (fsReason == QS_EVENT) { 03596 PATHTAKEN(0x1000); 03597 continue; 03598 } 03599 03600 switch (message = qmsg.msg.message) { 03601 case WM_QUEUESYNC: 03602 PATHTAKEN(0x2000); 03603 /* 03604 * This message is for CBT. Its parameters should already be 03605 * set up correctly. 03606 */ 03607 wParam = 0; 03608 lParam = qmsg.msg.lParam; 03609 03610 /* 03611 * Check if this is intended for the current app. Use the mouse 03612 * bit for WM_QUEUESYNC. 03613 */ 03614 if (pwnd != NULL && GETPTI(pwnd) != ptiCurrent) { 03615 /* 03616 * If this other app isn't going to read from this 03617 * queue, then skip this message. This can happen with 03618 * WM_QUEUESYNC if the app passed a window handle 03619 * to the wrong queue. This isn't likely to happen in 03620 * this case because WM_QUEUESYNCs come in while journalling, 03621 * which has all threads sharing the same queue. 03622 */ 03623 if (GETPTI(pwnd)->pq != ptiCurrent->pq) { 03624 PATHTAKEN(0x4000); 03625 goto SkipMessage; 03626 } 03627 03628 if (ptiMouseWake == NULL) 03629 ptiMouseWake = GETPTI(pwnd); 03630 PATHTAKEN(0x8000); 03631 goto NoMessages; 03632 } 03633 03634 if (!CheckMsgFilter(message, msgMinFilter, msgMaxFilter)) { 03635 PATHTAKEN(0x10000); 03636 goto NoMessages; 03637 } 03638 03639 /* 03640 * Eat the message. 03641 */ 03642 if (fRemove) { 03643 xxxSkipSysMsg(ptiCurrent, &qmsg); 03644 } 03645 03646 /* 03647 * !!HARDWARE HOOK!! goes here. 03648 */ 03649 03650 /* 03651 * Return the message. 03652 */ 03653 PATHTAKEN(0x20000); 03654 goto ReturnMessage; 03655 break; 03656 03657 /* 03658 * Mouse message or generic hardware messages 03659 * Key messages are handled in case statements 03660 * further down in this switch. 03661 */ 03662 default: 03663 ReprocessMsg: 03664 DUMPSUBPATHTAKEN(pathTaken, 0x40000); 03665 PATHTAKEN(0x40000); 03666 /* 03667 * !!GENERIC HARDWARE MESSAGE!! support goes here. 03668 */ 03669 03670 /* 03671 * Take the mouse position out of the message. 03672 */ 03673 pt.x = (int)(short)LOWORD(qmsg.msg.lParam); 03674 pt.y = (int)(short)HIWORD(qmsg.msg.lParam); 03675 03676 /* 03677 * Assume we have a capture. 03678 */ 03679 part = HTCLIENT; 03680 03681 /* 03682 * We have a special global we use for when we're full screen. 03683 * All mouse input will go to this window. 03684 */ 03685 if (gspwndScreenCapture != NULL) { 03686 /* 03687 * Change the mouse coordinates to full screen. 03688 */ 03689 pwnd = gspwndScreenCapture; 03690 lParam = MAKELONG((WORD)qmsg.msg.pt.x, 03691 (WORD)qmsg.msg.pt.y); 03692 PATHTAKEN(0x80000); 03693 } else if ((pwnd = ptiCurrent->pq->spwndCapture) == NULL) { 03694 03695 PATHTAKEN(0x100000); 03696 /* 03697 * We don't have the capture. Figure out which window owns 03698 * this message. 03699 * 03700 * NOTE: Use gptiRit and not ptiCurrent to get the desktop 03701 * window because if ptiCurrent is the thread that created 03702 * the main desktop, it's associated desktop is the logon 03703 * desktop - don't want to hittest against the logon desktop 03704 * while switched into the main desktop! 03705 */ 03706 pwndT = gptiRit->rpdesk->pDeskInfo->spwnd; 03707 03708 ThreadLockWithPti(ptiCurrent, pwndT, &tlpwndT); 03709 03710 hwnd = xxxWindowHitTest(pwndT, pt, &part, WHT_IGNOREDISABLED); 03711 ThreadUnlock(&tlpwndT); 03712 03713 if ((pwnd = RevalidateHwnd(hwnd)) == NULL) { 03714 pwnd = ptiCurrent->rpdesk->pDeskInfo->spwnd; 03715 PATHTAKEN(0x200000); 03716 } 03717 03718 if (part == HTCLIENT) { 03719 /* 03720 * Part of the client... normal mouse message. 03721 * NO_CAP_CLIENT means "not captured, in client area 03722 * of window". 03723 */ 03724 ptiCurrent->pq->codeCapture = NO_CAP_CLIENT; 03725 PATHTAKEN(0x400000); 03726 } else { 03727 /* 03728 * Not part of the client... must be an NCMOUSEMESSAGE. 03729 * NO_CAP_SYS is a creative name by raor which means 03730 * "not captured, in system area of window." 03731 */ 03732 ptiCurrent->pq->codeCapture = NO_CAP_SYS; 03733 PATHTAKEN(0x800000); 03734 } 03735 } 03736 03737 /* 03738 * We've reassigned pwnd, so lock it. 03739 */ 03740 ThreadLockExchange(pwnd, &tlpwnd); 03741 03742 if (fOtherApp = (GETPTI(pwnd) != ptiCurrent)) { 03743 03744 PATHTAKEN(0x1000000); 03745 /* 03746 * If this other app isn't going to read from this 03747 * queue, then skip this message. This can happen if 03748 * the RIT queues up a message thinking it goes to 03749 * a particular hwnd, but then by the time GetMessage() 03750 * is called for that thread, it doesn't go to that hwnd 03751 * (like in the case of mouse messages, window rearrangement 03752 * happens which changes which hwnd the mouse hits on). 03753 */ 03754 if (GETPTI(pwnd)->pq != ptiCurrent->pq) { 03755 zzzSetCursor(SYSCUR(ARROW)); 03756 PATHTAKEN(0x2000000); 03757 goto SkipMessage; 03758 } 03759 03760 /* 03761 * If we haven't already found a message that is intended 03762 * for another app, remember that we have one. 03763 */ 03764 if (ptiMouseWake == NULL) { 03765 ptiMouseWake = GETPTI(pwnd); 03766 PATHTAKEN(0x4000000); 03767 } 03768 } 03769 03770 /* 03771 * Map mouse coordinates based on hit test area code. 03772 */ 03773 ptScreen = pt; 03774 switch (ptiCurrent->pq->codeCapture) { 03775 case CLIENT_CAPTURE: 03776 case NO_CAP_CLIENT: 03777 #ifdef USE_MIRRORING 03778 //Screen To Client 03779 if (TestWF(pwnd, WEFLAYOUTRTL)) { 03780 pt.x = pwnd->rcClient.right - pt.x; 03781 } else 03782 #endif 03783 { 03784 pt.x -= pwnd->rcClient.left; 03785 } 03786 pt.y -= pwnd->rcClient.top; 03787 PATHTAKEN2(2); 03788 break; 03789 03790 case WINDOW_CAPTURE: 03791 #ifdef USE_MIRRORING 03792 //Screen To Window 03793 if (TestWF(pwnd, WEFLAYOUTRTL)) { 03794 pt.x = pwnd->rcWindow.right - pt.x; 03795 } else 03796 #endif 03797 { 03798 pt.x -= pwnd->rcWindow.left; 03799 } 03800 pt.y -= pwnd->rcWindow.top; 03801 PATHTAKEN2(4); 03802 break; 03803 } 03804 03805 /* 03806 * Track mouse moves when it moves to a different window or 03807 * a different hit-test area for hot-tracking, tooltips, 03808 * active window tracking and TrackMouseEvent. 03809 * Mouse clicks reset tracking state too. 03810 * Do it only if the message is for the current thread; 03811 * otherwise, the hit test code (part) is not valid 03812 * (it's always HTCLIENT; see xxxWindowHitTest2). 03813 * Tracking will take place when that thread wakes up 03814 * We also don't do it if this thread is not on pqCursor; 03815 * that would be the case for a slow app that gets the 03816 * input message when the mouse has already left its queue 03817 */ 03818 if (!fOtherApp && (ptiCurrent->pq == gpqCursor)) { 03819 BOOL fNewpwndTrack = (ptiCurrent->rpdesk->spwndTrack != pwnd); 03820 int htEx = FindNCHitEx(pwnd, part, pt); 03821 if ((message != WM_MOUSEMOVE) 03822 || fNewpwndTrack 03823 || (ptiCurrent->rpdesk->htEx != htEx)) { 03824 03825 xxxTrackMouseMove(pwnd, htEx, message); 03826 ValidateThreadLocks(NULL, ptiCurrent->ptl, (ULONG_PTR)&tlpwnd, TRUE); 03827 } 03828 03829 /* 03830 * Reset mouse hovering if needed. 03831 * 03832 */ 03833 if (!fNewpwndTrack && (ptiCurrent->rpdesk->dwDTFlags & DF_TRACKMOUSEHOVER)) { 03834 if ((message != WM_MOUSEMOVE) 03835 || !PtInRect(&ptiCurrent->rpdesk->rcMouseHover, ptScreen)) { 03836 03837 ResetMouseHover(ptiCurrent->rpdesk, ptScreen); 03838 } 03839 } else { 03840 /* 03841 * Hover must be canceled. 03842 */ 03843 UserAssert(!(ptiCurrent->rpdesk->dwDTFlags & DF_TRACKMOUSEHOVER)); 03844 } 03845 03846 } /* if (!fOtherApp.... */ 03847 03848 /* 03849 * Now see if it matches the window handle filter. If not, 03850 * get the next message. 03851 */ 03852 if (!CheckPwndFilter(pwnd, pwndFilter)) { 03853 PATHTAKEN(0x8000000); 03854 continue; 03855 } 03856 03857 /* 03858 * See if we need to map to a double click. 03859 */ 03860 codeMouseDown = 0; 03861 switch (message) { 03862 case WM_LBUTTONDOWN: 03863 case WM_RBUTTONDOWN: 03864 case WM_MBUTTONDOWN: 03865 case WM_XBUTTONDOWN: 03866 if (TestCF(pwnd, CFDBLCLKS) || 03867 ptiCurrent->pq->codeCapture == NO_CAP_SYS || 03868 IsMenuStarted(ptiCurrent)) { 03869 codeMouseDown++; 03870 PATHTAKEN(0x10000000); 03871 if (qmsg.msg.time <= ptiCurrent->pq->timeDblClk && 03872 (!gbClientDoubleClickSupport) && 03873 HW(pwnd) == ptiCurrent->pq->hwndDblClk && 03874 message == ptiCurrent->pq->msgDblClk && 03875 (message != WM_XBUTTONDOWN || 03876 GET_XBUTTON_WPARAM(qmsg.msg.wParam) == ptiCurrent->pq->xbtnDblClk)) { 03877 RECT rcDblClk = { 03878 ptiCurrent->pq->ptDblClk.x - SYSMET(CXDOUBLECLK) / 2, 03879 ptiCurrent->pq->ptDblClk.y - SYSMET(CYDOUBLECLK) / 2, 03880 ptiCurrent->pq->ptDblClk.x + SYSMET(CXDOUBLECLK) / 2, 03881 ptiCurrent->pq->ptDblClk.y + SYSMET(CYDOUBLECLK) / 2 03882 }; 03883 if (PtInRect(&rcDblClk, qmsg.msg.pt)) { 03884 message += (WM_LBUTTONDBLCLK - WM_LBUTTONDOWN); 03885 codeMouseDown++; 03886 PATHTAKEN(0x20000000); 03887 } 03888 } 03889 } 03890 03891 // FALL THROUGH!!! 03892 03893 case WM_LBUTTONUP: 03894 case WM_RBUTTONUP: 03895 case WM_MBUTTONUP: 03896 case WM_XBUTTONUP: 03897 /* 03898 * Note that the mouse button went up or down if we were 03899 * in menu status mode of alt-key down 03900 */ 03901 03902 PATHTAKEN(0x40000000); 03903 if (ptiCurrent->pq->QF_flags & QF_FMENUSTATUS) { 03904 ptiCurrent->pq->QF_flags |= QF_FMENUSTATUSBREAK; 03905 PATHTAKEN(0x80000000); 03906 } 03907 } 03908 03909 /* 03910 * Map message number based on hit test area code. 03911 */ 03912 if (ptiCurrent->pq->codeCapture == NO_CAP_SYS) { 03913 message += (UINT)(WM_NCMOUSEMOVE - WM_MOUSEMOVE); 03914 wParam = (UINT)part; 03915 PATHTAKEN2(1); 03916 } 03917 03918 /* 03919 * Message number has been mapped: see if it fits the filter. 03920 * If not, get the next message. 03921 */ 03922 if (!CheckMsgFilter(message, msgMinFilter, msgMaxFilter)) { 03923 PATHTAKEN2(8); 03924 continue; 03925 } 03926 03927 /* 03928 * If message is for another app but it fits our filter, then 03929 * we should stop looking for messages: this will ensure that 03930 * we don't keep looking and find and process a message that 03931 * occured later than the one that should be processed by the 03932 * other guy. 03933 */ 03934 if (fOtherApp) { 03935 PATHTAKEN2(0x10); 03936 goto NoMessages; 03937 } 03938 03939 /* 03940 * If we're doing full drag, the mouse messages should go to 03941 * the xxxMoveSize PeekMessage loop. So we get the next message. 03942 * This can happen when an application does a PeekMessage in 03943 * response to a message sent inside the movesize dragging loop. 03944 * This causes the dragging loop to not get the WM_LBUTTONUP 03945 * message and dragging continues after the button is up 03946 * (fix for Micrografx Draw). -johannec 03947 */ 03948 if (message >= WM_MOUSEFIRST && message <= WM_MOUSELAST && 03949 ptiCurrent->TIF_flags & TIF_MOVESIZETRACKING) { 03950 PATHTAKEN2(0x20); 03951 continue; 03952 } 03953 03954 if (FWINABLE() && (ptiCurrent->TIF_flags & TIF_MSGPOSCHANGED)) { 03955 ptiCurrent->TIF_flags &= ~TIF_MSGPOSCHANGED; 03956 xxxWindowEvent(EVENT_OBJECT_LOCATIONCHANGE, NULL, 03957 OBJID_CURSOR, INDEXID_CONTAINER, TRUE); 03958 ValidateThreadLocks(NULL, ptiCurrent->ptl, (ULONG_PTR)&tlpwnd, TRUE); 03959 } 03960 03961 /* 03962 * Let us call the mouse hook to find out if this click is 03963 * permitted by it. 03964 * 03965 * We want to inform the mouse hook before we test for 03966 * HTNOWHERE and HTERROR; Otherwise, the mouse hook won't 03967 * get these messages (sankar 12/10/91). 03968 */ 03969 if (IsHooked(ptiCurrent, WHF_MOUSE)) { 03970 fMouseHookCalled = TRUE; 03971 mhs.pt = qmsg.msg.pt; 03972 mhs.hwnd = HW(pwnd); 03973 mhs.wHitTestCode = (UINT)part; 03974 mhs.dwExtraInfo = qmsg.ExtraInfo; 03975 UserAssert(LOWORD(qmsg.msg.wParam) == 0); 03976 mhs.mouseData = (DWORD)qmsg.msg.wParam; 03977 03978 if (xxxCallMouseHook(message, &mhs, fRemove)) { 03979 /* 03980 * Not allowed by mouse hook; so skip it. 03981 */ 03982 PATHTAKEN2(0x40); 03983 goto SkipMessage; 03984 } 03985 PATHTAKEN2(0x80); 03986 ValidateThreadLocks(NULL, ptiCurrent->ptl, (ULONG_PTR)&tlpwnd, TRUE); 03987 } 03988 03989 /* 03990 * If a HTERROR or HTNOWHERE occured, send the window the 03991 * WM_SETCURSOR message so it can beep or whatever. Then skip 03992 * the message and try the next one. 03993 */ 03994 switch (part) { 03995 case HTERROR: 03996 case HTNOWHERE: 03997 /* 03998 * Now set the cursor shape. 03999 */ 04000 xxxSendMessage(pwnd, WM_SETCURSOR, (WPARAM)HW(pwnd), 04001 MAKELONG(part, qmsg.msg.message)); 04002 04003 /* 04004 * Skip the message. 04005 */ 04006 PATHTAKEN2(0x100); 04007 goto SkipMessage; 04008 break; 04009 } 04010 04011 if (fRemove) { 04012 PATHTAKEN2(0x200); 04013 /* 04014 * Since the processing of a down click may cause the next 04015 * message to be interpreted as a double click, we only want 04016 * to do the double click setup if we're actually going to 04017 * remove the message. Otherwise, the next time we read the 04018 * same message it would be interpreted as a double click. 04019 */ 04020 switch (codeMouseDown) { 04021 case 1: 04022 /* 04023 * Down clock: set up for later possible double click. 04024 */ 04025 ptiCurrent->pq->msgDblClk = qmsg.msg.message; 04026 04027 /* 04028 * Note that even if the following assertion were not true, 04029 * we could still put bogus data in ptiCurrent->pq->xbtnDblClk 04030 * when the message is not WM_XBUTTONDOWN, since when we check 04031 * for dblclick we compare the message number before the xbtnDblClk. 04032 */ 04033 UserAssert(qmsg.msg.message == WM_XBUTTONDOWN || GET_XBUTTON_WPARAM(qmsg.msg.wParam) == 0); 04034 ptiCurrent->pq->xbtnDblClk = GET_XBUTTON_WPARAM(qmsg.msg.wParam); 04035 04036 ptiCurrent->pq->timeDblClk = qmsg.msg.time + gdtDblClk; 04037 ptiCurrent->pq->hwndDblClk = HW(pwnd); 04038 ptiCurrent->pq->ptDblClk = qmsg.msg.pt; 04039 PATHTAKEN2(0x400); 04040 break; 04041 04042 case 2: 04043 /* 04044 * Double click: finish processing. 04045 */ 04046 ptiCurrent->pq->timeDblClk = 0L; 04047 PATHTAKEN2(0x800); 04048 break; 04049 04050 default: 04051 PATHTAKEN2(0x1000); 04052 break; 04053 } 04054 04055 /* 04056 * Set mouse cursor and allow app to activate window 04057 * only if we're removing the message. 04058 */ 04059 switch (xxxMouseActivate(ptiCurrent, pwnd, 04060 qmsg.msg.message, qmsg.msg.wParam, &qmsg.msg.pt, part)) { 04061 SkipMessage: 04062 case MA_SKIP: 04063 DUMPSUBPATHTAKEN(pathTaken2, 0x2000); 04064 PATHTAKEN2(0x2000); 04065 xxxSkipSysMsg(ptiCurrent, &qmsg); 04066 04067 /* 04068 * Inform the CBT hook that we skipped a mouse click. 04069 */ 04070 if (fMouseHookCalled) { 04071 if (IsHooked(ptiCurrent, WHF_CBT)) { 04072 xxxCallHook(HCBT_CLICKSKIPPED, message, 04073 (LPARAM)&mhs, WH_CBT); 04074 PATHTAKEN2(0x4000); 04075 } 04076 fMouseHookCalled = FALSE; 04077 } 04078 04079 /* 04080 * Inform the CBT hook that we skipped a key 04081 */ 04082 if (fKbdHookCalled) { 04083 if (IsHooked(ptiCurrent, WHF_CBT)) { 04084 xxxCallHook(HCBT_KEYSKIPPED, wParam, lParam, 04085 WH_CBT); 04086 PATHTAKEN2(0x8000); 04087 } 04088 fKbdHookCalled = FALSE; 04089 } 04090 04091 /* 04092 * If we aren't removing messages, don't reset idSysPeek 04093 * otherwise we will go into an infinite loop if 04094 * the keyboard hook says to ignore the message. 04095 * (bobgu 4/7/87). 04096 */ 04097 if (!fRemove) { 04098 PATHTAKEN2(0x10000); 04099 goto ContinueScan; 04100 } else { 04101 PATHTAKEN2(0x20000); 04102 goto RestartScan; 04103 } 04104 break; 04105 04106 case MA_REHITTEST: 04107 /* 04108 * Reprocess the message. 04109 */ 04110 PATHTAKEN2(0x40000); 04111 goto ReprocessMsg; 04112 } 04113 } 04114 04115 /* 04116 * Eat the message from the input queue (and set the keystate 04117 * table). 04118 */ 04119 PATHTAKEN2(0x80000); 04120 if (fRemove) { 04121 xxxSkipSysMsg(ptiCurrent, &qmsg); 04122 } 04123 04124 if (fRemove && fMouseHookCalled && IsHooked(ptiCurrent, WHF_CBT)) { 04125 xxxCallHook(HCBT_CLICKSKIPPED, message, 04126 (LPARAM)&mhs, WH_CBT); 04127 } 04128 fMouseHookCalled = FALSE; 04129 04130 lParam = MAKELONG((short)pt.x, (short)pt.y); 04131 04132 /* 04133 * Calculate virtual key state bitmask for wParam. 04134 */ 04135 if (message >= WM_MOUSEFIRST) { 04136 /* 04137 * This is a USER mouse message. Calculate the bit mask for the 04138 * virtual key state. 04139 */ 04140 wParam = GetMouseKeyFlags(ptiCurrent->pq); 04141 PATHTAKEN2(0x100000); 04142 } 04143 04144 if ( (WM_NCXBUTTONFIRST <= message && message <= WM_NCXBUTTONLAST) || 04145 (WM_XBUTTONFIRST <= message && message <= WM_XBUTTONLAST)) { 04146 04147 /* 04148 * The hiword of wParam is assigned the xbutton number when 04149 * the message is queued. 04150 */ 04151 UserAssert(LOWORD(qmsg.msg.wParam) == 0); 04152 UserAssert(HIWORD(wParam) == 0); 04153 wParam |= qmsg.msg.wParam; 04154 } 04155 04156 PATHTAKEN2(0x200000); 04157 04158 /* 04159 * If this app has a modeles menu bar, 04160 * then the menu code should get the first shot at messages on the menu 04161 * Note that this assumes that xxxHandleMenuMessages 04162 * doens't need any of the stuff set after ReturnMessage 04163 */ 04164 if ((part == HTMENU) 04165 && fRemove 04166 && (ptiCurrent->pMenuState != NULL) 04167 && ptiCurrent->pMenuState->fModelessMenu 04168 && (ptiCurrent->pMenuState->pGlobalPopupMenu != NULL) 04169 && (ptiCurrent->pMenuState->pGlobalPopupMenu->fIsMenuBar)) { 04170 04171 if (xxxCallHandleMenuMessages(ptiCurrent->pMenuState, pwnd, message, wParam, lParam)) { 04172 goto RestartScan; 04173 } 04174 } 04175 04176 goto ReturnMessage; 04177 break; 04178 04179 case WM_KEYDOWN: 04180 case WM_SYSKEYDOWN: 04181 fDown = TRUE; 04182 04183 /* 04184 * If we are sending keyboard input to an app that has been 04185 * spinning then boost it back up. If we don't you use spinning 04186 * apps like Write or Project and do two builds in the 04187 * background. Note the app will also be unboosted again shortly 04188 * after you stop typing by the old logic. #11188 04189 */ 04190 if (ptiCurrent->TIF_flags & TIF_SPINNING) 04191 CheckProcessForeground(ptiCurrent); 04192 04193 /* 04194 * Apps doing journal playback sometimes put trash in the hiword 04195 * of wParam... zero it out here. 04196 */ 04197 wParam = qmsg.msg.wParam & 0xFF; 04198 04199 /* 04200 * Clear QF_FMENUSTATUS if a key other than Alt it hit 04201 * since this means the break of the Alt wouldn't be a 04202 * menu key anymore. 04203 */ 04204 if (wParam != VK_MENU) 04205 ptiCurrent->pq->QF_flags &= ~(QF_FMENUSTATUS|QF_FMENUSTATUSBREAK); 04206 04207 /* 04208 * Check for keyboard language toggle. Build the key state 04209 * here for use during key up processing (where the layout 04210 * switching takes place. This code is skipped if layout 04211 * switching via the keyboard is disabled. 04212 */ 04213 if (gLangToggle[0].bVkey && (gLangToggleKeyState < KLT_NONE)) { 04214 DWORD i; 04215 BYTE scancode = LOBYTE(HIWORD(qmsg.msg.lParam)); 04216 BYTE vkey = LOBYTE(qmsg.msg.wParam); 04217 04218 for (i = 0; i < LANGTOGGLEKEYS_SIZE; i++) { 04219 if (gLangToggle[i].bScan) { 04220 if (gLangToggle[i].bScan == scancode) { 04221 gLangToggleKeyState |= gLangToggle[i].iBitPosition; 04222 break; 04223 } 04224 } else { 04225 if (gLangToggle[i].bVkey == vkey) { 04226 gLangToggleKeyState |= gLangToggle[i].iBitPosition; 04227 break; 04228 } 04229 } 04230 } 04231 04232 if (i == LANGTOGGLEKEYS_SIZE) { 04233 gLangToggleKeyState = KLT_NONE; // not a language toggle combination 04234 } 04235 } 04236 04237 /* 04238 * Check if it is the PrintScrn key. 04239 */ 04240 fAlt = TestKeyStateDown(ptiCurrent->pq, VK_MENU); 04241 if (wParam == VK_SNAPSHOT && 04242 ((fAlt && !(ptiCurrent->fsReserveKeys & CONSOLE_ALTPRTSC)) || 04243 (!fAlt && !(ptiCurrent->fsReserveKeys & CONSOLE_PRTSC)))) { 04244 04245 /* 04246 * Remove this message from the input queue. 04247 */ 04248 PATHTAKEN2(0x400000); 04249 xxxSkipSysMsg(ptiCurrent, &qmsg); 04250 04251 /* 04252 * PRINTSCREEN -> Snap the whole screen. 04253 * ALT-PRINTSCREEN -> Snap the current window. 04254 */ 04255 pwndT = ptiCurrent->pq->spwndActive; 04256 04257 /* 04258 * check also the scan code to see if we got here 04259 * through keybd_event(VK_SNAPSHOT, ... 04260 * the scan code is in lParam bits 16-23 04261 */ 04262 if (!fAlt && ((qmsg.msg.lParam & 0x00FF0000) != 0x00010000)) { 04263 pwndT = ptiCurrent->rpdesk->pDeskInfo->spwnd; 04264 } 04265 04266 if (pwndT != NULL) { 04267 ThreadLockAlwaysWithPti(ptiCurrent, pwndT, &tlpwndT); 04268 xxxSnapWindow(pwndT); 04269 ThreadUnlock(&tlpwndT); 04270 } 04271 04272 PATHTAKEN2(0x800000); 04273 goto RestartScan; 04274 } 04275 04276 /* 04277 * Check for hot keys being hit if any are defined. 04278 */ 04279 if (gcHotKey != 0 && (!gfEnableHexNumpad || (gfInNumpadHexInput & NUMPAD_HEXMODE_HL) == 0)) { 04280 UINT key; 04281 key = (UINT)wParam; 04282 04283 if (TestKeyStateDown(ptiCurrent->pq, VK_MENU)) 04284 key |= 0x0400; 04285 04286 if (TestKeyStateDown(ptiCurrent->pq, VK_CONTROL)) 04287 key |= 0x0200; 04288 04289 if (TestKeyStateDown(ptiCurrent->pq, VK_SHIFT)) 04290 key |= 0x0100; 04291 04292 pwndT = HotKeyToWindow(key); 04293 04294 if (pwndT != NULL) { 04295 /* 04296 * VK_PACKET shouldn't be a hot key. 04297 */ 04298 UserAssert((key & 0xff) != VK_PACKET); 04299 04300 _PostMessage(ptiCurrent->pq->spwndActive, WM_SYSCOMMAND, 04301 (WPARAM)SC_HOTKEY, (LPARAM)HWq(pwndT)); 04302 04303 /* 04304 * Remove this message from the input queue. 04305 */ 04306 xxxSkipSysMsg(ptiCurrent, &qmsg); 04307 PATHTAKEN2(0x1000000); 04308 goto RestartScan; 04309 } 04310 04311 PATHTAKEN2(0x2000000); 04312 } 04313 04314 #if DBG 04315 else if (gfInNumpadHexInput & NUMPAD_HEXMODE_HL) { 04316 RIPMSG0(RIP_VERBOSE, "xxxScanSysQueue: gfInNumpadHexInput is true, so we skipped hotkey."); 04317 } 04318 #endif 04319 04320 if (wParam == VK_PACKET) { 04321 /* 04322 * Save the character in thread's cache for TranslateMessage 04323 */ 04324 ptiCurrent->wchInjected = HIWORD(qmsg.msg.wParam); 04325 qmsg.msg.wParam = wParam; 04326 UserAssert(qmsg.msg.wParam == VK_PACKET); 04327 } 04328 04329 /* 04330 * Fall through. 04331 */ 04332 04333 case WM_SYSKEYUP: 04334 case WM_KEYUP: 04335 wParam = qmsg.msg.wParam & 0xFF; 04336 if (wParam == VK_PACKET) { 04337 qmsg.msg.wParam = wParam; 04338 } 04339 04340 /* 04341 * Special processing for thai locale toggle using grave accent key 04342 * Remove key message irrespective of fDown otherwise it will 04343 * generate WM_CHAR message 04344 */ 04345 if (gbGraveKeyToggle && 04346 // 04347 // In case of mstsc.exe, should not eat Grave Accent key message. 04348 // TS client must send Grave Accent key message to server side. 04349 // 04350 !(GetAppImeCompatFlags(NULL) & IMECOMPAT_HYDRACLIENT) && 04351 LOBYTE(HIWORD(qmsg.msg.lParam)) == SCANCODE_THAI_LAYOUT_TOGGLE && 04352 fRemove && 04353 !TestKeyStateDown(ptiCurrent->pq, VK_SHIFT) && 04354 !TestKeyStateDown(ptiCurrent->pq, VK_MENU) && 04355 !TestKeyStateDown(ptiCurrent->pq, VK_CONTROL) && 04356 !TestKeyStateDown(ptiCurrent->pq, VK_LWIN) && 04357 !TestKeyStateDown(ptiCurrent->pq, VK_RWIN)){ 04358 04359 if ((pwnd = ptiCurrent->pq->spwndFocus) == NULL){ 04360 pwnd = ptiCurrent->pq->spwndActive; 04361 } 04362 04363 /* 04364 * Post message only on WM_KEYUP 04365 */ 04366 if (!fDown && pwnd){ 04367 PTHREADINFO ptiToggle = GETPTI(pwnd); 04368 PKL pkl = ptiToggle->spklActive; 04369 04370 if (pkl && (pkl = HKLtoPKL(ptiToggle, (HKL)HKL_NEXT))) { 04371 _PostMessage( 04372 pwnd, 04373 WM_INPUTLANGCHANGEREQUEST, 04374 (WPARAM)(((pkl->dwFontSigs & gSystemFS) ? INPUTLANGCHANGE_SYSCHARSET : 0) | INPUTLANGCHANGE_FORWARD), 04375 (LPARAM)pkl->hkl 04376 ); 04377 } 04378 } 04379 /* 04380 * eat Accent Grave's key msgs 04381 */ 04382 xxxSkipSysMsg(ptiCurrent, &qmsg); 04383 goto RestartScan; 04384 } 04385 04386 /* 04387 * Process keyboard toggle keys only if this is 04388 * a break event and fRemove == TRUE. Some apps, 04389 * for instance Word 95, call PeekMessage with 04390 * PM_NOREMOVE followed by a call with PM_REMOVE. 04391 * We only want to process this once. Skip all 04392 * of this is layout switching via the keyboard 04393 * is disabled. 04394 */ 04395 if (!fDown && fRemove && gLangToggle[0].bVkey) { 04396 BOOL bDropToggle = FALSE; 04397 DWORD dwDirection = 0; 04398 PKL pkl; 04399 PTHREADINFO ptiToggle; 04400 // PWND pwndTop; 04401 BOOL bArabicSwitchPresent = FALSE; 04402 LCID lcid; 04403 04404 ZwQueryDefaultLocale(FALSE, &lcid); 04405 04406 pwnd = ptiCurrent->pq->spwndFocus; 04407 if (pwnd == NULL) { 04408 pwnd = ptiCurrent->pq->spwndActive; 04409 if (!pwnd) { 04410 goto NoLayoutSwitch; 04411 } 04412 } 04413 04414 ptiToggle = GETPTI(pwnd); 04415 pkl = ptiToggle->spklActive; 04416 UserAssert(ptiToggle->spklActive != NULL); 04417 04418 /* 04419 * Check for Arabic toggle context 04420 */ 04421 if (gLangToggleKeyState < KLT_NONE && PRIMARYLANGID(lcid) == LANG_ARABIC){ 04422 PKL pkl_next = HKLtoPKL (ptiToggle, (HKL)HKL_NEXT); 04423 04424 /* 04425 * test if there are exactly two pkl's and at least one 04426 * of them is arabic 04427 */ 04428 if (pkl && pkl_next && 04429 pkl->hkl != pkl_next->hkl && pkl_next == HKLtoPKL(ptiToggle, (HKL)HKL_PREV) && 04430 (PRIMARYLANGID(HandleToUlong(pkl->hkl)) == LANG_ARABIC || PRIMARYLANGID(HandleToUlong(pkl_next->hkl)) == LANG_ARABIC)){ 04431 bArabicSwitchPresent = TRUE; 04432 } 04433 } 04434 04435 /* 04436 * NT has always had Alt LShift going forward (down) the list, 04437 * and Alt RShift going backwards. Windows '95 is different. 04438 */ 04439 switch (gLangToggleKeyState) { 04440 case KLT_ALTLEFTSHIFT: 04441 bDropToggle = TRUE; 04442 dwDirection = INPUTLANGCHANGE_FORWARD; 04443 if (!bArabicSwitchPresent || PRIMARYLANGID(HandleToUlong(pkl->hkl)) == LANG_ARABIC){ 04444 pkl = HKLtoPKL(ptiToggle, (HKL)HKL_NEXT); 04445 } 04446 break; 04447 04448 case KLT_ALTRIGHTSHIFT: 04449 bDropToggle = TRUE; 04450 dwDirection = INPUTLANGCHANGE_BACKWARD; 04451 if (!bArabicSwitchPresent || PRIMARYLANGID(HandleToUlong(pkl->hkl)) != LANG_ARABIC){ 04452 pkl = HKLtoPKL(ptiToggle, (HKL)HKL_PREV); 04453 } 04454 break; 04455 04456 case KLT_ALTBOTHSHIFTS: 04457 pkl = gspklBaseLayout; 04458 break; 04459 04460 default: 04461 goto NoLayoutSwitch; 04462 break; 04463 } 04464 04465 if (pkl == NULL) { 04466 pkl = GETPTI(pwnd)->spklActive; 04467 } 04468 04469 /* 04470 * If these two are not NULL, then winlogon hasn't loaded 04471 * any keyboard layouts yet: but nobody should be getting 04472 * input yet, so Assert but check pkl anyway. #99321 04473 */ 04474 UserAssert(gspklBaseLayout != NULL); 04475 UserAssert(pkl); 04476 if (pkl) { 04477 /* 04478 * Not a very satisfactory window to post to, but it's hard 04479 * to figure out a better window. Just do as Memphis does. 04480 * Note: The following went up too high, bypassing Word 04481 * when using wordmail - IanJa bug #64744. 04482 * if ((pwndTop = GetTopLevelWindow(pwnd)) != NULL) { 04483 * pwnd = pwndTop; 04484 * } 04485 */ 04486 _PostMessage(pwnd, WM_INPUTLANGCHANGEREQUEST, 04487 (DWORD)(((pkl->dwFontSigs & gSystemFS) ? INPUTLANGCHANGE_SYSCHARSET : 0) | dwDirection), 04488 (LPARAM)pkl->hkl); 04489 } 04490 04491 NoLayoutSwitch: 04492 04493 if (bDropToggle) { 04494 /* 04495 * Clear this key from the key state so that multiple key 04496 * presses will work (i.e., Alt+Shft+Shft). We don't do 04497 * this when both shift keys are pressed simultaneously to 04498 * avoid two activates. 04499 */ 04500 DWORD i; 04501 BYTE scancode = LOBYTE(HIWORD(qmsg.msg.lParam)); 04502 BYTE vkey = LOBYTE(qmsg.msg.wParam); 04503 04504 for (i = 0; i < LANGTOGGLEKEYS_SIZE; i++) { 04505 if (gLangToggle[i].bScan) { 04506 if (gLangToggle[i].bScan == scancode) { 04507 gLangToggleKeyState &= ~(gLangToggle[i].iBitPosition); 04508 } 04509 } else { 04510 if (gLangToggle[i].bVkey == vkey) { 04511 gLangToggleKeyState &= ~(gLangToggle[i].iBitPosition); 04512 } 04513 } 04514 } 04515 } else { 04516 gLangToggleKeyState = 0; 04517 } 04518 } 04519 04520 /* 04521 * Convert F10 to syskey for new apps. 04522 */ 04523 if (wParam == VK_F10) 04524 message |= (WM_SYSKEYDOWN - WM_KEYDOWN); 04525 04526 if (TestKeyStateDown(ptiCurrent->pq, VK_CONTROL) && 04527 wParam == VK_ESCAPE) { 04528 message |= (WM_SYSKEYDOWN - WM_KEYDOWN); 04529 } 04530 04531 /* 04532 * Clear the 'simulated keystroke' bit for all applications except 04533 * console so it can pass it to 16-bit vdms. VDM keyboards need to 04534 * distinguish between AltGr (where Ctrl keystroke is simulated) 04535 * and a real Ctrl+Alt. Check TIF_CSRSSTHREAD for the console 04536 * input thread because it lives in the server. This is a cheap 04537 * way to check for it. 04538 */ 04539 if (!(ptiCurrent->TIF_flags & TIF_CSRSSTHREAD)) 04540 qmsg.msg.lParam &= ~FAKE_KEYSTROKE; 04541 PATHTAKEN2(0x4000000); 04542 04543 /* 04544 * Fall through. 04545 */ 04546 04547 /* 04548 * Some apps want to be able to feed WM_CHAR messages through 04549 * the playback hook. Why? Because they want to be able to 04550 * convert a string of characters info key messages 04551 * and feed them to themselves or other apps. Unfortunately, 04552 * there are no machine independent virtual key codes for 04553 * some characters (for example '$'), so they need to send 04554 * those through as WM_CHARs. (6/10/87). 04555 */ 04556 04557 case WM_CHAR: 04558 wParam = qmsg.msg.wParam & 0xFF; 04559 04560 /* 04561 * Assign the input to the focus window. If there is no focus 04562 * window, assign it to the active window as a SYS message. 04563 */ 04564 pwnd = ptiCurrent->pq->spwndFocus; 04565 if (ptiCurrent->pq->spwndFocus == NULL) { 04566 if ((pwnd = ptiCurrent->pq->spwndActive) != NULL) { 04567 if (CheckMsgFilter(message, WM_KEYDOWN, WM_DEADCHAR)) { 04568 message += (WM_SYSKEYDOWN - WM_KEYDOWN); 04569 PATHTAKEN2(0x8000000); 04570 } 04571 } else { 04572 PATHTAKEN2(0x10000000); 04573 goto SkipMessage; 04574 } 04575 } 04576 04577 /* 04578 * If there is no active window or focus window, eat this 04579 * message. 04580 */ 04581 if (pwnd == NULL) { 04582 PATHTAKEN2(0x20000000); 04583 goto SkipMessage; 04584 } 04585 04586 ThreadUnlock(&tlpwnd); 04587 ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwnd); 04588 04589 /* 04590 * Check if this is intended for the current app. 04591 */ 04592 if (fOtherApp = (GETPTI(pwnd) != ptiCurrent)) { 04593 PWND pwndModalLoop; 04594 04595 /* 04596 * If this other app isn't going to read from this 04597 * queue, then skip this message. This can happen if 04598 * the RIT queues up a message thinking it goes to 04599 * a particular hwnd, but then by the time GetMessage() 04600 * is called for that thread, it doesn't go to that hwnd 04601 * (like in the case of mouse messages, window rearrangement 04602 * happens which changes which hwnd the mouse hits on). 04603 */ 04604 if (GETPTI(pwnd)->pq != ptiCurrent->pq) { 04605 PATHTAKEN2(0x40000000); 04606 goto SkipMessage; 04607 } 04608 04609 /* 04610 * If the current thread is in the menu or movesize loop 04611 * then we need to give it the input 04612 */ 04613 if (IsInsideMenuLoop(ptiCurrent)) { 04614 pwndModalLoop = ptiCurrent->pMenuState->pGlobalPopupMenu->spwndNotify; 04615 } else if (ptiCurrent->pmsd != NULL) { 04616 pwndModalLoop = ptiCurrent->pmsd->spwnd; 04617 RIPMSG0(RIP_WARNING, "xxxScanSysQueue: returning key to movesize loop"); 04618 } else { 04619 pwndModalLoop = NULL; 04620 } 04621 04622 /* 04623 * If we're switching windows, lock the new one 04624 */ 04625 if (pwndModalLoop != NULL) { 04626 pwnd = pwndModalLoop; 04627 fOtherApp = (GETPTI(pwnd) != ptiCurrent); 04628 ThreadUnlock(&tlpwnd); 04629 ThreadLockWithPti(ptiCurrent, pwnd, &tlpwnd); 04630 PATHTAKEN2(0x80000000); 04631 } 04632 04633 /* 04634 * If not for us, then remember who it is for. 04635 */ 04636 if (ptiKeyWake == NULL) { 04637 PATHTAKEN3(1); 04638 ptiKeyWake = GETPTI(pwnd); 04639 } 04640 } 04641 04642 /* 04643 * See if this thing matches our filter. 04644 */ 04645 if (!CheckMsgFilter(message, msgMinFilter, msgMaxFilter) || 04646 !CheckPwndFilter(pwnd, pwndFilter)) { 04647 PATHTAKEN3(2); 04648 continue; 04649 } 04650 04651 /* 04652 * This message matches our filter. If it is not for us then 04653 * stop searching to make sure the real owner processes this 04654 * message first. 04655 */ 04656 if (fOtherApp) { 04657 PATHTAKEN3(4); 04658 goto NoMessages; 04659 } 04660 04661 /* 04662 * Generate some special messages if we are removing and we are 04663 * not inside the menu loop. 04664 */ 04665 if (fRemove && !IsInsideMenuLoop(ptiCurrent)) { 04666 /* 04667 * Generate a WM_CONTEXTMENU for the VK_APPS key 04668 */ 04669 if ((wParam == VK_APPS) && (message == WM_KEYUP)) { 04670 _PostMessage(pwnd, WM_CONTEXTMENU, (WPARAM)PtoH(pwnd), KEYBOARD_MENU); 04671 } 04672 04673 /* 04674 * If this is a WM_KEYDOWN message for F1 key then we must generate 04675 * the WM_KEYF1 message. 04676 */ 04677 if ((wParam == VK_F1) && (message == WM_KEYDOWN)) { 04678 _PostMessage(pwnd, WM_KEYF1, 0, 0); 04679 } 04680 } 04681 04682 /* 04683 * If one Shift key is released while the other Shift key is held 04684 * down, this keystroke is normally skipped, presumably to prevent 04685 * applications from thinking that the shift condition no longer 04686 * applies. 04687 */ 04688 if (wParam == VK_SHIFT) { 04689 BYTE vkHanded, vkOtherHand; 04690 04691 if (qmsg.msg.lParam & EXTENDED_BIT) { 04692 vkHanded = VK_RSHIFT; 04693 } else { 04694 vkHanded = VK_LSHIFT; 04695 } 04696 vkOtherHand = vkHanded ^ 1; 04697 04698 if (!fDown && TestKeyStateDown(ptiCurrent->pq, vkOtherHand)) { 04699 /* 04700 * Unlike normal apps, Console MUST be sent a Shift break 04701 * even when the other Shift key is still down, since it 04702 * has to be passed on to VDM, which maintains it's own 04703 * state. Check TIF_CSRSSTHREAD for the console input 04704 * thread because it lives in the server. This is a cheap 04705 * way to check for it. 04706 */ 04707 if ((ptiCurrent->TIF_flags & TIF_CSRSSTHREAD) == 0) { 04708 /* 04709 * We ignore this key event, so we must update 04710 * it's key state whether fRemove is TRUE or not. 04711 * (ignoring an key event is same as removing it) 04712 */ 04713 qmsg.msg.wParam = vkHanded; 04714 xxxSkipSysMsg(ptiCurrent, &qmsg); 04715 PATHTAKEN3(8); 04716 goto RestartScan; 04717 } 04718 PATHTAKEN3(0x10); 04719 } 04720 } 04721 04722 /* 04723 * Get the previous up/down state of the key here since 04724 * SkipSysMsg() sets the key state table and destroys 04725 * the previous state info. 04726 */ 04727 fPrevDown = FALSE; 04728 if (TestKeyStateDown(ptiCurrent->pq, wParam)) 04729 fPrevDown = TRUE; 04730 04731 /* 04732 * Eat the message from the input queue and set the keystate 04733 * table. 04734 */ 04735 PATHTAKEN3(0x20); 04736 if (fRemove) { 04737 xxxSkipSysMsg(ptiCurrent, &qmsg); 04738 } 04739 04740 /* 04741 * This gets us the LOWORD of lParam, the repeat count, 04742 * the bit in the hi byte indicating whether this is an extended 04743 * key, and the scan code. We also need to re-get the wParam in 04744 * case xxxSkipSysMsg called a hook which modified the message. 04745 * AfterDark's password protection does this. 04746 */ 04747 lParam = qmsg.msg.lParam; 04748 wParam = qmsg.msg.wParam; 04749 04750 /* 04751 * Indicate if it was previously down. 04752 */ 04753 if (fPrevDown) 04754 lParam |= 0x40000000; // KF_REPEAT 04755 04756 /* 04757 * Set the transition bit. 04758 */ 04759 switch (message) { 04760 case WM_KEYUP: 04761 case WM_SYSKEYUP: 04762 lParam |= 0x80000000; // KF_UP 04763 break; 04764 } 04765 04766 /* 04767 * Set the alt key down bit. 04768 */ 04769 if (TestKeyStateDown(ptiCurrent->pq, VK_MENU)) { 04770 lParam |= 0x20000000; // KF_ALTDOWN 04771 } 04772 04773 /* 04774 * Set the menu state flag. 04775 */ 04776 if (IsMenuStarted(ptiCurrent)) { 04777 lParam |= 0x10000000; // KF_MENUMODE 04778 } 04779 04780 /* 04781 * Set the dialog state flag. 04782 */ 04783 if (ptiCurrent->pq->QF_flags & QF_DIALOGACTIVE) { 04784 lParam |= 0x08000000; // KF_DLGMODE 04785 } 04786 04787 /* 04788 * 0x80000000 is set if up, clear if down 04789 * 0x40000000 is previous up/down state of key 04790 * 0x20000000 is whether the alt key is down 04791 * 0x10000000 is whether currently in menumode. 04792 * 0x08000000 is whether in dialog mode 04793 * 0x04000000 is not used 04794 * 0x02000000 is not used 04795 * 0x01000000 is whether this is an extended keyboard key 04796 * 04797 * Low word is repeat count, low byte hiword is scan code, 04798 * hi byte hiword is all these bits. 04799 */ 04800 04801 /* 04802 * Callback the client IME before calling the keyboard hook. 04803 * If the vkey is one of the IME hotkeys, the vkey will not 04804 * be passed to the keyboard hook. 04805 * If IME needs this vkey, VK_PROCESSKEY will be put into the 04806 * application queue instead of real vkey. 04807 */ 04808 UserAssert(ptiCurrent != NULL); 04809 if (gpImeHotKeyListHeader != NULL && 04810 fRemove && 04811 !IsMenuStarted(ptiCurrent) && 04812 !(ptiCurrent->TIF_flags & TIF_DISABLEIME) && 04813 pwnd != NULL) { 04814 04815 WPARAM wParamTemp = wParam; 04816 04817 if (wParam == VK_PACKET) { 04818 wParamTemp = MAKEWPARAM(wParam, ptiCurrent->wchInjected); 04819 } 04820 04821 /* 04822 * xxxImmProcessKey also checks the registered IME hotkeys. 04823 */ 04824 dwImmRet = xxxImmProcessKey( ptiCurrent->pq, 04825 pwnd, 04826 message, 04827 wParamTemp, 04828 lParam); 04829 if ( dwImmRet & (IPHK_HOTKEY | IPHK_SKIPTHISKEY) ) { 04830 dwImmRet = 0; 04831 goto SkipMessage; 04832 } 04833 } 04834 04835 /* 04836 * If we are removing the message, call the keyboard hook 04837 * with HC_ACTION, otherwise call the hook with HC_NOREMOVE 04838 * to let it know that the message is not being removed. 04839 */ 04840 if (IsHooked(ptiCurrent, WHF_KEYBOARD)) { 04841 fKbdHookCalled = TRUE; 04842 if (xxxCallHook(fRemove ? HC_ACTION : HC_NOREMOVE, 04843 wParam, lParam, WH_KEYBOARD)) { 04844 PATHTAKEN3(0x40); 04845 goto SkipMessage; 04846 } 04847 } 04848 04849 if (fKbdHookCalled && fRemove && IsHooked(ptiCurrent, WHF_CBT)) { 04850 xxxCallHook(HCBT_KEYSKIPPED, wParam, lParam, WH_CBT); 04851 PATHTAKEN3(0x80); 04852 } 04853 04854 fKbdHookCalled = FALSE; 04855 PATHTAKEN3(0x100); 04856 goto ReturnMessage; 04857 04858 case WM_MOUSEWHEEL: 04859 /* 04860 * If we are sending keyboard input to an app that has been 04861 * spinning then boost it back up. If we don't you use spinning 04862 * apps like Write or Project and do two builds in the 04863 * background. Note the app will also be unboosted again shortly 04864 * after you stop typing by the old logic. #11188 04865 */ 04866 if (ptiCurrent->TIF_flags & TIF_SPINNING) 04867 CheckProcessForeground(ptiCurrent); 04868 04869 /* 04870 * Assign the input to the focus window. If there is no focus 04871 * window, or we are in a menu loop, eat this message. 04872 */ 04873 pwnd = ptiCurrent->pq->spwndFocus; 04874 if (pwnd == NULL || IsInsideMenuLoop(ptiCurrent)) { 04875 PATHTAKEN2(0x20000000); 04876 goto SkipMessage; 04877 } 04878 04879 ThreadUnlock(&tlpwnd); 04880 ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwnd); 04881 04882 /* 04883 * Check if this is intended for the current app. 04884 */ 04885 if (fOtherApp = (GETPTI(pwnd) != ptiCurrent)) { 04886 04887 /* 04888 * If this other app isn't going to read from this 04889 * queue, then skip this message. This can happen if 04890 * the RIT queues up a message thinking it goes to 04891 * a particular hwnd, but then by the time GetMessage() 04892 * is called for that thread, it doesn't go to that hwnd 04893 * (like in the case of mouse messages, window rearrangement 04894 * happens which changes which hwnd the mouse hits on). 04895 */ 04896 if (GETPTI(pwnd)->pq != ptiCurrent->pq) { 04897 PATHTAKEN2(0x40000000); 04898 goto SkipMessage; 04899 } 04900 04901 /* 04902 * If not for us, then remember who it is for. 04903 */ 04904 if (ptiKeyWake == NULL) { 04905 PATHTAKEN3(1); 04906 ptiKeyWake = GETPTI(pwnd); 04907 } 04908 } 04909 04910 /* 04911 * See if this thing matches our filter. 04912 * NOTE: We need to check whether the caller is filtering 04913 * for all mouse messages - if so, we assume the caller 04914 * wants mouse wheel messages too. 04915 */ 04916 if ( !CheckMsgFilter(WM_MOUSEWHEEL, msgMinFilter, msgMaxFilter) || 04917 !CheckPwndFilter(pwnd, pwndFilter)) { 04918 PATHTAKEN3(2); 04919 continue; 04920 } 04921 04922 /* 04923 * This message matches our filter. If it is not for us then 04924 * stop searching to make sure the real owner processes this 04925 * message first. 04926 */ 04927 if (fOtherApp) { 04928 PATHTAKEN3(4); 04929 goto NoMessages; 04930 } 04931 04932 /* 04933 * Eat the message from the input queue and set the keystate 04934 * table. 04935 */ 04936 PATHTAKEN3(0x20); 04937 if (fRemove) { 04938 xxxSkipSysMsg(ptiCurrent, &qmsg); 04939 } 04940 04941 wParam = GetMouseKeyFlags(ptiCurrent->pq); 04942 UserAssert(LOWORD(qmsg.msg.wParam) == 0); 04943 UserAssert(HIWORD(wParam) == 0); 04944 wParam |= qmsg.msg.wParam; 04945 lParam = qmsg.msg.lParam; 04946 04947 /* 04948 * If we are removing the message, call the mouse hook 04949 * with HC_ACTION, otherwise call the hook with HC_NOREM 04950 * to let it know that the message is not being removed. 04951 */ 04952 if (IsHooked(ptiCurrent, WHF_MOUSE)) { 04953 fMouseHookCalled = TRUE; 04954 mhs.pt = qmsg.msg.pt; 04955 mhs.hwnd = HW(pwnd); 04956 mhs.wHitTestCode = HTNOWHERE; 04957 mhs.dwExtraInfo = qmsg.ExtraInfo; 04958 mhs.mouseData = (DWORD)qmsg.msg.wParam; 04959 if (xxxCallMouseHook(message, &mhs, fRemove)) { 04960 /* 04961 * Not allowed by mouse hook; so skip it. 04962 */ 04963 PATHTAKEN3(0x40); 04964 goto SkipMessage; 04965 } 04966 } 04967 04968 if (fMouseHookCalled && fRemove && IsHooked(ptiCurrent, WHF_CBT)) { 04969 /* 04970 * CONSIDER: Add new HCBT_ constant for the mouse wheel? 04971 */ 04972 xxxCallHook(HCBT_CLICKSKIPPED, message, (LPARAM)&mhs, WH_CBT); 04973 PATHTAKEN3(0x80); 04974 } 04975 04976 fMouseHookCalled = FALSE; 04977 PATHTAKEN3(0x100); 04978 goto ReturnMessage; 04979 } /* End of switch (message = qmsg.msg.message) */ 04980 } /* End of the GetNextSysMsg() loop */ 04981 04982 ReturnMessage: 04983 if (!RtlEqualMemory(&ptiCurrent->ptLast, &qmsg.msg.pt, sizeof(POINT))) { 04984 ptiCurrent->TIF_flags |= TIF_MSGPOSCHANGED; 04985 } 04986 ptiCurrent->ptLast = qmsg.msg.pt; 04987 ptiCurrent->timeLast = qmsg.msg.time; 04988 ptiCurrent->pq->ExtraInfo = qmsg.ExtraInfo; 04989 04990 /* 04991 * idSysLock value of 1 indicates that the message came from the input 04992 * queue. 04993 */ 04994 ptiCurrent->idLast = ptiCurrent->pq->idSysLock = 1; 04995 04996 /* 04997 * Now see if our input bit is set for this input. If it isn't, set ours 04998 * and clear the guy who had it previously. 04999 */ 05000 TransferWakeBit(ptiCurrent, message); 05001 05002 /* 05003 * Clear the input bits if no messages in the input queue. 05004 */ 05005 ClearWakeBit(ptiCurrent, QS_MOUSE | QS_KEY | QS_EVENT | QS_TRANSFER, TRUE); 05006 05007 /* 05008 * Get the message and split. 05009 */ 05010 lpMsg->hwnd = HW(pwnd); 05011 lpMsg->message = message; 05012 05013 /* 05014 * If the IME claims that it needs this vkey, replace it 05015 * with VK_PROCESSKEY. The real vkey has been saved in 05016 * the input context in the client side. 05017 */ 05018 lpMsg->wParam = (dwImmRet & IPHK_PROCESSBYIME) ? VK_PROCESSKEY : wParam; 05019 05020 lpMsg->lParam = lParam; 05021 lpMsg->time = qmsg.msg.time; 05022 lpMsg->pt = qmsg.msg.pt; 05023 05024 #if DBG 05025 if (gfLogPlayback && ptiCurrent->pq->idSysPeek == (LONG_PTR)PQMSG_PLAYBACK) 05026 LogPlayback(pwnd, lpMsg); 05027 #endif // DBG 05028 05029 ThreadUnlock(&tlpwnd); 05030 05031 PATHTAKEN3(0x200); 05032 DUMPPATHTAKEN(); 05033 return TRUE; 05034 05035 NoMessages: 05036 /* 05037 * The message was for another app, or none were found that fit the 05038 * filter. 05039 */ 05040 05041 /* 05042 * Unlock the system queue. 05043 */ 05044 ptiCurrent->pq->idSysLock = 0; 05045 CheckSysLock(4, ptiCurrent->pq, NULL); 05046 ptiCurrent->pq->ptiSysLock = NULL; 05047 ptiCurrent->pcti->CTIF_flags &= ~CTIF_SYSQUEUELOCKED; 05048 05049 /* 05050 * Wake up someone else if we found a message for him. QS_TRANSFER 05051 * signifies that the thread was woken due to input transfer 05052 * from another thread, rather than from a real input event. 05053 */ 05054 if (ptiKeyWake != NULL || ptiMouseWake != NULL || ptiEventWake != NULL) { 05055 PATHTAKEN3(0x400); 05056 if (ptiKeyWake != NULL) { 05057 SetWakeBit(ptiKeyWake, QS_KEY | QS_TRANSFER); 05058 ClearWakeBit(ptiCurrent, QS_KEY | QS_TRANSFER, FALSE); 05059 PATHTAKEN3(0x800); 05060 } 05061 05062 if (ptiMouseWake != NULL) { 05063 SetWakeBit(ptiMouseWake, QS_MOUSE | QS_TRANSFER); 05064 ClearWakeBit(ptiCurrent, QS_MOUSE | QS_TRANSFER, FALSE); 05065 PATHTAKEN3(0x1000); 05066 } 05067 05068 if (ptiEventWake != NULL) { 05069 SetWakeBit(ptiEventWake, QS_EVENTSET); 05070 ClearWakeBit(ptiCurrent, QS_EVENT, FALSE); 05071 PATHTAKEN3(0x2000); 05072 } else if (FJOURNALPLAYBACK()) { 05073 05074 /* 05075 * If journal playback is occuring, clear the input bits. This will 05076 * help prevent a race condition between two threads that call 05077 * WaitMessage/PeekMessage. This can occur when embedding an OLE 05078 * object. An example is inserting a Word object into an Excel 05079 * spreadsheet. 05080 * Also clear change bits else this thread might not xxxSleepThread. 05081 */ 05082 ptiCurrent->pcti->fsWakeBitsJournal |= (ptiCurrent->pcti->fsWakeBits & 05083 (QS_MOUSE | QS_KEY | QS_TRANSFER)); 05084 ClearWakeBit(ptiCurrent, QS_MOUSE | QS_KEY | QS_TRANSFER, FALSE); 05085 ptiCurrent->pcti->fsChangeBits &= ~(QS_MOUSE | QS_KEY | QS_TRANSFER); 05086 } 05087 } else { 05088 /* 05089 * Clear the input bits if no messages in the input queue. 05090 */ 05091 ptiCurrent->pcti->fsWakeBitsJournal = 0; 05092 ClearWakeBit(ptiCurrent, QS_MOUSE | QS_KEY | QS_EVENT | 05093 QS_TRANSFER, TRUE); 05094 PATHTAKEN3(0x4000); 05095 } 05096 05097 ThreadUnlock(&tlpwnd); 05098 05099 PATHTAKEN3(0x8000); 05100 DUMPPATHTAKEN(); 05101 return FALSE; 05102 }

void xxxSkipSysMsg PTHREADINFO  pti,
PQMSG  pqmsg
 

Definition at line 2982 of file ntuser/kernel/input.c.

References BOOL, BYTE, CheckPtiSysPeek, DelQEntry(), EqualMsg(), tagQMSG::ExtraInfo, FALSE, tagHOOK::flags, HF_NEEDHC_SKIP, tagQ::idSysPeek, LOBYTE, tagQ::mlInput, tagQMSG::msg, NULL, PhkFirstGlobalValid(), tagTHREADINFO::pq, PQMSG_PLAYBACK, tagQMSG::pqmsgNext, tagMLIST::pqmsgRead, tagQMSG::pti, TestKeyStateDown, TRUE, UpdateKeyState(), and xxxCallJournalRecordHook().

Referenced by xxxScanSysQueue().

02985 { 02986 PQMSG pqmsgT; 02987 BOOL fDown; 02988 BYTE vk; 02989 PHOOK phook; 02990 02991 /* 02992 * If idSysPeek is 0, then the pqmsg that we were looking at has been 02993 * deleted, probably because of a callout from ScanSysQueue, and that 02994 * callout then called PeekMessage(fRemove == TRUE), and then returned. 02995 */ 02996 if (pti->pq->idSysPeek == 0) 02997 return; 02998 02999 phook = PhkFirstGlobalValid(pti, WH_JOURNALPLAYBACK); 03000 if (phook != NULL) { 03001 /* 03002 * Tell the journal playback hook that we're done 03003 * with this message now. 03004 */ 03005 phook->flags |= HF_NEEDHC_SKIP; 03006 } else { 03007 phook = PhkFirstGlobalValid(pti, WH_JOURNALRECORD); 03008 if (phook != NULL) { 03009 /* 03010 * We've processed a new message: tell the journal record 03011 * hook what the message is. 03012 */ 03013 xxxCallJournalRecordHook(pqmsg); 03014 } 03015 03016 /* 03017 * If idSysPeek is 0 now, it means we've been recursed into yet 03018 * again. This would confuse a journalling app, but it would confuse 03019 * us more because we'd fault. Return if idSysPeek is 0. 03020 */ 03021 if ((pqmsgT = (PQMSG)pti->pq->idSysPeek) == NULL) 03022 return; 03023 03024 /* 03025 * Delete this message from the input queue. Make sure pqmsgT isn't 03026 * 1: this could happen if an app unhooked a journal record hook 03027 * during a callback from xxxScanSysQueue. 03028 */ 03029 if (pqmsgT != PQMSG_PLAYBACK) { 03030 /* 03031 * There are cases when idSysPeek points to a different message 03032 * than the one we are trying to remove. This can happen if 03033 * two threads enters in xxxScanSysQueue, sets the idSysPeek and 03034 * after this their queues got redistributed. The first thread 03035 * will have the idSysPeek preserved but the second one has to 03036 * search the queue for its message. - ask CLupu 03037 */ 03038 if (!EqualMsg(pqmsgT, pqmsg)) { 03039 03040 PQMSG pqmsgS; 03041 03042 #if DEBUGTAGS 03043 if (IsDbgTagEnabled(DBGTAG_SysPeek)) { 03044 gnSysPeekSearch++; 03045 } 03046 #endif 03047 03048 TAGMSG0(DBGTAG_SysPeek | RIP_THERESMORE, "Different message than idSysPeek\n"); 03049 TAGMSG2(DBGTAG_SysPeek | RIP_NONAME | RIP_THERESMORE, "pqmsg = %#p idSysPeek = %#p", pqmsg, pqmsgT); 03050 TAGMSG2(DBGTAG_SysPeek | RIP_NONAME | RIP_THERESMORE, "pti = %#p pti = %#p", pqmsg->pti, pqmsgT->pti); 03051 TAGMSG2(DBGTAG_SysPeek | RIP_NONAME | RIP_THERESMORE, "msg = %08lx msg = %08lx", pqmsg->msg.message, pqmsgT->msg.message); 03052 TAGMSG2(DBGTAG_SysPeek | RIP_NONAME | RIP_THERESMORE, "hwnd = %#p hwnd = %#p", pqmsg->msg.hwnd, pqmsgT->msg.hwnd); 03053 TAGMSG2(DBGTAG_SysPeek | RIP_NONAME | RIP_THERESMORE, "wParam = %#p wParam = %#p", pqmsg->msg.wParam, pqmsgT->msg.wParam); 03054 TAGMSG2(DBGTAG_SysPeek | RIP_NONAME | RIP_THERESMORE, "lParam = %#p lParam = %#p", pqmsg->msg.lParam, pqmsgT->msg.lParam); 03055 TAGMSG2(DBGTAG_SysPeek | RIP_NONAME | RIP_THERESMORE, "time = %08lx time = %08lx", pqmsg->msg.time, pqmsgT->msg.time); 03056 TAGMSG2(DBGTAG_SysPeek | RIP_NONAME | RIP_THERESMORE, "Extra = %08lx Extra = %08lx", pqmsg->ExtraInfo, pqmsgT->ExtraInfo); 03057 TAGMSG1(DBGTAG_SysPeek | RIP_NONAME, "\npqmsgT = %#p", pqmsgT); 03058 03059 /* 03060 * Begin to search for this message 03061 */ 03062 pqmsgS = pti->pq->mlInput.pqmsgRead; 03063 03064 while (pqmsgS != NULL) { 03065 if (EqualMsg(pqmsgS, pqmsg)) { 03066 TAGMSG2(DBGTAG_SysPeek | RIP_THERESMORE, 03067 "Deleting pqmsg %#p, pti %#p", 03068 pqmsgS, pqmsgS->pti); 03069 03070 TAGMSG4(DBGTAG_SysPeek | RIP_NONAME, 03071 "m %04lx, w %#p, l %#p, t %lx", 03072 pqmsgS->msg.message, pqmsgS->msg.hwnd, 03073 pqmsgS->msg.lParam, pqmsgS->msg.time); 03074 03075 pqmsgT = pqmsgS; 03076 break; 03077 } 03078 pqmsgS = pqmsgS->pqmsgNext; 03079 } 03080 if (pqmsgS == NULL) { 03081 TAGMSG0(DBGTAG_SysPeek, "Didn't find a matching message. No message removed."); 03082 return; 03083 } 03084 } 03085 03086 if (pqmsgT == (PQMSG)pti->pq->idSysPeek) { 03087 /* 03088 * We'll remove this message from the input queue 03089 * so set idSysPeek to 0. 03090 */ 03091 CheckPtiSysPeek(1, pti->pq, 0); 03092 pti->pq->idSysPeek = 0; 03093 } 03094 DelQEntry(&pti->pq->mlInput, pqmsgT); 03095 } 03096 } 03097 03098 fDown = TRUE; 03099 vk = 0; 03100 03101 switch (pqmsg->msg.message) { 03102 case WM_MOUSEMOVE: 03103 case WM_QUEUESYNC: 03104 default: 03105 /* 03106 * No state change. 03107 */ 03108 break; 03109 03110 case WM_KEYUP: 03111 case WM_SYSKEYUP: 03112 fDown = FALSE; 03113 03114 /* 03115 * Fall through. 03116 */ 03117 case WM_KEYDOWN: 03118 case WM_SYSKEYDOWN: 03119 vk = LOBYTE(LOWORD(pqmsg->msg.wParam)); 03120 break; 03121 03122 case WM_LBUTTONUP: 03123 fDown = FALSE; 03124 03125 /* 03126 * Fall through. 03127 */ 03128 case WM_LBUTTONDOWN: 03129 vk = VK_LBUTTON; 03130 break; 03131 03132 case WM_RBUTTONUP: 03133 fDown = FALSE; 03134 03135 /* 03136 * Fall through. 03137 */ 03138 case WM_RBUTTONDOWN: 03139 vk = VK_RBUTTON; 03140 break; 03141 03142 case WM_MBUTTONUP: 03143 fDown = FALSE; 03144 03145 /* 03146 * Fall through. 03147 */ 03148 case WM_MBUTTONDOWN: 03149 vk = VK_MBUTTON; 03150 break; 03151 03152 case WM_XBUTTONUP: 03153 fDown = FALSE; 03154 03155 /* 03156 * Fall through. 03157 */ 03158 case WM_XBUTTONDOWN: 03159 UserAssert(GET_XBUTTON_WPARAM(pqmsg->msg.wParam) == XBUTTON1 || 03160 GET_XBUTTON_WPARAM(pqmsg->msg.wParam) == XBUTTON2); 03161 03162 switch (GET_XBUTTON_WPARAM(pqmsg->msg.wParam)) { 03163 case XBUTTON1: 03164 vk = VK_XBUTTON1; 03165 break; 03166 03167 case XBUTTON2: 03168 vk = VK_XBUTTON2; 03169 break; 03170 } 03171 03172 break; 03173 } 03174 03175 /* 03176 * Set toggle and down bits appropriately. 03177 */ 03178 if ((vk == VK_SHIFT) || (vk == VK_MENU) || (vk == VK_CONTROL)) { 03179 BYTE vkHanded, vkOtherHand; 03180 /* 03181 * Convert this virtual key into a differentiated (Left/Right) key 03182 * depending on the extended key bit. 03183 */ 03184 vkHanded = (vk - VK_SHIFT) * 2 + VK_LSHIFT + 03185 ((pqmsg->msg.lParam & EXTENDED_BIT) ? 1 : 0); 03186 vkOtherHand = vkHanded ^ 1; 03187 03188 if (vk == VK_SHIFT) { 03189 /* 03190 * Clear extended bit for r.h. Shift, since it isn't really 03191 * extended (bit was set to indicate right-handed) 03192 */ 03193 pqmsg->msg.lParam &= ~EXTENDED_BIT; 03194 } 03195 03196 /* 03197 * Update the key state for the differentiated (Left/Right) key. 03198 */ 03199 UpdateKeyState(pti->pq, vkHanded, fDown); 03200 03201 /* 03202 * Update key state for the undifferentiated (logical) key. 03203 */ 03204 if (fDown || !TestKeyStateDown(pti->pq, vkOtherHand)) { 03205 UpdateKeyState(pti->pq, vk, fDown); 03206 } 03207 } else { 03208 UpdateKeyState(pti->pq, vk, fDown); 03209 } 03210 }

BOOL xxxWaitMessage VOID   ) 
 

Definition at line 112 of file ntuser/kernel/input.c.

References BOOL, TRUE, and xxxSleepThread().

Referenced by NtUserWaitMessage(), xxxHelpLoop(), xxxMoveSize(), and xxxOldNextWindow().

00113 { 00114 return xxxSleepThread(QS_ALLINPUT | QS_EVENT, 0, TRUE); 00115 }

void zzzActiveCursorTracking PWND  pwnd  ) 
 

Definition at line 2187 of file ntuser/kernel/input.c.

References BOOL, BoundCursor(), tagLASTINPUT::dwFlags, GetActiveTrackPwnd(), glinp, gptCursorAsync, gspwndCursor, LINP_KEYBOARD, NULL, PtInRect(), tagWND::rcWindow, SetVisible(), SV_SET, SV_UNSET, TestWF, WFVISIBLE, and zzzInternalSetCursorPos().

Referenced by xxxProcessEventMessage(), and xxxSetForegroundWindow2().

02188 { 02189 BOOL fVisible; 02190 POINT pt; 02191 02192 /* 02193 * If the last input event wasn't from the keyboard, bail 02194 * The user is probably moving the mouse. 02195 */ 02196 if (!(glinp.dwFlags & LINP_KEYBOARD)) { 02197 return; 02198 } 02199 /* 02200 * If we're already there, bail. 02201 */ 02202 if (PtInRect((LPRECT)&pwnd->rcWindow, gptCursorAsync)) { 02203 return; 02204 } 02205 /* 02206 * If the window the mouse is on is not "active-trackable", then 02207 * we can leave the mouse right where it is 02208 */ 02209 if ((gspwndCursor != NULL) && (GetActiveTrackPwnd(gspwndCursor, NULL) == NULL)) { 02210 return; 02211 } 02212 /* 02213 * If this window doesn't have a point visible in the screen, bail 02214 */ 02215 pt.x = pwnd->rcWindow.left + ((pwnd->rcWindow.right - pwnd->rcWindow.left) / 2); 02216 pt.y = pwnd->rcWindow.top + ((pwnd->rcWindow.bottom - pwnd->rcWindow.top) / 2); 02217 BoundCursor(&pt); 02218 if (!PtInRect((LPRECT)&pwnd->rcWindow, pt)) { 02219 return; 02220 } 02221 /* 02222 * We need to make sure that this window is marked as visible or someone 02223 * else will be waken up to update the cursor (and might 02224 * activate itself because of the active tracking). 02225 * 02226 * Later5.0 GerardoB: If the window is still not visible when 02227 * it wakes up, then we're out of luck. 02228 */ 02229 fVisible = TestWF(pwnd, WFVISIBLE); 02230 if (!fVisible) { 02231 SetVisible(pwnd, SV_SET); 02232 } 02233 02234 /* 02235 * Move the cursor to the center of this window 02236 */ 02237 zzzInternalSetCursorPos(pt.x, pt.y); 02238 /* 02239 * Restore visible bit. 02240 */ 02241 if (!fVisible) { 02242 SetVisible(pwnd, SV_UNSET); 02243 } 02244 }

void zzzAddAttachment PTHREADINFO  pti,
PQ  pqAttach,
LPBOOL  pfChanged
 

Definition at line 5305 of file ntuser/kernel/input.c.

References tagQ::cThreads, NULL, tagTHREADINFO::pqAttach, TRUE, and zzzDestroyQueue().

Referenced by zzzRecalc2().

05309 { 05310 if (pti->pqAttach != pqAttach) { 05311 /* 05312 * LATER 05313 * !!! This is totally screwed up, The only reason that this thing 05314 * could be non null is because two threads are going through 05315 * zzzAttachThreadInput() at the same time. No one can predict 05316 * what kind of problems are going to be caused by that. 05317 * We leave the critical section in one place where we send 05318 * WM_CANCELMODE below. We should figure out how to remove 05319 * the sendmessage. 05320 * 05321 * If there already is a queue there, as there may be, destroy it. 05322 * Note that zzzDestroyQueue() will only get rid of the queue if the 05323 * thread reference count goes to 0. 05324 */ 05325 PQ pqDestroy = pti->pqAttach; 05326 pti->pqAttach = pqAttach; 05327 if (pqDestroy != NULL) 05328 zzzDestroyQueue(pqDestroy, pti); 05329 pqAttach->cThreads++; 05330 *pfChanged = TRUE; 05331 } 05332 }

BOOL zzzAttachThreadInput PTHREADINFO  ptiAttach,
PTHREADINFO  ptiAttachTo,
BOOL  fAttach
 

Definition at line 6367 of file ntuser/kernel/input.c.

References ATTACHINFO, BOOL, CheckCritIn, tagDESKTOP::dwConsoleIMEThreadId, tagDESKTOP::dwConsoleThreadId, FALSE, FJOURNALPLAYBACK, FJOURNALRECORD, gpai, IS_IME_ENABLED, NULL, tagATTACHINFO::paiNext, tagATTACHINFO::pti1, tagATTACHINFO::pti2, PtiFromThreadId(), tagTHREADINFO::rpdesk, TIF_DONTATTACHQUEUE, tagTHREADINFO::TIF_flags, TRUE, and zzzReattachThreads().

Referenced by NtUserAttachThreadInput(), xxxCreateWindowEx(), xxxDestroyWindow(), xxxHandleOwnerSwitch(), and xxxSetParent().

06371 { 06372 CheckCritIn(); 06373 06374 /* 06375 * Attaching to yourself doesn't make any sense. 06376 */ 06377 if (ptiAttach == ptiAttachTo) 06378 return FALSE; 06379 06380 #if defined(FE_IME) 06381 /* 06382 * For console IME issue 06383 * 06384 * Console IME do attach to console input thread message queue. 06385 * So needs share message queue for synchronize a key state. 06386 */ 06387 if (IS_IME_ENABLED()) { 06388 PTHREADINFO ptiConsoleIME; 06389 PTHREADINFO ptiConsoleInput; 06390 06391 if ( ((ptiConsoleIME = PtiFromThreadId(ptiAttach->rpdesk->dwConsoleIMEThreadId)) != NULL) && 06392 ((ptiConsoleInput = PtiFromThreadId(ptiAttach->rpdesk->dwConsoleThreadId)) != NULL) && 06393 (ptiAttach == ptiConsoleIME) && 06394 (ptiAttachTo == ptiConsoleInput) && 06395 (ptiConsoleIME->TIF_flags & TIF_DONTATTACHQUEUE) 06396 ) 06397 { 06398 goto SkipCheck; 06399 } 06400 } 06401 #endif 06402 /* 06403 * Will this thread allow attaching? Shell threads and system threads 06404 * won't allow attaching. 06405 */ 06406 if (ptiAttachTo->TIF_flags & TIF_DONTATTACHQUEUE) 06407 return FALSE; 06408 if (ptiAttach->TIF_flags & TIF_DONTATTACHQUEUE) 06409 return FALSE; 06410 06411 #if defined(FE_IME) 06412 SkipCheck: 06413 #endif 06414 /* 06415 * Don't allow attaching across desktops, either. 06416 */ 06417 if (ptiAttachTo->rpdesk != ptiAttach->rpdesk) 06418 return FALSE; 06419 06420 /* 06421 * If attaching, make a new attachinfo structure for this thread. 06422 * If not attaching, remove an existing attach reference. 06423 */ 06424 if (fAttach) { 06425 PATTACHINFO pai; 06426 06427 /* 06428 * Alloc a new attachinfo struct, fill it in, link it in. 06429 */ 06430 if ((pai = (PATTACHINFO)UserAllocPool(sizeof(ATTACHINFO), TAG_ATTACHINFO)) == NULL) 06431 return FALSE; 06432 06433 pai->pti1 = ptiAttach; 06434 pai->pti2 = ptiAttachTo;; 06435 pai->paiNext = gpai; 06436 gpai = pai; 06437 } else { 06438 PATTACHINFO *ppai; 06439 BOOL fFound = FALSE; 06440 06441 /* 06442 * Search for this attachinfo struct. If we can't find it, fail. 06443 * If we do find it, unlink it and free it. 06444 */ 06445 for (ppai = &gpai; (*ppai) != NULL; ppai = &(*ppai)->paiNext) { 06446 if (((*ppai)->pti2 == ptiAttachTo) && ((*ppai)->pti1 == ptiAttach)) { 06447 PATTACHINFO paiKill = *ppai; 06448 fFound = TRUE; 06449 *ppai = (*ppai)->paiNext; 06450 UserFreePool((HLOCAL)paiKill); 06451 break; 06452 } 06453 } 06454 06455 /* 06456 * If we couldn't find this reference, then fail. 06457 */ 06458 if (!fFound) { 06459 return FALSE; 06460 } 06461 } 06462 06463 /* 06464 * Now do the actual reattachment work for all threads - unless we're 06465 * journalling. If we did by mistake do attachment while journalling 06466 * was occuring, journalling would be hosed because journalling requires 06467 * all threads to be attached - but it is also treated as a special 06468 * case so it doesn't affect the ATTACHINFO structures. Therefore 06469 * recalcing attach info based on ATTACHINFO structures would break 06470 * the attachment required for journalling. 06471 */ 06472 if (!FJOURNALRECORD() && !FJOURNALPLAYBACK()) 06473 return zzzReattachThreads(FALSE); 06474 06475 return TRUE; 06476 }

void zzzAttachToQueue PTHREADINFO  pti,
PQ  pqAttach,
PQ  pqJournal,
BOOL  fJoiningForeground
 

Definition at line 5940 of file ntuser/kernel/input.c.

References CANCEL_ACTIVESTATE, CANCEL_CAPTURESTATE, CANCEL_FOCUSSTATE, CancelInputState(), tagQ::caret, CheckTransferState(), tagMLIST::cMsgs, tagQ::codeCapture, tagQ::cThreads, CTS_CANCELOLD, CTS_DONOTHING, CTS_TRANSFER, ExitMenuLoop(), tagMENUSTATE::fInDoDragDrop, tagMENUSTATE::fModelessMenu, GETPTI, gspwndCursor, tagQ::iCursorLevel, IsInsideMenuLoop(), Lock, LockCaptureWindow(), LockQCursor, tagQ::mlInput, NULL, tagMENUSTATE::pGlobalPopupMenu, tagTHREADINFO::pMenuState, tagTHREADINFO::pq, tagMLIST::pqmsgRead, tagMLIST::pqmsgWriteLast, tagQ::ptiKeyboard, tagQ::ptiMouse, tagQ::ptiSysLock, QF_ACTIVATIONCHANGE, QF_CAPTURELOCKED, tagQ::QF_flags, RedistributeInput(), tagQ::spcurCurrent, tagCARET::spwnd, tagQ::spwndActive, tagQ::spwndActivePrev, tagQ::spwndCapture, tagQ::spwndFocus, tagWND::spwndNext, Unlock, UnlockCaptureWindow(), and zzzDestroyQueue().

Referenced by xxxHardErrorControl(), xxxSetThreadDesktop(), xxxSwitchDesktop(), zzzReattachThreads(), and zzzSetDesktop().

05945 { 05946 PQMSG pqmsgT; 05947 PQ pqDestroy; 05948 05949 /* 05950 * Check active state. 05951 */ 05952 switch (CheckTransferState(pti, pqAttach, 05953 FIELD_OFFSET(Q, spwndActive), fJoiningForeground)) { 05954 case CTS_CANCELOLD: 05955 CancelInputState(pti, CANCEL_ACTIVESTATE); 05956 break; 05957 05958 case CTS_TRANSFER: 05959 Lock(&pqAttach->spwndActive, pti->pq->spwndActive); 05960 Unlock(&pti->pq->spwndActive); 05961 05962 /* 05963 * The caret usually follows the focus window, which follows 05964 * the active window... 05965 */ 05966 if (pti->pq->caret.spwnd != NULL) { 05967 05968 if (GETPTI(pti->pq->caret.spwnd) == pti) { 05969 /* 05970 * Just copy the entire caret structure... that way we 05971 * don't need to deal with locking/unlocking the spwnd. 05972 */ 05973 if (pqAttach->caret.spwnd == NULL) { 05974 pqAttach->caret = pti->pq->caret; 05975 pti->pq->caret.spwnd = NULL; 05976 } 05977 } 05978 } 05979 break; 05980 } 05981 05982 /* 05983 * Check focus state. 05984 */ 05985 switch (CheckTransferState(pti, pqAttach, 05986 FIELD_OFFSET(Q, spwndFocus), fJoiningForeground)) { 05987 case CTS_CANCELOLD: 05988 CancelInputState(pti, CANCEL_FOCUSSTATE); 05989 break; 05990 05991 case CTS_TRANSFER: 05992 Lock(&pqAttach->spwndFocus, pti->pq->spwndFocus); 05993 Unlock(&pti->pq->spwndFocus); 05994 break; 05995 } 05996 05997 /* 05998 * Check capture state. 05999 */ 06000 switch (CheckTransferState(pti, pqAttach, 06001 FIELD_OFFSET(Q, spwndCapture), fJoiningForeground)) { 06002 case CTS_CANCELOLD: 06003 CancelInputState(pti, CANCEL_CAPTURESTATE); 06004 break; 06005 06006 case CTS_TRANSFER: 06007 LockCaptureWindow(pqAttach, pti->pq->spwndCapture); 06008 UnlockCaptureWindow(pti->pq); 06009 pqAttach->codeCapture = pti->pq->codeCapture; 06010 pqAttach->QF_flags ^= ((pqAttach->QF_flags ^ pti->pq->QF_flags) & QF_CAPTURELOCKED); 06011 break; 06012 06013 #if DBG 06014 case CTS_DONOTHING: 06015 /* 06016 * We should always transfer the capture state of a thread 06017 * in modal menu mode 06018 */ 06019 UserAssert((pti->pMenuState == NULL) 06020 || ExitMenuLoop(pti->pMenuState, pti->pMenuState->pGlobalPopupMenu) 06021 || pti->pMenuState->fModelessMenu 06022 || pti->pMenuState->fInDoDragDrop); 06023 06024 break; 06025 #endif 06026 } 06027 06028 /* 06029 * Check spwndActivePrev state. This check has some considerations. 06030 * If the CTS_TRANSFER is returned, it usually means there was no 06031 * prev-active in the attach-queue, and it will use the first 06032 * window it encounters. Since we walk the thread-list, a out-of-zorder 06033 * window could be chosen. So, to counter this, we'll check the 06034 * attach-queue-next-prev against the thread-previous window to see 06035 * if it is truly the next-zorder window. 06036 */ 06037 switch (CheckTransferState(pti, pqAttach, 06038 FIELD_OFFSET(Q, spwndActivePrev), fJoiningForeground)) { 06039 case CTS_TRANSFER: 06040 Lock(&pqAttach->spwndActivePrev, pti->pq->spwndActivePrev); 06041 Unlock(&pti->pq->spwndActivePrev); 06042 break; 06043 06044 case CTS_CANCELOLD: 06045 06046 /* 06047 * Check to see if the previous window is what we would expect it 06048 * to be. 06049 */ 06050 if (pqAttach->spwndActive && 06051 (pqAttach->spwndActivePrev && pti->pq->spwndActivePrev) && 06052 (pqAttach->spwndActive->spwndNext == pti->pq->spwndActivePrev)) { 06053 06054 Lock(&pqAttach->spwndActivePrev, pti->pq->spwndActivePrev); 06055 Unlock(&pti->pq->spwndActivePrev); 06056 } 06057 break; 06058 } 06059 06060 if (pti == pti->pq->ptiSysLock) { 06061 /* 06062 * Preserve any of the flags we might have already been set on pqAttach. 06063 * Note that these flags might have been set on a previous call 06064 * to this function that received the same pqAttach 06065 */ 06066 pqAttach->QF_flags ^= ((pqAttach->QF_flags ^ pti->pq->QF_flags) 06067 & ~(QF_CAPTURELOCKED)); 06068 06069 /* 06070 * Fix for 29967 "Start menu disappears when clicked and Office 06071 * taskbar has focus!". Win95 uses a global counter instead of this 06072 * flag. In NT when we click on Office taskbar and then on the Start 06073 * Menu, MSoffice calls zzzAttachThreadInput() which changes the Start 06074 * Menu's queue and the new queue has the QF_ACTIVATIONCHANGE flag on. 06075 * Inside the xxxMNLoop we test if this flag is on and if it is we 06076 * exit the menu. 06077 */ 06078 if (!IsInsideMenuLoop(pti)) { 06079 pqAttach->QF_flags &= ~QF_ACTIVATIONCHANGE; 06080 } 06081 06082 /* 06083 * Unlock the queue since pti is moving to anotther queue. 06084 */ 06085 /* CheckSysLock(6, pq, NULL); what number? */ 06086 pti->pq->ptiSysLock = NULL; 06087 } 06088 06089 if (gspwndCursor != NULL && pti == GETPTI(gspwndCursor)) { 06090 LockQCursor(pqAttach, pti->pq->spcurCurrent); 06091 } 06092 06093 /* 06094 * Each thread has its own cursor level, which is a count of the number 06095 * of times that app has called show/hide cursor. This gets added into 06096 * the queue's count for a completely accurate count every time this 06097 * queue recalculation is done. 06098 */ 06099 /* 06100 * LATER 06101 * We need to adjust the iCursorLevel of the old queue to reflect 06102 * the fact that a thread is departing. 06103 * FritzS 06104 */ 06105 pqAttach->iCursorLevel += pti->iCursorLevel; 06106 06107 /* 06108 * Pump up the new queue with the right input variables. 06109 */ 06110 pqAttach->ptiMouse = pti; 06111 pqAttach->ptiKeyboard = pti; 06112 06113 pqDestroy = pti->pq; 06114 06115 /* 06116 * Don't increment the thread count here because we already incremented 06117 * it when we put it in pti->pqAttach. Since we're moving it from pqAttach 06118 * to pq, we don't mess with the reference count. 06119 */ 06120 pti->pq = pqAttach; 06121 06122 /* 06123 * If the thread is using the journal queue, leave the message list 06124 * alone. Otherwise, redistribute the messages. 06125 */ 06126 if (pqDestroy != pqJournal) { 06127 06128 /* 06129 * Remember the current message list so it can get redistributed taking 06130 * into account ptiAttach's new queue. 06131 */ 06132 pqmsgT = pqDestroy->mlInput.pqmsgRead; 06133 pqDestroy->mlInput.pqmsgRead = NULL; 06134 pqDestroy->mlInput.pqmsgWriteLast = NULL; 06135 pqDestroy->mlInput.cMsgs = 0; 06136 06137 /* 06138 * Now redistribute the input messages from the old queue they go into the 06139 * right queues. 06140 * 06141 * Preserve the 'idSysPeek' when redistributing the queue 06142 */ 06143 RedistributeInput(pqmsgT, pqDestroy); 06144 06145 /* 06146 * Officially attach the new queue to this thread. Note that zzzDestroyQueue() 06147 * doesn't actually destroy anything until the thread reference count goes 06148 * to 0. 06149 */ 06150 zzzDestroyQueue(pqDestroy, pti); 06151 06152 } else { 06153 UserAssert(pqDestroy->cThreads); 06154 pqDestroy->cThreads--; 06155 } 06156 }

BOOL zzzReattachThreads BOOL  fJournalAttach  ) 
 

Definition at line 6158 of file ntuser/kernel/input.c.

References _GetNextQueueWindow(), BEGINATOMICCHECK, BOOL, tagQ::cLockCount, tagMLIST::cMsgs, tagQ::cThreads, DBGValidateQueueStates(), DeferWinEventNotify, ENDATOMICCHECK, EXITATOMICCHECK, FALSE, GETPTI, gpqForeground, gpqForegroundPrev, grpdeskRitInput, HWq, tagQ::mlInput, NULL, tagDESKTOP::pDeskInfo, PostEventMessage(), tagTHREADINFO::pq, tagTHREADINFO::pqAttach, tagMLIST::pqmsgRead, tagMLIST::pqmsgWriteLast, PtiCurrent, tagQ::ptiKeyboard, tagDESKTOP::PtiList, tagQ::ptiMouse, QEVENT_ACTIVATE, RedistributeInput(), tagTHREADINFO::rpdesk, tagDESKTOPINFO::spwnd, tagQ::spwndActive, tagQ::spwndActivePrev, tagWND::spwndChild, TRUE, zzzAttachToQueue(), zzzDestroyQueue(), zzzEndDeferWinEventNotify, zzzRecalcThreadAttachment(), and zzzSetFMouseMoved().

Referenced by xxxInternalGetMessage(), zzzAttachThreadInput(), zzzInitTask(), and zzzJournalAttach().

06160 { 06161 PTHREADINFO ptiCurrent = PtiCurrent(); 06162 PTHREADINFO pti; 06163 PQ pqForegroundPrevNew; 06164 PQ pqForegroundNew; 06165 PQ pqAttach; 06166 PQ pqJournal; 06167 PLIST_ENTRY pHead, pEntry; 06168 BOOL bHadAnActiveForegroundWindow; 06169 06170 /* 06171 * In all cases, do not leave do any send messages or any callbacks! 06172 * This is because this code is called from 06173 * SetWindowsHook(WH_JOURNALPLAYBACK | WH_JOURNALRECORD). No app currently 06174 * calling this routine expects to be called before this routine returns. 06175 * (If you do callback before it returns, you'll break at least Access 06176 * for Windows). - scottlu 06177 */ 06178 06179 #if DBG 06180 DBGValidateQueueStates(ptiCurrent->rpdesk); 06181 #endif 06182 06183 /* 06184 * Defer Win Event notifications so we can traverse PtiList with impunity 06185 * Also, we don't want to callback while we're half way attached 06186 */ 06187 DeferWinEventNotify(); 06188 BEGINATOMICCHECK(); 06189 06190 /* 06191 * Don't recalc attach info if this is a journal attach, because 06192 * the journal attach code has already done this for us. 06193 */ 06194 if (!fJournalAttach) { 06195 06196 /* 06197 * Now recalculate all the different queue groups, based on the 06198 * attach requests. This fills in the pqAttach of each thread info 06199 * with the new queue this thread belongs to. Always takes into 06200 * account all attachment requests. 06201 */ 06202 zzzRecalcThreadAttachment(); 06203 06204 /* 06205 * Make a guess about which queue is the journal queue. 06206 */ 06207 pqJournal = gpqForeground; 06208 if (pqJournal == NULL) 06209 pqJournal = ptiCurrent->pq; 06210 06211 /* 06212 * If the queue is only used by one thread, perform normal processing. 06213 */ 06214 if (pqJournal->cThreads == 1) { 06215 pqJournal = NULL; 06216 } else { 06217 06218 /* 06219 * Lock the queue to ensure that it stays valid 06220 * until we have redistributed the input. 06221 */ 06222 (pqJournal->cLockCount)++; 06223 } 06224 } else { 06225 pqJournal = NULL; 06226 } 06227 06228 /* 06229 * What will be the new foreground queue? 06230 */ 06231 pqForegroundNew = NULL; 06232 06233 /* 06234 * Remember if there is a foreground window so we don't force one 06235 * at the end if there wasn't one before the attach 06236 */ 06237 if (gpqForeground != NULL && gpqForeground->spwndActive != NULL) { 06238 bHadAnActiveForegroundWindow = TRUE; 06239 pqForegroundNew = GETPTI(gpqForeground->spwndActive)->pqAttach; 06240 } else { 06241 bHadAnActiveForegroundWindow = FALSE; 06242 } 06243 06244 pqForegroundPrevNew = NULL; 06245 if (gpqForegroundPrev != NULL && gpqForegroundPrev->spwndActivePrev != NULL) { 06246 pqForegroundPrevNew = GETPTI(gpqForegroundPrev->spwndActivePrev)->pqAttach; 06247 } 06248 06249 06250 pHead = &ptiCurrent->rpdesk->PtiList; 06251 for (pEntry = pHead->Flink; pEntry != pHead; pEntry = pEntry->Flink) { 06252 pti = CONTAINING_RECORD(pEntry, THREADINFO, PtiLink); 06253 06254 if (pti->pqAttach == pti->pq) { 06255 pti->pqAttach = NULL; 06256 } else if(pti->pqAttach != NULL) { 06257 /* 06258 * It is crucial that we NULL out pqAttach for this queue once 06259 * we have it in a local variable because the NULL-ness of this 06260 * field is checked in attach operations. 06261 */ 06262 pqAttach = pti->pqAttach; 06263 pti->pqAttach = NULL; 06264 06265 zzzAttachToQueue(pti, pqAttach, pqJournal, pqForegroundNew == pqAttach); 06266 } 06267 06268 } 06269 06270 /* 06271 * If we are doing a journal detach, redistribute the input messages 06272 * from the old queue. 06273 */ 06274 if (pqJournal != NULL) { 06275 PQMSG pqmsgRedist; 06276 06277 UserAssert(pqJournal->cLockCount); 06278 (pqJournal->cLockCount)--; 06279 pqmsgRedist = pqJournal->mlInput.pqmsgRead; 06280 06281 pqJournal->mlInput.pqmsgRead = NULL; 06282 pqJournal->mlInput.pqmsgWriteLast = NULL; 06283 pqJournal->mlInput.cMsgs = 0; 06284 RedistributeInput(pqmsgRedist, pqJournal); 06285 06286 /* 06287 * Only destroy the queue if it is no longer is use. 06288 */ 06289 if (pqJournal->cThreads == 0) { 06290 pqJournal->cThreads = 1; // prevent underflow 06291 zzzDestroyQueue(pqJournal, pti); // DeferWinEventNotify() ?? IANJA ?? 06292 } else { 06293 /* 06294 * Make sure that this queue doesn't point to a pti 06295 * no longer attached to it. 06296 * Hopefully we'll go to zzzDestroyQueue only once 06297 * Increment cThreads so the queue won't be destroyed 06298 * but we'll simply reassign the pti fields. 06299 */ 06300 if ((pqJournal->ptiMouse != NULL) 06301 && (pqJournal != pqJournal->ptiMouse->pq)) { 06302 pqJournal->cThreads++; 06303 zzzDestroyQueue(pqJournal, pqJournal->ptiMouse); 06304 } 06305 if ((pqJournal->ptiKeyboard != NULL) 06306 && (pqJournal != pqJournal->ptiKeyboard->pq)) { 06307 pqJournal->cThreads++; 06308 zzzDestroyQueue(pqJournal, pqJournal->ptiKeyboard); 06309 } 06310 } 06311 } 06312 06313 #if DBG 06314 DBGValidateQueueStates(ptiCurrent->rpdesk); 06315 #endif 06316 06317 /* 06318 * If the current thread is not on the active desktop, do not 06319 * change the global foreground state. 06320 */ 06321 if (PtiCurrent()->rpdesk != grpdeskRitInput) { 06322 EXITATOMICCHECK(); 06323 zzzEndDeferWinEventNotify(); 06324 return TRUE; 06325 } 06326 06327 /* 06328 * We're done attaching. gptiForeground hasn't changed... but 06329 * gpqForeground has! Try not to leave NULL as the foreground. 06330 */ 06331 #if DBG 06332 DBGValidateQueue(pqForegroundNew); 06333 #endif 06334 gpqForeground = pqForegroundNew; 06335 // So we can Alt-Esc xxxNextWindow without an AV 06336 // If we have a non-NULL gpqForeground, its kbd input thread better have an rpdesk! 06337 UserAssert(!gpqForeground || (gpqForeground->ptiKeyboard && gpqForeground->ptiKeyboard->rpdesk)); 06338 gpqForegroundPrev = pqForegroundPrevNew; 06339 06340 ENDATOMICCHECK(); 06341 zzzEndDeferWinEventNotify(); 06342 06343 if ((gpqForeground == NULL) && (bHadAnActiveForegroundWindow)) { 06344 PWND pwndNewForeground; 06345 PTHREADINFO pti = PtiCurrent(); 06346 06347 pwndNewForeground = _GetNextQueueWindow(pti->rpdesk->pDeskInfo->spwnd->spwndChild, 0, FALSE); 06348 06349 /* 06350 * Don't use xxxSetForegroundWindow2 because we must not leave 06351 * the critical section. There is no currently active foreground 06352 * so all that is needed is to post an activate event to the 06353 * new foreground queue. 06354 */ 06355 if (pwndNewForeground != NULL) { 06356 PostEventMessage(GETPTI(pwndNewForeground), 06357 GETPTI(pwndNewForeground)->pq, QEVENT_ACTIVATE, NULL, 0, 06358 0, (LPARAM)HWq(pwndNewForeground)); 06359 } 06360 } 06361 zzzSetFMouseMoved(); 06362 UserAssert((gpqForeground == NULL) || (gpqForeground->ptiMouse->rpdesk == grpdeskRitInput)); 06363 06364 return TRUE; 06365 }

void zzzRecalc2 PQ  pqAttach  ) 
 

Definition at line 5334 of file ntuser/kernel/input.c.

References BEGINATOMICCHECK, BOOL, DeferWinEventNotify, ENDATOMICCHECK, FALSE, gpai, NULL, tagATTACHINFO::paiNext, tagTHREADINFO::ppi, tagTHREADINFO::pqAttach, tagATTACHINFO::pti1, tagATTACHINFO::pti2, PtiCurrent, tagDESKTOP::PtiList, tagTHREADINFO::rpdesk, TIF_16BIT, tagTHREADINFO::TIF_flags, zzzAddAttachment(), and zzzEndDeferWinEventNotify.

Referenced by zzzRecalcThreadAttachment().

05336 { 05337 PATTACHINFO pai; 05338 PTHREADINFO pti; 05339 BOOL fChanged; 05340 PLIST_ENTRY pHead, pEntry; 05341 05342 /* 05343 * Defer Win Event notifications so we can traverse PtiList with impunity 05344 * #bug number from shiflet 05345 */ 05346 DeferWinEventNotify(); 05347 BEGINATOMICCHECK(); 05348 05349 /* 05350 * Keep adding attachments until everything that should be attached to this 05351 * queue is attached 05352 */ 05353 do { 05354 fChanged = FALSE; 05355 05356 /* 05357 * If a thread is attached to this Q attach all of it's attachments 05358 * and MWOW buddies if they aren't already attached. 05359 */ 05360 pHead = &PtiCurrent()->rpdesk->PtiList; 05361 for (pEntry = pHead->Flink; pEntry != pHead; pEntry = pEntry->Flink) { 05362 pti = CONTAINING_RECORD(pEntry, THREADINFO, PtiLink); 05363 05364 if (pti->pqAttach == pqAttach) { 05365 /* 05366 * check each of the attachments to see if this thread is attached 05367 * to any other threads 05368 */ 05369 for (pai = gpai; pai != NULL; pai = pai->paiNext) { 05370 /* 05371 * if they weren't attached already, attach them 05372 */ 05373 if (pai->pti1 == pti || pai->pti2 == pti) { 05374 zzzAddAttachment((pai->pti1 == pti) ? pai->pti2 : pai->pti1, 05375 pqAttach, &fChanged); 05376 } 05377 } 05378 05379 /* 05380 * If this is a 16bit thread attach to all other threads in 05381 * it's MWOW 05382 */ 05383 if (pti->TIF_flags & TIF_16BIT) { 05384 PTHREADINFO ptiAttach; 05385 PLIST_ENTRY pHeadAttach, pEntryAttach; 05386 05387 pHeadAttach = &pti->rpdesk->PtiList; 05388 for (pEntryAttach = pHeadAttach->Flink; 05389 pEntryAttach != pHeadAttach; 05390 pEntryAttach = pEntryAttach->Flink) { 05391 ptiAttach = CONTAINING_RECORD(pEntryAttach, THREADINFO, PtiLink); 05392 05393 if (ptiAttach->TIF_flags & TIF_16BIT && 05394 ptiAttach->ppi == pti->ppi) { 05395 zzzAddAttachment(ptiAttach, pqAttach, &fChanged); 05396 } 05397 } 05398 } 05399 } 05400 } 05401 } while (fChanged); 05402 ENDATOMICCHECK(); 05403 zzzEndDeferWinEventNotify(); 05404 }

void zzzRecalcThreadAttachment  ) 
 

Definition at line 5407 of file ntuser/kernel/input.c.

References AllocQueue(), tagQ::cThreads, IsWinEventNotifyDeferred, NULL, tagTHREADINFO::pq, tagTHREADINFO::pqAttach, PtiCurrent, and zzzRecalc2().

Referenced by zzzReattachThreads().

05408 { 05409 PTHREADINFO pti; 05410 PLIST_ENTRY pHead, pEntry; 05411 05412 /* 05413 * Win Event notifications must be defered so we can traverse PtiList with impunity 05414 */ 05415 UserAssert(IsWinEventNotifyDeferred()); 05416 05417 /* 05418 * For all threads, start an attach queue if a thread hasn't been 05419 * attached yet. 05420 */ 05421 pHead = &PtiCurrent()->rpdesk->PtiList; 05422 for (pEntry = pHead->Flink; pEntry != pHead; pEntry = pEntry->Flink) { 05423 pti = CONTAINING_RECORD(pEntry, THREADINFO, PtiLink); 05424 05425 /* 05426 * Assert: We should not leave the critsect from xxxCreateThreadInfo 05427 * with the new thread in the rpdesk->PtiList but not yet with a queue. 05428 */ 05429 UserAssert(pti->pq != NULL); 05430 05431 if (pti->pqAttach == NULL) { 05432 05433 /* 05434 * Allocate a new queue for this thread if more than 05435 * one thread references it. 05436 */ 05437 if (pti->pq->cThreads > 1) { 05438 pti->pqAttach = AllocQueue(NULL, NULL); 05439 05440 if (pti->pqAttach == NULL) { 05441 RIPMSG0(RIP_WARNING, "zzzRecalcThreadAttachment: AllocQueue failed"); 05442 break; 05443 } 05444 05445 pti->pqAttach->cThreads++; 05446 } else { 05447 pti->pqAttach = pti->pq; 05448 } 05449 05450 /* 05451 * Attach every thread that is directly or indirectly attached 05452 * to this thread. 05453 */ 05454 zzzRecalc2(pti->pqAttach); 05455 } 05456 } 05457 }

VOID zzzSetFMouseMoved  ) 
 

Definition at line 1363 of file ntuser/kernel/input.c.

References DeferWinEventNotify, DF_MOUSEMOVETRK, tagDESKTOP::dwDTFlags, gdwMouseMoveExtraInfo, GETPDESK, GETPTI, gpqCursor, gpsi, grpdeskRitInput, gspwndCursor, gspwndInternalCapture, gspwndMouseOwner, gspwndScreenCapture, tagDESKTOP::htEx, Lock, NULL, tagDESKTOP::pDeskInfo, PostEventMessage(), tagTHREADINFO::pq, tagQ::ptiMouse, PtoHq, QEVENT_CANCELMOUSEMOVETRK, tagQ::QF_flags, QF_MOUSEMOVED, SetWakeBit(), SpeedHitTest(), tagDESKTOPINFO::spwnd, tagQ::spwndCapture, tagDESKTOP::spwndTrack, VOID(), WakeSomeone(), zzzEndDeferWinEventNotify, and zzzUpdateCursorImage().

Referenced by ProcessQueuedMouseEvents(), xxxCapture(), xxxDestroyThreadInfo(), xxxMoveSize(), zzzDestroyQueue(), zzzInternalSetCursorPos(), zzzInvalidateDCCache(), zzzReattachThreads(), and zzzSetWindowsHookEx().

01364 { 01365 PWND pwnd; 01366 PWND pwndOldCursor; 01367 PQ pq; 01368 01369 #ifdef REDIRECTION 01370 PWND pwndStart; 01371 POINT ptMouse = gpsi->ptCursor; 01372 #endif // REDIRECTION 01373 01374 /* 01375 * Need to first figure out what queue this mouse event is in. Do NOT 01376 * check for mouse capture here !! Talk to scottlu. 01377 */ 01378 if ((pwnd = gspwndScreenCapture) == NULL) { 01379 01380 #ifdef REDIRECTION 01381 /* 01382 * Call the speed hit test hook 01383 */ 01384 pwndStart = xxxCallSpeedHitTestHook(&ptMouse); 01385 #endif // REDIRECTION 01386 01387 if ((pwnd = gspwndMouseOwner) == NULL) { 01388 if ((pwnd = gspwndInternalCapture) == NULL) { 01389 01390 UserAssert(grpdeskRitInput != NULL); 01391 01392 #ifdef REDIRECTION 01393 if (pwndStart == NULL) { 01394 pwndStart = grpdeskRitInput->pDeskInfo->spwnd; 01395 } 01396 pwnd = SpeedHitTest(pwndStart, ptMouse); 01397 #else 01398 pwnd = SpeedHitTest(grpdeskRitInput->pDeskInfo->spwnd, gpsi->ptCursor); 01399 #endif // REDIRECTION 01400 01401 } 01402 } 01403 } 01404 01405 if (pwnd == NULL) 01406 return; 01407 01408 /* 01409 * This is apparently needed by the attach/unattach code for some 01410 * reason. I'd like to get rid of it - scottlu. 01411 */ 01412 pwndOldCursor = Lock(&gspwndCursor, pwnd); 01413 01414 /* 01415 * If we're giving a mouse move to a new queue, be sure the cursor 01416 * image represents what this queue thinks it should be. 01417 */ 01418 pq = GETPTI(pwnd)->pq; 01419 01420 /* 01421 * Protect pq by deferring WinEvent notification 01422 */ 01423 DeferWinEventNotify(); 01424 01425 if (pq != gpqCursor) { 01426 /* 01427 * If the old queue had the mouse captured, let him know that 01428 * the mouse moved first. Need this to fix tooltips in 01429 * WordPerfect Office. Do the same for mouse tracking. 01430 */ 01431 if (gpqCursor != NULL) { 01432 01433 if (gpqCursor->spwndCapture != NULL) { 01434 gpqCursor->QF_flags |= QF_MOUSEMOVED; 01435 SetWakeBit(GETPTI(gpqCursor->spwndCapture), QS_MOUSEMOVE); 01436 01437 #ifdef REDIRECTION 01438 PushMouseMove(gpqCursor, ptMouse); 01439 #endif // REDIRECTION 01440 01441 } 01442 01443 if ((pwndOldCursor != NULL) && (PtoHq(pwndOldCursor) != PtoHq(pwnd))) { 01444 PDESKTOP pdesk = GETPDESK(pwndOldCursor); 01445 if (pdesk->dwDTFlags & DF_MOUSEMOVETRK) { 01446 PTHREADINFO pti = GETPTI(pdesk->spwndTrack); 01447 PostEventMessage(pti, pti->pq, QEVENT_CANCELMOUSEMOVETRK, 01448 pdesk->spwndTrack, pdesk->dwDTFlags, pdesk->htEx, 01449 DF_MOUSEMOVETRK); 01450 pdesk->dwDTFlags &= ~DF_MOUSEMOVETRK; 01451 } 01452 } 01453 } 01454 01455 /* 01456 * First re-assign gpqCursor so any zzzSetCursor() calls 01457 * will only take effect if done by the thread that 01458 * owns the window the mouse is currently over. 01459 */ 01460 gpqCursor = pq; 01461 01462 /* 01463 * Call zzzUpdateCursorImage() so the new gpqCursor's 01464 * notion of the current cursor is represented. 01465 */ 01466 zzzUpdateCursorImage(); 01467 01468 } 01469 01470 /* 01471 * Set the mouse moved bit for this queue so we know later to post 01472 * a move message to this queue. 01473 */ 01474 pq->QF_flags |= QF_MOUSEMOVED; 01475 01476 #ifdef REDIRECTION 01477 PushMouseMove(pq, ptMouse); 01478 #endif // REDIRECTION 01479 01480 01481 /* 01482 * Reassign mouse input to this thread - this indicates which thread 01483 * to wake up when new input comes in. 01484 */ 01485 pq->ptiMouse = GETPTI(pwnd); 01486 01487 /* 01488 * Wake some thread within this queue to process this mouse event. 01489 */ 01490 WakeSomeone(pq, WM_MOUSEMOVE, NULL); 01491 01492 /* 01493 * We're possibly generating a fake mouse move message - it has no 01494 * extra info associated with it - so 0 it out. 01495 */ 01496 gdwMouseMoveExtraInfo = 0; 01497 01498 zzzEndDeferWinEventNotify(); 01499 }

void zzzWakeInputIdle PTHREADINFO  pti  ) 
 

Definition at line 5200 of file ntuser/kernel/input.c.

References NULL, tagWOWTHREADINFO::pIdleEvent, tagTHREADINFO::ppi, tagTHREADINFO::ptdb, tagPROCESSINFO::ptiMainThread, tagTDB::pwti, SET_PSEUDO_EVENT, TIF_16BIT, TIF_FIRSTIDLE, tagTHREADINFO::TIF_flags, TIF_SHAREDWOW, and zzzCalcStartCursorHide().

Referenced by xxxGetInputEvent(), xxxInternalGetMessage(), xxxMsgWaitForMultipleObjects(), xxxSleepTask(), and xxxSleepThread().

05202 { 05203 PW32PROCESS W32Process = W32GetCurrentProcess(); 05204 05205 /* 05206 * clear out the TIF_FIRSTIDLE since here we are 05207 */ 05208 pti->TIF_flags &= ~TIF_FIRSTIDLE; 05209 05210 05211 /* 05212 * Shared Wow Apps use the per thread idle event for synchronization. 05213 * Separate Wow VDMs use the regular mechanism. 05214 */ 05215 if (pti->TIF_flags & TIF_SHAREDWOW) { 05216 UserAssert(pti->TIF_flags & TIF_16BIT); 05217 if (pti->ptdb->pwti) { 05218 SET_PSEUDO_EVENT(&pti->ptdb->pwti->pIdleEvent); 05219 } 05220 } else { 05221 /* 05222 * If the main thread is NULL, set it to this queue: it is calling 05223 * GetMessage(). 05224 */ 05225 if (pti->ppi->ptiMainThread == NULL) 05226 pti->ppi->ptiMainThread = pti; 05227 05228 /* 05229 * Wake up anyone waiting on this event. 05230 */ 05231 if (pti->ppi->ptiMainThread == pti) { 05232 SET_PSEUDO_EVENT(&W32Process->InputIdleEvent); 05233 } 05234 } 05235 05236 /* 05237 * Check to see if the startglass is on, and if so turn it off and update. 05238 */ 05239 if (W32Process->W32PF_Flags & W32PF_STARTGLASS) { 05240 /* 05241 * This app is no longer in "starting" mode. Recalc when to hide 05242 * the app starting cursor. 05243 */ 05244 W32Process->W32PF_Flags &= ~W32PF_STARTGLASS; 05245 zzzCalcStartCursorHide(NULL, 0); 05246 } 05247 }


Generated on Sat May 15 19:44:13 2004 for test by doxygen 1.3.7