branch update for HEAD-2003050101
[reactos.git] / 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$
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              MmUnlockAddressSpace(AddressSpace);
117              ObDereferenceObject(Process);
118              return(STATUS_INFO_LENGTH_MISMATCH);
119            }
120          
121          if (MemoryArea == NULL)
122            {
123              Info->State = MEM_FREE;
124              Info->BaseAddress = (PVOID)PAGE_ROUND_DOWN(Address);
125              Status = STATUS_SUCCESS;
126              ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
127            }
128          else if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY)
129            {
130              Status = MmQueryAnonMem(MemoryArea, Address, Info, 
131                                      &ResultLength);
132            }
133          else if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW)
134            {
135              Status = MmQuerySectionView(MemoryArea, Address, Info, 
136                                          &ResultLength);
137            }
138          else
139            {
140              Status = STATUS_UNSUCCESSFUL;
141              ResultLength = 0;
142            }
143          break;
144        }
145        
146      default:
147        {
148          Status = STATUS_INVALID_INFO_CLASS;
149          ResultLength = 0;
150          break;
151        }
152      }
153
154    MmUnlockAddressSpace(AddressSpace);
155    ObDereferenceObject(Process);
156    if (UnsafeResultLength != NULL)
157      {
158        MmCopyToCaller(UnsafeResultLength, &ResultLength, sizeof(ULONG));
159      }
160    return(Status);
161 }
162
163 NTSTATUS STDCALL
164 NtProtectVirtualMemory(IN       HANDLE  ProcessHandle,
165                        IN       PVOID   BaseAddress,
166                        IN       ULONG   NumberOfBytesToProtect,
167                        IN       ULONG   NewAccessProtection,
168                        OUT      PULONG  UnsafeOldAccessProtection)
169 {
170    PMEMORY_AREA MemoryArea;
171    PEPROCESS Process;
172    NTSTATUS Status;
173    PMADDRESS_SPACE AddressSpace;
174    ULONG OldAccessProtection;
175
176    NumberOfBytesToProtect =
177      PAGE_ROUND_UP(BaseAddress + NumberOfBytesToProtect) -
178      PAGE_ROUND_DOWN(BaseAddress);
179    BaseAddress = (PVOID)PAGE_ROUND_DOWN(BaseAddress);
180    
181    Status = ObReferenceObjectByHandle(ProcessHandle,
182                                       PROCESS_VM_OPERATION,
183                                       PsProcessType,
184                                       UserMode,
185                                       (PVOID*)(&Process),
186                                       NULL);
187    if (Status != STATUS_SUCCESS)
188      {
189         DPRINT("NtProtectVirtualMemory() = %x\n",Status);
190         return(Status);
191      }
192
193    AddressSpace = &Process->AddressSpace;
194    
195    MmLockAddressSpace(AddressSpace);
196    MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
197                                           BaseAddress);
198    if (MemoryArea == NULL)
199      {
200        MmUnlockAddressSpace(AddressSpace);
201        ObDereferenceObject(Process);
202        return(STATUS_UNSUCCESSFUL);
203      }
204    
205    if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY)
206      {
207        Status = MmProtectAnonMem(AddressSpace, MemoryArea, BaseAddress,
208                                  NumberOfBytesToProtect, NewAccessProtection,
209                                  &OldAccessProtection);
210      }
211    else if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW)
212      {
213        Status = MmProtectSectionView(AddressSpace, MemoryArea, BaseAddress,
214                                      NumberOfBytesToProtect, 
215                                      NewAccessProtection,
216                                      &OldAccessProtection);
217      }
218    
219    MmUnlockAddressSpace(AddressSpace);
220    ObDereferenceObject(Process);
221
222    MmCopyToCaller(UnsafeOldAccessProtection, &OldAccessProtection, 
223                   sizeof(ULONG));
224
225    return(Status);
226 }
227
228 NTSTATUS STDCALL 
229 NtReadVirtualMemory(IN  HANDLE  ProcessHandle,
230                     IN  PVOID   BaseAddress,
231                     OUT PVOID   Buffer,
232                     IN  ULONG   NumberOfBytesToRead,
233                     OUT PULONG  NumberOfBytesRead)
234 {
235   NTSTATUS Status;
236   PMDL Mdl;
237   PVOID SystemAddress;
238   PEPROCESS Process;
239   
240   DPRINT("NtReadVirtualMemory(ProcessHandle %x, BaseAddress %x, "
241          "Buffer %x, NumberOfBytesToRead %d)\n",ProcessHandle,BaseAddress,
242          Buffer,NumberOfBytesToRead);
243   
244   Status = ObReferenceObjectByHandle(ProcessHandle,
245                                      PROCESS_VM_WRITE,
246                                      NULL,
247                                      UserMode,
248                                      (PVOID*)(&Process),
249                                      NULL);
250   if (Status != STATUS_SUCCESS)
251     {
252       return(Status);
253     }
254   
255   Mdl = MmCreateMdl(NULL, 
256                     Buffer,
257                     NumberOfBytesToRead);
258   MmProbeAndLockPages(Mdl,
259                       UserMode,
260                       IoWriteAccess);
261   
262   KeAttachProcess(Process);
263   
264   SystemAddress = MmGetSystemAddressForMdl(Mdl);
265   memcpy(SystemAddress, BaseAddress, NumberOfBytesToRead);
266   
267   KeDetachProcess();
268   
269   if (Mdl->MappedSystemVa != NULL)
270     {        
271       MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
272     }
273   MmUnlockPages(Mdl);
274   ExFreePool(Mdl);
275   
276   ObDereferenceObject(Process);
277   
278   *NumberOfBytesRead = NumberOfBytesToRead;
279   return(STATUS_SUCCESS);
280 }
281
282 NTSTATUS STDCALL 
283 NtUnlockVirtualMemory(HANDLE    ProcessHandle,
284                       PVOID     BaseAddress,
285                       ULONG     NumberOfBytesToUnlock,
286                       PULONG NumberOfBytesUnlocked OPTIONAL)
287 {
288   UNIMPLEMENTED;
289 }
290
291
292 NTSTATUS STDCALL 
293 NtWriteVirtualMemory(IN HANDLE  ProcessHandle,
294                      IN PVOID   BaseAddress,
295                      IN PVOID   Buffer,
296                      IN ULONG   NumberOfBytesToWrite,
297                      OUT        PULONG  NumberOfBytesWritten)
298 {
299    NTSTATUS Status;
300    PMDL Mdl;
301    PVOID SystemAddress;
302    PEPROCESS Process;
303    
304    DPRINT("NtWriteVirtualMemory(ProcessHandle %x, BaseAddress %x, "
305             "Buffer %x, NumberOfBytesToWrite %d)\n",ProcessHandle,BaseAddress,
306             Buffer,NumberOfBytesToWrite);
307    
308    Status = ObReferenceObjectByHandle(ProcessHandle,
309                                       PROCESS_VM_WRITE,
310                                       NULL,
311                                       UserMode,
312                                       (PVOID*)(&Process),
313                                       NULL);
314    if (Status != STATUS_SUCCESS)
315      {
316         return(Status);
317      }
318    
319    Mdl = MmCreateMdl(NULL, 
320                      Buffer,
321                      NumberOfBytesToWrite);
322    MmProbeAndLockPages(Mdl,
323                        UserMode,
324                        IoReadAccess);
325    
326    KeAttachProcess(Process);
327    
328    SystemAddress = MmGetSystemAddressForMdl(Mdl);
329    memcpy(BaseAddress, SystemAddress, NumberOfBytesToWrite);
330    
331    KeDetachProcess();
332    
333    ObDereferenceObject(Process);
334
335    if (Mdl->MappedSystemVa != NULL)
336      {       
337        MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
338      }
339    MmUnlockPages(Mdl);
340    ExFreePool(Mdl);
341    
342    *NumberOfBytesWritten = NumberOfBytesToWrite;
343    
344    return(STATUS_SUCCESS);
345 }
346
347 DWORD STDCALL
348 MmSecureVirtualMemory (DWORD    Unknown0,
349                        DWORD    Unknown1,
350                        DWORD    Unknown2)
351 {
352   UNIMPLEMENTED;
353   return 0;
354 }
355
356
357 VOID STDCALL
358 MmUnsecureVirtualMemory (DWORD Unknown0)
359 {
360   UNIMPLEMENTED;
361 }
362
363 /* EOF */