2005-01-02 07:04:56 +00:00
|
|
|
/* $Id$
|
2000-04-02 13:32:43 +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
|
|
|
|
1999-01-16 02:11:45 +00:00
|
|
|
/* INCLUDE *****************************************************************/
|
|
|
|
|
2004-10-28 19:01:59 +00:00
|
|
|
#include <ntoskrnl.h>
|
1999-01-16 02:11:45 +00:00
|
|
|
|
|
|
|
#define NDEBUG
|
|
|
|
#include <internal/debug.h>
|
|
|
|
|
2000-08-18 22:27:09 +00:00
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
NTSTATUS STDCALL
|
|
|
|
NtFlushVirtualMemory(IN HANDLE ProcessHandle,
|
|
|
|
IN PVOID BaseAddress,
|
|
|
|
IN ULONG NumberOfBytesToFlush,
|
|
|
|
OUT PULONG NumberOfBytesFlushed OPTIONAL)
|
1999-01-16 02:11:45 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Flushes virtual memory to file
|
|
|
|
* ARGUMENTS:
|
2004-12-22 05:17:44 +00:00
|
|
|
* ProcessHandle = Points to the process that allocated the virtual
|
1999-01-16 02:11:45 +00:00
|
|
|
* memory
|
|
|
|
* BaseAddress = Points to the memory address
|
|
|
|
* NumberOfBytesToFlush = Limits the range to flush,
|
|
|
|
* NumberOfBytesFlushed = Actual number of bytes flushed
|
2004-12-22 05:17:44 +00:00
|
|
|
* RETURNS: Status
|
1999-01-16 02:11:45 +00:00
|
|
|
*/
|
|
|
|
{
|
2005-01-19 20:26:56 +00:00
|
|
|
/* This should be implemented once we support network filesystems */
|
|
|
|
DPRINT("NtFlushVirtualMemory is UNIMPLEMENTED\n");
|
|
|
|
return(STATUS_SUCCESS);
|
2001-03-08 22:06:02 +00:00
|
|
|
}
|
1999-01-16 02:11:45 +00:00
|
|
|
|
2004-10-28 19:01:59 +00:00
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
NTSTATUS STDCALL
|
2004-10-29 16:48:10 +00:00
|
|
|
MiLockVirtualMemory(HANDLE ProcessHandle,
|
2004-10-28 19:01:59 +00:00
|
|
|
PVOID BaseAddress,
|
|
|
|
ULONG NumberOfBytesToLock,
|
|
|
|
PULONG NumberOfBytesLocked,
|
|
|
|
PObReferenceObjectByHandle pObReferenceObjectByHandle,
|
|
|
|
PMmCreateMdl pMmCreateMdl,
|
|
|
|
PObDereferenceObject pObDereferenceObject,
|
|
|
|
PMmProbeAndLockPages pMmProbeAndLockPages,
|
|
|
|
PExFreePool pExFreePool)
|
2001-03-13 16:25:55 +00:00
|
|
|
{
|
2004-10-28 19:01:59 +00:00
|
|
|
PEPROCESS Process;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PMDL Mdl;
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2004-10-28 19:01:59 +00:00
|
|
|
Status = pObReferenceObjectByHandle(ProcessHandle,
|
|
|
|
PROCESS_VM_WRITE,
|
|
|
|
NULL,
|
|
|
|
UserMode,
|
|
|
|
(PVOID*)(&Process),
|
|
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
return(Status);
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2004-10-28 19:01:59 +00:00
|
|
|
Mdl = pMmCreateMdl(NULL,
|
|
|
|
BaseAddress,
|
|
|
|
NumberOfBytesToLock);
|
|
|
|
if (Mdl == NULL)
|
|
|
|
{
|
|
|
|
pObDereferenceObject(Process);
|
2004-06-19 08:53:35 +00:00
|
|
|
return(STATUS_NO_MEMORY);
|
2004-10-28 19:01:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pMmProbeAndLockPages(Mdl,
|
|
|
|
UserMode,
|
|
|
|
IoWriteAccess);
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2004-10-28 19:01:59 +00:00
|
|
|
pExFreePool(Mdl);
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2004-10-28 19:01:59 +00:00
|
|
|
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);
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2004-10-29 16:48:10 +00:00
|
|
|
return MiLockVirtualMemory(ProcessHandle,
|
2004-10-28 19:01:59 +00:00
|
|
|
BaseAddress,
|
|
|
|
NumberOfBytesToLock,
|
|
|
|
NumberOfBytesLocked,
|
|
|
|
ObReferenceObjectByHandle,
|
|
|
|
MmCreateMdl,
|
|
|
|
ObfDereferenceObject,
|
|
|
|
MmProbeAndLockPages,
|
|
|
|
ExFreePool);
|
2001-03-13 16:25:55 +00:00
|
|
|
}
|
|
|
|
|
2004-06-19 08:53:35 +00:00
|
|
|
|
2004-12-22 05:17:44 +00:00
|
|
|
NTSTATUS FASTCALL
|
|
|
|
MiQueryVirtualMemory (IN HANDLE ProcessHandle,
|
2004-04-10 22:36:07 +00:00
|
|
|
IN PVOID Address,
|
|
|
|
IN CINT VirtualMemoryInformationClass,
|
|
|
|
OUT PVOID VirtualMemoryInformation,
|
|
|
|
IN ULONG Length,
|
2004-12-22 05:17:44 +00:00
|
|
|
OUT PULONG ResultLength)
|
1999-01-16 02:11:45 +00:00
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
PEPROCESS Process;
|
2002-08-10 16:41:20 +00:00
|
|
|
MEMORY_AREA* MemoryArea;
|
2000-03-29 13:11:55 +00:00
|
|
|
PMADDRESS_SPACE AddressSpace;
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address < MmSystemRangeStart)
|
2004-07-10 17:01:03 +00:00
|
|
|
{
|
|
|
|
Status = ObReferenceObjectByHandle(ProcessHandle,
|
|
|
|
PROCESS_QUERY_INFORMATION,
|
|
|
|
NULL,
|
|
|
|
UserMode,
|
|
|
|
(PVOID*)(&Process),
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT("NtQueryVirtualMemory() = %x\n",Status);
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
AddressSpace = &Process->AddressSpace;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
AddressSpace = MmGetKernelAddressSpace();
|
|
|
|
}
|
2000-03-29 13:11:55 +00:00
|
|
|
MmLockAddressSpace(AddressSpace);
|
2005-01-02 19:14:52 +00:00
|
|
|
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address);
|
2002-08-10 16:41:20 +00:00
|
|
|
switch(VirtualMemoryInformationClass)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
|
|
|
case MemoryBasicInformation:
|
|
|
|
{
|
2004-12-22 05:17:44 +00:00
|
|
|
PMEMORY_BASIC_INFORMATION Info =
|
|
|
|
(PMEMORY_BASIC_INFORMATION)VirtualMemoryInformation;
|
2004-04-10 22:36:07 +00:00
|
|
|
if (Length != sizeof(MEMORY_BASIC_INFORMATION))
|
|
|
|
{
|
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
|
|
|
ObDereferenceObject(Process);
|
|
|
|
return(STATUS_INFO_LENGTH_MISMATCH);
|
|
|
|
}
|
2004-12-22 05:17:44 +00:00
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
if (MemoryArea == NULL)
|
|
|
|
{
|
2004-07-10 17:01:03 +00:00
|
|
|
Info->Type = 0;
|
2004-04-10 22:36:07 +00:00
|
|
|
Info->State = MEM_FREE;
|
2004-07-10 17:01:03 +00:00
|
|
|
Info->Protect = PAGE_NOACCESS;
|
|
|
|
Info->AllocationProtect = 0;
|
2004-04-10 22:36:07 +00:00
|
|
|
Info->BaseAddress = (PVOID)PAGE_ROUND_DOWN(Address);
|
2004-07-10 17:01:03 +00:00
|
|
|
Info->AllocationBase = NULL;
|
|
|
|
Info->RegionSize = MmFindGapAtAddress(AddressSpace, Info->BaseAddress);
|
2004-04-10 22:36:07 +00:00
|
|
|
Status = STATUS_SUCCESS;
|
2004-12-22 05:17:44 +00:00
|
|
|
*ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
|
2004-07-10 17:01:03 +00:00
|
|
|
}
|
2004-12-22 05:17:44 +00:00
|
|
|
else
|
2004-07-10 17:01:03 +00:00
|
|
|
{
|
|
|
|
switch(MemoryArea->Type)
|
|
|
|
{
|
|
|
|
case MEMORY_AREA_VIRTUAL_MEMORY:
|
2005-08-11 20:35:00 +00:00
|
|
|
case MEMORY_AREA_PEB_OR_TEB:
|
2004-07-10 17:01:03 +00:00
|
|
|
Status = MmQueryAnonMem(MemoryArea, Address, Info,
|
2004-12-22 05:17:44 +00:00
|
|
|
ResultLength);
|
2004-07-10 17:01:03 +00:00
|
|
|
break;
|
|
|
|
case MEMORY_AREA_SECTION_VIEW:
|
|
|
|
Status = MmQuerySectionView(MemoryArea, Address, Info,
|
2004-12-22 05:17:44 +00:00
|
|
|
ResultLength);
|
2004-07-10 17:01:03 +00:00
|
|
|
break;
|
|
|
|
case MEMORY_AREA_NO_ACCESS:
|
|
|
|
Info->Type = 0;
|
|
|
|
Info->State = MEM_FREE;
|
|
|
|
Info->Protect = MemoryArea->Attributes;
|
|
|
|
Info->AllocationProtect = MemoryArea->Attributes;
|
2005-01-02 17:55:06 +00:00
|
|
|
Info->BaseAddress = MemoryArea->StartingAddress;
|
|
|
|
Info->AllocationBase = MemoryArea->StartingAddress;
|
2005-05-09 01:38:29 +00:00
|
|
|
Info->RegionSize = (ULONG_PTR)MemoryArea->EndingAddress -
|
2005-01-02 17:55:06 +00:00
|
|
|
(ULONG_PTR)MemoryArea->StartingAddress;
|
2004-07-10 17:01:03 +00:00
|
|
|
Status = STATUS_SUCCESS;
|
2004-12-22 05:17:44 +00:00
|
|
|
*ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
|
2004-07-10 17:01:03 +00:00
|
|
|
break;
|
|
|
|
case MEMORY_AREA_SHARED_DATA:
|
|
|
|
Info->Type = 0;
|
|
|
|
Info->State = MEM_COMMIT;
|
|
|
|
Info->Protect = MemoryArea->Attributes;
|
|
|
|
Info->AllocationProtect = MemoryArea->Attributes;
|
2005-01-02 17:55:06 +00:00
|
|
|
Info->BaseAddress = MemoryArea->StartingAddress;
|
|
|
|
Info->AllocationBase = MemoryArea->StartingAddress;
|
2005-05-09 01:38:29 +00:00
|
|
|
Info->RegionSize = (ULONG_PTR)MemoryArea->EndingAddress -
|
2005-01-02 17:55:06 +00:00
|
|
|
(ULONG_PTR)MemoryArea->StartingAddress;
|
2004-07-10 17:01:03 +00:00
|
|
|
Status = STATUS_SUCCESS;
|
2004-12-22 05:17:44 +00:00
|
|
|
*ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
|
|
|
|
break;
|
|
|
|
case MEMORY_AREA_SYSTEM:
|
|
|
|
Info->Type = 0;
|
|
|
|
Info->State = MEM_COMMIT;
|
|
|
|
Info->Protect = MemoryArea->Attributes;
|
|
|
|
Info->AllocationProtect = MemoryArea->Attributes;
|
2005-01-02 17:55:06 +00:00
|
|
|
Info->BaseAddress = MemoryArea->StartingAddress;
|
|
|
|
Info->AllocationBase = MemoryArea->StartingAddress;
|
2005-05-09 01:38:29 +00:00
|
|
|
Info->RegionSize = (ULONG_PTR)MemoryArea->EndingAddress -
|
2005-01-02 17:55:06 +00:00
|
|
|
(ULONG_PTR)MemoryArea->StartingAddress;
|
2004-12-22 05:17:44 +00:00
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
*ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
|
|
|
|
break;
|
|
|
|
case MEMORY_AREA_KERNEL_STACK:
|
|
|
|
Info->Type = 0;
|
|
|
|
Info->State = MEM_COMMIT;
|
|
|
|
Info->Protect = MemoryArea->Attributes;
|
|
|
|
Info->AllocationProtect = MemoryArea->Attributes;
|
2005-01-02 17:55:06 +00:00
|
|
|
Info->BaseAddress = MemoryArea->StartingAddress;
|
|
|
|
Info->AllocationBase = MemoryArea->StartingAddress;
|
2005-05-09 01:38:29 +00:00
|
|
|
Info->RegionSize = (ULONG_PTR)MemoryArea->EndingAddress -
|
2005-01-02 17:55:06 +00:00
|
|
|
(ULONG_PTR)MemoryArea->StartingAddress;
|
2004-12-22 05:17:44 +00:00
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
*ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
|
2004-07-10 17:01:03 +00:00
|
|
|
break;
|
2005-08-11 20:35:00 +00:00
|
|
|
case MEMORY_AREA_PAGED_POOL:
|
|
|
|
Info->Type = 0;
|
|
|
|
Info->State = MEM_COMMIT;
|
|
|
|
Info->Protect = MemoryArea->Attributes;
|
|
|
|
Info->AllocationProtect = MemoryArea->Attributes;
|
|
|
|
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;
|
2004-07-10 17:01:03 +00:00
|
|
|
default:
|
2004-12-22 05:17:44 +00:00
|
|
|
DPRINT1("unhandled memory area type: 0x%x\n", MemoryArea->Type);
|
2004-07-10 17:01:03 +00:00
|
|
|
Status = STATUS_UNSUCCESSFUL;
|
2004-12-22 05:17:44 +00:00
|
|
|
*ResultLength = 0;
|
2004-07-10 17:01:03 +00:00
|
|
|
}
|
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
Status = STATUS_INVALID_INFO_CLASS;
|
2004-12-22 05:17:44 +00:00
|
|
|
*ResultLength = 0;
|
2004-04-10 22:36:07 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2002-08-10 16:41:20 +00:00
|
|
|
|
2000-03-29 13:11:55 +00:00
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address < MmSystemRangeStart)
|
2004-07-10 17:01:03 +00:00
|
|
|
{
|
|
|
|
ObDereferenceObject(Process);
|
|
|
|
}
|
|
|
|
|
2004-12-22 05:17:44 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* (tMk 2004.II.4)
|
|
|
|
* FUNCTION:
|
|
|
|
* Called from VirtualQueryEx (lib\kernel32\mem\virtual.c)
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
NTSTATUS STDCALL
|
|
|
|
NtQueryVirtualMemory (IN HANDLE ProcessHandle,
|
|
|
|
IN PVOID Address,
|
2005-09-05 07:51:15 +00:00
|
|
|
IN MEMORY_INFORMATION_CLASS VirtualMemoryInformationClass,
|
2004-12-22 05:17:44 +00:00
|
|
|
OUT PVOID VirtualMemoryInformation,
|
|
|
|
IN ULONG Length,
|
|
|
|
OUT PULONG UnsafeResultLength)
|
|
|
|
{
|
2005-07-22 20:52:31 +00:00
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
2004-12-22 05:17:44 +00:00
|
|
|
ULONG ResultLength = 0;
|
2005-07-22 20:52:31 +00:00
|
|
|
KPROCESSOR_MODE PreviousMode;
|
2004-12-22 05:17:44 +00:00
|
|
|
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);
|
|
|
|
|
2005-07-22 20:52:31 +00:00
|
|
|
PreviousMode = ExGetPreviousMode();
|
|
|
|
|
|
|
|
if (PreviousMode != KernelMode && UnsafeResultLength != NULL)
|
|
|
|
{
|
|
|
|
_SEH_TRY
|
|
|
|
{
|
2005-08-21 19:04:23 +00:00
|
|
|
ProbeForWriteUlong(UnsafeResultLength);
|
2005-07-22 20:52:31 +00:00
|
|
|
}
|
|
|
|
_SEH_HANDLE
|
|
|
|
{
|
|
|
|
Status = _SEH_GetExceptionCode();
|
|
|
|
}
|
|
|
|
_SEH_END;
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
2004-12-22 05:17:44 +00:00
|
|
|
|
2005-07-06 08:20:26 +00:00
|
|
|
if (Address >= MmSystemRangeStart)
|
2004-12-22 05:17:44 +00:00
|
|
|
{
|
|
|
|
DPRINT1("Invalid parameter\n");
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = MiQueryVirtualMemory ( ProcessHandle,
|
|
|
|
Address,
|
|
|
|
VirtualMemoryInformationClass,
|
|
|
|
&VirtualMemoryInfo,
|
|
|
|
Length,
|
|
|
|
&ResultLength );
|
|
|
|
|
2005-07-22 20:52:31 +00:00
|
|
|
if (NT_SUCCESS(Status))
|
2004-07-10 17:01:03 +00:00
|
|
|
{
|
2005-07-22 20:52:31 +00:00
|
|
|
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);
|
|
|
|
}
|
2004-12-22 05:17:44 +00:00
|
|
|
|
2005-07-22 20:52:31 +00:00
|
|
|
if (UnsafeResultLength != NULL)
|
|
|
|
{
|
|
|
|
*UnsafeResultLength = ResultLength;
|
|
|
|
}
|
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2005-07-22 20:52:31 +00:00
|
|
|
|
2002-08-10 16:41:20 +00:00
|
|
|
return(Status);
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
|
|
|
|
2004-06-19 08:53:35 +00:00
|
|
|
|
2005-01-12 19:04:06 +00:00
|
|
|
NTSTATUS STDCALL
|
|
|
|
MiProtectVirtualMemory(IN PEPROCESS Process,
|
|
|
|
IN OUT PVOID *BaseAddress,
|
|
|
|
IN OUT PULONG NumberOfBytesToProtect,
|
|
|
|
IN ULONG NewAccessProtection,
|
|
|
|
OUT PULONG OldAccessProtection OPTIONAL)
|
|
|
|
{
|
|
|
|
PMEMORY_AREA MemoryArea;
|
|
|
|
PMADDRESS_SPACE AddressSpace;
|
|
|
|
ULONG OldAccessProtection_;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
*NumberOfBytesToProtect =
|
|
|
|
PAGE_ROUND_UP((*BaseAddress) + (*NumberOfBytesToProtect)) -
|
|
|
|
PAGE_ROUND_DOWN(*BaseAddress);
|
|
|
|
*BaseAddress = (PVOID)PAGE_ROUND_DOWN(*BaseAddress);
|
|
|
|
|
|
|
|
AddressSpace = &Process->AddressSpace;
|
|
|
|
|
|
|
|
MmLockAddressSpace(AddressSpace);
|
|
|
|
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, *BaseAddress);
|
|
|
|
if (MemoryArea == NULL)
|
|
|
|
{
|
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (OldAccessProtection == NULL)
|
|
|
|
OldAccessProtection = &OldAccessProtection_;
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2005-01-13 20:30:59 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* FIXME: Should we return failure or success in this case? */
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
}
|
2005-01-12 19:04:06 +00:00
|
|
|
|
|
|
|
MmUnlockAddressSpace(AddressSpace);
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-06-19 08:53:35 +00:00
|
|
|
/* (tMk 2004.II.5)
|
2004-12-22 05:17:44 +00:00
|
|
|
* FUNCTION:
|
2004-06-19 08:53:35 +00:00
|
|
|
* Called from VirtualProtectEx (lib\kernel32\mem\virtual.c)
|
|
|
|
*
|
|
|
|
*/
|
2001-08-07 14:13:45 +00:00
|
|
|
NTSTATUS STDCALL
|
2004-04-10 22:36:07 +00:00
|
|
|
NtProtectVirtualMemory(IN HANDLE ProcessHandle,
|
2005-01-12 19:04:06 +00:00
|
|
|
IN OUT PVOID *UnsafeBaseAddress,
|
|
|
|
IN OUT ULONG *UnsafeNumberOfBytesToProtect,
|
2004-04-10 22:36:07 +00:00
|
|
|
IN ULONG NewAccessProtection,
|
|
|
|
OUT PULONG UnsafeOldAccessProtection)
|
1999-01-16 02:11:45 +00:00
|
|
|
{
|
|
|
|
PEPROCESS Process;
|
2002-08-10 16:41:20 +00:00
|
|
|
ULONG OldAccessProtection;
|
2005-07-22 20:52:31 +00:00
|
|
|
PVOID BaseAddress = NULL;
|
|
|
|
ULONG NumberOfBytesToProtect = 0;
|
|
|
|
KPROCESSOR_MODE PreviousMode;
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
PreviousMode = ExGetPreviousMode();
|
|
|
|
|
|
|
|
if (PreviousMode != KernelMode)
|
|
|
|
{
|
|
|
|
_SEH_TRY
|
|
|
|
{
|
2005-08-21 19:04:23 +00:00
|
|
|
ProbeForWritePointer(UnsafeBaseAddress);
|
|
|
|
ProbeForWriteUlong(UnsafeNumberOfBytesToProtect);
|
|
|
|
ProbeForWriteUlong(UnsafeOldAccessProtection);
|
2005-07-22 20:52:31 +00:00
|
|
|
|
|
|
|
BaseAddress = *UnsafeBaseAddress;
|
|
|
|
NumberOfBytesToProtect = *UnsafeNumberOfBytesToProtect;
|
|
|
|
}
|
|
|
|
_SEH_HANDLE
|
|
|
|
{
|
|
|
|
Status = _SEH_GetExceptionCode();
|
|
|
|
}
|
|
|
|
_SEH_END;
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BaseAddress = *UnsafeBaseAddress;
|
|
|
|
NumberOfBytesToProtect = *UnsafeNumberOfBytesToProtect;
|
|
|
|
}
|
2002-08-10 16:41:20 +00:00
|
|
|
|
2005-01-12 19:04:06 +00:00
|
|
|
/* (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'
|
|
|
|
*/
|
2004-12-22 05:17:44 +00:00
|
|
|
if(UnsafeOldAccessProtection == NULL)
|
2004-06-19 08:53:35 +00:00
|
|
|
{
|
|
|
|
return(STATUS_INVALID_PARAMETER);
|
|
|
|
}
|
2004-12-22 05:17:44 +00:00
|
|
|
|
1999-01-16 02:11:45 +00:00
|
|
|
Status = ObReferenceObjectByHandle(ProcessHandle,
|
2004-04-10 22:36:07 +00:00
|
|
|
PROCESS_VM_OPERATION,
|
|
|
|
PsProcessType,
|
|
|
|
UserMode,
|
|
|
|
(PVOID*)(&Process),
|
|
|
|
NULL);
|
2004-06-13 10:35:53 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
|
|
|
DPRINT("NtProtectVirtualMemory() = %x\n",Status);
|
|
|
|
return(Status);
|
|
|
|
}
|
1999-01-16 02:11:45 +00:00
|
|
|
|
2005-01-12 19:04:06 +00:00
|
|
|
Status = MiProtectVirtualMemory(Process,
|
|
|
|
&BaseAddress,
|
|
|
|
&NumberOfBytesToProtect,
|
|
|
|
NewAccessProtection,
|
|
|
|
&OldAccessProtection);
|
2004-04-10 22:36:07 +00:00
|
|
|
|
1999-04-01 12:39:43 +00:00
|
|
|
ObDereferenceObject(Process);
|
1999-10-07 23:46:27 +00:00
|
|
|
|
2005-07-22 20:52:31 +00:00
|
|
|
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;
|
|
|
|
}
|
1999-10-07 23:46:27 +00:00
|
|
|
|
2002-08-10 16:41:20 +00:00
|
|
|
return(Status);
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
|
|
|
|
2004-06-19 08:53:35 +00:00
|
|
|
|
|
|
|
/* (tMk 2004.II.05)
|
2004-12-22 05:17:44 +00:00
|
|
|
* FUNCTION:
|
2004-06-19 08:53:35 +00:00
|
|
|
* 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.
|
|
|
|
*/
|
2004-04-10 22:36:07 +00:00
|
|
|
NTSTATUS STDCALL
|
|
|
|
NtReadVirtualMemory(IN HANDLE ProcessHandle,
|
|
|
|
IN PVOID BaseAddress,
|
|
|
|
OUT PVOID Buffer,
|
|
|
|
IN ULONG NumberOfBytesToRead,
|
2004-05-29 11:53:43 +00:00
|
|
|
OUT PULONG NumberOfBytesRead OPTIONAL)
|
1999-03-30 12:55:31 +00:00
|
|
|
{
|
2004-04-10 22:36:07 +00:00
|
|
|
PMDL Mdl;
|
|
|
|
PVOID SystemAddress;
|
2005-03-14 15:22:46 +00:00
|
|
|
KPROCESSOR_MODE PreviousMode;
|
2004-08-31 20:17:18 +00:00
|
|
|
PEPROCESS Process, CurrentProcess;
|
2005-03-14 15:22:46 +00:00
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-14 15:22:46 +00:00
|
|
|
PAGED_CODE();
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-14 15:22:46 +00:00
|
|
|
PreviousMode = ExGetPreviousMode();
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-14 15:22:46 +00:00
|
|
|
if(PreviousMode != KernelMode)
|
|
|
|
{
|
|
|
|
_SEH_TRY
|
|
|
|
{
|
|
|
|
ProbeForWrite(Buffer,
|
|
|
|
NumberOfBytesToRead,
|
|
|
|
1);
|
|
|
|
if(NumberOfBytesRead != NULL)
|
|
|
|
{
|
2005-08-21 19:04:23 +00:00
|
|
|
ProbeForWriteUlong(NumberOfBytesRead);
|
2005-03-14 15:22:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
_SEH_HANDLE
|
|
|
|
{
|
|
|
|
Status = _SEH_GetExceptionCode();
|
|
|
|
}
|
|
|
|
_SEH_END;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-14 15:22:46 +00:00
|
|
|
if(!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
|
|
|
|
DPRINT("NtReadVirtualMemory(ProcessHandle %x, BaseAddress %x, "
|
|
|
|
"Buffer %x, NumberOfBytesToRead %d)\n",ProcessHandle,BaseAddress,
|
|
|
|
Buffer,NumberOfBytesToRead);
|
|
|
|
|
|
|
|
Status = ObReferenceObjectByHandle(ProcessHandle,
|
2005-04-26 09:40:30 +00:00
|
|
|
PROCESS_VM_READ,
|
2004-04-10 22:36:07 +00:00
|
|
|
NULL,
|
2005-03-14 15:22:46 +00:00
|
|
|
PreviousMode,
|
2004-04-10 22:36:07 +00:00
|
|
|
(PVOID*)(&Process),
|
|
|
|
NULL);
|
2004-06-19 08:53:35 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2002-08-10 16:41:20 +00:00
|
|
|
return(Status);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
|
2004-08-31 20:17:18 +00:00
|
|
|
CurrentProcess = PsGetCurrentProcess();
|
|
|
|
|
|
|
|
if (Process == CurrentProcess)
|
2004-06-19 08:53:35 +00:00
|
|
|
{
|
2005-03-14 15:22:46 +00:00
|
|
|
_SEH_TRY
|
|
|
|
{
|
|
|
|
RtlCopyMemory(Buffer, BaseAddress, NumberOfBytesToRead);
|
|
|
|
}
|
|
|
|
_SEH_HANDLE
|
|
|
|
{
|
|
|
|
Status = _SEH_GetExceptionCode();
|
|
|
|
}
|
|
|
|
_SEH_END;
|
2004-06-19 08:53:35 +00:00
|
|
|
}
|
2004-08-31 20:17:18 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
Mdl = MmCreateMdl(NULL,
|
|
|
|
Buffer,
|
|
|
|
NumberOfBytesToRead);
|
2004-12-22 05:17:44 +00:00
|
|
|
if(Mdl == NULL)
|
2004-08-31 20:17:18 +00:00
|
|
|
{
|
|
|
|
ObDereferenceObject(Process);
|
|
|
|
return(STATUS_NO_MEMORY);
|
|
|
|
}
|
2005-03-14 15:22:46 +00:00
|
|
|
_SEH_TRY
|
|
|
|
{
|
|
|
|
MmProbeAndLockPages(Mdl,
|
|
|
|
PreviousMode,
|
|
|
|
IoWriteAccess);
|
|
|
|
}
|
|
|
|
_SEH_HANDLE
|
|
|
|
{
|
|
|
|
Status = _SEH_GetExceptionCode();
|
|
|
|
}
|
|
|
|
_SEH_END;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2005-03-14 15:22:46 +00:00
|
|
|
if(NT_SUCCESS(Status))
|
2004-08-31 20:17:18 +00:00
|
|
|
{
|
2005-03-14 15:22:46 +00:00
|
|
|
KeAttachProcess(&Process->Pcb);
|
|
|
|
|
|
|
|
SystemAddress = MmGetSystemAddressForMdl(Mdl);
|
|
|
|
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
_SEH_TRY {
|
|
|
|
ProbeForRead(BaseAddress, NumberOfBytesToRead, 1);
|
|
|
|
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);
|
2004-08-31 20:17:18 +00:00
|
|
|
}
|
|
|
|
ExFreePool(Mdl);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ObDereferenceObject(Process);
|
|
|
|
|
2005-03-14 15:22:46 +00:00
|
|
|
if((NT_SUCCESS(Status) || Status == STATUS_PARTIAL_COPY) &&
|
|
|
|
NumberOfBytesRead != NULL)
|
|
|
|
{
|
|
|
|
_SEH_TRY
|
|
|
|
{
|
|
|
|
*NumberOfBytesRead = NumberOfBytesToRead;
|
|
|
|
}
|
|
|
|
_SEH_HANDLE
|
|
|
|
{
|
|
|
|
Status = _SEH_GetExceptionCode();
|
|
|
|
}
|
|
|
|
_SEH_END;
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2004-12-30 18:30:44 +00:00
|
|
|
return(Status);
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
|
|
|
|
2004-06-19 08:53:35 +00:00
|
|
|
/* (tMk 2004.II.05)
|
|
|
|
* FUNCTION: THIS function doesn't make a sense...
|
|
|
|
* Called from VirtualUnlock (lib\kernel32\mem\virtual.c)
|
|
|
|
*/
|
2004-04-10 22:36:07 +00:00
|
|
|
NTSTATUS STDCALL
|
|
|
|
NtUnlockVirtualMemory(HANDLE ProcessHandle,
|
|
|
|
PVOID BaseAddress,
|
|
|
|
ULONG NumberOfBytesToUnlock,
|
|
|
|
PULONG NumberOfBytesUnlocked OPTIONAL)
|
1999-01-16 02:11:45 +00:00
|
|
|
{
|
2004-04-10 22:36:07 +00:00
|
|
|
// 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);
|
2004-06-19 08:53:35 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2003-08-20 10:37:33 +00:00
|
|
|
return(Status);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Mdl = MmCreateMdl(NULL,
|
|
|
|
BaseAddress,
|
|
|
|
NumberOfBytesToUnlock);
|
2004-12-22 05:17:44 +00:00
|
|
|
if(Mdl == NULL)
|
2004-06-19 08:53:35 +00:00
|
|
|
{
|
|
|
|
ObDereferenceObject(Process);
|
|
|
|
return(STATUS_NO_MEMORY);
|
|
|
|
}
|
2003-08-20 10:37:33 +00:00
|
|
|
|
|
|
|
ObDereferenceObject(Process);
|
|
|
|
|
|
|
|
if (Mdl->MappedSystemVa != NULL)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
|
|
|
MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
|
|
|
|
}
|
2003-08-20 10:37:33 +00:00
|
|
|
MmUnlockPages(Mdl);
|
|
|
|
ExFreePool(Mdl);
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2003-08-20 10:37:33 +00:00
|
|
|
*NumberOfBytesUnlocked = NumberOfBytesToUnlock;
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2003-08-20 10:37:33 +00:00
|
|
|
return(STATUS_SUCCESS);
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-06-19 08:53:35 +00:00
|
|
|
/* (tMk 2004.II.05)
|
|
|
|
* FUNCTION:
|
|
|
|
* Called from WriteProcessMemory (lib\kernel32\mem\procmem.c) and KlInitPeb(lib\kernel32\process\create.c)
|
2004-12-22 05:17:44 +00:00
|
|
|
*
|
2004-06-19 08:53:35 +00:00
|
|
|
* NOTE: This function will be correct if MmProbeAndLockPages() would be fully IMPLEMENTED.
|
|
|
|
*/
|
2004-04-10 22:36:07 +00:00
|
|
|
NTSTATUS STDCALL
|
|
|
|
NtWriteVirtualMemory(IN HANDLE ProcessHandle,
|
|
|
|
IN PVOID BaseAddress,
|
|
|
|
IN PVOID Buffer,
|
|
|
|
IN ULONG NumberOfBytesToWrite,
|
2005-01-12 19:04:06 +00:00
|
|
|
OUT PULONG NumberOfBytesWritten OPTIONAL)
|
1999-01-16 02:11:45 +00:00
|
|
|
{
|
1999-03-30 12:55:31 +00:00
|
|
|
PMDL Mdl;
|
|
|
|
PVOID SystemAddress;
|
|
|
|
PEPROCESS Process;
|
2005-01-12 19:04:06 +00:00
|
|
|
ULONG OldProtection = 0;
|
|
|
|
PVOID ProtectBaseAddress;
|
|
|
|
ULONG ProtectNumberOfBytes;
|
2005-07-22 20:52:31 +00:00
|
|
|
KPROCESSOR_MODE PreviousMode;
|
|
|
|
NTSTATUS CopyStatus, Status = STATUS_SUCCESS;
|
2004-04-10 22:36:07 +00:00
|
|
|
|
1999-06-18 22:11:21 +00:00
|
|
|
DPRINT("NtWriteVirtualMemory(ProcessHandle %x, BaseAddress %x, "
|
2004-04-10 22:36:07 +00:00
|
|
|
"Buffer %x, NumberOfBytesToWrite %d)\n",ProcessHandle,BaseAddress,
|
|
|
|
Buffer,NumberOfBytesToWrite);
|
|
|
|
|
2005-07-22 20:52:31 +00:00
|
|
|
PreviousMode = ExGetPreviousMode();
|
|
|
|
|
|
|
|
if (PreviousMode != KernelMode && NumberOfBytesWritten != NULL)
|
|
|
|
{
|
|
|
|
_SEH_TRY
|
|
|
|
{
|
2005-08-21 19:04:23 +00:00
|
|
|
ProbeForWriteUlong(NumberOfBytesWritten);
|
2005-07-22 20:52:31 +00:00
|
|
|
}
|
|
|
|
_SEH_HANDLE
|
|
|
|
{
|
|
|
|
Status = _SEH_GetExceptionCode();
|
|
|
|
}
|
|
|
|
_SEH_END;
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-01-16 02:11:45 +00:00
|
|
|
Status = ObReferenceObjectByHandle(ProcessHandle,
|
2004-04-10 22:36:07 +00:00
|
|
|
PROCESS_VM_WRITE,
|
|
|
|
NULL,
|
|
|
|
UserMode,
|
|
|
|
(PVOID*)(&Process),
|
|
|
|
NULL);
|
2004-06-19 08:53:35 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
|
2005-01-12 19:04:06 +00:00
|
|
|
/* We have to make sure the target memory is writable.
|
|
|
|
*
|
|
|
|
* I am not sure if it is correct to do this in any case, but it has to be
|
|
|
|
* done at least in some cases because you can use WriteProcessMemory to
|
|
|
|
* write into the .text section of a module where memcpy() would crash.
|
|
|
|
* -blight (2005/01/09)
|
|
|
|
*/
|
|
|
|
ProtectBaseAddress = BaseAddress;
|
|
|
|
ProtectNumberOfBytes = NumberOfBytesToWrite;
|
2005-07-22 20:52:31 +00:00
|
|
|
|
|
|
|
CopyStatus = STATUS_SUCCESS;
|
2005-01-12 19:04:06 +00:00
|
|
|
|
|
|
|
/* Write memory */
|
2004-08-31 20:17:18 +00:00
|
|
|
if (Process == PsGetCurrentProcess())
|
2004-06-19 08:53:35 +00:00
|
|
|
{
|
2005-01-12 19:04:06 +00:00
|
|
|
Status = MiProtectVirtualMemory(Process,
|
|
|
|
&ProtectBaseAddress,
|
|
|
|
&ProtectNumberOfBytes,
|
|
|
|
PAGE_READWRITE,
|
|
|
|
&OldProtection);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
ObDereferenceObject(Process);
|
|
|
|
return Status;
|
|
|
|
}
|
2005-07-22 20:52:31 +00:00
|
|
|
|
|
|
|
if (PreviousMode != KernelMode)
|
|
|
|
{
|
|
|
|
_SEH_TRY
|
|
|
|
{
|
|
|
|
memcpy(BaseAddress, Buffer, NumberOfBytesToWrite);
|
|
|
|
}
|
|
|
|
_SEH_HANDLE
|
|
|
|
{
|
|
|
|
CopyStatus = _SEH_GetExceptionCode();
|
|
|
|
}
|
|
|
|
_SEH_END;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memcpy(BaseAddress, Buffer, NumberOfBytesToWrite);
|
|
|
|
}
|
2004-06-19 08:53:35 +00:00
|
|
|
}
|
2004-08-31 20:17:18 +00:00
|
|
|
else
|
|
|
|
{
|
2005-01-12 19:04:06 +00:00
|
|
|
/* Create MDL describing the source buffer. */
|
2004-08-31 20:17:18 +00:00
|
|
|
Mdl = MmCreateMdl(NULL,
|
|
|
|
Buffer,
|
|
|
|
NumberOfBytesToWrite);
|
|
|
|
if(Mdl == NULL)
|
|
|
|
{
|
|
|
|
ObDereferenceObject(Process);
|
|
|
|
return(STATUS_NO_MEMORY);
|
|
|
|
}
|
2005-01-12 19:04:06 +00:00
|
|
|
|
|
|
|
/* Make the target area writable. */
|
|
|
|
Status = MiProtectVirtualMemory(Process,
|
|
|
|
&ProtectBaseAddress,
|
|
|
|
&ProtectNumberOfBytes,
|
|
|
|
PAGE_READWRITE,
|
|
|
|
&OldProtection);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
ObDereferenceObject(Process);
|
|
|
|
ExFreePool(Mdl);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Map the MDL. */
|
|
|
|
MmProbeAndLockPages(Mdl,
|
|
|
|
UserMode,
|
|
|
|
IoReadAccess);
|
|
|
|
|
|
|
|
/* Copy memory from the mapped MDL into the target buffer. */
|
2004-11-13 22:27:16 +00:00
|
|
|
KeAttachProcess(&Process->Pcb);
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2004-08-31 20:17:18 +00:00
|
|
|
SystemAddress = MmGetSystemAddressForMdl(Mdl);
|
2005-07-22 20:52:31 +00:00
|
|
|
if (PreviousMode != KernelMode)
|
|
|
|
{
|
|
|
|
_SEH_TRY
|
|
|
|
{
|
|
|
|
memcpy(BaseAddress, SystemAddress, NumberOfBytesToWrite);
|
|
|
|
}
|
|
|
|
_SEH_HANDLE
|
|
|
|
{
|
|
|
|
CopyStatus = _SEH_GetExceptionCode();
|
|
|
|
}
|
|
|
|
_SEH_END;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memcpy(BaseAddress, SystemAddress, NumberOfBytesToWrite);
|
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2004-08-31 20:17:18 +00:00
|
|
|
KeDetachProcess();
|
2001-03-16 16:05:34 +00:00
|
|
|
|
2005-01-12 19:04:06 +00:00
|
|
|
/* Free the MDL. */
|
2004-08-31 20:17:18 +00:00
|
|
|
if (Mdl->MappedSystemVa != NULL)
|
|
|
|
{
|
|
|
|
MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
|
|
|
|
}
|
|
|
|
MmUnlockPages(Mdl);
|
|
|
|
ExFreePool(Mdl);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2004-08-31 20:17:18 +00:00
|
|
|
|
2005-01-12 19:04:06 +00:00
|
|
|
/* Reset the protection of the target memory. */
|
|
|
|
Status = MiProtectVirtualMemory(Process,
|
|
|
|
&ProtectBaseAddress,
|
|
|
|
&ProtectNumberOfBytes,
|
|
|
|
OldProtection,
|
|
|
|
&OldProtection);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to reset protection of the target memory! (Status 0x%x)\n", Status);
|
|
|
|
/* FIXME: Should we bugcheck here? */
|
|
|
|
}
|
|
|
|
|
2004-08-31 20:17:18 +00:00
|
|
|
ObDereferenceObject(Process);
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2005-01-12 19:04:06 +00:00
|
|
|
if (NumberOfBytesWritten != NULL)
|
2005-07-22 20:52:31 +00:00
|
|
|
{
|
|
|
|
if (PreviousMode != KernelMode)
|
|
|
|
{
|
|
|
|
_SEH_TRY
|
|
|
|
{
|
|
|
|
*NumberOfBytesWritten = NumberOfBytesToWrite;
|
|
|
|
}
|
|
|
|
_SEH_HANDLE
|
|
|
|
{
|
|
|
|
Status = _SEH_GetExceptionCode();
|
|
|
|
}
|
|
|
|
_SEH_END;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*NumberOfBytesWritten = NumberOfBytesToWrite;
|
|
|
|
}
|
|
|
|
}
|
2004-04-10 22:36:07 +00:00
|
|
|
|
2005-07-22 20:52:31 +00:00
|
|
|
return(NT_SUCCESS(CopyStatus) ? Status : CopyStatus);
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
|
|
|
|
2004-07-17 03:03:52 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
|
|
|
|
|
|
|
PVOID
|
|
|
|
STDCALL
|
|
|
|
MmGetVirtualForPhysical (
|
|
|
|
IN PHYSICAL_ADDRESS PhysicalAddress
|
|
|
|
)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-06-19 08:53:35 +00:00
|
|
|
/* FUNCTION:
|
|
|
|
* Called from EngSecureMem (subsys\win32k\eng\mem.c)
|
2003-07-10 21:05:04 +00:00
|
|
|
* @unimplemented
|
|
|
|
*/
|
2003-06-19 17:13:28 +00:00
|
|
|
PVOID STDCALL
|
|
|
|
MmSecureVirtualMemory (PVOID Address,
|
|
|
|
SIZE_T Length,
|
|
|
|
ULONG Mode)
|
2000-04-02 13:32:43 +00:00
|
|
|
{
|
2004-04-10 22:36:07 +00:00
|
|
|
/* Only works for user space */
|
|
|
|
if (MmHighestUserAddress < Address)
|
|
|
|
{
|
2003-06-19 17:13:28 +00:00
|
|
|
return NULL;
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2003-06-19 17:13:28 +00:00
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
UNIMPLEMENTED;
|
2003-06-19 17:13:28 +00:00
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
return 0;
|
2000-04-02 13:32:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-06-19 08:53:35 +00:00
|
|
|
/* FUNCTION:
|
|
|
|
* Called from EngUnsecureMem (subsys\win32k\eng\mem.c)
|
2003-07-10 21:05:04 +00:00
|
|
|
* @unimplemented
|
|
|
|
*/
|
2002-06-11 22:09:03 +00:00
|
|
|
VOID STDCALL
|
2003-06-19 17:13:28 +00:00
|
|
|
MmUnsecureVirtualMemory(PVOID SecureMem)
|
2000-04-02 13:32:43 +00:00
|
|
|
{
|
2004-04-10 22:36:07 +00:00
|
|
|
if (NULL == SecureMem)
|
|
|
|
{
|
2003-06-19 17:13:28 +00:00
|
|
|
return;
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2003-06-19 17:13:28 +00:00
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
UNIMPLEMENTED;
|
2000-04-02 13:32:43 +00:00
|
|
|
}
|
|
|
|
|
2003-08-14 10:41:36 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
VOID STDCALL
|
2005-01-02 07:04:56 +00:00
|
|
|
ProbeForRead (IN CONST VOID *Address,
|
2004-04-10 22:36:07 +00:00
|
|
|
IN ULONG Length,
|
|
|
|
IN ULONG Alignment)
|
2003-08-14 10:41:36 +00:00
|
|
|
{
|
2005-01-20 21:03:35 +00:00
|
|
|
ASSERT(Alignment == 1 || Alignment == 2 || Alignment == 4 || Alignment == 8);
|
2003-08-14 10:41:36 +00:00
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
if (Length == 0)
|
|
|
|
return;
|
2003-08-14 10:41:36 +00:00
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
if (((ULONG_PTR)Address & (Alignment - 1)) != 0)
|
|
|
|
{
|
2003-08-14 10:41:36 +00:00
|
|
|
ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2005-01-20 21:03:35 +00:00
|
|
|
else if ((ULONG_PTR)Address + Length - 1 < (ULONG_PTR)Address ||
|
2005-08-11 20:35:00 +00:00
|
|
|
(ULONG_PTR)Address + Length - 1 >= (ULONG_PTR)MmUserProbeAddress)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2003-08-14 10:41:36 +00:00
|
|
|
ExRaiseStatus (STATUS_ACCESS_VIOLATION);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2003-08-14 10:41:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
VOID STDCALL
|
2005-01-02 07:04:56 +00:00
|
|
|
ProbeForWrite (IN CONST VOID *Address,
|
2004-04-10 22:36:07 +00:00
|
|
|
IN ULONG Length,
|
|
|
|
IN ULONG Alignment)
|
2003-08-14 10:41:36 +00:00
|
|
|
{
|
2005-01-20 21:03:35 +00:00
|
|
|
volatile CHAR *Current;
|
|
|
|
PCHAR Last;
|
2003-08-14 10:41:36 +00:00
|
|
|
|
2005-01-20 21:03:35 +00:00
|
|
|
ASSERT(Alignment == 1 || Alignment == 2 || Alignment == 4 || Alignment == 8);
|
2003-08-14 10:41:36 +00:00
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
if (Length == 0)
|
|
|
|
return;
|
2003-08-14 10:41:36 +00:00
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
if (((ULONG_PTR)Address & (Alignment - 1)) != 0)
|
|
|
|
{
|
2003-08-14 10:41:36 +00:00
|
|
|
ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2005-01-20 21:03:35 +00:00
|
|
|
|
|
|
|
Last = (PCHAR)((ULONG_PTR)Address + Length - 1);
|
|
|
|
if ((ULONG_PTR)Last < (ULONG_PTR)Address ||
|
2005-08-11 20:35:00 +00:00
|
|
|
(ULONG_PTR)Last >= (ULONG_PTR)MmUserProbeAddress)
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2003-08-14 10:41:36 +00:00
|
|
|
ExRaiseStatus (STATUS_ACCESS_VIOLATION);
|
2004-04-10 22:36:07 +00:00
|
|
|
}
|
2003-08-14 10:41:36 +00:00
|
|
|
|
2004-04-10 22:36:07 +00:00
|
|
|
/* Check for accessible pages */
|
2005-01-20 21:03:35 +00:00
|
|
|
Current = (CHAR*)Address;
|
|
|
|
do
|
2004-04-10 22:36:07 +00:00
|
|
|
{
|
2005-01-20 21:03:35 +00:00
|
|
|
*Current = *Current;
|
|
|
|
Current = (CHAR*)((ULONG_PTR)Current + PAGE_SIZE);
|
|
|
|
} while (Current <= Last);
|
2003-08-14 10:41:36 +00:00
|
|
|
}
|
|
|
|
|
2000-04-02 13:32:43 +00:00
|
|
|
/* EOF */
|