/************************************************************************** * INT1.C * * Routines used to implement the interrupt trapping API in * TOOLHELP.DLL * **************************************************************************/ #include #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; }