reactos/subsystems/win32/csrsrv/session.c
Hermès Bélusca-Maïto b75ee7fd14 [CSRSRV]
- Zero-out some allocated memory.
- During my investigations preceding the implementation of AttachConsole (r58166), I wanted (in a first attempt; finally I've found a better way to achieve what I wanted to do) to retrieve the CSR_PROCESS structure of the parent of a given process. I've found the 'Parent' member in the CSR_PROCESS structure, however this member was always initialized to NULL when new processes were created via CsrCreateProcess (and via the call to CsrInsertProcess). After looking at some informating here (http://svn.reactos.org/svn/reactos/trunk/reactos/include/subsys/csr/server.h?r1=17363&r2=17362&pathrev=17363) and there (http://forum.sysinternals.com/csrwalker-processes-detection-from-user-mode_topic15457.html), I became convinced that the 'Parent' member was unexistent starting from Windows Server 2003. Also, after much more investigation, I've found that the CsrInsertProcess function was called with only two parameters starting from Windows Server 2003 (and still continues in Windows 7), the always-NULL paramater being removed.
Therefore, I remove that unneeded parameter from CsrInsertProcess and the corresponding 'Parent' member from CSR_PROCESS.

svn path=/branches/ros-csrss/; revision=58232
2013-01-26 21:23:10 +00:00

571 lines
15 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Client/Server Runtime SubSystem
* FILE: subsystems/win32/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;
// Does it exist a enumeration associated with it ?
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 CsrInitializeNtSessionList
*
* The CsrInitializeNtSessionList routine sets up support for CSR Sessions.
*
* @param None
*
* @return None
*
* @remarks None.
*
*--*/
NTSTATUS
NTAPI
CsrInitializeNtSessionList(VOID)
{
DPRINT("CSRSRV: %s called\n", __FUNCTION__);
/* Initialize the Session List */
InitializeListHead(&CsrNtSessionList);
/* Initialize the Session Lock */
return RtlInitializeCriticalSection(&CsrNtSessionLock);
}
/*++
* @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(IN ULONG SessionId)
{
PCSR_NT_SESSION NtSession;
/* Allocate an NT Session Object */
NtSession = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, sizeof(CSR_NT_SESSION));
if (NtSession)
{
/* Setup the Session Object */
NtSession->SessionId = SessionId;
NtSession->ReferenceCount = 1;
/* Insert it into the Session List */
CsrAcquireNtSessionLock();
InsertHeadList(&CsrNtSessionList, &NtSession->SessionLink);
CsrReleaseNtSessionLock();
}
else
{
ASSERT(NtSession != NULL);
}
/* 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(IN PCSR_NT_SESSION Session)
{
/* Acquire the lock */
CsrAcquireNtSessionLock();
/* Sanity checks */
ASSERT(!IsListEmpty(&Session->SessionLink));
ASSERT(Session->SessionId != 0);
ASSERT(Session->ReferenceCount != 0);
/* 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(IN PCSR_NT_SESSION Session,
IN NTSTATUS ExitStatus)
{
/* Acquire the lock */
CsrAcquireNtSessionLock();
/* Sanity checks */
ASSERT(!IsListEmpty(&Session->SessionLink));
ASSERT(Session->SessionId != 0);
ASSERT(Session->ReferenceCount != 0);
/* Dereference the Session Object */
if (!(--Session->ReferenceCount))
{
/* Remove it from the list */
RemoveEntryList(&Session->SessionLink);
/* 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 otherwise.
*
* @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_MSG ApiMessage)
{
PSB_CREATE_SESSION_MSG CreateSession = &ApiMessage->CreateSession;
HANDLE hProcess, hThread;
PCSR_PROCESS CsrProcess;
PCSR_THREAD CsrThread;
PCSR_SERVER_DLL ServerDll;
PVOID ProcessData;
NTSTATUS Status;
KERNEL_USER_TIMES KernelTimes;
ULONG i;
/* Save the Process and Thread Handles */
hProcess = CreateSession->ProcessInfo.ProcessHandle;
hThread = CreateSession->ProcessInfo.ThreadHandle;
/* Lock the Processes */
CsrAcquireProcessLock();
/* Allocate a new process */
CsrProcess = CsrAllocateProcess();
if (!CsrProcess)
{
/* Fail */
ApiMessage->ReturnValue = STATUS_NO_MEMORY;
CsrReleaseProcessLock();
return TRUE;
}
/* 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();
/* Strange as it seems, NTSTATUSes are actually returned */
return (BOOLEAN)Status;
}
/* Allocate a new Thread */
CsrThread = CsrAllocateThread(CsrProcess);
if (!CsrThread)
{
/* Fail the request */
CsrDeallocateProcess(CsrProcess);
CsrReleaseProcessLock();
ApiMessage->ReturnValue = STATUS_NO_MEMORY;
return TRUE;
}
/* Setup the Thread Object */
CsrThread->CreateTime = KernelTimes.CreateTime;
CsrThread->ClientId = CreateSession->ProcessInfo.ClientId;
CsrThread->ThreadHandle = hThread;
ProtectHandle(hThread);
CsrThread->Flags = 0;
/* Insert it into the Process List */
CsrInsertThread(CsrProcess, CsrThread);
/* Setup Process Data */
CsrProcess->ClientId = CreateSession->ProcessInfo.ClientId;
CsrProcess->ProcessHandle = hProcess;
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++)
{
/* Get the current Server */
ServerDll = CsrLoadedServerDll[i];
/* Check if the DLL is loaded and has Process Data */
if (ServerDll && ServerDll->SizeOfProcessData)
{
/* Write the pointer to the data */
CsrProcess->ServerData[i] = ProcessData;
/* Move to the next data location */
ProcessData = (PVOID)((ULONG_PTR)ProcessData +
ServerDll->SizeOfProcessData);
}
else
{
/* Nothing for this Process */
CsrProcess->ServerData[i] = NULL;
}
}
/* Insert the Process */
CsrInsertProcess(NULL, CsrProcess);
/* Activate the Thread */
ApiMessage->ReturnValue = 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 otherwise.
*
* @remarks The CsrSbForeignSessionComplete API is not yet implemented.
*
*--*/
BOOLEAN
NTAPI
CsrSbForeignSessionComplete(IN PSB_API_MSG ApiMessage)
{
/* Deprecated/Unimplemented in NT */
ApiMessage->ReturnValue = STATUS_NOT_IMPLEMENTED;
return TRUE;
}
/*++
* @name CsrSbTerminateSession
*
* The CsrSbTerminateSession API is called by the Session Manager
* whenever a foreign session should be destroyed.
*
* @param ApiMessage
* Pointer to the Session Manager API Message.
*
* @return TRUE in case of success, FALSE otherwise.
*
* @remarks The CsrSbTerminateSession API is not yet implemented.
*
*--*/
BOOLEAN
NTAPI
CsrSbTerminateSession(IN PSB_API_MSG ApiMessage)
{
ApiMessage->ReturnValue = STATUS_NOT_IMPLEMENTED;
return TRUE;
}
/*++
* @name CsrSbCreateProcess
*
* The CsrSbCreateProcess API is called by the Session Manager
* whenever a foreign session is created and a new process should be started.
*
* @param ApiMessage
* Pointer to the Session Manager API Message.
*
* @return TRUE in case of success, FALSE otherwise.
*
* @remarks The CsrSbCreateProcess API is not yet implemented.
*
*--*/
BOOLEAN
NTAPI
CsrSbCreateProcess(IN PSB_API_MSG ApiMessage)
{
ApiMessage->ReturnValue = STATUS_NOT_IMPLEMENTED;
return TRUE;
}
/*++
* @name CsrSbApiHandleConnectionRequest
*
* The CsrSbApiHandleConnectionRequest routine handles and accepts a new
* connection request to the SM API LPC Port.
*
* @param ApiMessage
* Pointer to the incoming CSR API Message which contains the
* connection request.
*
* @return STATUS_SUCCESS in case of success, or status code which caused
* the routine to error.
*
* @remarks None.
*
*--*/
NTSTATUS
NTAPI
CsrSbApiHandleConnectionRequest(IN PSB_API_MSG Message)
{
NTSTATUS Status;
REMOTE_PORT_VIEW RemotePortView;
HANDLE hPort;
/* Set the Port View Structure Length */
RemotePortView.Length = sizeof(REMOTE_PORT_VIEW);
/* Accept the connection */
Status = NtAcceptConnectPort(&hPort,
NULL,
(PPORT_MESSAGE)Message,
TRUE,
NULL,
&RemotePortView);
if (!NT_SUCCESS(Status))
{
DPRINT1("CSRSS: Sb Accept Connection failed %lx\n", Status);
return Status;
}
/* Complete the Connection */
Status = NtCompleteConnectPort(hPort);
if (!NT_SUCCESS(Status))
{
DPRINT1("CSRSS: Sb Complete Connection failed %lx\n",Status);
}
/* Return status */
return Status;
}
/*++
* @name CsrSbApiRequestThread
*
* The CsrSbApiRequestThread routine handles incoming messages or connection
* requests on the SM API LPC Port.
*
* @param Parameter
* System-default user-defined parameter. Unused.
*
* @return The thread exit code, if the thread is terminated.
*
* @remarks Before listening on the port, the routine will first attempt
* to connect to the user subsystem.
*
*--*/
VOID
NTAPI
CsrSbApiRequestThread(IN PVOID Parameter)
{
NTSTATUS Status;
SB_API_MSG ReceiveMsg;
PSB_API_MSG ReplyMsg = NULL;
PVOID PortContext;
ULONG MessageType;
/* Start the loop */
while (TRUE)
{
/* Wait for a message to come in */
Status = NtReplyWaitReceivePort(CsrSbApiPort,
&PortContext,
&ReplyMsg->h,
&ReceiveMsg.h);
/* Check if we didn't get success */
if (Status != STATUS_SUCCESS)
{
/* If we only got a warning, keep going */
if (NT_SUCCESS(Status)) continue;
/* We failed big time, so start out fresh */
ReplyMsg = NULL;
DPRINT1("CSRSS: ReceivePort failed - Status == %X\n", Status);
continue;
}
/* Save the message type */
MessageType = ReceiveMsg.h.u2.s2.Type;
/* Check if this is a connection request */
if (MessageType == LPC_CONNECTION_REQUEST)
{
/* Handle connection request */
CsrSbApiHandleConnectionRequest(&ReceiveMsg);
/* Start over */
ReplyMsg = NULL;
continue;
}
/* Check if the port died */
if (MessageType == LPC_PORT_CLOSED)
{
/* Close the handle if we have one */
if (PortContext) NtClose((HANDLE)PortContext);
/* Client died, start over */
ReplyMsg = NULL;
continue;
}
else if (MessageType == LPC_CLIENT_DIED)
{
/* Client died, start over */
ReplyMsg = NULL;
continue;
}
/*
* It's an API Message, check if it's within limits. If it's not, the
* NT Behaviour is to set this to the Maximum API.
*/
if (ReceiveMsg.ApiNumber > SbpMaxApiNumber)
{
ReceiveMsg.ApiNumber = SbpMaxApiNumber;
DPRINT1("CSRSS: %lx is invalid Sb ApiNumber\n", ReceiveMsg.ApiNumber);
}
/* Reuse the message */
ReplyMsg = &ReceiveMsg;
/* Make sure that the message is supported */
if (ReceiveMsg.ApiNumber < SbpMaxApiNumber)
{
/* Call the API */
if (!CsrServerSbApiDispatch[ReceiveMsg.ApiNumber](&ReceiveMsg))
{
/* It failed, so return nothing */
ReplyMsg = NULL;
}
}
else
{
/* We don't support this API Number */
ReplyMsg->ReturnValue = STATUS_NOT_IMPLEMENTED;
}
}
}
/* EOF */