当前位置: 代码迷 >> 驱动开发 >> 取消当前 IRP 执行的过程是怎样的?解决办法
  详细解决方案

取消当前 IRP 执行的过程是怎样的?解决办法

热度:1093   发布时间:2016-04-28 11:24:33.0
取消当前 IRP 执行的过程是怎样的?
#pragma code_seg("PAGE")
NTSTATUS MyWdmRead(PDEVICE_OBJECT DeviceObject,PIRP Irp)
{  
KdPrint(("enter MyWdmRead"));

PMY_DEVICE_EXTENSION pDevExt =(PMY_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
IoMarkIrpPending(Irp); 

IoSetCancelRoutine(Irp,OnCancelIrpRead); 
KIRQL oldirql;
KeRaiseIrql(DISPATCH_LEVEL,&oldirql
if(! KeInsertDeviceQueue(&pDevExt->ReadIrpQueue,&Irp->Tail.Overlay.DeviceQueueEntry));

MyStartIoRead(DeviceObject,Irp);// 会将队列中所有的IRP都处理掉
}
KeLowerIrql(oldirql);

KdPrint(("leave MyWdmRead "));
return STATUS_PENDING;
}
[/code]

C/C++ code
#pragma code_seg()VOID MyStartIoRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP pStartIoIrp){    KdPrint(("Enter MyStartIoRead"));    PMY_DEVICE_EXTENSION pDevExt=(PMY_DEVICE_EXTENSION)DeviceObject->DeviceExtension;    PKDEVICE_QUEUE_ENTRY Device_Entry;    PIRP pIrp=pStartIoIrp;    do     {                        NTSTATUS Status=STATUS_SUCCESS;        PIO_STACK_LOCATION stack=IoGetCurrentIrpStackLocation(Irp);        ULONG ulReadLength =stack->Parameters.Read.Length;              Irp->IoStatus.Status=Status;        Irp->IoStatus.Information=ulReadLength;        memset(Irp->AssociatedIrp.SystemBuffer,0xAA,ulReadLength);        IoCompleteRequest(Irp,IO_NO_INCREMENT);        //完成这个IRP                                //以下代码用来得到下一次循环中要处理的IRP        Device_Entry=KeRemoveDeviceQueue(&pDevExt->ReadIrpQueue);//从队列中移除一个IRP        //得到IRP中的List_ENTRY                if(Device_Entry==NULL)  //如果队列已经为空        {            break; //退出 do while 循换        }                 pIrp=CONTAINING_RECORD(Device_Entry,IRP,Tail.Overlay.DeviceQueueEntry);        //通过LIST_ENTRY得到Irp 这个Irp是下次循环中要处理的    } while (1);    KdPrint(("leave My startIoRead  function"));}



想要给上面这个自定义 IRP队列、自定义StartIo例程 写 Cancel例程

还在startIo 队列中等待执行的的Irp 还可以理解 从等待队列中摘除即可

如果是正在startIo例程中执行的IRP 比如已经在上面的do 循环里执行了一半了  

这时取消 该是什么样的?  
  比如如果在Cancel例程里 返回status_cancelled 用 IoCompleteRequest结束了这个IRP
   
  那DO循环里的代码才执行了一半 继续执行下去会怎样 

该怎么处理Cancek例程 要取消的IRP 是当前正执行IRP的情况?

------解决方案--------------------
1 If IRP currently being processed in StartIo or interrupt handler
then just quit without completing IRP. The IRP Cancel flag will
be detected in due course and the IRP completed (as cancelled) then.
2 If IRP still in StartIo queue then remove it and complete it as cancelled.
  相关解决方案