按照书上写的,做一个键盘驱动过滤。
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{
//...
DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
DriverObject->DriverUnload = Unload;
//...
IoCreateDevice(... ,FILE_DEVICE_KEYBOARD, ...);
//使用IoAttachDevice函数挂载在KeyboardClass0上面
//...
}
NTSTATUS Ctrl2capReadComplete( PDEVICE_OBJECT DeviceObject, PIRP Irp,PVOID Context )
{
//处理 KEYBOARD_INPUT_DATA
}
NTSTATUS DispatchRead( PDEVICE_OBJECT DeviceObject,PIRP Irp )
{
IoSetCompletionRoutine(... ,ReadComplete, ...);
}
VOID Unload(IN PDRIVER_OBJECT Driver )
{
UNREFERENCED_PARAMETER(Driver);
ASSERT(NULL == Driver->DeviceObject);
}
但是原文中Unload没有删除设备,所以我改成了下面这样。
VOID Unload(IN PDRIVER_OBJECT Driver )
{
//KeDelayExecutionThread 暂停5秒钟。
IoDeleteDevice(Driver->DeviceObject);
}
结果卸载驱动的时候蓝屏了,其他都正常运行。
请问怎样安全的动态卸载驱动?
------解决方案--------------------
我觉得不应该直接删除设备,因为该设备是绑定在键盘上的,
应该先接触该设备绑定,然后再删除该设备,这样应该才是正常的顺序。
------解决方案--------------------
一般情况下是在PnP IRP_MN_REMOVE_DEVICE request处理线程里面去IoDeleteDevice的。
在Uload Driver里面,只负责去释放一下驱动加载时候分配的内存或者是注销驱动加载过程中注册的一些信息。
另外,教材里面的例子是不会保证正确性的。很多教材的例子只是为了阐述一些知识点,会忽略很多错误处理和省略一些必需的IRP处理。
------解决方案--------------------
键盘的IRP是异步的, 在按下键盘的之前IRP已经发出了.
如果你卸载了驱动, 那个已经发出的IRP的所有分发函数都指向了无效地址, 你一按键盘就蓝屏了
卸载的时候需要取消最后一个IRP
可以在Read的时候记录那个IRP, ReadCompletion的时候取消该IRP的记录, Unload的时候如果存在pending的IRP就将它取消了