Share via


Función MoveVolatileMemory

Copia el contenido de un bloque de memoria de origen en un bloque de memoria de destino y admite bloques de memoria de origen y destino superpuestos.

Importante

Parte de la información hace referencia a un producto de versión preliminar que puede sufrir importantes modificaciones antes de que se publique la versión comercial. Microsoft no proporciona ninguna garantía, expresa o implícita, con respecto a la información proporcionada aquí.

Parámetros

Destino del parámetro [out]

Un puntero a la dirección inicial del destino del bloque copiado.

Origen del parámetro [in]

Un puntero a la dirección inicial del bloque de memoria que se va a copiar.

Longitud del parámetro [in]

El tamaño del bloque de memoria que se va a copiar, en bytes.

Sintaxis

volatile void* __cdecl
  MoveVolatileMemory (
    _Out_writes_bytes_all_(Length) volatile void* Destination,
    _In_reads_bytes_(Length) volatile const void* Source,
    SIZE_T Length
  );

Comentarios

Esta API existe para proporcionar el comportamiento de MoveMemory (es decir, copiar memoria de una ubicación a otra) en situaciones en las que el desarrollador debe asegurarse de que se produce la operación de copia (es decir, no está sujeta a optimizaciones del compilador). A diferencia de CopyVolatileMemory, esta API controla los casos en los que el búfer de Origen y el de Destino se superponen.

La API tiene las siguientes propiedades:

  • La API no se reconoce como intrínseca del compilador, por lo que este nunca optimizará la llamada (ya sea por completo o reemplazándola por una secuencia "equivalente" de instrucciones). Esto difiere de MoveMemory, que está sujeto a una variedad de optimizaciones del compilador.
  • Cuando se devuelve la llamada, los datos se han copiado de Origen a Destino. Esta función solo accederá a la memoria de Origen y Destino dentro de la función (es decir, el compilador no puede mover los accesos de memoria fuera de esta función).
  • La API puede realizar accesos a memoria no asignadas si la plataforma lo permite.
  • La API puede acceder a ubicaciones de memoria más de una vez como parte de su operación de copia.
  • Similar a MoveMemory en que admite operaciones de copia cuando Origen y Destino se superponen entre sí

Nota:

Esta función funciona en todas las versiones de Windows, no solo en la más reciente. Es necesario consumir el SDK más reciente para obtener la declaración de función del encabezado winbase.h. También se necesita la biblioteca (volatileaccessu.lib) del SDK más reciente. Sin embargo, el binario resultante se ejecutará correctamente en versiones anteriores de Windows.

Ejemplo

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
// MoveMemory/RtlMoveMemory so those functions are not guaranteed to actually
// make a local copy of data.
//
// MoveVolatileMemory 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;

MoveVolatileMemory(&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/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 FillMemory. It is possible the memory
  // could have changed between the two accesses resulting in the size check
  // being ineffective.

  FillMemory (RawBuffer, MyHeader.Size, 0);
}

Requisitos

Cliente mínimo admitido: compilación de versión preliminar de Windows 11 Insider

Encabezado: winbase.h (incluir Winbase.h)

Biblioteca en modo kernel: volatileaccessk.lib

Biblioteca en modo de usuario: volatileaccessu.lib

Consulte también