共用方式為


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。 否則,此方法可能會傳回下列其中一個值:

傳回碼 Description
STATUS_INVALID_PARAMETER
驅動程式提供無效的句柄。
STATUS_NOT_FOUND
在 I/O 佇列中找不到 FoundRequest 參數所識別的要求。
STATUS_NO_MORE_ENTRIES
架構到達 I/O 佇列的結尾,但找不到符合搜尋準則的要求。
 

這個方法也可能傳回其他 NTSTATUS值

如果驅動程式提供無效的物件句柄,就會發生錯誤檢查。

備註

WdfIoQueueFindRequest 方法會搜尋指定的 I/O 佇列,並嘗試尋找 I/O 要求。

只有在驅動程式使用指定 I/O 佇列的手動分派方法時,您的驅動程式才能呼叫 WdfIoQueueFindRequest

如果 FileObject 不是 NULL,WdfIoQueueFindRequest 只會檢查與指定之檔案物件句柄相關聯的要求。

如果 FoundRequestNULL,這個方法會在符合 FileObject 值的 I/O 佇列中找出第一個要求。 如果 FoundRequest 不是 NULL,則方法會開始搜尋 FoundRequest 所識別的要求。 若要建立反覆迴圈,請為第一次呼叫指定 NULL ,然後使用傳回的句柄作為後續呼叫的 FoundRequest 參數。

如果 Parameters 不是 NULL,這個方法會將找到的要求參數複製到驅動程式提供的結構中。

每個對 WdfIoQueueFindRequest 的呼叫都會傳回STATUS_SUCCESS遞增在 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.
    //
...
}
... 

規格需求

需求
目標平台 Universal
最小 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)

另請參閱

WDF_REQUEST_PARAMETERS

WdfIoQueueRetrieveFoundRequest

WdfIoQueueStop

WdfObjectDereference