Share via


Função CopyVolatileMemory

A função CopyVolatileMemory copia o conteúdo de um bloco de memória de origem para um bloco de memória de destino.

Importante

Algumas informações referem-se a um produto de pré-lançamento que pode ser substancialmente modificado antes de ser lançado comercialmente. A Microsoft não oferece nenhuma garantia, explícita ou implícita, quanto às informações fornecidas aqui.

Parâmetros

Parâmetro Destination [saída]

Um ponteiro para o endereço inicial do destino do bloco copiado.

Parâmetro Source [entrada]

Um ponteiro para o endereço inicial do bloco de memória que será copiado.

Parâmetro Length [entrada]

O tamanho do bloco de memória a ser copiado, em bytes.

Sintaxe

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

Comentários

Essa API existe para oferecer um comportamento CopyMemory (ou seja, copiar memória de um local para outro) em situações em que os desenvolvedores precisam ter certeza de que a operação de cópia ocorre (ou seja, não está sujeita a otimizações do compilador).

A API possui as seguintes características:

  • A API não é reconhecida como uma função intrínseca do compilar, portanto, o compilador nunca otimizará a chamada (seja totalmente ou substituindo a chamada por uma sequência "equivalente" de instruções). Isso difere de CopyMemory, que está sujeito a uma variedade de otimizações do compilador.
  • Quando a chamada retorna, os dados foram copiados da Source para o Destination. Os acessos à memória desta função a Source e Destination só serão realizados dentro da função (ou seja, o compilador não pode mover acessos à memória para fora desta função).
  • A API pode realizar acessos à memória não alinhados se a plataforma permitir.
  • A API pode acessar locais de memória mais de uma vez como parte da operação de cópia.
  • Semelhante a CopyMemory, no sentido que de que não suporta operações de cópia quando Source e Destination se sobrepõem.

Observação

Esta função é compatível com todas as versões do Windows, não apenas as mais recentes. Você precisa utilizar o SDK mais recente para obter a declaração de função do cabeçalho winbase.h. Você também precisa da biblioteca (volatileaccessu.lib) do SDK mais recente. Contudo, o binário resultante funcionará corretamente em versões anteriores do Windows.

Exemplo

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
// CopyMemory/RtlCopyMemory so those functions are not guaranteed to actually
// make a local copy of data.
//
// CopyVolatileMemory does not handle a source/dest buffer that overlap
// with each other (CopyMemory 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;

CopyVolatileMemory(&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 RtlCopyMemory/RtlCopyMemory had been used to copy the data, it is possible
  // that a compiler may optimize away the call to CopyMemory 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 com suporte: Windows 11 Insider Preview Build TBD

Cabeçalho: winbase.h (inclua Winbase.h)

Biblioteca em modo kernel: volatileaccessk.lib

Biblioteca em modo de usuário: volatileaccessu.lib

Confira também