diff --git a/reactos/ntoskrnl/include/internal/mm.h b/reactos/ntoskrnl/include/internal/mm.h index f306da2d1c5..0812a81f84e 100644 --- a/reactos/ntoskrnl/include/internal/mm.h +++ b/reactos/ntoskrnl/include/internal/mm.h @@ -496,6 +496,12 @@ MmIsSessionAddress( IN PVOID Address ); +ULONG +NTAPI +MmGetSessionId( + IN PEPROCESS Process +); + /* marea.c *******************************************************************/ NTSTATUS diff --git a/reactos/ntoskrnl/io/iomgr/irp.c b/reactos/ntoskrnl/io/iomgr/irp.c index aa1e977daa1..f88e80f46d8 100644 --- a/reactos/ntoskrnl/io/iomgr/irp.c +++ b/reactos/ntoskrnl/io/iomgr/irp.c @@ -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; } diff --git a/reactos/ntoskrnl/mm/ARM3/i386/init.c b/reactos/ntoskrnl/mm/ARM3/i386/init.c index 1e0e166faa6..4dbb4bc3768 100644 --- a/reactos/ntoskrnl/mm/ARM3/i386/init.c +++ b/reactos/ntoskrnl/mm/ARM3/i386/init.c @@ -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 */ diff --git a/reactos/ntoskrnl/mm/ARM3/miarm.h b/reactos/ntoskrnl/mm/ARM3/miarm.h index 67302b42f37..8b441da3d16 100644 --- a/reactos/ntoskrnl/mm/ARM3/miarm.h +++ b/reactos/ntoskrnl/mm/ARM3/miarm.h @@ -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( diff --git a/reactos/ntoskrnl/mm/ARM3/mminit.c b/reactos/ntoskrnl/mm/ARM3/mminit.c index f18323ea22a..3d4e1b0f4ac 100644 --- a/reactos/ntoskrnl/mm/ARM3/mminit.c +++ b/reactos/ntoskrnl/mm/ARM3/mminit.c @@ -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 diff --git a/reactos/ntoskrnl/mm/ARM3/pagfault.c b/reactos/ntoskrnl/mm/ARM3/pagfault.c index fdc3eb32e0f..98f11d4fbec 100644 --- a/reactos/ntoskrnl/mm/ARM3/pagfault.c +++ b/reactos/ntoskrnl/mm/ARM3/pagfault.c @@ -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 { diff --git a/reactos/ntoskrnl/mm/ARM3/procsup.c b/reactos/ntoskrnl/mm/ARM3/procsup.c index 69a5661d01c..44ae96a3cd6 100644 --- a/reactos/ntoskrnl/mm/ARM3/procsup.c +++ b/reactos/ntoskrnl/mm/ARM3/procsup.c @@ -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; diff --git a/reactos/ntoskrnl/mm/ARM3/section.c b/reactos/ntoskrnl/mm/ARM3/section.c index e6cd6380c5d..ce7fdebbdd1 100644 --- a/reactos/ntoskrnl/mm/ARM3/section.c +++ b/reactos/ntoskrnl/mm/ARM3/section.c @@ -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, diff --git a/reactos/ntoskrnl/ps/process.c b/reactos/ntoskrnl/ps/process.c index 535c4769919..7207ee39002 100644 --- a/reactos/ntoskrnl/ps/process.c +++ b/reactos/ntoskrnl/ps/process.c @@ -1114,8 +1114,7 @@ ULONG NTAPI PsGetCurrentProcessSessionId(VOID) { - // FIXME: this is broken! - return PtrToUlong(PsGetCurrentProcess()->Session); + return MmGetSessionId(PsGetCurrentProcess()); } /* diff --git a/reactos/ntoskrnl/ps/security.c b/reactos/ntoskrnl/ps/security.c index 2bd401cde20..76f33ff3d16 100644 --- a/reactos/ntoskrnl/ps/security.c +++ b/reactos/ntoskrnl/ps/security.c @@ -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);