2008-03-09 14:11:42 +00:00
|
|
|
/*
|
2005-01-26 13:58:37 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
|
|
|
* FILE: ntoskrnl/mm/virtual.c
|
|
|
|
* PURPOSE: Implementing operations on virtual memory.
|
2005-05-09 01:38:29 +00:00
|
|
|
*
|
2005-01-26 13:58:37 +00:00
|
|
|
* PROGRAMMERS: David Welch
|
1999-01-16 02:11:45 +00:00
|
|
|
*/
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2008-04-24 21:26:01 +00:00
|
|
|
/* INCLUDE ********************************************************************/
|
1999-01-16 02:11:45 +00:00
|
|
|
|
2004-10-28 19:01:59 +00:00
|
|
|
#include <ntoskrnl.h>
|
1999-01-16 02:11:45 +00:00
|
|
|
#define NDEBUG
|
2008-04-24 21:26:01 +00:00
|
|
|
#include <debug.h>
|
2000-08-18 22:27:09 +00:00
|
|
|
|
2008-04-24 21:26:01 +00:00
|
|
|
/* PRIVATE FUNCTIONS **********************************************************/
|
2004-10-28 19:01:59 +00:00
|
|
|
|
2004-12-22 05:17:44 +00:00
|
|
|
NTSTATUS FASTCALL
|
2007-10-23 11:08:18 +00:00
|
|
|
MiQueryVirtualMemory(IN HANDLE ProcessHandle,
|
|
|
|
IN PVOID Address,
|
|
|
|
IN MEMORY_INFORMATION_CLASS VirtualMemoryInformationClass,
|
|
|
|
OUT PVOID VirtualMemoryInformation,
|
2008-09-24 15:27:54 +00:00
|
|
|
IN SIZE_T Length,
|
|
|
|
OUT PSIZE_T ResultLength)
|
1999-01-16 02:11:45 +00:00
|
|
|
{
|
2007-10-23 11:08:18 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
PEPROCESS Process;
|
|
|
|
MEMORY_AREA* MemoryArea;
|
2009-04-27 10:12:57 +00:00
|
|
|
PMMSUPPORT AddressSpace;
|
2007-10-23 11:08:18 +00:00
|
|
|
|
2008-09-24 19:13:08 +00:00
|
|
|
Status = ObReferenceObjectByHandle(ProcessHandle,
|
|
|
|
PROCESS_QUERY_INFORMATION,
|
|
|
|
NULL,
|
|
|
|
UserMode,
|
|
|
|
(PVOID*)(&Process),
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
2007-10-23 11:08:18 +00:00
|
|
|
{
|
2008-09-24 19:13:08 +00:00
|
|
|
DPRINT("NtQueryVirtualMemory() = %x\n",Status);
|
|
|
|
return(Status);
|
2007-10-23 11:08:18 +00:00
|
|
|
}
|
2008-09-24 19:13:08 +00:00
|
|
|
|
2009-04-27 10:12:57 +00:00
|
|
|
AddressSpace = &Process->Vm;
|
2008-09-24 19:13:08 +00:00
|
|
|
|
2007-10-23 11:08:18 +00:00
|
|
|
MmLockAddressSpace(AddressSpace);
|
|
|
|
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address);
|
|
|
|
switch(VirtualMemoryInformationClass)
|
|
|
|
{
|
|
|
|
case MemoryBasicInformation:
|
|
|
|
{
|
|
|
|
PMEMORY_BASIC_INFORMATION Info =
|
|
|
|
(PMEMORY_BASIC_INFORMATION)VirtualMemoryInformation;
|
2004-04-10 22:36:07 +00:00
|
|
|
if (Length != sizeof(MEMORY_BASIC_INFORMATION))
|
|
|
|
{
|
2007-10-23 11:08:18 +00:00
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
|
|
|
ObDereferenceObject(Process);
|
|
|
|
return(STATUS_INFO_LENGTH_MISMATCH);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2004-12-22 05:17:44 +00:00
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
if (MemoryArea == NULL)
|
|
|
|
{
|
2007-10-23 11:08:18 +00:00
|
|
|
Info->Type = 0;
|
|
|
|
Info->State = MEM_FREE;
|
|
|
|
Info->Protect = PAGE_NOACCESS;
|
|
|
|
Info->AllocationProtect = 0;
|
|
|
|
Info->BaseAddress = (PVOID)PAGE_ROUND_DOWN(Address);
|
|
|
|
Info->AllocationBase = NULL;
|
|
|
|
Info->RegionSize = MmFindGapAtAddress(AddressSpace, Info->BaseAddress);
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
*ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
|
|
|
|
}
|
2004-12-22 05:17:44 +00:00
|
|
|
else
|
2007-10-23 11:08:18 +00:00
|
|
|
{
|
|
|
|
switch(MemoryArea->Type)
|
|
|
|
{
|
|
|
|
case MEMORY_AREA_VIRTUAL_MEMORY:
|
|
|
|
Status = MmQueryAnonMem(MemoryArea, Address, Info,
|
|
|
|
ResultLength);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MEMORY_AREA_SECTION_VIEW:
|
|
|
|
Status = MmQuerySectionView(MemoryArea, Address, Info,
|
|
|
|
ResultLength);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
DPRINT1("unhandled memory area type: 0x%x\n", MemoryArea->Type);
|
|
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
|
|
*ResultLength = 0;
|
|
|
|
}
|
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
break;
|
2007-10-23 11:08:18 +00:00
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2007-10-23 11:08:18 +00:00
|
|
|
default:
|
|
|
|
{
|
2009-07-20 18:03:16 +00:00
|
|
|
DPRINT1("Unsupported or unimplemented class: %lx\n", VirtualMemoryInformationClass);
|
2004-04-10 22:36:07 +00:00
|
|
|
Status = STATUS_INVALID_INFO_CLASS;
|
2004-12-22 05:17:44 +00:00
|
|
|
*ResultLength = 0;
|
2004-04-10 22:36:07 +00:00
|
|
|
break;
|
2007-10-23 11:08:18 +00:00
|
|
|
}
|
|
|
|
}
|
2002-08-10 16:41:20 +00:00
|
|
|
|
2007-10-23 11:08:18 +00:00
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
2008-09-24 19:13:08 +00:00
|
|
|
ObDereferenceObject(Process);
|
2004-07-10 17:01:03 +00:00
|
|
|
|
2007-10-23 11:08:18 +00:00
|
|
|
return Status;
|
2004-12-22 05:17:44 +00:00
|
|
|
}
|
|
|
|
|
2008-11-29 20:47:48 +00:00
|
|
|
NTSTATUS NTAPI
|
2005-01-12 19:04:06 +00:00
|
|
|
MiProtectVirtualMemory(IN PEPROCESS Process,
|
|
|
|
IN OUT PVOID *BaseAddress,
|
2008-09-24 15:27:54 +00:00
|
|
|
IN OUT PSIZE_T NumberOfBytesToProtect,
|
2005-01-12 19:04:06 +00:00
|
|
|
IN ULONG NewAccessProtection,
|
|
|
|
OUT PULONG OldAccessProtection OPTIONAL)
|
|
|
|
{
|
2007-10-23 11:08:18 +00:00
|
|
|
PMEMORY_AREA MemoryArea;
|
2009-04-27 10:12:57 +00:00
|
|
|
PMMSUPPORT AddressSpace;
|
2007-10-23 11:08:18 +00:00
|
|
|
ULONG OldAccessProtection_;
|
|
|
|
NTSTATUS Status;
|
2008-11-24 13:40:26 +00:00
|
|
|
|
2007-10-23 11:08:18 +00:00
|
|
|
*NumberOfBytesToProtect =
|
2008-04-24 21:26:01 +00:00
|
|
|
PAGE_ROUND_UP((ULONG_PTR)(*BaseAddress) + (*NumberOfBytesToProtect)) -
|
|
|
|
PAGE_ROUND_DOWN(*BaseAddress);
|
2007-10-23 11:08:18 +00:00
|
|
|
*BaseAddress = (PVOID)PAGE_ROUND_DOWN(*BaseAddress);
|
2008-11-24 13:40:26 +00:00
|
|
|
|
2009-04-27 10:12:57 +00:00
|
|
|
AddressSpace = &Process->Vm;
|
2008-11-24 13:40:26 +00:00
|
|
|
|
2007-10-23 11:08:18 +00:00
|
|
|
MmLockAddressSpace(AddressSpace);
|
|
|
|
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, *BaseAddress);
|
|
|
|
if (MemoryArea == NULL)
|
|
|
|
{
|
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
|
2007-10-23 11:08:18 +00:00
|
|
|
if (OldAccessProtection == NULL)
|
|
|
|
OldAccessProtection = &OldAccessProtection_;
|
2008-11-24 13:40:26 +00:00
|
|
|
|
2007-10-23 11:08:18 +00:00
|
|
|
if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY)
|
|
|
|
{
|
|
|
|
Status = MmProtectAnonMem(AddressSpace, MemoryArea, *BaseAddress,
|
|
|
|
*NumberOfBytesToProtect, NewAccessProtection,
|
|
|
|
OldAccessProtection);
|
|
|
|
}
|
|
|
|
else if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW)
|
|
|
|
{
|
|
|
|
Status = MmProtectSectionView(AddressSpace, MemoryArea, *BaseAddress,
|
|
|
|
*NumberOfBytesToProtect,
|
|
|
|
NewAccessProtection,
|
|
|
|
OldAccessProtection);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* FIXME: Should we return failure or success in this case? */
|
|
|
|
Status = STATUS_CONFLICTING_ADDRESSES;
|
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
|
2007-10-23 11:08:18 +00:00
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
2008-11-24 13:40:26 +00:00
|
|
|
|
2007-10-23 11:08:18 +00:00
|
|
|
return Status;
|
2005-01-12 19:04:06 +00:00
|
|
|
}
|
|
|
|
|
- Major rewrite of Memory Descriptor List (MDL) implementation (moving it towards using System PTEs).
- MmCreateMdl, MmSizeOfMdl: No Change.
- MmBuildMdlForNonPagedPool: Do not use MmGetPfnForProcess, just normal PMMPTE manipulation.
- This seems to cause issues in certain scenarios, because in ReactOS, nonpaged pool, a resident and guaranteed resources, does not always have its PDEs mapped!
- By calling MmGetPfnForProcess, this wound up in the annals of ReactOS mm code, which lazy-remapped the PDE. We detected this issue specifically in the cache manager, and fixed it there. It should not appear anywhere else.
- MmAllocatePagesForMdl, MmAllocatePagesForMdlEx, MmFreePagesFromMdl:
- The *Ex function is now implemented.
- Allocating pages now uses MiAllocatePagesForMdl, which is based on the older MmAllocPagesSpecifyRange.
- The code is cleaner, better commented, and better handles partial MDLs.
- Cache flags are still ignored (so the Ex functionality isn't really there).
- MmMapLockedPages, MmMapLockedPagesSpecifyCache, MmUnmapLockedPages:
- These functions now use System PTEs for the mappings, instead of the hacked-up "MDL Mapping Space".
- This frees up 256MB of Kernel Virtual Address Space.
- Takes advantage of all System PTE functionality.
- Once again, optimizations in the System PTE code will be felt here.
- For user-space mappings however, the old code is still kept and used.
- MiMapLockedPagesInUserSpace and MiUnMapLockedPagesInUserSpace are now in virtual.c and provide this.
- MmProbeAndLockPages, MmUnlockPages:
- The pages are actually probed now, in SEH. This did not seem to happen before (did someone misread the function's name?)
- Probe for write is only done for write access to user pages (as documented).
- We do not probe/check for write access for kernel requests (force Operation to be IoReadAccess).
- Proper locking is used now: Address Space lock for user mappings, PFN lock for kernel mappings.
- Faulting in pages (to make them available before locking) is now done outside the address space/PFN lock.
- You don't want to be holding a spinlock/mutex while doing disk I/O!
- For write/modify access, if the PTE is not writable, fail the request since the PTE protection overrides.
- However, if the PTE is writable but also copy on write, then we'll fault the page in for write access, which is a legitimate operation for certain user-mode scenarios.
- The old version always provided the CopyOnWrite behavior, even for non-CopyOnWrite pages!
- Reference and lock every valid page that has a PFN entry (non-I/O Pages).
- The older code did not seem to lock pages that had to be faulted in (weren't already valid).
- Cleanup the cleanup code (no pun intended). Because we now mark the pages as locked early-on, and because of changes in MmUnlockPages, we can simply use MmUnlockPages in case of error, since it will be able to fully back-out and references/locks that we did.
- Previous code attempted to do this on its own, in a pretty inconsistent manner, which would leave page leaks (both in references and lock count).
- In MmUnlockPages, not as many changes, but we now:
- Still make sure that an I/O Mapping MDL doesn't have valid PFN database pages (non-I/O).
- An MDL can cover pages that are both I/O mapped and RAM mapped, so we have to unlock/dereference the latter instead of skipping them as the old code did.
- Use the PFN lock when checking pages and unlocking/dereferencing them.
- Overall, non-complete MDLs are now marked by having a -1 PFN, and the MDL code has been updated to early-break out of page-scanning loops and/or ignore such pages, which can happen in a sparse MDL.
- Implementation has been tested on VMWare and QEMU for a variety of tasks and was found to be reliable and stable.
svn path=/trunk/; revision=41707
2009-06-30 08:29:22 +00:00
|
|
|
PVOID
|
|
|
|
NTAPI
|
|
|
|
MiMapLockedPagesInUserSpace(IN PMDL Mdl,
|
|
|
|
IN PVOID BaseVa,
|
|
|
|
IN MEMORY_CACHING_TYPE CacheType,
|
|
|
|
IN PVOID BaseAddress)
|
|
|
|
{
|
|
|
|
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))
|
|
|
|
{
|
|
|
|
if (Mdl->MdlFlags & MDL_MAPPING_CAN_FAIL)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Throw exception */
|
|
|
|
ExRaiseStatus(STATUS_ACCESS_VIOLATION);
|
|
|
|
ASSERT(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the virtual mappings for the MDL pages. */
|
|
|
|
if (Mdl->MdlFlags & MDL_IO_SPACE)
|
|
|
|
{
|
|
|
|
/* Map the pages */
|
|
|
|
Status = MmCreateVirtualMappingUnsafe(CurrentProcess,
|
|
|
|
Base,
|
|
|
|
Protect,
|
|
|
|
MdlPages,
|
|
|
|
PageCount);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Map the pages */
|
|
|
|
Status = MmCreateVirtualMapping(CurrentProcess,
|
|
|
|
Base,
|
|
|
|
Protect,
|
|
|
|
MdlPages,
|
|
|
|
PageCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if the mapping suceeded */
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2008-04-24 21:26:01 +00:00
|
|
|
/* SYSTEM CALLS ***************************************************************/
|
|
|
|
|
2008-11-29 20:47:48 +00:00
|
|
|
NTSTATUS NTAPI
|
2008-04-24 21:26:01 +00:00
|
|
|
NtQueryVirtualMemory(IN HANDLE ProcessHandle,
|
|
|
|
IN PVOID Address,
|
|
|
|
IN MEMORY_INFORMATION_CLASS VirtualMemoryInformationClass,
|
|
|
|
OUT PVOID VirtualMemoryInformation,
|
2008-09-24 15:27:54 +00:00
|
|
|
IN SIZE_T Length,
|
|
|
|
OUT PSIZE_T UnsafeResultLength)
|
1999-01-16 02:11:45 +00:00
|
|
|
{
|
2009-08-24 20:39:23 +00:00
|
|
|
NTSTATUS Status;
|
2008-09-24 15:27:54 +00:00
|
|
|
SIZE_T ResultLength = 0;
|
2007-10-23 11:08:18 +00:00
|
|
|
KPROCESSOR_MODE PreviousMode;
|
2008-10-29 19:50:55 +00:00
|
|
|
WCHAR ModuleFileNameBuffer[MAX_PATH] = {0};
|
|
|
|
UNICODE_STRING ModuleFileName;
|
|
|
|
PMEMORY_SECTION_NAME SectionName = NULL;
|
2009-06-14 08:30:22 +00:00
|
|
|
PEPROCESS Process;
|
2008-04-24 21:26:01 +00:00
|
|
|
union
|
2007-10-23 11:08:18 +00:00
|
|
|
{
|
2008-04-24 21:26:01 +00:00
|
|
|
MEMORY_BASIC_INFORMATION BasicInfo;
|
2007-10-23 11:08:18 +00:00
|
|
|
}
|
2008-04-24 21:26:01 +00:00
|
|
|
VirtualMemoryInfo;
|
2008-11-24 13:40:26 +00:00
|
|
|
|
2008-04-24 21:26:01 +00:00
|
|
|
DPRINT("NtQueryVirtualMemory(ProcessHandle %x, Address %x, "
|
|
|
|
"VirtualMemoryInformationClass %d, VirtualMemoryInformation %x, "
|
|
|
|
"Length %lu ResultLength %x)\n",ProcessHandle,Address,
|
|
|
|
VirtualMemoryInformationClass,VirtualMemoryInformation,
|
|
|
|
Length,ResultLength);
|
2008-11-24 13:40:26 +00:00
|
|
|
|
2008-04-24 21:26:01 +00:00
|
|
|
PreviousMode = ExGetPreviousMode();
|
2008-11-24 13:40:26 +00:00
|
|
|
|
2009-06-14 08:30:22 +00:00
|
|
|
if (PreviousMode != KernelMode)
|
2007-10-23 11:08:18 +00:00
|
|
|
{
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_TRY
|
2007-10-23 11:08:18 +00:00
|
|
|
{
|
2009-06-14 08:30:22 +00:00
|
|
|
ProbeForWrite(VirtualMemoryInformation,
|
|
|
|
Length,
|
|
|
|
sizeof(ULONG_PTR));
|
|
|
|
|
|
|
|
if (UnsafeResultLength) ProbeForWriteSize_t(UnsafeResultLength);
|
2007-10-23 11:08:18 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
2007-10-23 11:08:18 +00:00
|
|
|
{
|
2009-08-24 20:39:23 +00:00
|
|
|
/* Return the exception code */
|
|
|
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
2008-04-24 21:26:01 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_END;
|
2007-10-23 11:08:18 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
|
2008-04-24 21:26:01 +00:00
|
|
|
if (Address >= MmSystemRangeStart)
|
2007-10-23 11:08:18 +00:00
|
|
|
{
|
2008-04-24 21:26:01 +00:00
|
|
|
DPRINT1("Invalid parameter\n");
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
2007-10-23 11:08:18 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
|
2008-10-29 19:50:55 +00:00
|
|
|
/* FIXME: Move this inside MiQueryVirtualMemory */
|
|
|
|
if (VirtualMemoryInformationClass == MemorySectionName)
|
|
|
|
{
|
2009-06-14 08:30:22 +00:00
|
|
|
Status = ObReferenceObjectByHandle(ProcessHandle,
|
|
|
|
PROCESS_QUERY_INFORMATION,
|
|
|
|
NULL,
|
|
|
|
PreviousMode,
|
|
|
|
(PVOID*)(&Process),
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT("NtQueryVirtualMemory() = %x\n",Status);
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
|
2008-10-29 19:50:55 +00:00
|
|
|
RtlInitEmptyUnicodeString(&ModuleFileName, ModuleFileNameBuffer, sizeof(ModuleFileNameBuffer));
|
|
|
|
Status = MmGetFileNameForAddress(Address, &ModuleFileName);
|
2008-11-24 13:40:26 +00:00
|
|
|
|
2008-10-29 19:50:55 +00:00
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SectionName = VirtualMemoryInformation;
|
|
|
|
if (PreviousMode != KernelMode)
|
|
|
|
{
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_TRY
|
2008-10-29 19:50:55 +00:00
|
|
|
{
|
|
|
|
RtlInitUnicodeString(&SectionName->SectionFileName, SectionName->NameBuffer);
|
|
|
|
SectionName->SectionFileName.MaximumLength = Length;
|
|
|
|
RtlCopyUnicodeString(&SectionName->SectionFileName, &ModuleFileName);
|
2008-11-24 13:40:26 +00:00
|
|
|
|
2008-10-29 19:50:55 +00:00
|
|
|
if (UnsafeResultLength != NULL)
|
|
|
|
{
|
|
|
|
*UnsafeResultLength = ModuleFileName.Length;
|
|
|
|
}
|
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
2008-10-29 19:50:55 +00:00
|
|
|
{
|
2008-11-24 13:40:26 +00:00
|
|
|
Status = _SEH2_GetExceptionCode();
|
2008-10-29 19:50:55 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_END;
|
2008-10-29 19:50:55 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RtlInitUnicodeString(&SectionName->SectionFileName, SectionName->NameBuffer);
|
|
|
|
SectionName->SectionFileName.MaximumLength = Length;
|
|
|
|
RtlCopyUnicodeString(&SectionName->SectionFileName, &ModuleFileName);
|
2008-11-24 13:40:26 +00:00
|
|
|
|
2008-10-29 19:50:55 +00:00
|
|
|
if (UnsafeResultLength != NULL)
|
|
|
|
{
|
|
|
|
*UnsafeResultLength = ModuleFileName.Length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-06-14 08:30:22 +00:00
|
|
|
ObDereferenceObject(Process);
|
2008-10-29 19:50:55 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Status = MiQueryVirtualMemory(ProcessHandle,
|
|
|
|
Address,
|
|
|
|
VirtualMemoryInformationClass,
|
|
|
|
&VirtualMemoryInfo,
|
|
|
|
Length,
|
|
|
|
&ResultLength);
|
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
|
2008-04-24 21:26:01 +00:00
|
|
|
if (NT_SUCCESS(Status))
|
2007-10-23 11:08:18 +00:00
|
|
|
{
|
|
|
|
if (PreviousMode != KernelMode)
|
2005-07-22 20:52:31 +00:00
|
|
|
{
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_TRY
|
2005-07-22 20:52:31 +00:00
|
|
|
{
|
2008-04-24 21:26:01 +00:00
|
|
|
if (ResultLength > 0)
|
2005-10-24 17:21:23 +00:00
|
|
|
{
|
2008-04-24 21:26:01 +00:00
|
|
|
ProbeForWrite(VirtualMemoryInformation,
|
|
|
|
ResultLength,
|
|
|
|
1);
|
|
|
|
RtlCopyMemory(VirtualMemoryInformation,
|
|
|
|
&VirtualMemoryInfo,
|
|
|
|
ResultLength);
|
2005-10-24 17:21:23 +00:00
|
|
|
}
|
2008-04-24 21:26:01 +00:00
|
|
|
if (UnsafeResultLength != NULL)
|
2005-10-24 17:21:23 +00:00
|
|
|
{
|
2008-04-24 21:26:01 +00:00
|
|
|
*UnsafeResultLength = ResultLength;
|
2005-10-24 17:21:23 +00:00
|
|
|
}
|
2005-07-22 20:52:31 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
2007-10-23 11:08:18 +00:00
|
|
|
{
|
2008-11-24 13:40:26 +00:00
|
|
|
Status = _SEH2_GetExceptionCode();
|
2007-10-23 11:08:18 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_END;
|
2007-10-23 11:08:18 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-04-24 21:26:01 +00:00
|
|
|
if (ResultLength > 0)
|
|
|
|
{
|
|
|
|
RtlCopyMemory(VirtualMemoryInformation,
|
|
|
|
&VirtualMemoryInfo,
|
|
|
|
ResultLength);
|
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
|
2008-04-24 21:26:01 +00:00
|
|
|
if (UnsafeResultLength != NULL)
|
|
|
|
{
|
|
|
|
*UnsafeResultLength = ResultLength;
|
|
|
|
}
|
2007-10-23 11:08:18 +00:00
|
|
|
}
|
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
|
2008-04-24 21:26:01 +00:00
|
|
|
return(Status);
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
|
|
|
|
2000-04-02 13:32:43 +00:00
|
|
|
/* EOF */
|