WdfIoTargetSendIoctlSynchronously 函数 (wdfiotarget.h)

[适用于 KMDF 和 UMDF]

WdfIoTargetSendIoctlSynchronously 方法生成设备控制请求并将其同步发送到 I/O 目标。

语法

NTSTATUS WdfIoTargetSendIoctlSynchronously(
  [in]            WDFIOTARGET               IoTarget,
  [in, optional]  WDFREQUEST                Request,
  [in]            ULONG                     IoctlCode,
  [in, optional]  PWDF_MEMORY_DESCRIPTOR    InputBuffer,
  [in, optional]  PWDF_MEMORY_DESCRIPTOR    OutputBuffer,
  [in, optional]  PWDF_REQUEST_SEND_OPTIONS RequestOptions,
  [out, optional] PULONG_PTR                BytesReturned
);

参数

[in] IoTarget

从先前调用 WdfDeviceGetIoTargetWdfIoTargetCreate或从专用 I/O 目标提供的方法获取的本地或远程 I/O 目标对象的句柄。

[in, optional] Request

框架请求对象的句柄。 此参数是可选的,可以 NULL。 有关详细信息,请参阅以下“备注”部分。

[in] IoctlCode

I/O 目标支持的 I/O 控制代码(IOCTL)。

[in, optional] InputBuffer

指向调用方分配的 WDF_MEMORY_DESCRIPTOR 结构的指针,该结构描述将写入 I/O 目标的缓冲区。 有关详细信息,请参阅以下“备注”部分。 此参数是可选的,如果请求不发送数据,则可以 NULL

[in, optional] OutputBuffer

指向调用方分配的 WDF_MEMORY_DESCRIPTOR 结构的指针,该结构描述将从 I/O 目标接收数据的缓冲区。 有关详细信息,请参阅以下“备注”部分。 此参数是可选的,如果请求未收到数据,则可以 NULL

[in, optional] RequestOptions

指向调用方分配 WDF_REQUEST_SEND_OPTIONS 结构的指针,该结构指定请求的选项。 此指针是可选的,可以 NULL。 有关详细信息,请参阅以下“备注”部分。

[out, optional] BytesReturned

指向接收信息(例如传输的字节数)的位置的指针,另一个驱动程序通过调用 WdfRequestCompleteWithInformation完成请求时提供的信息。 此指针是可选的,可以 NULL

返回值

如果操作成功,WdfIoTargetSendIoctlSynchronously 设备控制请求完成后返回,返回值为请求的完成状态值。 否则,此方法可能会返回以下值之一:

返回代码 描述
STATUS_INVALID_PARAMETER
检测到无效参数。
STATUS_INFO_LENGTH_MISMATCH
RequestOptions 参数指向的 WDF_REQUEST_SEND_OPTIONS 结构的大小不正确。
STATUS_INVALID_DEVICE_REQUEST
请求已排队到 I/O 目标。
STATUS_INSUFFICIENT_RESOURCES
框架无法分配系统资源(通常是内存)。
STATUS_REQUEST_NOT_ACCEPTED
Request 参数表示的 I/O 请求数据包(IRP),不提供足够的 IO_STACK_LOCATION 结构,使驱动程序能够转发请求。
 

此方法还可以返回其他 NTSTATUS 值。

如果驱动程序提供无效的对象句柄,则会发生 bug 检查。

言论

使用 WdfIoTargetSendIoctlSynchronously 方法同步发送设备控制请求。 若要异步发送设备控制请求,请使用 WdfIoTargetFormatRequestForIoctl 方法,后跟 WdfRequestSend 方法。

有关设备控制请求的详细信息,请参阅 使用 I/O 控制代码

WdfIoTargetSendIoctlSynchronously 方法在请求完成之前不会返回,除非驱动程序在 RequestOptions 参数的 WDF_REQUEST_SEND_OPTIONS 结构中提供超时值,或者除非检测到错误。

可以转发驱动程序在 I/O 队列中收到的设备控制请求,也可以创建并发送新请求。 在任一情况下,框架都需要请求对象和一些缓冲区空间。

转发驱动程序在 I/O 队列中收到的设备控制请求:

  1. WdfIoTargetSendIoctlSynchronously 方法的 Request 参数指定收到的请求的句柄。
  2. 将收到的请求的输入缓冲区用于 WdfIoTargetSendIoctlSynchronously 方法的 InputBuffer 参数。

    驱动程序必须调用 WdfRequestRetrieveInputMemory 以获取表示请求输入缓冲区的框架内存对象的句柄。 然后,驱动程序必须将该句柄放置在驱动程序为 WdfIoTargetSendIoctlSynchronouslyInputBuffer 参数提供的 WDF_MEMORY_DESCRIPTOR 结构中。

  3. WdfIoTargetSendIoctlSynchronously方法的 outputBuffer 参数使用收到的请求的输出缓冲区。

    驱动程序必须调用 WdfRequestRetrieveOutputMemory 以获取表示请求输出缓冲区的框架内存对象的句柄。 然后,驱动程序必须将该句柄放置在驱动程序为 WdfIoTargetSendIoctlSynchronouslyOutputBuffer 参数提供的 WDF_MEMORY_DESCRIPTOR 结构中。

有关转发 I/O 请求的详细信息,请参阅 转发 I/O 请求

驱动程序通常会将收到的 I/O 请求划分为发送到 I/O 目标的较小请求,因此驱动程序可能会创建新请求。

