2 * PROJECT: ReactOS Windows-Compatible Session Manager
3 * LICENSE: BSD 2-Clause License
4 * FILE: base/system/smss/smss.c
5 * PURPOSE: Main SMSS Code
6 * PROGRAMMERS: Alex Ionescu
9 /* INCLUDES *******************************************************************/
15 /* GLOBALS ********************************************************************/
17 typedef struct _SMP_SESSION
21 PSMP_SUBSYSTEM Subsystem
;
22 PSMP_SUBSYSTEM OtherSubsystem
;
23 } SMP_SESSION
, *PSMP_SESSION
;
25 RTL_CRITICAL_SECTION SmpSessionListLock
;
26 LIST_ENTRY SmpSessionListHead
;
27 ULONG SmpNextSessionId
;
28 ULONG SmpNextSessionIdScanMode
;
29 BOOLEAN SmpDbgSsLoaded
;
30 HANDLE SmpSessionsObjectDirectory
;
32 /* FUNCTIONS ******************************************************************/
36 SmpCheckDuplicateMuSessionId(IN ULONG MuSessionId
)
38 PSMP_SUBSYSTEM Subsystem
;
39 BOOLEAN FoundDuplicate
= FALSE
;
40 PLIST_ENTRY NextEntry
;
42 /* Lock the subsystem database */
43 RtlEnterCriticalSection(&SmpKnownSubSysLock
);
46 NextEntry
= SmpKnownSubSysHead
.Flink
;
47 while (NextEntry
!= &SmpKnownSubSysHead
)
49 /* Check if this entry has the same session ID */
50 Subsystem
= CONTAINING_RECORD(NextEntry
, SMP_SUBSYSTEM
, Entry
);
51 if (Subsystem
->MuSessionId
== MuSessionId
)
53 /* Break out of here! */
54 FoundDuplicate
= TRUE
;
59 NextEntry
= NextEntry
->Flink
;
62 /* Release the database and return the result */
63 RtlLeaveCriticalSection(&SmpKnownSubSysLock
);
64 return FoundDuplicate
;
69 SmpSessionIdToSession(IN ULONG SessionId
)
71 PSMP_SESSION Session
, FoundSession
= NULL
;
72 PLIST_ENTRY NextEntry
;
74 /* Loop the session list -- lock must already be held! */
75 NextEntry
= SmpSessionListHead
.Flink
;
76 while (NextEntry
!= &SmpSessionListHead
)
78 /* Check if this session's ID matches */
79 Session
= CONTAINING_RECORD(NextEntry
, SMP_SESSION
, Entry
);
80 if (Session
->SessionId
== SessionId
)
82 /* Set this as the found session and break out */
83 FoundSession
= Session
;
88 NextEntry
= NextEntry
->Flink
;
91 /* Return the session that was found and exit */
97 SmpDeleteSession(IN ULONG SessionId
)
101 /* Enter the lock and get the session structure */
102 RtlEnterCriticalSection(&SmpSessionListLock
);
103 Session
= SmpSessionIdToSession(SessionId
);
106 /* Remove it from the list */
107 RemoveEntryList(&Session
->Entry
);
108 RtlLeaveCriticalSection(&SmpSessionListLock
);
110 /* Now free the structure outside of the lock */
111 RtlFreeHeap(SmpHeap
, 0, Session
);
115 /* ID doesn't map to one of our structures, nothing to do... */
116 RtlLeaveCriticalSection(&SmpSessionListLock
);
122 SmpAllocateSessionId(IN PSMP_SUBSYSTEM Subsystem
,
123 IN PSMP_SUBSYSTEM OtherSubsystem
)
126 PSMP_SESSION Session
;
128 /* Allocate a new ID while under the lock */
129 RtlEnterCriticalSection(&SmpSessionListLock
);
130 SessionId
= SmpNextSessionId
++;
132 /* Check for overflow */
133 if (SmpNextSessionIdScanMode
)
135 /* Break if it happened */
136 DbgPrint("SMSS: SessionId's Wrapped\n");
141 /* Detect it for next time */
142 if (!SmpNextSessionId
) SmpNextSessionIdScanMode
= 1;
145 /* Allocate a session structure */
146 Session
= RtlAllocateHeap(SmpHeap
, 0, sizeof(SMP_SESSION
));
149 /* Write the session data and insert it into the session list */
150 Session
->Subsystem
= Subsystem
;
151 Session
->SessionId
= SessionId
;
152 Session
->OtherSubsystem
= OtherSubsystem
;
153 InsertTailList(&SmpSessionListHead
, &Session
->Entry
);
157 DPRINT1("SMSS: Unable to keep track of session ID -- no memory available\n");
160 /* Release the session lock */
161 RtlLeaveCriticalSection(&SmpSessionListLock
);
167 SmpGetProcessMuSessionId(IN HANDLE ProcessHandle
,
168 OUT PULONG SessionId
)
171 ULONG ProcessSession
;
173 /* Query the kernel for the session ID */
174 Status
= NtQueryInformationProcess(ProcessHandle
,
175 ProcessSessionInformation
,
177 sizeof(ProcessSession
),
179 if (NT_SUCCESS(Status
))
181 /* Copy it back into the buffer */
182 *SessionId
= ProcessSession
;
186 /* Failure -- assume session zero */
187 DPRINT1("SMSS: GetProcessMuSessionId, Process=%x, Status=%x\n",
188 ProcessHandle
, Status
);
198 SmpSetProcessMuSessionId(IN HANDLE ProcessHandle
,
203 /* Tell the kernel about the session ID */
204 Status
= NtSetInformationProcess(ProcessHandle
,
205 ProcessSessionInformation
,
208 if (!NT_SUCCESS(Status
))
210 DPRINT1("SMSS: SetProcessMuSessionId, Process=%x, Status=%x\n",
211 ProcessHandle
, Status
);