154 lines
3.5 KiB
C
154 lines
3.5 KiB
C
/**************************************************************************
|
|
* INT1.C
|
|
*
|
|
* Routines used to implement the interrupt trapping API in
|
|
* TOOLHELP.DLL
|
|
*
|
|
**************************************************************************/
|
|
|
|
#include <string.h>
|
|
#include "toolpriv.h"
|
|
|
|
/* ----- Global variables ----- */
|
|
WORD wIntInstalled;
|
|
INTERRUPT NEAR *npIntHead;
|
|
|
|
/* InterruptRegister
|
|
* Registers an interrupt callback.
|
|
*/
|
|
|
|
BOOL TOOLHELPAPI InterruptRegister(
|
|
HANDLE hTask,
|
|
FARPROC lpfnCallback)
|
|
{
|
|
INTERRUPT *pInt;
|
|
INTERRUPT *pTemp;
|
|
|
|
/* Make sure TOOLHELP.DLL is installed */
|
|
if (!wLibInstalled)
|
|
return FALSE;
|
|
|
|
/* If the interrupt hook has not yet been installed, install it */
|
|
if (!wIntInstalled)
|
|
{
|
|
/* Make sure we can hook! */
|
|
if (!InterruptInit())
|
|
return FALSE;
|
|
wIntInstalled = TRUE;
|
|
}
|
|
|
|
/* NULL hTask means current task */
|
|
if (!hTask)
|
|
hTask = GetCurrentTask();
|
|
|
|
/* Register a death signal handler for this task (does nothing if one
|
|
* is already installed.
|
|
*/
|
|
SignalRegister(hTask);
|
|
|
|
/* Check to see if this task is already registered */
|
|
for (pInt = npIntHead ; pInt ; pInt = pInt->pNext)
|
|
if (pInt->hTask == hTask)
|
|
return FALSE;
|
|
|
|
/* Allocate a new INTERRUPT structure */
|
|
pInt = (INTERRUPT *)LocalAlloc(LMEM_FIXED, sizeof (INTERRUPT));
|
|
if (!pInt)
|
|
return FALSE;
|
|
|
|
/* Fill in the useful fields */
|
|
pInt->hTask = hTask;
|
|
pInt->lpfn = (LPFNCALLBACK) lpfnCallback;
|
|
|
|
/* If this is the only handler, just insert it */
|
|
if (!npIntHead)
|
|
{
|
|
pInt->pNext = npIntHead;
|
|
npIntHead = pInt;
|
|
}
|
|
|
|
/* Otherwise, insert at the end of the list */
|
|
else
|
|
{
|
|
for (pTemp = npIntHead ; pTemp->pNext ; pTemp = pTemp->pNext)
|
|
;
|
|
pInt->pNext = pTemp->pNext;
|
|
pTemp->pNext = pInt;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* InterruptUnRegister
|
|
* Called by an app whose callback is no longer to be used.
|
|
* NULL hTask uses current task.
|
|
*/
|
|
|
|
BOOL TOOLHELPAPI InterruptUnRegister(
|
|
HANDLE hTask)
|
|
{
|
|
INTERRUPT *pInt;
|
|
INTERRUPT *pBefore;
|
|
|
|
/* Make sure we have interrupt installed and that TOOLHELP is OK */
|
|
if (!wLibInstalled || !wIntInstalled)
|
|
return FALSE;
|
|
|
|
/* NULL hTask means current task */
|
|
if (!hTask)
|
|
hTask = GetCurrentTask();
|
|
|
|
/* First try to find the task */
|
|
pBefore = NULL;
|
|
for (pInt = npIntHead ; pInt ; pInt = pInt->pNext)
|
|
if (pInt->hTask == hTask)
|
|
break;
|
|
else
|
|
pBefore = pInt;
|
|
if (!pInt)
|
|
return FALSE;
|
|
|
|
/* Unhook the death signal proc only if there is no interrupt handler */
|
|
if (!NotifyIsHooked(hTask))
|
|
SignalUnRegister(hTask);
|
|
|
|
/* Remove it from the list */
|
|
if (!pBefore)
|
|
npIntHead = pInt->pNext;
|
|
else
|
|
pBefore->pNext = pInt->pNext;
|
|
|
|
/* Free the structure */
|
|
LocalFree((HANDLE)pInt);
|
|
|
|
/* If there are no more handlers, unhook the callback */
|
|
if (!npIntHead)
|
|
{
|
|
InterruptUnInit();
|
|
wIntInstalled = FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* ----- Helper functions ----- */
|
|
|
|
/* InterruptIsHooked
|
|
* Returns TRUE iff the parameter task already has a interrupt hook.
|
|
*/
|
|
|
|
BOOL PASCAL InterruptIsHooked(
|
|
HANDLE hTask)
|
|
{
|
|
INTERRUPT *pInt;
|
|
|
|
/* Loop thorugh all interrupts */
|
|
for (pInt = npIntHead ; pInt ; pInt = pInt->pNext)
|
|
if (pInt->hTask == hTask)
|
|
break;
|
|
|
|
/* Return found/not found */
|
|
return (BOOL)pInt;
|
|
}
|