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
|
|
|
|
#include "../ARM3/miarm.h"
|
|
|
|
|
2010-09-29 01:10:28 +00:00
|
|
|
/* GLOBALS ********************************************************************/
|
|
|
|
|
|
|
|
ULONG MmProcessColorSeed = 0x12345678;
|
2010-11-08 12:35:50 +00:00
|
|
|
PMMWSL MmWorkingSetList;
|
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 **********************************************************/
|
|
|
|
|
[NTOS]: MiRosTakeOverPebTebRanges now creates a small ~1MB ARM3 memory range on top of the ReactOS per-process VA. This does a couple of things: First of all, it changes the default PEB address to another static address. Still not dynamic like it will be soon, but at least it changes it a bit so we can test if anything breaks due to that. It also likewise changes the addresses of the TEBs (Shifted down by 1MB, basically). Finally, it blocks off that part of address space, which nobody should be using now, to see if anyone does indeed touch it.
[NTOS]: Knowing if this change causes issues will help later in determining regressions due to TEB/PEBs mapped as VADs by ARM3, and regressions simply due to the change in VA layout.
[NTOS]: When implemented, the VAD mapping for PEB/TEB will only use that ~1MB, which yes, will limit ReactOS processes to each have only 256 threads. That is obviously a temporary limitation, one I doubt we'll even hit, but I'm putting it out here so you know.
svn path=/trunk/; revision=48176
2010-07-22 03:22:43 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
2012-02-05 18:41:37 +00:00
|
|
|
MiRosTakeOverSharedUserPage(IN PEPROCESS Process)
|
[NTOS]: MiRosTakeOverPebTebRanges now creates a small ~1MB ARM3 memory range on top of the ReactOS per-process VA. This does a couple of things: First of all, it changes the default PEB address to another static address. Still not dynamic like it will be soon, but at least it changes it a bit so we can test if anything breaks due to that. It also likewise changes the addresses of the TEBs (Shifted down by 1MB, basically). Finally, it blocks off that part of address space, which nobody should be using now, to see if anyone does indeed touch it.
[NTOS]: Knowing if this change causes issues will help later in determining regressions due to TEB/PEBs mapped as VADs by ARM3, and regressions simply due to the change in VA layout.
[NTOS]: When implemented, the VAD mapping for PEB/TEB will only use that ~1MB, which yes, will limit ReactOS processes to each have only 256 threads. That is obviously a temporary limitation, one I doubt we'll even hit, but I'm putting it out here so you know.
svn path=/trunk/; revision=48176
2010-07-22 03:22:43 +00:00
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
PMEMORY_AREA MemoryArea;
|
2012-02-06 00:24:31 +00:00
|
|
|
PVOID AllocatedBase = (PVOID)MM_SHARED_USER_DATA_VA;
|
[NTOS]: MiRosTakeOverPebTebRanges now creates a small ~1MB ARM3 memory range on top of the ReactOS per-process VA. This does a couple of things: First of all, it changes the default PEB address to another static address. Still not dynamic like it will be soon, but at least it changes it a bit so we can test if anything breaks due to that. It also likewise changes the addresses of the TEBs (Shifted down by 1MB, basically). Finally, it blocks off that part of address space, which nobody should be using now, to see if anyone does indeed touch it.
[NTOS]: Knowing if this change causes issues will help later in determining regressions due to TEB/PEBs mapped as VADs by ARM3, and regressions simply due to the change in VA layout.
[NTOS]: When implemented, the VAD mapping for PEB/TEB will only use that ~1MB, which yes, will limit ReactOS processes to each have only 256 threads. That is obviously a temporary limitation, one I doubt we'll even hit, but I'm putting it out here so you know.
svn path=/trunk/; revision=48176
2010-07-22 03:22:43 +00:00
|
|
|
|
|
|
|
Status = MmCreateMemoryArea(&Process->Vm,
|
|
|
|
MEMORY_AREA_OWNED_BY_ARM3,
|
|
|
|
&AllocatedBase,
|
2012-02-05 18:41:37 +00:00
|
|
|
PAGE_SIZE,
|
[NTOS]: MiRosTakeOverPebTebRanges now creates a small ~1MB ARM3 memory range on top of the ReactOS per-process VA. This does a couple of things: First of all, it changes the default PEB address to another static address. Still not dynamic like it will be soon, but at least it changes it a bit so we can test if anything breaks due to that. It also likewise changes the addresses of the TEBs (Shifted down by 1MB, basically). Finally, it blocks off that part of address space, which nobody should be using now, to see if anyone does indeed touch it.
[NTOS]: Knowing if this change causes issues will help later in determining regressions due to TEB/PEBs mapped as VADs by ARM3, and regressions simply due to the change in VA layout.
[NTOS]: When implemented, the VAD mapping for PEB/TEB will only use that ~1MB, which yes, will limit ReactOS processes to each have only 256 threads. That is obviously a temporary limitation, one I doubt we'll even hit, but I'm putting it out here so you know.
svn path=/trunk/; revision=48176
2010-07-22 03:22:43 +00:00
|
|
|
PAGE_READWRITE,
|
|
|
|
&MemoryArea,
|
|
|
|
TRUE,
|
|
|
|
0,
|
2013-11-26 21:38:02 +00:00
|
|
|
PAGE_SIZE);
|
[NTOS]: MiRosTakeOverPebTebRanges now creates a small ~1MB ARM3 memory range on top of the ReactOS per-process VA. This does a couple of things: First of all, it changes the default PEB address to another static address. Still not dynamic like it will be soon, but at least it changes it a bit so we can test if anything breaks due to that. It also likewise changes the addresses of the TEBs (Shifted down by 1MB, basically). Finally, it blocks off that part of address space, which nobody should be using now, to see if anyone does indeed touch it.
[NTOS]: Knowing if this change causes issues will help later in determining regressions due to TEB/PEBs mapped as VADs by ARM3, and regressions simply due to the change in VA layout.
[NTOS]: When implemented, the VAD mapping for PEB/TEB will only use that ~1MB, which yes, will limit ReactOS processes to each have only 256 threads. That is obviously a temporary limitation, one I doubt we'll even hit, but I'm putting it out here so you know.
svn path=/trunk/; revision=48176
2010-07-22 03:22:43 +00:00
|
|
|
ASSERT(NT_SUCCESS(Status));
|
|
|
|
}
|
|
|
|
|
2010-07-22 19:08:45 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
MiCreatePebOrTeb(IN PEPROCESS Process,
|
|
|
|
IN ULONG Size,
|
|
|
|
OUT PULONG_PTR Base)
|
|
|
|
{
|
|
|
|
PETHREAD Thread = PsGetCurrentThread();
|
|
|
|
PMMVAD_LONG Vad;
|
|
|
|
NTSTATUS Status;
|
|
|
|
ULONG RandomCoeff;
|
|
|
|
ULONG_PTR StartAddress, EndAddress;
|
|
|
|
LARGE_INTEGER CurrentTime;
|
2010-08-23 03:00:03 +00:00
|
|
|
TABLE_SEARCH_RESULT Result = TableFoundNode;
|
|
|
|
PMMADDRESS_NODE Parent;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-07-22 19:08:45 +00:00
|
|
|
/* Allocate a VAD */
|
|
|
|
Vad = ExAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD_LONG), 'ldaV');
|
|
|
|
if (!Vad) return STATUS_NO_MEMORY;
|
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;
|
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
|
|
|
|
2010-07-22 19:08:45 +00:00
|
|
|
/* Lock the process address space */
|
|
|
|
KeAcquireGuardedMutex(&Process->AddressCreationLock);
|
|
|
|
|
|
|
|
/* Check if this is a PEB creation */
|
|
|
|
if (Size == sizeof(PEB))
|
|
|
|
{
|
|
|
|
/* Start at the highest valid address */
|
|
|
|
StartAddress = (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1;
|
|
|
|
|
|
|
|
/* Select the random coefficient */
|
|
|
|
KeQueryTickCount(&CurrentTime);
|
|
|
|
CurrentTime.LowPart &= ((64 * _1KB) >> PAGE_SHIFT) - 1;
|
|
|
|
if (CurrentTime.LowPart <= 1) CurrentTime.LowPart = 2;
|
|
|
|
RandomCoeff = CurrentTime.LowPart << PAGE_SHIFT;
|
|
|
|
|
|
|
|
/* Select the highest valid address minus the random coefficient */
|
|
|
|
StartAddress -= RandomCoeff;
|
|
|
|
EndAddress = StartAddress + ROUND_TO_PAGES(Size) - 1;
|
|
|
|
|
2010-08-23 03:00:03 +00:00
|
|
|
/* Try to find something below the random upper margin */
|
|
|
|
Result = MiFindEmptyAddressRangeDownTree(ROUND_TO_PAGES(Size),
|
|
|
|
EndAddress,
|
|
|
|
PAGE_SIZE,
|
|
|
|
&Process->VadRoot,
|
|
|
|
Base,
|
|
|
|
&Parent);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for success. TableFoundNode means nothing free. */
|
|
|
|
if (Result == TableFoundNode)
|
|
|
|
{
|
|
|
|
/* For TEBs, or if a PEB location couldn't be found, scan the VAD root */
|
|
|
|
Result = MiFindEmptyAddressRangeDownTree(ROUND_TO_PAGES(Size),
|
|
|
|
(ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1,
|
|
|
|
PAGE_SIZE,
|
|
|
|
&Process->VadRoot,
|
|
|
|
Base,
|
|
|
|
&Parent);
|
|
|
|
/* Bail out, if still nothing free was found */
|
2012-09-28 12:17:23 +00:00
|
|
|
if (Result == TableFoundNode)
|
|
|
|
{
|
|
|
|
ExFreePoolWithTag(Vad, 'ldaV');
|
|
|
|
return STATUS_NO_MEMORY;
|
|
|
|
}
|
2010-07-22 19:08:45 +00:00
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-07-22 19:08:45 +00:00
|
|
|
/* Validate that it came from the VAD ranges */
|
|
|
|
ASSERT(*Base >= (ULONG_PTR)MI_LOWEST_VAD_ADDRESS);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-07-22 19:08:45 +00:00
|
|
|
/* Build the rest of the VAD now */
|
|
|
|
Vad->StartingVpn = (*Base) >> PAGE_SHIFT;
|
2010-10-05 05:00:19 +00:00
|
|
|
Vad->EndingVpn = ((*Base) + Size - 1) >> PAGE_SHIFT;
|
2010-07-22 19:08:45 +00:00
|
|
|
Vad->u3.Secured.StartVpn = *Base;
|
|
|
|
Vad->u3.Secured.EndVpn = (Vad->EndingVpn << PAGE_SHIFT) | (PAGE_SIZE - 1);
|
2010-08-19 05:10:16 +00:00
|
|
|
Vad->u1.Parent = NULL;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-07-22 19:08:45 +00:00
|
|
|
/* FIXME: Should setup VAD bitmap */
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
/* Pretend as if we own the working set */
|
2012-09-03 06:23:31 +00:00
|
|
|
MiLockProcessWorkingSetUnsafe(Process, Thread);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-07-22 19:08:45 +00:00
|
|
|
/* Insert the VAD */
|
|
|
|
ASSERT(Vad->EndingVpn >= Vad->StartingVpn);
|
|
|
|
Process->VadRoot.NodeHint = Vad;
|
2010-10-17 20:02:17 +00:00
|
|
|
Vad->ControlArea = NULL; // For Memory-Area hack
|
|
|
|
Vad->FirstPrototypePte = NULL;
|
2010-10-18 13:10:54 +00:00
|
|
|
DPRINT("VAD: %p\n", Vad);
|
|
|
|
DPRINT("Allocated PEB/TEB at: 0x%p for %16s\n", *Base, Process->ImageFileName);
|
2010-08-23 03:00:03 +00:00
|
|
|
MiInsertNode(&Process->VadRoot, (PVOID)Vad, Parent, Result);
|
|
|
|
|
2010-07-22 19:08:45 +00:00
|
|
|
/* Release the working set */
|
2012-09-03 06:23:31 +00:00
|
|
|
MiUnlockProcessWorkingSetUnsafe(Process, Thread);
|
2010-07-22 19:08:45 +00:00
|
|
|
|
|
|
|
/* Release the address space lock */
|
|
|
|
KeReleaseGuardedMutex(&Process->AddressCreationLock);
|
|
|
|
|
|
|
|
/* Return the status */
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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;
|
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)
|
|
|
|
{
|
|
|
|
Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
|
2012-03-28 19:41:40 +00:00
|
|
|
InterlockedPushEntrySList(&MmDeadStackSListHead,
|
|
|
|
(PSLIST_ENTRY)&Pfn1->u1.NextStackPfn);
|
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 ?
|
|
|
|
KERNEL_LARGE_STACK_SIZE : KERNEL_STACK_SIZE);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-05-29 18:33:50 +00:00
|
|
|
/* Acquire the PFN lock */
|
|
|
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
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 */
|
|
|
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
|
|
|
|
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;
|
2012-03-04 17:56:00 +00:00
|
|
|
PMMPFN Pfn1;
|
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
|
|
|
|
//
|
|
|
|
StackPtes = BYTES_TO_PAGES(KERNEL_LARGE_STACK_SIZE);
|
|
|
|
StackPages = BYTES_TO_PAGES(KERNEL_LARGE_STACK_COMMIT);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2009-06-27 08:41:45 +00:00
|
|
|
}
|
|
|
|
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))
|
|
|
|
{
|
|
|
|
Pfn1 = (PMMPFN)InterlockedPopEntrySList(&MmDeadStackSListHead);
|
|
|
|
if (Pfn1)
|
|
|
|
{
|
|
|
|
PointerPte = Pfn1->PteAddress;
|
|
|
|
BaseAddress = MiPteToAddress(++PointerPte);
|
|
|
|
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;
|
|
|
|
if (GuiStack) PointerPte += BYTES_TO_PAGES(KERNEL_LARGE_STACK_SIZE -
|
|
|
|
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
|
|
|
|
//
|
|
|
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
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
|
|
|
|
//
|
|
|
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, 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) <=
|
|
|
|
(KERNEL_LARGE_STACK_SIZE + 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 -
|
|
|
|
KERNEL_LARGE_STACK_SIZE));
|
|
|
|
if (NewLimitPte < LastPte)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Sorry!
|
|
|
|
//
|
|
|
|
DPRINT1("Thread wants too much stack\n");
|
|
|
|
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
|
|
|
|
//
|
|
|
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
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
|
|
|
|
//
|
|
|
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, 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);
|
|
|
|
ASSERT(NT_SUCCESS(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;
|
|
|
|
}
|
|
|
|
|
2010-11-08 12:35:50 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
MiInitializeWorkingSetList(IN PEPROCESS CurrentProcess)
|
|
|
|
{
|
|
|
|
PMMPFN Pfn1;
|
2012-02-20 20:50:36 +00:00
|
|
|
PMMPTE sysPte;
|
|
|
|
MMPTE tempPte;
|
2010-11-08 12:35:50 +00:00
|
|
|
|
|
|
|
/* Setup some bogus list data */
|
|
|
|
MmWorkingSetList->LastEntry = CurrentProcess->Vm.MinimumWorkingSetSize;
|
|
|
|
MmWorkingSetList->HashTable = NULL;
|
|
|
|
MmWorkingSetList->HashTableSize = 0;
|
|
|
|
MmWorkingSetList->NumberOfImageWaiters = 0;
|
|
|
|
MmWorkingSetList->Wsle = (PVOID)0xDEADBABE;
|
|
|
|
MmWorkingSetList->VadBitMapHint = 1;
|
|
|
|
MmWorkingSetList->HashTableStart = (PVOID)0xBADAB00B;
|
|
|
|
MmWorkingSetList->HighestPermittedHashAddress = (PVOID)0xCAFEBABE;
|
|
|
|
MmWorkingSetList->FirstFree = 1;
|
|
|
|
MmWorkingSetList->FirstDynamic = 2;
|
|
|
|
MmWorkingSetList->NextSlot = 3;
|
|
|
|
MmWorkingSetList->LastInitializedWsle = 4;
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-11-08 12:35:50 +00:00
|
|
|
/* The rule is that the owner process is always in the FLINK of the PDE's PFN entry */
|
2012-02-04 23:08:20 +00:00
|
|
|
Pfn1 = MiGetPfnEntry(CurrentProcess->Pcb.DirectoryTableBase[0] >> PAGE_SHIFT);
|
2010-11-08 12:35:50 +00:00
|
|
|
ASSERT(Pfn1->u4.PteFrame == MiGetPfnEntryIndex(Pfn1));
|
|
|
|
Pfn1->u1.Event = (PKEVENT)CurrentProcess;
|
2012-02-27 16:10:30 +00:00
|
|
|
|
2012-02-20 20:50:36 +00:00
|
|
|
/* Map the process working set in kernel space */
|
|
|
|
sysPte = MiReserveSystemPtes(1, SystemPteSpace);
|
|
|
|
MI_MAKE_HARDWARE_PTE_KERNEL(&tempPte, sysPte, MM_READWRITE, CurrentProcess->WorkingSetPage);
|
|
|
|
MI_WRITE_VALID_PTE(sysPte, tempPte);
|
|
|
|
CurrentProcess->Vm.VmWorkingSetList = MiPteToAddress(sysPte);
|
2010-11-08 12:35:50 +00:00
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
PROS_SECTION_OBJECT SectionObject = Section;
|
|
|
|
PMMPTE PointerPte;
|
|
|
|
KIRQL OldIrql;
|
|
|
|
PMMPDE PointerPde;
|
|
|
|
PFN_NUMBER PageFrameNumber;
|
|
|
|
UNICODE_STRING FileName;
|
|
|
|
PWCHAR Source;
|
|
|
|
PCHAR Destination;
|
|
|
|
USHORT Length = 0;
|
2010-11-08 12:35:50 +00:00
|
|
|
MMPTE TempPte;
|
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;
|
|
|
|
|
|
|
|
/* Lock PFN database */
|
|
|
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
|
|
|
|
|
|
|
/* Setup the PFN for the PDE base of this process */
|
2012-02-04 23:08:20 +00:00
|
|
|
#ifdef _M_AMD64
|
|
|
|
PointerPte = MiAddressToPte(PXE_BASE);
|
|
|
|
#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 */
|
2012-02-04 23:08:20 +00:00
|
|
|
#ifdef _M_AMD64
|
|
|
|
PointerPde = MiAddressToPxe((PVOID)HYPER_SPACE);
|
|
|
|
#else
|
2010-07-24 15:01:05 +00:00
|
|
|
PointerPde = MiAddressToPde(HYPER_SPACE);
|
2012-02-04 23:08:20 +00:00
|
|
|
#endif
|
2010-07-24 15:01:05 +00:00
|
|
|
PageFrameNumber = PFN_FROM_PTE(PointerPde);
|
2012-02-04 23:08:20 +00:00
|
|
|
//ASSERT(Process->Pcb.DirectoryTableBase[0] == PageFrameNumber * PAGE_SIZE); // we're not lucky
|
2010-11-24 15:21:45 +00:00
|
|
|
MiInitializePfn(PageFrameNumber, (PMMPTE)PointerPde, TRUE);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-11-08 12:35:50 +00:00
|
|
|
/* Setup the PFN for the PTE for the working set */
|
|
|
|
PointerPte = MiAddressToPte(MI_WORKING_SET_LIST);
|
|
|
|
MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte, MM_READWRITE, 0);
|
|
|
|
ASSERT(PointerPte->u.Long != 0);
|
|
|
|
PageFrameNumber = PFN_FROM_PTE(PointerPte);
|
|
|
|
MI_WRITE_INVALID_PTE(PointerPte, DemandZeroPte);
|
|
|
|
MiInitializePfn(PageFrameNumber, PointerPte, TRUE);
|
|
|
|
TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
|
|
|
|
MI_WRITE_VALID_PTE(PointerPte, TempPte);
|
|
|
|
|
|
|
|
/* Now initialize the working set list */
|
|
|
|
MiInitializeWorkingSetList(Process);
|
|
|
|
|
|
|
|
/* Sanity check */
|
|
|
|
ASSERT(Process->PhysicalVadRoot == NULL);
|
2010-07-24 15:01:05 +00:00
|
|
|
|
|
|
|
/* Release PFN lock */
|
|
|
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
|
|
|
|
|
|
|
/* Lock the VAD, ARM3-owned ranges away */
|
2012-02-05 18:41:37 +00:00
|
|
|
MiRosTakeOverSharedUserPage(Process);
|
2010-07-24 15:01:05 +00:00
|
|
|
|
|
|
|
/* Check if there's a Section Object */
|
|
|
|
if (SectionObject)
|
|
|
|
{
|
|
|
|
/* Determine the image file name and save it to EPROCESS */
|
|
|
|
FileName = SectionObject->FileObject->FileName;
|
|
|
|
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 */
|
|
|
|
Status = SeInitializeProcessAuditName(SectionObject->FileObject,
|
|
|
|
FALSE,
|
|
|
|
AuditName);
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
2010-11-02 16:29:06 +00:00
|
|
|
INIT_FUNCTION
|
2010-07-24 15:01:05 +00:00
|
|
|
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;
|
2012-03-28 19:41:40 +00:00
|
|
|
|
2010-07-24 15:01:05 +00:00
|
|
|
/* Done */
|
|
|
|
Process->HasAddressSpace = TRUE;//??
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
2010-11-02 16:29:06 +00:00
|
|
|
INIT_FUNCTION
|
2010-07-24 15:01:05 +00:00
|
|
|
MmInitializeHandBuiltProcess2(IN PEPROCESS Process)
|
|
|
|
{
|
2010-12-26 15:23:03 +00:00
|
|
|
/* Lock the VAD, ARM3-owned ranges away */
|
2012-02-05 18:41:37 +00:00
|
|
|
MiRosTakeOverSharedUserPage(Process);
|
2010-07-24 15:01:05 +00:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2010-07-25 12:00:26 +00:00
|
|
|
#ifdef _M_IX86
|
2010-07-24 15:30:24 +00:00
|
|
|
/* FIXME: Evaluate ways to make this portable yet arch-specific */
|
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
MmCreateProcessAddressSpace(IN ULONG MinWs,
|
|
|
|
IN PEPROCESS Process,
|
|
|
|
OUT PULONG_PTR DirectoryTableBase)
|
|
|
|
{
|
|
|
|
KIRQL OldIrql;
|
2010-11-08 12:35:50 +00:00
|
|
|
PFN_NUMBER PdeIndex, HyperIndex, WsListIndex;
|
2010-07-24 15:30:24 +00:00
|
|
|
PMMPTE PointerPte;
|
|
|
|
MMPTE TempPte, PdePte;
|
|
|
|
ULONG PdeOffset;
|
2010-11-08 12:35:50 +00:00
|
|
|
PMMPTE SystemTable, HyperTable;
|
2010-09-29 01:10:28 +00:00
|
|
|
ULONG Color;
|
2010-11-08 12:35:50 +00:00
|
|
|
PMMPFN Pfn1;
|
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 */
|
|
|
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-09-29 01:10:28 +00:00
|
|
|
/* Get a zero page for the PDE, if possible */
|
|
|
|
Color = MI_GET_NEXT_PROCESS_COLOR(Process);
|
2010-11-02 15:16:22 +00:00
|
|
|
MI_SET_USAGE(MI_USAGE_PAGE_DIRECTORY);
|
2010-09-29 01:10:28 +00:00
|
|
|
PdeIndex = MiRemoveZeroPageSafe(Color);
|
|
|
|
if (!PdeIndex)
|
|
|
|
{
|
|
|
|
/* No zero pages, grab a free one */
|
|
|
|
PdeIndex = MiRemoveAnyPage(Color);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-09-29 01:10:28 +00:00
|
|
|
/* Zero it outside the PFN lock */
|
|
|
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
|
|
|
MiZeroPhysicalPage(PdeIndex);
|
|
|
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
|
|
|
}
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-09-29 01:10:28 +00:00
|
|
|
/* Get a zero page for hyperspace, if possible */
|
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 */
|
|
|
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
|
|
|
MiZeroPhysicalPage(HyperIndex);
|
2010-11-08 12:35:50 +00:00
|
|
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get a zero page for the woring set list, if possible */
|
|
|
|
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 */
|
|
|
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
|
|
|
MiZeroPhysicalPage(WsListIndex);
|
2010-09-29 01:10:28 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Release the PFN lock */
|
|
|
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
|
|
|
}
|
2010-07-24 15:30:24 +00:00
|
|
|
|
|
|
|
/* Switch to phase 1 initialization */
|
|
|
|
ASSERT(Process->AddressSpaceInitialized == 0);
|
|
|
|
Process->AddressSpaceInitialized = 1;
|
|
|
|
|
|
|
|
/* Set the base directory pointers */
|
2010-11-08 12:35:50 +00:00
|
|
|
Process->WorkingSetPage = WsListIndex;
|
2010-07-24 15:30:24 +00:00
|
|
|
DirectoryTableBase[0] = PdeIndex << PAGE_SHIFT;
|
|
|
|
DirectoryTableBase[1] = HyperIndex << PAGE_SHIFT;
|
|
|
|
|
|
|
|
/* Make sure we don't already have a page directory setup */
|
|
|
|
ASSERT(Process->Pcb.DirectoryTableBase[0] == 0);
|
2010-12-26 15:23:03 +00:00
|
|
|
|
2010-11-08 12:35:50 +00:00
|
|
|
/* Get a PTE to map hyperspace */
|
|
|
|
PointerPte = MiReserveSystemPtes(1, SystemPteSpace);
|
|
|
|
ASSERT(PointerPte != NULL);
|
|
|
|
|
|
|
|
/* Build it */
|
|
|
|
MI_MAKE_HARDWARE_PTE_KERNEL(&PdePte,
|
|
|
|
PointerPte,
|
|
|
|
MM_READWRITE,
|
|
|
|
HyperIndex);
|
|
|
|
|
|
|
|
/* Set it dirty and map it */
|
2010-11-24 15:21:45 +00:00
|
|
|
MI_MAKE_DIRTY_PAGE(&PdePte);
|
2010-11-08 12:35:50 +00:00
|
|
|
MI_WRITE_VALID_PTE(PointerPte, PdePte);
|
|
|
|
|
|
|
|
/* Now get hyperspace's page table */
|
|
|
|
HyperTable = MiPteToAddress(PointerPte);
|
|
|
|
|
|
|
|
/* Now write the PTE/PDE entry for the working set list index itself */
|
|
|
|
TempPte = ValidKernelPte;
|
|
|
|
TempPte.u.Hard.PageFrameNumber = WsListIndex;
|
2012-02-20 20:50:36 +00:00
|
|
|
/* Hyperspace is local */
|
|
|
|
MI_MAKE_LOCAL_PAGE(&TempPte);
|
2010-11-08 12:35:50 +00:00
|
|
|
PdeOffset = MiAddressToPteOffset(MmWorkingSetList);
|
|
|
|
HyperTable[PdeOffset] = TempPte;
|
|
|
|
|
|
|
|
/* Let go of the system PTE */
|
|
|
|
MiReleaseSystemPtes(PointerPte, 1, SystemPteSpace);
|
|
|
|
|
|
|
|
/* Save the PTE address of the page directory itself */
|
|
|
|
Pfn1 = MiGetPfnEntry(PdeIndex);
|
|
|
|
Pfn1->PteAddress = (PMMPTE)PDE_BASE;
|
2010-07-24 15:30:24 +00:00
|
|
|
|
|
|
|
/* Insert us into the Mm process list */
|
|
|
|
InsertTailList(&MmProcessList, &Process->MmProcessLinks);
|
|
|
|
|
|
|
|
/* Get a PTE to map the page directory */
|
|
|
|
PointerPte = MiReserveSystemPtes(1, SystemPteSpace);
|
|
|
|
ASSERT(PointerPte != NULL);
|
|
|
|
|
|
|
|
/* Build it */
|
|
|
|
MI_MAKE_HARDWARE_PTE_KERNEL(&PdePte,
|
|
|
|
PointerPte,
|
|
|
|
MM_READWRITE,
|
|
|
|
PdeIndex);
|
|
|
|
|
|
|
|
/* Set it dirty and map it */
|
2010-11-24 15:21:45 +00:00
|
|
|
MI_MAKE_DIRTY_PAGE(&PdePte);
|
2010-07-24 15:30:24 +00:00
|
|
|
MI_WRITE_VALID_PTE(PointerPte, PdePte);
|
|
|
|
|
|
|
|
/* Now get the page directory (which we'll double map, so call it a page table */
|
|
|
|
SystemTable = MiPteToAddress(PointerPte);
|
|
|
|
|
|
|
|
/* Copy all the kernel mappings */
|
|
|
|
PdeOffset = MiGetPdeOffset(MmSystemRangeStart);
|
|
|
|
RtlCopyMemory(&SystemTable[PdeOffset],
|
|
|
|
MiAddressToPde(MmSystemRangeStart),
|
|
|
|
PAGE_SIZE - PdeOffset * sizeof(MMPTE));
|
|
|
|
|
|
|
|
/* Now write the PTE/PDE entry for hyperspace itself */
|
|
|
|
TempPte = ValidKernelPte;
|
|
|
|
TempPte.u.Hard.PageFrameNumber = HyperIndex;
|
|
|
|
PdeOffset = MiGetPdeOffset(HYPER_SPACE);
|
|
|
|
SystemTable[PdeOffset] = TempPte;
|
|
|
|
|
|
|
|
/* Sanity check */
|
|
|
|
PdeOffset++;
|
|
|
|
ASSERT(MiGetPdeOffset(MmHyperSpaceEnd) >= PdeOffset);
|
|
|
|
|
|
|
|
/* Now do the x86 trick of making the PDE a page table itself */
|
|
|
|
PdeOffset = MiGetPdeOffset(PTE_BASE);
|
|
|
|
TempPte.u.Hard.PageFrameNumber = PdeIndex;
|
|
|
|
SystemTable[PdeOffset] = TempPte;
|
|
|
|
|
|
|
|
/* Let go of the system PTE */
|
|
|
|
MiReleaseSystemPtes(PointerPte, 1, SystemPteSpace);
|
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-25 12:00:26 +00:00
|
|
|
#endif
|
2010-07-24 15:30:24 +00:00
|
|
|
|
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;
|
|
|
|
|
|
|
|
/* 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
|
|
|
|
2010-10-05 05:00:19 +00:00
|
|
|
/* Skip ARM3 fake VADs, they'll be freed by MmDeleteProcessAddresSpace */
|
|
|
|
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);
|
|
|
|
}
|
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
|
|
|
|
MmDeleteProcessAddressSpace2(IN PEPROCESS Process)
|
|
|
|
{
|
|
|
|
PMMPFN Pfn1, Pfn2;
|
|
|
|
KIRQL OldIrql;
|
|
|
|
PFN_NUMBER PageFrameIndex;
|
|
|
|
|
|
|
|
//ASSERT(Process->CommitCharge == 0);
|
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
|
|
|
/* Acquire the PFN lock */
|
|
|
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
|
|
|
|
|
|
|
/* 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-20 20:50:36 +00:00
|
|
|
MiReleaseSystemPtes(MiAddressToPte(Process->Vm.VmWorkingSetList), 1, SystemPteSpace);
|
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 */
|
|
|
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
|
|
|
|
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 */
|