[NTOS]: Stop handling a bunch of MEMORY_AREA_TYPEs that aren't used anymore.
[reactos.git] / reactos / ntoskrnl / mm / virtual.c
index 6d9d0fe..0016133 100644 (file)
 #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 TAG('V', 'm', 'R', 'w')
-
 /* PRIVATE FUNCTIONS **********************************************************/
 
-_SEH_DEFINE_LOCALS(MiGetExceptionInfo)
-{
-    volatile BOOLEAN HaveBadAddress;
-    volatile ULONG_PTR BadAddress;
-};
-
-_SEH_FILTER(MiGetExceptionInfo)
-{
-    _SEH_ACCESS_LOCALS(MiGetExceptionInfo);
-    EXCEPTION_POINTERS *ExceptionInfo = _SEH_GetExceptionPointers();
-    PEXCEPTION_RECORD ExceptionRecord;
-    PAGED_CODE();
-    
-    /* Assume default */
-    _SEH_VAR(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 */
-            _SEH_VAR(HaveBadAddress) = TRUE;
-            _SEH_VAR(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 ULONG BufferSize,
-               IN KPROCESSOR_MODE PreviousMode,
-               OUT PULONG ReturnSize)
-{
-    PFN_NUMBER MdlBuffer[(sizeof(MDL) / sizeof(PFN_NUMBER)) + (MI_MAPPED_COPY_PAGES >> PAGE_SHIFT) + 1];
-    PMDL Mdl = (PMDL)MdlBuffer;
-    ULONG TotalSize, CurrentSize, RemainingSize;
-    BOOLEAN FailedInProbe = FALSE, FailedInMapping = FALSE, FailedInMoving;
-    BOOLEAN PagesLocked;
-    PVOID CurrentAddress = SourceAddress, CurrentTargetAddress = TargetAddress;
-    PVOID MdlAddress;
-    KAPC_STATE ApcState;
-    _SEH_DECLARE_LOCALS(MiGetExceptionInfo);
-    NTSTATUS Status = STATUS_SUCCESS;
-    PAGED_CODE();
-
-    /* Calculate the maximum amount of data to move */
-    TotalSize = (MI_MAPPED_COPY_PAGES - 2) * PAGE_SIZE;
-    if (BufferSize <= TotalSize) TotalSize = BufferSize;
-    CurrentSize = BufferSize;
-    RemainingSize = TotalSize;
-
-    /* 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 */
-        _SEH_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);
-        }
-        _SEH_EXCEPT(MiGetExceptionInfo)
-        {
-            /* 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 */
-                Status = _SEH_GetExceptionCode();
-                _SEH_YIELD();
-            }
-
-            /* Otherwise, we failed  probably during the move */
-            *ReturnSize = BufferSize - RemainingSize;
-            if (FailedInMoving)
-            {
-                /* Check if we know exactly where we stopped copying */
-                if (_SEH_VAR(HaveBadAddress))
-                {
-                    /* Return the exact number of bytes copied */
-                    *ReturnSize = _SEH_VAR(BadAddress) - (ULONG_PTR)SourceAddress;
-                }
-            }
-
-            /* Return partial copy */
-            Status = STATUS_PARTIAL_COPY;
-        }
-        _SEH_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 ULONG BufferSize,
-             IN KPROCESSOR_MODE PreviousMode,
-             OUT PULONG ReturnSize)
-{
-    UCHAR StackBuffer[MI_POOL_COPY_BYTES];
-    ULONG TotalSize, CurrentSize, RemainingSize;
-    BOOLEAN FailedInProbe = FALSE, FailedInMoving, HavePoolAddress = FALSE;
-    PVOID CurrentAddress = SourceAddress, CurrentTargetAddress = TargetAddress;
-    PVOID PoolAddress;
-    KAPC_STATE ApcState;
-    _SEH_DECLARE_LOCALS(MiGetExceptionInfo);
-    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 = BufferSize;
-    RemainingSize = TotalSize;
-
-    /* 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 */
-        _SEH_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);
-        }
-        _SEH_EXCEPT(MiGetExceptionInfo)
-        {
-            /* 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 = _SEH_GetExceptionCode();
-                _SEH_YIELD();
-            }
-
-            /* Otherwise, we failed  probably during the move */
-            *ReturnSize = BufferSize - RemainingSize;
-            if (FailedInMoving)
-            {
-                /* Check if we know exactly where we stopped copying */
-                if (_SEH_VAR(HaveBadAddress))
-                {
-                    /* Return the exact number of bytes copied */
-                    *ReturnSize = _SEH_VAR(BadAddress) - (ULONG_PTR)SourceAddress;
-                }
-            }
-
-            /* Return partial copy */
-            Status = STATUS_PARTIAL_COPY;
-        }
-        _SEH_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 ULONG BufferSize,
-                    IN KPROCESSOR_MODE PreviousMode,
-                    OUT PULONG 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,
                      IN PVOID Address,
                      IN MEMORY_INFORMATION_CLASS VirtualMemoryInformationClass,
                      OUT PVOID VirtualMemoryInformation,
