WdfRequestSend 函数 (wdfrequest.h)
[适用于 KMDF 和 UMDF]
WdfRequestSend 方法将指定的 I/O 请求发送到指定的 I/O 目标。
语法
BOOLEAN WdfRequestSend(
[in] WDFREQUEST Request,
[in] WDFIOTARGET Target,
PWDF_REQUEST_SEND_OPTIONS Options
);
参数
[in] Request
框架请求对象的句柄。
[in] Target
框架 I/O 目标对象的句柄。 有关如何获取此句柄的详细信息,请参阅以下“备注”部分。
Options
指向包含调用方提供的请求选项 的 WDF_REQUEST_SEND_OPTIONS 结构的指针。 此参数是可选的,如果不想启用任何请求选项,可以为 NULL 。
返回值
如果请求已发送到目标,则 WdfRequestSend 返回 TRUE。 否则,此方法返回 FALSE,调用 WdfRequestGetStatus 将返回NT_SUCCESS () 测试失败的状态。
如果驱动程序提供无效的对象句柄,则会发生 bug 检查。
注解
驱动程序为 Request 参数指定的请求对象可以是它 接收 的请求对象,也可以是通过调用 WdfRequestCreate 方法创建的。
若要获取 I/O 目标对象的句柄,驱动程序可以执行以下操作之一:
- 如果驱动程序使用常规 I/O 目标,则调用 WdfDeviceGetIoTarget。 有关详细信息,请参阅 初始化常规 I/O 目标。
- 如果驱动程序使用专用 I/O 目标,它将调用专用目标对象定义的一个或多个方法。 例如,USB 设备的驱动程序可以调用 WdfUsbTargetDeviceGetIoTarget 或 WdfUsbTargetPipeGetIoTarget。
如果 WdfRequestSend 失败,或者驱动程序设置WDF_REQUEST_SEND_OPTION_SYNCHRONOUS标志,驱动程序可以在调用 WdfRequestSend 后立即调用 WdfRequestGetStatus。
如果 WdfRequestSend 成功,并且驱动程序未设置WDF_REQUEST_SEND_OPTION_SYNCHRONOUS标志,则驱动程序通常会从 CompletionRoutine 回调函数中调用 WdfRequestGetStatus。
如果驱动程序以同步方式发送请求,我们建议驱动程序在 WDF_REQUEST_SEND_OPTIONS 结构中设置超时值,并在此结构的 Flags 成员中设置超时标志。
如果驱动程序提供超时值,则应在调用 WdfRequestSend 之前调用 WdfRequestAllocateTimer。 这可确保如果没有足够的系统资源来分配计时器, WdfRequestSend 不会失败。
如果驱动程序设置 WDF_REQUEST_SEND_OPTION_SYNCHRONOUS 标志,则必须在 IRQL = PASSIVE_LEVEL 调用 WdfRequestSend 。 如果未设置此标志,驱动程序必须在 IRQL <= DISPATCH_LEVEL 调用此方法。 WdfRequestSend 在调用方 IRQL 处发送请求。
如果驱动程序为该管道配置了连续读取器,则驱动程序无法调用 WdfRequestSend 将 I/O 请求发送到 USB 管道。
向 UMDF 驱动程序发送请求时,内核模式驱动程序必须遵循 在 UMDF 驱动程序中支持 Kernel-Mode 客户端中所述的 IRQL 限制。
有关 WdfRequestSend 的详细信息,请参阅 转发 I/O 请求。
示例
下面的代码示例是来自 kmdf_fx2 示例驱动程序的 EvtIoWrite 回调函数的缩短版本。 函数验证请求的缓冲区长度,获取缓冲区的句柄,格式化 USB 目标的请求,并发送请求。
VOID
OsrFxEvtIoWrite(
IN WDFQUEUE Queue,
IN WDFREQUEST Request,
IN size_t Length
)
{
WDFUSBPIPE pipe;
NTSTATUS status;
WDFMEMORY reqMemory;
PDEVICE_CONTEXT pDeviceContext;
UNREFERENCED_PARAMETER(Queue);
//
// Check if the transfer size is valid.
//
if (Length > MAX_TRANSFER_BUFFER_SIZE) {
status = STATUS_INVALID_PARAMETER;
goto Exit;
}
//
// Get driver-defined context space from
// the device object. The driver stored the
// pipe handle there.
//
pDeviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));
pipe = pDeviceContext->BulkWritePipe;
//
// Get a handle to a memory object that represents
// the input buffer.
//
status = WdfRequestRetrieveInputMemory(Request, &reqMemory);
if (!NT_SUCCESS(status)){
goto Exit;
}
//
// Format the request so it can be sent to a USB target.
//
status = WdfUsbTargetPipeFormatRequestForWrite(
pipe,
Request,
reqMemory,
NULL // Offsets
);
if (!NT_SUCCESS(status)) {
goto Exit;
}
//
// Set a CompletionRoutine callback function.
//
WdfRequestSetCompletionRoutine(
Request,
EvtRequestReadCompletionRoutine,
pipe
);
//
// Send the request. If an error occurs, complete the request.
//
if (WdfRequestSend(
Request,
WdfUsbTargetPipeGetIoTarget(pipe),
WDF_NO_SEND_OPTIONS
) == FALSE) {
status = WdfRequestGetStatus(Request);
goto Exit;
}
Exit:
if (!NT_SUCCESS(status)) {
WdfRequestCompleteWithInformation(
Request,
status,
0
);
}
return;
}
要求
要求 | 值 |
---|---|
目标平台 | 通用 |
最低 KMDF 版本 | 1.0 |
最低 UMDF 版本 | 2.0 |
标头 | wdfrequest.h (包括 Wdf.h) |
Library | Wdf01000.sys (KMDF) ;WUDFx02000.dll (UMDF) |
IRQL | 请参见“备注”部分。 |
DDI 符合性规则 | DeferredRequestCompleted (kmdf) 、 DriverCreate (kmdf) 、 InvalidReqAccess (kmdf) 、 InvalidReqAccessLocal (kmdf) 、 KmdfIrql (kmdf) 、 ReqCompletionRoutine (kmdf) 、 ReqMarkCancelableSend (kmdf) 、 ReqSendFail (kmdf) 、 ReqSendWhileSpinlock (kmdf) 、 RequestCompleted (kmdf) 、 RequestCompletedLocal (kmdf) , RequestFormattedValid (kmdf) 、 RequestGetStatusValid (kmdf) 、 RequestSendAndForgetNoFormatting (kmdf) 、 RequestSendAndForgetNoFormatting2 (kmdf) , SyncReqSend2 (kmdf) , WdfRequestSendSyncAtDispatch (kmdf) , WdfRequestSendSyncAtDispatch2 (kmdf) |