2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS CSR SubSystem
4 * FILE: subsystems/win32/csrss/csrsrv/session.c
5 * PURPOSE: CSR Server DLL Session Implementation
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
9 /* INCLUDES ******************************************************************/
16 /* DATA **********************************************************************/
18 RTL_CRITICAL_SECTION CsrNtSessionLock
;
19 LIST_ENTRY CsrNtSessionList
;
21 // Does it exist a enumeration associated with it ?
22 PSB_API_ROUTINE CsrServerSbApiDispatch
[5] =
25 CsrSbTerminateSession
,
26 CsrSbForeignSessionComplete
,
31 PCHAR CsrServerSbApiName
[5] =
35 "SbForeignSessionComplete",
37 "Unknown Csr Sb Api Number"
40 /* PRIVATE FUNCTIONS *********************************************************/
43 * @name CsrInitializeNtSessionList
45 * The CsrInitializeNtSessionList routine sets up support for CSR Sessions.
56 CsrInitializeNtSessionList(VOID
)
58 DPRINT("CSRSRV: %s called\n", __FUNCTION__
);
60 /* Initialize the Session List */
61 InitializeListHead(&CsrNtSessionList
);
63 /* Initialize the Session Lock */
64 return RtlInitializeCriticalSection(&CsrNtSessionLock
);
68 * @name CsrAllocateNtSession
70 * The CsrAllocateNtSession routine allocates a new CSR NT Session.
73 * Session ID of the CSR NT Session to allocate.
75 * @return Pointer to the newly allocated CSR NT Session.
82 CsrAllocateNtSession(IN ULONG SessionId
)
84 PCSR_NT_SESSION NtSession
;
86 /* Allocate an NT Session Object */
87 NtSession
= RtlAllocateHeap(CsrHeap
, 0, sizeof(CSR_NT_SESSION
));
90 /* Setup the Session Object */
91 NtSession
->SessionId
= SessionId
;
92 NtSession
->ReferenceCount
= 1;
94 /* Insert it into the Session List */
95 CsrAcquireNtSessionLock();
96 InsertHeadList(&CsrNtSessionList
, &NtSession
->SessionLink
);
97 CsrReleaseNtSessionLock();
101 ASSERT(NtSession
!= NULL
);
104 /* Return the Session (or NULL) */
109 * @name CsrReferenceNtSession
111 * The CsrReferenceNtSession increases the reference count of a CSR NT Session.
114 * Pointer to the CSR NT Session to reference.
123 CsrReferenceNtSession(IN PCSR_NT_SESSION Session
)
125 /* Acquire the lock */
126 CsrAcquireNtSessionLock();
129 ASSERT(!IsListEmpty(&Session
->SessionLink
));
130 ASSERT(Session
->SessionId
!= 0);
131 ASSERT(Session
->ReferenceCount
!= 0);
133 /* Increase the reference count */
134 Session
->ReferenceCount
++;
136 /* Release the lock */
137 CsrReleaseNtSessionLock();
141 * @name CsrDereferenceNtSession
143 * The CsrDereferenceNtSession decreases the reference count of a
147 * Pointer to the CSR NT Session to reference.
150 * If this is the last reference to the session, this argument
151 * specifies the exit status.
155 * @remarks CsrDereferenceNtSession will complete the session if
156 * the last reference to it has been closed.
161 CsrDereferenceNtSession(IN PCSR_NT_SESSION Session
,
162 IN NTSTATUS ExitStatus
)
164 /* Acquire the lock */
165 CsrAcquireNtSessionLock();
168 ASSERT(!IsListEmpty(&Session
->SessionLink
));
169 ASSERT(Session
->SessionId
!= 0);
170 ASSERT(Session
->ReferenceCount
!= 0);
172 /* Dereference the Session Object */
173 if (!(--Session
->ReferenceCount
))
175 /* Remove it from the list */
176 RemoveEntryList(&Session
->SessionLink
);
178 /* Release the lock */
179 CsrReleaseNtSessionLock();
181 /* Tell SM that we're done here */
182 SmSessionComplete(CsrSmApiPort
, Session
->SessionId
, ExitStatus
);
184 /* Free the Session Object */
185 RtlFreeHeap(CsrHeap
, 0, Session
);
189 /* Release the lock, the Session is still active */
190 CsrReleaseNtSessionLock();
194 /* SESSION MANAGER FUNCTIONS**************************************************/
197 * @name CsrSbCreateSession
199 * The CsrSbCreateSession API is called by the Session Manager whenever a new
200 * session is created.
203 * Pointer to the Session Manager API Message.
205 * @return TRUE in case of success, FALSE otherwise.
207 * @remarks The CsrSbCreateSession routine will initialize a new CSR NT
208 * Session and allocate a new CSR Process for the subsystem process.
213 CsrSbCreateSession(IN PSB_API_MSG ApiMessage
)
215 PSB_CREATE_SESSION_MSG CreateSession
= &ApiMessage
->CreateSession
;
216 HANDLE hProcess
, hThread
;
217 PCSR_PROCESS CsrProcess
;
219 KERNEL_USER_TIMES KernelTimes
;
220 PCSR_THREAD CsrThread
;
224 /* Save the Process and Thread Handles */
225 hProcess
= CreateSession
->ProcessInfo
.ProcessHandle
;
226 hThread
= CreateSession
->ProcessInfo
.ThreadHandle
;
228 /* Lock the Processes */
229 CsrAcquireProcessLock();
231 /* Allocate a new process */
232 CsrProcess
= CsrAllocateProcess();
236 ApiMessage
->ReturnValue
= STATUS_NO_MEMORY
;
237 CsrReleaseProcessLock();
241 /* Set the exception port */
242 Status
= NtSetInformationProcess(hProcess
,
243 ProcessExceptionPort
,
247 /* Check for success */
248 if (!NT_SUCCESS(Status
))
250 /* Fail the request */
251 CsrDeallocateProcess(CsrProcess
);
252 CsrReleaseProcessLock();
254 /* Strange as it seems, NTSTATUSes are actually returned */
255 return (BOOLEAN
)STATUS_NO_MEMORY
;
258 /* Get the Create Time */
259 Status
= NtQueryInformationThread(hThread
,
262 sizeof(KERNEL_USER_TIMES
),
265 /* Check for success */
266 if (!NT_SUCCESS(Status
))
268 /* Fail the request */
269 CsrDeallocateProcess(CsrProcess
);
270 CsrReleaseProcessLock();
272 /* Strange as it seems, NTSTATUSes are actually returned */
273 return (BOOLEAN
)Status
;
276 /* Allocate a new Thread */
277 CsrThread
= CsrAllocateThread(CsrProcess
);
280 /* Fail the request */
281 CsrDeallocateProcess(CsrProcess
);
282 CsrReleaseProcessLock();
284 ApiMessage
->ReturnValue
= STATUS_NO_MEMORY
;
288 /* Setup the Thread Object */
289 CsrThread
->CreateTime
= KernelTimes
.CreateTime
;
290 CsrThread
->ClientId
= CreateSession
->ProcessInfo
.ClientId
;
291 CsrThread
->ThreadHandle
= hThread
;
292 ProtectHandle(hThread
);
293 CsrThread
->Flags
= 0;
295 /* Insert it into the Process List */
296 CsrInsertThread(CsrProcess
, CsrThread
);
298 /* Setup Process Data */
299 CsrProcess
->ClientId
= CreateSession
->ProcessInfo
.ClientId
;
300 CsrProcess
->ProcessHandle
= hProcess
;
301 CsrProcess
->NtSession
= CsrAllocateNtSession(CreateSession
->SessionId
);
303 /* Set the Process Priority */
304 CsrSetBackgroundPriority(CsrProcess
);
306 /* Get the first data location */
307 ProcessData
= &CsrProcess
->ServerData
[CSR_SERVER_DLL_MAX
];
310 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
312 /* Check if the DLL is loaded and has Process Data */
313 if (CsrLoadedServerDll
[i
] && CsrLoadedServerDll
[i
]->SizeOfProcessData
)
315 /* Write the pointer to the data */
316 CsrProcess
->ServerData
[i
] = ProcessData
;
318 /* Move to the next data location */
319 ProcessData
= (PVOID
)((ULONG_PTR
)ProcessData
+
320 CsrLoadedServerDll
[i
]->SizeOfProcessData
);
324 /* Nothing for this Process */
325 CsrProcess
->ServerData
[i
] = NULL
;
329 /* HACK: FIXME: should go in BaseSrv part of CreateCallback done in Insert below */
330 // RtlInitializeCriticalSection(&CsrProcess->HandleTableLock);
332 /* Insert the Process */
333 CsrInsertProcess(NULL
, NULL
, CsrProcess
);
335 /* Activate the Thread */
336 ApiMessage
->ReturnValue
= NtResumeThread(hThread
, NULL
);
338 /* Release lock and return */
339 CsrReleaseProcessLock();
344 * @name CsrSbForeignSessionComplete
346 * The CsrSbForeignSessionComplete API is called by the Session Manager
347 * whenever a foreign session is completed (ie: terminated).
350 * Pointer to the Session Manager API Message.
352 * @return TRUE in case of success, FALSE otherwise.
354 * @remarks The CsrSbForeignSessionComplete API is not yet implemented.
359 CsrSbForeignSessionComplete(IN PSB_API_MSG ApiMessage
)
361 /* Deprecated/Unimplemented in NT */
362 ApiMessage
->ReturnValue
= STATUS_NOT_IMPLEMENTED
;
367 * @name CsrSbTerminateSession
369 * The CsrSbTerminateSession API is called by the Session Manager
370 * whenever a foreign session should be destroyed.
373 * Pointer to the Session Manager API Message.
375 * @return TRUE in case of success, FALSE otherwise.
377 * @remarks The CsrSbTerminateSession API is not yet implemented.
382 CsrSbTerminateSession(IN PSB_API_MSG ApiMessage
)
384 ApiMessage
->ReturnValue
= STATUS_NOT_IMPLEMENTED
;
389 * @name CsrSbCreateProcess
391 * The CsrSbCreateProcess API is called by the Session Manager
392 * whenever a foreign session is created and a new process should be started.
395 * Pointer to the Session Manager API Message.
397 * @return TRUE in case of success, FALSE otherwise.
399 * @remarks The CsrSbCreateProcess API is not yet implemented.
404 CsrSbCreateProcess(IN PSB_API_MSG ApiMessage
)
406 ApiMessage
->ReturnValue
= STATUS_NOT_IMPLEMENTED
;
411 * @name CsrSbApiHandleConnectionRequest
413 * The CsrSbApiHandleConnectionRequest routine handles and accepts a new
414 * connection request to the SM API LPC Port.
417 * Pointer to the incoming CSR API Message which contains the
418 * connection request.
420 * @return STATUS_SUCCESS in case of success, or status code which caused
421 * the routine to error.
428 CsrSbApiHandleConnectionRequest(IN PSB_API_MSG Message
)
431 REMOTE_PORT_VIEW RemotePortView
;
434 /* Set the Port View Structure Length */
435 RemotePortView
.Length
= sizeof(REMOTE_PORT_VIEW
);
437 /* Accept the connection */
438 Status
= NtAcceptConnectPort(&hPort
,
440 (PPORT_MESSAGE
)Message
,
444 if (!NT_SUCCESS(Status
))
446 DPRINT1("CSRSS: Sb Accept Connection failed %lx\n", Status
);
450 /* Complete the Connection */
451 Status
= NtCompleteConnectPort(hPort
);
452 if (!NT_SUCCESS(Status
))
454 DPRINT1("CSRSS: Sb Complete Connection failed %lx\n",Status
);
462 * @name CsrSbApiRequestThread
464 * The CsrSbApiRequestThread routine handles incoming messages or connection
465 * requests on the SM API LPC Port.
468 * System-default user-defined parameter. Unused.
470 * @return The thread exit code, if the thread is terminated.
472 * @remarks Before listening on the port, the routine will first attempt
473 * to connect to the user subsystem.
478 CsrSbApiRequestThread(IN PVOID Parameter
)
481 SB_API_MSG ReceiveMsg
;
482 PSB_API_MSG ReplyMsg
= NULL
;
489 /* Wait for a message to come in */
490 Status
= NtReplyWaitReceivePort(CsrSbApiPort
,
495 /* Check if we didn't get success */
496 if (Status
!= STATUS_SUCCESS
)
498 /* If we only got a warning, keep going */
499 if (NT_SUCCESS(Status
)) continue;
501 /* We failed big time, so start out fresh */
503 DPRINT1("CSRSS: ReceivePort failed - Status == %X\n", Status
);
507 /* Save the message type */
508 MessageType
= ReceiveMsg
.h
.u2
.s2
.Type
;
510 /* Check if this is a connection request */
511 if (MessageType
== LPC_CONNECTION_REQUEST
)
513 /* Handle connection request */
514 CsrSbApiHandleConnectionRequest(&ReceiveMsg
);
521 /* Check if the port died */
522 if (MessageType
== LPC_PORT_CLOSED
)
524 /* Close the handle if we have one */
525 if (PortContext
) NtClose((HANDLE
)PortContext
);
527 /* Client died, start over */
531 else if (MessageType
== LPC_CLIENT_DIED
)
533 /* Client died, start over */
539 * It's an API Message, check if it's within limits. If it's not, the
540 * NT Behaviour is to set this to the Maximum API.
542 if (ReceiveMsg
.ApiNumber
> SbpMaxApiNumber
)
544 ReceiveMsg
.ApiNumber
= SbpMaxApiNumber
;
545 DPRINT1("CSRSS: %lx is invalid Sb ApiNumber\n", ReceiveMsg
.ApiNumber
);
548 /* Reuse the message */
549 ReplyMsg
= &ReceiveMsg
;
551 /* Make sure that the message is supported */
552 if (ReceiveMsg
.ApiNumber
< SbpMaxApiNumber
)
555 if (!CsrServerSbApiDispatch
[ReceiveMsg
.ApiNumber
](&ReceiveMsg
))
557 /* It failed, so return nothing */
563 /* We don't support this API Number */
564 ReplyMsg
->ReturnValue
= STATUS_NOT_IMPLEMENTED
;