Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

165 lines
4.1 KiB

  1. /**************************************************************************
  2. * NOTIFY1.C
  3. *
  4. * Routines used to implement the Debugger Notification API in
  5. * TOOLHELP.DLL
  6. *
  7. **************************************************************************/
  8. #include <string.h>
  9. #include "toolpriv.h"
  10. /* ----- Global variables ----- */
  11. WORD wNotifyInstalled;
  12. NOTIFYSTRUCT NEAR *npNotifyHead;
  13. NOTIFYSTRUCT NEAR *npNotifyNext;
  14. /* NotifyRegister
  15. * Registers a debugger notification callback. This callback will
  16. * be called whenever KERNEL has a notification to be sent.
  17. * The format of the call to the callback function is documented
  18. * elsewhere.
  19. */
  20. BOOL TOOLHELPAPI NotifyRegister(
  21. HANDLE hTask,
  22. LPFNNOTIFYCALLBACK lpfn,
  23. WORD wFlags)
  24. {
  25. NOTIFYSTRUCT *pInfo;
  26. NOTIFYSTRUCT *pTemp;
  27. /* Make sure TOOLHELP.DLL is installed */
  28. if (!wLibInstalled)
  29. return FALSE;
  30. /* If the notification hook has not yet been installed, install it */
  31. if (!wNotifyInstalled)
  32. {
  33. /* Make sure we can get a hook! */
  34. if (!NotifyInit())
  35. return FALSE;
  36. wNotifyInstalled = TRUE;
  37. }
  38. /* NULL hTask means current task */
  39. if (!hTask)
  40. hTask = GetCurrentTask();
  41. /* Register a death signal handler for this task (does nothing if one
  42. * is already installed.
  43. */
  44. SignalRegister(hTask);
  45. /* Check to see if this task is already registered */
  46. for (pInfo = npNotifyHead ; pInfo ; pInfo = pInfo->pNext)
  47. if (pInfo->hTask == hTask)
  48. return FALSE;
  49. /* Allocate a new NOTIFYSTRUCT structure */
  50. pInfo = (NOTIFYSTRUCT *)LocalAlloc(LMEM_FIXED, sizeof (NOTIFYSTRUCT));
  51. if (!pInfo)
  52. return FALSE;
  53. /* Fill in the useful fields */
  54. pInfo->hTask = hTask;
  55. pInfo->wFlags = wFlags;
  56. pInfo->lpfn = lpfn;
  57. /* If this is the only handler, just insert it */
  58. if (!npNotifyHead)
  59. {
  60. pInfo->pNext = npNotifyHead;
  61. npNotifyHead = pInfo;
  62. }
  63. /* Otherwise, insert at the end of the list */
  64. else
  65. {
  66. for (pTemp = npNotifyHead ; pTemp->pNext ; pTemp = pTemp->pNext)
  67. ;
  68. pInfo->pNext = pTemp->pNext;
  69. pTemp->pNext = pInfo;
  70. }
  71. return TRUE;
  72. }
  73. /* NotifyUnRegister
  74. * Called by an app whose callback is no longer to be used.
  75. * NULL hTask uses current task.
  76. */
  77. BOOL TOOLHELPAPI NotifyUnRegister(
  78. HANDLE hTask)
  79. {
  80. NOTIFYSTRUCT *pNotify;
  81. NOTIFYSTRUCT *pBefore;
  82. /* Make sure we have notifications installed and that TOOLHELP is OK */
  83. if (!wLibInstalled || !wNotifyInstalled)
  84. return FALSE;
  85. /* NULL hTask means current task */
  86. if (!hTask)
  87. hTask = GetCurrentTask();
  88. /* First try to find the task */
  89. pBefore = NULL;
  90. for (pNotify = npNotifyHead ; pNotify ; pNotify = pNotify->pNext)
  91. if (pNotify->hTask == hTask)
  92. break;
  93. else
  94. pBefore = pNotify;
  95. if (!pNotify)
  96. return FALSE;
  97. /* Unhook the death signal proc only if there is no interrupt handler */
  98. if (!InterruptIsHooked(hTask))
  99. SignalUnRegister(hTask);
  100. /* Check to see if the notification handler is about to use this entry.
  101. * If it is, we point it to the next one, if any.
  102. */
  103. if (npNotifyNext == pNotify)
  104. npNotifyNext = pNotify->pNext;
  105. /* Remove it from the list */
  106. if (!pBefore)
  107. npNotifyHead = pNotify->pNext;
  108. else
  109. pBefore->pNext = pNotify->pNext;
  110. /* Free the structure */
  111. LocalFree((HANDLE)pNotify);
  112. /* If there are no more handlers, unhook the callback */
  113. if (!npNotifyHead)
  114. {
  115. NotifyUnInit();
  116. wNotifyInstalled = FALSE;
  117. }
  118. return TRUE;
  119. }
  120. /* ----- Helper functions ----- */
  121. /* NotifyIsHooked
  122. * Returns TRUE iff the parameter task already has a notification hook.
  123. */
  124. BOOL PASCAL NotifyIsHooked(
  125. HANDLE hTask)
  126. {
  127. NOTIFYSTRUCT *pNotify;
  128. /* Loop thorugh all notifications */
  129. for (pNotify = npNotifyHead ; pNotify ; pNotify = pNotify->pNext)
  130. if (pNotify->hTask == hTask)
  131. break;
  132. /* Return found/not found */
  133. return (BOOL)pNotify;
  134. }