Annotation of pmsdk/samples/spy/spyhook.c, revision 1.1.1.2

1.1       root        1: /***********************************************************************\
1.1.1.2 ! root        2: * spyhook.c - Spy global input hook interface library
        !             3: * Created by Microsoft Corporation, 1989
1.1       root        4: *
1.1.1.2 ! root        5: * This dynlink is needed because global input hooks must reside in a DLL.
1.1       root        6: \***********************************************************************/
1.1.1.2 ! root        7: #define INCL_DOSPROCESS
        !             8: #define        INCL_WINHEAP
        !             9: #define        INCL_WINHOOKS
        !            10: #define        INCL_WINWINDOWMGR
1.1       root       11: #include <os2.h>
                     12: #include "spyhook.h"
                     13: 
                     14: ULONG spyhookSem = 0L;          /* global semaphore for this module */
                     15: HMODULE hmodSpy;                /* dynlink module handle            */
1.1.1.2 ! root       16: SHORT    SpybHooks;             /* Which hook do we use?            */
1.1       root       17: 
1.1.1.2 ! root       18: HAB habOwner = (HAB)0;          /* Hook owner's anchor block        */
1.1       root       19: HMQ hmqOwner = (HMQ)0;          /* Hook owner's message queue       */
                     20: BOOL fRecording = FALSE;        /* Are we recording now?            */
1.1.1.2 ! root       21: BOOL fAnythingToWatch = FALSE;  /* Is there anything to watch?      */
        !            22: BOOL fDispMsgsNotInList = TRUE; /* Disp msgs not in list?           */
1.1       root       23: 
                     24: /* Define array of window handles that we are going to process */
1.1.1.2 ! root       25: BOOL fProcessAllFrames = FALSE; /* Are we processing all frame messages?*/
        !            26: BOOL fProcessAllWindows = FALSE;/* Are we processing all windows?*/
        !            27: HWND *pahwndSpy = NULL;         /* Array of hwnds to spy on, no max here */
        !            28: int  chwndSpy = 0;             /* Max windows to spy */
        !            29: 
        !            30: /* Define array of HMQ's to spy on */
        !            31: HMQ *pahmqSpy = NULL;           /* HMQ list to spy on */
        !            32: int chmqSpy = 0;                /* Count of hmqs we are spying on */
        !            33: 
1.1       root       34: 
                     35: /* Define message filter array */
                     36: UCHAR rgMessageFilter[MAXMSGFILTERBYTES] = "";
1.1.1.2 ! root       37: UCHAR  GMsgEnableAndType(USHORT);       /* Is message in message list?*/
        !            38: VOID   GrabMsgDataWords(SHORT, UCHAR);  /* Get extra words for message */
        !            39: VOID   CopyStruct(UCHAR FAR *pbSrc, UCHAR FAR *pbDst, SHORT cb);/* Copy bytes */
1.1       root       40: 
                     41: /* Define an array of messages to pass to whomever calls us */
                     42: ULONG spyMsgSem =  0L;          /* global semaphore for this module */
1.1.1.2 ! root       43: 
        !            44: QMSGSPY  rgqmsgSpy[MAXMSGCNT];  /* Array of messages to process */
1.1       root       45: SHORT cmsgSpy = 0;              /* Count of messages yet to be read */
                     46: SHORT imsgWrite = 0;            /* Index to message to write out */
                     47: SHORT imsgRead = 0;             /* Index to message to read */
                     48: 
1.1.1.2 ! root       49: HHEAP hheapSpyHook;             /* Heap for SpyHook DLL */
        !            50: SHORT acbMPTypes[MP_MASK+1] = { /* Number of desired bytes to extract */
        !            51:     0,                          /* Normal fields, no pointers */
        !            52:     sizeof(SWP),                /* MPT_SWP */
        !            53:     sizeof(RECTL),              /* MPT_RECTL */
        !            54:     0,                          /* MPT_WNDPRMS we don't process yet */
        !            55:     sizeof(QMSG)                /* MPT_QMSG */
        !            56: };
        !            57: 
        !            58: 
        !            59: /* Information for getting selector information in different PID context */
        !            60: PID     pidLNSpy = 0xffff;      /* Which process */
        !            61: USHORT  selectorLNSpy = 0;      /* Which Selector */
        !            62: WHOISINFO   whoIsLNSpy;         /* Symbol information */
        !            63: int     rcLNSpy = -1;           /* Return code */
        !            64: 
        !            65: 
        !            66: /* Define all external functions */
        !            67: extern VOID  BuildStackTrace(CHAR FAR *, SHORT, SHORT);
        !            68: 
        !            69: /* Define all function prototypes */
        !            70: VOID SpyCheckPIDForSymbol(VOID);
        !            71: BOOL FAR PASCAL SpyInputHook(HAB, PQMSG, USHORT);
        !            72: BOOL FAR PASCAL SpySendMsgHook(HAB, PSMHSTRUCT, USHORT);
        !            73: VOID PASCAL Init(HMODULE);
1.1       root       74: 
1.1.1.2 ! root       75: /***********************************************************************\
        !            76: * BOOL FAR PASCAL SpyInputHook( hab, lpqmsg, fs )
1.1       root       77: * HAB hab;
                     78: * PQMSG  lpqmsg;
1.1.1.2 ! root       79: * USHORT    fs;
1.1       root       80: *
                     81: * Effect:  This is the global input hook procedure.  Note that hook
                     82: *   procedures can be chained, so we always return FALSE to pass the
1.1.1.2 ! root       83: *   message to the next guy in the chain.
1.1       root       84: *
                     85: * Return value:  FALSE to pass message to next hook procedure.
                     86: \***********************************************************************/
