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

hooks.c File Reference

#include "precomp.h"

Go to the source code of this file.

Defines

#define HKF_SYSTEM   0x01
#define HKF_TASK   0x02
#define HKF_JOURNAL   0x04
#define HKF_NZRET   0x08
#define HKF_INTERSENDABLE   0x10
#define HKF_LOWLEVEL   0x20
#define IS_CHAR_MSG(msg)   ((msg) & 0x02)
#define DbgValidatefsHook(phk, nFilterType, pti, fGlobal)

Functions

void UnlinkHook (PHOOK phkFree)
BOOL zzzJournalAttach (PTHREADINFO pti, BOOL fAttach)
void InterQueueMsgCleanup (DWORD dwTimeFromLastRead)
void zzzCancelJournalling (void)
PROC zzzSetWindowsHookAW (int nFilterType, PROC pfnFilterProc, DWORD dwFlags)
PHOOK zzzSetWindowsHookEx (HANDLE hmod, PUNICODE_STRING pstrLib, PTHREADINFO ptiThread, int nFilterType, PROC pfnFilterProc, DWORD dwFlags)
LRESULT xxxCallNextHookEx (int nCode, WPARAM wParam, LPARAM lParam)
VOID CheckWHFBits (PTHREADINFO pti, int nFilterType)
BOOL zzzUnhookWindowsHook (int nFilterType, PROC pfnFilterProc)
BOOL zzzUnhookWindowsHookEx (PHOOK phkFree)
BOOL _CallMsgFilter (LPMSG pmsg, int nCode)
int xxxCallHook (int nCode, WPARAM wParam, LPARAM lParam, int iHook)
LRESULT xxxCallHook2 (PHOOK phkCall, int nCode, WPARAM wParam, LPARAM lParam, LPBOOL lpbAnsiHook)
BOOL xxxCallMouseHook (UINT message, PMOUSEHOOKSTRUCTEX pmhs, BOOL fRemove)
void xxxCallJournalRecordHook (PQMSG pqmsg)
DWORD xxxCallJournalPlaybackHook (PQMSG pqmsg)
VOID FreeHook (PHOOK phkFree)
PHOOK PhkFirstGlobalValid (PTHREADINFO pti, int nFilterType)
PHOOK PhkFirstValid (PTHREADINFO pti, int nFilterType)
VOID FreeThreadsWindowHooks (VOID)
VOID zzzRegisterSystemThread (DWORD dwFlags, DWORD dwReserved)

Variables

CONST int ampiHookError [CWINHOOKS]
CONST BYTE abHookFlags [CWINHOOKS]


Define Documentation

#define DbgValidatefsHook phk,
nFilterType,
pti,
fGlobal   ) 
 

Definition at line 274 of file hooks.c.

Referenced by PhkFirstGlobalValid(), and PhkFirstValid().

#define HKF_INTERSENDABLE   0x10
 

Definition at line 24 of file hooks.c.

Referenced by xxxCallHook2(), zzzSetWindowsHookEx(), and zzzUnhookWindowsHookEx().

#define HKF_JOURNAL   0x04
 

Definition at line 22 of file hooks.c.

Referenced by xxxCallHook2(), zzzSetWindowsHookEx(), and zzzUnhookWindowsHookEx().

#define HKF_LOWLEVEL   0x20
 

Definition at line 25 of file hooks.c.

Referenced by xxxCallHook2().

#define HKF_NZRET   0x08
 

Definition at line 23 of file hooks.c.

Referenced by zzzSetWindowsHookAW().

#define HKF_SYSTEM   0x01
 

Definition at line 20 of file hooks.c.

#define HKF_TASK   0x02
 

Definition at line 21 of file hooks.c.

Referenced by zzzSetWindowsHookEx().

#define IS_CHAR_MSG msg   )     ((msg) & 0x02)
 

Definition at line 126 of file hooks.c.

Referenced by xxxCallJournalPlaybackHook().


Function Documentation

BOOL _CallMsgFilter LPMSG  pmsg,
int  nCode
 

Definition at line 1210 of file hooks.c.

References BOOL, FALSE, IsHooked, PtiCurrent, TRUE, WHF_MSGFILTER, WHF_SYSMSGFILTER, and xxxCallHook().

Referenced by NtUserCallMsgFilter(), xxxMNLoop(), xxxMoveSize(), xxxOldNextWindow(), xxxSBTrackLoop(), and xxxSendMenuSelect().

01213 { 01214 PTHREADINFO pti; 01215 01216 pti = PtiCurrent(); 01217 01218 /* 01219 * First call WH_SYSMSGFILTER. If it returns non-zero, don't 01220 * bother calling WH_MSGFILTER, just return TRUE. Otherwise 01221 * return what WH_MSGFILTER gives us. 01222 */ 01223 if (IsHooked(pti, WHF_SYSMSGFILTER) && xxxCallHook(nCode, 0, (LPARAM)pmsg, 01224 WH_SYSMSGFILTER)) { 01225 return TRUE; 01226 } 01227 01228 if (IsHooked(pti, WHF_MSGFILTER)) { 01229 return (BOOL)xxxCallHook(nCode, 0, (LPARAM)pmsg, WH_MSGFILTER); 01230 } 01231 01232 return FALSE; 01233 }

VOID CheckWHFBits PTHREADINFO  pti,
int  nFilterType
 

Definition at line 986 of file hooks.c.

References BOOL, FALSE, tagHOOK::flags, tagDESKTOPINFO::fsHooks, _CLIENTINFO::fsHooks, tagTHREADINFO::fsHooks, HF_GLOBAL, KeAttachProcess(), KeDetachProcess(), NULL, tagTHREADINFO::pClientInfo, tagTHREADINFO::pDeskInfo, PhkFirstGlobalValid(), PhkFirstValid(), tagTHREADINFO::ppi, PpiCurrent, TRUE, VOID(), and WHF_FROM_WH.

Referenced by FreeHook().

00989 { 00990 BOOL fClearThreadBits; 00991 BOOL fClearDesktopBits; 00992 PHOOK phook; 00993 00994 00995 /* 00996 * Assume we're are going to clear local(thread) and 00997 * global(desktop) bits. 00998 */ 00999 fClearThreadBits = TRUE; 01000 fClearDesktopBits = TRUE; 01001 /* 01002 * Get the first valid hook for this thread 01003 */ 01004 phook = PhkFirstValid(pti, nFilterType); 01005 if (phook != NULL) { 01006 /* 01007 * If it found a global hook, don't clear the desktop bits 01008 * (that would mean that there are no local(thread) hooks 01009 * so we fall through to clear the thread bits) 01010 */ 01011 if (phook->flags & HF_GLOBAL) { 01012 fClearDesktopBits = FALSE; 01013 } else { 01014 /* 01015 * It found a thread hook so don't clear the thread bits 01016 */ 01017 fClearThreadBits = FALSE; 01018 /* 01019 * Check for global hooks now. If there is one, don't 01020 * clear the desktop bits 01021 */ 01022 phook = PhkFirstGlobalValid(pti, nFilterType); 01023 fClearDesktopBits = (phook == NULL); 01024 } 01025 } /* if (phook != NULL) */ 01026 01027 if (fClearThreadBits) { 01028 pti->fsHooks &= ~(WHF_FROM_WH(nFilterType)); 01029 /* 01030 * Set the flags in the thread's TEB 01031 */ 01032 if (pti->pClientInfo) { 01033 BOOL fAttached; 01034 /* 01035 * If the hooked thread is in another process, attach 01036 * to that process to access its address space. 01037 */ 01038 if (pti->ppi != PpiCurrent()) { 01039 KeAttachProcess(&pti->ppi->Process->Pcb); 01040 fAttached = TRUE; 01041 } else 01042 fAttached = FALSE; 01043 01044 pti->pClientInfo->fsHooks = pti->fsHooks; 01045 01046 if (fAttached) 01047 KeDetachProcess(); 01048 } 01049 } 01050 01051 if (fClearDesktopBits) { 01052 pti->pDeskInfo->fsHooks &= ~(WHF_FROM_WH(nFilterType)); 01053 } 01054 }

VOID FreeHook PHOOK  phkFree  ) 
 

Definition at line 1976 of file hooks.c.

References CheckWHFBits(), DbgValidateHooks, tagHOOK::flags, GETPTI, HF_DESTROYED, HF_GLOBAL, HMFreeObject(), HMMarkObjectDestroy(), tagHOOK::iHook, NULL, tagHOOK::ptiHooked, RemoveHmodDependency(), UnlinkHook(), and VOID().

Referenced by FreeThreadsWindowHooks(), xxxCallHook2(), and zzzUnhookWindowsHookEx().

