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 *******************************************************************/
16 /* GLOBALS ********************************************************************/
18 typedef struct _SMP_SESSION
22 PSMP_SUBSYSTEM Subsystem
;
23 PSMP_SUBSYSTEM OtherSubsystem
;
24 } SMP_SESSION
, *PSMP_SESSION
;
26 RTL_CRITICAL_SECTION SmpSessionListLock
;
27 LIST_ENTRY SmpSessionListHead
;
28 ULONG SmpNextSessionId
;
29 ULONG SmpNextSessionIdScanMode
;
30 BOOLEAN SmpDbgSsLoaded
;
31 HANDLE SmpSessionsObjectDirectory
;
33 /* FUNCTIONS ******************************************************************/
37 SmpCheckDuplicateMuSessionId(IN ULONG MuSessionId
)
39 PSMP_SUBSYSTEM Subsystem
;
40 BOOLEAN FoundDuplicate
= FALSE
;
41 PLIST_ENTRY NextEntry
;
43 /* Lock the subsystem database */
44 RtlEnterCriticalSection(&SmpKnownSubSysLock
);
47 NextEntry
= SmpKnownSubSysHead
.Flink
;
48 while (NextEntry
!= &SmpKnownSubSysHead
)
50 /* Check if this entry has the same session ID */
51 Subsystem
= CONTAINING_RECORD(NextEntry
, SMP_SUBSYSTEM
, Entry
);
52 if (Subsystem
->MuSessionId
== MuSessionId
)
54 /* Break out of here! */
55 FoundDuplicate
= TRUE
;
60 NextEntry
= NextEntry
->Flink
;
63 /* Release the database and return the result */
64 RtlLeaveCriticalSection(&SmpKnownSubSysLock
);
65 return FoundDuplicate
;
70 SmpSessionIdToSession(IN ULONG SessionId
)
72 PSMP_SESSION Session
, FoundSession
= NULL
;
73 PLIST_ENTRY NextEntry
;
75 /* Loop the session list -- lock must already be held! */
76 NextEntry
= SmpSessionListHead
.Flink
;
77 while (NextEntry
!= &SmpSessionListHead
)
79 /* Check if this session's ID matches */
80 Session
= CONTAINING_RECORD(NextEntry
, SMP_SESSION
, Entry
);
81 if (Session
->SessionId
== SessionId
)
83 /* Set this as the found session and break out */
84 FoundSession
= Session
;
89 NextEntry
= NextEntry
->Flink
;
92 /* Return the session that was found and exit */
98 SmpDeleteSession(IN ULONG SessionId
)
100 PSMP_SESSION Session
;
102 /* Enter the lock and get the session structure */
103 RtlEnterCriticalSection(&SmpSessionListLock
);
104 Session
= SmpSessionIdToSession(SessionId
);
107 /* Remove it from the list */
108 RemoveEntryList(&Session
->Entry
);
109 RtlLeaveCriticalSection(&SmpSessionListLock
);
111 /* Now free the structure outside of the lock */
112 RtlFreeHeap(SmpHeap
, 0, Session
);
116 /* ID doesn't map to one of our structures, nothing to do... */
117 RtlLeaveCriticalSection(&SmpSessionListLock
);
123 SmpAllocateSessionId(IN PSMP_SUBSYSTEM Subsystem
,
124 IN PSMP_SUBSYSTEM OtherSubsystem
)
127 PSMP_SESSION Session
;
129 /* Allocate a new ID while under the lock */
130 RtlEnterCriticalSection(&SmpSessionListLock
);
131 SessionId
= SmpNextSessionId
++;
133 /* Check for overflow */
134 if (SmpNextSessionIdScanMode
)
136 /* Break if it happened */
137 DbgPrint("SMSS: SessionId's Wrapped\n");
142 /* Detect it for next time */
143 if (!SmpNextSessionId
) SmpNextSessionIdScanMode
= 1;
146 /* Allocate a session structure */
147 Session
= RtlAllocateHeap(SmpHeap
, 0, sizeof(SMP_SESSION
));
150 /* Write the session data and insert it into the session list */
151 Session
->Subsystem
= Subsystem
;
152 Session
->SessionId
= SessionId
;
153 Session
->OtherSubsystem
= OtherSubsystem
;
154 InsertTailList(&SmpSessionListHead
, &Session
->Entry
);
158 DPRINT1("SMSS: Unable to keep track of session ID -- no memory available\n");
161 /* Release the session lock */
162 RtlLeaveCriticalSection(&SmpSessionListLock
);
168 SmpGetProcessMuSessionId(IN HANDLE ProcessHandle
,
169 OUT PULONG SessionId
)
172 ULONG ProcessSession
;
174 /* Query the kernel for the session ID */
175 Status
= NtQueryInformationProcess(ProcessHandle
,
176 ProcessSessionInformation
,
178 sizeof(ProcessSession
),
180 if (NT_SUCCESS(Status
))
182 /* Copy it back into the buffer */
183 *SessionId
= ProcessSession
;
187 /* Failure -- assume session zero */
188 DPRINT1("SMSS: GetProcessMuSessionId, Process=%p, Status=%x\n",
189 ProcessHandle
, Status
);
199 SmpSetProcessMuSessionId(IN HANDLE ProcessHandle
,
204 /* Tell the kernel about the session ID */
205 Status
= NtSetInformationProcess(ProcessHandle
,
206 ProcessSessionInformation
,
209 if (!NT_SUCCESS(Status
))
211 DPRINT1("SMSS: SetProcessMuSessionId, Process=%p, Status=%x\n",
212 ProcessHandle
, Status
);