SendDownStreamIrp Function

本主题中提供的函数的代码示例 SendDownStreamIrp 演示如何实现向 ACPI 驱动程序发送同步 IOCTL 请求的驱动程序提供的函数。 The SendDownStreamIrp function can be used to send an IOCTL_ACPI_EVAL_METHOD request, an IOCTL_ACPI_EVAL_METHOD_EX request, or an IOCTL_ACPI_ENUM_CHILDREN request.

本节中包含的函数的示例代码 SendDownStreamIrp 执行以下作序列:

  • 创建事件对象。

  • Calls IoBuildDeviceIoControlRequest to create the IOCTL request.

  • Calls IoCallDriver to send the IOCTL request.

  • 等待 ACPI 驱动程序向事件对象发出信号,该对象指示请求已完成。

  • 返回向调用方发出的请求的状态。

NTSTATUS
SendDownStreamIrp(
    IN PDEVICE_OBJECT   Pdo,
    IN ULONG            Ioctl,
    IN PVOID            InputBuffer,
    IN ULONG            InputSize,
    IN PVOID            OutputBuffer,
    IN ULONG            OutputSize
)
/*
Routine Description:
    General-purpose function called to send a request to the PDO. 
    The IOCTL argument accepts the control method being passed down
    by the calling function

    This subroutine is only valid for the IOCTLS other than ASYNC EVAL. 

Parameters:
    Pdo             - the request is sent to this device object
    Ioctl           - the request - specified by the calling function
    InputBuffer     - incoming request
    InputSize       - size of the incoming request
    OutputBuffer    - the answer
    OutputSize      - size of the answer buffer

Return Value:
    NT Status of the operation
*/
{
    IO_STATUS_BLOCK     ioBlock;
    KEVENT              myIoctlEvent;
    NTSTATUS            status;
    PIRP                irp;

    // Initialize an event to wait on
    KeInitializeEvent(&myIoctlEvent, SynchronizationEvent, FALSE);

    // Build the request
    irp = IoBuildDeviceIoControlRequest(
        Ioctl, 
        Pdo,
        InputBuffer,
        InputSize,
        OutputBuffer,
        OutputSize,
        FALSE,
        &myIoctlEvent,
        &ioBlock);

    if (!irp) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    // Pass request to Pdo, always wait for completion routine
    status = IoCallDriver(Pdo, irp);

    if (status == STATUS_PENDING) {
        // Wait for the IRP to be completed, and then return the status code
        KeWaitForSingleObject(
            &myIoctlEvent,
            Executive,
            KernelMode,
            FALSE,
            NULL);

        status = ioBlock.Status;
    }

    return status;
}