WdfIoQueueFindRequest 函数 (wdfio.h)

[适用于 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。 否则,此方法可能会返回以下值之一:

返回代码 说明
STATUS_INVALID_PARAMETER
驱动程序提供的句柄无效。
STATUS_NOT_FOUND
在 I/O 队列中找不到 由 FoundRequest 参数标识的请求。
STATUS_NO_MORE_ENTRIES
框架到达 I/O 队列的末尾,但找不到与搜索条件匹配的请求。
 

此方法还可能返回其他 NTSTATUS 值

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

注解

WdfIoQueueFindRequest 方法搜索指定的 I/O 队列并尝试查找 I/O 请求。

仅当驱动程序对指定的 I/O 队列使用手动调度方法时,驱动程序才能调用 WdfIoQueueFindRequest

如果 FileObject 不为 NULL则 WdfIoQueueFindRequest 仅检查与指定的文件对象句柄关联的请求。

如果 FoundRequestNULL,此方法在 I/O 队列中查找与 FileObject 值匹配的第一个请求。 如果 FoundRequest 不为 NULL,则该方法开始搜索 由 FoundRequest 标识的请求。 若要创建迭代循环,请为第一次调用指定 NULL ,然后使用返回的句柄作为后续调用的 FoundRequest 参数。

如果 Parameters 不为 NULL,此方法会将找到的请求的参数复制到驱动程序提供的结构中。

每次调用返回STATUS_SUCCESS的 WdfIoQueueFindRequest 都会递增请求对象的引用计数,该对象的句柄在 OutRequest 中返回。 因此,驱动程序必须在使用完句柄后调用 WdfObjectDereference

调用 WdfIoQueueFindRequest不会 授予任何请求的驱动程序 所有权 。 如果希望驱动程序获取请求的所有权,以便它可以处理请求,驱动程序必须调用 WdfIoQueueRetrieveFoundRequest。 事实上,驱动程序只能使用它为 OutRequest 参数接收的句柄执行以下操作:

如果对 WdfIoQueueFindRequest 的调用返回STATUS_NOT_FOUND,则之前在队列中的请求已被删除。 请求可能已取消。 对 WdfIoQueueRetrieveFoundRequest 的调用也可以返回STATUS_NOT_FOUND。

有关 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(&params);
 
    *Request = NULL;
    prevTagRequest = tagRequest = NULL;

    do {
        WDF_REQUEST_PARAMETERS_INIT(&params);
        status = WdfIoQueueFindRequest(
                                       Queue,
                                       prevTagRequest,
                                       NULL,
                                       &params,
                                       &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)
Library 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)

另请参阅

WDF_REQUEST_PARAMETERS

WdfIoQueueRetrieveFoundRequest

WdfIoQueueStop

WdfObjectDereference