--- /dev/null
+/*
+ * 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 <debug.h>
+
+/* 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;
+}