File:  [OS/2 SDKs] / os232sdk / toolkt20 / c / samples / spy / spyhk32.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 12:26:30 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: os2sdk-1990, HEAD
Microsoft OS/2 SDK 2.0 05-30-1990

/***********************************************************************\
* spyhook.C - Spy Global input hook interface library.
*
* Created: Microsoft, IBM Corporation 1990
*
*	DISCLAIMER OF WARRANTIES.  The following [enclosed] code is 
*	sample code created by Microsoft Corporation and/or IBM 
*	Corporation. This sample code is not part of any standard 
*	Microsoft or IBM product and is provided to you solely for 
*	the purpose of assisting you in the development of your 
*	applications.  The code is provided "AS IS", without 
*	warranty of any kind.  Neither Microsoft nor IBM shall be 
*	liable for any damages arising out of your use of the sample 
*	code, even if they have been advised of the possibility of 
*	such damages.
*
* Purpose:  This dynlink is needed because global input hooks must
*   reside in a DLL.
*
\***********************************************************************/
#define INCL_PM
#define INCL_DOSPROCESS
#define INCL_DOSMODULEMGR
#define INCL_DOSSEMAPHORES
#define INCL_ERRORS
#include <os2.h>
#include "spyhk32.h"

// Needed to make a dll link properly
int _acrtused = 0;

HMTX  hmtxSpyHook;              /* global semaphore for this module */
HEV   hevSpyMsg;                /* global semaphore for this module */

HMODULE hmodSpy;                /* dynlink module handle            */
SHORT    SpybHooks;             /* Whichs Hook do we use             */

HAB habOwner = (HAB)0;          /* Hook owner's anchore block       */
HMQ hmqOwner = (HMQ)0;          /* Hook owner's message queue       */
BOOL fRecording = FALSE;        /* Are we recording now?            */
BOOL fAnythingToWatch = FALSE;  /* Is there anything to watch       */
BOOL fDispMsgsNotInList = TRUE; /* Disp msgs not in list?           */

/* Define array of window handles that we are going to process */
BOOL fInitialized = FALSE;
BOOL fProcessAllFrames = FALSE; /* Are we processing all frame messages */
BOOL fProcessAllWindows = FALSE;/* Are we processing all windows */
HWND *pahwndSpy = NULL;         /* Array of hwnds to spy on, no max here */
int  chwndSpy = 0;  /* Max windows to spy */

/* Define array of HMQ's to spy on */
HMQ *pahmqSpy = NULL;           /* HMQ list to spy on */
int chmqSpy = 0;                /* Count of hmqs we are spying on */


/* Define message filter array */
UCHAR rgMessageFilter[MAXMSGFILTERBYTES] = "";
UCHAR  GMsgEnableAndType(USHORT);       /* Is message in message list */
VOID   GrabMsgDataWords(SHORT, UCHAR);  /* Get extra words for message */
BOOL   CopyStruct(UCHAR *pbSrc, UCHAR *pbDst, SHORT cb);  /* Copy bytes */
void    DebugBreak(void);

/* Define an array of messages to pass to whomever calls us */

QMSGSPY  rgqmsgSpy[MAXMSGCNT];     /* Array of messages to process */
SHORT cmsgSpy = 0;              /* Count of messages yet to be read */
SHORT imsgWrite = 0;            /* Index to message to write out */
SHORT imsgRead = 0;             /* Index to message to read */

/* Use the Dos Sub allocate functions to make sure to use shared memory */
#define HEAPSIZE 16384 /* 16K should be plenty? */
PVOID pheapSpyHook;      /* Heap to use for Spy Hook DLL */

PBYTE AllocMem(ULONG cb);
VOID  FreeMem(PBYTE pMem, ULONG cb);
BOOL EnterSem(ULONG ulWait);
BOOL LeaveSem(VOID);
BOOL SignalEvent(VOID);



SHORT acbMPTypes[MP_MASK+1] = { /* Number of desired bytes to extract */
    0,                          /* Normal fields, no pointers */
    sizeof(SWP),                /* MPT_SWP */
    sizeof(RECTL),              /* MPT_RECTL */
    0,                          /* MPT_WNDPRMS we dont process yet */
    sizeof(QMSG)                /* MPT_QMSG */
};


/* Information for geting selector information in diffent PID context */
PIT pit = {0xffff, 0, 0L, NULL, 0};
USHORT  selectorLNSpy = 0;      /* Which Selector */
VOID SpyCheckPIDForIntercept(VOID);
ULONG EXPENTRY Init(ULONG hPDLL, HMODULE hmod);

