SM: some server side code for SM_API_QUERY_INFORMATION
[reactos.git] / reactos / subsys / smss / client.c
1 /* $Id: smss.c 12852 2005-01-06 13:58:04Z mf $
2 *
3 * client.c - Session Manager client Management
4 *
5 * ReactOS Operating System
6 *
7 * --------------------------------------------------------------------
8 *
9 * This software is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of the
12 * License, or (at your option) any later version.
13 *
14 * This software is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this software; see the file COPYING.LIB. If not, write
21 * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
22 * MA 02139, USA.
23 *
24 * --------------------------------------------------------------------
25 */
26 #define NTOS_MODE_USER
27 #include <ntos.h>
28 #include "smss.h"
29 #include <sm/helper.h>
30
31 #define NDEBUG
32 #include <debug.h>
33
34 /* Private ADT */
35
36
37 struct _SM_CLIENT_DIRECTORY
38 {
39 RTL_CRITICAL_SECTION Lock;
40 ULONG Count;
41 PSM_CLIENT_DATA Client;
42
43 } SmpClientDirectory;
44
45 /**********************************************************************
46 * SmInitializeClientManagement/0
47 */
48 NTSTATUS
49 SmInitializeClientManagement (VOID)
50 {
51 DPRINT("SM: %s called\n", __FUNCTION__);
52 RtlInitializeCriticalSection(& SmpClientDirectory.Lock);
53 SmpClientDirectory.Count = 0;
54 SmpClientDirectory.Client = NULL;
55 return STATUS_SUCCESS;
56
57 }
58
59 /**********************************************************************
60 * SmCompleteClientInitialization/1
61 *
62 * DESCRIPTION
63 * Lookup the subsystem server descriptor given the process handle
64 * of the subsystem server process.
65 */
66 NTSTATUS STDCALL
67 SmCompleteClientInitialization (HANDLE hProcess)
68 {
69 NTSTATUS Status = STATUS_SUCCESS;
70 PSM_CLIENT_DATA Client = NULL;
71
72 DPRINT("SM: %s called\n", __FUNCTION__);
73
74 RtlEnterCriticalSection (& SmpClientDirectory.Lock);
75 if (SmpClientDirectory.Count > 0)
76 {
77 Client = SmpClientDirectory.Client;
78 while (NULL != Client)
79 {
80 if (hProcess == Client->ServerProcess)
81 {
82 Client->Initialized = TRUE;
83 break;
84 }
85 Client = Client->Next;
86 }
87 Status = STATUS_NOT_FOUND;
88 }
89 RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
90 return Status;
91 }
92
93 /**********************************************************************
94 * SmpLookupClient/1 PRIVATE
95 *
96 * DESCRIPTION
97 * Lookup the subsystem server descriptor given its image ID.
98 *
99 * SIDE EFFECTS
100 * SmpClientDirectory.Lock is released only on success.
101 */
102 static PSM_CLIENT_DATA FASTCALL
103 SmpLookupClientUnsafe (USHORT SubsystemId,
104 PSM_CLIENT_DATA * Parent)
105 {
106 PSM_CLIENT_DATA Client = NULL;
107
108 DPRINT("SM: %s(%d) called\n", __FUNCTION__, SubsystemId);
109
110 if(NULL != Parent)
111 {
112 *Parent = NULL;
113 }
114 if (SmpClientDirectory.Count > 0)
115 {
116 Client = SmpClientDirectory.Client;
117 while (NULL != Client)
118 {
119 if (SubsystemId == Client->SubsystemId)
120 {
121 break;
122 }
123 if(NULL != Parent)
124 {
125 *Parent = Client;
126 }
127 Client = Client->Next;
128 }
129 }
130 return Client;
131 }
132
133 static PSM_CLIENT_DATA STDCALL
134 SmpLookupClient (USHORT SubsystemId)
135 {
136 PSM_CLIENT_DATA Client = NULL;
137
138 DPRINT("SM: %s called\n", __FUNCTION__);
139
140 RtlEnterCriticalSection (& SmpClientDirectory.Lock);
141 Client = SmpLookupClientUnsafe (SubsystemId, NULL);
142 if(NULL != Client)
143 {
144 RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
145 }
146 /*
147 * Note that we do *not* release SmpClientDirectory.Lock here
148 * because SmpLookupClient is called to FAIL when SubsystemId
149 * is not registered yet.
150 */
151 return Client;
152 }
153
154 /**********************************************************************
155 * SmpCreateClient/2
156 */
157 NTSTATUS STDCALL
158 SmCreateClient(PSM_PORT_MESSAGE Request, PSM_CLIENT_DATA * ClientData)
159 {
160 PSM_CLIENT_DATA pClient = NULL;
161 PSM_CONNECT_DATA ConnectData = SmpGetConnectData (Request);
162 ULONG SbApiPortNameSize = SM_CONNECT_DATA_SIZE(*Request);
163
164 DPRINT("SM: %s called\n", __FUNCTION__);
165
166 /*
167 * Check if a client for the ID already exist.
168 */
169 if (SmpLookupClient(ConnectData->SubSystemId))
170 {
171 DPRINT("SM: %s: attempt to register again subsystem %d.\n",
172 __FUNCTION__,
173 ConnectData->SubSystemId);
174 return STATUS_UNSUCCESSFUL;
175 }
176 DPRINT("SM: %s: registering subsystem ID=%d \n", __FUNCTION__, ConnectData->SubSystemId);
177 /*
178 * Allocate the storage for client data
179 */
180 pClient = RtlAllocateHeap (SmpHeap,
181 HEAP_ZERO_MEMORY,
182 sizeof (SM_CLIENT_DATA));
183 if (NULL == pClient)
184 {
185 DPRINT("SM: %s: out of memory!\n",__FUNCTION__);
186 return STATUS_NO_MEMORY;
187 }
188 /*
189 * Initialize the client data
190 */
191 pClient->SubsystemId = ConnectData->SubSystemId;
192 /* SM auto-initializes; other subsystems are required to call
193 * SM_API_COMPLETE_SESSION via SMDLL. */
194 pClient->Initialized = (IMAGE_SUBSYSTEM_NATIVE == pClient->SubsystemId);
195 if (SbApiPortNameSize > 0)
196 {
197 RtlCopyMemory (pClient->SbApiPortName,
198 ConnectData->SbName,
199 SbApiPortNameSize);
200 }
201 /*
202 * Insert the new descriptor in the
203 * client directory.
204 */
205 if (NULL == SmpClientDirectory.Client)
206 {
207 SmpClientDirectory.Client = pClient;
208 } else {
209 PSM_CLIENT_DATA pCD = NULL;
210
211 for (pCD=SmpClientDirectory.Client;
212 (NULL != pCD->Next);
213 pCD = pCD->Next);
214 pCD->Next = pClient;
215 }
216 pClient->Next = NULL;
217 ++ SmpClientDirectory.Count;
218 /*
219 * Note we unlock the client directory here, because
220 * it was locked by SmpLookupClient on failure.
221 */
222 RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
223 if (ClientData)
224 {
225 *ClientData = pClient;
226 }
227 return STATUS_SUCCESS;
228 }
229
230 /**********************************************************************
231 * SmpDestroyClient/1
232 *
233 * 1. close any handle
234 * 2. kill client process
235 * 3. release resources
236 */
237 NTSTATUS STDCALL
238 SmDestroyClient (ULONG SubsystemId)
239 {
240 NTSTATUS Status = STATUS_SUCCESS;
241 PSM_CLIENT_DATA Parent = NULL;
242 PSM_CLIENT_DATA Client = NULL;
243
244 DPRINT("SM: %s called\n", __FUNCTION__);
245
246 RtlEnterCriticalSection (& SmpClientDirectory.Lock);
247 Client = SmpLookupClientUnsafe (SubsystemId, & Parent);
248 if(NULL == Client)
249 {
250 DPRINT1("SM: %s: del req for non existent subsystem (id=%d)\n",
251 __FUNCTION__, SubsystemId);
252 Status = STATUS_NOT_FOUND;
253 }
254 else
255 {
256 /* 1st in the list? */
257 if(NULL == Parent)
258 {
259 SmpClientDirectory.Client = Client->Next;
260 }
261 else
262 {
263 if(NULL != Parent)
264 {
265 Parent->Next = Client->Next;
266 } else {
267 DPRINT1("SM: %s: n-th has no parent!\n", __FUNCTION__);
268 Status = STATUS_UNSUCCESSFUL; /* FIXME */
269 }
270 }
271 /* TODO: send shutdown or kill */
272 RtlFreeHeap (SmpHeap, 0, Client);
273 -- SmpClientDirectory.Count;
274 }
275 RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
276 return Status;
277 }
278
279 /* === Utilities for SmQryInfo === */
280
281 /**********************************************************************
282 * SmGetClientBasicInformation/1
283 */
284 NTSTATUS FASTCALL
285 SmGetClientBasicInformation (PSM_BASIC_INFORMATION i)
286 {
287 INT Index = 0;
288 PSM_CLIENT_DATA Client = NULL;
289
290 DPRINT("SM: %s called\n", __FUNCTION__);
291
292 RtlEnterCriticalSection (& SmpClientDirectory.Lock);
293
294 i->SubSystemCount = SmpClientDirectory.Count;
295 i->Unused = 0;
296
297 if (SmpClientDirectory.Count > 0)
298 {
299 Client = SmpClientDirectory.Client;
300 while ((NULL != Client) && (Index < SM_QRYINFO_MAX_SS_COUNT))
301 {
302 i->SubSystem[Index].Id = Client->SubsystemId;
303 i->SubSystem[Index].Flags = 0; /* TODO */
304 i->SubSystem[Index].ProcessId = 0; /* TODO */
305 Client = Client->Next;
306 }
307 }
308
309 RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
310 return STATUS_SUCCESS;
311 }
312
313 /**********************************************************************
314 * SmGetSubSystemInformation/1
315 */
316 NTSTATUS FASTCALL
317 SmGetSubSystemInformation (PSM_SUBSYSTEM_INFORMATION i)
318 {
319 DPRINT("SM: %s called\n", __FUNCTION__);
320
321 return STATUS_NOT_IMPLEMENTED;
322 }
323
324 /* EOF */