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


Функция WdfDeviceInitAssignWdmIrpPreprocessCallback (wdfdevice.h)

[Применяется только к KMDF]

Метод WdfDeviceInitAssignWdmIrpPreprocessCallback регистрирует функцию обратного вызова для обработки кода основной функции IRP и при необходимости одного или нескольких дополнительных кодов функций, связанных с кодом основной функции.

Синтаксис

NTSTATUS WdfDeviceInitAssignWdmIrpPreprocessCallback(
  [in]           PWDFDEVICE_INIT                  DeviceInit,
  [in]           PFN_WDFDEVICE_WDM_IRP_PREPROCESS EvtDeviceWdmIrpPreprocess,
  [in]           UCHAR                            MajorFunction,
  [in, optional] PUCHAR                           MinorFunctions,
  [in]           ULONG                            NumMinorFunctions
);

Параметры

[in] DeviceInit

Указатель на структуру WDFDEVICE_INIT .

[in] EvtDeviceWdmIrpPreprocess

Указатель на функцию обратного вызова EvtDeviceWdmIrpPreprocess драйвера.

[in] MajorFunction

Один из кодов основных функций IRP, определенных в wdm.h.

[in, optional] MinorFunctions

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

[in] NumMinorFunctions

Количество дополнительных кодов функций, содержащихся в массиве MinorFunctions .

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

Если операция выполнена успешно, метод возвращает STATUS_SUCCESS. К дополнительным возвращаемым значениям относятся:

Код возврата Описание
STATUS_INVALID_PARAMETER
Недопустимое значение MajorFunction .
STATUS_INSUFFICIENT_RESOURCES
Недостаточно памяти.
STATUS_INVALID_DEVICE_REQUEST
Драйвер ранее зарегистрировал массив MinorFunctions для этой основной функции и пытается снова указать дополнительные функции для указанного кода MajorFunction .
 

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

Комментарии

Драйверы могут вызывать метод WdfDeviceInitAssignWdmIrpPreprocessCallback по двум причинам:

  • Для обработки основного или дополнительного кода функции IRP, который не поддерживается платформой.

    Например, платформа не поддерживает IRP_MJ_FLUSH_BUFFERS. Если драйвер должен поддерживать этот IRP, он должен зарегистрировать функцию обратного вызова EvtDeviceWdmIrpPreprocess , которая обрабатывает IRP. Драйвер должен следовать правилам WDM для обработки IRP.

  • Предварительная обработка IRP до его обработки платформой.

    В редких случаях драйверу может потребоваться обработать IRP, прежде чем платформа обработает его. В таких случаях функция обратного вызова EvtDeviceWdmIrpPreprocess драйвера может обработать IRP, а затем вызвать WdfDeviceWdmDispatchPreprocessedIrp , чтобы вернуть IRP в платформу. В зависимости от кода функции IRP платформа может обработать сам IRP или снова доставить IRP драйверу в объекте запроса платформы.

Платформа вызывает функцию обратного вызова EvtDeviceWdmIrpPreprocess всякий раз, когда получает пакет запроса ввода-вывода (IRP), содержащий код основной функции IRP, соответствующий параметру MajorFunction , и дополнительный код функции, соответствующий одному из дополнительных кодов функций, которые находятся в массиве MinorFunctions .

Если указатель на массив MinorFunctions имеет значение NULL, платформа вызывает функцию обратного вызова для всех дополнительных кодов функций, связанных с указанным кодом основной функции. Если указатель на массив MinorFunctions не равен NULL, платформа создает копию массива, чтобы драйверу не нужно было постоянно хранить свой массив.

Если драйвер получил указатель DeviceInit из WdfPdoInitAllocate или функции обратного вызова события EvtChildListCreateDevice , функция обратного вызова EvtDeviceWdmIrpPreprocess драйвера не может задать подпрограмму завершения для IRP, содержащей код основной функции IRP_MJ_PNP. В противном случае средство проверки драйверов сообщит об ошибке.

Если драйвер вызывает WdfDeviceInitAssignWdmIrpPreprocessCallback один раз, платформа увеличивает элемент StackSize структуры WDM DEVICE_OBJECT драйвера один раз. В результате диспетчер операций ввода-вывода добавляет дополнительное расположение стека ввода-вывода во все irP, чтобы функция обратного вызова EvtDeviceWdmIrpPreprocess может задать подпрограмму IoCompletion . Обратите внимание, что это дополнительное расположение стека ввода-вывода добавляется ко всем irP, а не только к тем, которые содержат код основной функции IRP, указанный в вызове WdfDeviceInitAssignWdmIrpPreprocessCallback. Поэтому, чтобы избежать неоправданного увеличения использования драйвером непагированного пула памяти, следует избегать использования WdfDeviceInitAssignWdmIrpPreprocessCallback , если нет альтернативы.

