首页 > 代码库 > 白话IoSkipCurrentIrpStackLocation

白话IoSkipCurrentIrpStackLocation

我们在IRP的Passthrough例程中会这样处理放过的IRP

         

<pre name="code" class="cpp">IoSkipCurrentIrpStackLocation( Irp );
return IoCallDriver( ...->AttachedToDeviceObject, Irp );



那么这两个函数内在本质是什么呢?

WDK的wdm.h 中有关于 IoSkipCurrentIrpStackLocation 的源码


<pre name="code" class="cpp"><pre name="code" class="cpp">FORCEINLINE
VOID
IoSkipCurrentIrpStackLocation (
    __inout PIRP Irp
)
{
    ASSERT(Irp->CurrentLocation <= Irp->StackCount);
    Irp->CurrentLocation++;
    Irp->Tail.Overlay.CurrentStackLocation++;
}


WRK源码base\ntos\io\iomgr.h 下有IopfCallDriver 源码


NTSTATUS
FORCEINLINE
IopfCallDriver(
    IN PDEVICE_OBJECT DeviceObject,
    IN OUT PIRP Irp
    )
{
    PIO_STACK_LOCATION irpSp;
    PDRIVER_OBJECT driverObject;
    NTSTATUS status;

    //
    // Ensure that this is really an I/O Request Packet.
    //

    ASSERT( Irp->Type == IO_TYPE_IRP );

    //
    // Update the IRP stack to point to the next location.
    //
    Irp->CurrentLocation--;

    if (Irp->CurrentLocation <= 0) {
        KiBugCheck3( NO_MORE_IRP_STACK_LOCATIONS, (ULONG_PTR) Irp, 0, 0 );
    }

    irpSp = IoGetNextIrpStackLocation( Irp );
    Irp->Tail.Overlay.CurrentStackLocation = irpSp;

    //
    // Save a pointer to the device object for this request so that it can
    // be used later in completion.
    //

    irpSp->DeviceObject = DeviceObject;


    //
    // Invoke the driver at its dispatch routine entry point.
    //

    driverObject = DeviceObject->DriverObject;

    //
    // Prevent the driver from unloading.
    //


    status = driverObject->MajorFunction[irpSp->MajorFunction]( DeviceObject,
                                                              Irp );

    return status;

}

其中IoGetNextIrpStackLocation( Irp );

#define IoGetNextIrpStackLocation( Irp ) (    (Irp)->Tail.Overlay.CurrentStackLocation - 1 )

IoSkipCurrentIrpStackLocation()做了两件事

    1  Irp->CurrentLocation++;

    2  Irp->Tail.Overlay.CurrentStackLocation++;

而 IopfCallDriver 中
   1  Irp->CurrentLocation--;
   2  Irp->Tail.Overlay.CurrentStackLocation = Irp->Tail.Overlay.CurrentStackLocation - 1

 这时候 driverObject->MajorFunction[irpSp->MajorFunction]( DeviceObject, Irp );中的IRP没有改变,还是原来的IRP。也就是说, 下层驱动处理的IRP就是上层传递下来的IRP。

再回头看 MSDN 中 关于 IoSkipCurrentIrpStackLocation 写到

        The IoSkipCurrentIrpStackLocation macro modifies the system‘s IO_STACK_LOCATION array pointer, so that when the current driver calls the next-lower driver, that driver receives the same IO_STACK_LOCATION structure that the current driver received.

        下层驱动接收到  same IO_STACK_LOCATION structure 。


白话IoSkipCurrentIrpStackLocation