/***********************************************************************\
* VOID Init( hmod )
* 
* Effect:	Saves the Spy module handle
\***********************************************************************/
ULONG EXPENTRY Init(hPDLL, hmod)
ULONG	hPDLL;
HMODULE	hmod;
{
    /* Save the module handle */
    hmodSpy = hmod;

    return (ULONG)hmodSpy;

    /* Unreferenced formal parameters referenced here to prevent compiler
        warning */
    hPDLL;
}




/***************************** Exported Function ***********************\
* BOOL EXPENTRY SpyInputHook( hab, lpqmsg, fs)
* HAB hab;
* PQMSG  lpqmsg;
* USHORT    fs;
*
* Effect:  This is the global input hook procedure.  Note that hook
*   procedures can be chained, so we always return FALSE to pass the
*   message to the next guy in chain.
*
* Return value:  FALSE to pass message to next hook procedure.
\***********************************************************************/
BOOL EXPENTRY SpyInputHook( hab, lpqmsg, fs )
HAB hab;
PQMSG lpqmsg;
USHORT  fs;
{
    UCHAR       bMPType;

    /*
     * Check first to see if we are looking for a process symbols
     */
    if (pit.pid != 0xffff)
        SpyCheckPIDForIntercept();

    /*
     * First check to see if we are processing any hook messages
     */
    if (!fRecording || !fAnythingToWatch || (cmsgSpy >= MAXMSGCNT))
        return (FALSE); /* No let the next one have it now */

    /*
     * See if we have any messages to process - Recheck to make sure we
     * Dont overwrite our queue.
     */
    if (!EnterSem(100L)) {
        DebugBreak();
        return (FALSE);
    }
    if (cmsgSpy < MAXMSGCNT) {
        if (SpyFWindowInList(lpqmsg->hwnd, FALSE) &&
                (bMPType = GMsgEnableAndType(lpqmsg->msg))) {
            rgqmsgSpy[imsgWrite].fs = fs;       /* Save the flags */
            rgqmsgSpy[imsgWrite].qmsg = *lpqmsg;   /* Save the message */

            GrabMsgDataWords(imsgWrite, bMPType);
            imsgWrite++;

            if (imsgWrite == MAXMSGCNT)
                imsgWrite = 0;  /* Wrap around */
            cmsgSpy++;
            SignalEvent();
        }
    }

    LeaveSem();
    return FALSE;   /* Let system take normal action. */

    /* Unreferenced formal parameters referenced here to prevent compiler
        warning */
    hab;

}


/***************************** Exported Function ***********************\
* BOOL EXPENTRY SpySendMsgHook( hab, lpsmh, fInterTask)
* HAB hab;
* PQMSG  lpqmsg;
*
* Effect:  This is the global input hook procedure.  Note that hook
*   procedures can be chained, so we always return FALSE to pass the
*   message to the next guy in chain.
*
* Return value:  FALSE to pass message to next hook procedure.
\***********************************************************************/
BOOL EXPENTRY SpySendMsgHook( hab, lpsmh, fInterTask )
HAB hab;
PSMHSTRUCT      lpsmh;
BOOL            fInterTask;
{
    UCHAR           bMPType;
    PPIB            ppib;
    PTIB            ptib;

    /*
     * Check first to see if we are looking for a process symbols
     */
    if (pit.pid != 0xffff)
        SpyCheckPIDForIntercept();

    /*
     * First check to see if we are processing any hook messages
     */
    if (!fRecording || !fAnythingToWatch || (cmsgSpy >= MAXMSGCNT))
        return (FALSE); /* No let the next one have it now */

    /*
     * See if we have any messages to process
     */
    if (!EnterSem(100L)) {
        DebugBreak();
        return (FALSE);
    }
    /* Make sure no one got in by mistake */
    if (cmsgSpy < MAXMSGCNT) {
        if (SpyFWindowInList(lpsmh->hwnd, FALSE) &&
                (bMPType = GMsgEnableAndType(lpsmh->msg))) {
            /*
             * Store out message, must move pieces seperatly
             */
            rgqmsgSpy[imsgWrite].fs = fInterTask;
            rgqmsgSpy[imsgWrite].qmsg.hwnd = lpsmh->hwnd;
            rgqmsgSpy[imsgWrite].qmsg.msg  = lpsmh->msg;
            rgqmsgSpy[imsgWrite].qmsg.mp1  = lpsmh->mp1;
            rgqmsgSpy[imsgWrite].qmsg.mp2  = lpsmh->mp2;
            rgqmsgSpy[imsgWrite].qmsg.time = (ULONG)-1;
            rgqmsgSpy[imsgWrite].qmsg.ptl.x  = 0;
            rgqmsgSpy[imsgWrite].qmsg.ptl.y  = 0;

            GrabMsgDataWords(imsgWrite, bMPType);

            /* Now get the PID/TID info, and do the stack backtrace */
            DosGetThreadInfo(&ptib, &ppib);
            rgqmsgSpy[imsgWrite].pidSend = ppib->pib_ulpid;
            rgqmsgSpy[imsgWrite].tidSend = ptib->tib_ultid;

            imsgWrite++;
            if (imsgWrite == MAXMSGCNT)
                imsgWrite = 0;  /* Wrap around */
            cmsgSpy++;
            SignalEvent();
        }
    }

    LeaveSem();
    return FALSE;   /* Let system take normal action. */

    /* Unreferenced formal parameters referenced here to prevent compiler
        warning */
    hab;

}


