2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/mm/virtual.c
5 * PURPOSE: Implementing operations on virtual memory.
7 * PROGRAMMERS: David Welch
10 /* INCLUDE *****************************************************************/
15 #include <internal/debug.h>
17 /* FUNCTIONS *****************************************************************/
20 NtFlushVirtualMemory(IN HANDLE ProcessHandle
,
21 IN OUT PVOID
*BaseAddress
,
22 IN OUT PSIZE_T NumberOfBytesToFlush
,
23 OUT PIO_STATUS_BLOCK IoStatusBlock
)
25 * FUNCTION: Flushes virtual memory to file
27 * ProcessHandle = Points to the process that allocated the virtual
29 * BaseAddress = Points to the memory address
30 * NumberOfBytesToFlush = Limits the range to flush,
31 * NumberOfBytesFlushed = Actual number of bytes flushed
35 /* This should be implemented once we support network filesystems */
36 DPRINT("NtFlushVirtualMemory is UNIMPLEMENTED\n");
37 return(STATUS_SUCCESS
);
42 MiLockVirtualMemory(HANDLE ProcessHandle
,
44 ULONG NumberOfBytesToLock
,
45 PULONG NumberOfBytesLocked
,
46 PObReferenceObjectByHandle pObReferenceObjectByHandle
,
47 PMmCreateMdl pMmCreateMdl
,
48 PObDereferenceObject pObDereferenceObject
,
49 PMmProbeAndLockPages pMmProbeAndLockPages
,
50 PExFreePool pExFreePool
)
56 Status
= pObReferenceObjectByHandle(ProcessHandle
,
62 if (!NT_SUCCESS(Status
))
65 Mdl
= pMmCreateMdl(NULL
,
70 pObDereferenceObject(Process
);
71 return(STATUS_NO_MEMORY
);
74 pMmProbeAndLockPages(Mdl
,
80 pObDereferenceObject(Process
);
82 *NumberOfBytesLocked
= NumberOfBytesToLock
;
83 return(STATUS_SUCCESS
);
88 NtLockVirtualMemory(HANDLE ProcessHandle
,
90 ULONG NumberOfBytesToLock
,
91 PULONG NumberOfBytesLocked
)
93 DPRINT("NtLockVirtualMemory(ProcessHandle %x, BaseAddress %x, "
94 "NumberOfBytesToLock %d, NumberOfBytesLocked %x)\n",
100 return MiLockVirtualMemory(ProcessHandle
,
104 ObReferenceObjectByHandle
,
106 (PVOID
)ObfDereferenceObject
,
113 MiQueryVirtualMemory(IN HANDLE ProcessHandle
,
115 IN MEMORY_INFORMATION_CLASS VirtualMemoryInformationClass
,
116 OUT PVOID VirtualMemoryInformation
,
118 OUT PULONG ResultLength
)
122 MEMORY_AREA
* MemoryArea
;
123 PMADDRESS_SPACE AddressSpace
;
125 if (Address
< MmSystemRangeStart
)
127 Status
= ObReferenceObjectByHandle(ProcessHandle
,
128 PROCESS_QUERY_INFORMATION
,
134 if (!NT_SUCCESS(Status
))
136 DPRINT("NtQueryVirtualMemory() = %x\n",Status
);
139 AddressSpace
= (PMADDRESS_SPACE
)&Process
->VadRoot
;
143 AddressSpace
= MmGetKernelAddressSpace();
145 MmLockAddressSpace(AddressSpace
);
146 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, Address
);
147 switch(VirtualMemoryInformationClass
)
149 case MemoryBasicInformation
:
151 PMEMORY_BASIC_INFORMATION Info
=
152 (PMEMORY_BASIC_INFORMATION
)VirtualMemoryInformation
;
153 if (Length
!= sizeof(MEMORY_BASIC_INFORMATION
))
155 MmUnlockAddressSpace(AddressSpace
);
156 ObDereferenceObject(Process
);
157 return(STATUS_INFO_LENGTH_MISMATCH
);
160 if (MemoryArea
== NULL
)
163 Info
->State
= MEM_FREE
;
164 Info
->Protect
= PAGE_NOACCESS
;
165 Info
->AllocationProtect
= 0;
166 Info
->BaseAddress
= (PVOID
)PAGE_ROUND_DOWN(Address
);
167 Info
->AllocationBase
= NULL
;
168 Info
->RegionSize
= MmFindGapAtAddress(AddressSpace
, Info
->BaseAddress
);
169 Status
= STATUS_SUCCESS
;
170 *ResultLength
= sizeof(MEMORY_BASIC_INFORMATION
);
174 switch(MemoryArea
->Type
)
176 case MEMORY_AREA_VIRTUAL_MEMORY
:
177 case MEMORY_AREA_PEB_OR_TEB
:
178 Status
= MmQueryAnonMem(MemoryArea
, Address
, Info
,
182 case MEMORY_AREA_SECTION_VIEW
:
183 Status
= MmQuerySectionView(MemoryArea
, Address
, Info
,
187 case MEMORY_AREA_NO_ACCESS
:
188 Info
->Type
= MEM_PRIVATE
;
189 Info
->State
= MEM_RESERVE
;
190 Info
->Protect
= MemoryArea
->Protect
;
191 Info
->AllocationProtect
= MemoryArea
->Protect
;
192 Info
->BaseAddress
= MemoryArea
->StartingAddress
;
193 Info
->AllocationBase
= MemoryArea
->StartingAddress
;
194 Info
->RegionSize
= (ULONG_PTR
)MemoryArea
->EndingAddress
-
195 (ULONG_PTR
)MemoryArea
->StartingAddress
;
196 Status
= STATUS_SUCCESS
;
197 *ResultLength
= sizeof(MEMORY_BASIC_INFORMATION
);
200 case MEMORY_AREA_SHARED_DATA
:
201 Info
->Type
= MEM_PRIVATE
;
202 Info
->State
= MEM_COMMIT
;
203 Info
->Protect
= MemoryArea
->Protect
;
204 Info
->AllocationProtect
= MemoryArea
->Protect
;
205 Info
->BaseAddress
= MemoryArea
->StartingAddress
;
206 Info
->AllocationBase
= MemoryArea
->StartingAddress
;
207 Info
->RegionSize
= (ULONG_PTR
)MemoryArea
->EndingAddress
-
208 (ULONG_PTR
)MemoryArea
->StartingAddress
;
209 Status
= STATUS_SUCCESS
;
210 *ResultLength
= sizeof(MEMORY_BASIC_INFORMATION
);
213 case MEMORY_AREA_SYSTEM
:
215 Info
->State
= MEM_COMMIT
;
216 Info
->Protect
= MemoryArea
->Protect
;
217 Info
->AllocationProtect
= MemoryArea
->Protect
;
218 Info
->BaseAddress
= MemoryArea
->StartingAddress
;
219 Info
->AllocationBase
= MemoryArea
->StartingAddress
;
220 Info
->RegionSize
= (ULONG_PTR
)MemoryArea
->EndingAddress
-
221 (ULONG_PTR
)MemoryArea
->StartingAddress
;
222 Status
= STATUS_SUCCESS
;
223 *ResultLength
= sizeof(MEMORY_BASIC_INFORMATION
);
226 case MEMORY_AREA_KERNEL_STACK
:
228 Info
->State
= MEM_COMMIT
;
229 Info
->Protect
= MemoryArea
->Protect
;
230 Info
->AllocationProtect
= MemoryArea
->Protect
;
231 Info
->BaseAddress
= MemoryArea
->StartingAddress
;
232 Info
->AllocationBase
= MemoryArea
->StartingAddress
;
233 Info
->RegionSize
= (ULONG_PTR
)MemoryArea
->EndingAddress
-
234 (ULONG_PTR
)MemoryArea
->StartingAddress
;
235 Status
= STATUS_SUCCESS
;
236 *ResultLength
= sizeof(MEMORY_BASIC_INFORMATION
);
239 case MEMORY_AREA_PAGED_POOL
:
241 Info
->State
= MEM_COMMIT
;
242 Info
->Protect
= MemoryArea
->Protect
;
243 Info
->AllocationProtect
= MemoryArea
->Protect
;
244 Info
->BaseAddress
= MemoryArea
->StartingAddress
;
245 Info
->AllocationBase
= MemoryArea
->StartingAddress
;
246 Info
->RegionSize
= (ULONG_PTR
)MemoryArea
->EndingAddress
-
247 (ULONG_PTR
)MemoryArea
->StartingAddress
;
248 Status
= STATUS_SUCCESS
;
249 *ResultLength
= sizeof(MEMORY_BASIC_INFORMATION
);
253 DPRINT1("unhandled memory area type: 0x%x\n", MemoryArea
->Type
);
254 Status
= STATUS_UNSUCCESSFUL
;
263 Status
= STATUS_INVALID_INFO_CLASS
;
269 MmUnlockAddressSpace(AddressSpace
);
270 if (Address
< MmSystemRangeStart
)
273 ObDereferenceObject(Process
);
281 * Called from VirtualQueryEx (lib\kernel32\mem\virtual.c)
285 NtQueryVirtualMemory(IN HANDLE ProcessHandle
,
287 IN MEMORY_INFORMATION_CLASS VirtualMemoryInformationClass
,
288 OUT PVOID VirtualMemoryInformation
,
290 OUT PULONG UnsafeResultLength
)
292 NTSTATUS Status
= STATUS_SUCCESS
;
293 ULONG ResultLength
= 0;
294 KPROCESSOR_MODE PreviousMode
;
297 MEMORY_BASIC_INFORMATION BasicInfo
;
301 DPRINT("NtQueryVirtualMemory(ProcessHandle %x, Address %x, "
302 "VirtualMemoryInformationClass %d, VirtualMemoryInformation %x, "
303 "Length %lu ResultLength %x)\n",ProcessHandle
,Address
,
304 VirtualMemoryInformationClass
,VirtualMemoryInformation
,
305 Length
,ResultLength
);
307 PreviousMode
= ExGetPreviousMode();
309 if (PreviousMode
!= KernelMode
&& UnsafeResultLength
!= NULL
)
313 ProbeForWriteUlong(UnsafeResultLength
);
317 Status
= _SEH_GetExceptionCode();
321 if (!NT_SUCCESS(Status
))
327 if (Address
>= MmSystemRangeStart
)
329 DPRINT1("Invalid parameter\n");
330 return STATUS_INVALID_PARAMETER
;
333 Status
= MiQueryVirtualMemory(ProcessHandle
,
335 VirtualMemoryInformationClass
,
340 if (NT_SUCCESS(Status
))
342 if (PreviousMode
!= KernelMode
)
346 if (ResultLength
> 0)
348 ProbeForWrite(VirtualMemoryInformation
,
351 RtlCopyMemory(VirtualMemoryInformation
,
355 if (UnsafeResultLength
!= NULL
)
357 *UnsafeResultLength
= ResultLength
;
362 Status
= _SEH_GetExceptionCode();
368 if (ResultLength
> 0)
370 RtlCopyMemory(VirtualMemoryInformation
,
375 if (UnsafeResultLength
!= NULL
)
377 *UnsafeResultLength
= ResultLength
;
387 MiProtectVirtualMemory(IN PEPROCESS Process
,
388 IN OUT PVOID
*BaseAddress
,
389 IN OUT PULONG NumberOfBytesToProtect
,
390 IN ULONG NewAccessProtection
,
391 OUT PULONG OldAccessProtection OPTIONAL
)
393 PMEMORY_AREA MemoryArea
;
394 PMADDRESS_SPACE AddressSpace
;
395 ULONG OldAccessProtection_
;
398 *NumberOfBytesToProtect
=
399 PAGE_ROUND_UP((ULONG_PTR
)(*BaseAddress
) + (*NumberOfBytesToProtect
)) -
400 PAGE_ROUND_DOWN(*BaseAddress
);
401 *BaseAddress
= (PVOID
)PAGE_ROUND_DOWN(*BaseAddress
);
403 AddressSpace
= (PMADDRESS_SPACE
)&(Process
)->VadRoot
;
405 MmLockAddressSpace(AddressSpace
);
406 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, *BaseAddress
);
407 if (MemoryArea
== NULL
)
409 MmUnlockAddressSpace(AddressSpace
);
410 return STATUS_UNSUCCESSFUL
;
413 if (OldAccessProtection
== NULL
)
414 OldAccessProtection
= &OldAccessProtection_
;
416 if (MemoryArea
->Type
== MEMORY_AREA_VIRTUAL_MEMORY
)
418 Status
= MmProtectAnonMem(AddressSpace
, MemoryArea
, *BaseAddress
,
419 *NumberOfBytesToProtect
, NewAccessProtection
,
420 OldAccessProtection
);
422 else if (MemoryArea
->Type
== MEMORY_AREA_SECTION_VIEW
)
424 Status
= MmProtectSectionView(AddressSpace
, MemoryArea
, *BaseAddress
,
425 *NumberOfBytesToProtect
,
427 OldAccessProtection
);
431 /* FIXME: Should we return failure or success in this case? */
432 Status
= STATUS_CONFLICTING_ADDRESSES
;
435 MmUnlockAddressSpace(AddressSpace
);
443 * Called from VirtualProtectEx (lib\kernel32\mem\virtual.c)
447 NtProtectVirtualMemory(IN HANDLE ProcessHandle
,
448 IN OUT PVOID
*UnsafeBaseAddress
,
449 IN OUT ULONG
*UnsafeNumberOfBytesToProtect
,
450 IN ULONG NewAccessProtection
,
451 OUT PULONG UnsafeOldAccessProtection
)
454 ULONG OldAccessProtection
;
455 PVOID BaseAddress
= NULL
;
456 ULONG NumberOfBytesToProtect
= 0;
457 KPROCESSOR_MODE PreviousMode
;
458 NTSTATUS Status
= STATUS_SUCCESS
;
460 PreviousMode
= ExGetPreviousMode();
462 if (PreviousMode
!= KernelMode
)
466 ProbeForWritePointer(UnsafeBaseAddress
);
467 ProbeForWriteUlong(UnsafeNumberOfBytesToProtect
);
468 ProbeForWriteUlong(UnsafeOldAccessProtection
);
470 BaseAddress
= *UnsafeBaseAddress
;
471 NumberOfBytesToProtect
= *UnsafeNumberOfBytesToProtect
;
475 Status
= _SEH_GetExceptionCode();
479 if (!NT_SUCCESS(Status
))
486 BaseAddress
= *UnsafeBaseAddress
;
487 NumberOfBytesToProtect
= *UnsafeNumberOfBytesToProtect
;
490 if ((ULONG_PTR
)BaseAddress
+ NumberOfBytesToProtect
- 1 < (ULONG_PTR
)BaseAddress
||
491 (ULONG_PTR
)BaseAddress
+ NumberOfBytesToProtect
- 1 >= MmUserProbeAddress
)
493 /* Don't allow to change the protection of a kernel mode address */
494 return STATUS_INVALID_PARAMETER_2
;
497 /* (tMk 2004.II.5) in Microsoft SDK I read:
498 * 'if this parameter is NULL or does not point to a valid variable, the function fails'
500 if(UnsafeOldAccessProtection
== NULL
)
502 return(STATUS_INVALID_PARAMETER
);
505 Status
= ObReferenceObjectByHandle(ProcessHandle
,
506 PROCESS_VM_OPERATION
,
511 if (!NT_SUCCESS(Status
))
513 DPRINT("NtProtectVirtualMemory() = %x\n",Status
);
517 Status
= MiProtectVirtualMemory(Process
,
519 &NumberOfBytesToProtect
,
521 &OldAccessProtection
);
523 ObDereferenceObject(Process
);
525 if (PreviousMode
!= KernelMode
)
529 *UnsafeOldAccessProtection
= OldAccessProtection
;
530 *UnsafeBaseAddress
= BaseAddress
;
531 *UnsafeNumberOfBytesToProtect
= NumberOfBytesToProtect
;
535 Status
= _SEH_GetExceptionCode();
541 *UnsafeOldAccessProtection
= OldAccessProtection
;
542 *UnsafeBaseAddress
= BaseAddress
;
543 *UnsafeNumberOfBytesToProtect
= NumberOfBytesToProtect
;
552 * Called from ReadProcessMemory (lib\kernel32\mem\procmem.c) and KlInitPeb(lib\kernel32\process\create.c)
554 * NOTE: This function will be correct if MmProbeAndLockPages() would be fully IMPLEMENTED.
557 NtReadVirtualMemory(IN HANDLE ProcessHandle
,
558 IN PVOID BaseAddress
,
560 IN ULONG NumberOfBytesToRead
,
561 OUT PULONG NumberOfBytesRead OPTIONAL
)
565 KPROCESSOR_MODE PreviousMode
;
566 PEPROCESS Process
, CurrentProcess
;
567 NTSTATUS Status
= STATUS_SUCCESS
;
571 DPRINT("NtReadVirtualMemory(ProcessHandle %x, BaseAddress %x, "
572 "Buffer %x, NumberOfBytesToRead %d)\n",ProcessHandle
,BaseAddress
,
573 Buffer
,NumberOfBytesToRead
);
575 if ((ULONG_PTR
)BaseAddress
+ NumberOfBytesToRead
- 1 < (ULONG_PTR
)BaseAddress
||
576 (ULONG_PTR
)BaseAddress
+ NumberOfBytesToRead
- 1 >= MmUserProbeAddress
)
578 /* Don't allow to read from kernel space */
579 return STATUS_ACCESS_VIOLATION
;
582 PreviousMode
= ExGetPreviousMode();
584 if (PreviousMode
!= KernelMode
)
586 if ((ULONG_PTR
)Buffer
+ NumberOfBytesToRead
- 1 < (ULONG_PTR
)Buffer
||
587 (ULONG_PTR
)Buffer
+ NumberOfBytesToRead
- 1 >= MmUserProbeAddress
)
589 /* Don't allow to write into kernel space */
590 return STATUS_ACCESS_VIOLATION
;
594 Status
= ObReferenceObjectByHandle(ProcessHandle
,
600 if (!NT_SUCCESS(Status
))
605 CurrentProcess
= PsGetCurrentProcess();
607 if(PreviousMode
!= KernelMode
)
611 if(NumberOfBytesRead
!= NULL
)
613 ProbeForWriteUlong(NumberOfBytesRead
);
618 Status
= _SEH_GetExceptionCode();
622 if(!NT_SUCCESS(Status
))
629 if (Process
== CurrentProcess
)
633 RtlCopyMemory(Buffer
, BaseAddress
, NumberOfBytesToRead
);
637 Status
= _SEH_GetExceptionCode();
643 Mdl
= MmCreateMdl(NULL
,
645 NumberOfBytesToRead
);
648 ObDereferenceObject(Process
);
649 return(STATUS_NO_MEMORY
);
654 MmProbeAndLockPages(Mdl
, PreviousMode
, IoWriteAccess
);
658 Status
= _SEH_GetExceptionCode();
662 if(NT_SUCCESS(Status
))
664 KeAttachProcess(&Process
->Pcb
);
666 SystemAddress
= MmGetSystemAddressForMdl(Mdl
);
668 Status
= STATUS_SUCCESS
;
671 Status
= STATUS_PARTIAL_COPY
;
672 RtlCopyMemory(SystemAddress
, BaseAddress
, NumberOfBytesToRead
);
673 Status
= STATUS_SUCCESS
;
677 if(Status
!= STATUS_PARTIAL_COPY
)
678 Status
= _SEH_GetExceptionCode();
684 if (Mdl
->MappedSystemVa
!= NULL
)
686 MmUnmapLockedPages(Mdl
->MappedSystemVa
, Mdl
);
693 ObDereferenceObject(Process
);
695 if ((NT_SUCCESS(Status
) || Status
== STATUS_PARTIAL_COPY
) &&
696 NumberOfBytesRead
!= NULL
)
700 *NumberOfBytesRead
= NumberOfBytesToRead
;
704 Status
= _SEH_GetExceptionCode();
713 * FUNCTION: THIS function doesn't make a sense...
714 * Called from VirtualUnlock (lib\kernel32\mem\virtual.c)
717 NtUnlockVirtualMemory(HANDLE ProcessHandle
,
719 ULONG NumberOfBytesToUnlock
,
720 PULONG NumberOfBytesUnlocked OPTIONAL
)
722 // AG [08-20-03] : I have *no* idea if this is correct, I just used the
723 // other functions as a template and made a few intelligent guesses...
729 DPRINT("NtUnlockVirtualMemory(ProcessHandle %x, BaseAddress %x, "
730 "NumberOfBytesToUnlock %d), NumberOfBytesUnlocked %x\n",ProcessHandle
,BaseAddress
,
731 NumberOfBytesToUnlock
, NumberOfBytesUnlocked
);
733 Status
= ObReferenceObjectByHandle(ProcessHandle
,
739 if (!NT_SUCCESS(Status
))
744 Mdl
= MmCreateMdl(NULL
,
746 NumberOfBytesToUnlock
);
749 ObDereferenceObject(Process
);
750 return(STATUS_NO_MEMORY
);
753 ObDereferenceObject(Process
);
755 if (Mdl
->MappedSystemVa
!= NULL
)
757 MmUnmapLockedPages(Mdl
->MappedSystemVa
, Mdl
);
762 *NumberOfBytesUnlocked
= NumberOfBytesToUnlock
;
764 return(STATUS_SUCCESS
);
770 * Called from WriteProcessMemory (lib\kernel32\mem\procmem.c) and KlInitPeb(lib\kernel32\process\create.c)
772 * NOTE: This function will be correct if MmProbeAndLockPages() would be fully IMPLEMENTED.
775 NtWriteVirtualMemory(IN HANDLE ProcessHandle
,
776 IN PVOID BaseAddress
,
778 IN ULONG NumberOfBytesToWrite
,
779 OUT PULONG NumberOfBytesWritten OPTIONAL
)
784 KPROCESSOR_MODE PreviousMode
;
785 NTSTATUS CopyStatus
, Status
= STATUS_SUCCESS
;
787 DPRINT("NtWriteVirtualMemory(ProcessHandle %x, BaseAddress %x, "
788 "Buffer %x, NumberOfBytesToWrite %d)\n",ProcessHandle
,BaseAddress
,
789 Buffer
,NumberOfBytesToWrite
);
791 if ((ULONG_PTR
)BaseAddress
+ NumberOfBytesToWrite
- 1 < (ULONG_PTR
)BaseAddress
||
792 (ULONG_PTR
)BaseAddress
+ NumberOfBytesToWrite
- 1 >= MmUserProbeAddress
)
794 /* Don't allow to write into kernel space */
795 return STATUS_ACCESS_VIOLATION
;
798 PreviousMode
= ExGetPreviousMode();
800 if (PreviousMode
!= KernelMode
)
802 if ((ULONG_PTR
)Buffer
+ NumberOfBytesToWrite
- 1 < (ULONG_PTR
)Buffer
||
803 (ULONG_PTR
)Buffer
+ NumberOfBytesToWrite
- 1 >= MmUserProbeAddress
)
805 /* Don't allow to read from kernel space */
806 return STATUS_ACCESS_VIOLATION
;
808 if (NumberOfBytesWritten
!= NULL
)
812 ProbeForWriteUlong(NumberOfBytesWritten
);
816 Status
= _SEH_GetExceptionCode();
820 if (!NT_SUCCESS(Status
))
827 Status
= ObReferenceObjectByHandle(ProcessHandle
,
833 if (!NT_SUCCESS(Status
))
838 CopyStatus
= STATUS_SUCCESS
;
841 if (Process
== PsGetCurrentProcess())
843 if (PreviousMode
!= KernelMode
)
847 memcpy(BaseAddress
, Buffer
, NumberOfBytesToWrite
);
851 CopyStatus
= _SEH_GetExceptionCode();
857 memcpy(BaseAddress
, Buffer
, NumberOfBytesToWrite
);
862 /* Create MDL describing the source buffer. */
863 Mdl
= MmCreateMdl(NULL
,
865 NumberOfBytesToWrite
);
868 ObDereferenceObject(Process
);
869 return(STATUS_NO_MEMORY
);
874 MmProbeAndLockPages(Mdl
, UserMode
, IoReadAccess
);
878 CopyStatus
= _SEH_GetExceptionCode();
882 if (NT_SUCCESS(CopyStatus
))
884 /* Copy memory from the mapped MDL into the target buffer. */
885 KeAttachProcess(&Process
->Pcb
);
887 SystemAddress
= MmGetSystemAddressForMdl(Mdl
);
888 if (PreviousMode
!= KernelMode
)
892 memcpy(BaseAddress
, SystemAddress
, NumberOfBytesToWrite
);
896 CopyStatus
= _SEH_GetExceptionCode();
902 memcpy(BaseAddress
, SystemAddress
, NumberOfBytesToWrite
);
909 if (Mdl
->MappedSystemVa
!= NULL
)
911 MmUnmapLockedPages(Mdl
->MappedSystemVa
, Mdl
);
916 ObDereferenceObject(Process
);
918 if (NT_SUCCESS(CopyStatus
) && NumberOfBytesWritten
!= NULL
)
920 if (PreviousMode
!= KernelMode
)
924 *NumberOfBytesWritten
= NumberOfBytesToWrite
;
928 Status
= _SEH_GetExceptionCode();
934 *NumberOfBytesWritten
= NumberOfBytesToWrite
;
938 return(NT_SUCCESS(CopyStatus
) ? Status
: CopyStatus
);
947 MmGetVirtualForPhysical(
948 IN PHYSICAL_ADDRESS PhysicalAddress
956 * Called from EngSecureMem (subsys\win32k\eng\mem.c)
960 MmSecureVirtualMemory(PVOID Address
,
964 /* Only works for user space */
965 if (((ULONG_PTR
)Address
>= (ULONG_PTR
)Address
+ Length
) ||
966 ((ULONG_PTR
)MmHighestUserAddress
< (ULONG_PTR
)Address
+ Length
))
978 * Called from EngUnsecureMem (subsys\win32k\eng\mem.c)
982 MmUnsecureVirtualMemory(PVOID SecureMem
)
984 if (NULL
== SecureMem
)
997 ProbeForRead(IN CONST VOID
*Address
,
1003 ASSERT(Alignment
== 1 || Alignment
== 2 || Alignment
== 4 || Alignment
== 8);
1005 if (((ULONG_PTR
)Address
& (Alignment
- 1)) != 0)
1007 ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT
);
1009 else if ((ULONG_PTR
)Address
+ Length
- 1 < (ULONG_PTR
)Address
||
1010 (ULONG_PTR
)Address
+ Length
- 1 >= (ULONG_PTR
)MmUserProbeAddress
)
1012 ExRaiseStatus (STATUS_ACCESS_VIOLATION
);
1022 ProbeForWrite(IN PVOID Address
,
1026 volatile CHAR
*Current
;
1031 ASSERT(Alignment
== 1 || Alignment
== 2 || Alignment
== 4 || Alignment
== 8);
1033 if (((ULONG_PTR
)Address
& (Alignment
- 1)) != 0)
1035 ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT
);
1038 Last
= (PCHAR
)((ULONG_PTR
)Address
+ Length
- 1);
1039 if ((ULONG_PTR
)Last
< (ULONG_PTR
)Address
||
1040 (ULONG_PTR
)Last
>= (ULONG_PTR
)MmUserProbeAddress
)
1042 ExRaiseStatus (STATUS_ACCESS_VIOLATION
);
1045 /* Check for accessible pages, do *not* touch any memory outside of the
1047 Current
= (volatile CHAR
*)Address
;
1048 Last
= (PCHAR
)(PAGE_ROUND_DOWN(Last
));
1051 *Current
= *Current
;
1052 Current
= (volatile CHAR
*)(PAGE_ROUND_DOWN(Current
) + PAGE_SIZE
);
1053 } while (Current
<= Last
);