1.1.1.2 ! root       87: BOOL FAR PASCAL SpyInputHook( hab, lpqmsg, fs )
        !            88: HAB    hab;
        !            89: PQMSG  lpqmsg;
        !            90: USHORT  fs;
1.1       root       91: {
1.1.1.2 ! root       92:     UCHAR       bMPType;
        !            93: 
1.1       root       94:     /*
1.1.1.2 ! root       95:      * Check first to see if we are looking for a process's symbols
1.1       root       96:      */
1.1.1.2 ! root       97:     if (pidLNSpy != 0xffff)
        !            98:         SpyCheckPIDForSymbol();
1.1       root       99: 
1.1.1.2 ! root      100:     /*
        !           101:      * First check to see if we are processing any hook messages
        !           102:      */
        !           103:     if (!fRecording || !fAnythingToWatch || (cmsgSpy >= MAXMSGCNT))
        !           104:         return (FALSE); /* No, let the next one have it now */
1.1       root      105: 
                    106:     /*
1.1.1.2 ! root      107:      * See if we have any messages to process - re-check to make sure we
        !           108:      * don't overwrite our queue.
1.1       root      109:      */
                    110:     if (DosSemRequest((HSEM)(PULONG)&spyhookSem, 100L) != 0)
                    111:         return (FALSE);
                    112:     if (cmsgSpy < MAXMSGCNT) {
1.1.1.2 ! root      113:         if (SpyFWindowInList(lpqmsg->hwnd, FALSE) &&
        !           114:                 (bMPType = GMsgEnableAndType(lpqmsg->msg))) {
        !           115:             rgqmsgSpy[imsgWrite].fs = fs;       /* Save the flags */
        !           116:             rgqmsgSpy[imsgWrite].qmsg = *lpqmsg;   /* Save the message */
        !           117: 
        !           118:             GrabMsgDataWords(imsgWrite, bMPType);
        !           119:             imsgWrite++;
        !           120: 
1.1       root      121:             if (imsgWrite == MAXMSGCNT)
                    122:                 imsgWrite = 0;  /* Wrap around */
                    123:             cmsgSpy++;
                    124:             DosSemClear((HSEM)(PULONG)&spyMsgSem);
                    125:         }
                    126:     }
                    127: 
                    128:     DosSemClear( (HSEM)(PULONG)&spyhookSem );
1.1.1.2 ! root      129:     return FALSE;   /* Let system take normal action */
1.1       root      130: }
                    131: 
                    132: 
1.1.1.2 ! root      133: /***********************************************************************\
        !           134: * BOOL FAR PASCAL SpySendMsgHook( hab, lpsmh, fInterTask )
        !           135: * HAB          hab;
        !           136: * PSMHSTRUCT   lpsmh;
        !           137: * BOOL         fInterTask;
1.1       root      138: *
                    139: * Effect:  This is the global input hook procedure.  Note that hook
                    140: *   procedures can be chained, so we always return FALSE to pass the
1.1.1.2 ! root      141: *   message to the next guy in the chain.
1.1       root      142: *
                    143: * Return value:  FALSE to pass message to next hook procedure.
                    144: \***********************************************************************/
                    145: BOOL FAR PASCAL SpySendMsgHook( hab, lpsmh, fInterTask )
1.1.1.2 ! root      146: HAB            hab;
1.1       root      147: PSMHSTRUCT      lpsmh;
                    148: BOOL            fInterTask;
                    149: {
1.1.1.2 ! root      150:     UCHAR           bMPType;
        !           151:     PIDINFO         pidinfo;
        !           152: 
        !           153:     /*
        !           154:      * Check first to see if we are looking for a process's symbols
        !           155:      */
        !           156:     if (pidLNSpy != 0xffff)
        !           157:         SpyCheckPIDForSymbol();
        !           158: 
1.1       root      159:     /*
                    160:      * First check to see if we are processing any hook messages
                    161:      */
1.1.1.2 ! root      162:     if (!fRecording || !fAnythingToWatch || (cmsgSpy >= MAXMSGCNT))
        !           163:         return (FALSE); /* No, let the next one have it now */
1.1       root      164: 
                    165:     /*
                    166:      * See if we have any messages to process
                    167:      */
                    168:     if (DosSemRequest((HSEM)(PULONG)&spyhookSem, 100L) != 0)
                    169:         return (FALSE);
                    170:     /* Make sure no one got in by mistake */
                    171:     if (cmsgSpy < MAXMSGCNT) {
1.1.1.2 ! root      172:         if (SpyFWindowInList(lpsmh->hwnd, FALSE) &&
        !           173:                 (bMPType = GMsgEnableAndType(lpsmh->msg))) {
        !           174:             /*
        !           175:              * Store out message, must move pieces separately
1.1       root      176:              */
1.1.1.2 ! root      177:             rgqmsgSpy[imsgWrite].fs = fInterTask;
        !           178:             rgqmsgSpy[imsgWrite].qmsg.hwnd = lpsmh->hwnd;
        !           179:             rgqmsgSpy[imsgWrite].qmsg.msg  = lpsmh->msg;
        !           180:             rgqmsgSpy[imsgWrite].qmsg.mp1  = lpsmh->mp1;
        !           181:             rgqmsgSpy[imsgWrite].qmsg.mp2  = lpsmh->mp2;
        !           182:             rgqmsgSpy[imsgWrite].qmsg.time = (ULONG)-1;
        !           183:             rgqmsgSpy[imsgWrite].qmsg.ptl.x  = 0;
        !           184:             rgqmsgSpy[imsgWrite].qmsg.ptl.y  = 0;
        !           185: 
        !           186:             GrabMsgDataWords(imsgWrite, bMPType);
        !           187: 
        !           188:             /* Now get the PID/TID info, and do the stack backtrace */
        !           189:             DosGetPID(&pidinfo);
        !           190:             rgqmsgSpy[imsgWrite].pidSend = pidinfo.pid;
        !           191:             rgqmsgSpy[imsgWrite].tidSend = pidinfo.tid;
        !           192:             BuildStackTrace((CHAR FAR *)rgqmsgSpy[imsgWrite].pvoidStack,
        !           193:                     CALLSTOSKIP, MAXSTRACE);
1.1       root      194: 
                    195:             imsgWrite++;
                    196:             if (imsgWrite == MAXMSGCNT)
                    197:                 imsgWrite = 0;  /* Wrap around */
                    198:             cmsgSpy++;
                    199:             DosSemClear((HSEM)(PULONG)&spyMsgSem);
                    200:         }
                    201:     }
                    202: 
                    203:     DosSemClear( (HSEM)(PULONG)&spyhookSem );
1.1.1.2 ! root      204:     return FALSE;   /* Let system take normal action */
1.1       root      205: }
                    206: 
                    207: 
