3 * smapi.c - \SmApiPort LPC port message management
5 * Reactos Session Manager
10 #include <rosrtl/string.h>
15 /* GLOBAL VARIABLES *********************************************************/
17 static HANDLE SmApiPort
= INVALID_HANDLE_VALUE
;
19 /* SM API *******************************************************************/
23 DPRINT("SM: %s called\n",__FUNCTION__
);
24 Request
->SmHeader
.Status
= STATUS_NOT_IMPLEMENTED
;
25 return STATUS_SUCCESS
;
29 typedef NTSTATUS (FASTCALL
* SM_PORT_API
)(PSM_PORT_MESSAGE
);
31 SM_PORT_API SmApi
[] =
33 SmInvalid
, /* unused */
34 SmCompSes
, /* smapicomp.c */
35 SmInvalid
, /* obsolete */
36 SmInvalid
, /* unknown */
37 SmExecPgm
, /* smapiexec.c */
38 SmQryInfo
/* smapyqry.c */
41 /* TODO: optimize this address computation (it should be done
43 PSM_CONNECT_DATA FASTCALL
SmpGetConnectData (PSM_PORT_MESSAGE Request
)
45 PLPC_MAX_MESSAGE LpcMaxMessage
= (PLPC_MAX_MESSAGE
) Request
;
46 return (PSM_CONNECT_DATA
) & LpcMaxMessage
->Data
[0];
49 #if !defined(__USE_NT_LPC__)
51 SmpHandleConnectionRequest (PSM_PORT_MESSAGE Request
);
54 /**********************************************************************
57 * The SM calls back a previously connected subsystem process to
58 * authorizes it to bootstrap (initialize). The SM connects to a
59 * named LPC port which name was sent in the connection data by the
60 * candidate subsystem server process.
63 SmpCallbackServer (PSM_PORT_MESSAGE Request
,
64 PSM_CLIENT_DATA ClientData
)
66 NTSTATUS Status
= STATUS_SUCCESS
;
67 PSM_CONNECT_DATA ConnectData
= SmpGetConnectData (Request
);
68 UNICODE_STRING CallbackPortName
;
69 ULONG CallbackPortNameLength
= SM_SB_NAME_MAX_LENGTH
; /* TODO: compute length */
70 SB_CONNECT_DATA SbConnectData
;
71 ULONG SbConnectDataLength
= sizeof SbConnectData
;
73 DPRINT("SM: %s called\n", __FUNCTION__
);
75 if(IMAGE_SUBSYSTEM_NATIVE
== ConnectData
->SubSystemId
)
77 DPRINT("SM: %s: we do not need calling back SM!\n",
79 return STATUS_SUCCESS
;
81 RtlCopyMemory (ClientData
->SbApiPortName
,
83 CallbackPortNameLength
);
84 RtlInitUnicodeString (& CallbackPortName
,
85 ClientData
->SbApiPortName
);
87 SbConnectData
.SmApiMax
= (sizeof SmApi
/ sizeof SmApi
[0]);
88 Status
= NtConnectPort (& ClientData
->SbApiPort
,
95 & SbConnectDataLength
);
99 /**********************************************************************
101 * SmpApiConnectedThread/1
104 * Entry point for the listener thread of LPC port "\SmApiPort".
107 SmpApiConnectedThread(PVOID pConnectedPort
)
109 NTSTATUS Status
= STATUS_SUCCESS
;
110 PVOID Unknown
= NULL
;
111 PLPC_MESSAGE Reply
= NULL
;
112 SM_PORT_MESSAGE Request
= {{0}};
113 HANDLE ConnectedPort
= * (PHANDLE
) pConnectedPort
;
115 DPRINT("SM: %s called\n", __FUNCTION__
);
119 DPRINT("SM: %s: waiting for message\n",__FUNCTION__
);
121 Status
= NtReplyWaitReceivePort(ConnectedPort
,
124 (PLPC_MESSAGE
) & Request
);
125 if (NT_SUCCESS(Status
))
127 DPRINT("SM: %s: message received (type=%d)\n",
129 PORT_MESSAGE_TYPE(Request
));
131 switch (Request
.Header
.MessageType
)
133 case LPC_CONNECTION_REQUEST
:
134 SmpHandleConnectionRequest (&Request
);
137 case LPC_DEBUG_EVENT
:
138 // DbgSsHandleKmApiMsg (&Request, 0);
141 case LPC_PORT_CLOSED
:
145 if ((Request
.SmHeader
.ApiIndex
) &&
146 (Request
.SmHeader
.ApiIndex
< (sizeof SmApi
/ sizeof SmApi
[0])))
148 Status
= SmApi
[Request
.SmHeader
.ApiIndex
](&Request
);
149 Reply
= (PLPC_MESSAGE
) & Request
;
151 Request
.SmHeader
.Status
= STATUS_NOT_IMPLEMENTED
;
152 Reply
= (PLPC_MESSAGE
) & Request
;
160 NtClose (ConnectedPort
);
161 NtTerminateThread (NtCurrentThread(), Status
);
164 /**********************************************************************
166 * SmpHandleConnectionRequest/1
169 * Request: LPC connection request message
172 * Quoted in http://support.microsoft.com/kb/258060/EN-US/
175 SmpHandleConnectionRequest (PSM_PORT_MESSAGE Request
)
177 PSM_CONNECT_DATA ConnectData
= SmpGetConnectData (Request
);
178 NTSTATUS Status
= STATUS_SUCCESS
;
180 PSM_CLIENT_DATA ClientData
= NULL
;
181 HANDLE hClientDataApiPort
= (HANDLE
) 0;
182 PHANDLE ClientDataApiPort
= & hClientDataApiPort
;
183 HANDLE hClientDataApiPortThread
= (HANDLE
) 0;
184 PHANDLE ClientDataApiPortThread
= & hClientDataApiPortThread
;
185 PVOID Context
= NULL
;
187 DPRINT("SM: %s called:\n SubSystemID=%d\n SbName=\"%S\"\n",
188 __FUNCTION__
, ConnectData
->SubSystemId
, ConnectData
->SbName
);
190 if(sizeof (SM_CONNECT_DATA
) == Request
->Header
.DataSize
)
192 if(IMAGE_SUBSYSTEM_UNKNOWN
== ConnectData
->SubSystemId
)
195 * This is not a call to register an image set,
196 * but a simple connection request from a process
197 * that will use the SM API.
199 DPRINT("SM: %s: simple request\n", __FUNCTION__
);
200 ClientDataApiPort
= & hClientDataApiPort
;
201 ClientDataApiPortThread
= & hClientDataApiPortThread
;
204 DPRINT("SM: %s: request to register an image set\n", __FUNCTION__
);
206 * Reject GUIs classes: only odd subsystem IDs are
207 * allowed to register here (tty mode images).
209 if(1 == (ConnectData
->SubSystemId
% 2))
211 DPRINT("SM: %s: id = %d\n", __FUNCTION__
, ConnectData
->SubSystemId
);
213 * SmCreateClient/2 is called here explicitly to *fail*.
214 * If it succeeds, there is something wrong in the
215 * connection request. An environment subsystem *never*
216 * registers twice. (security issue)
218 Status
= SmCreateClient (Request
, & ClientData
);
219 if(STATUS_SUCCESS
== Status
)
221 DPRINT("SM: %s: ClientData = 0x%08lx\n",
222 __FUNCTION__
, ClientData
);
224 * OK: the client is an environment subsystem
225 * willing to manage a free image type.
227 ClientDataApiPort
= & ClientData
->ApiPort
;
228 ClientDataApiPortThread
= & ClientData
->ApiPortThread
;
230 * Call back the candidate environment subsystem
231 * server (use the port name sent in in the
232 * connection request message).
234 Status
= SmpCallbackServer (Request
, ClientData
);
235 if(NT_SUCCESS(Status
))
237 DPRINT("SM: %s: SmpCallbackServer OK\n",
241 DPRINT("SM: %s: SmpCallbackServer failed (Status=%08lx)\n",
242 __FUNCTION__
, Status
);
243 Status
= SmDestroyClient (ConnectData
->SubSystemId
);
249 DPRINT("SM: %s: before NtAcceptConnectPort\n", __FUNCTION__
);
250 #if defined(__USE_NT_LPC__)
251 Status
= NtAcceptConnectPort (ClientDataApiPort
,
253 (PLPC_MESSAGE
) Request
,
257 #else /* ReactOS LPC */
258 Status
= NtAcceptConnectPort (ClientDataApiPort
,
259 SmApiPort
, // ROS LPC requires the listen port here
267 if(!NT_SUCCESS(Status
))
269 DPRINT1("SM: %s: NtAcceptConnectPort() failed (Status=0x%08lx)\n",
270 __FUNCTION__
, Status
);
273 DPRINT("SM: %s: completing conn req\n", __FUNCTION__
);
274 Status
= NtCompleteConnectPort (*ClientDataApiPort
);
275 if (!NT_SUCCESS(Status
))
277 DPRINT1("SM: %s: NtCompleteConnectPort() failed (Status=0x%08lx)\n",
278 __FUNCTION__
, Status
);
281 #if !defined(__USE_NT_LPC__) /* ReactOS LPC */
282 DPRINT("SM: %s: server side comm port thread (ROS LPC)\n", __FUNCTION__
);
283 Status
= RtlCreateUserThread(NtCurrentProcess(),
289 (PTHREAD_START_ROUTINE
) SmpApiConnectedThread
,
291 ClientDataApiPortThread
,
293 if (!NT_SUCCESS(Status
))
295 DPRINT1("SM: %s: Unable to create server thread (Status=0x%08lx)\n",
296 __FUNCTION__
, Status
);
301 Status
= STATUS_SUCCESS
;
303 DPRINT("SM: %s done\n", __FUNCTION__
);
307 /**********************************************************************
312 * Due to differences in LPC implementation between NT and ROS,
313 * we need a thread to listen for connection request that
314 * creates a new thread for each connected port. This is not
315 * necessary in NT LPC, because server side connected ports are
316 * never used to receive requests.
319 SmpApiThread (HANDLE ListeningPort
)
321 NTSTATUS Status
= STATUS_SUCCESS
;
322 LPC_MAX_MESSAGE Request
= {{0}};
324 DPRINT("SM: %s called\n", __FUNCTION__
);
328 Status
= NtListenPort (ListeningPort
, & Request
.Header
);
329 if (!NT_SUCCESS(Status
))
331 DPRINT1("SM: %s: NtListenPort() failed! (Status==x%08lx)\n", __FUNCTION__
, Status
);
334 Status
= SmpHandleConnectionRequest ((PSM_PORT_MESSAGE
) & Request
);
335 if(!NT_SUCCESS(Status
))
337 DPRINT1("SM: %s: SmpHandleConnectionRequest failed (Status=0x%08lx)\n",
338 __FUNCTION__
, Status
);
343 NtClose(ListeningPort
);
345 NtTerminateThread(NtCurrentThread(), Status
);
349 /* LPC PORT INITIALIZATION **************************************************/
352 /**********************************************************************
359 SmCreateApiPort(VOID
)
361 OBJECT_ATTRIBUTES ObjectAttributes
= {0};
362 UNICODE_STRING UnicodeString
= {0};
363 NTSTATUS Status
= STATUS_SUCCESS
;
365 RtlRosInitUnicodeStringFromLiteral(&UnicodeString
,
367 InitializeObjectAttributes(&ObjectAttributes
,
373 Status
= NtCreatePort(&SmApiPort
,
378 if (!NT_SUCCESS(Status
))
383 * Create one thread for the named LPC
386 RtlCreateUserThread(NtCurrentProcess(),
392 (PTHREAD_START_ROUTINE
)SmpApiThread
,