[适用于 KMDF 和 UMDF]
WdfIoQueueFindRequest 方法在 I/O 队列中找到下一个请求,或与指定条件匹配的下一个请求,但不向驱动程序授予 所有权。
语法
NTSTATUS WdfIoQueueFindRequest(
[in] WDFQUEUE Queue,
[in, optional] WDFREQUEST FoundRequest,
[in, optional] WDFFILEOBJECT FileObject,
[in, out] PWDF_REQUEST_PARAMETERS Parameters,
[out] WDFREQUEST *OutRequest
);
参数
[in] Queue
框架队列对象的句柄。
[in, optional] FoundRequest
驱动程序从上一次调用 WdfIoQueueFindRequest收到的请求对象句柄。 此参数是可选的,可以 NULL。
[in, optional] FileObject
框架文件对象的句柄。 此参数是可选的,可以 NULL。
[in, out] Parameters
指向驱动程序分配 WDF_REQUEST_PARAMETERS 结构的指针,该结构接收与找到的请求关联的参数。 此参数是可选的,可以 NULL。
[out] OutRequest
指向接收找到请求句柄的位置的指针。 如果未找到匹配项,则位置接收 NULL。
返回值
WdfIoQueueFindRequest 如果作成功,则返回STATUS_SUCCESS。 否则,此方法可能会返回以下值之一:
| 返回代码 | 说明 |
|---|---|
|
驱动程序提供无效句柄。 |
|
在 I/O 队列中找不到由 FoundRequest 参数标识的请求。 |
|
框架到达 I/O 队列的末尾,但没有找到与搜索条件匹配的请求。 |
此方法还可以 返回其他NTSTATUS 值。
如果驱动程序提供无效的对象句柄,则会发生 bug 检查。
注解
WdfIoQueueFindRequest 方法搜索指定的 I/O 队列并尝试查找 I/O 请求。
仅当驱动程序为指定的 I/O 队列使用手动 调度方法 时,驱动程序才能调用 WdfIoQueueFindRequest。
如果 FileObject 未 NULL,WdfIoQueueFindRequest 仅检查与指定文件对象句柄关联的请求。
如果 FoundRequestNULL,此方法在 I/O 队列中查找与 FileObject 值匹配的第一个请求。 如果 FoundRequest 未 NULL,该方法将开始在 FoundRequest标识的请求中搜索。 若要创建迭代循环,请为第一次调用指定 NULL,然后将返回的句柄用作后续调用的 FoundRequest 参数。
如果 参数 未 NULL,此方法会将找到的请求的参数复制到驱动程序提供的结构中。
每次调用 WdfIoQueueFindRequest 返回STATUS_SUCCESS递增其句柄在 OutRequest中返回的请求对象的引用计数。 因此,驱动程序在使用句柄后必须调用 WdfObjectDereference。
调用 WdfIoQueueFindRequest 不会 不 授予驱动程序 任何请求 所有权。 如果希望驱动程序获取请求的所有权,以便它可以处理请求,驱动程序必须调用 WdfIoQueueRetrieveFoundRequest。 事实上,驱动程序只能对 OutRequest 参数接收的句柄执行以下作:
- 在对 WdfIoQueueFindRequest的后续调用中,将其用作 FoundRequest 参数。
- 在对 WdfIoQueueRetrieveFoundRequest的后续调用中,将其用作 FoundRequest 参数。
- 在后续调用中将其用作输入参数,WdfObjectGetTypedContext 或驱动程序定义的方法来访问对象的 上下文空间。
- 将其用作输入参数来 WdfObjectDereference。
有关 WdfIoQueueFindRequest 方法的详细信息,请参阅 管理 I/O 队列。
例子
示例 1
下面的代码示例来自 PCIDRV 示例驱动程序。 此示例在 I/O 队列中搜索包含指定 I/O 函数代码的请求。 如果找到匹配的请求,该示例将调用 WdfIoQueueRetrieveFoundRequest。
NTSTATUS
NICGetIoctlRequest(
IN WDFQUEUE Queue,
IN ULONG FunctionCode,
OUT WDFREQUEST* Request
)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
WDF_REQUEST_PARAMETERS params;
WDFREQUEST tagRequest;
WDFREQUEST prevTagRequest;
WDF_REQUEST_PARAMETERS_INIT(¶ms);
*Request = NULL;
prevTagRequest = tagRequest = NULL;
do {
WDF_REQUEST_PARAMETERS_INIT(¶ms);
status = WdfIoQueueFindRequest(
Queue,
prevTagRequest,
NULL,
¶ms,
&tagRequest
);
if (prevTagRequest) {
WdfObjectDereference(prevTagRequest);
}
if (status == STATUS_NO_MORE_ENTRIES) {
status = STATUS_UNSUCCESSFUL;
break;
}
if (status == STATUS_NOT_FOUND) {
//
// The prevTagRequest request has disappeared from the
// queue. There might be other requests that match
// the criteria, so restart the search.
//
prevTagRequest = tagRequest = NULL;
continue;
}
if (!NT_SUCCESS(status)) {
status = STATUS_UNSUCCESSFUL;
break;
}
if (FunctionCode == params.Parameters.DeviceIoControl.IoControlCode){
//
// Found a match. Retrieve the request from the queue.
//
status = WdfIoQueueRetrieveFoundRequest(
Queue,
tagRequest,
Request
);
WdfObjectDereference(tagRequest);
if (status == STATUS_NOT_FOUND) {
//
// The tagRequest request has disappeared from the
// queue. There might be other requests that match
// the criteria, so restart the search.
//
prevTagRequest = tagRequest = NULL;
continue;
}
if (!NT_SUCCESS(status)) {
status = STATUS_UNSUCCESSFUL;
break;
}
//
// Found a request.
//
ASSERT(*Request == tagRequest);
status = STATUS_SUCCESS;
break;
} else {
//
// This request is not the correct one. Drop the reference
// on the tagRequest after the driver obtains the next request.
//
prevTagRequest = tagRequest;
continue;
}
} while (TRUE);
return status;
}
示例 2
下面的代码示例演示如何创建调用特定于搜索的子例程的常规用途搜索例程。 如果驱动程序必须搜索一个或多个队列以获取多种类型的信息,则可以提供多个特定于搜索的子例程。 每当驱动程序调用常规用途搜索例程时,它都会指定搜索特定子例程之一的地址。
//
// Type declaration for the driver's search-specific subroutines.
//
typedef BOOLEAN (*PFN_CALLBACK_COMPARE)(WDFREQUEST, ULONG);
//
// General-purpose search routine. One of the routine's
// parameters is the address of a search-specific
// subroutine. The search routine calls back to the
// subroutine.
//
WDFREQUEST
FindRequestWithMatchingData(
__in WDFQUEUE Queue,
__in PFN_CALLBACK_COMPARE CallbackCompare,
__in ULONG Data
)
{
WDFREQUEST prevTagRequest = NULL;
WDFREQUEST tagRequest = NULL;
WDFREQUEST outRequest = NULL;
NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
PAGED_CODE();
do {
status = WdfIoQueueFindRequest(Queue,
prevTagRequest,
NULL,
NULL,
&tagRequest);
if (prevTagRequest) {
//
// WdfIoQueueFindRequest incremented the
// reference count of the prevTagRequest object,
// so we decrement the count here.
//
WdfObjectDereference(prevTagRequest);
}
if (status == STATUS_NO_MORE_ENTRIES) {
KdPrint(("WdfIoQueueFindRequest returned status 0x%x\n", status));
break;
}
if (status == STATUS_NOT_FOUND) {
//
// The prevTagRequest object is no longer
// in the queue.
//
prevTagRequest = tagRequest = NULL;
continue;
}
if ( !NT_SUCCESS(status)) {
KdPrint(("WdfIoQueueFindRequest failed 0x%x\n", status));
break;
}
//
// We have a handle to the next request that is
// in the queue. Now we call the subroutine
// that determines if this request matches our
// search criteria.
//
if (CallbackCompare(tagRequest, Data)) {
//
// We found a match. Get the request handle.
//
status = WdfIoQueueRetrieveFoundRequest(Queue,
tagRequest,
&outRequest);
//
// WdfIoQueueRetrieveFoundRequest incremented the
// reference count of the TagRequest object,
// so we decrement the count here.
//
WdfObjectDereference(tagRequest);
if (status == STATUS_NOT_FOUND) {
//
// The TagRequest object is no longer
// in the queue. But other requests might
// match our criteria, so we restart the search.
//
prevTagRequest = tagRequest = NULL;
continue;
}
if (!NT_SUCCESS(status)) {
KdPrint(("WdfIoQueueRetrieveFoundRequest failed 0x%x\n",
status));
}
//
// We found the request we were looking for.
//
break;
} else {
//
// The request did not match our criteria.
// Get another request.
//
prevTagRequest = tagRequest;
continue;
}
} while(TRUE);
return outRequest;
}
/
// An example of a driver's search-specific subroutine.
// Your driver can have multiple subroutines to handle
// multiple types of searches.
//
BOOLEAN
CallbackCheckForInfo1(
__in WDFREQUEST Request,
__in ULONG DataToBeMatched
)
{
PREQUEST_CONTEXT reqContext;
PAGED_CODE();
//
// Retrieve information that the driver has stored
// in the request object's context space.
//
reqContext = GetRequestContext(Request);
if (reqContext->ContextInfo1 == DataToBeMatched) {
return TRUE;
}
else {
return FALSE;
}
}
//
// This code shows a call to the FindRequestWithMatchingData routine.
//
WDFREQUEST matchedRequest = NULL;
...
matchedRequest = FindRequestWithMatchingData(readQueue,
CallbackCheckForInfo1,
INFO_VALUE);
if (matchedRequest != NULL) {
//
// Found a request with a context value of INFO_VALIUE.
//
...
}
...
要求
| 要求 | 价值 |
|---|---|
| 目标平台 | 普遍 |
| 最低 KMDF 版本 | 1.0 |
| 最低 UMDF 版本 | 2.0 |
| 标头 | wdfio.h (包括 Wdf.h) |
| 图书馆 | Wdf01000.sys(KMDF):WUDFx02000.dll (UMDF) |
| IRQL | <= DISPATCH_LEVEL |
| DDI 符合性规则 | DriverCreate(kmdf),KmdfIrql(kmdf),KmdfIrql2(kmdf),KmdfIrqlExplicit(kmdf),wdfioqueuefindrequestfailed, WdfIoQueueFindRequestFailed(kmdf)、 wdfioqueueretrievefoundrequest, WdfIoQueueRetrieveFoundRequest(kmdf), wdfioqueueretrievenextrequest, WdfIoQueueRetrieveNextRequest(kmdf) |