InterruptRegister

3.1

  #include <toolhelp.h>    

  BOOL InterruptRegister(htask, lpfnIntCallback)    
  HTASK htask; /* handle of task, */  
  FARPROC lpfnIntCallback; /* address of callback function */

The InterruptRegister function installs a callback function to handle all system interrupts.

Parameters

htask

Identifies the task that is registering the callback function. The htask value is for registration purposes, not for filtering interrupts. Typically, this value is NULL, indicating the current task. The only time this value is not NULL is when an application requires more than one interrupt handler.

lpfnIntCallback

Points to the interrupt callback function that will handle interrupts. The Tool Helper library calls this function whenever a task receives an interrupt.

The lpfnIntCallback value is normally the return value of a call to the MakeProcInstance function. This causes the interrupt callback function to be entered with the AX register set to the selector of the application's data segment. Usually, an exported function prolog contains the following code:

mov  ds,ax

Return Value

The return value is nonzero if the function is successful. Otherwise, it is zero.

Comments

The syntax of the function pointed to by lpfnIntCallback is as follows:

void InterruptRegisterCallback(void)

InterruptRegisterCallback is a placeholder for the application-defined function name. The actual name must be exported by including it an EXPORTS in the application's module-definition file.

An interrupt callback function must be reentrant, must be page-locked, and must explicitly preserve all register values. When the Tool Helper library calls the function, the stack will be organized as shown in the following illustration.

The SS and SP values will not be on the stack unless a low-stack fault occurred. This fault is indicated by the high bit of the interrupt number being set.

When Windows calls a callback function, the AX register contains the DS value for the instance of the application that contains the callback function. For more information about this process, see the MakeProcInstance function.

Typically, an interrupt callback function is exported. If it is not exported, the developer should verify that the appropriate stack frame is generated, including the correct DS value.

An interrupt callback function must save and restore all register values. The function must also do one of the following:

Execute an retf instruction if it does not handle the interrupt. The Tool Helper library will pass the interrupt to the next appropriate handler in the interrupt handler list.

Terminate the application by using the TerminateApp function.

Correct the problem that caused the interrupt, clear the first 10 bytes of the stack, and execute an iret instruction. This action will restart execution at the specified address. An application may change this address, if necessary.

Execute a nonlocal goto to a known position in the application by using the Catch and Throw functions. This type of interrupt handling can be hazardous; the system may be in an unstable state and another fault may occur. Applications that handle interrupts in this way must verify that the fault was a result of the application's code.

The Tool Helper library supports the following interrupts:

Name Number Meaning

INT_DIV0 0 Divide-error exception
INT_1 1 Debugger interrupt
INT_3 3 Breakpoint interrupt
INT_UDINSTR 6 Invalid-opcode exception
INT_STKFAULT 12 Stack exception
INT_GPFAULT 13 General protection violation
INT_BADPAGEFAULT 14 Page fault not caused by normal virtual-memory operation
INT_CTLALTSYS RQ 256 User pressed CTRL+ALT+SYS RQ

The Tool Helper library returns interrupt numbers as word values. Normal software interrupts and processor faults are represented by numbers in the range 0 through 255. Interrupts specific to Tool Helper are represented by numbers greater than 255.

Some developers may wish to use CTRL+ALT+SYS RQ (Interrupt 256) to break into the debugger. Be cautious about implementing this interrupt, because the point at which execution stops will probably be in a sensitive part of the Windows kernel. All InterruptRegisterCallback functions must be page-locked to prevent problems when this interrupt is used. In addition, the debugger probably will not be able to perform user-interface functions. However, the debugger can use Tool Helper functions to set breakpoints and gather information. The debugger may also be able to use a debugging terminal or secondary screen to display information.

Low-stack Faults

A low-stack fault occurs when inadequate stack space is available on the faulting application's stack. For example, if any fault occurs when there is less than 128 bytes of stack space available or if runaway recursion depletes the stack, a low-stack fault occurs. The Tool Helper library processes a low-stack fault differently than it processes other faults.

A low-stack fault is indicated by the high-order bit of the interrupt number being set. For example, if a stack fault occurs and the SP value becomes invalid, the Tool Helper library will return the fault number as 0x800C rather than 0x000C.

Interrupt handlers designed to process low-stack faults must be aware that the Tool Helper library has passed a fault frame on a stack other that the faulting application's stack. The SS:SP value is on the stack because it was pushed before the rest of the information in the stack frame. The SS:SP value is available only for advisory purposes.

An interrupt handler should never restart the faulting instruction, because this will cause the system to crash. The handler may terminate the application with TerminateApp or pass the fault to the next handler in the interrupt-handler list.

Interrupt handlers should not assume that all stack faults are low-stack faults. For example, if an application accesses a stack-relative variable that is out of range, a stack fault will occur. This type of fault can be processed in the same manner as any general protection (GP) fault. If the high-order bit of the interrupt number is not set, the instruction can be restarted.

Interrupt handlers also should not assume that all low-stack faults are stack faults. Any fault that occurs when there is less than 128 bytes of stack available will cause a low-stack fault.

Interrupt callback functions that are not designed to process low-stack faults should execute an retf instruction so that the Tool Helper library will pass the fault to the next appropriate handler in the interrupt-handler list.

See Also

Catch, InterruptUnRegister, NotifyRegister, NotifyUnRegister, TerminateApp, Throw