/*************************** Public Function ***************************\
* BOOL EXPENTRY SpyInstallHook( hab, hmq, fSendMessage, bHooks)
*
* Effect:  This routine installs a system-wide HK_INPUT hook.  The hab
*   hmq are remembered for message posting.  Note that we only allow
*   one input hook to be installed through this routine, but other
*   apps may call WinSetHook directly.
*
* Returns value:  TRUE if hook installed successfully, FALSE otherwise.
\***********************************************************************/
BOOL EXPENTRY SpyInstallHook( hab, hmq, bHooks )
HAB     hab;
HMQ     hmq;
USHORT  bHooks;
{
    BOOL fRet;
    ULONG   ulPostCt;

    EnterSem(-1L);


    /*
     * Look at hook index if == HK_INPUT Install a system-wide input hook.
     * else set system wide SENDMSG hook
     */
    SpybHooks = bHooks;
    if (SpybHooks & SPYH_INPUT)
        fRet = WinSetHook( hab, (HMQ)0, HK_INPUT, (PFN)SpyInputHook,
                    hmodSpy );

    if (SpybHooks & SPYH_SENDMSG)
        fRet = WinSetHook( hab, (HMQ)0, HK_SENDMSG, (PFN)SpySendMsgHook,
                    hmodSpy );
    if (fRet) {
        habOwner = hab;
        hmqOwner = hmq;
    }

    DosResetEventSem(hevSpyMsg, &ulPostCt);    /* Init, no messages avail */
    LeaveSem();

    return fRet;
}



/*************************** Public Function ***************************\
* BOOL EXPENTRY SpySetWindowList( chwnd, rghwnd)
*
* Effect:  This routine sets the list of window that we are interested
*   in watching the messages for.
*
* Returns value:  TRUE
\***********************************************************************/
BOOL EXPENTRY SpySetWindowList( chwnd, rghwnd )
SHORT       chwnd;
HWND    *rghwnd;
{
    SHORT   i;
    HWND    *phwndT;

    EnterSem(-1L);

    if (pahwndSpy) {
        FreeMem((char *)pahwndSpy, sizeof(HWND) * chwndSpy);
        pahwndSpy = NULL;
    }


    chwndSpy = chwnd;

    if (chwndSpy > 0 ) {

        phwndT = pahwndSpy = (HWND *)AllocMem(sizeof(HWND) * chwndSpy);

        if (phwndT != NULL) {
            for (i=0; i < chwnd; i++) {
                *phwndT++ = *rghwnd++;
            }
        } else
            chwndSpy = 0;
    }

    fAnythingToWatch = (chwndSpy > 0) || (chmqSpy > 0) ||
            fProcessAllWindows || fProcessAllFrames;

    LeaveSem();
    return(TRUE);
}


/*************************** Public Function ***************************\
* BOOL EXPENTRY SpyGetWindowList( chwnd, rghwnd)
*
* Effect:  This routine sets the list of window that we are interested
*   in watching the messages for.
*
* Returns value:  TRUE
\***********************************************************************/
SHORT EXPENTRY SpyGetWindowList( chwnd, rghwnd )
SHORT       chwnd;
HWND    *rghwnd;
{
    SHORT   i;
    HWND    *phwndT;

    EnterSem(-1L);

    if (chwnd > chwndSpy)
            chwnd = chwndSpy;

    phwndT = pahwndSpy;
    for (i=0; i < chwnd; i++) {
        *rghwnd++ = *phwndT++;
    }

    LeaveSem();

    return(chwnd);
}




