Функция WdfDeviceInitAssignWdmIrpPreprocessCallback (wdfdevice.h)
[Применяется только к KMDF]
Метод WdfDeviceInitAssignWdmIrpPreprocessCallback регистрирует функцию обратного вызова для обработки кода основной функции IRP и при необходимости одного или нескольких дополнительных кодов функций, связанных с кодом основной функции.
Синтаксис
NTSTATUS WdfDeviceInitAssignWdmIrpPreprocessCallback(
[in] PWDFDEVICE_INIT DeviceInit,
[in] PFN_WDFDEVICE_WDM_IRP_PREPROCESS EvtDeviceWdmIrpPreprocess,
[in] UCHAR MajorFunction,
[in, optional] PUCHAR MinorFunctions,
[in] ULONG NumMinorFunctions
);
Параметры
[in] DeviceInit
Указатель на структуру WDFDEVICE_INIT .
[in] EvtDeviceWdmIrpPreprocess
Указатель на функцию обратного вызова EvtDeviceWdmIrpPreprocess драйвера.
[in] MajorFunction
Один из кодов основных функций IRP, определенных в wdm.h.
[in, optional] MinorFunctions
Указатель на массив из одного или нескольких кодов дополнительных функций IRP, связанных с указанным кодом основной функции. Этот параметр является необязательным и может иметь значение NULL. Дополнительные сведения см. в разделе "Примечания".
[in] NumMinorFunctions
Количество дополнительных кодов функций, содержащихся в массиве MinorFunctions .
Возвращаемое значение
Если операция выполнена успешно, метод возвращает STATUS_SUCCESS. К дополнительным возвращаемым значениям относятся:
Код возврата | Описание |
---|---|
|
Недопустимое значение MajorFunction . |
|
Недостаточно памяти. |
|
Драйвер ранее зарегистрировал массив MinorFunctions для этой основной функции и пытается снова указать дополнительные функции для указанного кода MajorFunction . |
Метод может возвращать другие значения NTSTATUS.
Комментарии
Драйверы могут вызывать метод WdfDeviceInitAssignWdmIrpPreprocessCallback по двум причинам:
-
Для обработки основного или дополнительного кода функции IRP, который не поддерживается платформой.
Например, платформа не поддерживает IRP_MJ_FLUSH_BUFFERS. Если драйвер должен поддерживать этот IRP, он должен зарегистрировать функцию обратного вызова EvtDeviceWdmIrpPreprocess , которая обрабатывает IRP. Драйвер должен следовать правилам WDM для обработки IRP.
-
Предварительная обработка IRP до его обработки платформой.
В редких случаях драйверу может потребоваться обработать IRP, прежде чем платформа обработает его. В таких случаях функция обратного вызова EvtDeviceWdmIrpPreprocess драйвера может обработать IRP, а затем вызвать WdfDeviceWdmDispatchPreprocessedIrp , чтобы вернуть IRP в платформу. В зависимости от кода функции IRP платформа может обработать сам IRP или снова доставить IRP драйверу в объекте запроса платформы.
Если указатель на массив MinorFunctions имеет значение NULL, платформа вызывает функцию обратного вызова для всех дополнительных кодов функций, связанных с указанным кодом основной функции. Если указатель на массив MinorFunctions не равен NULL, платформа создает копию массива, чтобы драйверу не нужно было постоянно хранить свой массив.
Если драйвер получил указатель DeviceInit из WdfPdoInitAllocate или функции обратного вызова события EvtChildListCreateDevice , функция обратного вызова EvtDeviceWdmIrpPreprocess драйвера не может задать подпрограмму завершения для IRP, содержащей код основной функции IRP_MJ_PNP. В противном случае средство проверки драйверов сообщит об ошибке.
Если драйвер вызывает WdfDeviceInitAssignWdmIrpPreprocessCallback один раз, платформа увеличивает элемент StackSize структуры WDM DEVICE_OBJECT драйвера один раз. В результате диспетчер операций ввода-вывода добавляет дополнительное расположение стека ввода-вывода во все irP, чтобы функция обратного вызова EvtDeviceWdmIrpPreprocess может задать подпрограмму IoCompletion . Обратите внимание, что это дополнительное расположение стека ввода-вывода добавляется ко всем irP, а не только к тем, которые содержат код основной функции IRP, указанный в вызове WdfDeviceInitAssignWdmIrpPreprocessCallback. Поэтому, чтобы избежать неоправданного увеличения использования драйвером непагированного пула памяти, следует избегать использования WdfDeviceInitAssignWdmIrpPreprocessCallback , если нет альтернативы.
Если драйвер вызывает WdfDeviceInitAssignWdmIrpPreprocessCallback несколько раз для одного и того же основного кода, платформа сохраняет только последнюю заданную функцию обратного вызова EvtDeviceWdmIrpPreprocess для этого основного кода. (Драйвер не может зарегистрировать несколько обратных вызовов предварительной обработки для одного основного кода.)
Дополнительные сведения о методе WdfDeviceInitAssignWdmIrpPreprocessCallback см. в разделе Обработка WDM IRP за пределами платформы.
Примеры
В следующем примере кода определяется функция обратного вызова события EvtDeviceWdmIrpPreprocess , а затем регистрируется функция обратного вызова для обработки IRP_MJ_QUERY_INFORMATION IRP.
NTSTATUS
SerialQueryInformationFile(
IN WDFDEVICE Device,
IN PIRP Irp
)
/*++
Routine Description:
This routine is used to query the end of file information on
the opened serial port. Any other file information request
is returned with an invalid parameter.
This routine always returns an end of file of 0.
Arguments:
DeviceObject - Pointer to the device object for this device
Irp - Pointer to the IRP for the current request
Return Value:
The function value is the final status of the call
--*/
{
NTSTATUS Status;
PIO_STACK_LOCATION IrpSp;
SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, ">SerialQueryInformationFile(%p, %p)\n", Device, Irp);
PAGED_CODE();
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Irp->IoStatus.Information = 0L;
Status = STATUS_SUCCESS;
if (IrpSp->Parameters.QueryFile.FileInformationClass ==
FileStandardInformation) {
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(FILE_STANDARD_INFORMATION))
{
Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
PFILE_STANDARD_INFORMATION Buf = Irp->AssociatedIrp.SystemBuffer;
Buf->AllocationSize.QuadPart = 0;
Buf->EndOfFile = Buf->AllocationSize;
Buf->NumberOfLinks = 0;
Buf->DeletePending = FALSE;
Buf->Directory = FALSE;
Irp->IoStatus.Information = sizeof(FILE_STANDARD_INFORMATION);
}
} else if (IrpSp->Parameters.QueryFile.FileInformationClass ==
FilePositionInformation) {
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(FILE_POSITION_INFORMATION))
{
Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
((PFILE_POSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer)->
CurrentByteOffset.QuadPart = 0;
Irp->IoStatus.Information = sizeof(FILE_POSITION_INFORMATION);
}
} else {
Status = STATUS_INVALID_PARAMETER;
}
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
NTSTATUS
SerialEvtDeviceAdd(
IN WDFDRIVER Driver,
IN PWDFDEVICE_INIT DeviceInit
)
{
...
status = WdfDeviceInitAssignWdmIrpPreprocessCallback(
DeviceInit,
SerialQueryInformationFile,
IRP_MJ_QUERY_INFORMATION,
NULL, // Pointer to the minor function table
0 // Number of entries in the table
);
if (!NT_SUCCESS(status)) {
return status;
}
...
}
Требования
Требование | Значение |
---|---|
Целевая платформа | Универсальное |
Минимальная версия KMDF | 1,0 |
Верхняя часть | wdfdevice.h (включая Wdf.h) |
Библиотека | Wdf01000.sys (см. раздел Управление версиями библиотеки платформы). |
IRQL | <= DISPATCH_LEVEL |
Правила соответствия DDI | ChildDeviceInitAPI(kmdf), ControlDeviceInitAPI(kmdf), DeviceInitAPI(kmdf), DriverCreate(kmdf), InitFreeDeviceCallback(kmdf), InitFreeDeviceCreate(kmdf), InitFreeNull(kmdf), KmdfIrql(kmdf), KmdfIrql2(kmdf), KmdfIrqlExplicit(kmdf), PdoDeviceInitAPI(kmdf), PdoInitFreeDeviceCallback(kmdf), PdoInitFreeDeviceCreate(kmdf) |