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