01978 { 01979 /* 01980 * Paranoia... 01981 */ 01982 UserAssert(!(phkFree->flags & HF_FREED)); 01983 /* 01984 * BUGBUG 01985 * Unless we come from zzzUnhookWindowsHook, if this was a journaling hook 01986 * we don't unattach the threads. We should reconsider this one day. 01987 * MCostea Jan 21, 99 01988 */ 01989 01990 /* 01991 * Clear fsHooks bits the first time around (and mark it as destroyed). 01992 */ 01993 if (!(phkFree->flags & HF_DESTROYED)) { 01994 DbgValidateHooks (phkFree, phkFree->iHook); 01995 phkFree->flags |= HF_DESTROYED; 01996 /* 01997 * This hook has been marked as destroyed so CheckWHSBits 01998 * won't take it into account when updating the fsHooks bits. 01999 * However, this means that right at this moment fsHooks is 02000 * out of sync. So we need a flag to make the assertion freaks 02001 * (i.e., me) happy. 02002 */ 02003 #if DBG 02004 phkFree->flags |= HF_INCHECKWHF; 02005 #endif 02006 UserAssert((phkFree->ptiHooked != NULL) || (phkFree->flags & HF_GLOBAL)); 02007 CheckWHFBits(phkFree->ptiHooked != NULL 02008 ? phkFree->ptiHooked 02009 : GETPTI(phkFree), 02010 phkFree->iHook); 02011 #if DBG 02012 phkFree->flags &= ~HF_INCHECKWHF; 02013 #endif 02014 } 02015 /* 02016 * Mark it for destruction. If it the object is locked it can't 02017 * be freed right now. 02018 */ 02019 if (!HMMarkObjectDestroy((PVOID)phkFree)) { 02020 return; 02021 } 02022 /* 02023 * We're going to free this hook so get it off the list. 02024 */ 02025 UnlinkHook(phkFree); 02026 /* 02027 * Now remove the hmod dependency and free the 02028 * HOOK structure. 02029 */ 02030 if (phkFree->ihmod >= 0) { 02031 RemoveHmodDependency(phkFree->ihmod); 02032 } 02033 02034 #ifdef HOOKBATCH 02035 /* 02036 * Free the cached Events 02037 */ 02038 if (phkFree->aEventCache) { 02039 UserFreePool(phkFree->aEventCache); 02040 phkFree->aEventCache = NULL; 02041 } 02042 #endif //HOOKBATCH 02043 02044 #if DBG 02045 phkFree->flags |= HF_FREED; 02046 #endif 02047 02048 HMFreeObject((PVOID)phkFree); 02049 return; 02050 }

VOID FreeThreadsWindowHooks VOID   ) 
 

Definition at line 2227 of file hooks.c.

References tagTHREADINFO::aphkStart, tagDESKTOPINFO::aphkStart, tagHOOK::flags, FreeHook(), tagTHREADINFO::fsHooks, GETPTI, HF_DESTROYED, HF_GLOBAL, NULL, tagTHREADINFO::pDeskInfo, tagHOOK::phkNext, PtiCurrent, tagHOOK::ptiHooked, tagTHREADINFO::rpdesk, tagTHREADINFO::sphkCurrent, tagTHREADINFO::TIF_flags, TIF_INCLEANUP, UnlinkHook(), Unlock, and VOID().

Referenced by xxxDestroyThreadInfo().

02228 { 02229 int iHook; 02230 PHOOK phk, phkNext; 02231 PTHREADINFO ptiCurrent = PtiCurrent(); 02232 02233 /* 02234 * If there is not thread info, there are not hooks to worry about 02235 */ 02236 if (ptiCurrent == NULL || ptiCurrent->rpdesk == NULL) { 02237 return; 02238 } 02239 /* 02240 * In case we have a hook locked in as the current hook unlock it 02241 * so it can be freed 02242 */ 02243 Unlock(&ptiCurrent->sphkCurrent); 02244 02245 UserAssert(ptiCurrent->TIF_flags & TIF_INCLEANUP); 02246 // Why bother doing this? We won't be calling back to user mode again! 02247 // if (ptiCurrent->pClientInfo) { 02248 // ptiCurrent->pClientInfo->phkCurrent = NULL; 02249 // } 02250 02251 /* 02252 * Loop through all the hook types. 02253 */ 02254 for (iHook = WH_MIN ; iHook <= WH_MAX ; ++iHook) { 02255 /* 02256 * Loop through all the hooks of this type, including the 02257 * ones already marked as destroyed (so don't call 02258 * PhkFirstValid and PhkNextValid). 02259 */ 02260 phk = ptiCurrent->aphkStart[iHook + 1]; 02261 if (phk == NULL) { 02262 phk = ptiCurrent->pDeskInfo->aphkStart[iHook + 1]; 02263 UserAssert((phk == NULL) || (phk->flags & HF_GLOBAL)); 02264 } 02265 02266 while (phk != NULL) { 02267 /* 02268 * We might free phk below, so grab the next now 02269 * If at end of local chain, jump to the global chain 02270 */ 02271 phkNext = phk->phkNext; 02272 if ((phkNext == NULL) && !(phk->flags & HF_GLOBAL)) { 02273 phkNext = ptiCurrent->pDeskInfo->aphkStart[iHook + 1]; 02274 UserAssert((phkNext == NULL) || (phkNext->flags & HF_GLOBAL)); 02275 } 02276 /* 02277 * If this is a local(thread) hook, unlink it and mark it as 02278 * destroyed so we won't call it anymore. We want to do 02279 * this even if not calling FreeHook; also note that 02280 * FreeHook won't unlink it if locked so we do it here anyway. 02281 */ 02282 if (!(phk->flags & HF_GLOBAL)) { 02283 UserAssert(ptiCurrent == phk->ptiHooked); 02284 UnlinkHook(phk); 02285 phk->flags |= HF_DESTROYED; 02286 phk->phkNext = NULL; 02287 } 02288 /* 02289 * If this hook was created by this thread, free it 02290 */ 02291 if (GETPTI(phk) == ptiCurrent) { 02292 FreeHook(phk); 02293 } 02294 02295 phk = phkNext; 02296 } 02297 /* 02298 * All local hooks should be unlinked 02299 */ 02300 UserAssert(ptiCurrent->aphkStart[iHook + 1] == NULL); 02301 } /* for (iHook = WH_MIN....*/ 02302 02303 /* 02304 * Keep fsHooks in sync. 02305 */ 02306 ptiCurrent->fsHooks = 0; 02307 }

void InterQueueMsgCleanup DWORD  dwTimeFromLastRead  ) 
 

Definition at line 339 of file hooks.c.

References CheckCritIn, FHungApp(), gpsmsList, NULL, PSMS, and ReceiverDied().

Referenced by zzzCancelJournalling().

00340 { 00341 PSMS *ppsms; 00342 PSMS psmsNext; 00343 00344 CheckCritIn(); 00345 00346 /* 00347 * Walk gpsmsList 00348 */ 00349 for (ppsms = &gpsmsList; *ppsms; ) { 00350 psmsNext = (*ppsms)->psmsNext; 00351 /* 00352 * If this is an inter queue message 00353 */ 00354 if (((*ppsms)->ptiSender != NULL) 00355 && ((*ppsms)->ptiReceiver != NULL) 00356 && ((*ppsms)->ptiSender->pq != (*ppsms)->ptiReceiver->pq)) { 00357 /* 00358 * If the receiver has been hung for a while 00359 */ 00360 if (FHungApp ((*ppsms)->ptiReceiver, dwTimeFromLastRead)) { 00361 00362 switch ((*ppsms)->message) { 00363 /* 00364 * Activation messages 00365 */ 00366 case WM_NCACTIVATE: 00367 case WM_ACTIVATEAPP: 00368 case WM_ACTIVATE: 00369 case WM_SETFOCUS: 00370 case WM_KILLFOCUS: 00371 case WM_QUERYNEWPALETTE: 00372 /* 00373 * Sent to spwndFocus, which now can be in a different queue 00374 */ 00375 case WM_INPUTLANGCHANGE: 00376 RIPMSG3 (RIP_WARNING, "InterQueueMsgCleanup: ptiSender:%#p ptiReceiver:%#p message:%#lx", 00377 (*ppsms)->ptiSender, (*ppsms)->ptiReceiver, (*ppsms)->message); 00378 ReceiverDied(*ppsms, ppsms); 00379 break; 00380 00381 } /* switch */ 00382 00383 } /* If hung receiver */ 00384 00385 } /* If inter queue message */ 00386 00387 /* 00388 * If the message was not unlinked, go to the next one. 00389 */ 00390 if (*ppsms != psmsNext) 00391 ppsms = &(*ppsms)->psmsNext; 00392 00393 } /* for */ 00394 }

PHOOK PhkFirstGlobalValid PTHREADINFO  pti,
int  nFilterType
 

Definition at line 2151 of file hooks.c.

References tagDESKTOPINFO::aphkStart, CheckCritIn, DbgValidatefsHook, DbgValidateHooks, tagHOOK::flags, HF_DESTROYED, NULL, tagTHREADINFO::pDeskInfo, PhkNextValid(), and TRUE.

Referenced by CheckWHFBits(), GetJournallingQueue(), xxxCallJournalPlaybackHook(), xxxCallJournalRecordHook(), xxxGetNextSysMsg(), xxxInternalGetMessage(), xxxSkipSysMsg(), zzzCancelJournalling(), and zzzUnhookWindowsHookEx().

02152 { 02153 PHOOK phk; 02154 02155 CheckCritIn(); 02156 phk = pti->pDeskInfo->aphkStart[nFilterType + 1]; 02157 /* 02158 * Return the first hook that it's not destroyed (i.e, the 02159 * first valid one). 02160 */ 02161 if ((phk != NULL) && (phk->flags & HF_DESTROYED)) { 02162 phk = PhkNextValid(phk); 02163 } 02164 /* 02165 * Good place to check fsHooks. If the bits are out of sync, 02166 * someone must be adjusting them. 02167 */ 02168 DbgValidatefsHook(phk, nFilterType, pti, TRUE); 02169 DbgValidateHooks(phk, nFilterType); 02170 return phk; 02171 }

PHOOK PhkFirstValid PTHREADINFO  pti,
int  nFilterType
 

Definition at line 2183 of file hooks.c.

References tagTHREADINFO::aphkStart, tagDESKTOPINFO::aphkStart, CheckCritIn, DbgValidatefsHook, DbgValidateHooks, FALSE, tagHOOK::flags, HF_DESTROYED, NULL, tagTHREADINFO::pDeskInfo, and PhkNextValid().

Referenced by CheckWHFBits(), xxxButtonEvent(), xxxCallHook(), xxxCallMouseHook(), xxxDoButtonEvent(), xxxKeyEvent(), xxxMoveEventAbsolute(), and zzzUnhookWindowsHook().

02186 { 02187 PHOOK phk; 02188 CheckCritIn(); 02189 /* 02190 * Grab the first hook off the local hook-list 02191 * for the current queue. 02192 */ 02193 phk = pti->aphkStart[nFilterType + 1]; 02194 /* 02195 * If there aren't any local hooks, try the global hooks. 02196 */ 02197 if (phk == NULL) { 02198 phk = pti->pDeskInfo->aphkStart[nFilterType + 1]; 02199 } 02200 /* 02201 * Return the first hook that it's not destroyed (i.e, the 02202 * first valid one). 02203 */ 02204 if ((phk != NULL) && (phk->flags & HF_DESTROYED)) { 02205 phk = PhkNextValid(phk); 02206 } 02207 /* 02208 * Good place to check fsHooks. If the bits are out of sync, 02209 * someone must be adjusting them. 02210 */ 02211 02212 DbgValidatefsHook(phk, nFilterType, pti, FALSE); 02213 DbgValidateHooks(phk, nFilterType); 02214 return phk; 02215 }

void UnlinkHook PHOOK  phkFree  ) 
 

Definition at line 2061 of file hooks.c.

References tagDESKTOPINFO::aphkStart, tagTHREADINFO::aphkStart, CheckCritIn, tagHOOK::flags, GETPTI, gptiRit, tagHOOK::head, HF_GLOBAL, tagHOOK::iHook, NULL, tagTHREADINFO::pDeskInfo, tagDESKTOP::pDeskInfo, tagHOOK::phkNext, tagHOOK::ptiHooked, tagHOOK::rpdesk, and UnlockDesktop.

Referenced by FreeHook(), and FreeThreadsWindowHooks().

