驱动程序的取消IRP

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

你可能感兴趣的:(驱动程序的取消IRP)