转载自: http://blog.csdn.net/zacklin/article/details/7612888
当应用层发出的IRP请求很久得不到处理的时候,有时需要把IRP请求取消,每一个IRP都可以对应一个取消例程,通过IoSetCancelRoutine(pIrp,CancelReadIRP);函数把IRP与取消例程进行关联,当要删除取消例程时,把第二个参数设为空即IoSetCancelRoutine(pIrp,NULL);即可。
程序员可以用IoCancelIrp函数取消IRP的请求,该函数在内部通过在IoAcquireCancelSpinLock函数获得取消自旋锁,因为在我们的取消例程中必须要调用IoReleaseCancelSpinLock函数释放取消自旋锁。在应用层可以通过调用CancelIrp取消IRP请求。
下面是驱动程序:
#include<ntddk.h> typedef struct _Ext { UNICODE_STRING devicename; UNICODE_STRING symbolicname; }DEVICE_EXTENSION,*PDEVICE_EXTENSION; VOID CancelReadIRP(IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp); VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject); NTSTATUS DeviceCreate(IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp); NTSTATUS DeviceClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp); NTSTATUS DeviceRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp); NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegistryPath) { NTSTATUS status=STATUS_SUCCESS; PDEVICE_OBJECT pDeviceObject=NULL; UNICODE_STRING DeviceName,Symbolname; PDEVICE_EXTENSION pDeviceExt=NULL; RtlInitUnicodeString(&DeviceName,L"\\Device\\Device_8"); RtlInitUnicodeString(&Symbolname,L"\\??\\Device_8_Symbol"); KdPrint(("Enter DriverEntry!\n")); pDriverObject->MajorFunction[IRP_MJ_CREATE]=DeviceCreate; pDriverObject->MajorFunction[IRP_MJ_CLOSE]=DeviceClose; pDriverObject->MajorFunction[IRP_MJ_READ]=DeviceRead; pDriverObject->DriverUnload=DriverUnload; status=IoCreateDevice(pDriverObject, sizeof(DEVICE_EXTENSION), &DeviceName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDeviceObject); if(!NT_SUCCESS(status)) { KdPrint(("\ncreate device fail!\n")); return status; } KdPrint(("\nCreate Device Successfully!\n")); pDeviceObject->Flags|=DO_BUFFERED_IO; status=IoCreateSymbolicLink(&Symbolname,&DeviceName); if(!NT_SUCCESS(status)) { KdPrint(("\nCreate symbolic fail!\n")); IoDeleteDevice(pDeviceObject); return status; } KdPrint(("\nCreate symbolicLink successfully!\n")); pDeviceExt=(PDEVICE_EXTENSION)pDeviceObject->DeviceExtension; pDeviceExt->devicename=DeviceName; pDeviceExt->symbolicname=Symbolname; return status; } VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject) { PDEVICE_OBJECT pDeviceObject; PDEVICE_EXTENSION pDeviceExt; pDeviceObject=pDriverObject->DeviceObject; if(pDeviceObject!=NULL) { pDeviceExt=(PDEVICE_EXTENSION)pDeviceObject->DeviceExtension; if(pDeviceExt!=NULL) { IoDeleteSymbolicLink(&pDeviceExt->symbolicname); IoDeleteDevice(pDeviceObject); KdPrint(("\nDriverUnload Successfully!\n")); return; } } KdPrint(("\nDriverUnload fail!\n")); } NTSTATUS DeviceCreate(IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp) { NTSTATUS status=STATUS_SUCCESS; KdPrint(("\nEnter Create Device \n")); pIrp->IoStatus.Status=status; pIrp->IoStatus.Information=0; IoCompleteRequest(pIrp,0); return status; } NTSTATUS DeviceClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp) { NTSTATUS status=STATUS_SUCCESS; KdPrint(("\nEnter Close Device \n")); pIrp->IoStatus.Status=status; pIrp->IoStatus.Information=0; IoCompleteRequest(pIrp,0); KdPrint(("\nClose Device Successfully!\n")); return status; } NTSTATUS DeviceRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp) { KdPrint(("\nEnter Read IRP \n")); IoSetCancelRoutine(pIrp,CancelReadIRP); IoMarkIrpPending(pIrp); KdPrint(("\nLeave Read IRP \n")); return STATUS_PENDING; } VOID CancelReadIRP(IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp) { KdPrint(("\nEnter CancelReadIRP\n")); pIrp->IoStatus.Status=STATUS_CANCELLED; pIrp->IoStatus.Information=0; IoCompleteRequest(pIrp,0); IoReleaseCancelSpinLock(pIrp->CancelIrql);//释放取消锁 KdPrint(("\nLeave CancelReadIRP\n")); }
下面的是应用层的测试程序:
#include<windows.h> #include<stdio.h> int main() { HANDLE hDevice=CreateFile("\\\\.\\Device_8_Symbol", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, NULL); if(hDevice==INVALID_HANDLE_VALUE) { printf("Open Device failed!\n"); return 1; } OVERLAPPED overlap1={0}; OVERLAPPED overlap2={0}; ULONG ulread; char buffer[10]; BOOL bread=ReadFile(hDevice,buffer,10,&ulread,&overlap1); if(!bread&&GetLastError()==ERROR_IO_PENDING) { printf("The Operation is pending\n"); } bread=ReadFile(hDevice,buffer,10,&ulread,&overlap2); if(!bread&&GetLastError()==ERROR_IO_PENDING) { printf("The Operation is pending\n"); } Sleep(3000); CancelIo(hDevice); CloseHandle(hDevice); return 0; }