02063 { 02064 PHOOK *pphkNext; 02065 PTHREADINFO ptiT; 02066 02067 CheckCritIn(); 02068 /* 02069 * Since we have the HOOK structure, we can tell if this a global 02070 * or local hook and start on the right list. 02071 */ 02072 if (phkFree->flags & HF_GLOBAL) { 02073 pphkNext = &GETPTI(phkFree)->pDeskInfo->aphkStart[phkFree->iHook + 1]; 02074 } else { 02075 ptiT = phkFree->ptiHooked; 02076 if (ptiT == NULL) { 02077 /* 02078 * Already unlinked (by FreeThreadsWindowHooks) 02079 */ 02080 return; 02081 } else { 02082 /* 02083 * Clear ptiHooked so we won't try to unlink it again. 02084 */ 02085 phkFree->ptiHooked = NULL; 02086 } 02087 pphkNext = &(ptiT->aphkStart[phkFree->iHook + 1]); 02088 /* 02089 * There must be at least one hook in the chain 02090 */ 02091 UserAssert(*pphkNext != NULL); 02092 } 02093 /* 02094 * Find the address of the phkNext pointing to phkFree 02095 */ 02096 while ((*pphkNext != phkFree) && (*pphkNext != NULL)) { 02097 pphkNext = &(*pphkNext)->phkNext; 02098 } 02099 /* 02100 * If we haven't found it, it must be global hook whose owner is gone or 02101 * has switched desktops. 02102 */ 02103 if (*pphkNext == NULL) { 02104 UserAssert(phkFree->flags & HF_GLOBAL); 02105 /* 02106 * if we saved a pdesk, use it. Else use the one we allocated it from 02107 */ 02108 if (phkFree->rpdesk != NULL) { 02109 UserAssert(GETPTI(phkFree) == gptiRit); 02110 UserAssert(phkFree->rpdesk != NULL); 02111 UserAssert(phkFree->rpdesk->pDeskInfo != gptiRit->pDeskInfo); 02112 02113 pphkNext = &phkFree->rpdesk->pDeskInfo->aphkStart[phkFree->iHook + 1]; 02114 } else { 02115 UserAssert(GETPTI(phkFree)->pDeskInfo != phkFree->head.rpdesk->pDeskInfo); 02116 pphkNext = &phkFree->head.rpdesk->pDeskInfo->aphkStart[phkFree->iHook + 1]; 02117 } 02118 02119 UserAssert(*pphkNext != NULL); 02120 while ((*pphkNext != phkFree) && (*pphkNext != NULL)) { 02121 pphkNext = &(*pphkNext)->phkNext; 02122 } 02123 } 02124 /* 02125 * We're supposed to find it 02126 */ 02127 UserAssert(*pphkNext == phkFree); 02128 /* 02129 * Unlink it 02130 */ 02131 *pphkNext = phkFree->phkNext; 02132 phkFree->phkNext = NULL; 02133 /* 02134 * If we had a desktop, unlock it 02135 */ 02136 if (phkFree->rpdesk != NULL) { 02137 UserAssert(phkFree->flags & HF_GLOBAL); 02138 UserAssert(GETPTI(phkFree) == gptiRit); 02139 UnlockDesktop(&phkFree->rpdesk, LDU_HOOK_DESK, 0); 02140 } 02141 }

int xxxCallHook int  nCode,
WPARAM  wParam,
LPARAM  lParam,
int  iHook
 

Definition at line 1246 of file hooks.c.

References BOOL, PhkFirstValid(), PtiCurrent, and xxxCallHook2().

Referenced by _CallMsgFilter(), xxxActivateThisWindow(), xxxCallHook2(), xxxCallJournalPlaybackHook(), xxxCreateWindowEx(), xxxDefWindowProc(), xxxDestroyWindow(), xxxEndDeferWindowPosEx(), xxxFlashWindow(), xxxGetInputEvent(), xxxHandleOwnerSwitch(), xxxInternalActivateKeyboardLayout(), xxxInternalGetMessage(), xxxInternalUnloadKeyboardLayout(), xxxIsDragging(), xxxLoadKeyboardLayoutEx(), xxxMinMaximize(), xxxMoveSize(), xxxMS_TrackMove(), xxxMsgWaitForMultipleObjects(), xxxNotifyIMEStatus(), xxxProcessEventMessage(), xxxReceiveMessage(), xxxRedrawFrameAndHook(), xxxRedrawTitle(), xxxScanSysQueue(), xxxSendMessageCallback(), xxxSendMessageTimeout(), xxxSendMinRectMessages(), xxxSetFocus(), xxxSetTrayWindow(), xxxSleepTask(), xxxSleepThread(), xxxSysCommand(), and xxxSystemParametersInfo().

01251 { 01252 BOOL bAnsiHook; 01253 01254 return (int)xxxCallHook2(PhkFirstValid(PtiCurrent(), iHook), nCode, wParam, lParam, &bAnsiHook); 01255 }

LRESULT xxxCallHook2 PHOOK  phkCall,
int  nCode,
WPARAM  wParam,
LPARAM  lParam,
LPBOOL  lpbAnsiHook
 

Definition at line 1288 of file hooks.c.

References abHookFlags, ampiHookError, BOOL, BYTE, CheckCritIn, CMSHUNGAPPTIMEOUT, FHungApp(), tagHOOK::flags, FreeHook(), tagINTERSENDMSGEX::fuCall, tagINTERSENDMSGEX::fuSend, GETPTI, gnllHooksTimeout, gptiRit, HF_ANSI, HF_GLOBAL, HF_HOOKFAULTED, HF_WX86KNOWNDLL, HKF_INTERSENDABLE, HKF_JOURNAL, HKF_LOWLEVEL, HMIsMarkDestroy, HOOKMSGSTRUCT, tagHOOK::ihmod, tagHOOK::iHook, INTRSENDMSGEX, IsHooked, ISM_TIMEOUT, IsRestricted(), Lock, tagHOOKMSGSTRUCT::lParam, tagINTERSENDMSGEX::lpdwResult, tagPROCESSINFO::luidSession, luidSystem, tagHOOKMSGSTRUCT::nCode, NULL, tagTHREADINFO::pClientInfo, tagHOOKMSGSTRUCT::phk, _CLIENTINFO::phkCurrent, PhkNextValid(), tagTHREADINFO::ppi, PtiCurrent, tagHOOK::ptiHooked, tagTHREADINFO::rpdesk, RtlEqualLuid(), SET_TIME_LAST_READ, tagTHREADINFO::sphkCurrent, TESTHMODLOADED, ThreadLockAlwaysWithPti, ThreadLockWithPti, ThreadUnlock, TIDq, TIF_16BIT, TIF_ALLOWOTHERACCOUNTHOOK, TIF_CSRSSTHREAD, TIF_DISABLEHOOKS, TIF_DOSEMULATOR, tagTHREADINFO::TIF_flags, TIF_INCLEANUP, TIF_SYSTEMTHREAD, TIF_WOW64, UINT, tagINTERSENDMSGEX::uTimeout, WHF_DEBUG, xxxCallHook(), xxxHkCallHook(), xxxInterSendMsgEx(), and xxxLoadHmodIndex().

Referenced by xxxButtonEvent(), xxxCallHook(), xxxCallJournalPlaybackHook(), xxxCallJournalRecordHook(), xxxCallMouseHook(), xxxCallNextHookEx(), xxxDoButtonEvent(), xxxKeyEvent(), xxxMoveEventAbsolute(), and xxxReceiveMessage().

