3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* $Id: virtual.c,v 1.71 2003/12/14 17:44:02 hbirr Exp $
21 * PROJECT: ReactOS kernel
22 * FILE: ntoskrnl/mm/virtual.c
23 * PURPOSE: Implementing operations on virtual memory.
24 * PROGRAMMER: David Welch
27 /* INCLUDE *****************************************************************/
29 #include <ddk/ntddk.h>
30 #include <internal/mm.h>
31 #include <internal/ob.h>
32 #include <internal/io.h>
33 #include <internal/ps.h>
34 #include <internal/pool.h>
35 #include <internal/safe.h>
38 #include <internal/debug.h>
40 /* FUNCTIONS *****************************************************************/
43 NtFlushVirtualMemory(IN HANDLE ProcessHandle
,
45 IN ULONG NumberOfBytesToFlush
,
46 OUT PULONG NumberOfBytesFlushed OPTIONAL
)
48 * FUNCTION: Flushes virtual memory to file
50 * ProcessHandle = Points to the process that allocated the virtual
52 * BaseAddress = Points to the memory address
53 * NumberOfBytesToFlush = Limits the range to flush,
54 * NumberOfBytesFlushed = Actual number of bytes flushed
59 return(STATUS_NOT_IMPLEMENTED
);
63 NtLockVirtualMemory(HANDLE ProcessHandle
,
65 ULONG NumberOfBytesToLock
,
66 PULONG NumberOfBytesLocked
) // ULONG LockOption?
68 // AG [08-20-03] : I have *no* idea if this is correct, I just used the
69 // other functions as a template and made a few intelligent guesses...
75 DPRINT("NtLockVirtualMemory(ProcessHandle %x, BaseAddress %x, "
76 "NumberOfBytesToLock %d), NumberOfBytesLocked %x\n",ProcessHandle
,BaseAddress
,
77 NumberOfBytesToLock
, NumberOfBytesLocked
);
79 Status
= ObReferenceObjectByHandle(ProcessHandle
,
85 if (Status
!= STATUS_SUCCESS
)
90 Mdl
= MmCreateMdl(NULL
,
93 MmProbeAndLockPages(Mdl
,
97 ExFreePool(Mdl
); // Are we supposed to do this here?
99 ObDereferenceObject(Process
);
101 *NumberOfBytesLocked
= NumberOfBytesToLock
;
102 return(STATUS_SUCCESS
);
106 NtQueryVirtualMemory (IN HANDLE ProcessHandle
,
108 IN CINT VirtualMemoryInformationClass
,
109 OUT PVOID VirtualMemoryInformation
,
111 OUT PULONG UnsafeResultLength
)
115 MEMORY_AREA
* MemoryArea
;
116 ULONG ResultLength
= 0;
117 PMADDRESS_SPACE AddressSpace
;
119 DPRINT("NtQueryVirtualMemory(ProcessHandle %x, Address %x, "
120 "VirtualMemoryInformationClass %d, VirtualMemoryInformation %x, "
121 "Length %lu ResultLength %x)\n",ProcessHandle
,Address
,
122 VirtualMemoryInformationClass
,VirtualMemoryInformation
,
123 Length
,ResultLength
);
125 Status
= ObReferenceObjectByHandle(ProcessHandle
,
126 PROCESS_QUERY_INFORMATION
,
132 if (!NT_SUCCESS(Status
))
134 DPRINT("NtQueryVirtualMemory() = %x\n",Status
);
138 AddressSpace
= &Process
->AddressSpace
;
139 MmLockAddressSpace(AddressSpace
);
140 MemoryArea
= MmOpenMemoryAreaByAddress(AddressSpace
,
142 switch(VirtualMemoryInformationClass
)
144 case MemoryBasicInformation
:
146 PMEMORY_BASIC_INFORMATION Info
=
147 (PMEMORY_BASIC_INFORMATION
)VirtualMemoryInformation
;
149 if (Length
!= sizeof(MEMORY_BASIC_INFORMATION
))
151 MmUnlockAddressSpace(AddressSpace
);
152 ObDereferenceObject(Process
);
153 return(STATUS_INFO_LENGTH_MISMATCH
);
156 if (MemoryArea
== NULL
)
158 Info
->State
= MEM_FREE
;
159 Info
->BaseAddress
= (PVOID
)PAGE_ROUND_DOWN(Address
);
160 Status
= STATUS_SUCCESS
;
161 ResultLength
= sizeof(MEMORY_BASIC_INFORMATION
);
163 else if (MemoryArea
->Type
== MEMORY_AREA_VIRTUAL_MEMORY
)
165 Status
= MmQueryAnonMem(MemoryArea
, Address
, Info
,
168 else if (MemoryArea
->Type
== MEMORY_AREA_SECTION_VIEW
)
170 Status
= MmQuerySectionView(MemoryArea
, Address
, Info
,
175 Status
= STATUS_UNSUCCESSFUL
;
183 Status
= STATUS_INVALID_INFO_CLASS
;
189 MmUnlockAddressSpace(AddressSpace
);
190 ObDereferenceObject(Process
);
191 if (UnsafeResultLength
!= NULL
)
193 MmCopyToCaller(UnsafeResultLength
, &ResultLength
, sizeof(ULONG
));
199 NtProtectVirtualMemory(IN HANDLE ProcessHandle
,
200 IN PVOID BaseAddress
,
201 IN ULONG NumberOfBytesToProtect
,
202 IN ULONG NewAccessProtection
,
203 OUT PULONG UnsafeOldAccessProtection
)
205 PMEMORY_AREA MemoryArea
;
208 PMADDRESS_SPACE AddressSpace
;
209 ULONG OldAccessProtection
;
211 NumberOfBytesToProtect
=
212 PAGE_ROUND_UP(BaseAddress
+ NumberOfBytesToProtect
) -
213 PAGE_ROUND_DOWN(BaseAddress
);
214 BaseAddress
= (PVOID
)PAGE_ROUND_DOWN(BaseAddress
);
216 Status
= ObReferenceObjectByHandle(ProcessHandle
,
217 PROCESS_VM_OPERATION
,
222 if (Status
!= STATUS_SUCCESS
)
224 DPRINT("NtProtectVirtualMemory() = %x\n",Status
);
228 AddressSpace
= &Process
->AddressSpace
;
230 MmLockAddressSpace(AddressSpace
);
231 MemoryArea
= MmOpenMemoryAreaByAddress(AddressSpace
,
233 if (MemoryArea
== NULL
)
235 MmUnlockAddressSpace(AddressSpace
);
236 ObDereferenceObject(Process
);
237 return(STATUS_UNSUCCESSFUL
);
240 if (MemoryArea
->Type
== MEMORY_AREA_VIRTUAL_MEMORY
)
242 Status
= MmProtectAnonMem(AddressSpace
, MemoryArea
, BaseAddress
,
243 NumberOfBytesToProtect
, NewAccessProtection
,
244 &OldAccessProtection
);
246 else if (MemoryArea
->Type
== MEMORY_AREA_SECTION_VIEW
)
248 Status
= MmProtectSectionView(AddressSpace
, MemoryArea
, BaseAddress
,
249 NumberOfBytesToProtect
,
251 &OldAccessProtection
);
254 MmUnlockAddressSpace(AddressSpace
);
255 ObDereferenceObject(Process
);
257 MmCopyToCaller(UnsafeOldAccessProtection
, &OldAccessProtection
,
264 NtReadVirtualMemory(IN HANDLE ProcessHandle
,
265 IN PVOID BaseAddress
,
267 IN ULONG NumberOfBytesToRead
,
268 OUT PULONG NumberOfBytesRead
)
275 DPRINT("NtReadVirtualMemory(ProcessHandle %x, BaseAddress %x, "
276 "Buffer %x, NumberOfBytesToRead %d)\n",ProcessHandle
,BaseAddress
,
277 Buffer
,NumberOfBytesToRead
);
279 Status
= ObReferenceObjectByHandle(ProcessHandle
,
285 if (Status
!= STATUS_SUCCESS
)
290 Mdl
= MmCreateMdl(NULL
,
292 NumberOfBytesToRead
);
293 MmProbeAndLockPages(Mdl
,
297 KeAttachProcess(Process
);
299 SystemAddress
= MmGetSystemAddressForMdl(Mdl
);
300 memcpy(SystemAddress
, BaseAddress
, NumberOfBytesToRead
);
304 if (Mdl
->MappedSystemVa
!= NULL
)
306 MmUnmapLockedPages(Mdl
->MappedSystemVa
, Mdl
);
311 ObDereferenceObject(Process
);
313 *NumberOfBytesRead
= NumberOfBytesToRead
;
314 return(STATUS_SUCCESS
);
318 NtUnlockVirtualMemory(HANDLE ProcessHandle
,
320 ULONG NumberOfBytesToUnlock
,
321 PULONG NumberOfBytesUnlocked OPTIONAL
)
323 // AG [08-20-03] : I have *no* idea if this is correct, I just used the
324 // other functions as a template and made a few intelligent guesses...
330 DPRINT("NtUnlockVirtualMemory(ProcessHandle %x, BaseAddress %x, "
331 "NumberOfBytesToUnlock %d), NumberOfBytesUnlocked %x\n",ProcessHandle
,BaseAddress
,
332 NumberOfBytesToUnlock
, NumberOfBytesUnlocked
);
334 Status
= ObReferenceObjectByHandle(ProcessHandle
,
340 if (Status
!= STATUS_SUCCESS
)
345 Mdl
= MmCreateMdl(NULL
,
347 NumberOfBytesToUnlock
);
349 ObDereferenceObject(Process
);
351 if (Mdl
->MappedSystemVa
!= NULL
)
353 MmUnmapLockedPages(Mdl
->MappedSystemVa
, Mdl
);
358 *NumberOfBytesUnlocked
= NumberOfBytesToUnlock
;
360 return(STATUS_SUCCESS
);
365 NtWriteVirtualMemory(IN HANDLE ProcessHandle
,
366 IN PVOID BaseAddress
,
368 IN ULONG NumberOfBytesToWrite
,
369 OUT PULONG NumberOfBytesWritten
)
376 DPRINT("NtWriteVirtualMemory(ProcessHandle %x, BaseAddress %x, "
377 "Buffer %x, NumberOfBytesToWrite %d)\n",ProcessHandle
,BaseAddress
,
378 Buffer
,NumberOfBytesToWrite
);
380 Status
= ObReferenceObjectByHandle(ProcessHandle
,
386 if (Status
!= STATUS_SUCCESS
)
391 Mdl
= MmCreateMdl(NULL
,
393 NumberOfBytesToWrite
);
394 MmProbeAndLockPages(Mdl
,
398 KeAttachProcess(Process
);
400 SystemAddress
= MmGetSystemAddressForMdl(Mdl
);
401 memcpy(BaseAddress
, SystemAddress
, NumberOfBytesToWrite
);
405 ObDereferenceObject(Process
);
407 if (Mdl
->MappedSystemVa
!= NULL
)
409 MmUnmapLockedPages(Mdl
->MappedSystemVa
, Mdl
);
414 *NumberOfBytesWritten
= NumberOfBytesToWrite
;
416 return(STATUS_SUCCESS
);
423 MmSecureVirtualMemory (PVOID Address
,
427 /* Only works for user space */
428 if (MmHighestUserAddress
< Address
)
443 MmUnsecureVirtualMemory(PVOID SecureMem
)
445 if (NULL
== SecureMem
)
458 ProbeForRead (IN PVOID Address
,
462 assert (Alignment
==1 || Alignment
== 2 || Alignment
== 4 || Alignment
== 8);
467 if (((ULONG_PTR
)Address
& (Alignment
- 1)) != 0)
469 ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT
);
471 else if ((ULONG_PTR
)Address
+ Length
< (ULONG_PTR
)Address
||
472 (ULONG_PTR
)Address
+ Length
> (ULONG_PTR
)MmUserProbeAddress
)
474 ExRaiseStatus (STATUS_ACCESS_VIOLATION
);
483 ProbeForWrite (IN PVOID Address
,
491 assert (Alignment
==1 || Alignment
== 2 || Alignment
== 4 || Alignment
== 8);
496 if (((ULONG_PTR
)Address
& (Alignment
- 1)) != 0)
498 ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT
);
500 else if ((ULONG_PTR
)Address
+ Length
< (ULONG_PTR
)Address
||
501 (ULONG_PTR
)Address
+ Length
> (ULONG_PTR
)MmUserProbeAddress
)
503 ExRaiseStatus (STATUS_ACCESS_VIOLATION
);
506 /* Check for accessible pages */
507 for (i
= 0; i
< Length
; i
+= PAGE_SIZE
)
509 Ptr
= (PULONG
)(((ULONG_PTR
)Address
& ~(PAGE_SIZE
- 1)) + i
);