reactos/subsystems/csr/csrsrv/session.c
Timo Kreuzer 6afbc8f483 Hopefully create a branch and not destroy the svn repository.
svn path=/branches/reactos-yarotows/; revision=45219
2010-01-23 23:25:04 +00:00

352 lines
8.8 KiB
C

/*
* 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 <debug.h>
/* 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 */