创建新的 I/O 请求:

  1. WdfIoTargetSendIoctlSynchronously 方法的 Request 参数提供 NULL 请求句柄,或创建新的请求对象并提供其句柄:
    • 如果提供 NULL 请求句柄,框架将使用内部请求对象。 此方法易于使用,但驱动程序无法取消请求。
    • 如果调用 WdfRequestCreate 来创建一个或多个请求对象,可以通过调用 WdfRequestReuse来重复使用这些请求对象。 通过此方法,驱动程序的 EvtDriverDeviceAdd 回调函数可以预分配设备的请求对象。 此外,另一个驱动程序线程可以根据需要调用 WdfRequestCancelSentRequest 以取消请求。

    驱动程序可以指定非NULLRequestOptions 参数,无论驱动程序提供非NULL 还是 NULLRequest 参数。 例如,可以使用 RequestOptions 参数指定超时值。

  2. 如果请求需要,请为 WdfIoTargetSendIoctlSynchronously 方法的 InputBufferOutputBuffer 参数提供缓冲区空间。

    驱动程序可以将此缓冲区空间指定为本地分配的缓冲区、WDFMEMORY 句柄或内存描述符列表(MDL)。 可以使用哪种方法最方便。

    如有必要,框架会转换缓冲区说明,以便它们对于 IOCTL 的传输类型是正确的。 有关 IOCTL 传输类型的详细信息,请参阅 定义 I/O 控制代码

    可以使用以下方法来指定缓冲区空间:

    • 提供本地缓冲区。

      由于 WdfIoTargetSendIoctlSynchronously 同步处理 I/O 请求,因此驱动程序可以创建调用例程本地的请求缓冲区,如以下代码示例所示。

      WDF_MEMORY_DESCRIPTOR  MemoryDescriptor;
      MY_BUFFER_TYPE  MyBuffer;
      WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&MemoryDescriptor,
                                        (PVOID) &MyBuffer,
                                        sizeof(MyBuffer));
      
    • 提供 WDFMEMORY 句柄。

      调用 WdfMemoryCreateWdfMemoryCreatePreallocated 以获取框架托管内存的句柄,如以下代码示例所示。

      WDF_MEMORY_DESCRIPTOR  MemoryDescriptor;
      WDFMEMORY  MemoryHandle = NULL;
      status = WdfMemoryCreate(NULL,
                               NonPagedPool,
                               POOL_TAG,
                               MY_BUFFER_SIZE,
                               &MemoryHandle,
                               NULL);
      WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&MemoryDescriptor,
                                        MemoryHandle,
                                        NULL);
      

      或者,驱动程序可以调用 WdfRequestRetrieveInputMemoryWdfRequestRetrieveOutputMemory 以获取表示接收的 I/O 请求缓冲区的框架内存对象的句柄(如果希望驱动程序将缓冲区的内容传递到 I/O 目标)。 在 WdfIoTargetSendIoctlSynchronously 发送到 I/O 目标的新请求已删除、重复使用或重新格式化之前,驱动程序不得完成收到的 I/O 请求。 (WdfIoTargetSendIoctlSynchronously 递增内存对象的引用计数。删除、重用或重新格式化请求对象会递减内存对象的引用计数。

    • 提供 MDL。

      驱动程序可以通过调用 WdfRequestRetrieveInputWdmMdlWdfRequestRetrieveOutputWdmMdl来获取与收到的 I/O 请求关联的 MDL。

有关在 I/O 请求完成后获取状态信息的信息,请参阅 获取完成信息

有关 WdfIoTargetSendIoctlSynchronously的详细信息,请参阅 向常规 I/O 目标发送 I/O 请求

有关 I/O 目标的详细信息,请参阅 使用 I/O 目标

例子

下面的代码示例定义本地缓冲区,初始化 WDF_MEMORY_DESCRIPTOR 结构,并调用 WdfIoTargetSendIoctlSynchronously。 此示例为请求对象句柄指定 NULL,因此框架将为 I/O 目标创建新的请求对象。

WDF_MEMORY_DESCRIPTOR  outputDescriptor;
NTSTATUS  status;
HID_COLLECTION_INFORMATION  collectionInformation;

WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(
                                  &outputDescriptor,
                                  (PVOID) &collectionInformation,
                                  sizeof(HID_COLLECTION_INFORMATION)
                                  );

status = WdfIoTargetSendIoctlSynchronously(
                                           hidTarget,
                                           NULL,
                                           IOCTL_HID_GET_COLLECTION_INFORMATION,
                                           NULL,
                                           &outputDescriptor,
                                           NULL,
                                           NULL
                                           );

要求

要求 价值
目标平台 普遍
最低 KMDF 版本 1.0
最低 UMDF 版本 2.0
标头 wdfiotarget.h (包括 Wdf.h)
Wdf01000.sys(KMDF):WUDFx02000.dll (UMDF)
IRQL PASSIVE_LEVEL
DDI 符合性规则 DeferredRequestCompleted(kmdf)DriverCreate(kmdf)InternalIoctlReqs(kmdf)KmdfIrql(kmdf)KmdfIrql2(kmdf), KmdfIrqlExplicit(kmdf),ReadReqs(kmdf)RequestCompleted(kmdf)RequestCompletedLocal(kmdf)SyncReqSend(kmdf)WriteReqs(kmdf)

另请参阅

EvtDriverDeviceAdd

WDF_MEMORY_DESCRIPTOR

WDF_MEMORY_DESCRIPTOR_INIT_BUFFER

WDF_REQUEST_SEND_OPTIONS

WdfDeviceGetIoTarget

WdfIoTargetCreate

WdfIoTargetFormatRequestForIoctl

WdfIoTargetSendInternalIoctlSynchronously

WdfMemoryCreate

WdfMemoryCreatePreallocated

WdfRequestCancelSentRequest

WdfRequestCompleteWithInformation

WdfRequestCreate

WdfRequestRetrieveInputMemory

WdfRequestRetrieveInputWdmMdl

WdfRequestRetrieveOutputMemory

WdfRequestRetrieveOutputWdmMdl

WdfRequestReuse