/*************************** Public Function ***************************\
* BOOL EXPENTRY SpySetQueueList( chmq, rghmq)
*
* Effect:  This routine sets the list of Queue that we are interested
*   in watching the messages for.
*
* Returns value:  TRUE
\***********************************************************************/
BOOL EXPENTRY SpySetQueueList( chmq, rghmq )
SHORT       chmq;
HMQ    *rghmq;
{
    SHORT   i;
    HMQ     *phmqT;

    EnterSem(-1L);

    /*
     * If we previously had a list of HMQs to spy on, free the old list
     * now
     */
    if (pahmqSpy != NULL) {
        FreeMem((char *)pahmqSpy, sizeof(HMQ) * chmqSpy);
        pahmqSpy = NULL;
    }

    chmqSpy = chmq;

    if (chmqSpy > 0) {
        phmqT = pahmqSpy = (HMQ *)AllocMem(sizeof(HMQ) * chmqSpy);

        if (phmqT != NULL) {
            for (i=0; i < chmq; i++) {
                *phmqT++ = *rghmq++;
            }
        } else
            chmqSpy = 0;
    }

    fAnythingToWatch = (chwndSpy > 0) || (chmqSpy > 0) ||
            fProcessAllWindows || fProcessAllFrames;
    LeaveSem();

    return(TRUE);
}


/*************************** Public Function ***************************\
* BOOL EXPENTRY SpyGetQueueList( chmq, rghmq)
*
* Effect:  This routine sets the list of Queue that we are interested
*   in watching the messages for.
*
* Returns value:  TRUE
\***********************************************************************/
SHORT EXPENTRY SpyGetQueueList( chmq, rghmq )
SHORT       chmq;
HMQ    *rghmq;
{
    SHORT   i;
    HMQ     *phmqT;

    EnterSem(-1L);

    if (chmq > chmqSpy)
        chmq = chmqSpy;

    phmqT = pahmqSpy;

    for (i=0; i < chmq; i++) {
        *rghmq++ = *phmqT++;
    }

    LeaveSem();

    return(chmq);
}


/*************************** Public Function ***************************\
* BOOL EXPENTRY SpySetMessageList(UCHAR *prgNewMsgFilter,
*                   BOOL fNewDispMsgsNotInList)
*
* Effect:  This routine sets the list of window that we are interested
*   in watching the messages for.
*
* Returns value:  TRUE
\***********************************************************************/
BOOL EXPENTRY SpySetMessageList(prgNewMsgFilter, fNewDispMsgsNotInList)
UCHAR           *prgNewMsgFilter;
BOOL                fNewDispMsgsNotInList;
{
    SHORT           i;
    unsigned char   *prgb;

    EnterSem(-1L);

    prgb = rgMessageFilter;


    fDispMsgsNotInList = fNewDispMsgsNotInList;

    for (i=0; i < MAXMSGFILTERBYTES; i++) {
        *prgb++ = *prgNewMsgFilter++;
    }

    LeaveSem();

    return(TRUE);
}


/*************************** Public Function ***************************\
* BOOL EXPENTRY SpyFWindowInList (hwnd, fInWindowListOnly)
*
* Effect:  This function checks our current list of windows, and returns
*          TRUE if the window is in the list, else returns FALSE.
* Returns value:  TRUE if window is in list.  Also if We are in the special
*           state we will pass through all frame windows.
\***********************************************************************/
BOOL EXPENTRY SpyFWindowInList (hwnd, fInWindowListOnly)
register HWND  hwnd;
BOOL            fInWindowListOnly;
{
    register int    i;
    char            szClassName[10];    /* Class name of window */
    CLASSINFO       classinfo;          /* Information about class */
    HMQ             hmqWindow;          /* HMQ of window        */
    HMQ             *phmqT;             /* Temporary pointer in hmq list */
    HWND            *phwndT;            /* Temporary pointer to HWND list */
    PPIB            ppib;
    PTIB            ptib;
    MQINFO          mqinfo;             /* Queue info */



    phwndT = pahwndSpy;
    for (i=0; i < chwndSpy; i++) {
        if (hwnd == *phwndT++)
            return (TRUE);
    }

    /* See if we are restricting to only windows in list */
    if (fInWindowListOnly)
        return (FALSE);

    if (fProcessAllWindows)
        return (TRUE);      /* All windows pass through */

    /*
     * See if we are watching any message queues
     */
    if (phmqT = pahmqSpy) {
        if (hwnd != NULL) {
            /*
             * Sent to specific window First see if the user has specified
             * that the want all messages that are sent to this message
             * queue
             */
            hmqWindow = (HMQ)WinQueryWindowULong(hwnd, QWL_HMQ);
            for (i=0; i < chmqSpy; i++) {
                if (*phmqT++ == hmqWindow)
                    return (TRUE);
            }
        } else {
            // For NULL window handle, see if the current process has HMQ
            /*
             * Null Window handle, so instead we need to go through the
             * list of queues we are watching and see if their PID and TID
             * matches our current thread.
             */
            DosGetThreadInfo(&ptib, &ppib);
            for (i=0; i < chmqSpy; i++) {
                if (WinQueryQueueInfo(*phmqT, &mqinfo, sizeof(mqinfo))) {
                    if ((mqinfo.pid == ppib->pib_ulpid) &&
                            (mqinfo.tid == ptib->tib_ultid))
                        return (TRUE);      // Yes we want this queue!

                }
                phmqT++;
            }
        }
    }

    if (fProcessAllFrames) {
        /* See if frame class */
        if (hwnd == NULL)
            return (TRUE);      /* pass queue messages through */
        WinQueryClassName(hwnd, sizeof(szClassName),
            (PSZ)szClassName);
        WinQueryClassInfo((HAB)NULL, (PSZ)szClassName,
            &classinfo);
        if (classinfo.flClassStyle & CS_FRAME)
            return (TRUE);
    }

    return (FALSE);
}


