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 <ddk/ntddk.h>
16 #include <internal/mm.h>
17 #include <internal/mmhal.h>
18 #include <internal/ob.h>
19 #include <internal/io.h>
20 #include <internal/ps.h>
22 #include <internal/string.h>
25 #include <internal/debug.h>
27 /* FUNCTIONS ****************************************************************/
29 NTSTATUS
MmReleaseMemoryArea(PEPROCESS Process
, PMEMORY_AREA Marea
)
33 DPRINT("MmReleaseMemoryArea(Process %x, Marea %x)\n",Process
,Marea
);
35 DPRINT("Releasing %x between %x %x\n",
36 Marea
, Marea
->BaseAddress
, Marea
->BaseAddress
+ Marea
->Length
);
37 for (i
= Marea
->BaseAddress
;
38 i
< (Marea
->BaseAddress
+ Marea
->Length
);
41 MmDeletePageEntry(Process
, i
, TRUE
);
45 return(STATUS_SUCCESS
);
48 NTSTATUS
MmReleaseMmInfo(PEPROCESS Process
)
50 PLIST_ENTRY CurrentEntry
;
53 DbgPrint("MmReleaseMmInfo(Process %x)\n",Process
);
55 while (!IsListEmpty(&Process
->Pcb
.MemoryAreaList
))
57 CurrentEntry
= RemoveHeadList(&Process
->Pcb
.MemoryAreaList
);
58 Current
= CONTAINING_RECORD(CurrentEntry
, MEMORY_AREA
, Entry
);
60 MmReleaseMemoryArea(Process
, Current
);
63 Mmi386ReleaseMmInfo(Process
);
65 DPRINT("Finished MmReleaseMmInfo()\n");
66 return(STATUS_SUCCESS
);
69 BOOLEAN
MmIsNonPagedSystemAddressValid(PVOID VirtualAddress
)
74 BOOLEAN
MmIsAddressValid(PVOID VirtualAddress
)
76 * FUNCTION: Checks whether the given address is valid for a read or write
78 * VirtualAddress = address to check
79 * RETURNS: True if the access would be valid
80 * False if the access would cause a page fault
81 * NOTES: This function checks whether a byte access to the page would
82 * succeed. Is this realistic for RISC processors which don't
83 * allow byte granular access?
86 MEMORY_AREA
* MemoryArea
;
88 MemoryArea
= MmOpenMemoryAreaByAddress(PsGetCurrentProcess(),
91 if (MemoryArea
== NULL
)
101 NtAllocateVirtualMemory (
102 IN HANDLE ProcessHandle
,
103 IN OUT PVOID
* BaseAddress
,
105 IN OUT PULONG RegionSize
,
106 IN ULONG AllocationType
,
110 * FUNCTION: Allocates a block of virtual memory in the process address space
112 * ProcessHandle = The handle of the process which owns the virtual memory
113 * BaseAddress = A pointer to the virtual memory allocated. If you
114 * supply a non zero value the system will try to
115 * allocate the memory at the address supplied. It round
116 * it down to a multiple of the page size.
117 * ZeroBits = (OPTIONAL) You can specify the number of high order bits
118 * that must be zero, ensuring that the memory will be
119 * allocated at a address below a certain value.
120 * RegionSize = The number of bytes to allocate
121 * AllocationType = Indicates the type of virtual memory you like to
122 * allocated, can be one of the values : MEM_COMMIT,
123 * MEM_RESERVE, MEM_RESET, MEM_TOP_DOWN
124 * Protect = Indicates the protection type of the pages allocated, can be
125 * a combination of PAGE_READONLY, PAGE_READWRITE,
126 * PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_GUARD,
129 * This function maps to the win32 VirtualAllocEx. Virtual memory is
130 * process based so the protocol starts with a ProcessHandle. I
131 * splitted the functionality of obtaining the actual address and
132 * specifying the start address in two parameters ( BaseAddress and
133 * StartAddress ) The NumberOfBytesAllocated specify the range and the
134 * AllocationType and ProctectionType map to the other two parameters.
139 MEMORY_AREA
* MemoryArea
;
143 DPRINT("NtAllocateVirtualMemory(ProcessHandle %x, *BaseAddress %x, "
144 "ZeroBits %d, *RegionSize %x, AllocationType %x, Protect %x)\n",
145 ProcessHandle
,*BaseAddress
,ZeroBits
,*RegionSize
,AllocationType
,
148 Status
= ObReferenceObjectByHandle(ProcessHandle
,
149 PROCESS_VM_OPERATION
,
154 if (Status
!= STATUS_SUCCESS
)
156 DPRINT("NtAllocateVirtualMemory() = %x\n",Status
);
160 if (AllocationType
& MEM_RESERVE
)
162 Type
= MEMORY_AREA_RESERVE
;
166 Type
= MEMORY_AREA_COMMIT
;
169 if ((*BaseAddress
) != 0)
171 MemoryArea
= MmOpenMemoryAreaByAddress(Process
, *BaseAddress
);
173 if (MemoryArea
!= NULL
)
175 if (MemoryArea
->BaseAddress
== (*BaseAddress
) &&
176 MemoryArea
->Length
== *RegionSize
)
178 MemoryArea
->Type
= Type
;
179 MemoryArea
->Attributes
=Protect
;
180 DPRINT("*BaseAddress %x\n",*BaseAddress
);
181 ObDereferenceObject(Process
);
182 return(STATUS_SUCCESS
);
185 MemoryArea
= MmSplitMemoryArea(Process
,
191 DPRINT("*BaseAddress %x\n",*BaseAddress
);
192 ObDereferenceObject(Process
);
193 return(STATUS_SUCCESS
);
197 //FIXME RegionSize should be passed as pointer
200 Status
= MmCreateMemoryArea(UserMode
,
208 if (Status
!= STATUS_SUCCESS
)
210 DPRINT("NtAllocateVirtualMemory() = %x\n",Status
);
211 ObDereferenceObject(Process
);
215 DPRINT("*BaseAddress %x\n",*BaseAddress
);
216 ObDereferenceObject(Process
);
217 return(STATUS_SUCCESS
);
223 NtFlushVirtualMemory (
224 IN HANDLE ProcessHandle
,
225 IN PVOID BaseAddress
,
226 IN ULONG NumberOfBytesToFlush
,
227 OUT PULONG NumberOfBytesFlushed OPTIONAL
230 * FUNCTION: Flushes virtual memory to file
232 * ProcessHandle = Points to the process that allocated the virtual
234 * BaseAddress = Points to the memory address
235 * NumberOfBytesToFlush = Limits the range to flush,
236 * NumberOfBytesFlushed = Actual number of bytes flushed
246 NtFreeVirtualMemory (
247 IN HANDLE ProcessHandle
,
248 IN PVOID
* BaseAddress
,
249 IN PULONG RegionSize
,
253 * FUNCTION: Frees a range of virtual memory
255 * ProcessHandle = Points to the process that allocated the virtual
257 * BaseAddress = Points to the memory address, rounded down to a
258 * multiple of the pagesize
259 * RegionSize = Limits the range to free, rounded up to a multiple of
261 * FreeType = Can be one of the values: MEM_DECOMMIT, or MEM_RELEASE
265 MEMORY_AREA
* MemoryArea
;
269 DPRINT("NtFreeVirtualMemory(ProcessHandle %x, *BaseAddress %x, "
270 "*RegionSize %x, FreeType %x)\n",ProcessHandle
,*BaseAddress
,
271 *RegionSize
,FreeType
);
274 Status
= ObReferenceObjectByHandle(ProcessHandle
,
275 PROCESS_VM_OPERATION
,
280 if (Status
!= STATUS_SUCCESS
)
285 MemoryArea
= MmOpenMemoryAreaByAddress(Process
,*BaseAddress
);
286 if (MemoryArea
== NULL
)
288 ObDereferenceObject(Process
);
289 return(STATUS_UNSUCCESSFUL
);
295 if (MemoryArea
->BaseAddress
!= (*BaseAddress
))
297 ObDereferenceObject(Process
);
298 return(STATUS_UNSUCCESSFUL
);
300 MmFreeMemoryArea(PsGetCurrentProcess(),
304 ObDereferenceObject(Process
);
305 return(STATUS_SUCCESS
);
308 MmSplitMemoryArea(PsGetCurrentProcess(),
313 MemoryArea
->Attributes
);
314 ObDereferenceObject(Process
);
315 return(STATUS_SUCCESS
);
317 ObDereferenceObject(Process
);
318 return(STATUS_NOT_IMPLEMENTED
);
324 NtLockVirtualMemory (
325 HANDLE ProcessHandle
,
327 ULONG NumberOfBytesToLock
,
328 PULONG NumberOfBytesLocked
335 VOID
MmChangeAreaProtection(PEPROCESS Process
,
342 for (i
=0; i
<(Length
/PAGESIZE
); i
++)
344 if (MmIsPagePresent(Process
, BaseAddress
+ (i
*PAGESIZE
)))
346 MmSetPageProtect(Process
, BaseAddress
+ (i
*PAGESIZE
), Protect
);
354 NtProtectVirtualMemory (
355 IN HANDLE ProcessHandle
,
356 IN PVOID BaseAddress
,
357 IN ULONG NumberOfBytesToProtect
,
358 IN ULONG NewAccessProtection
,
359 OUT PULONG OldAccessProtection
362 PMEMORY_AREA MemoryArea
;
366 Status
= ObReferenceObjectByHandle(ProcessHandle
,
367 PROCESS_VM_OPERATION
,
372 if (Status
!= STATUS_SUCCESS
)
374 DPRINT("NtProtectVirtualMemory() = %x\n",Status
);
378 MemoryArea
= MmOpenMemoryAreaByAddress(Process
,BaseAddress
);
379 if (MemoryArea
== NULL
)
381 DPRINT("NtProtectVirtualMemory() = %x\n",STATUS_UNSUCCESSFUL
);
382 ObDereferenceObject(Process
);
383 return(STATUS_UNSUCCESSFUL
);
386 *OldAccessProtection
= MemoryArea
->Attributes
;
388 if (MemoryArea
->BaseAddress
== BaseAddress
&&
389 MemoryArea
->Length
== NumberOfBytesToProtect
)
391 MemoryArea
->Attributes
= NewAccessProtection
;
395 MemoryArea
= MmSplitMemoryArea(Process
,
398 NumberOfBytesToProtect
,
400 NewAccessProtection
);
402 MmChangeAreaProtection(Process
,BaseAddress
,NumberOfBytesToProtect
,
403 NewAccessProtection
);
404 ObDereferenceObject(Process
);
405 return(STATUS_SUCCESS
);
411 NtQueryVirtualMemory (
412 IN HANDLE ProcessHandle
,
414 IN CINT VirtualMemoryInformationClass
,
415 OUT PVOID VirtualMemoryInformation
,
417 OUT PULONG ResultLength
422 MEMORY_AREA
* MemoryArea
;
425 DbgPrint("NtReadVirtualMemory(ProcessHandle %x, Address %x, "
426 "VirtualMemoryInformationClass %d, VirtualMemoryInformation %x, "
427 "Length %lu ResultLength %x)\n",ProcessHandle
,Address
,
428 VirtualMemoryInformationClass
,VirtualMemoryInformation
,
429 Length
,ResultLength
);
431 switch(VirtualMemoryInformationClass
)
433 case MemoryBasicInformation
:
435 PMEMORY_BASIC_INFORMATION Info
=
436 (PMEMORY_BASIC_INFORMATION
)VirtualMemoryInformation
;
438 if (Length
< sizeof(MEMORY_BASIC_INFORMATION
))
440 ObDereferenceObject(Process
);
441 return(STATUS_INFO_LENGTH_MISMATCH
);
444 *ResultLength
= sizeof(MEMORY_BASIC_INFORMATION
);
447 Status
= ObReferenceObjectByHandle(ProcessHandle
,
448 PROCESS_QUERY_INFORMATION
,
454 if (!NT_SUCCESS(Status
))
456 // DbdPrint("NtQueryVirtualMemory() = %x\n",Status);
460 MemoryArea
= MmOpenMemoryAreaByAddress(Process
,
463 if (MemoryArea
== NULL
)
465 Info
->State
= MEM_FREE
;
466 DbgPrint("Virtual memory at %p is free.\n", Address
);
467 ObDereferenceObject(Process
);
468 return (STATUS_SUCCESS
);
471 if (MemoryArea
->Type
== MEMORY_AREA_COMMIT
)
473 Info
->State
= MEM_COMMIT
;
477 Info
->State
= MEM_RESERVE
;
480 Info
->BaseAddress
= MemoryArea
->BaseAddress
;
481 Info
->RegionSize
= MemoryArea
->Length
;
483 DbgPrint("BaseAddress %p, Length %x\n",
484 Info
->BaseAddress
, Info
->RegionSize
);
487 ObDereferenceObject(Process
);
488 return (STATUS_SUCCESS
);
493 return(STATUS_INVALID_INFO_CLASS
);
501 NtReadVirtualMemory (
502 IN HANDLE ProcessHandle
,
503 IN PVOID BaseAddress
,
505 IN ULONG NumberOfBytesToRead
,
506 OUT PULONG NumberOfBytesRead
514 DPRINT("NtReadVirtualMemory(ProcessHandle %x, BaseAddress %x, "
515 "Buffer %x, NumberOfBytesToRead %d)\n",ProcessHandle
,BaseAddress
,
516 Buffer
,NumberOfBytesToRead
);
518 Status
= ObReferenceObjectByHandle(ProcessHandle
,
524 if (Status
!= STATUS_SUCCESS
)
529 Mdl
= MmCreateMdl(NULL
,
531 NumberOfBytesToRead
);
532 MmProbeAndLockPages(Mdl
,
536 KeAttachProcess(Process
);
538 SystemAddress
= MmGetSystemAddressForMdl(Mdl
);
539 memcpy(SystemAddress
, BaseAddress
, NumberOfBytesToRead
);
543 ObDereferenceObject(Process
);
545 *NumberOfBytesRead
= NumberOfBytesToRead
;
546 return(STATUS_SUCCESS
);
552 NtUnlockVirtualMemory (
553 HANDLE ProcessHandle
,
555 ULONG NumberOfBytesToUnlock
,
556 PULONG NumberOfBytesUnlocked OPTIONAL
565 NtWriteVirtualMemory (
566 IN HANDLE ProcessHandle
,
567 IN PVOID BaseAddress
,
569 IN ULONG NumberOfBytesToWrite
,
570 OUT PULONG NumberOfBytesWritten
578 DPRINT("NtWriteVirtualMemory(ProcessHandle %x, BaseAddress %x, "
579 "Buffer %x, NumberOfBytesToWrite %d)\n",ProcessHandle
,BaseAddress
,
580 Buffer
,NumberOfBytesToWrite
);
582 Status
= ObReferenceObjectByHandle(ProcessHandle
,
588 if (Status
!= STATUS_SUCCESS
)
593 Mdl
= MmCreateMdl(NULL
,
595 NumberOfBytesToWrite
);
596 MmProbeAndLockPages(Mdl
,
600 KeAttachProcess(Process
);
602 SystemAddress
= MmGetSystemAddressForMdl(Mdl
);
603 memcpy(BaseAddress
, SystemAddress
, NumberOfBytesToWrite
);
607 ObDereferenceObject(Process
);
609 *NumberOfBytesWritten
= NumberOfBytesToWrite
;
610 return(STATUS_SUCCESS
);