1.1.1.2 ! root      208: /***********************************************************************\
1.1       root      209: * BOOL FAR PASCAL SpyInstallHook( hab, hmq, fSendMessage, bHooks)
                    210: *
                    211: * Effect:  This routine installs a system-wide HK_INPUT hook.  The hab
                    212: *   hmq are remembered for message posting.  Note that we only allow
                    213: *   one input hook to be installed through this routine, but other
                    214: *   apps may call WinSetHook directly.
                    215: *
                    216: * Returns value:  TRUE if hook installed successfully, FALSE otherwise.
                    217: \***********************************************************************/
                    218: BOOL FAR PASCAL SpyInstallHook( hab, hmq, bHooks )
                    219: HAB     hab;
                    220: HMQ     hmq;
                    221: USHORT  bHooks;
                    222: {
                    223:     BOOL fRet;
1.1.1.2 ! root      224:     SEL  selHeap;
1.1       root      225: 
                    226:     DosSemRequest( (HSEM)(PULONG)&spyhookSem, -1L);
                    227: 
1.1.1.2 ! root      228:     /*
        !           229:      * If this is the first time through, we need to create a local heap
        !           230:      * to store message information.
        !           231:      */
        !           232:     if (hheapSpyHook == NULL) {
        !           233:         selHeap = (SEL)(((ULONG)((PSZ)&hheapSpyHook)) >> 16);
        !           234:         hheapSpyHook = WinCreateHeap(selHeap, 1024, 0, 0, 100,
        !           235:             HM_MOVEABLE | HM_VALIDSIZE);
        !           236:         if (hheapSpyHook == NULL)
        !           237:             return (FALSE);
        !           238:     }
        !           239: 
        !           240: 
        !           241: 
        !           242:     /*
        !           243:      * Look at hook index.
        !           244:      *
        !           245:      * if it equals  HK_INPUT then
        !           246:      *         install a system-wide input hook
        !           247:      * else
        !           248:      *         set system wide SENDMSG hook
        !           249:      */
1.1       root      250:     SpybHooks = bHooks;
                    251:     if (SpybHooks & SPYH_INPUT)
                    252:         fRet = WinSetHook( hab, (HMQ)0, HK_INPUT, (PFN)SpyInputHook,
1.1.1.2 ! root      253:                     hmodSpy );
1.1       root      254: 
                    255:     if (SpybHooks & SPYH_SENDMSG)
                    256:         fRet = WinSetHook( hab, (HMQ)0, HK_SENDMSG, (PFN)SpySendMsgHook,
1.1.1.2 ! root      257:                     hmodSpy );
1.1       root      258:     if (fRet) {
                    259:         habOwner = hab;
                    260:         hmqOwner = hmq;
                    261:     }
                    262: 
                    263:     DosSemSet((HSEM)(PULONG)&spyMsgSem);    /* Init, no messages avail */
                    264:     DosSemClear( (HSEM)(PULONG)&spyhookSem );
                    265: 
                    266:     return fRet;
                    267: }
                    268: 
                    269: 
                    270: 
1.1.1.2 ! root      271: /***********************************************************************\
1.1       root      272: * BOOL FAR PASCAL SpySetWindowList( chwnd, rghwnd)
                    273: *
                    274: * Effect:  This routine sets the list of window that we are interested
                    275: *   in watching the messages for.
                    276: *
1.1.1.2 ! root      277: * Returns value:  TRUE
1.1       root      278: \***********************************************************************/
                    279: BOOL FAR PASCAL SpySetWindowList( chwnd, rghwnd )
                    280: SHORT       chwnd;
                    281: HWND FAR    *rghwnd;
                    282: {
                    283:     SHORT   i;
1.1.1.2 ! root      284:     HWND    *phwndT;
1.1       root      285: 
                    286:     DosSemRequest( (HSEM)(PULONG)&spyhookSem, -1L);
                    287: 
1.1.1.2 ! root      288:     if (pahwndSpy) {
        !           289:         WinFreeMem(hheapSpyHook, (char *)pahwndSpy, sizeof(HWND) * chwndSpy);
        !           290:         pahwndSpy = NULL;
        !           291:     }
        !           292: 
        !           293: 
1.1       root      294:     chwndSpy = chwnd;
                    295: 
1.1.1.2 ! root      296:     if (chwndSpy > 0 ) {
        !           297: 
        !           298:         phwndT = pahwndSpy = WinAllocMem(hheapSpyHook,
        !           299:                 sizeof(HWND) * chwndSpy);
        !           300: 
        !           301:         if (phwndT != NULL) {
        !           302:             for (i=0; i < chwnd; i++) {
        !           303:                 *phwndT++ = *rghwnd++;
        !           304:             }
        !           305:         } else
        !           306:             chwndSpy = 0;
1.1       root      307:     }
                    308: 
1.1.1.2 ! root      309:     fAnythingToWatch = (chwndSpy > 0) || (chmqSpy > 0) ||
        !           310:             fProcessAllWindows || fProcessAllFrames;
1.1       root      311: 
1.1.1.2 ! root      312:     DosSemClear( (HSEM)(PULONG)&spyhookSem );
1.1       root      313:     return(TRUE);
                    314: }
                    315: 
                    316: 