/*************************** Public Function ***************************\
* BOOL EXPENTRY SpyReleaseHook(fZeroQueue)
*
* Effect:  This routine releases the input hook, if it is installed.
*
* Returns value: TRUE if hook is released, FALSE otherwise.
\***********************************************************************/
BOOL EXPENTRY SpyReleaseHook(fZeroQueue)
BOOL    fZeroQueue;
{
    BOOL fRet;

    EnterSem(-1L);

    if ( habOwner ) {
        if (SpybHooks & SPYH_INPUT)
                fRet = WinReleaseHook( habOwner, (HMQ)0, HK_INPUT,
                    (PFN)SpyInputHook, hmodSpy );

        if (SpybHooks & SPYH_SENDMSG)
                fRet = WinReleaseHook( habOwner, (HMQ)0, HK_SENDMSG,
                    (PFN)SpySendMsgHook, hmodSpy );
            if ( fRet ) {
                habOwner = (HAB)0;
                hmqOwner = (HMQ)0;
        }
    }

    /*
     * When the hook is freed, we want to clear message count out,
     * make sure any process waiting will abort
     * Only do this if the Zeroqueu flag was passed
     */
    if (fZeroQueue) {
        cmsgSpy = 0;
        imsgWrite = 0;
        imsgRead = 0;
        if (pahwndSpy != NULL)
            FreeMem((char *)pahwndSpy, sizeof(HWND) * chwndSpy);
        pahwndSpy = NULL;
        chwndSpy = 0;           /* Max windows to spy */
        fRecording = FALSE;     /* Set recording to off */
        if (pahmqSpy != NULL)
            FreeMem((char *)pahmqSpy, sizeof(HMQ) * chmqSpy);

        pahmqSpy = NULL;
        chmqSpy = 0;
        fAnythingToWatch = FALSE;
        SignalEvent();    /* Free any process */
    }
    LeaveSem();

    return fRet;
}


/*************************** Public Function ***************************\
* BOOL EXPENTRY SpyHookOnOrOff( fOn)
*
* Effect:  This routine allows the application to turn the hook
*   processing on or off.
*
* Returns value:
\***********************************************************************/
BOOL EXPENTRY SpyHookOnOrOff(fOn)
BOOL fOn;
{
    EnterSem(-1L);

    fRecording = fOn;

    LeaveSem();
    return (TRUE);
}



/*************************** Public Function ***************************\
* BOOL EXPENTRY SpySetAllFrameOpt(fAllFrames)
*
* Effect:  Special state if TRUE will cause the window filter to pass
*       all frame windows through.  This is usefull when debuging
*       interactions between frame windows, when the windows are
*       net yet created.
*
* Returns value:
\***********************************************************************/
BOOL EXPENTRY SpySetAllFrameOpt(fAllFrames)
BOOL fAllFrames;
{
    fProcessAllFrames = fAllFrames;
    fAnythingToWatch = (chwndSpy > 0) || (chmqSpy > 0) ||
            fProcessAllWindows || fProcessAllFrames;
    return (TRUE);
}

