StartIO/CancelIO

     驱动程序中的StartIO,CancelIO比较复杂,也很可能出错。翻了一下WDK,删除了一些无关紧要的code,贴在这里方便以后查阅:

  1. BOOLEAN
  2. IoCancelIrp(
  3.     IN PIRP Irp
  4.     )
  5. {
  6.     PDRIVER_CANCEL cancelRoutine;
  7.     KIRQL irql;
  8.     BOOLEAN returnValue;
  9.     ASSERT( Irp->Type == IO_TYPE_IRP );
  10.     //
  11.     // Acquire the cancel spin lock.
  12.     //
  13.     IoAcquireCancelSpinLock( &irql );
  14.     //
  15.     // Set the cancel flag in the IRP.
  16.     //
  17.     Irp->Cancel = TRUE;
  18.     //
  19.     // Obtain the address of the cancel routine, and if one was specified,
  20.     // invoke it.
  21.     //
  22.     cancelRoutine = (PDRIVER_CANCEL) (ULONG_PTR) InterlockedExchangePointer( (PVOID *) &Irp->CancelRoutine, NULL );
  23.     if (cancelRoutine) {
  24.         Irp->CancelIrql = irql;
  25.         cancelRoutine( Irp->Tail.Overlay.CurrentStackLocation->DeviceObject,
  26.                        Irp );
  27.         //
  28.         // The cancel spinlock should have been released by the cancel routine.
  29.         //
  30.         return(TRUE);
  31.     } else {
  32.         //
  33.         // There was no cancel routine, so release the cancel spinlock and
  34.         // return indicating the Irp was not currently cancelable.
  35.         //
  36.         IoReleaseCancelSpinLock( irql );
  37.         return(FALSE);
  38.     }
  39. }
  1. VOID
  2. IoStartPacket(
  3.     IN PDEVICE_OBJECT DeviceObject,
  4.     IN PIRP Irp,
  5.     IN PULONG Key OPTIONAL,
  6.     IN PDRIVER_CANCEL CancelFunction OPTIONAL
  7.     )
  8. /*++
  9. Routine Description:
  10.     This routine attempts to start the specified packet request (IRP) on the
  11.     specified device.  If the device is already busy, then the packet is
  12.     simply queued to the device queue. If a non-NULL CancelFunction is
  13.     supplied, it will be put in the IRP.  If the IRP has been canceled, the
  14.     CancelFunction will be called after the IRP has been inserted into the
  15.     queue or made the current packet.
  16. Arguments:
  17.     DeviceObject - Pointer to device object itself.
  18.     Irp - I/O Request Packet which should be started on the device.
  19.     Key - Key to be used in inserting packet into device queue;  optional
  20.         (if not specified, then packet is inserted at the tail).
  21.     CancelFunction - Pointer to an optional cancel routine.
  22. Return Value:
  23.     None.
  24. --*/
  25. {
  26.     KIRQL oldIrql;
  27.     KIRQL cancelIrql = PASSIVE_LEVEL;
  28.     BOOLEAN i;
  29.     //
  30.     // Raise the IRQL of the processor to dispatch level for synchronization.
  31.     //
  32.     KeRaiseIrql( DISPATCH_LEVEL, &oldIrql );
  33.     //
  34.     // If the driver has indicated that packets are cancelable, then acquire
  35.     // the cancel spinlock and set the address of the cancel function to
  36.     // indicate that the packet is not only cancelable, but indicates what
  37.     // routine to invoke should it be cancelled.
  38.     //
  39.     if (CancelFunction) {
  40.         IoAcquireCancelSpinLock( &cancelIrql );
  41.         Irp->CancelRoutine = CancelFunction;
  42.     }
  43.     i = KeInsertDeviceQueue( &DeviceObject->DeviceQueue,
  44.                              &Irp->Tail.Overlay.DeviceQueueEntry );
  45.     //
  46.     // If the packet was not inserted into the queue, then this request is
  47.     // now the current packet for this device.  Indicate so by storing its
  48.     // address in the current IRP field, and begin processing the request.
  49.     //
  50.     if (!i) {
  51.         DeviceObject->CurrentIrp = Irp;
  52.         if (CancelFunction) {
  53.             IoReleaseCancelSpinLock( cancelIrql );
  54.         }
  55.         //
  56.         // Invoke the driver's start I/O routine to get the request going on the device.
  57.         // The StartIo routine should handle the cancellation.
  58.         //
  59.         DeviceObject->DriverObject->DriverStartIo( DeviceObject, Irp );
  60.     } else {
  61.         //
  62.         // The packet was successfully inserted into the device's work queue.
  63.         // Make one last check to determine whether or not the packet has
  64.         // already been marked cancelled.  If it has, then invoke the
  65.         // driver's cancel routine now.  Note that because the cancel
  66.         // spinlock is currently being held, an attempt to cancel the request
  67.         // from another processor at this point will simply wait until this
  68.         // routine is finished, and then get it cancelled.
  69.         //
  70.         if (CancelFunction) {
  71.             if (Irp->Cancel) {
  72.                 Irp->CancelIrql = cancelIrql;
  73.                 Irp->CancelRoutine = (PDRIVER_CANCEL) NULL;
  74.                 CancelFunction( DeviceObject, Irp );
  75.             } else {
  76.                 IoReleaseCancelSpinLock( cancelIrql );
  77.             }
  78.         }
  79.     }
  80.     //
  81.     // Restore the IRQL back to its value upon entry to this function before
  82.     // returning to the caller.
  83.     //
  84.     KeLowerIrql( oldIrql );
  85. }
  1. VOID
  2. IopStartNextPacket(
  3.     IN PDEVICE_OBJECT DeviceObject,
  4.     IN LOGICAL Cancelable
  5.     )
  6. /*++
  7. Routine Description:
  8.     This routine is invoked to dequeue the next packet (IRP) from the
  9.     specified device work queue and invoke the device driver's start I/O
  10.     routine for it.  If the Cancelable parameter is TRUE, then the update of
  11.     current IRP is synchronized using the cancel spinlock.
  12. Arguments:
  13.     DeviceObject - Pointer to device object itself.
  14.     Cancelable - Indicates that IRPs in the device queue may be cancelable.
  15. Return Value:
  16.     None.
  17. --*/
  18. {
  19.     KIRQL cancelIrql = PASSIVE_LEVEL;
  20.     PIRP irp;
  21.     PKDEVICE_QUEUE_ENTRY packet;
  22.     //
  23.     // Begin by checking to see whether or not this driver's requests are
  24.     // to be considered cancelable.  If so, then acquire the cancel spinlock.
  25.     //
  26.     if (Cancelable) {
  27.         IoAcquireCancelSpinLock( &cancelIrql );
  28.     }
  29.     //
  30.     // Clear the current IRP field before starting another request.
  31.     //
  32.     DeviceObject->CurrentIrp = (PIRP) NULL;
  33.     //
  34.     // Remove the next packet from the head of the queue.  If a packet was
  35.     // found, then process it.
  36.     //
  37.     packet = KeRemoveDeviceQueue( &DeviceObject->DeviceQueue );
  38.     if (packet) {
  39.         irp = CONTAINING_RECORD( packet, IRP, Tail.Overlay.DeviceQueueEntry );
  40.         //
  41.         // A packet was located so make it the current packet for this
  42.         // device.
  43.         //
  44.         DeviceObject->CurrentIrp = irp;
  45.         if (Cancelable) {
  46.            
  47.            IoReleaseCancelSpinLock( cancelIrql );
  48.         }
  49.         //
  50.         // Invoke the driver's start I/O routine for this packet.
  51.         //
  52.         DeviceObject->DriverObject->DriverStartIo( DeviceObject, irp );
  53.     } else {
  54.         //
  55.         // No packet was found, so simply release the cancel spinlock if
  56.         // it was acquired.
  57.         //
  58.         if (Cancelable) {
  59.            IoReleaseCancelSpinLock( cancelIrql );
  60.         }
  61.     }
  62. }
  1. #define IoSetCancelRoutine( Irp, NewCancelRoutine ) (  /
  2.     (PDRIVER_CANCEL) (ULONG_PTR) InterlockedExchangePointer( (PVOID *) &(Irp)->CancelRoutine, (PVOID) (ULONG_PTR)(NewCancelRoutine) ) )
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值