1.1.1.2 ! root      317: /***********************************************************************\
1.1       root      318: * BOOL FAR PASCAL SpyGetWindowList( chwnd, rghwnd)
                    319: *
                    320: * Effect:  This routine sets the list of window that we are interested
                    321: *   in watching the messages for.
                    322: *
1.1.1.2 ! root      323: * Returns value:  TRUE
1.1       root      324: \***********************************************************************/
                    325: SHORT FAR PASCAL SpyGetWindowList( chwnd, rghwnd )
                    326: SHORT       chwnd;
                    327: HWND FAR    *rghwnd;
                    328: {
                    329:     SHORT   i;
1.1.1.2 ! root      330:     HWND    *phwndT;
1.1       root      331: 
                    332:     DosSemRequest( (HSEM)(PULONG)&spyhookSem, -1L);
                    333: 
1.1.1.2 ! root      334:     if (chwnd > chwndSpy)
        !           335:             chwnd = chwndSpy;
1.1       root      336: 
1.1.1.2 ! root      337:     phwndT = pahwndSpy;
1.1       root      338:     for (i=0; i < chwnd; i++) {
1.1.1.2 ! root      339:         *rghwnd++ = *pahwndSpy++;
1.1       root      340:     }
                    341: 
                    342:     DosSemClear( (HSEM)(PULONG)&spyhookSem );
                    343: 
                    344:     return(chwnd);
                    345: }
                    346: 
                    347: 
1.1.1.2 ! root      348: 
        !           349: 
        !           350: /***********************************************************************\
        !           351: * BOOL FAR PASCAL SpySetQueueList( chmq, rghmq )
1.1       root      352: *
1.1.1.2 ! root      353: * Effect:  This routine sets the list of queues whose messages we watch.
        !           354: *
        !           355: * Returns value:  TRUE
        !           356: \***********************************************************************/
        !           357: BOOL FAR PASCAL SpySetQueueList( chmq, rghmq )
        !           358: SHORT       chmq;
        !           359: HMQ FAR    *rghmq;
        !           360: {
        !           361:     SHORT   i;
        !           362:     HMQ     *phmqT;
        !           363: 
        !           364:     DosSemRequest( (HSEM)(PULONG)&spyhookSem, -1L);
        !           365: 
        !           366:     /*
        !           367:      * If we previously had a list of HMQs to spy on, free the old list
        !           368:      * now
        !           369:      */
        !           370:     if (pahmqSpy != NULL) {
        !           371:         WinFreeMem(hheapSpyHook, (char *)pahmqSpy, sizeof(HMQ) * chmqSpy);
        !           372:         pahmqSpy = NULL;
        !           373:     }
        !           374: 
        !           375:     chmqSpy = chmq;
        !           376: 
        !           377:     if (chmqSpy > 0) {
        !           378:         phmqT = pahmqSpy = WinAllocMem(hheapSpyHook, sizeof(HMQ) * chmqSpy);
        !           379: 
        !           380:         if (phmqT != NULL) {
        !           381:             for (i=0; i < chmq; i++) {
        !           382:                 *phmqT++ = *rghmq++;
        !           383:             }
        !           384:         } else
        !           385:             chmqSpy = 0;
        !           386:     }
        !           387: 
        !           388:     fAnythingToWatch = (chwndSpy > 0) || (chmqSpy > 0) ||
        !           389:             fProcessAllWindows || fProcessAllFrames;
        !           390:     DosSemClear( (HSEM)(PULONG)&spyhookSem );
        !           391: 
        !           392:     return(TRUE);
        !           393: }
        !           394: 
        !           395: 
        !           396: /***********************************************************************\
        !           397: * BOOL FAR PASCAL SpyGetQueueList( chmq, rghmq )
        !           398: *
        !           399: * Effect:  This routine gets the list of queues whose messages we watch.
        !           400: *
        !           401: * Returns value:  TRUE
        !           402: \***********************************************************************/
        !           403: SHORT FAR PASCAL SpyGetQueueList( chmq, rghmq )
        !           404: SHORT       chmq;
        !           405: HMQ FAR    *rghmq;
        !           406: {
        !           407:     SHORT   i;
        !           408:     HMQ     *phmqT;
        !           409: 
        !           410:     DosSemRequest( (HSEM)(PULONG)&spyhookSem, -1L);
        !           411: 
        !           412:     if (chmq > chmqSpy)
        !           413:         chmq = chmqSpy;
        !           414: 
        !           415:     phmqT = pahmqSpy;
        !           416: 
        !           417:     for (i=0; i < chmq; i++) {
        !           418:         *rghmq++ = *phmqT++;
        !           419:     }
        !           420: 
        !           421:     DosSemClear( (HSEM)(PULONG)&spyhookSem );
        !           422: 
        !           423:     return(chmq);
        !           424: }
        !           425: 
        !           426: 
        !           427: /***********************************************************************\
        !           428: * BOOL FAR PASCAL SpySetMessageList(UCHAR FAR *prgNewMsgFilter,
        !           429: *                   BOOL fNewDispMsgsNotInList)
        !           430: *
        !           431: * Effect:  This routine sets the list of windows that whose message we watch.
1.1       root      432: *
1.1.1.2 ! root      433: * Returns value:  TRUE
1.1       root      434: \***********************************************************************/
1.1.1.2 ! root      435: BOOL FAR PASCAL SpySetMessageList(prgNewMsgFilter, fNewDispMsgsNotInList)
1.1       root      436: UCHAR FAR           *prgNewMsgFilter;
1.1.1.2 ! root      437: BOOL                fNewDispMsgsNotInList;
1.1       root      438: {
                    439:     SHORT           i;
                    440:     unsigned char   *prgb;
                    441: 
                    442:     DosSemRequest( (HSEM)(PULONG)&spyhookSem, -1L);
                    443: 
                    444:     prgb = rgMessageFilter;
                    445: 
1.1.1.2 ! root      446: 
        !           447:     fDispMsgsNotInList = fNewDispMsgsNotInList;
        !           448: 
1.1       root      449:     for (i=0; i < MAXMSGFILTERBYTES; i++) {
                    450:         *prgb++ = *prgNewMsgFilter++;
                    451:     }
                    452: 
                    453:     DosSemClear( (HSEM)(PULONG)&spyhookSem );
                    454: 
                    455:     return(TRUE);
                    456: }
                    457: 
                    458: 
