取消当前 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]
#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"));}