SM: subsystem registration (partial)
[reactos.git] / reactos / subsys / smss / smapi.c
1 /* $Id$
2 *
3 * smapi.c - \SmApiPort LPC port message management
4 *
5 * Reactos Session Manager
6 *
7 */
8
9 #include "smss.h"
10 #include <rosrtl/string.h>
11
12 //#define NDEBUG
13 #include <debug.h>
14
15 /* GLOBAL VARIABLES *********************************************************/
16
17 static HANDLE SmApiPort = INVALID_HANDLE_VALUE;
18
19 /* SM API *******************************************************************/
20
21 SMAPI(SmInvalid)
22 {
23 DPRINT("SM: %s called\n",__FUNCTION__);
24 Request->Status = STATUS_NOT_IMPLEMENTED;
25 return STATUS_SUCCESS;
26 }
27
28 /* SM API Table */
29 typedef NTSTATUS (FASTCALL * SM_PORT_API)(PSM_PORT_MESSAGE);
30
31 SM_PORT_API SmApi [] =
32 {
33 SmInvalid, /* unused */
34 SmCompSes, /* smapicomp.c */
35 SmInvalid, /* obsolete */
36 SmInvalid, /* unknown */
37 SmExecPgm /* smapiexec.c */
38 };
39
40 #if !defined(__USE_NT_LPC__)
41 NTSTATUS STDCALL
42 SmpHandleConnectionRequest (PSM_PORT_MESSAGE Request);
43 #endif
44
45
46 /**********************************************************************
47 * NAME
48 * SmpApiConnectedThread/1
49 *
50 * DESCRIPTION
51 * Entry point for the listener thread of LPC port "\SmApiPort".
52 */
53 VOID STDCALL
54 SmpApiConnectedThread(PVOID dummy)
55 {
56 NTSTATUS Status = STATUS_SUCCESS;
57 PVOID Unknown = NULL;
58 PLPC_MESSAGE Reply = NULL;
59 SM_PORT_MESSAGE Request = {{0}};
60
61 DPRINT("SM: %s running\n",__FUNCTION__);
62
63 while (TRUE)
64 {
65 DPRINT("SM: %s: waiting for message\n",__FUNCTION__);
66
67 Status = NtReplyWaitReceivePort(SmApiPort,
68 (PULONG) & Unknown,
69 Reply,
70 (PLPC_MESSAGE) & Request);
71 if (NT_SUCCESS(Status))
72 {
73 DPRINT("SM: %s: message received (type=%d)\n",
74 __FUNCTION__,
75 PORT_MESSAGE_TYPE(Request));
76
77 switch (Request.Header.MessageType)
78 {
79 case LPC_CONNECTION_REQUEST:
80 SmpHandleConnectionRequest (&Request);
81 Reply = NULL;
82 break;
83 case LPC_DEBUG_EVENT:
84 // DbgSsHandleKmApiMsg (&Request, 0);
85 Reply = NULL;
86 break;
87 case LPC_PORT_CLOSED:
88 Reply = NULL;
89 break;
90 default:
91 if ((Request.ApiIndex) &&
92 (Request.ApiIndex < (sizeof SmApi / sizeof SmApi[0])))
93 {
94 Status = SmApi[Request.ApiIndex](&Request);
95 Reply = (PLPC_MESSAGE) & Request;
96 } else {
97 Request.Status = STATUS_NOT_IMPLEMENTED;
98 Reply = (PLPC_MESSAGE) & Request;
99 }
100 }
101 }
102 }
103 }
104
105 /**********************************************************************
106 * NAME
107 * SmpHandleConnectionRequest/1
108 *
109 * ARGUMENTS
110 * Request: LPC connection request message
111 *
112 * REMARKS
113 * Quoted in http://support.microsoft.com/kb/258060/EN-US/
114 */
115 NTSTATUS STDCALL
116 SmpHandleConnectionRequest (PSM_PORT_MESSAGE Request)
117 {
118 #if defined(__USE_NT_LPC__)
119 NTSTATUS Status = STATUS_SUCCESS;
120 PSM_CLIENT_DATA ClientData = NULL;
121 PVOID Context = NULL;
122
123 DPRINT("SM: %s called\n",__FUNCTION__);
124
125 /*
126 * SmCreateClient/2 is called here explicitly to *fail*.
127 * If it succeeds, there is something wrong in the
128 * connection request. An environment subsystem *never*
129 * registers twice. (Security issue: maybe we will
130 * write this event into the security log).
131 */
132 Status = SmCreateClient (Request, & ClientData);
133 if(STATUS_SUCCESS == Status)
134 {
135 /* OK: the client is an environment subsystem
136 * willing to manage a free image type.
137 * Accept it.
138 */
139 Status = NtAcceptConnectPort (& ClientData->ApiPort,
140 Context,
141 (PLPC_MESSAGE) Request,
142 TRUE, //accept
143 NULL,
144 NULL);
145 if(NT_SUCCESS(Status))
146 {
147 Status = NtCompleteConnectPort(ClientData->ApiPort);
148 }
149 return STATUS_SUCCESS;
150 } else {
151 /* Reject the subsystem */
152 Status = NtAcceptConnectPort (& ClientData->ApiPort,
153 Context,
154 (PLPC_MESSAGE) Request,
155 FALSE, //reject
156 NULL,
157 NULL);
158 }
159 #else /* ReactOS LPC */
160 NTSTATUS Status = STATUS_SUCCESS;
161 PSM_CLIENT_DATA ClientData = NULL;
162
163 DPRINT("SM: %s called\n",__FUNCTION__);
164
165 Status = SmCreateClient (Request, & ClientData);
166 if(STATUS_SUCCESS == Status)
167 {
168 Status = NtAcceptConnectPort (& ClientData->ApiPort,
169 SmApiPort,
170 NULL,
171 TRUE, //accept
172 NULL,
173 NULL);
174 if (!NT_SUCCESS(Status))
175 {
176 DPRINT1("SM: %s: NtAcceptConnectPort() failed (Status=0x%08lx)\n",
177 __FUNCTION__, Status);
178 return Status;
179 } else {
180 Status = NtCompleteConnectPort(ClientData->ApiPort);
181 if (!NT_SUCCESS(Status))
182 {
183 DPRINT1("SM: %s: NtCompleteConnectPort() failed (Status=0x%08lx)\n",
184 __FUNCTION__, Status);
185 return Status;
186 }
187 Status = RtlCreateUserThread(NtCurrentProcess(),
188 NULL,
189 FALSE,
190 0,
191 NULL,
192 NULL,
193 (PTHREAD_START_ROUTINE) SmpApiConnectedThread,
194 ClientData->ApiPort,
195 & ClientData->ApiPortThread,
196 NULL);
197 if (!NT_SUCCESS(Status))
198 {
199 DPRINT1("SM: %s: Unable to create server thread (Status=0x%08lx)\n",
200 __FUNCTION__, Status);
201 return Status;
202 }
203 }
204 return STATUS_SUCCESS;
205 } else {
206 /* Reject the subsystem */
207 Status = NtAcceptConnectPort (& ClientData->ApiPort,
208 SmApiPort,
209 NULL,
210 FALSE, //reject
211 NULL,
212 NULL);
213 }
214 #endif /* defined __USE_NT_LPC__ */
215 return Status;
216 }
217
218 /**********************************************************************
219 * NAME
220 * SmpApiThread/1
221 *
222 * DECRIPTION
223 * Due to differences in LPC implementation between NT and ROS,
224 * we need a thread to listen for connection request that
225 * creates a new thread for each connected port. This is not
226 * necessary in NT LPC, because server side connected ports are
227 * never used to receive requests.
228 */
229 VOID STDCALL
230 SmpApiThread (HANDLE ListeningPort)
231 {
232 NTSTATUS Status = STATUS_SUCCESS;
233 LPC_MAX_MESSAGE Request = {{0}};
234
235 while (TRUE)
236 {
237 Status = NtListenPort (ListeningPort, & Request.Header);
238 if (!NT_SUCCESS(Status))
239 {
240 DPRINT1("SM: %s: NtListenPort() failed! (Status==x%08lx)\n", __FUNCTION__, Status);
241 break;
242 }
243 Status = SmpHandleConnectionRequest ((PSM_PORT_MESSAGE) & Request);
244 if(!NT_SUCCESS(Status))
245 {
246 DPRINT1("SM: %s: SmpHandleConnectionRequest failed (Status=0x%08lx)\n",
247 __FUNCTION__, Status);
248 break;
249 }
250 }
251 /* Cleanup */
252 NtClose(ListeningPort);
253 /* DIE */
254 NtTerminateThread(NtCurrentThread(), Status);
255 }
256
257
258 /* LPC PORT INITIALIZATION **************************************************/
259
260
261 /**********************************************************************
262 * NAME
263 * SmCreateApiPort/0
264 *
265 * DECRIPTION
266 */
267 NTSTATUS
268 SmCreateApiPort(VOID)
269 {
270 OBJECT_ATTRIBUTES ObjectAttributes = {0};
271 UNICODE_STRING UnicodeString = {0};
272 NTSTATUS Status = STATUS_SUCCESS;
273
274 RtlRosInitUnicodeStringFromLiteral(&UnicodeString,
275 L"\\SmApiPort");
276 InitializeObjectAttributes(&ObjectAttributes,
277 &UnicodeString,
278 PORT_ALL_ACCESS,
279 NULL,
280 NULL);
281
282 Status = NtCreatePort(&SmApiPort,
283 &ObjectAttributes,
284 0,
285 0,
286 0);
287 if (!NT_SUCCESS(Status))
288 {
289 return(Status);
290 }
291 /*
292 * Create one thread for the named LPC
293 * port \SmApiPort
294 */
295 RtlCreateUserThread(NtCurrentProcess(),
296 NULL,
297 FALSE,
298 0,
299 NULL,
300 NULL,
301 (PTHREAD_START_ROUTINE)SmpApiThread,
302 (PVOID)SmApiPort,
303 NULL,
304 NULL);
305
306 return(Status);
307 }
308
309 /* EOF */