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.
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);
158 if (PhysicalAddress.QuadPart == 0)
164 * Paging out non-dirty data is easy.
168 MmDeleteVirtualMapping(MemoryArea->Process, Address, FALSE, NULL, NULL);
169 MmDeleteAllRmaps(PhysicalAddress, NULL, NULL);
170 if ((SwapEntry = MmGetSavedSwapEntryPage(PhysicalAddress)) != 0)
172 MmCreatePageFileMapping(MemoryArea->Process, Address, SwapEntry);
173 MmSetSavedSwapEntryPage(PhysicalAddress, 0);
175 MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
176 PageOp->Status = STATUS_SUCCESS;
177 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
178 MmReleasePageOp(PageOp);
179 return(STATUS_SUCCESS);
183 * If necessary, allocate an entry in the paging file for this page
185 SwapEntry = MmGetSavedSwapEntryPage(PhysicalAddress);
188 SwapEntry = MmAllocSwapPage();
191 MmShowOutOfSpaceMessagePagingFile();
192 MmEnableVirtualMapping(MemoryArea->Process, Address);
193 PageOp->Status = STATUS_UNSUCCESSFUL;
194 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
195 MmReleasePageOp(PageOp);
196 return(STATUS_UNSUCCESSFUL);
201 * Write the page to the pagefile
203 Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE);
204 MmBuildMdlFromPages(Mdl, &PhysicalAddress.u.LowPart);
205 Status = MmWriteToSwapPage(SwapEntry, Mdl);
206 if (!NT_SUCCESS(Status))
208 DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
210 MmEnableVirtualMapping(MemoryArea->Process, Address);
211 PageOp->Status = STATUS_UNSUCCESSFUL;
212 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
213 MmReleasePageOp(PageOp);
214 return(STATUS_UNSUCCESSFUL);
218 * Otherwise we have succeeded, free the page
220 DPRINT("MM: Swapped out virtual memory page 0x%.8X!\n", PhysicalAddress);
221 MmDeleteVirtualMapping(MemoryArea->Process, Address, FALSE, NULL, NULL);
222 MmCreatePageFileMapping(MemoryArea->Process, Address, SwapEntry);
223 MmDeleteAllRmaps(PhysicalAddress, NULL, NULL);
224 MmSetSavedSwapEntryPage(PhysicalAddress, 0);
225 MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
226 PageOp->Status = STATUS_SUCCESS;
227 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
228 MmReleasePageOp(PageOp);
229 return(STATUS_SUCCESS);
233 MmNotPresentFaultVirtualMemory(PMADDRESS_SPACE AddressSpace,
234 MEMORY_AREA* MemoryArea,
238 * FUNCTION: Move data into memory to satisfy a page not present fault
240 * AddressSpace = Address space within which the fault occurred
241 * MemoryArea = The memory area within which the fault occurred
242 * Address = The absolute address of fault
244 * NOTES: This function is called with the address space lock held.
247 PHYSICAL_ADDRESS Page;
253 * There is a window between taking the page fault and locking the
254 * address space when another thread could load the page so we check
257 if (MmIsPagePresent(NULL, Address))
261 MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
263 return(STATUS_SUCCESS);
267 * Check for the virtual memory area being deleted.
269 if (MemoryArea->DeleteInProgress)
271 return(STATUS_UNSUCCESSFUL);
275 * Get the segment corresponding to the virtual address
277 Region = MmFindRegion(MemoryArea->BaseAddress,
278 &MemoryArea->Data.VirtualMemoryData.RegionListHead,
280 if (Region->Type == MEM_RESERVE)
282 return(STATUS_UNSUCCESSFUL);
286 * Get or create a page operation
288 PageOp = MmGetPageOp(MemoryArea, (ULONG)PsGetCurrentProcessId(),
289 (PVOID)PAGE_ROUND_DOWN(Address), NULL, 0,
293 DPRINT1("MmGetPageOp failed");
298 * Check if someone else is already handling this fault, if so wait
301 if (PageOp->Thread != PsGetCurrentThread())
303 MmUnlockAddressSpace(AddressSpace);
304 Status = KeWaitForSingleObject(&PageOp->CompletionEvent,
310 * Check for various strange conditions
312 if (Status != STATUS_SUCCESS)
314 DPRINT1("Failed to wait for page op\n");
317 if (PageOp->Status == STATUS_PENDING)
319 DPRINT1("Woke for page op before completion\n");
323 * If this wasn't a pagein then we need to restart the handling
325 if (PageOp->OpType != MM_PAGEOP_PAGEIN)
327 MmLockAddressSpace(AddressSpace);
328 MmReleasePageOp(PageOp);
329 return(STATUS_MM_RESTART_OPERATION);
332 * If the thread handling this fault has failed then we don't retry
334 if (!NT_SUCCESS(PageOp->Status))
336 MmLockAddressSpace(AddressSpace);
337 MmReleasePageOp(PageOp);
340 MmLockAddressSpace(AddressSpace);
343 MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
345 MmReleasePageOp(PageOp);
346 return(STATUS_SUCCESS);
350 * Try to allocate a page
352 Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page);
353 if (Status == STATUS_NO_MEMORY)
355 MmUnlockAddressSpace(AddressSpace);
356 Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
357 MmLockAddressSpace(AddressSpace);
361 * Handle swapped out pages.
363 if (MmIsPageSwapEntry(NULL, Address))
368 MmDeletePageFileMapping(NULL, Address, &SwapEntry);
369 Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE);
370 MmBuildMdlFromPages(Mdl, (PULONG)&Page);
371 Status = MmReadFromSwapPage(SwapEntry, Mdl);
372 if (!NT_SUCCESS(Status))
376 MmSetSavedSwapEntryPage(Page, SwapEntry);
380 * Set the page. If we fail because we are out of memory then
383 Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
385 MemoryArea->Attributes,
388 while (Status == STATUS_NO_MEMORY)
390 MmUnlockAddressSpace(AddressSpace);
391 Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
393 MemoryArea->Attributes,
396 MmLockAddressSpace(AddressSpace);
398 if (!NT_SUCCESS(Status))
400 DPRINT1("MmCreateVirtualMapping failed, not out of memory\n");
406 * Add the page to the process's working set
408 MmInsertRmap(Page, PsGetCurrentProcess(), (PVOID)PAGE_ROUND_DOWN(Address));
411 * Finish the operation
415 MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
417 PageOp->Status = STATUS_SUCCESS;
418 KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
419 MmReleasePageOp(PageOp);
420 return(STATUS_SUCCESS);
424 MmModifyAttributes(PMADDRESS_SPACE AddressSpace,
432 * FUNCTION: Modify the attributes of a memory region
436 * If we are switching a previously committed region to reserved then
437 * free any allocated pages within the region
439 if (NewType == MEM_RESERVE && OldType == MEM_COMMIT)
443 for (i=0; i < PAGE_ROUND_UP(RegionSize)/PAGE_SIZE; i++)
445 LARGE_INTEGER PhysicalAddr;
447 if (MmIsPageSwapEntry(AddressSpace->Process,
448 BaseAddress + (i * PAGE_SIZE)))
452 MmDeletePageFileMapping(AddressSpace->Process,
453 BaseAddress + (i * PAGE_SIZE),
455 MmFreeSwapPage(SwapEntry);
459 PhysicalAddr = MmGetPhysicalAddress(BaseAddress + (i*PAGE_SIZE));
460 MmDeleteVirtualMapping(AddressSpace->Process,
461 BaseAddress + (i*PAGE_SIZE),
463 if (PhysicalAddr.QuadPart != 0)
465 SWAPENTRY SavedSwapEntry;
466 SavedSwapEntry = MmGetSavedSwapEntryPage(PhysicalAddr);
467 if (SavedSwapEntry != 0)
469 MmFreeSwapPage(SavedSwapEntry);
470 MmSetSavedSwapEntryPage(PhysicalAddr, 0);
472 MmDeleteRmap(PhysicalAddr, AddressSpace->Process,
473 BaseAddress + (i * PAGE_SIZE));
474 MmReleasePageMemoryConsumer(MC_USER, PhysicalAddr);
481 * If we are changing the protection attributes of a committed region then
482 * alter the attributes for any allocated pages within the region
484 if (NewType == MEM_COMMIT && OldType == MEM_COMMIT &&
485 OldProtect != NewProtect)
489 for (i=0; i < PAGE_ROUND_UP(RegionSize)/PAGE_SIZE; i++)
491 if (MmIsPagePresent(AddressSpace->Process,
492 BaseAddress + (i*PAGE_SIZE)))
494 MmSetPageProtect(AddressSpace->Process,
495 BaseAddress + (i*PAGE_SIZE),
503 NtAllocateVirtualMemory(IN HANDLE ProcessHandle,
504 IN OUT PVOID* UBaseAddress,
506 IN OUT PULONG URegionSize,
507 IN ULONG AllocationType,
510 * FUNCTION: Allocates a block of virtual memory in the process address space
512 * ProcessHandle = The handle of the process which owns the virtual memory
513 * BaseAddress = A pointer to the virtual memory allocated. If you
514 * supply a non zero value the system will try to
515 * allocate the memory at the address supplied. It round
516 * it down to a multiple of the page size.
517 * ZeroBits = (OPTIONAL) You can specify the number of high order bits
518 * that must be zero, ensuring that the memory will be
519 * allocated at a address below a certain value.
520 * RegionSize = The number of bytes to allocate
521 * AllocationType = Indicates the type of virtual memory you like to
522 * allocated, can be a combination of MEM_COMMIT,
523 * MEM_RESERVE, MEM_RESET, MEM_TOP_DOWN.
524 * Protect = Indicates the protection type of the pages allocated, can be
525 * a combination of PAGE_READONLY, PAGE_READWRITE,
526 * PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_GUARD,
532 MEMORY_AREA* MemoryArea;
535 PMADDRESS_SPACE AddressSpace;
541 DPRINT("NtAllocateVirtualMemory(*UBaseAddress %x, "
542 "ZeroBits %d, *URegionSize %x, AllocationType %x, Protect %x)\n",
543 *UBaseAddress,ZeroBits,*URegionSize,AllocationType,
547 * Check the validity of the parameters
549 if ((Protect & PAGE_FLAGS_VALID_FROM_USER_MODE) != Protect)
551 return(STATUS_INVALID_PAGE_PROTECTION);
553 if ((AllocationType & (MEM_COMMIT | MEM_RESERVE)) == 0)
555 return(STATUS_INVALID_PARAMETER);
558 PBaseAddress = *UBaseAddress;
559 PRegionSize = *URegionSize;
561 BaseAddress = (PVOID)PAGE_ROUND_DOWN(PBaseAddress);
562 RegionSize = PAGE_ROUND_UP(PBaseAddress + PRegionSize) -
563 PAGE_ROUND_DOWN(PBaseAddress);
565 Status = ObReferenceObjectByHandle(ProcessHandle,
566 PROCESS_VM_OPERATION,
571 if (!NT_SUCCESS(Status))
573 DPRINT("NtAllocateVirtualMemory() = %x\n",Status);
577 Type = (AllocationType & MEM_COMMIT) ? MEM_COMMIT : MEM_RESERVE;
578 DPRINT("Type %x\n", Type);
580 AddressSpace = &Process->AddressSpace;
581 MmLockAddressSpace(AddressSpace);
583 if (PBaseAddress != 0)
585 MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
588 if (MemoryArea != NULL &&
589 MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY &&
590 MemoryArea->Length >= RegionSize)
593 MmAlterRegion(AddressSpace,
594 MemoryArea->BaseAddress,
595 &MemoryArea->Data.VirtualMemoryData.RegionListHead,
596 PBaseAddress, RegionSize,
597 Type, Protect, MmModifyAttributes);
598 MmUnlockAddressSpace(AddressSpace);
599 ObDereferenceObject(Process);
600 DPRINT("NtAllocateVirtualMemory() = %x\n",Status);
603 else if (MemoryArea != NULL)
605 MmUnlockAddressSpace(AddressSpace);
606 ObDereferenceObject(Process);
607 return(STATUS_UNSUCCESSFUL);
611 Status = MmCreateMemoryArea(Process,
612 &Process->AddressSpace,
613 MEMORY_AREA_VIRTUAL_MEMORY,
620 if (!NT_SUCCESS(Status))
622 MmUnlockAddressSpace(AddressSpace);
623 ObDereferenceObject(Process);
624 DPRINT("NtAllocateVirtualMemory() = %x\n",Status);
627 MmInitialiseRegion(&MemoryArea->Data.VirtualMemoryData.RegionListHead,
628 RegionSize, Type, Protect);
630 if ((AllocationType & MEM_COMMIT) &&
631 ((Protect & PAGE_READWRITE) ||
632 (Protect & PAGE_EXECUTE_READWRITE)))
634 MmReserveSwapPages(RegionSize);
637 *UBaseAddress = BaseAddress;
638 *URegionSize = RegionSize;
639 DPRINT("*UBaseAddress %x *URegionSize %x\n", BaseAddress, RegionSize);
641 MmUnlockAddressSpace(AddressSpace);
642 ObDereferenceObject(Process);
643 return(STATUS_SUCCESS);
647 MmFreeVirtualMemoryPage(PVOID Context,
648 MEMORY_AREA* MemoryArea,
650 PHYSICAL_ADDRESS PhysicalAddr,
654 PEPROCESS Process = (PEPROCESS)Context;
656 if (PhysicalAddr.QuadPart != 0)
658 SWAPENTRY SavedSwapEntry;
659 SavedSwapEntry = MmGetSavedSwapEntryPage(PhysicalAddr);
660 if (SavedSwapEntry != 0)
662 MmFreeSwapPage(SavedSwapEntry);
663 MmSetSavedSwapEntryPage(PhysicalAddr, 0);
665 MmDeleteRmap(PhysicalAddr, Process, Address);
666 MmReleasePageMemoryConsumer(MC_USER, PhysicalAddr);
668 else if (SwapEntry != 0)
670 MmFreeSwapPage(SwapEntry);
675 MmFreeVirtualMemory(PEPROCESS Process,
676 PMEMORY_AREA MemoryArea)
678 PLIST_ENTRY current_entry;
682 DPRINT("MmFreeVirtualMemory(Process %p MemoryArea %p)\n", Process,
685 /* Mark this memory area as about to be deleted. */
686 MemoryArea->DeleteInProgress = TRUE;
689 * Wait for any ongoing paging operations. Notice that since we have
690 * flagged this memory area as deleted no more page ops will be added.
692 if (MemoryArea->PageOpCount > 0)
694 for (i = 0; i < PAGE_ROUND_UP(MemoryArea->Length) / PAGE_SIZE; i++)
698 if (MemoryArea->PageOpCount == 0)
703 PageOp = MmCheckForPageOp(MemoryArea, Process->UniqueProcessId,
704 MemoryArea->BaseAddress + (i * PAGE_SIZE),
709 MmUnlockAddressSpace(&Process->AddressSpace);
710 Status = KeWaitForSingleObject(&PageOp->CompletionEvent,
715 if (Status != STATUS_SUCCESS)
717 DPRINT1("Failed to wait for page op\n");
720 MmLockAddressSpace(&Process->AddressSpace);
721 MmReleasePageOp(PageOp);
726 /* Free all the individual segments. */
727 current_entry = MemoryArea->Data.VirtualMemoryData.RegionListHead.Flink;
728 while (current_entry != &MemoryArea->Data.VirtualMemoryData.RegionListHead)
730 current = CONTAINING_RECORD(current_entry, MM_REGION, RegionListEntry);
731 current_entry = current_entry->Flink;
735 /* Actually free the memory area. */
736 MmFreeMemoryArea(&Process->AddressSpace,
737 MemoryArea->BaseAddress,
739 MmFreeVirtualMemoryPage,
744 NtFreeVirtualMemory(IN HANDLE ProcessHandle,
745 IN PVOID* PBaseAddress,
746 IN PULONG PRegionSize,
749 * FUNCTION: Frees a range of virtual memory
751 * ProcessHandle = Points to the process that allocated the virtual
753 * BaseAddress = Points to the memory address, rounded down to a
754 * multiple of the pagesize
755 * RegionSize = Limits the range to free, rounded up to a multiple of
757 * FreeType = Can be one of the values: MEM_DECOMMIT, or MEM_RELEASE
761 MEMORY_AREA* MemoryArea;
764 PMADDRESS_SPACE AddressSpace;
768 DPRINT("NtFreeVirtualMemory(ProcessHandle %x, *PBaseAddress %x, "
769 "*PRegionSize %x, FreeType %x)\n",ProcessHandle,*PBaseAddress,
770 *PRegionSize,FreeType);
772 BaseAddress = (PVOID)PAGE_ROUND_DOWN((*PBaseAddress));
773 RegionSize = PAGE_ROUND_UP((*PBaseAddress) + (*PRegionSize)) -
774 PAGE_ROUND_DOWN((*PBaseAddress));
776 Status = ObReferenceObjectByHandle(ProcessHandle,
777 PROCESS_VM_OPERATION,
782 if (!NT_SUCCESS(Status))
787 AddressSpace = &Process->AddressSpace;
789 MmLockAddressSpace(AddressSpace);
790 MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
792 if (MemoryArea == NULL)
794 MmUnlockAddressSpace(AddressSpace);
795 ObDereferenceObject(Process);
796 return(STATUS_UNSUCCESSFUL);
802 /* We can only free a memory area in one step. */
803 if (MemoryArea->BaseAddress != BaseAddress)
805 MmUnlockAddressSpace(AddressSpace);
806 ObDereferenceObject(Process);
807 return(STATUS_UNSUCCESSFUL);
809 MmFreeVirtualMemory(Process, MemoryArea);
810 MmUnlockAddressSpace(AddressSpace);
811 ObDereferenceObject(Process);
812 return(STATUS_SUCCESS);
816 MmAlterRegion(AddressSpace,
817 MemoryArea->BaseAddress,
818 &MemoryArea->Data.VirtualMemoryData.RegionListHead,
824 MmUnlockAddressSpace(AddressSpace);
825 ObDereferenceObject(Process);
828 MmUnlockAddressSpace(AddressSpace);
829 ObDereferenceObject(Process);
830 return(STATUS_NOT_IMPLEMENTED);
834 MmProtectAnonMem(PMADDRESS_SPACE AddressSpace,
835 PMEMORY_AREA MemoryArea,
844 Region = MmFindRegion(MemoryArea->BaseAddress,
845 &MemoryArea->Data.VirtualMemoryData.RegionListHead,
847 *OldProtect = Region->Protect;
848 Status = MmAlterRegion(AddressSpace, MemoryArea->BaseAddress,
849 &MemoryArea->Data.VirtualMemoryData.RegionListHead,
850 BaseAddress, Length, Region->Type, Protect,
856 MmQueryAnonMem(PMEMORY_AREA MemoryArea,
858 PMEMORY_BASIC_INFORMATION Info,
864 Info->BaseAddress = (PVOID)PAGE_ROUND_DOWN(Address);
866 Region = MmFindRegion(MemoryArea->BaseAddress,
867 &MemoryArea->Data.VirtualMemoryData.RegionListHead,
868 Address, &RegionBase);
869 Info->AllocationBase = RegionBase;
870 Info->AllocationProtect = Region->Protect; /* FIXME */
871 Info->RegionSize = Region->Length;
872 Info->State = Region->Type;
873 Info->Protect = Region->Protect;
874 Info->Type = MEM_PRIVATE;
875 return(STATUS_SUCCESS);