3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/mm/virtual.c
6 * PURPOSE: Implementing operations on virtual memory.
8 * PROGRAMMERS: David Welch
11 /* INCLUDE *****************************************************************/
16 #include <internal/debug.h>
18 /* FUNCTIONS *****************************************************************/
21 NtFlushVirtualMemory(IN HANDLE ProcessHandle
,
22 IN OUT PVOID
*BaseAddress
,
23 IN OUT PSIZE_T NumberOfBytesToFlush
,
24 OUT PIO_STATUS_BLOCK IoStatusBlock
)
26 * FUNCTION: Flushes virtual memory to file
28 * ProcessHandle = Points to the process that allocated the virtual
30 * BaseAddress = Points to the memory address
31 * NumberOfBytesToFlush = Limits the range to flush,
32 * NumberOfBytesFlushed = Actual number of bytes flushed
36 /* This should be implemented once we support network filesystems */
37 DPRINT("NtFlushVirtualMemory is UNIMPLEMENTED\n");
38 return(STATUS_SUCCESS
);
43 MiLockVirtualMemory(HANDLE ProcessHandle
,
45 ULONG NumberOfBytesToLock
,
46 PULONG NumberOfBytesLocked
,
47 PObReferenceObjectByHandle pObReferenceObjectByHandle
,
48 PMmCreateMdl pMmCreateMdl
,
49 PObDereferenceObject pObDereferenceObject
,
50 PMmProbeAndLockPages pMmProbeAndLockPages
,
51 PExFreePool pExFreePool
)
57 Status
= pObReferenceObjectByHandle(ProcessHandle
,
63 if (!NT_SUCCESS(Status
))
66 Mdl
= pMmCreateMdl(NULL
,
71 pObDereferenceObject(Process
);
72 return(STATUS_NO_MEMORY
);
75 pMmProbeAndLockPages(Mdl
,
81 pObDereferenceObject(Process
);
83 *NumberOfBytesLocked
= NumberOfBytesToLock
;
84 return(STATUS_SUCCESS
);
89 NtLockVirtualMemory(HANDLE ProcessHandle
,
91 ULONG NumberOfBytesToLock
,
92 PULONG NumberOfBytesLocked
)
94 DPRINT("NtLockVirtualMemory(ProcessHandle %x, BaseAddress %x, "
95 "NumberOfBytesToLock %d, NumberOfBytesLocked %x)\n",
101 return MiLockVirtualMemory(ProcessHandle
,
105 ObReferenceObjectByHandle
,
107 (PVOID
)ObfDereferenceObject
,
114 MiQueryVirtualMemory(IN HANDLE ProcessHandle
,
116 IN MEMORY_INFORMATION_CLASS VirtualMemoryInformationClass
,
117 OUT PVOID VirtualMemoryInformation
,
119 OUT PULONG ResultLength
)
123 MEMORY_AREA
* MemoryArea
;
124 PMADDRESS_SPACE AddressSpace
;
126 if (Address
< MmSystemRangeStart
)
128 Status
= ObReferenceObjectByHandle(ProcessHandle
,
129 PROCESS_QUERY_INFORMATION
,
135 if (!NT_SUCCESS(Status
))
137 DPRINT("NtQueryVirtualMemory() = %x\n",Status
);
140 AddressSpace
= (PMADDRESS_SPACE
)&Process
->VadRoot
;
144 AddressSpace
= MmGetKernelAddressSpace();
146 MmLockAddressSpace(AddressSpace
);
147 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, Address
);
148 switch(VirtualMemoryInformationClass
)
150 case MemoryBasicInformation
:
152 PMEMORY_BASIC_INFORMATION Info
=
153 (PMEMORY_BASIC_INFORMATION
)VirtualMemoryInformation
;
154 if (Length
!= sizeof(MEMORY_BASIC_INFORMATION
))
156 MmUnlockAddressSpace(AddressSpace
);
157 ObDereferenceObject(Process
);
158 return(STATUS_INFO_LENGTH_MISMATCH
);
161 if (MemoryArea
== NULL
)
164 Info
->State
= MEM_FREE
;
165 Info
->Protect
= PAGE_NOACCESS
;
166 Info
->AllocationProtect
= 0;
167 Info
->BaseAddress
= (PVOID
)PAGE_ROUND_DOWN(Address
);
168 Info
->AllocationBase
= NULL
;
169 Info
->RegionSize
= MmFindGapAtAddress(AddressSpace
, Info
->BaseAddress
);
170 Status
= STATUS_SUCCESS
;
171 *ResultLength
= sizeof(MEMORY_BASIC_INFORMATION
);
175 switch(MemoryArea
->Type
)
177 case MEMORY_AREA_VIRTUAL_MEMORY
:
178 case MEMORY_AREA_PEB_OR_TEB
:
179 Status
= MmQueryAnonMem(MemoryArea
, Address
, Info
,
183 case MEMORY_AREA_SECTION_VIEW
:
184 Status
= MmQuerySectionView(MemoryArea
, Address
, Info
,
188 case MEMORY_AREA_NO_ACCESS
:
189 Info
->Type
= MEM_PRIVATE
;
190 Info
->State
= MEM_RESERVE
;
191 Info
->Protect
= MemoryArea
->Protect
;
192 Info
->AllocationProtect
= MemoryArea
->Protect
;
193 Info
->BaseAddress
= MemoryArea
->StartingAddress
;
194 Info
->AllocationBase
= MemoryArea
->StartingAddress
;
195 Info
->RegionSize
= (ULONG_PTR
)MemoryArea
->EndingAddress
-
196 (ULONG_PTR
)MemoryArea
->StartingAddress
;
197 Status
= STATUS_SUCCESS
;
198 *ResultLength
= sizeof(MEMORY_BASIC_INFORMATION
);
201 case MEMORY_AREA_SHARED_DATA
:
202 Info
->Type
= MEM_PRIVATE
;
203 Info
->State
= MEM_COMMIT
;
204 Info
->Protect
= MemoryArea
->Protect
;
205 Info
->AllocationProtect
= MemoryArea
->Protect
;
206 Info
->BaseAddress
= MemoryArea
->StartingAddress
;
207 Info
->AllocationBase
= MemoryArea
->StartingAddress
;
208 Info
->RegionSize
= (ULONG_PTR
)MemoryArea
->EndingAddress
-
209 (ULONG_PTR
)MemoryArea
->StartingAddress
;
210 Status
= STATUS_SUCCESS
;
211 *ResultLength
= sizeof(MEMORY_BASIC_INFORMATION
);
214 case MEMORY_AREA_SYSTEM
:
216 Info
->State
= MEM_COMMIT
;
217 Info
->Protect
= MemoryArea
->Protect
;
218 Info
->AllocationProtect
= MemoryArea
->Protect
;
219 Info
->BaseAddress
= MemoryArea
->StartingAddress
;
220 Info
->AllocationBase
= MemoryArea
->StartingAddress
;
221 Info
->RegionSize
= (ULONG_PTR
)MemoryArea
->EndingAddress
-
222 (ULONG_PTR
)MemoryArea
->StartingAddress
;
223 Status
= STATUS_SUCCESS
;
224 *ResultLength
= sizeof(MEMORY_BASIC_INFORMATION
);
227 case MEMORY_AREA_KERNEL_STACK
:
229 Info
->State
= MEM_COMMIT
;
230 Info
->Protect
= MemoryArea
->Protect
;
231 Info
->AllocationProtect
= MemoryArea
->Protect
;
232 Info
->BaseAddress
= MemoryArea
->StartingAddress
;
233 Info
->AllocationBase
= MemoryArea
->StartingAddress
;
234 Info
->RegionSize
= (ULONG_PTR
)MemoryArea
->EndingAddress
-
235 (ULONG_PTR
)MemoryArea
->StartingAddress
;
236 Status
= STATUS_SUCCESS
;
237 *ResultLength
= sizeof(MEMORY_BASIC_INFORMATION
);
240 case MEMORY_AREA_PAGED_POOL
:
242 Info
->State
= MEM_COMMIT
;
243 Info
->Protect
= MemoryArea
->Protect
;
244 Info
->AllocationProtect
= MemoryArea
->Protect
;
245 Info
->BaseAddress
= MemoryArea
->StartingAddress
;
246 Info
->AllocationBase
= MemoryArea
->StartingAddress
;
247 Info
->RegionSize
= (ULONG_PTR
)MemoryArea
->EndingAddress
-
248 (ULONG_PTR
)MemoryArea
->StartingAddress
;
249 Status
= STATUS_SUCCESS
;
250 *ResultLength
= sizeof(MEMORY_BASIC_INFORMATION
);
254 DPRINT1("unhandled memory area type: 0x%x\n", MemoryArea
->Type
);
255 Status
= STATUS_UNSUCCESSFUL
;
264 Status
= STATUS_INVALID_INFO_CLASS
;
270 MmUnlockAddressSpace(AddressSpace
);
271 if (Address
< MmSystemRangeStart
)
274 ObDereferenceObject(Process
);
282 * Called from VirtualQueryEx (lib\kernel32\mem\virtual.c)
286 NtQueryVirtualMemory(IN HANDLE ProcessHandle
,
288 IN MEMORY_INFORMATION_CLASS VirtualMemoryInformationClass
,
289 OUT PVOID VirtualMemoryInformation
,
291 OUT PULONG UnsafeResultLength
)
293 NTSTATUS Status
= STATUS_SUCCESS
;
294 ULONG ResultLength
= 0;
295 KPROCESSOR_MODE PreviousMode
;
298 MEMORY_BASIC_INFORMATION BasicInfo
;
302 DPRINT("NtQueryVirtualMemory(ProcessHandle %x, Address %x, "
303 "VirtualMemoryInformationClass %d, VirtualMemoryInformation %x, "
304 "Length %lu ResultLength %x)\n",ProcessHandle
,Address
,
305 VirtualMemoryInformationClass
,VirtualMemoryInformation
,
306 Length
,ResultLength
);
308 PreviousMode
= ExGetPreviousMode();
310 if (PreviousMode
!= KernelMode
&& UnsafeResultLength
!= NULL
)
314 ProbeForWriteUlong(UnsafeResultLength
);
318 Status
= _SEH_GetExceptionCode();
322 if (!NT_SUCCESS(Status
))
328 if (Address
>= MmSystemRangeStart
)
330 DPRINT1("Invalid parameter\n");
331 return STATUS_INVALID_PARAMETER
;
334 Status
= MiQueryVirtualMemory(ProcessHandle
,
336 VirtualMemoryInformationClass
,
341 if (NT_SUCCESS(Status
))
343 if (PreviousMode
!= KernelMode
)
347 if (ResultLength
> 0)
349 ProbeForWrite(VirtualMemoryInformation
,
352 RtlCopyMemory(VirtualMemoryInformation
,
356 if (UnsafeResultLength
!= NULL
)
358 *UnsafeResultLength
= ResultLength
;
363 Status
= _SEH_GetExceptionCode();
369 if (ResultLength
> 0)
371 RtlCopyMemory(VirtualMemoryInformation
,
376 if (UnsafeResultLength
!= NULL
)
378 *UnsafeResultLength
= ResultLength
;
388 MiProtectVirtualMemory(IN PEPROCESS Process
,
389 IN OUT PVOID
*BaseAddress
,
390 IN OUT PULONG NumberOfBytesToProtect
,
391 IN ULONG NewAccessProtection
,
392 OUT PULONG OldAccessProtection OPTIONAL
)
394 PMEMORY_AREA MemoryArea
;
395 PMADDRESS_SPACE AddressSpace
;
396 ULONG OldAccessProtection_
;
399 *NumberOfBytesToProtect
=
400 PAGE_ROUND_UP((ULONG_PTR
)(*BaseAddress
) + (*NumberOfBytesToProtect
)) -
401 PAGE_ROUND_DOWN(*BaseAddress
);
402 *BaseAddress
= (PVOID
)PAGE_ROUND_DOWN(*BaseAddress
);
404 AddressSpace
= (PMADDRESS_SPACE
)&(Process
)->VadRoot
;
406 MmLockAddressSpace(AddressSpace
);
407 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, *BaseAddress
);
408 if (MemoryArea
== NULL
)
410 MmUnlockAddressSpace(AddressSpace
);
411 return STATUS_UNSUCCESSFUL
;
414 if (OldAccessProtection
== NULL
)
415 OldAccessProtection
= &OldAccessProtection_
;
417 if (MemoryArea
->Type
== MEMORY_AREA_VIRTUAL_MEMORY
)
419 Status
= MmProtectAnonMem(AddressSpace
, MemoryArea
, *BaseAddress
,
420 *NumberOfBytesToProtect
, NewAccessProtection
,
421 OldAccessProtection
);
423 else if (MemoryArea
->Type
== MEMORY_AREA_SECTION_VIEW
)
425 Status
= MmProtectSectionView(AddressSpace
, MemoryArea
, *BaseAddress
,
426 *NumberOfBytesToProtect
,
428 OldAccessProtection
);
432 /* FIXME: Should we return failure or success in this case? */
433 Status
= STATUS_CONFLICTING_ADDRESSES
;
436 MmUnlockAddressSpace(AddressSpace
);
444 * Called from VirtualProtectEx (lib\kernel32\mem\virtual.c)
448 NtProtectVirtualMemory(IN HANDLE ProcessHandle
,
449 IN OUT PVOID
*UnsafeBaseAddress
,
450 IN OUT ULONG
*UnsafeNumberOfBytesToProtect
,
451 IN ULONG NewAccessProtection
,
452 OUT PULONG UnsafeOldAccessProtection
)
455 ULONG OldAccessProtection
;
456 PVOID BaseAddress
= NULL
;
457 ULONG NumberOfBytesToProtect
= 0;
458 KPROCESSOR_MODE PreviousMode
;
459 NTSTATUS Status
= STATUS_SUCCESS
;
461 PreviousMode
= ExGetPreviousMode();
463 if (PreviousMode
!= KernelMode
)
467 ProbeForWritePointer(UnsafeBaseAddress
);
468 ProbeForWriteUlong(UnsafeNumberOfBytesToProtect
);
469 ProbeForWriteUlong(UnsafeOldAccessProtection
);
471 BaseAddress
= *UnsafeBaseAddress
;
472 NumberOfBytesToProtect
= *UnsafeNumberOfBytesToProtect
;
476 Status
= _SEH_GetExceptionCode();
480 if (!NT_SUCCESS(Status
))
487 BaseAddress
= *UnsafeBaseAddress
;
488 NumberOfBytesToProtect
= *UnsafeNumberOfBytesToProtect
;
491 if ((ULONG_PTR
)BaseAddress
+ NumberOfBytesToProtect
- 1 < (ULONG_PTR
)BaseAddress
||
492 (ULONG_PTR
)BaseAddress
+ NumberOfBytesToProtect
- 1 >= MmUserProbeAddress
)
494 /* Don't allow to change the protection of a kernel mode address */
495 return STATUS_INVALID_PARAMETER_2
;
498 /* (tMk 2004.II.5) in Microsoft SDK I read:
499 * 'if this parameter is NULL or does not point to a valid variable, the function fails'
501 if(UnsafeOldAccessProtection
== NULL
)
503 return(STATUS_INVALID_PARAMETER
);
506 Status
= ObReferenceObjectByHandle(ProcessHandle
,
507 PROCESS_VM_OPERATION
,
512 if (!NT_SUCCESS(Status
))
514 DPRINT("NtProtectVirtualMemory() = %x\n",Status
);
518 Status
= MiProtectVirtualMemory(Process
,
520 &NumberOfBytesToProtect
,
522 &OldAccessProtection
);
524 ObDereferenceObject(Process
);
526 if (PreviousMode
!= KernelMode
)
530 *UnsafeOldAccessProtection
= OldAccessProtection
;
531 *UnsafeBaseAddress
= BaseAddress
;
532 *UnsafeNumberOfBytesToProtect
= NumberOfBytesToProtect
;
536 Status
= _SEH_GetExceptionCode();
542 *UnsafeOldAccessProtection
= OldAccessProtection
;
543 *UnsafeBaseAddress
= BaseAddress
;
544 *UnsafeNumberOfBytesToProtect
= NumberOfBytesToProtect
;
553 * Called from ReadProcessMemory (lib\kernel32\mem\procmem.c) and KlInitPeb(lib\kernel32\process\create.c)
555 * NOTE: This function will be correct if MmProbeAndLockPages() would be fully IMPLEMENTED.
558 NtReadVirtualMemory(IN HANDLE ProcessHandle
,
559 IN PVOID BaseAddress
,
561 IN ULONG NumberOfBytesToRead
,
562 OUT PULONG NumberOfBytesRead OPTIONAL
)
566 KPROCESSOR_MODE PreviousMode
;
567 PEPROCESS Process
, CurrentProcess
;
568 NTSTATUS Status
= STATUS_SUCCESS
;
572 DPRINT("NtReadVirtualMemory(ProcessHandle %x, BaseAddress %x, "
573 "Buffer %x, NumberOfBytesToRead %d)\n",ProcessHandle
,BaseAddress
,
574 Buffer
,NumberOfBytesToRead
);
576 if ((ULONG_PTR
)BaseAddress
+ NumberOfBytesToRead
- 1 < (ULONG_PTR
)BaseAddress
||
577 (ULONG_PTR
)BaseAddress
+ NumberOfBytesToRead
- 1 >= MmUserProbeAddress
)
579 /* Don't allow to read from kernel space */
580 return STATUS_ACCESS_VIOLATION
;
583 PreviousMode
= ExGetPreviousMode();
585 if (PreviousMode
!= KernelMode
)
587 if ((ULONG_PTR
)Buffer
+ NumberOfBytesToRead
- 1 < (ULONG_PTR
)Buffer
||
588 (ULONG_PTR
)Buffer
+ NumberOfBytesToRead
- 1 >= MmUserProbeAddress
)
590 /* Don't allow to write into kernel space */
591 return STATUS_ACCESS_VIOLATION
;
595 Status
= ObReferenceObjectByHandle(ProcessHandle
,
601 if (!NT_SUCCESS(Status
))
606 CurrentProcess
= PsGetCurrentProcess();
608 if(PreviousMode
!= KernelMode
)
612 if(NumberOfBytesRead
!= NULL
)
614 ProbeForWriteUlong(NumberOfBytesRead
);
619 Status
= _SEH_GetExceptionCode();
623 if(!NT_SUCCESS(Status
))
630 if (Process
== CurrentProcess
)
634 RtlCopyMemory(Buffer
, BaseAddress
, NumberOfBytesToRead
);
638 Status
= _SEH_GetExceptionCode();
644 Mdl
= MmCreateMdl(NULL
,
646 NumberOfBytesToRead
);
649 ObDereferenceObject(Process
);
650 return(STATUS_NO_MEMORY
);
655 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
659 Status
= _SEH_GetExceptionCode();
663 if(NT_SUCCESS(Status
))
665 KeAttachProcess(&Process
->Pcb
);
667 SystemAddress
= MmGetSystemAddressForMdl(Mdl
);
669 Status
= STATUS_SUCCESS
;
672 Status
= STATUS_PARTIAL_COPY
;
673 RtlCopyMemory(SystemAddress
, BaseAddress
, NumberOfBytesToRead
);
674 Status
= STATUS_SUCCESS
;
678 if(Status
!= STATUS_PARTIAL_COPY
)
679 Status
= _SEH_GetExceptionCode();
685 if (Mdl
->MappedSystemVa
!= NULL
)
687 MmUnmapLockedPages(Mdl
->MappedSystemVa
, Mdl
);
694 ObDereferenceObject(Process
);
696 if ((NT_SUCCESS(Status
) || Status
== STATUS_PARTIAL_COPY
) &&
697 NumberOfBytesRead
!= NULL
)
701 *NumberOfBytesRead
= NumberOfBytesToRead
;
705 Status
= _SEH_GetExceptionCode();
714 * FUNCTION: THIS function doesn't make a sense...
715 * Called from VirtualUnlock (lib\kernel32\mem\virtual.c)
718 NtUnlockVirtualMemory(HANDLE ProcessHandle
,
720 ULONG NumberOfBytesToUnlock
,
721 PULONG NumberOfBytesUnlocked OPTIONAL
)
723 // AG [08-20-03] : I have *no* idea if this is correct, I just used the
724 // other functions as a template and made a few intelligent guesses...
730 DPRINT("NtUnlockVirtualMemory(ProcessHandle %x, BaseAddress %x, "
731 "NumberOfBytesToUnlock %d), NumberOfBytesUnlocked %x\n",ProcessHandle
,BaseAddress
,
732 NumberOfBytesToUnlock
, NumberOfBytesUnlocked
);
734 Status
= ObReferenceObjectByHandle(ProcessHandle
,
740 if (!NT_SUCCESS(Status
))
745 Mdl
= MmCreateMdl(NULL
,
747 NumberOfBytesToUnlock
);
750 ObDereferenceObject(Process
);
751 return(STATUS_NO_MEMORY
);
754 ObDereferenceObject(Process
);
756 if (Mdl
->MappedSystemVa
!= NULL
)
758 MmUnmapLockedPages(Mdl
->MappedSystemVa
, Mdl
);
763 *NumberOfBytesUnlocked
= NumberOfBytesToUnlock
;
765 return(STATUS_SUCCESS
);
771 * Called from WriteProcessMemory (lib\kernel32\mem\procmem.c) and KlInitPeb(lib\kernel32\process\create.c)
773 * NOTE: This function will be correct if MmProbeAndLockPages() would be fully IMPLEMENTED.
776 NtWriteVirtualMemory(IN HANDLE ProcessHandle
,
777 IN PVOID BaseAddress
,
779 IN ULONG NumberOfBytesToWrite
,
780 OUT PULONG NumberOfBytesWritten OPTIONAL
)
785 KPROCESSOR_MODE PreviousMode
;
786 NTSTATUS CopyStatus
, Status
= STATUS_SUCCESS
;
788 DPRINT("NtWriteVirtualMemory(ProcessHandle %x, BaseAddress %x, "
789 "Buffer %x, NumberOfBytesToWrite %d)\n",ProcessHandle
,BaseAddress
,
790 Buffer
,NumberOfBytesToWrite
);
792 if ((ULONG_PTR
)BaseAddress
+ NumberOfBytesToWrite
- 1 < (ULONG_PTR
)BaseAddress
||
793 (ULONG_PTR
)BaseAddress
+ NumberOfBytesToWrite
- 1 >= MmUserProbeAddress
)
795 /* Don't allow to write into kernel space */
796 return STATUS_ACCESS_VIOLATION
;
799 PreviousMode
= ExGetPreviousMode();
801 if (PreviousMode
!= KernelMode
)
803 if ((ULONG_PTR
)Buffer
+ NumberOfBytesToWrite
- 1 < (ULONG_PTR
)Buffer
||
804 (ULONG_PTR
)Buffer
+ NumberOfBytesToWrite
- 1 >= MmUserProbeAddress
)
806 /* Don't allow to read from kernel space */
807 return STATUS_ACCESS_VIOLATION
;
809 if (NumberOfBytesWritten
!= NULL
)
813 ProbeForWriteUlong(NumberOfBytesWritten
);
817 Status
= _SEH_GetExceptionCode();
821 if (!NT_SUCCESS(Status
))
828 Status
= ObReferenceObjectByHandle(ProcessHandle
,
834 if (!NT_SUCCESS(Status
))
839 CopyStatus
= STATUS_SUCCESS
;
842 if (Process
== PsGetCurrentProcess())
844 if (PreviousMode
!= KernelMode
)
848 memcpy(BaseAddress
, Buffer
, NumberOfBytesToWrite
);
852 CopyStatus
= _SEH_GetExceptionCode();
858 memcpy(BaseAddress
, Buffer
, NumberOfBytesToWrite
);
863 /* Create MDL describing the source buffer. */
864 Mdl
= MmCreateMdl(NULL
,
866 NumberOfBytesToWrite
);
869 ObDereferenceObject(Process
);
870 return(STATUS_NO_MEMORY
);
875 MmProbeAndLockPages(Mdl
, UserMode
, IoReadAccess
);
879 CopyStatus
= _SEH_GetExceptionCode();
883 if (NT_SUCCESS(CopyStatus
))
885 /* Copy memory from the mapped MDL into the target buffer. */
886 KeAttachProcess(&Process
->Pcb
);
888 SystemAddress
= MmGetSystemAddressForMdl(Mdl
);
889 if (PreviousMode
!= KernelMode
)
893 memcpy(BaseAddress
, SystemAddress
, NumberOfBytesToWrite
);
897 CopyStatus
= _SEH_GetExceptionCode();
903 memcpy(BaseAddress
, SystemAddress
, NumberOfBytesToWrite
);
910 if (Mdl
->MappedSystemVa
!= NULL
)
912 MmUnmapLockedPages(Mdl
->MappedSystemVa
, Mdl
);
917 ObDereferenceObject(Process
);
919 if (NT_SUCCESS(CopyStatus
) && NumberOfBytesWritten
!= NULL
)
921 if (PreviousMode
!= KernelMode
)
925 *NumberOfBytesWritten
= NumberOfBytesToWrite
;
929 Status
= _SEH_GetExceptionCode();
935 *NumberOfBytesWritten
= NumberOfBytesToWrite
;
939 return(NT_SUCCESS(CopyStatus
) ? Status
: CopyStatus
);
948 MmGetVirtualForPhysical(
949 IN PHYSICAL_ADDRESS PhysicalAddress
957 * Called from EngSecureMem (subsys\win32k\eng\mem.c)
961 MmSecureVirtualMemory(PVOID Address
,
966 if ( ( (DWORD
)Address
+ Length
> (DWORD
)MmHighestUserAddress
) ||
967 ( (DWORD
)Address
+ Length
<= (DWORD
)Address
) )
968 /* Only works for user space */
969 if (((ULONG_PTR
)Address
> (ULONG_PTR
)Address
+ Length
) ||
970 ((ULONG_PTR
)MmHighestUserAddress
< (ULONG_PTR
)Address
+ Length
))
982 * Called from EngUnsecureMem (subsys\win32k\eng\mem.c)
986 MmUnsecureVirtualMemory(PVOID SecureMem
)
988 if (NULL
== SecureMem
)
1001 ProbeForRead(IN CONST VOID
*Address
,
1007 ASSERT(Alignment
== 1 || Alignment
== 2 || Alignment
== 4 || Alignment
== 8);
1009 if (((ULONG_PTR
)Address
& (Alignment
- 1)) != 0)
1011 ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT
);
1013 else if ((ULONG_PTR
)Address
+ Length
- 1 < (ULONG_PTR
)Address
||
1014 (ULONG_PTR
)Address
+ Length
- 1 >= (ULONG_PTR
)MmUserProbeAddress
)
1016 ExRaiseStatus (STATUS_ACCESS_VIOLATION
);
1026 ProbeForWrite(IN PVOID Address
,
1030 volatile CHAR
*Current
;
1035 ASSERT(Alignment
== 1 || Alignment
== 2 || Alignment
== 4 || Alignment
== 8);
1037 if (((ULONG_PTR
)Address
& (Alignment
- 1)) != 0)
1039 ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT
);
1042 Last
= (PCHAR
)((ULONG_PTR
)Address
+ Length
- 1);
1043 if ((ULONG_PTR
)Last
< (ULONG_PTR
)Address
||
1044 (ULONG_PTR
)Last
>= (ULONG_PTR
)MmUserProbeAddress
)
1046 ExRaiseStatus (STATUS_ACCESS_VIOLATION
);
1049 /* Check for accessible pages, do *not* touch any memory outside of the
1051 Current
= (volatile CHAR
*)Address
;
1052 Last
= (PCHAR
)(PAGE_ROUND_DOWN(Last
));
1055 *Current
= *Current
;
1056 Current
= (volatile CHAR
*)(PAGE_ROUND_DOWN(Current
) + PAGE_SIZE
);
1057 } while (Current
<= Last
);