3 * Copyright (C) 1998, 1999, 2000, 2001, 2002 ReactOS Team
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.
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.
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.
19 /* $Id: anonmem.c,v 1.5 2002/09/07 15:12:59 chorns Exp $
21 * PROJECT: ReactOS kernel
22 * FILE: ntoskrnl/mm/anonmem.c
23 * PURPOSE: Implementing anonymous memory.
24 * PROGRAMMER: David Welch
27 /* INCLUDE *****************************************************************/
32 #include <internal/debug.h>
34 /* FUNCTIONS *****************************************************************/
37 MmWritePageVirtualMemory(PMADDRESS_SPACE AddressSpace
,
38 PMEMORY_AREA MemoryArea
,
43 LARGE_INTEGER PhysicalAddress
;
48 * Check for paging out from a deleted virtual memory area.
50 if (MemoryArea
->DeleteInProgress
)
52 PageOp
->Status
= STATUS_UNSUCCESSFUL
;
53 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
54 MmReleasePageOp(PageOp
);
55 return(STATUS_UNSUCCESSFUL
);
59 MmGetPhysicalAddressForProcess(AddressSpace
->Process
, Address
);
62 * Get that the page actually is dirty.
64 if (!MmIsDirtyPage(MemoryArea
->Process
, Address
))
66 PageOp
->Status
= STATUS_SUCCESS
;
67 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
68 MmReleasePageOp(PageOp
);
69 return(STATUS_SUCCESS
);
73 * Speculatively set the mapping to clean.
75 MmSetCleanPage(MemoryArea
->Process
, Address
);
78 * If necessary, allocate an entry in the paging file for this page
80 SwapEntry
= MmGetSavedSwapEntryPage(PhysicalAddress
);
83 SwapEntry
= MmAllocSwapPage();
86 MmSetDirtyPage(MemoryArea
->Process
, Address
);
87 PageOp
->Status
= STATUS_PAGEFILE_QUOTA_EXCEEDED
;
88 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
89 MmReleasePageOp(PageOp
);
90 return(STATUS_PAGEFILE_QUOTA_EXCEEDED
);
95 * Write the page to the pagefile
97 Mdl
= MmCreateMdl(NULL
, NULL
, PAGE_SIZE
);
98 MmBuildMdlFromPages(Mdl
, (PULONG
)&PhysicalAddress
);
99 Status
= MmWriteToSwapPage(SwapEntry
, Mdl
);
100 if (!NT_SUCCESS(Status
))
102 DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
104 MmSetDirtyPage(MemoryArea
->Process
, Address
);
105 PageOp
->Status
= STATUS_UNSUCCESSFUL
;
106 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
107 MmReleasePageOp(PageOp
);
108 return(STATUS_UNSUCCESSFUL
);
112 * Otherwise we have succeeded.
114 MmSetSavedSwapEntryPage(PhysicalAddress
, SwapEntry
);
115 PageOp
->Status
= STATUS_SUCCESS
;
116 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
117 MmReleasePageOp(PageOp
);
118 return(STATUS_SUCCESS
);
122 MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace
,
123 PMEMORY_AREA MemoryArea
,
127 PHYSICAL_ADDRESS PhysicalAddress
;
133 DPRINT("MmPageOutVirtualMemory(Address 0x%.8X) PID %d\n",
134 Address
, MemoryArea
->Process
->UniqueProcessId
);
137 * Check for paging out from a deleted virtual memory area.
139 if (MemoryArea
->DeleteInProgress
)
141 PageOp
->Status
= STATUS_UNSUCCESSFUL
;
142 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
143 MmReleasePageOp(PageOp
);
144 return(STATUS_UNSUCCESSFUL
);
148 * Disable the virtual mapping.
150 MmDisableVirtualMapping(MemoryArea
->Process
, Address
,
151 &WasDirty
, &PhysicalAddress
);
152 if (PhysicalAddress
.QuadPart
== 0)
158 * Paging out non-dirty data is easy.
162 MmDeleteVirtualMapping(MemoryArea
->Process
, Address
, FALSE
, NULL
, NULL
);
163 MmDeleteAllRmaps(PhysicalAddress
, NULL
, NULL
);
164 if ((SwapEntry
= MmGetSavedSwapEntryPage(PhysicalAddress
)) != 0)
166 MmCreatePageFileMapping(MemoryArea
->Process
, Address
, SwapEntry
);
167 MmSetSavedSwapEntryPage(PhysicalAddress
, 0);
169 MmReleasePageMemoryConsumer(MC_USER
, PhysicalAddress
);
170 PageOp
->Status
= STATUS_SUCCESS
;
171 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
172 MmReleasePageOp(PageOp
);
173 return(STATUS_SUCCESS
);
177 * If necessary, allocate an entry in the paging file for this page
179 SwapEntry
= MmGetSavedSwapEntryPage(PhysicalAddress
);
182 SwapEntry
= MmAllocSwapPage();
185 MmShowOutOfSpaceMessagePagingFile();
186 MmEnableVirtualMapping(MemoryArea
->Process
, Address
);
187 PageOp
->Status
= STATUS_UNSUCCESSFUL
;
188 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
189 MmReleasePageOp(PageOp
);
190 return(STATUS_UNSUCCESSFUL
);
195 * Write the page to the pagefile
197 Mdl
= MmCreateMdl(NULL
, NULL
, PAGE_SIZE
);
198 MmBuildMdlFromPages(Mdl
, (PULONG
)&PhysicalAddress
);
199 Status
= MmWriteToSwapPage(SwapEntry
, Mdl
);
200 if (!NT_SUCCESS(Status
))
202 DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
204 MmEnableVirtualMapping(MemoryArea
->Process
, Address
);
205 PageOp
->Status
= STATUS_UNSUCCESSFUL
;
206 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
207 MmReleasePageOp(PageOp
);
208 return(STATUS_UNSUCCESSFUL
);
212 * Otherwise we have succeeded, free the page
214 DPRINT("MM: Swapped out virtual memory page 0x%.8X!\n", PhysicalAddress
);
215 MmDeleteVirtualMapping(MemoryArea
->Process
, Address
, FALSE
, NULL
, NULL
);
216 MmCreatePageFileMapping(MemoryArea
->Process
, Address
, SwapEntry
);
217 MmDeleteAllRmaps(PhysicalAddress
, NULL
, NULL
);
218 MmSetSavedSwapEntryPage(PhysicalAddress
, 0);
219 MmReleasePageMemoryConsumer(MC_USER
, PhysicalAddress
);
220 PageOp
->Status
= STATUS_SUCCESS
;
221 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
222 MmReleasePageOp(PageOp
);
223 return(STATUS_SUCCESS
);
227 MmNotPresentFaultVirtualMemory(PMADDRESS_SPACE AddressSpace
,
228 MEMORY_AREA
* MemoryArea
,
232 * FUNCTION: Move data into memory to satisfy a page not present fault
234 * AddressSpace = Address space within which the fault occurred
235 * MemoryArea = The memory area within which the fault occurred
236 * Address = The absolute address of fault
238 * NOTES: This function is called with the address space lock held.
241 PHYSICAL_ADDRESS Page
;
247 * There is a window between taking the page fault and locking the
248 * address space when another thread could load the page so we check
251 if (MmIsPagePresent(NULL
, Address
))
255 MmLockPage(MmGetPhysicalAddressForProcess(NULL
, Address
));
257 return(STATUS_SUCCESS
);
261 * Check for the virtual memory area being deleted.
263 if (MemoryArea
->DeleteInProgress
)
265 return(STATUS_UNSUCCESSFUL
);
269 * Get the segment corresponding to the virtual address
271 Region
= MmFindRegion(MemoryArea
->BaseAddress
,
272 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
274 if (Region
->Type
== MEM_RESERVE
)
276 return(STATUS_UNSUCCESSFUL
);
280 * Get or create a page operation
282 PageOp
= MmGetPageOp(MemoryArea
, (ULONG
)PsGetCurrentProcessId(),
283 (PVOID
)PAGE_ROUND_DOWN(Address
), NULL
, 0,
287 DPRINT1("MmGetPageOp failed");
292 * Check if someone else is already handling this fault, if so wait
295 if (PageOp
->Thread
!= PsGetCurrentThread())
297 MmUnlockAddressSpace(AddressSpace
);
298 Status
= KeWaitForSingleObject(&PageOp
->CompletionEvent
,
304 * Check for various strange conditions
306 if (Status
!= STATUS_SUCCESS
)
308 DPRINT1("Failed to wait for page op\n");
311 if (PageOp
->Status
== STATUS_PENDING
)
313 DPRINT1("Woke for page op before completion\n");
317 * If this wasn't a pagein then we need to restart the handling
319 if (PageOp
->OpType
!= MM_PAGEOP_PAGEIN
)
321 MmLockAddressSpace(AddressSpace
);
322 MmReleasePageOp(PageOp
);
323 return(STATUS_MM_RESTART_OPERATION
);
326 * If the thread handling this fault has failed then we don't retry
328 if (!NT_SUCCESS(PageOp
->Status
))
330 MmLockAddressSpace(AddressSpace
);
331 MmReleasePageOp(PageOp
);
334 MmLockAddressSpace(AddressSpace
);
337 MmLockPage(MmGetPhysicalAddressForProcess(NULL
, Address
));
339 MmReleasePageOp(PageOp
);
340 return(STATUS_SUCCESS
);
344 * Try to allocate a page
346 Status
= MmRequestPageMemoryConsumer(MC_USER
, FALSE
, &Page
);
347 if (Status
== STATUS_NO_MEMORY
)
349 MmUnlockAddressSpace(AddressSpace
);
350 Status
= MmRequestPageMemoryConsumer(MC_USER
, TRUE
, &Page
);
351 MmLockAddressSpace(AddressSpace
);
355 * Handle swapped out pages.
357 if (MmIsPageSwapEntry(NULL
, Address
))
362 MmDeletePageFileMapping(NULL
, Address
, &SwapEntry
);
363 Mdl
= MmCreateMdl(NULL
, NULL
, PAGE_SIZE
);
364 MmBuildMdlFromPages(Mdl
, (PULONG
)&Page
);
365 Status
= MmReadFromSwapPage(SwapEntry
, Mdl
);
366 if (!NT_SUCCESS(Status
))
370 MmSetSavedSwapEntryPage(Page
, SwapEntry
);
374 * Set the page. If we fail because we are out of memory then
377 Status
= MmCreateVirtualMapping(PsGetCurrentProcess(),
379 MemoryArea
->Attributes
,
382 while (Status
== STATUS_NO_MEMORY
)
384 MmUnlockAddressSpace(AddressSpace
);
385 Status
= MmCreateVirtualMapping(PsGetCurrentProcess(),
387 MemoryArea
->Attributes
,
390 MmLockAddressSpace(AddressSpace
);
392 if (!NT_SUCCESS(Status
))
394 DPRINT1("MmCreateVirtualMapping failed, not out of memory\n");
400 * Add the page to the process's working set
402 MmInsertRmap(Page
, PsGetCurrentProcess(), (PVOID
)PAGE_ROUND_DOWN(Address
));
405 * Finish the operation
409 MmLockPage(MmGetPhysicalAddressForProcess(NULL
, Address
));
411 PageOp
->Status
= STATUS_SUCCESS
;
412 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
413 MmReleasePageOp(PageOp
);
414 return(STATUS_SUCCESS
);
418 MmModifyAttributes(PMADDRESS_SPACE AddressSpace
,
426 * FUNCTION: Modify the attributes of a memory region
430 * If we are switching a previously committed region to reserved then
431 * free any allocated pages within the region
433 if (NewType
== MEM_RESERVE
&& OldType
== MEM_COMMIT
)
437 for (i
=0; i
<= (RegionSize
/PAGE_SIZE
); i
++)
439 LARGE_INTEGER PhysicalAddr
;
441 if (MmIsPageSwapEntry(AddressSpace
->Process
,
442 BaseAddress
+ (i
* PAGE_SIZE
)))
446 MmDeletePageFileMapping(AddressSpace
->Process
,
447 BaseAddress
+ (i
* PAGE_SIZE
),
449 MmFreeSwapPage(SwapEntry
);
453 PhysicalAddr
= MmGetPhysicalAddress(BaseAddress
+ (i
*PAGE_SIZE
));
454 MmDeleteVirtualMapping(AddressSpace
->Process
,
455 BaseAddress
+ (i
*PAGE_SIZE
),
457 if (PhysicalAddr
.QuadPart
!= 0)
459 SWAPENTRY SavedSwapEntry
;
460 SavedSwapEntry
= MmGetSavedSwapEntryPage(PhysicalAddr
);
461 if (SavedSwapEntry
!= 0)
463 MmFreeSwapPage(SavedSwapEntry
);
464 MmSetSavedSwapEntryPage(PhysicalAddr
, 0);
466 MmDeleteRmap(PhysicalAddr
, AddressSpace
->Process
,
467 BaseAddress
+ (i
* PAGE_SIZE
));
468 MmReleasePageMemoryConsumer(MC_USER
, PhysicalAddr
);
475 * If we are changing the protection attributes of a committed region then
476 * alter the attributes for any allocated pages within the region
478 if (NewType
== MEM_COMMIT
&& OldType
== MEM_COMMIT
&&
479 OldProtect
!= NewProtect
)
483 for (i
=0; i
<= (RegionSize
/PAGE_SIZE
); i
++)
485 if (MmIsPagePresent(AddressSpace
->Process
,
486 BaseAddress
+ (i
*PAGE_SIZE
)))
488 MmSetPageProtect(AddressSpace
->Process
,
489 BaseAddress
+ (i
*PAGE_SIZE
),
497 NtAllocateVirtualMemory(IN HANDLE ProcessHandle
,
498 IN OUT PVOID
* UBaseAddress
,
500 IN OUT PULONG URegionSize
,
501 IN ULONG AllocationType
,
504 * FUNCTION: Allocates a block of virtual memory in the process address space
506 * ProcessHandle = The handle of the process which owns the virtual memory
507 * BaseAddress = A pointer to the virtual memory allocated. If you
508 * supply a non zero value the system will try to
509 * allocate the memory at the address supplied. It round
510 * it down to a multiple of the page size.
511 * ZeroBits = (OPTIONAL) You can specify the number of high order bits
512 * that must be zero, ensuring that the memory will be
513 * allocated at a address below a certain value.
514 * RegionSize = The number of bytes to allocate
515 * AllocationType = Indicates the type of virtual memory you like to
516 * allocated, can be a combination of MEM_COMMIT,
517 * MEM_RESERVE, MEM_RESET, MEM_TOP_DOWN.
518 * Protect = Indicates the protection type of the pages allocated, can be
519 * a combination of PAGE_READONLY, PAGE_READWRITE,
520 * PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_GUARD,
526 MEMORY_AREA
* MemoryArea
;
529 PMADDRESS_SPACE AddressSpace
;
535 DPRINT("NtAllocateVirtualMemory(*UBaseAddress %x, "
536 "ZeroBits %d, *URegionSize %x, AllocationType %x, Protect %x)\n",
537 *UBaseAddress
,ZeroBits
,*URegionSize
,AllocationType
,
541 * Check the validity of the parameters
543 if ((Protect
& PAGE_FLAGS_VALID_FROM_USER_MODE
) != Protect
)
545 return(STATUS_INVALID_PAGE_PROTECTION
);
547 if ((AllocationType
& (MEM_COMMIT
| MEM_RESERVE
)) == 0)
549 return(STATUS_INVALID_PARAMETER
);
552 PBaseAddress
= *UBaseAddress
;
553 PRegionSize
= *URegionSize
;
555 BaseAddress
= (PVOID
)PAGE_ROUND_DOWN(PBaseAddress
);
556 RegionSize
= PAGE_ROUND_UP(PBaseAddress
+ PRegionSize
) -
557 PAGE_ROUND_DOWN(PBaseAddress
);
559 Status
= ObReferenceObjectByHandle(ProcessHandle
,
560 PROCESS_VM_OPERATION
,
565 if (!NT_SUCCESS(Status
))
567 DPRINT("NtAllocateVirtualMemory() = %x\n",Status
);
571 Type
= (AllocationType
& MEM_COMMIT
) ? MEM_COMMIT
: MEM_RESERVE
;
572 DPRINT("Type %x\n", Type
);
574 AddressSpace
= &Process
->AddressSpace
;
575 MmLockAddressSpace(AddressSpace
);
577 if (PBaseAddress
!= 0)
579 MemoryArea
= MmOpenMemoryAreaByAddress(&Process
->AddressSpace
,
582 if (MemoryArea
!= NULL
&&
583 MemoryArea
->Type
== MEMORY_AREA_VIRTUAL_MEMORY
&&
584 MemoryArea
->Length
>= RegionSize
)
587 MmAlterRegion(&Process
->AddressSpace
,
588 MemoryArea
->BaseAddress
,
589 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
590 PBaseAddress
, RegionSize
,
591 Type
, Protect
, MmModifyAttributes
);
592 MmUnlockAddressSpace(AddressSpace
);
593 ObDereferenceObject(Process
);
594 DPRINT("NtAllocateVirtualMemory() = %x\n",Status
);
597 else if (MemoryArea
!= NULL
)
599 MmUnlockAddressSpace(AddressSpace
);
600 ObDereferenceObject(Process
);
601 return(STATUS_UNSUCCESSFUL
);
605 Status
= MmCreateMemoryArea(Process
,
606 &Process
->AddressSpace
,
607 MEMORY_AREA_VIRTUAL_MEMORY
,
614 if (!NT_SUCCESS(Status
))
616 MmUnlockAddressSpace(AddressSpace
);
617 ObDereferenceObject(Process
);
618 DPRINT("NtAllocateVirtualMemory() = %x\n",Status
);
621 MmInitialiseRegion(&MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
622 RegionSize
, Type
, Protect
);
624 if ((AllocationType
& MEM_COMMIT
) &&
625 ((Protect
& PAGE_READWRITE
) ||
626 (Protect
& PAGE_EXECUTE_READWRITE
)))
628 MmReserveSwapPages(RegionSize
);
631 *UBaseAddress
= BaseAddress
;
632 *URegionSize
= RegionSize
;
633 DPRINT("*UBaseAddress %x *URegionSize %x\n", BaseAddress
, RegionSize
);
635 MmUnlockAddressSpace(AddressSpace
);
636 ObDereferenceObject(Process
);
637 return(STATUS_SUCCESS
);
641 MmFreeVirtualMemoryPage(PVOID Context
,
642 MEMORY_AREA
* MemoryArea
,
644 PHYSICAL_ADDRESS PhysicalAddr
,
648 PEPROCESS Process
= (PEPROCESS
)Context
;
650 if (PhysicalAddr
.QuadPart
!= 0)
652 SWAPENTRY SavedSwapEntry
;
653 SavedSwapEntry
= MmGetSavedSwapEntryPage(PhysicalAddr
);
654 if (SavedSwapEntry
!= 0)
656 MmFreeSwapPage(SavedSwapEntry
);
657 MmSetSavedSwapEntryPage(PhysicalAddr
, 0);
659 MmDeleteRmap(PhysicalAddr
, Process
, Address
);
660 MmReleasePageMemoryConsumer(MC_USER
, PhysicalAddr
);
662 else if (SwapEntry
!= 0)
664 MmFreeSwapPage(SwapEntry
);
669 MmFreeVirtualMemory(PEPROCESS Process
,
670 PMEMORY_AREA MemoryArea
)
672 PLIST_ENTRY current_entry
;
676 DPRINT("MmFreeVirtualMemory(Process %p MemoryArea %p)\n", Process
,
679 /* Mark this memory area as about to be deleted. */
680 MemoryArea
->DeleteInProgress
= TRUE
;
683 * Wait for any ongoing paging operations. Notice that since we have
684 * flagged this memory area as deleted no more page ops will be added.
686 if (MemoryArea
->PageOpCount
> 0)
688 for (i
= 0; i
< (PAGE_ROUND_UP(MemoryArea
->Length
) / PAGE_SIZE
); i
++)
692 if (MemoryArea
->PageOpCount
== 0)
697 PageOp
= MmCheckForPageOp(MemoryArea
, Process
->UniqueProcessId
,
698 MemoryArea
->BaseAddress
+ (i
* PAGE_SIZE
),
703 MmUnlockAddressSpace(&Process
->AddressSpace
);
704 Status
= KeWaitForSingleObject(&PageOp
->CompletionEvent
,
709 if (Status
!= STATUS_SUCCESS
)
711 DPRINT1("Failed to wait for page op\n");
714 MmLockAddressSpace(&Process
->AddressSpace
);
715 MmReleasePageOp(PageOp
);
720 /* Free all the individual segments. */
721 current_entry
= MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
.Flink
;
722 while (current_entry
!= &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
)
724 current
= CONTAINING_RECORD(current_entry
, MM_REGION
, RegionListEntry
);
725 current_entry
= current_entry
->Flink
;
729 /* Actually free the memory area. */
730 MmFreeMemoryArea(&Process
->AddressSpace
,
731 MemoryArea
->BaseAddress
,
733 MmFreeVirtualMemoryPage
,
738 NtFreeVirtualMemory(IN HANDLE ProcessHandle
,
739 IN PVOID
* PBaseAddress
,
740 IN PULONG PRegionSize
,
743 * FUNCTION: Frees a range of virtual memory
745 * ProcessHandle = Points to the process that allocated the virtual
747 * BaseAddress = Points to the memory address, rounded down to a
748 * multiple of the PAGE_SIZE
749 * RegionSize = Limits the range to free, rounded up to a multiple of
751 * FreeType = Can be one of the values: MEM_DECOMMIT, or MEM_RELEASE
755 MEMORY_AREA
* MemoryArea
;
758 PMADDRESS_SPACE AddressSpace
;
762 DPRINT("NtFreeVirtualMemory(ProcessHandle %x, *PBaseAddress %x, "
763 "*PRegionSize %x, FreeType %x)\n",ProcessHandle
,*PBaseAddress
,
764 *PRegionSize
,FreeType
);
766 BaseAddress
= (PVOID
)PAGE_ROUND_DOWN((*PBaseAddress
));
767 RegionSize
= PAGE_ROUND_UP((*PBaseAddress
) + (*PRegionSize
)) -
768 PAGE_ROUND_DOWN((*PBaseAddress
));
770 Status
= ObReferenceObjectByHandle(ProcessHandle
,
771 PROCESS_VM_OPERATION
,
776 if (!NT_SUCCESS(Status
))
781 AddressSpace
= &Process
->AddressSpace
;
783 MmLockAddressSpace(AddressSpace
);
784 MemoryArea
= MmOpenMemoryAreaByAddress(AddressSpace
,
786 if (MemoryArea
== NULL
)
788 MmUnlockAddressSpace(AddressSpace
);
789 ObDereferenceObject(Process
);
790 return(STATUS_UNSUCCESSFUL
);
796 /* We can only free a memory area in one step. */
797 if (MemoryArea
->BaseAddress
!= BaseAddress
)
799 MmUnlockAddressSpace(AddressSpace
);
800 ObDereferenceObject(Process
);
801 return(STATUS_UNSUCCESSFUL
);
803 MmFreeVirtualMemory(Process
, MemoryArea
);
804 MmUnlockAddressSpace(AddressSpace
);
805 ObDereferenceObject(Process
);
806 return(STATUS_SUCCESS
);
810 MmAlterRegion(AddressSpace
,
811 MemoryArea
->BaseAddress
,
812 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
818 MmUnlockAddressSpace(AddressSpace
);
819 ObDereferenceObject(Process
);
822 MmUnlockAddressSpace(AddressSpace
);
823 ObDereferenceObject(Process
);
824 return(STATUS_NOT_IMPLEMENTED
);
828 MmProtectAnonMem(PMADDRESS_SPACE AddressSpace
,
829 PMEMORY_AREA MemoryArea
,
838 Region
= MmFindRegion(MemoryArea
->BaseAddress
,
839 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
841 *OldProtect
= Region
->Protect
;
842 Status
= MmAlterRegion(AddressSpace
, MemoryArea
->BaseAddress
,
843 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
844 BaseAddress
, Length
, Region
->Type
, Protect
,
850 MmQueryAnonMem(PMEMORY_AREA MemoryArea
,
852 PMEMORY_BASIC_INFORMATION Info
,
858 Info
->BaseAddress
= (PVOID
)PAGE_ROUND_DOWN(Address
);
860 Region
= MmFindRegion(MemoryArea
->BaseAddress
,
861 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
862 Address
, &RegionBase
);
863 Info
->AllocationBase
= RegionBase
;
864 Info
->AllocationProtect
= Region
->Protect
; /* FIXME */
865 Info
->RegionSize
= Region
->Length
;
866 Info
->State
= Region
->Type
;
867 Info
->Protect
= Region
->Protect
;
868 Info
->Type
= MEM_PRIVATE
;
869 return(STATUS_SUCCESS
);