WdfIoTargetFormatRequestForInternalIoctlOthers 函数 (wdfiotarget.h)
[仅适用于 KMDF]
WdfIoTargetFormatRequestForInternalIoctlOthers 方法为 I/O 目标生成非标准内部设备控制请求,但不发送请求。
语法
NTSTATUS WdfIoTargetFormatRequestForInternalIoctlOthers(
[in] WDFIOTARGET IoTarget,
[in] WDFREQUEST Request,
[in] ULONG IoctlCode,
[in, optional] WDFMEMORY OtherArg1,
[in, optional] PWDFMEMORY_OFFSET OtherArg1Offset,
[in, optional] WDFMEMORY OtherArg2,
[in, optional] PWDFMEMORY_OFFSET OtherArg2Offset,
[in, optional] WDFMEMORY OtherArg4,
[in, optional] PWDFMEMORY_OFFSET OtherArg4Offset
);
参数
[in] IoTarget
本地或远程 I/O 目标对象的句柄,该对象是从上一次调用 WdfDeviceGetIoTarget 或 WdfIoTargetCreate 获取的,或者从专用 I/O 目标提供的方法获取的。
[in] Request
框架请求对象的句柄。 有关更多信息,请参见下面的“备注”部分。
[in] IoctlCode
I/O 目标支持的 IOCTL) (I/O 控制代码。
[in, optional] OtherArg1
框架内存对象的句柄。 此对象表示驱动程序用于请求特定的驱动程序定义的上下文信息的缓冲区。 有关更多信息,请参见下面的“备注”部分。 此参数是可选的,可以为 NULL。
[in, optional] OtherArg1Offset
指向调用方分配 的WDFMEMORY_OFFSET 结构的指针,该结构提供可选的字节偏移量和长度值。 驱动程序可以使用这些值来指定 由 OtherArg1 指定的上下文区域段的起始地址和长度。 此参数是可选的,可以为 NULL。
[in, optional] OtherArg2
框架内存对象的句柄。 此对象表示驱动程序用于请求特定的驱动程序定义的上下文信息的缓冲区。 有关更多信息,请参见下面的“备注”部分。 此参数是可选的,可以为 NULL。
[in, optional] OtherArg2Offset
指向调用方分配 的WDFMEMORY_OFFSET 结构的指针,该结构提供可选的字节偏移量和长度值。 驱动程序可以使用这些值来指定 OtherArg2 指定的上下文区域段的起始地址和长度。 此参数是可选的,可以为 NULL。
[in, optional] OtherArg4
框架内存对象的句柄。 此对象表示驱动程序用于请求特定的驱动程序定义的上下文信息的缓冲区。 有关更多信息,请参见下面的“备注”部分。 此参数是可选的,可以为 NULL。
[in, optional] OtherArg4Offset
指向调用方分配 的WDFMEMORY_OFFSET 结构的指针,该结构提供可选的字节偏移量和长度值。 驱动程序可以使用这些值指定 由 OtherArg4 指定的上下文区域段的起始地址和长度。 此参数是可选的,可以为 NULL。
返回值
如果操作成功,WdfIoTargetFormatRequestForInternalIoctlOthers 将返回STATUS_SUCCESS。 否则,此方法可能会返回以下值之一:
返回代码 | 说明 |
---|---|
|
检测到参数无效。 |
|
传输长度大于缓冲区长度,或者 I/O 请求已排队到 I/O 目标。 |
|
框架无法分配系统资源 (通常是内存) 。 |
|
Request 参数表示的 I/O 请求数据包 (IRP) 不提供足够的IO_STACK_LOCATION结构来允许驱动程序转发请求。 |
此方法还可能返回其他 NTSTATUS 值。
如果驱动程序提供无效的对象句柄,则会发生 bug 检查。
注解
使用 WdfIoTargetFormatRequestForInternalIoctlOthers 方法,后跟 WdfRequestSend 方法以同步或异步方式发送非标准内部设备控制请求。 或者,使用 WdfIoTargetSendInternalIoctlOthersSynchronously 方法以同步方式发送非标准内部设备控制请求。
可以转发驱动程序在 I/O 队列中收到的非标准内部设备控制请求,也可以创建并发送新请求。 在任一情况下,框架都需要请求对象和一些缓冲区空间。
转发驱动程序在 I/O 队列中收到的非标准内部设备控制请求:
- 为 WdfIoTargetFormatRequestForInternalIoctlOthers 方法的 Request 参数指定接收的请求句柄。
-
对 WdfIoTargetFormatRequestForInternalIoctlOthers 方法的 OtherArg1、 OtherArg2、 OtherArg4 参数使用收到的请求的上下文信息。
若要获取这些参数值,驱动程序必须调用 WdfRequestGetParameters 并使用返回的 WDF_REQUEST_PARAMETERS 结构的 DeviceIoControl 成员。
驱动程序通常将收到的 I/O 请求划分为发送到 I/O 目标的较小请求,因此驱动程序可能会创建新请求。
创建新的 I/O 请求:
-
创建新的请求对象,并为 WdfIoTargetFormatRequestForInternalIoctlOthers 方法的 Request 参数提供其 句 柄。
调用 WdfRequestCreate 以预分配一个或多个请求对象。 可以通过调用 WdfRequestReuse 来重复使用这些请求对象。 驱动程序的 EvtDriverDeviceAdd 回调函数可以为设备预分配请求对象。
-
如果请求需要上下文缓冲区,请提供上下文缓冲区,并为 WdfIoTargetFormatRequestForInternalIoctlOthers 方法的 OtherArg1、 OtherArg2 和 OtherArg4 参数提供缓冲区句柄。
驱动程序必须将此缓冲区空间指定为框架托管内存的 WDFMEMORY 句柄。 为了获取 WDFMEMORY 句柄,驱动程序调用 WdfMemoryCreate 或 WdfMemoryCreatePreallocated。
对使用同一请求的 WdfIoTargetFormatRequestForInternalIoctlOthers 的多次调用不会导致额外的资源分配。 因此,为了降低 WdfRequestCreate 返回STATUS_INSUFFICIENT_RESOURCES的可能性,驱动程序的 EvtDriverDeviceAdd 回调函数可以调用 WdfRequestCreate 来预分配设备的一个或多个请求对象。 驱动程序随后可以重复使用 (调用 WdfRequestReuse) ,重新设置格式 (调用 WdfIoTargetFormatRequestForInternalIoctlOthers) ,并重新发送 (调用 WdfRequestSend) 每个请求对象,而不会STATUS_INSUFFICIENT_RESOURCES对 WdfRequestCreate 的后续调用返回值。 (如果驱动程序每次都不调用相同的请求格式设置方法,则可能会分配其他资源。) 如果参数值不更改,对重用请求对象的 WdfIoTargetFormatRequestForInternalIoctlOthers 的所有后续调用都将返回STATUS_SUCCESS。
有关在 I/O 请求完成后获取状态信息的信息,请参阅 获取完成信息。
有关 WdfIoTargetFormatRequestForInternalIoctlOthers 的详细信息,请参阅 向常规 I/O 目标发送 I/O 请求。
有关 I/O 目标的详细信息,请参阅 使用 I/O 目标。
示例
下面的代码示例创建一个框架内存对象,获取内存对象包含的缓冲区,并初始化该缓冲区。 然后,该示例格式化请求,设置 CompletionRoutine 回调函数,并将请求发送到 I/O 目标。
PIRB pIrb;
WDFMEMORY memory;
NTSTATUS status;
status = WdfMemoryCreate(
WDF_NO_OBJECT_ATTRIBUTES,
NonPagedPool,
0,
sizeof(IRB),
&memory,
NULL
);
if (!NT_SUCCESS(status)) {
goto Done;
}
pIrb = WdfMemoryGetBuffer(
memory,
NULL
);
pIrb->FunctionNumber = REQUEST_ALLOCATE_ADDRESS_RANGE;
pIrb->Flags = 0;
pIrb->u.AllocateAddressRange.Mdl = pAsyncAddressData->pMdl;
pIrb->u.AllocateAddressRange.fulFlags = fulFlags;
pIrb->u.AllocateAddressRange.nLength = nLength;
pIrb->u.AllocateAddressRange.MaxSegmentSize = MaxSegmentSize;
pIrb->u.AllocateAddressRange.fulAccessType = fulAccessType;
pIrb->u.AllocateAddressRange.fulNotificationOptions = fulNotificationOptions;
pIrb->u.AllocateAddressRange.Callback = NULL;
pIrb->u.AllocateAddressRange.Context = NULL;
pIrb->u.AllocateAddressRange.Required1394Offset = *Required1394Offset;
pIrb->u.AllocateAddressRange.FifoSListHead = NULL;
pIrb->u.AllocateAddressRange.FifoSpinLock = NULL;
pIrb->u.AllocateAddressRange.AddressesReturned = 0;
pIrb->u.AllocateAddressRange.p1394AddressRange = pAsyncAddressData->AddressRange;
pIrb->u.AllocateAddressRange.DeviceExtension = deviceExtension;
status = WdfIoTargetFormatRequestForInternalIoctlOthers(
IoTarget,
Request,
IOCTL_1394_CLASS,
memory,
NULL,
NULL,
NULL,
NULL,
NULL
);
if (!NT_SUCCESS(status)) {
goto Done;
}
WdfRequestSetCompletionRoutine(
Request,
MyRequestCompletion,
NULL
);
if (WdfRequestSend(
Request,
IoTarget,
NULL
) == FALSE) {
status = WdfRequestGetStatus(Request);
}
else {
status = STATUS_SUCCESS;
}
要求
要求 | 值 |
---|---|
目标平台 | 通用 |
最低 KMDF 版本 | 1.0 |
标头 | wdfiotarget.h (包括 Wdf.h) |
Library | Wdf01000.sys (请参阅框架库 Versioning.) |
IRQL | <=DISPATCH_LEVEL |
DDI 符合性规则 | DriverCreate (kmdf) , KmdfIrql (kmdf) , KmdfIrql2 (kmdf) , KmdfIrqlExplicit (kmdf) , RequestFormattedValid (kmdf) 、 RequestSendAndForgetNoFormatting (kmdf) 、 RequestSendAndForgetNoFormatting2 (kmdf) |
另请参阅
WdfIoTargetSendInternalIoctlOthersSynchronously