/*************************** Public Function ***************************\
* BOOL EXPENTRY SpySetAllWindowOpt(fAllWindows)
*
* Effect:  Special state if TRUE will cause the window filter to pass
*       all windows through.  This is usefull when debuging
*       interactions between all of the windows
*
* Returns value:
\***********************************************************************/
BOOL EXPENTRY SpySetAllWindowOpt(fAllWindows)
BOOL fAllWindows;
{
    fProcessAllWindows = fAllWindows;
    fAnythingToWatch = (chwndSpy > 0) || (chmqSpy > 0) ||
            fProcessAllWindows || fProcessAllFrames;
    return (TRUE);
}


/*************************** Public Function ***************************\
* BOOL EXPENTRY SpySetPIDIntercept(PID pid, USHORT usPIT, ULONG ulInfo);
*
*
* Effect:  Hack to tell the hook to be on the look out for a specific
*       PID.  If it finds it is running in the context of the specified
*       process, it will get the selector information for the specified
*       selector.
*
* Returns value:
\***********************************************************************/
BOOL EXPENTRY SpySetPIDIntercept(pid, usPIT, ulInfo)
PID     pid;
USHORT  usPIT;
ULONG   ulInfo;
{
    if (pit.pid == 0xffff) {
        pit.pid = pid;
        pit.usPIT = usPIT;
        pit.ulInfo = ulInfo;
        return (TRUE);
    } else
        return (FALSE);
}



/***************************** Exported Function ***********************\
* VOID SpyCheckPIDForIntercept(VOID)
*
* Effect:  Only called when we are looking for a symbol
*
\***********************************************************************/
VOID SpyCheckPIDForIntercept()
{
    PPIB            ppib;
    PTIB            ptib;

    /*
     * Get the spy semaphore to serialize access and see if we are the
     * correct PID;
     */
    DosGetThreadInfo(&ptib, &ppib);
    if (!EnterSem(100L))
        return;

    if (ppib->pib_ulpid == pit.pid) {
        /*
         * We are the correct process, so continue to try go get the
         * symbol information.
         */
        pit.pid = 0xffff;       /* reset to not enter again */

        switch (pit.usPIT) {
                break;
            case PIT_ACCEL:
                // Allocate memory for the Accel table.
                pit.cbData = WinCopyAccelTable((HACCEL)pit.ulInfo,
                        (PACCELTABLE)NULL, 0);
                pit.pvoidData = AllocMem(pit.cbData);
                if (pit.pvoidData == NULL) {
                    pit.cbData = 0;
                    break;
                }
                WinCopyAccelTable((HACCEL)pit.ulInfo,
                        (PACCELTABLE)pit.pvoidData, pit.cbData);
                break;
        }
    }

    LeaveSem();
}



/*************************** Public Function ***************************\
* int EXPENTRY SpyGetLNSymbolSelector(pwhoinfo)
*
* Effect:  Hack to get the information about the specified selector.
*       If the specified process has not been executed since the
*       function SpySetPIDIntercept has been called, it will return -1,
*       else it will return what was returned from IdentifyCodeSelector.
*
* Returns value:
\***********************************************************************/
USHORT EXPENTRY SpyGetPIDInterceptData(pvoidBuffer, cbBuffer, pmresult)
PVOID  pvoidBuffer;
USHORT cbBuffer;
PMRESULT pmresult;
{
    if (pvoidBuffer != NULL) {
        if (pit.pvoidData != NULL) {
            if (cbBuffer > pit.cbData)
                cbBuffer = pit.cbData;
            CopyStruct(pit.pvoidData, pvoidBuffer, cbBuffer);
            FreeMem(pit.pvoidData, pit.cbData);
            pit.pvoidData = NULL;
        }
    }

    if (pmresult != NULL)
        *pmresult = pit.mresult;

    return (pit.cbData);
}




