Author: ros-arm-bringup
Date: Thu Oct 15 18:50:49 2009
New Revision: 43480
URL:
http://svn.reactos.org/svn/reactos?rev=43480&view=rev
Log:
- Multiple Virtual Memory API fixes:
- MiDoMappedcopy: The MDL should have 16 pages total, so MI_MAPPED_COPY_PAGES should be
14, not 16, to account for the MDL page itself, and the extra add-on page.
- MiDoMappedCopy: Check for working set quota exception.
- NtRead/WriteVirtualMemory: Do not attempt to do any work if the size is 0.
- NtRead/WriteVirtualMemory: Do not return SEH status if we fail to write the number of
bytes read/written -- return the function status.
- NtProtectVirtualMemory: Protect the memory while attached to the target process.
- NtProtectVirtualMemory: Do not return SEH status if we fail to write the number of
bytes protected -- return the function status.
- NtLock/UnlockVirtualMemory: Fix incorrect function definition. The last parameter is a
bitfield. The middle two parameters are pointers, not values.
- VirtualLock/Unlock: Fix calling NtLock/UnlockVirtualMemory with new correct function
definitions. Call with MAP_PROCESS.
- NtLock/UnlockVirtualMemory: Apply SEH. Validate flags. Validate parameters.
- NtLock/UnlockVirtualMemory: Attach to the process while doing the operation. Reference
the process.
- NtLock/UnlockVirtualMemory: Check for SE_LOCK_MEMORY_PRIVILEGE if MAP_SYSTEM is
specified.
- Move MAP_SYSTEM and MAP_PROCESS from ntifs.h to mmtypes.h in NDK.
- NtLock/UnlockVirtualMemory: Return success and semi-legitimate return values saying
nothing was actually done.
- NtFlushVirtualMemory: Apply SEH. Validate flags. Validate parameters. Call
MmFlushVirtualMemory.
- NtFlushVirtualMemory: Reference the process.
- NtFlushVirtualMemory: Return success and semi-legitimate return values indicating
nothing was flushed.
- NtGetWriteWatch: Fix function prototype.
- NtGet/ResetWriteWatch: Apply SEH instead of hacked parameter checks. Validate
parameters.
- NtGet/ResetWriteWatch: Reference the process.
- NtGet/ResetWriteWatch: Return semi-legitimate return values indicating nothing was
written to.
- These APIs are now owned by ARM3.
Added:
trunk/reactos/ntoskrnl/mm/ARM3/virtual.c (with props)
Modified:
trunk/reactos/dll/win32/kernel32/mem/virtual.c
trunk/reactos/include/ddk/ntifs.h
trunk/reactos/include/ndk/mmfuncs.h
trunk/reactos/include/ndk/mmtypes.h
trunk/reactos/ntoskrnl/mm/virtual.c
trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild
Modified: trunk/reactos/dll/win32/kernel32/mem/virtual.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/mem/vir…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/mem/virtual.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/mem/virtual.c [iso-8859-1] Thu Oct 15 18:50:49 2009
@@ -170,14 +170,15 @@
VirtualLock(IN LPVOID lpAddress,
IN SIZE_T dwSize)
{
- ULONG BytesLocked;
- NTSTATUS Status;
+ NTSTATUS Status;
+ ULONG RegionSize = dwSize;
+ PVOID BaseAddress = lpAddress;
/* Lock the memory */
Status = NtLockVirtualMemory(NtCurrentProcess(),
- lpAddress,
- dwSize,
- &BytesLocked);
+ &BaseAddress,
+ &RegionSize,
+ MAP_PROCESS);
if (!NT_SUCCESS(Status))
{
/* We failed */
@@ -244,14 +245,15 @@
VirtualUnlock(IN LPVOID lpAddress,
IN SIZE_T dwSize)
{
- ULONG BytesLocked;
- NTSTATUS Status;
-
- /* Unlock the memory */
+ NTSTATUS Status;
+ ULONG RegionSize = dwSize;
+ PVOID BaseAddress = lpAddress;
+
+ /* Lock the memory */
Status = NtUnlockVirtualMemory(NtCurrentProcess(),
- lpAddress,
- dwSize,
- &BytesLocked);
+ &BaseAddress,
+ &RegionSize,
+ MAP_PROCESS);
if (!NT_SUCCESS(Status))
{
/* We failed */
Modified: trunk/reactos/include/ddk/ntifs.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/ddk/ntifs.h?rev=43…
==============================================================================
--- trunk/reactos/include/ddk/ntifs.h [iso-8859-1] (original)
+++ trunk/reactos/include/ddk/ntifs.h [iso-8859-1] Thu Oct 15 18:50:49 2009
@@ -329,8 +329,6 @@
#define MAILSLOT_SIZE_AUTO 0
-#define MAP_PROCESS 1L
-#define MAP_SYSTEM 2L
#define MEM_DOS_LIM 0x40000000
#define MCB_FLAG_RAISE_ON_ALLOCATION_FAILURE 1
Modified: trunk/reactos/include/ndk/mmfuncs.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/mmfuncs.h?rev=…
==============================================================================
--- trunk/reactos/include/ndk/mmfuncs.h [iso-8859-1] (original)
+++ trunk/reactos/include/ndk/mmfuncs.h [iso-8859-1] Thu Oct 15 18:50:49 2009
@@ -173,10 +173,10 @@
NTSTATUS
NTAPI
NtLockVirtualMemory(
- HANDLE ProcessHandle,
- PVOID BaseAddress,
- SIZE_T NumberOfBytesToLock,
- PSIZE_T NumberOfBytesLocked
+ IN HANDLE ProcessHandle,
+ IN OUT PVOID *BaseAddress,
+ IN OUT PSIZE_T NumberOfBytesToLock,
+ IN ULONG MapType
);
NTSTATUS
@@ -278,9 +278,9 @@
NTAPI
NtUnlockVirtualMemory(
IN HANDLE ProcessHandle,
- IN PVOID BaseAddress,
- IN SIZE_T NumberOfBytesToUnlock,
- OUT PSIZE_T NumberOfBytesUnlocked OPTIONAL
+ IN OUT PVOID *BaseAddress,
+ IN OUT PSIZE_T NumberOfBytesToUnlock,
+ IN ULONG MapType
);
NTSYSCALLAPI
@@ -367,10 +367,10 @@
NTSTATUS
NTAPI
ZwLockVirtualMemory(
- HANDLE ProcessHandle,
- PVOID BaseAddress,
- SIZE_T NumberOfBytesToLock,
- PSIZE_T NumberOfBytesLocked
+ IN HANDLE ProcessHandle,
+ IN OUT PVOID *BaseAddress,
+ IN OUT PSIZE_T NumberOfBytesToLock,
+ IN ULONG MapType
);
NTSYSAPI
@@ -448,9 +448,9 @@
NTAPI
ZwUnlockVirtualMemory(
IN HANDLE ProcessHandle,
- IN PVOID BaseAddress,
- IN SIZE_T NumberOfBytesToUnlock,
- OUT PSIZE_T NumberOfBytesUnlocked OPTIONAL
+ IN OUT PVOID *BaseAddress,
+ IN OUT PSIZE_T NumberOfBytesToUnlock,
+ IN ULONG MapType
);
NTSYSAPI
Modified: trunk/reactos/include/ndk/mmtypes.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/mmtypes.h?rev=…
==============================================================================
--- trunk/reactos/include/ndk/mmtypes.h [iso-8859-1] (original)
+++ trunk/reactos/include/ndk/mmtypes.h [iso-8859-1] Thu Oct 15 18:50:49 2009
@@ -56,6 +56,12 @@
#define MMPFNUSE_AWEPAGE 9
#define MMPFNUSE_DRIVERLOCKPAGE 10
#define MMPFNUSE_KERNELSTACK 11
+
+//
+// Lock/Unlock Virtuam Memory Flags
+//
+#define MAP_PROCESS 1
+#define MAP_SYSTEM 2
#ifndef NTOS_MODE_USER
Added: trunk/reactos/ntoskrnl/mm/ARM3/virtual.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/virtual.c…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/virtual.c (added)
+++ trunk/reactos/ntoskrnl/mm/ARM3/virtual.c [iso-8859-1] Thu Oct 15 18:50:49 2009
@@ -1,0 +1,1757 @@
+/*
+ * PROJECT: ReactOS Kernel
+ * LICENSE: BSD - See COPYING.ARM in the top level directory
+ * FILE: ntoskrnl/mm/ARM3/virtual.c
+ * PURPOSE: ARM Memory Manager Virtual Memory Management
+ * PROGRAMMERS: ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <debug.h>
+
+#line 15 "ARM³::VIRTUAL"
+#define MODULE_INVOLVED_IN_ARM3
+#include "../ARM3/miarm.h"
+
+#define MI_MAPPED_COPY_PAGES 14
+#define MI_POOL_COPY_BYTES 512
+#define MI_MAX_TRANSFER_SIZE 64 * 1024
+
+NTSTATUS NTAPI
+MiProtectVirtualMemory(IN PEPROCESS Process,
+ IN OUT PVOID *BaseAddress,
+ IN OUT PSIZE_T NumberOfBytesToProtect,
+ IN ULONG NewAccessProtection,
+ OUT PULONG OldAccessProtection OPTIONAL);
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+LONG
+MiGetExceptionInfo(IN PEXCEPTION_POINTERS ExceptionInfo,
+ OUT PBOOLEAN HaveBadAddress,
+ OUT PULONG_PTR BadAddress)
+{
+ PEXCEPTION_RECORD ExceptionRecord;
+ PAGED_CODE();
+
+ //
+ // Assume default
+ //
+ *HaveBadAddress = FALSE;
+
+ //
+ // Get the exception record
+ //
+ ExceptionRecord = ExceptionInfo->ExceptionRecord;
+
+ //
+ // Look at the exception code
+ //
+ if ((ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION) ||
+ (ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION) ||
+ (ExceptionRecord->ExceptionCode == STATUS_IN_PAGE_ERROR))
+ {
+ //
+ // We can tell the address if we have more than one parameter
+ //
+ if (ExceptionRecord->NumberParameters > 1)
+ {
+ //
+ // Return the address
+ //
+ *HaveBadAddress = TRUE;
+ *BadAddress = ExceptionRecord->ExceptionInformation[1];
+ }
+ }
+
+ //
+ // Continue executing the next handler
+ //
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+NTSTATUS
+NTAPI
+MiDoMappedCopy(IN PEPROCESS SourceProcess,
+ IN PVOID SourceAddress,
+ IN PEPROCESS TargetProcess,
+ OUT PVOID TargetAddress,
+ IN SIZE_T BufferSize,
+ IN KPROCESSOR_MODE PreviousMode,
+ OUT PSIZE_T ReturnSize)
+{
+ PFN_NUMBER MdlBuffer[(sizeof(MDL) / sizeof(PFN_NUMBER)) + MI_MAPPED_COPY_PAGES + 1];
+ PMDL Mdl = (PMDL)MdlBuffer;
+ SIZE_T TotalSize, CurrentSize, RemainingSize;
+ volatile BOOLEAN FailedInProbe = FALSE, FailedInMapping = FALSE, FailedInMoving;
+ volatile BOOLEAN PagesLocked;
+ PVOID CurrentAddress = SourceAddress, CurrentTargetAddress = TargetAddress;
+ volatile PVOID MdlAddress;
+ KAPC_STATE ApcState;
+ BOOLEAN HaveBadAddress;
+ ULONG_PTR BadAddress;
+ NTSTATUS Status = STATUS_SUCCESS;
+ PAGED_CODE();
+
+ //
+ // Calculate the maximum amount of data to move
+ //
+ TotalSize = MI_MAPPED_COPY_PAGES * PAGE_SIZE;
+ if (BufferSize <= TotalSize) TotalSize = BufferSize;
+ CurrentSize = TotalSize;
+ RemainingSize = BufferSize;
+
+ //
+ // Loop as long as there is still data
+ //
+ while (RemainingSize > 0)
+ {
+ //
+ // Check if this transfer will finish everything off
+ //
+ if (RemainingSize < CurrentSize) CurrentSize = RemainingSize;
+
+ //
+ // Attach to the source address space
+ //
+ KeStackAttachProcess(&SourceProcess->Pcb, &ApcState);
+
+ //
+ // Reset state for this pass
+ //
+ MdlAddress = NULL;
+ PagesLocked = FALSE;
+ FailedInMoving = FALSE;
+ ASSERT(FailedInProbe == FALSE);
+
+ //
+ // Protect user-mode copy
+ //
+ _SEH2_TRY
+ {
+ //
+ // If this is our first time, probe the buffer
+ //
+ if ((CurrentAddress == SourceAddress) && (PreviousMode !=
KernelMode))
+ {
+ //
+ // Catch a failure here
+ //
+ FailedInProbe = TRUE;
+
+ //
+ // Do the probe
+ //
+ ProbeForRead(SourceAddress, BufferSize, sizeof(CHAR));
+
+ //
+ // Passed
+ //
+ FailedInProbe = FALSE;
+ }
+
+ //
+ // Initialize and probe and lock the MDL
+ //
+ MmInitializeMdl(Mdl, CurrentAddress, CurrentSize);
+ MmProbeAndLockPages(Mdl, PreviousMode, IoReadAccess);
+ PagesLocked = TRUE;
+
+ //
+ // Now map the pages
+ //
+ MdlAddress = MmMapLockedPagesSpecifyCache(Mdl,
+ KernelMode,
+ MmCached,
+ NULL,
+ FALSE,
+ HighPagePriority);
+ if (!MdlAddress)
+ {
+ //
+ // Use our SEH handler to pick this up
+ //
+ FailedInMapping = TRUE;
+ ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ //
+ // Now let go of the source and grab to the target process
+ //
+ KeUnstackDetachProcess(&ApcState);
+ KeStackAttachProcess(&TargetProcess->Pcb, &ApcState);
+
+ //
+ // Check if this is our first time through
+ //
+ if ((CurrentAddress == SourceAddress) && (PreviousMode !=
KernelMode))
+ {
+ //
+ // Catch a failure here
+ //
+ FailedInProbe = TRUE;
+
+ //
+ // Do the probe
+ //
+ ProbeForWrite(TargetAddress, BufferSize, sizeof(CHAR));
+
+ //
+ // Passed
+ //
+ FailedInProbe = FALSE;
+ }
+
+ //
+ // Now do the actual move
+ //
+ FailedInMoving = TRUE;
+ RtlCopyMemory(CurrentTargetAddress, MdlAddress, CurrentSize);
+ }
+ _SEH2_EXCEPT(MiGetExceptionInfo(_SEH2_GetExceptionInformation(),
+ &HaveBadAddress,
+ &BadAddress))
+ {
+ //
+ // Detach from whoever we may be attached to
+ //
+ KeUnstackDetachProcess(&ApcState);
+
+ //
+ // Check if we had mapped the pages
+ //
+ if (MdlAddress) MmUnmapLockedPages(MdlAddress, Mdl);
+
+ //
+ // Check if we had locked the pages
+ //
+ if (PagesLocked) MmUnlockPages(Mdl);
+
+ //
+ // Check if we hit working set quota
+ //
+ if (_SEH2_GetExceptionCode() == STATUS_WORKING_SET_QUOTA)
+ {
+ //
+ // Return the error
+ //
+ return STATUS_WORKING_SET_QUOTA;
+ }
+
+ //
+ // Check if we failed during the probe or mapping
+ //
+ if ((FailedInProbe) || (FailedInMapping))
+ {
+ //
+ // Exit
+ //
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(return Status);
+ }
+
+ //
+ // Otherwise, we failed probably during the move
+ //
+ *ReturnSize = BufferSize - RemainingSize;
+ if (FailedInMoving)
+ {
+ //
+ // Check if we know exactly where we stopped copying
+ //
+ if (HaveBadAddress)
+ {
+ //
+ // Return the exact number of bytes copied
+ //
+ *ReturnSize = BadAddress - (ULONG_PTR)SourceAddress;
+ }
+ }
+
+ //
+ // Return partial copy
+ //
+ Status = STATUS_PARTIAL_COPY;
+ }
+ _SEH2_END;
+
+ //
+ // Check for SEH status
+ //
+ if (Status != STATUS_SUCCESS) return Status;
+
+ //
+ // Detach from target
+ //
+ KeUnstackDetachProcess(&ApcState);
+
+ //
+ // Unmap and unlock
+ //
+ MmUnmapLockedPages(MdlAddress, Mdl);
+ MmUnlockPages(Mdl);
+
+ //
+ // Update location and size
+ //
+ RemainingSize -= CurrentSize;
+ CurrentAddress = (PVOID)((ULONG_PTR)CurrentAddress + CurrentSize);
+ CurrentTargetAddress = (PVOID)((ULONG_PTR)CurrentTargetAddress + CurrentSize);
+ }
+
+ //
+ // All bytes read
+ //
+ *ReturnSize = BufferSize;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+MiDoPoolCopy(IN PEPROCESS SourceProcess,
+ IN PVOID SourceAddress,
+ IN PEPROCESS TargetProcess,
+ OUT PVOID TargetAddress,
+ IN SIZE_T BufferSize,
+ IN KPROCESSOR_MODE PreviousMode,
+ OUT PSIZE_T ReturnSize)
+{
+ UCHAR StackBuffer[MI_POOL_COPY_BYTES];
+ SIZE_T TotalSize, CurrentSize, RemainingSize;
+ volatile BOOLEAN FailedInProbe = FALSE, FailedInMoving, HavePoolAddress = FALSE;
+ PVOID CurrentAddress = SourceAddress, CurrentTargetAddress = TargetAddress;
+ PVOID PoolAddress;
+ KAPC_STATE ApcState;
+ BOOLEAN HaveBadAddress;
+ ULONG_PTR BadAddress;
+ NTSTATUS Status = STATUS_SUCCESS;
+ PAGED_CODE();
+
+ //
+ // Calculate the maximum amount of data to move
+ //
+ TotalSize = MI_MAX_TRANSFER_SIZE;
+ if (BufferSize <= MI_MAX_TRANSFER_SIZE) TotalSize = BufferSize;
+ CurrentSize = TotalSize;
+ RemainingSize = BufferSize;
+
+ //
+ // Check if we can use the stack
+ //
+ if (BufferSize <= MI_POOL_COPY_BYTES)
+ {
+ //
+ // Use it
+ //
+ PoolAddress = (PVOID)StackBuffer;
+ }
+ else
+ {
+ //
+ // Allocate pool
+ //
+ PoolAddress = ExAllocatePoolWithTag(NonPagedPool, TotalSize, 'VmRw');
+ if (!PoolAddress) ASSERT(FALSE);
+ HavePoolAddress = TRUE;
+ }
+
+ //
+ // Loop as long as there is still data
+ //
+ while (RemainingSize > 0)
+ {
+ //
+ // Check if this transfer will finish everything off
+ //
+ if (RemainingSize < CurrentSize) CurrentSize = RemainingSize;
+
+ //
+ // Attach to the source address space
+ //
+ KeStackAttachProcess(&SourceProcess->Pcb, &ApcState);
+
+ //
+ // Reset state for this pass
+ //
+ FailedInMoving = FALSE;
+ ASSERT(FailedInProbe == FALSE);
+
+ //
+ // Protect user-mode copy
+ //
+ _SEH2_TRY
+ {
+ //
+ // If this is our first time, probe the buffer
+ //
+ if ((CurrentAddress == SourceAddress) && (PreviousMode !=
KernelMode))
+ {
+ //
+ // Catch a failure here
+ //
+ FailedInProbe = TRUE;
+
+ //
+ // Do the probe
+ //
+ ProbeForRead(SourceAddress, BufferSize, sizeof(CHAR));
+
+ //
+ // Passed
+ //
+ FailedInProbe = FALSE;
+ }
+
+ //
+ // Do the copy
+ //
+ RtlCopyMemory(PoolAddress, CurrentAddress, CurrentSize);
+
+ //
+ // Now let go of the source and grab to the target process
+ //
+ KeUnstackDetachProcess(&ApcState);
+ KeStackAttachProcess(&TargetProcess->Pcb, &ApcState);
+
+ //
+ // Check if this is our first time through
+ //
+ if ((CurrentAddress == SourceAddress) && (PreviousMode !=
KernelMode))
+ {
+ //
+ // Catch a failure here
+ //
+ FailedInProbe = TRUE;
+
+ //
+ // Do the probe
+ //
+ ProbeForWrite(TargetAddress, BufferSize, sizeof(CHAR));
+
+ //
+ // Passed
+ //
+ FailedInProbe = FALSE;
+ }
+
+ //
+ // Now do the actual move
+ //
+ FailedInMoving = TRUE;
+ RtlCopyMemory(CurrentTargetAddress, PoolAddress, CurrentSize);
+ }
+ _SEH2_EXCEPT(MiGetExceptionInfo(_SEH2_GetExceptionInformation(),
+ &HaveBadAddress,
+ &BadAddress))
+ {
+ //
+ // Detach from whoever we may be attached to
+ //
+ KeUnstackDetachProcess(&ApcState);
+
+ //
+ // Check if we had allocated pool
+ //
+ if (HavePoolAddress) ExFreePool(PoolAddress);
+
+ //
+ // Check if we failed during the probe
+ //
+ if (FailedInProbe)
+ {
+ //
+ // Exit
+ //
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(return Status);
+ }
+
+ //
+ // Otherwise, we failed, probably during the move
+ //
+ *ReturnSize = BufferSize - RemainingSize;
+ if (FailedInMoving)
+ {
+ //
+ // Check if we know exactly where we stopped copying
+ //
+ if (HaveBadAddress)
+ {
+ //
+ // Return the exact number of bytes copied
+ //
+ *ReturnSize = BadAddress - (ULONG_PTR)SourceAddress;
+ }
+ }
+
+ //
+ // Return partial copy
+ //
+ Status = STATUS_PARTIAL_COPY;
+ }
+ _SEH2_END;
+
+ //
+ // Check for SEH status
+ //
+ if (Status != STATUS_SUCCESS) return Status;
+
+ //
+ // Detach from target
+ //
+ KeUnstackDetachProcess(&ApcState);
+
+ //
+ // Update location and size
+ //
+ RemainingSize -= CurrentSize;
+ CurrentAddress = (PVOID)((ULONG_PTR)CurrentAddress + CurrentSize);
+ CurrentTargetAddress = (PVOID)((ULONG_PTR)CurrentTargetAddress +
+ CurrentSize);
+ }
+
+ //
+ // Check if we had allocated pool
+ //
+ if (HavePoolAddress) ExFreePool(PoolAddress);
+
+ //
+ // All bytes read
+ //
+ *ReturnSize = BufferSize;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+MmCopyVirtualMemory(IN PEPROCESS SourceProcess,
+ IN PVOID SourceAddress,
+ IN PEPROCESS TargetProcess,
+ OUT PVOID TargetAddress,
+ IN SIZE_T BufferSize,
+ IN KPROCESSOR_MODE PreviousMode,
+ OUT PSIZE_T ReturnSize)
+{
+ NTSTATUS Status;
+ PEPROCESS Process = SourceProcess;
+
+ //
+ // Don't accept zero-sized buffers
+ //
+ if (!BufferSize) return STATUS_SUCCESS;
+
+ //
+ // If we are copying from ourselves, lock the target instead
+ //
+ if (SourceProcess == PsGetCurrentProcess()) Process = TargetProcess;
+
+ //
+ // Acquire rundown protection
+ //
+ if (!ExAcquireRundownProtection(&Process->RundownProtect))
+ {
+ //
+ // Fail
+ //
+ return STATUS_PROCESS_IS_TERMINATING;
+ }
+
+ //
+ // See if we should use the pool copy
+ //
+ if (BufferSize > MI_POOL_COPY_BYTES)
+ {
+ //
+ // Use MDL-copy
+ //
+ Status = MiDoMappedCopy(SourceProcess,
+ SourceAddress,
+ TargetProcess,
+ TargetAddress,
+ BufferSize,
+ PreviousMode,
+ ReturnSize);
+ }
+ else
+ {
+ //
+ // Do pool copy
+ //
+ Status = MiDoPoolCopy(SourceProcess,
+ SourceAddress,
+ TargetProcess,
+ TargetAddress,
+ BufferSize,
+ PreviousMode,
+ ReturnSize);
+ }
+
+ //
+ // Release the lock
+ //
+ ExReleaseRundownProtection(&Process->RundownProtect);
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+MmFlushVirtualMemory(IN PEPROCESS Process,
+ IN OUT PVOID *BaseAddress,
+ IN OUT PSIZE_T RegionSize,
+ OUT PIO_STATUS_BLOCK IoStatusBlock)
+{
+ PAGED_CODE();
+ UNIMPLEMENTED;
+
+ //
+ // Fake success
+ //
+ return STATUS_SUCCESS;
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+/*
+ * @unimplemented
+ */
+PVOID
+NTAPI
+MmGetVirtualForPhysical(IN PHYSICAL_ADDRESS PhysicalAddress)
+{
+ UNIMPLEMENTED;
+ return 0;
+}
+
+/*
+ * @unimplemented
+ */
+PVOID
+NTAPI
+MmSecureVirtualMemory(IN PVOID Address,
+ IN SIZE_T Length,
+ IN ULONG Mode)
+{
+ UNIMPLEMENTED;
+ return NULL;
+}
+
+/*
+ * @unimplemented
+ */
+VOID
+NTAPI
+MmUnsecureVirtualMemory(IN PVOID SecureMem)
+{
+ UNIMPLEMENTED;
+}
+
+/* SYSTEM CALLS ***************************************************************/
+
+NTSTATUS
+NTAPI
+NtReadVirtualMemory(IN HANDLE ProcessHandle,
+ IN PVOID BaseAddress,
+ OUT PVOID Buffer,
+ IN SIZE_T NumberOfBytesToRead,
+ OUT PSIZE_T NumberOfBytesRead OPTIONAL)
+{
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ PEPROCESS Process;
+ NTSTATUS Status = STATUS_SUCCESS;
+ SIZE_T BytesRead = 0;
+ PAGED_CODE();
+
+ //
+ // Check if we came from user mode
+ //
+ if (PreviousMode != KernelMode)
+ {
+ //
+ // Validate the read addresses
+ //
+ if ((((ULONG_PTR)BaseAddress + NumberOfBytesToRead) < (ULONG_PTR)BaseAddress)
||
+ (((ULONG_PTR)Buffer + NumberOfBytesToRead) < (ULONG_PTR)Buffer) ||
+ (((ULONG_PTR)BaseAddress + NumberOfBytesToRead) > MmUserProbeAddress) ||
+ (((ULONG_PTR)Buffer + NumberOfBytesToRead) > MmUserProbeAddress))
+ {
+ //
+ // Don't allow to write into kernel space
+ //
+ return STATUS_ACCESS_VIOLATION;
+ }
+
+ //
+ // Enter SEH for probe
+ //
+ _SEH2_TRY
+ {
+ //
+ // Probe the output value
+ //
+ if (NumberOfBytesRead) ProbeForWriteSize_t(NumberOfBytesRead);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //
+ // Get exception code
+ //
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+ }
+
+ //
+ // Don't do zero-byte transfers
+ //
+ if (NumberOfBytesToRead)
+ {
+ //
+ // Reference the process
+ //
+ Status = ObReferenceObjectByHandle(ProcessHandle,
+ PROCESS_VM_READ,
+ PsProcessType,
+ PreviousMode,
+ (PVOID*)(&Process),
+ NULL);
+ if (NT_SUCCESS(Status))
+ {
+ //
+ // Do the copy
+ //
+ Status = MmCopyVirtualMemory(Process,
+ BaseAddress,
+ PsGetCurrentProcess(),
+ Buffer,
+ NumberOfBytesToRead,
+ PreviousMode,
+ &BytesRead);
+
+ //
+ // Dereference the process
+ //
+ ObDereferenceObject(Process);
+ }
+ }
+
+ //
+ // Check if the caller sent this parameter
+ //
+ if (NumberOfBytesRead)
+ {
+ //
+ // Enter SEH to guard write
+ //
+ _SEH2_TRY
+ {
+ //
+ // Return the number of bytes read
+ //
+ *NumberOfBytesRead = BytesRead;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ }
+ _SEH2_END;
+ }
+
+ //
+ // Return status
+ //
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+NtWriteVirtualMemory(IN HANDLE ProcessHandle,
+ IN PVOID BaseAddress,
+ IN PVOID Buffer,
+ IN SIZE_T NumberOfBytesToWrite,
+ OUT PSIZE_T NumberOfBytesWritten OPTIONAL)
+{
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ PEPROCESS Process;
+ NTSTATUS Status = STATUS_SUCCESS;
+ ULONG BytesWritten = 0;
+ PAGED_CODE();
+
+ //
+ // Check if we came from user mode
+ //
+ if (PreviousMode != KernelMode)
+ {
+ //
+ // Validate the read addresses
+ //
+ if ((((ULONG_PTR)BaseAddress + NumberOfBytesToWrite) < (ULONG_PTR)BaseAddress)
||
+ (((ULONG_PTR)Buffer + NumberOfBytesToWrite) < (ULONG_PTR)Buffer) ||
+ (((ULONG_PTR)BaseAddress + NumberOfBytesToWrite) > MmUserProbeAddress) ||
+ (((ULONG_PTR)Buffer + NumberOfBytesToWrite) > MmUserProbeAddress))
+ {
+ //
+ // Don't allow to write into kernel space
+ //
+ return STATUS_ACCESS_VIOLATION;
+ }
+
+ //
+ // Enter SEH for probe
+ //
+ _SEH2_TRY
+ {
+ //
+ // Probe the output value
+ //
+ if (NumberOfBytesWritten) ProbeForWriteSize_t(NumberOfBytesWritten);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //
+ // Get exception code
+ //
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+ }
+
+ //
+ // Don't do zero-byte transfers
+ //
+ if (NumberOfBytesToWrite)
+ {
+ //
+ // Reference the process
+ //
+ Status = ObReferenceObjectByHandle(ProcessHandle,
+ PROCESS_VM_WRITE,
+ PsProcessType,
+ PreviousMode,
+ (PVOID*)&Process,
+ NULL);
+ if (NT_SUCCESS(Status))
+ {
+ //
+ // Do the copy
+ //
+ Status = MmCopyVirtualMemory(PsGetCurrentProcess(),
+ Buffer,
+ Process,
+ BaseAddress,
+ NumberOfBytesToWrite,
+ PreviousMode,
+ &BytesWritten);
+
+ //
+ // Dereference the process
+ //
+ ObDereferenceObject(Process);
+ }
+ }
+
+ //
+ // Check if the caller sent this parameter
+ //
+ if (NumberOfBytesWritten)
+ {
+ //
+ // Enter SEH to guard write
+ //
+ _SEH2_TRY
+ {
+ //
+ // Return the number of bytes written
+ //
+ *NumberOfBytesWritten = BytesWritten;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ }
+ _SEH2_END;
+ }
+
+ //
+ // Return status
+ //
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+NtProtectVirtualMemory(IN HANDLE ProcessHandle,
+ IN OUT PVOID *UnsafeBaseAddress,
+ IN OUT SIZE_T *UnsafeNumberOfBytesToProtect,
+ IN ULONG NewAccessProtection,
+ OUT PULONG UnsafeOldAccessProtection)
+{
+ PEPROCESS Process;
+ ULONG OldAccessProtection;
+ ULONG Protection;
+ PEPROCESS CurrentProcess = PsGetCurrentProcess();
+ PVOID BaseAddress = NULL;
+ SIZE_T NumberOfBytesToProtect = 0;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ NTSTATUS Status;
+ BOOLEAN Attached = FALSE;
+ KAPC_STATE ApcState;
+ PAGED_CODE();
+
+ //
+ // Check for valid protection flags
+ //
+ Protection = NewAccessProtection & ~(PAGE_GUARD|PAGE_NOCACHE);
+ if (Protection != PAGE_NOACCESS &&
+ Protection != PAGE_READONLY &&
+ Protection != PAGE_READWRITE &&
+ Protection != PAGE_WRITECOPY &&
+ Protection != PAGE_EXECUTE &&
+ Protection != PAGE_EXECUTE_READ &&
+ Protection != PAGE_EXECUTE_READWRITE &&
+ Protection != PAGE_EXECUTE_WRITECOPY)
+ {
+ //
+ // Fail
+ //
+ return STATUS_INVALID_PAGE_PROTECTION;
+ }
+
+ //
+ // Check if we came from user mode
+ //
+ if (PreviousMode != KernelMode)
+ {
+ //
+ // Enter SEH for probing
+ //
+ _SEH2_TRY
+ {
+ //
+ // Validate all outputs
+ //
+ ProbeForWritePointer(UnsafeBaseAddress);
+ ProbeForWriteSize_t(UnsafeNumberOfBytesToProtect);
+ ProbeForWriteUlong(UnsafeOldAccessProtection);
+
+ //
+ // Capture them
+ //
+ BaseAddress = *UnsafeBaseAddress;
+ NumberOfBytesToProtect = *UnsafeNumberOfBytesToProtect;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //
+ // Get exception code
+ //
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+ }
+ else
+ {
+ //
+ // Capture directly
+ //
+ BaseAddress = *UnsafeBaseAddress;
+ NumberOfBytesToProtect = *UnsafeNumberOfBytesToProtect;
+ }
+
+ //
+ // Catch illegal base address
+ //
+ if (BaseAddress > MM_HIGHEST_USER_ADDRESS) return STATUS_INVALID_PARAMETER_2;
+
+ //
+ // Catch illegal region size
+ //
+ if ((MmUserProbeAddress - (ULONG_PTR)BaseAddress) < NumberOfBytesToProtect)
+ {
+ //
+ // Fail
+ //
+ return STATUS_INVALID_PARAMETER_3;
+ }
+
+ //
+ // 0 is also illegal
+ //
+ if (!NumberOfBytesToProtect) return STATUS_INVALID_PARAMETER_3;
+
+ //
+ // Get a reference to the process
+ //
+ Status = ObReferenceObjectByHandle(ProcessHandle,
+ PROCESS_VM_OPERATION,
+ PsProcessType,
+ PreviousMode,
+ (PVOID*)(&Process),
+ NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ //
+ // Check if we should attach
+ //
+ if (CurrentProcess != Process)
+ {
+ //
+ // Do it
+ //
+ KeStackAttachProcess(&Process->Pcb, &ApcState);
+ Attached = TRUE;
+ }
+
+ //
+ // Do the actual work
+ //
+ Status = MiProtectVirtualMemory(Process,
+ &BaseAddress,
+ &NumberOfBytesToProtect,
+ NewAccessProtection,
+ &OldAccessProtection);
+
+ //
+ // Detach if needed
+ //
+ if (Attached) KeUnstackDetachProcess(&ApcState);
+
+ //
+ // Release reference
+ //
+ ObDereferenceObject(Process);
+
+ //
+ // Enter SEH to return data
+ //
+ _SEH2_TRY
+ {
+ //
+ // Return data to user
+ //
+ *UnsafeOldAccessProtection = OldAccessProtection;
+ *UnsafeBaseAddress = BaseAddress;
+ *UnsafeNumberOfBytesToProtect = NumberOfBytesToProtect;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ }
+ _SEH2_END;
+
+ //
+ // Return status
+ //
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+NtLockVirtualMemory(IN HANDLE ProcessHandle,
+ IN OUT PVOID *BaseAddress,
+ IN OUT PSIZE_T NumberOfBytesToLock,
+ IN ULONG MapType)
+{
+ PEPROCESS Process;
+ PEPROCESS CurrentProcess = PsGetCurrentProcess();
+ NTSTATUS Status;
+ BOOLEAN Attached = FALSE;
+ KAPC_STATE ApcState;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ PVOID CapturedBaseAddress;
+ SIZE_T CapturedBytesToLock;
+ PAGED_CODE();
+
+ //
+ // Validate flags
+ //
+ if ((MapType & ~(MAP_PROCESS | MAP_SYSTEM)))
+ {
+ //
+ // Invalid set of flags
+ //
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // At least one flag must be specified
+ //
+ if (!(MapType & (MAP_PROCESS | MAP_SYSTEM)))
+ {
+ //
+ // No flag given
+ //
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Enter SEH for probing
+ //
+ _SEH2_TRY
+ {
+ //
+ // Validate output data
+ //
+ ProbeForWritePointer(BaseAddress);
+ ProbeForWriteSize_t(NumberOfBytesToLock);
+
+ //
+ // Capture it
+ //
+ CapturedBaseAddress = *BaseAddress;
+ CapturedBytesToLock = *NumberOfBytesToLock;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //
+ // Get exception code
+ //
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+
+ //
+ // Catch illegal base address
+ //
+ if (CapturedBaseAddress > MM_HIGHEST_USER_ADDRESS) return
STATUS_INVALID_PARAMETER;
+
+ //
+ // Catch illegal region size
+ //
+ if ((MmUserProbeAddress - (ULONG_PTR)CapturedBaseAddress) < CapturedBytesToLock)
+ {
+ //
+ // Fail
+ //
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // 0 is also illegal
+ //
+ if (!CapturedBytesToLock) return STATUS_INVALID_PARAMETER;
+
+ //
+ // Get a reference to the process
+ //
+ Status = ObReferenceObjectByHandle(ProcessHandle,
+ PROCESS_VM_OPERATION,
+ PsProcessType,
+ PreviousMode,
+ (PVOID*)(&Process),
+ NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ //
+ // Check if this is is system-mapped
+ //
+ if (MapType & MAP_SYSTEM)
+ {
+ //
+ // Check for required privilege
+ //
+ if (!SeSinglePrivilegeCheck(SeLockMemoryPrivilege, PreviousMode))
+ {
+ //
+ // Fail: Don't have it
+ //
+ ObDereferenceObject(Process);
+ return STATUS_PRIVILEGE_NOT_HELD;
+ }
+ }
+
+ //
+ // Check if we should attach
+ //
+ if (CurrentProcess != Process)
+ {
+ //
+ // Do it
+ //
+ KeStackAttachProcess(&Process->Pcb, &ApcState);
+ Attached = TRUE;
+ }
+
+ //
+ // Oops :(
+ //
+ UNIMPLEMENTED;
+
+ //
+ // Detach if needed
+ //
+ if (Attached) KeUnstackDetachProcess(&ApcState);
+
+ //
+ // Release reference
+ //
+ ObDereferenceObject(Process);
+
+ //
+ // Enter SEH to return data
+ //
+ _SEH2_TRY
+ {
+ //
+ // Return data to user
+ //
+ *BaseAddress = CapturedBaseAddress;
+ *NumberOfBytesToLock = 0;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //
+ // Get exception code
+ //
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+
+ //
+ // Return status
+ //
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+NtUnlockVirtualMemory(IN HANDLE ProcessHandle,
+ IN OUT PVOID *BaseAddress,
+ IN OUT PSIZE_T NumberOfBytesToUnlock,
+ IN ULONG MapType)
+{
+ PEPROCESS Process;
+ PEPROCESS CurrentProcess = PsGetCurrentProcess();
+ NTSTATUS Status;
+ BOOLEAN Attached = FALSE;
+ KAPC_STATE ApcState;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ PVOID CapturedBaseAddress;
+ SIZE_T CapturedBytesToUnlock;
+ PAGED_CODE();
+
+ //
+ // Validate flags
+ //
+ if ((MapType & ~(MAP_PROCESS | MAP_SYSTEM)))
+ {
+ //
+ // Invalid set of flags
+ //
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // At least one flag must be specified
+ //
+ if (!(MapType & (MAP_PROCESS | MAP_SYSTEM)))
+ {
+ //
+ // No flag given
+ //
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Enter SEH for probing
+ //
+ _SEH2_TRY
+ {
+ //
+ // Validate output data
+ //
+ ProbeForWritePointer(BaseAddress);
+ ProbeForWriteSize_t(NumberOfBytesToUnlock);
+
+ //
+ // Capture it
+ //
+ CapturedBaseAddress = *BaseAddress;
+ CapturedBytesToUnlock = *NumberOfBytesToUnlock;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //
+ // Get exception code
+ //
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+
+ //
+ // Catch illegal base address
+ //
+ if (CapturedBaseAddress > MM_HIGHEST_USER_ADDRESS) return
STATUS_INVALID_PARAMETER;
+
+ //
+ // Catch illegal region size
+ //
+ if ((MmUserProbeAddress - (ULONG_PTR)CapturedBaseAddress) <
CapturedBytesToUnlock)
+ {
+ //
+ // Fail
+ //
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // 0 is also illegal
+ //
+ if (!CapturedBytesToUnlock) return STATUS_INVALID_PARAMETER;
+
+ //
+ // Get a reference to the process
+ //
+ Status = ObReferenceObjectByHandle(ProcessHandle,
+ PROCESS_VM_OPERATION,
+ PsProcessType,
+ PreviousMode,
+ (PVOID*)(&Process),
+ NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ //
+ // Check if this is is system-mapped
+ //
+ if (MapType & MAP_SYSTEM)
+ {
+ //
+ // Check for required privilege
+ //
+ if (!SeSinglePrivilegeCheck(SeLockMemoryPrivilege, PreviousMode))
+ {
+ //
+ // Fail: Don't have it
+ //
+ ObDereferenceObject(Process);
+ return STATUS_PRIVILEGE_NOT_HELD;
+ }
+ }
+
+ //
+ // Check if we should attach
+ //
+ if (CurrentProcess != Process)
+ {
+ //
+ // Do it
+ //
+ KeStackAttachProcess(&Process->Pcb, &ApcState);
+ Attached = TRUE;
+ }
+
+ //
+ // Oops :(
+ //
+ UNIMPLEMENTED;
+
+ //
+ // Detach if needed
+ //
+ if (Attached) KeUnstackDetachProcess(&ApcState);
+
+ //
+ // Release reference
+ //
+ ObDereferenceObject(Process);
+
+ //
+ // Enter SEH to return data
+ //
+ _SEH2_TRY
+ {
+ //
+ // Return data to user
+ //
+ *BaseAddress = PAGE_ALIGN(CapturedBaseAddress);
+ *NumberOfBytesToUnlock = 0;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //
+ // Get exception code
+ //
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+
+ //
+ // Return status
+ //
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+NtFlushVirtualMemory(IN HANDLE ProcessHandle,
+ IN OUT PVOID *BaseAddress,
+ IN OUT PSIZE_T NumberOfBytesToFlush,
+ OUT PIO_STATUS_BLOCK IoStatusBlock)
+{
+ PEPROCESS Process;
+ NTSTATUS Status;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ PVOID CapturedBaseAddress;
+ SIZE_T CapturedBytesToFlush;
+ IO_STATUS_BLOCK LocalStatusBlock;
+ PAGED_CODE();
+
+ //
+ // Check if we came from user mode
+ //
+ if (PreviousMode != KernelMode)
+ {
+ //
+ // Enter SEH for probing
+ //
+ _SEH2_TRY
+ {
+ //
+ // Validate all outputs
+ //
+ ProbeForWritePointer(BaseAddress);
+ ProbeForWriteSize_t(NumberOfBytesToFlush);
+ ProbeForWriteIoStatusBlock(IoStatusBlock);
+
+ //
+ // Capture them
+ //
+ CapturedBaseAddress = *BaseAddress;
+ CapturedBytesToFlush = *NumberOfBytesToFlush;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //
+ // Get exception code
+ //
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+ }
+ else
+ {
+ //
+ // Capture directly
+ //
+ CapturedBaseAddress = *BaseAddress;
+ CapturedBytesToFlush = *NumberOfBytesToFlush;
+ }
+
+ //
+ // Catch illegal base address
+ //
+ if (CapturedBaseAddress > MM_HIGHEST_USER_ADDRESS) return
STATUS_INVALID_PARAMETER;
+
+ //
+ // Catch illegal region size
+ //
+ if ((MmUserProbeAddress - (ULONG_PTR)CapturedBaseAddress) < CapturedBytesToFlush)
+ {
+ //
+ // Fail
+ //
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Get a reference to the process
+ //
+ Status = ObReferenceObjectByHandle(ProcessHandle,
+ PROCESS_VM_OPERATION,
+ PsProcessType,
+ PreviousMode,
+ (PVOID*)(&Process),
+ NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ //
+ // Do it
+ //
+ Status = MmFlushVirtualMemory(Process,
+ &CapturedBaseAddress,
+ &CapturedBytesToFlush,
+ &LocalStatusBlock);
+
+ //
+ // Release reference
+ //
+ ObDereferenceObject(Process);
+
+ //
+ // Enter SEH to return data
+ //
+ _SEH2_TRY
+ {
+ //
+ // Return data to user
+ //
+ *BaseAddress = PAGE_ALIGN(CapturedBaseAddress);
+ *NumberOfBytesToFlush = 0;
+ *IoStatusBlock = LocalStatusBlock;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ }
+ _SEH2_END;
+
+ //
+ // Return status
+ //
+ return Status;
+}
+
+/*
+ * @unimplemented
+ */
+NTSTATUS
+NTAPI
+NtGetWriteWatch(IN HANDLE ProcessHandle,
+ IN ULONG Flags,
+ IN PVOID BaseAddress,
+ IN SIZE_T RegionSize,
+ IN PVOID *UserAddressArray,
+ OUT PULONG_PTR EntriesInUserAddressArray,
+ OUT PULONG Granularity)
+{
+ PEPROCESS Process;
+ NTSTATUS Status;
+ PVOID EndAddress;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ ULONG_PTR CapturedEntryCount;
+ PAGED_CODE();
+
+ //
+ // Check if we came from user mode
+ //
+ if (PreviousMode != KernelMode)
+ {
+ //
+ // Enter SEH for probing
+ //
+ _SEH2_TRY
+ {
+ //
+ // Catch illegal base address
+ //
+ if (BaseAddress > MM_HIGHEST_USER_ADDRESS) return
STATUS_INVALID_PARAMETER_2;
+
+ //
+ // Catch illegal region size
+ //
+ if ((MmUserProbeAddress - (ULONG_PTR)BaseAddress) < RegionSize)
+ {
+ //
+ // Fail
+ //
+ return STATUS_INVALID_PARAMETER_3;
+ }
+
+ //
+ // Validate all data
+ //
+ ProbeForWriteSize_t(EntriesInUserAddressArray);
+ ProbeForWriteUlong(Granularity);
+
+ //
+ // Capture them
+ //
+ CapturedEntryCount = *EntriesInUserAddressArray;
+
+ //
+ // Must have a count
+ //
+ if (CapturedEntryCount == 0) return STATUS_INVALID_PARAMETER_5;
+
+ //
+ // Can't be larger than the maximum
+ //
+ if (CapturedEntryCount > (MAXULONG_PTR / sizeof(ULONG_PTR)))
+ {
+ //
+ // Fail
+ //
+ return STATUS_INVALID_PARAMETER_5;
+ }
+
+ //
+ // Probe the actual array
+ //
+ ProbeForWrite(UserAddressArray,
+ CapturedEntryCount * sizeof(PVOID),
+ sizeof(PVOID));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //
+ // Get exception code
+ //
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+ }
+ else
+ {
+ //
+ // Capture directly
+ //
+ CapturedEntryCount = *EntriesInUserAddressArray;
+ ASSERT(CapturedEntryCount != 0);
+ }
+
+ //
+ // Check if this is a local request
+ //
+ if (ProcessHandle == NtCurrentProcess())
+ {
+ //
+ // No need to reference the process
+ //
+ Process = PsGetCurrentProcess();
+ }
+ else
+ {
+ //
+ // Reference the target
+ //
+ Status = ObReferenceObjectByHandle(ProcessHandle,
+ PROCESS_VM_OPERATION,
+ PsProcessType,
+ PreviousMode,
+ (PVOID *)&Process,
+ NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ }
+
+ //
+ // Compute the last address and validate it
+ //
+ EndAddress = (PVOID)((ULONG_PTR)BaseAddress + RegionSize - 1);
+ if (BaseAddress > EndAddress)
+ {
+ //
+ // Fail
+ //
+ if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process);
+ return STATUS_INVALID_PARAMETER_4;
+ }
+
+ //
+ // Oops :(
+ //
+ UNIMPLEMENTED;
+
+ //
+ // Dereference if needed
+ //
+ if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process);
+
+ //
+ // Enter SEH to return data
+ //
+ _SEH2_TRY
+ {
+ //
+ // Return data to user
+ //
+ *EntriesInUserAddressArray = 0;
+ *Granularity = PAGE_SIZE;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //
+ // Get exception code
+ //
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ //
+ // Return success
+ //
+ return STATUS_SUCCESS;
+}
+
+/*
+ * @unimplemented
+ */
+NTSTATUS
+NTAPI
+NtResetWriteWatch(IN HANDLE ProcessHandle,
+ IN PVOID BaseAddress,
+ IN SIZE_T RegionSize)
+{
+ PVOID EndAddress;
+ PEPROCESS Process;
+ NTSTATUS Status;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
+
+ //
+ // Catch illegal base address
+ //
+ if (BaseAddress > MM_HIGHEST_USER_ADDRESS) return STATUS_INVALID_PARAMETER_2;
+
+ //
+ // Catch illegal region size
+ //
+ if ((MmUserProbeAddress - (ULONG_PTR)BaseAddress) < RegionSize)
+ {
+ //
+ // Fail
+ //
+ return STATUS_INVALID_PARAMETER_3;
+ }
+
+ //
+ // Check if this is a local request
+ //
+ if (ProcessHandle == NtCurrentProcess())
+ {
+ //
+ // No need to reference the process
+ //
+ Process = PsGetCurrentProcess();
+ }
+ else
+ {
+ //
+ // Reference the target
+ //
+ Status = ObReferenceObjectByHandle(ProcessHandle,
+ PROCESS_VM_OPERATION,
+ PsProcessType,
+ PreviousMode,
+ (PVOID *)&Process,
+ NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+ }
+
+ //
+ // Compute the last address and validate it
+ //
+ EndAddress = (PVOID)((ULONG_PTR)BaseAddress + RegionSize - 1);
+ if (BaseAddress > EndAddress)
+ {
+ //
+ // Fail
+ //
+ if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process);
+ return STATUS_INVALID_PARAMETER_3;
+ }
+
+ //
+ // Oops :(
+ //
+ UNIMPLEMENTED;
+
+ //
+ // Dereference if needed
+ //
+ if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process);
+
+ //
+ // Return success
+ //
+ return STATUS_SUCCESS;
+}
+
+/* EOF */
Propchange: trunk/reactos/ntoskrnl/mm/ARM3/virtual.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: trunk/reactos/ntoskrnl/mm/ARM3/virtual.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: trunk/reactos/ntoskrnl/mm/virtual.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/virtual.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/virtual.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/virtual.c [iso-8859-1] Thu Oct 15 18:50:49 2009
@@ -13,391 +13,7 @@
#define NDEBUG
#include <debug.h>
-#define MI_MAPPED_COPY_PAGES 16
-#define MI_POOL_COPY_BYTES 512
-#define MI_MAX_TRANSFER_SIZE 64 * 1024
-#define TAG_VM 'wRmV'
-
/* PRIVATE FUNCTIONS **********************************************************/
-
-LONG
-MiGetExceptionInfo(EXCEPTION_POINTERS *ExceptionInfo, BOOLEAN * HaveBadAddress, ULONG_PTR
* BadAddress)
-{
- PEXCEPTION_RECORD ExceptionRecord;
- PAGED_CODE();
-
- /* Assume default */
- *HaveBadAddress = FALSE;
-
- /* Get the exception record */
- ExceptionRecord = ExceptionInfo->ExceptionRecord;
-
- /* Look at the exception code */
- if ((ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION) ||
- (ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION) ||
- (ExceptionRecord->ExceptionCode == STATUS_IN_PAGE_ERROR))
- {
- /* We can tell the address if we have more than one parameter */
- if (ExceptionRecord->NumberParameters > 1)
- {
- /* Return the address */
- *HaveBadAddress = TRUE;
- *BadAddress = ExceptionRecord->ExceptionInformation[1];
- }
- }
-
- /* Continue executing the next handler */
- return EXCEPTION_EXECUTE_HANDLER;
-}
-
-NTSTATUS
-NTAPI
-MiDoMappedCopy(IN PEPROCESS SourceProcess,
- IN PVOID SourceAddress,
- IN PEPROCESS TargetProcess,
- OUT PVOID TargetAddress,
- IN SIZE_T BufferSize,
- IN KPROCESSOR_MODE PreviousMode,
- OUT PSIZE_T ReturnSize)
-{
- PFN_NUMBER MdlBuffer[(sizeof(MDL) / sizeof(PFN_NUMBER)) + MI_MAPPED_COPY_PAGES + 1];
- PMDL Mdl = (PMDL)MdlBuffer;
- SIZE_T TotalSize, CurrentSize, RemainingSize;
- volatile BOOLEAN FailedInProbe = FALSE, FailedInMapping = FALSE, FailedInMoving;
- volatile BOOLEAN PagesLocked;
- PVOID CurrentAddress = SourceAddress, CurrentTargetAddress = TargetAddress;
- volatile PVOID MdlAddress;
- KAPC_STATE ApcState;
- BOOLEAN HaveBadAddress;
- ULONG_PTR BadAddress;
- PAGED_CODE();
-
- /* Calculate the maximum amount of data to move */
- TotalSize = (MI_MAPPED_COPY_PAGES - 2) * PAGE_SIZE;
- if (BufferSize <= TotalSize) TotalSize = BufferSize;
- CurrentSize = TotalSize;
- RemainingSize = BufferSize;
-
- /* Loop as long as there is still data */
- while (RemainingSize > 0)
- {
- /* Check if this transfer will finish everything off */
- if (RemainingSize < CurrentSize) CurrentSize = RemainingSize;
-
- /* Attach to the source address space */
- KeStackAttachProcess(&SourceProcess->Pcb, &ApcState);
-
- /* Reset state for this pass */
- MdlAddress = NULL;
- PagesLocked = FALSE;
- FailedInMoving = FALSE;
- ASSERT(FailedInProbe == FALSE);
-
- /* Protect user-mode copy */
- _SEH2_TRY
- {
- /* If this is our first time, probe the buffer */
- if ((CurrentAddress == SourceAddress) && (PreviousMode !=
KernelMode))
- {
- /* Catch a failure here */
- FailedInProbe = TRUE;
-
- /* Do the probe */
- ProbeForRead(SourceAddress, BufferSize, sizeof(CHAR));
-
- /* Passed */
- FailedInProbe = FALSE;
- }
-
- /* Initialize and probe and lock the MDL */
- MmInitializeMdl (Mdl, CurrentAddress, CurrentSize);
- MmProbeAndLockPages (Mdl, PreviousMode, IoReadAccess);
- PagesLocked = TRUE;
-
- /* Now map the pages */
- MdlAddress = MmMapLockedPagesSpecifyCache(Mdl,
- KernelMode,
- MmCached,
- NULL,
- FALSE,
- HighPagePriority);
- if (!MdlAddress)
- {
- /* Use our SEH handler to pick this up */
- FailedInMapping = TRUE;
- ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
- }
-
- /* Now let go of the source and grab to the target process */
- KeUnstackDetachProcess(&ApcState);
- KeStackAttachProcess(&TargetProcess->Pcb, &ApcState);
-
- /* Check if this is our first time through */
- if ((CurrentAddress == SourceAddress) && (PreviousMode !=
KernelMode))
- {
- /* Catch a failure here */
- FailedInProbe = TRUE;
-
- /* Do the probe */
- ProbeForWrite(TargetAddress, BufferSize, sizeof(CHAR));
-
- /* Passed */
- FailedInProbe = FALSE;
- }
-
- /* Now do the actual move */
- FailedInMoving = TRUE;
- RtlCopyMemory(CurrentTargetAddress, MdlAddress, CurrentSize);
- }
- _SEH2_EXCEPT(MiGetExceptionInfo(_SEH2_GetExceptionInformation(),
&HaveBadAddress, &BadAddress))
- {
- /* Detach from whoever we may be attached to */
- KeUnstackDetachProcess(&ApcState);
-
- /* Check if we had mapped the pages */
- if (MdlAddress) MmUnmapLockedPages(MdlAddress, Mdl);
-
- /* Check if we had locked the pages */
- if (PagesLocked) MmUnlockPages(Mdl);
-
- /* Check if we failed during the probe or mapping */
- if ((FailedInProbe) || (FailedInMapping))
- {
- /* Exit */
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
- }
-
- /* Otherwise, we failed probably during the move */
- *ReturnSize = BufferSize - RemainingSize;
- if (FailedInMoving)
- {
- /* Check if we know exactly where we stopped copying */
- if (HaveBadAddress)
- {
- /* Return the exact number of bytes copied */
- *ReturnSize = BadAddress - (ULONG_PTR)SourceAddress;
- }
- }
-
- /* Return partial copy */
- _SEH2_YIELD(return STATUS_PARTIAL_COPY);
- }
- _SEH2_END;
-
- /* Detach from target */
- KeUnstackDetachProcess(&ApcState);
-
- /* Unmap and unlock */
- MmUnmapLockedPages(MdlAddress, Mdl);
- MmUnlockPages(Mdl);
-
- /* Update location and size */
- RemainingSize -= CurrentSize;
- CurrentAddress = (PVOID)((ULONG_PTR)CurrentAddress + CurrentSize);
- CurrentTargetAddress = (PVOID)((ULONG_PTR)CurrentTargetAddress + CurrentSize);
- }
-
- /* All bytes read */
- *ReturnSize = BufferSize;
- return STATUS_SUCCESS;
-}
-
-NTSTATUS
-NTAPI
-MiDoPoolCopy(IN PEPROCESS SourceProcess,
- IN PVOID SourceAddress,
- IN PEPROCESS TargetProcess,
- OUT PVOID TargetAddress,
- IN SIZE_T BufferSize,
- IN KPROCESSOR_MODE PreviousMode,
- OUT PSIZE_T ReturnSize)
-{
- UCHAR StackBuffer[MI_POOL_COPY_BYTES];
- SIZE_T TotalSize, CurrentSize, RemainingSize;
- volatile BOOLEAN FailedInProbe = FALSE, FailedInMoving, HavePoolAddress = FALSE;
- PVOID CurrentAddress = SourceAddress, CurrentTargetAddress = TargetAddress;
- PVOID PoolAddress;
- KAPC_STATE ApcState;
- BOOLEAN HaveBadAddress;
- ULONG_PTR BadAddress;
- PAGED_CODE();
-
- /* Calculate the maximum amount of data to move */
- TotalSize = MI_MAX_TRANSFER_SIZE;
- if (BufferSize <= MI_MAX_TRANSFER_SIZE) TotalSize = BufferSize;
- CurrentSize = TotalSize;
- RemainingSize = BufferSize;
-
- /* Check if we can use the stack */
- if (BufferSize <= MI_POOL_COPY_BYTES)
- {
- /* Use it */
- PoolAddress = (PVOID)StackBuffer;
- }
- else
- {
- /* Allocate pool */
- PoolAddress = ExAllocatePoolWithTag(NonPagedPool, TotalSize, TAG_VM);
- if (!PoolAddress) ASSERT(FALSE);
- HavePoolAddress = TRUE;
- }
-
- /* Loop as long as there is still data */
- while (RemainingSize > 0)
- {
- /* Check if this transfer will finish everything off */
- if (RemainingSize < CurrentSize) CurrentSize = RemainingSize;
-
- /* Attach to the source address space */
- KeStackAttachProcess(&SourceProcess->Pcb, &ApcState);
-
- /* Reset state for this pass */
- FailedInMoving = FALSE;
- ASSERT(FailedInProbe == FALSE);
-
- /* Protect user-mode copy */
- _SEH2_TRY
- {
- /* If this is our first time, probe the buffer */
- if ((CurrentAddress == SourceAddress) && (PreviousMode !=
KernelMode))
- {
- /* Catch a failure here */
- FailedInProbe = TRUE;
-
- /* Do the probe */
- ProbeForRead(SourceAddress, BufferSize, sizeof(CHAR));
-
- /* Passed */
- FailedInProbe = FALSE;
- }
-
- /* Do the copy */
- RtlCopyMemory(PoolAddress, CurrentAddress, CurrentSize);
-
- /* Now let go of the source and grab to the target process */
- KeUnstackDetachProcess(&ApcState);
- KeStackAttachProcess(&TargetProcess->Pcb, &ApcState);
-
- /* Check if this is our first time through */
- if ((CurrentAddress == SourceAddress) && (PreviousMode !=
KernelMode))
- {
- /* Catch a failure here */
- FailedInProbe = TRUE;
-
- /* Do the probe */
- ProbeForWrite(TargetAddress, BufferSize, sizeof(CHAR));
-
- /* Passed */
- FailedInProbe = FALSE;
- }
-
- /* Now do the actual move */
- FailedInMoving = TRUE;
- RtlCopyMemory(CurrentTargetAddress, PoolAddress, CurrentSize);
- }
- _SEH2_EXCEPT(MiGetExceptionInfo(_SEH2_GetExceptionInformation(),
&HaveBadAddress, &BadAddress))
- {
- /* Detach from whoever we may be attached to */
- KeUnstackDetachProcess(&ApcState);
-
- /* Check if we had allocated pool */
- if (HavePoolAddress) ExFreePool(PoolAddress);
-
- /* Check if we failed during the probe */
- if (FailedInProbe)
- {
- /* Exit */
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
- }
-
- /* Otherwise, we failed probably during the move */
- *ReturnSize = BufferSize - RemainingSize;
- if (FailedInMoving)
- {
- /* Check if we know exactly where we stopped copying */
- if (HaveBadAddress)
- {
- /* Return the exact number of bytes copied */
- *ReturnSize = BadAddress - (ULONG_PTR)SourceAddress;
- }
- }
-
- /* Return partial copy */
- _SEH2_YIELD(return STATUS_PARTIAL_COPY);
- }
- _SEH2_END;
-
- /* Detach from target */
- KeUnstackDetachProcess(&ApcState);
-
- /* Update location and size */
- RemainingSize -= CurrentSize;
- CurrentAddress = (PVOID)((ULONG_PTR)CurrentAddress + CurrentSize);
- CurrentTargetAddress = (PVOID)((ULONG_PTR)CurrentTargetAddress + CurrentSize);
- }
-
- /* Check if we had allocated pool */
- if (HavePoolAddress) ExFreePool(PoolAddress);
-
- /* All bytes read */
- *ReturnSize = BufferSize;
- return STATUS_SUCCESS;
-}
-
-NTSTATUS
-NTAPI
-MmCopyVirtualMemory(IN PEPROCESS SourceProcess,
- IN PVOID SourceAddress,
- IN PEPROCESS TargetProcess,
- OUT PVOID TargetAddress,
- IN SIZE_T BufferSize,
- IN KPROCESSOR_MODE PreviousMode,
- OUT PSIZE_T ReturnSize)
-{
- NTSTATUS Status;
- PEPROCESS Process = SourceProcess;
-
- /* Don't accept zero-sized buffers */
- if (!BufferSize) return STATUS_SUCCESS;
-
- /* If we are copying from ourselves, lock the target instead */
- if (SourceProcess == PsGetCurrentProcess()) Process = TargetProcess;
-
- /* Acquire rundown protection */
- if (!ExAcquireRundownProtection(&Process->RundownProtect))
- {
- /* Fail */
- return STATUS_PROCESS_IS_TERMINATING;
- }
-
- /* See if we should use the pool copy */
- if (BufferSize > MI_POOL_COPY_BYTES)
- {
- /* Use MDL-copy */
- Status = MiDoMappedCopy(SourceProcess,
- SourceAddress,
- TargetProcess,
- TargetAddress,
- BufferSize,
- PreviousMode,
- ReturnSize);
- }
- else
- {
- /* Do pool copy */
- Status = MiDoPoolCopy(SourceProcess,
- SourceAddress,
- TargetProcess,
- TargetAddress,
- BufferSize,
- PreviousMode,
- ReturnSize);
- }
-
- /* Release the lock */
- ExReleaseRundownProtection(&Process->RundownProtect);
- return Status;
-}
NTSTATUS FASTCALL
MiQueryVirtualMemory(IN HANDLE ProcessHandle,
@@ -721,322 +337,7 @@
NULL);
}
-/* PUBLIC FUNCTIONS ***********************************************************/
-
-/*
- * @unimplemented
- */
-PVOID
-NTAPI
-MmGetVirtualForPhysical(IN PHYSICAL_ADDRESS PhysicalAddress)
-{
- UNIMPLEMENTED;
- return 0;
-}
-
-/*
- * @unimplemented
- */
-PVOID
-NTAPI
-MmSecureVirtualMemory(IN PVOID Address,
- IN SIZE_T Length,
- IN ULONG Mode)
-{
- UNIMPLEMENTED;
- return NULL;
-}
-
-/*
- * @unimplemented
- */
-VOID
-NTAPI
-MmUnsecureVirtualMemory(IN PVOID SecureMem)
-{
- UNIMPLEMENTED;
-}
-
/* SYSTEM CALLS ***************************************************************/
-
-NTSTATUS
-NTAPI
-NtReadVirtualMemory(IN HANDLE ProcessHandle,
- IN PVOID BaseAddress,
- OUT PVOID Buffer,
- IN SIZE_T NumberOfBytesToRead,
- OUT PSIZE_T NumberOfBytesRead OPTIONAL)
-{
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- PEPROCESS Process;
- NTSTATUS Status;
- SIZE_T BytesRead = 0;
- PAGED_CODE();
-
- /* Check if we came from user mode */
- if (PreviousMode != KernelMode)
- {
- /* Validate the read addresses */
- if ((((ULONG_PTR)BaseAddress + NumberOfBytesToRead) < (ULONG_PTR)BaseAddress)
||
- (((ULONG_PTR)Buffer + NumberOfBytesToRead) < (ULONG_PTR)Buffer) ||
- (((ULONG_PTR)BaseAddress + NumberOfBytesToRead) > MmUserProbeAddress) ||
- (((ULONG_PTR)Buffer + NumberOfBytesToRead) > MmUserProbeAddress))
- {
- /* Don't allow to write into kernel space */
- return STATUS_ACCESS_VIOLATION;
- }
-
- /* Enter SEH for probe */
- _SEH2_TRY
- {
- /* Probe the output value */
- if (NumberOfBytesRead) ProbeForWriteSize_t(NumberOfBytesRead);
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- /* Return the exception code */
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
- }
- _SEH2_END;
- }
-
- /* Reference the process */
- Status = ObReferenceObjectByHandle(ProcessHandle,
- PROCESS_VM_READ,
- PsProcessType,
- PreviousMode,
- (PVOID*)(&Process),
- NULL);
- if (NT_SUCCESS(Status))
- {
- /* Do the copy */
- Status = MmCopyVirtualMemory(Process,
- BaseAddress,
- PsGetCurrentProcess(),
- Buffer,
- NumberOfBytesToRead,
- PreviousMode,
- &BytesRead);
-
- /* Dereference the process */
- ObDereferenceObject(Process);
- }
-
- /* Check if the caller sent this parameter */
- if (NumberOfBytesRead)
- {
- /* Enter SEH to guard write */
- _SEH2_TRY
- {
- /* Return the number of bytes read */
- *NumberOfBytesRead = BytesRead;
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- /* Handle exception */
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END;
- }
-
- /* Return status */
- return Status;
-}
-
-NTSTATUS
-NTAPI
-NtWriteVirtualMemory(IN HANDLE ProcessHandle,
- IN PVOID BaseAddress,
- IN PVOID Buffer,
- IN SIZE_T NumberOfBytesToWrite,
- OUT PSIZE_T NumberOfBytesWritten OPTIONAL)
-{
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- PEPROCESS Process;
- NTSTATUS Status;
- ULONG BytesWritten = 0;
- PAGED_CODE();
-
- /* Check if we came from user mode */
- if (PreviousMode != KernelMode)
- {
- /* Validate the read addresses */
- if ((((ULONG_PTR)BaseAddress + NumberOfBytesToWrite) < (ULONG_PTR)BaseAddress)
||
- (((ULONG_PTR)Buffer + NumberOfBytesToWrite) < (ULONG_PTR)Buffer) ||
- (((ULONG_PTR)BaseAddress + NumberOfBytesToWrite) > MmUserProbeAddress) ||
- (((ULONG_PTR)Buffer + NumberOfBytesToWrite) > MmUserProbeAddress))
- {
- /* Don't allow to write into kernel space */
- return STATUS_ACCESS_VIOLATION;
- }
-
- /* Enter SEH for probe */
- _SEH2_TRY
- {
- /* Probe the output value */
- if (NumberOfBytesWritten) ProbeForWriteSize_t(NumberOfBytesWritten);
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- /* Return the exception code */
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
- }
- _SEH2_END;
- }
-
- /* Reference the process */
- Status = ObReferenceObjectByHandle(ProcessHandle,
- PROCESS_VM_WRITE,
- PsProcessType,
- PreviousMode,
- (PVOID*)&Process,
- NULL);
- if (NT_SUCCESS(Status))
- {
- /* Do the copy */
- Status = MmCopyVirtualMemory(PsGetCurrentProcess(),
- Buffer,
- Process,
- BaseAddress,
- NumberOfBytesToWrite,
- PreviousMode,
- &BytesWritten);
-
- /* Dereference the process */
- ObDereferenceObject(Process);
- }
-
- /* Check if the caller sent this parameter */
- if (NumberOfBytesWritten)
- {
- /* Enter SEH to guard write */
- _SEH2_TRY
- {
- /* Return the number of bytes read */
- *NumberOfBytesWritten = BytesWritten;
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- /* Handle exception */
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END;
- }
-
- /* Return status */
- return Status;
-}
-
-NTSTATUS
-NTAPI
-NtProtectVirtualMemory(IN HANDLE ProcessHandle,
- IN OUT PVOID *UnsafeBaseAddress,
- IN OUT SIZE_T *UnsafeNumberOfBytesToProtect,
- IN ULONG NewAccessProtection,
- OUT PULONG UnsafeOldAccessProtection)
-{
- PEPROCESS Process;
- ULONG OldAccessProtection;
- ULONG Protection;
- PVOID BaseAddress = NULL;
- SIZE_T NumberOfBytesToProtect = 0;
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- NTSTATUS Status;
- PAGED_CODE();
-
- /* Check for valid protection flags */
- Protection = NewAccessProtection & ~(PAGE_GUARD|PAGE_NOCACHE);
- if (Protection != PAGE_NOACCESS &&
- Protection != PAGE_READONLY &&
- Protection != PAGE_READWRITE &&
- Protection != PAGE_WRITECOPY &&
- Protection != PAGE_EXECUTE &&
- Protection != PAGE_EXECUTE_READ &&
- Protection != PAGE_EXECUTE_READWRITE &&
- Protection != PAGE_EXECUTE_WRITECOPY)
- {
- return STATUS_INVALID_PAGE_PROTECTION;
- }
-
- /* Check if we came from user mode */
- if (PreviousMode != KernelMode)
- {
- /* Enter SEH for probing */
- _SEH2_TRY
- {
- /* Validate all outputs */
- ProbeForWritePointer(UnsafeBaseAddress);
- ProbeForWriteSize_t(UnsafeNumberOfBytesToProtect);
- ProbeForWriteUlong(UnsafeOldAccessProtection);
-
- /* Capture them */
- BaseAddress = *UnsafeBaseAddress;
- NumberOfBytesToProtect = *UnsafeNumberOfBytesToProtect;
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- /* Return the exception code */
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
- }
- _SEH2_END;
- }
- else
- {
- /* Capture directly */
- BaseAddress = *UnsafeBaseAddress;
- NumberOfBytesToProtect = *UnsafeNumberOfBytesToProtect;
- }
-
- /* Catch illegal base address */
- if (BaseAddress > (PVOID)MmUserProbeAddress) return STATUS_INVALID_PARAMETER_2;
-
- /* Catch illegal region size */
- if ((MmUserProbeAddress - (ULONG_PTR)BaseAddress) < NumberOfBytesToProtect)
- {
- /* Fail */
- return STATUS_INVALID_PARAMETER_3;
- }
-
- /* 0 is also illegal */
- if (!NumberOfBytesToProtect) return STATUS_INVALID_PARAMETER_3;
-
- /* Get a reference to the process */
- Status = ObReferenceObjectByHandle(ProcessHandle,
- PROCESS_VM_OPERATION,
- PsProcessType,
- PreviousMode,
- (PVOID*)(&Process),
- NULL);
- if (!NT_SUCCESS(Status)) return Status;
-
- /* Do the actual work */
- Status = MiProtectVirtualMemory(Process,
- &BaseAddress,
- &NumberOfBytesToProtect,
- NewAccessProtection,
- &OldAccessProtection);
-
- /* Release reference */
- ObDereferenceObject(Process);
-
- /* Enter SEH to return data */
- _SEH2_TRY
- {
- /* Return data to user */
- *UnsafeOldAccessProtection = OldAccessProtection;
- *UnsafeBaseAddress = BaseAddress;
- *UnsafeNumberOfBytesToProtect = NumberOfBytesToProtect;
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- /* Catch exception */
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END;
-
- /* Return status */
- return Status;
-}
NTSTATUS NTAPI
NtQueryVirtualMemory(IN HANDLE ProcessHandle,
@@ -1202,92 +503,4 @@
return(Status);
}
-NTSTATUS
-NTAPI
-NtLockVirtualMemory(IN HANDLE ProcessHandle,
- IN PVOID BaseAddress,
- IN SIZE_T NumberOfBytesToLock,
- OUT PSIZE_T NumberOfBytesLocked OPTIONAL)
-{
- UNIMPLEMENTED;
- if (NumberOfBytesLocked) *NumberOfBytesLocked = 0;
- return STATUS_SUCCESS;
-}
-
-NTSTATUS
-NTAPI
-NtUnlockVirtualMemory(IN HANDLE ProcessHandle,
- IN PVOID BaseAddress,
- IN SIZE_T NumberOfBytesToUnlock,
- OUT PSIZE_T NumberOfBytesUnlocked OPTIONAL)
-{
- UNIMPLEMENTED;
- if (NumberOfBytesUnlocked) *NumberOfBytesUnlocked = 0;
- return STATUS_SUCCESS;
-}
-
-NTSTATUS
-NTAPI
-NtFlushVirtualMemory(IN HANDLE ProcessHandle,
- IN OUT PVOID *BaseAddress,
- IN OUT PSIZE_T NumberOfBytesToFlush,
- OUT PIO_STATUS_BLOCK IoStatusBlock)
-{
- UNIMPLEMENTED;
- return STATUS_SUCCESS;
-}
-
-/*
- * @unimplemented
- */
-NTSTATUS
-NTAPI
-NtGetWriteWatch(IN HANDLE ProcessHandle,
- IN ULONG Flags,
- IN PVOID BaseAddress,
- IN ULONG RegionSize,
- IN PVOID *UserAddressArray,
- OUT PULONG EntriesInUserAddressArray,
- OUT PULONG Granularity)
-{
- if (!EntriesInUserAddressArray || !Granularity)
- {
- return STATUS_ACCESS_VIOLATION;
- }
-
- if (!*EntriesInUserAddressArray || !RegionSize)
- {
- return STATUS_INVALID_PARAMETER;
- }
-
- if (!UserAddressArray)
- {
- return STATUS_ACCESS_VIOLATION;
- }
-
- /* HACK: Set granularity to PAGE_SIZE */
- *Granularity = PAGE_SIZE;
-
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
-
-/*
- * @unimplemented
- */
-NTSTATUS
-NTAPI
-NtResetWriteWatch(IN HANDLE ProcessHandle,
- IN PVOID BaseAddress,
- IN ULONG RegionSize)
-{
- if (!RegionSize)
- {
- return STATUS_INVALID_PARAMETER;
- }
-
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
-
/* EOF */
Modified: trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ntoskrnl-generic.…
==============================================================================
--- trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild [iso-8859-1] Thu Oct 15 18:50:49 2009
@@ -394,6 +394,7 @@
<file>pool.c</file>
<file>procsup.c</file>
<file>syspte.c</file>
+ <file>virtual.c</file>
</directory>
<file>anonmem.c</file>
<file>balance.c</file>