Функция WdfIoTargetFormatRequestForIoctl (wdfiotarget.h)

[Применимо к KMDF и UMDF]

Метод WdfIoTargetFormatRequestForIoctl создает запрос управления устройством для целевого объекта ввода-вывода, но не отправляет запрос.

Синтаксис

NTSTATUS WdfIoTargetFormatRequestForIoctl(
  [in]           WDFIOTARGET       IoTarget,
  [in]           WDFREQUEST        Request,
  [in]           ULONG             IoctlCode,
  [in, optional] WDFMEMORY         InputBuffer,
  [in, optional] PWDFMEMORY_OFFSET InputBufferOffset,
  [in, optional] WDFMEMORY         OutputBuffer,
  [in, optional] PWDFMEMORY_OFFSET OutputBufferOffset
);

Параметры

[in] IoTarget

Дескриптор для локального или удаленного целевого объекта ввода-вывода, полученного из предыдущего вызова WdfDeviceGetIoTarget или WdfIoTargetCreate, или из метода, который предоставляет специализированный целевой объект ввода-вывода.

[in] Request

Дескриптор объекта запроса платформы. Дополнительные сведения см. в разделе "Примечания".

[in] IoctlCode

Код элемента управления вводом-выводом (IOCTL), поддерживаемый целевым объектом ввода-вывода.

[in, optional] InputBuffer

Дескриптор объекта памяти платформы. Этот объект представляет буфер, содержащий данные, которые будут отправлены в целевой объект ввода-вывода. Дополнительные сведения см. в разделе "Примечания".

[in, optional] InputBufferOffset

Указатель на структуру, выделенную вызывающим объектом WDFMEMORY_OFFSET , которая предоставляет необязательные значения смещения и длины байтов. Платформа использует эти значения для определения начального адреса и длины во входных буферах для передачи данных. Если этот указатель имеет значение NULL, передача данных начинается в начале входного буфера, а размер передачи равен размеру буфера.

[in, optional] OutputBuffer

Дескриптор объекта памяти платформы. Этот объект представляет буфер, который будет получать данные из целевого объекта ввода-вывода. Дополнительные сведения см. в разделе "Примечания".

[in, optional] OutputBufferOffset

Указатель на структуру, выделенную вызывающим объектом WDFMEMORY_OFFSET , которая предоставляет необязательные значения смещения и длины байтов. Платформа использует эти значения для определения начального адреса и длины в выходном буфере для передачи данных. Если этот указатель имеет значение NULL, передача данных начинается в начале выходного буфера, а размер передачи равен размеру буфера.

Возвращаемое значение

WdfIoTargetFormatRequestForIoctl возвращает STATUS_SUCCESS, если операция выполнена успешно. В противном случае этот метод может возвращать одно из следующих значений:

Код возврата Описание
STATUS_INVALID_PARAMETER
Обнаружен недопустимый параметр.
STATUS_INVALID_DEVICE_REQUEST
Длина передачи была больше длины буфера, или запрос ввода-вывода уже был помещен в очередь в целевой объект ввода-вывода.
STATUS_INSUFFICIENT_RESOURCES
Платформе не удалось выделить системные ресурсы (обычно это память).
STATUS_REQUEST_NOT_ACCEPTED
Пакет запроса ввода-вывода (IRP), который представляет параметр Request , не предоставляет достаточно IO_STACK_LOCATION структур, позволяющих драйверу пересылать запрос.
 

Этот метод также может возвращать другие значения NTSTATUS.

Ошибка проверка возникает, если драйвер предоставляет недопустимый дескриптор объекта.

Комментарии

Используйте метод WdfIoTargetFormatRequestForIoctl , за которым следует метод WdfRequestSend , чтобы отправлять запросы управления устройствами синхронно или асинхронно. Кроме того, можно использовать метод WdfIoTargetSendIoctlSynchronously для синхронной отправки запросов управления устройствами.

Дополнительные сведения о запросах управления устройствами см. в разделе Использование кодов управления вводом-выводом.

Вы можете переслать запрос на управление устройством, полученный драйвером в очереди ввода-вывода, или создать и отправить новый запрос. В любом случае платформе требуется объект запроса и некоторое буферное пространство.

