NTSTATUS
NtWriteVirtualMemory(
__in HANDLE ProcessHandle,
__in_opt PVOID BaseAddress,
__in_bcount(BufferSize) CONST VOID *Buffer,
__in SIZE_T BufferSize,
__out_opt PSIZE_T NumberOfBytesWritten
)
/*++
Routine Description:
This function copies the specified address range from the current
process into the specified address range of the specified process.
Arguments:
ProcessHandle - Supplies an open handle to a process object.
BaseAddress - Supplies the base address to be written to in the
specified process.
Buffer - Supplies the address of a buffer which contains the
contents to be written into the specified process
address space.
BufferSize - Supplies the requested number of bytes to write
into the specified process.
NumberOfBytesWritten - Receives the actual number of bytes
transferred into the specified address space.
Return Value:
NTSTATUS.
--*/
{
SIZE_T BytesCopied;
KPROCESSOR_MODE PreviousMode;
PEPROCESS Process;
NTSTATUS Status;
PETHREAD CurrentThread;
PAGED_CODE();
//
// Get the previous mode and probe output argument if necessary.
//
CurrentThread = PsGetCurrentThread ();
PreviousMode = KeGetPreviousModeByThread(&CurrentThread->Tcb);
if (PreviousMode != KernelMode) {
if (((PCHAR)BaseAddress + BufferSize < (PCHAR)BaseAddress) ||
((PCHAR)Buffer + BufferSize < (PCHAR)Buffer) ||
((PVOID)((PCHAR)BaseAddress + BufferSize) > MM_HIGHEST_USER_ADDRESS) ||
((PVOID)((PCHAR)Buffer + BufferSize) > MM_HIGHEST_USER_ADDRESS)) {
return STATUS_ACCESS_VIOLATION;
}
if (ARGUMENT_PRESENT(NumberOfBytesWritten)) {
try {
ProbeForWriteUlong_ptr(NumberOfBytesWritten);
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}
}
}
//
// If the buffer size is not zero, then attempt to write data from the
// current process address space into the target process address space.
//
BytesCopied = 0;
Status = STATUS_SUCCESS;
if (BufferSize != 0) {
//
// Reference the target process.
//
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_VM_WRITE,
PsProcessType,
PreviousMode,
(PVOID *)&Process,
NULL);
//
// If the process was successfully referenced, then attempt to
// write the specified memory either by direct mapping or copying
// through nonpaged pool.
//
if (Status == STATUS_SUCCESS) {
Status = MmCopyVirtualMemory (PsGetCurrentProcessByThread(CurrentThread),
Buffer,
Process,
BaseAddress,
BufferSize,
PreviousMode,
&BytesCopied);
//
// Dereference the target process.
//
ObDereferenceObject(Process);
}
}
//
// If requested, return the number of bytes read.
//
if (ARGUMENT_PRESENT(NumberOfBytesWritten)) {
try {
*NumberOfBytesWritten = BytesCopied;
} except(EXCEPTION_EXECUTE_HANDLER) {
NOTHING;
}
}
return Status;
}