Sync with trunk r63786.
[reactos.git] / base / system / smss / smsessn.c
1 /*
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
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include "smss.h"
12
13 #define NDEBUG
14 #include <debug.h>
15
16 /* GLOBALS ********************************************************************/
17
18 typedef struct _SMP_SESSION
19 {
20 LIST_ENTRY Entry;
21 ULONG SessionId;
22 PSMP_SUBSYSTEM Subsystem;
23 PSMP_SUBSYSTEM OtherSubsystem;
24 } SMP_SESSION, *PSMP_SESSION;
25
26 RTL_CRITICAL_SECTION SmpSessionListLock;
27 LIST_ENTRY SmpSessionListHead;
28 ULONG SmpNextSessionId;
29 ULONG SmpNextSessionIdScanMode;
30 BOOLEAN SmpDbgSsLoaded;
31 HANDLE SmpSessionsObjectDirectory;
32
33 /* FUNCTIONS ******************************************************************/
34
35 BOOLEAN
36 NTAPI
37 SmpCheckDuplicateMuSessionId(IN ULONG MuSessionId)
38 {
39 PSMP_SUBSYSTEM Subsystem;
40 BOOLEAN FoundDuplicate = FALSE;
41 PLIST_ENTRY NextEntry;
42
43 /* Lock the subsystem database */
44 RtlEnterCriticalSection(&SmpKnownSubSysLock);
45
46 /* Scan each entry */
47 NextEntry = SmpKnownSubSysHead.Flink;
48 while (NextEntry != &SmpKnownSubSysHead)
49 {
50 /* Check if this entry has the same session ID */
51 Subsystem = CONTAINING_RECORD(NextEntry, SMP_SUBSYSTEM, Entry);
52 if (Subsystem->MuSessionId == MuSessionId)
53 {
54 /* Break out of here! */
55 FoundDuplicate = TRUE;
56 break;
57 }
58
59 /* Keep going */
60 NextEntry = NextEntry->Flink;
61 }
62
63 /* Release the database and return the result */
64 RtlLeaveCriticalSection(&SmpKnownSubSysLock);
65 return FoundDuplicate;
66 }
67
68 PSMP_SESSION
69 NTAPI
70 SmpSessionIdToSession(IN ULONG SessionId)
71 {
72 PSMP_SESSION Session, FoundSession = NULL;
73 PLIST_ENTRY NextEntry;
74
75 /* Loop the session list -- lock must already be held! */
76 NextEntry = SmpSessionListHead.Flink;
77 while (NextEntry != &SmpSessionListHead)
78 {
79 /* Check if this session's ID matches */
80 Session = CONTAINING_RECORD(NextEntry, SMP_SESSION, Entry);
81 if (Session->SessionId == SessionId)
82 {
83 /* Set this as the found session and break out */
84 FoundSession = Session;
85 break;
86 }
87
88 /* Keep going */
89 NextEntry = NextEntry->Flink;
90 }
91
92 /* Return the session that was found and exit */
93 return FoundSession;
94 }
95
96 VOID
97 NTAPI
98 SmpDeleteSession(IN ULONG SessionId)
99 {
100 PSMP_SESSION Session;
101
102 /* Enter the lock and get the session structure */
103 RtlEnterCriticalSection(&SmpSessionListLock);
104 Session = SmpSessionIdToSession(SessionId);
105 if (Session)
106 {
107 /* Remove it from the list */
108 RemoveEntryList(&Session->Entry);
109 RtlLeaveCriticalSection(&SmpSessionListLock);
110
111 /* Now free the structure outside of the lock */
112 RtlFreeHeap(SmpHeap, 0, Session);
113 }
114 else
115 {
116 /* ID doesn't map to one of our structures, nothing to do... */
117 RtlLeaveCriticalSection(&SmpSessionListLock);
118 }
119 }
120
121 ULONG
122 NTAPI
123 SmpAllocateSessionId(IN PSMP_SUBSYSTEM Subsystem,
124 IN PSMP_SUBSYSTEM OtherSubsystem)
125 {
126 ULONG SessionId;
127 PSMP_SESSION Session;
128
129 /* Allocate a new ID while under the lock */
130 RtlEnterCriticalSection(&SmpSessionListLock);
131 SessionId = SmpNextSessionId++;
132
133 /* Check for overflow */
134 if (SmpNextSessionIdScanMode)
135 {
136 /* Break if it happened */
137 DbgPrint("SMSS: SessionId's Wrapped\n");
138 DbgBreakPoint();
139 }
140 else
141 {
142 /* Detect it for next time */
143 if (!SmpNextSessionId) SmpNextSessionIdScanMode = 1;
144 }
145
146 /* Allocate a session structure */
147 Session = RtlAllocateHeap(SmpHeap, 0, sizeof(SMP_SESSION));
148 if (Session)
149 {
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);
155 }
156 else
157 {
158 DPRINT1("SMSS: Unable to keep track of session ID -- no memory available\n");
159 }
160
161 /* Release the session lock */
162 RtlLeaveCriticalSection(&SmpSessionListLock);
163 return SessionId;
164 }
165
166 NTSTATUS
167 NTAPI
168 SmpGetProcessMuSessionId(IN HANDLE ProcessHandle,
169 OUT PULONG SessionId)
170 {
171 NTSTATUS Status;
172 ULONG ProcessSession;
173
174 /* Query the kernel for the session ID */
175 Status = NtQueryInformationProcess(ProcessHandle,
176 ProcessSessionInformation,
177 &ProcessSession,
178 sizeof(ProcessSession),
179 NULL);
180 if (NT_SUCCESS(Status))
181 {
182 /* Copy it back into the buffer */
183 *SessionId = ProcessSession;
184 }
185 else
186 {
187 /* Failure -- assume session zero */
188 DPRINT1("SMSS: GetProcessMuSessionId, Process=%p, Status=%x\n",
189 ProcessHandle, Status);
190 *SessionId = 0;
191 }
192
193 /* Return result */
194 return Status;
195 }
196
197 NTSTATUS
198 NTAPI
199 SmpSetProcessMuSessionId(IN HANDLE ProcessHandle,
200 IN ULONG SessionId)
201 {
202 NTSTATUS Status;
203
204 /* Tell the kernel about the session ID */
205 Status = NtSetInformationProcess(ProcessHandle,
206 ProcessSessionInformation,
207 &SessionId,
208 sizeof(SessionId));
209 if (!NT_SUCCESS(Status))
210 {
211 DPRINT1("SMSS: SetProcessMuSessionId, Process=%p, Status=%x\n",
212 ProcessHandle, Status);
213 }
214
215 /* Return */
216 return Status;
217 }