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

在 wdm.h 中定义的 IRP 主要函数代码之一。

[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,则必须注册处理 IRP 的 EvtDeviceWdmIrpPreprocess 回调函数。 驱动程序必须遵循 WDM 规则来处理 IRP。

  • 在框架处理 IRP 之前对其进行预处理。

    在极少数情况下,驱动程序可能需要在框架处理 IRP 之前对其进行处理。 在这种情况下,驱动程序的 EvtDeviceWdmIrpPreprocess 回调函数可以处理 IRP,然后调用 WdfDeviceWdmDispatchPreprocessedIrp 将 IRP 返回到框架。 根据 IRP 的函数代码,框架可能会处理 IRP 本身,也可能在框架请求对象中再次将 IRP 传递给驱动程序。

每当框架收到 I/O 请求数据包时,框架将调用 EvtDeviceWdmIrpPreprocess 回调函数 (IRP) ,该数据包包含与 MajorFunction 参数匹配的 IRP 主要函数代码和与 MinorFunctions 数组中的一个次要函数代码匹配的次要函数代码。

如果 MinorFunctions 数组指针为 NULL,框架将调用与指定主函数代码关联的所有次要函数代码的回调函数。 如果 MinorFunctions 数组指针不为 NULL,框架将创建数组的副本,以便驱动程序不必永久保留其数组。

如果驱动程序从 WdfPdoInitAllocateEvtChildListCreateDevice 事件回调函数接收 DeviceInit 指针,则驱动程序的 EvtDeviceWdmIrpPreprocess 回调函数无法为包含 IRP_MJ_PNP 的主要函数代码的 IRP 设置完成例程。 否则, 驱动程序验证程序 将报告错误。

如果驱动程序调用 WdfDeviceInitAssignWdmIrpPreprocessCallback 一次或多次,框架会将驱动程序 WDM DEVICE_OBJECT 结构的 StackSize 成员递增一次。 因此,I/O 管理器向所有 IRP 添加额外的 I/O 堆栈位置 ,以便 EvtDeviceWdmIrpPreprocess 回调函数可以设置 IoCompletion 例程。 请注意,此额外的 I/O 堆栈位置将添加到所有 IRP,而不仅仅是包含你在调用 WdfDeviceInitAssignWdmIrpPreprocessCallback 中指定的 IRP 主要函数代码的位置。 因此,为了避免不必要地增加驱动程序对非分页内存池的使用,应避免使用 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)
Library Wdf01000.sys (请参阅框架库 Versioning.)
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