3 * smapi.c - \SmApiPort LPC port message management
5 * Reactos Session Manager
13 /* GLOBAL VARIABLES *********************************************************/
15 static HANDLE SmApiPort
= INVALID_HANDLE_VALUE
;
17 /* SM API *******************************************************************/
21 DPRINT("SM: %s called\n",__FUNCTION__
);
22 Request
->SmHeader
.Status
= STATUS_NOT_IMPLEMENTED
;
23 return STATUS_SUCCESS
;
27 typedef NTSTATUS (FASTCALL
* SM_PORT_API
)(PSM_PORT_MESSAGE
);
29 SM_PORT_API SmApi
[] =
31 SmInvalid
, /* unused */
32 SmCompSes
, /* smapicomp.c */
33 SmInvalid
, /* obsolete */
34 SmInvalid
, /* unknown */
35 SmExecPgm
, /* smapiexec.c */
36 SmQryInfo
/* smapyqry.c */
39 /* TODO: optimize this address computation (it should be done
41 PSM_CONNECT_DATA FASTCALL
SmpGetConnectData (PSM_PORT_MESSAGE Request
)
43 PLPC_MAX_MESSAGE LpcMaxMessage
= (PLPC_MAX_MESSAGE
) Request
;
44 return (PSM_CONNECT_DATA
) & LpcMaxMessage
->Data
[0];
47 #if !defined(__USE_NT_LPC__)
49 SmpHandleConnectionRequest (PSM_PORT_MESSAGE Request
);
52 /**********************************************************************
56 * The SM calls back a previously connected subsystem process to
57 * authorize it to bootstrap (initialize). The SM connects to a
58 * named LPC port which name was sent in the connection data by
59 * the candidate subsystem server process.
62 SmpCallbackServer (PSM_PORT_MESSAGE Request
,
63 PSM_CLIENT_DATA ClientData
)
65 NTSTATUS Status
= STATUS_SUCCESS
;
66 PSM_CONNECT_DATA ConnectData
= SmpGetConnectData (Request
);
67 UNICODE_STRING CallbackPortName
;
68 ULONG CallbackPortNameLength
= SM_SB_NAME_MAX_LENGTH
; /* TODO: compute length */
69 SB_CONNECT_DATA SbConnectData
;
70 ULONG SbConnectDataLength
= sizeof SbConnectData
;
72 DPRINT("SM: %s called\n", __FUNCTION__
);
74 if ( (IMAGE_SUBSYSTEM_UNKNOWN
== ConnectData
->SubSystemId
) ||
75 (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 * SmBeginClientInitialization/2 will succeed only if there
214 * is a candidate client ready.
216 Status
= SmBeginClientInitialization (Request
, & ClientData
);
217 if(STATUS_SUCCESS
== Status
)
219 DPRINT("SM: %s: ClientData = 0x%08lx\n",
220 __FUNCTION__
, ClientData
);
222 * OK: the client is an environment subsystem
223 * willing to manage a free image type.
225 ClientDataApiPort
= & ClientData
->ApiPort
;
226 ClientDataApiPortThread
= & ClientData
->ApiPortThread
;
228 * Call back the candidate environment subsystem
229 * server (use the port name sent in in the
230 * connection request message).
232 Status
= SmpCallbackServer (Request
, ClientData
);
233 if(NT_SUCCESS(Status
))
235 DPRINT("SM: %s: SmpCallbackServer OK\n",
239 DPRINT("SM: %s: SmpCallbackServer failed (Status=%08lx)\n",
240 __FUNCTION__
, Status
);
241 Status
= SmDestroyClient (ConnectData
->SubSystemId
);
247 DPRINT("SM: %s: before NtAcceptConnectPort\n", __FUNCTION__
);
248 #if defined(__USE_NT_LPC__)
249 Status
= NtAcceptConnectPort (ClientDataApiPort
,
251 (PLPC_MESSAGE
) Request
,
255 #else /* ReactOS LPC */
256 Status
= NtAcceptConnectPort (ClientDataApiPort
,
257 SmApiPort
, // ROS LPC requires the listen port here
265 if(!NT_SUCCESS(Status
))
267 DPRINT1("SM: %s: NtAcceptConnectPort() failed (Status=0x%08lx)\n",
268 __FUNCTION__
, Status
);
271 DPRINT("SM: %s: completing conn req\n", __FUNCTION__
);
272 Status
= NtCompleteConnectPort (*ClientDataApiPort
);
273 if (!NT_SUCCESS(Status
))
275 DPRINT1("SM: %s: NtCompleteConnectPort() failed (Status=0x%08lx)\n",
276 __FUNCTION__
, Status
);
279 #if !defined(__USE_NT_LPC__) /* ReactOS LPC */
280 DPRINT("SM: %s: server side comm port thread (ROS LPC)\n", __FUNCTION__
);
281 Status
= RtlCreateUserThread(NtCurrentProcess(),
287 (PTHREAD_START_ROUTINE
) SmpApiConnectedThread
,
289 ClientDataApiPortThread
,
291 if (!NT_SUCCESS(Status
))
293 DPRINT1("SM: %s: Unable to create server thread (Status=0x%08lx)\n",
294 __FUNCTION__
, Status
);
299 Status
= STATUS_SUCCESS
;
301 DPRINT("SM: %s done\n", __FUNCTION__
);
305 /**********************************************************************
310 * Due to differences in LPC implementation between NT and ROS,
311 * we need a thread to listen to for connection request that
312 * creates a new thread for each connected port. This is not
313 * necessary in NT LPC, because server side connected ports are
314 * never used to receive requests.
317 SmpApiThread (HANDLE ListeningPort
)
319 NTSTATUS Status
= STATUS_SUCCESS
;
320 LPC_MAX_MESSAGE Request
= {{0}};
322 DPRINT("SM: %s called\n", __FUNCTION__
);
326 Status
= NtListenPort (ListeningPort
, & Request
.Header
);
327 if (!NT_SUCCESS(Status
))
329 DPRINT1("SM: %s: NtListenPort() failed! (Status==x%08lx)\n", __FUNCTION__
, Status
);
332 Status
= SmpHandleConnectionRequest ((PSM_PORT_MESSAGE
) & Request
);
333 if(!NT_SUCCESS(Status
))
335 DPRINT1("SM: %s: SmpHandleConnectionRequest failed (Status=0x%08lx)\n",
336 __FUNCTION__
, Status
);
341 NtClose(ListeningPort
);
343 NtTerminateThread(NtCurrentThread(), Status
);
347 /* LPC PORT INITIALIZATION **************************************************/
350 /**********************************************************************
357 SmCreateApiPort(VOID
)
359 OBJECT_ATTRIBUTES ObjectAttributes
= {0};
360 UNICODE_STRING UnicodeString
= RTL_CONSTANT_STRING(L
"\\SmApiPort");
361 NTSTATUS Status
= STATUS_SUCCESS
;
363 InitializeObjectAttributes(&ObjectAttributes
,
369 Status
= NtCreatePort(&SmApiPort
,
374 if (!NT_SUCCESS(Status
))
379 * Create one thread for the named LPC
382 RtlCreateUserThread(NtCurrentProcess(),
388 (PTHREAD_START_ROUTINE
)SmpApiThread
,