Чтобы переслать запрос на управление устройством, полученный драйвером в очереди ввода-вывода, выполните приведенные далее действия.

  1. Укажите дескриптор полученного запроса для параметра Request метода WdfIoTargetFormatRequestForIoctl.
  2. Используйте входной буфер полученного запроса для параметра InputBuffer метода WdfIoTargetFormatRequestForIoctl.

    Драйвер должен вызвать WdfRequestRetrieveInputMemory , чтобы получить дескриптор объекта памяти платформы, который представляет входной буфер запроса, и использовать этот дескриптор в качестве значения inputBuffer.

  3. Используйте выходной буфер полученного запроса для параметра OutputBuffer метода WdfIoTargetFormatRequestForIoctl.

    Драйвер должен вызвать WdfRequestRetrieveOutputMemory , чтобы получить дескриптор выходного буфера запроса, и использовать этот дескриптор в качестве значения для OutputBuffer.

Дополнительные сведения о пересылке запроса ввода-вывода см. в разделе Пересылка запросов ввода-вывода.

Драйверы часто разделяют полученные запросы ввода-вывода на более мелкие запросы, отправляемые в целевой объект ввода-вывода, поэтому драйвер может создавать новые запросы.

Чтобы создать новый запрос ввода-вывода, выполните приведенные далее действия.

  1. Создайте объект запроса и укажите его дескриптор для параметра Request метода WdfIoTargetFormatRequestForIoctl.

    Вызовите WdfRequestCreate , чтобы предварительно выделить один или несколько объектов запроса. Эти объекты запроса можно повторно использовать, вызвав WdfRequestReuse. Функция обратного вызова EvtDriverDeviceAdd драйвера может предварительно выделить объекты запроса для устройства.

  2. Укажите буферное пространство и укажите дескриптор буфера для параметров InputBuffer и OutputBuffer метода WdfIoTargetFormatRequestForIoctl.

    Драйвер должен указать это буферное пространство, так как WDFMEMORY обрабатывает память, управляемую платформой. Драйвер может выполнить одно из следующих действий:

    • Вызовите WdfMemoryCreate или WdfMemoryCreatePreallocated , чтобы создать буфер памяти, если вы хотите, чтобы драйвер передал новый буфер целевому объекту ввода-вывода.
    • Вызовите WdfRequestRetrieveInputMemory или WdfRequestRetrieveOutputMemory , чтобы получить дескриптор объекта памяти, который представляет буфер полученного запроса ввода-вывода, если требуется, чтобы драйвер передал содержимое этого буфера целевому объекту ввода-вывода.
    Обратите внимание, что если драйвер вызывает WdfRequestRetrieveInputMemory или WdfRequestRetrieveOutputMemory и передает дескриптор памяти в WdfIoTargetFormatRequestForIoctl, драйвер не должен выполнять полученный запрос ввода-вывода до тех пор, пока драйвер не удалит, повторно использует или переформатирует новый созданный драйвером объект запроса. (WdfIoTargetFormatRequestForIoctl увеличивает количество ссылок объекта памяти. Удаление, повторное использование или переформатирование объекта запроса уменьшает количество ссылок на объект памяти.)
После того как драйвер вызывает WdfIoTargetFormatRequestForIoctl для форматирования запроса на управление устройством, драйвер должен вызвать WdfRequestSend для отправки запроса (синхронно или асинхронно) в целевой объект ввода-вывода.

Несколько вызовов WdfIoTargetFormatRequestForIoctl , использующих один и тот же запрос, не приводят к выделению дополнительных ресурсов. Таким образом, чтобы снизить вероятность того, что WdfRequestCreate вернет STATUS_INSUFFICIENT_RESOURCES, функция обратного вызова EvtDriverDeviceAdd драйвера может вызвать WdfRequestCreate для предварительного выделения одного или нескольких объектов запроса для устройства. Впоследствии драйвер может повторно использовать (вызвать WdfRequestReuse), переформатировать (вызвать WdfIoTargetFormatRequestForIoctl) и повторно отправить (вызвать WdfRequestSend) каждый объект запроса, не рискуя STATUS_INSUFFICIENT_RESOURCES возвращаемого значения при последующем вызове WdfRequestCreate. Все последующие вызовы WdfIoTargetFormatRequestForIoctl для повторно использованного объекта запроса будут возвращать STATUS_SUCCESS, если значения параметров не изменяются. (Если драйвер не вызывает один и тот же метод форматирования запросов каждый раз, могут быть выделены дополнительные ресурсы. Кроме того, если код элемента управления вводом-выводом указывает тип передачи METHOD_BUFFERED, платформа должна выделить системный буфер для каждого запроса, и это выделение может завершиться ошибкой из-за нехватки ресурсов памяти.)