01294 { 01295 UINT iHook; 01296 PHOOK phkSave; 01297 LONG_PTR nRet; 01298 PTHREADINFO ptiCurrent; 01299 BOOL fLoadSuccess; 01300 TL tlphkCall; 01301 TL tlphkSave; 01302 BYTE bHookFlags; 01303 BOOL fMustIntersend; 01304 01305 CheckCritIn(); 01306 01307 if (phkCall == NULL) { 01308 return 0; 01309 } 01310 01311 iHook = phkCall->iHook; 01312 01313 ptiCurrent = PtiCurrent(); 01314 /* 01315 * Only low level hooks are allowed in the RIT context 01316 * (This check used to be done in PhkFirstValid). 01317 */ 01318 if (ptiCurrent == gptiRit) { 01319 switch (iHook) { 01320 case WH_MOUSE_LL: 01321 case WH_KEYBOARD_LL: 01322 01323 #ifdef REDIRECTION 01324 case WH_HITTEST: 01325 #endif // REDIRECTION 01326 01327 break; 01328 01329 default: 01330 return 0; 01331 } 01332 } 01333 01334 /* 01335 * If this queue is in cleanup, exit: it has no business calling back 01336 * a hook proc. Also check if hooks are disabled for the thread. 01337 */ 01338 if ( ptiCurrent->TIF_flags & (TIF_INCLEANUP | TIF_DISABLEHOOKS) || 01339 ((ptiCurrent->rpdesk == NULL) && (phkCall->iHook != WH_MOUSE_LL))) { 01340 return ampiHookError[iHook + 1]; 01341 } 01342 01343 /* 01344 * Try to call each hook in the list until one is successful or 01345 * we reach the end of the list. 01346 */ 01347 do { 01348 *lpbAnsiHook = phkCall->flags & HF_ANSI; 01349 bHookFlags = abHookFlags[phkCall->iHook + 1]; 01350 01351 /* 01352 * Some WH_SHELL hook types can be called from console 01353 * HSHELL_APPCOMMAND added for bug 346575 DefWindowProc invokes a shell hook 01354 * for console windows if they don't handle the wm_appcommand message - we need the hook 01355 * to go through for csrss. 01356 */ 01357 if ((phkCall->iHook == WH_SHELL) && (ptiCurrent->TIF_flags & TIF_CSRSSTHREAD)) { 01358 if ((nCode == HSHELL_LANGUAGE) || (nCode == HSHELL_WINDOWACTIVATED) || 01359 (nCode == HSHELL_APPCOMMAND)) { 01360 bHookFlags |= HKF_INTERSENDABLE; 01361 } 01362 } 01363 01364 if ((phkCall->iHook == WH_SHELL) && (ptiCurrent->TIF_flags & TIF_SYSTEMTHREAD)) { 01365 if ((nCode == HSHELL_ACCESSIBILITYSTATE) ) { 01366 bHookFlags |= HKF_INTERSENDABLE; 01367 } 01368 } 01369 01370 fMustIntersend = 01371 (GETPTI(phkCall) != ptiCurrent) && 01372 ( 01373 /* 01374 * We always want to intersend journal hooks. 01375 * CONSIDER (adams): Why? There's a performance hit by 01376 * doing so, so if we haven't a reason, we shouldn't 01377 * do it. 01378 * 01379 * we also need to intersend low level hooks. They can be called 01380 * from the desktop thread, the raw input thread AND also from 01381 * any thread that calls CallNextHookEx. 01382 */ 01383 (bHookFlags & (HKF_JOURNAL | HKF_LOWLEVEL)) 01384 01385 /* 01386 * We must intersend if a 16bit app hooks a 32bit app 01387 * because we can't load a 16bit dll into a 32bit process. 01388 * We must also intersend if a 16bit app hooks another 16bit app 01389 * in a different VDM, because we can't load a 16bit dll from 01390 * one VDM into a 16bit app in another VDM (because that 01391 * VDM is actually a 32bit process). 01392 */ 01393 || 01394 ( GETPTI(phkCall)->TIF_flags & TIF_16BIT && 01395 ( !(ptiCurrent->TIF_flags & TIF_16BIT) || 01396 ptiCurrent->ppi != GETPTI(phkCall)->ppi)) 01397 01398 #if defined(_WIN64) 01399 01400 /* 01401 * Intersend if a 64bit app hooks a 32bit app or 01402 * a 32bit app hooks a 64bit app. 01403 * This is necessary since a hook DLL can not be loaded 01404 * cross bit type. 01405 */ 01406 || 01407 ( (GETPTI(phkCall)->TIF_flags & TIF_WOW64) != 01408 (ptiCurrent->TIF_flags & TIF_WOW64) 01409 ) 01410 01411 #endif /* defined(_WIN64) */ 01412 01413 /* 01414 * We must intersend if a console or system thread is calling a hook 01415 * that is not in the same console or the system process. 01416 */ 01417 || 01418 ( ptiCurrent->TIF_flags & (TIF_CSRSSTHREAD | TIF_SYSTEMTHREAD) && 01419 GETPTI(phkCall)->ppi != ptiCurrent->ppi) 01420 01421 /* 01422 * If this is a global and non-journal hook, do a security 01423 * check on the current desktop to see if we can call here. 01424 * Note that we allow processes with the SYSTEM_LUID to hook 01425 * other processes even if the other process says that it 01426 * doesn't allow other accounts to hook them. We did this 01427 * because there was a bug in NT 3.x that allowed it and some 01428 * services were written to use it. 01429 */ 01430 || 01431 ( phkCall->flags & HF_GLOBAL && 01432 !RtlEqualLuid(&GETPTI(phkCall)->ppi->luidSession, &ptiCurrent->ppi->luidSession) && 01433 !(ptiCurrent->TIF_flags & TIF_ALLOWOTHERACCOUNTHOOK) && 01434 !RtlEqualLuid(&GETPTI(phkCall)->ppi->luidSession, &luidSystem)) 01435 01436 /* 01437 * We must intersend if the hooking thread is running in 01438 * another process and is restricted. 01439 */ 01440 || 01441 ( GETPTI(phkCall)->ppi != ptiCurrent->ppi && 01442 IsRestricted(GETPTI(phkCall)->pEThread)) 01443 ); 01444 01445 /* 01446 * We're calling back... make sure the hook doesn't go away while 01447 * we're calling back. We've thread locked here: we must unlock before 01448 * returning or enumerating the next hook in the chain. 01449 */ 01450 ThreadLockAlwaysWithPti(ptiCurrent, phkCall, &tlphkCall); 01451 01452 if (!fMustIntersend) { 01453 /* 01454 * Make sure the DLL for this hook, if any, has been loaded 01455 * for the current process. 01456 */ 01457 if ((phkCall->ihmod != -1) && 01458 (TESTHMODLOADED(ptiCurrent, phkCall->ihmod) == 0)) { 01459 01460 BOOL bWx86KnownDll; 01461 01462 /* 01463 * Try loading the library, since it isn't loaded in this processes 01464 * context. First lock this hook so it doesn't go away while we're 01465 * loading this library. 01466 */ 01467 bWx86KnownDll = (phkCall->flags & HF_WX86KNOWNDLL) != 0; 01468 fLoadSuccess = (xxxLoadHmodIndex(phkCall->ihmod, bWx86KnownDll) != NULL); 01469 01470 /* 01471 * If the LoadLibrary() failed, skip to the next hook and try 01472 * again. 01473 */ 01474 if (!fLoadSuccess) { 01475 goto LoopAgain; 01476 } 01477 } 01478 01479 /* 01480 * Is WH_DEBUG installed? If we're not already calling it, do so. 01481 */ 01482 if (IsHooked(ptiCurrent, WHF_DEBUG) && (phkCall->iHook != WH_DEBUG)) { 01483 DEBUGHOOKINFO debug; 01484 01485 debug.idThread = TIDq(ptiCurrent); 01486 debug.idThreadInstaller = 0; 01487 debug.code = nCode; 01488 debug.wParam = wParam; 01489 debug.lParam = lParam; 01490 01491 if (xxxCallHook(HC_ACTION, phkCall->iHook, (LPARAM)&debug, WH_DEBUG)) { 01492 /* 01493 * If WH_DEBUG returned non-zero, skip this hook and 01494 * try the next one. 01495 */ 01496 goto LoopAgain; 01497 } 01498 } 01499 01500 /* 01501 * Make sure the hook is still around before we 01502 * try and call it. 01503 */ 01504 if (HMIsMarkDestroy(phkCall)) { 01505 goto LoopAgain; 01506 } 01507 01508 /* 01509 * Time to call the hook! Lock it first so that it doesn't go away 01510 * while we're using it. Thread lock right away in case the lock frees 01511 * the previous contents. 01512 */ 01513 01514 #if DBG 01515 if (phkCall->flags & HF_GLOBAL) { 01516 UserAssert(phkCall->ptiHooked == NULL); 01517 } else { 01518 UserAssert(phkCall->ptiHooked == ptiCurrent); 01519 } 01520 #endif 01521 phkSave = ptiCurrent->sphkCurrent; 01522 ThreadLockWithPti(ptiCurrent, phkSave, &tlphkSave); 01523 01524 Lock(&ptiCurrent->sphkCurrent, phkCall); 01525 if (ptiCurrent->pClientInfo) 01526 ptiCurrent->pClientInfo->phkCurrent = phkCall; 01527 01528 nRet = xxxHkCallHook(phkCall, nCode, wParam, lParam); 01529 01530 Lock(&ptiCurrent->sphkCurrent, phkSave); 01531 if (ptiCurrent->pClientInfo) 01532 ptiCurrent->pClientInfo->phkCurrent = phkSave; 01533 01534 ThreadUnlock(&tlphkSave); 01535 01536 /* 01537 * This hook proc faulted, so unhook it and try the next one. 01538 */ 01539 if (phkCall->flags & HF_HOOKFAULTED) { 01540 PHOOK phkFault; 01541 01542 phkCall = PhkNextValid(phkCall); 01543 phkFault = ThreadUnlock(&tlphkCall); 01544 if (phkFault != NULL) { 01545 FreeHook(phkFault); 01546 } 01547 01548 continue; 01549 } 01550 01551 /* 01552 * Lastly, we're done with this hook so it is ok to unlock it (it may 01553 * get freed here! 01554 */ 01555 ThreadUnlock(&tlphkCall); 01556 01557 return nRet; 01558 01559 } else if (bHookFlags & HKF_INTERSENDABLE) { 01560 01561 /* 01562 * Receiving thread can access this structure since the 01563 * sender thread's stack is locked down during xxxInterSendMsgEx 01564 */ 01565 HOOKMSGSTRUCT hkmp; 01566 int timeout = 200; // 1/5 second !!! 01567 01568 hkmp.lParam = lParam; 01569 hkmp.phk = phkCall; 01570 hkmp.nCode = nCode; 01571 01572 /* 01573 * Thread lock right away in case the lock frees the previous contents 01574 */ 01575 phkSave = ptiCurrent->sphkCurrent; 01576 01577 ThreadLockWithPti(ptiCurrent, phkSave, &tlphkSave); 01578 01579 Lock(&ptiCurrent->sphkCurrent, phkCall); 01580 if (ptiCurrent->pClientInfo) 01581 ptiCurrent->pClientInfo->phkCurrent = phkCall; 01582 01583 /* 01584 * Make sure we don't get hung! 01585 */ 01586 if (bHookFlags & HKF_LOWLEVEL) 01587 timeout = gnllHooksTimeout; 01588 01589 /* 01590 * CONSIDER(adams): Why should a journaling hook be allowed to 01591 * hang the console or a system thread? Will that interfere with 01592 * the user's ability to cancel journaling through Ctrl+Esc? 01593 */ 01594 if (((bHookFlags & HKF_LOWLEVEL) == 0) && 01595 ( (bHookFlags & HKF_JOURNAL) || 01596 !(ptiCurrent->TIF_flags & (TIF_CSRSSTHREAD | TIF_SYSTEMTHREAD)))) { 01597 01598 nRet = xxxInterSendMsgEx(NULL, WM_HOOKMSG, wParam, 01599 (LPARAM)&hkmp, ptiCurrent, GETPTI(phkCall), NULL); 01600 } else { 01601 /* 01602 * We are a server thread (console/desktop) and we aren't 01603 * journalling, so we can't allow the hookproc to hang us - 01604 * we must use a timeout. 01605 */ 01606 INTRSENDMSGEX ism; 01607 01608 ism.fuCall = ISM_TIMEOUT; 01609 ism.fuSend = SMTO_ABORTIFHUNG | SMTO_NORMAL; 01610 ism.uTimeout = timeout; 01611 ism.lpdwResult = &nRet; 01612 01613 /* 01614 * Don't hook DOS apps connected to the emulator - they often 01615 * grab too much CPU for the callback to the hookproc to 01616 * complete in a timely fashion, causing poor response. 01617 */ 01618 if ((ptiCurrent->TIF_flags & TIF_DOSEMULATOR) || 01619 FHungApp(GETPTI(phkCall), CMSHUNGAPPTIMEOUT) || 01620 !xxxInterSendMsgEx(NULL, WM_HOOKMSG, wParam, 01621 (LPARAM)&hkmp, ptiCurrent, GETPTI(phkCall), &ism)) { 01622 nRet = ampiHookError[iHook + 1]; 01623 } 01624 01625 /* 01626 * If the low-level hook is eaten, the app may wake up from 01627 * MsgWaitForMultipleObjects, clear the wake mask, but not get 01628 * anything in GetMessage / PeekMessage and we will think it's 01629 * hung. This causes problems in DirectInput because then the 01630 * app may miss some hooks if FHungApp returns true, see bug 01631 * 430342 for more details on this. 01632 */ 01633 if ((bHookFlags & HKF_LOWLEVEL) && nRet) { 01634 SET_TIME_LAST_READ(GETPTI(phkCall)); 01635 } 01636 } 01637 01638 Lock(&ptiCurrent->sphkCurrent, phkSave); 01639 if (ptiCurrent->pClientInfo) 01640 ptiCurrent->pClientInfo->phkCurrent = phkSave; 01641 01642 ThreadUnlock(&tlphkSave); 01643 ThreadUnlock(&tlphkCall); 01644 return nRet; 01645 } 01646 // fall-through 01647 01648 LoopAgain: 01649 phkCall = PhkNextValid(phkCall); 01650 ThreadUnlock(&tlphkCall); 01651 } while (phkCall != NULL); 01652 01653 return ampiHookError[iHook + 1]; 01654 }

DWORD xxxCallJournalPlaybackHook PQMSG  pqmsg  ) 
 

Definition at line 1797 of file hooks.c.

References BOOL, BYTE, dt(), DWORD, gpsi, IS_CHAR_MSG, IS_DBCS_ENABLED, IsWinEventNotifyDeferredOK, L, LOBYTE, tagQMSG::msg, NtGetTickCount(), NULL, tagHOOK::offPfn, PhkFirstGlobalValid(), tagTHREADINFO::pq, PtiCurrent, RevalidateHwnd, tagQ::spwndActive, StoreQMessage(), TestKeyStateDown, ThreadLockWithPti, ThreadUnlock, tagTHREADINFO::TIF_flags, TIF_IGNOREPLAYBACKDELAY, UINT, tagTHREADINFO::wchInjected, xxxCallHook(), xxxCallHook2(), and zzzInternalSetCursorPos().

Referenced by xxxGetNextSysMsg().

01799 { 01800 EVENTMSG emsg; 01801 LONG dt; 01802 PWND pwnd; 01803 WPARAM wParam; 01804 LPARAM lParam; 01805 POINT pt; 01806 PTHREADINFO ptiCurrent; 01807 BOOL bAnsiHook; 01808 PHOOK phkCall; 01809 TL tlphkCall; 01810 01811 UserAssert(IsWinEventNotifyDeferredOK()); 01812 01813 TryNextEvent: 01814 01815 /* 01816 * Initialized to the current time for compatibility with 01817 * <= 3.0. 01818 */ 01819 emsg.time = NtGetTickCount(); 01820 ptiCurrent = PtiCurrent(); 01821 pwnd = NULL; 01822 01823 phkCall = PhkFirstGlobalValid(ptiCurrent, WH_JOURNALPLAYBACK); 01824 ThreadLockWithPti(ptiCurrent, phkCall, &tlphkCall); 01825 01826 dt = (DWORD)xxxCallHook2(phkCall, HC_GETNEXT, 0, (LPARAM)&emsg, &bAnsiHook); 01827 01828 /* 01829 * -1 means some error occured. Return -1 for error. 01830 */ 01831 if (dt == 0xFFFFFFFF) { 01832 ThreadUnlock(&tlphkCall); 01833 return dt; 01834 } 01835 01836 /* 01837 * Update the message id. Need this if we decide to sleep. 01838 */ 01839 pqmsg->msg.message = emsg.message; 01840 01841 if (dt > 0) { 01842 if (ptiCurrent->TIF_flags & TIF_IGNOREPLAYBACKDELAY) { 01843 /* 01844 * This flag tells us to ignore the requested delay (set in mnloop) 01845 * We clear it to indicate that we did so. 01846 */ 01847 RIPMSG1(RIP_WARNING, "Journal Playback delay ignored (%lx)", emsg.message); 01848 ptiCurrent->TIF_flags &= ~TIF_IGNOREPLAYBACKDELAY; 01849 dt = 0; 01850 } else { 01851 ThreadUnlock(&tlphkCall); 01852 return dt; 01853 } 01854 } 01855 01856 /* 01857 * The app is ready to be asked for the next event 01858 */ 01859 01860 if ((emsg.message >= WM_MOUSEFIRST) && (emsg.message <= WM_MOUSELAST)) { 01861 01862 pt.x = (int)emsg.paramL; 01863 pt.y = (int)emsg.paramH; 01864 01865 lParam = MAKELONG(LOWORD(pt.x), LOWORD(pt.y)); 01866 wParam = 0; 01867 01868 /* 01869 * If the message has changed the mouse position, 01870 * update the cursor. 01871 */ 01872 if (pt.x != gpsi->ptCursor.x || pt.y != gpsi->ptCursor.y) { 01873 zzzInternalSetCursorPos(pt.x, pt.y); 01874 } 01875 01876 } else if ((emsg.message >= WM_KEYFIRST) && (emsg.message <= WM_KEYLAST)) { 01877 UINT wExtraStuff = 0; 01878 01879 if ((emsg.message == WM_KEYUP) || (emsg.message == WM_SYSKEYUP)) { 01880 wExtraStuff |= 0x8000; 01881 } 01882 01883 if ((emsg.message == WM_SYSKEYUP) || (emsg.message == WM_SYSKEYDOWN)) { 01884 wExtraStuff |= 0x2000; 01885 } 01886 01887 if (emsg.paramH & 0x8000) { 01888 wExtraStuff |= 0x0100; 01889 } 01890 01891 if (TestKeyStateDown(ptiCurrent->pq, (BYTE)emsg.paramL)) { 01892 wExtraStuff |= 0x4000; 01893 } 01894 lParam = MAKELONG(1, (UINT)((emsg.paramH & 0xFF) | wExtraStuff)); 01895 01896 if ((LOWORD(emsg.paramL) == VK_PACKET) && (LOBYTE(emsg.paramH) == 0)) { 01897 /* 01898 * We are playing back an injected Unicode char (see SendInput) 01899 * save the character for TranslateMessage to pick up. 01900 */ 01901 ptiCurrent->wchInjected = HIWORD(emsg.paramL); 01902 } else { 01903 /* 01904 * Raid# 65331 01905 * WM_KEY* and WM_SYSKEY* messages should only contain 8bit Virtual Keys. 01906 * Some applications passes scan code in HIBYTE and could screw up 01907 * the system. E.g. Tab Keydown, paramL: 0x0f09 where 0f is scan code 01908 */ 01909 DWORD dwMask = 0xff; 01910 01911 /* 01912 * There are old ANSI apps that only fill in the byte for when 01913 * they generate journal playback so we used to strip everything 01914 * else off. That however breaks unicode journalling; 22645 01915 * (Yes, some apps apparently do Playback WM_*CHAR msgs!) 01916 * 01917 */ 01918 if (!bAnsiHook || IS_DBCS_ENABLED()) { 01919 if (IS_CHAR_MSG(emsg.message)) { 01920 RIPMSG1(RIP_VERBOSE, "Unusual char message(%x) passed through JournalPlayback.", emsg.message); 01921 /* 01922 * Don't mask off HIBYTE(LOWORD(paramL)) for DBCS and UNICODE. 01923 */ 01924 dwMask = 0xffff; 01925 } 01926 } 01927 01928 wParam = emsg.paramL & dwMask; 01929 } 01930 01931 } else if (emsg.message == WM_QUEUESYNC) { 01932 if (emsg.paramL == 0) { 01933 pwnd = ptiCurrent->pq->spwndActive; 01934 } else { 01935 if ((pwnd = RevalidateHwnd((HWND)IntToPtr( emsg.paramL ))) == NULL) 01936 pwnd = ptiCurrent->pq->spwndActive; 01937 } 01938 01939 } else { 01940 /* 01941 * This event doesn't match up with what we're looking 01942 * for. If the hook is still valid, then skip this message 01943 * and try the next. 01944 */ 01945 if (phkCall == NULL || phkCall->offPfn == 0L) { 01946 /* Hook is nolonger valid, return -1 */ 01947 ThreadUnlock(&tlphkCall); 01948 return 0xFFFFFFFF; 01949 } 01950 01951 RIPMSG1(RIP_WARNING, 01952 "Bad journal playback message=0x%08lx", 01953 emsg.message); 01954 01955 xxxCallHook(HC_SKIP, 0, 0, WH_JOURNALPLAYBACK); 01956 ThreadUnlock(&tlphkCall); 01957 goto TryNextEvent; 01958 } 01959 01960 StoreQMessage(pqmsg, pwnd, emsg.message, wParam, lParam, 0, 0, 0); 01961 01962 ThreadUnlock(&tlphkCall); 01963 return 0; 01964 }

void xxxCallJournalRecordHook PQMSG  pqmsg  ) 
 

Definition at line 1695 of file hooks.c.

References BOOL, BYTE, tagQMSG::dwQEvent, HIBYTE, LOBYTE, tagQMSG::msg, NULL, PBYTE, PhkFirstGlobalValid(), PtiCurrent, RevalidateHwnd, UINT, and xxxCallHook2().

Referenced by xxxSkipSysMsg().

01697 { 01698 EVENTMSG emsg; 01699 BOOL bAnsiHook; 01700 01701 /* 01702 * Setup the EVENTMSG structure. 01703 */ 01704 emsg.message = pqmsg->msg.message; 01705 emsg.time = pqmsg->msg.time; 01706 01707 if (RevalidateHwnd(pqmsg->msg.hwnd)) { 01708 emsg.hwnd = pqmsg->msg.hwnd; 01709 } else { 01710 emsg.hwnd = NULL; 01711 } 01712 01713 if ((emsg.message >= WM_MOUSEFIRST) && (emsg.message <= WM_MOUSELAST)) { 01714 emsg.paramL = (UINT)pqmsg->msg.pt.x; 01715 emsg.paramH = (UINT)pqmsg->msg.pt.y; 01716 01717 } else if ((emsg.message >= WM_KEYFIRST) && (emsg.message <= WM_KEYLAST)) { 01718 BYTE bScanCode = LOBYTE(HIWORD(pqmsg->msg.lParam)); 01719 /* 01720 * Build up a Win 3.1 compatible journal record key 01721 * Win 3.1 ParamL 00 00 SC VK (SC=scan code VK=virtual key) 01722 * Also set ParamH 00 00 00 SC to be compatible with our Playback 01723 * 01724 * If WM_*CHAR messages ever come this way we would have a problem 01725 * because we would lose the top byte of the Unicode character. We'd 01726 * We'd get ParamL 00 00 SC CH (SC=scan code, CH = low byte of WCHAR) 01727 * 01728 */ 01729 if ((LOWORD(pqmsg->msg.wParam) == VK_PACKET) && (bScanCode == 0)) { 01730 /* 01731 * If we have an injected Unicode char (from SendInput), the 01732 * character value was cached, let's give that to them too. 01733 */ 01734 emsg.paramL = (UINT)MAKELONG(pqmsg->msg.wParam, PtiCurrent()->wchInjected); 01735 } else { 01736 emsg.paramL = MAKELONG(MAKEWORD(pqmsg->msg.wParam, bScanCode),0); 01737 } 01738 emsg.paramH = bScanCode; 01739 01740 UserAssert((emsg.message != WM_CHAR) && 01741 (emsg.message != WM_DEADCHAR) && 01742 (emsg.message != WM_SYSCHAR) && 01743 (emsg.message != WM_SYSDEADCHAR)); 01744 /* 01745 * Set extended-key bit. 01746 */ 01747 if (pqmsg->msg.lParam & 0x01000000) { 01748 emsg.paramH |= 0x8000; 01749 } 01750 01751 } else { 01752 RIPMSG2(RIP_WARNING, 01753 "Bad journal record message!\n" 01754 " message = 0x%08lx\n" 01755 " dwQEvent = 0x%08lx", 01756 pqmsg->msg.message, 01757 pqmsg->dwQEvent); 01758 } 01759 01760 /* 01761 * Call the journal recording hook. 01762 */ 01763 xxxCallHook2(PhkFirstGlobalValid(PtiCurrent(), WH_JOURNALRECORD), HC_ACTION, 0, 01764 (LPARAM)&emsg, &bAnsiHook); 01765 01766 /* 01767 * Write the MSG parameters back because the app may have modified it. 01768 * AfterDark's screen saver password actually zero's out the keydown 01769 * chars. 01770 * 01771 * If it was a mouse message patch up the mouse point. If it was a 01772 * WM_KEYxxx message convert the Win 3.1 compatible journal record key 01773 * back into a half backed WM_KEYxxx format. Only the VK and SC fields 01774 * where initialized at this point. 01775 * 01776 * wParam 00 00 00 VK lParam 00 SC 00 00 01777 */ 01778 if ((pqmsg->msg.message >= WM_MOUSEFIRST) && (pqmsg->msg.message <= WM_MOUSELAST)) { 01779 pqmsg->msg.pt.x = emsg.paramL; 01780 pqmsg->msg.pt.y = emsg.paramH; 01781 01782 } else if ((pqmsg->msg.message >= WM_KEYFIRST) && (pqmsg->msg.message <= WM_KEYLAST)) { 01783 (BYTE)pqmsg->msg.wParam = (BYTE)emsg.paramL; 01784 ((PBYTE)&pqmsg->msg.lParam)[2] = HIBYTE(LOWORD(emsg.paramL)); 01785 } 01786 }

BOOL xxxCallMouseHook UINT  message,
PMOUSEHOOKSTRUCTEX  pmhs,
BOOL  fRemove
 

Definition at line 1666 of file hooks.c.

References BOOL, DWORD, FALSE, PhkFirstValid(), PtiCurrent, TRUE, and xxxCallHook2().

Referenced by xxxScanSysQueue().

01670 { 01671 BOOL bAnsiHook; 01672 01673 /* 01674 * Call the mouse hook. 01675 */ 01676 if (xxxCallHook2(PhkFirstValid(PtiCurrent(), WH_MOUSE), fRemove ? 01677 HC_ACTION : HC_NOREMOVE, (DWORD)message, (LPARAM)pmhs, &bAnsiHook)) { 01678 return TRUE; 01679 } 01680 01681 return FALSE; 01682 }

LRESULT xxxCallNextHookEx int  nCode,
WPARAM  wParam,
LPARAM  lParam
 

Definition at line 961 of file hooks.c.

References BOOL, NULL, PhkNextValid(), PtiCurrent, and xxxCallHook2().

Referenced by fnHkINLPCWPEXSTRUCT(), fnHkINLPCWPRETEXSTRUCT(), NtUserCallNextHookEx(), NtUserfnHkINLPCBTACTIVATESTRUCT(), NtUserfnHkINLPCBTCREATESTRUCT(), NtUserfnHkINLPDEBUGHOOKSTRUCT(), NtUserfnHkINLPKBDLLHOOKSTRUCT(), NtUserfnHkINLPMOUSEHOOKSTRUCTEX(), NtUserfnHkINLPMSG(), NtUserfnHkINLPMSLLHOOKSTRUCT(), NtUserfnHkINLPRECT(), and NtUserfnHkOPTINLPEVENTMSG().

00965 { 00966 BOOL bAnsiHook; 00967 00968 if (PtiCurrent()->sphkCurrent == NULL) { 00969 return 0; 00970 } 00971 00972 return xxxCallHook2(PhkNextValid(PtiCurrent()->sphkCurrent), nCode, wParam, lParam, &bAnsiHook); 00973 }

void zzzCancelJournalling void   ) 
 