1.1.1.2 ! root      459: /***********************************************************************\
        !           460: * BOOL FAR PASCAL SpyFWindowInList (hwnd, fInWindowListOnly)
1.1       root      461: *
                    462: * Effect:  This function checks our current list of windows, and returns
                    463: *          TRUE if the window is in the list, else returns FALSE.
1.1.1.2 ! root      464: *
        !           465: * Returns value:  TRUE if window is in list.  Also, if we are in the special
1.1       root      466: *           state we will pass through all frame windows.
                    467: \***********************************************************************/
1.1.1.2 ! root      468: BOOL FAR PASCAL SpyFWindowInList (hwnd, fInWindowListOnly)
1.1       root      469: register HWND  hwnd;
1.1.1.2 ! root      470: BOOL            fInWindowListOnly;
1.1       root      471: {
                    472:     register int    i;
                    473:     char            szClassName[10];    /* Class name of window */
                    474:     CLASSINFO       classinfo;          /* Information about class */
1.1.1.2 ! root      475:     HMQ             hmqWindow;          /* HMQ of window        */
        !           476:     HMQ             *phmqT;             /* Temporary pointer in hmq list */
        !           477:     HWND            *phwndT;            /* Temporary pointer to HWND list */
        !           478: 
        !           479:     phwndT = pahwndSpy;
        !           480:     for (i=0; i < chwndSpy; i++) {
        !           481:         if (hwnd == *phwndT++)
        !           482:             return (TRUE);
        !           483:     }
        !           484: 
        !           485:     /* See if we are restricting to only windows in list */
        !           486:     if (fInWindowListOnly)
        !           487:         return (FALSE);
1.1       root      488: 
                    489:     if (fProcessAllWindows)
                    490:         return (TRUE);      /* All windows pass through */
                    491: 
1.1.1.2 ! root      492:     /*
        !           493:      * See if we are watching any message queues
        !           494:      */
        !           495:     if (phmqT = pahmqSpy) {
        !           496:         hmqWindow = (HMQ)WinQueryWindowULong(hwnd, QWL_HMQ);
        !           497:         for (i=0; i < chmqSpy; i++) {
        !           498:             if (*phmqT++ == hmqWindow)
        !           499:                 return (TRUE);
        !           500:         }
1.1       root      501:     }
                    502: 
                    503:     if (fProcessAllFrames) {
                    504:         /* See if frame class */
                    505:         if (hwnd == NULL)
                    506:             return (TRUE);      /* pass queue messages through */
                    507:         WinQueryClassName(hwnd, sizeof(szClassName),
                    508:             (PSZ)szClassName);
                    509:         WinQueryClassInfo((HAB)NULL, (PSZ)szClassName,
                    510:             &classinfo);
                    511:         if (classinfo.flClassStyle & CS_FRAME)
                    512:             return (TRUE);
                    513:     }
                    514: 
                    515:     return (FALSE);
                    516: }
                    517: 
                    518: 
