Using the CONNECT_MESSAGE_BASED Version of IoConnectInterruptEx

For Windows Vista and later operating systems, a driver can use the CONNECT_MESSAGE_BASED version of IoConnectInterruptEx to register an ISR for the driver's message-signaled interrupts. The driver specifies a value of CONNECT_MESSAGE_BASED for Parameters->Version, and uses the members of Parameters->MessageBased to specify the other parameters of the operation.

  • Parameters->MessageBased.PhysicalDeviceObject specifies the PDO for the device that the ISR services. The system uses the device object to automatically identify the device's message-signaled interrupts.

  • Parameters->MessageBased.MessageServiceRoutine points to the InterruptMessageService routine, while Parameters->MessageBased.ServiceContext specifies the value that the system passes as the ServiceContext parameter to InterruptMessageService. The driver can use this to pass context information. For more information about passing context information, see Providing ISR Context Information.

  • The driver can also specify a fallback InterruptMessageService routine in Parameters->MessageBased.FallBackServiceRoutine. If the device has line-based interrupts, but no message-signaled interrupts, the system will instead register the InterruptMessageService routine to service the line-based interrupts. In this case, the system passes Parameters->MessageBased.ServiceContext as the ServiceContext parameter to InterruptService. IoConnectInterruptEx updates Parameters->Version to CONNECT_LINE_BASED if it registered the fallback routine.

  • Parameters->MessageBased.ConnectionContext points to a variable that receives a pointer to either a IO_INTERRUPT_MESSAGE_INFO (for InterruptMessageService) structure or a KINTERRUPT structure (for InterruptService). The driver can use the received pointer to remove the ISR. For more information, see Removing an ISR.

  • Drivers can optionally specify a spin lock in Parameters->MessageBased.SpinLock for the system to use when synchronizing with the ISR. Most drivers can just specify NULL to enable the system to allocate a spin lock on behalf of the driver. For more information about synchronizing with an ISR, see Synchronizing Access to Device Data.

The following code example demonstrates how to register an InterruptMessageService routine by using CONNECT_MESSAGE_BASED.

IO_CONNECT_INTERRUPT_PARAMETERS params;

// deviceExtension is a pointer to the driver's device extension. 
//     deviceExtension->IntInfo is a PVOID.
//     deviceExtension->IntType is a ULONG.
// deviceInterruptService is a pointer to the driver's InterruptService routine.
// deviceInterruptMessageService is a pointer to the driver's InterruptMessageService routine.
// PhysicalDeviceObject is a pointer to the device's PDO. 
// ServiceContext is a pointer to driver-specified context for the ISR.

RtlZeroMemory( &params, sizeof(IO_CONNECT_INTERRUPT_PARAMETERS) );
params.Version = CONNECT_MESSAGE_BASED;
params.MessageBased.PhysicalDeviceObject = PhysicalDeviceObject;
params.MessageBased.MessageServiceRoutine = deviceInterruptMessageService;
params.MessageBased.ServiceContext = ServiceContext;
params.MessageBased.SpinLock = NULL;
params.MessageBased.SynchronizeIrql = 0;
params.MessageBased.FloatingSave = FALSE;
params.MessageBased.FallBackServiceRoutine = deviceInterruptService;

status = IoConnectInterruptEx(&params);

if (NT_SUCCESS(status)) {
    // We record the type of ISR registered.
    devExt->IsrType = params.Version;
} else {
    // Operation failed. Handle error.
    ...
}