NTSTATUS
NTAPI
-MmWritePageVirtualMemory(PMM_AVL_TABLE AddressSpace,
+MmWritePageVirtualMemory(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PVOID Address,
PMM_PAGEOP PageOp)
{
SWAPENTRY SwapEntry;
- PFN_TYPE Page;
+ PFN_NUMBER Page;
NTSTATUS Status;
PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
NTSTATUS
NTAPI
-MmPageOutVirtualMemory(PMM_AVL_TABLE AddressSpace,
+MmPageOutVirtualMemory(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PVOID Address,
PMM_PAGEOP PageOp)
{
- PFN_TYPE Page;
+ PFN_NUMBER Page;
BOOLEAN WasDirty;
SWAPENTRY SwapEntry;
NTSTATUS Status;
if (Page == 0)
{
- ASSERT(FALSE);
+ KeBugCheck(MEMORY_MANAGEMENT);
}
/*
NTSTATUS
NTAPI
-MmNotPresentFaultVirtualMemory(PMM_AVL_TABLE AddressSpace,
+MmNotPresentFaultVirtualMemory(PMMSUPPORT AddressSpace,
MEMORY_AREA* MemoryArea,
PVOID Address,
BOOLEAN Locked)
* NOTES: This function is called with the address space lock held.
*/
{
- PFN_TYPE Page;
+ PFN_NUMBER Page;
NTSTATUS Status;
PMM_REGION Region;
PMM_PAGEOP PageOp;
*/
if (MmIsPagePresent(NULL, Address))
{
- if (Locked)
- {
- MmLockPage(MmGetPfnForProcess(NULL, Address));
- }
return(STATUS_SUCCESS);
}
Region = MmFindRegion(MemoryArea->StartingAddress,
&MemoryArea->Data.VirtualMemoryData.RegionListHead,
Address, NULL);
+
if (Region->Type == MEM_RESERVE || Region->Protect == PAGE_NOACCESS)
{
return(STATUS_ACCESS_VIOLATION);
}
+ /*
+ * FIXME
+ */
+ if (Region->Protect & PAGE_GUARD)
+ {
+ return(STATUS_GUARD_PAGE_VIOLATION);
+ }
+
/*
* Get or create a page operation
*/
if (PageOp == NULL)
{
DPRINT1("MmGetPageOp failed");
- ASSERT(FALSE);
+ KeBugCheck(MEMORY_MANAGEMENT);
}
/*
if (Status != STATUS_SUCCESS)
{
DPRINT1("Failed to wait for page op\n");
- ASSERT(FALSE);
+ KeBugCheck(MEMORY_MANAGEMENT);
}
if (PageOp->Status == STATUS_PENDING)
{
DPRINT1("Woke for page op before completion\n");
- ASSERT(FALSE);
+ KeBugCheck(MEMORY_MANAGEMENT);
}
/*
* If this wasn't a pagein then we need to restart the handling
return(Status);
}
MmLockAddressSpace(AddressSpace);
- if (Locked)
- {
- MmLockPage(MmGetPfnForProcess(NULL, Address));
- }
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
return(STATUS_SUCCESS);
if (!NT_SUCCESS(Status))
{
DPRINT1("MmRequestPageMemoryConsumer failed, status = %x\n", Status);
- ASSERT(FALSE);
+ KeBugCheck(MEMORY_MANAGEMENT);
}
/*
Status = MmReadFromSwapPage(SwapEntry, Page);
if (!NT_SUCCESS(Status))
{
- ASSERT(FALSE);
+ KeBugCheck(MEMORY_MANAGEMENT);
}
MmSetSavedSwapEntryPage(Page, SwapEntry);
}
if (!NT_SUCCESS(Status))
{
DPRINT1("MmCreateVirtualMapping failed, not out of memory\n");
- ASSERT(FALSE);
+ KeBugCheck(MEMORY_MANAGEMENT);
return(Status);
}
/*
* Finish the operation
*/
- if (Locked)
- {
- MmLockPage(Page);
- }
PageOp->Status = STATUS_SUCCESS;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
return(STATUS_SUCCESS);
}
-VOID static
-MmModifyAttributes(PMM_AVL_TABLE AddressSpace,
+static VOID
+MmModifyAttributes(PMMSUPPORT AddressSpace,
PVOID BaseAddress,
ULONG RegionSize,
ULONG OldType,
for (i=0; i < PAGE_ROUND_UP(RegionSize)/PAGE_SIZE; i++)
{
- PFN_TYPE Page;
+ PFN_NUMBER Page;
if (MmIsPageSwapEntry(Process,
(char*)BaseAddress + (i * PAGE_SIZE)))
* AllocationType = Indicates the type of virtual memory you like to
* allocated, can be a combination of MEM_COMMIT,
* MEM_RESERVE, MEM_RESET, MEM_TOP_DOWN.
- * Protect = Indicates the protection type of the pages allocated, can be
- * a combination of PAGE_READONLY, PAGE_READWRITE,
- * PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_GUARD,
- * PAGE_NOACCESS
+ * Protect = Indicates the protection type of the pages allocated.
* RETURNS: Status
*/
{
ULONG_PTR MemoryAreaLength;
ULONG Type;
NTSTATUS Status;
- PMM_AVL_TABLE AddressSpace;
+ PMMSUPPORT AddressSpace;
PVOID BaseAddress;
ULONG RegionSize;
PVOID PBaseAddress;
ULONG PRegionSize;
+ ULONG MemProtection;
PHYSICAL_ADDRESS BoundaryAddressMultiple;
KPROCESSOR_MODE PreviousMode;
Protect);
/* Check for valid protection flags */
- if ((Protect & PAGE_FLAGS_VALID_FROM_USER_MODE) != Protect)
+ MemProtection = Protect & ~(PAGE_GUARD|PAGE_NOCACHE);
+ if (MemProtection != PAGE_NOACCESS &&
+ MemProtection != PAGE_READONLY &&
+ MemProtection != PAGE_READWRITE &&
+ MemProtection != PAGE_WRITECOPY &&
+ MemProtection != PAGE_EXECUTE &&
+ MemProtection != PAGE_EXECUTE_READ &&
+ MemProtection != PAGE_EXECUTE_READWRITE &&
+ MemProtection != PAGE_EXECUTE_WRITECOPY)
{
DPRINT1("Invalid page protection\n");
return STATUS_INVALID_PAGE_PROTECTION;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- /* Get the exception code */
- Status = _SEH2_GetExceptionCode();
- _SEH2_YIELD(return Status);
+ /* Return the exception code */
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
}
_SEH2_END;
Type = (AllocationType & MEM_COMMIT) ? MEM_COMMIT : MEM_RESERVE;
DPRINT("Type %x\n", Type);
- AddressSpace = &Process->VadRoot;
+ AddressSpace = &Process->Vm;
MmLockAddressSpace(AddressSpace);
if (PBaseAddress != 0)
{
MemoryAreaLength = (ULONG_PTR)MemoryArea->EndingAddress -
(ULONG_PTR)MemoryArea->StartingAddress;
+
+ if (((ULONG_PTR)BaseAddress + RegionSize) > (ULONG_PTR)MemoryArea->EndingAddress)
+ {
+ DPRINT("BaseAddress + RegionSize %x is larger than MemoryArea's EndingAddress %x\n",
+ (ULONG_PTR)BaseAddress + RegionSize, MemoryArea->EndingAddress);
+
+ MmUnlockAddressSpace(AddressSpace);
+ ObDereferenceObject(Process);
+
+ return STATUS_MEMORY_NOT_ALLOCATED;
+ }
+
+ if (AllocationType == MEM_RESET)
+ {
+ if (MmIsPagePresent(Process, BaseAddress))
+ {
+ /* FIXME: mark pages as not modified */
+ }
+ else
+ {
+ /* FIXME: if pages are in paging file discard them and bring in pages of zeros */
+ }
+
+ MmUnlockAddressSpace(AddressSpace);
+ ObDereferenceObject(Process);
+
+ /* MEM_RESET does not modify any attributes of region */
+ return STATUS_SUCCESS;
+ }
+
if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY &&
MemoryAreaLength >= RegionSize)
{
return(STATUS_SUCCESS);
}
-VOID static
+static VOID
MmFreeVirtualMemoryPage(PVOID Context,
MEMORY_AREA* MemoryArea,
PVOID Address,
- PFN_TYPE Page,
+ PFN_NUMBER Page,
SWAPENTRY SwapEntry,
BOOLEAN Dirty)
{
if (PageOp != NULL)
{
NTSTATUS Status;
- MmUnlockAddressSpace(&Process->VadRoot);
+ MmUnlockAddressSpace(&Process->Vm);
Status = KeWaitForSingleObject(&PageOp->CompletionEvent,
0,
KernelMode,
if (Status != STATUS_SUCCESS)
{
DPRINT1("Failed to wait for page op\n");
- ASSERT(FALSE);
+ KeBugCheck(MEMORY_MANAGEMENT);
}
- MmLockAddressSpace(&Process->VadRoot);
+ MmLockAddressSpace(&Process->Vm);
MmReleasePageOp(PageOp);
}
}
}
/* Actually free the memory area. */
- MmFreeMemoryArea(&Process->VadRoot,
+ MmFreeMemoryArea(&Process->Vm,
MemoryArea,
MmFreeVirtualMemoryPage,
(PVOID)Process);
MEMORY_AREA* MemoryArea;
NTSTATUS Status;
PEPROCESS Process;
- PMM_AVL_TABLE AddressSpace;
+ PMMSUPPORT AddressSpace;
PVOID BaseAddress;
ULONG RegionSize;
+ PAGED_CODE();
+
DPRINT("NtFreeVirtualMemory(ProcessHandle %x, *PBaseAddress %x, "
"*PRegionSize %x, FreeType %x)\n",ProcessHandle,*PBaseAddress,
*PRegionSize,FreeType);
+ if (!(FreeType & (MEM_RELEASE | MEM_DECOMMIT)))
+ {
+ DPRINT1("Invalid FreeType\n");
+ return STATUS_INVALID_PARAMETER_4;
+ }
+
+ if (ExGetPreviousMode() != KernelMode)
+ {
+ _SEH2_TRY
+ {
+ /* Probe user pointers */
+ ProbeForWriteSize_t(PRegionSize);
+ ProbeForWritePointer(PBaseAddress);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Return the exception code */
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+ }
+
BaseAddress = (PVOID)PAGE_ROUND_DOWN((*PBaseAddress));
RegionSize = PAGE_ROUND_UP((ULONG_PTR)(*PBaseAddress) + (*PRegionSize)) -
PAGE_ROUND_DOWN((*PBaseAddress));
return(Status);
}
- AddressSpace = &Process->VadRoot;
+ AddressSpace = &Process->Vm;
MmLockAddressSpace(AddressSpace);
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress);
Status =
MmAlterRegion(AddressSpace,
MemoryArea->StartingAddress,
- &MemoryArea->Data.VirtualMemoryData.RegionListHead,
+ (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW) ?
+ &MemoryArea->Data.SectionData.RegionListHead :
+ &MemoryArea->Data.VirtualMemoryData.RegionListHead,
BaseAddress,
RegionSize,
MEM_RESERVE,
NTSTATUS
NTAPI
-MmProtectAnonMem(PMM_AVL_TABLE AddressSpace,
+MmProtectAnonMem(PMMSUPPORT AddressSpace,
PMEMORY_AREA MemoryArea,
PVOID BaseAddress,
ULONG Length,
PULONG OldProtect)
{
PMM_REGION Region;
- NTSTATUS Status;
+ NTSTATUS Status = STATUS_SUCCESS;
+ ULONG LengthCount = 0;
- Region = MmFindRegion(MemoryArea->StartingAddress,
- &MemoryArea->Data.VirtualMemoryData.RegionListHead,
- BaseAddress, NULL);
- *OldProtect = Region->Protect;
- Status = MmAlterRegion(AddressSpace, MemoryArea->StartingAddress,
- &MemoryArea->Data.VirtualMemoryData.RegionListHead,
- BaseAddress, Length, Region->Type, Protect,
- MmModifyAttributes);
- return(Status);
+ /* Search all Regions in MemoryArea up to Length */
+ /* Every Region up to Length must be committed for success */
+ for (;;)
+ {
+ Region = MmFindRegion(MemoryArea->StartingAddress,
+ &MemoryArea->Data.VirtualMemoryData.RegionListHead,
+ (PVOID)((ULONG_PTR)BaseAddress + (ULONG_PTR)LengthCount), NULL);
+
+ /* If a Region was found and it is committed */
+ if ((Region) && (Region->Type == MEM_COMMIT))
+ {
+ LengthCount += Region->Length;
+ if (Length <= LengthCount) break;
+ continue;
+ }
+ /* If Region was found and it is not commited */
+ else if (Region)
+ {
+ Status = STATUS_NOT_COMMITTED;
+ break;
+ }
+ /* If no Region was found at all */
+ else if (LengthCount == 0)
+ {
+ Status = STATUS_INVALID_ADDRESS;
+ break;
+ }
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ *OldProtect = Region->Protect;
+ Status = MmAlterRegion(AddressSpace, MemoryArea->StartingAddress,
+ &MemoryArea->Data.VirtualMemoryData.RegionListHead,
+ BaseAddress, Length, Region->Type, Protect,
+ MmModifyAttributes);
+ }
+
+ return (Status);
}
NTSTATUS NTAPI
MmQueryAnonMem(PMEMORY_AREA MemoryArea,
PVOID Address,
PMEMORY_BASIC_INFORMATION Info,
- PULONG ResultLength)
+ PSIZE_T ResultLength)
{
PMM_REGION Region;
PVOID RegionBase = NULL;