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。 否則,此方法可能會傳回下列其中一個值:
傳回碼 | Description |
---|---|
|
輸入參數無效。 |
|
Length 參數為零。 |
|
要求已經完成或無效。 |
|
目前的線程不是 I/O 要求的建立者。 |
|
記憶體不足,無法完成作業。 |
這個方法也可能傳回其他 NTSTATUS值。
如果驅動程式提供無效的物件句柄,就會發生錯誤檢查。
備註
只有最上層驅動程式可以呼叫 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;
}
規格需求
需求 | 值 |
---|---|
目標平台 | Universal |
最小 KMDF 版本 | 1.0 |
標頭 | wdfrequest.h (包含 Wdf.h) |
程式庫 | Wdf01000.sys (請參閱 Framework Library Versioning.) |
IRQL | PASSIVE_LEVEL |
DDI 合規性規則 | DriverCreate (kmdf) , InvalidReqAccess (kmdf ) , InvalidReqAccessLocal (kmdf ) , KmdfIrql (kmdf) , KmdfIrql2 (kmdf) , KmdfIrqlExplicit (kmdf) |