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.7 2002/10/01 19:27:22 chorns Exp $
21 * PROJECT: ReactOS kernel
22 * FILE: ntoskrnl/mm/anonmem.c
23 * PURPOSE: Implementing anonymous memory.
24 * PROGRAMMER: David Welch
27 /* INCLUDE *****************************************************************/
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>
37 #include <internal/debug.h>
39 /* FUNCTIONS *****************************************************************/
42 MmWritePageVirtualMemory(PMADDRESS_SPACE AddressSpace
,
43 PMEMORY_AREA MemoryArea
,
48 LARGE_INTEGER PhysicalAddress
;
53 * Check for paging out from a deleted virtual memory area.
55 if (MemoryArea
->DeleteInProgress
)
57 PageOp
->Status
= STATUS_UNSUCCESSFUL
;
58 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
59 MmReleasePageOp(PageOp
);
60 return(STATUS_UNSUCCESSFUL
);
64 MmGetPhysicalAddressForProcess(AddressSpace
->Process
, Address
);
67 * Get that the page actually is dirty.
69 if (!MmIsDirtyPage(MemoryArea
->Process
, Address
))
71 PageOp
->Status
= STATUS_SUCCESS
;
72 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
73 MmReleasePageOp(PageOp
);
74 return(STATUS_SUCCESS
);
78 * Speculatively set the mapping to clean.
80 MmSetCleanPage(MemoryArea
->Process
, Address
);
83 * If necessary, allocate an entry in the paging file for this page
85 SwapEntry
= MmGetSavedSwapEntryPage(PhysicalAddress
);
88 SwapEntry
= MmAllocSwapPage();
91 MmSetDirtyPage(MemoryArea
->Process
, Address
);
92 PageOp
->Status
= STATUS_PAGEFILE_QUOTA_EXCEEDED
;
93 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
94 MmReleasePageOp(PageOp
);
95 return(STATUS_PAGEFILE_QUOTA_EXCEEDED
);
100 * Write the page to the pagefile
102 Mdl
= MmCreateMdl(NULL
, NULL
, PAGE_SIZE
);
103 MmBuildMdlFromPages(Mdl
, (PULONG
)&PhysicalAddress
);
104 Status
= MmWriteToSwapPage(SwapEntry
, Mdl
);
105 if (!NT_SUCCESS(Status
))
107 DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
109 MmSetDirtyPage(MemoryArea
->Process
, Address
);
110 PageOp
->Status
= STATUS_UNSUCCESSFUL
;
111 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
112 MmReleasePageOp(PageOp
);
113 return(STATUS_UNSUCCESSFUL
);
117 * Otherwise we have succeeded.
119 MmSetSavedSwapEntryPage(PhysicalAddress
, SwapEntry
);
120 PageOp
->Status
= STATUS_SUCCESS
;
121 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
122 MmReleasePageOp(PageOp
);
123 return(STATUS_SUCCESS
);
127 MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace
,
128 PMEMORY_AREA MemoryArea
,
132 PHYSICAL_ADDRESS PhysicalAddress
;
138 DPRINT("MmPageOutVirtualMemory(Address 0x%.8X) PID %d\n",
139 Address
, MemoryArea
->Process
->UniqueProcessId
);
142 * Check for paging out from a deleted virtual memory area.
144 if (MemoryArea
->DeleteInProgress
)
146 PageOp
->Status
= STATUS_UNSUCCESSFUL
;
147 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
148 MmReleasePageOp(PageOp
);
149 return(STATUS_UNSUCCESSFUL
);
153 * Disable the virtual mapping.
155 MmDisableVirtualMapping(MemoryArea
->Process
, Address
,
156 &WasDirty
, &PhysicalAddress
);
157 if (PhysicalAddress
.QuadPart
== 0)
163 * Paging out non-dirty data is easy.
167 MmDeleteVirtualMapping(MemoryArea
->Process
, Address
, FALSE
, NULL
, NULL
);
168 MmDeleteAllRmaps(PhysicalAddress
, NULL
, NULL
);
169 if ((SwapEntry
= MmGetSavedSwapEntryPage(PhysicalAddress
)) != 0)
171 MmCreatePageFileMapping(MemoryArea
->Process
, Address
, SwapEntry
);
172 MmSetSavedSwapEntryPage(PhysicalAddress
, 0);
174 MmReleasePageMemoryConsumer(MC_USER
, PhysicalAddress
);
175 PageOp
->Status
= STATUS_SUCCESS
;
176 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
177 MmReleasePageOp(PageOp
);
178 return(STATUS_SUCCESS
);
182 * If necessary, allocate an entry in the paging file for this page
184 SwapEntry
= MmGetSavedSwapEntryPage(PhysicalAddress
);
187 SwapEntry
= MmAllocSwapPage();
190 MmShowOutOfSpaceMessagePagingFile();
191 MmEnableVirtualMapping(MemoryArea
->Process
, Address
);
192 PageOp
->Status
= STATUS_UNSUCCESSFUL
;
193 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
194 MmReleasePageOp(PageOp
);
195 return(STATUS_UNSUCCESSFUL
);
200 * Write the page to the pagefile
202 Mdl
= MmCreateMdl(NULL
, NULL
, PAGE_SIZE
);
203 MmBuildMdlFromPages(Mdl
, (PULONG
)&PhysicalAddress
);
204 Status
= MmWriteToSwapPage(SwapEntry
, Mdl
);
205 if (!NT_SUCCESS(Status
))
207 DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
209 MmEnableVirtualMapping(MemoryArea
->Process
, Address
);
210 PageOp
->Status
= STATUS_UNSUCCESSFUL
;
211 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
212 MmReleasePageOp(PageOp
);
213 return(STATUS_UNSUCCESSFUL
);
217 * Otherwise we have succeeded, free the page
219 DPRINT("MM: Swapped out virtual memory page 0x%.8X!\n", PhysicalAddress
);
220 MmDeleteVirtualMapping(MemoryArea
->Process
, Address
, FALSE
, NULL
, NULL
);
221 MmCreatePageFileMapping(MemoryArea
->Process
, Address
, SwapEntry
);
222 MmDeleteAllRmaps(PhysicalAddress
, NULL
, NULL
);
223 MmSetSavedSwapEntryPage(PhysicalAddress
, 0);
224 MmReleasePageMemoryConsumer(MC_USER
, PhysicalAddress
);
225 PageOp
->Status
= STATUS_SUCCESS
;
226 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
227 MmReleasePageOp(PageOp
);
228 return(STATUS_SUCCESS
);
232 MmNotPresentFaultVirtualMemory(PMADDRESS_SPACE AddressSpace
,
233 MEMORY_AREA
* MemoryArea
,
237 * FUNCTION: Move data into memory to satisfy a page not present fault
239 * AddressSpace = Address space within which the fault occurred
240 * MemoryArea = The memory area within which the fault occurred
241 * Address = The absolute address of fault
243 * NOTES: This function is called with the address space lock held.
246 PHYSICAL_ADDRESS Page
;
252 * There is a window between taking the page fault and locking the
253 * address space when another thread could load the page so we check
256 if (MmIsPagePresent(NULL
, Address
))
260 MmLockPage(MmGetPhysicalAddressForProcess(NULL
, Address
));
262 return(STATUS_SUCCESS
);
266 * Check for the virtual memory area being deleted.
268 if (MemoryArea
->DeleteInProgress
)
270 return(STATUS_UNSUCCESSFUL
);
274 * Get the segment corresponding to the virtual address
276 Region
= MmFindRegion(MemoryArea
->BaseAddress
,
277 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
279 if (Region
->Type
== MEM_RESERVE
)
281 return(STATUS_UNSUCCESSFUL
);
285 * Get or create a page operation
287 PageOp
= MmGetPageOp(MemoryArea
, (ULONG
)PsGetCurrentProcessId(),
288 (PVOID
)PAGE_ROUND_DOWN(Address
), NULL
, 0,
292 DPRINT1("MmGetPageOp failed");
297 * Check if someone else is already handling this fault, if so wait
300 if (PageOp
->Thread
!= PsGetCurrentThread())
302 MmUnlockAddressSpace(AddressSpace
);
303 Status
= KeWaitForSingleObject(&PageOp
->CompletionEvent
,
309 * Check for various strange conditions
311 if (Status
!= STATUS_SUCCESS
)
313 DPRINT1("Failed to wait for page op\n");
316 if (PageOp
->Status
== STATUS_PENDING
)
318 DPRINT1("Woke for page op before completion\n");
322 * If this wasn't a pagein then we need to restart the handling
324 if (PageOp
->OpType
!= MM_PAGEOP_PAGEIN
)
326 MmLockAddressSpace(AddressSpace
);
327 MmReleasePageOp(PageOp
);
328 return(STATUS_MM_RESTART_OPERATION
);
331 * If the thread handling this fault has failed then we don't retry
333 if (!NT_SUCCESS(PageOp
->Status
))
335 MmLockAddressSpace(AddressSpace
);
336 MmReleasePageOp(PageOp
);
339 MmLockAddressSpace(AddressSpace
);
342 MmLockPage(MmGetPhysicalAddressForProcess(NULL
, Address
));
344 MmReleasePageOp(PageOp
);
345 return(STATUS_SUCCESS
);
349 * Try to allocate a page
351 Status
= MmRequestPageMemoryConsumer(MC_USER
, FALSE
, &Page
);
352 if (Status
== STATUS_NO_MEMORY
)
354 MmUnlockAddressSpace(AddressSpace
);
355 Status
= MmRequestPageMemoryConsumer(MC_USER
, TRUE
, &Page
);
356 MmLockAddressSpace(AddressSpace
);
360 * Handle swapped out pages.
362 if (MmIsPageSwapEntry(NULL
, Address
))
367 MmDeletePageFileMapping(NULL
, Address
, &SwapEntry
);
368 Mdl
= MmCreateMdl(NULL
, NULL
, PAGE_SIZE
);
369 MmBuildMdlFromPages(Mdl
, (PULONG
)&Page
);
370 Status
= MmReadFromSwapPage(SwapEntry
, Mdl
);
371 if (!NT_SUCCESS(Status
))
375 MmSetSavedSwapEntryPage(Page
, SwapEntry
);
379 * Set the page. If we fail because we are out of memory then
382 Status
= MmCreateVirtualMapping(PsGetCurrentProcess(),
384 MemoryArea
->Attributes
,
387 while (Status
== STATUS_NO_MEMORY
)
389 MmUnlockAddressSpace(AddressSpace
);
390 Status
= MmCreateVirtualMapping(PsGetCurrentProcess(),
392 MemoryArea
->Attributes
,
395 MmLockAddressSpace(AddressSpace
);
397 if (!NT_SUCCESS(Status
))
399 DPRINT1("MmCreateVirtualMapping failed, not out of memory\n");
405 * Add the page to the process's working set
407 MmInsertRmap(Page
, PsGetCurrentProcess(), (PVOID
)PAGE_ROUND_DOWN(Address
));
410 * Finish the operation
414 MmLockPage(MmGetPhysicalAddressForProcess(NULL
, Address
));
416 PageOp
->Status
= STATUS_SUCCESS
;
417 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
418 MmReleasePageOp(PageOp
);
419 return(STATUS_SUCCESS
);
423 MmModifyAttributes(PMADDRESS_SPACE AddressSpace
,
431 * FUNCTION: Modify the attributes of a memory region
435 * If we are switching a previously committed region to reserved then
436 * free any allocated pages within the region
438 if (NewType
== MEM_RESERVE
&& OldType
== MEM_COMMIT
)
442 for (i
=0; i
<= (RegionSize
/PAGE_SIZE
); i
++)
444 LARGE_INTEGER PhysicalAddr
;
446 if (MmIsPageSwapEntry(AddressSpace
->Process
,
447 BaseAddress
+ (i
* PAGE_SIZE
)))
451 MmDeletePageFileMapping(AddressSpace
->Process
,
452 BaseAddress
+ (i
* PAGE_SIZE
),
454 MmFreeSwapPage(SwapEntry
);
458 PhysicalAddr
= MmGetPhysicalAddress(BaseAddress
+ (i
*PAGE_SIZE
));
459 MmDeleteVirtualMapping(AddressSpace
->Process
,
460 BaseAddress
+ (i
*PAGE_SIZE
),
462 if (PhysicalAddr
.QuadPart
!= 0)
464 SWAPENTRY SavedSwapEntry
;
465 SavedSwapEntry
= MmGetSavedSwapEntryPage(PhysicalAddr
);
466 if (SavedSwapEntry
!= 0)
468 MmFreeSwapPage(SavedSwapEntry
);
469 MmSetSavedSwapEntryPage(PhysicalAddr
, 0);
471 MmDeleteRmap(PhysicalAddr
, AddressSpace
->Process
,
472 BaseAddress
+ (i
* PAGE_SIZE
));
473 MmReleasePageMemoryConsumer(MC_USER
, PhysicalAddr
);
480 * If we are changing the protection attributes of a committed region then
481 * alter the attributes for any allocated pages within the region
483 if (NewType
== MEM_COMMIT
&& OldType
== MEM_COMMIT
&&
484 OldProtect
!= NewProtect
)
488 for (i
=0; i
<= (RegionSize
/PAGE_SIZE
); i
++)
490 if (MmIsPagePresent(AddressSpace
->Process
,
491 BaseAddress
+ (i
*PAGE_SIZE
)))
493 MmSetPageProtect(AddressSpace
->Process
,
494 BaseAddress
+ (i
*PAGE_SIZE
),
502 NtAllocateVirtualMemory(IN HANDLE ProcessHandle
,
503 IN OUT PVOID
* UBaseAddress
,
505 IN OUT PULONG URegionSize
,
506 IN ULONG AllocationType
,
509 * FUNCTION: Allocates a block of virtual memory in the process address space
511 * ProcessHandle = The handle of the process which owns the virtual memory
512 * BaseAddress = A pointer to the virtual memory allocated. If you
513 * supply a non zero value the system will try to
514 * allocate the memory at the address supplied. It round
515 * it down to a multiple of the page size.
516 * ZeroBits = (OPTIONAL) You can specify the number of high order bits
517 * that must be zero, ensuring that the memory will be
518 * allocated at a address below a certain value.
519 * RegionSize = The number of bytes to allocate
520 * AllocationType = Indicates the type of virtual memory you like to
521 * allocated, can be a combination of MEM_COMMIT,
522 * MEM_RESERVE, MEM_RESET, MEM_TOP_DOWN.
523 * Protect = Indicates the protection type of the pages allocated, can be
524 * a combination of PAGE_READONLY, PAGE_READWRITE,
525 * PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_GUARD,
531 MEMORY_AREA
* MemoryArea
;
534 PMADDRESS_SPACE AddressSpace
;
540 DPRINT("NtAllocateVirtualMemory(*UBaseAddress %x, "
541 "ZeroBits %d, *URegionSize %x, AllocationType %x, Protect %x)\n",
542 *UBaseAddress
,ZeroBits
,*URegionSize
,AllocationType
,
546 * Check the validity of the parameters
548 if ((Protect
& PAGE_FLAGS_VALID_FROM_USER_MODE
) != Protect
)
550 return(STATUS_INVALID_PAGE_PROTECTION
);
552 if ((AllocationType
& (MEM_COMMIT
| MEM_RESERVE
)) == 0)
554 return(STATUS_INVALID_PARAMETER
);
557 PBaseAddress
= *UBaseAddress
;
558 PRegionSize
= *URegionSize
;
560 BaseAddress
= (PVOID
)PAGE_ROUND_DOWN(PBaseAddress
);
561 RegionSize
= PAGE_ROUND_UP(PBaseAddress
+ PRegionSize
) -
562 PAGE_ROUND_DOWN(PBaseAddress
);
564 Status
= ObReferenceObjectByHandle(ProcessHandle
,
565 PROCESS_VM_OPERATION
,
570 if (!NT_SUCCESS(Status
))
572 DPRINT("NtAllocateVirtualMemory() = %x\n",Status
);
576 Type
= (AllocationType
& MEM_COMMIT
) ? MEM_COMMIT
: MEM_RESERVE
;
577 DPRINT("Type %x\n", Type
);
579 AddressSpace
= &Process
->AddressSpace
;
580 MmLockAddressSpace(AddressSpace
);
582 if (PBaseAddress
!= 0)
584 MemoryArea
= MmOpenMemoryAreaByAddress(&Process
->AddressSpace
,
587 if (MemoryArea
!= NULL
&&
588 MemoryArea
->Type
== MEMORY_AREA_VIRTUAL_MEMORY
&&
589 MemoryArea
->Length
>= RegionSize
)
592 MmAlterRegion(&Process
->AddressSpace
,
593 MemoryArea
->BaseAddress
,
594 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
595 PBaseAddress
, RegionSize
,
596 Type
, Protect
, MmModifyAttributes
);
597 MmUnlockAddressSpace(AddressSpace
);
598 ObDereferenceObject(Process
);
599 DPRINT("NtAllocateVirtualMemory() = %x\n",Status
);
602 else if (MemoryArea
!= NULL
)
604 MmUnlockAddressSpace(AddressSpace
);
605 ObDereferenceObject(Process
);
606 return(STATUS_UNSUCCESSFUL
);
610 Status
= MmCreateMemoryArea(Process
,
611 &Process
->AddressSpace
,
612 MEMORY_AREA_VIRTUAL_MEMORY
,
619 if (!NT_SUCCESS(Status
))
621 MmUnlockAddressSpace(AddressSpace
);
622 ObDereferenceObject(Process
);
623 DPRINT("NtAllocateVirtualMemory() = %x\n",Status
);
626 MmInitialiseRegion(&MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
627 RegionSize
, Type
, Protect
);
629 if ((AllocationType
& MEM_COMMIT
) &&
630 ((Protect
& PAGE_READWRITE
) ||
631 (Protect
& PAGE_EXECUTE_READWRITE
)))
633 MmReserveSwapPages(RegionSize
);
636 *UBaseAddress
= BaseAddress
;
637 *URegionSize
= RegionSize
;
638 DPRINT("*UBaseAddress %x *URegionSize %x\n", BaseAddress
, RegionSize
);
640 MmUnlockAddressSpace(AddressSpace
);
641 ObDereferenceObject(Process
);
642 return(STATUS_SUCCESS
);
646 MmFreeVirtualMemoryPage(PVOID Context
,
647 MEMORY_AREA
* MemoryArea
,
649 PHYSICAL_ADDRESS PhysicalAddr
,
653 PEPROCESS Process
= (PEPROCESS
)Context
;
655 if (PhysicalAddr
.QuadPart
!= 0)
657 SWAPENTRY SavedSwapEntry
;
658 SavedSwapEntry
= MmGetSavedSwapEntryPage(PhysicalAddr
);
659 if (SavedSwapEntry
!= 0)
661 MmFreeSwapPage(SavedSwapEntry
);
662 MmSetSavedSwapEntryPage(PhysicalAddr
, 0);
664 MmDeleteRmap(PhysicalAddr
, Process
, Address
);
665 MmReleasePageMemoryConsumer(MC_USER
, PhysicalAddr
);
667 else if (SwapEntry
!= 0)
669 MmFreeSwapPage(SwapEntry
);
674 MmFreeVirtualMemory(PEPROCESS Process
,
675 PMEMORY_AREA MemoryArea
)
677 PLIST_ENTRY current_entry
;
681 DPRINT("MmFreeVirtualMemory(Process %p MemoryArea %p)\n", Process
,
684 /* Mark this memory area as about to be deleted. */
685 MemoryArea
->DeleteInProgress
= TRUE
;
688 * Wait for any ongoing paging operations. Notice that since we have
689 * flagged this memory area as deleted no more page ops will be added.
691 if (MemoryArea
->PageOpCount
> 0)
693 for (i
= 0; i
< (PAGE_ROUND_UP(MemoryArea
->Length
) / PAGE_SIZE
); i
++)
697 if (MemoryArea
->PageOpCount
== 0)
702 PageOp
= MmCheckForPageOp(MemoryArea
, Process
->UniqueProcessId
,
703 MemoryArea
->BaseAddress
+ (i
* PAGE_SIZE
),
708 MmUnlockAddressSpace(&Process
->AddressSpace
);
709 Status
= KeWaitForSingleObject(&PageOp
->CompletionEvent
,
714 if (Status
!= STATUS_SUCCESS
)
716 DPRINT1("Failed to wait for page op\n");
719 MmLockAddressSpace(&Process
->AddressSpace
);
720 MmReleasePageOp(PageOp
);
725 /* Free all the individual segments. */
726 current_entry
= MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
.Flink
;
727 while (current_entry
!= &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
)
729 current
= CONTAINING_RECORD(current_entry
, MM_REGION
, RegionListEntry
);
730 current_entry
= current_entry
->Flink
;
734 /* Actually free the memory area. */
735 MmFreeMemoryArea(&Process
->AddressSpace
,
736 MemoryArea
->BaseAddress
,
738 MmFreeVirtualMemoryPage
,
743 NtFreeVirtualMemory(IN HANDLE ProcessHandle
,
744 IN PVOID
* PBaseAddress
,
745 IN PULONG PRegionSize
,
748 * FUNCTION: Frees a range of virtual memory
750 * ProcessHandle = Points to the process that allocated the virtual
752 * BaseAddress = Points to the memory address, rounded down to a
753 * multiple of the pagesize
754 * RegionSize = Limits the range to free, rounded up to a multiple of
756 * FreeType = Can be one of the values: MEM_DECOMMIT, or MEM_RELEASE
760 MEMORY_AREA
* MemoryArea
;
763 PMADDRESS_SPACE AddressSpace
;
767 DPRINT("NtFreeVirtualMemory(ProcessHandle %x, *PBaseAddress %x, "
768 "*PRegionSize %x, FreeType %x)\n",ProcessHandle
,*PBaseAddress
,
769 *PRegionSize
,FreeType
);
771 BaseAddress
= (PVOID
)PAGE_ROUND_DOWN((*PBaseAddress
));
772 RegionSize
= PAGE_ROUND_UP((*PBaseAddress
) + (*PRegionSize
)) -
773 PAGE_ROUND_DOWN((*PBaseAddress
));
775 Status
= ObReferenceObjectByHandle(ProcessHandle
,
776 PROCESS_VM_OPERATION
,
781 if (!NT_SUCCESS(Status
))
786 AddressSpace
= &Process
->AddressSpace
;
788 MmLockAddressSpace(AddressSpace
);
789 MemoryArea
= MmOpenMemoryAreaByAddress(AddressSpace
,
791 if (MemoryArea
== NULL
)
793 MmUnlockAddressSpace(AddressSpace
);
794 ObDereferenceObject(Process
);
795 return(STATUS_UNSUCCESSFUL
);
801 /* We can only free a memory area in one step. */
802 if (MemoryArea
->BaseAddress
!= BaseAddress
)
804 MmUnlockAddressSpace(AddressSpace
);
805 ObDereferenceObject(Process
);
806 return(STATUS_UNSUCCESSFUL
);
808 MmFreeVirtualMemory(Process
, MemoryArea
);
809 MmUnlockAddressSpace(AddressSpace
);
810 ObDereferenceObject(Process
);
811 return(STATUS_SUCCESS
);
815 MmAlterRegion(AddressSpace
,
816 MemoryArea
->BaseAddress
,
817 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
823 MmUnlockAddressSpace(AddressSpace
);
824 ObDereferenceObject(Process
);
827 MmUnlockAddressSpace(AddressSpace
);
828 ObDereferenceObject(Process
);
829 return(STATUS_NOT_IMPLEMENTED
);
833 MmProtectAnonMem(PMADDRESS_SPACE AddressSpace
,
834 PMEMORY_AREA MemoryArea
,
843 Region
= MmFindRegion(MemoryArea
->BaseAddress
,
844 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
846 *OldProtect
= Region
->Protect
;
847 Status
= MmAlterRegion(AddressSpace
, MemoryArea
->BaseAddress
,
848 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
849 BaseAddress
, Length
, Region
->Type
, Protect
,
855 MmQueryAnonMem(PMEMORY_AREA MemoryArea
,
857 PMEMORY_BASIC_INFORMATION Info
,
863 Info
->BaseAddress
= (PVOID
)PAGE_ROUND_DOWN(Address
);
865 Region
= MmFindRegion(MemoryArea
->BaseAddress
,
866 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
867 Address
, &RegionBase
);
868 Info
->AllocationBase
= RegionBase
;
869 Info
->AllocationProtect
= Region
->Protect
; /* FIXME */
870 Info
->RegionSize
= Region
->Length
;
871 Info
->State
= Region
->Type
;
872 Info
->Protect
= Region
->Protect
;
873 Info
->Type
= MEM_PRIVATE
;
874 return(STATUS_SUCCESS
);