ReactOS  0.4.13-dev-563-g0561610
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  DPRINT1("%s is not yet implemented\n", __FUNCTION__);
157  return STATUS_NOT_IMPLEMENTED;
158 }
159 
160 NTSTATUS
161 NTAPI
165 {
166  DPRINT1("%s is not yet implemented\n", __FUNCTION__);
167  return STATUS_NOT_IMPLEMENTED;
168 }
169 
171 {
175  SmpExecPgm,
177  SmpStartCsr,
178  SmpStopCsr
179 };
180 
181 /* FUNCTIONS ******************************************************************/
182 
183 NTSTATUS
184 NTAPI
186  IN PSB_API_MSG SbApiMsg)
187 {
188  BOOLEAN Accept = TRUE;
189  HANDLE PortHandle, ProcessHandle;
191  UNICODE_STRING SubsystemPort;
195  REMOTE_PORT_VIEW PortView;
196  SECURITY_QUALITY_OF_SERVICE SecurityQos;
197  PSMP_SUBSYSTEM CidSubsystem, TypeSubsystem;
198 
199  /* Initialize QoS data */
202  SecurityQos.EffectiveOnly = TRUE;
203 
204  /* Check if this is SM connecting to itself */
205  if (SbApiMsg->h.ClientId.UniqueProcess == SmUniqueProcessId)
206  {
207  /* No need to get any handle -- assume session 0 */
209  SessionId = 0;
210  }
211  else
212  {
213  /* Reference the foreign process */
218  &SbApiMsg->h.ClientId);
219  if (!NT_SUCCESS(Status)) Accept = FALSE;
220 
221  /* Get its session ID */
223  }
224 
225  /* See if we already know about the caller's subsystem */
226  CidSubsystem = SmpLocateKnownSubSysByCid(&SbApiMsg->h.ClientId);
227  if ((CidSubsystem) && (Accept))
228  {
229  /* Check if we already have a subsystem for this kind of image */
230  TypeSubsystem = SmpLocateKnownSubSysByType(SessionId,
231  SbApiMsg->ConnectionInfo.SubsystemType);
232  if (TypeSubsystem == CidSubsystem)
233  {
234  /* Someone is trying to take control of an existing subsystem, fail */
235  Accept = FALSE;
236  DPRINT1("SMSS: Connection from SubSystem rejected\n");
237  DPRINT1("SMSS: Image type already being served\n");
238  }
239  else
240  {
241  /* Set this image type as the type for this subsystem */
242  CidSubsystem->ImageType = SbApiMsg->ConnectionInfo.SubsystemType;
243  }
244 
245  /* Drop the reference we had acquired */
246  if (TypeSubsystem) SmpDereferenceSubsystem(TypeSubsystem);
247  }
248 
249  /* Check if we'll be accepting the connection */
250  if (Accept)
251  {
252  /* We will, so create a client context for it */
254  if (ClientContext)
255  {
256  ClientContext->ProcessHandle = ProcessHandle;
257  ClientContext->Subsystem = CidSubsystem;
258  ClientContext->dword10 = 0;
260  }
261  else
262  {
263  /* Failed to allocate a client context, so reject the connection */
264  DPRINT1("Rejecting connectiond due to lack of memory\n");
265  Accept = FALSE;
266  }
267  }
268  else
269  {
270  /* Use a bogus context since we're going to reject the message */
272  }
273 
274  /* Now send the actual accept reply (which could be a rejection) */
275  PortView.Length = sizeof(PortView);
276  Status = NtAcceptConnectPort(&PortHandle,
278  &SbApiMsg->h,
279  Accept,
280  NULL,
281  &PortView);
282  if (!(Accept) || !(NT_SUCCESS(Status)))
283  {
284  /* Close the process handle, reference the subsystem, and exit */
285  DPRINT1("Accept failed or rejected: %lx\n", Status);
286  if (ClientContext != (PVOID)SbApiMsg) RtlFreeHeap(SmpHeap, 0, ClientContext);
288  if (CidSubsystem) SmpDereferenceSubsystem(CidSubsystem);
289  return Status;
290  }
291 
292  /* Save the port handle now that we've accepted it */
293  if (ClientContext) ClientContext->PortHandle = PortHandle;
294  if (CidSubsystem) CidSubsystem->PortHandle = PortHandle;
295 
296  /* Complete the port connection */
297  Status = NtCompleteConnectPort(PortHandle);
298  if ((NT_SUCCESS(Status)) && (CidSubsystem))
299  {
300  /* This was an actual subsystem, so connect back to it */
301  SbApiMsg->ConnectionInfo.SbApiPortName[119] = UNICODE_NULL;
302  RtlCreateUnicodeString(&SubsystemPort,
303  SbApiMsg->ConnectionInfo.SbApiPortName);
304  Status = NtConnectPort(&CidSubsystem->SbApiPort,
305  &SubsystemPort,
306  &SecurityQos,
307  NULL,
308  NULL,
309  NULL,
310  NULL,
311  NULL);
312  if (!NT_SUCCESS(Status))
313  {
314  DPRINT1("SMSS: Connect back to Sb %wZ failed %lx\n", &SubsystemPort, Status);
315  }
316  RtlFreeUnicodeString(&SubsystemPort);
317 
318  /* Now that we're connected, signal the event handle */
319  NtSetEvent(CidSubsystem->Event, NULL);
320  }
321  else if (CidSubsystem)
322  {
323  /* We failed to complete the connection, so clear the port handle */
324  DPRINT1("Completing the connection failed: %lx\n", Status);
325  CidSubsystem->PortHandle = NULL;
326  }
327 
328  /* Dereference the subsystem and return the result */
329  if (CidSubsystem) SmpDereferenceSubsystem(CidSubsystem);
330  return Status;
331 }
332 
333 ULONG
334 NTAPI
336 {
340  PSM_API_MSG ReplyMsg = NULL;
341  SM_API_MSG RequestMsg;
342  PROCESS_BASIC_INFORMATION ProcessInformation;
344 
345  /* Increase the number of API threads for throttling code for later */
347 
348  /* Mark us critical */
350 
351  /* Set the PID of the SM process itself for later checking */
354  &ProcessInformation,
355  sizeof(ProcessInformation),
356  NULL);
357  SmUniqueProcessId = (HANDLE)ProcessInformation.UniqueProcessId;
358 
359  /* Now process incoming messages */
360  while (TRUE)
361  {
362  /* Begin waiting on a request */
364  (PVOID*)&ClientContext,
365  &ReplyMsg->h,
366  &RequestMsg.h);
367  if (Status == STATUS_NO_MEMORY)
368  {
369  /* Ran out of memory, so do a little timeout and try again */
370  if (ReplyMsg) DPRINT1("SMSS: Failed to reply to calling thread, retrying.\n");
371  Timeout.QuadPart = -50000000;
373  continue;
374  }
375 
376  /* Check what kind of request we received */
377  switch (RequestMsg.h.u2.s2.Type)
378  {
379  /* A new connection */
381  /* Create the right structures for it */
383  ReplyMsg = NULL;
384  break;
385 
386  /* A closed connection */
387  case LPC_PORT_CLOSED:
388  /* Destroy any state we had for this client */
389  DPRINT1("Port closed\n");
390  //if (ClientContext) SmpPushDeferredClientContext(ClientContext);
391  ReplyMsg = NULL;
392  break;
393 
394  /* An actual API message */
395  default:
396  if (!ClientContext)
397  {
398  ReplyMsg = NULL;
399  break;
400  }
401 
402  RequestMsg.ReturnValue = STATUS_PENDING;
403 
404  /* Check if the API is valid */
405  if (RequestMsg.ApiNumber >= SmpMaxApiNumber)
406  {
407  /* It isn't, fail */
408  DPRINT1("Invalid API: %lx\n", RequestMsg.ApiNumber);
410  }
411  else if ((RequestMsg.ApiNumber <= SmpTerminateForeignSessionApi) &&
412  !(ClientContext->Subsystem))
413  {
414  /* It's valid, but doesn't have a subsystem with it */
415  DPRINT1("Invalid session API\n");
417  }
418  else
419  {
420  /* It's totally okay, so call the dispatcher for it */
421  Status = SmpApiDispatch[RequestMsg.ApiNumber](&RequestMsg,
423  SmApiPort);
424  }
425 
426  /* Write the result value and return the message back */
427  RequestMsg.ReturnValue = Status;
428  ReplyMsg = &RequestMsg;
429  break;
430  }
431  }
432  return STATUS_SUCCESS;
433 }
PORT_MESSAGE h
Definition: smmsg.h:92
NTSTATUS NTAPI SmpHandleConnectionRequest(IN HANDLE SmApiPort, IN PSB_API_MSG SbApiMsg)
Definition: smloop.c:185
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:162
#define IN
Definition: typedefs.h:38
#define THREAD_ALL_ACCESS
Definition: nt_native.h:1339
#define TRUE
Definition: types.h:120
HANDLE PortHandle
Definition: smss.h:64
#define PROCESS_ALL_ACCESS
Definition: nt_native.h:1324
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
#define PROCESS_QUERY_INFORMATION
Definition: pstypes.h:158
HANDLE SmApiPort
Definition: smss.c:23
NTSTATUS(NTAPI * PSM_API_HANDLER)(IN PSM_API_MSG SmApiMsg, IN PSMP_CLIENT_CONTEXT ClientContext, IN HANDLE SmApiPort)
Definition: smloop.c:28
#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 NtQueryInformationProcess(IN HANDLE ProcessHandle, IN PROCESSINFOCLASS ProcessInformationClass, OUT PVOID ProcessInformation, IN ULONG ProcessInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: query.c:59
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:335
_In_ PVOID Parameter
Definition: ldrtypes.h:240
ULONG ImageType
Definition: smss.h:63
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
while(1)
Definition: macro.lex.yy.c:740
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 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
smooth NULL
Definition: ftsmooth.c:416
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:61
PSM_API_HANDLER SmpApiDispatch[SmpMaxApiNumber - SmpCreateForeignSessionApi]
Definition: smloop.c:170
NTSTATUS NTAPI NtDelayExecution(IN BOOLEAN Alertable, IN PLARGE_INTEGER DelayInterval)
Definition: wait.c:879
#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
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:458
#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:71
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
HANDLE SbApiPort
Definition: smss.h:65
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
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
HANDLE PortHandle
Definition: smloop.c:22
Status
Definition: gdiplustypes.h:24
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:246
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 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:3407
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
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
return STATUS_SUCCESS
Definition: btrfs.c:2777
#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 SmpSessionComplete(IN PSM_API_MSG SmApiMsg, IN PSMP_CLIENT_CONTEXT ClientContext, IN HANDLE SmApiPort)
Definition: smloop.c:51