关于IoCallDriver

通常我们所知IoCallDriver是把irp传递给下一层设备,传递到底是什么意思呢?
IoCallDriver中实际调用了IopfCallDriver,其代码如下:
NTSTATUS
FORCEINLINE
IopfCallDriver(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
)

/*++

Routine Description:

This routine is invoked to pass an I/O Request Packet (IRP) to another
driver at its dispatch routine.

Arguments:

DeviceObject - Pointer to device object to which the IRP should be passed.

Irp - Pointer to IRP for request.

Return Value:

Return status from driver's dispatch routine.

–*/

{
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;

}

可以看到,IopfCallDriver首先将irp的当前位置减一,即得到下一个位置。而IoGetNextIrpStackLocation是一个宏,得到下一个irp堆栈的指针,并将这一指针身为当前irp堆栈指针。实际上就是irp->Tail.Overlay.CurrentStackLocation - 1。然后从该irp堆栈中取出它所对应的device object,从而得到driver object。最后,传递irp实际上就是调用对应这次请求的例程。这个请求或者从irp堆栈中取出一些参数,或者干些其他什么事,这我们就不管了。

再有就是有关于完成例程IoCompletionRoutine,它是如何被调用的?当完成一个irp时,我们会呼叫IoCompleteRequest。这个函数遍历一遍irp堆栈,如果发现堆栈中设置了IoCompletionRoutine指针,就调用它。

你可能感兴趣的:(关于IoCallDriver)