reactos/base/system/smss/smsessn.c

217 lines
5.7 KiB
C

/*
* PROJECT: ReactOS Windows-Compatible Session Manager
* LICENSE: BSD 2-Clause License
* FILE: base/system/smss/smsessn.c
* PURPOSE: Main SMSS Code
* PROGRAMMERS: Alex Ionescu
*/
/* INCLUDES *******************************************************************/
#include "smss.h"
#define NDEBUG
#include <debug.h>
/* GLOBALS ********************************************************************/
typedef struct _SMP_SESSION
{
LIST_ENTRY Entry;
ULONG SessionId;
PSMP_SUBSYSTEM Subsystem;
PSMP_SUBSYSTEM OtherSubsystem;
} SMP_SESSION, *PSMP_SESSION;
RTL_CRITICAL_SECTION SmpSessionListLock;
LIST_ENTRY SmpSessionListHead;
ULONG SmpNextSessionId;
ULONG SmpNextSessionIdScanMode;
BOOLEAN SmpDbgSsLoaded;
HANDLE SmpSessionsObjectDirectory;
/* FUNCTIONS ******************************************************************/
BOOLEAN
NTAPI
SmpCheckDuplicateMuSessionId(IN ULONG MuSessionId)
{
PSMP_SUBSYSTEM Subsystem;
BOOLEAN FoundDuplicate = FALSE;
PLIST_ENTRY NextEntry;
/* Lock the subsystem database */
RtlEnterCriticalSection(&SmpKnownSubSysLock);
/* Scan each entry */
NextEntry = SmpKnownSubSysHead.Flink;
while (NextEntry != &SmpKnownSubSysHead)
{
/* Check if this entry has the same session ID */
Subsystem = CONTAINING_RECORD(NextEntry, SMP_SUBSYSTEM, Entry);
if (Subsystem->MuSessionId == MuSessionId)
{
/* Break out of here! */
FoundDuplicate = TRUE;
break;
}
/* Keep going */
NextEntry = NextEntry->Flink;
}
/* Release the database and return the result */
RtlLeaveCriticalSection(&SmpKnownSubSysLock);
return FoundDuplicate;
}
PSMP_SESSION
NTAPI
SmpSessionIdToSession(IN ULONG SessionId)
{
PSMP_SESSION Session, FoundSession = NULL;
PLIST_ENTRY NextEntry;
/* Loop the session list -- lock must already be held! */
NextEntry = SmpSessionListHead.Flink;
while (NextEntry != &SmpSessionListHead)
{
/* Check if this session's ID matches */
Session = CONTAINING_RECORD(NextEntry, SMP_SESSION, Entry);
if (Session->SessionId == SessionId)
{
/* Set this as the found session and break out */
FoundSession = Session;
break;
}
/* Keep going */
NextEntry = NextEntry->Flink;
}
/* Return the session that was found and exit */
return FoundSession;
}
VOID
NTAPI
SmpDeleteSession(IN ULONG SessionId)
{
PSMP_SESSION Session;
/* Enter the lock and get the session structure */
RtlEnterCriticalSection(&SmpSessionListLock);
Session = SmpSessionIdToSession(SessionId);
if (Session)
{
/* Remove it from the list */
RemoveEntryList(&Session->Entry);
RtlLeaveCriticalSection(&SmpSessionListLock);
/* Now free the structure outside of the lock */
RtlFreeHeap(SmpHeap, 0, Session);
}
else
{
/* ID doesn't map to one of our structures, nothing to do... */
RtlLeaveCriticalSection(&SmpSessionListLock);
}
}
ULONG
NTAPI
SmpAllocateSessionId(IN PSMP_SUBSYSTEM Subsystem,
IN PSMP_SUBSYSTEM OtherSubsystem)
{
ULONG SessionId;
PSMP_SESSION Session;
/* Allocate a new ID while under the lock */
RtlEnterCriticalSection(&SmpSessionListLock);
SessionId = SmpNextSessionId++;
/* Check for overflow */
if (SmpNextSessionIdScanMode)
{
/* Break if it happened */
DbgPrint("SMSS: SessionId's Wrapped\n");
DbgBreakPoint();
}
else
{
/* Detect it for next time */
if (!SmpNextSessionId) SmpNextSessionIdScanMode = 1;
}
/* Allocate a session structure */
Session = RtlAllocateHeap(SmpHeap, 0, sizeof(SMP_SESSION));
if (Session)
{
/* Write the session data and insert it into the session list */
Session->Subsystem = Subsystem;
Session->SessionId = SessionId;
Session->OtherSubsystem = OtherSubsystem;
InsertTailList(&SmpSessionListHead, &Session->Entry);
}
else
{
DPRINT1("SMSS: Unable to keep track of session ID -- no memory available\n");
}
/* Release the session lock */
RtlLeaveCriticalSection(&SmpSessionListLock);
return SessionId;
}
NTSTATUS
NTAPI
SmpGetProcessMuSessionId(IN HANDLE ProcessHandle,
OUT PULONG SessionId)
{
NTSTATUS Status;
ULONG ProcessSession;
/* Query the kernel for the session ID */
Status = NtQueryInformationProcess(ProcessHandle,
ProcessSessionInformation,
&ProcessSession,
sizeof(ProcessSession),
NULL);
if (NT_SUCCESS(Status))
{
/* Copy it back into the buffer */
*SessionId = ProcessSession;
}
else
{
/* Failure -- assume session zero */
DPRINT1("SMSS: GetProcessMuSessionId, Process=%p, Status=%x\n",
ProcessHandle, Status);
*SessionId = 0;
}
/* Return result */
return Status;
}
NTSTATUS
NTAPI
SmpSetProcessMuSessionId(IN HANDLE ProcessHandle,
IN ULONG SessionId)
{
NTSTATUS Status;
/* Tell the kernel about the session ID */
Status = NtSetInformationProcess(ProcessHandle,
ProcessSessionInformation,
&SessionId,
sizeof(SessionId));
if (!NT_SUCCESS(Status))
{
DPRINT1("SMSS: SetProcessMuSessionId, Process=%p, Status=%x\n",
ProcessHandle, Status);
}
/* Return */
return Status;
}