test: hooks.c File Reference

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:

     {
        HKF_SYSTEM | HKF_TASK | HKF_NZRET                       ,
        HKF_SYSTEM | HKF_JOURNAL          | HKF_INTERSENDABLE   ,
        HKF_SYSTEM | HKF_JOURNAL          | HKF_INTERSENDABLE   ,
        HKF_SYSTEM | HKF_TASK | HKF_NZRET | HKF_INTERSENDABLE   ,
        HKF_SYSTEM | HKF_TASK                                   ,
        HKF_SYSTEM | HKF_TASK                                   ,
        HKF_SYSTEM | HKF_TASK                                   ,
        HKF_SYSTEM                                              ,
        HKF_SYSTEM | HKF_TASK             | HKF_INTERSENDABLE   ,
        HKF_SYSTEM | HKF_TASK                                   ,
        HKF_SYSTEM | HKF_TASK                                   ,
        HKF_SYSTEM | HKF_TASK                                   ,
        HKF_SYSTEM | HKF_TASK                                   ,
        HKF_SYSTEM | HKF_TASK                                   ,
        HKF_SYSTEM | HKF_LOWLEVEL         | HKF_INTERSENDABLE   ,
        HKF_SYSTEM | HKF_LOWLEVEL         | HKF_INTERSENDABLE

    }

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().