Функция 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 (режим пользователя) |