当应用层发出的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>