Оценка метода элемента управления без входных аргументов
Чтобы синхронно оценить метод элемента управления, который не принимает входные аргументы, драйвер устройства отправляет на устройство запрос 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 сначала выделяет ACPI_EVAL_INPUT_BUFFER структуру inputBuffer и присваивает члену 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_BUFFER структуру outputBuffer, но не задает ни одного из членов outputBuffer.
Затем GetAbcData вызывает предоставленную драйвером функцию с именем SendDownStreamIrp, которая выполняет следующие действия:
Вызывает IoBuildDeviceIoControlRequest для сборки запроса.
Вызывает IoCallDriver для отправки запроса в стек устройств.
Ожидает, пока диспетчер ввода-вывода сообщит драйверу о том, что драйвер нижнего уровня завершил запрос.
SendDownStreamIrp возвращается после того, как диспетчер ввода-вывода сообщит, что драйверы нижнего уровня завершили запрос. В приведенном выше примере кода выполняется следующее:
Проверяет состояние запроса и возвращает без дополнительной обработки, если драйверы более низкого уровня не возвращали STATUS_SUCCESS.
Проверяет допустимость выходных аргументов. Чтобы outputBuffer содержал допустимые выходные данные, параметр Signature должен иметь значение ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE а значение Count должно быть больше нуля.
Обрабатывает выходные аргументы, переданные драйвером 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;
}