1 /* $Id: smss.c 12852 2005-01-06 13:58:04Z mf $
3 * client.c - Session Manager client Management
5 * ReactOS Operating System
7 * --------------------------------------------------------------------
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.
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.
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,
24 * --------------------------------------------------------------------
26 #define NTOS_MODE_USER
29 #include <sm/helper.h>
37 struct _SM_CLIENT_DIRECTORY
39 RTL_CRITICAL_SECTION Lock
;
41 PSM_CLIENT_DATA Client
;
45 /**********************************************************************
46 * SmInitializeClientManagement/0
49 SmInitializeClientManagement (VOID
)
51 DPRINT("SM: %s called\n", __FUNCTION__
);
52 RtlInitializeCriticalSection(& SmpClientDirectory
.Lock
);
53 SmpClientDirectory
.Count
= 0;
54 SmpClientDirectory
.Client
= NULL
;
55 return STATUS_SUCCESS
;
59 /**********************************************************************
60 * SmCompleteClientInitialization/1
63 * Lookup the subsystem server descriptor given the process handle
64 * of the subsystem server process.
67 SmCompleteClientInitialization (HANDLE hProcess
)
69 NTSTATUS Status
= STATUS_SUCCESS
;
70 PSM_CLIENT_DATA Client
= NULL
;
72 DPRINT("SM: %s called\n", __FUNCTION__
);
74 RtlEnterCriticalSection (& SmpClientDirectory
.Lock
);
75 if (SmpClientDirectory
.Count
> 0)
77 Client
= SmpClientDirectory
.Client
;
78 while (NULL
!= Client
)
80 if (hProcess
== Client
->ServerProcess
)
82 Client
->Initialized
= TRUE
;
85 Client
= Client
->Next
;
87 Status
= STATUS_NOT_FOUND
;
89 RtlLeaveCriticalSection (& SmpClientDirectory
.Lock
);
93 /**********************************************************************
94 * SmpLookupClient/1 PRIVATE
97 * Lookup the subsystem server descriptor given its image ID.
100 * SmpClientDirectory.Lock is released only on success.
102 static PSM_CLIENT_DATA FASTCALL
103 SmpLookupClientUnsafe (USHORT SubsystemId
,
104 PSM_CLIENT_DATA
* Parent
)
106 PSM_CLIENT_DATA Client
= NULL
;
108 DPRINT("SM: %s(%d) called\n", __FUNCTION__
, SubsystemId
);
114 if (SmpClientDirectory
.Count
> 0)
116 Client
= SmpClientDirectory
.Client
;
117 while (NULL
!= Client
)
119 if (SubsystemId
== Client
->SubsystemId
)
127 Client
= Client
->Next
;
133 static PSM_CLIENT_DATA STDCALL
134 SmpLookupClient (USHORT SubsystemId
)
136 PSM_CLIENT_DATA Client
= NULL
;
138 DPRINT("SM: %s called\n", __FUNCTION__
);
140 RtlEnterCriticalSection (& SmpClientDirectory
.Lock
);
141 Client
= SmpLookupClientUnsafe (SubsystemId
, NULL
);
144 RtlLeaveCriticalSection (& SmpClientDirectory
.Lock
);
147 * Note that we do *not* release SmpClientDirectory.Lock here
148 * because SmpLookupClient is called to FAIL when SubsystemId
149 * is not registered yet.
154 /**********************************************************************
158 SmCreateClient(PSM_PORT_MESSAGE Request
, PSM_CLIENT_DATA
* ClientData
)
160 PSM_CLIENT_DATA pClient
= NULL
;
161 PSM_CONNECT_DATA ConnectData
= SmpGetConnectData (Request
);
162 ULONG SbApiPortNameSize
= SM_CONNECT_DATA_SIZE(*Request
);
164 DPRINT("SM: %s called\n", __FUNCTION__
);
167 * Check if a client for the ID already exist.
169 if (SmpLookupClient(ConnectData
->SubSystemId
))
171 DPRINT("SM: %s: attempt to register again subsystem %d.\n",
173 ConnectData
->SubSystemId
);
174 return STATUS_UNSUCCESSFUL
;
176 DPRINT("SM: %s: registering subsystem ID=%d \n", __FUNCTION__
, ConnectData
->SubSystemId
);
178 * Allocate the storage for client data
180 pClient
= RtlAllocateHeap (SmpHeap
,
182 sizeof (SM_CLIENT_DATA
));
185 DPRINT("SM: %s: out of memory!\n",__FUNCTION__
);
186 return STATUS_NO_MEMORY
;
189 * Initialize the client data
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)
197 RtlCopyMemory (pClient
->SbApiPortName
,
202 * Insert the new descriptor in the
205 if (NULL
== SmpClientDirectory
.Client
)
207 SmpClientDirectory
.Client
= pClient
;
209 PSM_CLIENT_DATA pCD
= NULL
;
211 for (pCD
=SmpClientDirectory
.Client
;
216 pClient
->Next
= NULL
;
217 ++ SmpClientDirectory
.Count
;
219 * Note we unlock the client directory here, because
220 * it was locked by SmpLookupClient on failure.
222 RtlLeaveCriticalSection (& SmpClientDirectory
.Lock
);
225 *ClientData
= pClient
;
227 return STATUS_SUCCESS
;
230 /**********************************************************************
233 * 1. close any handle
234 * 2. kill client process
235 * 3. release resources
238 SmDestroyClient (ULONG SubsystemId
)
240 NTSTATUS Status
= STATUS_SUCCESS
;
241 PSM_CLIENT_DATA Parent
= NULL
;
242 PSM_CLIENT_DATA Client
= NULL
;
244 DPRINT("SM: %s called\n", __FUNCTION__
);
246 RtlEnterCriticalSection (& SmpClientDirectory
.Lock
);
247 Client
= SmpLookupClientUnsafe (SubsystemId
, & Parent
);
250 DPRINT1("SM: %s: del req for non existent subsystem (id=%d)\n",
251 __FUNCTION__
, SubsystemId
);
252 Status
= STATUS_NOT_FOUND
;
256 /* 1st in the list? */
259 SmpClientDirectory
.Client
= Client
->Next
;
265 Parent
->Next
= Client
->Next
;
267 DPRINT1("SM: %s: n-th has no parent!\n", __FUNCTION__
);
268 Status
= STATUS_UNSUCCESSFUL
; /* FIXME */
271 /* TODO: send shutdown or kill */
272 RtlFreeHeap (SmpHeap
, 0, Client
);
273 -- SmpClientDirectory
.Count
;
275 RtlLeaveCriticalSection (& SmpClientDirectory
.Lock
);