/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS CSR Sub System * FILE: subsys/csr/csrsrv/session.c * PURPOSE: CSR Server DLL Session Implementation * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) */ /* INCLUDES ******************************************************************/ #include "srv.h" #define NDEBUG #include /* DATA **********************************************************************/ RTL_CRITICAL_SECTION CsrNtSessionLock; LIST_ENTRY CsrNtSessionList; HANDLE CsrSmApiPort; PSB_API_ROUTINE CsrServerSbApiDispatch[5] = { CsrSbCreateSession, CsrSbTerminateSession, CsrSbForeignSessionComplete, CsrSbCreateProcess, NULL }; PCHAR CsrServerSbApiName[5] = { "SbCreateSession", "SbTerminateSession", "SbForeignSessionComplete", "SbCreateProcess", "Unknown Csr Sb Api Number" }; /* PRIVATE FUNCTIONS *********************************************************/ /*++ * @name CsrInitializeNtSessions * * The CsrInitializeNtSessions routine sets up support for CSR Sessions. * * @param None * * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL * othwerwise. * * @remarks None. * *--*/ NTSTATUS NTAPI CsrInitializeNtSessions(VOID) { NTSTATUS Status; DPRINT("CSRSRV: %s called\n", __FUNCTION__); /* Initialize the Session List */ InitializeListHead(&CsrNtSessionList); /* Initialize the Session Lock */ Status = RtlInitializeCriticalSection(&CsrNtSessionLock); return Status; } /*++ * @name CsrAllocateNtSession * * The CsrAllocateNtSession routine allocates a new CSR NT Session. * * @param SessionId * Session ID of the CSR NT Session to allocate. * * @return Pointer to the newly allocated CSR NT Session. * * @remarks None. * *--*/ PCSR_NT_SESSION NTAPI CsrAllocateNtSession(ULONG SessionId) { PCSR_NT_SESSION NtSession; /* Allocate an NT Session Object */ NtSession = RtlAllocateHeap(CsrHeap, 0, sizeof(CSR_NT_SESSION)); /* Setup the Session Object */ if (NtSession) { NtSession->SessionId = SessionId; NtSession->ReferenceCount = 1; /* Insert it into the Session List */ CsrAcquireNtSessionLock(); InsertHeadList(&CsrNtSessionList, &NtSession->SessionList); CsrReleaseNtSessionLock(); } /* Return the Session (or NULL) */ return NtSession; } /*++ * @name CsrReferenceNtSession * * The CsrReferenceNtSession increases the reference count of a CSR NT Session. * * @param Session * Pointer to the CSR NT Session to reference. * * @return None. * * @remarks None. * *--*/ VOID NTAPI CsrReferenceNtSession(PCSR_NT_SESSION Session) { /* Acquire the lock */ CsrAcquireNtSessionLock(); /* Increase the reference count */ Session->ReferenceCount++; /* Release the lock */ CsrReleaseNtSessionLock(); } /*++ * @name CsrDereferenceNtSession * * The CsrDereferenceNtSession decreases the reference count of a * CSR NT Session. * * @param Session * Pointer to the CSR NT Session to reference. * * @param ExitStatus * If this is the last reference to the session, this argument * specifies the exit status. * * @return None. * * @remarks CsrDereferenceNtSession will complete the session if * the last reference to it has been closed. * *--*/ VOID NTAPI CsrDereferenceNtSession(PCSR_NT_SESSION Session, NTSTATUS ExitStatus) { /* Acquire the lock */ CsrAcquireNtSessionLock(); /* Dereference the Session Object */ if (!(--Session->ReferenceCount)) { /* Remove it from the list */ RemoveEntryList(&Session->SessionList); /* Release the lock */ CsrReleaseNtSessionLock(); /* Tell SM that we're done here */ SmSessionComplete(CsrSmApiPort, Session->SessionId, ExitStatus); /* Free the Session Object */ RtlFreeHeap(CsrHeap, 0, Session); } else { /* Release the lock, the Session is still active */ CsrReleaseNtSessionLock(); } } /* SESSION MANAGER FUNCTIONS**************************************************/ /*++ * @name CsrSbCreateSession * * The CsrSbCreateSession API is called by the Session Manager whenever a new * session is created. * * @param ApiMessage * Pointer to the Session Manager API Message. * * @return TRUE in case of success, FALSE othwerwise. * * @remarks The CsrSbCreateSession routine will initialize a new CSR NT * Session and allocate a new CSR Process for the subsystem process. * *--*/ BOOLEAN NTAPI CsrSbCreateSession(IN PSB_API_MESSAGE ApiMessage) { PSB_CREATE_SESSION CreateSession = &ApiMessage->SbCreateSession; HANDLE hProcess, hThread; PCSR_PROCESS CsrProcess; NTSTATUS Status; KERNEL_USER_TIMES KernelTimes; PCSR_THREAD CsrThread; PVOID ProcessData; ULONG i; /* Save the Process and Thread Handles */ hProcess = CreateSession->ProcessInfo.ProcessHandle; hThread = CreateSession->ProcessInfo.ThreadHandle; /* Lock the Processes */ CsrAcquireProcessLock(); /* Allocate a new process */ if (!(CsrProcess = CsrAllocateProcess())) { /* Fail */ ApiMessage->Status = STATUS_NO_MEMORY; CsrReleaseProcessLock(); return TRUE; } /* Setup Process Data */ CsrProcess->ClientId = CreateSession->ProcessInfo.ClientId; CsrProcess->ProcessHandle = hProcess; /* Set the exception port */ Status = NtSetInformationProcess(hProcess, ProcessExceptionPort, &CsrApiPort, sizeof(HANDLE)); /* Check for success */ if (!NT_SUCCESS(Status)) { /* Fail the request */ CsrDeallocateProcess(CsrProcess); CsrReleaseProcessLock(); /* Strange as it seems, NTSTATUSes are actually returned */ return (BOOLEAN)STATUS_NO_MEMORY; } /* Get the Create Time */ Status = NtQueryInformationThread(hThread, ThreadTimes, &KernelTimes, sizeof(KERNEL_USER_TIMES), NULL); /* Check for success */ if (!NT_SUCCESS(Status)) { /* Fail the request */ CsrDeallocateProcess(CsrProcess); CsrReleaseProcessLock(); return (BOOLEAN)Status; } /* Allocate a new Thread */ if (!(CsrThread = CsrAllocateThread(CsrProcess))) { /* Fail the request */ CsrDeallocateProcess(CsrProcess); ApiMessage->Status = STATUS_NO_MEMORY; CsrReleaseProcessLock(); return TRUE; } /* Setup the Thread Object */ CsrThread->CreateTime = KernelTimes.CreateTime; CsrThread->ClientId = CreateSession->ProcessInfo.ClientId; CsrThread->ThreadHandle = hThread; CsrThread->Flags = 0; /* Insert it into the Process List */ CsrInsertThread(CsrProcess, CsrThread); /* Allocate a new Session */ CsrProcess->NtSession = CsrAllocateNtSession(CreateSession->SessionId); /* Set the Process Priority */ CsrSetBackgroundPriority(CsrProcess); /* Get the first data location */ ProcessData = &CsrProcess->ServerData[CSR_SERVER_DLL_MAX]; /* Loop every DLL */ for (i = 0; i < CSR_SERVER_DLL_MAX; i++) { /* Check if the DLL is loaded and has Process Data */ if (CsrLoadedServerDll[i] && CsrLoadedServerDll[i]->SizeOfProcessData) { /* Write the pointer to the data */ CsrProcess->ServerData[i] = ProcessData; /* Move to the next data location */ ProcessData = (PVOID)((ULONG_PTR)ProcessData + CsrLoadedServerDll[i]->SizeOfProcessData); } else { /* Nothing for this Process */ CsrProcess->ServerData[i] = NULL; } } /* Insert the Process */ CsrInsertProcess(NULL, NULL, CsrProcess); /* Activate the Thread */ ApiMessage->Status = NtResumeThread(hThread, NULL); /* Release lock and return */ CsrReleaseProcessLock(); return TRUE; } /*++ * @name CsrSbForeignSessionComplete * * The CsrSbForeignSessionComplete API is called by the Session Manager * whenever a foreign session is completed (ie: terminated). * * @param ApiMessage * Pointer to the Session Manager API Message. * * @return TRUE in case of success, FALSE othwerwise. * * @remarks The CsrSbForeignSessionComplete API is not yet implemented. * *--*/ BOOLEAN NTAPI CsrSbForeignSessionComplete(IN PSB_API_MESSAGE ApiMessage) { /* Deprecated/Unimplemented in NT */ ApiMessage->Status = STATUS_NOT_IMPLEMENTED; return TRUE; } /* EOF */