WdfRequestProbeAndLockUserBufferForRead 函数 (wdfrequest.h)
[仅适用于 KMDF]
WdfRequestProbeAndLockUserBufferForRead 方法验证 I/O 请求的用户模式缓冲区是否可读,然后锁定缓冲区的物理内存页,以便驱动程序堆栈中的驱动程序可以读取缓冲区。
语法
NTSTATUS WdfRequestProbeAndLockUserBufferForRead(
[in] WDFREQUEST Request,
[in] PVOID Buffer,
[in] size_t Length,
[out] WDFMEMORY *MemoryObject
);
参数
[in] Request
框架请求对象的句柄。
[in] Buffer
指向请求的输入缓冲区的指针。 有关更多信息,请参见下面的“备注”部分。
[in] Length
请求的输入缓冲区的长度(以字节为单位)。
[out] MemoryObject
指向位置的指针,该位置接收表示用户输入缓冲区的框架内存对象的句柄。
返回值
如果操作成功,WdfRequestProbeAndLockUserBufferForRead 将返回STATUS_SUCCESS。 否则,此方法可能会返回以下值之一:
返回代码 | 说明 |
---|---|
|
输入参数无效。 |
|
Length 参数为零。 |
|
请求已完成或无效。 |
|
当前线程不是 I/O 请求的创建者。 |
|
内存不足,无法完成操作。 |
此方法还可能返回其他 NTSTATUS 值。
如果驱动程序提供无效的对象句柄,则会发生 bug 检查。
注解
只有顶级驱动程序才能调用 WdfRequestProbeAndLockUserBufferForRead 方法,因为该方法需要创建 I/O 请求的进程的进程上下文。
用户输入缓冲区通常包含要写入设备的信息。
Buffer 参数指定的用户模式缓冲区可以是 WdfRequestRetrieveUnsafeUserInputBuffer 检索的缓冲区,也可以是不同的用户模式输入缓冲区。 例如,使用缓冲访问方法的 I/O 控制代码可能会传递包含指向用户模式缓冲区的嵌入指针的结构。 在这种情况下,驱动程序可以使用WdfRequestProbeAndLockUserBufferForRead 获取缓冲区的内存对象。
Length 参数指定的缓冲区长度不得大于缓冲区的实际大小。 否则,驱动程序可以访问缓冲区外部的内存,这是一种安全风险。
如果 WdfRequestProbeAndLockUserBufferForRead 返回STATUS_SUCCESS,则驱动程序将接收表示用户模式缓冲区的框架内存对象的句柄。 若要访问缓冲区,驱动程序必须调用 WdfMemoryGetBuffer。
当驱动程序调用 WdfRequestComplete 时,将自动释放框架内存对象。
有关 WdfRequestProbeAndLockUserBufferForRead 的详细信息,请参阅 在 Framework-Based 驱动程序中访问数据缓冲区。
示例
下面的代码示例是 NONPNP 示例驱动程序包含的 EvtIoInCallerContext 回调函数的缩短版本。 当回调函数收到 I/O 请求时,它会确定请求是否包含传输类型为 METHOD_NEITHER 的 I/O 控制代码。 如果请求包含此类 I/O 控制代码,则 函数:
- 调用 WdfRequestRetrieveUnsafeUserInputBuffer 和 WdfRequestRetrieveUnsafeUserOutputBuffer 以获取请求的读取和写入缓冲区的虚拟地址。
- 调用 WdfRequestProbeAndLockUserBufferForRead 和 WdfRequestProbeAndLockUserBufferForWrite 来探测和锁定缓冲区,并获取表示每个缓冲区的框架内存对象的句柄。
VOID
NonPnpEvtIoInCallerContext(
IN WDFDEVICE Device,
IN WDFREQUEST Request
)
{
NTSTATUS status = STATUS_SUCCESS;
PREQUEST_CONTEXT reqContext = NULL;
WDF_OBJECT_ATTRIBUTES attributes;
WDF_REQUEST_PARAMETERS params;
size_t inBufLen, outBufLen;
PVOID inBuf, outBuf;
WDF_REQUEST_PARAMETERS_INIT(¶ms);
WdfRequestGetParameters(
Request,
¶ms
);
//
// Check to see whether the driver received a METHOD_NEITHER I/O control code.
// If not, just send the request back to the framework.
//
if(!(params.Type == WdfRequestTypeDeviceControl &&
params.Parameters.DeviceIoControl.IoControlCode ==
IOCTL_NONPNP_METHOD_NEITHER)) {
status = WdfDeviceEnqueueRequest(
Device,
Request
);
if( !NT_SUCCESS(status) ) {
goto End;
}
return;
}
//
// The I/O control code is METHOD_NEITHER.
// First, retrieve the virtual addresses of
// the input and output buffers.
//
status = WdfRequestRetrieveUnsafeUserInputBuffer(
Request,
0,
&inBuf,
&inBufLen
);
if(!NT_SUCCESS(status)) {
goto End;
}
status = WdfRequestRetrieveUnsafeUserOutputBuffer(
Request,
0,
&outBuf,
&outBufLen
);
if(!NT_SUCCESS(status)) {
goto End;
}
//
// Next, allocate context space for the request, so that the
// driver can store handles to the memory objects that will
// be created for input and output buffers.
//
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes,
REQUEST_CONTEXT);
status = WdfObjectAllocateContext(
Request,
&attributes,
&reqContext
);
if(!NT_SUCCESS(status)) {
goto End;
}
//
// Next, probe and lock the read and write buffers.
//
status = WdfRequestProbeAndLockUserBufferForRead(
Request,
inBuf,
inBufLen,
&reqContext->InputMemoryBuffer
);
if(!NT_SUCCESS(status)) {
goto End;
}
status = WdfRequestProbeAndLockUserBufferForWrite(
Request,
outBuf,
outBufLen,
&reqContext->OutputMemoryBuffer
);
if(!NT_SUCCESS(status)) {
goto End;
}
//
// Finally, return the request to the framework.
//
status = WdfDeviceEnqueueRequest(
Device,
Request
);
if(!NT_SUCCESS(status)) {
goto End;
}
return;
End:
WdfRequestComplete(
Request,
status
);
return;
}
要求
要求 | 值 |
---|---|
目标平台 | 通用 |
最低 KMDF 版本 | 1.0 |
标头 | wdfrequest.h (包括 Wdf.h) |
Library | Wdf01000.sys (请参阅框架库 Versioning.) |
IRQL | PASSIVE_LEVEL |
DDI 符合性规则 | DriverCreate (kmdf) 、 InvalidReqAccess (kmdf) 、 InvalidReqAccessLocal (kmdf) 、 KmdfIrql (kmdf) 、 KmdfIrql2 (kmdf) 、 KmdfIrqlExplicit (kmdf) |