Поделиться через


Функция WdfIoQueueFindRequest (wdfio.h)

[Применимо к KMDF и UMDF]

Метод WdfIoQueueFindRequest находит следующий запрос в очереди ввода-вывода или следующий запрос, соответствующий указанным критериям, но не предоставляет драйверу права владения запросом.

Синтаксис

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
Запрос, который определяется параметром FoundRequest , не может быть найден в очереди ввода-вывода.
STATUS_NO_MORE_ENTRIES
Платформа достигла конца очереди ввода-вывода, не найдя запрос, соответствующий условиям поиска.
 

Этот метод также может возвращать другие значения NTSTATUS.

Ошибка проверка возникает, если драйвер предоставляет недопустимый дескриптор объекта.

Комментарии

Метод WdfIoQueueFindRequest выполняет поиск указанной очереди ввода-вывода и пытается найти запрос ввода-вывода.

Драйвер может вызывать WdfIoQueueFindRequest , только если драйвер использует метод отправки вручную для указанной очереди ввода-вывода.

Если fileObject не имеет значение NULL, WdfIoQueueFindRequest проверяет только запросы, связанные с указанным дескриптором объекта файла.

Если параметр FoundRequest имеет значение NULL, этот метод находит первый запрос в очереди ввода-вывода, соответствующий значению FileObject . Если свойство FoundRequest не равно NULL, метод начинает поиск по запросу, который определяется FoundRequest. Чтобы создать итеративный цикл, укажите ЗНАЧЕНИЕ NULL для первого вызова, а затем используйте возвращенный дескриптор в качестве параметра FoundRequest для последующих вызовов.

Если параметр Parameters не равен NULL, этот метод копирует параметры найденного запроса в структуру, предоставленную драйвером.

Каждый вызов WdfIoQueueFindRequest , возвращающий STATUS_SUCCESS увеличивает число ссылок объекта запроса, дескриптор которого возвращается в OutRequest. Поэтому после завершения использования дескриптора драйвер должен вызвать WdfObjectDereference .

Вызов WdfIoQueueFindRequestне предоставляет драйверу права владения ни на какие запросы. Если вы хотите, чтобы драйвер был владельцем запроса, он должен вызвать WdfIoQueueRetrieveFoundRequest. Фактически драйвер может выполнять только следующие действия с дескриптором, который он получает для параметра OutRequest :

  • Используйте его в качестве параметра FoundRequest в последующем вызове WdfIoQueueFindRequest.
  • Используйте его в качестве параметра FoundRequest в последующем вызове WdfIoQueueRetrieveFoundRequest.
  • Используйте его в качестве входного параметра при последующем вызове WdfObjectGetTypedContext или определяемого драйвером метода для доступа к контексту объекта.
  • Используйте его в качестве входного параметра для WdfObjectDereference.
Если вызов WdfIoQueueFindRequest возвращает STATUS_NOT_FOUND, запрос, который ранее находился в очереди, был удален. Возможно, запрос был отменен. Вызов WdfIoQueueRetrieveFoundRequest также может возвращать STATUS_NOT_FOUND.

Дополнительные сведения о методе WdfIoQueueFindRequest см. в разделе Управление очередями ввода-вывода.

Примеры

Пример 1

Следующий пример кода получен из примера драйвера PCIDRV . В этом примере выполняется поиск в очереди ввода-вывода запроса, содержащего указанный код функции ввода-вывода. При обнаружении соответствующего запроса в примере вызывается 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)
Библиотека 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