StartIO常式————IoStartPacket、IoStartNextPacket、IoCancelIrp實現代碼

來源:互聯網
上載者:User
StartIO常式------------IoStartPacket、IoStartNextPacket、IoCancelIrp實現代碼

根據wdk代碼做的IoStartPacket、IoStartNextPacket、IoCancelIrp簡化版:

VOID
IoStartPacket(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PULONG Key OPTIONAL,
    IN PDRIVER_CANCEL CancelFunction OPTIONAL
    )
/*++
Routine Description:
    This routine attempts to start the specified packet request (IRP) on the
    specified device.  If the device is already busy, then the packet is
    simply queued to the device queue. If a non-NULL CancelFunction is
    supplied, it will be put in the IRP.  If the IRP has been canceled, the
    CancelFunction will be called after the IRP has been inserted into the
    queue or made the current packet.

Arguments:
    DeviceObject - Pointer to device object itself.
    Irp - I/O Request Packet which should be started on the device.
    Key - Key to be used in inserting packet into device queue;  optional
        (if not specified, then packet is inserted at the tail).
    CancelFunction - Pointer to an optional cancel routine.

Return Value:
    None.
--*/

{
    KIRQL oldIrql;
    KIRQL cancelIrql = PASSIVE_LEVEL;
    BOOLEAN i;

    // Raise the IRQL of the processor to dispatch level for synchronization.

    KeRaiseIrql( DISPATCH_LEVEL, &oldIrql );

    // If the driver has indicated that packets are cancelable, then acquire
    // the cancel spinlock and set the address of the cancel function to
    // indicate that the packet is not only cancelable, but indicates what
    // routine to invoke should it be cancelled.

    if (CancelFunction) {
        IoAcquireCancelSpinLock( &cancelIrql );
        Irp->CancelRoutine = CancelFunction;
    }
    i = KeInsertDeviceQueue( &DeviceObject->DeviceQueue,
                             &Irp->Tail.Overlay.DeviceQueueEntry );

    // If the packet was not inserted into the queue, then this request is
    // now the current packet for this device.  Indicate so by storing its
    // address in the current IRP field, and begin processing the request.

    if (!i) {
        DeviceObject->CurrentIrp = Irp;
        if (CancelFunction) {
            IoReleaseCancelSpinLock( cancelIrql );
        }

        // Invoke the driver's start I/O routine to get the request going on the device.

        // The StartIo routine should handle the cancellation.

        DeviceObject->DriverObject->DriverStartIo( DeviceObject, Irp );

    } else {

        // The packet was successfully inserted into the device's work queue.
        // Make one last check to determine whether or not the packet has
        // already been marked cancelled.  If it has, then invoke the
        // driver's cancel routine now.  Note that because the cancel
        // spinlock is currently being held, an attempt to cancel the request
        // from another processor at this point will simply wait until this
        // routine is finished, and then get it cancelled.

        if (CancelFunction) {
            if (Irp->Cancel) {
                Irp->CancelIrql = cancelIrql;
                Irp->CancelRoutine = (PDRIVER_CANCEL) NULL;
                CancelFunction( DeviceObject, Irp );
            } else {
                IoReleaseCancelSpinLock( cancelIrql );
            }
        }
    }

    // Restore the IRQL back to its value upon entry to this function before
    // returning to the caller.

    KeLowerIrql( oldIrql );
}

 

VOID
IopStartNextPacket(
    IN PDEVICE_OBJECT DeviceObject,
    IN LOGICAL Cancelable
    )
/*++
Routine Description:

    This routine is invoked to dequeue the next packet (IRP) from the
    specified device work queue and invoke the device driver's start I/O
    routine for it.  If the Cancelable parameter is TRUE, then the update of
    current IRP is synchronized using the cancel spinlock.

Arguments:
    DeviceObject - Pointer to device object itself.
    Cancelable - Indicates that IRPs in the device queue may be cancelable.

Return Value:
    None.
--*/
{
    KIRQL cancelIrql = PASSIVE_LEVEL;
    PIRP irp;
    PKDEVICE_QUEUE_ENTRY packet;

    // Begin by checking to see whether or not this driver's requests are
    // to be considered cancelable.  If so, then acquire the cancel spinlock.

    if (Cancelable) {
        IoAcquireCancelSpinLock( &cancelIrql );
    }

    // Clear the current IRP field before starting another request.

    DeviceObject->CurrentIrp = (PIRP) NULL;

    // Remove the next packet from the head of the queue.  If a packet was
    // found, then process it.

    packet = KeRemoveDeviceQueue( &DeviceObject->DeviceQueue );

    if (packet) {
        irp = CONTAINING_RECORD( packet, IRP, Tail.Overlay.DeviceQueueEntry );

        // A packet was located so make it the current packet for this
        // device.

        DeviceObject->CurrentIrp = irp;
        if (Cancelable) {     
           IoReleaseCancelSpinLock( cancelIrql );
        }

        // Invoke the driver's start I/O routine for this packet.

        DeviceObject->DriverObject->DriverStartIo( DeviceObject, irp );
    } else {

        // No packet was found, so simply release the cancel spinlock if
        // it was acquired.

        if (Cancelable) {
           IoReleaseCancelSpinLock( cancelIrql );
        }
    }
}

 

BOOLEAN
IoCancelIrp(
    IN PIRP Irp
    )
{
    PDRIVER_CANCEL cancelRoutine;
    KIRQL irql;
    BOOLEAN returnValue;

    ASSERT( Irp->Type == IO_TYPE_IRP );

    // Acquire the cancel spin lock.

    IoAcquireCancelSpinLock( &irql );

    // Set the cancel flag in the IRP.

    Irp->Cancel = TRUE;

    // Obtain the address of the cancel routine, and if one was specified,
    // invoke it.

    cancelRoutine = (PDRIVER_CANCEL) (ULONG_PTR) InterlockedExchangePointer( (PVOID *) &Irp->CancelRoutine, NULL );

    if (cancelRoutine) {
        Irp->CancelIrql = irql;
        cancelRoutine( Irp->Tail.Overlay.CurrentStackLocation->DeviceObject,
                       Irp );
        // The cancel spinlock should have been released by the cancel routine.

        return(TRUE);
    } else {

        // There was no cancel routine, so release the cancel spinlock and
        // return indicating the Irp was not currently cancelable.

        IoReleaseCancelSpinLock( irql );
        return(FALSE);
    }
}

#define IoSetCancelRoutine( Irp, NewCancelRoutine ) (  /
    (PDRIVER_CANCEL) (ULONG_PTR) InterlockedExchangePointer( (PVOID *) &(Irp)->CancelRoutine, (PVOID) (ULONG_PTR)(NewCancelRoutine) ) )

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.