xref: /reactos/base/system/smss/smsessn.c (revision f43ce465)
1 /*
2  * PROJECT:         ReactOS Windows-Compatible Session Manager
3  * LICENSE:         BSD 2-Clause License
4  * FILE:            base/system/smss/smsessn.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 BOOLEAN SmpNextSessionIdScanMode;
30 BOOLEAN SmpDbgSsLoaded;
31 HANDLE SmpSessionsObjectDirectory;
32 
33 /* FUNCTIONS ******************************************************************/
34 
35 BOOLEAN
36 NTAPI
SmpCheckDuplicateMuSessionId(IN ULONG MuSessionId)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
SmpSessionIdToSession(IN ULONG SessionId)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
SmpDeleteSession(IN ULONG SessionId)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
SmpAllocateSessionId(IN PSMP_SUBSYSTEM Subsystem,IN PSMP_SUBSYSTEM OtherSubsystem)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         UNIMPLEMENTED_DBGBREAK("SMSS: SessionId's Wrapped\n");
138     }
139     else
140     {
141         /* Detect it for next time */
142         if (!SmpNextSessionId)
143             SmpNextSessionIdScanMode = TRUE;
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
SmpGetProcessMuSessionId(IN HANDLE ProcessHandle,OUT PULONG SessionId)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
SmpSetProcessMuSessionId(IN HANDLE ProcessHandle,IN ULONG SessionId)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 }
218