2 * COPYRIGHT: See COPYING in the top directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/mm/virtual.c
5 * PURPOSE: implementing the Virtualxxx section of the win32 api
6 * PROGRAMMER: David Welch
9 * 10/6/98: Corrections from Fatahi (i_fatahi@hotmail.com)
10 * 30/9/98: Implemented ZwxxxVirtualMemory functions
13 /* INCLUDE *****************************************************************/
15 #include <internal/mm.h>
16 #include <internal/mmhal.h>
17 #include <internal/ob.h>
18 #include <internal/io.h>
19 #include <internal/ps.h>
21 #include <internal/string.h>
24 #include <internal/debug.h>
26 /* FUNCTIONS ****************************************************************/
28 NTSTATUS
MmReleaseMemoryArea(PEPROCESS Process
, PMEMORY_AREA Marea
)
32 DPRINT("MmReleaseMemoryArea(Process %x, Marea %x)\n",Process
,Marea
);
34 DPRINT("Releasing %x between %x %x\n",
35 Marea
, Marea
->BaseAddress
, Marea
->BaseAddress
+ Marea
->Length
);
36 for (i
= Marea
->BaseAddress
;
37 i
< (Marea
->BaseAddress
+ Marea
->Length
);
40 MmDeletePageEntry(Process
, i
, TRUE
);
44 return(STATUS_SUCCESS
);
47 NTSTATUS
MmReleaseMmInfo(PEPROCESS Process
)
49 PLIST_ENTRY CurrentEntry
;
52 DbgPrint("MmReleaseMmInfo(Process %x)\n",Process
);
54 while (!IsListEmpty(&Process
->Pcb
.MemoryAreaList
))
56 CurrentEntry
= RemoveHeadList(&Process
->Pcb
.MemoryAreaList
);
57 Current
= CONTAINING_RECORD(CurrentEntry
, MEMORY_AREA
, Entry
);
59 MmReleaseMemoryArea(Process
, Current
);
62 Mmi386ReleaseMmInfo(Process
);
64 DPRINT("Finished MmReleaseMmInfo()\n");
65 return(STATUS_SUCCESS
);
68 BOOLEAN
MmIsNonPagedSystemAddressValid(PVOID VirtualAddress
)
73 BOOLEAN
MmIsAddressValid(PVOID VirtualAddress
)
75 * FUNCTION: Checks whether the given address is valid for a read or write
77 * VirtualAddress = address to check
78 * RETURNS: True if the access would be valid
79 * False if the access would cause a page fault
80 * NOTES: This function checks whether a byte access to the page would
81 * succeed. Is this realistic for RISC processors which don't
82 * allow byte granular access?
85 MEMORY_AREA
* MemoryArea
;
87 MemoryArea
= MmOpenMemoryAreaByAddress(PsGetCurrentProcess(),
90 if (MemoryArea
== NULL
)
100 NtAllocateVirtualMemory (
101 IN HANDLE ProcessHandle
,
102 IN OUT PVOID
* BaseAddress
,
104 IN OUT PULONG RegionSize
,
105 IN ULONG AllocationType
,
109 * FUNCTION: Allocates a block of virtual memory in the process address space
111 * ProcessHandle = The handle of the process which owns the virtual memory
112 * BaseAddress = A pointer to the virtual memory allocated. If you
113 * supply a non zero value the system will try to
114 * allocate the memory at the address supplied. It round
115 * it down to a multiple of the page size.
116 * ZeroBits = (OPTIONAL) You can specify the number of high order bits
117 * that must be zero, ensuring that the memory will be
118 * allocated at a address below a certain value.
119 * RegionSize = The number of bytes to allocate
120 * AllocationType = Indicates the type of virtual memory you like to
121 * allocated, can be one of the values : MEM_COMMIT,
122 * MEM_RESERVE, MEM_RESET, MEM_TOP_DOWN
123 * Protect = Indicates the protection type of the pages allocated, can be
124 * a combination of PAGE_READONLY, PAGE_READWRITE,
125 * PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_GUARD,
128 * This function maps to the win32 VirtualAllocEx. Virtual memory is
129 * process based so the protocol starts with a ProcessHandle. I
130 * splitted the functionality of obtaining the actual address and
131 * specifying the start address in two parameters ( BaseAddress and
132 * StartAddress ) The NumberOfBytesAllocated specify the range and the
133 * AllocationType and ProctectionType map to the other two parameters.
138 MEMORY_AREA
* MemoryArea
;
142 DPRINT("NtAllocateVirtualMemory(ProcessHandle %x, *BaseAddress %x, "
143 "ZeroBits %d, *RegionSize %x, AllocationType %x, Protect %x)\n",
144 ProcessHandle
,*BaseAddress
,ZeroBits
,*RegionSize
,AllocationType
,
147 Status
= ObReferenceObjectByHandle(ProcessHandle
,
148 PROCESS_VM_OPERATION
,
153 if (Status
!= STATUS_SUCCESS
)
155 DPRINT("NtAllocateVirtualMemory() = %x\n",Status
);
159 if (AllocationType
& MEM_RESERVE
)
161 Type
= MEMORY_AREA_RESERVE
;
165 Type
= MEMORY_AREA_COMMIT
;
168 if ((*BaseAddress
) != 0)
170 MemoryArea
= MmOpenMemoryAreaByAddress(Process
, *BaseAddress
);
172 if (MemoryArea
!= NULL
)
174 if (MemoryArea
->BaseAddress
== (*BaseAddress
) &&
175 MemoryArea
->Length
== *RegionSize
)
177 MemoryArea
->Type
= Type
;
178 MemoryArea
->Attributes
=Protect
;
179 DPRINT("*BaseAddress %x\n",*BaseAddress
);
180 ObDereferenceObject(Process
);
181 return(STATUS_SUCCESS
);
184 MemoryArea
= MmSplitMemoryArea(Process
,
190 DPRINT("*BaseAddress %x\n",*BaseAddress
);
191 ObDereferenceObject(Process
);
192 return(STATUS_SUCCESS
);
196 //FIXME RegionSize should be passed as pointer
199 Status
= MmCreateMemoryArea(UserMode
,
207 if (Status
!= STATUS_SUCCESS
)
209 DPRINT("NtAllocateVirtualMemory() = %x\n",Status
);
210 ObDereferenceObject(Process
);
214 DPRINT("*BaseAddress %x\n",*BaseAddress
);
215 ObDereferenceObject(Process
);
216 return(STATUS_SUCCESS
);
222 NtFlushVirtualMemory (
223 IN HANDLE ProcessHandle
,
224 IN PVOID BaseAddress
,
225 IN ULONG NumberOfBytesToFlush
,
226 OUT PULONG NumberOfBytesFlushed OPTIONAL
229 * FUNCTION: Flushes virtual memory to file
231 * ProcessHandle = Points to the process that allocated the virtual
233 * BaseAddress = Points to the memory address
234 * NumberOfBytesToFlush = Limits the range to flush,
235 * NumberOfBytesFlushed = Actual number of bytes flushed
245 NtFreeVirtualMemory (
246 IN HANDLE ProcessHandle
,
247 IN PVOID
* BaseAddress
,
248 IN PULONG RegionSize
,
252 * FUNCTION: Frees a range of virtual memory
254 * ProcessHandle = Points to the process that allocated the virtual
256 * BaseAddress = Points to the memory address, rounded down to a
257 * multiple of the pagesize
258 * RegionSize = Limits the range to free, rounded up to a multiple of
260 * FreeType = Can be one of the values: MEM_DECOMMIT, or MEM_RELEASE
264 MEMORY_AREA
* MemoryArea
;
268 DPRINT("NtFreeVirtualMemory(ProcessHandle %x, *BaseAddress %x, "
269 "*RegionSize %x, FreeType %x)\n",ProcessHandle
,*BaseAddress
,
270 *RegionSize
,FreeType
);
273 Status
= ObReferenceObjectByHandle(ProcessHandle
,
274 PROCESS_VM_OPERATION
,
279 if (Status
!= STATUS_SUCCESS
)
284 MemoryArea
= MmOpenMemoryAreaByAddress(Process
,*BaseAddress
);
285 if (MemoryArea
== NULL
)
287 ObDereferenceObject(Process
);
288 return(STATUS_UNSUCCESSFUL
);
294 if (MemoryArea
->BaseAddress
!= (*BaseAddress
))
296 ObDereferenceObject(Process
);
297 return(STATUS_UNSUCCESSFUL
);
299 MmFreeMemoryArea(PsGetCurrentProcess(),
303 ObDereferenceObject(Process
);
304 return(STATUS_SUCCESS
);
307 MmSplitMemoryArea(PsGetCurrentProcess(),
312 MemoryArea
->Attributes
);
313 ObDereferenceObject(Process
);
314 return(STATUS_SUCCESS
);
316 ObDereferenceObject(Process
);
317 return(STATUS_NOT_IMPLEMENTED
);
323 NtLockVirtualMemory (
324 HANDLE ProcessHandle
,
326 ULONG NumberOfBytesToLock
,
327 PULONG NumberOfBytesLocked
334 VOID
MmChangeAreaProtection(PEPROCESS Process
,
341 for (i
=0; i
<(Length
/PAGESIZE
); i
++)
343 if (MmIsPagePresent(Process
, BaseAddress
+ (i
*PAGESIZE
)))
345 MmSetPageProtect(Process
, BaseAddress
+ (i
*PAGESIZE
), Protect
);
353 NtProtectVirtualMemory (
354 IN HANDLE ProcessHandle
,
355 IN PVOID BaseAddress
,
356 IN ULONG NumberOfBytesToProtect
,
357 IN ULONG NewAccessProtection
,
358 OUT PULONG OldAccessProtection
361 PMEMORY_AREA MemoryArea
;
365 Status
= ObReferenceObjectByHandle(ProcessHandle
,
366 PROCESS_VM_OPERATION
,
371 if (Status
!= STATUS_SUCCESS
)
373 DPRINT("NtProtectVirtualMemory() = %x\n",Status
);
377 MemoryArea
= MmOpenMemoryAreaByAddress(Process
,BaseAddress
);
378 if (MemoryArea
== NULL
)
380 DPRINT("NtProtectVirtualMemory() = %x\n",STATUS_UNSUCCESSFUL
);
381 ObDereferenceObject(Process
);
382 return(STATUS_UNSUCCESSFUL
);
385 *OldAccessProtection
= MemoryArea
->Attributes
;
387 if (MemoryArea
->BaseAddress
== BaseAddress
&&
388 MemoryArea
->Length
== NumberOfBytesToProtect
)
390 MemoryArea
->Attributes
= NewAccessProtection
;
394 MemoryArea
= MmSplitMemoryArea(Process
,
397 NumberOfBytesToProtect
,
399 NewAccessProtection
);
401 MmChangeAreaProtection(Process
,BaseAddress
,NumberOfBytesToProtect
,
402 NewAccessProtection
);
403 ObDereferenceObject(Process
);
404 return(STATUS_SUCCESS
);
410 NtQueryVirtualMemory (
411 IN HANDLE ProcessHandle
,
413 IN CINT VirtualMemoryInformationClass
,
414 OUT PVOID VirtualMemoryInformation
,
416 OUT PULONG ResultLength
425 NtReadVirtualMemory (
426 IN HANDLE ProcessHandle
,
427 IN PVOID BaseAddress
,
429 IN ULONG NumberOfBytesToRead
,
430 OUT PULONG NumberOfBytesRead
438 DPRINT("NtReadVirtualMemory(ProcessHandle %x, BaseAddress %x, "
439 "Buffer %x, NumberOfBytesToRead %d)\n",ProcessHandle
,BaseAddress
,
440 Buffer
,NumberOfBytesToRead
);
442 Status
= ObReferenceObjectByHandle(ProcessHandle
,
448 if (Status
!= STATUS_SUCCESS
)
453 Mdl
= MmCreateMdl(NULL
,
455 NumberOfBytesToRead
);
456 MmProbeAndLockPages(Mdl
,
460 KeAttachProcess(Process
);
462 SystemAddress
= MmGetSystemAddressForMdl(Mdl
);
463 memcpy(SystemAddress
, BaseAddress
, NumberOfBytesToRead
);
467 ObDereferenceObject(Process
);
469 *NumberOfBytesRead
= NumberOfBytesToRead
;
470 return(STATUS_SUCCESS
);
476 NtUnlockVirtualMemory (
477 HANDLE ProcessHandle
,
479 ULONG NumberOfBytesToUnlock
,
480 PULONG NumberOfBytesUnlocked OPTIONAL
489 NtWriteVirtualMemory (
490 IN HANDLE ProcessHandle
,
491 IN PVOID BaseAddress
,
493 IN ULONG NumberOfBytesToWrite
,
494 OUT PULONG NumberOfBytesWritten
502 DPRINT("NtWriteVirtualMemory(ProcessHandle %x, BaseAddress %x, "
503 "Buffer %x, NumberOfBytesToWrite %d)\n",ProcessHandle
,BaseAddress
,
504 Buffer
,NumberOfBytesToWrite
);
506 Status
= ObReferenceObjectByHandle(ProcessHandle
,
512 if (Status
!= STATUS_SUCCESS
)
517 Mdl
= MmCreateMdl(NULL
,
519 NumberOfBytesToWrite
);
520 MmProbeAndLockPages(Mdl
,
524 KeAttachProcess(Process
);
526 SystemAddress
= MmGetSystemAddressForMdl(Mdl
);
527 memcpy(BaseAddress
, SystemAddress
, NumberOfBytesToWrite
);
531 ObDereferenceObject(Process
);
533 *NumberOfBytesWritten
= NumberOfBytesToWrite
;
534 return(STATUS_SUCCESS
);