-                     IN ULONG Length,
-                     OUT PULONG ResultLength)
+                     IN SIZE_T Length,
+                     OUT PSIZE_T ResultLength)
 {
     NTSTATUS Status;
     PEPROCESS Process;
     MEMORY_AREA* MemoryArea;
-    PMADDRESS_SPACE AddressSpace;
+    PMMSUPPORT AddressSpace;
 
-    if (Address < MmSystemRangeStart)
-    {
-        Status = ObReferenceObjectByHandle(ProcessHandle,
-                                           PROCESS_QUERY_INFORMATION,
-                                           NULL,
-                                           UserMode,
-                                           (PVOID*)(&Process),
-                                           NULL);
+    Status = ObReferenceObjectByHandle(ProcessHandle,
+                                       PROCESS_QUERY_INFORMATION,
+                                       NULL,
+                                       UserMode,
+                                       (PVOID*)(&Process),
+                                       NULL);
 
-        if (!NT_SUCCESS(Status))
-        {
-            DPRINT("NtQueryVirtualMemory() = %x\n",Status);
-            return(Status);
-        }
-        AddressSpace = (PMADDRESS_SPACE)&Process->VadRoot;
-    }
-    else
+    if (!NT_SUCCESS(Status))
     {
-        AddressSpace = MmGetKernelAddressSpace();
+        DPRINT("NtQueryVirtualMemory() = %x\n",Status);
+        return(Status);
     }
+
+    AddressSpace = &Process->Vm;
+
     MmLockAddressSpace(AddressSpace);
     MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address);
     switch(VirtualMemoryInformationClass)
