Annotation of os232sdk/toolkt20/c/samples/spy/spyhk32.c, revision 1.1.1.1

1.1       root        1: /***********************************************************************\
                      2: * spyhook.C - Spy Global input hook interface library.
                      3: *
                      4: * Created: Microsoft, IBM Corporation 1990
                      5: *
                      6: *      DISCLAIMER OF WARRANTIES.  The following [enclosed] code is 
                      7: *      sample code created by Microsoft Corporation and/or IBM 
                      8: *      Corporation. This sample code is not part of any standard 
                      9: *      Microsoft or IBM product and is provided to you solely for 
                     10: *      the purpose of assisting you in the development of your 
                     11: *      applications.  The code is provided "AS IS", without 
                     12: *      warranty of any kind.  Neither Microsoft nor IBM shall be 
                     13: *      liable for any damages arising out of your use of the sample 
                     14: *      code, even if they have been advised of the possibility of 
                     15: *      such damages.
                     16: *
                     17: * Purpose:  This dynlink is needed because global input hooks must
                     18: *   reside in a DLL.
                     19: *
                     20: \***********************************************************************/
                     21: #define INCL_PM
                     22: #define INCL_DOSPROCESS
                     23: #define INCL_DOSMODULEMGR
                     24: #define INCL_DOSSEMAPHORES
                     25: #define INCL_ERRORS
                     26: #include <os2.h>
                     27: #include "spyhk32.h"
                     28: 
                     29: // Needed to make a dll link properly
                     30: int _acrtused = 0;
                     31: 
                     32: HMTX  hmtxSpyHook;              /* global semaphore for this module */
                     33: HEV   hevSpyMsg;                /* global semaphore for this module */
                     34: 
                     35: HMODULE hmodSpy;                /* dynlink module handle            */
                     36: SHORT    SpybHooks;             /* Whichs Hook do we use             */
                     37: 
                     38: HAB habOwner = (HAB)0;          /* Hook owner's anchore block       */
                     39: HMQ hmqOwner = (HMQ)0;          /* Hook owner's message queue       */
                     40: BOOL fRecording = FALSE;        /* Are we recording now?            */
                     41: BOOL fAnythingToWatch = FALSE;  /* Is there anything to watch       */
                     42: BOOL fDispMsgsNotInList = TRUE; /* Disp msgs not in list?           */
                     43: 
                     44: /* Define array of window handles that we are going to process */
                     45: BOOL fInitialized = FALSE;
                     46: BOOL fProcessAllFrames = FALSE; /* Are we processing all frame messages */
                     47: BOOL fProcessAllWindows = FALSE;/* Are we processing all windows */
                     48: HWND *pahwndSpy = NULL;         /* Array of hwnds to spy on, no max here */
                     49: int  chwndSpy = 0;  /* Max windows to spy */
                     50: 
                     51: /* Define array of HMQ's to spy on */
                     52: HMQ *pahmqSpy = NULL;           /* HMQ list to spy on */
                     53: int chmqSpy = 0;                /* Count of hmqs we are spying on */
                     54: 
                     55: 
                     56: /* Define message filter array */
                     57: UCHAR rgMessageFilter[MAXMSGFILTERBYTES] = "";
                     58: UCHAR  GMsgEnableAndType(USHORT);       /* Is message in message list */
                     59: VOID   GrabMsgDataWords(SHORT, UCHAR);  /* Get extra words for message */
                     60: BOOL   CopyStruct(UCHAR *pbSrc, UCHAR *pbDst, SHORT cb);  /* Copy bytes */
                     61: void    DebugBreak(void);
                     62: 
                     63: /* Define an array of messages to pass to whomever calls us */
                     64: 
                     65: QMSGSPY  rgqmsgSpy[MAXMSGCNT];     /* Array of messages to process */
                     66: SHORT cmsgSpy = 0;              /* Count of messages yet to be read */
                     67: SHORT imsgWrite = 0;            /* Index to message to write out */
                     68: SHORT imsgRead = 0;             /* Index to message to read */
                     69: 
                     70: /* Use the Dos Sub allocate functions to make sure to use shared memory */
                     71: #define HEAPSIZE 16384 /* 16K should be plenty? */
                     72: PVOID pheapSpyHook;      /* Heap to use for Spy Hook DLL */
                     73: 
                     74: PBYTE AllocMem(ULONG cb);
                     75: VOID  FreeMem(PBYTE pMem, ULONG cb);
                     76: BOOL EnterSem(ULONG ulWait);
                     77: BOOL LeaveSem(VOID);
                     78: BOOL SignalEvent(VOID);
                     79: 
                     80: 
                     81: 
                     82: SHORT acbMPTypes[MP_MASK+1] = { /* Number of desired bytes to extract */
                     83:     0,                          /* Normal fields, no pointers */
                     84:     sizeof(SWP),                /* MPT_SWP */
                     85:     sizeof(RECTL),              /* MPT_RECTL */
                     86:     0,                          /* MPT_WNDPRMS we dont process yet */
                     87:     sizeof(QMSG)                /* MPT_QMSG */
                     88: };
                     89: 
                     90: 
                     91: /* Information for geting selector information in diffent PID context */
                     92: PIT pit = {0xffff, 0, 0L, NULL, 0};
                     93: USHORT  selectorLNSpy = 0;      /* Which Selector */
                     94: VOID SpyCheckPIDForIntercept(VOID);
                     95: ULONG EXPENTRY Init(ULONG hPDLL, HMODULE hmod);
                     96: 
                     97: /***********************************************************************\
                     98: * VOID Init( hmod )
                     99: * 
                    100: * Effect:      Saves the Spy module handle
                    101: \***********************************************************************/
                    102: ULONG EXPENTRY Init(hPDLL, hmod)
                    103: ULONG  hPDLL;
                    104: HMODULE        hmod;
                    105: {
                    106:     /* Save the module handle */
                    107:     hmodSpy = hmod;
                    108: 
                    109:     return (ULONG)hmodSpy;
                    110: 
                    111:     /* Unreferenced formal parameters referenced here to prevent compiler
                    112:         warning */
                    113:     hPDLL;
                    114: }
                    115: 
                    116: 
                    117: 
                    118: 
                    119: /***************************** Exported Function ***********************\
                    120: * BOOL EXPENTRY SpyInputHook( hab, lpqmsg, fs)
                    121: * HAB hab;
                    122: * PQMSG  lpqmsg;
                    123: * USHORT    fs;
                    124: *
                    125: * Effect:  This is the global input hook procedure.  Note that hook
                    126: *   procedures can be chained, so we always return FALSE to pass the
                    127: *   message to the next guy in chain.
                    128: *
                    129: * Return value:  FALSE to pass message to next hook procedure.
                    130: \***********************************************************************/
                    131: BOOL EXPENTRY SpyInputHook( hab, lpqmsg, fs )
                    132: HAB hab;
                    133: PQMSG lpqmsg;
                    134: USHORT  fs;
                    135: {
                    136:     UCHAR       bMPType;
                    137: 
                    138:     /*
                    139:      * Check first to see if we are looking for a process symbols
                    140:      */
                    141:     if (pit.pid != 0xffff)
                    142:         SpyCheckPIDForIntercept();
                    143: 
                    144:     /*
                    145:      * First check to see if we are processing any hook messages
                    146:      */
                    147:     if (!fRecording || !fAnythingToWatch || (cmsgSpy >= MAXMSGCNT))
                    148:         return (FALSE); /* No let the next one have it now */
                    149: 
                    150:     /*
                    151:      * See if we have any messages to process - Recheck to make sure we
                    152:      * Dont overwrite our queue.
                    153:      */
                    154:     if (!EnterSem(100L)) {
                    155:         DebugBreak();
                    156:         return (FALSE);
                    157:     }
                    158:     if (cmsgSpy < MAXMSGCNT) {
                    159:         if (SpyFWindowInList(lpqmsg->hwnd, FALSE) &&
                    160:                 (bMPType = GMsgEnableAndType(lpqmsg->msg))) {
                    161:             rgqmsgSpy[imsgWrite].fs = fs;       /* Save the flags */
                    162:             rgqmsgSpy[imsgWrite].qmsg = *lpqmsg;   /* Save the message */
                    163: 
                    164:             GrabMsgDataWords(imsgWrite, bMPType);
                    165:             imsgWrite++;
                    166: 
                    167:             if (imsgWrite == MAXMSGCNT)
                    168:                 imsgWrite = 0;  /* Wrap around */
                    169:             cmsgSpy++;
                    170:             SignalEvent();
                    171:         }
                    172:     }
                    173: 
                    174:     LeaveSem();
                    175:     return FALSE;   /* Let system take normal action. */
                    176: 
                    177:     /* Unreferenced formal parameters referenced here to prevent compiler
                    178:         warning */
                    179:     hab;
                    180: 
                    181: }
                    182: 
                    183: 
                    184: /***************************** Exported Function ***********************\
                    185: * BOOL EXPENTRY SpySendMsgHook( hab, lpsmh, fInterTask)
                    186: * HAB hab;
                    187: * PQMSG  lpqmsg;
                    188: *
                    189: * Effect:  This is the global input hook procedure.  Note that hook
                    190: *   procedures can be chained, so we always return FALSE to pass the
                    191: *   message to the next guy in chain.
                    192: *
                    193: * Return value:  FALSE to pass message to next hook procedure.
                    194: \***********************************************************************/
                    195: BOOL EXPENTRY SpySendMsgHook( hab, lpsmh, fInterTask )
                    196: HAB hab;
                    197: PSMHSTRUCT      lpsmh;
                    198: BOOL            fInterTask;
                    199: {
                    200:     UCHAR           bMPType;
                    201:     PPIB            ppib;
                    202:     PTIB            ptib;
                    203: 
                    204:     /*
                    205:      * Check first to see if we are looking for a process symbols
                    206:      */
                    207:     if (pit.pid != 0xffff)
                    208:         SpyCheckPIDForIntercept();
                    209: 
                    210:     /*
                    211:      * First check to see if we are processing any hook messages
                    212:      */
                    213:     if (!fRecording || !fAnythingToWatch || (cmsgSpy >= MAXMSGCNT))
                    214:         return (FALSE); /* No let the next one have it now */
                    215: 
                    216:     /*
                    217:      * See if we have any messages to process
                    218:      */
                    219:     if (!EnterSem(100L)) {
                    220:         DebugBreak();
                    221:         return (FALSE);
                    222:     }
                    223:     /* Make sure no one got in by mistake */
                    224:     if (cmsgSpy < MAXMSGCNT) {
                    225:         if (SpyFWindowInList(lpsmh->hwnd, FALSE) &&
                    226:                 (bMPType = GMsgEnableAndType(lpsmh->msg))) {
                    227:             /*
                    228:              * Store out message, must move pieces seperatly
                    229:              */
                    230:             rgqmsgSpy[imsgWrite].fs = fInterTask;
                    231:             rgqmsgSpy[imsgWrite].qmsg.hwnd = lpsmh->hwnd;
                    232:             rgqmsgSpy[imsgWrite].qmsg.msg  = lpsmh->msg;
                    233:             rgqmsgSpy[imsgWrite].qmsg.mp1  = lpsmh->mp1;
                    234:             rgqmsgSpy[imsgWrite].qmsg.mp2  = lpsmh->mp2;
                    235:             rgqmsgSpy[imsgWrite].qmsg.time = (ULONG)-1;
                    236:             rgqmsgSpy[imsgWrite].qmsg.ptl.x  = 0;
                    237:             rgqmsgSpy[imsgWrite].qmsg.ptl.y  = 0;
                    238: 
                    239:             GrabMsgDataWords(imsgWrite, bMPType);
                    240: 
                    241:             /* Now get the PID/TID info, and do the stack backtrace */
                    242:             DosGetThreadInfo(&ptib, &ppib);
                    243:             rgqmsgSpy[imsgWrite].pidSend = ppib->pib_ulpid;
                    244:             rgqmsgSpy[imsgWrite].tidSend = ptib->tib_ultid;
                    245: 
                    246:             imsgWrite++;
                    247:             if (imsgWrite == MAXMSGCNT)
                    248:                 imsgWrite = 0;  /* Wrap around */
                    249:             cmsgSpy++;
                    250:             SignalEvent();
                    251:         }
                    252:     }
                    253: 
                    254:     LeaveSem();
                    255:     return FALSE;   /* Let system take normal action. */
                    256: 
                    257:     /* Unreferenced formal parameters referenced here to prevent compiler
                    258:         warning */
                    259:     hab;
                    260: 
                    261: }
                    262: 
                    263: 
                    264: /*************************** Public Function ***************************\
                    265: * BOOL EXPENTRY SpyInstallHook( hab, hmq, fSendMessage, bHooks)
                    266: *
                    267: * Effect:  This routine installs a system-wide HK_INPUT hook.  The hab
                    268: *   hmq are remembered for message posting.  Note that we only allow
                    269: *   one input hook to be installed through this routine, but other
                    270: *   apps may call WinSetHook directly.
                    271: *
                    272: * Returns value:  TRUE if hook installed successfully, FALSE otherwise.
                    273: \***********************************************************************/
                    274: BOOL EXPENTRY SpyInstallHook( hab, hmq, bHooks )
                    275: HAB     hab;
                    276: HMQ     hmq;
                    277: USHORT  bHooks;
                    278: {
                    279:     BOOL fRet;
                    280:     ULONG   ulPostCt;
                    281: 
                    282:     EnterSem(-1L);
                    283: 
                    284: 
                    285:     /*
                    286:      * Look at hook index if == HK_INPUT Install a system-wide input hook.
                    287:      * else set system wide SENDMSG hook
                    288:      */
                    289:     SpybHooks = bHooks;
                    290:     if (SpybHooks & SPYH_INPUT)
                    291:         fRet = WinSetHook( hab, (HMQ)0, HK_INPUT, (PFN)SpyInputHook,
                    292:                     hmodSpy );
                    293: 
                    294:     if (SpybHooks & SPYH_SENDMSG)
                    295:         fRet = WinSetHook( hab, (HMQ)0, HK_SENDMSG, (PFN)SpySendMsgHook,
                    296:                     hmodSpy );
                    297:     if (fRet) {
                    298:         habOwner = hab;
                    299:         hmqOwner = hmq;
                    300:     }
                    301: 
                    302:     DosResetEventSem(hevSpyMsg, &ulPostCt);    /* Init, no messages avail */
                    303:     LeaveSem();
                    304: 
                    305:     return fRet;
                    306: }
                    307: 
                    308: 
                    309: 
                    310: /*************************** Public Function ***************************\
                    311: * BOOL EXPENTRY SpySetWindowList( chwnd, rghwnd)
                    312: *
                    313: * Effect:  This routine sets the list of window that we are interested
                    314: *   in watching the messages for.
                    315: *
                    316: * Returns value:  TRUE
                    317: \***********************************************************************/
                    318: BOOL EXPENTRY SpySetWindowList( chwnd, rghwnd )
                    319: SHORT       chwnd;
                    320: HWND    *rghwnd;
                    321: {
                    322:     SHORT   i;
                    323:     HWND    *phwndT;
                    324: 
                    325:     EnterSem(-1L);
                    326: 
                    327:     if (pahwndSpy) {
                    328:         FreeMem((char *)pahwndSpy, sizeof(HWND) * chwndSpy);
                    329:         pahwndSpy = NULL;
                    330:     }
                    331: 
                    332: 
                    333:     chwndSpy = chwnd;
                    334: 
                    335:     if (chwndSpy > 0 ) {
                    336: 
                    337:         phwndT = pahwndSpy = (HWND *)AllocMem(sizeof(HWND) * chwndSpy);
                    338: 
                    339:         if (phwndT != NULL) {
                    340:             for (i=0; i < chwnd; i++) {
                    341:                 *phwndT++ = *rghwnd++;
                    342:             }
                    343:         } else
                    344:             chwndSpy = 0;
                    345:     }
                    346: 
                    347:     fAnythingToWatch = (chwndSpy > 0) || (chmqSpy > 0) ||
                    348:             fProcessAllWindows || fProcessAllFrames;
                    349: 
                    350:     LeaveSem();
                    351:     return(TRUE);
                    352: }
                    353: 
                    354: 
                    355: /*************************** Public Function ***************************\
                    356: * BOOL EXPENTRY SpyGetWindowList( chwnd, rghwnd)
                    357: *
                    358: * Effect:  This routine sets the list of window that we are interested
                    359: *   in watching the messages for.
                    360: *
                    361: * Returns value:  TRUE
                    362: \***********************************************************************/
                    363: SHORT EXPENTRY SpyGetWindowList( chwnd, rghwnd )
                    364: SHORT       chwnd;
                    365: HWND    *rghwnd;
                    366: {
                    367:     SHORT   i;
                    368:     HWND    *phwndT;
                    369: 
                    370:     EnterSem(-1L);
                    371: 
                    372:     if (chwnd > chwndSpy)
                    373:             chwnd = chwndSpy;
                    374: 
                    375:     phwndT = pahwndSpy;
                    376:     for (i=0; i < chwnd; i++) {
                    377:         *rghwnd++ = *phwndT++;
                    378:     }
                    379: 
                    380:     LeaveSem();
                    381: 
                    382:     return(chwnd);
                    383: }
                    384: 
                    385: 
                    386: 
                    387: 
                    388: /*************************** Public Function ***************************\
                    389: * BOOL EXPENTRY SpySetQueueList( chmq, rghmq)
                    390: *
                    391: * Effect:  This routine sets the list of Queue that we are interested
                    392: *   in watching the messages for.
                    393: *
                    394: * Returns value:  TRUE
                    395: \***********************************************************************/
                    396: BOOL EXPENTRY SpySetQueueList( chmq, rghmq )
                    397: SHORT       chmq;
                    398: HMQ    *rghmq;
                    399: {
                    400:     SHORT   i;
                    401:     HMQ     *phmqT;
                    402: 
                    403:     EnterSem(-1L);
                    404: 
                    405:     /*
                    406:      * If we previously had a list of HMQs to spy on, free the old list
                    407:      * now
                    408:      */
                    409:     if (pahmqSpy != NULL) {
                    410:         FreeMem((char *)pahmqSpy, sizeof(HMQ) * chmqSpy);
                    411:         pahmqSpy = NULL;
                    412:     }
                    413: 
                    414:     chmqSpy = chmq;
                    415: 
                    416:     if (chmqSpy > 0) {
                    417:         phmqT = pahmqSpy = (HMQ *)AllocMem(sizeof(HMQ) * chmqSpy);
                    418: 
                    419:         if (phmqT != NULL) {
                    420:             for (i=0; i < chmq; i++) {
                    421:                 *phmqT++ = *rghmq++;
                    422:             }
                    423:         } else
                    424:             chmqSpy = 0;
                    425:     }
                    426: 
                    427:     fAnythingToWatch = (chwndSpy > 0) || (chmqSpy > 0) ||
                    428:             fProcessAllWindows || fProcessAllFrames;
                    429:     LeaveSem();
                    430: 
                    431:     return(TRUE);
                    432: }
                    433: 
                    434: 
                    435: /*************************** Public Function ***************************\
                    436: * BOOL EXPENTRY SpyGetQueueList( chmq, rghmq)
                    437: *
                    438: * Effect:  This routine sets the list of Queue that we are interested
                    439: *   in watching the messages for.
                    440: *
                    441: * Returns value:  TRUE
                    442: \***********************************************************************/
                    443: SHORT EXPENTRY SpyGetQueueList( chmq, rghmq )
                    444: SHORT       chmq;
                    445: HMQ    *rghmq;
                    446: {
                    447:     SHORT   i;
                    448:     HMQ     *phmqT;
                    449: 
                    450:     EnterSem(-1L);
                    451: 
                    452:     if (chmq > chmqSpy)
                    453:         chmq = chmqSpy;
                    454: 
                    455:     phmqT = pahmqSpy;
                    456: 
                    457:     for (i=0; i < chmq; i++) {
                    458:         *rghmq++ = *phmqT++;
                    459:     }
                    460: 
                    461:     LeaveSem();
                    462: 
                    463:     return(chmq);
                    464: }
                    465: 
                    466: 
                    467: /*************************** Public Function ***************************\
                    468: * BOOL EXPENTRY SpySetMessageList(UCHAR *prgNewMsgFilter,
                    469: *                   BOOL fNewDispMsgsNotInList)
                    470: *
                    471: * Effect:  This routine sets the list of window that we are interested
                    472: *   in watching the messages for.
                    473: *
                    474: * Returns value:  TRUE
                    475: \***********************************************************************/
                    476: BOOL EXPENTRY SpySetMessageList(prgNewMsgFilter, fNewDispMsgsNotInList)
                    477: UCHAR           *prgNewMsgFilter;
                    478: BOOL                fNewDispMsgsNotInList;
                    479: {
                    480:     SHORT           i;
                    481:     unsigned char   *prgb;
                    482: 
                    483:     EnterSem(-1L);
                    484: 
                    485:     prgb = rgMessageFilter;
                    486: 
                    487: 
                    488:     fDispMsgsNotInList = fNewDispMsgsNotInList;
                    489: 
                    490:     for (i=0; i < MAXMSGFILTERBYTES; i++) {
                    491:         *prgb++ = *prgNewMsgFilter++;
                    492:     }
                    493: 
                    494:     LeaveSem();
                    495: 
                    496:     return(TRUE);
                    497: }
                    498: 
                    499: 
                    500: /*************************** Public Function ***************************\
                    501: * BOOL EXPENTRY SpyFWindowInList (hwnd, fInWindowListOnly)
                    502: *
                    503: * Effect:  This function checks our current list of windows, and returns
                    504: *          TRUE if the window is in the list, else returns FALSE.
                    505: * Returns value:  TRUE if window is in list.  Also if We are in the special
                    506: *           state we will pass through all frame windows.
                    507: \***********************************************************************/
                    508: BOOL EXPENTRY SpyFWindowInList (hwnd, fInWindowListOnly)
                    509: register HWND  hwnd;
                    510: BOOL            fInWindowListOnly;
                    511: {
                    512:     register int    i;
                    513:     char            szClassName[10];    /* Class name of window */
                    514:     CLASSINFO       classinfo;          /* Information about class */
                    515:     HMQ             hmqWindow;          /* HMQ of window        */
                    516:     HMQ             *phmqT;             /* Temporary pointer in hmq list */
                    517:     HWND            *phwndT;            /* Temporary pointer to HWND list */
                    518:     PPIB            ppib;
                    519:     PTIB            ptib;
                    520:     MQINFO          mqinfo;             /* Queue info */
                    521: 
                    522: 
                    523: 
                    524:     phwndT = pahwndSpy;
                    525:     for (i=0; i < chwndSpy; i++) {
                    526:         if (hwnd == *phwndT++)
                    527:             return (TRUE);
                    528:     }
                    529: 
                    530:     /* See if we are restricting to only windows in list */
                    531:     if (fInWindowListOnly)
                    532:         return (FALSE);
                    533: 
                    534:     if (fProcessAllWindows)
                    535:         return (TRUE);      /* All windows pass through */
                    536: 
                    537:     /*
                    538:      * See if we are watching any message queues
                    539:      */
                    540:     if (phmqT = pahmqSpy) {
                    541:         if (hwnd != NULL) {
                    542:             /*
                    543:              * Sent to specific window First see if the user has specified
                    544:              * that the want all messages that are sent to this message
                    545:              * queue
                    546:              */
                    547:             hmqWindow = (HMQ)WinQueryWindowULong(hwnd, QWL_HMQ);
                    548:             for (i=0; i < chmqSpy; i++) {
                    549:                 if (*phmqT++ == hmqWindow)
                    550:                     return (TRUE);
                    551:             }
                    552:         } else {
                    553:             // For NULL window handle, see if the current process has HMQ
                    554:             /*
                    555:              * Null Window handle, so instead we need to go through the
                    556:              * list of queues we are watching and see if their PID and TID
                    557:              * matches our current thread.
                    558:              */
                    559:             DosGetThreadInfo(&ptib, &ppib);
                    560:             for (i=0; i < chmqSpy; i++) {
                    561:                 if (WinQueryQueueInfo(*phmqT, &mqinfo, sizeof(mqinfo))) {
                    562:                     if ((mqinfo.pid == ppib->pib_ulpid) &&
                    563:                             (mqinfo.tid == ptib->tib_ultid))
                    564:                         return (TRUE);      // Yes we want this queue!
                    565: 
                    566:                 }
                    567:                 phmqT++;
                    568:             }
                    569:         }
                    570:     }
                    571: 
                    572:     if (fProcessAllFrames) {
                    573:         /* See if frame class */
                    574:         if (hwnd == NULL)
                    575:             return (TRUE);      /* pass queue messages through */
                    576:         WinQueryClassName(hwnd, sizeof(szClassName),
                    577:             (PSZ)szClassName);
                    578:         WinQueryClassInfo((HAB)NULL, (PSZ)szClassName,
                    579:             &classinfo);
                    580:         if (classinfo.flClassStyle & CS_FRAME)
                    581:             return (TRUE);
                    582:     }
                    583: 
                    584:     return (FALSE);
                    585: }
                    586: 
                    587: 
                    588: /*************************** Public Function ***************************\
                    589: * BOOL EXPENTRY SpyReleaseHook(fZeroQueue)
                    590: *
                    591: * Effect:  This routine releases the input hook, if it is installed.
                    592: *
                    593: * Returns value: TRUE if hook is released, FALSE otherwise.
                    594: \***********************************************************************/
                    595: BOOL EXPENTRY SpyReleaseHook(fZeroQueue)
                    596: BOOL    fZeroQueue;
                    597: {
                    598:     BOOL fRet;
                    599: 
                    600:     EnterSem(-1L);
                    601: 
                    602:     if ( habOwner ) {
                    603:         if (SpybHooks & SPYH_INPUT)
                    604:                 fRet = WinReleaseHook( habOwner, (HMQ)0, HK_INPUT,
                    605:                     (PFN)SpyInputHook, hmodSpy );
                    606: 
                    607:         if (SpybHooks & SPYH_SENDMSG)
                    608:                 fRet = WinReleaseHook( habOwner, (HMQ)0, HK_SENDMSG,
                    609:                     (PFN)SpySendMsgHook, hmodSpy );
                    610:             if ( fRet ) {
                    611:                 habOwner = (HAB)0;
                    612:                 hmqOwner = (HMQ)0;
                    613:         }
                    614:     }
                    615: 
                    616:     /*
                    617:      * When the hook is freed, we want to clear message count out,
                    618:      * make sure any process waiting will abort
                    619:      * Only do this if the Zeroqueu flag was passed
                    620:      */
                    621:     if (fZeroQueue) {
                    622:         cmsgSpy = 0;
                    623:         imsgWrite = 0;
                    624:         imsgRead = 0;
                    625:         if (pahwndSpy != NULL)
                    626:             FreeMem((char *)pahwndSpy, sizeof(HWND) * chwndSpy);
                    627:         pahwndSpy = NULL;
                    628:         chwndSpy = 0;           /* Max windows to spy */
                    629:         fRecording = FALSE;     /* Set recording to off */
                    630:         if (pahmqSpy != NULL)
                    631:             FreeMem((char *)pahmqSpy, sizeof(HMQ) * chmqSpy);
                    632: 
                    633:         pahmqSpy = NULL;
                    634:         chmqSpy = 0;
                    635:         fAnythingToWatch = FALSE;
                    636:         SignalEvent();    /* Free any process */
                    637:     }
                    638:     LeaveSem();
                    639: 
                    640:     return fRet;
                    641: }
                    642: 
                    643: 
                    644: /*************************** Public Function ***************************\
                    645: * BOOL EXPENTRY SpyHookOnOrOff( fOn)
                    646: *
                    647: * Effect:  This routine allows the application to turn the hook
                    648: *   processing on or off.
                    649: *
                    650: * Returns value:
                    651: \***********************************************************************/
                    652: BOOL EXPENTRY SpyHookOnOrOff(fOn)
                    653: BOOL fOn;
                    654: {
                    655:     EnterSem(-1L);
                    656: 
                    657:     fRecording = fOn;
                    658: 
                    659:     LeaveSem();
                    660:     return (TRUE);
                    661: }
                    662: 
                    663: 
                    664: 
                    665: /*************************** Public Function ***************************\
                    666: * BOOL EXPENTRY SpySetAllFrameOpt(fAllFrames)
                    667: *
                    668: * Effect:  Special state if TRUE will cause the window filter to pass
                    669: *       all frame windows through.  This is usefull when debuging
                    670: *       interactions between frame windows, when the windows are
                    671: *       net yet created.
                    672: *
                    673: * Returns value:
                    674: \***********************************************************************/
                    675: BOOL EXPENTRY SpySetAllFrameOpt(fAllFrames)
                    676: BOOL fAllFrames;
                    677: {
                    678:     fProcessAllFrames = fAllFrames;
                    679:     fAnythingToWatch = (chwndSpy > 0) || (chmqSpy > 0) ||
                    680:             fProcessAllWindows || fProcessAllFrames;
                    681:     return (TRUE);
                    682: }
                    683: 
                    684: /*************************** Public Function ***************************\
                    685: * BOOL EXPENTRY SpySetAllWindowOpt(fAllWindows)
                    686: *
                    687: * Effect:  Special state if TRUE will cause the window filter to pass
                    688: *       all windows through.  This is usefull when debuging
                    689: *       interactions between all of the windows
                    690: *
                    691: * Returns value:
                    692: \***********************************************************************/
                    693: BOOL EXPENTRY SpySetAllWindowOpt(fAllWindows)
                    694: BOOL fAllWindows;
                    695: {
                    696:     fProcessAllWindows = fAllWindows;
                    697:     fAnythingToWatch = (chwndSpy > 0) || (chmqSpy > 0) ||
                    698:             fProcessAllWindows || fProcessAllFrames;
                    699:     return (TRUE);
                    700: }
                    701: 
                    702: 
                    703: /*************************** Public Function ***************************\
                    704: * BOOL EXPENTRY SpySetPIDIntercept(PID pid, USHORT usPIT, ULONG ulInfo);
                    705: *
                    706: *
                    707: * Effect:  Hack to tell the hook to be on the look out for a specific
                    708: *       PID.  If it finds it is running in the context of the specified
                    709: *       process, it will get the selector information for the specified
                    710: *       selector.
                    711: *
                    712: * Returns value:
                    713: \***********************************************************************/
                    714: BOOL EXPENTRY SpySetPIDIntercept(pid, usPIT, ulInfo)
                    715: PID     pid;
                    716: USHORT  usPIT;
                    717: ULONG   ulInfo;
                    718: {
                    719:     if (pit.pid == 0xffff) {
                    720:         pit.pid = pid;
                    721:         pit.usPIT = usPIT;
                    722:         pit.ulInfo = ulInfo;
                    723:         return (TRUE);
                    724:     } else
                    725:         return (FALSE);
                    726: }
                    727: 
                    728: 
                    729: 
                    730: /***************************** Exported Function ***********************\
                    731: * VOID SpyCheckPIDForIntercept(VOID)
                    732: *
                    733: * Effect:  Only called when we are looking for a symbol
                    734: *
                    735: \***********************************************************************/
                    736: VOID SpyCheckPIDForIntercept()
                    737: {
                    738:     PPIB            ppib;
                    739:     PTIB            ptib;
                    740: 
                    741:     /*
                    742:      * Get the spy semaphore to serialize access and see if we are the
                    743:      * correct PID;
                    744:      */
                    745:     DosGetThreadInfo(&ptib, &ppib);
                    746:     if (!EnterSem(100L))
                    747:         return;
                    748: 
                    749:     if (ppib->pib_ulpid == pit.pid) {
                    750:         /*
                    751:          * We are the correct process, so continue to try go get the
                    752:          * symbol information.
                    753:          */
                    754:         pit.pid = 0xffff;       /* reset to not enter again */
                    755: 
                    756:         switch (pit.usPIT) {
                    757:                 break;
                    758:             case PIT_ACCEL:
                    759:                 // Allocate memory for the Accel table.
                    760:                 pit.cbData = WinCopyAccelTable((HACCEL)pit.ulInfo,
                    761:                         (PACCELTABLE)NULL, 0);
                    762:                 pit.pvoidData = AllocMem(pit.cbData);
                    763:                 if (pit.pvoidData == NULL) {
                    764:                     pit.cbData = 0;
                    765:                     break;
                    766:                 }
                    767:                 WinCopyAccelTable((HACCEL)pit.ulInfo,
                    768:                         (PACCELTABLE)pit.pvoidData, pit.cbData);
                    769:                 break;
                    770:         }
                    771:     }
                    772: 
                    773:     LeaveSem();
                    774: }
                    775: 
                    776: 
                    777: 
                    778: /*************************** Public Function ***************************\
                    779: * int EXPENTRY SpyGetLNSymbolSelector(pwhoinfo)
                    780: *
                    781: * Effect:  Hack to get the information about the specified selector.
                    782: *       If the specified process has not been executed since the
                    783: *       function SpySetPIDIntercept has been called, it will return -1,
                    784: *       else it will return what was returned from IdentifyCodeSelector.
                    785: *
                    786: * Returns value:
                    787: \***********************************************************************/
                    788: USHORT EXPENTRY SpyGetPIDInterceptData(pvoidBuffer, cbBuffer, pmresult)
                    789: PVOID  pvoidBuffer;
                    790: USHORT cbBuffer;
                    791: PMRESULT pmresult;
                    792: {
                    793:     if (pvoidBuffer != NULL) {
                    794:         if (pit.pvoidData != NULL) {
                    795:             if (cbBuffer > pit.cbData)
                    796:                 cbBuffer = pit.cbData;
                    797:             CopyStruct(pit.pvoidData, pvoidBuffer, cbBuffer);
                    798:             FreeMem(pit.pvoidData, pit.cbData);
                    799:             pit.pvoidData = NULL;
                    800:         }
                    801:     }
                    802: 
                    803:     if (pmresult != NULL)
                    804:         *pmresult = pit.mresult;
                    805: 
                    806:     return (pit.cbData);
                    807: }
                    808: 
                    809: 
                    810: 
                    811: 
                    812: /*************************** Public Function **************************\
                    813: * VOID GrabMsgDataWords (SHORT imsg, UCHAR bMPType)
                    814: *
                    815: * Effect:
                    816: *   Get the next message from the list - if timeout != 0 an message
                    817: *   processing threads, you may have problems, - If lpqmsg==NULL, this
                    818: *   function acts like a query or wait function.
                    819: *
                    820: * Returns value:
                    821: \***********************************************************************/
                    822: VOID GrabMsgDataWords(imsg, bMPType)
                    823: SHORT       imsg;
                    824: UCHAR       bMPType;
                    825: {
                    826:     UCHAR   bMP1Type;
                    827:     UCHAR   bMP2Type;
                    828:     SHORT   cbMPs;
                    829:     SHORT   cbMP1;
                    830:     SHORT   cbMP2;
                    831:     UCHAR   *rgBuf;
                    832: 
                    833:     /*
                    834:      * This function will use the MPType data to know if MP1 and/or MP2
                    835:      * are pointers to any known data, that we want to extract off
                    836:      * and save for spy to display later
                    837:      */
                    838:     rgqmsgSpy[imsg].bMPType = bMPType;
                    839:     bMP1Type = bMPType & MP_MASK;
                    840:     cbMPs = cbMP1 = rgqmsgSpy[imsg].cbDataMP1 = acbMPTypes[bMP1Type];
                    841: 
                    842:     bMP2Type = (bMPType >> 3) & MP_MASK;
                    843:     cbMPs += (cbMP2 = rgqmsgSpy[imsg].cbDataMP2 = acbMPTypes[bMP2Type]);
                    844: 
                    845:     if (cbMPs > 0) {
                    846:         /* Allocate memory to save the data into */
                    847:         rgBuf = rgqmsgSpy[imsg].rgData = AllocMem(cbMPs);
                    848: 
                    849:         if (rgBuf != NULL) {
                    850:             /* Copy the data down, Note: if count is 0 will NOP */
                    851:             if (cbMP1) {
                    852:                 rgqmsgSpy[imsg].fMP1Valid = CopyStruct(
                    853:                         (CHAR *)rgqmsgSpy[imsg].qmsg.mp1, rgBuf, cbMP1);
                    854:                 rgBuf += cbMP1;
                    855:             }
                    856: 
                    857:             if (cbMP2) {
                    858:                 rgqmsgSpy[imsg].fMP2Valid = CopyStruct(
                    859:                         (CHAR *)rgqmsgSpy[imsg].qmsg.mp2, rgBuf, cbMP2);
                    860:             }
                    861:         }
                    862: 
                    863:     } else {
                    864:         rgqmsgSpy[imsg].rgData = NULL;
                    865:     }
                    866: }
                    867: 
                    868: 
                    869: 
                    870: 
                    871: 
                    872: 
                    873: /*************************** Public Function **************************\
                    874: * SpyGetNextMessage (lpqmsg, lpBuf, cbBuf, lTimeOut)
                    875: *
                    876: * Effect:
                    877: *   Get the next message from the list - if timeout != 0 an message
                    878: *   processing threads, you may have problems, - If lpqmsg==NULL, this
                    879: *   function acts like a query or wait function.
                    880: *
                    881: * Returns value:
                    882: \***********************************************************************/
                    883: BOOL EXPENTRY SpyGetNextMessage(lpqmsg, lpBuf, cbBuf, lTimeOut)
                    884: PQMSGSPY   lpqmsg;      /* Pointer where the user wants the message stored */
                    885: PSZ        lpBuf;       /* pointer to buffer */
                    886: SHORT      cbBuf;       /* size of buffer in bytes */
                    887: LONG    lTimeOut;       /* Timeout value */
                    888: {
                    889: 
                    890:     SHORT       cbMsg;  /* Count of bytes associated with message */
                    891:     ULONG       ulPostCt;   /* Count of posts to semaphore before reset */
                    892: 
                    893:     /* Quick escape hatch */
                    894:     if ((lTimeOut == 0) && (cmsgSpy == 0))
                    895:         return (FALSE);     /* Dont Wait */
                    896: 
                    897:     /*
                    898:      * Now lets possibly wait for a message
                    899:      */
                    900:     if (cmsgSpy == 0) {
                    901:         if (DosWaitEventSem(hevSpyMsg, lTimeOut) != 0)
                    902:             return (FALSE); /* No messages after timeout */
                    903:         if (cmsgSpy == 0)
                    904:             return (FALSE); /* Still no messages, return condition */
                    905:     }
                    906: 
                    907:     /*
                    908:      * If the lpqmsg is NULL, the user is simply asking if there is
                    909:      * a message and/or waiting for the message, so dont extract
                    910:      * the message, but simply return the status.
                    911:      */
                    912:     if (lpqmsg != NULL) {
                    913:         if (DosRequestMutexSem(hmtxSpyHook, lTimeOut) == 0) {
                    914:             *lpqmsg = rgqmsgSpy[imsgRead];   /* Extract the message */
                    915: 
                    916:             cbMsg = rgqmsgSpy[imsgRead].cbDataMP1
                    917:                     + rgqmsgSpy[imsgRead].cbDataMP2;
                    918: 
                    919:             if ((cbMsg > 0) && (lpBuf != NULL)) {
                    920:                 if (cbMsg < cbBuf)
                    921:                     cbBuf = cbMsg;  /* Number of bytes to copy */
                    922:                 CopyStruct(rgqmsgSpy[imsgRead].rgData, lpBuf, cbBuf);
                    923:             }
                    924: 
                    925:             if (cbMsg > 0)
                    926:                 FreeMem(rgqmsgSpy[imsgRead].rgData, cbMsg);
                    927: 
                    928:             /* Also give the caller any additional information on message */
                    929: 
                    930:             imsgRead++;
                    931:             if (imsgRead == MAXMSGCNT)
                    932:                 imsgRead = 0;  /* Wrap around */
                    933: 
                    934:             /*
                    935:              * Decrement count of messages, if we go to zero, set
                    936:              * the semaphore, so that the next read will suspend until
                    937:              * the next message
                    938:              */
                    939:             cmsgSpy--;
                    940:             if (cmsgSpy == 0)
                    941:                 DosResetEventSem(hevSpyMsg, &ulPostCt);
                    942: 
                    943:             LeaveSem();
                    944:         }
                    945:     }
                    946: 
                    947:     return (TRUE);
                    948: }
                    949: 
                    950: 
                    951: 
                    952: 
                    953: /*************************** Private Function **************************\
                    954: * VOID SpyInitializeHookt(void)
                    955: *
                    956: * Effect:
                    957: *
                    958: *
                    959: * Returns value:
                    960: \***********************************************************************/
                    961: BOOL EXPENTRY SpyInitializeHook (VOID)
                    962: {
                    963: 
                    964:     if (fInitialized) {
                    965:         return (TRUE);
                    966:     }
                    967: 
                    968:     fInitialized = TRUE;
                    969: 
                    970:     /* Make an event semaphore to signal spy program with */
                    971:     DosCreateMutexSem(NULL, &hmtxSpyHook, DC_SEM_SHARED, FALSE);
                    972:     DosCreateEventSem(NULL, &hevSpyMsg, DC_SEM_SHARED, FALSE);
                    973: 
                    974:     /* Initialize our local heap */
                    975:     DosAllocSharedMem(&pheapSpyHook, NULL, HEAPSIZE,
                    976:             PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_GETTABLE);
                    977:     DosSubSet((PVOID)pheapSpyHook, 1, HEAPSIZE);
                    978: 
                    979:     /* Get the module handle. */
                    980:     return TRUE;
                    981: 
                    982: }
                    983: 
                    984: 
                    985: /*************************** Private Function **************************\
                    986: * VOID SpyTerminateHook(  )
                    987: *
                    988: * Effect:
                    989: *
                    990: *
                    991: * Returns value:
                    992: \***********************************************************************/
                    993: BOOL EXPENTRY SpyTerminateHook (VOID)
                    994: {
                    995: 
                    996: 
                    997:     if (!fInitialized) {
                    998:         return (FALSE);
                    999:     }
                   1000: 
                   1001:     fInitialized = FALSE;
                   1002: 
                   1003:     /* Close the semaphore off now */
                   1004:     DosCloseMutexSem(hmtxSpyHook);
                   1005:     DosCloseEventSem(hevSpyMsg);
                   1006: 
                   1007:     /* Also need to free memory */
                   1008: 
                   1009: 
                   1010: }
                   1011: 
                   1012: 
                   1013: /*************************** Private Function **************************\
                   1014: * UCHAR GMsgEnableAndType (USHORT msg)
                   1015: *
                   1016: * Effect:
                   1017: *   Should the message be processed.  If the message is out of range,
                   1018: *   or bit is set in message bitmask return TRUE
                   1019: *
                   1020: * Returns value:
                   1021: *   BOOL
                   1022: \***********************************************************************/
                   1023: UCHAR GMsgEnableAndType(msg)
                   1024: USHORT  msg;
                   1025: {
                   1026:     if (msg > MAXMSGFILTER)
                   1027:         return ((UCHAR)(fDispMsgsNotInList? MP_ENABLED : 0));
                   1028: 
                   1029:     return (rgMessageFilter[msg]);   /* One byte per message */
                   1030: }
                   1031: 
                   1032: 
                   1033: /*************************** Private Function **************************\
                   1034: * PBYTE AllocMem (ULONG cb)
                   1035: *
                   1036: * Effect:
                   1037: *   Allocates memory from our local heap, and hides that we are no longer
                   1038: *   calling WinAllocMem.
                   1039: *
                   1040: * Returns value:
                   1041: *   PBYTE
                   1042: \***********************************************************************/
                   1043: PBYTE AllocMem(ULONG cb)
                   1044: {
                   1045:     PVOID   pbT;
                   1046:     ULONG   ulCb;
                   1047:     ULONG   ulFlag;
                   1048: 
                   1049:     if (DosQueryMem(pheapSpyHook, &ulCb, &ulFlag)) {
                   1050:         if (DosGetSharedMem(pheapSpyHook, PAG_READ | PAG_WRITE)) {
                   1051:             DebugBreak;
                   1052:             return (NULL);
                   1053:         }
                   1054:     }
                   1055: 
                   1056:     if (DosSubAlloc((PVOID)pheapSpyHook, (PPVOID)&pbT, cb))
                   1057:         return(NULL);
                   1058: 
                   1059:     return(pbT);
                   1060: }
                   1061: 
                   1062: 
                   1063: /*************************** Private Function **************************\
                   1064: * UCHAR FreeMem (PBYTE pMem, ULONG cb)
                   1065: *
                   1066: * Effect:
                   1067: *   Frees any memory previously allocated by Allocmem
                   1068: *
                   1069: * Returns value:
                   1070: *   NULL
                   1071: \***********************************************************************/
                   1072: 
                   1073: VOID FreeMem(PBYTE pMem, ULONG cb)
                   1074: {
                   1075:     DosSubFree((PVOID)pheapSpyHook, (PVOID)pMem, cb);
                   1076: }
                   1077: 
                   1078: 
                   1079: /*************************** Private Function **************************\
                   1080: * BOOL EnterSem
                   1081: *
                   1082: * Effect:
                   1083: *   Enters the Main spy Mutex semaphore
                   1084: *
                   1085: * Returns value:
                   1086: *   BOOL;
                   1087: \***********************************************************************/
                   1088: 
                   1089: BOOL EnterSem(ULONG ulWait)
                   1090: {
                   1091:     ULONG   rc;
                   1092:     HMTX    hmtx;
                   1093: 
                   1094:     if ((rc = DosRequestMutexSem(hmtxSpyHook, ulWait)) == 0)
                   1095:         return (TRUE);
                   1096: 
                   1097:     if (rc != ERROR_INVALID_HANDLE)
                   1098:         return (FALSE);
                   1099: #ifdef LATER
                   1100:     * We should Close semaphore when we are done???
                   1101: #endif
                   1102: 
                   1103:     hmtx = hmtxSpyHook;
                   1104:     if (DosOpenMutexSem(NULL, &hmtx) != 0)
                   1105:         return (FALSE);
                   1106: 
                   1107:     DosGetSharedMem(pheapSpyHook, PAG_READ | PAG_WRITE);
                   1108: 
                   1109:     return (DosRequestMutexSem(hmtxSpyHook, 100L) == 0);
                   1110: 
                   1111: }
                   1112: 
                   1113: /*************************** Private Function **************************\
                   1114: * BOOL LeaveSem
                   1115: *
                   1116: * Effect:
                   1117: *   Enters the Main spy Mutex semaphore
                   1118: *
                   1119: * Returns value:
                   1120: *   BOOL;
                   1121: \***********************************************************************/
                   1122: 
                   1123: BOOL LeaveSem()
                   1124: {
                   1125:     return (DosReleaseMutexSem(hmtxSpyHook) == 0);
                   1126: 
                   1127: }
                   1128: 
                   1129: 
                   1130: 
                   1131: /*************************** Private Function **************************\
                   1132: * BOOL SignalEvent
                   1133: *
                   1134: * Effect:
                   1135: *   Signal an event to spy to let him know something is available.
                   1136: *
                   1137: * Returns value:
                   1138: *   BOOL;
                   1139: \***********************************************************************/
                   1140: 
                   1141: BOOL SignalEvent()
                   1142: {
                   1143:     ULONG   rc;
                   1144:     HEV     hev;
                   1145: 
                   1146:     if ((rc = DosPostEventSem(hevSpyMsg)) == 0)
                   1147:         return (TRUE);
                   1148: 
                   1149:     if (rc != ERROR_INVALID_HANDLE)
                   1150:         return (FALSE);
                   1151: #ifdef LATER
                   1152:     * We should Close semaphore when we are done???
                   1153: #endif
                   1154: 
                   1155:     hev = hevSpyMsg;
                   1156:     if (DosOpenEventSem(NULL, &hev) != 0)
                   1157:         return (FALSE);
                   1158: 
                   1159:     return (DosPostEventSem(hevSpyMsg) == 0);
                   1160: 
                   1161: }

unix.superglobalmegacorp.com

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