RtlMoveVolatileMemory 函数 (wdm.h)

RtlMoveVolatileMemory 函数的存在是为了提供 RtlMoveMemory 行为 (例如,在开发人员需要确保复制操作 (不受编译器优化) 的情况下,将内存从一个位置复制到另一个位置) 。 与 RtlCopyVolatileMemory 不同,此函数处理 缓冲区和 目标 缓冲区重叠的情况。

语法

volatile void * RtlMoveVolatileMemory(
  [out] volatile void       *Destination,
  [in]  volatile const void *Source,
  [in]  size_t              Length
);

参数

[out] Destination

指向复制块目标的起始地址的指针。

[in] Source

指向要复制的内存块的起始地址的指针。

[in] Length

要复制的内存块的大小(以字节为单位)。

返回值

返回 Destination 的值。

注解

RtlMoveVolatileMemory 函数具有以下属性:

  • 函数未被识别为编译器内部函数,因此编译器永远不会完全优化调用 (,也不会将调用替换为) 的等效指令序列。 这与 RtlMoveMemory 不同,RtlMoveMemory 受各种编译器优化的约束。

  • 调用返回时,数据已从 复制到 目标。 此函数对 目标的 内存访问仅在 函数中执行 (例如,编译器无法将内存访问移出此函数) 。

  • 如果平台允许,函数可能会执行未对齐的内存访问。

  • 函数可以在复制操作过程中多次访问内存位置。

  • RtlMoveMemory 类似,当 目标 相互重叠时,它支持复制操作。

注意

此函数适用于所有版本的 Windows,而不仅仅是最新版本。 需要使用最新的 WDK 才能从 wdm.h 标头获取函数声明。 还需要从最新 WDK (volatileaccessk.lib) 库。 但是,生成的驱动程序将在较旧版本的 Windows 上运行正常。

示例

HEADER MyHeader;

UCHAR RawBuffer[100];

// Ensure that the shared memory (which could be constantly changing)
// is copied in to the local MyHeader variable.
// Note that the compiler is allowed to optimize away calls to
// RtlMoveMemory so those functions are not guaranteed to actually
// make a local copy of data.
//
// RtlMoveVolatileMemory does handle buffers 
// that overlap with each other (MoveMemory semantics).
// Assume SharedMemory points to virtual memory that is also mapped in an untrusted process.
// Assume that untrusted process is changing the memory contents while you are accessing it.

PVOID SharedMemory;

RtlMoveVolatileMemory(&MyHeader, SharedMemory, sizeof(MyHeader));

if (MyHeader.Size < 100) {

    // Because MyHeader is local and we are guaranteed we actually made
    // a local copy, we can be sure that the "Size" value will not change
    // between the previous bounds check and the below call to RtlFillMemory.
    // If RtlMoveMemory had been used to copy the data, it is possible
    // that a compiler may optimize away the call to MoveMemory and instead fetch
    // the "size" field of MyHeader directly from untrusted memory two times.
    // The first time it would be fetched for the bounds check, and the second
    // time it is fetched is for the call to RtlFillMemory. It is possible the memory
    // could have changed between the two accesses resulting in the size check
    // being ineffective.
    
    RtlFillMemory (RawBuffer, MyHeader.Size, 0);

}

要求

要求
Header wdm.h (包括 Wdm.h)
Library volatileaccessk.lib (内核模式) ,volatileaccessu.lib (用户模式)

另请参阅

RtlCopyVolatileMemory

RtlMoveMemory