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
,
23 IN ULONG NumberOfBytesToFlush
,
24 OUT PULONG NumberOfBytesFlushed OPTIONAL
)
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
,
182 case MEMORY_AREA_SECTION_VIEW
:
183 Status
= MmQuerySectionView(MemoryArea
, Address
, Info
,
186 case MEMORY_AREA_NO_ACCESS
:
187 Info
->Type
= MEM_PRIVATE
;
188 Info
->State
= MEM_RESERVE
;
189 Info
->Protect
= MemoryArea
->Protect
;
190 Info
->AllocationProtect
= MemoryArea
->Protect
;
191 Info
->BaseAddress
= MemoryArea
->StartingAddress
;
192 Info
->AllocationBase
= MemoryArea
->StartingAddress
;
193 Info
->RegionSize
= (ULONG_PTR
)MemoryArea
->EndingAddress
-
194 (ULONG_PTR
)MemoryArea
->StartingAddress
;
195 Status
= STATUS_SUCCESS
;
196 *ResultLength
= sizeof(MEMORY_BASIC_INFORMATION
);
198 case MEMORY_AREA_SHARED_DATA
:
199 Info
->Type
= MEM_PRIVATE
;
200 Info
->State
= MEM_COMMIT
;
201 Info
->Protect
= MemoryArea
->Protect
;
202 Info
->AllocationProtect
= MemoryArea
->Protect
;
203 Info
->BaseAddress
= MemoryArea
->StartingAddress
;
204 Info
->AllocationBase
= MemoryArea
->StartingAddress
;
205 Info
->RegionSize
= (ULONG_PTR
)MemoryArea
->EndingAddress
-
206 (ULONG_PTR
)MemoryArea
->StartingAddress
;
207 Status
= STATUS_SUCCESS
;
208 *ResultLength
= sizeof(MEMORY_BASIC_INFORMATION
);
210 case MEMORY_AREA_SYSTEM
:
212 Info
->State
= MEM_COMMIT
;
213 Info
->Protect
= MemoryArea
->Protect
;
214 Info
->AllocationProtect
= MemoryArea
->Protect
;
215 Info
->BaseAddress
= MemoryArea
->StartingAddress
;
216 Info
->AllocationBase
= MemoryArea
->StartingAddress
;
217 Info
->RegionSize
= (ULONG_PTR
)MemoryArea
->EndingAddress
-
218 (ULONG_PTR
)MemoryArea
->StartingAddress
;
219 Status
= STATUS_SUCCESS
;
220 *ResultLength
= sizeof(MEMORY_BASIC_INFORMATION
);
222 case MEMORY_AREA_KERNEL_STACK
:
224 Info
->State
= MEM_COMMIT
;
225 Info
->Protect
= MemoryArea
->Protect
;
226 Info
->AllocationProtect
= MemoryArea
->Protect
;
227 Info
->BaseAddress
= MemoryArea
->StartingAddress
;
228 Info
->AllocationBase
= MemoryArea
->StartingAddress
;
229 Info
->RegionSize
= (ULONG_PTR
)MemoryArea
->EndingAddress
-
230 (ULONG_PTR
)MemoryArea
->StartingAddress
;
231 Status
= STATUS_SUCCESS
;
232 *ResultLength
= sizeof(MEMORY_BASIC_INFORMATION
);
234 case MEMORY_AREA_PAGED_POOL
:
236 Info
->State
= MEM_COMMIT
;
237 Info
->Protect
= MemoryArea
->Protect
;
238 Info
->AllocationProtect
= MemoryArea
->Protect
;
239 Info
->BaseAddress
= MemoryArea
->StartingAddress
;
240 Info
->AllocationBase
= MemoryArea
->StartingAddress
;
241 Info
->RegionSize
= (ULONG_PTR
)MemoryArea
->EndingAddress
-
242 (ULONG_PTR
)MemoryArea
->StartingAddress
;
243 Status
= STATUS_SUCCESS
;
244 *ResultLength
= sizeof(MEMORY_BASIC_INFORMATION
);
247 DPRINT1("unhandled memory area type: 0x%x\n", MemoryArea
->Type
);
248 Status
= STATUS_UNSUCCESSFUL
;
257 Status
= STATUS_INVALID_INFO_CLASS
;
263 MmUnlockAddressSpace(AddressSpace
);
264 if (Address
< MmSystemRangeStart
)
267 ObDereferenceObject(Process
);
275 * Called from VirtualQueryEx (lib\kernel32\mem\virtual.c)
279 NtQueryVirtualMemory (IN HANDLE ProcessHandle
,
281 IN MEMORY_INFORMATION_CLASS VirtualMemoryInformationClass
,
282 OUT PVOID VirtualMemoryInformation
,
284 OUT PULONG UnsafeResultLength
)
286 NTSTATUS Status
= STATUS_SUCCESS
;
287 ULONG ResultLength
= 0;
288 KPROCESSOR_MODE PreviousMode
;
291 MEMORY_BASIC_INFORMATION BasicInfo
;
295 DPRINT("NtQueryVirtualMemory(ProcessHandle %x, Address %x, "
296 "VirtualMemoryInformationClass %d, VirtualMemoryInformation %x, "
297 "Length %lu ResultLength %x)\n",ProcessHandle
,Address
,
298 VirtualMemoryInformationClass
,VirtualMemoryInformation
,
299 Length
,ResultLength
);
301 PreviousMode
= ExGetPreviousMode();
303 if (PreviousMode
!= KernelMode
&& UnsafeResultLength
!= NULL
)
307 ProbeForWriteUlong(UnsafeResultLength
);
311 Status
= _SEH_GetExceptionCode();
315 if (!NT_SUCCESS(Status
))
321 if (Address
>= MmSystemRangeStart
)
323 DPRINT1("Invalid parameter\n");
324 return STATUS_INVALID_PARAMETER
;
327 Status
= MiQueryVirtualMemory ( ProcessHandle
,
329 VirtualMemoryInformationClass
,
334 if (NT_SUCCESS(Status
))
336 if (PreviousMode
!= KernelMode
)
340 if (ResultLength
> 0)
342 ProbeForWrite(VirtualMemoryInformation
,
345 RtlCopyMemory(VirtualMemoryInformation
,
349 if (UnsafeResultLength
!= NULL
)
351 *UnsafeResultLength
= ResultLength
;
356 Status
= _SEH_GetExceptionCode();
362 if (ResultLength
> 0)
364 RtlCopyMemory(VirtualMemoryInformation
,
369 if (UnsafeResultLength
!= NULL
)
371 *UnsafeResultLength
= ResultLength
;
381 MiProtectVirtualMemory(IN PEPROCESS Process
,
382 IN OUT PVOID
*BaseAddress
,
383 IN OUT PULONG NumberOfBytesToProtect
,
384 IN ULONG NewAccessProtection
,
385 OUT PULONG OldAccessProtection OPTIONAL
)
387 PMEMORY_AREA MemoryArea
;
388 PMADDRESS_SPACE AddressSpace
;
389 ULONG OldAccessProtection_
;
392 *NumberOfBytesToProtect
=
393 PAGE_ROUND_UP((*BaseAddress
) + (*NumberOfBytesToProtect
)) -
394 PAGE_ROUND_DOWN(*BaseAddress
);
395 *BaseAddress
= (PVOID
)PAGE_ROUND_DOWN(*BaseAddress
);
397 AddressSpace
= (PMADDRESS_SPACE
)&(Process
)->VadRoot
;
399 MmLockAddressSpace(AddressSpace
);
400 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, *BaseAddress
);
401 if (MemoryArea
== NULL
)
403 MmUnlockAddressSpace(AddressSpace
);
404 return STATUS_UNSUCCESSFUL
;
407 if (OldAccessProtection
== NULL
)
408 OldAccessProtection
= &OldAccessProtection_
;
410 if (MemoryArea
->Type
== MEMORY_AREA_VIRTUAL_MEMORY
)
412 Status
= MmProtectAnonMem(AddressSpace
, MemoryArea
, *BaseAddress
,
413 *NumberOfBytesToProtect
, NewAccessProtection
,
414 OldAccessProtection
);
416 else if (MemoryArea
->Type
== MEMORY_AREA_SECTION_VIEW
)
418 Status
= MmProtectSectionView(AddressSpace
, MemoryArea
, *BaseAddress
,
419 *NumberOfBytesToProtect
,
421 OldAccessProtection
);
425 /* FIXME: Should we return failure or success in this case? */
426 Status
= STATUS_CONFLICTING_ADDRESSES
;
429 MmUnlockAddressSpace(AddressSpace
);
437 * Called from VirtualProtectEx (lib\kernel32\mem\virtual.c)
441 NtProtectVirtualMemory(IN HANDLE ProcessHandle
,
442 IN OUT PVOID
*UnsafeBaseAddress
,
443 IN OUT ULONG
*UnsafeNumberOfBytesToProtect
,
444 IN ULONG NewAccessProtection
,
445 OUT PULONG UnsafeOldAccessProtection
)
448 ULONG OldAccessProtection
;
449 PVOID BaseAddress
= NULL
;
450 ULONG NumberOfBytesToProtect
= 0;
451 KPROCESSOR_MODE PreviousMode
;
452 NTSTATUS Status
= STATUS_SUCCESS
;
454 PreviousMode
= ExGetPreviousMode();
456 if (PreviousMode
!= KernelMode
)
460 ProbeForWritePointer(UnsafeBaseAddress
);
461 ProbeForWriteUlong(UnsafeNumberOfBytesToProtect
);
462 ProbeForWriteUlong(UnsafeOldAccessProtection
);
464 BaseAddress
= *UnsafeBaseAddress
;
465 NumberOfBytesToProtect
= *UnsafeNumberOfBytesToProtect
;
469 Status
= _SEH_GetExceptionCode();
473 if (!NT_SUCCESS(Status
))
480 BaseAddress
= *UnsafeBaseAddress
;
481 NumberOfBytesToProtect
= *UnsafeNumberOfBytesToProtect
;
484 if ((ULONG_PTR
)BaseAddress
+ NumberOfBytesToProtect
- 1 < (ULONG_PTR
)BaseAddress
||
485 (ULONG_PTR
)BaseAddress
+ NumberOfBytesToProtect
- 1 >= MmUserProbeAddress
)
487 /* Don't allow to change the protection of a kernel mode address */
488 return STATUS_INVALID_PARAMETER_2
;
491 /* (tMk 2004.II.5) in Microsoft SDK I read:
492 * 'if this parameter is NULL or does not point to a valid variable, the function fails'
494 if(UnsafeOldAccessProtection
== NULL
)
496 return(STATUS_INVALID_PARAMETER
);
499 Status
= ObReferenceObjectByHandle(ProcessHandle
,
500 PROCESS_VM_OPERATION
,
505 if (!NT_SUCCESS(Status
))
507 DPRINT("NtProtectVirtualMemory() = %x\n",Status
);
511 Status
= MiProtectVirtualMemory(Process
,
513 &NumberOfBytesToProtect
,
515 &OldAccessProtection
);
517 ObDereferenceObject(Process
);
519 if (PreviousMode
!= KernelMode
)
523 *UnsafeOldAccessProtection
= OldAccessProtection
;
524 *UnsafeBaseAddress
= BaseAddress
;
525 *UnsafeNumberOfBytesToProtect
= NumberOfBytesToProtect
;
529 Status
= _SEH_GetExceptionCode();
535 *UnsafeOldAccessProtection
= OldAccessProtection
;
536 *UnsafeBaseAddress
= BaseAddress
;
537 *UnsafeNumberOfBytesToProtect
= NumberOfBytesToProtect
;
546 * Called from ReadProcessMemory (lib\kernel32\mem\procmem.c) and KlInitPeb(lib\kernel32\process\create.c)
548 * NOTE: This function will be correct if MmProbeAndLockPages() would be fully IMPLEMENTED.
551 NtReadVirtualMemory(IN HANDLE ProcessHandle
,
552 IN PVOID BaseAddress
,
554 IN ULONG NumberOfBytesToRead
,
555 OUT PULONG NumberOfBytesRead OPTIONAL
)
559 KPROCESSOR_MODE PreviousMode
;
560 PEPROCESS Process
, CurrentProcess
;
561 NTSTATUS Status
= STATUS_SUCCESS
;
565 DPRINT("NtReadVirtualMemory(ProcessHandle %x, BaseAddress %x, "
566 "Buffer %x, NumberOfBytesToRead %d)\n",ProcessHandle
,BaseAddress
,
567 Buffer
,NumberOfBytesToRead
);
569 if ((ULONG_PTR
)BaseAddress
+ NumberOfBytesToRead
- 1 < (ULONG_PTR
)BaseAddress
||
570 (ULONG_PTR
)BaseAddress
+ NumberOfBytesToRead
- 1 >= MmUserProbeAddress
)
572 /* Don't allow to read from kernel space */
573 return STATUS_ACCESS_VIOLATION
;
576 PreviousMode
= ExGetPreviousMode();
578 if (PreviousMode
!= KernelMode
)
580 if ((ULONG_PTR
)Buffer
+ NumberOfBytesToRead
- 1 < (ULONG_PTR
)Buffer
||
581 (ULONG_PTR
)Buffer
+ NumberOfBytesToRead
- 1 >= MmUserProbeAddress
)
583 /* Don't allow to write into kernel space */
584 return STATUS_ACCESS_VIOLATION
;
588 Status
= ObReferenceObjectByHandle(ProcessHandle
,
594 if (!NT_SUCCESS(Status
))
599 CurrentProcess
= PsGetCurrentProcess();
601 if(PreviousMode
!= KernelMode
)
605 if(NumberOfBytesRead
!= NULL
)
607 ProbeForWriteUlong(NumberOfBytesRead
);
612 Status
= _SEH_GetExceptionCode();
616 if(!NT_SUCCESS(Status
))
623 if (Process
== CurrentProcess
)
627 RtlCopyMemory(Buffer
, BaseAddress
, NumberOfBytesToRead
);
631 Status
= _SEH_GetExceptionCode();
637 Mdl
= MmCreateMdl(NULL
,
639 NumberOfBytesToRead
);
642 ObDereferenceObject(Process
);
643 return(STATUS_NO_MEMORY
);
647 MmProbeAndLockPages(Mdl
,
653 Status
= _SEH_GetExceptionCode();
657 if(NT_SUCCESS(Status
))
659 KeAttachProcess(&Process
->Pcb
);
661 SystemAddress
= MmGetSystemAddressForMdl(Mdl
);
663 Status
= STATUS_SUCCESS
;
665 Status
= STATUS_PARTIAL_COPY
;
666 RtlCopyMemory(SystemAddress
, BaseAddress
, NumberOfBytesToRead
);
667 Status
= STATUS_SUCCESS
;
669 if(Status
!= STATUS_PARTIAL_COPY
)
670 Status
= _SEH_GetExceptionCode();
675 if (Mdl
->MappedSystemVa
!= NULL
)
677 MmUnmapLockedPages(Mdl
->MappedSystemVa
, Mdl
);
684 ObDereferenceObject(Process
);
686 if((NT_SUCCESS(Status
) || Status
== STATUS_PARTIAL_COPY
) &&
687 NumberOfBytesRead
!= NULL
)
691 *NumberOfBytesRead
= NumberOfBytesToRead
;
695 Status
= _SEH_GetExceptionCode();
704 * FUNCTION: THIS function doesn't make a sense...
705 * Called from VirtualUnlock (lib\kernel32\mem\virtual.c)
708 NtUnlockVirtualMemory(HANDLE ProcessHandle
,
710 ULONG NumberOfBytesToUnlock
,
711 PULONG NumberOfBytesUnlocked OPTIONAL
)
713 // AG [08-20-03] : I have *no* idea if this is correct, I just used the
714 // other functions as a template and made a few intelligent guesses...
720 DPRINT("NtUnlockVirtualMemory(ProcessHandle %x, BaseAddress %x, "
721 "NumberOfBytesToUnlock %d), NumberOfBytesUnlocked %x\n",ProcessHandle
,BaseAddress
,
722 NumberOfBytesToUnlock
, NumberOfBytesUnlocked
);
724 Status
= ObReferenceObjectByHandle(ProcessHandle
,
730 if (!NT_SUCCESS(Status
))
735 Mdl
= MmCreateMdl(NULL
,
737 NumberOfBytesToUnlock
);
740 ObDereferenceObject(Process
);
741 return(STATUS_NO_MEMORY
);
744 ObDereferenceObject(Process
);
746 if (Mdl
->MappedSystemVa
!= NULL
)
748 MmUnmapLockedPages(Mdl
->MappedSystemVa
, Mdl
);
753 *NumberOfBytesUnlocked
= NumberOfBytesToUnlock
;
755 return(STATUS_SUCCESS
);
761 * Called from WriteProcessMemory (lib\kernel32\mem\procmem.c) and KlInitPeb(lib\kernel32\process\create.c)
763 * NOTE: This function will be correct if MmProbeAndLockPages() would be fully IMPLEMENTED.
766 NtWriteVirtualMemory(IN HANDLE ProcessHandle
,
767 IN PVOID BaseAddress
,
769 IN ULONG NumberOfBytesToWrite
,
770 OUT PULONG NumberOfBytesWritten OPTIONAL
)
775 KPROCESSOR_MODE PreviousMode
;
776 NTSTATUS CopyStatus
, Status
= STATUS_SUCCESS
;
778 DPRINT("NtWriteVirtualMemory(ProcessHandle %x, BaseAddress %x, "
779 "Buffer %x, NumberOfBytesToWrite %d)\n",ProcessHandle
,BaseAddress
,
780 Buffer
,NumberOfBytesToWrite
);
782 if ((ULONG_PTR
)BaseAddress
+ NumberOfBytesToWrite
- 1 < (ULONG_PTR
)BaseAddress
||
783 (ULONG_PTR
)BaseAddress
+ NumberOfBytesToWrite
- 1 >= MmUserProbeAddress
)
785 /* Don't allow to write into kernel space */
786 return STATUS_ACCESS_VIOLATION
;
789 PreviousMode
= ExGetPreviousMode();
791 if (PreviousMode
!= KernelMode
)
793 if ((ULONG_PTR
)Buffer
+ NumberOfBytesToWrite
- 1 < (ULONG_PTR
)Buffer
||
794 (ULONG_PTR
)Buffer
+ NumberOfBytesToWrite
- 1 >= MmUserProbeAddress
)
796 /* Don't allow to read from kernel space */
797 return STATUS_ACCESS_VIOLATION
;
799 if (NumberOfBytesWritten
!= NULL
)
803 ProbeForWriteUlong(NumberOfBytesWritten
);
807 Status
= _SEH_GetExceptionCode();
811 if (!NT_SUCCESS(Status
))
818 Status
= ObReferenceObjectByHandle(ProcessHandle
,
824 if (!NT_SUCCESS(Status
))
829 CopyStatus
= STATUS_SUCCESS
;
832 if (Process
== PsGetCurrentProcess())
834 if (PreviousMode
!= KernelMode
)
838 memcpy(BaseAddress
, Buffer
, NumberOfBytesToWrite
);
842 CopyStatus
= _SEH_GetExceptionCode();
848 memcpy(BaseAddress
, Buffer
, NumberOfBytesToWrite
);
853 /* Create MDL describing the source buffer. */
854 Mdl
= MmCreateMdl(NULL
,
856 NumberOfBytesToWrite
);
859 ObDereferenceObject(Process
);
860 return(STATUS_NO_MEMORY
);
865 MmProbeAndLockPages(Mdl
,
871 CopyStatus
= _SEH_GetExceptionCode();
875 if (NT_SUCCESS(CopyStatus
))
877 /* Copy memory from the mapped MDL into the target buffer. */
878 KeAttachProcess(&Process
->Pcb
);
880 SystemAddress
= MmGetSystemAddressForMdl(Mdl
);
881 if (PreviousMode
!= KernelMode
)
885 memcpy(BaseAddress
, SystemAddress
, NumberOfBytesToWrite
);
889 CopyStatus
= _SEH_GetExceptionCode();
895 memcpy(BaseAddress
, SystemAddress
, NumberOfBytesToWrite
);
902 if (Mdl
->MappedSystemVa
!= NULL
)
904 MmUnmapLockedPages(Mdl
->MappedSystemVa
, Mdl
);
909 ObDereferenceObject(Process
);
911 if (NT_SUCCESS(CopyStatus
) && NumberOfBytesWritten
!= NULL
)
913 if (PreviousMode
!= KernelMode
)
917 *NumberOfBytesWritten
= NumberOfBytesToWrite
;
921 Status
= _SEH_GetExceptionCode();
927 *NumberOfBytesWritten
= NumberOfBytesToWrite
;
931 return(NT_SUCCESS(CopyStatus
) ? Status
: CopyStatus
);
940 MmGetVirtualForPhysical (
941 IN PHYSICAL_ADDRESS PhysicalAddress
949 * Called from EngSecureMem (subsys\win32k\eng\mem.c)
953 MmSecureVirtualMemory (PVOID Address
,
957 /* Only works for user space */
958 if (MmHighestUserAddress
< Address
)
970 * Called from EngUnsecureMem (subsys\win32k\eng\mem.c)
974 MmUnsecureVirtualMemory(PVOID SecureMem
)
976 if (NULL
== SecureMem
)
989 ProbeForRead (IN CONST VOID
*Address
,
995 ASSERT(Alignment
== 1 || Alignment
== 2 || Alignment
== 4 || Alignment
== 8);
997 if (((ULONG_PTR
)Address
& (Alignment
- 1)) != 0)
999 ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT
);
1001 else if ((ULONG_PTR
)Address
+ Length
- 1 < (ULONG_PTR
)Address
||
1002 (ULONG_PTR
)Address
+ Length
- 1 >= (ULONG_PTR
)MmUserProbeAddress
)
1004 ExRaiseStatus (STATUS_ACCESS_VIOLATION
);
1014 ProbeForWrite (IN PVOID Address
,
1018 volatile CHAR
*Current
;
1023 ASSERT(Alignment
== 1 || Alignment
== 2 || Alignment
== 4 || Alignment
== 8);
1025 if (((ULONG_PTR
)Address
& (Alignment
- 1)) != 0)
1027 ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT
);
1030 Last
= (PCHAR
)((ULONG_PTR
)Address
+ Length
- 1);
1031 if ((ULONG_PTR
)Last
< (ULONG_PTR
)Address
||
1032 (ULONG_PTR
)Last
>= (ULONG_PTR
)MmUserProbeAddress
)
1034 ExRaiseStatus (STATUS_ACCESS_VIOLATION
);
1037 /* Check for accessible pages, do *not* touch any memory outside of the
1039 Current
= (volatile CHAR
*)Address
;
1040 Last
= (PCHAR
)(PAGE_ROUND_DOWN(Last
));
1043 *Current
= *Current
;
1044 Current
= (volatile CHAR
*)(PAGE_ROUND_DOWN(Current
) + PAGE_SIZE
);
1045 } while (Current
<= Last
);