3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/mm/anonmem.c
6 * PURPOSE: Implementing anonymous memory.
8 * PROGRAMMERS: David Welch
11 /* INCLUDE *****************************************************************/
15 #include <internal/debug.h>
17 /* FUNCTIONS *****************************************************************/
20 MmWritePageVirtualMemory(PMADDRESS_SPACE AddressSpace
,
21 PMEMORY_AREA MemoryArea
,
30 * Check for paging out from a deleted virtual memory area.
32 if (MemoryArea
->DeleteInProgress
)
34 PageOp
->Status
= STATUS_UNSUCCESSFUL
;
35 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
36 MmReleasePageOp(PageOp
);
37 return(STATUS_UNSUCCESSFUL
);
40 Page
= MmGetPfnForProcess(AddressSpace
->Process
, Address
);
43 * Get that the page actually is dirty.
45 if (!MmIsDirtyPage(MemoryArea
->Process
, Address
))
47 PageOp
->Status
= STATUS_SUCCESS
;
48 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
49 MmReleasePageOp(PageOp
);
50 return(STATUS_SUCCESS
);
54 * Speculatively set the mapping to clean.
56 MmSetCleanPage(MemoryArea
->Process
, Address
);
59 * If necessary, allocate an entry in the paging file for this page
61 SwapEntry
= MmGetSavedSwapEntryPage(Page
);
64 SwapEntry
= MmAllocSwapPage();
67 MmSetDirtyPage(MemoryArea
->Process
, Address
);
68 PageOp
->Status
= STATUS_PAGEFILE_QUOTA_EXCEEDED
;
69 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
70 MmReleasePageOp(PageOp
);
71 return(STATUS_PAGEFILE_QUOTA_EXCEEDED
);
76 * Write the page to the pagefile
78 Status
= MmWriteToSwapPage(SwapEntry
, Page
);
79 if (!NT_SUCCESS(Status
))
81 DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
83 MmSetDirtyPage(MemoryArea
->Process
, Address
);
84 PageOp
->Status
= STATUS_UNSUCCESSFUL
;
85 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
86 MmReleasePageOp(PageOp
);
87 return(STATUS_UNSUCCESSFUL
);
91 * Otherwise we have succeeded.
93 MmSetSavedSwapEntryPage(Page
, SwapEntry
);
94 PageOp
->Status
= STATUS_SUCCESS
;
95 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
96 MmReleasePageOp(PageOp
);
97 return(STATUS_SUCCESS
);
101 MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace
,
102 PMEMORY_AREA MemoryArea
,
111 DPRINT("MmPageOutVirtualMemory(Address 0x%.8X) PID %d\n",
112 Address
, MemoryArea
->Process
->UniqueProcessId
);
115 * Check for paging out from a deleted virtual memory area.
117 if (MemoryArea
->DeleteInProgress
)
119 PageOp
->Status
= STATUS_UNSUCCESSFUL
;
120 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
121 MmReleasePageOp(PageOp
);
122 return(STATUS_UNSUCCESSFUL
);
126 * Disable the virtual mapping.
128 MmDisableVirtualMapping(MemoryArea
->Process
, Address
,
137 * Paging out non-dirty data is easy.
141 MmDeleteVirtualMapping(MemoryArea
->Process
, Address
, FALSE
, NULL
, NULL
);
142 MmDeleteAllRmaps(Page
, NULL
, NULL
);
143 if ((SwapEntry
= MmGetSavedSwapEntryPage(Page
)) != 0)
145 MmCreatePageFileMapping(MemoryArea
->Process
, Address
, SwapEntry
);
146 MmSetSavedSwapEntryPage(Page
, 0);
148 MmReleasePageMemoryConsumer(MC_USER
, Page
);
149 PageOp
->Status
= STATUS_SUCCESS
;
150 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
151 MmReleasePageOp(PageOp
);
152 return(STATUS_SUCCESS
);
156 * If necessary, allocate an entry in the paging file for this page
158 SwapEntry
= MmGetSavedSwapEntryPage(Page
);
161 SwapEntry
= MmAllocSwapPage();
164 MmShowOutOfSpaceMessagePagingFile();
165 MmEnableVirtualMapping(MemoryArea
->Process
, Address
);
166 PageOp
->Status
= STATUS_UNSUCCESSFUL
;
167 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
168 MmReleasePageOp(PageOp
);
169 return(STATUS_PAGEFILE_QUOTA
);
174 * Write the page to the pagefile
176 Status
= MmWriteToSwapPage(SwapEntry
, Page
);
177 if (!NT_SUCCESS(Status
))
179 DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
181 MmEnableVirtualMapping(MemoryArea
->Process
, Address
);
182 PageOp
->Status
= STATUS_UNSUCCESSFUL
;
183 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
184 MmReleasePageOp(PageOp
);
185 return(STATUS_UNSUCCESSFUL
);
189 * Otherwise we have succeeded, free the page
191 DPRINT("MM: Swapped out virtual memory page 0x%.8X!\n", Page
<< PAGE_SHIFT
);
192 MmDeleteVirtualMapping(MemoryArea
->Process
, Address
, FALSE
, NULL
, NULL
);
193 MmCreatePageFileMapping(MemoryArea
->Process
, Address
, SwapEntry
);
194 MmDeleteAllRmaps(Page
, NULL
, NULL
);
195 MmSetSavedSwapEntryPage(Page
, 0);
196 MmReleasePageMemoryConsumer(MC_USER
, Page
);
197 PageOp
->Status
= STATUS_SUCCESS
;
198 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
199 MmReleasePageOp(PageOp
);
200 return(STATUS_SUCCESS
);
204 MmNotPresentFaultVirtualMemory(PMADDRESS_SPACE AddressSpace
,
205 MEMORY_AREA
* MemoryArea
,
209 * FUNCTION: Move data into memory to satisfy a page not present fault
211 * AddressSpace = Address space within which the fault occurred
212 * MemoryArea = The memory area within which the fault occurred
213 * Address = The absolute address of fault
215 * NOTES: This function is called with the address space lock held.
224 * There is a window between taking the page fault and locking the
225 * address space when another thread could load the page so we check
228 if (MmIsPagePresent(NULL
, Address
))
232 MmLockPage(MmGetPfnForProcess(NULL
, Address
));
234 return(STATUS_SUCCESS
);
238 * Check for the virtual memory area being deleted.
240 if (MemoryArea
->DeleteInProgress
)
242 return(STATUS_UNSUCCESSFUL
);
246 * Get the segment corresponding to the virtual address
248 Region
= MmFindRegion(MemoryArea
->StartingAddress
,
249 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
251 if (Region
->Type
== MEM_RESERVE
|| Region
->Protect
== PAGE_NOACCESS
)
253 return(STATUS_ACCESS_VIOLATION
);
257 * Get or create a page operation
259 PageOp
= MmGetPageOp(MemoryArea
, MemoryArea
->Process
->UniqueProcessId
,
260 (PVOID
)PAGE_ROUND_DOWN(Address
), NULL
, 0,
261 MM_PAGEOP_PAGEIN
, FALSE
);
264 DPRINT1("MmGetPageOp failed");
269 * Check if someone else is already handling this fault, if so wait
272 if (PageOp
->Thread
!= PsGetCurrentThread())
274 MmUnlockAddressSpace(AddressSpace
);
275 Status
= KeWaitForSingleObject(&PageOp
->CompletionEvent
,
281 * Check for various strange conditions
283 if (Status
!= STATUS_SUCCESS
)
285 DPRINT1("Failed to wait for page op\n");
288 if (PageOp
->Status
== STATUS_PENDING
)
290 DPRINT1("Woke for page op before completion\n");
294 * If this wasn't a pagein then we need to restart the handling
296 if (PageOp
->OpType
!= MM_PAGEOP_PAGEIN
)
298 MmLockAddressSpace(AddressSpace
);
299 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
300 MmReleasePageOp(PageOp
);
301 return(STATUS_MM_RESTART_OPERATION
);
304 * If the thread handling this fault has failed then we don't retry
306 if (!NT_SUCCESS(PageOp
->Status
))
308 MmLockAddressSpace(AddressSpace
);
309 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
310 Status
= PageOp
->Status
;
311 MmReleasePageOp(PageOp
);
314 MmLockAddressSpace(AddressSpace
);
317 MmLockPage(MmGetPfnForProcess(NULL
, Address
));
319 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
320 MmReleasePageOp(PageOp
);
321 return(STATUS_SUCCESS
);
325 * Try to allocate a page
327 Status
= MmRequestPageMemoryConsumer(MC_USER
, FALSE
, &Page
);
328 if (Status
== STATUS_NO_MEMORY
)
330 MmUnlockAddressSpace(AddressSpace
);
331 Status
= MmRequestPageMemoryConsumer(MC_USER
, TRUE
, &Page
);
332 MmLockAddressSpace(AddressSpace
);
334 if (!NT_SUCCESS(Status
))
336 DPRINT1("MmRequestPageMemoryConsumer failed, status = %x\n", Status
);
341 * Handle swapped out pages.
343 if (MmIsPageSwapEntry(NULL
, Address
))
347 MmDeletePageFileMapping(MemoryArea
->Process
, Address
, &SwapEntry
);
348 Status
= MmReadFromSwapPage(SwapEntry
, Page
);
349 if (!NT_SUCCESS(Status
))
353 MmSetSavedSwapEntryPage(Page
, SwapEntry
);
357 * Set the page. If we fail because we are out of memory then
360 Status
= MmCreateVirtualMapping(MemoryArea
->Process
,
361 (PVOID
)PAGE_ROUND_DOWN(Address
),
365 while (Status
== STATUS_NO_MEMORY
)
367 MmUnlockAddressSpace(AddressSpace
);
368 Status
= MmCreateVirtualMapping(MemoryArea
->Process
,
373 MmLockAddressSpace(AddressSpace
);
375 if (!NT_SUCCESS(Status
))
377 DPRINT1("MmCreateVirtualMapping failed, not out of memory\n");
383 * Add the page to the process's working set
385 MmInsertRmap(Page
, MemoryArea
->Process
, (PVOID
)PAGE_ROUND_DOWN(Address
));
388 * Finish the operation
394 PageOp
->Status
= STATUS_SUCCESS
;
395 KeSetEvent(&PageOp
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
396 MmReleasePageOp(PageOp
);
397 return(STATUS_SUCCESS
);
401 MmModifyAttributes(PMADDRESS_SPACE AddressSpace
,
409 * FUNCTION: Modify the attributes of a memory region
413 * If we are switching a previously committed region to reserved then
414 * free any allocated pages within the region
416 if (NewType
== MEM_RESERVE
&& OldType
== MEM_COMMIT
)
420 for (i
=0; i
< PAGE_ROUND_UP(RegionSize
)/PAGE_SIZE
; i
++)
424 if (MmIsPageSwapEntry(AddressSpace
->Process
,
425 (char*)BaseAddress
+ (i
* PAGE_SIZE
)))
429 MmDeletePageFileMapping(AddressSpace
->Process
,
430 (char*)BaseAddress
+ (i
* PAGE_SIZE
),
432 MmFreeSwapPage(SwapEntry
);
436 MmDeleteVirtualMapping(AddressSpace
->Process
,
437 (char*)BaseAddress
+ (i
*PAGE_SIZE
),
441 SWAPENTRY SavedSwapEntry
;
442 SavedSwapEntry
= MmGetSavedSwapEntryPage(Page
);
443 if (SavedSwapEntry
!= 0)
445 MmFreeSwapPage(SavedSwapEntry
);
446 MmSetSavedSwapEntryPage(Page
, 0);
448 MmDeleteRmap(Page
, AddressSpace
->Process
,
449 (char*)BaseAddress
+ (i
* PAGE_SIZE
));
450 MmReleasePageMemoryConsumer(MC_USER
, Page
);
457 * If we are changing the protection attributes of a committed region then
458 * alter the attributes for any allocated pages within the region
460 if (NewType
== MEM_COMMIT
&& OldType
== MEM_COMMIT
&&
461 OldProtect
!= NewProtect
)
465 for (i
=0; i
< PAGE_ROUND_UP(RegionSize
)/PAGE_SIZE
; i
++)
467 if (MmIsPagePresent(AddressSpace
->Process
,
468 (char*)BaseAddress
+ (i
*PAGE_SIZE
)))
470 MmSetPageProtect(AddressSpace
->Process
,
471 (char*)BaseAddress
+ (i
*PAGE_SIZE
),
482 NtAllocateVirtualMemory(IN HANDLE ProcessHandle
,
483 IN OUT PVOID
* UBaseAddress
,
485 IN OUT PULONG URegionSize
,
486 IN ULONG AllocationType
,
489 * FUNCTION: Allocates a block of virtual memory in the process address space
491 * ProcessHandle = The handle of the process which owns the virtual memory
492 * BaseAddress = A pointer to the virtual memory allocated. If you
493 * supply a non zero value the system will try to
494 * allocate the memory at the address supplied. It round
495 * it down to a multiple of the page size.
496 * ZeroBits = (OPTIONAL) You can specify the number of high order bits
497 * that must be zero, ensuring that the memory will be
498 * allocated at a address below a certain value.
499 * RegionSize = The number of bytes to allocate
500 * AllocationType = Indicates the type of virtual memory you like to
501 * allocated, can be a combination of MEM_COMMIT,
502 * MEM_RESERVE, MEM_RESET, MEM_TOP_DOWN.
503 * Protect = Indicates the protection type of the pages allocated, can be
504 * a combination of PAGE_READONLY, PAGE_READWRITE,
505 * PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_GUARD,
511 MEMORY_AREA
* MemoryArea
;
512 ULONG_PTR MemoryAreaLength
;
515 PMADDRESS_SPACE AddressSpace
;
520 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
522 DPRINT("NtAllocateVirtualMemory(*UBaseAddress %x, "
523 "ZeroBits %d, *URegionSize %x, AllocationType %x, Protect %x)\n",
524 *UBaseAddress
,ZeroBits
,*URegionSize
,AllocationType
,
528 * Check the validity of the parameters
530 if ((Protect
& PAGE_FLAGS_VALID_FROM_USER_MODE
) != Protect
)
532 return(STATUS_INVALID_PAGE_PROTECTION
);
534 if ((AllocationType
& (MEM_COMMIT
| MEM_RESERVE
)) == 0)
536 return(STATUS_INVALID_PARAMETER
);
539 PBaseAddress
= *UBaseAddress
;
540 PRegionSize
= *URegionSize
;
541 BoundaryAddressMultiple
.QuadPart
= 0;
543 BaseAddress
= (PVOID
)PAGE_ROUND_DOWN(PBaseAddress
);
544 RegionSize
= PAGE_ROUND_UP(PBaseAddress
+ PRegionSize
) -
545 PAGE_ROUND_DOWN(PBaseAddress
);
547 Status
= ObReferenceObjectByHandle(ProcessHandle
,
548 PROCESS_VM_OPERATION
,
553 if (!NT_SUCCESS(Status
))
555 DPRINT("NtAllocateVirtualMemory() = %x\n",Status
);
559 Type
= (AllocationType
& MEM_COMMIT
) ? MEM_COMMIT
: MEM_RESERVE
;
560 DPRINT("Type %x\n", Type
);
562 AddressSpace
= &Process
->AddressSpace
;
563 MmLockAddressSpace(AddressSpace
);
565 if (PBaseAddress
!= 0)
567 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, BaseAddress
);
569 if (MemoryArea
!= NULL
)
571 MemoryAreaLength
= (ULONG_PTR
)MemoryArea
->EndingAddress
-
572 (ULONG_PTR
)MemoryArea
->StartingAddress
;
573 if (MemoryArea
->Type
== MEMORY_AREA_VIRTUAL_MEMORY
&&
574 MemoryAreaLength
>= RegionSize
)
577 MmAlterRegion(AddressSpace
,
578 MemoryArea
->StartingAddress
,
579 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
580 BaseAddress
, RegionSize
,
581 Type
, Protect
, MmModifyAttributes
);
582 MmUnlockAddressSpace(AddressSpace
);
583 ObDereferenceObject(Process
);
584 DPRINT("NtAllocateVirtualMemory() = %x\n",Status
);
587 else if (MemoryAreaLength
>= RegionSize
)
590 MmAlterRegion(AddressSpace
,
591 MemoryArea
->StartingAddress
,
592 &MemoryArea
->Data
.SectionData
.RegionListHead
,
593 BaseAddress
, RegionSize
,
594 Type
, Protect
, MmModifyAttributes
);
595 MmUnlockAddressSpace(AddressSpace
);
596 ObDereferenceObject(Process
);
597 DPRINT("NtAllocateVirtualMemory() = %x\n",Status
);
602 MmUnlockAddressSpace(AddressSpace
);
603 ObDereferenceObject(Process
);
604 return(STATUS_UNSUCCESSFUL
);
609 Status
= MmCreateMemoryArea(Process
,
611 MEMORY_AREA_VIRTUAL_MEMORY
,
617 (AllocationType
& MEM_TOP_DOWN
) == MEM_TOP_DOWN
,
618 BoundaryAddressMultiple
);
619 if (!NT_SUCCESS(Status
))
621 MmUnlockAddressSpace(AddressSpace
);
622 ObDereferenceObject(Process
);
623 DPRINT("NtAllocateVirtualMemory() = %x\n",Status
);
627 MemoryAreaLength
= (ULONG_PTR
)MemoryArea
->EndingAddress
-
628 (ULONG_PTR
)MemoryArea
->StartingAddress
;
630 MmInitialiseRegion(&MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
631 MemoryAreaLength
, Type
, Protect
);
633 if ((AllocationType
& MEM_COMMIT
) &&
634 ((Protect
& PAGE_READWRITE
) ||
635 (Protect
& PAGE_EXECUTE_READWRITE
)))
637 MmReserveSwapPages(MemoryAreaLength
);
640 *UBaseAddress
= BaseAddress
;
641 *URegionSize
= MemoryAreaLength
;
642 DPRINT("*UBaseAddress %x *URegionSize %x\n", BaseAddress
, RegionSize
);
644 MmUnlockAddressSpace(AddressSpace
);
645 ObDereferenceObject(Process
);
646 return(STATUS_SUCCESS
);
650 MmFreeVirtualMemoryPage(PVOID Context
,
651 MEMORY_AREA
* MemoryArea
,
657 PEPROCESS Process
= (PEPROCESS
)Context
;
661 SWAPENTRY SavedSwapEntry
;
662 SavedSwapEntry
= MmGetSavedSwapEntryPage(Page
);
663 if (SavedSwapEntry
!= 0)
665 MmFreeSwapPage(SavedSwapEntry
);
666 MmSetSavedSwapEntryPage(Page
, 0);
668 MmDeleteRmap(Page
, Process
, Address
);
669 MmReleasePageMemoryConsumer(MC_USER
, Page
);
671 else if (SwapEntry
!= 0)
673 MmFreeSwapPage(SwapEntry
);
678 MmFreeVirtualMemory(PEPROCESS Process
,
679 PMEMORY_AREA MemoryArea
)
681 PLIST_ENTRY current_entry
;
685 DPRINT("MmFreeVirtualMemory(Process %p MemoryArea %p)\n", Process
,
688 /* Mark this memory area as about to be deleted. */
689 MemoryArea
->DeleteInProgress
= TRUE
;
692 * Wait for any ongoing paging operations. Notice that since we have
693 * flagged this memory area as deleted no more page ops will be added.
695 if (MemoryArea
->PageOpCount
> 0)
697 ULONG_PTR MemoryAreaLength
= (ULONG_PTR
)MemoryArea
->EndingAddress
-
698 (ULONG_PTR
)MemoryArea
->StartingAddress
;
700 /* FiN TODO: Optimize loop counter! */
701 for (i
= 0; i
< PAGE_ROUND_UP(MemoryAreaLength
) / PAGE_SIZE
; i
++)
705 if (MemoryArea
->PageOpCount
== 0)
710 PageOp
= MmCheckForPageOp(MemoryArea
, Process
->UniqueProcessId
,
711 (PVOID
)((ULONG_PTR
)MemoryArea
->StartingAddress
+ (i
* PAGE_SIZE
)),
716 MmUnlockAddressSpace(&Process
->AddressSpace
);
717 Status
= KeWaitForSingleObject(&PageOp
->CompletionEvent
,
722 if (Status
!= STATUS_SUCCESS
)
724 DPRINT1("Failed to wait for page op\n");
727 MmLockAddressSpace(&Process
->AddressSpace
);
728 MmReleasePageOp(PageOp
);
733 /* Free all the individual segments. */
734 current_entry
= MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
.Flink
;
735 while (current_entry
!= &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
)
737 current
= CONTAINING_RECORD(current_entry
, MM_REGION
, RegionListEntry
);
738 current_entry
= current_entry
->Flink
;
742 /* Actually free the memory area. */
743 MmFreeMemoryArea(&Process
->AddressSpace
,
745 MmFreeVirtualMemoryPage
,
753 NtFreeVirtualMemory(IN HANDLE ProcessHandle
,
754 IN PVOID
* PBaseAddress
,
755 IN PULONG PRegionSize
,
758 * FUNCTION: Frees a range of virtual memory
760 * ProcessHandle = Points to the process that allocated the virtual
762 * BaseAddress = Points to the memory address, rounded down to a
763 * multiple of the pagesize
764 * RegionSize = Limits the range to free, rounded up to a multiple of
766 * FreeType = Can be one of the values: MEM_DECOMMIT, or MEM_RELEASE
770 MEMORY_AREA
* MemoryArea
;
773 PMADDRESS_SPACE AddressSpace
;
777 DPRINT("NtFreeVirtualMemory(ProcessHandle %x, *PBaseAddress %x, "
778 "*PRegionSize %x, FreeType %x)\n",ProcessHandle
,*PBaseAddress
,
779 *PRegionSize
,FreeType
);
781 BaseAddress
= (PVOID
)PAGE_ROUND_DOWN((*PBaseAddress
));
782 RegionSize
= PAGE_ROUND_UP((*PBaseAddress
) + (*PRegionSize
)) -
783 PAGE_ROUND_DOWN((*PBaseAddress
));
785 Status
= ObReferenceObjectByHandle(ProcessHandle
,
786 PROCESS_VM_OPERATION
,
791 if (!NT_SUCCESS(Status
))
796 AddressSpace
= &Process
->AddressSpace
;
798 MmLockAddressSpace(AddressSpace
);
799 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, BaseAddress
);
800 if (MemoryArea
== NULL
)
802 MmUnlockAddressSpace(AddressSpace
);
803 ObDereferenceObject(Process
);
804 return(STATUS_UNSUCCESSFUL
);
810 /* We can only free a memory area in one step. */
811 if (MemoryArea
->StartingAddress
!= BaseAddress
||
812 MemoryArea
->Type
!= MEMORY_AREA_VIRTUAL_MEMORY
)
814 MmUnlockAddressSpace(AddressSpace
);
815 ObDereferenceObject(Process
);
816 return(STATUS_UNSUCCESSFUL
);
818 MmFreeVirtualMemory(Process
, MemoryArea
);
819 MmUnlockAddressSpace(AddressSpace
);
820 ObDereferenceObject(Process
);
821 return(STATUS_SUCCESS
);
825 MmAlterRegion(AddressSpace
,
826 MemoryArea
->StartingAddress
,
827 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
833 MmUnlockAddressSpace(AddressSpace
);
834 ObDereferenceObject(Process
);
837 MmUnlockAddressSpace(AddressSpace
);
838 ObDereferenceObject(Process
);
839 return(STATUS_NOT_IMPLEMENTED
);
843 MmProtectAnonMem(PMADDRESS_SPACE AddressSpace
,
844 PMEMORY_AREA MemoryArea
,
853 Region
= MmFindRegion(MemoryArea
->StartingAddress
,
854 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
856 *OldProtect
= Region
->Protect
;
857 Status
= MmAlterRegion(AddressSpace
, MemoryArea
->StartingAddress
,
858 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
859 BaseAddress
, Length
, Region
->Type
, Protect
,
865 MmQueryAnonMem(PMEMORY_AREA MemoryArea
,
867 PMEMORY_BASIC_INFORMATION Info
,
873 Info
->BaseAddress
= (PVOID
)PAGE_ROUND_DOWN(Address
);
875 Region
= MmFindRegion(MemoryArea
->StartingAddress
,
876 &MemoryArea
->Data
.VirtualMemoryData
.RegionListHead
,
877 Address
, &RegionBase
);
878 Info
->BaseAddress
= RegionBase
;
879 Info
->AllocationBase
= MemoryArea
->StartingAddress
;
880 Info
->AllocationProtect
= MemoryArea
->Attributes
;
881 Info
->RegionSize
= (char*)RegionBase
+ Region
->Length
- (char*)Info
->BaseAddress
;
882 Info
->State
= Region
->Type
;
883 Info
->Protect
= Region
->Protect
;
884 Info
->Type
= MEM_PRIVATE
;
886 *ResultLength
= sizeof(MEMORY_BASIC_INFORMATION
);
887 return(STATUS_SUCCESS
);