@@ -479,7 +75,6 @@ MiQueryVirtualMemory(IN HANDLE ProcessHandle,
                 switch(MemoryArea->Type)
                 {
                     case MEMORY_AREA_VIRTUAL_MEMORY:
-                    case MEMORY_AREA_PEB_OR_TEB:
                         Status = MmQueryAnonMem(MemoryArea, Address, Info,
                                                 ResultLength);
                         break;
@@ -489,71 +84,6 @@ MiQueryVirtualMemory(IN HANDLE ProcessHandle,
                                                     ResultLength);
                         break;
 
-                    case MEMORY_AREA_NO_ACCESS:
-                        Info->Type = MEM_PRIVATE;
-                        Info->State = MEM_RESERVE;
-                        Info->Protect = MemoryArea->Protect;
-                        Info->AllocationProtect = MemoryArea->Protect;
-                        Info->BaseAddress = MemoryArea->StartingAddress;
-                        Info->AllocationBase = MemoryArea->StartingAddress;
-                        Info->RegionSize = (ULONG_PTR)MemoryArea->EndingAddress -
-                                           (ULONG_PTR)MemoryArea->StartingAddress;
-                        Status = STATUS_SUCCESS;
-                        *ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
-                        break;
-
-                    case MEMORY_AREA_SHARED_DATA:
-                        Info->Type = MEM_PRIVATE;
-                        Info->State = MEM_COMMIT;
-                        Info->Protect = MemoryArea->Protect;
-                        Info->AllocationProtect = MemoryArea->Protect;
-                        Info->BaseAddress = MemoryArea->StartingAddress;
-                        Info->AllocationBase = MemoryArea->StartingAddress;
-                        Info->RegionSize = (ULONG_PTR)MemoryArea->EndingAddress -
-                                           (ULONG_PTR)MemoryArea->StartingAddress;
-                        Status = STATUS_SUCCESS;
-                        *ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
-                        break;
-
-                    case MEMORY_AREA_SYSTEM:
-                        Info->Type = 0;
-                        Info->State = MEM_COMMIT;
-                        Info->Protect = MemoryArea->Protect;
-                        Info->AllocationProtect = MemoryArea->Protect;
-                        Info->BaseAddress = MemoryArea->StartingAddress;
-                        Info->AllocationBase = MemoryArea->StartingAddress;
-                        Info->RegionSize = (ULONG_PTR)MemoryArea->EndingAddress -
-                                           (ULONG_PTR)MemoryArea->StartingAddress;
-                        Status = STATUS_SUCCESS;
-                        *ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
-                        break;
-
-                    case MEMORY_AREA_KERNEL_STACK:
-                        Info->Type = 0;
-                        Info->State = MEM_COMMIT;
-                        Info->Protect = MemoryArea->Protect;
-                        Info->AllocationProtect = MemoryArea->Protect;
-                        Info->BaseAddress = MemoryArea->StartingAddress;
-                        Info->AllocationBase = MemoryArea->StartingAddress;
-                        Info->RegionSize = (ULONG_PTR)MemoryArea->EndingAddress -
-                                           (ULONG_PTR)MemoryArea->StartingAddress;
-                        Status = STATUS_SUCCESS;
-                        *ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
-                        break;
-
-                    case MEMORY_AREA_PAGED_POOL:
-                        Info->Type = 0;
-                        Info->State = MEM_COMMIT;
-                        Info->Protect = MemoryArea->Protect;
-                        Info->AllocationProtect = MemoryArea->Protect;
-                        Info->BaseAddress = MemoryArea->StartingAddress;
-                        Info->AllocationBase = MemoryArea->StartingAddress;
-                        Info->RegionSize = (ULONG_PTR)MemoryArea->EndingAddress -
-                                           (ULONG_PTR)MemoryArea->StartingAddress;
-                        Status = STATUS_SUCCESS;
-                        *ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
-                        break;
-
                     default:
                         DPRINT1("unhandled memory area type: 0x%x\n", MemoryArea->Type);
                         Status = STATUS_UNSUCCESSFUL;
@@ -565,6 +95,7 @@ MiQueryVirtualMemory(IN HANDLE ProcessHandle,
 
         default:
         {
+            DPRINT1("Unsupported or unimplemented class: %lx\n", VirtualMemoryInformationClass);
             Status = STATUS_INVALID_INFO_CLASS;
             *ResultLength = 0;
             break;
@@ -572,34 +103,30 @@ MiQueryVirtualMemory(IN HANDLE ProcessHandle,
     }
 
     MmUnlockAddressSpace(AddressSpace);
-    if (Address < MmSystemRangeStart)
-    {
-        ASSERT(Process);
-        ObDereferenceObject(Process);
-    }
+    ObDereferenceObject(Process);
 
     return Status;
 }
 
-NTSTATUS STDCALL
+NTSTATUS NTAPI
 MiProtectVirtualMemory(IN PEPROCESS Process,
                        IN OUT PVOID *BaseAddress,
-                       IN OUT PULONG NumberOfBytesToProtect,
+                       IN OUT PSIZE_T NumberOfBytesToProtect,
                        IN ULONG NewAccessProtection,
                        OUT PULONG OldAccessProtection  OPTIONAL)
 {
     PMEMORY_AREA MemoryArea;
-    PMADDRESS_SPACE AddressSpace;
+    PMMSUPPORT AddressSpace;
     ULONG OldAccessProtection_;
     NTSTATUS Status;
-    
+
     *NumberOfBytesToProtect =
     PAGE_ROUND_UP((ULONG_PTR)(*BaseAddress) + (*NumberOfBytesToProtect)) -
     PAGE_ROUND_DOWN(*BaseAddress);
     *BaseAddress = (PVOID)PAGE_ROUND_DOWN(*BaseAddress);
-    
-    AddressSpace = (PMADDRESS_SPACE)&(Process)->VadRoot;
-    
+
+    AddressSpace = &Process->Vm;
+
     MmLockAddressSpace(AddressSpace);
     MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, *BaseAddress);
     if (MemoryArea == NULL)
@@ -607,10 +134,10 @@ MiProtectVirtualMemory(IN PEPROCESS Process,
         MmUnlockAddressSpace(AddressSpace);
         return STATUS_UNSUCCESSFUL;
     }
-    
+
     if (OldAccessProtection == NULL)
         OldAccessProtection = &OldAccessProtection_;
-    
+
     if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY)
     {
         Status = MmProtectAnonMem(AddressSpace, MemoryArea, *BaseAddress,
@@ -629,383 +156,247 @@ MiProtectVirtualMemory(IN PEPROCESS Process,
         /* FIXME: Should we return failure or success in this case? */
         Status = STATUS_CONFLICTING_ADDRESSES;
     }
-    
-    MmUnlockAddressSpace(AddressSpace);
-    
-    return Status;
-}
 
-/* PUBLIC FUNCTIONS ***********************************************************/
+    MmUnlockAddressSpace(AddressSpace);
 
-/*
- * @unimplemented
- */
-PVOID
-NTAPI
-MmGetVirtualForPhysical(IN PHYSICAL_ADDRESS PhysicalAddress)
-{
-    UNIMPLEMENTED;
-    return 0;
+    return Status;
 }
 
-/*
- * @unimplemented
- */
 PVOID
 NTAPI
-MmSecureVirtualMemory(IN PVOID Address,
-                      IN SIZE_T Length,
-                      IN ULONG Mode)
-{
-    UNIMPLEMENTED;
-    return NULL;
-}
-
-/*
- * @unimplemented
- */
-VOID
-NTAPI
-MmUnsecureVirtualMemory(IN PVOID SecureMem)
+MiMapLockedPagesInUserSpace(IN PMDL Mdl,
+                            IN PVOID BaseVa,
+                            IN MEMORY_CACHING_TYPE CacheType,
+                            IN PVOID BaseAddress)
 {
-    UNIMPLEMENTED;
-}
-
-/* SYSTEM CALLS ***************************************************************/
-
-NTSTATUS
-NTAPI
-NtReadVirtualMemory(IN HANDLE ProcessHandle,
-                    IN PVOID BaseAddress,
-                    OUT PVOID Buffer,
-                    IN ULONG NumberOfBytesToRead,
-                    OUT PULONG NumberOfBytesRead OPTIONAL)
-{
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    PEPROCESS Process;
-    NTSTATUS Status = STATUS_SUCCESS;
-    ULONG BytesRead = 0;
-    PAGED_CODE();    
-
-    /* Check if we came from user mode */
-    if (PreviousMode != KernelMode)
+    PVOID Base;
+    PPFN_NUMBER MdlPages;
+    ULONG PageCount;   
+    PEPROCESS CurrentProcess;
+    NTSTATUS Status;
+    ULONG Protect;
+    MEMORY_AREA *Result;
+    LARGE_INTEGER BoundaryAddressMultiple;
+    
+    /* Calculate the number of pages required. */
+    MdlPages = (PPFN_NUMBER)(Mdl + 1);
+    PageCount = PAGE_ROUND_UP(Mdl->ByteCount + Mdl->ByteOffset) / PAGE_SIZE;
+    
+    /* Set default page protection */
+    Protect = PAGE_READWRITE;
+    if (CacheType == MmNonCached) Protect |= PAGE_NOCACHE;
+    
+    BoundaryAddressMultiple.QuadPart = 0;
+    Base = BaseAddress;
+    
+    CurrentProcess = PsGetCurrentProcess();
+    
+    MmLockAddressSpace(&CurrentProcess->Vm);
+    Status = MmCreateMemoryArea(&CurrentProcess->Vm,
+                                MEMORY_AREA_MDL_MAPPING,
+                                &Base,
+                                PageCount * PAGE_SIZE,
+                                Protect,
+                                &Result,
+                                (Base != NULL),
+                                0,
+                                BoundaryAddressMultiple);
+    MmUnlockAddressSpace(&CurrentProcess->Vm);
+    if (!NT_SUCCESS(Status))
     {
-        /* 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 */
-        _SEH_TRY
+        if (Mdl->MdlFlags & MDL_MAPPING_CAN_FAIL)
         {
-            /* Probe the output value */
-            if (NumberOfBytesRead) ProbeForWriteUlong(NumberOfBytesRead);
+            return NULL;
         }
-        _SEH_HANDLE
-        {
-            /* Get exception code */
-            Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
-        
-        /* Return if we failed */
-        if (!NT_SUCCESS(Status)) return Status;
-    }
-    
-    /* 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);
         
-        /* Derefernece the process */
-        ObDereferenceObject(Process);
+        /* Throw exception */
+        ExRaiseStatus(STATUS_ACCESS_VIOLATION);
+        ASSERT(0);
     }
     
-    /* Check if the caller sent this parameter */
-    if (NumberOfBytesRead)
+    /* Set the virtual mappings for the MDL pages. */
+    if (Mdl->MdlFlags & MDL_IO_SPACE)
     {
-        /* Enter SEH to guard write */
-        _SEH_TRY
-        {
-            /* Return the number of bytes read */
-            *NumberOfBytesRead = BytesRead;
-        }
-        _SEH_HANDLE
-        {
-            /* Handle exception */
-            Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
+        /* Map the pages */
+        Status = MmCreateVirtualMappingUnsafe(CurrentProcess,
+                                              Base,
+                                              Protect,
+                                              MdlPages,
+                                              PageCount);
     }
-
-    /* Return status */
-    return Status;
-}
-
-NTSTATUS
-NTAPI
-NtWriteVirtualMemory(IN HANDLE ProcessHandle,
-                     IN PVOID BaseAddress,
-                     IN PVOID Buffer,
-                     IN ULONG NumberOfBytesToWrite,
-                     OUT PULONG 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)
+    else
     {
-        /* 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 */
-        _SEH_TRY
-        {
-            /* Probe the output value */
-            if (NumberOfBytesWritten) ProbeForWriteUlong(NumberOfBytesWritten);
-        }
-        _SEH_HANDLE
-        {
-            /* Get exception code */
-            Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
-        
-        /* Return if we failed */
-        if (!NT_SUCCESS(Status)) return Status;
+        /* Map the pages */
+        Status = MmCreateVirtualMapping(CurrentProcess,
+                                        Base,
+                                        Protect,
+                                        MdlPages,
+                                        PageCount);
     }
     
-    /* Reference the process */
-    Status = ObReferenceObjectByHandle(ProcessHandle,
-                                       PROCESS_VM_WRITE,
-                                       PsProcessType,
-                                       PreviousMode,
-                                       (PVOID*)&Process,
-                                       NULL);
-    if (NT_SUCCESS(Status))
+    /* Check if the mapping suceeded */
+    if (!NT_SUCCESS(Status))
     {
-        /* Do the copy */
-        Status = MmCopyVirtualMemory(PsGetCurrentProcess(),
-                                     Buffer,
-                                     Process,
-                                     BaseAddress,
-                                     NumberOfBytesToWrite,
-                                     PreviousMode,
-                                     &BytesWritten);
+        /* If it can fail, return NULL */
+        if (Mdl->MdlFlags & MDL_MAPPING_CAN_FAIL) return NULL;
         
-        /* Derefernece the process */
-        ObDereferenceObject(Process);
-    }
-    
-    /* Check if the caller sent this parameter */
-    if (NumberOfBytesWritten)
-    {
-        /* Enter SEH to guard write */
-        _SEH_TRY
-        {
-            /* Return the number of bytes read */
-            *NumberOfBytesWritten = BytesWritten;
-        }
-        _SEH_HANDLE
-        {
-            /* Handle exception */
-            Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
+        /* Throw exception */
+        ExRaiseStatus(STATUS_ACCESS_VIOLATION);
     }
     
-    /* Return status */
-    return Status;
+    /* Return the base */
+    Base = (PVOID)((ULONG_PTR)Base + Mdl->ByteOffset);
+    return Base;
 }
 
-NTSTATUS
+VOID
 NTAPI
-NtProtectVirtualMemory(IN HANDLE ProcessHandle,
-                       IN OUT PVOID *UnsafeBaseAddress,
-                       IN OUT ULONG *UnsafeNumberOfBytesToProtect,
-                       IN ULONG NewAccessProtection,
-                       OUT PULONG UnsafeOldAccessProtection)
+MiUnmapLockedPagesInUserSpace(IN PVOID BaseAddress,
+                              IN PMDL Mdl)
 {
-    PEPROCESS Process;
-    ULONG OldAccessProtection;
-    PVOID BaseAddress = NULL;
-    ULONG NumberOfBytesToProtect = 0;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    NTSTATUS Status = STATUS_SUCCESS;
-
-    /* Check if we came from user mode */
-    if (PreviousMode != KernelMode)
-    {
-        /* Enter SEH for probing */
-        _SEH_TRY
-        {
-            /* Validate all outputs */
-            ProbeForWritePointer(UnsafeBaseAddress);
-            ProbeForWriteUlong(UnsafeNumberOfBytesToProtect);
-            ProbeForWriteUlong(UnsafeOldAccessProtection);
-            
-            /* Capture them */
-            BaseAddress = *UnsafeBaseAddress;
-            NumberOfBytesToProtect = *UnsafeNumberOfBytesToProtect;
-        }
-        _SEH_HANDLE
-        {
-            /* Get exception code */
-            Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
-        
-        /* Return on exception */
-        if (!NT_SUCCESS(Status)) return Status;
-    }
-    else
-    {
-        /* Capture directly */
-        BaseAddress = *UnsafeBaseAddress;
-        NumberOfBytesToProtect = *UnsafeNumberOfBytesToProtect;
-    }
+    PMEMORY_AREA MemoryArea;
     
-    /* Catch illegal base address */
-    if (BaseAddress > (PVOID)MmUserProbeAddress) return STATUS_INVALID_PARAMETER_2;
+    /* Sanity check */
+    ASSERT(Mdl->Process == PsGetCurrentProcess());
     
-    /* 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);
+    /* Find the memory area */
+    MemoryArea = MmLocateMemoryAreaByAddress(&Mdl->Process->Vm,
+                                             BaseAddress);
+    ASSERT(MemoryArea);
     
-    /* Enter SEH to return data */
-    _SEH_TRY
-    {
-        /* Return data to user */
-        *UnsafeOldAccessProtection = OldAccessProtection;
-        *UnsafeBaseAddress = BaseAddress;
-        *UnsafeNumberOfBytesToProtect = NumberOfBytesToProtect;
-    }
-    _SEH_HANDLE
-    {
-        /* Catch exception */
-        Status = _SEH_GetExceptionCode();
-    }
-    _SEH_END;
-
-    /* Return status */
-    return Status;
+    /* Free it */
+    MmFreeMemoryArea(&Mdl->Process->Vm,
+                     MemoryArea,
+                     NULL,
+                     NULL);    
 }
 
-NTSTATUS STDCALL
+/* SYSTEM CALLS ***************************************************************/
+
+NTSTATUS NTAPI
 NtQueryVirtualMemory(IN HANDLE ProcessHandle,
                      IN PVOID Address,
                      IN MEMORY_INFORMATION_CLASS VirtualMemoryInformationClass,
                      OUT PVOID VirtualMemoryInformation,
-                     IN ULONG Length,
-                     OUT PULONG UnsafeResultLength)
+                     IN SIZE_T Length,
+                     OUT PSIZE_T UnsafeResultLength)
 {
-    NTSTATUS Status = STATUS_SUCCESS;
-    ULONG ResultLength = 0;
+    NTSTATUS Status;
+    SIZE_T ResultLength = 0;
     KPROCESSOR_MODE PreviousMode;
+    WCHAR ModuleFileNameBuffer[MAX_PATH] = {0};
+    UNICODE_STRING ModuleFileName;
+    PMEMORY_SECTION_NAME SectionName = NULL;
+    PEPROCESS Process;
     union
     {
         MEMORY_BASIC_INFORMATION BasicInfo;
     }
     VirtualMemoryInfo;
-    
+
     DPRINT("NtQueryVirtualMemory(ProcessHandle %x, Address %x, "
            "VirtualMemoryInformationClass %d, VirtualMemoryInformation %x, "
            "Length %lu ResultLength %x)\n",ProcessHandle,Address,
            VirtualMemoryInformationClass,VirtualMemoryInformation,
            Length,ResultLength);
-    
+
     PreviousMode =  ExGetPreviousMode();
-    
-    if (PreviousMode != KernelMode && UnsafeResultLength != NULL)
+
+    if (PreviousMode != KernelMode)
     {
-        _SEH_TRY
+        _SEH2_TRY
         {
-            ProbeForWriteUlong(UnsafeResultLength);
-        }
-        _SEH_HANDLE
-        {
-            Status = _SEH_GetExceptionCode();
+            ProbeForWrite(VirtualMemoryInformation,
+                          Length,
+                          sizeof(ULONG_PTR));
+
+            if (UnsafeResultLength) ProbeForWriteSize_t(UnsafeResultLength);
         }
-        _SEH_END;
-        
-        if (!NT_SUCCESS(Status))
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
         {
-            return Status;
+            /* Return the exception code */
+            _SEH2_YIELD(return _SEH2_GetExceptionCode());
         }
+        _SEH2_END;
     }
-    
+
     if (Address >= MmSystemRangeStart)
     {
         DPRINT1("Invalid parameter\n");
         return STATUS_INVALID_PARAMETER;
     }
-    
-    Status = MiQueryVirtualMemory(ProcessHandle,
-                                  Address,
-                                  VirtualMemoryInformationClass,
-                                  &VirtualMemoryInfo,
-                                  Length,
-                                  &ResultLength );
-    
+
+    /* FIXME: Move this inside MiQueryVirtualMemory */
+    if (VirtualMemoryInformationClass == MemorySectionName)
+    {
+        Status = ObReferenceObjectByHandle(ProcessHandle,
+                                           PROCESS_QUERY_INFORMATION,
+                                           NULL,
+                                           PreviousMode,
+                                           (PVOID*)(&Process),
+                                           NULL);
+
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT("NtQueryVirtualMemory() = %x\n",Status);
+            return(Status);
+        }
+
+        RtlInitEmptyUnicodeString(&ModuleFileName, ModuleFileNameBuffer, sizeof(ModuleFileNameBuffer));
+        Status = MmGetFileNameForAddress(Address, &ModuleFileName);
+
+        if (NT_SUCCESS(Status))
+        {
+            SectionName = VirtualMemoryInformation;
+            if (PreviousMode != KernelMode)
+            {
+                _SEH2_TRY
+                {
+                    RtlInitUnicodeString(&SectionName->SectionFileName, SectionName->NameBuffer);
+                    SectionName->SectionFileName.MaximumLength = Length;
+                    RtlCopyUnicodeString(&SectionName->SectionFileName, &ModuleFileName);
+
+                    if (UnsafeResultLength != NULL)
+                    {
+                        *UnsafeResultLength = ModuleFileName.Length;
+                    }
+                }
+                _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+                {
+                    Status = _SEH2_GetExceptionCode();
+                }
+                _SEH2_END;
+            }
+            else
+            {
+                RtlInitUnicodeString(&SectionName->SectionFileName, SectionName->NameBuffer);
+                SectionName->SectionFileName.MaximumLength = Length;
+                RtlCopyUnicodeString(&SectionName->SectionFileName, &ModuleFileName);
+
+                if (UnsafeResultLength != NULL)
+                {
+                    *UnsafeResultLength = ModuleFileName.Length;
+                }
+            }
+        }
+        ObDereferenceObject(Process);
+        return Status;
+    }
+    else
+    {
+        Status = MiQueryVirtualMemory(ProcessHandle,
+                                      Address,
+                                      VirtualMemoryInformationClass,
+                                      &VirtualMemoryInfo,
+                                      Length,
+                                      &ResultLength);
+    }
+
     if (NT_SUCCESS(Status))
     {
         if (PreviousMode != KernelMode)
         {
-            _SEH_TRY
+            _SEH2_TRY
             {
                 if (ResultLength > 0)
                 {
@@ -1021,11 +412,11 @@ NtQueryVirtualMemory(IN HANDLE ProcessHandle,
                     *UnsafeResultLength = ResultLength;
                 }
             }
-            _SEH_HANDLE
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
-                Status = _SEH_GetExceptionCode();
+                Status = _SEH2_GetExceptionCode();
             }
-            _SEH_END;
+            _SEH2_END;
         }
         else
         {
@@ -1035,50 +426,15 @@ NtQueryVirtualMemory(IN HANDLE ProcessHandle,
                               &VirtualMemoryInfo,
                               ResultLength);
             }
-            
+
             if (UnsafeResultLength != NULL)
             {
                 *UnsafeResultLength = ResultLength;
             }
         }
     }
-    
-    return(Status);
-}
 
-NTSTATUS
-NTAPI
-NtLockVirtualMemory(IN HANDLE ProcessHandle,
-                    IN PVOID BaseAddress,
-                    IN ULONG NumberOfBytesToLock,
-                    OUT PULONG NumberOfBytesLocked OPTIONAL)
-{
-    UNIMPLEMENTED;
-    if (NumberOfBytesLocked) *NumberOfBytesLocked = 0;
-    return STATUS_SUCCESS;
-}
-
-NTSTATUS
-NTAPI
-NtUnlockVirtualMemory(IN HANDLE ProcessHandle,
-                      IN PVOID BaseAddress,
-                      IN ULONG NumberOfBytesToUnlock,
-                      OUT PULONG 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;
+    return(Status);
 }
 
 /* EOF */