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
wdm.h 中定義的其中一個 IRP 主要函式程式碼。
[in, optional] MinorFunctions
與指定的主要函式程式代碼相關聯的一或多個 IRP 次要函式代碼數位數組指標。 這個參數是選擇性的,而且可以 NULL。 如需詳細資訊,請參閱下列一節。
[in] NumMinorFunctions
MinorFunctions 陣列中包含的次要函式代碼數目。
傳回值
如果作業成功,方法會傳回STATUS_SUCCESS。 其他傳回值包括:
傳回碼 | 描述 |
---|---|
|
MajorFunction 值無效。 |
|
記憶體不足。 |
|
驅動程式先前註冊了這個主要函式的 MinorFunctions 陣列,並嘗試再次為 指定的 MajorFunction 程式代碼指定次要函式。 |
方法可能會 傳回其他NTSTATUS 值。
言論
驅動程式可以呼叫 WdfDeviceInitAssignWdmIrpPreprocessCallback 方法,原因有兩種:
-
處理架構不支援的 IRP 主要或次要函式程式代碼。
例如,架構不支援 IRP_MJ_FLUSH_BUFFERS。 如果您的驅動程式必須支援此 IRP,則必須註冊處理 IRP 的 EvtDeviceWdmIrpPreprocess 回呼函式。 驅動程式必須遵循 WDM 規則來處理 IRP。
-
在架構處理 IRP 之前先處理 IRP。
在罕見的情況下,驅動程式可能需要先處理 IRP,再處理架構。 在這種情況下,驅動程式的 EvtDeviceWdmIrpPreprocess 回呼函式可以處理 IRP,然後呼叫 WdfDeviceWdmDispatchPreprocessedIrp 將 IRP 傳回架構。 根據 IRP 的函式程式代碼,架構可能會處理 IRP 本身,或在架構要求物件中再次將 IRP 傳遞至驅動程式。
如果 MinorFunctions 陣列指標 NULL,則架構會針對與指定的主要函式程式代碼相關聯的所有次要函式程式代碼呼叫回呼函式。 如果 MinorFunctions 陣列指標未 NULL,則架構會建立數位的複本,讓驅動程式不必永久保留其陣列。
如果驅動程式從 WdfPdoInitAllocate 或 EvtChildListCreateDevice 事件回呼函式收到 DeviceInit 指標,則驅動程式的 EvtDeviceWdmIrpPreprocess 回呼函式無法設定包含IRP_MJ_PNP主要函式程式代碼的 IRP 完成例程。 否則,驅動程式驗證器 會回報錯誤。
如果您的驅動程式呼叫 WdfDeviceInitAssignWdmIrpPreprocessCallback 一次或多次,架構就會遞增驅動程式 WDM DEVICE_OBJECT 結構 成員 StackSize。 因此,I/O 管理員會將額外的 I/O 堆棧位置 新增至所有 IRP,讓 EvtDeviceWdmIrpPreprocess 回呼函式可以設定 IoCompletion 例程。 請注意,這個額外的 I/O 堆疊位置會新增至所有 IRP,而不只是包含您在呼叫 WdfDeviceInitAssignWdmIrpPreprocessCallback 中所指定的 IRP 主要函式程式代碼。 因此,為了避免不必要地增加驅動程式使用非分頁記憶體集區,您應該避免使用 WdfDeviceInitAssignWdmIrpPreprocessCallback,除非沒有替代方案。
如果您的驅動程式針對相同的主要程式代碼多次呼叫 WdfDeviceInitAssignWdmIrpPreprocessCallbackCallback 多次,架構只會保留這個主要程序代碼的最新設定 EvtDeviceWdmIrpPreprocess 回呼函式。 (您的驅動程式無法為單一主要程式碼註冊多個前置處理回呼。
如需 WdfDeviceInitAssignWdmIrpPreprocessCallback 方法的詳細資訊,請參閱 處理 Framework 外部的 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) kmdf),KmdfIrql(kmdf),KmdfIrql2(kmdf),KmdfIrqlExplicit(kmdf),PdoDeviceInitAPI(kmdf), PdoInitFreeDeviceCallback(kmdf), PdoInitFreeDeviceCreate(kmdf) |