Definition at line 404 of file hooks.c.

References _PostThreadMessage(), ClrWF, CMSWAITTOKILLTIMEOUT, DeferWinEventNotify, gppiLockSFW, gptiRit, grpdeskRitInput, gwMouseOwnerButton, tagHOOK::head, InterQueueMsgCleanup(), NULL, tagTHREADINFO::pDeskInfo, tagDESKTOP::pDeskInfo, PhkFirstGlobalValid(), PhkNextValid(), SendMsgCleanup(), tagDESKTOPINFO::spwnd, TestWF, WFDISABLED, zzzEndDeferWinEventNotify, and zzzUnhookWindowsHookEx().

Referenced by xxxDoHotKeyStuff(), and xxxSwitchDesktop().

00405 { 00406 PTHREADINFO ptiCancelJournal; 00407 PHOOK phook; 00408 PHOOK phookNext; 00409 00410 /* 00411 * Mouse buttons sometimes get stuck down due to hardware glitches, 00412 * usually due to input concentrator switchboxes or faulty serial 00413 * mouse COM ports, so clear the global button state here just in case, 00414 * otherwise we may not be able to change focus with the mouse. 00415 * Also do this in Alt-Tab processing. 00416 */ 00417 #if DBG 00418 if (gwMouseOwnerButton) 00419 RIPMSG1(RIP_WARNING, 00420 "gwMouseOwnerButton=%x, being cleared forcibly\n", 00421 gwMouseOwnerButton); 00422 #endif 00423 gwMouseOwnerButton = 0; 00424 00425 /* 00426 * Remove journal hooks. This'll cause threads to associate with 00427 * different queues. 00428 * DeferWinEventNotify() so we can traverse the phook list safely 00429 */ 00430 DeferWinEventNotify(); 00431 UserAssert(gptiRit->pDeskInfo == grpdeskRitInput->pDeskInfo); 00432 phook = PhkFirstGlobalValid(gptiRit, WH_JOURNALPLAYBACK); 00433 while (phook != NULL) { 00434 ptiCancelJournal = phook->head.pti; 00435 00436 if (ptiCancelJournal != NULL) { 00437 /* 00438 * Let the thread that set the journal hook know this is happening. 00439 */ 00440 _PostThreadMessage(ptiCancelJournal, WM_CANCELJOURNAL, 0, 0); 00441 00442 /* 00443 * If there was an app waiting for a response back from the journal 00444 * application, cancel that request so the app can continue running 00445 * (for example, we don't want winlogon or console to wait for an 00446 * app that may be hung!) 00447 */ 00448 SendMsgCleanup(ptiCancelJournal); 00449 } 00450 00451 phookNext = PhkNextValid(phook); 00452 zzzUnhookWindowsHookEx(phook); // May free phook memory 00453 phook = phookNext; 00454 } 00455 zzzEndDeferWinEventNotify(); 00456 00457 /* 00458 * DeferWinEventNotify() so we can traverse the phook list safely 00459 */ 00460 DeferWinEventNotify(); 00461 UserAssert(gptiRit->pDeskInfo == grpdeskRitInput->pDeskInfo); 00462 phook = PhkFirstGlobalValid(gptiRit, WH_JOURNALRECORD); 00463 while (phook != NULL) { 00464 ptiCancelJournal = phook->head.pti; 00465 00466 if (ptiCancelJournal != NULL) { 00467 /* 00468 * Let the thread that set the journal hook know this is happening. 00469 */ 00470 _PostThreadMessage(ptiCancelJournal, WM_CANCELJOURNAL, 0, 0); 00471 00472 /* 00473 * If there was an app waiting for a response back from the journal 00474 * application, cancel that request so the app can continue running 00475 * (for example, we don't want winlogon or console to wait for an 00476 * app that may be hung!) 00477 */ 00478 SendMsgCleanup(ptiCancelJournal); 00479 } 00480 00481 phookNext = PhkNextValid(phook); 00482 zzzUnhookWindowsHookEx(phook); // May free phook memory 00483 phook = phookNext; 00484 } 00485 zzzEndDeferWinEventNotify(); 00486 00487 00488 /* 00489 * Make sure journalling ssync mode didn't hose any one 00490 */ 00491 InterQueueMsgCleanup(CMSWAITTOKILLTIMEOUT); 00492 00493 /* 00494 * Unlock SetForegroundWindow (if locked) 00495 */ 00496 gppiLockSFW = NULL; 00497 00498 /* 00499 * NT5's last minute hack for evil applications, who disables the desktop window 00500 * (perhaps by accidents though) leaving the system pretty unusable. 00501 * See Raid #423704. 00502 */ 00503 if (grpdeskRitInput && grpdeskRitInput->pDeskInfo) { 00504 PWND pwndDesktop = grpdeskRitInput->pDeskInfo->spwnd; 00505 00506 if (pwndDesktop && TestWF(pwndDesktop, WFDISABLED)) { 00507 ClrWF(pwndDesktop, WFDISABLED); 00508 } 00509 } 00510 }

BOOL zzzJournalAttach PTHREADINFO  pti,
BOOL  fAttach
 

Definition at line 285 of file hooks.c.

References AllocQueue(), BOOL, tagQ::cThreads, FALSE, NULL, tagTHREADINFO::pqAttach, tagDESKTOP::PtiList, tagTHREADINFO::rpdesk, TIF_DONTJOURNALATTACH, tagTHREADINFO::TIF_flags, TIF_INCLEANUP, and zzzReattachThreads().

Referenced by zzzRegisterSystemThread(), zzzSetWindowsHookEx(), and zzzUnhookWindowsHookEx().

00288 { 00289 PTHREADINFO ptiT; 00290 PQ pq; 00291 PLIST_ENTRY pHead, pEntry; 00292 00293 /* 00294 * If we're attaching, calculate the pqAttach for all threads journalling. 00295 * If we're unattaching, just call zzzReattachThreads() and it will calculate 00296 * the non-journalling queues to attach to. 00297 */ 00298 if (fAttach) { 00299 if ((pq = AllocQueue(pti, NULL)) == NULL) 00300 return FALSE; 00301 00302 pHead = &pti->rpdesk->PtiList; 00303 for (pEntry = pHead->Flink; pEntry != pHead; pEntry = pEntry->Flink) { 00304 ptiT = CONTAINING_RECORD(pEntry, THREADINFO, PtiLink); 00305 00306 /* 00307 * This is the Q to attach to for all threads that will do 00308 * journalling. 00309 */ 00310 if (!(ptiT->TIF_flags & (TIF_DONTJOURNALATTACH | TIF_INCLEANUP))) { 00311 ptiT->pqAttach = pq; 00312 ptiT->pqAttach->cThreads++; 00313 } 00314 } 00315 } 00316 00317 return zzzReattachThreads(fAttach); 00318 }

VOID zzzRegisterSystemThread DWORD  dwFlags,
DWORD  dwReserved
 

Definition at line 2318 of file hooks.c.

References dwFlags, FALSE, FJOURNALPLAYBACK, FJOURNALRECORD, PtiCurrent, TIF_DONTATTACHQUEUE, TIF_DONTJOURNALATTACH, tagTHREADINFO::TIF_flags, TRUE, VOID(), and zzzJournalAttach().

02319 { 02320 PTHREADINFO ptiCurrent; 02321 02322 UserAssert(dwReserved == 0); 02323 02324 if (dwReserved != 0) 02325 return; 02326 02327 ptiCurrent = PtiCurrent(); 02328 02329 if (dwFlags & RST_DONTATTACHQUEUE) 02330 ptiCurrent->TIF_flags |= TIF_DONTATTACHQUEUE; 02331 02332 if (dwFlags & RST_DONTJOURNALATTACH) { 02333 ptiCurrent->TIF_flags |= TIF_DONTJOURNALATTACH; 02334 02335 /* 02336 * If we are already journaling, then this queue was already 02337 * journal attached. We need to unattach and reattach journaling 02338 * so that we are removed from the journal attached queues. 02339 */ 02340 if (FJOURNALPLAYBACK() || FJOURNALRECORD()) { 02341 zzzJournalAttach(ptiCurrent, FALSE); 02342 zzzJournalAttach(ptiCurrent, TRUE); 02343 } 02344 } 02345 }

PROC zzzSetWindowsHookAW int  nFilterType,
PROC  pfnFilterProc,
DWORD  dwFlags
 

Definition at line 528 of file hooks.c.

References abHookFlags, dwFlags, HKF_NZRET, NULL, tagHOOK::phkNext, PtiCurrent, and zzzSetWindowsHookEx().

Referenced by NtUserSetWindowsHookAW().

00532 { 00533 PHOOK phk; 00534 00535 phk = zzzSetWindowsHookEx(NULL, NULL, PtiCurrent(), 00536 nFilterType, pfnFilterProc, dwFlags); 00537 00538 /* 00539 * If we get an error from zzzSetWindowsHookEx() then we return 00540 * -1 to be compatible with older version of Windows. 00541 */ 00542 if (phk == NULL) { 00543 return (PROC)-1; 00544 } 00545 00546 /* 00547 * Handle the backwards compatibility return value cases for 00548 * SetWindowsHook. If this was the first hook in the chain, 00549 * then return NULL, else return something non-zero. HKF_NZRET 00550 * is a special case where SetWindowsHook would always return 00551 * something because there was a default hook installed. Some 00552 * apps relied on a non-zero return value in those cases. 00553 */ 00554 if ((phk->phkNext != NULL) || (abHookFlags[nFilterType + 1] & HKF_NZRET)) { 00555 return (PROC)phk; 00556 } 00557 00558 return NULL; 00559 }

PHOOK zzzSetWindowsHookEx HANDLE  hmod,
PUNICODE_STRING  pstrLib,
PTHREADINFO  ptiThread,
int  nFilterType,
PROC  pfnFilterProc,
DWORD  dwFlags
 

Definition at line 576 of file hooks.c.

References abHookFlags, AddHmodDependency(), tagTHREADINFO::amdesk, tagTHREADINFO::aphkStart, tagDESKTOPINFO::aphkStart, BOOL, DbgValidateHooks, dwFlags, tagWINDOWSTATION::dwWSF_Flags, FALSE, tagHOOK::flags, tagTHREADINFO::fsHooks, _CLIENTINFO::fsHooks, tagDESKTOPINFO::fsHooks, GetHmodTableIndex(), gppiInputProvider, HF_ANSI, HF_GLOBAL, HF_WX86KNOWNDLL, HKF_INTERSENDABLE, HKF_JOURNAL, HKF_TASK, HMAllocObject(), HMFreeObject(), tagHOOK::ihmod, tagHOOK::iHook, KeAttachProcess(), KeDetachProcess(), KeSetPriorityThread(), tagPROCESSINFO::luidSession, NULL, tagHOOK::offPfn, tagTHREADINFO::pClientInfo, tagTHREADINFO::pDeskInfo, tagHOOK::phkNext, tagTHREADINFO::ppi, PtiCurrent, tagHOOK::ptiHooked, tagTHREADINFO::rpdesk, tagDESKTOP::rpwinstaParent, RtlAreAllAccessesGranted(), RtlEqualLuid(), THREAD_TO_PROCESS, ThreadLockAlwaysWithPti, ThreadUnlock, TIF_ALLOWOTHERACCOUNTHOOK, TIF_CSRSSTHREAD, tagTHREADINFO::TIF_flags, TIF_GLOBALHOOKER, TIF_SYSTEMTHREAD, TRUE, TYPE_HOOK, WHF_FROM_WH, WSF_NOIO, zzzJournalAttach(), zzzSetFMouseMoved(), and zzzUnhookWindowsHookEx().

Referenced by NtUserSetWindowsHookEx(), and zzzSetWindowsHookAW().

00583 { 00584 ACCESS_MASK amDesired; 00585 PHOOK phkNew; 00586 TL tlphkNew; 00587 PHOOK *pphkStart; 00588 PTHREADINFO ptiCurrent; 00589 00590 /* 00591 * Check to see if filter type is valid. 00592 */ 00593 if ((nFilterType < WH_MIN) || (nFilterType > WH_MAX)) { 00594 RIPERR0(ERROR_INVALID_HOOK_FILTER, RIP_VERBOSE, ""); 00595 return NULL; 00596 } 00597 00598 /* 00599 * Check to see if filter proc is valid. 00600 */ 00601 if (pfnFilterProc == NULL) { 00602 RIPERR0(ERROR_INVALID_FILTER_PROC, RIP_VERBOSE, ""); 00603 return NULL; 00604 } 00605 00606 ptiCurrent = PtiCurrent(); 00607 00608 if (ptiThread == NULL) { 00609 /* 00610 * Is the app trying to set a global hook without a library? 00611 * If so return an error. 00612 */ 00613 if (hmod == NULL) { 00614 RIPERR0(ERROR_HOOK_NEEDS_HMOD, RIP_VERBOSE, ""); 00615 return NULL; 00616 } 00617 } else { 00618 /* 00619 * Is the app trying to set a local hook that is global-only? 00620 * If so return an error. 00621 */ 00622 if (!(abHookFlags[nFilterType + 1] & HKF_TASK)) { 00623 RIPERR0(ERROR_GLOBAL_ONLY_HOOK, RIP_VERBOSE, ""); 00624 return NULL; 00625 } 00626 00627 /* 00628 * Can't hook outside our own desktop. 00629 */ 00630 if (ptiThread->rpdesk != ptiCurrent->rpdesk) { 00631 RIPERR0(ERROR_ACCESS_DENIED, 00632 RIP_WARNING, 00633 "Access denied to desktop in zzzSetWindowsHookEx - can't hook other desktops"); 00634 00635 return NULL; 00636 } 00637 00638 if (ptiCurrent->ppi != ptiThread->ppi) { 00639 /* 00640 * Is the app trying to set hook in another process without a library? 00641 * If so return an error. 00642 */ 00643 if (hmod == NULL) { 00644 RIPERR0(ERROR_HOOK_NEEDS_HMOD, RIP_VERBOSE, ""); 00645 return NULL; 00646 } 00647 00648 /* 00649 * Is the app hooking another user without access? 00650 * If so return an error. Note that this check is done 00651 * for global hooks every time the hook is called. 00652 */ 00653 if ((!RtlEqualLuid(&ptiThread->ppi->luidSession, 00654 &ptiCurrent->ppi->luidSession)) && 00655 !(ptiThread->TIF_flags & TIF_ALLOWOTHERACCOUNTHOOK)) { 00656 00657 RIPERR0(ERROR_ACCESS_DENIED, 00658 RIP_WARNING, 00659 "Access denied to other user in zzzSetWindowsHookEx"); 00660 00661 return NULL; 00662 } 00663 00664 if ((ptiThread->TIF_flags & (TIF_CSRSSTHREAD | TIF_SYSTEMTHREAD)) && 00665 !(abHookFlags[nFilterType + 1] & HKF_INTERSENDABLE)) { 00666 00667 /* 00668 * Can't hook console or GUI system thread if inter-thread 00669 * calling isn't implemented for this hook type. 00670 */ 00671 RIPERR1(ERROR_HOOK_TYPE_NOT_ALLOWED, 00672 RIP_WARNING, 00673 "nFilterType (%ld) not allowed in zzzSetWindowsHookEx", 00674 nFilterType); 00675 00676 return NULL; 00677 } 00678 } 00679 } 00680 00681 /* 00682 * Check if this thread has access to hook its desktop. 00683 */ 00684 switch( nFilterType ) { 00685 case WH_JOURNALRECORD: 00686 amDesired = DESKTOP_JOURNALRECORD; 00687 break; 00688 00689 case WH_JOURNALPLAYBACK: 00690 amDesired = DESKTOP_JOURNALPLAYBACK; 00691 break; 00692 00693 default: 00694 amDesired = DESKTOP_HOOKCONTROL; 00695 break; 00696 } 00697 00698 if (!RtlAreAllAccessesGranted(ptiCurrent->amdesk, amDesired)) { 00699 RIPERR0(ERROR_ACCESS_DENIED, 00700 RIP_WARNING, 00701 "Access denied to desktop in zzzSetWindowsHookEx"); 00702 00703 return NULL; 00704 } 00705 00706 if (amDesired != DESKTOP_HOOKCONTROL && 00707 (ptiCurrent->rpdesk->rpwinstaParent->dwWSF_Flags & WSF_NOIO)) { 00708 RIPERR0(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION, 00709 RIP_WARNING, 00710 "Journal hooks invalid on a desktop belonging to a non-interactive WindowStation."); 00711 00712 return NULL; 00713 } 00714 00715 #if 0 00716 /* 00717 * Is this a journal hook? 00718 */ 00719 if (abHookFlags[nFilterType + 1] & HKF_JOURNAL) { 00720 /* 00721 * Is a journal hook of this type already installed? 00722 * If so it's an error. 00723 * If this code is enabled, use PhkFirstGlobalValid instead 00724 * of checking phkStart directly 00725 */ 00726 if (ptiCurrent->pDeskInfo->asphkStart[nFilterType + 1] != NULL) { 00727 RIPERR0(ERROR_JOURNAL_HOOK_SET, RIP_VERBOSE, ""); 00728 return NULL; 00729 } 00730 } 00731 #endif 00732 00733 /* 00734 * Allocate the new HOOK structure. 00735 */ 00736 phkNew = (PHOOK)HMAllocObject(ptiCurrent, ptiCurrent->rpdesk, 00737 TYPE_HOOK, sizeof(HOOK)); 00738 if (phkNew == NULL) { 00739 return NULL; 00740 } 00741 00742 /* 00743 * If a DLL is required for this hook, register the library with 00744 * the library management routines so we can assure it's loaded 00745 * into all the processes necessary. 00746 */ 00747 phkNew->ihmod = -1; 00748 if (hmod != NULL) { 00749 00750 #if defined(WX86) 00751 00752 phkNew->flags |= (dwFlags & HF_WX86KNOWNDLL); 00753 00754 #endif 00755 00756 phkNew->ihmod = GetHmodTableIndex(pstrLib); 00757 00758 if (phkNew->ihmod == -1) { 00759 RIPERR0(ERROR_MOD_NOT_FOUND, RIP_VERBOSE, ""); 00760 HMFreeObject((PVOID)phkNew); 00761 return NULL; 00762 } 00763 00764 /* 00765 * Add a dependency on this module - meaning, increment a count 00766 * that simply counts the number of hooks set into this module. 00767 */ 00768 if (phkNew->ihmod >= 0) { 00769 AddHmodDependency(phkNew->ihmod); 00770 } 00771 } 00772 00773 /* 00774 * Depending on whether we're setting a global or local hook, 00775 * get the start of the appropriate linked-list of HOOKs. Also 00776 * set the HF_GLOBAL flag if it's a global hook. 00777 */ 00778 if (ptiThread != NULL) { 00779 pphkStart = &ptiThread->aphkStart[nFilterType + 1]; 00780 00781 /* 00782 * Set the WHF_* in the THREADINFO so we know it's hooked. 00783 */ 00784 ptiThread->fsHooks |= WHF_FROM_WH(nFilterType); 00785 00786 /* 00787 * Set the flags in the thread's TEB 00788 */ 00789 if (ptiThread->pClientInfo) { 00790 BOOL fAttached; 00791 00792 /* 00793 * If the thread being hooked is in another process, attach 00794 * to that process so that we can access its ClientInfo. 00795 */ 00796 if (ptiThread->ppi != ptiCurrent->ppi) { 00797 KeAttachProcess(&ptiThread->ppi->Process->Pcb); 00798 fAttached = TRUE; 00799 } else 00800 fAttached = FALSE; 00801 00802 ptiThread->pClientInfo->fsHooks = ptiThread->fsHooks; 00803 00804 if (fAttached) 00805 KeDetachProcess(); 00806 } 00807 00808 /* 00809 * Remember which thread we're hooking. 00810 */ 00811 phkNew->ptiHooked = ptiThread; 00812 00813 } else { 00814 pphkStart = &ptiCurrent->pDeskInfo->aphkStart[nFilterType + 1]; 00815 phkNew->flags |= HF_GLOBAL; 00816 00817 /* 00818 * Set the WHF_* in the SERVERINFO so we know it's hooked. 00819 */ 00820 ptiCurrent->pDeskInfo->fsHooks |= WHF_FROM_WH(nFilterType); 00821 00822 phkNew->ptiHooked = NULL; 00823 } 00824 00825 /* 00826 * Does the hook function expect ANSI or Unicode text? 00827 */ 00828 phkNew->flags |= (dwFlags & HF_ANSI); 00829 00830 /* 00831 * Initialize the HOOK structure. Unreferenced parameters are assumed 00832 * to be initialized to zero by LocalAlloc(). 00833 */ 00834 phkNew->iHook = nFilterType; 00835 00836 /* 00837 * Libraries are loaded at different linear addresses in different 00838 * process contexts. For this reason, we need to convert the filter 00839 * proc address into an offset while setting the hook, and then convert 00840 * it back to a real per-process function pointer when calling a 00841 * hook. Do this by subtracting the 'hmod' (which is a pointer to the 00842 * linear and contiguous .exe header) from the function index. 00843 */ 00844 phkNew->offPfn = ((ULONG_PTR)pfnFilterProc) - ((ULONG_PTR)hmod); 00845 00846 #ifdef HOOKBATCH 00847 phkNew->cEventMessages = 0; 00848 phkNew->iCurrentEvent = 0; 00849 phkNew->CacheTimeOut = 0; 00850 phkNew->aEventCache = NULL; 00851 #endif //HOOKBATCH 00852 00853 /* 00854 * Link this hook into the front of the hook-list. 00855 */ 00856 phkNew->phkNext = *pphkStart; 00857 *pphkStart = phkNew; 00858 00859 /* 00860 * If this is a journal hook, setup synchronized input processing 00861 * AFTER we set the hook - so this synchronization can be cancelled 00862 * with control-esc. 00863 */ 00864 if (abHookFlags[nFilterType + 1] & HKF_JOURNAL) { 00865 /* 00866 * Attach everyone to us so journal-hook processing 00867 * will be synchronized. 00868 * No need to DeferWinEventNotify() here, since we lock phkNew. 00869 */ 00870 ThreadLockAlwaysWithPti(ptiCurrent, phkNew, &tlphkNew); 00871 if (!zzzJournalAttach(ptiCurrent, TRUE)) { 00872 RIPMSG1(RIP_WARNING, "zzzJournalAttach failed, so abort hook %#p", phkNew); 00873 if (ThreadUnlock(&tlphkNew) != NULL) { 00874 zzzUnhookWindowsHookEx(phkNew); 00875 } 00876 return NULL; 00877 } 00878 if ((phkNew = ThreadUnlock(&tlphkNew)) == NULL) { 00879 return NULL; 00880 } 00881 } 00882 00883 UserAssert(phkNew != NULL); 00884 00885 /* 00886 * Later 5.0 GerardoB: The old code just to check this but 00887 * I think it's some left over stuff from server side days. 00888 .* Let's assert on it for a while 00889 * Also, I added the assertions in the else's below because I reorganized 00890 * the code and want to make sure we don't change behavior 00891 */ 00892 UserAssert(ptiCurrent->pEThread && THREAD_TO_PROCESS(ptiCurrent->pEThread)); 00893 00894 /* 00895 * Can't allow a process that has set a global hook that works 00896 * on server-side winprocs to run at background priority! Bump 00897 * up it's dynamic priority and mark it so it doesn't get reset. 00898 */ 00899 if ((phkNew->flags & HF_GLOBAL) && 00900 (abHookFlags[nFilterType + 1] & HKF_INTERSENDABLE)) { 00901 00902 ptiCurrent->TIF_flags |= TIF_GLOBALHOOKER; 00903 KeSetPriorityThread(&ptiCurrent->pEThread->Tcb, LOW_REALTIME_PRIORITY-2); 00904 00905 if (abHookFlags[nFilterType + 1] & HKF_JOURNAL) { 00906 ThreadLockAlwaysWithPti(ptiCurrent, phkNew, &tlphkNew); 00907 /* 00908 * If we're changing the journal hooks, jiggle the mouse. 00909 * This way the first event will always be a mouse move, which 00910 * will ensure that the cursor is set properly. 00911 */ 00912 zzzSetFMouseMoved(); 00913 phkNew = ThreadUnlock(&tlphkNew); 00914 /* 00915 * If setting a journal playback hook, this process is the input 00916 * provider. This gives it the right to call SetForegroundWindow 00917 */ 00918 if (nFilterType == WH_JOURNALPLAYBACK) { 00919 gppiInputProvider = ptiCurrent->ppi; 00920 } 00921 } else { 00922 UserAssert(nFilterType != WH_JOURNALPLAYBACK); 00923 } 00924 } else { 00925 UserAssert(!(abHookFlags[nFilterType + 1] & HKF_JOURNAL)); 00926 UserAssert(nFilterType != WH_JOURNALPLAYBACK); 00927 } 00928 00929 00930 00931 00932 /* 00933 * Return pointer to our internal hook structure so we know 00934 * which hook to call next in CallNextHookEx(). 00935 */ 00936 DbgValidateHooks(phkNew, phkNew->iHook); 00937 return phkNew; 00938 }

BOOL zzzUnhookWindowsHook int  nFilterType,
PROC  pfnFilterProc
 

Definition at line 1068 of file hooks.c.

References BOOL, FALSE, GETPTI, NULL, PFNHOOK, PhkFirstValid(), PhkNextValid(), PtiCurrent, and zzzUnhookWindowsHookEx().

01071 { 01072 PHOOK phk; 01073 PTHREADINFO ptiCurrent; 01074 01075 if ((nFilterType < WH_MIN) || (nFilterType > WH_MAX)) { 01076 RIPERR0(ERROR_INVALID_HOOK_FILTER, RIP_VERBOSE, ""); 01077 return FALSE; 01078 } 01079 01080 ptiCurrent = PtiCurrent(); 01081 01082 for (phk = PhkFirstValid(ptiCurrent, nFilterType); phk != NULL; phk = PhkNextValid(phk)) { 01083 /* 01084 * Is this the hook we're looking for? 01085 */ 01086 if (PFNHOOK(phk) == pfnFilterProc) { 01087 01088 /* 01089 * Are we on the thread that set the hook? 01090 * If not return an error. 01091 */ 01092 if (GETPTI(phk) != ptiCurrent) { 01093 RIPERR0(ERROR_ACCESS_DENIED, 01094 RIP_WARNING, 01095 "Access denied in zzzUnhookWindowsHook: " 01096 "this thread is not the same as that which set the hook"); 01097 01098 return FALSE; 01099 } 01100 01101 return zzzUnhookWindowsHookEx( phk ); 01102 } 01103 } 01104 01105 /* 01106 * Didn't find the hook we were looking for so return FALSE. 01107 */ 01108 RIPERR0(ERROR_HOOK_NOT_INSTALLED, RIP_VERBOSE, ""); 01109 return FALSE; 01110 }

BOOL zzzUnhookWindowsHookEx PHOOK  phkFree  ) 
 

Definition at line 1126 of file hooks.c.

References abHookFlags, BOOL, FALSE, tagHOOK::flags, FreeHook(), GETPTI, HF_DESTROYED, HKF_INTERSENDABLE, HKF_JOURNAL, tagHOOK::iHook, NULL, PhkFirstGlobalValid(), PhkNextValid(), tagTHREADINFO::TIF_flags, TIF_GLOBALHOOKER, TRUE, and zzzJournalAttach().

Referenced by NtUserUnhookWindowsHookEx(), zzzCancelJournalling(), zzzSetWindowsHookEx(), and zzzUnhookWindowsHook().

01128 { 01129 PTHREADINFO pti; 01130 01131 pti = GETPTI(phkFree); 01132 01133 /* 01134 * If this hook is already destroyed, bail 01135 */ 01136 if (phkFree->flags & HF_DESTROYED) { 01137 RIPMSG1(RIP_WARNING, "_UnhookWindowsHookEx(%#p) already destroyed", phkFree); 01138 return FALSE; 01139 } 01140 01141 /* 01142 * Clear the journaling flags in all the queues. 01143 */ 01144 if (abHookFlags[phkFree->iHook + 1] & HKF_JOURNAL) { 01145 zzzJournalAttach(pti, FALSE); 01146 /* 01147 * If someone got stuck because of the hook, let him go 01148 * 01149 * I want to get some performance numbers before checking this in. 01150 * MSTest hooks and unhooks all the time when running a script. 01151 * This code has never been in. 5/22/96. GerardoB 01152 */ 01153 // InterQueueMsgCleanup(3 * CMSWAITTOKILLTIMEOUT); 01154 } 01155 01156 /* 01157 * If no one is currently calling this hook, 01158 * go ahead and free it now. 01159 */ 01160 FreeHook(phkFree); 01161 01162 /* 01163 * If this thread has no more global hooks that are able to hook 01164 * server-side window procs, we must clear it's TIF_GLOBALHOOKER bit. 01165 */ 01166 if (pti->TIF_flags & TIF_GLOBALHOOKER) { 01167 int iHook; 01168 PHOOK phk; 01169 for (iHook = WH_MIN ; iHook <= WH_MAX ; ++iHook) { 01170 /* 01171 * Ignore those that can't hook server-side winprocs 01172 */ 01173 if (!(abHookFlags[iHook + 1] & HKF_INTERSENDABLE)) { 01174 continue; 01175 } 01176 01177 /* 01178 * Scan the global hooks 01179 */ 01180 for (phk = PhkFirstGlobalValid(pti, iHook); 01181 phk != NULL; phk = PhkNextValid(phk)) { 01182 01183 if (GETPTI(phk) == pti) { 01184 goto StillHasGlobalHooks; 01185 } 01186 } 01187 } 01188 pti->TIF_flags &= ~TIF_GLOBALHOOKER; 01189 } 01190 01191 StillHasGlobalHooks: 01192 /* 01193 * Success, return TRUE. 01194 */ 01195 return TRUE; 01196 }


Variable Documentation

CONST BYTE abHookFlags[CWINHOOKS]
 

Initial value:

Definition at line 49 of file hooks.c.

Referenced by xxxCallHook2(), zzzSetWindowsHookAW(), zzzSetWindowsHookEx(), and zzzUnhookWindowsHookEx().

CONST int ampiHookError[CWINHOOKS]
 

Initial value:

{ 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }

Definition at line 27 of file hooks.c.

Referenced by xxxCallHook2().


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