总线驱动程序如果想捕获到相关设备插入拔出事件,可以在其IRP_MN_START_DEVICE结束处用IoRegisterPlugPlayNotification注册一回调函数。
IoRegisterPlugPlayNotification原型如下:
NTSTATUS
IoRegisterPlugPlayNotification(
IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory,
IN ULONG EventCategoryFlags,
IN PVOID EventCategoryData OPTIONAL,
IN PDRIVER_OBJECT DriverObject,
IN PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine,
IN PVOID Context,
OUT PVOID *NotificationEntry
);
各个参数的细节可以参考MSDN。
比如我想在驱动中得知硬盘插入拔出的事件,那么我可以如下使用:
IoRegisterPlugPlayNotification(
EventCategoryDeviceInterfaceChange,
PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
(PVOID)(&GUID_DEVINTERFACE_DISK),
DeviceData->pDriverObject,
(PDRIVER_NOTIFICATION_CALLBACK_ROUTINE)DriverDevInterxNotifyCallBack,
(PVOID)DeviceData,
&NotificationEntry);
上面的DriverDevInterxNotifyCallBack在收硬盘在插入和拔出时会被调用。
此回调函数的原型如下:
typedef NTSTATUS (*PDRIVER_NOTIFICATION_CALLBACK_ROUTINE) (
IN PVOID NotificationStructure,
IN PVOID Context
);
这里需要注意一点,就是IoRegisterPlugPlayNotification的最后一个参数,它需要的是一个地址,此地址指向的内存不用自己分配,但需要自己释放。
例子中NotificationEntry的定义如下:
PVOID NotificationEntry = NULL;
然后就直接调用。