Поделиться через


Оценка метода управления без входных аргументов

Чтобы синхронно оценить метод управления, который не принимает входные аргументы, драйвер для устройства отправляет запрос IOCTL_ACPI_EVAL_METHOD или запрос IOCTL_ACPI_EVAL_METHOD_EX на устройство. Общая процедура использования обоих запросов описана в статье "Оценка методов управления ACPI синхронно". Конкретная разница между использованием этих двух запросов выглядит следующим образом:

  • Если метод управления является непосредственным дочерним объектом устройства, драйвер отправляет запрос IOCTL_ACPI_EVAL_METHOD и предоставляет ACPI_EVAL_INPUT_BUFFER входную структуру.

  • Если метод управления является дочерним объектом в пространстве имен ACPI устройства, но не является непосредственным дочерним объектом устройства, драйвер отправляет запрос IOCTL_ACPI_EVAL_METHOD_EX и предоставляет структуру ACPI_EVAL_INPUT_BUFFER_EX .

В примере функции GetAbcData , предоставленной в этом разделе, показано, как драйвер для устройства может использовать запрос IOCTL_ACPI_EVAL_METHOD для оценки метода управления с именем ABCD, который поддерживает устройство. Метод управления ABCD является непосредственным дочерним элементом устройства в пространстве имен ACPI и не принимает входные аргументы или возвращает выходные аргументы.

Если метод управления ABCD не был непосредственным дочерним объектом, необходимые изменения в этом примере кода приведены следующим образом:

  • Отправьте запрос IOCTL_ACPI_EVAL_METHOD_EX вместо запроса IOCTL_ACPI_EVAL_METHOD.

  • Укажите структуру ACPI_EVAL_INPUT_BUFFER_EX вместо структуры ACPI_EVAL_INPUT_BUFFER.

GetAbcData сначала выделяет структуру inputBuffer типа ACPI_EVAL_INPUT_BUFFER и устанавливает элемент MethodNameAsUlong в имя метода управления, а элемент Signature в ACPI_EVAL_INPUT_BUFFER_SIGNATURE.

    // Fill in the input data
    inputBuffer.MethodNameAsUlong = (ULONG) ('DCBA');
    inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;

GetAbcData также выделяет структуру ACPI_EVAL_OUTPUT_BUFFERoutputBuffer, но не задает ни одного из элементов outputBuffer.

Затем GetAbcData вызывает предоставленную драйвером функцию с именем SendDownStreamIrp , которая выполняет следующие действия:

  1. Вызывает IoBuildDeviceIoControlRequest для создания запроса.

  2. Вызывает IoCallDriver, чтобы отправить запрос вниз по стеку устройств.

  3. Ожидает, пока диспетчер ввода-вывода сигнализирует драйверу о том, что драйверы нижнего уровня завершили запрос.

SendDownStreamIrp возвращается после того, как диспетчер ввода-вывода сигнализирует о том, что драйверы нижнего уровня завершили запрос. Приведенный ранее пример кода выполняет следующие действия:

  1. Проверяет состояние запроса и возвращает без дополнительной обработки, если драйверы нижнего уровня не возвращали STATUS_SUCCESS.

  2. Проверяет допустимость выходных аргументов. Чтобы outputBuffer содержал допустимые выходные данные, Signature должна быть установлена в ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE, а Count должен быть больше нуля.

  3. Обрабатывает выходные аргументы, которые драйвер ACPI передал обратно драйверу.

Хотя этот шаг не включен в пример кода, драйвер также должен вызвать IoCompleteRequest после обработки выходных данных, чтобы завершить ожидающий запрос IOCTL_ACPI_EVAL_METHOD или IOCTL_ACPI_EVAL_METHOD запрос, который драйвер отправил для оценки метода управления.

Структуры и константы данных ACPI, используемые в следующем примере, определяются в Acpiioct.h.

NTSTATUS
GetAbcdData(
    IN PDEVICE_OBJECT   Pdo,
    OUT PULONG          ReturnStatus
    )
/*++

Routine Description:
    Evaluates the ABCD method on the device in the ACPI namespace referenced by Pdo

Parameters
    Pdo             - PDO for the device
    ReturnStatus    - Pointer to where the status data is placed

Return Value:
    NT Status of the operation

--*/
{
    ACPI_EVAL_INPUT_BUFFER  inputBuffer;
    ACPI_EVAL_OUTPUT_BUFFER outputBuffer;
    NTSTATUS                status;
    PACPI_METHOD_ARGUMENT   argument;

    .
    .

    ASSERT( ReturnStatus != NULL );
    *ReturnStatus = 0x0;

    // Fill in the input data
    inputBuffer.MethodNameAsUlong = (ULONG) ('DCBA');
    inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;

    // Send the request along
    status = SendDownStreamIrp(
       Pdo,
       IOCTL_ACPI_EVAL_METHOD,
       &inputBuffer,
       sizeof(ACPI_EVAL_INPUT_BUFFER),
       &outputBuffer,
       sizeof(ACPI_EVAL_OUTPUT_BUFFER)
       );

    if (!NT_SUCCESS(status)) {
       return status;
    }

    // Verify the data
    if (outputBuffer != NULL) {
        if ( ( (PACPI_EVAL_OUTPUT_BUFFER) outputBuffer->Signature != 
            ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE ||
            ( (PACPI_EVAL_OUTPUT_BUFFER) outputBuffer->Count == 0) {
            return STATUS_ACPI_INVALID_DATA;
        } 
}

    // Retrieve the output argument
    argument = outputBuffer.Argument;
 
// Process the output argument
 .
.
.
 
    return status;
}