关于IoCallDriver使用的疑惑

#pragma PAGEDCODE
NTSTATUS HelloDDKRead(IN PDEVICE_OBJECT pDevObj,
                                 IN PIRP pIrp) 
{
    KdPrint(("DriverB:Enter B HelloDDKRead
"));
    NTSTATUS ntStatus = STATUS_SUCCESS;

    UNICODE_STRING DeviceName;
    RtlInitUnicodeString( &DeviceName, L"\Device\MyDDKDeviceA" );

    PDEVICE_OBJECT DeviceObject = NULL;
    PFILE_OBJECT FileObject = NULL;
    //得到设备对象指针
    ntStatus = IoGetDeviceObjectPointer(&DeviceName,FILE_ALL_ACCESS,&FileObject,&DeviceObject);

    KdPrint(("DriverB:FileObject:%x
",FileObject));
    KdPrint(("DriverB:DeviceObject:%x
",DeviceObject));

    if (!NT_SUCCESS(ntStatus))
    {
        KdPrint(("DriverB:IoGetDeviceObjectPointer() 0x%x
", ntStatus ));
        ntStatus = STATUS_UNSUCCESSFUL;
        // 完成IRP
        pIrp->IoStatus.Status = ntStatus;
        pIrp->IoStatus.Information = 0;    // bytes xfered
        IoCompleteRequest( pIrp, IO_NO_INCREMENT );
        KdPrint(("DriverB:Leave B HelloDDKRead
"));

        return ntStatus;
    }

    KEVENT event;
    KeInitializeEvent(&event,NotificationEvent,FALSE);

    PIRP pNewIrp = IoAllocateIrp(DeviceObject->StackSize,FALSE);
    KdPrint(("pNewIrp->UserEvent :%x
",pNewIrp->UserEvent));
    pNewIrp->UserEvent = &event;

    IO_STATUS_BLOCK status_block;
    pNewIrp->UserIosb = &status_block;
    pNewIrp->Tail.Overlay.Thread = PsGetCurrentThread();

    //因为DriverA是BUFFER IO设备
    pNewIrp->AssociatedIrp.SystemBuffer = NULL;
    
     KdPrint(("DriverB:pNewIrp:%x
",pNewIrp));

    PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation(pNewIrp);
    stack->MajorFunction = IRP_MJ_READ;
    stack->MinorFunction=IRP_MN_NORMAL;//0
    stack->FileObject = FileObject;

    //调用DriverA驱动
    NTSTATUS status = IoCallDriver(DeviceObject,pNewIrp);

    if (status == STATUS_PENDING) {
       status = KeWaitForSingleObject(
                            &event,
                            Executive,
                            KernelMode,
                            FALSE, // Not alertable
                            NULL);
       KdPrint(("STATUS_PENDING
"));
    }

     ObDereferenceObject( FileObject );
    IoFreeIrp(pNewIrp);

    ntStatus = STATUS_SUCCESS;
    // 完成IRP
    pIrp->IoStatus.Status = ntStatus;
    pIrp->IoStatus.Information = 0;    // bytes xfered
    IoCompleteRequest( pIrp, IO_NO_INCREMENT );
    KdPrint(("DriverB:Leave B HelloDDKRead
"));
    return ntStatus;
}
《windows驱动开发详解》中有一个例子,使用DriverB创建一个DriverA的IRP并使用IoCallDriver发送IRP请求,我不明白为什么在设置DriverA堆栈时使用IoGetNextIrpStackLocation 获取下层堆栈并设置
原文地址:https://www.cnblogs.com/zwt1234/p/4600251.html