Функция 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 в том, что поддерживает операции копирования, когда источник и назначение перекрываются друг с другом.

Примечание

Эта функция работает во всех версиях Windows, а не только в последней версии. Чтобы получить объявление функции из заголовка wdm.h, необходимо использовать последнюю версию WDK. Вам также потребуется библиотека (volatileaccessk.lib) из последней версии WDK. Однако полученный драйвер будет работать нормально в более старых версиях 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);

}

Требования

Требование Значение
Заголовок wdm.h (включая Wdm.h)
Библиотека volatileaccessk.lib (режим ядра), volatileaccessu.lib (режим пользователя)

См. также раздел

RtlCopyVolatileMemory

RtlMoveMemory