SendDownStreamIrp 函数

本主题中提供的 SendDownStreamIrp 函数代码示例演示了如何实现向 ACPI 驱动程序发送同步 IOCTL 请求的驱动程序提供的函数。 SendDownStreamIrp 函数可用于发送 IOCTL_ACPI_EVAL_METHOD 请求、IOCTL_ACPI_EVAL_METHOD_EX 请求或 IOCTL_ACPI_ENUM_CHILDREN 请求。

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

  • 创建事件对象。

  • 调用 IoBuildDeviceIoControlRequest 来创建 IOCTL 请求。

  • 调用 IoCallDriver 来发送 IOCTL 请求。

  • 等至 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;
}