Функция 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, если операция выполнена успешно. В противном случае этот метод может возвращать одно из следующих значений:
Код возврата | Описание |
---|---|
|
Драйвер предоставляет недопустимый дескриптор. |
|
Запрос, который определяется параметром FoundRequest , не может быть найден в очереди ввода-вывода. |
|
Платформа достигла конца очереди ввода-вывода, не найдя запрос, соответствующий условиям поиска. |
Этот метод также может возвращать другие значения 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 см. в разделе Управление очередями ввода-вывода.
Примеры
Пример 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(¶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) |