fixed some memory leaks
[reactos.git] / reactos / subsys / csr / csrsrv / session.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS CSR Sub System
4 * FILE: subsys/csr/csrsrv/session.c
5 * PURPOSE: CSR Server DLL Session Implementation
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "srv.h"
12
13 #define NDEBUG
14 #include <debug.h>
15
16 /* DATA **********************************************************************/
17 RTL_CRITICAL_SECTION CsrNtSessionLock;
18 LIST_ENTRY CsrNtSessionList;
19 HANDLE CsrSmApiPort;
20
21 PSB_API_ROUTINE CsrServerSbApiDispatch[5] =
22 {
23 CsrSbCreateSession,
24 CsrSbForeignSessionComplete,
25 CsrSbForeignSessionComplete,
26 CsrSbCreateProcess,
27 NULL
28 };
29
30 PCHAR CsrServerSbApiName[5] =
31 {
32 "SbCreateSession",
33 "SbTerminateSEssion",
34 "SbForeignSessionComplete",
35 "SbCreateProcess",
36 "Unknown Csr Sb Api Number"
37 };
38
39 /* PRIVATE FUNCTIONS *********************************************************/
40
41 /*++
42 * @name CsrInitializeNtSessions
43 *
44 * The CsrInitializeNtSessions routine sets up support for CSR Sessions.
45 *
46 * @param None
47 *
48 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
49 * othwerwise.
50 *
51 * @remarks None.
52 *
53 *--*/
54 NTSTATUS
55 NTAPI
56 CsrInitializeNtSessions(VOID)
57 {
58 NTSTATUS Status;
59 DPRINT("CSRSRV: %s called\n", __FUNCTION__);
60
61 /* Initialize the Session List */
62 InitializeListHead(&CsrNtSessionList);
63
64 /* Initialize the Session Lock */
65 Status = RtlInitializeCriticalSection(&CsrNtSessionLock);
66 return Status;
67 }
68
69 /*++
70 * @name CsrAllocateNtSession
71 *
72 * The CsrAllocateNtSession routine allocates a new CSR NT Session.
73 *
74 * @param SessionId
75 * Session ID of the CSR NT Session to allocate.
76 *
77 * @return Pointer to the newly allocated CSR NT Session.
78 *
79 * @remarks None.
80 *
81 *--*/
82 PCSR_NT_SESSION
83 NTAPI
84 CsrAllocateNtSession(ULONG SessionId)
85 {
86 PCSR_NT_SESSION NtSession;
87
88 /* Allocate an NT Session Object */
89 NtSession = RtlAllocateHeap(CsrHeap,
90 0,
91 sizeof(CSR_NT_SESSION));
92
93 /* Setup the Session Object */
94 if (NtSession)
95 {
96 NtSession->SessionId = SessionId;
97 NtSession->ReferenceCount = 1;
98
99 /* Insert it into the Session List */
100 CsrAcquireNtSessionLock();
101 InsertHeadList(&CsrNtSessionList, &NtSession->SessionList);
102 CsrReleaseNtSessionLock();
103 }
104
105 /* Return the Session (or NULL) */
106 return NtSession;
107 }
108
109 /*++
110 * @name CsrReferenceNtSession
111 *
112 * The CsrReferenceNtSession increases the reference count of a CSR NT Session.
113 *
114 * @param Session
115 * Pointer to the CSR NT Session to reference.
116 *
117 * @return None.
118 *
119 * @remarks None.
120 *
121 *--*/
122 VOID
123 NTAPI
124 CsrReferenceNtSession(PCSR_NT_SESSION Session)
125 {
126 /* Acquire the lock */
127 CsrAcquireNtSessionLock();
128
129 /* Increase the reference count */
130 Session->ReferenceCount++;
131
132 /* Release the lock */
133 CsrReleaseNtSessionLock();
134 }
135
136 /*++
137 * @name CsrDereferenceNtSession
138 *
139 * The CsrDereferenceNtSession decreases the reference count of a
140 * CSR NT Session.
141 *
142 * @param Session
143 * Pointer to the CSR NT Session to reference.
144 *
145 * @param ExitStatus
146 * If this is the last reference to the session, this argument
147 * specifies the exit status.
148 *
149 * @return None.
150 *
151 * @remarks CsrDereferenceNtSession will complete the session if
152 * the last reference to it has been closed.
153 *
154 *--*/
155 VOID
156 NTAPI
157 CsrDereferenceNtSession(PCSR_NT_SESSION Session,
158 NTSTATUS ExitStatus)
159 {
160 /* Acquire the lock */
161 CsrAcquireNtSessionLock();
162
163 /* Dereference the Session Object */
164 if (!(--Session->ReferenceCount))
165 {
166 /* Remove it from the list */
167 RemoveEntryList(&Session->SessionList);
168
169 /* Release the lock */
170 CsrReleaseNtSessionLock();
171
172 /* Tell SM that we're done here */
173 SmSessionComplete(CsrSmApiPort, Session->SessionId, ExitStatus);
174
175 /* Free the Session Object */
176 RtlFreeHeap(CsrHeap, 0, Session);
177 }
178 else
179 {
180 /* Release the lock, the Session is still active */
181 CsrReleaseNtSessionLock();
182 }
183 }
184
185
186 /* SESSION MANAGER FUNCTIONS**************************************************/
187
188 /*++
189 * @name CsrSbCreateSession
190 *
191 * The CsrSbCreateSession API is called by the Session Manager whenever a new
192 * session is created.
193 *
194 * @param ApiMessage
195 * Pointer to the Session Manager API Message.
196 *
197 * @return TRUE in case of success, FALSE othwerwise.
198 *
199 * @remarks The CsrSbCreateSession routine will initialize a new CSR NT
200 * Session and allocate a new CSR Process for the subsystem process.
201 *
202 *--*/
203 BOOLEAN
204 NTAPI
205 CsrSbCreateSession(IN PSB_API_MESSAGE ApiMessage)
206 {
207 PSB_CREATE_SESSION CreateSession = &ApiMessage->SbCreateSession;
208 HANDLE hProcess, hThread;
209 PCSR_PROCESS CsrProcess;
210 NTSTATUS Status;
211 KERNEL_USER_TIMES KernelTimes;
212 PCSR_THREAD CsrThread;
213 PVOID ProcessData;
214 ULONG i;
215
216 /* Save the Process and Thread Handles */
217 hProcess = CreateSession->ProcessInfo.ProcessHandle;
218 hThread = CreateSession->ProcessInfo.ThreadHandle;
219
220 /* Lock the Processes */
221 CsrAcquireProcessLock();
222
223 /* Allocate a new process */
224 if (!(CsrProcess = CsrAllocateProcess()))
225 {
226 /* Fail */
227 ApiMessage->Status = STATUS_NO_MEMORY;
228 CsrReleaseProcessLock();
229 return TRUE;
230 }
231
232 /* Setup Process Data */
233 CsrProcess->ClientId = CreateSession->ProcessInfo.ClientId;
234 CsrProcess->ProcessHandle = hProcess;
235
236 /* Set the exception port */
237 Status = NtSetInformationProcess(hProcess,
238 ProcessExceptionPort,
239 &CsrApiPort,
240 sizeof(HANDLE));
241
242 /* Check for success */
243 if (!NT_SUCCESS(Status))
244 {
245 /* Fail the request */
246 CsrDeallocateProcess(CsrProcess);
247 CsrReleaseProcessLock();
248
249 /* Strange as it seems, NTSTATUSes are actually returned */
250 return (BOOLEAN)STATUS_NO_MEMORY;
251 }
252
253 /* Get the Create Time */
254 Status = NtQueryInformationThread(hThread,
255 ThreadTimes,
256 &KernelTimes,
257 sizeof(KERNEL_USER_TIMES),
258 NULL);
259
260 /* Check for success */
261 if (!NT_SUCCESS(Status))
262 {
263 /* Fail the request */
264 CsrDeallocateProcess(CsrProcess);
265 CsrReleaseProcessLock();
266
267 return (BOOLEAN)Status;
268 }
269
270 /* Allocate a new Thread */
271 if (!(CsrThread = CsrAllocateThread(CsrProcess)))
272 {
273 /* Fail the request */
274 CsrDeallocateProcess(CsrProcess);
275 ApiMessage->Status = STATUS_NO_MEMORY;
276 CsrReleaseProcessLock();
277 return TRUE;
278 }
279
280 /* Setup the Thread Object */
281 CsrThread->CreateTime = KernelTimes.CreateTime;
282 CsrThread->ClientId = CreateSession->ProcessInfo.ClientId;
283 CsrThread->ThreadHandle = hThread;
284 CsrThread->Flags = 0;
285
286 /* Insert it into the Process List */
287 CsrInsertThread(CsrProcess, CsrThread);
288
289 /* Allocate a new Session */
290 CsrProcess->NtSession = CsrAllocateNtSession(CreateSession->SessionId);
291
292 /* Set the Process Priority */
293 CsrSetBackgroundPriority(CsrProcess);
294
295 /* Get the first data location */
296 ProcessData = &CsrProcess->ServerData[CSR_SERVER_DLL_MAX];
297
298 /* Loop every DLL */
299 for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
300 {
301 /* Check if the DLL is loaded and has Process Data */
302 if (CsrLoadedServerDll[i] && CsrLoadedServerDll[i]->SizeOfProcessData)
303 {
304 /* Write the pointer to the data */
305 CsrProcess->ServerData[i] = ProcessData;
306
307 /* Move to the next data location */
308 ProcessData = (PVOID)((ULONG_PTR)ProcessData +
309 CsrLoadedServerDll[i]->SizeOfProcessData);
310 }
311 else
312 {
313 /* Nothing for this Process */
314 CsrProcess->ServerData[i] = NULL;
315 }
316 }
317
318 /* Insert the Process */
319 CsrInsertProcess(NULL, NULL, CsrProcess);
320
321 /* Activate the Thread */
322 ApiMessage->Status = NtResumeThread(hThread, NULL);
323
324 /* Release lock and return */
325 CsrReleaseProcessLock();
326 return TRUE;
327 }
328
329 /*++
330 * @name CsrSbForeignSessionComplete
331 *
332 * The CsrSbForeignSessionComplete API is called by the Session Manager
333 * whenever a foreign session is completed (ie: terminated).
334 *
335 * @param ApiMessage
336 * Pointer to the Session Manager API Message.
337 *
338 * @return TRUE in case of success, FALSE othwerwise.
339 *
340 * @remarks The CsrSbForeignSessionComplete API is not yet implemented.
341 *
342 *--*/
343 BOOLEAN
344 NTAPI
345 CsrSbForeignSessionComplete(IN PSB_API_MESSAGE ApiMessage)
346 {
347 /* Deprecated/Unimplemented in NT */
348 ApiMessage->Status = STATUS_NOT_IMPLEMENTED;
349 return TRUE;
350 }
351 /* EOF */