/*************************** Public Function **************************\
* VOID GrabMsgDataWords (SHORT imsg, UCHAR bMPType)
*
* Effect:
*   Get the next message from the list - if timeout != 0 an message
*   processing threads, you may have problems, - If lpqmsg==NULL, this
*   function acts like a query or wait function.
*
* Returns value:
\***********************************************************************/
VOID GrabMsgDataWords(imsg, bMPType)
SHORT       imsg;
UCHAR       bMPType;
{
    UCHAR   bMP1Type;
    UCHAR   bMP2Type;
    SHORT   cbMPs;
    SHORT   cbMP1;
    SHORT   cbMP2;
    UCHAR   *rgBuf;

    /*
     * This function will use the MPType data to know if MP1 and/or MP2
     * are pointers to any known data, that we want to extract off
     * and save for spy to display later
     */
    rgqmsgSpy[imsg].bMPType = bMPType;
    bMP1Type = bMPType & MP_MASK;
    cbMPs = cbMP1 = rgqmsgSpy[imsg].cbDataMP1 = acbMPTypes[bMP1Type];

    bMP2Type = (bMPType >> 3) & MP_MASK;
    cbMPs += (cbMP2 = rgqmsgSpy[imsg].cbDataMP2 = acbMPTypes[bMP2Type]);

    if (cbMPs > 0) {
        /* Allocate memory to save the data into */
        rgBuf = rgqmsgSpy[imsg].rgData = AllocMem(cbMPs);

        if (rgBuf != NULL) {
            /* Copy the data down, Note: if count is 0 will NOP */
            if (cbMP1) {
                rgqmsgSpy[imsg].fMP1Valid = CopyStruct(
                        (CHAR *)rgqmsgSpy[imsg].qmsg.mp1, rgBuf, cbMP1);
                rgBuf += cbMP1;
            }

            if (cbMP2) {
                rgqmsgSpy[imsg].fMP2Valid = CopyStruct(
                        (CHAR *)rgqmsgSpy[imsg].qmsg.mp2, rgBuf, cbMP2);
            }
        }

    } else {
        rgqmsgSpy[imsg].rgData = NULL;
    }
}






/*************************** Public Function **************************\
* SpyGetNextMessage (lpqmsg, lpBuf, cbBuf, lTimeOut)
*
* Effect:
*   Get the next message from the list - if timeout != 0 an message
*   processing threads, you may have problems, - If lpqmsg==NULL, this
*   function acts like a query or wait function.
*
* Returns value:
\***********************************************************************/
BOOL EXPENTRY SpyGetNextMessage(lpqmsg, lpBuf, cbBuf, lTimeOut)
PQMSGSPY   lpqmsg;      /* Pointer where the user wants the message stored */
PSZ        lpBuf;       /* pointer to buffer */
SHORT      cbBuf;       /* size of buffer in bytes */
LONG    lTimeOut;       /* Timeout value */
{

    SHORT       cbMsg;  /* Count of bytes associated with message */
    ULONG       ulPostCt;   /* Count of posts to semaphore before reset */

    /* Quick escape hatch */
    if ((lTimeOut == 0) && (cmsgSpy == 0))
        return (FALSE);     /* Dont Wait */

    /*
     * Now lets possibly wait for a message
     */
    if (cmsgSpy == 0) {
        if (DosWaitEventSem(hevSpyMsg, lTimeOut) != 0)
            return (FALSE); /* No messages after timeout */
        if (cmsgSpy == 0)
            return (FALSE); /* Still no messages, return condition */
    }

    /*
     * If the lpqmsg is NULL, the user is simply asking if there is
     * a message and/or waiting for the message, so dont extract
     * the message, but simply return the status.
     */
    if (lpqmsg != NULL) {
        if (DosRequestMutexSem(hmtxSpyHook, lTimeOut) == 0) {
            *lpqmsg = rgqmsgSpy[imsgRead];   /* Extract the message */

            cbMsg = rgqmsgSpy[imsgRead].cbDataMP1
                    + rgqmsgSpy[imsgRead].cbDataMP2;

            if ((cbMsg > 0) && (lpBuf != NULL)) {
                if (cbMsg < cbBuf)
                    cbBuf = cbMsg;  /* Number of bytes to copy */
                CopyStruct(rgqmsgSpy[imsgRead].rgData, lpBuf, cbBuf);
            }

            if (cbMsg > 0)
                FreeMem(rgqmsgSpy[imsgRead].rgData, cbMsg);

            /* Also give the caller any additional information on message */

            imsgRead++;
            if (imsgRead == MAXMSGCNT)
                imsgRead = 0;  /* Wrap around */

            /*
             * Decrement count of messages, if we go to zero, set
             * the semaphore, so that the next read will suspend until
             * the next message
             */
            cmsgSpy--;
            if (cmsgSpy == 0)
                DosResetEventSem(hevSpyMsg, &ulPostCt);

            LeaveSem();
        }
    }

    return (TRUE);
}




/*************************** Private Function **************************\
* VOID SpyInitializeHookt(void)
*
* Effect:
*
*
* Returns value:
\***********************************************************************/
BOOL EXPENTRY SpyInitializeHook (VOID)
{

    if (fInitialized) {
        return (TRUE);
    }

    fInitialized = TRUE;

    /* Make an event semaphore to signal spy program with */
    DosCreateMutexSem(NULL, &hmtxSpyHook, DC_SEM_SHARED, FALSE);
    DosCreateEventSem(NULL, &hevSpyMsg, DC_SEM_SHARED, FALSE);

    /* Initialize our local heap */
    DosAllocSharedMem(&pheapSpyHook, NULL, HEAPSIZE,
            PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_GETTABLE);
    DosSubSet((PVOID)pheapSpyHook, 1, HEAPSIZE);

    /* Get the module handle. */
    return TRUE;

}


