-/*
- * ReactOS kernel
- * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+/* $Id$
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/* $Id: virtual.c,v 1.86 2004/12/22 05:17:44 royce Exp $
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/mm/virtual.c
+ * PURPOSE: Implementing operations on virtual memory.
*
- * PROJECT: ReactOS kernel
- * FILE: ntoskrnl/mm/virtual.c
- * PURPOSE: Implementing operations on virtual memory.
- * PROGRAMMER: David Welch
+ * PROGRAMMERS: David Welch
*/
/* INCLUDE *****************************************************************/
* RETURNS: Status
*/
{
- UNIMPLEMENTED;
- return(STATUS_NOT_IMPLEMENTED);
+ /* This should be implemented once we support network filesystems */
+ DPRINT("NtFlushVirtualMemory is UNIMPLEMENTED\n");
+ return(STATUS_SUCCESS);
}
MEMORY_AREA* MemoryArea;
PMADDRESS_SPACE AddressSpace;
- if (Address < (PVOID)KERNEL_BASE)
+ if (Address < MmSystemRangeStart)
{
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION,
AddressSpace = MmGetKernelAddressSpace();
}
MmLockAddressSpace(AddressSpace);
- MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
- Address);
+ MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address);
switch(VirtualMemoryInformationClass)
{
case MemoryBasicInformation:
switch(MemoryArea->Type)
{
case MEMORY_AREA_VIRTUAL_MEMORY:
+ case MEMORY_AREA_PEB_OR_TEB:
Status = MmQueryAnonMem(MemoryArea, Address, Info,
ResultLength);
break;
ResultLength);
break;
case MEMORY_AREA_NO_ACCESS:
- Info->Type = 0;
- Info->State = MEM_FREE;
+ Info->Type = MEM_PRIVATE;
+ Info->State = MEM_RESERVE;
Info->Protect = MemoryArea->Attributes;
Info->AllocationProtect = MemoryArea->Attributes;
- Info->BaseAddress = MemoryArea->BaseAddress;
- Info->AllocationBase = MemoryArea->BaseAddress;
- Info->RegionSize = MemoryArea->Length;
+ 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 = 0;
+ Info->Type = MEM_PRIVATE;
Info->State = MEM_COMMIT;
Info->Protect = MemoryArea->Attributes;
Info->AllocationProtect = MemoryArea->Attributes;
- Info->BaseAddress = MemoryArea->BaseAddress;
- Info->AllocationBase = MemoryArea->BaseAddress;
- Info->RegionSize = MemoryArea->Length;
+ 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:
- {
- static int warned = 0;
- if ( !warned )
- {
- DPRINT1("FIXME: MEMORY_AREA_SYSTEM case incomplete (or possibly wrong) for NtQueryVirtualMemory()\n");
- warned = 1;
- }
- }
- /* FIXME - don't have a clue if this is right, but it's better than nothing */
Info->Type = 0;
Info->State = MEM_COMMIT;
Info->Protect = MemoryArea->Attributes;
Info->AllocationProtect = MemoryArea->Attributes;
- Info->BaseAddress = MemoryArea->BaseAddress;
- Info->AllocationBase = MemoryArea->BaseAddress;
- Info->RegionSize = MemoryArea->Length;
+ 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:
- {
- static int warned = 0;
- if ( !warned )
- {
- DPRINT1("FIXME: MEMORY_AREA_KERNEL_STACK case incomplete (or possibly wrong) for NtQueryVirtualMemory()\n");
- warned = 1;
- }
- }
- /* FIXME - don't have a clue if this is right, but it's better than nothing */
Info->Type = 0;
Info->State = MEM_COMMIT;
Info->Protect = MemoryArea->Attributes;
Info->AllocationProtect = MemoryArea->Attributes;
- Info->BaseAddress = MemoryArea->BaseAddress;
- Info->AllocationBase = MemoryArea->BaseAddress;
- Info->RegionSize = MemoryArea->Length;
+ 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->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;
}
MmUnlockAddressSpace(AddressSpace);
- if (Address < (PVOID)KERNEL_BASE)
+ if (Address < MmSystemRangeStart)
{
ObDereferenceObject(Process);
}
NTSTATUS STDCALL
NtQueryVirtualMemory (IN HANDLE ProcessHandle,
IN PVOID Address,
- IN CINT VirtualMemoryInformationClass,
+ IN MEMORY_INFORMATION_CLASS VirtualMemoryInformationClass,
OUT PVOID VirtualMemoryInformation,
IN ULONG Length,
OUT PULONG UnsafeResultLength)
{
- NTSTATUS Status;
+ NTSTATUS Status = STATUS_SUCCESS;
ULONG ResultLength = 0;
- KPROCESSOR_MODE PrevMode;
+ KPROCESSOR_MODE PreviousMode;
union
{
MEMORY_BASIC_INFORMATION BasicInfo;
VirtualMemoryInformationClass,VirtualMemoryInformation,
Length,ResultLength);
- PrevMode = ExGetPreviousMode();
+ 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 (PrevMode == UserMode && Address >= (PVOID)KERNEL_BASE)
+ if (Address >= MmSystemRangeStart)
{
DPRINT1("Invalid parameter\n");
return STATUS_INVALID_PARAMETER;
Length,
&ResultLength );
- if (NT_SUCCESS(Status) && ResultLength > 0)
+ if (NT_SUCCESS(Status))
{
- Status = MmCopyToCaller(VirtualMemoryInformation, &VirtualMemoryInfo, ResultLength);
- if (!NT_SUCCESS(Status))
- {
- ResultLength = 0;
- }
+ 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
+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 (UnsafeResultLength != NULL)
+ if (OldAccessProtection == NULL)
+ OldAccessProtection = &OldAccessProtection_;
+
+ if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY)
{
- MmCopyToCaller(UnsafeResultLength, &ResultLength, sizeof(ULONG));
+ Status = MmProtectAnonMem(AddressSpace, MemoryArea, *BaseAddress,
+ *NumberOfBytesToProtect, NewAccessProtection,
+ OldAccessProtection);
}
- return(Status);
+ 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;
+ }
+
+ MmUnlockAddressSpace(AddressSpace);
+
+ return Status;
}
*/
NTSTATUS STDCALL
NtProtectVirtualMemory(IN HANDLE ProcessHandle,
- IN PVOID *UnsafeBaseAddress,
- IN ULONG *UnsafeNumberOfBytesToProtect,
+ IN OUT PVOID *UnsafeBaseAddress,
+ IN OUT ULONG *UnsafeNumberOfBytesToProtect,
IN ULONG NewAccessProtection,
OUT PULONG UnsafeOldAccessProtection)
{
- PMEMORY_AREA MemoryArea;
PEPROCESS Process;
- NTSTATUS Status;
- PMADDRESS_SPACE AddressSpace;
ULONG OldAccessProtection;
- PVOID BaseAddress;
- ULONG NumberOfBytesToProtect;
-
- Status = MmCopyFromCaller(&BaseAddress, UnsafeBaseAddress, sizeof(PVOID));
- if (!NT_SUCCESS(Status))
- return Status;
- Status = MmCopyFromCaller(&NumberOfBytesToProtect, UnsafeNumberOfBytesToProtect, sizeof(ULONG));
- if (!NT_SUCCESS(Status))
- return Status;
+ PVOID BaseAddress = NULL;
+ ULONG NumberOfBytesToProtect = 0;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PreviousMode = ExGetPreviousMode();
+
+ if (PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWritePointer(UnsafeBaseAddress);
+ ProbeForWriteUlong(UnsafeNumberOfBytesToProtect);
+ ProbeForWriteUlong(UnsafeOldAccessProtection);
- // (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'
+ BaseAddress = *UnsafeBaseAddress;
+ NumberOfBytesToProtect = *UnsafeNumberOfBytesToProtect;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+ else
+ {
+ BaseAddress = *UnsafeBaseAddress;
+ NumberOfBytesToProtect = *UnsafeNumberOfBytesToProtect;
+ }
+
+ 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)
{
return(STATUS_INVALID_PARAMETER);
}
- NumberOfBytesToProtect =
- PAGE_ROUND_UP(BaseAddress + NumberOfBytesToProtect) -
- PAGE_ROUND_DOWN(BaseAddress);
- BaseAddress = (PVOID)PAGE_ROUND_DOWN(BaseAddress);
-
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_VM_OPERATION,
PsProcessType,
return(Status);
}
- AddressSpace = &Process->AddressSpace;
+ Status = MiProtectVirtualMemory(Process,
+ &BaseAddress,
+ &NumberOfBytesToProtect,
+ NewAccessProtection,
+ &OldAccessProtection);
- MmLockAddressSpace(AddressSpace);
- MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
- BaseAddress);
- if (MemoryArea == NULL)
- {
- MmUnlockAddressSpace(AddressSpace);
- ObDereferenceObject(Process);
- return(STATUS_UNSUCCESSFUL);
- }
-
- 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);
- }
-
- MmUnlockAddressSpace(AddressSpace);
ObDereferenceObject(Process);
- MmCopyToCaller(UnsafeOldAccessProtection, &OldAccessProtection, sizeof(ULONG));
- MmCopyToCaller(UnsafeBaseAddress, &BaseAddress, sizeof(PVOID));
- MmCopyToCaller(UnsafeNumberOfBytesToProtect, &NumberOfBytesToProtect, sizeof(ULONG));
+ 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;
+ }
return(Status);
}
IN ULONG NumberOfBytesToRead,
OUT PULONG NumberOfBytesRead OPTIONAL)
{
- NTSTATUS Status;
PMDL Mdl;
PVOID SystemAddress;
+ 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)
+ {
+ /* Don't allow to read from kernel space */
+ return STATUS_ACCESS_VIOLATION;
+ }
+
+ PreviousMode = ExGetPreviousMode();
+
+ if (PreviousMode != KernelMode)
+ {
+ if ((ULONG_PTR)Buffer + NumberOfBytesToRead - 1 < (ULONG_PTR)Buffer ||
+ (ULONG_PTR)Buffer + NumberOfBytesToRead - 1 >= MmUserProbeAddress)
+ {
+ /* Don't allow to write into kernel space */
+ return STATUS_ACCESS_VIOLATION;
+ }
+ }
+
Status = ObReferenceObjectByHandle(ProcessHandle,
- PROCESS_VM_WRITE,
+ PROCESS_VM_READ,
NULL,
- UserMode,
+ PreviousMode,
(PVOID*)(&Process),
NULL);
if (!NT_SUCCESS(Status))
CurrentProcess = PsGetCurrentProcess();
+ if(PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ if(NumberOfBytesRead != NULL)
+ {
+ ProbeForWriteUlong(NumberOfBytesRead);
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+
+
if (Process == CurrentProcess)
{
- memcpy(Buffer, BaseAddress, NumberOfBytesToRead);
+ _SEH_TRY
+ {
+ RtlCopyMemory(Buffer, BaseAddress, NumberOfBytesToRead);
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
}
else
{
ObDereferenceObject(Process);
return(STATUS_NO_MEMORY);
}
- MmProbeAndLockPages(Mdl,
- UserMode,
- IoWriteAccess);
-
- KeAttachProcess(&Process->Pcb);
-
- SystemAddress = MmGetSystemAddressForMdl(Mdl);
- memcpy(SystemAddress, BaseAddress, NumberOfBytesToRead);
-
- KeDetachProcess();
+ _SEH_TRY
+ {
+ MmProbeAndLockPages(Mdl,
+ PreviousMode,
+ IoWriteAccess);
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
- if (Mdl->MappedSystemVa != NULL)
+ if(NT_SUCCESS(Status))
{
- MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
+ 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);
}
- MmUnlockPages(Mdl);
ExFreePool(Mdl);
}
ObDereferenceObject(Process);
- if (NumberOfBytesRead)
- *NumberOfBytesRead = NumberOfBytesToRead;
- return(STATUS_SUCCESS);
+ if((NT_SUCCESS(Status) || Status == STATUS_PARTIAL_COPY) &&
+ NumberOfBytesRead != NULL)
+ {
+ _SEH_TRY
+ {
+ *NumberOfBytesRead = NumberOfBytesToRead;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
+
+ return(Status);
}
/* (tMk 2004.II.05)
IN PVOID BaseAddress,
IN PVOID Buffer,
IN ULONG NumberOfBytesToWrite,
- OUT PULONG NumberOfBytesWritten)
+ OUT PULONG NumberOfBytesWritten OPTIONAL)
{
- NTSTATUS Status;
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
+ {
+ ProbeForWriteUlong(NumberOfBytesWritten);
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+ }
+
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_VM_WRITE,
NULL,
return(Status);
}
+ CopyStatus = STATUS_SUCCESS;
+
+ /* Write memory */
if (Process == PsGetCurrentProcess())
{
- memcpy(BaseAddress, Buffer, NumberOfBytesToWrite);
+ 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);
- MmProbeAndLockPages(Mdl,
- UserMode,
- IoReadAccess);
if(Mdl == NULL)
- {
- ObDereferenceObject(Process);
- return(STATUS_NO_MEMORY);
- }
- KeAttachProcess(&Process->Pcb);
-
- SystemAddress = MmGetSystemAddressForMdl(Mdl);
- memcpy(BaseAddress, SystemAddress, NumberOfBytesToWrite);
+ {
+ 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)
+ {
+ _SEH_TRY
+ {
+ memcpy(BaseAddress, SystemAddress, NumberOfBytesToWrite);
+ }
+ _SEH_HANDLE
+ {
+ CopyStatus = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
+ else
+ {
+ memcpy(BaseAddress, SystemAddress, NumberOfBytesToWrite);
+ }
- KeDetachProcess();
+ KeDetachProcess();
+ }
+ /* Free the MDL. */
if (Mdl->MappedSystemVa != NULL)
{
MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
MmUnlockPages(Mdl);
ExFreePool(Mdl);
}
-
ObDereferenceObject(Process);
- *NumberOfBytesWritten = NumberOfBytesToWrite;
+ if (NT_SUCCESS(CopyStatus) && NumberOfBytesWritten != NULL)
+ {
+ if (PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ *NumberOfBytesWritten = NumberOfBytesToWrite;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
+ else
+ {
+ *NumberOfBytesWritten = NumberOfBytesToWrite;
+ }
+ }
- return(STATUS_SUCCESS);
+ return(NT_SUCCESS(CopyStatus) ? Status : CopyStatus);
}
/*
* @implemented
*/
VOID STDCALL
-ProbeForRead (IN PVOID Address,
+ProbeForRead (IN CONST VOID *Address,
IN ULONG Length,
IN ULONG Alignment)
{
- ASSERT(Alignment ==1 || Alignment == 2 || Alignment == 4 || Alignment == 8);
+ ASSERT(Alignment == 1 || Alignment == 2 || Alignment == 4 || Alignment == 8);
if (Length == 0)
return;
{
ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
}
- else if ((ULONG_PTR)Address + Length < (ULONG_PTR)Address ||
- (ULONG_PTR)Address + Length > (ULONG_PTR)MmUserProbeAddress)
+ 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,
+ProbeForWrite (IN CONST VOID *Address,
IN ULONG Length,
IN ULONG Alignment)
{
- PULONG Ptr;
- ULONG x;
- ULONG i;
+ volatile CHAR *Current;
+ PCHAR Last;
- ASSERT(Alignment ==1 || Alignment == 2 || Alignment == 4 || Alignment == 8);
+ ASSERT(Alignment == 1 || Alignment == 2 || Alignment == 4 || Alignment == 8);
if (Length == 0)
return;
{
ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
}
- else if ((ULONG_PTR)Address + Length < (ULONG_PTR)Address ||
- (ULONG_PTR)Address + Length > (ULONG_PTR)MmUserProbeAddress)
+
+ Last = (CHAR*)((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 */
- for (i = 0; i < Length; i += PAGE_SIZE)
+ Current = (CHAR*)Address;
+ *Current = *Current;
+ Current = (PCHAR)((ULONG_PTR)PAGE_ROUND_DOWN(Current) + PAGE_SIZE);
+ while (Current <= Last)
{
- Ptr = (PULONG)(((ULONG_PTR)Address & ~(PAGE_SIZE - 1)) + i);
- x = *Ptr;
- *Ptr = x;
- }
+ *Current = *Current;
+ Current = (CHAR*)((ULONG_PTR)Current + PAGE_SIZE);
+ }
}
/* EOF */