Reverted latest changes.
[reactos.git] / reactos / ntoskrnl / mm / virtual.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /* $Id: virtual.c,v 1.64 2002/09/08 10:23:37 chorns Exp $
20 *
21 * PROJECT: ReactOS kernel
22 * FILE: ntoskrnl/mm/virtual.c
23 * PURPOSE: Implementing operations on virtual memory.
24 * PROGRAMMER: David Welch
25 */
26
27 /* INCLUDE *****************************************************************/
28
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>
36
37 #define NDEBUG
38 #include <internal/debug.h>
39
40 /* FUNCTIONS *****************************************************************/
41
42 NTSTATUS STDCALL
43 NtFlushVirtualMemory(IN HANDLE ProcessHandle,
44 IN PVOID BaseAddress,
45 IN ULONG NumberOfBytesToFlush,
46 OUT PULONG NumberOfBytesFlushed OPTIONAL)
47 /*
48 * FUNCTION: Flushes virtual memory to file
49 * ARGUMENTS:
50 * ProcessHandle = Points to the process that allocated the virtual
51 * memory
52 * BaseAddress = Points to the memory address
53 * NumberOfBytesToFlush = Limits the range to flush,
54 * NumberOfBytesFlushed = Actual number of bytes flushed
55 * RETURNS: Status
56 */
57 {
58 UNIMPLEMENTED;
59 }
60
61 NTSTATUS STDCALL
62 NtLockVirtualMemory(HANDLE ProcessHandle,
63 PVOID BaseAddress,
64 ULONG NumberOfBytesToLock,
65 PULONG NumberOfBytesLocked)
66 {
67 UNIMPLEMENTED;
68 }
69
70 NTSTATUS STDCALL
71 NtQueryVirtualMemory (IN HANDLE ProcessHandle,
72 IN PVOID Address,
73 IN CINT VirtualMemoryInformationClass,
74 OUT PVOID VirtualMemoryInformation,
75 IN ULONG Length,
76 OUT PULONG UnsafeResultLength)
77 {
78 NTSTATUS Status;
79 PEPROCESS Process;
80 MEMORY_AREA* MemoryArea;
81 ULONG ResultLength = 0;
82 PMADDRESS_SPACE AddressSpace;
83
84 DPRINT("NtQueryVirtualMemory(ProcessHandle %x, Address %x, "
85 "VirtualMemoryInformationClass %d, VirtualMemoryInformation %x, "
86 "Length %lu ResultLength %x)\n",ProcessHandle,Address,
87 VirtualMemoryInformationClass,VirtualMemoryInformation,
88 Length,ResultLength);
89
90 Status = ObReferenceObjectByHandle(ProcessHandle,
91 PROCESS_QUERY_INFORMATION,
92 NULL,
93 UserMode,
94 (PVOID*)(&Process),
95 NULL);
96
97 if (!NT_SUCCESS(Status))
98 {
99 DPRINT("NtQueryVirtualMemory() = %x\n",Status);
100 return(Status);
101 }
102
103 AddressSpace = &Process->AddressSpace;
104 MmLockAddressSpace(AddressSpace);
105 MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
106 Address);
107 switch(VirtualMemoryInformationClass)
108 {
109 case MemoryBasicInformation:
110 {
111 PMEMORY_BASIC_INFORMATION Info =
112 (PMEMORY_BASIC_INFORMATION)VirtualMemoryInformation;
113
114 if (Length != sizeof(MEMORY_BASIC_INFORMATION))
115 {
116 ObDereferenceObject(Process);
117 return(STATUS_INFO_LENGTH_MISMATCH);
118 }
119
120 if (MemoryArea == NULL)
121 {
122 Info->State = MEM_FREE;
123 Info->BaseAddress = (PVOID)PAGE_ROUND_DOWN(Address);
124 Status = STATUS_SUCCESS;
125 ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
126 }
127 else if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY)
128 {
129 Status = MmQueryAnonMem(MemoryArea, Address, Info,
130 &ResultLength);
131 }
132 else if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW)
133 {
134 Status = MmQuerySectionView(MemoryArea, Address, Info,
135 &ResultLength);
136 }
137 else
138 {
139 Status = STATUS_UNSUCCESSFUL;
140 ResultLength = 0;
141 }
142 break;
143 }
144
145 default:
146 {
147 Status = STATUS_INVALID_INFO_CLASS;
148 ResultLength = 0;
149 break;
150 }
151 }
152
153 MmUnlockAddressSpace(AddressSpace);
154 ObDereferenceObject(Process);
155 if (UnsafeResultLength != NULL)
156 {
157 MmCopyToCaller(UnsafeResultLength, &ResultLength, sizeof(ULONG));
158 }
159 return(Status);
160 }
161
162 NTSTATUS STDCALL
163 NtProtectVirtualMemory(IN HANDLE ProcessHandle,
164 IN PVOID BaseAddress,
165 IN ULONG NumberOfBytesToProtect,
166 IN ULONG NewAccessProtection,
167 OUT PULONG UnsafeOldAccessProtection)
168 {
169 PMEMORY_AREA MemoryArea;
170 PEPROCESS Process;
171 NTSTATUS Status;
172 PMADDRESS_SPACE AddressSpace;
173 ULONG OldAccessProtection;
174
175 NumberOfBytesToProtect =
176 PAGE_ROUND_UP(BaseAddress + NumberOfBytesToProtect) -
177 PAGE_ROUND_DOWN(BaseAddress);
178 BaseAddress = (PVOID)PAGE_ROUND_DOWN(BaseAddress);
179
180 Status = ObReferenceObjectByHandle(ProcessHandle,
181 PROCESS_VM_OPERATION,
182 PsProcessType,
183 UserMode,
184 (PVOID*)(&Process),
185 NULL);
186 if (Status != STATUS_SUCCESS)
187 {
188 DPRINT("NtProtectVirtualMemory() = %x\n",Status);
189 return(Status);
190 }
191
192 AddressSpace = &Process->AddressSpace;
193
194 MmLockAddressSpace(AddressSpace);
195 MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
196 BaseAddress);
197 if (MemoryArea == NULL)
198 {
199 MmUnlockAddressSpace(AddressSpace);
200 ObDereferenceObject(Process);
201 return(STATUS_UNSUCCESSFUL);
202 }
203
204 if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY)
205 {
206 Status = MmProtectAnonMem(AddressSpace, MemoryArea, BaseAddress,
207 NumberOfBytesToProtect, NewAccessProtection,
208 &OldAccessProtection);
209 }
210 else if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW)
211 {
212 Status = MmProtectSectionView(AddressSpace, MemoryArea, BaseAddress,
213 NumberOfBytesToProtect,
214 NewAccessProtection,
215 &OldAccessProtection);
216 }
217
218 MmUnlockAddressSpace(AddressSpace);
219 ObDereferenceObject(Process);
220
221 MmCopyToCaller(UnsafeOldAccessProtection, &OldAccessProtection,
222 sizeof(ULONG));
223
224 return(Status);
225 }
226
227 NTSTATUS STDCALL
228 NtReadVirtualMemory(IN HANDLE ProcessHandle,
229 IN PVOID BaseAddress,
230 OUT PVOID Buffer,
231 IN ULONG NumberOfBytesToRead,
232 OUT PULONG NumberOfBytesRead)
233 {
234 NTSTATUS Status;
235 PMDL Mdl;
236 PVOID SystemAddress;
237 PEPROCESS Process;
238
239 DPRINT("NtReadVirtualMemory(ProcessHandle %x, BaseAddress %x, "
240 "Buffer %x, NumberOfBytesToRead %d)\n",ProcessHandle,BaseAddress,
241 Buffer,NumberOfBytesToRead);
242
243 Status = ObReferenceObjectByHandle(ProcessHandle,
244 PROCESS_VM_WRITE,
245 NULL,
246 UserMode,
247 (PVOID*)(&Process),
248 NULL);
249 if (Status != STATUS_SUCCESS)
250 {
251 return(Status);
252 }
253
254 Mdl = MmCreateMdl(NULL,
255 Buffer,
256 NumberOfBytesToRead);
257 MmProbeAndLockPages(Mdl,
258 UserMode,
259 IoWriteAccess);
260
261 KeAttachProcess(Process);
262
263 SystemAddress = MmGetSystemAddressForMdl(Mdl);
264 memcpy(SystemAddress, BaseAddress, NumberOfBytesToRead);
265
266 KeDetachProcess();
267
268 if (Mdl->MappedSystemVa != NULL)
269 {
270 MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
271 }
272 MmUnlockPages(Mdl);
273 ExFreePool(Mdl);
274
275 ObDereferenceObject(Process);
276
277 *NumberOfBytesRead = NumberOfBytesToRead;
278 return(STATUS_SUCCESS);
279 }
280
281 NTSTATUS STDCALL
282 NtUnlockVirtualMemory(HANDLE ProcessHandle,
283 PVOID BaseAddress,
284 ULONG NumberOfBytesToUnlock,
285 PULONG NumberOfBytesUnlocked OPTIONAL)
286 {
287 UNIMPLEMENTED;
288 }
289
290
291 NTSTATUS STDCALL
292 NtWriteVirtualMemory(IN HANDLE ProcessHandle,
293 IN PVOID BaseAddress,
294 IN PVOID Buffer,
295 IN ULONG NumberOfBytesToWrite,
296 OUT PULONG NumberOfBytesWritten)
297 {
298 NTSTATUS Status;
299 PMDL Mdl;
300 PVOID SystemAddress;
301 PEPROCESS Process;
302
303 DPRINT("NtWriteVirtualMemory(ProcessHandle %x, BaseAddress %x, "
304 "Buffer %x, NumberOfBytesToWrite %d)\n",ProcessHandle,BaseAddress,
305 Buffer,NumberOfBytesToWrite);
306
307 Status = ObReferenceObjectByHandle(ProcessHandle,
308 PROCESS_VM_WRITE,
309 NULL,
310 UserMode,
311 (PVOID*)(&Process),
312 NULL);
313 if (Status != STATUS_SUCCESS)
314 {
315 return(Status);
316 }
317
318 Mdl = MmCreateMdl(NULL,
319 Buffer,
320 NumberOfBytesToWrite);
321 MmProbeAndLockPages(Mdl,
322 UserMode,
323 IoReadAccess);
324
325 KeAttachProcess(Process);
326
327 SystemAddress = MmGetSystemAddressForMdl(Mdl);
328 memcpy(BaseAddress, SystemAddress, NumberOfBytesToWrite);
329
330 KeDetachProcess();
331
332 ObDereferenceObject(Process);
333
334 if (Mdl->MappedSystemVa != NULL)
335 {
336 MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
337 }
338 MmUnlockPages(Mdl);
339 ExFreePool(Mdl);
340
341 *NumberOfBytesWritten = NumberOfBytesToWrite;
342
343 return(STATUS_SUCCESS);
344 }
345
346 DWORD STDCALL
347 MmSecureVirtualMemory (DWORD Unknown0,
348 DWORD Unknown1,
349 DWORD Unknown2)
350 {
351 UNIMPLEMENTED;
352 return 0;
353 }
354
355
356 VOID STDCALL
357 MmUnsecureVirtualMemory (DWORD Unknown0)
358 {
359 UNIMPLEMENTED;
360 }
361
362 /* EOF */