/*************************** Private Function **************************\
* VOID SpyTerminateHook(  )
*
* Effect:
*
*
* Returns value:
\***********************************************************************/
BOOL EXPENTRY SpyTerminateHook (VOID)
{


    if (!fInitialized) {
        return (FALSE);
    }

    fInitialized = FALSE;

    /* Close the semaphore off now */
    DosCloseMutexSem(hmtxSpyHook);
    DosCloseEventSem(hevSpyMsg);

    /* Also need to free memory */


}


/*************************** Private Function **************************\
* UCHAR GMsgEnableAndType (USHORT msg)
*
* Effect:
*   Should the message be processed.  If the message is out of range,
*   or bit is set in message bitmask return TRUE
*
* Returns value:
*   BOOL
\***********************************************************************/
UCHAR GMsgEnableAndType(msg)
USHORT  msg;
{
    if (msg > MAXMSGFILTER)
        return ((UCHAR)(fDispMsgsNotInList? MP_ENABLED : 0));

    return (rgMessageFilter[msg]);   /* One byte per message */
}


/*************************** Private Function **************************\
* PBYTE AllocMem (ULONG cb)
*
* Effect:
*   Allocates memory from our local heap, and hides that we are no longer
*   calling WinAllocMem.
*
* Returns value:
*   PBYTE
\***********************************************************************/
PBYTE AllocMem(ULONG cb)
{
    PVOID   pbT;
    ULONG   ulCb;
    ULONG   ulFlag;

    if (DosQueryMem(pheapSpyHook, &ulCb, &ulFlag)) {
        if (DosGetSharedMem(pheapSpyHook, PAG_READ | PAG_WRITE)) {
            DebugBreak;
            return (NULL);
        }
    }

    if (DosSubAlloc((PVOID)pheapSpyHook, (PPVOID)&pbT, cb))
        return(NULL);

    return(pbT);
}


/*************************** Private Function **************************\
* UCHAR FreeMem (PBYTE pMem, ULONG cb)
*
* Effect:
*   Frees any memory previously allocated by Allocmem
*
* Returns value:
*   NULL
\***********************************************************************/

VOID FreeMem(PBYTE pMem, ULONG cb)
{
    DosSubFree((PVOID)pheapSpyHook, (PVOID)pMem, cb);
}


/*************************** Private Function **************************\
* BOOL EnterSem
*
* Effect:
*   Enters the Main spy Mutex semaphore
*
* Returns value:
*   BOOL;
\***********************************************************************/

BOOL EnterSem(ULONG ulWait)
{
    ULONG   rc;
    HMTX    hmtx;

    if ((rc = DosRequestMutexSem(hmtxSpyHook, ulWait)) == 0)
        return (TRUE);

    if (rc != ERROR_INVALID_HANDLE)
        return (FALSE);
#ifdef LATER
    * We should Close semaphore when we are done???
#endif

    hmtx = hmtxSpyHook;
    if (DosOpenMutexSem(NULL, &hmtx) != 0)
        return (FALSE);

    DosGetSharedMem(pheapSpyHook, PAG_READ | PAG_WRITE);

    return (DosRequestMutexSem(hmtxSpyHook, 100L) == 0);

}

/*************************** Private Function **************************\
* BOOL LeaveSem
*
* Effect:
*   Enters the Main spy Mutex semaphore
*
* Returns value:
*   BOOL;
\***********************************************************************/

BOOL LeaveSem()
{
    return (DosReleaseMutexSem(hmtxSpyHook) == 0);

}



/*************************** Private Function **************************\
* BOOL SignalEvent
*
* Effect:
*   Signal an event to spy to let him know something is available.
*
* Returns value:
*   BOOL;
\***********************************************************************/

BOOL SignalEvent()
{
    ULONG   rc;
    HEV     hev;

    if ((rc = DosPostEventSem(hevSpyMsg)) == 0)
        return (TRUE);

    if (rc != ERROR_INVALID_HANDLE)
        return (FALSE);
#ifdef LATER
    * We should Close semaphore when we are done???
#endif

    hev = hevSpyMsg;
    if (DosOpenEventSem(NULL, &hev) != 0)
        return (FALSE);

    return (DosPostEventSem(hevSpyMsg) == 0);

}

unix.superglobalmegacorp.com

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