[NTOS]: Stop handling a bunch of MEMORY_AREA_TYPEs that aren't used anymore.
[reactos.git] / reactos / ntoskrnl / mm / virtual.c
index 377e1a1..0016133 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id$
- *
+/*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/mm/virtual.c
  * PROGRAMMERS:     David Welch
  */
 
-/* INCLUDE *****************************************************************/
+/* INCLUDE ********************************************************************/
 
 #include <ntoskrnl.h>
-
 #define NDEBUG
-#include <internal/debug.h>
-
-/* FUNCTIONS *****************************************************************/
-
-NTSTATUS STDCALL
-NtFlushVirtualMemory(IN HANDLE ProcessHandle,
-                     IN OUT PVOID *BaseAddress,
-                     IN OUT PSIZE_T NumberOfBytesToFlush,
-                     OUT PIO_STATUS_BLOCK IoStatusBlock)
-/*
- * FUNCTION: Flushes virtual memory to file
- * ARGUMENTS:
- *        ProcessHandle = Points to the process that allocated the virtual
- *                        memory
- *        BaseAddress = Points to the memory address
- *        NumberOfBytesToFlush = Limits the range to flush,
- *        NumberOfBytesFlushed = Actual number of bytes flushed
- * RETURNS: Status
- */
-{
-    /* This should be implemented once we support network filesystems */
-    DPRINT("NtFlushVirtualMemory is UNIMPLEMENTED\n");
-    return(STATUS_SUCCESS);
-}
-
-
-NTSTATUS STDCALL
-MiLockVirtualMemory(HANDLE ProcessHandle,
-                    PVOID BaseAddress,
-                    ULONG NumberOfBytesToLock,
-                    PULONG NumberOfBytesLocked,
-                    PObReferenceObjectByHandle pObReferenceObjectByHandle,
-                    PMmCreateMdl pMmCreateMdl,
-                    PObDereferenceObject pObDereferenceObject,
-                    PMmProbeAndLockPages pMmProbeAndLockPages,
-                    PExFreePool pExFreePool)
-{
-    PEPROCESS Process;
-    NTSTATUS Status;
-    PMDL Mdl;
-
-    Status = pObReferenceObjectByHandle(ProcessHandle,
-                                        PROCESS_VM_WRITE,
-                                        NULL,
-                                        UserMode,
-                                        (PVOID*)(&Process),
-                                        NULL);
-    if (!NT_SUCCESS(Status))
-        return(Status);
-
-    Mdl = pMmCreateMdl(NULL,
-                       BaseAddress,
-                       NumberOfBytesToLock);
-    if (Mdl == NULL)
-    {
-        pObDereferenceObject(Process);
-        return(STATUS_NO_MEMORY);
-    }
-
-    pMmProbeAndLockPages(Mdl,
-                         UserMode,
-                         IoWriteAccess);
-
-    pExFreePool(Mdl);
-
-    pObDereferenceObject(Process);
-
-    *NumberOfBytesLocked = NumberOfBytesToLock;
-    return(STATUS_SUCCESS);
-}
-
-
-NTSTATUS STDCALL
-NtLockVirtualMemory(HANDLE ProcessHandle,
-                    PVOID BaseAddress,
-                    ULONG NumberOfBytesToLock,
-                    PULONG NumberOfBytesLocked)
-{
-    DPRINT("NtLockVirtualMemory(ProcessHandle %x, BaseAddress %x, "
-        "NumberOfBytesToLock %d, NumberOfBytesLocked %x)\n",
-        ProcessHandle,
-        BaseAddress,
-        NumberOfBytesToLock,
-        NumberOfBytesLocked);
-
-    return MiLockVirtualMemory(ProcessHandle,
-                               BaseAddress,
-                               NumberOfBytesToLock,
-                               NumberOfBytesLocked,
-                               ObReferenceObjectByHandle,
-                               MmCreateMdl,
-                               (PVOID)ObfDereferenceObject,
-                               MmProbeAndLockPages,
-                               ExFreePool);
-}
+#include <debug.h>
 
+/* PRIVATE FUNCTIONS **********************************************************/
 
 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)
