CopyVolatileMemory 関数
CopyVolatileMemory 関数は、ソース メモリ ブロックの内容をコピー先のメモリ ブロックにコピーします。
重要
一部の情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。
パラメーター
Param Destination [out]
コピーしたブロックのコピー先の開始アドレスへのポインター。
Param Source [in]
コピーするメモリ ブロックの開始アドレスへのポインター。
Param Length [in]
コピーするメモリ ブロックのサイズ (バイト単位)。
構文
volatile void* __cdecl
CopyVolatileMemory (
_Out_writes_bytes_all_(Length) volatile void* Destination,
_In_reads_bytes_(Length) volatile const void* Source,
SIZE_T Length
);
解説
この API は、コピー操作が確実に実行されるようにする必要がある (つまり、コンパイラの最適化の対象ではない) 場合に、CopyMemory の動作 (つまり、ある場所から別の場所へのメモリのコピー) を提供するために存在します。
この API には、次のプロパティがあります。
- この API は、コンパイラとして認識されないため、コンパイラが呼び出しを最適化することはありません (呼び出しを完全に最適化したり、"同等の" 命令シーケンスに置き換えたりすることはありません)。 これは、さまざまなコンパイラ最適化の対象となる CopyMemory とは異なります。
- 呼び出しが返されると、データはコピー元からコピー先にコピーされます。 この関数のコピー先とコピー元へのメモリ アクセスは、関数内でのみ実行されます (つまり、コンパイラはこの関数からメモリ アクセスを移動できません)。
- API は、プラットフォームで許可されている場合、アラインされていないメモリ アクセスを実行できます。
- API は、コピー操作の一環としてメモリの場所に複数回アクセスできます。
- CopyMemory と同様に、コピー元とコピー先が互いに重なっている場合はコピー操作をサポートしません。
Note
この関数は、最新バージョンだけではなく、すべてのバージョンの Windows で動作します。 winbase.h
ヘッダーから関数宣言を取得するには、最新の SDK を使用する必要があります。 また、最新の SDK のライブラリ (volatileaccessu.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
// 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);
}
要件
サポートされている最小のクライアント: Windows 11 Insider Preview ビルド TBD
ヘッダー: winbase.h (Winbase.h を含みます)
カーネル モード ライブラリ: volatileaccessk.lib
ユーザー モード ライブラリ: volatileaccessu.lib