1.1.1.2 ! root      519: /***********************************************************************\
1.1       root      520: * BOOL FAR PASCAL SpyReleaseHook(fZeroQueue)
                    521: *
                    522: * Effect:  This routine releases the input hook, if it is installed.
                    523: *
                    524: * Returns value: TRUE if hook is released, FALSE otherwise.
                    525: \***********************************************************************/
                    526: BOOL FAR PASCAL SpyReleaseHook(fZeroQueue)
                    527: BOOL    fZeroQueue;
                    528: {
                    529:     BOOL fRet;
                    530: 
                    531:     DosSemRequest ( (HSEM)(PULONG)&spyhookSem, -1L );
                    532: 
                    533:     if ( habOwner ) {
1.1.1.2 ! root      534:         if (SpybHooks & SPYH_INPUT)
        !           535:                 fRet = WinReleaseHook( habOwner, (HMQ)0, HK_INPUT,
        !           536:                     (PFN)SpyInputHook, hmodSpy );
        !           537: 
        !           538:         if (SpybHooks & SPYH_SENDMSG)
        !           539:                 fRet = WinReleaseHook( habOwner, (HMQ)0, HK_SENDMSG,
        !           540:                     (PFN)SpySendMsgHook, hmodSpy );
        !           541:             if ( fRet ) {
1.1       root      542:                 habOwner = (HAB)0;
                    543:                 hmqOwner = (HMQ)0;
                    544:         }
                    545:     }
                    546: 
                    547:     /*
                    548:      * When the hook is freed, we want to clear message count out,
                    549:      * make sure any process waiting will abort
                    550:      * Only do this if the Zeroqueu flag was passed
                    551:      */
                    552:     if (fZeroQueue) {
1.1.1.2 ! root      553:         cmsgSpy = 0;
1.1       root      554:         imsgWrite = 0;
1.1.1.2 ! root      555:         imsgRead = 0;
        !           556:         if (pahwndSpy != NULL)
        !           557:             WinFreeMem(hheapSpyHook, (char *)pahwndSpy,
        !           558:                     sizeof(HWND) * chwndSpy);
        !           559:         pahwndSpy = NULL;
1.1       root      560:         chwndSpy = 0;           /* Max windows to spy */
                    561:         fRecording = FALSE;     /* Set recording to off */
1.1.1.2 ! root      562:         if (pahmqSpy != NULL)
        !           563:             WinFreeMem(hheapSpyHook, (char *)pahmqSpy, sizeof(HMQ) * chmqSpy);
        !           564: 
        !           565:         pahmqSpy = NULL;
        !           566:         chmqSpy = 0;
        !           567:         fAnythingToWatch = FALSE;
1.1       root      568:         DosSemClear((HSEM)(PULONG)&spyMsgSem);    /* Free any process */
                    569:     }
                    570:     DosSemClear((HSEM)(PULONG)&spyhookSem);
                    571: 
                    572:     return fRet;
                    573: }
                    574: 
                    575: 
1.1.1.2 ! root      576: /***********************************************************************\
1.1       root      577: * BOOL FAR PASCAL SpyHookOnOrOff( fOn)
                    578: *
                    579: * Effect:  This routine allows the application to turn the hook
                    580: *   processing on or off.
                    581: *
1.1.1.2 ! root      582: * Returns:     TRUE
1.1       root      583: \***********************************************************************/
                    584: BOOL FAR PASCAL SpyHookOnOrOff(fOn)
                    585: BOOL fOn;
                    586: {
                    587:     DosSemRequest ( (HSEM)(PULONG)&spyhookSem, -1L);
                    588: 
                    589:     fRecording = fOn;
                    590: 
                    591:     DosSemClear( (HSEM)(PULONG)&spyhookSem );
                    592:     return (TRUE);
                    593: }
                    594: 
                    595: 
                    596: 
1.1.1.2 ! root      597: /***********************************************************************\
1.1       root      598: * BOOL FAR PASCAL SpySetAllFrameOpt(fAllFrames)
                    599: *
                    600: * Effect:  Special state if TRUE will cause the window filter to pass
1.1.1.2 ! root      601: *       all frame windows through.  This is useful when debugging
1.1       root      602: *       interactions between frame windows, when the windows are
                    603: *       net yet created.
                    604: *
1.1.1.2 ! root      605: * Returns:     TRUE
1.1       root      606: \***********************************************************************/
                    607: BOOL FAR PASCAL SpySetAllFrameOpt(fAllFrames)
                    608: BOOL fAllFrames;
                    609: {
                    610:     fProcessAllFrames = fAllFrames;
1.1.1.2 ! root      611:     fAnythingToWatch = (chwndSpy > 0) || (chmqSpy > 0) ||
        !           612:             fProcessAllWindows || fProcessAllFrames;
1.1       root      613:     return (TRUE);
                    614: }
1.1.1.2 ! root      615: 
        !           616: /***********************************************************************\
1.1       root      617: * BOOL FAR PASCAL SpySetAllWindowOpt(fAllWindows)
                    618: *
                    619: * Effect:  Special state if TRUE will cause the window filter to pass
1.1.1.2 ! root      620: *       all windows through.  This is useful when debugging
        !           621: *       interactions between all of the windows.
1.1       root      622: *
1.1.1.2 ! root      623: * Returns:     TRUE
1.1       root      624: \***********************************************************************/
                    625: BOOL FAR PASCAL SpySetAllWindowOpt(fAllWindows)
                    626: BOOL fAllWindows;
                    627: {
                    628:     fProcessAllWindows = fAllWindows;
1.1.1.2 ! root      629:     fAnythingToWatch = (chwndSpy > 0) || (chmqSpy > 0) ||
        !           630:             fProcessAllWindows || fProcessAllFrames;
1.1       root      631:     return (TRUE);
                    632: }
                    633: 
