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 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 } 218