:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[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              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 */