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

1.1       root        1: /***********************************************************************\
                      2: * spyhook.C - Spy Global input hook interface library.
                      3: *
                      4: * Purpose:  This dynlink is needed because global input hooks must
                      5: *   reside in a DLL. 
                      6: *
                      7: * Created by Microsoft Corp. 1987
                      8: *
                      9: \***********************************************************************/
                     10: #define INCL_PM
                     11: #include <os2.h>
                     12: #include "spyhook.h"
                     13: 
                     14: 
                     15: ULONG spyhookSem = 0L;          /* global semaphore for this module */
                     16: HMODULE hmodSpy;                /* dynlink module handle            */
                     17: SHORT   SpybHooks;             /* Which Hooks do we use             */
                     18: 
                     19: HAB habOwner = (HAB)0;         /* Hook owner's anchor block       */
                     20: HMQ hmqOwner = (HMQ)0;          /* Hook owner's message queue       */
                     21: BOOL fRecording = FALSE;        /* Are we recording now?            */
                     22: 
                     23: /* Define array of window handles that we are going to process */
                     24: BOOL fProcessAllFrames = FALSE; /* Are we processing all frame messages */
                     25: BOOL fProcessAllWindows = FALSE; /* Are we processing all windows */
                     26: HWND rghwndSpy[MAXHWNDS];
                     27: int  chwndSpy = 0;  /* Max windows to spy */
                     28: 
                     29: /* Define message filter array */
                     30: UCHAR rgMessageFilter[MAXMSGFILTERBYTES] = "";
                     31: BOOL  FMsgInMsgList(USHORT);    /* Is message in message list */
                     32: UCHAR         rgBitMasks[8] = {0x01, 0x02, 0x04, 0x08,
                     33:                                0x10, 0x20, 0x40, 0x80 };
                     34: 
                     35: 
                     36: /* Define an array of messages to pass to whomever calls us */
                     37: ULONG spyMsgSem =  0L;          /* global semaphore for this module */
                     38: QMSG  rgqmsgSpy[MAXMSGCNT];     /* Array of messages to process */
                     39: SHORT cmsgSpy = 0;              /* Count of messages yet to be read */
                     40: SHORT imsgWrite = 0;            /* Index to message to write out */
                     41: SHORT imsgRead = 0;             /* Index to message to read */
                     42: 
                     43: 
                     44: 
                     45: 
                     46: 
                     47: /***************************** Exported Function ***********************\
                     48: * BOOL FAR PASCAL SpyInputHook( hab, lpqmsg )
                     49: * HAB hab;
                     50: * PQMSG  lpqmsg;
                     51: *
                     52: * Effect:  This is the global input hook procedure.  Note that hook
                     53: *   procedures can be chained, so we always return FALSE to pass the
                     54: *   message to the next guy in chain.
                     55: *
                     56: * Return value:  FALSE to pass message to next hook procedure.
                     57: \***********************************************************************/
                     58: BOOL FAR PASCAL SpyInputHook( hab, lpqmsg )
                     59: HAB hab;
                     60: PQMSG lpqmsg;
                     61: {
                     62:     /*
                     63:      * First check to see if we are processing any hook messages
                     64:      */
                     65:     if (!fRecording || (cmsgSpy >= MAXMSGCNT))
                     66:         return (FALSE); /* No let the next one have it now */
                     67: 
                     68:     if ((chwndSpy == 0) && !fProcessAllWindows && !fProcessAllFrames)
                     69:         return (FALSE);
                     70: 
                     71:     /*
                     72:      * See if we have any messages to process - Recheck to make sure we
                     73:      * Dont overwrite our queue.
                     74:      */
                     75:     if (DosSemRequest((HSEM)(PULONG)&spyhookSem, 100L) != 0)
                     76:         return (FALSE);
                     77:     if (cmsgSpy < MAXMSGCNT) {
                     78:         if (SpyFWindowInList(lpqmsg->hwnd) && FMsgInMsgList(lpqmsg->msg)) {
                     79:             rgqmsgSpy[imsgWrite++] = *lpqmsg;   /* Save the message */
                     80:             if (imsgWrite == MAXMSGCNT)
                     81:                 imsgWrite = 0;  /* Wrap around */
                     82:             cmsgSpy++;
                     83:             DosSemClear((HSEM)(PULONG)&spyMsgSem);
                     84:         }
                     85:     }
                     86: 
                     87:     DosSemClear( (HSEM)(PULONG)&spyhookSem );
                     88:     return FALSE;   /* Let system take normal action. */
                     89: }
                     90: 
                     91: 
                     92: /***************************** Exported Function ***********************\
                     93: * BOOL FAR PASCAL SpySendMsgHook( hab, lpsmh, fInterTask)
                     94: * HAB hab;
                     95: * PQMSG  lpqmsg;
                     96: *
                     97: * Effect:  This is the global input hook procedure.  Note that hook
                     98: *   procedures can be chained, so we always return FALSE to pass the
                     99: *   message to the next guy in chain.
                    100: *
                    101: * Return value:  FALSE to pass message to next hook procedure.
                    102: \***********************************************************************/
                    103: BOOL FAR PASCAL SpySendMsgHook( hab, lpsmh, fInterTask )
                    104: HAB hab;
                    105: PSMHSTRUCT      lpsmh;
                    106: BOOL            fInterTask;
                    107: {
                    108:     /*
                    109:      * First check to see if we are processing any hook messages
                    110:      */
                    111:     if (!fRecording || (cmsgSpy >= MAXMSGCNT))
                    112:         return (FALSE); /* No let the next one have it now */
                    113: 
                    114:     if ((chwndSpy == 0) && !fProcessAllWindows && !fProcessAllFrames)
                    115:         return (FALSE);
                    116:     /*
                    117:      * See if we have any messages to process
                    118:      */
                    119:     if (DosSemRequest((HSEM)(PULONG)&spyhookSem, 100L) != 0)
                    120:         return (FALSE);
                    121:     /* Make sure no one got in by mistake */
                    122:     if (cmsgSpy < MAXMSGCNT) {
                    123:         if (SpyFWindowInList(lpsmh->hwnd) && FMsgInMsgList(lpsmh->msg)) {
                    124:             /* 
                    125:              * Store out message, must move pieces seperatly
                    126:              */
                    127:             rgqmsgSpy[imsgWrite].hwnd = lpsmh->hwnd;
                    128:             rgqmsgSpy[imsgWrite].msg  = lpsmh->msg;
                    129:             rgqmsgSpy[imsgWrite].mp1  = lpsmh->mp1;
                    130:             rgqmsgSpy[imsgWrite].mp2  = lpsmh->mp2;
                    131:             rgqmsgSpy[imsgWrite].time = (ULONG)-1;  
                    132:             rgqmsgSpy[imsgWrite].ptl.x  = (LONG)fInterTask;  
                    133:             rgqmsgSpy[imsgWrite].ptl.y  = 0;  
                    134: 
                    135:             imsgWrite++;
                    136:             if (imsgWrite == MAXMSGCNT)
                    137:                 imsgWrite = 0;  /* Wrap around */
                    138:             cmsgSpy++;
                    139:             DosSemClear((HSEM)(PULONG)&spyMsgSem);
                    140:         }
                    141:     }
                    142: 
                    143:     DosSemClear( (HSEM)(PULONG)&spyhookSem );
                    144:     return FALSE;   /* Let system take normal action. */
                    145: }
                    146: 
                    147: 
                    148: /*************************** Public Function ***************************\
                    149: * BOOL FAR PASCAL SpyInstallHook( hab, hmq, fSendMessage, bHooks)
                    150: *
                    151: * Effect:  This routine installs a system-wide HK_INPUT hook.  The hab
                    152: *   hmq are remembered for message posting.  Note that we only allow
                    153: *   one input hook to be installed through this routine, but other
                    154: *   apps may call WinSetHook directly.
                    155: *
                    156: * Returns value:  TRUE if hook installed successfully, FALSE otherwise.
                    157: \***********************************************************************/
                    158: BOOL FAR PASCAL SpyInstallHook( hab, hmq, bHooks )
                    159: HAB     hab;
                    160: HMQ     hmq;
                    161: USHORT  bHooks;
                    162: {
                    163:     BOOL fRet;
                    164: 
                    165:     DosSemRequest( (HSEM)(PULONG)&spyhookSem, -1L);
                    166: 
                    167:     /* 
                    168:      * Look at hook index if == HK_INPUT Install a system-wide input hook.
                    169:      * else set system wide SENDMSG hook
                    170:      */         
                    171:     SpybHooks = bHooks;
                    172:     if (SpybHooks & SPYH_INPUT)
                    173:         fRet = WinSetHook( hab, (HMQ)0, HK_INPUT, (PFN)SpyInputHook,
                    174:                    hmodSpy );
                    175: 
                    176:     if (SpybHooks & SPYH_SENDMSG)
                    177:         fRet = WinSetHook( hab, (HMQ)0, HK_SENDMSG, (PFN)SpySendMsgHook,
                    178:                    hmodSpy );
                    179:     if (fRet) {
                    180:         habOwner = hab;
                    181:         hmqOwner = hmq;
                    182:     }
                    183: 
                    184:     DosSemSet((HSEM)(PULONG)&spyMsgSem);    /* Init, no messages avail */
                    185:     DosSemClear( (HSEM)(PULONG)&spyhookSem );
                    186: 
                    187:     return fRet;
                    188: }
                    189: 
                    190: 
                    191: 
                    192: /*************************** Public Function ***************************\
                    193: * BOOL FAR PASCAL SpySetWindowList( chwnd, rghwnd)
                    194: *
                    195: * Effect:  This routine sets the list of window that we are interested
                    196: *   in watching the messages for.
                    197: *
                    198: * Returns value:  TRUE 
                    199: \***********************************************************************/
                    200: BOOL FAR PASCAL SpySetWindowList( chwnd, rghwnd )
                    201: SHORT       chwnd;
                    202: HWND FAR    *rghwnd;
                    203: {
                    204:     SHORT   i;
                    205: 
                    206:     DosSemRequest( (HSEM)(PULONG)&spyhookSem, -1L);
                    207: 
                    208:     chwndSpy = chwnd;
                    209: 
                    210:     for (i=0; i < chwnd; i++) {
                    211:         rghwndSpy[i] = *rghwnd++;
                    212:     }
                    213: 
                    214:     DosSemClear( (HSEM)(PULONG)&spyhookSem );
                    215: 
                    216:     return(TRUE);
                    217: }
                    218: 
                    219: 
                    220: /*************************** Public Function ***************************\
                    221: * BOOL FAR PASCAL SpyGetWindowList( chwnd, rghwnd)
                    222: *
                    223: * Effect:  This routine sets the list of window that we are interested
                    224: *   in watching the messages for.
                    225: *
                    226: * Returns value:  TRUE 
                    227: \***********************************************************************/
                    228: SHORT FAR PASCAL SpyGetWindowList( chwnd, rghwnd )
                    229: SHORT       chwnd;
                    230: HWND FAR    *rghwnd;
                    231: {
                    232:     SHORT   i;
                    233: 
                    234:     DosSemRequest( (HSEM)(PULONG)&spyhookSem, -1L);
                    235: 
                    236:        if (chwnd > chwndSpy)
                    237:                chwnd = chwndSpy;
                    238: 
                    239:     for (i=0; i < chwnd; i++) {
                    240:         *rghwnd++ = rghwndSpy[i];
                    241:     }
                    242: 
                    243:     DosSemClear( (HSEM)(PULONG)&spyhookSem );
                    244: 
                    245:     return(chwnd);
                    246: }
                    247: 
                    248: 
                    249: /*************************** Public Function ***************************\
                    250: * BOOL FAR PASCAL SpySetMessageList( chwnd, rghwnd)
                    251: *
                    252: * Effect:  This routine sets the list of window that we are interested
                    253: *   in watching the messages for.
                    254: *
                    255: * Returns value:  TRUE 
                    256: \***********************************************************************/
                    257: BOOL FAR PASCAL SpySetMessageList(prgNewMsgFilter)
                    258: UCHAR FAR           *prgNewMsgFilter;
                    259: {
                    260:     SHORT           i;
                    261:     unsigned char   *prgb;
                    262: 
                    263:     DosSemRequest( (HSEM)(PULONG)&spyhookSem, -1L);
                    264: 
                    265:     prgb = rgMessageFilter;
                    266: 
                    267:     for (i=0; i < MAXMSGFILTERBYTES; i++) {
                    268:         *prgb++ = *prgNewMsgFilter++;
                    269:     }
                    270: 
                    271:     DosSemClear( (HSEM)(PULONG)&spyhookSem );
                    272: 
                    273:     return(TRUE);
                    274: }
                    275: 
                    276: 
                    277: /*************************** Public Function ***************************\
                    278: * BOOL FAR PASCAL SpyFWindowInList (hwnd)
                    279: *
                    280: * Effect:  This function checks our current list of windows, and returns
                    281: *          TRUE if the window is in the list, else returns FALSE.
                    282: * Returns value:  TRUE if window is in list.  Also if We are in the special
                    283: *           state we will pass through all frame windows.
                    284: \***********************************************************************/
                    285: BOOL FAR PASCAL SpyFWindowInList (hwnd)
                    286: register HWND  hwnd;
                    287: {
                    288:     register int    i;
                    289:     char            szClassName[10];    /* Class name of window */
                    290:     CLASSINFO       classinfo;          /* Information about class */
                    291: 
                    292:     if (fProcessAllWindows)
                    293:         return (TRUE);      /* All windows pass through */
                    294: 
                    295:     for (i=0; i< chwndSpy; i++) {
                    296:         if (hwnd == rghwndSpy[i])
                    297:             return (TRUE); 
                    298:     }
                    299: 
                    300:     if (fProcessAllFrames) {
                    301:         /* See if frame class */
                    302:         if (hwnd == NULL)
                    303:             return (TRUE);      /* pass queue messages through */
                    304:         WinQueryClassName(hwnd, sizeof(szClassName),
                    305:             (PSZ)szClassName);
                    306:         WinQueryClassInfo((HAB)NULL, (PSZ)szClassName,
                    307:             &classinfo);
                    308:         if (classinfo.flClassStyle & CS_FRAME)
                    309:             return (TRUE);
                    310:     }
                    311: 
                    312:     return (FALSE);
                    313: }
                    314: 
                    315: 
                    316: /*************************** Public Function ***************************\
                    317: * BOOL FAR PASCAL SpyReleaseHook(fZeroQueue)
                    318: *
                    319: * Effect:  This routine releases the input hook, if it is installed.
                    320: *
                    321: * Returns value: TRUE if hook is released, FALSE otherwise.
                    322: \***********************************************************************/
                    323: BOOL FAR PASCAL SpyReleaseHook(fZeroQueue)
                    324: BOOL    fZeroQueue;
                    325: {
                    326:     BOOL fRet;
                    327: 
                    328:     DosSemRequest ( (HSEM)(PULONG)&spyhookSem, -1L );
                    329: 
                    330:     if ( habOwner ) {
                    331:         if (SpybHooks & SPYH_INPUT) 
                    332:                fRet = WinReleaseHook( habOwner, (HMQ)0, HK_INPUT,
                    333:                    (PFN)SpyInputHook, hmodSpy );
                    334: 
                    335:         if (SpybHooks & SPYH_SENDMSG) 
                    336:                fRet = WinReleaseHook( habOwner, (HMQ)0, HK_SENDMSG,
                    337:                    (PFN)SpySendMsgHook, hmodSpy );
                    338:            if ( fRet ) {
                    339:                 habOwner = (HAB)0;
                    340:                 hmqOwner = (HMQ)0;
                    341:         }
                    342:     }
                    343: 
                    344:     /*
                    345:      * When the hook is freed, we want to clear message count out,
                    346:      * make sure any process waiting will abort
                    347:      * Only do this if the Zeroqueu flag was passed
                    348:      */
                    349:     if (fZeroQueue) {
                    350:         cmsgSpy = 0;  
                    351:         imsgWrite = 0;
                    352:         imsgRead = 0; 
                    353:         chwndSpy = 0;           /* Max windows to spy */
                    354:         fRecording = FALSE;     /* Set recording to off */
                    355:         DosSemClear((HSEM)(PULONG)&spyMsgSem);    /* Free any process */
                    356:     }
                    357:     DosSemClear((HSEM)(PULONG)&spyhookSem);
                    358: 
                    359:     return fRet;
                    360: }
                    361: 
                    362: 
                    363: /*************************** Public Function ***************************\
                    364: * BOOL FAR PASCAL SpyHookOnOrOff( fOn)
                    365: *
                    366: * Effect:  This routine allows the application to turn the hook
                    367: *   processing on or off.
                    368: *
                    369: * Returns value:  
                    370: \***********************************************************************/
                    371: BOOL FAR PASCAL SpyHookOnOrOff(fOn)
                    372: BOOL fOn;
                    373: {
                    374:     DosSemRequest ( (HSEM)(PULONG)&spyhookSem, -1L);
                    375: 
                    376:     fRecording = fOn;
                    377: 
                    378:     DosSemClear( (HSEM)(PULONG)&spyhookSem );
                    379:     return (TRUE);
                    380: }
                    381: 
                    382: 
                    383: 
                    384: /*************************** Public Function ***************************\
                    385: * BOOL FAR PASCAL SpySetAllFrameOpt(fAllFrames)
                    386: *
                    387: * Effect:  Special state if TRUE will cause the window filter to pass
                    388: *       all frame windows through.  This is usefull when debuging
                    389: *       interactions between frame windows, when the windows are
                    390: *       net yet created.
                    391: *
                    392: * Returns value:  
                    393: \***********************************************************************/
                    394: BOOL FAR PASCAL SpySetAllFrameOpt(fAllFrames)
                    395: BOOL fAllFrames;
                    396: {
                    397:     fProcessAllFrames = fAllFrames;
                    398:     return (TRUE);
                    399: }
                    400: /*************************** Public Function ***************************\
                    401: * BOOL FAR PASCAL SpySetAllWindowOpt(fAllWindows)
                    402: *
                    403: * Effect:  Special state if TRUE will cause the window filter to pass
                    404: *       all windows through.  This is usefull when debuging
                    405: *       interactions between all of the windows
                    406: *
                    407: * Returns value:  
                    408: \***********************************************************************/
                    409: BOOL FAR PASCAL SpySetAllWindowOpt(fAllWindows)
                    410: BOOL fAllWindows;
                    411: {
                    412:     fProcessAllWindows = fAllWindows;
                    413:     return (TRUE);
                    414: }
                    415: 
                    416: /*************************** Public Function **************************\
                    417: * SpyGetNextMessage (lpqmsg, lTimeOut)
                    418: *
                    419: * Effect:
                    420: *   Get the next message from the list - if timeout != 0 an message
                    421: *   processing threads, you may have problems, - If lpqmsg==NULL, this
                    422: *   function acts like a query or wait function.
                    423: *
                    424: * Returns value:
                    425: \***********************************************************************/
                    426: BOOL FAR PASCAL SpyGetNextMessage(lpqmsg, lTimeOut)
                    427: PQMSG   lpqmsg;
                    428: LONG    lTimeOut;
                    429: {
                    430:     /* Quick escape hatch */
                    431:     if ((lTimeOut == 0) && (cmsgSpy == 0))
                    432:         return (FALSE);     /* Dont Wait */
                    433: 
                    434:     /*
                    435:      * Now lets possibly wait for a message
                    436:      */
                    437:     if (cmsgSpy == 0) {
                    438:         if (DosSemWait((HSEM)(PULONG)&spyMsgSem, lTimeOut) != 0)
                    439:             return (FALSE); /* No messages after timeout */
                    440:         if (cmsgSpy == 0)
                    441:             return (FALSE); /* Still no messages, return condition */
                    442:     }
                    443: 
                    444:     /*
                    445:      * If the lpqmsg is NULL, the user is simply asking if there is
                    446:      * a message and/or waiting for the message, so dont extract
                    447:      * the message, but simply return the status.
                    448:      */
                    449:     if (lpqmsg != NULL) {
                    450:         if (DosSemRequest((HSEM)(PULONG)&spyhookSem, lTimeOut) == 0) {
                    451:             *lpqmsg = rgqmsgSpy[imsgRead++];   /* Extract the message */
                    452:             if (imsgRead == MAXMSGCNT)
                    453:                 imsgRead = 0;  /* Wrap around */
                    454: 
                    455:             /*
                    456:              * Decrement count of messages, if we go to zero, set
                    457:              * the semaphore, so that the next read will suspend until
                    458:              * the next message
                    459:              */
                    460:             cmsgSpy--;
                    461:             if (cmsgSpy == 0)
                    462:                 DosSemSet((HSEM)(PULONG)&spyMsgSem);
                    463: 
                    464:             DosSemClear( (HSEM)(PULONG)&spyhookSem );
                    465:         }
                    466:     }
                    467: 
                    468:     return (TRUE);
                    469: }
                    470: 
                    471: 
                    472: 
                    473: 
                    474: /*************************** Private Function **************************\
                    475: * VOID PASCAL Init( hmod )
                    476: *
                    477: * Effect:
                    478: *
                    479: *
                    480: * Returns value:
                    481: \***********************************************************************/
                    482: VOID PASCAL Init( hmod )
                    483: HMODULE hmod;
                    484: {
                    485:     register INT i;
                    486: 
                    487:     /* Save the module handle. */
                    488:     hmodSpy = hmod;
                    489: }
                    490: 
                    491: 
                    492: /*************************** Private Function **************************\
                    493: * Bool FMsgInMsgList (USHORT msg)
                    494: *
                    495: * Effect:
                    496: *   Should the message be processed.  If the message is out of range,
                    497: *   or bit is set in message bitmask return TRUE
                    498: *
                    499: * Returns value:
                    500: *   BOOL
                    501: \***********************************************************************/
                    502: BOOL FMsgInMsgList(msg)
                    503: USHORT  msg;
                    504: {
                    505:     if (msg > MAXMSGFILTER)
                    506:         return (TRUE);
                    507: 
                    508:     if (rgMessageFilter[msg >> 3] & rgBitMasks[msg & 0x07])
                    509:         return (TRUE);
                    510:     return (FALSE);
                    511: }

unix.superglobalmegacorp.com

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