diff --git a/reactos/ntoskrnl/mm/anonmem.c b/reactos/ntoskrnl/mm/anonmem.c index 669b3366130..2e44b99064b 100644 --- a/reactos/ntoskrnl/mm/anonmem.c +++ b/reactos/ntoskrnl/mm/anonmem.c @@ -51,164 +51,164 @@ NTSTATUS NTAPI MmPageOutVirtualMemory(PMMSUPPORT AddressSpace, - PMEMORY_AREA MemoryArea, - PVOID Address, - PMM_PAGEOP PageOp) + PMEMORY_AREA MemoryArea, + PVOID Address, + PMM_PAGEOP PageOp) { - PFN_NUMBER Page; - BOOLEAN WasDirty; - SWAPENTRY SwapEntry; - NTSTATUS Status; - PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace); + PFN_NUMBER Page; + BOOLEAN WasDirty; + SWAPENTRY SwapEntry; + NTSTATUS Status; + PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace); - DPRINT("MmPageOutVirtualMemory(Address 0x%.8X) PID %d\n", - Address, Process->UniqueProcessId); + DPRINT("MmPageOutVirtualMemory(Address 0x%.8X) PID %d\n", + Address, Process->UniqueProcessId); - /* + /* * Check for paging out from a deleted virtual memory area. */ - if (MemoryArea->DeleteInProgress) - { - PageOp->Status = STATUS_UNSUCCESSFUL; - KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); - MmReleasePageOp(PageOp); - return(STATUS_UNSUCCESSFUL); - } + if (MemoryArea->DeleteInProgress) + { + PageOp->Status = STATUS_UNSUCCESSFUL; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_UNSUCCESSFUL); + } - /* + /* * Disable the virtual mapping. */ - MmDisableVirtualMapping(Process, Address, - &WasDirty, &Page); + MmDisableVirtualMapping(Process, Address, + &WasDirty, &Page); - if (Page == 0) - { - KeBugCheck(MEMORY_MANAGEMENT); - } + if (Page == 0) + { + KeBugCheck(MEMORY_MANAGEMENT); + } - /* + /* * Paging out non-dirty data is easy. */ - if (!WasDirty) - { - MmLockAddressSpace(AddressSpace); - MmDeleteVirtualMapping(Process, Address, FALSE, NULL, NULL); - MmDeleteAllRmaps(Page, NULL, NULL); - if ((SwapEntry = MmGetSavedSwapEntryPage(Page)) != 0) - { - MmCreatePageFileMapping(Process, Address, SwapEntry); - MmSetSavedSwapEntryPage(Page, 0); - } - MmUnlockAddressSpace(AddressSpace); - MmReleasePageMemoryConsumer(MC_USER, Page); - PageOp->Status = STATUS_SUCCESS; - KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); - MmReleasePageOp(PageOp); - return(STATUS_SUCCESS); - } + if (!WasDirty) + { + MmLockAddressSpace(AddressSpace); + MmDeleteVirtualMapping(Process, Address, FALSE, NULL, NULL); + MmDeleteAllRmaps(Page, NULL, NULL); + if ((SwapEntry = MmGetSavedSwapEntryPage(Page)) != 0) + { + MmCreatePageFileMapping(Process, Address, SwapEntry); + MmSetSavedSwapEntryPage(Page, 0); + } + MmUnlockAddressSpace(AddressSpace); + MmReleasePageMemoryConsumer(MC_USER, Page); + PageOp->Status = STATUS_SUCCESS; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_SUCCESS); + } - /* + /* * If necessary, allocate an entry in the paging file for this page */ - SwapEntry = MmGetSavedSwapEntryPage(Page); - if (SwapEntry == 0) - { - SwapEntry = MmAllocSwapPage(); - if (SwapEntry == 0) - { - MmShowOutOfSpaceMessagePagingFile(); - MmEnableVirtualMapping(Process, Address); - PageOp->Status = STATUS_UNSUCCESSFUL; - KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); - MmReleasePageOp(PageOp); - return(STATUS_PAGEFILE_QUOTA); - } - } + SwapEntry = MmGetSavedSwapEntryPage(Page); + if (SwapEntry == 0) + { + SwapEntry = MmAllocSwapPage(); + if (SwapEntry == 0) + { + MmShowOutOfSpaceMessagePagingFile(); + MmEnableVirtualMapping(Process, Address); + PageOp->Status = STATUS_UNSUCCESSFUL; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_PAGEFILE_QUOTA); + } + } - /* + /* * Write the page to the pagefile */ - Status = MmWriteToSwapPage(SwapEntry, Page); - if (!NT_SUCCESS(Status)) - { - DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n", - Status); - MmEnableVirtualMapping(Process, Address); - PageOp->Status = STATUS_UNSUCCESSFUL; - KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); - MmReleasePageOp(PageOp); - return(STATUS_UNSUCCESSFUL); - } + Status = MmWriteToSwapPage(SwapEntry, Page); + if (!NT_SUCCESS(Status)) + { + DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n", + Status); + MmEnableVirtualMapping(Process, Address); + PageOp->Status = STATUS_UNSUCCESSFUL; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_UNSUCCESSFUL); + } - /* + /* * Otherwise we have succeeded, free the page */ - DPRINT("MM: Swapped out virtual memory page 0x%.8X!\n", Page << PAGE_SHIFT); - MmLockAddressSpace(AddressSpace); - MmDeleteVirtualMapping(Process, Address, FALSE, NULL, NULL); - MmCreatePageFileMapping(Process, Address, SwapEntry); - MmUnlockAddressSpace(AddressSpace); - MmDeleteAllRmaps(Page, NULL, NULL); - MmSetSavedSwapEntryPage(Page, 0); - MmReleasePageMemoryConsumer(MC_USER, Page); - PageOp->Status = STATUS_SUCCESS; - KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); - MmReleasePageOp(PageOp); - return(STATUS_SUCCESS); + DPRINT("MM: Swapped out virtual memory page 0x%.8X!\n", Page << PAGE_SHIFT); + MmLockAddressSpace(AddressSpace); + MmDeleteVirtualMapping(Process, Address, FALSE, NULL, NULL); + MmCreatePageFileMapping(Process, Address, SwapEntry); + MmUnlockAddressSpace(AddressSpace); + MmDeleteAllRmaps(Page, NULL, NULL); + MmSetSavedSwapEntryPage(Page, 0); + MmReleasePageMemoryConsumer(MC_USER, Page); + PageOp->Status = STATUS_SUCCESS; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_SUCCESS); } NTSTATUS NTAPI MmNotPresentFaultVirtualMemory(PMMSUPPORT AddressSpace, - MEMORY_AREA* MemoryArea, - PVOID Address) + MEMORY_AREA* MemoryArea, + PVOID Address) /* - * FUNCTION: Move data into memory to satisfy a page not present fault - * ARGUMENTS: - * AddressSpace = Address space within which the fault occurred - * MemoryArea = The memory area within which the fault occurred - * Address = The absolute address of fault - * RETURNS: Status - * NOTES: This function is called with the address space lock held. - */ +* FUNCTION: Move data into memory to satisfy a page not present fault +* ARGUMENTS: +* AddressSpace = Address space within which the fault occurred +* MemoryArea = The memory area within which the fault occurred +* Address = The absolute address of fault +* RETURNS: Status +* NOTES: This function is called with the address space lock held. +*/ { - PFN_NUMBER Page; - NTSTATUS Status; - PMM_REGION Region; - PMM_PAGEOP PageOp; - PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace); + PFN_NUMBER Page; + NTSTATUS Status; + PMM_REGION Region; + PMM_PAGEOP PageOp; + PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace); - /* + /* * There is a window between taking the page fault and locking the * address space when another thread could load the page so we check * that. */ - if (MmIsPagePresent(NULL, Address)) - { - return(STATUS_SUCCESS); - } + if (MmIsPagePresent(NULL, Address)) + { + return(STATUS_SUCCESS); + } - /* + /* * Check for the virtual memory area being deleted. */ - if (MemoryArea->DeleteInProgress) - { - return(STATUS_UNSUCCESSFUL); - } + if (MemoryArea->DeleteInProgress) + { + return(STATUS_UNSUCCESSFUL); + } - /* + /* * Get the segment corresponding to the virtual address */ - Region = MmFindRegion(MemoryArea->StartingAddress, - &MemoryArea->Data.VirtualMemoryData.RegionListHead, - Address, NULL); + Region = MmFindRegion(MemoryArea->StartingAddress, + &MemoryArea->Data.VirtualMemoryData.RegionListHead, + Address, NULL); - if (Region->Type == MEM_RESERVE || Region->Protect == PAGE_NOACCESS) - { - return(STATUS_ACCESS_VIOLATION); - } + if (Region->Type == MEM_RESERVE || Region->Protect == PAGE_NOACCESS) + { + return(STATUS_ACCESS_VIOLATION); + } - /* + /* * FIXME */ if (Region->Protect & PAGE_GUARD) @@ -216,230 +216,230 @@ MmNotPresentFaultVirtualMemory(PMMSUPPORT AddressSpace, return(STATUS_GUARD_PAGE_VIOLATION); } - /* + /* * Get or create a page operation */ - PageOp = MmGetPageOp(MemoryArea, Process->UniqueProcessId, - (PVOID)PAGE_ROUND_DOWN(Address), NULL, 0, - MM_PAGEOP_PAGEIN, FALSE); - if (PageOp == NULL) - { - DPRINT1("MmGetPageOp failed"); - KeBugCheck(MEMORY_MANAGEMENT); - } + PageOp = MmGetPageOp(MemoryArea, Process->UniqueProcessId, + (PVOID)PAGE_ROUND_DOWN(Address), NULL, 0, + MM_PAGEOP_PAGEIN, FALSE); + if (PageOp == NULL) + { + DPRINT1("MmGetPageOp failed"); + KeBugCheck(MEMORY_MANAGEMENT); + } - /* + /* * Check if someone else is already handling this fault, if so wait * for them */ - if (PageOp->Thread != PsGetCurrentThread()) - { - MmUnlockAddressSpace(AddressSpace); - Status = KeWaitForSingleObject(&PageOp->CompletionEvent, - 0, - KernelMode, - FALSE, - NULL); - /* - * Check for various strange conditions - */ - if (Status != STATUS_SUCCESS) - { - DPRINT1("Failed to wait for page op\n"); - KeBugCheck(MEMORY_MANAGEMENT); - } - if (PageOp->Status == STATUS_PENDING) - { - DPRINT1("Woke for page op before completion\n"); - KeBugCheck(MEMORY_MANAGEMENT); - } - /* - * If this wasn't a pagein then we need to restart the handling - */ - if (PageOp->OpType != MM_PAGEOP_PAGEIN) - { - MmLockAddressSpace(AddressSpace); - KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); - MmReleasePageOp(PageOp); - return(STATUS_MM_RESTART_OPERATION); - } - /* - * If the thread handling this fault has failed then we don't retry - */ - if (!NT_SUCCESS(PageOp->Status)) - { - MmLockAddressSpace(AddressSpace); - KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); - Status = PageOp->Status; - MmReleasePageOp(PageOp); - return(Status); - } - MmLockAddressSpace(AddressSpace); - KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); - MmReleasePageOp(PageOp); - return(STATUS_SUCCESS); - } + if (PageOp->Thread != PsGetCurrentThread()) + { + MmUnlockAddressSpace(AddressSpace); + Status = KeWaitForSingleObject(&PageOp->CompletionEvent, + 0, + KernelMode, + FALSE, + NULL); + /* + * Check for various strange conditions + */ + if (Status != STATUS_SUCCESS) + { + DPRINT1("Failed to wait for page op\n"); + KeBugCheck(MEMORY_MANAGEMENT); + } + if (PageOp->Status == STATUS_PENDING) + { + DPRINT1("Woke for page op before completion\n"); + KeBugCheck(MEMORY_MANAGEMENT); + } + /* + * If this wasn't a pagein then we need to restart the handling + */ + if (PageOp->OpType != MM_PAGEOP_PAGEIN) + { + MmLockAddressSpace(AddressSpace); + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_MM_RESTART_OPERATION); + } + /* + * If the thread handling this fault has failed then we don't retry + */ + if (!NT_SUCCESS(PageOp->Status)) + { + MmLockAddressSpace(AddressSpace); + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + Status = PageOp->Status; + MmReleasePageOp(PageOp); + return(Status); + } + MmLockAddressSpace(AddressSpace); + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_SUCCESS); + } - /* + /* * Try to allocate a page */ - MI_SET_USAGE(MI_USAGE_VAD); - MI_SET_PROCESS2(Process->ImageFileName); - Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page); - if (Status == STATUS_NO_MEMORY) - { - MmUnlockAddressSpace(AddressSpace); - Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page); - MmLockAddressSpace(AddressSpace); - } - if (!NT_SUCCESS(Status)) - { - DPRINT1("MmRequestPageMemoryConsumer failed, status = %x\n", Status); - KeBugCheck(MEMORY_MANAGEMENT); - } + MI_SET_USAGE(MI_USAGE_VAD); + MI_SET_PROCESS2(Process->ImageFileName); + Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page); + if (Status == STATUS_NO_MEMORY) + { + MmUnlockAddressSpace(AddressSpace); + Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page); + MmLockAddressSpace(AddressSpace); + } + if (!NT_SUCCESS(Status)) + { + DPRINT1("MmRequestPageMemoryConsumer failed, status = %x\n", Status); + KeBugCheck(MEMORY_MANAGEMENT); + } - /* + /* * Handle swapped out pages. */ - if (MmIsPageSwapEntry(NULL, Address)) - { - SWAPENTRY SwapEntry; + if (MmIsPageSwapEntry(NULL, Address)) + { + SWAPENTRY SwapEntry; - MmDeletePageFileMapping(Process, Address, &SwapEntry); - Status = MmReadFromSwapPage(SwapEntry, Page); - if (!NT_SUCCESS(Status)) - { - KeBugCheck(MEMORY_MANAGEMENT); - } - MmSetSavedSwapEntryPage(Page, SwapEntry); - } + MmDeletePageFileMapping(Process, Address, &SwapEntry); + Status = MmReadFromSwapPage(SwapEntry, Page); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(MEMORY_MANAGEMENT); + } + MmSetSavedSwapEntryPage(Page, SwapEntry); + } - /* + /* * Set the page. If we fail because we are out of memory then * try again */ - Status = MmCreateVirtualMapping(Process, - (PVOID)PAGE_ROUND_DOWN(Address), - Region->Protect, - &Page, - 1); - while (Status == STATUS_NO_MEMORY) - { - MmUnlockAddressSpace(AddressSpace); - Status = MmCreateVirtualMapping(Process, - Address, - Region->Protect, - &Page, - 1); - MmLockAddressSpace(AddressSpace); - } - if (!NT_SUCCESS(Status)) - { - DPRINT1("MmCreateVirtualMapping failed, not out of memory\n"); - KeBugCheck(MEMORY_MANAGEMENT); - return(Status); - } + Status = MmCreateVirtualMapping(Process, + (PVOID)PAGE_ROUND_DOWN(Address), + Region->Protect, + &Page, + 1); + while (Status == STATUS_NO_MEMORY) + { + MmUnlockAddressSpace(AddressSpace); + Status = MmCreateVirtualMapping(Process, + Address, + Region->Protect, + &Page, + 1); + MmLockAddressSpace(AddressSpace); + } + if (!NT_SUCCESS(Status)) + { + DPRINT1("MmCreateVirtualMapping failed, not out of memory\n"); + KeBugCheck(MEMORY_MANAGEMENT); + return(Status); + } - /* + /* * Add the page to the process's working set */ - MmInsertRmap(Page, Process, (PVOID)PAGE_ROUND_DOWN(Address)); + MmInsertRmap(Page, Process, (PVOID)PAGE_ROUND_DOWN(Address)); - /* + /* * Finish the operation */ - PageOp->Status = STATUS_SUCCESS; - KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); - MmReleasePageOp(PageOp); - return(STATUS_SUCCESS); + PageOp->Status = STATUS_SUCCESS; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_SUCCESS); } static VOID MmModifyAttributes(PMMSUPPORT AddressSpace, - PVOID BaseAddress, - SIZE_T RegionSize, - ULONG OldType, - ULONG OldProtect, - ULONG NewType, - ULONG NewProtect) + PVOID BaseAddress, + SIZE_T RegionSize, + ULONG OldType, + ULONG OldProtect, + ULONG NewType, + ULONG NewProtect) /* - * FUNCTION: Modify the attributes of a memory region - */ +* FUNCTION: Modify the attributes of a memory region +*/ { - PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace); + PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace); - /* + /* * If we are switching a previously committed region to reserved then * free any allocated pages within the region */ - if (NewType == MEM_RESERVE && OldType == MEM_COMMIT) - { - ULONG i; + if (NewType == MEM_RESERVE && OldType == MEM_COMMIT) + { + ULONG i; - for (i=0; i < PAGE_ROUND_UP(RegionSize)/PAGE_SIZE; i++) - { - PFN_NUMBER Page; + for (i=0; i < PAGE_ROUND_UP(RegionSize)/PAGE_SIZE; i++) + { + PFN_NUMBER Page; - if (MmIsPageSwapEntry(Process, - (char*)BaseAddress + (i * PAGE_SIZE))) - { - SWAPENTRY SwapEntry; - - MmDeletePageFileMapping(Process, - (char*)BaseAddress + (i * PAGE_SIZE), - &SwapEntry); - MmFreeSwapPage(SwapEntry); - } - else - { - MmDeleteVirtualMapping(Process, - (char*)BaseAddress + (i*PAGE_SIZE), - FALSE, NULL, &Page); - if (Page != 0) + if (MmIsPageSwapEntry(Process, + (char*)BaseAddress + (i * PAGE_SIZE))) { - SWAPENTRY SavedSwapEntry; - SavedSwapEntry = MmGetSavedSwapEntryPage(Page); - if (SavedSwapEntry != 0) - { - MmFreeSwapPage(SavedSwapEntry); - MmSetSavedSwapEntryPage(Page, 0); - } - MmDeleteRmap(Page, Process, - (char*)BaseAddress + (i * PAGE_SIZE)); - MmReleasePageMemoryConsumer(MC_USER, Page); - } - } - } - } + SWAPENTRY SwapEntry; - /* + MmDeletePageFileMapping(Process, + (char*)BaseAddress + (i * PAGE_SIZE), + &SwapEntry); + MmFreeSwapPage(SwapEntry); + } + else + { + MmDeleteVirtualMapping(Process, + (char*)BaseAddress + (i*PAGE_SIZE), + FALSE, NULL, &Page); + if (Page != 0) + { + SWAPENTRY SavedSwapEntry; + SavedSwapEntry = MmGetSavedSwapEntryPage(Page); + if (SavedSwapEntry != 0) + { + MmFreeSwapPage(SavedSwapEntry); + MmSetSavedSwapEntryPage(Page, 0); + } + MmDeleteRmap(Page, Process, + (char*)BaseAddress + (i * PAGE_SIZE)); + MmReleasePageMemoryConsumer(MC_USER, Page); + } + } + } + } + + /* * If we are changing the protection attributes of a committed region then * alter the attributes for any allocated pages within the region */ - if (NewType == MEM_COMMIT && OldType == MEM_COMMIT && - OldProtect != NewProtect) - { - ULONG i; + if (NewType == MEM_COMMIT && OldType == MEM_COMMIT && + OldProtect != NewProtect) + { + ULONG i; - for (i=0; i < PAGE_ROUND_UP(RegionSize)/PAGE_SIZE; i++) - { - if (MmIsPagePresent(Process, - (char*)BaseAddress + (i*PAGE_SIZE))) - { - MmSetPageProtect(Process, - (char*)BaseAddress + (i*PAGE_SIZE), - NewProtect); - } - } - } + for (i=0; i < PAGE_ROUND_UP(RegionSize)/PAGE_SIZE; i++) + { + if (MmIsPagePresent(Process, + (char*)BaseAddress + (i*PAGE_SIZE))) + { + MmSetPageProtect(Process, + (char*)BaseAddress + (i*PAGE_SIZE), + NewProtect); + } + } + } } NTSTATUS NTAPI MiProtectVirtualMemory(IN PEPROCESS Process, - IN OUT PVOID *BaseAddress, - IN OUT PSIZE_T NumberOfBytesToProtect, - IN ULONG NewAccessProtection, - OUT PULONG OldAccessProtection OPTIONAL) + IN OUT PVOID *BaseAddress, + IN OUT PSIZE_T NumberOfBytesToProtect, + IN ULONG NewAccessProtection, + OUT PULONG OldAccessProtection OPTIONAL) { PMEMORY_AREA MemoryArea; PMMSUPPORT AddressSpace; @@ -462,20 +462,20 @@ MiProtectVirtualMemory(IN PEPROCESS Process, } if (OldAccessProtection == NULL) - OldAccessProtection = &OldAccessProtection_; + OldAccessProtection = &OldAccessProtection_; if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY) { Status = MmProtectAnonMem(AddressSpace, MemoryArea, *BaseAddress, - *NumberOfBytesToProtect, NewAccessProtection, - OldAccessProtection); + *NumberOfBytesToProtect, NewAccessProtection, + OldAccessProtection); } else if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW) { Status = MmProtectSectionView(AddressSpace, MemoryArea, *BaseAddress, - *NumberOfBytesToProtect, - NewAccessProtection, - OldAccessProtection); + *NumberOfBytesToProtect, + NewAccessProtection, + OldAccessProtection); } else { @@ -489,28 +489,28 @@ MiProtectVirtualMemory(IN PEPROCESS Process, } /* - * @implemented - */ +* @implemented +*/ NTSTATUS NTAPI NtAllocateVirtualMemory(IN HANDLE ProcessHandle, - IN OUT PVOID* UBaseAddress, - IN ULONG_PTR ZeroBits, - IN OUT PSIZE_T URegionSize, - IN ULONG AllocationType, - IN ULONG Protect) + IN OUT PVOID* UBaseAddress, + IN ULONG_PTR ZeroBits, + IN OUT PSIZE_T URegionSize, + IN ULONG AllocationType, + IN ULONG Protect) { - PEPROCESS Process; - MEMORY_AREA* MemoryArea; - ULONG_PTR MemoryAreaLength; - ULONG Type; - NTSTATUS Status; - PMMSUPPORT AddressSpace; - PVOID BaseAddress; - ULONG RegionSize; - PVOID PBaseAddress; - ULONG_PTR PRegionSize; - PHYSICAL_ADDRESS BoundaryAddressMultiple; + PEPROCESS Process; + MEMORY_AREA* MemoryArea; + ULONG_PTR MemoryAreaLength; + ULONG Type; + NTSTATUS Status; + PMMSUPPORT AddressSpace; + PVOID BaseAddress; + ULONG RegionSize; + PVOID PBaseAddress; + ULONG_PTR PRegionSize; + PHYSICAL_ADDRESS BoundaryAddressMultiple; PEPROCESS CurrentProcess = PsGetCurrentProcess(); KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); KAPC_STATE ApcState; @@ -528,7 +528,7 @@ NtAllocateVirtualMemory(IN HANDLE ProcessHandle, /* Check for valid Allocation Types */ if ((AllocationType & ~(MEM_COMMIT | MEM_RESERVE | MEM_RESET | MEM_PHYSICAL | - MEM_TOP_DOWN | MEM_WRITE_WATCH))) + MEM_TOP_DOWN | MEM_WRITE_WATCH))) { DPRINT1("Invalid Allocation Type\n"); return STATUS_INVALID_PARAMETER_5; @@ -659,11 +659,11 @@ NtAllocateVirtualMemory(IN HANDLE ProcessHandle, { /* Reference the handle for correct permissions */ Status = ObReferenceObjectByHandle(ProcessHandle, - PROCESS_VM_OPERATION, - PsProcessType, - PreviousMode, - (PVOID*)&Process, - NULL); + PROCESS_VM_OPERATION, + PsProcessType, + PreviousMode, + (PVOID*)&Process, + NULL); if (!NT_SUCCESS(Status)) return Status; /* Check if not running in the current process */ @@ -688,297 +688,297 @@ NtAllocateVirtualMemory(IN HANDLE ProcessHandle, } } - BaseAddress = (PVOID)PAGE_ROUND_DOWN(PBaseAddress); - RegionSize = PAGE_ROUND_UP((ULONG_PTR)PBaseAddress + PRegionSize) - - PAGE_ROUND_DOWN(PBaseAddress); + BaseAddress = (PVOID)PAGE_ROUND_DOWN(PBaseAddress); + RegionSize = PAGE_ROUND_UP((ULONG_PTR)PBaseAddress + PRegionSize) - + PAGE_ROUND_DOWN(PBaseAddress); - /* + /* * Copy on Write is reserved for system use. This case is a certain failure * but there may be other cases...needs more testing */ - if ((!BaseAddress || (AllocationType & MEM_RESERVE)) && - (Protect & (PAGE_WRITECOPY | PAGE_EXECUTE_WRITECOPY))) - { - DPRINT1("Copy on write is not supported by VirtualAlloc\n"); - return STATUS_INVALID_PAGE_PROTECTION; - } + if ((!BaseAddress || (AllocationType & MEM_RESERVE)) && + (Protect & (PAGE_WRITECOPY | PAGE_EXECUTE_WRITECOPY))) + { + DPRINT1("Copy on write is not supported by VirtualAlloc\n"); + return STATUS_INVALID_PAGE_PROTECTION; + } - Type = (AllocationType & MEM_COMMIT) ? MEM_COMMIT : MEM_RESERVE; - DPRINT("Type %x\n", Type); + Type = (AllocationType & MEM_COMMIT) ? MEM_COMMIT : MEM_RESERVE; + DPRINT("Type %x\n", Type); - AddressSpace = &Process->Vm; - MmLockAddressSpace(AddressSpace); + AddressSpace = &Process->Vm; + MmLockAddressSpace(AddressSpace); - if (PBaseAddress != 0) - { - MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress); + if (PBaseAddress != 0) + { + MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress); - if (MemoryArea != NULL) - { - MemoryAreaLength = (ULONG_PTR)MemoryArea->EndingAddress - - (ULONG_PTR)MemoryArea->StartingAddress; + if (MemoryArea != NULL) + { + 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); - if (Attached) KeUnstackDetachProcess(&ApcState); - if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process); - return STATUS_MEMORY_NOT_ALLOCATED; - } - - if (AllocationType == MEM_RESET) - { - if (MmIsPagePresent(Process, BaseAddress)) + if (((ULONG_PTR)BaseAddress + RegionSize) > (ULONG_PTR)MemoryArea->EndingAddress) { - /* FIXME: mark pages as not modified */ + DPRINT("BaseAddress + RegionSize %x is larger than MemoryArea's EndingAddress %x\n", + (ULONG_PTR)BaseAddress + RegionSize, MemoryArea->EndingAddress); + + MmUnlockAddressSpace(AddressSpace); + if (Attached) KeUnstackDetachProcess(&ApcState); + if (ProcessHandle != NtCurrentProcess()) 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); + if (Attached) KeUnstackDetachProcess(&ApcState); + if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process); + + /* MEM_RESET does not modify any attributes of region */ + return STATUS_SUCCESS; + } + + if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY && + MemoryAreaLength >= RegionSize) + { + Status = + MmAlterRegion(AddressSpace, + MemoryArea->StartingAddress, + &MemoryArea->Data.VirtualMemoryData.RegionListHead, + BaseAddress, RegionSize, + Type, Protect, MmModifyAttributes); + MmUnlockAddressSpace(AddressSpace); + if (Attached) KeUnstackDetachProcess(&ApcState); + if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process); + DPRINT("NtAllocateVirtualMemory() = %x\n",Status); + + /* Give the caller rounded BaseAddress and area length */ + if (NT_SUCCESS(Status)) + { + *UBaseAddress = BaseAddress; + *URegionSize = RegionSize; + DPRINT("*UBaseAddress %x *URegionSize %x\n", BaseAddress, RegionSize); + } + + return(Status); + } + else if (MemoryAreaLength >= RegionSize) + { + /* Region list initialized? */ + if (MemoryArea->Data.SectionData.RegionListHead.Flink) + { + Status = + MmAlterRegion(AddressSpace, + MemoryArea->StartingAddress, + &MemoryArea->Data.SectionData.RegionListHead, + BaseAddress, RegionSize, + Type, Protect, MmModifyAttributes); + } + else + { + Status = STATUS_ACCESS_VIOLATION; + } + + MmUnlockAddressSpace(AddressSpace); + if (Attached) KeUnstackDetachProcess(&ApcState); + if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process); + DPRINT("NtAllocateVirtualMemory() = %x\n",Status); + + /* Give the caller rounded BaseAddress and area length */ + if (NT_SUCCESS(Status)) + { + *UBaseAddress = BaseAddress; + *URegionSize = RegionSize; + DPRINT("*UBaseAddress %x *URegionSize %x\n", BaseAddress, RegionSize); + } + + return(Status); } else { - /* FIXME: if pages are in paging file discard them and bring in pages of zeros */ + MmUnlockAddressSpace(AddressSpace); + if (Attached) KeUnstackDetachProcess(&ApcState); + if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process); + return(STATUS_UNSUCCESSFUL); } + } + } - MmUnlockAddressSpace(AddressSpace); - if (Attached) KeUnstackDetachProcess(&ApcState); - if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process); + Status = MmCreateMemoryArea(AddressSpace, + MEMORY_AREA_VIRTUAL_MEMORY, + &BaseAddress, + RegionSize, + Protect, + &MemoryArea, + PBaseAddress != 0, + AllocationType & MEM_TOP_DOWN, + BoundaryAddressMultiple); + if (!NT_SUCCESS(Status)) + { + MmUnlockAddressSpace(AddressSpace); + if (Attached) KeUnstackDetachProcess(&ApcState); + if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process); + DPRINT("NtAllocateVirtualMemory() = %x\n",Status); + return(Status); + } - /* MEM_RESET does not modify any attributes of region */ - return STATUS_SUCCESS; - } + MemoryAreaLength = (ULONG_PTR)MemoryArea->EndingAddress - + (ULONG_PTR)MemoryArea->StartingAddress; - if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY && - MemoryAreaLength >= RegionSize) - { - Status = - MmAlterRegion(AddressSpace, - MemoryArea->StartingAddress, - &MemoryArea->Data.VirtualMemoryData.RegionListHead, - BaseAddress, RegionSize, - Type, Protect, MmModifyAttributes); - MmUnlockAddressSpace(AddressSpace); - if (Attached) KeUnstackDetachProcess(&ApcState); - if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process); - DPRINT("NtAllocateVirtualMemory() = %x\n",Status); + MmInitializeRegion(&MemoryArea->Data.VirtualMemoryData.RegionListHead, + MemoryAreaLength, Type, Protect); - /* Give the caller rounded BaseAddress and area length */ - if (NT_SUCCESS(Status)) - { - *UBaseAddress = BaseAddress; - *URegionSize = RegionSize; - DPRINT("*UBaseAddress %x *URegionSize %x\n", BaseAddress, RegionSize); - } + if ((AllocationType & MEM_COMMIT) && + (Protect & (PAGE_READWRITE | PAGE_EXECUTE_READWRITE))) + { + const ULONG nPages = PAGE_ROUND_UP(MemoryAreaLength) >> PAGE_SHIFT; + MmReserveSwapPages(nPages); + } - return(Status); - } - else if (MemoryAreaLength >= RegionSize) - { - /* Region list initialized? */ - if (MemoryArea->Data.SectionData.RegionListHead.Flink) - { - Status = - MmAlterRegion(AddressSpace, - MemoryArea->StartingAddress, - &MemoryArea->Data.SectionData.RegionListHead, - BaseAddress, RegionSize, - Type, Protect, MmModifyAttributes); - } - else - { - Status = STATUS_ACCESS_VIOLATION; - } + MmUnlockAddressSpace(AddressSpace); + if (Attached) KeUnstackDetachProcess(&ApcState); + if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process); - MmUnlockAddressSpace(AddressSpace); - if (Attached) KeUnstackDetachProcess(&ApcState); - if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process); - DPRINT("NtAllocateVirtualMemory() = %x\n",Status); + *UBaseAddress = BaseAddress; + *URegionSize = MemoryAreaLength; + DPRINT("*UBaseAddress %x *URegionSize %x\n", BaseAddress, RegionSize); - /* Give the caller rounded BaseAddress and area length */ - if (NT_SUCCESS(Status)) - { - *UBaseAddress = BaseAddress; - *URegionSize = RegionSize; - DPRINT("*UBaseAddress %x *URegionSize %x\n", BaseAddress, RegionSize); - } - - return(Status); - } - else - { - MmUnlockAddressSpace(AddressSpace); - if (Attached) KeUnstackDetachProcess(&ApcState); - if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process); - return(STATUS_UNSUCCESSFUL); - } - } - } - - Status = MmCreateMemoryArea(AddressSpace, - MEMORY_AREA_VIRTUAL_MEMORY, - &BaseAddress, - RegionSize, - Protect, - &MemoryArea, - PBaseAddress != 0, - AllocationType & MEM_TOP_DOWN, - BoundaryAddressMultiple); - if (!NT_SUCCESS(Status)) - { - MmUnlockAddressSpace(AddressSpace); - if (Attached) KeUnstackDetachProcess(&ApcState); - if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process); - DPRINT("NtAllocateVirtualMemory() = %x\n",Status); - return(Status); - } - - MemoryAreaLength = (ULONG_PTR)MemoryArea->EndingAddress - - (ULONG_PTR)MemoryArea->StartingAddress; - - MmInitializeRegion(&MemoryArea->Data.VirtualMemoryData.RegionListHead, - MemoryAreaLength, Type, Protect); - - if ((AllocationType & MEM_COMMIT) && - (Protect & (PAGE_READWRITE | PAGE_EXECUTE_READWRITE))) - { - const ULONG nPages = PAGE_ROUND_UP(MemoryAreaLength) >> PAGE_SHIFT; - MmReserveSwapPages(nPages); - } - - MmUnlockAddressSpace(AddressSpace); - if (Attached) KeUnstackDetachProcess(&ApcState); - if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process); - - *UBaseAddress = BaseAddress; - *URegionSize = MemoryAreaLength; - DPRINT("*UBaseAddress %x *URegionSize %x\n", BaseAddress, RegionSize); - - return(STATUS_SUCCESS); + return(STATUS_SUCCESS); } static VOID MmFreeVirtualMemoryPage(PVOID Context, - MEMORY_AREA* MemoryArea, - PVOID Address, - PFN_NUMBER Page, - SWAPENTRY SwapEntry, - BOOLEAN Dirty) + MEMORY_AREA* MemoryArea, + PVOID Address, + PFN_NUMBER Page, + SWAPENTRY SwapEntry, + BOOLEAN Dirty) { - PEPROCESS Process = (PEPROCESS)Context; + PEPROCESS Process = (PEPROCESS)Context; - if (Page != 0) - { - SWAPENTRY SavedSwapEntry; - SavedSwapEntry = MmGetSavedSwapEntryPage(Page); - if (SavedSwapEntry != 0) - { - MmFreeSwapPage(SavedSwapEntry); - MmSetSavedSwapEntryPage(Page, 0); - } - MmDeleteRmap(Page, Process, Address); - MmReleasePageMemoryConsumer(MC_USER, Page); - } - else if (SwapEntry != 0) - { - MmFreeSwapPage(SwapEntry); - } + if (Page != 0) + { + SWAPENTRY SavedSwapEntry; + SavedSwapEntry = MmGetSavedSwapEntryPage(Page); + if (SavedSwapEntry != 0) + { + MmFreeSwapPage(SavedSwapEntry); + MmSetSavedSwapEntryPage(Page, 0); + } + MmDeleteRmap(Page, Process, Address); + MmReleasePageMemoryConsumer(MC_USER, Page); + } + else if (SwapEntry != 0) + { + MmFreeSwapPage(SwapEntry); + } } VOID NTAPI MmFreeVirtualMemory(PEPROCESS Process, - PMEMORY_AREA MemoryArea) + PMEMORY_AREA MemoryArea) { - PLIST_ENTRY current_entry; - PMM_REGION current; - ULONG i; + PLIST_ENTRY current_entry; + PMM_REGION current; + ULONG i; - DPRINT("MmFreeVirtualMemory(Process %p MemoryArea %p)\n", Process, - MemoryArea); + DPRINT("MmFreeVirtualMemory(Process %p MemoryArea %p)\n", Process, + MemoryArea); - /* Mark this memory area as about to be deleted. */ - MemoryArea->DeleteInProgress = TRUE; + /* Mark this memory area as about to be deleted. */ + MemoryArea->DeleteInProgress = TRUE; - /* + /* * Wait for any ongoing paging operations. Notice that since we have * flagged this memory area as deleted no more page ops will be added. */ - if (MemoryArea->PageOpCount > 0) - { - ULONG_PTR MemoryAreaLength = (ULONG_PTR)MemoryArea->EndingAddress - - (ULONG_PTR)MemoryArea->StartingAddress; - const ULONG nPages = PAGE_ROUND_UP(MemoryAreaLength) >> PAGE_SHIFT; + if (MemoryArea->PageOpCount > 0) + { + ULONG_PTR MemoryAreaLength = (ULONG_PTR)MemoryArea->EndingAddress - + (ULONG_PTR)MemoryArea->StartingAddress; + const ULONG nPages = PAGE_ROUND_UP(MemoryAreaLength) >> PAGE_SHIFT; - for (i = 0; i < nPages && MemoryArea->PageOpCount != 0; ++i) - { - PMM_PAGEOP PageOp; - PageOp = MmCheckForPageOp(MemoryArea, Process->UniqueProcessId, - (PVOID)((ULONG_PTR)MemoryArea->StartingAddress + (i * PAGE_SIZE)), - NULL, 0); - if (PageOp != NULL) - { - NTSTATUS Status; - MmUnlockAddressSpace(&Process->Vm); - Status = KeWaitForSingleObject(&PageOp->CompletionEvent, - 0, - KernelMode, - FALSE, - NULL); - if (Status != STATUS_SUCCESS) + for (i = 0; i < nPages && MemoryArea->PageOpCount != 0; ++i) + { + PMM_PAGEOP PageOp; + PageOp = MmCheckForPageOp(MemoryArea, Process->UniqueProcessId, + (PVOID)((ULONG_PTR)MemoryArea->StartingAddress + (i * PAGE_SIZE)), + NULL, 0); + if (PageOp != NULL) { - DPRINT1("Failed to wait for page op\n"); - KeBugCheck(MEMORY_MANAGEMENT); + NTSTATUS Status; + MmUnlockAddressSpace(&Process->Vm); + Status = KeWaitForSingleObject(&PageOp->CompletionEvent, + 0, + KernelMode, + FALSE, + NULL); + if (Status != STATUS_SUCCESS) + { + DPRINT1("Failed to wait for page op\n"); + KeBugCheck(MEMORY_MANAGEMENT); + } + MmLockAddressSpace(&Process->Vm); + MmReleasePageOp(PageOp); } - MmLockAddressSpace(&Process->Vm); - MmReleasePageOp(PageOp); - } - } - } + } + } - /* Free all the individual segments. */ - current_entry = MemoryArea->Data.VirtualMemoryData.RegionListHead.Flink; - while (current_entry != &MemoryArea->Data.VirtualMemoryData.RegionListHead) - { - current = CONTAINING_RECORD(current_entry, MM_REGION, RegionListEntry); - current_entry = current_entry->Flink; - ExFreePool(current); - } + /* Free all the individual segments. */ + current_entry = MemoryArea->Data.VirtualMemoryData.RegionListHead.Flink; + while (current_entry != &MemoryArea->Data.VirtualMemoryData.RegionListHead) + { + current = CONTAINING_RECORD(current_entry, MM_REGION, RegionListEntry); + current_entry = current_entry->Flink; + ExFreePool(current); + } - /* Actually free the memory area. */ - MmFreeMemoryArea(&Process->Vm, - MemoryArea, - MmFreeVirtualMemoryPage, - (PVOID)Process); + /* Actually free the memory area. */ + MmFreeMemoryArea(&Process->Vm, + MemoryArea, + MmFreeVirtualMemoryPage, + (PVOID)Process); } /* - * @implemented - */ +* @implemented +*/ NTSTATUS NTAPI NtFreeVirtualMemory(IN HANDLE ProcessHandle, - IN PVOID* UBaseAddress, - IN PSIZE_T URegionSize, - IN ULONG FreeType) + IN PVOID* UBaseAddress, + IN PSIZE_T URegionSize, + IN ULONG FreeType) /* - * FUNCTION: Frees a range of virtual memory - * ARGUMENTS: - * ProcessHandle = Points to the process that allocated the virtual - * memory - * BaseAddress = Points to the memory address, rounded down to a - * multiple of the pagesize - * RegionSize = Limits the range to free, rounded up to a multiple of - * the paging size - * FreeType = Can be one of the values: MEM_DECOMMIT, or MEM_RELEASE - * RETURNS: Status - */ +* FUNCTION: Frees a range of virtual memory +* ARGUMENTS: +* ProcessHandle = Points to the process that allocated the virtual +* memory +* BaseAddress = Points to the memory address, rounded down to a +* multiple of the pagesize +* RegionSize = Limits the range to free, rounded up to a multiple of +* the paging size +* FreeType = Can be one of the values: MEM_DECOMMIT, or MEM_RELEASE +* RETURNS: Status +*/ { - MEMORY_AREA* MemoryArea; - NTSTATUS Status; - PEPROCESS Process; - PMMSUPPORT AddressSpace; - PVOID BaseAddress, PBaseAddress; - SIZE_T RegionSize, PRegionSize; + MEMORY_AREA* MemoryArea; + NTSTATUS Status; + PEPROCESS Process; + PMMSUPPORT AddressSpace; + PVOID BaseAddress, PBaseAddress; + SIZE_T RegionSize, PRegionSize; PEPROCESS CurrentProcess = PsGetCurrentProcess(); KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); KAPC_STATE ApcState; @@ -991,15 +991,15 @@ NtFreeVirtualMemory(IN HANDLE ProcessHandle, DPRINT1("Invalid FreeType\n"); return STATUS_INVALID_PARAMETER_4; } - + /* Check if no flag was used, or if both flags were used */ if (!((FreeType & (MEM_DECOMMIT | MEM_RELEASE))) || - ((FreeType & (MEM_DECOMMIT | MEM_RELEASE)) == (MEM_DECOMMIT | MEM_RELEASE))) + ((FreeType & (MEM_DECOMMIT | MEM_RELEASE)) == (MEM_DECOMMIT | MEM_RELEASE))) { DPRINT1("Invalid FreeType combination\n"); return STATUS_INVALID_PARAMETER_4; } - + /* Enter SEH */ _SEH2_TRY { @@ -1010,7 +1010,7 @@ NtFreeVirtualMemory(IN HANDLE ProcessHandle, ProbeForWritePointer(UBaseAddress); ProbeForWriteUlong(URegionSize); } - + /* Capture their values */ PBaseAddress = *UBaseAddress; PRegionSize = *URegionSize; @@ -1021,180 +1021,180 @@ NtFreeVirtualMemory(IN HANDLE ProcessHandle, _SEH2_YIELD(return _SEH2_GetExceptionCode()); } _SEH2_END; - + /* Make sure the allocation isn't past the user area */ if (PBaseAddress >= MM_HIGHEST_USER_ADDRESS) { DPRINT1("Virtual free base above User Space\n"); return STATUS_INVALID_PARAMETER_2; } - - /* Make sure the allocation wouldn't overflow past the user area */ - if (((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (ULONG_PTR)PBaseAddress) < PRegionSize) - { - DPRINT1("Region size would overflow into kernel-memory\n"); - return STATUS_INVALID_PARAMETER_3; - } - /* Check if this is for the current process */ - if (ProcessHandle == NtCurrentProcess()) - { - /* We already have the current process, no need to go through Ob */ - Process = CurrentProcess; - } - else - { - /* Reference the handle for correct permissions */ - Status = ObReferenceObjectByHandle(ProcessHandle, - PROCESS_VM_OPERATION, - PsProcessType, - PreviousMode, - (PVOID*)&Process, - NULL); - if (!NT_SUCCESS(Status)) return Status; - - /* Check if not running in the current process */ - if (CurrentProcess != Process) - { - /* Attach to it */ - KeStackAttachProcess(&Process->Pcb, &ApcState); - Attached = TRUE; - } - } + /* Make sure the allocation wouldn't overflow past the user area */ + if (((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (ULONG_PTR)PBaseAddress) < PRegionSize) + { + DPRINT1("Region size would overflow into kernel-memory\n"); + return STATUS_INVALID_PARAMETER_3; + } - BaseAddress = (PVOID)PAGE_ROUND_DOWN((PBaseAddress)); - RegionSize = PAGE_ROUND_UP((ULONG_PTR)(PBaseAddress) + (PRegionSize)) - - PAGE_ROUND_DOWN((PBaseAddress)); + /* Check if this is for the current process */ + if (ProcessHandle == NtCurrentProcess()) + { + /* We already have the current process, no need to go through Ob */ + Process = CurrentProcess; + } + else + { + /* Reference the handle for correct permissions */ + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_VM_OPERATION, + PsProcessType, + PreviousMode, + (PVOID*)&Process, + NULL); + if (!NT_SUCCESS(Status)) return Status; + + /* Check if not running in the current process */ + if (CurrentProcess != Process) + { + /* Attach to it */ + KeStackAttachProcess(&Process->Pcb, &ApcState); + Attached = TRUE; + } + } - AddressSpace = &Process->Vm; + BaseAddress = (PVOID)PAGE_ROUND_DOWN((PBaseAddress)); + RegionSize = PAGE_ROUND_UP((ULONG_PTR)(PBaseAddress) + (PRegionSize)) - + PAGE_ROUND_DOWN((PBaseAddress)); - MmLockAddressSpace(AddressSpace); - MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress); - if (MemoryArea == NULL) - { - Status = STATUS_UNSUCCESSFUL; - goto unlock_deref_and_return; - } + AddressSpace = &Process->Vm; - switch (FreeType) - { - case MEM_RELEASE: - /* We can only free a memory area in one step. */ - if (MemoryArea->StartingAddress != BaseAddress || - MemoryArea->Type != MEMORY_AREA_VIRTUAL_MEMORY) - { + MmLockAddressSpace(AddressSpace); + MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress); + if (MemoryArea == NULL) + { + Status = STATUS_UNSUCCESSFUL; + goto unlock_deref_and_return; + } + + switch (FreeType) + { + case MEM_RELEASE: + /* We can only free a memory area in one step. */ + if (MemoryArea->StartingAddress != BaseAddress || + MemoryArea->Type != MEMORY_AREA_VIRTUAL_MEMORY) + { Status = STATUS_UNSUCCESSFUL; goto unlock_deref_and_return; - } + } - MmFreeVirtualMemory(Process, MemoryArea); - Status = STATUS_SUCCESS; - goto unlock_deref_and_return; + MmFreeVirtualMemory(Process, MemoryArea); + Status = STATUS_SUCCESS; + goto unlock_deref_and_return; - case MEM_DECOMMIT: - Status = - MmAlterRegion(AddressSpace, - MemoryArea->StartingAddress, - (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW) ? - &MemoryArea->Data.SectionData.RegionListHead : - &MemoryArea->Data.VirtualMemoryData.RegionListHead, - BaseAddress, - RegionSize, - MEM_RESERVE, - PAGE_NOACCESS, - MmModifyAttributes); - goto unlock_deref_and_return; - } + case MEM_DECOMMIT: + Status = + MmAlterRegion(AddressSpace, + MemoryArea->StartingAddress, + (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW) ? + &MemoryArea->Data.SectionData.RegionListHead : + &MemoryArea->Data.VirtualMemoryData.RegionListHead, + BaseAddress, + RegionSize, + MEM_RESERVE, + PAGE_NOACCESS, + MmModifyAttributes); + goto unlock_deref_and_return; + } - Status = STATUS_NOT_IMPLEMENTED; + Status = STATUS_NOT_IMPLEMENTED; -unlock_deref_and_return: + unlock_deref_and_return: - MmUnlockAddressSpace(AddressSpace); - if (Attached) KeUnstackDetachProcess(&ApcState); - if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process); + MmUnlockAddressSpace(AddressSpace); + if (Attached) KeUnstackDetachProcess(&ApcState); + if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process); - return(Status); + return(Status); } NTSTATUS NTAPI MmProtectAnonMem(PMMSUPPORT AddressSpace, - PMEMORY_AREA MemoryArea, - PVOID BaseAddress, - SIZE_T Length, - ULONG Protect, - PULONG OldProtect) + PMEMORY_AREA MemoryArea, + PVOID BaseAddress, + SIZE_T Length, + ULONG Protect, + PULONG OldProtect) { - PMM_REGION Region; - NTSTATUS Status = STATUS_SUCCESS; - ULONG_PTR LengthCount = 0; + PMM_REGION Region; + NTSTATUS Status = STATUS_SUCCESS; + ULONG_PTR LengthCount = 0; - /* 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 + LengthCount), NULL); + /* 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 + 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 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); - } + if (NT_SUCCESS(Status)) + { + *OldProtect = Region->Protect; + Status = MmAlterRegion(AddressSpace, MemoryArea->StartingAddress, + &MemoryArea->Data.VirtualMemoryData.RegionListHead, + BaseAddress, Length, Region->Type, Protect, + MmModifyAttributes); + } - return (Status); + return (Status); } NTSTATUS NTAPI MmQueryAnonMem(PMEMORY_AREA MemoryArea, - PVOID Address, - PMEMORY_BASIC_INFORMATION Info, - PSIZE_T ResultLength) + PVOID Address, + PMEMORY_BASIC_INFORMATION Info, + PSIZE_T ResultLength) { - PMM_REGION Region; - PVOID RegionBase = NULL; + PMM_REGION Region; + PVOID RegionBase = NULL; - Info->BaseAddress = (PVOID)PAGE_ROUND_DOWN(Address); + Info->BaseAddress = (PVOID)PAGE_ROUND_DOWN(Address); - Region = MmFindRegion(MemoryArea->StartingAddress, - &MemoryArea->Data.VirtualMemoryData.RegionListHead, - Address, &RegionBase); - Info->BaseAddress = RegionBase; - Info->AllocationBase = MemoryArea->StartingAddress; - Info->AllocationProtect = MemoryArea->Protect; - Info->RegionSize = Region->Length; - Info->State = Region->Type; - Info->Protect = Region->Protect; - Info->Type = MEM_PRIVATE; + Region = MmFindRegion(MemoryArea->StartingAddress, + &MemoryArea->Data.VirtualMemoryData.RegionListHead, + Address, &RegionBase); + Info->BaseAddress = RegionBase; + Info->AllocationBase = MemoryArea->StartingAddress; + Info->AllocationProtect = MemoryArea->Protect; + Info->RegionSize = Region->Length; + Info->State = Region->Type; + Info->Protect = Region->Protect; + Info->Type = MEM_PRIVATE; - *ResultLength = sizeof(MEMORY_BASIC_INFORMATION); - return(STATUS_SUCCESS); + *ResultLength = sizeof(MEMORY_BASIC_INFORMATION); + return(STATUS_SUCCESS); } /* EOF */