ReactOS  0.4.15-dev-3451-gf606fec
smloop.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Windows-Compatible Session Manager
3  * LICENSE: BSD 2-Clause License
4  * FILE: base/system/smss/smloop.c
5  * PURPOSE: Main SMSS Code
6  * PROGRAMMERS: Alex Ionescu
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include "smss.h"
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 /* GLOBALS ********************************************************************/
17 
18 typedef struct _SMP_CLIENT_CONTEXT
19 {
25 
26 typedef
29  IN PSM_API_MSG SmApiMsg,
32 );
33 
36 
37 /* API HANDLERS ***************************************************************/
38 
40 NTAPI
44 {
45  DPRINT1("%s is not yet implemented\n", __FUNCTION__);
47 }
48 
50 NTAPI
54 {
55  DPRINT1("%s is not yet implemented\n", __FUNCTION__);
57 }
58 
60 NTAPI
64 {
65  DPRINT1("%s is not yet implemented\n", __FUNCTION__);
67 }
68 
70 NTAPI
74 {
78  RTL_USER_PROCESS_INFORMATION ProcessInformation;
80 
81  /* Open the client process */
86  &SmApiMsg->h.ClientId);
87  if (!NT_SUCCESS(Status))
88  {
89  /* Fail */
90  DPRINT1("SmExecPgm: NtOpenProcess Failed %lx\n", Status);
91  return Status;
92  }
93 
94  /* Copy the process information out of the message */
95  SmExecPgm = &SmApiMsg->u.ExecPgm;
96  ProcessInformation = SmExecPgm->ProcessInformation;
97 
98  /* Duplicate the process handle */
100  SmExecPgm->ProcessInformation.ProcessHandle,
102  &ProcessInformation.ProcessHandle,
104  0,
105  0);
106  if (!NT_SUCCESS(Status))
107  {
108  /* Close the handle and fail */
110  DPRINT1("SmExecPgm: NtDuplicateObject (Process) Failed %lx\n", Status);
111  return Status;
112  }
113 
114  /* Duplicate the thread handle */
116  SmExecPgm->ProcessInformation.ThreadHandle,
118  &ProcessInformation.ThreadHandle,
120  0,
121  0);
122  if (!NT_SUCCESS(Status))
123  {
124  /* Close both handles and fail */
125  NtClose(ProcessInformation.ProcessHandle);
127  DPRINT1("SmExecPgm: NtDuplicateObject (Thread) Failed %lx\n", Status);
128  return Status;
129  }
130 
131  /* Close the process handle and call the internal client API */
133  return SmpSbCreateSession(NULL,
134  NULL,
135  &ProcessInformation,
136  0,
137  SmExecPgm->DebugFlag ? &SmApiMsg->h.ClientId : NULL);
138 }
139 
140 NTSTATUS
141 NTAPI
145 {
146  DPRINT1("%s is not yet implemented\n", __FUNCTION__);
147  return STATUS_NOT_IMPLEMENTED;
148 }
149 
150 NTSTATUS
151 NTAPI
155 {
156  PSM_START_CSR_MSG SmStartCsr = &SmApiMsg->u.StartCsr;
157  UNICODE_STRING InitialCommand;
158  HANDLE InitialCommandProcess, InitialCommandProcessId, WindowsSubSysProcessId;
160 
162  &WindowsSubSysProcessId,
163  &InitialCommand);
164  if (!NT_SUCCESS(Status))
165  {
166  DPRINT1("SMSS: SmpLoadSubSystemsForMuSession failed with status 0x%08x\n", Status);
167  return Status;
168  }
169 
170  if (SmStartCsr->Length)
171  {
172  InitialCommand.Length = InitialCommand.MaximumLength = SmStartCsr->Length;
173  InitialCommand.Buffer = SmStartCsr->Buffer;
174  }
175 
177  &InitialCommand,
178  &InitialCommandProcess,
179  &InitialCommandProcessId);
180  if (!NT_SUCCESS(Status))
181  {
182  DPRINT1("SMSS: SmpExecuteInitialCommand failed with status 0x%08x\n", Status);
183  /* FIXME: undo effects of SmpLoadSubSystemsForMuSession */
184  ASSERT(FALSE);
185  return Status;
186  }
187 
188  NtClose(InitialCommandProcess);
189 
190  SmStartCsr->WindowsSubSysProcessId = WindowsSubSysProcessId;
191  SmStartCsr->SmpInitialCommandProcessId = InitialCommandProcessId;
192 
193  return STATUS_SUCCESS;
194 }
195 
196 NTSTATUS
197 NTAPI
201 {
202  DPRINT1("%s is not yet implemented\n", __FUNCTION__);
203  return STATUS_NOT_IMPLEMENTED;
204 }
205 
207 {
211  SmpExecPgm,
213  SmpStartCsr,
214  SmpStopCsr
215 };
216 
217 /* FUNCTIONS ******************************************************************/
218 
219 NTSTATUS
220 NTAPI
222  IN PSB_API_MSG SbApiMsg)
223 {
224  BOOLEAN Accept = TRUE;
225  HANDLE PortHandle, ProcessHandle;
227  UNICODE_STRING SubsystemPort;
231  REMOTE_PORT_VIEW PortView;
232  SECURITY_QUALITY_OF_SERVICE SecurityQos;
233  PSMP_SUBSYSTEM CidSubsystem, TypeSubsystem;
234 
235  /* Initialize QoS data */
238  SecurityQos.EffectiveOnly = TRUE;
239 
240  /* Check if this is SM connecting to itself */
241  if (SbApiMsg->h.ClientId.UniqueProcess == SmUniqueProcessId)
242  {
243  /* No need to get any handle -- assume session 0 */
245  SessionId = 0;
246  }
247  else
248  {
249  /* Reference the foreign process */
254  &SbApiMsg->h.ClientId);
255  if (!NT_SUCCESS(Status)) Accept = FALSE;
256 
257  /* Get its session ID */
259  }
260 
261  /* See if we already know about the caller's subsystem */
262  CidSubsystem = SmpLocateKnownSubSysByCid(&SbApiMsg->h.ClientId);
263  if ((CidSubsystem) && (Accept))
264  {
265  /* Check if we already have a subsystem for this kind of image */
266  TypeSubsystem = SmpLocateKnownSubSysByType(SessionId,
267  SbApiMsg->ConnectionInfo.SubsystemType);
268  if (TypeSubsystem == CidSubsystem)
269  {
270  /* Someone is trying to take control of an existing subsystem, fail */
271  Accept = FALSE;
272  DPRINT1("SMSS: Connection from SubSystem rejected\n");
273  DPRINT1("SMSS: Image type already being served\n");
274  }
275  else
276  {
277  /* Set this image type as the type for this subsystem */
278  CidSubsystem->ImageType = SbApiMsg->ConnectionInfo.SubsystemType;
279  }
280 
281  /* Drop the reference we had acquired */
282  if (TypeSubsystem) SmpDereferenceSubsystem(TypeSubsystem);
283  }
284 
285  /* Check if we'll be accepting the connection */
286  if (Accept)
287  {
288  /* We will, so create a client context for it */
290  if (ClientContext)
291  {
292  ClientContext->ProcessHandle = ProcessHandle;
293  ClientContext->Subsystem = CidSubsystem;
294  ClientContext->dword10 = 0;
296  }
297  else
298  {
299  /* Failed to allocate a client context, so reject the connection */
300  DPRINT1("Rejecting connectiond due to lack of memory\n");
301  Accept = FALSE;
302  }
303  }
304  else
305  {
306  /* Use a bogus context since we're going to reject the message */
308  }
309 
310  /* Now send the actual accept reply (which could be a rejection) */
311  PortView.Length = sizeof(PortView);
312  Status = NtAcceptConnectPort(&PortHandle,
314  &SbApiMsg->h,
315  Accept,
316  NULL,
317  &PortView);
318  if (!(Accept) || !(NT_SUCCESS(Status)))
319  {
320  /* Close the process handle, reference the subsystem, and exit */
321  DPRINT1("Accept failed or rejected: %lx\n", Status);
322  if (ClientContext != (PVOID)SbApiMsg) RtlFreeHeap(SmpHeap, 0, ClientContext);
324  if (CidSubsystem) SmpDereferenceSubsystem(CidSubsystem);
325  return Status;
326  }
327 
328  /* Save the port handle now that we've accepted it */
329  if (ClientContext) ClientContext->PortHandle = PortHandle;
330  if (CidSubsystem) CidSubsystem->PortHandle = PortHandle;
331 
332  /* Complete the port connection */
333  Status = NtCompleteConnectPort(PortHandle);
334  if ((NT_SUCCESS(Status)) && (CidSubsystem))
335  {
336  /* This was an actual subsystem, so connect back to it */
337  SbApiMsg->ConnectionInfo.SbApiPortName[119] = UNICODE_NULL;
338  RtlCreateUnicodeString(&SubsystemPort,
339  SbApiMsg->ConnectionInfo.SbApiPortName);
340  Status = NtConnectPort(&CidSubsystem->SbApiPort,
341  &SubsystemPort,
342  &SecurityQos,
343  NULL,
344  NULL,
345  NULL,
346  NULL,
347  NULL);
348  if (!NT_SUCCESS(Status))
349  {
350  DPRINT1("SMSS: Connect back to Sb %wZ failed %lx\n", &SubsystemPort, Status);
351  }
352  RtlFreeUnicodeString(&SubsystemPort);
353 
354  /* Now that we're connected, signal the event handle */
355  NtSetEvent(CidSubsystem->Event, NULL);
356  }
357  else if (CidSubsystem)
358  {
359  /* We failed to complete the connection, so clear the port handle */
360  DPRINT1("Completing the connection failed: %lx\n", Status);
361  CidSubsystem->PortHandle = NULL;
362  }
363 
364  /* Dereference the subsystem and return the result */
365  if (CidSubsystem) SmpDereferenceSubsystem(CidSubsystem);
366  return Status;
367 }
368 
369 ULONG
370 NTAPI
372 {
376  PSM_API_MSG ReplyMsg = NULL;
377  SM_API_MSG RequestMsg;
378  PROCESS_BASIC_INFORMATION ProcessInformation;
380 
381  /* Increase the number of API threads for throttling code for later */
383 
384  /* Mark us critical */
386 
387  /* Set the PID of the SM process itself for later checking */
390  &ProcessInformation,
391  sizeof(ProcessInformation),
392  NULL);
393  SmUniqueProcessId = (HANDLE)ProcessInformation.UniqueProcessId;
394 
395  /* Now process incoming messages */
396  while (TRUE)
397  {
398  /* Begin waiting on a request */
400  (PVOID*)&ClientContext,
401  &ReplyMsg->h,
402  &RequestMsg.h);
403  if (Status == STATUS_NO_MEMORY)
404  {
405  /* Ran out of memory, so do a little timeout and try again */
406  if (ReplyMsg) DPRINT1("SMSS: Failed to reply to calling thread, retrying.\n");
407  Timeout.QuadPart = -50000000;
409  continue;
410  }
411 
412  /* Check what kind of request we received */
413  switch (RequestMsg.h.u2.s2.Type)
414  {
415  /* A new connection */
417  /* Create the right structures for it */
419  ReplyMsg = NULL;
420  break;
421 
422  /* A closed connection */
423  case LPC_PORT_CLOSED:
424  /* Destroy any state we had for this client */
425  DPRINT1("Port closed\n");
426  //if (ClientContext) SmpPushDeferredClientContext(ClientContext);
427  ReplyMsg = NULL;
428  break;
429 
430  /* An actual API message */
431  default:
432  if (!ClientContext)
433  {
434  ReplyMsg = NULL;
435  break;
436  }
437 
438  RequestMsg.ReturnValue = STATUS_PENDING;
439 
440  /* Check if the API is valid */
441  if (RequestMsg.ApiNumber >= SmpMaxApiNumber)
442  {
443  /* It isn't, fail */
444  DPRINT1("Invalid API: %lx\n", RequestMsg.ApiNumber);
446  }
447  else if ((RequestMsg.ApiNumber <= SmpTerminateForeignSessionApi) &&
448  !(ClientContext->Subsystem))
449  {
450  /* It's valid, but doesn't have a subsystem with it */
451  DPRINT1("Invalid session API\n");
453  }
454  else
455  {
456  /* It's totally okay, so call the dispatcher for it */
457  Status = SmpApiDispatch[RequestMsg.ApiNumber](&RequestMsg,
459  SmApiPort);
460  }
461 
462  /* Write the result value and return the message back */
463  RequestMsg.ReturnValue = Status;
464  ReplyMsg = &RequestMsg;
465  break;
466  }
467  }
468  return STATUS_SUCCESS;
469 }
PORT_MESSAGE h
Definition: smmsg.h:92
NTSTATUS NTAPI SmpHandleConnectionRequest(IN HANDLE SmApiPort, IN PSB_API_MSG SbApiMsg)
Definition: smloop.c:221
NTSTATUS NTAPI SmStartCsr(IN HANDLE SmApiPort, OUT PULONG pMuSessionId, IN PUNICODE_STRING CommandLine, OUT PHANDLE pWindowsSubSysProcessId, OUT PHANDLE pInitialCommandProcessId)
Definition: smclient.c:173
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
NTSTATUS NTAPI SmpStopCsr(IN PSM_API_MSG SmApiMsg, IN PSMP_CLIENT_CONTEXT ClientContext, IN HANDLE SmApiPort)
Definition: smloop.c:198
#define IN
Definition: typedefs.h:39
#define THREAD_ALL_ACCESS
Definition: nt_native.h:1339
HANDLE PortHandle
Definition: smss.h:66
#define PROCESS_ALL_ACCESS
Definition: nt_native.h:1324
#define PROCESS_QUERY_INFORMATION
Definition: pstypes.h:166
HANDLE SmApiPort
Definition: smss.c:23
USHORT MaximumLength
Definition: env_spec_w32.h:370
NTSTATUS(NTAPI * PSM_API_HANDLER)(IN PSM_API_MSG SmApiMsg, IN PSMP_CLIENT_CONTEXT ClientContext, IN HANDLE SmApiPort)
Definition: smloop.c:28
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
ULONG SessionId
Definition: dllmain.c:28
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS NTAPI SmpStartCsr(IN PSM_API_MSG SmApiMsg, IN PSMP_CLIENT_CONTEXT ClientContext, IN HANDLE SmApiPort)
Definition: smloop.c:152
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
NTSTATUS NTAPI SmpLoadDeferedSubsystem(IN PSM_API_MSG SmApiMsg, IN PSMP_CLIENT_CONTEXT ClientContext, IN HANDLE SmApiPort)
Definition: smloop.c:142
ULONG NTAPI SmpApiLoop(IN PVOID Parameter)
Definition: smloop.c:371
NTSTATUS NTAPI SmpExecuteInitialCommand(IN ULONG MuSessionId, IN PUNICODE_STRING InitialCommand, IN HANDLE InitialCommandProcess, OUT PHANDLE ReturnPid)
Definition: smss.c:294
_In_ PVOID Parameter
Definition: ldrtypes.h:241
ULONG ImageType
Definition: smss.h:65
NTSTATUS NTAPI NtOpenProcess(OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId)
Definition: process.c:1440
struct _SMP_CLIENT_CONTEXT SMP_CLIENT_CONTEXT
NTSTATUS NTAPI SmpGetProcessMuSessionId(IN HANDLE ProcessHandle, OUT PULONG SessionId)
Definition: smsessn.c:168
SECURITY_CONTEXT_TRACKING_MODE ContextTrackingMode
Definition: lsa.idl:66
PSMP_SUBSYSTEM NTAPI SmpLocateKnownSubSysByCid(IN PCLIENT_ID ClientId)
Definition: smsubsys.c:68
return STATUS_NOT_IMPLEMENTED
HANDLE SmUniqueProcessId
Definition: smloop.c:35
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
HANDLE ProcessHandle
Definition: smloop.c:21
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
PVOID SmpHeap
Definition: sminit.c:24
long LONG
Definition: pedump.c:60
#define PROCESS_DUP_HANDLE
unsigned char BOOLEAN
SB_API_NUMBER ApiNumber
Definition: smmsg.h:208
NTSYSAPI NTSTATUS __cdecl RtlSetThreadIsCritical(_In_ BOOLEAN NewValue, _Out_opt_ PBOOLEAN OldValue, _In_ BOOLEAN NeedBreaks)
volatile LONG SmTotalApiThreads
Definition: smloop.c:34
HANDLE Event
Definition: smss.h:63
PSM_API_HANDLER SmpApiDispatch[SmpMaxApiNumber - SmpCreateForeignSessionApi]
Definition: smloop.c:206
NTSTATUS NTAPI NtDelayExecution(IN BOOLEAN Alertable, IN PLARGE_INTEGER DelayInterval)
Definition: wait.c:876
#define NtCurrentProcess()
Definition: nt_native.h:1657
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
NTSTATUS ReturnValue
Definition: smmsg.h:209
Status
Definition: gdiplustypes.h:24
NTSTATUS NTAPI NtAcceptConnectPort(OUT PHANDLE PortHandle, IN PVOID PortContext OPTIONAL, IN PPORT_MESSAGE ReplyMessage, IN BOOLEAN AcceptConnection, IN OUT PPORT_VIEW ServerView OPTIONAL, OUT PREMOTE_PORT_VIEW ClientView OPTIONAL)
Definition: complete.c:40
NTSTATUS NTAPI NtConnectPort(OUT PHANDLE PortHandle, IN PUNICODE_STRING PortName, IN PSECURITY_QUALITY_OF_SERVICE SecurityQos, IN OUT PPORT_VIEW ClientView OPTIONAL, IN OUT PREMOTE_PORT_VIEW ServerView OPTIONAL, OUT PULONG MaxMessageLength OPTIONAL, IN OUT PVOID ConnectionInformation OPTIONAL, IN OUT PULONG ConnectionInformationLength OPTIONAL)
Definition: connect.c:753
NTSTATUS NTAPI NtSetEvent(IN HANDLE EventHandle, OUT PLONG PreviousState OPTIONAL)
Definition: event.c:455
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
_In_ PVOID ClientContext
Definition: netioddk.h:55
PSMP_SUBSYSTEM NTAPI SmpLocateKnownSubSysByType(IN ULONG MuSessionId, IN ULONG ImageType)
Definition: smsubsys.c:102
PVOID HANDLE
Definition: typedefs.h:73
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
HANDLE SbApiPort
Definition: smss.h:67
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3398
NTSTATUS NTAPI SmpSbCreateSession(IN PVOID Reserved, IN PSMP_SUBSYSTEM OtherSubsystem, IN PRTL_USER_PROCESS_INFORMATION ProcessInformation, IN ULONG MuSessionId, IN PCLIENT_ID DbgClientId)
Definition: smsbapi.c:31
NTSTATUS NTAPI SmExecPgm(IN HANDLE SmApiPort, IN PRTL_USER_PROCESS_INFORMATION ProcessInformation, IN BOOLEAN DebugFlag)
Definition: smclient.c:21
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define SECURITY_DYNAMIC_TRACKING
Definition: setypes.h:103
NTSTATUS NTAPI NtReplyWaitReceivePort(IN HANDLE PortHandle, OUT PVOID *PortContext OPTIONAL, IN PPORT_MESSAGE ReplyMessage OPTIONAL, OUT PPORT_MESSAGE ReceiveMessage)
Definition: reply.c:743
#define NTSTATUS
Definition: precomp.h:20
NTSTATUS NTAPI SmpLoadSubSystemsForMuSession(IN PULONG MuSessionId, OUT PHANDLE ProcessId, IN PUNICODE_STRING InitialCommand)
Definition: smsubsys.c:513
HANDLE PortHandle
Definition: smloop.c:22
VOID NTAPI SmpDereferenceSubsystem(IN PSMP_SUBSYSTEM SubSystem)
Definition: smsubsys.c:47
static ULONG Timeout
Definition: ping.c:61
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
NTSTATUS NTAPI SmpTerminateForeignSession(IN PSM_API_MSG SmApiMsg, IN PSMP_CLIENT_CONTEXT ClientContext, IN HANDLE SmApiPort)
Definition: smloop.c:61
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
Definition: lsa.idl:65
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
struct _SMP_CLIENT_CONTEXT * PSMP_CLIENT_CONTEXT
NTSTATUS NTAPI NtDuplicateObject(IN HANDLE SourceProcessHandle, IN HANDLE SourceHandle, IN HANDLE TargetProcessHandle OPTIONAL, OUT PHANDLE TargetHandle OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG HandleAttributes, IN ULONG Options)
Definition: obhandle.c:3406
NTSTATUS NTAPI NtCompleteConnectPort(IN HANDLE PortHandle)
Definition: complete.c:421
unsigned int ULONG
Definition: retypes.h:1
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define STATUS_SUCCESS
Definition: shellext.h:65
NTSTATUS NTAPI SmpExecPgm(IN PSM_API_MSG SmApiMsg, IN PSMP_CLIENT_CONTEXT ClientContext, IN HANDLE SmApiPort)
Definition: smloop.c:71
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:403
#define __FUNCTION__
Definition: types.h:112
long __cdecl _InterlockedExchangeAdd(_Interlocked_operand_ long volatile *_Addend, long _Value)
NTSTATUS NTAPI SmpCreateForeignSession(IN PSM_API_MSG SmApiMsg, IN PSMP_CLIENT_CONTEXT ClientContext, IN HANDLE SmApiPort)
Definition: smloop.c:41
NTSTATUS NTAPI NtQueryInformationProcess(_In_ HANDLE ProcessHandle, _In_ PROCESSINFOCLASS ProcessInformationClass, _Out_ PVOID ProcessInformation, _In_ ULONG ProcessInformationLength, _Out_opt_ PULONG ReturnLength)
Definition: query.c:59
NTSTATUS NTAPI SmpSessionComplete(IN PSM_API_MSG SmApiMsg, IN PSMP_CLIENT_CONTEXT ClientContext, IN HANDLE SmApiPort)
Definition: smloop.c:51