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.67 2003/07/10 21:05:04 royce 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 *****************************************************************/
46 NtFlushVirtualMemory(IN HANDLE ProcessHandle
,
48 IN ULONG NumberOfBytesToFlush
,
49 OUT PULONG NumberOfBytesFlushed OPTIONAL
)
51 * FUNCTION: Flushes virtual memory to file
53 * ProcessHandle = Points to the process that allocated the virtual
55 * BaseAddress = Points to the memory address
56 * NumberOfBytesToFlush = Limits the range to flush,
57 * NumberOfBytesFlushed = Actual number of bytes flushed
68 NtLockVirtualMemory(HANDLE ProcessHandle
,
70 ULONG NumberOfBytesToLock
,
71 PULONG NumberOfBytesLocked
)
80 NtQueryVirtualMemory (IN HANDLE ProcessHandle
,
82 IN CINT VirtualMemoryInformationClass
,
83 OUT PVOID VirtualMemoryInformation
,
85 OUT PULONG UnsafeResultLength
)
89 MEMORY_AREA
* MemoryArea
;
90 ULONG ResultLength
= 0;
91 PMADDRESS_SPACE AddressSpace
;
93 DPRINT("NtQueryVirtualMemory(ProcessHandle %x, Address %x, "
94 "VirtualMemoryInformationClass %d, VirtualMemoryInformation %x, "
95 "Length %lu ResultLength %x)\n",ProcessHandle
,Address
,
96 VirtualMemoryInformationClass
,VirtualMemoryInformation
,
99 Status
= ObReferenceObjectByHandle(ProcessHandle
,
100 PROCESS_QUERY_INFORMATION
,
106 if (!NT_SUCCESS(Status
))
108 DPRINT("NtQueryVirtualMemory() = %x\n",Status
);
112 AddressSpace
= &Process
->AddressSpace
;
113 MmLockAddressSpace(AddressSpace
);
114 MemoryArea
= MmOpenMemoryAreaByAddress(AddressSpace
,
116 switch(VirtualMemoryInformationClass
)
118 case MemoryBasicInformation
:
120 PMEMORY_BASIC_INFORMATION Info
=
121 (PMEMORY_BASIC_INFORMATION
)VirtualMemoryInformation
;
123 if (Length
!= sizeof(MEMORY_BASIC_INFORMATION
))
125 MmUnlockAddressSpace(AddressSpace
);
126 ObDereferenceObject(Process
);
127 return(STATUS_INFO_LENGTH_MISMATCH
);
130 if (MemoryArea
== NULL
)
132 Info
->State
= MEM_FREE
;
133 Info
->BaseAddress
= (PVOID
)PAGE_ROUND_DOWN(Address
);
134 Status
= STATUS_SUCCESS
;
135 ResultLength
= sizeof(MEMORY_BASIC_INFORMATION
);
137 else if (MemoryArea
->Type
== MEMORY_AREA_VIRTUAL_MEMORY
)
139 Status
= MmQueryAnonMem(MemoryArea
, Address
, Info
,
142 else if (MemoryArea
->Type
== MEMORY_AREA_SECTION_VIEW
)
144 Status
= MmQuerySectionView(MemoryArea
, Address
, Info
,
149 Status
= STATUS_UNSUCCESSFUL
;
157 Status
= STATUS_INVALID_INFO_CLASS
;
163 MmUnlockAddressSpace(AddressSpace
);
164 ObDereferenceObject(Process
);
165 if (UnsafeResultLength
!= NULL
)
167 MmCopyToCaller(UnsafeResultLength
, &ResultLength
, sizeof(ULONG
));
176 NtProtectVirtualMemory(IN HANDLE ProcessHandle
,
177 IN PVOID BaseAddress
,
178 IN ULONG NumberOfBytesToProtect
,
179 IN ULONG NewAccessProtection
,
180 OUT PULONG UnsafeOldAccessProtection
)
182 PMEMORY_AREA MemoryArea
;
185 PMADDRESS_SPACE AddressSpace
;
186 ULONG OldAccessProtection
;
188 NumberOfBytesToProtect
=
189 PAGE_ROUND_UP(BaseAddress
+ NumberOfBytesToProtect
) -
190 PAGE_ROUND_DOWN(BaseAddress
);
191 BaseAddress
= (PVOID
)PAGE_ROUND_DOWN(BaseAddress
);
193 Status
= ObReferenceObjectByHandle(ProcessHandle
,
194 PROCESS_VM_OPERATION
,
199 if (Status
!= STATUS_SUCCESS
)
201 DPRINT("NtProtectVirtualMemory() = %x\n",Status
);
205 AddressSpace
= &Process
->AddressSpace
;
207 MmLockAddressSpace(AddressSpace
);
208 MemoryArea
= MmOpenMemoryAreaByAddress(AddressSpace
,
210 if (MemoryArea
== NULL
)
212 MmUnlockAddressSpace(AddressSpace
);
213 ObDereferenceObject(Process
);
214 return(STATUS_UNSUCCESSFUL
);
217 if (MemoryArea
->Type
== MEMORY_AREA_VIRTUAL_MEMORY
)
219 Status
= MmProtectAnonMem(AddressSpace
, MemoryArea
, BaseAddress
,
220 NumberOfBytesToProtect
, NewAccessProtection
,
221 &OldAccessProtection
);
223 else if (MemoryArea
->Type
== MEMORY_AREA_SECTION_VIEW
)
225 Status
= MmProtectSectionView(AddressSpace
, MemoryArea
, BaseAddress
,
226 NumberOfBytesToProtect
,
228 &OldAccessProtection
);
231 MmUnlockAddressSpace(AddressSpace
);
232 ObDereferenceObject(Process
);
234 MmCopyToCaller(UnsafeOldAccessProtection
, &OldAccessProtection
,
244 NtReadVirtualMemory(IN HANDLE ProcessHandle
,
245 IN PVOID BaseAddress
,
247 IN ULONG NumberOfBytesToRead
,
248 OUT PULONG NumberOfBytesRead
)
255 DPRINT("NtReadVirtualMemory(ProcessHandle %x, BaseAddress %x, "
256 "Buffer %x, NumberOfBytesToRead %d)\n",ProcessHandle
,BaseAddress
,
257 Buffer
,NumberOfBytesToRead
);
259 Status
= ObReferenceObjectByHandle(ProcessHandle
,
265 if (Status
!= STATUS_SUCCESS
)
270 Mdl
= MmCreateMdl(NULL
,
272 NumberOfBytesToRead
);
273 MmProbeAndLockPages(Mdl
,
277 KeAttachProcess(Process
);
279 SystemAddress
= MmGetSystemAddressForMdl(Mdl
);
280 memcpy(SystemAddress
, BaseAddress
, NumberOfBytesToRead
);
284 if (Mdl
->MappedSystemVa
!= NULL
)
286 MmUnmapLockedPages(Mdl
->MappedSystemVa
, Mdl
);
291 ObDereferenceObject(Process
);
293 *NumberOfBytesRead
= NumberOfBytesToRead
;
294 return(STATUS_SUCCESS
);
301 NtUnlockVirtualMemory(HANDLE ProcessHandle
,
303 ULONG NumberOfBytesToUnlock
,
304 PULONG NumberOfBytesUnlocked OPTIONAL
)
314 NtWriteVirtualMemory(IN HANDLE ProcessHandle
,
315 IN PVOID BaseAddress
,
317 IN ULONG NumberOfBytesToWrite
,
318 OUT PULONG NumberOfBytesWritten
)
325 DPRINT("NtWriteVirtualMemory(ProcessHandle %x, BaseAddress %x, "
326 "Buffer %x, NumberOfBytesToWrite %d)\n",ProcessHandle
,BaseAddress
,
327 Buffer
,NumberOfBytesToWrite
);
329 Status
= ObReferenceObjectByHandle(ProcessHandle
,
335 if (Status
!= STATUS_SUCCESS
)
340 Mdl
= MmCreateMdl(NULL
,
342 NumberOfBytesToWrite
);
343 MmProbeAndLockPages(Mdl
,
347 KeAttachProcess(Process
);
349 SystemAddress
= MmGetSystemAddressForMdl(Mdl
);
350 memcpy(BaseAddress
, SystemAddress
, NumberOfBytesToWrite
);
354 ObDereferenceObject(Process
);
356 if (Mdl
->MappedSystemVa
!= NULL
)
358 MmUnmapLockedPages(Mdl
->MappedSystemVa
, Mdl
);
363 *NumberOfBytesWritten
= NumberOfBytesToWrite
;
365 return(STATUS_SUCCESS
);
372 MmSecureVirtualMemory (PVOID Address
,
376 /* Only works for user space */
377 if (MmHighestUserAddress
< Address
)
392 MmUnsecureVirtualMemory(PVOID SecureMem
)
394 if (NULL
== SecureMem
)