1.1.1.2 ! root      634: 
        !           635: /***********************************************************************\
        !           636: * BOOL FAR PASCAL SpySetLNSymbolPID(PID pid, SELECTOR sel);
1.1       root      637: *
1.1.1.2 ! root      638: *
        !           639: * Effect:  Tell the hook to be on the lookout for a specific PID.
        !           640: *       If found running in the context of the specified process, we
        !           641: *       will get the selector information for the specified selector.
        !           642: \***********************************************************************/
        !           643: BOOL FAR PASCAL SpySetLNSymbolPID(pid, selector)
        !           644: PID     pid;
        !           645: USHORT  selector;
        !           646: {
        !           647:     if (pidLNSpy == 0xffff) {
        !           648:         selectorLNSpy = selector;
        !           649:         rcLNSpy = -1;               /* Assume error for now */
        !           650:         pidLNSpy = pid;             /* Save PID to look for */
        !           651:         return (TRUE);
        !           652:     } else
        !           653:         return (FALSE);
        !           654: }
        !           655: 
        !           656: 
        !           657: 
        !           658: /***********************************************************************\
        !           659: * VOID SpyCheckPIDForSymbol(VOID)
        !           660: *
        !           661: * Effect:  Only called when we are looking for a symbol
        !           662: *
        !           663: \***********************************************************************/
        !           664: VOID SpyCheckPIDForSymbol()
        !           665: {
        !           666:     PIDINFO         pidinfo;
        !           667: 
        !           668:     /*
        !           669:      * Get the spy semaphore to serialize access and see if we are the
        !           670:      * correct PID;
        !           671:      */
        !           672:     DosGetPID(&pidinfo);
        !           673:     if (DosSemRequest((HSEM)(PULONG)&spyhookSem, 100L) != 0)
        !           674:         return;
        !           675: 
        !           676:     if (pidinfo.pid == pidLNSpy) {
        !           677:         /*
        !           678:          * We are the correct process, so continue to try go get the
        !           679:          * symbol information.
        !           680:          */
        !           681:         pidLNSpy = 0xffff;       /* reset to not enter again */
        !           682:         rcLNSpy = IdentifyCodeSelector( selectorLNSpy,
        !           683:             (PWHOISINFO)&whoIsLNSpy);
        !           684:     }
        !           685: 
        !           686:     DosSemClear( (HSEM)(PULONG)&spyhookSem );
        !           687: }
        !           688: 
        !           689: 
        !           690: 
        !           691: /***********************************************************************\
        !           692: * int FAR PASCAL SpyGetLNSymbolSelector(pwhoinfo)
        !           693: *
        !           694: * Effect:  Get the information about the specified selector.
        !           695: *       If the specified process has not been executed since the
        !           696: *       function SpySetLNSymbolPID has been called, it will return -1,
        !           697: *       else it will return what was returned from IdentifyCodeSelector.
        !           698: \***********************************************************************/
        !           699: int FAR PASCAL SpyGetLNSymbolSelector(pwhoIsinfo)
        !           700: PWHOISINFO    pwhoIsinfo;
