2009-06-27 08:41:45 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Kernel
|
|
|
|
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
|
|
|
* FILE: ntoskrnl/mm/ARM3/procsup.c
|
|
|
|
* PURPOSE: ARM Memory Manager Process Related Management
|
|
|
|
* PROGRAMMERS: ReactOS Portable Systems Group
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *******************************************************************/
|
|
|
|
|
|
|
|
#include <ntoskrnl.h>
|
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
|
|
|
#define MODULE_INVOLVED_IN_ARM3
|
2014-11-10 16:26:55 +00:00
|
|
|
#include <mm/ARM3/miarm.h>
|
2009-06-27 08:41:45 +00:00
|
|
|
|
2010-09-29 01:10:28 +00:00
|
|
|
/* GLOBALS ********************************************************************/
|
|
|
|
|
|
|
|
ULONG MmProcessColorSeed = 0x12345678;
|
2012-03-04 17:56:00 +00:00
|
|
|
ULONG MmMaximumDeadKernelStacks = 5;
|
|
|
|
SLIST_HEADER MmDeadStackSListHead;
|
2009-10-15 05:56:41 +00:00
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
/* PRIVATE FUNCTIONS **********************************************************/
|
|
|
|
|
2010-07-22 19:08:45 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
MiCreatePebOrTeb(IN PEPROCESS Process,
|
|
|
|
IN ULONG Size,
|
2014-10-08 00:31:35 +00:00
|
|
|
OUT PULONG_PTR BaseAddress)
|
2010-07-22 19:08:45 +00:00
|
|
|
{
|
|
|
|
PMMVAD_LONG Vad;
|
|
|
|
NTSTATUS Status;
|
2014-10-08 00:31:35 +00:00
|
|
|
ULONG_PTR HighestAddress, RandomBase;
|
|
|
|
ULONG AlignedSize;
|
2010-07-22 19:08:45 +00:00
|
|
|
LARGE_INTEGER CurrentTime;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2022-06-29 08:49:05 +00:00
|
|
|
Status = PsChargeProcessNonPagedPoolQuota(Process, sizeof(MMVAD_LONG));
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
return Status;
|
|
|
|
|
2010-07-22 19:08:45 +00:00
|
|
|
/* Allocate a VAD */
|
|
|
|
Vad = ExAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD_LONG), 'ldaV');
|
2022-06-29 08:49:05 +00:00
|
|
|
if (!Vad)
|
|
|
|
{
|
|
|
|
Status = STATUS_NO_MEMORY;
|
|
|
|
goto FailPath;
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-07-22 19:08:45 +00:00
|
|
|
/* Setup the primary flags with the size, and make it commited, private, RW */
|
|
|
|
Vad->u.LongFlags = 0;
|
|
|
|
Vad->u.VadFlags.CommitCharge = BYTES_TO_PAGES(Size);
|
|
|
|
Vad->u.VadFlags.MemCommit = TRUE;
|
|
|
|
Vad->u.VadFlags.PrivateMemory = TRUE;
|
|
|
|
Vad->u.VadFlags.Protection = MM_READWRITE;
|
|
|
|
Vad->u.VadFlags.NoChange = TRUE;
|
2014-10-08 00:31:49 +00:00
|
|
|
Vad->u1.Parent = NULL;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-07-22 19:08:45 +00:00
|
|
|
/* Setup the secondary flags to make it a secured, writable, long VAD */
|
|
|
|
Vad->u2.LongFlags2 = 0;
|
|
|
|
Vad->u2.VadFlags2.OneSecured = TRUE;
|
|
|
|
Vad->u2.VadFlags2.LongVad = TRUE;
|
|
|
|
Vad->u2.VadFlags2.ReadOnly = FALSE;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2014-10-08 00:31:49 +00:00
|
|
|
Vad->ControlArea = NULL; // For Memory-Area hack
|
|
|
|
Vad->FirstPrototypePte = NULL;
|
2010-07-22 19:08:45 +00:00
|
|
|
|
|
|
|
/* Check if this is a PEB creation */
|
2014-10-08 00:31:49 +00:00
|
|
|
ASSERT(sizeof(TEB) != sizeof(PEB));
|
2010-07-22 19:08:45 +00:00
|
|
|
if (Size == sizeof(PEB))
|
|
|
|
{
|
2014-10-08 00:31:35 +00:00
|
|
|
/* Create a random value to select one page in a 64k region */
|
2010-07-22 19:08:45 +00:00
|
|
|
KeQueryTickCount(&CurrentTime);
|
2014-10-08 00:31:35 +00:00
|
|
|
CurrentTime.LowPart &= (_64K / PAGE_SIZE) - 1;
|
|
|
|
|
|
|
|
/* Calculate a random base address */
|
|
|
|
RandomBase = (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1;
|
|
|
|
RandomBase -= CurrentTime.LowPart << PAGE_SHIFT;
|
|
|
|
|
|
|
|
/* Make sure the base address is not too high */
|
|
|
|
AlignedSize = ROUND_TO_PAGES(Size);
|
|
|
|
if ((RandomBase + AlignedSize) > (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1)
|
|
|
|
{
|
|
|
|
RandomBase = (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1 - AlignedSize;
|
|
|
|
}
|
2010-07-22 19:08:45 +00:00
|
|
|
|
2014-10-08 00:31:35 +00:00
|
|
|
/* Calculate the highest allowed address */
|
|
|
|
HighestAddress = RandomBase + AlignedSize - 1;
|
2010-08-23 03:00:03 +00:00
|
|
|
}
|
2014-10-08 00:31:49 +00:00
|
|
|
else
|
2010-08-23 03:00:03 +00:00
|
|
|
{
|
2014-10-08 00:31:49 +00:00
|
|
|
HighestAddress = (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS;
|
2010-07-22 19:08:45 +00:00
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2014-10-08 00:31:49 +00:00
|
|
|
*BaseAddress = 0;
|
|
|
|
Status = MiInsertVadEx((PMMVAD)Vad,
|
|
|
|
BaseAddress,
|
2018-01-29 11:37:26 +00:00
|
|
|
Size,
|
2014-10-08 00:31:49 +00:00
|
|
|
HighestAddress,
|
|
|
|
PAGE_SIZE,
|
|
|
|
MEM_TOP_DOWN);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
ExFreePoolWithTag(Vad, 'ldaV');
|
2022-06-29 08:49:05 +00:00
|
|
|
Status = STATUS_NO_MEMORY;
|
|
|
|
goto FailPath;
|
2014-10-08 00:31:49 +00:00
|
|
|
}
|
2010-07-22 19:08:45 +00:00
|
|
|
|
2022-05-12 06:11:52 +00:00
|
|
|
|
2014-10-08 00:31:49 +00:00
|
|
|
/* Success */
|
|
|
|
return STATUS_SUCCESS;
|
2022-06-29 08:49:05 +00:00
|
|
|
|
|
|
|
FailPath:
|
|
|
|
PsReturnProcessNonPagedPoolQuota(Process, sizeof(MMVAD_LONG));
|
|
|
|
|
|
|
|
return Status;
|
2010-07-22 19:08:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MmDeleteTeb(IN PEPROCESS Process,
|
|
|
|
IN PTEB Teb)
|
|
|
|
{
|
2010-07-24 16:28:51 +00:00
|
|
|
ULONG_PTR TebEnd;
|
|
|
|
PETHREAD Thread = PsGetCurrentThread();
|
|
|
|
PMMVAD Vad;
|
|
|
|
PMM_AVL_TABLE VadTree = &Process->VadRoot;
|
|
|
|
DPRINT("Deleting TEB: %p in %16s\n", Teb, Process->ImageFileName);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-07-24 16:28:51 +00:00
|
|
|
/* TEB is one page */
|
|
|
|
TebEnd = (ULONG_PTR)Teb + ROUND_TO_PAGES(sizeof(TEB)) - 1;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-07-24 16:28:51 +00:00
|
|
|
/* Attach to the process */
|
|
|
|
KeAttachProcess(&Process->Pcb);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-07-24 16:28:51 +00:00
|
|
|
/* Lock the process address space */
|
|
|
|
KeAcquireGuardedMutex(&Process->AddressCreationLock);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-07-24 16:28:51 +00:00
|
|
|
/* Find the VAD, make sure it's a TEB VAD */
|
|
|
|
Vad = MiLocateAddress(Teb);
|
|
|
|
DPRINT("Removing node for VAD: %lx %lx\n", Vad->StartingVpn, Vad->EndingVpn);
|
2010-12-26 15:23:03 +00:00
|
|
|
ASSERT(Vad != NULL);
|
2010-07-24 16:28:51 +00:00
|
|
|
if (Vad->StartingVpn != ((ULONG_PTR)Teb >> PAGE_SHIFT))
|
|
|
|
{
|
|
|
|
/* Bug in the AVL code? */
|
|
|
|
DPRINT1("Corrupted VAD!\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Sanity checks for a valid TEB VAD */
|
|
|
|
ASSERT((Vad->StartingVpn == ((ULONG_PTR)Teb >> PAGE_SHIFT) &&
|
|
|
|
(Vad->EndingVpn == (TebEnd >> PAGE_SHIFT))));
|
|
|
|
ASSERT(Vad->u.VadFlags.NoChange == TRUE);
|
2010-11-02 14:41:03 +00:00
|
|
|
ASSERT(Vad->u2.VadFlags2.OneSecured == TRUE);
|
2010-07-24 16:28:51 +00:00
|
|
|
ASSERT(Vad->u2.VadFlags2.MultipleSecured == FALSE);
|
|
|
|
|
|
|
|
/* Lock the working set */
|
2012-09-03 06:23:31 +00:00
|
|
|
MiLockProcessWorkingSetUnsafe(Process, Thread);
|
2010-07-24 16:28:51 +00:00
|
|
|
|
|
|
|
/* Remove this VAD from the tree */
|
|
|
|
ASSERT(VadTree->NumberGenericTableElements >= 1);
|
|
|
|
MiRemoveNode((PMMADDRESS_NODE)Vad, VadTree);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
[NTOSKRNL]: This is kind of embarssing, but after doing a local grep for some of cgutman and zekflop's changes (respectively the patch that had added MmDeleteProcessPageDirectory, and the mshtml fix patch), I fell upon a .patch file. It included 3 memory-leak-fixing patches from richard that had been sent to me during his last days -- which, had I paid attention, would've fixed the MSHTML bug and the memory leaks months ago! I've tried my best to now re-integrate a portion of the patch (the other two portions deal with freeing the loader block, and freeing .INIT sections, and I will commit them later) with the current state of trunk. Some things that patch did, no longer seem to work, and I've commented where appropriate. But in general it does seem to dereference/delete some PTEs that had been left behind before (such as deleted TEBs, and deleted VA mappings). It no longer seems to be able to delete the root PDE nor the shared data page however (this worked in the original patch's timeframe). Zekflop, tkreuzer, please take a look. I hope this will set us on a better path!
svn path=/trunk/; revision=55666
2012-02-17 07:07:47 +00:00
|
|
|
/* Delete the pages */
|
|
|
|
MiDeleteVirtualAddresses((ULONG_PTR)Teb, TebEnd, NULL);
|
2012-02-27 16:10:30 +00:00
|
|
|
|
2010-07-24 16:28:51 +00:00
|
|
|
/* Release the working set */
|
2012-09-03 06:23:31 +00:00
|
|
|
MiUnlockProcessWorkingSetUnsafe(Process, Thread);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-07-24 16:28:51 +00:00
|
|
|
/* Remove the VAD */
|
|
|
|
ExFreePool(Vad);
|
2022-05-12 06:11:52 +00:00
|
|
|
|
|
|
|
/* Return the quota the VAD used */
|
|
|
|
PsReturnProcessNonPagedPoolQuota(Process, sizeof(MMVAD_LONG));
|
2010-07-24 16:28:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Release the address space lock */
|
|
|
|
KeReleaseGuardedMutex(&Process->AddressCreationLock);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-07-24 16:28:51 +00:00
|
|
|
/* Detach */
|
|
|
|
KeDetachProcess();
|
2010-07-22 19:08:45 +00:00
|
|
|
}
|
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MmDeleteKernelStack(IN PVOID StackBase,
|
|
|
|
IN BOOLEAN GuiStack)
|
|
|
|
{
|
|
|
|
PMMPTE PointerPte;
|
[NTOSKRNL]: This is kind of embarssing, but after doing a local grep for some of cgutman and zekflop's changes (respectively the patch that had added MmDeleteProcessPageDirectory, and the mshtml fix patch), I fell upon a .patch file. It included 3 memory-leak-fixing patches from richard that had been sent to me during his last days -- which, had I paid attention, would've fixed the MSHTML bug and the memory leaks months ago! I've tried my best to now re-integrate a portion of the patch (the other two portions deal with freeing the loader block, and freeing .INIT sections, and I will commit them later) with the current state of trunk. Some things that patch did, no longer seem to work, and I've commented where appropriate. But in general it does seem to dereference/delete some PTEs that had been left behind before (such as deleted TEBs, and deleted VA mappings). It no longer seems to be able to delete the root PDE nor the shared data page however (this worked in the original patch's timeframe). Zekflop, tkreuzer, please take a look. I hope this will set us on a better path!
svn path=/trunk/; revision=55666
2012-02-17 07:07:47 +00:00
|
|
|
PFN_NUMBER PageFrameNumber, PageTableFrameNumber;
|
[HAL/NDK]
- Make Vector parameter in HalEnableSystemInterrupt, HalDisableSystemInterrupt and HalBeginSystemInterrupt an ULONG, not an UCHAR
[NDK]
- 64bit fixes for HANDLE_TABLE, KPROCESS, SECTION_IMAGE_INFORMATION, MMADDRESS_LIST, MMVAD_FLAGS, MMVAD, MMVAD_LONG, MMVAD_SHORT, MEMORY_DESCRIPTOR, MEMORY_ALLOCATION_DESCRIPTOR, LdrVerifyMappedImageMatchesChecksum
- KDPC_DATA::DpcQueueDepth is signed on amd64, unsigned on x86
[NTOSKRNL]
- Fix hundreds of MSVC and amd64 warnings
- add a pragma message to FstubFixupEfiPartition, since it looks broken
- Move portable Ke constants from <arch>/cpu.c to krnlinit.c
- Fixed a bug in amd64 KiGeneralProtectionFaultHandler
svn path=/trunk/; revision=53734
2011-09-18 13:11:45 +00:00
|
|
|
PFN_COUNT StackPages;
|
2012-02-27 16:10:30 +00:00
|
|
|
PMMPFN Pfn1, Pfn2;
|
2009-06-27 08:41:45 +00:00
|
|
|
ULONG i;
|
2010-05-29 18:33:50 +00:00
|
|
|
KIRQL OldIrql;
|
2018-02-04 12:30:47 +00:00
|
|
|
PSLIST_ENTRY SListEntry;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
//
|
|
|
|
// This should be the guard page, so decrement by one
|
|
|
|
//
|
|
|
|
PointerPte = MiAddressToPte(StackBase);
|
|
|
|
PointerPte--;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2012-03-04 17:56:00 +00:00
|
|
|
//
|
|
|
|
// If this is a small stack, just push the stack onto the dead stack S-LIST
|
|
|
|
//
|
|
|
|
if (!GuiStack)
|
|
|
|
{
|
|
|
|
if (ExQueryDepthSList(&MmDeadStackSListHead) < MmMaximumDeadKernelStacks)
|
|
|
|
{
|
2018-02-04 12:30:47 +00:00
|
|
|
SListEntry = ((PSLIST_ENTRY)StackBase) - 1;
|
|
|
|
InterlockedPushEntrySList(&MmDeadStackSListHead, SListEntry);
|
2012-03-04 17:56:00 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
//
|
|
|
|
// Calculate pages used
|
|
|
|
//
|
|
|
|
StackPages = BYTES_TO_PAGES(GuiStack ?
|
2015-09-03 20:04:28 +00:00
|
|
|
MmLargeStackSize : KERNEL_STACK_SIZE);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-05-29 18:33:50 +00:00
|
|
|
/* Acquire the PFN lock */
|
2017-11-21 22:33:42 +00:00
|
|
|
OldIrql = MiAcquirePfnLock();
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
//
|
|
|
|
// Loop them
|
|
|
|
//
|
|
|
|
for (i = 0; i < StackPages; i++)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Check if this is a valid PTE
|
|
|
|
//
|
|
|
|
if (PointerPte->u.Hard.Valid == 1)
|
|
|
|
{
|
2010-05-29 18:33:50 +00:00
|
|
|
/* Get the PTE's page */
|
|
|
|
PageFrameNumber = PFN_FROM_PTE(PointerPte);
|
|
|
|
Pfn1 = MiGetPfnEntry(PageFrameNumber);
|
2012-02-27 16:10:30 +00:00
|
|
|
|
2010-05-29 18:33:50 +00:00
|
|
|
/* Now get the page of the page table mapping it */
|
|
|
|
PageTableFrameNumber = Pfn1->u4.PteFrame;
|
2012-02-27 16:10:30 +00:00
|
|
|
Pfn2 = MiGetPfnEntry(PageTableFrameNumber);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-05-29 18:33:50 +00:00
|
|
|
/* Remove a shared reference, since the page is going away */
|
2012-02-27 16:10:30 +00:00
|
|
|
MiDecrementShareCount(Pfn2, PageTableFrameNumber);
|
|
|
|
|
2010-05-29 18:33:50 +00:00
|
|
|
/* Set the special pending delete marker */
|
2010-10-17 20:02:17 +00:00
|
|
|
MI_SET_PFN_DELETED(Pfn1);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-05-29 18:33:50 +00:00
|
|
|
/* And now delete the actual stack page */
|
|
|
|
MiDecrementShareCount(Pfn1, PageFrameNumber);
|
2009-06-27 08:41:45 +00:00
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
//
|
|
|
|
// Next one
|
|
|
|
//
|
|
|
|
PointerPte--;
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
//
|
|
|
|
// We should be at the guard page now
|
|
|
|
//
|
|
|
|
ASSERT(PointerPte->u.Hard.Valid == 0);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-05-29 18:33:50 +00:00
|
|
|
/* Release the PFN lock */
|
2017-11-21 22:33:42 +00:00
|
|
|
MiReleasePfnLock(OldIrql);
|
2010-05-29 18:33:50 +00:00
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
//
|
|
|
|
// Release the PTEs
|
|
|
|
//
|
|
|
|
MiReleaseSystemPtes(PointerPte, StackPages + 1, SystemPteSpace);
|
|
|
|
}
|
|
|
|
|
|
|
|
PVOID
|
|
|
|
NTAPI
|
|
|
|
MmCreateKernelStack(IN BOOLEAN GuiStack,
|
|
|
|
IN UCHAR Node)
|
|
|
|
{
|
[HAL/NDK]
- Make Vector parameter in HalEnableSystemInterrupt, HalDisableSystemInterrupt and HalBeginSystemInterrupt an ULONG, not an UCHAR
[NDK]
- 64bit fixes for HANDLE_TABLE, KPROCESS, SECTION_IMAGE_INFORMATION, MMADDRESS_LIST, MMVAD_FLAGS, MMVAD, MMVAD_LONG, MMVAD_SHORT, MEMORY_DESCRIPTOR, MEMORY_ALLOCATION_DESCRIPTOR, LdrVerifyMappedImageMatchesChecksum
- KDPC_DATA::DpcQueueDepth is signed on amd64, unsigned on x86
[NTOSKRNL]
- Fix hundreds of MSVC and amd64 warnings
- add a pragma message to FstubFixupEfiPartition, since it looks broken
- Move portable Ke constants from <arch>/cpu.c to krnlinit.c
- Fixed a bug in amd64 KiGeneralProtectionFaultHandler
svn path=/trunk/; revision=53734
2011-09-18 13:11:45 +00:00
|
|
|
PFN_COUNT StackPtes, StackPages;
|
2009-06-27 08:41:45 +00:00
|
|
|
PMMPTE PointerPte, StackPte;
|
|
|
|
PVOID BaseAddress;
|
Testers: Please test this build.
[NTOS]: Implement a MI_MAKE_HARDWARE_PTE macro for the generation of valid kernel PTEs instead of always taking the ValidKernelPte and changing its flags. This macro will take into account the protection mask (up until now ignored) and use the array previously implemented to determine the correct hardware PTE settings. Assertions are also added to validate correct usage of the macro, and later revisions will fill out NT-specific fields to help deal with transition PTEs, page faults, etc.
[NTOS]: Make the stack code the first user of this macro, for the stack PTEs. Good testing base as we create kernel stacks very often.
[NTOS]: The NT MM ABI specifies that in between the allocation of a new PTE and its initialization as a valid PFN, the PTE entry should be an invalid PTE, and should only be marked valid after the PFN has been initialized. For stack PTEs, do this -- first allocating the page, making it invalid, then initializing the PFN, and then writing the valid page.
svn path=/trunk/; revision=47571
2010-06-04 17:49:36 +00:00
|
|
|
MMPTE TempPte, InvalidPte;
|
2009-06-27 08:41:45 +00:00
|
|
|
KIRQL OldIrql;
|
|
|
|
PFN_NUMBER PageFrameIndex;
|
|
|
|
ULONG i;
|
2018-02-04 12:30:47 +00:00
|
|
|
PSLIST_ENTRY SListEntry;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
//
|
|
|
|
// Calculate pages needed
|
|
|
|
//
|
|
|
|
if (GuiStack)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// We'll allocate 64KB stack, but only commit 12K
|
|
|
|
//
|
2015-09-03 20:04:28 +00:00
|
|
|
StackPtes = BYTES_TO_PAGES(MmLargeStackSize);
|
2009-06-27 08:41:45 +00:00
|
|
|
StackPages = BYTES_TO_PAGES(KERNEL_LARGE_STACK_COMMIT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-03-04 17:56:00 +00:00
|
|
|
//
|
|
|
|
// If the dead stack S-LIST has a stack on it, use it instead of allocating
|
|
|
|
// new system PTEs for this stack
|
|
|
|
//
|
|
|
|
if (ExQueryDepthSList(&MmDeadStackSListHead))
|
|
|
|
{
|
2018-02-04 12:30:47 +00:00
|
|
|
SListEntry = InterlockedPopEntrySList(&MmDeadStackSListHead);
|
|
|
|
if (SListEntry != NULL)
|
2012-03-04 17:56:00 +00:00
|
|
|
{
|
2018-02-04 12:30:47 +00:00
|
|
|
BaseAddress = (SListEntry + 1);
|
2012-03-04 17:56:00 +00:00
|
|
|
return BaseAddress;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
//
|
|
|
|
// We'll allocate 12K and that's it
|
|
|
|
//
|
|
|
|
StackPtes = BYTES_TO_PAGES(KERNEL_STACK_SIZE);
|
|
|
|
StackPages = StackPtes;
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
//
|
|
|
|
// Reserve stack pages, plus a guard page
|
|
|
|
//
|
|
|
|
StackPte = MiReserveSystemPtes(StackPtes + 1, SystemPteSpace);
|
|
|
|
if (!StackPte) return NULL;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
//
|
|
|
|
// Get the stack address
|
|
|
|
//
|
|
|
|
BaseAddress = MiPteToAddress(StackPte + StackPtes + 1);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
//
|
|
|
|
// Select the right PTE address where we actually start committing pages
|
|
|
|
//
|
|
|
|
PointerPte = StackPte;
|
2015-09-03 20:04:28 +00:00
|
|
|
if (GuiStack) PointerPte += BYTES_TO_PAGES(MmLargeStackSize -
|
2009-06-27 08:41:45 +00:00
|
|
|
KERNEL_LARGE_STACK_COMMIT);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
Testers: Please test this build.
[NTOS]: Implement a MI_MAKE_HARDWARE_PTE macro for the generation of valid kernel PTEs instead of always taking the ValidKernelPte and changing its flags. This macro will take into account the protection mask (up until now ignored) and use the array previously implemented to determine the correct hardware PTE settings. Assertions are also added to validate correct usage of the macro, and later revisions will fill out NT-specific fields to help deal with transition PTEs, page faults, etc.
[NTOS]: Make the stack code the first user of this macro, for the stack PTEs. Good testing base as we create kernel stacks very often.
[NTOS]: The NT MM ABI specifies that in between the allocation of a new PTE and its initialization as a valid PFN, the PTE entry should be an invalid PTE, and should only be marked valid after the PFN has been initialized. For stack PTEs, do this -- first allocating the page, making it invalid, then initializing the PFN, and then writing the valid page.
svn path=/trunk/; revision=47571
2010-06-04 17:49:36 +00:00
|
|
|
|
|
|
|
/* Setup the temporary invalid PTE */
|
|
|
|
MI_MAKE_SOFTWARE_PTE(&InvalidPte, MM_NOACCESS);
|
|
|
|
|
|
|
|
/* Setup the template stack PTE */
|
2010-07-22 02:20:27 +00:00
|
|
|
MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte, PointerPte + 1, MM_READWRITE, 0);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
//
|
|
|
|
// Acquire the PFN DB lock
|
|
|
|
//
|
2017-11-21 22:33:42 +00:00
|
|
|
OldIrql = MiAcquirePfnLock();
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
//
|
|
|
|
// Loop each stack page
|
|
|
|
//
|
|
|
|
for (i = 0; i < StackPages; i++)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Next PTE
|
|
|
|
//
|
|
|
|
PointerPte++;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
Testers: Please test this build.
[NTOS]: Implement a MI_MAKE_HARDWARE_PTE macro for the generation of valid kernel PTEs instead of always taking the ValidKernelPte and changing its flags. This macro will take into account the protection mask (up until now ignored) and use the array previously implemented to determine the correct hardware PTE settings. Assertions are also added to validate correct usage of the macro, and later revisions will fill out NT-specific fields to help deal with transition PTEs, page faults, etc.
[NTOS]: Make the stack code the first user of this macro, for the stack PTEs. Good testing base as we create kernel stacks very often.
[NTOS]: The NT MM ABI specifies that in between the allocation of a new PTE and its initialization as a valid PFN, the PTE entry should be an invalid PTE, and should only be marked valid after the PFN has been initialized. For stack PTEs, do this -- first allocating the page, making it invalid, then initializing the PFN, and then writing the valid page.
svn path=/trunk/; revision=47571
2010-06-04 17:49:36 +00:00
|
|
|
/* Get a page and write the current invalid PTE */
|
2010-11-02 15:16:22 +00:00
|
|
|
MI_SET_USAGE(MI_USAGE_KERNEL_STACK);
|
|
|
|
MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName);
|
2010-09-29 01:10:28 +00:00
|
|
|
PageFrameIndex = MiRemoveAnyPage(MI_GET_NEXT_COLOR());
|
2010-06-06 18:45:46 +00:00
|
|
|
MI_WRITE_INVALID_PTE(PointerPte, InvalidPte);
|
|
|
|
|
2010-05-29 18:33:50 +00:00
|
|
|
/* Initialize the PFN entry for this page */
|
|
|
|
MiInitializePfn(PageFrameIndex, PointerPte, 1);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-05-29 18:33:50 +00:00
|
|
|
/* Write the valid PTE */
|
|
|
|
TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
|
2010-06-06 18:45:46 +00:00
|
|
|
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
2009-06-27 08:41:45 +00:00
|
|
|
}
|
2010-01-02 20:41:04 +00:00
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
//
|
|
|
|
// Release the PFN lock
|
|
|
|
//
|
2017-11-21 22:33:42 +00:00
|
|
|
MiReleasePfnLock(OldIrql);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
//
|
|
|
|
// Return the stack address
|
|
|
|
//
|
|
|
|
return BaseAddress;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
MmGrowKernelStackEx(IN PVOID StackPointer,
|
|
|
|
IN ULONG GrowSize)
|
|
|
|
{
|
|
|
|
PKTHREAD Thread = KeGetCurrentThread();
|
|
|
|
PMMPTE LimitPte, NewLimitPte, LastPte;
|
|
|
|
KIRQL OldIrql;
|
Testers: Please test this build.
[NTOS]: Implement a MI_MAKE_HARDWARE_PTE macro for the generation of valid kernel PTEs instead of always taking the ValidKernelPte and changing its flags. This macro will take into account the protection mask (up until now ignored) and use the array previously implemented to determine the correct hardware PTE settings. Assertions are also added to validate correct usage of the macro, and later revisions will fill out NT-specific fields to help deal with transition PTEs, page faults, etc.
[NTOS]: Make the stack code the first user of this macro, for the stack PTEs. Good testing base as we create kernel stacks very often.
[NTOS]: The NT MM ABI specifies that in between the allocation of a new PTE and its initialization as a valid PFN, the PTE entry should be an invalid PTE, and should only be marked valid after the PFN has been initialized. For stack PTEs, do this -- first allocating the page, making it invalid, then initializing the PFN, and then writing the valid page.
svn path=/trunk/; revision=47571
2010-06-04 17:49:36 +00:00
|
|
|
MMPTE TempPte, InvalidPte;
|
2009-06-27 08:41:45 +00:00
|
|
|
PFN_NUMBER PageFrameIndex;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
//
|
|
|
|
// Make sure the stack did not overflow
|
|
|
|
//
|
|
|
|
ASSERT(((ULONG_PTR)Thread->StackBase - (ULONG_PTR)Thread->StackLimit) <=
|
2015-09-03 20:04:28 +00:00
|
|
|
(MmLargeStackSize + PAGE_SIZE));
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
//
|
|
|
|
// Get the current stack limit
|
|
|
|
//
|
|
|
|
LimitPte = MiAddressToPte(Thread->StackLimit);
|
|
|
|
ASSERT(LimitPte->u.Hard.Valid == 1);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
//
|
|
|
|
// Get the new one and make sure this isn't a retarded request
|
|
|
|
//
|
|
|
|
NewLimitPte = MiAddressToPte((PVOID)((ULONG_PTR)StackPointer - GrowSize));
|
|
|
|
if (NewLimitPte == LimitPte) return STATUS_SUCCESS;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
//
|
|
|
|
// Now make sure you're not going past the reserved space
|
|
|
|
//
|
|
|
|
LastPte = MiAddressToPte((PVOID)((ULONG_PTR)Thread->StackBase -
|
2015-09-03 20:04:28 +00:00
|
|
|
MmLargeStackSize));
|
2009-06-27 08:41:45 +00:00
|
|
|
if (NewLimitPte < LastPte)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Sorry!
|
|
|
|
//
|
|
|
|
return STATUS_STACK_OVERFLOW;
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
//
|
|
|
|
// Calculate the number of new pages
|
|
|
|
//
|
|
|
|
LimitPte--;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
Testers: Please test this build.
[NTOS]: Implement a MI_MAKE_HARDWARE_PTE macro for the generation of valid kernel PTEs instead of always taking the ValidKernelPte and changing its flags. This macro will take into account the protection mask (up until now ignored) and use the array previously implemented to determine the correct hardware PTE settings. Assertions are also added to validate correct usage of the macro, and later revisions will fill out NT-specific fields to help deal with transition PTEs, page faults, etc.
[NTOS]: Make the stack code the first user of this macro, for the stack PTEs. Good testing base as we create kernel stacks very often.
[NTOS]: The NT MM ABI specifies that in between the allocation of a new PTE and its initialization as a valid PFN, the PTE entry should be an invalid PTE, and should only be marked valid after the PFN has been initialized. For stack PTEs, do this -- first allocating the page, making it invalid, then initializing the PFN, and then writing the valid page.
svn path=/trunk/; revision=47571
2010-06-04 17:49:36 +00:00
|
|
|
/* Setup the temporary invalid PTE */
|
|
|
|
MI_MAKE_SOFTWARE_PTE(&InvalidPte, MM_NOACCESS);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
//
|
|
|
|
// Acquire the PFN DB lock
|
|
|
|
//
|
2017-11-21 22:33:42 +00:00
|
|
|
OldIrql = MiAcquirePfnLock();
|
2010-05-12 22:47:46 +00:00
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
//
|
|
|
|
// Loop each stack page
|
|
|
|
//
|
|
|
|
while (LimitPte >= NewLimitPte)
|
|
|
|
{
|
Testers: Please test this build.
[NTOS]: Implement a MI_MAKE_HARDWARE_PTE macro for the generation of valid kernel PTEs instead of always taking the ValidKernelPte and changing its flags. This macro will take into account the protection mask (up until now ignored) and use the array previously implemented to determine the correct hardware PTE settings. Assertions are also added to validate correct usage of the macro, and later revisions will fill out NT-specific fields to help deal with transition PTEs, page faults, etc.
[NTOS]: Make the stack code the first user of this macro, for the stack PTEs. Good testing base as we create kernel stacks very often.
[NTOS]: The NT MM ABI specifies that in between the allocation of a new PTE and its initialization as a valid PFN, the PTE entry should be an invalid PTE, and should only be marked valid after the PFN has been initialized. For stack PTEs, do this -- first allocating the page, making it invalid, then initializing the PFN, and then writing the valid page.
svn path=/trunk/; revision=47571
2010-06-04 17:49:36 +00:00
|
|
|
/* Get a page and write the current invalid PTE */
|
2010-11-02 15:16:22 +00:00
|
|
|
MI_SET_USAGE(MI_USAGE_KERNEL_STACK_EXPANSION);
|
|
|
|
MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName);
|
2010-09-29 01:10:28 +00:00
|
|
|
PageFrameIndex = MiRemoveAnyPage(MI_GET_NEXT_COLOR());
|
2010-06-06 18:45:46 +00:00
|
|
|
MI_WRITE_INVALID_PTE(LimitPte, InvalidPte);
|
|
|
|
|
2010-05-29 18:33:50 +00:00
|
|
|
/* Initialize the PFN entry for this page */
|
|
|
|
MiInitializePfn(PageFrameIndex, LimitPte, 1);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
Testers: Please test this build.
[NTOS]: Implement a MI_MAKE_HARDWARE_PTE macro for the generation of valid kernel PTEs instead of always taking the ValidKernelPte and changing its flags. This macro will take into account the protection mask (up until now ignored) and use the array previously implemented to determine the correct hardware PTE settings. Assertions are also added to validate correct usage of the macro, and later revisions will fill out NT-specific fields to help deal with transition PTEs, page faults, etc.
[NTOS]: Make the stack code the first user of this macro, for the stack PTEs. Good testing base as we create kernel stacks very often.
[NTOS]: The NT MM ABI specifies that in between the allocation of a new PTE and its initialization as a valid PFN, the PTE entry should be an invalid PTE, and should only be marked valid after the PFN has been initialized. For stack PTEs, do this -- first allocating the page, making it invalid, then initializing the PFN, and then writing the valid page.
svn path=/trunk/; revision=47571
2010-06-04 17:49:36 +00:00
|
|
|
/* Setup the template stack PTE */
|
2010-07-22 02:20:27 +00:00
|
|
|
MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte, LimitPte, MM_READWRITE, PageFrameIndex);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-05-12 22:47:46 +00:00
|
|
|
/* Write the valid PTE */
|
2010-06-06 18:45:46 +00:00
|
|
|
MI_WRITE_VALID_PTE(LimitPte--, TempPte);
|
2009-06-27 08:41:45 +00:00
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
//
|
|
|
|
// Release the PFN lock
|
|
|
|
//
|
2017-11-21 22:33:42 +00:00
|
|
|
MiReleasePfnLock(OldIrql);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
//
|
|
|
|
// Set the new limit
|
|
|
|
//
|
|
|
|
Thread->StackLimit = (ULONG_PTR)MiPteToAddress(NewLimitPte);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
MmGrowKernelStack(IN PVOID StackPointer)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Call the extended version
|
|
|
|
//
|
|
|
|
return MmGrowKernelStackEx(StackPointer, KERNEL_LARGE_STACK_COMMIT);
|
|
|
|
}
|
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
MmSetMemoryPriorityProcess(IN PEPROCESS Process,
|
|
|
|
IN UCHAR MemoryPriority)
|
|
|
|
{
|
|
|
|
UCHAR OldPriority;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
|
|
|
// Check if we have less then 16MB of Physical Memory
|
|
|
|
//
|
|
|
|
if ((MmSystemSize == MmSmallSystem) &&
|
2009-10-18 13:55:44 +00:00
|
|
|
(MmNumberOfPhysicalPages < ((15 * 1024 * 1024) / PAGE_SIZE)))
|
2009-10-15 05:56:41 +00:00
|
|
|
{
|
|
|
|
//
|
|
|
|
// Always use background priority
|
|
|
|
//
|
|
|
|
MemoryPriority = MEMORY_PRIORITY_BACKGROUND;
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
|
|
|
// Save the old priority and update it
|
|
|
|
//
|
|
|
|
OldPriority = (UCHAR)Process->Vm.Flags.MemoryPriority;
|
|
|
|
Process->Vm.Flags.MemoryPriority = MemoryPriority;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
|
|
|
// Return the old priority
|
|
|
|
//
|
|
|
|
return OldPriority;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
MmCreatePeb(IN PEPROCESS Process,
|
|
|
|
IN PINITIAL_PEB InitialPeb,
|
|
|
|
OUT PPEB *BasePeb)
|
|
|
|
{
|
|
|
|
PPEB Peb = NULL;
|
|
|
|
LARGE_INTEGER SectionOffset;
|
|
|
|
SIZE_T ViewSize = 0;
|
|
|
|
PVOID TableBase = NULL;
|
|
|
|
PIMAGE_NT_HEADERS NtHeaders;
|
|
|
|
PIMAGE_LOAD_CONFIG_DIRECTORY ImageConfigData;
|
|
|
|
NTSTATUS Status;
|
|
|
|
USHORT Characteristics;
|
|
|
|
KAFFINITY ProcessAffinityMask = 0;
|
|
|
|
SectionOffset.QuadPart = (ULONGLONG)0;
|
|
|
|
*BasePeb = NULL;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
|
|
|
// Attach to Process
|
|
|
|
//
|
|
|
|
KeAttachProcess(&Process->Pcb);
|
[HAL/NDK]
- Make Vector parameter in HalEnableSystemInterrupt, HalDisableSystemInterrupt and HalBeginSystemInterrupt an ULONG, not an UCHAR
[NDK]
- 64bit fixes for HANDLE_TABLE, KPROCESS, SECTION_IMAGE_INFORMATION, MMADDRESS_LIST, MMVAD_FLAGS, MMVAD, MMVAD_LONG, MMVAD_SHORT, MEMORY_DESCRIPTOR, MEMORY_ALLOCATION_DESCRIPTOR, LdrVerifyMappedImageMatchesChecksum
- KDPC_DATA::DpcQueueDepth is signed on amd64, unsigned on x86
[NTOSKRNL]
- Fix hundreds of MSVC and amd64 warnings
- add a pragma message to FstubFixupEfiPartition, since it looks broken
- Move portable Ke constants from <arch>/cpu.c to krnlinit.c
- Fixed a bug in amd64 KiGeneralProtectionFaultHandler
svn path=/trunk/; revision=53734
2011-09-18 13:11:45 +00:00
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
|
|
|
// Map NLS Tables
|
|
|
|
//
|
2010-10-19 20:23:37 +00:00
|
|
|
Status = MmMapViewOfSection(ExpNlsSectionPointer,
|
2009-10-15 05:56:41 +00:00
|
|
|
(PEPROCESS)Process,
|
|
|
|
&TableBase,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
&SectionOffset,
|
|
|
|
&ViewSize,
|
|
|
|
ViewShare,
|
|
|
|
MEM_TOP_DOWN,
|
|
|
|
PAGE_READONLY);
|
2011-09-08 08:28:41 +00:00
|
|
|
DPRINT("NLS Tables at: %p\n", TableBase);
|
2011-08-04 13:10:57 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Cleanup and exit */
|
|
|
|
KeDetachProcess();
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Allocate the PEB
|
|
|
|
//
|
|
|
|
Status = MiCreatePebOrTeb(Process, sizeof(PEB), (PULONG_PTR)&Peb);
|
2011-09-08 08:28:41 +00:00
|
|
|
DPRINT("PEB at: %p\n", Peb);
|
2011-08-04 13:10:57 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Cleanup and exit */
|
|
|
|
KeDetachProcess();
|
|
|
|
return Status;
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
|
|
|
// Use SEH in case we can't load the PEB
|
|
|
|
//
|
|
|
|
_SEH2_TRY
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Initialize the PEB
|
|
|
|
//
|
|
|
|
RtlZeroMemory(Peb, sizeof(PEB));
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
|
|
|
// Set up data
|
|
|
|
//
|
|
|
|
Peb->ImageBaseAddress = Process->SectionBaseAddress;
|
|
|
|
Peb->InheritedAddressSpace = InitialPeb->InheritedAddressSpace;
|
|
|
|
Peb->Mutant = InitialPeb->Mutant;
|
|
|
|
Peb->ImageUsesLargePages = InitialPeb->ImageUsesLargePages;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
|
|
|
// NLS
|
|
|
|
//
|
|
|
|
Peb->AnsiCodePageData = (PCHAR)TableBase + ExpAnsiCodePageDataOffset;
|
|
|
|
Peb->OemCodePageData = (PCHAR)TableBase + ExpOemCodePageDataOffset;
|
|
|
|
Peb->UnicodeCaseTableData = (PCHAR)TableBase + ExpUnicodeCaseTableDataOffset;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
|
|
|
// Default Version Data (could get changed below)
|
|
|
|
//
|
|
|
|
Peb->OSMajorVersion = NtMajorVersion;
|
|
|
|
Peb->OSMinorVersion = NtMinorVersion;
|
|
|
|
Peb->OSBuildNumber = (USHORT)(NtBuildNumber & 0x3FFF);
|
2012-11-01 12:52:34 +00:00
|
|
|
Peb->OSPlatformId = VER_PLATFORM_WIN32_NT;
|
2009-10-15 05:56:41 +00:00
|
|
|
Peb->OSCSDVersion = (USHORT)CmNtCSDVersion;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
|
|
|
// Heap and Debug Data
|
|
|
|
//
|
|
|
|
Peb->NumberOfProcessors = KeNumberProcessors;
|
2011-08-04 13:10:57 +00:00
|
|
|
Peb->BeingDebugged = (BOOLEAN)(Process->DebugPort != NULL);
|
2009-10-15 05:56:41 +00:00
|
|
|
Peb->NtGlobalFlag = NtGlobalFlag;
|
2013-08-28 18:57:29 +00:00
|
|
|
Peb->HeapSegmentReserve = MmHeapSegmentReserve;
|
|
|
|
Peb->HeapSegmentCommit = MmHeapSegmentCommit;
|
|
|
|
Peb->HeapDeCommitTotalFreeThreshold = MmHeapDeCommitTotalFreeThreshold;
|
|
|
|
Peb->HeapDeCommitFreeBlockThreshold = MmHeapDeCommitFreeBlockThreshold;
|
2013-01-14 13:55:12 +00:00
|
|
|
Peb->CriticalSectionTimeout = MmCriticalSectionTimeout;
|
2013-08-28 18:57:29 +00:00
|
|
|
Peb->MinimumStackCommit = MmMinimumStackCommitInBytes;
|
2009-10-15 05:56:41 +00:00
|
|
|
Peb->MaximumNumberOfHeaps = (PAGE_SIZE - sizeof(PEB)) / sizeof(PVOID);
|
|
|
|
Peb->ProcessHeaps = (PVOID*)(Peb + 1);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
|
|
|
// Session ID
|
|
|
|
//
|
2013-09-21 23:21:24 +00:00
|
|
|
if (Process->Session) Peb->SessionId = MmGetSessionId(Process);
|
2009-10-15 05:56:41 +00:00
|
|
|
}
|
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Fail
|
|
|
|
//
|
|
|
|
KeDetachProcess();
|
|
|
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
|
|
|
}
|
|
|
|
_SEH2_END;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
|
|
|
// Use SEH in case we can't load the image
|
|
|
|
//
|
|
|
|
_SEH2_TRY
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Get NT Headers
|
|
|
|
//
|
|
|
|
NtHeaders = RtlImageNtHeader(Peb->ImageBaseAddress);
|
|
|
|
Characteristics = NtHeaders->FileHeader.Characteristics;
|
|
|
|
}
|
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Fail
|
|
|
|
//
|
|
|
|
KeDetachProcess();
|
|
|
|
_SEH2_YIELD(return STATUS_INVALID_IMAGE_PROTECT);
|
|
|
|
}
|
|
|
|
_SEH2_END;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
|
|
|
// Parse the headers
|
|
|
|
//
|
|
|
|
if (NtHeaders)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Use SEH in case we can't load the headers
|
|
|
|
//
|
|
|
|
_SEH2_TRY
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Get the Image Config Data too
|
|
|
|
//
|
|
|
|
ImageConfigData = RtlImageDirectoryEntryToData(Peb->ImageBaseAddress,
|
|
|
|
TRUE,
|
|
|
|
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
|
2010-07-16 00:34:26 +00:00
|
|
|
(PULONG)&ViewSize);
|
2009-10-15 05:56:41 +00:00
|
|
|
if (ImageConfigData)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Probe it
|
|
|
|
//
|
|
|
|
ProbeForRead(ImageConfigData,
|
|
|
|
sizeof(IMAGE_LOAD_CONFIG_DIRECTORY),
|
|
|
|
sizeof(ULONG));
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
|
|
|
// Write subsystem data
|
|
|
|
//
|
2009-12-10 00:35:12 +00:00
|
|
|
Peb->ImageSubsystem = NtHeaders->OptionalHeader.Subsystem;
|
|
|
|
Peb->ImageSubsystemMajorVersion = NtHeaders->OptionalHeader.MajorSubsystemVersion;
|
|
|
|
Peb->ImageSubsystemMinorVersion = NtHeaders->OptionalHeader.MinorSubsystemVersion;
|
2009-10-15 05:56:41 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Check for version data
|
|
|
|
//
|
|
|
|
if (NtHeaders->OptionalHeader.Win32VersionValue)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Extract values and write them
|
|
|
|
//
|
|
|
|
Peb->OSMajorVersion = NtHeaders->OptionalHeader.Win32VersionValue & 0xFF;
|
|
|
|
Peb->OSMinorVersion = (NtHeaders->OptionalHeader.Win32VersionValue >> 8) & 0xFF;
|
|
|
|
Peb->OSBuildNumber = (NtHeaders->OptionalHeader.Win32VersionValue >> 16) & 0x3FFF;
|
|
|
|
Peb->OSPlatformId = (NtHeaders->OptionalHeader.Win32VersionValue >> 30) ^ 2;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2011-08-04 13:10:57 +00:00
|
|
|
/* Process CSD version override */
|
|
|
|
if ((ImageConfigData) && (ImageConfigData->CSDVersion))
|
2009-10-15 05:56:41 +00:00
|
|
|
{
|
2011-08-04 13:10:57 +00:00
|
|
|
/* Take the value from the image configuration directory */
|
2009-10-15 05:56:41 +00:00
|
|
|
Peb->OSCSDVersion = ImageConfigData->CSDVersion;
|
|
|
|
}
|
2011-08-04 13:10:57 +00:00
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2011-08-04 13:10:57 +00:00
|
|
|
/* Process optional process affinity mask override */
|
|
|
|
if ((ImageConfigData) && (ImageConfigData->ProcessAffinityMask))
|
|
|
|
{
|
|
|
|
/* Take the value from the image configuration directory */
|
|
|
|
ProcessAffinityMask = ImageConfigData->ProcessAffinityMask;
|
2009-10-15 05:56:41 +00:00
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
|
|
|
// Check if this is a UP image
|
|
|
|
if (Characteristics & IMAGE_FILE_UP_SYSTEM_ONLY)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Force it to use CPU 0
|
|
|
|
//
|
2011-08-04 13:10:57 +00:00
|
|
|
/* FIXME: this should use the MmRotatingUniprocessorNumber */
|
2009-10-15 05:56:41 +00:00
|
|
|
Peb->ImageProcessAffinityMask = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Whatever was configured
|
|
|
|
//
|
|
|
|
Peb->ImageProcessAffinityMask = ProcessAffinityMask;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Fail
|
|
|
|
//
|
|
|
|
KeDetachProcess();
|
|
|
|
_SEH2_YIELD(return STATUS_INVALID_IMAGE_PROTECT);
|
|
|
|
}
|
|
|
|
_SEH2_END;
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
|
|
|
// Detach from the Process
|
|
|
|
//
|
|
|
|
KeDetachProcess();
|
|
|
|
*BasePeb = Peb;
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
MmCreateTeb(IN PEPROCESS Process,
|
|
|
|
IN PCLIENT_ID ClientId,
|
|
|
|
IN PINITIAL_TEB InitialTeb,
|
|
|
|
OUT PTEB *BaseTeb)
|
|
|
|
{
|
|
|
|
PTEB Teb;
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
*BaseTeb = NULL;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
|
|
|
// Attach to Target
|
|
|
|
//
|
|
|
|
KeAttachProcess(&Process->Pcb);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
|
|
|
// Allocate the TEB
|
|
|
|
//
|
2010-07-22 19:08:45 +00:00
|
|
|
Status = MiCreatePebOrTeb(Process, sizeof(TEB), (PULONG_PTR)&Teb);
|
2016-07-04 22:23:07 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Cleanup and exit */
|
|
|
|
KeDetachProcess();
|
|
|
|
return Status;
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
|
|
|
// Use SEH in case we can't load the TEB
|
|
|
|
//
|
|
|
|
_SEH2_TRY
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Initialize the PEB
|
|
|
|
//
|
|
|
|
RtlZeroMemory(Teb, sizeof(TEB));
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
|
|
|
// Set TIB Data
|
|
|
|
//
|
2012-02-06 00:24:31 +00:00
|
|
|
#ifdef _M_AMD64
|
|
|
|
Teb->NtTib.ExceptionList = NULL;
|
|
|
|
#else
|
2009-12-10 00:35:12 +00:00
|
|
|
Teb->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
|
2012-02-06 00:24:31 +00:00
|
|
|
#endif
|
2009-12-10 00:35:12 +00:00
|
|
|
Teb->NtTib.Self = (PNT_TIB)Teb;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
|
|
|
// Identify this as an OS/2 V3.0 ("Cruiser") TIB
|
|
|
|
//
|
2009-12-10 00:35:12 +00:00
|
|
|
Teb->NtTib.Version = 30 << 8;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
|
|
|
// Set TEB Data
|
|
|
|
//
|
|
|
|
Teb->ClientId = *ClientId;
|
|
|
|
Teb->RealClientId = *ClientId;
|
|
|
|
Teb->ProcessEnvironmentBlock = Process->Peb;
|
|
|
|
Teb->CurrentLocale = PsDefaultThreadLocaleId;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
|
|
|
// Check if we have a grandparent TEB
|
|
|
|
//
|
|
|
|
if ((InitialTeb->PreviousStackBase == NULL) &&
|
|
|
|
(InitialTeb->PreviousStackLimit == NULL))
|
|
|
|
{
|
|
|
|
//
|
2009-10-15 16:47:26 +00:00
|
|
|
// Use initial TEB values
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
2009-12-10 00:35:12 +00:00
|
|
|
Teb->NtTib.StackBase = InitialTeb->StackBase;
|
|
|
|
Teb->NtTib.StackLimit = InitialTeb->StackLimit;
|
2009-10-15 16:47:26 +00:00
|
|
|
Teb->DeallocationStack = InitialTeb->AllocatedStackBase;
|
2009-10-15 05:56:41 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//
|
2009-10-15 16:47:26 +00:00
|
|
|
// Use grandparent TEB values
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
2009-12-10 00:35:12 +00:00
|
|
|
Teb->NtTib.StackBase = InitialTeb->PreviousStackBase;
|
|
|
|
Teb->NtTib.StackLimit = InitialTeb->PreviousStackLimit;
|
2009-10-15 05:56:41 +00:00
|
|
|
}
|
2009-10-15 16:47:26 +00:00
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
//
|
|
|
|
// Initialize the static unicode string
|
|
|
|
//
|
|
|
|
Teb->StaticUnicodeString.MaximumLength = sizeof(Teb->StaticUnicodeBuffer);
|
|
|
|
Teb->StaticUnicodeString.Buffer = Teb->StaticUnicodeBuffer;
|
|
|
|
}
|
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Get error code
|
|
|
|
//
|
|
|
|
Status = _SEH2_GetExceptionCode();
|
|
|
|
}
|
|
|
|
_SEH2_END;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Return
|
|
|
|
//
|
|
|
|
KeDetachProcess();
|
|
|
|
*BaseTeb = Teb;
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2020-03-07 18:35:15 +00:00
|
|
|
#ifdef _M_AMD64
|
|
|
|
static
|
|
|
|
NTSTATUS
|
2022-05-12 06:11:52 +00:00
|
|
|
MiInsertSharedUserPageVad(
|
|
|
|
_In_ PEPROCESS Process)
|
2020-03-07 18:35:15 +00:00
|
|
|
{
|
|
|
|
PMMVAD_LONG Vad;
|
|
|
|
ULONG_PTR BaseAddress;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
2022-06-29 08:49:05 +00:00
|
|
|
if (Process->QuotaBlock != NULL)
|
|
|
|
{
|
|
|
|
Status = PsChargeProcessNonPagedPoolQuota(Process, sizeof(MMVAD_LONG));
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Ran out of quota.\n");
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-07 18:35:15 +00:00
|
|
|
/* Allocate a VAD */
|
|
|
|
Vad = ExAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD_LONG), 'ldaV');
|
|
|
|
if (Vad == NULL)
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to allocate VAD for shared user page\n");
|
2022-06-29 08:49:05 +00:00
|
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
goto FailPath;
|
2020-03-07 18:35:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Setup the primary flags with the size, and make it private, RO */
|
|
|
|
Vad->u.LongFlags = 0;
|
|
|
|
Vad->u.VadFlags.CommitCharge = 0;
|
|
|
|
Vad->u.VadFlags.NoChange = TRUE;
|
|
|
|
Vad->u.VadFlags.VadType = VadNone;
|
|
|
|
Vad->u.VadFlags.MemCommit = FALSE;
|
|
|
|
Vad->u.VadFlags.Protection = MM_READONLY;
|
|
|
|
Vad->u.VadFlags.PrivateMemory = TRUE;
|
|
|
|
Vad->u1.Parent = NULL;
|
|
|
|
|
|
|
|
/* Setup the secondary flags to make it a secured, readonly, long VAD */
|
|
|
|
Vad->u2.LongFlags2 = 0;
|
|
|
|
Vad->u2.VadFlags2.OneSecured = TRUE;
|
|
|
|
Vad->u2.VadFlags2.LongVad = TRUE;
|
|
|
|
Vad->u2.VadFlags2.ReadOnly = FALSE;
|
|
|
|
|
|
|
|
Vad->ControlArea = NULL; // For Memory-Area hack
|
|
|
|
Vad->FirstPrototypePte = NULL;
|
|
|
|
|
|
|
|
/* Insert it into the process VAD table */
|
|
|
|
BaseAddress = MM_SHARED_USER_DATA_VA;
|
|
|
|
Status = MiInsertVadEx((PMMVAD)Vad,
|
|
|
|
&BaseAddress,
|
|
|
|
PAGE_SIZE,
|
|
|
|
(ULONG_PTR)MM_HIGHEST_VAD_ADDRESS,
|
|
|
|
PAGE_SIZE,
|
|
|
|
MEM_TOP_DOWN);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to insert shared user VAD\n");
|
|
|
|
ExFreePoolWithTag(Vad, 'ldaV');
|
2022-06-29 08:49:05 +00:00
|
|
|
goto FailPath;
|
2020-03-07 18:35:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Success */
|
|
|
|
return STATUS_SUCCESS;
|
2022-06-29 08:49:05 +00:00
|
|
|
|
|
|
|
FailPath:
|
|
|
|
if (Process->QuotaBlock != NULL)
|
|
|
|
PsReturnProcessNonPagedPoolQuota(Process, sizeof(MMVAD_LONG));
|
|
|
|
|
|
|
|
return Status;
|
2020-03-07 18:35:15 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-07-24 15:01:05 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
MmInitializeProcessAddressSpace(IN PEPROCESS Process,
|
|
|
|
IN PEPROCESS ProcessClone OPTIONAL,
|
|
|
|
IN PVOID Section OPTIONAL,
|
|
|
|
IN OUT PULONG Flags,
|
|
|
|
IN POBJECT_NAME_INFORMATION *AuditName OPTIONAL)
|
|
|
|
{
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
SIZE_T ViewSize = 0;
|
|
|
|
PVOID ImageBase = 0;
|
|
|
|
PMMPTE PointerPte;
|
|
|
|
KIRQL OldIrql;
|
|
|
|
PMMPDE PointerPde;
|
2021-04-12 09:36:19 +00:00
|
|
|
PMMPFN Pfn;
|
2010-07-24 15:01:05 +00:00
|
|
|
PFN_NUMBER PageFrameNumber;
|
|
|
|
UNICODE_STRING FileName;
|
|
|
|
PWCHAR Source;
|
|
|
|
PCHAR Destination;
|
|
|
|
USHORT Length = 0;
|
2021-05-19 20:20:38 +00:00
|
|
|
|
2020-10-26 10:12:04 +00:00
|
|
|
#if (_MI_PAGING_LEVELS >= 3)
|
|
|
|
PMMPPE PointerPpe;
|
|
|
|
#endif
|
|
|
|
#if (_MI_PAGING_LEVELS == 4)
|
|
|
|
PMMPXE PointerPxe;
|
|
|
|
#endif
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-07-24 15:01:05 +00:00
|
|
|
/* We should have a PDE */
|
|
|
|
ASSERT(Process->Pcb.DirectoryTableBase[0] != 0);
|
|
|
|
ASSERT(Process->PdeUpdateNeeded == FALSE);
|
|
|
|
|
|
|
|
/* Attach to the process */
|
|
|
|
KeAttachProcess(&Process->Pcb);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-07-24 15:01:05 +00:00
|
|
|
/* The address space should now been in phase 1 or 0 */
|
|
|
|
ASSERT(Process->AddressSpaceInitialized <= 1);
|
|
|
|
Process->AddressSpaceInitialized = 2;
|
|
|
|
|
|
|
|
/* Initialize the Addresss Space lock */
|
|
|
|
KeInitializeGuardedMutex(&Process->AddressCreationLock);
|
|
|
|
Process->Vm.WorkingSetExpansionLinks.Flink = NULL;
|
|
|
|
|
|
|
|
/* Initialize AVL tree */
|
|
|
|
ASSERT(Process->VadRoot.NumberGenericTableElements == 0);
|
|
|
|
Process->VadRoot.BalancedRoot.u1.Parent = &Process->VadRoot.BalancedRoot;
|
|
|
|
|
2021-04-12 09:36:19 +00:00
|
|
|
/* Lock our working set */
|
|
|
|
MiLockProcessWorkingSet(Process, PsGetCurrentThread());
|
2020-10-26 10:12:04 +00:00
|
|
|
|
2010-07-24 15:01:05 +00:00
|
|
|
/* Lock PFN database */
|
2017-11-21 22:33:42 +00:00
|
|
|
OldIrql = MiAcquirePfnLock();
|
2010-07-24 15:01:05 +00:00
|
|
|
|
|
|
|
/* Setup the PFN for the PDE base of this process */
|
2020-10-26 10:12:04 +00:00
|
|
|
#if (_MI_PAGING_LEVELS == 4)
|
2012-02-04 23:08:20 +00:00
|
|
|
PointerPte = MiAddressToPte(PXE_BASE);
|
2020-10-26 10:12:04 +00:00
|
|
|
#elif (_MI_PAGING_LEVELS == 3)
|
|
|
|
PointerPte = MiAddressToPte(PPE_BASE);
|
2012-02-04 23:08:20 +00:00
|
|
|
#else
|
2010-07-24 15:01:05 +00:00
|
|
|
PointerPte = MiAddressToPte(PDE_BASE);
|
2012-02-04 23:08:20 +00:00
|
|
|
#endif
|
2010-07-24 15:01:05 +00:00
|
|
|
PageFrameNumber = PFN_FROM_PTE(PointerPte);
|
2012-02-04 23:08:20 +00:00
|
|
|
ASSERT(Process->Pcb.DirectoryTableBase[0] == PageFrameNumber * PAGE_SIZE);
|
2010-07-24 15:30:24 +00:00
|
|
|
MiInitializePfn(PageFrameNumber, PointerPte, TRUE);
|
2010-07-24 15:01:05 +00:00
|
|
|
|
|
|
|
/* Do the same for hyperspace */
|
2021-04-12 09:36:19 +00:00
|
|
|
PointerPde = MiAddressToPde(HYPER_SPACE);
|
2010-07-24 15:01:05 +00:00
|
|
|
PageFrameNumber = PFN_FROM_PTE(PointerPde);
|
2010-11-24 15:21:45 +00:00
|
|
|
MiInitializePfn(PageFrameNumber, (PMMPTE)PointerPde, TRUE);
|
2021-04-01 13:54:19 +00:00
|
|
|
#if (_MI_PAGING_LEVELS == 2)
|
|
|
|
ASSERT(Process->Pcb.DirectoryTableBase[1] == PageFrameNumber * PAGE_SIZE);
|
|
|
|
#endif
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2020-10-26 10:12:04 +00:00
|
|
|
#if (_MI_PAGING_LEVELS >= 3)
|
|
|
|
PointerPpe = MiAddressToPpe((PVOID)HYPER_SPACE);
|
|
|
|
PageFrameNumber = PFN_FROM_PTE(PointerPpe);
|
|
|
|
MiInitializePfn(PageFrameNumber, PointerPpe, TRUE);
|
2021-04-01 13:54:19 +00:00
|
|
|
#if (_MI_PAGING_LEVELS == 3)
|
|
|
|
ASSERT(Process->Pcb.DirectoryTableBase[1] == PageFrameNumber * PAGE_SIZE);
|
|
|
|
#endif
|
2020-10-26 10:12:04 +00:00
|
|
|
#endif
|
|
|
|
#if (_MI_PAGING_LEVELS == 4)
|
|
|
|
PointerPxe = MiAddressToPxe((PVOID)HYPER_SPACE);
|
|
|
|
PageFrameNumber = PFN_FROM_PTE(PointerPxe);
|
|
|
|
MiInitializePfn(PageFrameNumber, PointerPxe, TRUE);
|
2021-04-01 13:54:19 +00:00
|
|
|
ASSERT(Process->Pcb.DirectoryTableBase[1] == PageFrameNumber * PAGE_SIZE);
|
2020-10-26 10:12:04 +00:00
|
|
|
#endif
|
|
|
|
|
2021-04-12 09:36:19 +00:00
|
|
|
/* Do the same for the Working set list */
|
|
|
|
PointerPte = MiAddressToPte(MmWorkingSetList);
|
2010-11-08 12:35:50 +00:00
|
|
|
PageFrameNumber = PFN_FROM_PTE(PointerPte);
|
|
|
|
MiInitializePfn(PageFrameNumber, PointerPte, TRUE);
|
2021-04-12 09:36:19 +00:00
|
|
|
|
2021-05-11 10:03:52 +00:00
|
|
|
/* All our pages are now active & valid. Release the lock. */
|
|
|
|
MiReleasePfnLock(OldIrql);
|
|
|
|
|
2021-04-12 09:36:19 +00:00
|
|
|
/* This should be in hyper space, but not in the mapping range */
|
|
|
|
Process->Vm.VmWorkingSetList = MmWorkingSetList;
|
|
|
|
ASSERT(((ULONG_PTR)MmWorkingSetList >= MI_MAPPING_RANGE_END) && ((ULONG_PTR)MmWorkingSetList <= HYPER_SPACE_END));
|
2010-11-08 12:35:50 +00:00
|
|
|
|
|
|
|
/* Now initialize the working set list */
|
2021-04-12 09:36:19 +00:00
|
|
|
MiInitializeWorkingSetList(&Process->Vm);
|
|
|
|
|
|
|
|
/* The rule is that the owner process is always in the FLINK of the PDE's PFN entry */
|
|
|
|
Pfn = MiGetPfnEntry(Process->Pcb.DirectoryTableBase[0] >> PAGE_SHIFT);
|
|
|
|
ASSERT(Pfn->u4.PteFrame == MiGetPfnEntryIndex(Pfn));
|
|
|
|
ASSERT(Pfn->u1.WsIndex == 0);
|
|
|
|
Pfn->u1.Event = (PKEVENT)Process;
|
2010-11-08 12:35:50 +00:00
|
|
|
|
|
|
|
/* Sanity check */
|
|
|
|
ASSERT(Process->PhysicalVadRoot == NULL);
|
2010-07-24 15:01:05 +00:00
|
|
|
|
2021-04-12 09:36:19 +00:00
|
|
|
/* Release the process working set */
|
|
|
|
MiUnlockProcessWorkingSet(Process, PsGetCurrentThread());
|
2020-10-26 10:12:04 +00:00
|
|
|
|
2020-03-07 18:35:15 +00:00
|
|
|
#ifdef _M_AMD64
|
|
|
|
/* On x64 we need a VAD for the shared user page */
|
2022-05-12 06:11:52 +00:00
|
|
|
Status = MiInsertSharedUserPageVad(Process);
|
2020-03-07 18:35:15 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("MiCreateSharedUserPageVad() failed: 0x%lx\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-07-24 15:01:05 +00:00
|
|
|
/* Check if there's a Section Object */
|
2020-10-23 14:39:15 +00:00
|
|
|
if (Section)
|
2010-07-24 15:01:05 +00:00
|
|
|
{
|
|
|
|
/* Determine the image file name and save it to EPROCESS */
|
2020-10-23 14:39:15 +00:00
|
|
|
PFILE_OBJECT FileObject = MmGetFileObjectForSection(Section);
|
|
|
|
FileName = FileObject->FileName;
|
2010-07-24 15:01:05 +00:00
|
|
|
Source = (PWCHAR)((PCHAR)FileName.Buffer + FileName.Length);
|
|
|
|
if (FileName.Buffer)
|
|
|
|
{
|
|
|
|
/* Loop the file name*/
|
|
|
|
while (Source > FileName.Buffer)
|
|
|
|
{
|
|
|
|
/* Make sure this isn't a backslash */
|
|
|
|
if (*--Source == OBJ_NAME_PATH_SEPARATOR)
|
|
|
|
{
|
|
|
|
/* If so, stop it here */
|
|
|
|
Source++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Otherwise, keep going */
|
|
|
|
Length++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Copy the to the process and truncate it to 15 characters if necessary */
|
|
|
|
Destination = Process->ImageFileName;
|
|
|
|
Length = min(Length, sizeof(Process->ImageFileName) - 1);
|
|
|
|
while (Length--) *Destination++ = (UCHAR)*Source++;
|
|
|
|
*Destination = ANSI_NULL;
|
|
|
|
|
|
|
|
/* Check if caller wants an audit name */
|
|
|
|
if (AuditName)
|
|
|
|
{
|
|
|
|
/* Setup the audit name */
|
2020-10-23 14:39:15 +00:00
|
|
|
Status = SeInitializeProcessAuditName(FileObject, FALSE, AuditName);
|
2010-07-24 15:01:05 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Fail */
|
|
|
|
KeDetachProcess();
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Map the section */
|
|
|
|
Status = MmMapViewOfSection(Section,
|
|
|
|
Process,
|
|
|
|
(PVOID*)&ImageBase,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
&ViewSize,
|
|
|
|
0,
|
|
|
|
MEM_COMMIT,
|
|
|
|
PAGE_READWRITE);
|
|
|
|
|
|
|
|
/* Save the pointer */
|
|
|
|
Process->SectionBaseAddress = ImageBase;
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-07-24 15:01:05 +00:00
|
|
|
/* Be nice and detach */
|
|
|
|
KeDetachProcess();
|
|
|
|
|
|
|
|
/* Return status to caller */
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
2010-07-24 15:01:05 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
MmInitializeHandBuiltProcess(IN PEPROCESS Process,
|
|
|
|
IN PULONG_PTR DirectoryTableBase)
|
|
|
|
{
|
|
|
|
/* Share the directory base with the idle process */
|
|
|
|
DirectoryTableBase[0] = PsGetCurrentProcess()->Pcb.DirectoryTableBase[0];
|
|
|
|
DirectoryTableBase[1] = PsGetCurrentProcess()->Pcb.DirectoryTableBase[1];
|
|
|
|
|
|
|
|
/* Initialize the Addresss Space */
|
|
|
|
KeInitializeGuardedMutex(&Process->AddressCreationLock);
|
|
|
|
KeInitializeSpinLock(&Process->HyperSpaceLock);
|
|
|
|
Process->Vm.WorkingSetExpansionLinks.Flink = NULL;
|
|
|
|
ASSERT(Process->VadRoot.NumberGenericTableElements == 0);
|
|
|
|
Process->VadRoot.BalancedRoot.u1.Parent = &Process->VadRoot.BalancedRoot;
|
|
|
|
|
2012-03-04 20:30:42 +00:00
|
|
|
/* Use idle process Working set */
|
|
|
|
Process->Vm.VmWorkingSetList = PsGetCurrentProcess()->Vm.VmWorkingSetList;
|
2021-07-28 14:25:29 +00:00
|
|
|
Process->WorkingSetPage = PsGetCurrentProcess()->WorkingSetPage;
|
2012-03-28 19:41:40 +00:00
|
|
|
|
2010-07-24 15:01:05 +00:00
|
|
|
/* Done */
|
|
|
|
Process->HasAddressSpace = TRUE;//??
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2020-10-06 19:44:01 +00:00
|
|
|
CODE_SEG("INIT")
|
2010-07-24 15:01:05 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
MmInitializeHandBuiltProcess2(IN PEPROCESS Process)
|
|
|
|
{
|
2010-12-26 15:23:03 +00:00
|
|
|
/* Lock the VAD, ARM3-owned ranges away */
|
2010-07-24 15:01:05 +00:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2010-07-24 15:30:24 +00:00
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
MmCreateProcessAddressSpace(IN ULONG MinWs,
|
|
|
|
IN PEPROCESS Process,
|
|
|
|
OUT PULONG_PTR DirectoryTableBase)
|
|
|
|
{
|
|
|
|
KIRQL OldIrql;
|
2021-04-01 13:54:19 +00:00
|
|
|
PFN_NUMBER TableBaseIndex, HyperIndex, WsListIndex;
|
2010-09-29 01:10:28 +00:00
|
|
|
ULONG Color;
|
2021-04-01 13:54:19 +00:00
|
|
|
|
|
|
|
/* Make sure we don't already have a page directory setup */
|
|
|
|
ASSERT(Process->Pcb.DirectoryTableBase[0] == 0);
|
|
|
|
ASSERT(Process->Pcb.DirectoryTableBase[1] == 0);
|
|
|
|
ASSERT(Process->WorkingSetPage == 0);
|
2010-07-24 15:30:24 +00:00
|
|
|
|
2010-09-29 01:10:28 +00:00
|
|
|
/* Choose a process color */
|
[HAL/NDK]
- Make Vector parameter in HalEnableSystemInterrupt, HalDisableSystemInterrupt and HalBeginSystemInterrupt an ULONG, not an UCHAR
[NDK]
- 64bit fixes for HANDLE_TABLE, KPROCESS, SECTION_IMAGE_INFORMATION, MMADDRESS_LIST, MMVAD_FLAGS, MMVAD, MMVAD_LONG, MMVAD_SHORT, MEMORY_DESCRIPTOR, MEMORY_ALLOCATION_DESCRIPTOR, LdrVerifyMappedImageMatchesChecksum
- KDPC_DATA::DpcQueueDepth is signed on amd64, unsigned on x86
[NTOSKRNL]
- Fix hundreds of MSVC and amd64 warnings
- add a pragma message to FstubFixupEfiPartition, since it looks broken
- Move portable Ke constants from <arch>/cpu.c to krnlinit.c
- Fixed a bug in amd64 KiGeneralProtectionFaultHandler
svn path=/trunk/; revision=53734
2011-09-18 13:11:45 +00:00
|
|
|
Process->NextPageColor = (USHORT)RtlRandom(&MmProcessColorSeed);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-07-24 15:30:24 +00:00
|
|
|
/* Setup the hyperspace lock */
|
|
|
|
KeInitializeSpinLock(&Process->HyperSpaceLock);
|
|
|
|
|
|
|
|
/* Lock PFN database */
|
2017-11-21 22:33:42 +00:00
|
|
|
OldIrql = MiAcquirePfnLock();
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2021-04-01 13:54:19 +00:00
|
|
|
/*
|
|
|
|
* Get a page for the table base, one for hyper space & one for the working set list.
|
|
|
|
* The PFNs for these pages will be initialized in MmInitializeProcessAddressSpace,
|
|
|
|
* when we are already attached to the process.
|
|
|
|
* The other pages (if any) are allocated in the arch-specific part.
|
|
|
|
*/
|
2010-09-29 01:10:28 +00:00
|
|
|
Color = MI_GET_NEXT_PROCESS_COLOR(Process);
|
2010-11-02 15:16:22 +00:00
|
|
|
MI_SET_USAGE(MI_USAGE_PAGE_DIRECTORY);
|
2021-04-01 13:54:19 +00:00
|
|
|
TableBaseIndex = MiRemoveZeroPageSafe(Color);
|
|
|
|
if (!TableBaseIndex)
|
2010-09-29 01:10:28 +00:00
|
|
|
{
|
|
|
|
/* No zero pages, grab a free one */
|
2021-04-01 13:54:19 +00:00
|
|
|
TableBaseIndex = MiRemoveAnyPage(Color);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-09-29 01:10:28 +00:00
|
|
|
/* Zero it outside the PFN lock */
|
2017-11-21 22:33:42 +00:00
|
|
|
MiReleasePfnLock(OldIrql);
|
2021-04-01 13:54:19 +00:00
|
|
|
MiZeroPhysicalPage(TableBaseIndex);
|
2017-11-21 22:33:42 +00:00
|
|
|
OldIrql = MiAcquirePfnLock();
|
2010-09-29 01:10:28 +00:00
|
|
|
}
|
2010-11-02 15:16:22 +00:00
|
|
|
MI_SET_USAGE(MI_USAGE_PAGE_DIRECTORY);
|
2010-09-29 01:10:28 +00:00
|
|
|
Color = MI_GET_NEXT_PROCESS_COLOR(Process);
|
|
|
|
HyperIndex = MiRemoveZeroPageSafe(Color);
|
|
|
|
if (!HyperIndex)
|
|
|
|
{
|
|
|
|
/* No zero pages, grab a free one */
|
|
|
|
HyperIndex = MiRemoveAnyPage(Color);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-09-29 01:10:28 +00:00
|
|
|
/* Zero it outside the PFN lock */
|
2017-11-21 22:33:42 +00:00
|
|
|
MiReleasePfnLock(OldIrql);
|
2010-09-29 01:10:28 +00:00
|
|
|
MiZeroPhysicalPage(HyperIndex);
|
2017-11-21 22:33:42 +00:00
|
|
|
OldIrql = MiAcquirePfnLock();
|
2010-11-08 12:35:50 +00:00
|
|
|
}
|
|
|
|
MI_SET_USAGE(MI_USAGE_PAGE_TABLE);
|
|
|
|
Color = MI_GET_NEXT_PROCESS_COLOR(Process);
|
|
|
|
WsListIndex = MiRemoveZeroPageSafe(Color);
|
|
|
|
if (!WsListIndex)
|
|
|
|
{
|
|
|
|
/* No zero pages, grab a free one */
|
|
|
|
WsListIndex = MiRemoveAnyPage(Color);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-11-08 12:35:50 +00:00
|
|
|
/* Zero it outside the PFN lock */
|
2017-11-21 22:33:42 +00:00
|
|
|
MiReleasePfnLock(OldIrql);
|
2010-11-08 12:35:50 +00:00
|
|
|
MiZeroPhysicalPage(WsListIndex);
|
2010-09-29 01:10:28 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Release the PFN lock */
|
2017-11-21 22:33:42 +00:00
|
|
|
MiReleasePfnLock(OldIrql);
|
2010-09-29 01:10:28 +00:00
|
|
|
}
|
2010-07-24 15:30:24 +00:00
|
|
|
|
|
|
|
/* Set the base directory pointers */
|
2010-11-08 12:35:50 +00:00
|
|
|
Process->WorkingSetPage = WsListIndex;
|
2021-04-01 13:54:19 +00:00
|
|
|
DirectoryTableBase[0] = TableBaseIndex << PAGE_SHIFT;
|
2010-07-24 15:30:24 +00:00
|
|
|
DirectoryTableBase[1] = HyperIndex << PAGE_SHIFT;
|
|
|
|
|
2021-04-01 13:54:19 +00:00
|
|
|
/* Perform the arch-specific parts */
|
|
|
|
if (!MiArchCreateProcessAddressSpace(Process, DirectoryTableBase))
|
|
|
|
{
|
|
|
|
OldIrql = MiAcquirePfnLock();
|
|
|
|
MiInsertPageInFreeList(WsListIndex);
|
|
|
|
MiInsertPageInFreeList(HyperIndex);
|
|
|
|
MiInsertPageInFreeList(TableBaseIndex);
|
|
|
|
MiReleasePfnLock(OldIrql);
|
|
|
|
Process->WorkingSetPage = 0;
|
|
|
|
DirectoryTableBase[0] = 0;
|
|
|
|
DirectoryTableBase[1] = 0;
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-07-24 15:30:24 +00:00
|
|
|
|
2021-04-01 13:54:19 +00:00
|
|
|
/* Switch to phase 1 initialization */
|
|
|
|
ASSERT(Process->AddressSpaceInitialized == 0);
|
|
|
|
Process->AddressSpaceInitialized = 1;
|
2012-08-01 07:54:37 +00:00
|
|
|
|
|
|
|
/* Add the process to the session */
|
|
|
|
MiSessionAddProcess(Process);
|
2010-07-24 15:30:24 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-07-24 16:12:39 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MmCleanProcessAddressSpace(IN PEPROCESS Process)
|
|
|
|
{
|
|
|
|
PMMVAD Vad;
|
|
|
|
PMM_AVL_TABLE VadTree;
|
|
|
|
PETHREAD Thread = PsGetCurrentThread();
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-11-02 14:41:03 +00:00
|
|
|
/* Only support this */
|
|
|
|
ASSERT(Process->AddressSpaceInitialized == 2);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2012-08-01 07:54:37 +00:00
|
|
|
/* Remove from the session */
|
|
|
|
MiSessionRemoveProcess();
|
|
|
|
|
2010-07-24 16:12:39 +00:00
|
|
|
/* Lock the process address space from changes */
|
|
|
|
MmLockAddressSpace(&Process->Vm);
|
2012-09-03 06:23:31 +00:00
|
|
|
MiLockProcessWorkingSetUnsafe(Process, Thread);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-11-02 14:41:03 +00:00
|
|
|
/* VM is deleted now */
|
|
|
|
Process->VmDeleted = TRUE;
|
2012-09-03 06:23:31 +00:00
|
|
|
MiUnlockProcessWorkingSetUnsafe(Process, Thread);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-07-24 16:12:39 +00:00
|
|
|
/* Enumerate the VADs */
|
|
|
|
VadTree = &Process->VadRoot;
|
|
|
|
while (VadTree->NumberGenericTableElements)
|
|
|
|
{
|
|
|
|
/* Grab the current VAD */
|
|
|
|
Vad = (PMMVAD)VadTree->BalancedRoot.RightChild;
|
|
|
|
|
2015-05-17 00:34:59 +00:00
|
|
|
/* Check for old-style memory areas */
|
|
|
|
if (Vad->u.VadFlags.Spare == 1)
|
|
|
|
{
|
|
|
|
/* Let RosMm handle this */
|
|
|
|
MiRosCleanupMemoryArea(Process, Vad);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2010-07-24 16:12:39 +00:00
|
|
|
/* Lock the working set */
|
2012-09-03 06:23:31 +00:00
|
|
|
MiLockProcessWorkingSetUnsafe(Process, Thread);
|
2010-07-24 16:12:39 +00:00
|
|
|
|
|
|
|
/* Remove this VAD from the tree */
|
|
|
|
ASSERT(VadTree->NumberGenericTableElements >= 1);
|
|
|
|
MiRemoveNode((PMMADDRESS_NODE)Vad, VadTree);
|
|
|
|
|
2010-10-19 17:07:11 +00:00
|
|
|
/* Only regular VADs supported for now */
|
2010-07-24 16:12:39 +00:00
|
|
|
ASSERT(Vad->u.VadFlags.VadType == VadNone);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-10-19 17:07:11 +00:00
|
|
|
/* Check if this is a section VAD */
|
|
|
|
if (!(Vad->u.VadFlags.PrivateMemory) && (Vad->ControlArea))
|
|
|
|
{
|
|
|
|
/* Remove the view */
|
|
|
|
MiRemoveMappedView(Process, Vad);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Delete the addresses */
|
|
|
|
MiDeleteVirtualAddresses(Vad->StartingVpn << PAGE_SHIFT,
|
|
|
|
(Vad->EndingVpn << PAGE_SHIFT) | (PAGE_SIZE - 1),
|
|
|
|
Vad);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-10-19 17:07:11 +00:00
|
|
|
/* Release the working set */
|
2012-09-03 06:23:31 +00:00
|
|
|
MiUnlockProcessWorkingSetUnsafe(Process, Thread);
|
2010-10-19 17:07:11 +00:00
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2015-05-17 00:34:59 +00:00
|
|
|
/* Skip ARM3 fake VADs, they'll be freed by MmDeleteProcessAddresSpace */
|
2010-10-05 05:00:19 +00:00
|
|
|
if (Vad->u.VadFlags.Spare == 1)
|
|
|
|
{
|
|
|
|
/* Set a flag so MmDeleteMemoryArea knows to free, but not to remove */
|
|
|
|
Vad->u.VadFlags.Spare = 2;
|
|
|
|
continue;
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-07-24 16:12:39 +00:00
|
|
|
/* Free the VAD memory */
|
|
|
|
ExFreePool(Vad);
|
2022-05-12 06:11:52 +00:00
|
|
|
|
|
|
|
/* Return the quota the VAD used */
|
|
|
|
PsReturnProcessNonPagedPoolQuota(Process, sizeof(MMVAD_LONG));
|
2010-07-24 16:12:39 +00:00
|
|
|
}
|
2012-08-01 07:54:37 +00:00
|
|
|
|
2012-09-03 06:23:31 +00:00
|
|
|
/* Lock the working set */
|
|
|
|
MiLockProcessWorkingSetUnsafe(Process, Thread);
|
|
|
|
ASSERT(Process->CloneRoot == NULL);
|
|
|
|
ASSERT(Process->PhysicalVadRoot == NULL);
|
|
|
|
|
2012-02-21 00:32:24 +00:00
|
|
|
/* Delete the shared user data section */
|
|
|
|
MiDeleteVirtualAddresses(USER_SHARED_DATA, USER_SHARED_DATA, NULL);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2012-09-03 06:23:31 +00:00
|
|
|
/* Release the working set */
|
|
|
|
MiUnlockProcessWorkingSetUnsafe(Process, Thread);
|
|
|
|
|
2010-07-24 16:12:39 +00:00
|
|
|
/* Release the address space */
|
|
|
|
MmUnlockAddressSpace(&Process->Vm);
|
|
|
|
}
|
|
|
|
|
[NTOSKRNL]: This is kind of embarssing, but after doing a local grep for some of cgutman and zekflop's changes (respectively the patch that had added MmDeleteProcessPageDirectory, and the mshtml fix patch), I fell upon a .patch file. It included 3 memory-leak-fixing patches from richard that had been sent to me during his last days -- which, had I paid attention, would've fixed the MSHTML bug and the memory leaks months ago! I've tried my best to now re-integrate a portion of the patch (the other two portions deal with freeing the loader block, and freeing .INIT sections, and I will commit them later) with the current state of trunk. Some things that patch did, no longer seem to work, and I've commented where appropriate. But in general it does seem to dereference/delete some PTEs that had been left behind before (such as deleted TEBs, and deleted VA mappings). It no longer seems to be able to delete the root PDE nor the shared data page however (this worked in the original patch's timeframe). Zekflop, tkreuzer, please take a look. I hope this will set us on a better path!
svn path=/trunk/; revision=55666
2012-02-17 07:07:47 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
2021-04-26 16:18:23 +00:00
|
|
|
MmDeleteProcessAddressSpace(IN PEPROCESS Process)
|
[NTOSKRNL]: This is kind of embarssing, but after doing a local grep for some of cgutman and zekflop's changes (respectively the patch that had added MmDeleteProcessPageDirectory, and the mshtml fix patch), I fell upon a .patch file. It included 3 memory-leak-fixing patches from richard that had been sent to me during his last days -- which, had I paid attention, would've fixed the MSHTML bug and the memory leaks months ago! I've tried my best to now re-integrate a portion of the patch (the other two portions deal with freeing the loader block, and freeing .INIT sections, and I will commit them later) with the current state of trunk. Some things that patch did, no longer seem to work, and I've commented where appropriate. But in general it does seem to dereference/delete some PTEs that had been left behind before (such as deleted TEBs, and deleted VA mappings). It no longer seems to be able to delete the root PDE nor the shared data page however (this worked in the original patch's timeframe). Zekflop, tkreuzer, please take a look. I hope this will set us on a better path!
svn path=/trunk/; revision=55666
2012-02-17 07:07:47 +00:00
|
|
|
{
|
|
|
|
PMMPFN Pfn1, Pfn2;
|
|
|
|
KIRQL OldIrql;
|
|
|
|
PFN_NUMBER PageFrameIndex;
|
|
|
|
|
2021-04-26 16:18:23 +00:00
|
|
|
#ifndef _M_AMD64
|
|
|
|
OldIrql = MiAcquireExpansionLock();
|
|
|
|
RemoveEntryList(&Process->MmProcessLinks);
|
|
|
|
MiReleaseExpansionLock(OldIrql);
|
|
|
|
#endif
|
|
|
|
|
[NTOSKRNL]: This is kind of embarssing, but after doing a local grep for some of cgutman and zekflop's changes (respectively the patch that had added MmDeleteProcessPageDirectory, and the mshtml fix patch), I fell upon a .patch file. It included 3 memory-leak-fixing patches from richard that had been sent to me during his last days -- which, had I paid attention, would've fixed the MSHTML bug and the memory leaks months ago! I've tried my best to now re-integrate a portion of the patch (the other two portions deal with freeing the loader block, and freeing .INIT sections, and I will commit them later) with the current state of trunk. Some things that patch did, no longer seem to work, and I've commented where appropriate. But in general it does seem to dereference/delete some PTEs that had been left behind before (such as deleted TEBs, and deleted VA mappings). It no longer seems to be able to delete the root PDE nor the shared data page however (this worked in the original patch's timeframe). Zekflop, tkreuzer, please take a look. I hope this will set us on a better path!
svn path=/trunk/; revision=55666
2012-02-17 07:07:47 +00:00
|
|
|
//ASSERT(Process->CommitCharge == 0);
|
2012-02-27 16:10:30 +00:00
|
|
|
|
2021-04-12 09:36:19 +00:00
|
|
|
/* Remove us from the list */
|
|
|
|
OldIrql = MiAcquireExpansionLock();
|
|
|
|
RemoveEntryList(&Process->Vm.WorkingSetExpansionLinks);
|
|
|
|
MiReleaseExpansionLock(OldIrql);
|
|
|
|
|
[NTOSKRNL]: This is kind of embarssing, but after doing a local grep for some of cgutman and zekflop's changes (respectively the patch that had added MmDeleteProcessPageDirectory, and the mshtml fix patch), I fell upon a .patch file. It included 3 memory-leak-fixing patches from richard that had been sent to me during his last days -- which, had I paid attention, would've fixed the MSHTML bug and the memory leaks months ago! I've tried my best to now re-integrate a portion of the patch (the other two portions deal with freeing the loader block, and freeing .INIT sections, and I will commit them later) with the current state of trunk. Some things that patch did, no longer seem to work, and I've commented where appropriate. But in general it does seem to dereference/delete some PTEs that had been left behind before (such as deleted TEBs, and deleted VA mappings). It no longer seems to be able to delete the root PDE nor the shared data page however (this worked in the original patch's timeframe). Zekflop, tkreuzer, please take a look. I hope this will set us on a better path!
svn path=/trunk/; revision=55666
2012-02-17 07:07:47 +00:00
|
|
|
/* Acquire the PFN lock */
|
2017-11-21 22:33:42 +00:00
|
|
|
OldIrql = MiAcquirePfnLock();
|
[NTOSKRNL]: This is kind of embarssing, but after doing a local grep for some of cgutman and zekflop's changes (respectively the patch that had added MmDeleteProcessPageDirectory, and the mshtml fix patch), I fell upon a .patch file. It included 3 memory-leak-fixing patches from richard that had been sent to me during his last days -- which, had I paid attention, would've fixed the MSHTML bug and the memory leaks months ago! I've tried my best to now re-integrate a portion of the patch (the other two portions deal with freeing the loader block, and freeing .INIT sections, and I will commit them later) with the current state of trunk. Some things that patch did, no longer seem to work, and I've commented where appropriate. But in general it does seem to dereference/delete some PTEs that had been left behind before (such as deleted TEBs, and deleted VA mappings). It no longer seems to be able to delete the root PDE nor the shared data page however (this worked in the original patch's timeframe). Zekflop, tkreuzer, please take a look. I hope this will set us on a better path!
svn path=/trunk/; revision=55666
2012-02-17 07:07:47 +00:00
|
|
|
|
|
|
|
/* Check for fully initialized process */
|
|
|
|
if (Process->AddressSpaceInitialized == 2)
|
|
|
|
{
|
|
|
|
/* Map the working set page and its page table */
|
|
|
|
Pfn1 = MiGetPfnEntry(Process->WorkingSetPage);
|
|
|
|
Pfn2 = MiGetPfnEntry(Pfn1->u4.PteFrame);
|
|
|
|
|
|
|
|
/* Nuke it */
|
|
|
|
MI_SET_PFN_DELETED(Pfn1);
|
|
|
|
MiDecrementShareCount(Pfn2, Pfn1->u4.PteFrame);
|
|
|
|
MiDecrementShareCount(Pfn1, Process->WorkingSetPage);
|
|
|
|
ASSERT((Pfn1->u3.e2.ReferenceCount == 0) || (Pfn1->u3.e1.WriteInProgress));
|
2012-02-27 16:10:30 +00:00
|
|
|
|
[NTOSKRNL]: This is kind of embarssing, but after doing a local grep for some of cgutman and zekflop's changes (respectively the patch that had added MmDeleteProcessPageDirectory, and the mshtml fix patch), I fell upon a .patch file. It included 3 memory-leak-fixing patches from richard that had been sent to me during his last days -- which, had I paid attention, would've fixed the MSHTML bug and the memory leaks months ago! I've tried my best to now re-integrate a portion of the patch (the other two portions deal with freeing the loader block, and freeing .INIT sections, and I will commit them later) with the current state of trunk. Some things that patch did, no longer seem to work, and I've commented where appropriate. But in general it does seem to dereference/delete some PTEs that had been left behind before (such as deleted TEBs, and deleted VA mappings). It no longer seems to be able to delete the root PDE nor the shared data page however (this worked in the original patch's timeframe). Zekflop, tkreuzer, please take a look. I hope this will set us on a better path!
svn path=/trunk/; revision=55666
2012-02-17 07:07:47 +00:00
|
|
|
/* Now map hyperspace and its page table */
|
|
|
|
PageFrameIndex = Process->Pcb.DirectoryTableBase[1] >> PAGE_SHIFT;
|
|
|
|
Pfn1 = MiGetPfnEntry(PageFrameIndex);
|
|
|
|
Pfn2 = MiGetPfnEntry(Pfn1->u4.PteFrame);
|
|
|
|
|
|
|
|
/* Nuke it */
|
|
|
|
MI_SET_PFN_DELETED(Pfn1);
|
|
|
|
MiDecrementShareCount(Pfn2, Pfn1->u4.PteFrame);
|
|
|
|
MiDecrementShareCount(Pfn1, PageFrameIndex);
|
|
|
|
ASSERT((Pfn1->u3.e2.ReferenceCount == 0) || (Pfn1->u3.e1.WriteInProgress));
|
2012-02-27 16:10:30 +00:00
|
|
|
|
[NTOSKRNL]: This is kind of embarssing, but after doing a local grep for some of cgutman and zekflop's changes (respectively the patch that had added MmDeleteProcessPageDirectory, and the mshtml fix patch), I fell upon a .patch file. It included 3 memory-leak-fixing patches from richard that had been sent to me during his last days -- which, had I paid attention, would've fixed the MSHTML bug and the memory leaks months ago! I've tried my best to now re-integrate a portion of the patch (the other two portions deal with freeing the loader block, and freeing .INIT sections, and I will commit them later) with the current state of trunk. Some things that patch did, no longer seem to work, and I've commented where appropriate. But in general it does seem to dereference/delete some PTEs that had been left behind before (such as deleted TEBs, and deleted VA mappings). It no longer seems to be able to delete the root PDE nor the shared data page however (this worked in the original patch's timeframe). Zekflop, tkreuzer, please take a look. I hope this will set us on a better path!
svn path=/trunk/; revision=55666
2012-02-17 07:07:47 +00:00
|
|
|
/* Finally, nuke the PDE itself */
|
|
|
|
PageFrameIndex = Process->Pcb.DirectoryTableBase[0] >> PAGE_SHIFT;
|
|
|
|
Pfn1 = MiGetPfnEntry(PageFrameIndex);
|
|
|
|
MI_SET_PFN_DELETED(Pfn1);
|
|
|
|
MiDecrementShareCount(Pfn1, PageFrameIndex);
|
|
|
|
MiDecrementShareCount(Pfn1, PageFrameIndex);
|
2012-02-27 16:10:30 +00:00
|
|
|
|
2012-02-21 00:32:24 +00:00
|
|
|
/* Page table is now dead. Bye bye... */
|
|
|
|
ASSERT((Pfn1->u3.e2.ReferenceCount == 0) || (Pfn1->u3.e1.WriteInProgress));
|
[NTOSKRNL]: This is kind of embarssing, but after doing a local grep for some of cgutman and zekflop's changes (respectively the patch that had added MmDeleteProcessPageDirectory, and the mshtml fix patch), I fell upon a .patch file. It included 3 memory-leak-fixing patches from richard that had been sent to me during his last days -- which, had I paid attention, would've fixed the MSHTML bug and the memory leaks months ago! I've tried my best to now re-integrate a portion of the patch (the other two portions deal with freeing the loader block, and freeing .INIT sections, and I will commit them later) with the current state of trunk. Some things that patch did, no longer seem to work, and I've commented where appropriate. But in general it does seem to dereference/delete some PTEs that had been left behind before (such as deleted TEBs, and deleted VA mappings). It no longer seems to be able to delete the root PDE nor the shared data page however (this worked in the original patch's timeframe). Zekflop, tkreuzer, please take a look. I hope this will set us on a better path!
svn path=/trunk/; revision=55666
2012-02-17 07:07:47 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* A partly-initialized process should never exit through here */
|
|
|
|
ASSERT(FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Release the PFN lock */
|
2017-11-21 22:33:42 +00:00
|
|
|
MiReleasePfnLock(OldIrql);
|
[NTOSKRNL]: This is kind of embarssing, but after doing a local grep for some of cgutman and zekflop's changes (respectively the patch that had added MmDeleteProcessPageDirectory, and the mshtml fix patch), I fell upon a .patch file. It included 3 memory-leak-fixing patches from richard that had been sent to me during his last days -- which, had I paid attention, would've fixed the MSHTML bug and the memory leaks months ago! I've tried my best to now re-integrate a portion of the patch (the other two portions deal with freeing the loader block, and freeing .INIT sections, and I will commit them later) with the current state of trunk. Some things that patch did, no longer seem to work, and I've commented where appropriate. But in general it does seem to dereference/delete some PTEs that had been left behind before (such as deleted TEBs, and deleted VA mappings). It no longer seems to be able to delete the root PDE nor the shared data page however (this worked in the original patch's timeframe). Zekflop, tkreuzer, please take a look. I hope this will set us on a better path!
svn path=/trunk/; revision=55666
2012-02-17 07:07:47 +00:00
|
|
|
|
2012-08-01 07:54:37 +00:00
|
|
|
/* Drop a reference on the session */
|
|
|
|
if (Process->Session) MiReleaseProcessReferenceToSessionDataPage(Process->Session);
|
2012-02-27 16:10:30 +00:00
|
|
|
|
[NTOSKRNL]: This is kind of embarssing, but after doing a local grep for some of cgutman and zekflop's changes (respectively the patch that had added MmDeleteProcessPageDirectory, and the mshtml fix patch), I fell upon a .patch file. It included 3 memory-leak-fixing patches from richard that had been sent to me during his last days -- which, had I paid attention, would've fixed the MSHTML bug and the memory leaks months ago! I've tried my best to now re-integrate a portion of the patch (the other two portions deal with freeing the loader block, and freeing .INIT sections, and I will commit them later) with the current state of trunk. Some things that patch did, no longer seem to work, and I've commented where appropriate. But in general it does seem to dereference/delete some PTEs that had been left behind before (such as deleted TEBs, and deleted VA mappings). It no longer seems to be able to delete the root PDE nor the shared data page however (this worked in the original patch's timeframe). Zekflop, tkreuzer, please take a look. I hope this will set us on a better path!
svn path=/trunk/; revision=55666
2012-02-17 07:07:47 +00:00
|
|
|
/* Clear out the PDE pages */
|
|
|
|
Process->Pcb.DirectoryTableBase[0] = 0;
|
|
|
|
Process->Pcb.DirectoryTableBase[1] = 0;
|
|
|
|
}
|
|
|
|
|
2012-02-06 18:14:36 +00:00
|
|
|
|
2009-10-15 05:56:41 +00:00
|
|
|
/* SYSTEM CALLS ***************************************************************/
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
NtAllocateUserPhysicalPages(IN HANDLE ProcessHandle,
|
|
|
|
IN OUT PULONG_PTR NumberOfPages,
|
|
|
|
IN OUT PULONG_PTR UserPfnArray)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
NtMapUserPhysicalPages(IN PVOID VirtualAddresses,
|
|
|
|
IN ULONG_PTR NumberOfPages,
|
|
|
|
IN OUT PULONG_PTR UserPfnArray)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
NtMapUserPhysicalPagesScatter(IN PVOID *VirtualAddresses,
|
|
|
|
IN ULONG_PTR NumberOfPages,
|
|
|
|
IN OUT PULONG_PTR UserPfnArray)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
NtFreeUserPhysicalPages(IN HANDLE ProcessHandle,
|
|
|
|
IN OUT PULONG_PTR NumberOfPages,
|
|
|
|
IN OUT PULONG_PTR UserPfnArray)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
/* EOF */
|