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.30 2004/08/01 07:24:57 hbirr 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
,
52 * Check for paging out from a deleted virtual memory area.
54 if (MemoryArea
->DeleteInProgress
)
56 PageOp
->Status
= STATUS_UNSUCCESSFUL
;
57 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
58 MmReleasePageOp(PageOp
);
59 return(STATUS_UNSUCCESSFUL
);
62 Page
= MmGetPfnForProcess(AddressSpace
->Process
, Address
);
65 * Get that the page actually is dirty.
67 if (!MmIsDirtyPage(MemoryArea
->Process
, Address
))
69 PageOp
->Status
= STATUS_SUCCESS
;
70 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
71 MmReleasePageOp(PageOp
);
72 return(STATUS_SUCCESS
);
76 * Speculatively set the mapping to clean.
78 MmSetCleanPage(MemoryArea
->Process
, Address
);
81 * If necessary, allocate an entry in the paging file for this page
83 SwapEntry
= MmGetSavedSwapEntryPage(Page
);
86 SwapEntry
= MmAllocSwapPage();
89 MmSetDirtyPage(MemoryArea
->Process
, Address
);
90 PageOp
->Status
= STATUS_PAGEFILE_QUOTA_EXCEEDED
;
91 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
92 MmReleasePageOp(PageOp
);
93 return(STATUS_PAGEFILE_QUOTA_EXCEEDED
);
98 * Write the page to the pagefile
100 Status
= MmWriteToSwapPage(SwapEntry
, Page
);
101 if (!NT_SUCCESS(Status
))
103 DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
105 MmSetDirtyPage(MemoryArea
->Process
, Address
);
106 PageOp
->Status
= STATUS_UNSUCCESSFUL
;
107 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
108 MmReleasePageOp(PageOp
);
109 return(STATUS_UNSUCCESSFUL
);
113 * Otherwise we have succeeded.
115 MmSetSavedSwapEntryPage(Page
, SwapEntry
);
116 PageOp
->Status
= STATUS_SUCCESS
;
117 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
118 MmReleasePageOp(PageOp
);
119 return(STATUS_SUCCESS
);
123 MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace
,
124 PMEMORY_AREA MemoryArea
,
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
,
159 * Paging out non-dirty data is easy.
163 MmDeleteVirtualMapping(MemoryArea
->Process
, Address
, FALSE
, NULL
, NULL
);
164 MmDeleteAllRmaps(Page
, NULL
, NULL
);
165 if ((SwapEntry
= MmGetSavedSwapEntryPage(Page
)) != 0)
167 MmCreatePageFileMapping(MemoryArea
->Process
, Address
, SwapEntry
);
168 MmSetSavedSwapEntryPage(Page
, 0);
170 MmReleasePageMemoryConsumer(MC_USER
, Page
);
171 PageOp
->Status
= STATUS_SUCCESS
;
172 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
173 MmReleasePageOp(PageOp
);
174 return(STATUS_SUCCESS
);
178 * If necessary, allocate an entry in the paging file for this page
180 SwapEntry
= MmGetSavedSwapEntryPage(Page
);
183 SwapEntry
= MmAllocSwapPage();
186 MmShowOutOfSpaceMessagePagingFile();
187 MmEnableVirtualMapping(MemoryArea
->Process
, Address
);
188 PageOp
->Status
= STATUS_UNSUCCESSFUL
;
189 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
190 MmReleasePageOp(PageOp
);
191 return(STATUS_PAGEFILE_QUOTA
);
196 * Write the page to the pagefile
198 Status
= MmWriteToSwapPage(SwapEntry
, Page
);
199 if (!NT_SUCCESS(Status
))
201 DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
203 MmEnableVirtualMapping(MemoryArea
->Process
, Address
);
204 PageOp
->Status
= STATUS_UNSUCCESSFUL
;
205 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
206 MmReleasePageOp(PageOp
);
207 return(STATUS_UNSUCCESSFUL
);
211 * Otherwise we have succeeded, free the page
213 DPRINT("MM: Swapped out virtual memory page 0x%.8X!\n", Page
<< PAGE_SHIFT
);
214 MmDeleteVirtualMapping(MemoryArea
->Process
, Address
, FALSE
, NULL
, NULL
);
215 MmCreatePageFileMapping(MemoryArea
->Process
, Address
, SwapEntry
);
216 MmDeleteAllRmaps(Page
, NULL
, NULL
);
217 MmSetSavedSwapEntryPage(Page
, 0);
218 MmReleasePageMemoryConsumer(MC_USER
, Page
);
219 PageOp
->Status
= STATUS_SUCCESS
;
220 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
221 MmReleasePageOp(PageOp
);
222 return(STATUS_SUCCESS
);
226 MmNotPresentFaultVirtualMemory(PMADDRESS_SPACE AddressSpace
,
227 MEMORY_AREA
* MemoryArea
,
231 * FUNCTION: Move data into memory to satisfy a page not present fault
233 * AddressSpace = Address space within which the fault occurred
234 * MemoryArea = The memory area within which the fault occurred
235 * Address = The absolute address of fault
237 * NOTES: This function is called with the address space lock held.
246 * There is a window between taking the page fault and locking the
247 * address space when another thread could load the page so we check
250 if (MmIsPagePresent(NULL
, Address
))
254 MmLockPage(MmGetPfnForProcess(NULL
, Address
));
256 return(STATUS_SUCCESS
);
260 * Check for the virtual memory area being deleted.
262 if (MemoryArea
->DeleteInProgress
)
264 return(STATUS_UNSUCCESSFUL
);
268 * Get the segment corresponding to the virtual address
270 Region
= MmFindRegion(MemoryArea
->BaseAddress
,
271 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
273 if (Region
->Type
== MEM_RESERVE
|| Region
->Protect
== PAGE_NOACCESS
)
275 return(STATUS_ACCESS_VIOLATION
);
279 * Get or create a page operation
281 PageOp
= MmGetPageOp(MemoryArea
, (ULONG
)MemoryArea
->Process
->UniqueProcessId
,
282 (PVOID
)PAGE_ROUND_DOWN(Address
), NULL
, 0,
283 MM_PAGEOP_PAGEIN
, FALSE
);
286 DPRINT1("MmGetPageOp failed");
291 * Check if someone else is already handling this fault, if so wait
294 if (PageOp
->Thread
!= PsGetCurrentThread())
296 MmUnlockAddressSpace(AddressSpace
);
297 Status
= KeWaitForSingleObject(&PageOp
->CompletionEvent
,
303 * Check for various strange conditions
305 if (Status
!= STATUS_SUCCESS
)
307 DPRINT1("Failed to wait for page op\n");
310 if (PageOp
->Status
== STATUS_PENDING
)
312 DPRINT1("Woke for page op before completion\n");
316 * If this wasn't a pagein then we need to restart the handling
318 if (PageOp
->OpType
!= MM_PAGEOP_PAGEIN
)
320 MmLockAddressSpace(AddressSpace
);
321 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
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 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
332 Status
= PageOp
->Status
;
333 MmReleasePageOp(PageOp
);
336 MmLockAddressSpace(AddressSpace
);
339 MmLockPage(MmGetPfnForProcess(NULL
, Address
));
341 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
342 MmReleasePageOp(PageOp
);
343 return(STATUS_SUCCESS
);
347 * Try to allocate a page
349 Status
= MmRequestPageMemoryConsumer(MC_USER
, FALSE
, &Page
);
350 if (Status
== STATUS_NO_MEMORY
)
352 MmUnlockAddressSpace(AddressSpace
);
353 Status
= MmRequestPageMemoryConsumer(MC_USER
, TRUE
, &Page
);
354 MmLockAddressSpace(AddressSpace
);
356 if (!NT_SUCCESS(Status
))
358 DPRINT1("MmRequestPageMemoryConsumer failed, status = %x\n", Status
);
363 * Handle swapped out pages.
365 if (MmIsPageSwapEntry(NULL
, Address
))
369 MmDeletePageFileMapping(MemoryArea
->Process
, Address
, &SwapEntry
);
370 Status
= MmReadFromSwapPage(SwapEntry
, Page
);
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(MemoryArea
->Process
,
383 (PVOID
)PAGE_ROUND_DOWN(Address
),
387 while (Status
== STATUS_NO_MEMORY
)
389 MmUnlockAddressSpace(AddressSpace
);
390 Status
= MmCreateVirtualMapping(MemoryArea
->Process
,
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
, MemoryArea
->Process
, (PVOID
)PAGE_ROUND_DOWN(Address
));
410 * Finish the operation
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
< PAGE_ROUND_UP(RegionSize
)/PAGE_SIZE
; i
++)
446 if (MmIsPageSwapEntry(AddressSpace
->Process
,
447 (char*)BaseAddress
+ (i
* PAGE_SIZE
)))
451 MmDeletePageFileMapping(AddressSpace
->Process
,
452 (char*)BaseAddress
+ (i
* PAGE_SIZE
),
454 MmFreeSwapPage(SwapEntry
);
458 MmDeleteVirtualMapping(AddressSpace
->Process
,
459 (char*)BaseAddress
+ (i
*PAGE_SIZE
),
463 SWAPENTRY SavedSwapEntry
;
464 SavedSwapEntry
= MmGetSavedSwapEntryPage(Page
);
465 if (SavedSwapEntry
!= 0)
467 MmFreeSwapPage(SavedSwapEntry
);
468 MmSetSavedSwapEntryPage(Page
, 0);
470 MmDeleteRmap(Page
, AddressSpace
->Process
,
471 (char*)BaseAddress
+ (i
* PAGE_SIZE
));
472 MmReleasePageMemoryConsumer(MC_USER
, Page
);
479 * If we are changing the protection attributes of a committed region then
480 * alter the attributes for any allocated pages within the region
482 if (NewType
== MEM_COMMIT
&& OldType
== MEM_COMMIT
&&
483 OldProtect
!= NewProtect
)
487 for (i
=0; i
< PAGE_ROUND_UP(RegionSize
)/PAGE_SIZE
; i
++)
489 if (MmIsPagePresent(AddressSpace
->Process
,
490 (char*)BaseAddress
+ (i
*PAGE_SIZE
)))
492 MmSetPageProtect(AddressSpace
->Process
,
493 (char*)BaseAddress
+ (i
*PAGE_SIZE
),
504 NtAllocateVirtualMemory(IN HANDLE ProcessHandle
,
505 IN OUT PVOID
* UBaseAddress
,
507 IN OUT PULONG URegionSize
,
508 IN ULONG AllocationType
,
511 * FUNCTION: Allocates a block of virtual memory in the process address space
513 * ProcessHandle = The handle of the process which owns the virtual memory
514 * BaseAddress = A pointer to the virtual memory allocated. If you
515 * supply a non zero value the system will try to
516 * allocate the memory at the address supplied. It round
517 * it down to a multiple of the page size.
518 * ZeroBits = (OPTIONAL) You can specify the number of high order bits
519 * that must be zero, ensuring that the memory will be
520 * allocated at a address below a certain value.
521 * RegionSize = The number of bytes to allocate
522 * AllocationType = Indicates the type of virtual memory you like to
523 * allocated, can be a combination of MEM_COMMIT,
524 * MEM_RESERVE, MEM_RESET, MEM_TOP_DOWN.
525 * Protect = Indicates the protection type of the pages allocated, can be
526 * a combination of PAGE_READONLY, PAGE_READWRITE,
527 * PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_GUARD,
533 MEMORY_AREA
* MemoryArea
;
536 PMADDRESS_SPACE AddressSpace
;
541 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
543 DPRINT("NtAllocateVirtualMemory(*UBaseAddress %x, "
544 "ZeroBits %d, *URegionSize %x, AllocationType %x, Protect %x)\n",
545 *UBaseAddress
,ZeroBits
,*URegionSize
,AllocationType
,
549 * Check the validity of the parameters
551 if ((Protect
& PAGE_FLAGS_VALID_FROM_USER_MODE
) != Protect
)
553 return(STATUS_INVALID_PAGE_PROTECTION
);
555 if ((AllocationType
& (MEM_COMMIT
| MEM_RESERVE
)) == 0)
557 return(STATUS_INVALID_PARAMETER
);
560 PBaseAddress
= *UBaseAddress
;
561 PRegionSize
= *URegionSize
;
562 BoundaryAddressMultiple
.QuadPart
= 0;
564 BaseAddress
= (PVOID
)PAGE_ROUND_DOWN(PBaseAddress
);
565 RegionSize
= PAGE_ROUND_UP(PBaseAddress
+ PRegionSize
) -
566 PAGE_ROUND_DOWN(PBaseAddress
);
568 Status
= ObReferenceObjectByHandle(ProcessHandle
,
569 PROCESS_VM_OPERATION
,
574 if (!NT_SUCCESS(Status
))
576 DPRINT("NtAllocateVirtualMemory() = %x\n",Status
);
580 Type
= (AllocationType
& MEM_COMMIT
) ? MEM_COMMIT
: MEM_RESERVE
;
581 DPRINT("Type %x\n", Type
);
583 AddressSpace
= &Process
->AddressSpace
;
584 MmLockAddressSpace(AddressSpace
);
586 if (PBaseAddress
!= 0)
588 MemoryArea
= MmOpenMemoryAreaByAddress(AddressSpace
,
591 if (MemoryArea
!= NULL
&&
592 MemoryArea
->Type
== MEMORY_AREA_VIRTUAL_MEMORY
&&
593 MemoryArea
->Length
>= RegionSize
)
596 MmAlterRegion(AddressSpace
,
597 MemoryArea
->BaseAddress
,
598 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
599 BaseAddress
, RegionSize
,
600 Type
, Protect
, MmModifyAttributes
);
601 MmUnlockAddressSpace(AddressSpace
);
602 ObDereferenceObject(Process
);
603 DPRINT("NtAllocateVirtualMemory() = %x\n",Status
);
606 else if (MemoryArea
!= NULL
&& MemoryArea
->Length
>= RegionSize
)
609 MmAlterRegion(AddressSpace
,
610 MemoryArea
->BaseAddress
,
611 &MemoryArea
->Data
.SectionData
.RegionListHead
,
612 BaseAddress
, RegionSize
,
613 Type
, Protect
, MmModifyAttributes
);
614 MmUnlockAddressSpace(AddressSpace
);
615 ObDereferenceObject(Process
);
616 DPRINT("NtAllocateVirtualMemory() = %x\n",Status
);
619 else if (MemoryArea
!= NULL
)
621 MmUnlockAddressSpace(AddressSpace
);
622 ObDereferenceObject(Process
);
623 return(STATUS_UNSUCCESSFUL
);
627 Status
= MmCreateMemoryArea(Process
,
629 MEMORY_AREA_VIRTUAL_MEMORY
,
635 (AllocationType
& MEM_TOP_DOWN
),
636 BoundaryAddressMultiple
);
637 if (!NT_SUCCESS(Status
))
639 MmUnlockAddressSpace(AddressSpace
);
640 ObDereferenceObject(Process
);
641 DPRINT("NtAllocateVirtualMemory() = %x\n",Status
);
644 MmInitialiseRegion(&MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
645 RegionSize
, Type
, Protect
);
647 if ((AllocationType
& MEM_COMMIT
) &&
648 ((Protect
& PAGE_READWRITE
) ||
649 (Protect
& PAGE_EXECUTE_READWRITE
)))
651 MmReserveSwapPages(RegionSize
);
654 *UBaseAddress
= BaseAddress
;
655 *URegionSize
= RegionSize
;
656 DPRINT("*UBaseAddress %x *URegionSize %x\n", BaseAddress
, RegionSize
);
658 MmUnlockAddressSpace(AddressSpace
);
659 ObDereferenceObject(Process
);
660 return(STATUS_SUCCESS
);
664 MmFreeVirtualMemoryPage(PVOID Context
,
665 MEMORY_AREA
* MemoryArea
,
671 PEPROCESS Process
= (PEPROCESS
)Context
;
675 SWAPENTRY SavedSwapEntry
;
676 SavedSwapEntry
= MmGetSavedSwapEntryPage(Page
);
677 if (SavedSwapEntry
!= 0)
679 MmFreeSwapPage(SavedSwapEntry
);
680 MmSetSavedSwapEntryPage(Page
, 0);
682 MmDeleteRmap(Page
, Process
, Address
);
683 MmReleasePageMemoryConsumer(MC_USER
, Page
);
685 else if (SwapEntry
!= 0)
687 MmFreeSwapPage(SwapEntry
);
692 MmFreeVirtualMemory(PEPROCESS Process
,
693 PMEMORY_AREA MemoryArea
)
695 PLIST_ENTRY current_entry
;
699 DPRINT("MmFreeVirtualMemory(Process %p MemoryArea %p)\n", Process
,
702 /* Mark this memory area as about to be deleted. */
703 MemoryArea
->DeleteInProgress
= TRUE
;
706 * Wait for any ongoing paging operations. Notice that since we have
707 * flagged this memory area as deleted no more page ops will be added.
709 if (MemoryArea
->PageOpCount
> 0)
711 for (i
= 0; i
< PAGE_ROUND_UP(MemoryArea
->Length
) / PAGE_SIZE
; i
++)
715 if (MemoryArea
->PageOpCount
== 0)
720 PageOp
= MmCheckForPageOp(MemoryArea
, Process
->UniqueProcessId
,
721 (char*)MemoryArea
->BaseAddress
+ (i
* PAGE_SIZE
),
726 MmUnlockAddressSpace(&Process
->AddressSpace
);
727 Status
= KeWaitForSingleObject(&PageOp
->CompletionEvent
,
732 if (Status
!= STATUS_SUCCESS
)
734 DPRINT1("Failed to wait for page op\n");
737 MmLockAddressSpace(&Process
->AddressSpace
);
738 MmReleasePageOp(PageOp
);
743 /* Free all the individual segments. */
744 current_entry
= MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
.Flink
;
745 while (current_entry
!= &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
)
747 current
= CONTAINING_RECORD(current_entry
, MM_REGION
, RegionListEntry
);
748 current_entry
= current_entry
->Flink
;
752 /* Actually free the memory area. */
753 MmFreeMemoryArea(&Process
->AddressSpace
,
754 MemoryArea
->BaseAddress
,
756 MmFreeVirtualMemoryPage
,
764 NtFreeVirtualMemory(IN HANDLE ProcessHandle
,
765 IN PVOID
* PBaseAddress
,
766 IN PULONG PRegionSize
,
769 * FUNCTION: Frees a range of virtual memory
771 * ProcessHandle = Points to the process that allocated the virtual
773 * BaseAddress = Points to the memory address, rounded down to a
774 * multiple of the pagesize
775 * RegionSize = Limits the range to free, rounded up to a multiple of
777 * FreeType = Can be one of the values: MEM_DECOMMIT, or MEM_RELEASE
781 MEMORY_AREA
* MemoryArea
;
784 PMADDRESS_SPACE AddressSpace
;
788 DPRINT("NtFreeVirtualMemory(ProcessHandle %x, *PBaseAddress %x, "
789 "*PRegionSize %x, FreeType %x)\n",ProcessHandle
,*PBaseAddress
,
790 *PRegionSize
,FreeType
);
792 BaseAddress
= (PVOID
)PAGE_ROUND_DOWN((*PBaseAddress
));
793 RegionSize
= PAGE_ROUND_UP((*PBaseAddress
) + (*PRegionSize
)) -
794 PAGE_ROUND_DOWN((*PBaseAddress
));
796 Status
= ObReferenceObjectByHandle(ProcessHandle
,
797 PROCESS_VM_OPERATION
,
802 if (!NT_SUCCESS(Status
))
807 AddressSpace
= &Process
->AddressSpace
;
809 MmLockAddressSpace(AddressSpace
);
810 MemoryArea
= MmOpenMemoryAreaByAddress(AddressSpace
,
812 if (MemoryArea
== NULL
)
814 MmUnlockAddressSpace(AddressSpace
);
815 ObDereferenceObject(Process
);
816 return(STATUS_UNSUCCESSFUL
);
822 /* We can only free a memory area in one step. */
823 if (MemoryArea
->BaseAddress
!= BaseAddress
)
825 MmUnlockAddressSpace(AddressSpace
);
826 ObDereferenceObject(Process
);
827 return(STATUS_UNSUCCESSFUL
);
829 MmFreeVirtualMemory(Process
, MemoryArea
);
830 MmUnlockAddressSpace(AddressSpace
);
831 ObDereferenceObject(Process
);
832 return(STATUS_SUCCESS
);
836 MmAlterRegion(AddressSpace
,
837 MemoryArea
->BaseAddress
,
838 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
844 MmUnlockAddressSpace(AddressSpace
);
845 ObDereferenceObject(Process
);
848 MmUnlockAddressSpace(AddressSpace
);
849 ObDereferenceObject(Process
);
850 return(STATUS_NOT_IMPLEMENTED
);
854 MmProtectAnonMem(PMADDRESS_SPACE AddressSpace
,
855 PMEMORY_AREA MemoryArea
,
864 Region
= MmFindRegion(MemoryArea
->BaseAddress
,
865 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
867 *OldProtect
= Region
->Protect
;
868 Status
= MmAlterRegion(AddressSpace
, MemoryArea
->BaseAddress
,
869 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
870 BaseAddress
, Length
, Region
->Type
, Protect
,
876 MmQueryAnonMem(PMEMORY_AREA MemoryArea
,
878 PMEMORY_BASIC_INFORMATION Info
,
884 Info
->BaseAddress
= (PVOID
)PAGE_ROUND_DOWN(Address
);
886 Region
= MmFindRegion(MemoryArea
->BaseAddress
,
887 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
888 Address
, &RegionBase
);
889 Info
->BaseAddress
= RegionBase
;
890 Info
->AllocationBase
= MemoryArea
->BaseAddress
;
891 Info
->AllocationProtect
= MemoryArea
->Attributes
;
892 Info
->RegionSize
= (char*)RegionBase
+ Region
->Length
- (char*)Info
->BaseAddress
;
893 Info
->State
= Region
->Type
;
894 Info
->Protect
= Region
->Protect
;
895 Info
->Type
= MEM_PRIVATE
;
897 *ResultLength
= sizeof(MEMORY_BASIC_INFORMATION
);
898 return(STATUS_SUCCESS
);