Если драйвер вызывает WdfDeviceInitAssignWdmIrpPreprocessCallback несколько раз для одного и того же основного кода, платформа сохраняет только последнюю заданную функцию обратного вызова EvtDeviceWdmIrpPreprocess для этого основного кода. (Драйвер не может зарегистрировать несколько обратных вызовов предварительной обработки для одного основного кода.)

Дополнительные сведения о методе WdfDeviceInitAssignWdmIrpPreprocessCallback см. в разделе Обработка WDM IRP за пределами платформы.

Примеры

В следующем примере кода определяется функция обратного вызова события EvtDeviceWdmIrpPreprocess , а затем регистрируется функция обратного вызова для обработки IRP_MJ_QUERY_INFORMATION IRP.

NTSTATUS
SerialQueryInformationFile(
    IN WDFDEVICE Device,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine is used to query the end of file information on
    the opened serial port.  Any other file information request
    is returned with an invalid parameter.

    This routine always returns an end of file of 0.

Arguments:

    DeviceObject - Pointer to the device object for this device

    Irp - Pointer to the IRP for the current request

Return Value:

    The function value is the final status of the call

--*/

{
    NTSTATUS Status;
    PIO_STACK_LOCATION IrpSp;

    SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, ">SerialQueryInformationFile(%p, %p)\n", Device, Irp);

    PAGED_CODE();


    IrpSp = IoGetCurrentIrpStackLocation(Irp);
    Irp->IoStatus.Information = 0L;
    Status = STATUS_SUCCESS;

    if (IrpSp->Parameters.QueryFile.FileInformationClass ==
        FileStandardInformation) {

        if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
                sizeof(FILE_STANDARD_INFORMATION))
        {
                Status = STATUS_BUFFER_TOO_SMALL;
        }
        else
        {
            PFILE_STANDARD_INFORMATION Buf = Irp->AssociatedIrp.SystemBuffer;

            Buf->AllocationSize.QuadPart = 0;
            Buf->EndOfFile = Buf->AllocationSize;
            Buf->NumberOfLinks = 0;
            Buf->DeletePending = FALSE;
            Buf->Directory = FALSE;
            Irp->IoStatus.Information = sizeof(FILE_STANDARD_INFORMATION);
        }

    } else if (IrpSp->Parameters.QueryFile.FileInformationClass ==
               FilePositionInformation) {

        if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
                sizeof(FILE_POSITION_INFORMATION))
        {
                Status = STATUS_BUFFER_TOO_SMALL;
        }
        else
        {

            ((PFILE_POSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer)->
                CurrentByteOffset.QuadPart = 0;
            Irp->IoStatus.Information = sizeof(FILE_POSITION_INFORMATION);
        }

    } else {
        Status = STATUS_INVALID_PARAMETER;
    }

    Irp->IoStatus.Status = Status;

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    return Status;

}

NTSTATUS
SerialEvtDeviceAdd(
    IN WDFDRIVER Driver,
    IN PWDFDEVICE_INIT DeviceInit
    )
{
...
    status = WdfDeviceInitAssignWdmIrpPreprocessCallback(
                                                 DeviceInit,
                                                 SerialQueryInformationFile,
                                                 IRP_MJ_QUERY_INFORMATION,
                                                 NULL, // Pointer to the minor function table
                                                 0 // Number of entries in the table
                                                 ); 
    if (!NT_SUCCESS(status)) {
        return status;
    }
...
}

Требования

Требование Значение
Целевая платформа Универсальное
Минимальная версия KMDF 1,0
Верхняя часть wdfdevice.h (включая Wdf.h)
Библиотека Wdf01000.sys (см. раздел Управление версиями библиотеки платформы).
IRQL <= DISPATCH_LEVEL
Правила соответствия DDI ChildDeviceInitAPI(kmdf), ControlDeviceInitAPI(kmdf), DeviceInitAPI(kmdf), DriverCreate(kmdf), InitFreeDeviceCallback(kmdf), InitFreeDeviceCreate(kmdf), InitFreeNull(kmdf), KmdfIrql(kmdf), KmdfIrql2(kmdf), KmdfIrqlExplicit(kmdf), PdoDeviceInitAPI(kmdf), PdoInitFreeDeviceCallback(kmdf), PdoInitFreeDeviceCreate(kmdf)

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

WdfDeviceWdmDispatchPreprocessedIrp