[仅适用于 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 驱动程序中的数据缓冲区。
例子
以下代码示例是 EvtIoInCallerContext 回调函数的缩短版本,NONPNP 示例驱动程序包含。 当回调函数收到 I/O 请求时,它确定请求是否包含具有传输类型的 I/O 控制代码METHOD_NEITHER。 如果请求包含此类 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) | 
| 库 | Wdf01000.sys(请参阅框架库版本控制。 | 
| IRQL | PASSIVE_LEVEL | 
| DDI 符合性规则 | DriverCreate(kmdf),InvalidReqAccess(kmdf),InvalidReqAccessLocal(kmdf),KmdfIrql(kmdf),KmdfIrql2(kmdf),KmdfIrqlExplicit(kmdf) |