1.1       root      701: {
1.1.1.2 ! root      702:     *pwhoIsinfo = whoIsLNSpy;
        !           703:     return (rcLNSpy);
        !           704: }
        !           705: 
        !           706: 
        !           707: 
        !           708: 
        !           709: /**********************************************************************\
        !           710: * VOID GrabMsgDataWords (SHORT imsg, UCHAR bMPType)
        !           711: *
        !           712: * Effect:  Gets the next message from the list.
        !           713: *
        !           714: *      if timeout != 0 on message processing threads, problems may occur.
        !           715: *      if lpqmsg==NULL, this function acts like a query or wait function.
        !           716: \***********************************************************************/
        !           717: VOID GrabMsgDataWords(imsg, bMPType)
        !           718: SHORT       imsg;
        !           719: UCHAR       bMPType;
        !           720: {
        !           721:     UCHAR   bMP1Type;
        !           722:     UCHAR   bMP2Type;
        !           723:     SHORT   cbMPs;
        !           724:     SHORT   cbMP1;
        !           725:     SHORT   cbMP2;
        !           726:     UCHAR   *rgBuf;
        !           727: 
        !           728:     /*
        !           729:      * This function will use the MPType data to know if MP1 and/or MP2
        !           730:      * are pointers to any known data, that we want to extract off
        !           731:      * and save for spy to display later
        !           732:      */
        !           733:     rgqmsgSpy[imsg].bMPType = bMPType;
        !           734:     bMP1Type = bMPType & MP_MASK;
        !           735:     cbMPs = cbMP1 = rgqmsgSpy[imsg].cbDataMP1 = acbMPTypes[bMP1Type];
        !           736: 
        !           737:     bMP2Type = (bMPType >> 3) & MP_MASK;
        !           738:     cbMPs += (cbMP2 = rgqmsgSpy[imsg].cbDataMP2 = acbMPTypes[bMP2Type]);
        !           739: 
        !           740:     if (cbMPs > 0) {
        !           741:         /* Allocate memory to save the data into */
        !           742:         rgBuf = rgqmsgSpy[imsg].rgData = WinAllocMem(hheapSpyHook, cbMPs);
        !           743: 
        !           744:         if (rgBuf != NULL) {
        !           745:             /* Copy the data down, Note: if count is 0 will NOP */
        !           746:             if (cbMP1) {
        !           747:                 CopyStruct((CHAR FAR *)rgqmsgSpy[imsg].qmsg.mp1,
        !           748:                         rgBuf, cbMP1);
        !           749:                 rgBuf += cbMP1;
        !           750:             }
        !           751: 
        !           752:             if (cbMP2) {
        !           753:                 CopyStruct((CHAR FAR *)rgqmsgSpy[imsg].qmsg.mp2,
        !           754:                         rgBuf, cbMP2);
        !           755:             }
        !           756:         }
        !           757: 
        !           758:     } else {
        !           759:         rgqmsgSpy[imsg].rgData = NULL;
        !           760:     }
        !           761: }
        !           762: 
        !           763: /**********************************************************************\
        !           764: * SpyGetNextMessage (lpqmsg, lpBuf, cbBuf, lTimeOut)
        !           765: *
        !           766: * Effect:  Get the next message from the list.
        !           767: *      if timeout != 0 on message processing threads, problems may occur.
        !           768: *      if lpqmsg==NULL, this function acts like a query or wait function.
        !           769: *
        !           770: * Returns:     Whether SpyGetNextMessage succeeds or not.
        !           771: \***********************************************************************/
        !           772: BOOL FAR PASCAL SpyGetNextMessage(lpqmsg, lpBuf, cbBuf, lTimeOut)
        !           773: PQMSGSPY   lpqmsg;      /* Pointer where the user wants the message stored */
        !           774: PSZ        lpBuf;       /* pointer to buffer */
        !           775: SHORT      cbBuf;       /* size of buffer in bytes */
        !           776: LONG    lTimeOut;       /* Timeout value */
        !           777: {
        !           778: 
        !           779:     SHORT       cbMsg;  /* Count of bytes associated with message */
        !           780: 
1.1       root      781:     /* Quick escape hatch */
                    782:     if ((lTimeOut == 0) && (cmsgSpy == 0))
1.1.1.2 ! root      783:         return (FALSE);     /* Don't Wait */
1.1       root      784: 
                    785:     /*
1.1.1.2 ! root      786:      * Now let's possibly wait for a message
1.1       root      787:      */
                    788:     if (cmsgSpy == 0) {
                    789:         if (DosSemWait((HSEM)(PULONG)&spyMsgSem, lTimeOut) != 0)
                    790:             return (FALSE); /* No messages after timeout */
                    791:         if (cmsgSpy == 0)
                    792:             return (FALSE); /* Still no messages, return condition */
                    793:     }
                    794: 
                    795:     /*
                    796:      * If the lpqmsg is NULL, the user is simply asking if there is
1.1.1.2 ! root      797:      * a message and/or waiting for the message, so don't extract
1.1       root      798:      * the message, but simply return the status.
                    799:      */
                    800:     if (lpqmsg != NULL) {
                    801:         if (DosSemRequest((HSEM)(PULONG)&spyhookSem, lTimeOut) == 0) {
1.1.1.2 ! root      802:             *lpqmsg = rgqmsgSpy[imsgRead];   /* Extract the message */
        !           803: 
        !           804:             cbMsg = rgqmsgSpy[imsgRead].cbDataMP1
        !           805:                     + rgqmsgSpy[imsgRead].cbDataMP2;
        !           806: 
        !           807:             if ((cbMsg > 0) && (lpBuf != NULL)) {
        !           808:                 if (cbMsg < cbBuf)
        !           809:                     cbBuf = cbMsg;  /* Number of bytes to copy */
        !           810:                 CopyStruct(rgqmsgSpy[imsgRead].rgData, lpBuf, cbBuf);
        !           811:             }
        !           812: 
        !           813:             if (cbMsg > 0)
        !           814:                 WinFreeMem(hheapSpyHook, rgqmsgSpy[imsgRead].rgData, cbMsg);
        !           815: 
        !           816:             /* Also give the caller any additional information on message */
        !           817: 
        !           818:             imsgRead++;
1.1       root      819:             if (imsgRead == MAXMSGCNT)
                    820:                 imsgRead = 0;  /* Wrap around */
                    821: 
                    822:             /*
                    823:              * Decrement count of messages, if we go to zero, set
                    824:              * the semaphore, so that the next read will suspend until
                    825:              * the next message
                    826:              */
                    827:             cmsgSpy--;
                    828:             if (cmsgSpy == 0)
                    829:                 DosSemSet((HSEM)(PULONG)&spyMsgSem);
                    830: 
                    831:             DosSemClear( (HSEM)(PULONG)&spyhookSem );
                    832:         }
                    833:     }
                    834: 
                    835:     return (TRUE);
                    836: }
                    837: 
1.1.1.2 ! root      838: /***********************************************************************\
1.1       root      839: * VOID PASCAL Init( hmod )
1.1.1.2 ! root      840: * 
        !           841: * Effect:      Saves the Spy module handle
1.1       root      842: \***********************************************************************/
                    843: VOID PASCAL Init( hmod )
                    844: HMODULE hmod;
                    845: {
1.1.1.2 ! root      846:     /* Save the module handle */
1.1       root      847:     hmodSpy = hmod;
                    848: }
                    849: 
1.1.1.2 ! root      850: /***********************************************************************\
        !           851: * UCHAR GMsgEnableAndType (USHORT msg)
1.1       root      852: *
                    853: * Effect:
1.1.1.2 ! root      854: *   Should the message be processed?
1.1       root      855: *
1.1.1.2 ! root      856: *   If the message is out of range 
        !           857: *      or bit is set in message bitmask then return TRUE;
1.1       root      858: \***********************************************************************/
1.1.1.2 ! root      859: UCHAR GMsgEnableAndType(msg)
1.1       root      860: USHORT  msg;
                    861: {
                    862:     if (msg > MAXMSGFILTER)
1.1.1.2 ! root      863:         return ((UCHAR)(fDispMsgsNotInList? MP_ENABLED : 0));
1.1       root      864: 
1.1.1.2 ! root      865:     return (rgMessageFilter[msg]);   /* One byte per message */
1.1       root      866: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.