@@ -175,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;
@@ -185,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;
@@ -261,6 +95,7 @@ MiQueryVirtualMemory(IN HANDLE ProcessHandle,
 
         default:
         {
+            DPRINT1("Unsupported or unimplemented class: %lx\n", VirtualMemoryInformationClass);
             Status = STATUS_INVALID_INFO_CLASS;
             *ResultLength = 0;
             break;
@@ -268,140 +103,29 @@ MiQueryVirtualMemory(IN HANDLE ProcessHandle,
     }
 
     MmUnlockAddressSpace(AddressSpace);
-    if (Address < MmSystemRangeStart)
-    {
-        ASSERT(Process);
-        ObDereferenceObject(Process);
-    }
+    ObDereferenceObject(Process);
 
     return Status;
 }
 
-/* (tMk 2004.II.4)
- * FUNCTION:
- * Called from VirtualQueryEx (lib\kernel32\mem\virtual.c)
- *
- */
-NTSTATUS STDCALL
-NtQueryVirtualMemory(IN HANDLE ProcessHandle,
-                     IN PVOID Address,
-                     IN MEMORY_INFORMATION_CLASS VirtualMemoryInformationClass,
-                     OUT PVOID VirtualMemoryInformation,
-                     IN ULONG Length,
-                     OUT PULONG UnsafeResultLength)
-{
-    NTSTATUS Status = STATUS_SUCCESS;
-    ULONG ResultLength = 0;
-    KPROCESSOR_MODE PreviousMode;
-    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)
-    {
-        _SEH_TRY
-        {
-            ProbeForWriteUlong(UnsafeResultLength);
-        }
-        _SEH_HANDLE
-        {
-            Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
-
-        if (!NT_SUCCESS(Status))
-        {
-            return Status;
-        }
-    }
-
-    if (Address >= MmSystemRangeStart)
-    {
-        DPRINT1("Invalid parameter\n");
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    Status = MiQueryVirtualMemory(ProcessHandle,
-                                  Address,
-                                  VirtualMemoryInformationClass,
-                                  &VirtualMemoryInfo,
-                                  Length,
-                                  &ResultLength );
-
-    if (NT_SUCCESS(Status))
-    {
-        if (PreviousMode != KernelMode)
-        {
-            _SEH_TRY
-            {
-                if (ResultLength > 0)
-                {
-                    ProbeForWrite(VirtualMemoryInformation,
-                                  ResultLength,
-                                  1);
-                    RtlCopyMemory(VirtualMemoryInformation,
-                                  &VirtualMemoryInfo,
-                                  ResultLength);
-                }
-                if (UnsafeResultLength != NULL)
-                {
-                    *UnsafeResultLength = ResultLength;
-                }
-            }
-            _SEH_HANDLE
-            {
-                Status = _SEH_GetExceptionCode();
-            }
-            _SEH_END;
-        }
-        else
-        {
-            if (ResultLength > 0)
-            {
-                RtlCopyMemory(VirtualMemoryInformation,
-                              &VirtualMemoryInfo,
-                              ResultLength);
-            }
-
-            if (UnsafeResultLength != NULL)
-            {
-                *UnsafeResultLength = ResultLength;
-            }
-        }
-    }
-
-   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);
+    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);
@@ -438,620 +162,279 @@ MiProtectVirtualMemory(IN PEPROCESS Process,
     return Status;
 }
 
-
-/* (tMk 2004.II.5)
- * FUNCTION:
- * Called from VirtualProtectEx (lib\kernel32\mem\virtual.c)
- *
- */
-NTSTATUS STDCALL
-NtProtectVirtualMemory(IN HANDLE ProcessHandle,
-                       IN OUT PVOID *UnsafeBaseAddress,
-                       IN OUT ULONG *UnsafeNumberOfBytesToProtect,
-                       IN ULONG NewAccessProtection,
-                       OUT PULONG UnsafeOldAccessProtection)
+PVOID
+NTAPI
+MiMapLockedPagesInUserSpace(IN PMDL Mdl,
+                            IN PVOID BaseVa,
+                            IN MEMORY_CACHING_TYPE CacheType,
+                            IN PVOID BaseAddress)
 {
-    PEPROCESS Process;
-    ULONG OldAccessProtection;
-    PVOID BaseAddress = NULL;
-    ULONG NumberOfBytesToProtect = 0;
-    KPROCESSOR_MODE PreviousMode;
-    NTSTATUS Status = STATUS_SUCCESS;
-
-    PreviousMode = ExGetPreviousMode();
-
-    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))
     {
-        _SEH_TRY
-        {
-            ProbeForWritePointer(UnsafeBaseAddress);
-            ProbeForWriteUlong(UnsafeNumberOfBytesToProtect);
-            ProbeForWriteUlong(UnsafeOldAccessProtection);
-
-            BaseAddress = *UnsafeBaseAddress;
-            NumberOfBytesToProtect = *UnsafeNumberOfBytesToProtect;
-        }
-        _SEH_HANDLE
-        {
-            Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
-
-        if (!NT_SUCCESS(Status))
+        if (Mdl->MdlFlags & MDL_MAPPING_CAN_FAIL)
         {
-            return Status;
+            return NULL;
         }
+        
+        /* Throw exception */
+        ExRaiseStatus(STATUS_ACCESS_VIOLATION);
+        ASSERT(0);
     }
-    else
+    
+    /* Set the virtual mappings for the MDL pages. */
+    if (Mdl->MdlFlags & MDL_IO_SPACE)
     {
-        BaseAddress = *UnsafeBaseAddress;
-        NumberOfBytesToProtect = *UnsafeNumberOfBytesToProtect;
+        /* Map the pages */
+        Status = MmCreateVirtualMappingUnsafe(CurrentProcess,
+                                              Base,
+                                              Protect,
+                                              MdlPages,
+                                              PageCount);
     }
-
-    if ((ULONG_PTR)BaseAddress + NumberOfBytesToProtect - 1 < (ULONG_PTR)BaseAddress ||
-        (ULONG_PTR)BaseAddress + NumberOfBytesToProtect - 1 >= MmUserProbeAddress)
-    {
-        /* Don't allow to change the protection of a kernel mode address */
-        return STATUS_INVALID_PARAMETER_2;
-    }
-
-    /* (tMk 2004.II.5) in Microsoft SDK I read:
-     * 'if this parameter is NULL or does not point to a valid variable, the function fails'
-     */
-    if(UnsafeOldAccessProtection == NULL)
+    else
     {
-        return(STATUS_INVALID_PARAMETER);
+        /* Map the pages */
+        Status = MmCreateVirtualMapping(CurrentProcess,
+                                        Base,
+                                        Protect,
+                                        MdlPages,
+                                        PageCount);
     }
-
-    Status = ObReferenceObjectByHandle(ProcessHandle,
-                                       PROCESS_VM_OPERATION,
-                                       PsProcessType,
-                                       UserMode,
-                                       (PVOID*)(&Process),
-                                       NULL);
+    
+    /* Check if the mapping suceeded */
     if (!NT_SUCCESS(Status))
     {
-        DPRINT("NtProtectVirtualMemory() = %x\n",Status);
-        return(Status);
-    }
-
-    Status = MiProtectVirtualMemory(Process,
-                                    &BaseAddress,
-                                    &NumberOfBytesToProtect,
-                                    NewAccessProtection,
-                                    &OldAccessProtection);
-
-    ObDereferenceObject(Process);
-
-    if (PreviousMode != KernelMode)
-    {
-        _SEH_TRY
-        {
-            *UnsafeOldAccessProtection = OldAccessProtection;
-            *UnsafeBaseAddress = BaseAddress;
-            *UnsafeNumberOfBytesToProtect = NumberOfBytesToProtect;
-        }
-        _SEH_HANDLE
-        {
-            Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
-    }
-    else
-    {
-        *UnsafeOldAccessProtection = OldAccessProtection;
-        *UnsafeBaseAddress = BaseAddress;
-        *UnsafeNumberOfBytesToProtect = NumberOfBytesToProtect;
+        /* If it can fail, return NULL */
+        if (Mdl->MdlFlags & MDL_MAPPING_CAN_FAIL) return NULL;
+        
+        /* Throw exception */
+        ExRaiseStatus(STATUS_ACCESS_VIOLATION);
     }
+    
+    /* Return the base */
+    Base = (PVOID)((ULONG_PTR)Base + Mdl->ByteOffset);
+    return Base;
+}
 
-    return(Status);
+VOID
+NTAPI
+MiUnmapLockedPagesInUserSpace(IN PVOID BaseAddress,
+                              IN PMDL Mdl)
+{
+    PMEMORY_AREA MemoryArea;
+    
+    /* Sanity check */
+    ASSERT(Mdl->Process == PsGetCurrentProcess());
+    
+    /* Find the memory area */
+    MemoryArea = MmLocateMemoryAreaByAddress(&Mdl->Process->Vm,
+                                             BaseAddress);
+    ASSERT(MemoryArea);
+    
+    /* Free it */
+    MmFreeMemoryArea(&Mdl->Process->Vm,
+                     MemoryArea,
+                     NULL,
+                     NULL);    
 }
 
+/* SYSTEM CALLS ***************************************************************/
 
-/* (tMk 2004.II.05)
- * FUNCTION:
- * Called from ReadProcessMemory (lib\kernel32\mem\procmem.c) and KlInitPeb(lib\kernel32\process\create.c)
- *
- * NOTE: This function will be correct if MmProbeAndLockPages() would be fully IMPLEMENTED.
- */
-NTSTATUS STDCALL
-NtReadVirtualMemory(IN HANDLE ProcessHandle,
-                    IN PVOID BaseAddress,
-                    OUT PVOID Buffer,
-                    IN ULONG NumberOfBytesToRead,
-                    OUT PULONG NumberOfBytesRead OPTIONAL)
+NTSTATUS NTAPI
+NtQueryVirtualMemory(IN HANDLE ProcessHandle,
+                     IN PVOID Address,
+                     IN MEMORY_INFORMATION_CLASS VirtualMemoryInformationClass,
+                     OUT PVOID VirtualMemoryInformation,
+                     IN SIZE_T Length,
+                     OUT PSIZE_T UnsafeResultLength)
 {
-    PMDL Mdl;
-    PVOID SystemAddress;
+    NTSTATUS Status;
+    SIZE_T ResultLength = 0;
     KPROCESSOR_MODE PreviousMode;
-    PEPROCESS Process, CurrentProcess;
-    NTSTATUS Status = STATUS_SUCCESS;
-
-    PAGED_CODE();
-
-    DPRINT("NtReadVirtualMemory(ProcessHandle %x, BaseAddress %x, "
-           "Buffer %x, NumberOfBytesToRead %d)\n",ProcessHandle,BaseAddress,
-           Buffer,NumberOfBytesToRead);
-
-    if ((ULONG_PTR)BaseAddress + NumberOfBytesToRead - 1 < (ULONG_PTR)BaseAddress ||
-        (ULONG_PTR)BaseAddress + NumberOfBytesToRead - 1 >= MmUserProbeAddress)
+    WCHAR ModuleFileNameBuffer[MAX_PATH] = {0};
+    UNICODE_STRING ModuleFileName;
+    PMEMORY_SECTION_NAME SectionName = NULL;
+    PEPROCESS Process;
+    union
     {
-        /* Don't allow to read from kernel space */
-        return STATUS_ACCESS_VIOLATION;
+        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();
+    PreviousMode =  ExGetPreviousMode();
 
     if (PreviousMode != KernelMode)
     {
-        if ((ULONG_PTR)Buffer + NumberOfBytesToRead - 1 < (ULONG_PTR)Buffer ||
-            (ULONG_PTR)Buffer + NumberOfBytesToRead - 1 >= MmUserProbeAddress)
+        _SEH2_TRY
         {
-            /* Don't allow to write into kernel space */
-            return STATUS_ACCESS_VIOLATION;
-        }
-    }
-
-    Status = ObReferenceObjectByHandle(ProcessHandle,
-                                       PROCESS_VM_READ,
-                                       NULL,
-                                       PreviousMode,
-                                       (PVOID*)(&Process),
-                                       NULL);
-    if (!NT_SUCCESS(Status))
-    {
-        return(Status);
-    }
+            ProbeForWrite(VirtualMemoryInformation,
+                          Length,
+                          sizeof(ULONG_PTR));
 
-    CurrentProcess = PsGetCurrentProcess();
-
-    if(PreviousMode != KernelMode)
-    {
-        _SEH_TRY
-        {
-            if(NumberOfBytesRead != NULL)
-            {
-                ProbeForWriteUlong(NumberOfBytesRead);
-            }
+            if (UnsafeResultLength) ProbeForWriteSize_t(UnsafeResultLength);
         }
-        _SEH_HANDLE
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
         {
-            Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
-
-        if(!NT_SUCCESS(Status))
-        {
-            return Status;
+            /* Return the exception code */
+            _SEH2_YIELD(return _SEH2_GetExceptionCode());
         }
+        _SEH2_END;
     }
 
-
-    if (Process == CurrentProcess)
+    if (Address >= MmSystemRangeStart)
     {
-        _SEH_TRY
-        {
-            RtlCopyMemory(Buffer, BaseAddress, NumberOfBytesToRead);
-        }
-        _SEH_HANDLE
-        {
-            Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
+        DPRINT1("Invalid parameter\n");
+        return STATUS_INVALID_PARAMETER;
     }
-    else
-    {
-        Mdl = MmCreateMdl(NULL,
-                          Buffer,
-                          NumberOfBytesToRead);
-        if(Mdl == NULL)
-        {
-            ObDereferenceObject(Process);
-            return(STATUS_NO_MEMORY);
-        }
 
-        _SEH_TRY
-        {
-            MmProbeAndLockPages(Mdl, PreviousMode, IoWriteAccess);
-        }
-        _SEH_HANDLE
-        {
-            Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
+    /* FIXME: Move this inside MiQueryVirtualMemory */
+    if (VirtualMemoryInformationClass == MemorySectionName)
+    {
+        Status = ObReferenceObjectByHandle(ProcessHandle,
+                                           PROCESS_QUERY_INFORMATION,
+                                           NULL,
+                                           PreviousMode,
+                                           (PVOID*)(&Process),
+                                           NULL);
 
-        if(NT_SUCCESS(Status))
+        if (!NT_SUCCESS(Status))
         {
-            KeAttachProcess(&Process->Pcb);
-
-            SystemAddress = MmGetSystemAddressForMdl(Mdl);
-
-            Status = STATUS_SUCCESS;
-            _SEH_TRY
-            {
-                Status = STATUS_PARTIAL_COPY;
-                RtlCopyMemory(SystemAddress, BaseAddress, NumberOfBytesToRead);
-                Status = STATUS_SUCCESS;
-            }
-            _SEH_HANDLE
-            {
-                if(Status != STATUS_PARTIAL_COPY)
-                    Status = _SEH_GetExceptionCode();
-            }
-            _SEH_END;
-
-            KeDetachProcess();
-
-            if (Mdl->MappedSystemVa != NULL)
-            {
-                MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
-            }
-            MmUnlockPages(Mdl);
+            DPRINT("NtQueryVirtualMemory() = %x\n",Status);
+            return(Status);
         }
-        ExFreePool(Mdl);
-    }
 
-    ObDereferenceObject(Process);
+        RtlInitEmptyUnicodeString(&ModuleFileName, ModuleFileNameBuffer, sizeof(ModuleFileNameBuffer));
+        Status = MmGetFileNameForAddress(Address, &ModuleFileName);
 
-    if ((NT_SUCCESS(Status) || Status == STATUS_PARTIAL_COPY) &&
-        NumberOfBytesRead != NULL)
-    {
-        _SEH_TRY
+        if (NT_SUCCESS(Status))
         {
-            *NumberOfBytesRead = NumberOfBytesToRead;
-        }
-        _SEH_HANDLE
-        {
-            Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
-    }
-
-    return(Status);
-}
-
-/* (tMk 2004.II.05)
- * FUNCTION:  THIS function doesn't make a sense...
- * Called from VirtualUnlock (lib\kernel32\mem\virtual.c)
- */
-NTSTATUS STDCALL
-NtUnlockVirtualMemory(HANDLE ProcessHandle,
-                      PVOID BaseAddress,
-                      ULONG NumberOfBytesToUnlock,
-                      PULONG NumberOfBytesUnlocked OPTIONAL)
-{
-    // AG [08-20-03] : I have *no* idea if this is correct, I just used the
-    // other functions as a template and made a few intelligent guesses...
-
-    NTSTATUS Status;
-    PMDL Mdl;
-    PEPROCESS Process;
-
-    DPRINT("NtUnlockVirtualMemory(ProcessHandle %x, BaseAddress %x, "
-           "NumberOfBytesToUnlock %d), NumberOfBytesUnlocked %x\n",ProcessHandle,BaseAddress,
-           NumberOfBytesToUnlock, NumberOfBytesUnlocked);
-
-    Status = ObReferenceObjectByHandle(ProcessHandle,
-                                       PROCESS_VM_WRITE,
-                                       NULL,
-                                       UserMode,
-                                       (PVOID*)(&Process),
-                                       NULL);
-    if (!NT_SUCCESS(Status))
-    {
-        return(Status);
-    }
-
-    Mdl = MmCreateMdl(NULL,
-                      BaseAddress,
-                      NumberOfBytesToUnlock);
-    if(Mdl == NULL)
-    {
-        ObDereferenceObject(Process);
-        return(STATUS_NO_MEMORY);
-    }
-
-    ObDereferenceObject(Process);
-
-    if (Mdl->MappedSystemVa != NULL)
-    {
-        MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
-    }
-    MmUnlockPages(Mdl);
-    ExFreePool(Mdl);
-
-    *NumberOfBytesUnlocked = NumberOfBytesToUnlock;
-
-    return(STATUS_SUCCESS);
-}
-
-
-/* (tMk 2004.II.05)
- * FUNCTION:
- * Called from WriteProcessMemory (lib\kernel32\mem\procmem.c) and KlInitPeb(lib\kernel32\process\create.c)
- *
- * NOTE: This function will be correct if MmProbeAndLockPages() would be fully IMPLEMENTED.
- */
-NTSTATUS STDCALL
-NtWriteVirtualMemory(IN HANDLE ProcessHandle,
-                     IN PVOID BaseAddress,
-                     IN PVOID Buffer,
-                     IN ULONG NumberOfBytesToWrite,
-                     OUT PULONG NumberOfBytesWritten  OPTIONAL)
-{
-    PMDL Mdl;
-    PVOID SystemAddress;
-    PEPROCESS Process;
-    KPROCESSOR_MODE PreviousMode;
-    NTSTATUS CopyStatus, Status = STATUS_SUCCESS;
-
-    DPRINT("NtWriteVirtualMemory(ProcessHandle %x, BaseAddress %x, "
-           "Buffer %x, NumberOfBytesToWrite %d)\n",ProcessHandle,BaseAddress,
-           Buffer,NumberOfBytesToWrite);
-
-    if ((ULONG_PTR)BaseAddress + NumberOfBytesToWrite - 1 < (ULONG_PTR)BaseAddress ||
-        (ULONG_PTR)BaseAddress + NumberOfBytesToWrite - 1 >= MmUserProbeAddress)
-    {
-        /* Don't allow to write into kernel space */
-        return STATUS_ACCESS_VIOLATION;
-    }
-
-    PreviousMode = ExGetPreviousMode();
-
-    if (PreviousMode != KernelMode)
-    {
-        if ((ULONG_PTR)Buffer + NumberOfBytesToWrite - 1 < (ULONG_PTR)Buffer ||
-            (ULONG_PTR)Buffer + NumberOfBytesToWrite - 1 >= MmUserProbeAddress)
-        {
-            /* Don't allow to read from kernel space */
-            return STATUS_ACCESS_VIOLATION;
-        }
-        if (NumberOfBytesWritten != NULL)
-        {
-            _SEH_TRY
+            SectionName = VirtualMemoryInformation;
+            if (PreviousMode != KernelMode)
             {
-                ProbeForWriteUlong(NumberOfBytesWritten);
+                _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;
             }
-            _SEH_HANDLE
+            else
             {
-                Status = _SEH_GetExceptionCode();
-            }
-            _SEH_END;
+                RtlInitUnicodeString(&SectionName->SectionFileName, SectionName->NameBuffer);
+                SectionName->SectionFileName.MaximumLength = Length;
+                RtlCopyUnicodeString(&SectionName->SectionFileName, &ModuleFileName);
 
-            if (!NT_SUCCESS(Status))
-            {
-                return Status;
+                if (UnsafeResultLength != NULL)
+                {
+                    *UnsafeResultLength = ModuleFileName.Length;
+                }
             }
         }
+        ObDereferenceObject(Process);
+        return Status;
     }
-
-    Status = ObReferenceObjectByHandle(ProcessHandle,
-                                       PROCESS_VM_WRITE,
-                                       NULL,
-                                       UserMode,
-                                       (PVOID*)(&Process),
-                                       NULL);
-    if (!NT_SUCCESS(Status))
+    else
     {
-        return(Status);
+        Status = MiQueryVirtualMemory(ProcessHandle,
+                                      Address,
+                                      VirtualMemoryInformationClass,
+                                      &VirtualMemoryInfo,
+                                      Length,
+                                      &ResultLength);
     }
 
-    CopyStatus = STATUS_SUCCESS;
-
-    /* Write memory */
-    if (Process == PsGetCurrentProcess())
+    if (NT_SUCCESS(Status))
     {
         if (PreviousMode != KernelMode)
         {
-            _SEH_TRY
-            {
-                memcpy(BaseAddress, Buffer, NumberOfBytesToWrite);
-            }
-            _SEH_HANDLE
-            {
-                CopyStatus = _SEH_GetExceptionCode();
-            }
-            _SEH_END;
-        }
-        else
-        {
-            memcpy(BaseAddress, Buffer, NumberOfBytesToWrite);
-        }
-    }
-    else
-    {
-        /* Create MDL describing the source buffer. */
-        Mdl = MmCreateMdl(NULL,
-                          Buffer,
-                          NumberOfBytesToWrite);
-        if (Mdl == NULL)
-        {
-            ObDereferenceObject(Process);
-            return(STATUS_NO_MEMORY);
-        }
-        _SEH_TRY
-        {
-            /* Map the MDL. */
-            MmProbeAndLockPages(Mdl, UserMode, IoReadAccess);
-        }
-        _SEH_HANDLE
-        {
-            CopyStatus = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
-
-        if (NT_SUCCESS(CopyStatus))
-        {
-            /* Copy memory from the mapped MDL into the target buffer. */
-            KeAttachProcess(&Process->Pcb);
-
-            SystemAddress = MmGetSystemAddressForMdl(Mdl);
-            if (PreviousMode != KernelMode)
+            _SEH2_TRY
             {
-                _SEH_TRY
+                if (ResultLength > 0)
                 {
-                    memcpy(BaseAddress, SystemAddress, NumberOfBytesToWrite);
+                    ProbeForWrite(VirtualMemoryInformation,
+                                  ResultLength,
+                                  1);
+                    RtlCopyMemory(VirtualMemoryInformation,
+                                  &VirtualMemoryInfo,
+                                  ResultLength);
                 }
-                _SEH_HANDLE
+                if (UnsafeResultLength != NULL)
                 {
-                    CopyStatus = _SEH_GetExceptionCode();
+                    *UnsafeResultLength = ResultLength;
                 }
-                _SEH_END;
             }
-            else
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
-                memcpy(BaseAddress, SystemAddress, NumberOfBytesToWrite);
+                Status = _SEH2_GetExceptionCode();
             }
-
-            KeDetachProcess();
+            _SEH2_END;
         }
-
-        /* Free the MDL. */
-        if (Mdl->MappedSystemVa != NULL)
-        {
-            MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
-        }
-        MmUnlockPages(Mdl);
-        ExFreePool(Mdl);
-    }
-    ObDereferenceObject(Process);
-
-    if (NT_SUCCESS(CopyStatus) && NumberOfBytesWritten != NULL)
-    {
-        if (PreviousMode != KernelMode)
+        else
         {
-            _SEH_TRY
+            if (ResultLength > 0)
             {
-                *NumberOfBytesWritten = NumberOfBytesToWrite;
+                RtlCopyMemory(VirtualMemoryInformation,
+                              &VirtualMemoryInfo,
+                              ResultLength);
             }
-            _SEH_HANDLE
+
+            if (UnsafeResultLength != NULL)
             {
-                Status = _SEH_GetExceptionCode();
+                *UnsafeResultLength = ResultLength;
             }
-            _SEH_END;
-        }
-        else
-        {
-            *NumberOfBytesWritten = NumberOfBytesToWrite;
         }
     }
 
-    return(NT_SUCCESS(CopyStatus) ? Status : CopyStatus);
-}
-
-/*
- * @unimplemented
- */
-
-PVOID
-STDCALL
-MmGetVirtualForPhysical(
-    IN PHYSICAL_ADDRESS PhysicalAddress
-    )
-{
-    UNIMPLEMENTED;
-    return 0;
-}
-
-/* FUNCTION:
- * Called from EngSecureMem (subsys\win32k\eng\mem.c)
- * @unimplemented
- */
-PVOID STDCALL
-MmSecureVirtualMemory(PVOID  Address,
-                      SIZE_T Length,
-                      ULONG  Mode)
-{
-    /* Only works for user space */
-    if (MmHighestUserAddress < Address)
-    {
-        return NULL;
-    }
-
-    UNIMPLEMENTED;
-
-    return 0;
-}
-
-
-/* FUNCTION:
- * Called from EngUnsecureMem (subsys\win32k\eng\mem.c)
- * @unimplemented
- */
-VOID STDCALL
-MmUnsecureVirtualMemory(PVOID SecureMem)
-{
-    if (NULL == SecureMem)
-    {
-        return;
-    }
-
-    UNIMPLEMENTED;
-}
-
-
-/*
- * @implemented
- */
-VOID STDCALL
-ProbeForRead(IN CONST VOID *Address,
-             IN ULONG Length,
-             IN ULONG Alignment)
-{
-    if (Length != 0)
-    {
-        ASSERT(Alignment == 1 || Alignment == 2 || Alignment == 4 || Alignment == 8);
-
-        if (((ULONG_PTR)Address & (Alignment - 1)) != 0)
-        {
-            ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
-        }
-        else if ((ULONG_PTR)Address + Length - 1 < (ULONG_PTR)Address ||
-                 (ULONG_PTR)Address + Length - 1 >= (ULONG_PTR)MmUserProbeAddress)
-        {
-            ExRaiseStatus (STATUS_ACCESS_VIOLATION);
-        }
-    }
-}
-
-
-/*
- * @implemented
- */
-VOID STDCALL
-ProbeForWrite(IN PVOID Address,
-              IN ULONG Length,
-              IN ULONG Alignment)
-{
-    volatile CHAR *Current;
-    PCHAR Last;
-
-    if (Length != 0)
-    {
-        ASSERT(Alignment == 1 || Alignment == 2 || Alignment == 4 || Alignment == 8);
-
-        if (((ULONG_PTR)Address & (Alignment - 1)) != 0)
-        {
-            ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
-        }
-
-        Last = (PCHAR)((ULONG_PTR)Address + Length - 1);
-        if ((ULONG_PTR)Last < (ULONG_PTR)Address ||
-            (ULONG_PTR)Last >= (ULONG_PTR)MmUserProbeAddress)
-        {
-            ExRaiseStatus (STATUS_ACCESS_VIOLATION);
-        }
-
-        /* Check for accessible pages, do *not* touch any memory outside of the
-           range!*/
-        Current = (volatile CHAR*)Address;
-        Last = (PCHAR)(PAGE_ROUND_DOWN(Last));
-        do
-        {
-            *Current = *Current;
-            Current = (volatile CHAR*)(PAGE_ROUND_DOWN(Current) + PAGE_SIZE);
-        } while (Current <= Last);
-    }
+    return(Status);
 }
 
 /* EOF */