@implemented and @unimplemented comments for ntoskrnl/mm/*.c and also added a few...
[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.67 2003/07/10 21:05:04 royce 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 /*
43 * @unimplemented
44 */
45 NTSTATUS STDCALL
46 NtFlushVirtualMemory(IN HANDLE ProcessHandle,
47 IN PVOID BaseAddress,
48 IN ULONG NumberOfBytesToFlush,
49 OUT PULONG NumberOfBytesFlushed OPTIONAL)
50 /*
51 * FUNCTION: Flushes virtual memory to file
52 * ARGUMENTS:
53 * ProcessHandle = Points to the process that allocated the virtual
54 * memory
55 * BaseAddress = Points to the memory address
56 * NumberOfBytesToFlush = Limits the range to flush,
57 * NumberOfBytesFlushed = Actual number of bytes flushed
58 * RETURNS: Status
59 */
60 {
61 UNIMPLEMENTED;
62 }
63
64 /*
65 * @unimplemented
66 */
67 NTSTATUS STDCALL
68 NtLockVirtualMemory(HANDLE ProcessHandle,
69 PVOID BaseAddress,
70 ULONG NumberOfBytesToLock,
71 PULONG NumberOfBytesLocked)
72 {
73 UNIMPLEMENTED;
74 }
75
76 /*
77 * @implemented
78 */
79 NTSTATUS STDCALL
80 NtQueryVirtualMemory (IN HANDLE ProcessHandle,
81 IN PVOID Address,
82 IN CINT VirtualMemoryInformationClass,
83 OUT PVOID VirtualMemoryInformation,
84 IN ULONG Length,
85 OUT PULONG UnsafeResultLength)
86 {
87 NTSTATUS Status;
88 PEPROCESS Process;
89 MEMORY_AREA* MemoryArea;
90 ULONG ResultLength = 0;
91 PMADDRESS_SPACE AddressSpace;
92
93 DPRINT("NtQueryVirtualMemory(ProcessHandle %x, Address %x, "
94 "VirtualMemoryInformationClass %d, VirtualMemoryInformation %x, "
95 "Length %lu ResultLength %x)\n",ProcessHandle,Address,
96 VirtualMemoryInformationClass,VirtualMemoryInformation,
97 Length,ResultLength);
98
99 Status = ObReferenceObjectByHandle(ProcessHandle,
100 PROCESS_QUERY_INFORMATION,
101 NULL,
102 UserMode,
103 (PVOID*)(&Process),
104 NULL);
105
106 if (!NT_SUCCESS(Status))
107 {
108 DPRINT("NtQueryVirtualMemory() = %x\n",Status);
109 return(Status);
110 }
111
112 AddressSpace = &Process->AddressSpace;
113 MmLockAddressSpace(AddressSpace);
114 MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
115 Address);
116 switch(VirtualMemoryInformationClass)
117 {
118 case MemoryBasicInformation:
119 {
120 PMEMORY_BASIC_INFORMATION Info =
121 (PMEMORY_BASIC_INFORMATION)VirtualMemoryInformation;
122
123 if (Length != sizeof(MEMORY_BASIC_INFORMATION))
124 {
125 MmUnlockAddressSpace(AddressSpace);
126 ObDereferenceObject(Process);
127 return(STATUS_INFO_LENGTH_MISMATCH);
128 }
129
130 if (MemoryArea == NULL)
131 {
132 Info->State = MEM_FREE;
133 Info->BaseAddress = (PVOID)PAGE_ROUND_DOWN(Address);
134 Status = STATUS_SUCCESS;
135 ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
136 }
137 else if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY)
138 {
139 Status = MmQueryAnonMem(MemoryArea, Address, Info,
140 &ResultLength);
141 }
142 else if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW)
143 {
144 Status = MmQuerySectionView(MemoryArea, Address, Info,
145 &ResultLength);
146 }
147 else
148 {
149 Status = STATUS_UNSUCCESSFUL;
150 ResultLength = 0;
151 }
152 break;
153 }
154
155 default:
156 {
157 Status = STATUS_INVALID_INFO_CLASS;
158 ResultLength = 0;
159 break;
160 }
161 }
162
163 MmUnlockAddressSpace(AddressSpace);
164 ObDereferenceObject(Process);
165 if (UnsafeResultLength != NULL)
166 {
167 MmCopyToCaller(UnsafeResultLength, &ResultLength, sizeof(ULONG));
168 }
169 return(Status);
170 }
171
172 /*
173 * @implemented
174 */
175 NTSTATUS STDCALL
176 NtProtectVirtualMemory(IN HANDLE ProcessHandle,
177 IN PVOID BaseAddress,
178 IN ULONG NumberOfBytesToProtect,
179 IN ULONG NewAccessProtection,
180 OUT PULONG UnsafeOldAccessProtection)
181 {
182 PMEMORY_AREA MemoryArea;
183 PEPROCESS Process;
184 NTSTATUS Status;
185 PMADDRESS_SPACE AddressSpace;
186 ULONG OldAccessProtection;
187
188 NumberOfBytesToProtect =
189 PAGE_ROUND_UP(BaseAddress + NumberOfBytesToProtect) -
190 PAGE_ROUND_DOWN(BaseAddress);
191 BaseAddress = (PVOID)PAGE_ROUND_DOWN(BaseAddress);
192
193 Status = ObReferenceObjectByHandle(ProcessHandle,
194 PROCESS_VM_OPERATION,
195 PsProcessType,
196 UserMode,
197 (PVOID*)(&Process),
198 NULL);
199 if (Status != STATUS_SUCCESS)
200 {
201 DPRINT("NtProtectVirtualMemory() = %x\n",Status);
202 return(Status);
203 }
204
205 AddressSpace = &Process->AddressSpace;
206
207 MmLockAddressSpace(AddressSpace);
208 MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
209 BaseAddress);
210 if (MemoryArea == NULL)
211 {
212 MmUnlockAddressSpace(AddressSpace);
213 ObDereferenceObject(Process);
214 return(STATUS_UNSUCCESSFUL);
215 }
216
217 if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY)
218 {
219 Status = MmProtectAnonMem(AddressSpace, MemoryArea, BaseAddress,
220 NumberOfBytesToProtect, NewAccessProtection,
221 &OldAccessProtection);
222 }
223 else if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW)
224 {
225 Status = MmProtectSectionView(AddressSpace, MemoryArea, BaseAddress,
226 NumberOfBytesToProtect,
227 NewAccessProtection,
228 &OldAccessProtection);
229 }
230
231 MmUnlockAddressSpace(AddressSpace);
232 ObDereferenceObject(Process);
233
234 MmCopyToCaller(UnsafeOldAccessProtection, &OldAccessProtection,
235 sizeof(ULONG));
236
237 return(Status);
238 }
239
240 /*
241 * @implemented
242 */
243 NTSTATUS STDCALL
244 NtReadVirtualMemory(IN HANDLE ProcessHandle,
245 IN PVOID BaseAddress,
246 OUT PVOID Buffer,
247 IN ULONG NumberOfBytesToRead,
248 OUT PULONG NumberOfBytesRead)
249 {
250 NTSTATUS Status;
251 PMDL Mdl;
252 PVOID SystemAddress;
253 PEPROCESS Process;
254
255 DPRINT("NtReadVirtualMemory(ProcessHandle %x, BaseAddress %x, "
256 "Buffer %x, NumberOfBytesToRead %d)\n",ProcessHandle,BaseAddress,
257 Buffer,NumberOfBytesToRead);
258
259 Status = ObReferenceObjectByHandle(ProcessHandle,
260 PROCESS_VM_WRITE,
261 NULL,
262 UserMode,
263 (PVOID*)(&Process),
264 NULL);
265 if (Status != STATUS_SUCCESS)
266 {
267 return(Status);
268 }
269
270 Mdl = MmCreateMdl(NULL,
271 Buffer,
272 NumberOfBytesToRead);
273 MmProbeAndLockPages(Mdl,
274 UserMode,
275 IoWriteAccess);
276
277 KeAttachProcess(Process);
278
279 SystemAddress = MmGetSystemAddressForMdl(Mdl);
280 memcpy(SystemAddress, BaseAddress, NumberOfBytesToRead);
281
282 KeDetachProcess();
283
284 if (Mdl->MappedSystemVa != NULL)
285 {
286 MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
287 }
288 MmUnlockPages(Mdl);
289 ExFreePool(Mdl);
290
291 ObDereferenceObject(Process);
292
293 *NumberOfBytesRead = NumberOfBytesToRead;
294 return(STATUS_SUCCESS);
295 }
296
297 /*
298 * @unimplemented
299 */
300 NTSTATUS STDCALL
301 NtUnlockVirtualMemory(HANDLE ProcessHandle,
302 PVOID BaseAddress,
303 ULONG NumberOfBytesToUnlock,
304 PULONG NumberOfBytesUnlocked OPTIONAL)
305 {
306 UNIMPLEMENTED;
307 }
308
309
310 /*
311 * @implemented
312 */
313 NTSTATUS STDCALL
314 NtWriteVirtualMemory(IN HANDLE ProcessHandle,
315 IN PVOID BaseAddress,
316 IN PVOID Buffer,
317 IN ULONG NumberOfBytesToWrite,
318 OUT PULONG NumberOfBytesWritten)
319 {
320 NTSTATUS Status;
321 PMDL Mdl;
322 PVOID SystemAddress;
323 PEPROCESS Process;
324
325 DPRINT("NtWriteVirtualMemory(ProcessHandle %x, BaseAddress %x, "
326 "Buffer %x, NumberOfBytesToWrite %d)\n",ProcessHandle,BaseAddress,
327 Buffer,NumberOfBytesToWrite);
328
329 Status = ObReferenceObjectByHandle(ProcessHandle,
330 PROCESS_VM_WRITE,
331 NULL,
332 UserMode,
333 (PVOID*)(&Process),
334 NULL);
335 if (Status != STATUS_SUCCESS)
336 {
337 return(Status);
338 }
339
340 Mdl = MmCreateMdl(NULL,
341 Buffer,
342 NumberOfBytesToWrite);
343 MmProbeAndLockPages(Mdl,
344 UserMode,
345 IoReadAccess);
346
347 KeAttachProcess(Process);
348
349 SystemAddress = MmGetSystemAddressForMdl(Mdl);
350 memcpy(BaseAddress, SystemAddress, NumberOfBytesToWrite);
351
352 KeDetachProcess();
353
354 ObDereferenceObject(Process);
355
356 if (Mdl->MappedSystemVa != NULL)
357 {
358 MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
359 }
360 MmUnlockPages(Mdl);
361 ExFreePool(Mdl);
362
363 *NumberOfBytesWritten = NumberOfBytesToWrite;
364
365 return(STATUS_SUCCESS);
366 }
367
368 /*
369 * @unimplemented
370 */
371 PVOID STDCALL
372 MmSecureVirtualMemory (PVOID Address,
373 SIZE_T Length,
374 ULONG Mode)
375 {
376 /* Only works for user space */
377 if (MmHighestUserAddress < Address)
378 {
379 return NULL;
380 }
381
382 UNIMPLEMENTED;
383
384 return 0;
385 }
386
387
388 /*
389 * @unimplemented
390 */
391 VOID STDCALL
392 MmUnsecureVirtualMemory(PVOID SecureMem)
393 {
394 if (NULL == SecureMem)
395 {
396 return;
397 }
398
399 UNIMPLEMENTED;
400 }
401
402 /* EOF */