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 PPORT_MESSAGE PortMessage
= (PPORT_MESSAGE
) Request
;
44 return (PSM_CONNECT_DATA
)(PortMessage
+ 1);
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 ( ((USHORT
)-1 == 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 PPORT_MESSAGE Reply
= NULL
;
112 SM_PORT_MESSAGE Request
;
113 HANDLE ConnectedPort
= * (PHANDLE
) pConnectedPort
;
115 DPRINT("SM: %s called\n", __FUNCTION__
);
116 RtlZeroMemory(&Request
, sizeof(SM_PORT_MESSAGE
));
120 DPRINT("SM: %s: waiting for message\n",__FUNCTION__
);
122 Status
= NtReplyWaitReceivePort(ConnectedPort
,
125 (PPORT_MESSAGE
) & Request
);
126 if (NT_SUCCESS(Status
))
128 DPRINT("SM: %s: message received (type=%d)\n",
130 Request
.Header
.u2
.s2
.Type
);
132 switch (Request
.Header
.u2
.s2
.Type
)
134 case LPC_CONNECTION_REQUEST
:
135 SmpHandleConnectionRequest (&Request
);
138 case LPC_DEBUG_EVENT
:
139 // DbgSsHandleKmApiMsg (&Request, 0);
142 case LPC_PORT_CLOSED
:
146 if ((Request
.SmHeader
.ApiIndex
) &&
147 (Request
.SmHeader
.ApiIndex
< (sizeof SmApi
/ sizeof SmApi
[0])))
149 Status
= SmApi
[Request
.SmHeader
.ApiIndex
](&Request
);
150 Reply
= (PPORT_MESSAGE
) & Request
;
152 Request
.SmHeader
.Status
= STATUS_NOT_IMPLEMENTED
;
153 Reply
= (PPORT_MESSAGE
) & Request
;
161 NtClose (ConnectedPort
);
162 NtTerminateThread (NtCurrentThread(), Status
);
165 /**********************************************************************
167 * SmpHandleConnectionRequest/1
170 * Request: LPC connection request message
173 * Quoted in http://support.microsoft.com/kb/258060/EN-US/
176 SmpHandleConnectionRequest (PSM_PORT_MESSAGE Request
)
178 PSM_CONNECT_DATA ConnectData
= SmpGetConnectData (Request
);
179 NTSTATUS Status
= STATUS_SUCCESS
;
181 PSM_CLIENT_DATA ClientData
= NULL
;
182 HANDLE hClientDataApiPort
= (HANDLE
) 0;
183 PHANDLE ClientDataApiPort
= & hClientDataApiPort
;
184 HANDLE hClientDataApiPortThread
= (HANDLE
) 0;
185 PHANDLE ClientDataApiPortThread
= & hClientDataApiPortThread
;
186 PVOID Context
= NULL
;
188 DPRINT("SM: %s called:\n SubSystemID=%d\n SbName=\"%S\"\n",
189 __FUNCTION__
, ConnectData
->SubSystemId
, ConnectData
->SbName
);
191 if(sizeof (SM_CONNECT_DATA
) == Request
->Header
.u1
.s1
.DataLength
)
193 if(IMAGE_SUBSYSTEM_UNKNOWN
== ConnectData
->SubSystemId
)
196 * This is not a call to register an image set,
197 * but a simple connection request from a process
198 * that will use the SM API.
200 DPRINT("SM: %s: simple request\n", __FUNCTION__
);
201 ClientDataApiPort
= & hClientDataApiPort
;
202 ClientDataApiPortThread
= & hClientDataApiPortThread
;
205 DPRINT("SM: %s: request to register an image set\n", __FUNCTION__
);
207 * Reject GUIs classes: only odd subsystem IDs are
208 * allowed to register here (tty mode images).
210 if(1 == (ConnectData
->SubSystemId
% 2))
212 DPRINT("SM: %s: id = %d\n", __FUNCTION__
, ConnectData
->SubSystemId
);
214 * SmBeginClientInitialization/2 will succeed only if there
215 * is a candidate client ready.
217 Status
= SmBeginClientInitialization (Request
, & ClientData
);
218 if(STATUS_SUCCESS
== Status
)
220 DPRINT("SM: %s: ClientData = 0x%08lx\n",
221 __FUNCTION__
, ClientData
);
223 * OK: the client is an environment subsystem
224 * willing to manage a free image type.
226 ClientDataApiPort
= & ClientData
->ApiPort
;
227 ClientDataApiPortThread
= & ClientData
->ApiPortThread
;
229 * Call back the candidate environment subsystem
230 * server (use the port name sent in in the
231 * connection request message).
233 Status
= SmpCallbackServer (Request
, ClientData
);
234 if(NT_SUCCESS(Status
))
236 DPRINT("SM: %s: SmpCallbackServer OK\n",
240 DPRINT("SM: %s: SmpCallbackServer failed (Status=%08lx)\n",
241 __FUNCTION__
, Status
);
242 Status
= SmDestroyClient (ConnectData
->SubSystemId
);
248 DPRINT("SM: %s: before NtAcceptConnectPort\n", __FUNCTION__
);
249 #if defined(__USE_NT_LPC__)
250 Status
= NtAcceptConnectPort (ClientDataApiPort
,
252 (PPORT_MESSAGE
) Request
,
256 #else /* ReactOS LPC */
257 Status
= NtAcceptConnectPort (ClientDataApiPort
,
258 SmApiPort
, // ROS LPC requires the listen port here
266 if(!NT_SUCCESS(Status
))
268 DPRINT1("SM: %s: NtAcceptConnectPort() failed (Status=0x%08lx)\n",
269 __FUNCTION__
, Status
);
272 DPRINT("SM: %s: completing conn req\n", __FUNCTION__
);
273 Status
= NtCompleteConnectPort (*ClientDataApiPort
);
274 if (!NT_SUCCESS(Status
))
276 DPRINT1("SM: %s: NtCompleteConnectPort() failed (Status=0x%08lx)\n",
277 __FUNCTION__
, Status
);
280 #if !defined(__USE_NT_LPC__) /* ReactOS LPC */
281 DPRINT("SM: %s: server side comm port thread (ROS LPC)\n", __FUNCTION__
);
282 Status
= RtlCreateUserThread(NtCurrentProcess(),
288 (PTHREAD_START_ROUTINE
) SmpApiConnectedThread
,
290 ClientDataApiPortThread
,
292 if (!NT_SUCCESS(Status
))
294 DPRINT1("SM: %s: Unable to create server thread (Status=0x%08lx)\n",
295 __FUNCTION__
, Status
);
300 Status
= STATUS_SUCCESS
;
302 DPRINT("SM: %s done\n", __FUNCTION__
);
306 /**********************************************************************
311 * Due to differences in LPC implementation between NT and ROS,
312 * we need a thread to listen to for connection request that
313 * creates a new thread for each connected port. This is not
314 * necessary in NT LPC, because server side connected ports are
315 * never used to receive requests.
318 SmpApiThread (HANDLE ListeningPort
)
320 NTSTATUS Status
= STATUS_SUCCESS
;
321 SM_PORT_MESSAGE Request
;
323 DPRINT("SM: %s called\n", __FUNCTION__
);
324 RtlZeroMemory(&Request
, sizeof(PORT_MESSAGE
));
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 (& 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
= RTL_CONSTANT_STRING(L
"\\SmApiPort");
363 NTSTATUS Status
= STATUS_SUCCESS
;
365 InitializeObjectAttributes(&ObjectAttributes
,
371 Status
= NtCreatePort(&SmApiPort
,
376 if (!NT_SUCCESS(Status
))
381 * Create one thread for the named LPC
384 RtlCreateUserThread(NtCurrentProcess(),
390 (PTHREAD_START_ROUTINE
)SmpApiThread
,