mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 08:55:19 +00:00
[NTOSKRNL]: Implement last bits of session space support (minus session pool). Processes now have a ->Session pointer! Implement and enable MmSessionId in a bunch of places.
[NTOSKRNL]: Set MiSessionSpaceWs address and use where needed. [NTOSKRNL]: Initialize the session working set, and add support to MiLockWorkingSet and MiUnlockWorkingSet for session WS. [NTOSKRNL]: Implement MiSessionAddProcess and MiSessionRemoveProcess which does the work required for this. [NTOSKRNL]: Fix IoGetIrpRequestorProcess. In my private branch, MmMapViewInSessionSpace is working fine for the user and GDI heaps. Will enable after TestBot tests. svn path=/trunk/; revision=57011
This commit is contained in:
parent
4f1b5e8e7b
commit
b3b73888b1
10 changed files with 462 additions and 46 deletions
|
@ -496,6 +496,12 @@ MmIsSessionAddress(
|
|||
IN PVOID Address
|
||||
);
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
MmGetSessionId(
|
||||
IN PEPROCESS Process
|
||||
);
|
||||
|
||||
/* marea.c *******************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
|
|
|
@ -1615,7 +1615,14 @@ IoGetRequestorProcess(IN PIRP Irp)
|
|||
/* Return the requestor process */
|
||||
if (Irp->Tail.Overlay.Thread)
|
||||
{
|
||||
return Irp->Tail.Overlay.Thread->ThreadsProcess;
|
||||
if (Irp->ApcEnvironment == OriginalApcEnvironment)
|
||||
{
|
||||
return Irp->Tail.Overlay.Thread->ThreadsProcess;
|
||||
}
|
||||
else if (Irp->ApcEnvironment == AttachedApcEnvironment)
|
||||
{
|
||||
return (PEPROCESS)Irp->Tail.Overlay.Thread->Tcb.ApcState.Process;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -1631,10 +1638,8 @@ IoGetRequestorProcessId(IN PIRP Irp)
|
|||
PEPROCESS Process;
|
||||
|
||||
/* Return the requestor process' id */
|
||||
if ((Process = IoGetRequestorProcess(Irp)))
|
||||
{
|
||||
return PtrToUlong(Process->UniqueProcessId);
|
||||
}
|
||||
Process = IoGetRequestorProcess(Irp);
|
||||
if (Process) return PtrToUlong(Process->UniqueProcessId);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1650,10 +1655,10 @@ IoGetRequestorSessionId(IN PIRP Irp,
|
|||
PEPROCESS Process;
|
||||
|
||||
/* Return the session */
|
||||
if ((Process = IoGetRequestorProcess(Irp)))
|
||||
if (Irp->Tail.Overlay.Thread)
|
||||
{
|
||||
// FIXME: broken
|
||||
*pSessionId = PtrToUlong(Process->Session);
|
||||
Process = Irp->Tail.Overlay.Thread->ThreadsProcess;
|
||||
*pSessionId = MmGetSessionId(Process);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -110,6 +110,7 @@ MiInitializeSessionSpaceLayout()
|
|||
MiSessionImagePteStart = MiAddressToPte(MiSessionImageStart);
|
||||
MiSessionImagePteEnd = MiAddressToPte(MiSessionImageEnd);
|
||||
MiSessionBasePte = MiAddressToPte(MmSessionBase);
|
||||
MiSessionSpaceWs = (PVOID)((ULONG_PTR)MiSessionViewStart + MmSessionViewSize);
|
||||
MiSessionLastPte = MiAddressToPte(MiSessionSpaceEnd);
|
||||
|
||||
/* Initialize session space */
|
||||
|
|
|
@ -687,6 +687,7 @@ extern PVOID MiSystemViewStart;
|
|||
extern PVOID MiSessionPoolEnd; // 0xBE000000
|
||||
extern PVOID MiSessionPoolStart; // 0xBD000000
|
||||
extern PVOID MiSessionViewStart; // 0xBE000000
|
||||
extern PVOID MiSessionSpaceWs;
|
||||
extern ULONG MmMaximumDeadKernelStacks;
|
||||
extern SLIST_HEADER MmDeadStackSListHead;
|
||||
extern MM_AVL_TABLE MmSectionBasedRoot;
|
||||
|
@ -1059,9 +1060,10 @@ MiLockWorkingSet(IN PETHREAD Thread,
|
|||
}
|
||||
else if (WorkingSet->Flags.SessionSpace)
|
||||
{
|
||||
/* We don't implement this yet */
|
||||
UNIMPLEMENTED;
|
||||
while (TRUE);
|
||||
/* Own the session working set */
|
||||
ASSERT((Thread->OwnsSessionWorkingSetExclusive == FALSE) &&
|
||||
(Thread->OwnsSessionWorkingSetShared == FALSE));
|
||||
Thread->OwnsSessionWorkingSetExclusive = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1093,9 +1095,10 @@ MiUnlockWorkingSet(IN PETHREAD Thread,
|
|||
}
|
||||
else if (WorkingSet->Flags.SessionSpace)
|
||||
{
|
||||
/* We don't implement this yet */
|
||||
UNIMPLEMENTED;
|
||||
while (TRUE);
|
||||
/* Release the session working set */
|
||||
ASSERT((Thread->OwnsSessionWorkingSetExclusive == TRUE) ||
|
||||
(Thread->OwnsSessionWorkingSetShared == TRUE));
|
||||
Thread->OwnsSessionWorkingSetExclusive = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1610,6 +1613,24 @@ MiInitializeSystemSpaceMap(
|
|||
IN PMMSESSION InputSession OPTIONAL
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
MiSessionRemoveProcess(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
MiReleaseProcessReferenceToSessionDataPage(
|
||||
IN PMM_SESSION_SPACE SessionGlobal
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
MiSessionAddProcess(
|
||||
IN PEPROCESS NewProcess
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiSessionCommitPageTables(
|
||||
|
|
|
@ -128,6 +128,7 @@ PFN_NUMBER MmSizeOfPagedPoolInPages = MI_MIN_INIT_PAGED_POOLSIZE / PAGE_SIZE;
|
|||
PVOID MiSessionSpaceEnd; // 0xC0000000
|
||||
PVOID MiSessionImageEnd; // 0xC0000000
|
||||
PVOID MiSessionImageStart; // 0xBF800000
|
||||
PVOID MiSessionSpaceWs;
|
||||
PVOID MiSessionViewStart; // 0xBE000000
|
||||
PVOID MiSessionPoolEnd; // 0xBE000000
|
||||
PVOID MiSessionPoolStart; // 0xBD000000
|
||||
|
|
|
@ -153,9 +153,79 @@ NTSTATUS
|
|||
FASTCALL
|
||||
MiCheckPdeForSessionSpace(IN PVOID Address)
|
||||
{
|
||||
/* Code not yet tested */
|
||||
ASSERT(FALSE);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
MMPTE TempPde;
|
||||
PMMPTE PointerPde;
|
||||
PVOID SessionPageTable;
|
||||
ULONG Index;
|
||||
|
||||
/* Is this a session PTE? */
|
||||
if (MI_IS_SESSION_PTE(Address))
|
||||
{
|
||||
/* Make sure the PDE for session space is valid */
|
||||
PointerPde = MiAddressToPde(MmSessionSpace);
|
||||
if (!PointerPde->u.Hard.Valid)
|
||||
{
|
||||
/* This means there's no valid session, bail out */
|
||||
DbgPrint("MiCheckPdeForSessionSpace: No current session for PTE %p\n",
|
||||
Address);
|
||||
DbgBreakPoint();
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
|
||||
/* Now get the session-specific page table for this address */
|
||||
SessionPageTable = MiPteToAddress(Address);
|
||||
PointerPde = MiPteToAddress(Address);
|
||||
if (PointerPde->u.Hard.Valid) return STATUS_WAIT_1;
|
||||
|
||||
/* It's not valid, so find it in the page table array */
|
||||
Index = ((ULONG_PTR)SessionPageTable - (ULONG_PTR)MmSessionBase) >> 22;
|
||||
TempPde.u.Long = MmSessionSpace->PageTables[Index].u.Long;
|
||||
if (TempPde.u.Hard.Valid)
|
||||
{
|
||||
/* The copy is valid, so swap it in */
|
||||
InterlockedExchange((PLONG)PointerPde, TempPde.u.Long);
|
||||
return STATUS_WAIT_1;
|
||||
}
|
||||
|
||||
/* We don't seem to have allocated a page table for this address yet? */
|
||||
DbgPrint("MiCheckPdeForSessionSpace: No Session PDE for PTE %p, %p\n",
|
||||
PointerPde->u.Long, SessionPageTable);
|
||||
DbgBreakPoint();
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
|
||||
/* Is the address also a session address? If not, we're done */
|
||||
if (!MI_IS_SESSION_ADDRESS(Address)) return STATUS_SUCCESS;
|
||||
|
||||
/* It is, so again get the PDE for session space */
|
||||
PointerPde = MiAddressToPde(MmSessionSpace);
|
||||
if (!PointerPde->u.Hard.Valid)
|
||||
{
|
||||
/* This means there's no valid session, bail out */
|
||||
DbgPrint("MiCheckPdeForSessionSpace: No current session for VA %p\n",
|
||||
Address);
|
||||
DbgBreakPoint();
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
|
||||
/* Now get the PDE for the address itself */
|
||||
PointerPde = MiAddressToPde(Address);
|
||||
if (!PointerPde->u.Hard.Valid)
|
||||
{
|
||||
/* Do the swap, we should be good to go */
|
||||
Index = ((ULONG_PTR)Address - (ULONG_PTR)MmSessionBase) >> 22;
|
||||
PointerPde->u.Long = MmSessionSpace->PageTables[Index].u.Long;
|
||||
if (PointerPde->u.Hard.Valid) return STATUS_WAIT_1;
|
||||
|
||||
/* We had not allocated a page table for this session address yet, fail! */
|
||||
DbgPrint("MiCheckPdeForSessionSpace: No Session PDE for VA %p, %p\n",
|
||||
PointerPde->u.Long, Address);
|
||||
DbgBreakPoint();
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
|
||||
/* It's valid, so there's nothing to do */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
|
@ -305,16 +375,14 @@ MiResolveDemandZeroFault(IN PVOID Address,
|
|||
/* Check if we need a zero page */
|
||||
NeedZero = (OldIrql != MM_NOIRQL);
|
||||
|
||||
#if 0
|
||||
/* Session-backed image views must be zeroed */
|
||||
if ((Process == HYDRA_PROCESS) &&
|
||||
((MI_IS_SESSION_IMAGE_ADDRESS(Address)) ||
|
||||
((Address >= (PVOID)MiSessionViewStart) &&
|
||||
(Address < (PVOID)MiSessionSpaceWs))))
|
||||
((Address >= MiSessionViewStart) && (Address < MiSessionSpaceWs))))
|
||||
{
|
||||
NeedZero = TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Hardcode unknown color */
|
||||
Color = 0xFFFFFFFF;
|
||||
}
|
||||
|
@ -1200,18 +1268,22 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
|||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Not yet handled */
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if this was a session PTE that needs to remap the session PDE */
|
||||
if (MI_IS_SESSION_PTE(Address))
|
||||
{
|
||||
/* Not yet handled */
|
||||
ASSERT(FALSE);
|
||||
/* Do the remapping */
|
||||
Status = MiCheckPdeForSessionSpace(Address);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* It failed, this address is invalid */
|
||||
KeBugCheckEx(PAGE_FAULT_IN_NONPAGED_AREA,
|
||||
(ULONG_PTR)Address,
|
||||
StoreInstruction,
|
||||
(ULONG_PTR)TrapInformation,
|
||||
6);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for a fault on the page table or hyperspace */
|
||||
|
@ -1249,8 +1321,17 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
|||
}
|
||||
else
|
||||
{
|
||||
/* Not yet handled */
|
||||
ASSERT(FALSE);
|
||||
/* Use the session process and working set */
|
||||
CurrentProcess = HYDRA_PROCESS;
|
||||
WorkingSet = &MmSessionSpace->GlobalVirtualAddress->Vm;
|
||||
|
||||
/* Make sure we don't have a recursive working set lock */
|
||||
if ((CurrentThread->OwnsSessionWorkingSetExclusive) ||
|
||||
(CurrentThread->OwnsSessionWorkingSetShared))
|
||||
{
|
||||
/* Fail */
|
||||
return STATUS_IN_PAGE_ERROR | 0x10000000;
|
||||
}
|
||||
}
|
||||
|
||||
/* Acquire the working set lock */
|
||||
|
@ -1282,8 +1363,28 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
|||
}
|
||||
}
|
||||
|
||||
/* Case not yet handled */
|
||||
ASSERT(!IsSessionAddress);
|
||||
/* Check for read-only write in session space */
|
||||
if ((IsSessionAddress) &&
|
||||
(StoreInstruction) &&
|
||||
!(TempPte.u.Hard.Write))
|
||||
{
|
||||
/* Sanity check */
|
||||
ASSERT(MI_IS_SESSION_IMAGE_ADDRESS(Address));
|
||||
|
||||
/* Was this COW? */
|
||||
if (TempPte.u.Hard.CopyOnWrite == 0)
|
||||
{
|
||||
/* Then this is not allowed */
|
||||
KeBugCheckEx(ATTEMPTED_WRITE_TO_READONLY_MEMORY,
|
||||
(ULONG_PTR)Address,
|
||||
(ULONG_PTR)TempPte.u.Long,
|
||||
(ULONG_PTR)TrapInformation,
|
||||
13);
|
||||
}
|
||||
|
||||
/* Otherwise, handle COW */
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
/* Release the working set */
|
||||
MiUnlockWorkingSet(CurrentThread, WorkingSet);
|
||||
|
@ -1315,8 +1416,16 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
|
|||
/* Get the prototype PTE! */
|
||||
ProtoPte = MiProtoPteToPte(&TempPte);
|
||||
|
||||
/* Case not yet handled */
|
||||
ASSERT(!IsSessionAddress);
|
||||
/* Do we need to locate the prototype PTE in session space? */
|
||||
if ((IsSessionAddress) &&
|
||||
(TempPte.u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED))
|
||||
{
|
||||
/* Yep, go find it as well as the VAD for it */
|
||||
ProtoPte = MiCheckVirtualAddress(Address,
|
||||
&ProtectionCode,
|
||||
&Vad);
|
||||
ASSERT(ProtoPte != NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -577,9 +577,7 @@ MmGetSessionLocaleId(VOID)
|
|||
//
|
||||
// Get the Locale ID
|
||||
//
|
||||
#if ROS_HAS_SESSIONS
|
||||
return ((PMM_SESSION_SPACE)Process->Session)->LocaleId;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -698,7 +696,7 @@ MmCreatePeb(IN PEPROCESS Process,
|
|||
//
|
||||
// Session ID
|
||||
//
|
||||
if (Process->Session) Peb->SessionId = 0; // MmGetSessionId(Process);
|
||||
MmGetSessionId(Process);
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
|
@ -1317,6 +1315,9 @@ MmCreateProcessAddressSpace(IN ULONG MinWs,
|
|||
|
||||
/* Let go of the system PTE */
|
||||
MiReleaseSystemPtes(PointerPte, 1, SystemPteSpace);
|
||||
|
||||
/* Add the process to the session */
|
||||
MiSessionAddProcess(Process);
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
@ -1332,6 +1333,9 @@ MmCleanProcessAddressSpace(IN PEPROCESS Process)
|
|||
/* Only support this */
|
||||
ASSERT(Process->AddressSpaceInitialized == 2);
|
||||
|
||||
/* Remove from the session */
|
||||
MiSessionRemoveProcess();
|
||||
|
||||
/* Lock the process address space from changes */
|
||||
MmLockAddressSpace(&Process->Vm);
|
||||
|
||||
|
@ -1383,6 +1387,7 @@ MmCleanProcessAddressSpace(IN PEPROCESS Process)
|
|||
/* Free the VAD memory */
|
||||
ExFreePool(Vad);
|
||||
}
|
||||
|
||||
/* Delete the shared user data section */
|
||||
MiDeleteVirtualAddresses(USER_SHARED_DATA, USER_SHARED_DATA, NULL);
|
||||
|
||||
|
@ -1447,8 +1452,8 @@ MmDeleteProcessAddressSpace2(IN PEPROCESS Process)
|
|||
/* Release the PFN lock */
|
||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||
|
||||
/* No support for sessions yet */
|
||||
ASSERT(Process->Session == 0);
|
||||
/* Drop a reference on the session */
|
||||
if (Process->Session) MiReleaseProcessReferenceToSessionDataPage(Process->Session);
|
||||
|
||||
/* Clear out the PDE pages */
|
||||
Process->Pcb.DirectoryTableBase[0] = 0;
|
||||
|
@ -1528,6 +1533,257 @@ MiSessionLeader(IN PEPROCESS Process)
|
|||
KeReleaseQueuedSpinLock(LockQueueExpansionLock, OldIrql);
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
MmGetSessionId(IN PEPROCESS Process)
|
||||
{
|
||||
PMM_SESSION_SPACE SessionGlobal;
|
||||
|
||||
/* The session leader is always session zero */
|
||||
if (Process->Vm.Flags.SessionLeader == 1) return 0;
|
||||
|
||||
/* Otherwise, get the session global, and read the session ID from it */
|
||||
SessionGlobal = (PMM_SESSION_SPACE)Process->Session;
|
||||
if (!SessionGlobal) return 0;
|
||||
return SessionGlobal->SessionId;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
MiReleaseProcessReferenceToSessionDataPage(IN PMM_SESSION_SPACE SessionGlobal)
|
||||
{
|
||||
ULONG i, SessionId;
|
||||
PMMPTE PointerPte;
|
||||
PFN_NUMBER PageFrameIndex[MI_SESSION_DATA_PAGES_MAXIMUM];
|
||||
PMMPFN Pfn1;
|
||||
KIRQL OldIrql;
|
||||
|
||||
/* Is there more than just this reference? If so, bail out */
|
||||
if (InterlockedDecrement(&SessionGlobal->ProcessReferenceToSession)) return;
|
||||
|
||||
/* Get the session ID */
|
||||
SessionId = SessionGlobal->SessionId;
|
||||
DPRINT1("Last process in sessino %d going down!!!\n", SessionId);
|
||||
|
||||
/* Free the session page tables */
|
||||
ExFreePool(SessionGlobal->PageTables);
|
||||
ASSERT(!MI_IS_PHYSICAL_ADDRESS(SessionGlobal));
|
||||
|
||||
/* Capture the data page PFNs */
|
||||
PointerPte = MiAddressToPte(SessionGlobal);
|
||||
for (i = 0; i < MiSessionDataPages; i++)
|
||||
{
|
||||
PageFrameIndex[i] = PFN_FROM_PTE(PointerPte + i);
|
||||
}
|
||||
|
||||
/* Release them */
|
||||
MiReleaseSystemPtes(PointerPte, MiSessionDataPages, SystemPteSpace);
|
||||
|
||||
/* Mark them as deleted */
|
||||
for (i = 0; i < MiSessionDataPages; i++)
|
||||
{
|
||||
Pfn1 = MI_PFN_ELEMENT(PageFrameIndex[i]);
|
||||
MI_SET_PFN_DELETED(Pfn1);
|
||||
}
|
||||
|
||||
/* Loop every data page and drop a reference count */
|
||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||
for (i = 0; i < MiSessionDataPages; i++)
|
||||
{
|
||||
/* Sanity check that the page is correct, then decrement it */
|
||||
Pfn1 = MI_PFN_ELEMENT(PageFrameIndex[i]);
|
||||
ASSERT(Pfn1->u2.ShareCount == 1);
|
||||
ASSERT(Pfn1->u3.e2.ReferenceCount == 1);
|
||||
MiDecrementShareCount(Pfn1, PageFrameIndex[i]);
|
||||
}
|
||||
|
||||
/* Done playing with pages, release the lock */
|
||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||
|
||||
/* Decrement the number of data pages */
|
||||
InterlockedDecrement(&MmSessionDataPages);
|
||||
|
||||
/* Free this session ID from the session bitmap */
|
||||
KeAcquireGuardedMutex(&MiSessionIdMutex);
|
||||
ASSERT(RtlCheckBit(MiSessionIdBitmap, SessionId));
|
||||
RtlClearBit(MiSessionIdBitmap, SessionId);
|
||||
KeReleaseGuardedMutex(&MiSessionIdMutex);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
MiSessionRemoveProcess(VOID)
|
||||
{
|
||||
PEPROCESS CurrentProcess = PsGetCurrentProcess();
|
||||
|
||||
/* If the process isn't already in a session, or if it's the leader... */
|
||||
if (!(CurrentProcess->Flags & PSF_PROCESS_IN_SESSION_BIT) ||
|
||||
(CurrentProcess->Vm.Flags.SessionLeader))
|
||||
{
|
||||
/* Then there's nothing to do */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Sanity check */
|
||||
ASSERT(MmIsAddressValid(MmSessionSpace) == TRUE);
|
||||
|
||||
/* Remove the process from the list ,and dereference the session */
|
||||
RemoveEntryList(&CurrentProcess->SessionProcessLinks);
|
||||
//MiDereferenceSession();
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
MiSessionAddProcess(IN PEPROCESS NewProcess)
|
||||
{
|
||||
PMM_SESSION_SPACE SessionGlobal;
|
||||
|
||||
/* The current process must already be in a session */
|
||||
if (!(PsGetCurrentProcess()->Flags & PSF_PROCESS_IN_SESSION_BIT)) return;
|
||||
|
||||
/* Sanity check */
|
||||
ASSERT(MmIsAddressValid(MmSessionSpace) == TRUE);
|
||||
|
||||
/* Get the global session */
|
||||
SessionGlobal = MmSessionSpace->GlobalVirtualAddress;
|
||||
|
||||
/* Increment counters */
|
||||
InterlockedIncrement((PLONG)&SessionGlobal->ReferenceCount);
|
||||
InterlockedIncrement(&SessionGlobal->ResidentProcessCount);
|
||||
InterlockedIncrement(&SessionGlobal->ProcessReferenceToSession);
|
||||
|
||||
/* Set the session pointer */
|
||||
ASSERT(NewProcess->Session == NULL);
|
||||
NewProcess->Session = SessionGlobal;
|
||||
|
||||
/* Insert it into the process list */
|
||||
InsertTailList(&SessionGlobal->ProcessList, &NewProcess->SessionProcessLinks);
|
||||
|
||||
/* Set the flag */
|
||||
PspSetProcessFlag(NewProcess, PSF_PROCESS_IN_SESSION_BIT);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiSessionInitializeWorkingSetList(VOID)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
PMMPTE PointerPte, PointerPde;
|
||||
MMPTE TempPte;
|
||||
ULONG Color, Index;
|
||||
PFN_NUMBER PageFrameIndex;
|
||||
PMM_SESSION_SPACE SessionGlobal;
|
||||
BOOLEAN AllocatedPageTable;
|
||||
PMMWSL WorkingSetList;
|
||||
|
||||
/* Get pointers to session global and the session working set list */
|
||||
SessionGlobal = MmSessionSpace->GlobalVirtualAddress;
|
||||
WorkingSetList = (PMMWSL)MiSessionSpaceWs;
|
||||
|
||||
/* Fill out the two pointers */
|
||||
MmSessionSpace->Vm.VmWorkingSetList = WorkingSetList;
|
||||
MmSessionSpace->Wsle = (PMMWSLE)WorkingSetList->UsedPageTableEntries;
|
||||
|
||||
/* Get the PDE for the working set, and check if it's already allocated */
|
||||
PointerPde = MiAddressToPde(WorkingSetList);
|
||||
if (PointerPde->u.Hard.Valid == 1)
|
||||
{
|
||||
/* Nope, we'll have to do it */
|
||||
ASSERT(PointerPde->u.Hard.Global == 0);
|
||||
AllocatedPageTable = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Yep, that makes our job easier */
|
||||
AllocatedPageTable = TRUE;
|
||||
}
|
||||
|
||||
/* Get the PTE for the working set */
|
||||
PointerPte = MiAddressToPte(WorkingSetList);
|
||||
|
||||
/* Initialize the working set lock, and lock the PFN database */
|
||||
ExInitializePushLock(&SessionGlobal->Vm.WorkingSetMutex);
|
||||
//MmLockPageableSectionByHandle(ExPageLockHandle);
|
||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||
|
||||
/* Check if we need a page table */
|
||||
if (AllocatedPageTable == TRUE)
|
||||
{
|
||||
/* Get a zeroed colored zero page */
|
||||
Color = MI_GET_NEXT_COLOR();
|
||||
PageFrameIndex = MiRemoveZeroPageSafe(Color);
|
||||
if (!PageFrameIndex)
|
||||
{
|
||||
/* No zero pages, grab a free one */
|
||||
PageFrameIndex = MiRemoveAnyPage(Color);
|
||||
|
||||
/* Zero it outside the PFN lock */
|
||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||
MiZeroPhysicalPage(PageFrameIndex);
|
||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||
}
|
||||
|
||||
/* Write a valid PDE for it */
|
||||
TempPte.u.Long = ValidKernelPdeLocal.u.Long;
|
||||
TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
|
||||
MI_WRITE_VALID_PTE(PointerPde, TempPte);
|
||||
|
||||
/* Add this into the list */
|
||||
Index = ((ULONG_PTR)WorkingSetList - (ULONG_PTR)MmSessionBase) >> 22;
|
||||
MmSessionSpace->PageTables[Index] = TempPte;
|
||||
|
||||
/* Initialize the page directory page, and now zero the working set list itself */
|
||||
MiInitializePfnForOtherProcess(PageFrameIndex,
|
||||
PointerPde,
|
||||
MmSessionSpace->SessionPageDirectoryIndex);
|
||||
KeZeroPages(PointerPte, PAGE_SIZE);
|
||||
}
|
||||
|
||||
/* Get a zeroed colored zero page */
|
||||
Color = MI_GET_NEXT_COLOR();
|
||||
PageFrameIndex = MiRemoveZeroPageSafe(Color);
|
||||
if (!PageFrameIndex)
|
||||
{
|
||||
/* No zero pages, grab a free one */
|
||||
PageFrameIndex = MiRemoveAnyPage(Color);
|
||||
|
||||
/* Zero it outside the PFN lock */
|
||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||
MiZeroPhysicalPage(PageFrameIndex);
|
||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||
}
|
||||
|
||||
/* Write a valid PTE for it */
|
||||
TempPte.u.Long = ValidKernelPteLocal.u.Long;
|
||||
TempPte.u.Hard.Dirty = TRUE;
|
||||
TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
|
||||
|
||||
/* Initialize the working set list page */
|
||||
MiInitializePfnAndMakePteValid(PageFrameIndex, PointerPte, TempPte);
|
||||
|
||||
/* Now we can release the PFN database lock */
|
||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||
|
||||
/* Fill out the working set structure */
|
||||
MmSessionSpace->Vm.Flags.SessionSpace = 1;
|
||||
MmSessionSpace->Vm.MinimumWorkingSetSize = 20;
|
||||
MmSessionSpace->Vm.MaximumWorkingSetSize = 384;
|
||||
WorkingSetList->LastEntry = 20;
|
||||
WorkingSetList->HashTable = NULL;
|
||||
WorkingSetList->HashTableSize = 0;
|
||||
WorkingSetList->Wsle = MmSessionSpace->Wsle;
|
||||
|
||||
/* FIXME: Handle list insertions */
|
||||
ASSERT(SessionGlobal->WsListEntry.Flink == NULL);
|
||||
ASSERT(SessionGlobal->WsListEntry.Blink == NULL);
|
||||
ASSERT(SessionGlobal->Vm.WorkingSetExpansionLinks.Flink == NULL);
|
||||
ASSERT(SessionGlobal->Vm.WorkingSetExpansionLinks.Blink == NULL);
|
||||
|
||||
/* All done, return */
|
||||
//MmUnlockPageableImageSection(ExPageLockHandle);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiSessionCreateInternal(OUT PULONG SessionId)
|
||||
|
@ -1770,12 +2026,31 @@ MmSessionCreate(OUT PULONG SessionId)
|
|||
MiSessionLeader(Process);
|
||||
}
|
||||
|
||||
/* FIXME: Actually create a session */
|
||||
/* Create the session */
|
||||
KeEnterCriticalRegion();
|
||||
Status = MiSessionCreateInternal(SessionId);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
KeLeaveCriticalRegion();
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Set up the session working set */
|
||||
Status = MiSessionInitializeWorkingSetList();
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Fail */
|
||||
//MiDereferenceSession();
|
||||
ASSERT(FALSE);
|
||||
KeLeaveCriticalRegion();
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* All done */
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
/* Set and assert the flags, and return */
|
||||
MmSessionSpace->u.Flags.Initialized = 1;
|
||||
PspSetProcessFlag(Process, PSF_PROCESS_IN_SESSION_BIT);
|
||||
ASSERT(MiSessionLeaderExists == 1);
|
||||
return Status;
|
||||
|
|
|
@ -827,7 +827,7 @@ MiSessionCommitPageTables(IN PVOID StartVa,
|
|||
/* Get the start and end PDE, then loop each one */
|
||||
StartPde = MiAddressToPde(StartVa);
|
||||
EndPde = MiAddressToPde((PVOID)((ULONG_PTR)EndVa - 1));
|
||||
Index = (ULONG_PTR)StartVa >> 22;
|
||||
Index = ((ULONG_PTR)StartVa - (ULONG_PTR)MmSessionBase) >> 22;
|
||||
while (StartPde <= EndPde)
|
||||
{
|
||||
/* If we don't already have a page table for it, increment count */
|
||||
|
@ -843,7 +843,7 @@ MiSessionCommitPageTables(IN PVOID StartVa,
|
|||
|
||||
/* Reset the start PDE and index */
|
||||
StartPde = MiAddressToPde(StartVa);
|
||||
Index = (ULONG_PTR)StartVa >> 22;
|
||||
Index = ((ULONG_PTR)StartVa - (ULONG_PTR)MmSessionBase) >> 22;
|
||||
|
||||
/* Loop each PDE while holding the working set lock */
|
||||
// MiLockWorkingSet(PsGetCurrentThread(),
|
||||
|
@ -2330,7 +2330,6 @@ MmMapViewInSessionSpace(IN PVOID Section,
|
|||
|
||||
/* Use the system space API, but with the session view instead */
|
||||
ASSERT(MmIsAddressValid(MmSessionSpace) == TRUE);
|
||||
ASSERT(FALSE);
|
||||
return MiMapViewInSystemSpace(Section,
|
||||
&MmSessionSpace->Session,
|
||||
MappedBase,
|
||||
|
|
|
@ -1114,8 +1114,7 @@ ULONG
|
|||
NTAPI
|
||||
PsGetCurrentProcessSessionId(VOID)
|
||||
{
|
||||
// FIXME: this is broken!
|
||||
return PtrToUlong(PsGetCurrentProcess()->Session);
|
||||
return MmGetSessionId(PsGetCurrentProcess());
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -86,7 +86,7 @@ PspInitializeProcessSecurity(IN PEPROCESS Process,
|
|||
Status = SeSubProcessToken(ParentToken,
|
||||
&NewToken,
|
||||
TRUE,
|
||||
0);//MmGetSessionId(Process));
|
||||
MmGetSessionId(Process));
|
||||
|
||||
/* Dereference the Parent */
|
||||
ObFastDereferenceObject(&Parent->Token, ParentToken);
|
||||
|
|
Loading…
Reference in a new issue