/* * PROJECT: ReactOS Windows-Compatible Session Manager * LICENSE: BSD 2-Clause License * FILE: base/system/smss/smsessn.c * PURPOSE: Main SMSS Code * PROGRAMMERS: Alex Ionescu */ /* INCLUDES *******************************************************************/ #include "smss.h" #define NDEBUG #include /* GLOBALS ********************************************************************/ typedef struct _SMP_SESSION { LIST_ENTRY Entry; ULONG SessionId; PSMP_SUBSYSTEM Subsystem; PSMP_SUBSYSTEM OtherSubsystem; } SMP_SESSION, *PSMP_SESSION; RTL_CRITICAL_SECTION SmpSessionListLock; LIST_ENTRY SmpSessionListHead; ULONG SmpNextSessionId; ULONG SmpNextSessionIdScanMode; BOOLEAN SmpDbgSsLoaded; HANDLE SmpSessionsObjectDirectory; /* FUNCTIONS ******************************************************************/ BOOLEAN NTAPI SmpCheckDuplicateMuSessionId(IN ULONG MuSessionId) { PSMP_SUBSYSTEM Subsystem; BOOLEAN FoundDuplicate = FALSE; PLIST_ENTRY NextEntry; /* Lock the subsystem database */ RtlEnterCriticalSection(&SmpKnownSubSysLock); /* Scan each entry */ NextEntry = SmpKnownSubSysHead.Flink; while (NextEntry != &SmpKnownSubSysHead) { /* Check if this entry has the same session ID */ Subsystem = CONTAINING_RECORD(NextEntry, SMP_SUBSYSTEM, Entry); if (Subsystem->MuSessionId == MuSessionId) { /* Break out of here! */ FoundDuplicate = TRUE; break; } /* Keep going */ NextEntry = NextEntry->Flink; } /* Release the database and return the result */ RtlLeaveCriticalSection(&SmpKnownSubSysLock); return FoundDuplicate; } PSMP_SESSION NTAPI SmpSessionIdToSession(IN ULONG SessionId) { PSMP_SESSION Session, FoundSession = NULL; PLIST_ENTRY NextEntry; /* Loop the session list -- lock must already be held! */ NextEntry = SmpSessionListHead.Flink; while (NextEntry != &SmpSessionListHead) { /* Check if this session's ID matches */ Session = CONTAINING_RECORD(NextEntry, SMP_SESSION, Entry); if (Session->SessionId == SessionId) { /* Set this as the found session and break out */ FoundSession = Session; break; } /* Keep going */ NextEntry = NextEntry->Flink; } /* Return the session that was found and exit */ return FoundSession; } VOID NTAPI SmpDeleteSession(IN ULONG SessionId) { PSMP_SESSION Session; /* Enter the lock and get the session structure */ RtlEnterCriticalSection(&SmpSessionListLock); Session = SmpSessionIdToSession(SessionId); if (Session) { /* Remove it from the list */ RemoveEntryList(&Session->Entry); RtlLeaveCriticalSection(&SmpSessionListLock); /* Now free the structure outside of the lock */ RtlFreeHeap(SmpHeap, 0, Session); } else { /* ID doesn't map to one of our structures, nothing to do... */ RtlLeaveCriticalSection(&SmpSessionListLock); } } ULONG NTAPI SmpAllocateSessionId(IN PSMP_SUBSYSTEM Subsystem, IN PSMP_SUBSYSTEM OtherSubsystem) { ULONG SessionId; PSMP_SESSION Session; /* Allocate a new ID while under the lock */ RtlEnterCriticalSection(&SmpSessionListLock); SessionId = SmpNextSessionId++; /* Check for overflow */ if (SmpNextSessionIdScanMode) { /* Break if it happened */ DbgPrint("SMSS: SessionId's Wrapped\n"); DbgBreakPoint(); } else { /* Detect it for next time */ if (!SmpNextSessionId) SmpNextSessionIdScanMode = 1; } /* Allocate a session structure */ Session = RtlAllocateHeap(SmpHeap, 0, sizeof(SMP_SESSION)); if (Session) { /* Write the session data and insert it into the session list */ Session->Subsystem = Subsystem; Session->SessionId = SessionId; Session->OtherSubsystem = OtherSubsystem; InsertTailList(&SmpSessionListHead, &Session->Entry); } else { DPRINT1("SMSS: Unable to keep track of session ID -- no memory available\n"); } /* Release the session lock */ RtlLeaveCriticalSection(&SmpSessionListLock); return SessionId; } NTSTATUS NTAPI SmpGetProcessMuSessionId(IN HANDLE ProcessHandle, OUT PULONG SessionId) { NTSTATUS Status; ULONG ProcessSession; /* Query the kernel for the session ID */ Status = NtQueryInformationProcess(ProcessHandle, ProcessSessionInformation, &ProcessSession, sizeof(ProcessSession), NULL); if (NT_SUCCESS(Status)) { /* Copy it back into the buffer */ *SessionId = ProcessSession; } else { /* Failure -- assume session zero */ DPRINT1("SMSS: GetProcessMuSessionId, Process=%p, Status=%x\n", ProcessHandle, Status); *SessionId = 0; } /* Return result */ return Status; } NTSTATUS NTAPI SmpSetProcessMuSessionId(IN HANDLE ProcessHandle, IN ULONG SessionId) { NTSTATUS Status; /* Tell the kernel about the session ID */ Status = NtSetInformationProcess(ProcessHandle, ProcessSessionInformation, &SessionId, sizeof(SessionId)); if (!NT_SUCCESS(Status)) { DPRINT1("SMSS: SetProcessMuSessionId, Process=%p, Status=%x\n", ProcessHandle, Status); } /* Return */ return Status; }