windows-nt/Source/XPSP1/NT/base/mvdm/wow16/toolhelp/notify1.c
2020-09-26 16:20:57 +08:00

166 lines
4.1 KiB
C

/**************************************************************************
* NOTIFY1.C
*
* Routines used to implement the Debugger Notification API in
* TOOLHELP.DLL
*
**************************************************************************/
#include <string.h>
#include "toolpriv.h"
/* ----- Global variables ----- */
WORD wNotifyInstalled;
NOTIFYSTRUCT NEAR *npNotifyHead;
NOTIFYSTRUCT NEAR *npNotifyNext;
/* NotifyRegister
* Registers a debugger notification callback. This callback will
* be called whenever KERNEL has a notification to be sent.
* The format of the call to the callback function is documented
* elsewhere.
*/
BOOL TOOLHELPAPI NotifyRegister(
HANDLE hTask,
LPFNNOTIFYCALLBACK lpfn,
WORD wFlags)
{
NOTIFYSTRUCT *pInfo;
NOTIFYSTRUCT *pTemp;
/* Make sure TOOLHELP.DLL is installed */
if (!wLibInstalled)
return FALSE;
/* If the notification hook has not yet been installed, install it */
if (!wNotifyInstalled)
{
/* Make sure we can get a hook! */
if (!NotifyInit())
return FALSE;
wNotifyInstalled = 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 (pInfo = npNotifyHead ; pInfo ; pInfo = pInfo->pNext)
if (pInfo->hTask == hTask)
return FALSE;
/* Allocate a new NOTIFYSTRUCT structure */
pInfo = (NOTIFYSTRUCT *)LocalAlloc(LMEM_FIXED, sizeof (NOTIFYSTRUCT));
if (!pInfo)
return FALSE;
/* Fill in the useful fields */
pInfo->hTask = hTask;
pInfo->wFlags = wFlags;
pInfo->lpfn = lpfn;
/* If this is the only handler, just insert it */
if (!npNotifyHead)
{
pInfo->pNext = npNotifyHead;
npNotifyHead = pInfo;
}
/* Otherwise, insert at the end of the list */
else
{
for (pTemp = npNotifyHead ; pTemp->pNext ; pTemp = pTemp->pNext)
;
pInfo->pNext = pTemp->pNext;
pTemp->pNext = pInfo;
}
return TRUE;
}
/* NotifyUnRegister
* Called by an app whose callback is no longer to be used.
* NULL hTask uses current task.
*/
BOOL TOOLHELPAPI NotifyUnRegister(
HANDLE hTask)
{
NOTIFYSTRUCT *pNotify;
NOTIFYSTRUCT *pBefore;
/* Make sure we have notifications installed and that TOOLHELP is OK */
if (!wLibInstalled || !wNotifyInstalled)
return FALSE;
/* NULL hTask means current task */
if (!hTask)
hTask = GetCurrentTask();
/* First try to find the task */
pBefore = NULL;
for (pNotify = npNotifyHead ; pNotify ; pNotify = pNotify->pNext)
if (pNotify->hTask == hTask)
break;
else
pBefore = pNotify;
if (!pNotify)
return FALSE;
/* Unhook the death signal proc only if there is no interrupt handler */
if (!InterruptIsHooked(hTask))
SignalUnRegister(hTask);
/* Check to see if the notification handler is about to use this entry.
* If it is, we point it to the next one, if any.
*/
if (npNotifyNext == pNotify)
npNotifyNext = pNotify->pNext;
/* Remove it from the list */
if (!pBefore)
npNotifyHead = pNotify->pNext;
else
pBefore->pNext = pNotify->pNext;
/* Free the structure */
LocalFree((HANDLE)pNotify);
/* If there are no more handlers, unhook the callback */
if (!npNotifyHead)
{
NotifyUnInit();
wNotifyInstalled = FALSE;
}
return TRUE;
}
/* ----- Helper functions ----- */
/* NotifyIsHooked
* Returns TRUE iff the parameter task already has a notification hook.
*/
BOOL PASCAL NotifyIsHooked(
HANDLE hTask)
{
NOTIFYSTRUCT *pNotify;
/* Loop thorugh all notifications */
for (pNotify = npNotifyHead ; pNotify ; pNotify = pNotify->pNext)
if (pNotify->hTask == hTask)
break;
/* Return found/not found */
return (BOOL)pNotify;
}