使用 IoConnectInterruptEx 的 CONNECT_MESSAGE_BASED 版本
对于 Windows Vista 和更高版本的操作系统,驱动程序可以使用 ioConnectInterruptEx CONNECT_MESSAGE_BASED 版本为驱动程序的消息信号中断注册 ISR。 驱动程序为 Parameters-Version> 指定值 CONNECT_MESSAGE_BASED,并使用 Parameters-MessageBased> 的成员指定操作的其他参数。
Parameters-MessageBased.PhysicalDeviceObject> 指定 ISR 服务的设备的 PDO。 系统使用设备对象自动识别设备的消息信号中断。
Parameters-MessageBased.MessageServiceRoutine> 指向 InterruptMessageService 例程,而 Parameters-MessageBased.ServiceContext> 指定系统作为 ServiceContext 参数传递给 InterruptMessageService 的值。 驱动程序可以使用此来传递上下文信息。 有关传递上下文信息的详细信息,请参阅 提供 ISR 上下文信息。
驱动程序还可以在 Parameters-MessageBased.FallBackServiceRoutine> 中指定回退 InterruptMessageService 例程。 如果设备具有基于线路的中断,但没有消息信号中断,系统将改为注册 InterruptMessageService 例程来为基于线路的中断提供服务。 在这种情况下,系统会将 Parameters-MessageBased.ServiceContext> 作为 ServiceContext 参数传递给 InterruptService。 IoConnectInterruptEx 将 Parameters-Version> 更新为 CONNECT_LINE_BASED(如果它注册了回退例程)。
Parameters-MessageBased.ConnectionContext> 指向一个变量,该变量接收指向用于 InterruptMessageService) 结构的IO_INTERRUPT_MESSAGE_INFO (或用于 InterruptService) 的 KINTERRUPT 结构 (的指针。 驱动程序可以使用收到的指针删除 ISR。 有关详细信息,请参阅 删除 ISR。
驱动程序可以选择在 Parameters-MessageBased.SpinLock> 中指定一个旋转锁,供系统在与 ISR 同步时使用。 大多数驱动程序只能指定 NULL ,使系统能够代表驱动程序分配旋转锁。 有关与 ISR 同步的详细信息,请参阅 同步对设备数据的访问。
下面的代码示例演示如何使用 CONNECT_MESSAGE_BASED 注册 InterruptMessageService 例程。
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( ¶ms, 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(¶ms);
if (NT_SUCCESS(status)) {
// We record the type of ISR registered.
devExt->IsrType = params.Version;
} else {
// Operation failed. Handle error.
...
}