Сведения о получении сведений о состоянии после завершения запроса ввода-вывода см. в разделе Получение сведений о завершении.

Дополнительные сведения о WdfIoTargetFormatRequestForIoctl см. в разделе Отправка запросов ввода-вывода к общим целевым объектам ввода-вывода.

Дополнительные сведения о целевых объектах ввода-вывода см. в разделе Использование целевых объектов ввода-вывода.

Примеры

Следующий код повторно использует предварительно выделенный объект запроса и предварительно выделенные объекты памяти. В этом примере объекты памяти назначают входные и выходные буферы, форматируют объект запроса, регистрируют функцию обратного вызова CompletionRoutine и отправляют запрос целевому объекту ввода-вывода.

NTSTATUS
NICSendOidRequestToTargetAsync(
    IN WDFIOTARGET  IoTarget,
    IN WDFREQUEST  Request,
    IN PFILE_OBJECT  FileObject,
    IN ULONG  IoctlControlCode,
    IN OUT PVOID  InputBuffer,
    IN ULONG  InputBufferLength,
    IN OUT PVOID  OutputBuffer,
    IN ULONG  OutputBufferLength,
    OUT PULONG  BytesReadOrWritten
    )
{
    NTSTATUS  status;
    PREQUEST_CONTEXT  reqContext;
    WDF_REQUEST_REUSE_PARAMS  params;
    WDFMEMORY  inputMem, outputMem;
 
    WDF_REQUEST_REUSE_PARAMS_INIT(
                                  &params, 
                                  WDF_REQUEST_REUSE_NO_FLAGS, 
                                  STATUS_SUCCESS
                                  );
    status = WdfRequestReuse(Request, &params);
    if (!NT_SUCCESS(status)){
        return status;
    }

    reqContext = GetRequestContext(Request);

    inputMem = outputMem = NULL;
 
    if (InputBuffer != NULL) {
        status = WdfMemoryAssignBuffer(
                                       reqContext->InputMemory,
                                       InputBuffer, 
                                       InputBufferLength
                                       );
        if (!NT_SUCCESS(status)) {
             return status;
        }
        inputMem = reqContext->InputMemory;
    }

    if (OutputBuffer != NULL) {
        status = WdfMemoryAssignBuffer(
                                       reqContext->OutputMemory,
                                       OutputBuffer, 
                                       OutputBufferLength
                                       );
        if (!NT_SUCCESS(status)) {
            return status;
        }
        outputMem = reqContext->OutputMemory;
    }

    status = WdfIoTargetFormatRequestForIoctl(
                                              IoTarget,
                                              Request,
                                              IoctlControlCode,
                                              inputMem,
                                              NULL,
                                              outputMem,
                                              NULL
                                              );
    if (!NT_SUCCESS(status)) {
        return status;
    }

    WdfRequestSetCompletionRoutine(
                                   Request,
                                   NICSendOidRequestToTargetAsyncCompletionRoutine,
                                   BytesReadOrWritten
                                   );

    if (WdfRequestSend(
                       Request,
                       IoTarget,
                       WDF_NO_SEND_OPTIONS
                       ) == FALSE) {
        status = WdfRequestGetStatus(Request);
    }
    return status;
}

Требования

Требование Значение
Целевая платформа Универсальное
Минимальная версия KMDF 1,0
Минимальная версия UMDF 2,0
Верхняя часть wdfiotarget.h (включая Wdf.h)
Библиотека Wdf01000.sys (KMDF); WUDFx02000.dll (UMDF)
IRQL <=DISPATCH_LEVEL
Правила соответствия DDI DriverCreate(kmdf), KmdfIrql(kmdf), KmdfIrql2(kmdf), KmdfIrqlExplicit(kmdf), RequestFormattedValid(kmdf), RequestSendAndForgetNoFormatting(kmdf), RequestSendAndForgetNoFormatting2(kmdf)

См. также раздел

EvtDriverDeviceAdd

WDFMEMORY_OFFSET

WdfDeviceGetIoTarget

WdfIoTargetCreate

WdfIoTargetFormatRequestForInternalIoctl

WdfIoTargetSendIoctlSynchronously

WdfMemoryCreate

WdfMemoryCreatePreallocated

WdfRequestCreate

WdfRequestRetrieveInputMemory

WdfRequestRetrieveOutputMemory

WdfRequestReuse

WdfRequestSend