xref: /reactos/base/system/smss/smsbapi.c (revision c8d07514)
1 /*
2  * PROJECT:         ReactOS Windows-Compatible Session Manager
3  * LICENSE:         BSD 2-Clause License
4  * FILE:            base/system/smss/smsbapi.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 PCHAR SmpSubSystemNames[] =
19 {
20     "Unknown",
21     "Native",
22     "Windows",
23     "Posix",
24     "OS/2"
25 };
26 
27 /* FUNCTIONS ******************************************************************/
28 
29 NTSTATUS
30 NTAPI
31 SmpSbCreateSession(IN PVOID Reserved,
32                    IN PSMP_SUBSYSTEM OtherSubsystem,
33                    IN PRTL_USER_PROCESS_INFORMATION ProcessInformation,
34                    IN ULONG MuSessionId,
35                    IN PCLIENT_ID DbgClientId)
36 {
37     NTSTATUS Status;
38     PSMP_SUBSYSTEM KnownSubsys;
39     SB_API_MSG SbApiMsg;
40     ULONG SessionId;
41     PSB_CREATE_SESSION_MSG CreateSessionMsg;
42 
43     /* Write out the create session message including its initial process */
44     CreateSessionMsg = &SbApiMsg.CreateSession;
45     CreateSessionMsg->ProcessInfo = *ProcessInformation;
46     CreateSessionMsg->MuSessionId = MuSessionId;
47     if (DbgClientId)
48     {
49         CreateSessionMsg->ClientId = *DbgClientId;
50     }
51     else
52     {
53         CreateSessionMsg->ClientId.UniqueThread = NULL;
54         CreateSessionMsg->ClientId.UniqueProcess = NULL;
55     }
56 
57     /* Find a subsystem responsible for this session */
58     SmpGetProcessMuSessionId(ProcessInformation->ProcessHandle, &MuSessionId);
59     if (!SmpCheckDuplicateMuSessionId(MuSessionId))
60     {
61         NtClose(ProcessInformation->ProcessHandle);
62         NtClose(ProcessInformation->ThreadHandle);
63         DPRINT1("SMSS: CreateSession status=%x\n", STATUS_OBJECT_NAME_NOT_FOUND);
64         return STATUS_OBJECT_NAME_NOT_FOUND;
65     }
66 
67     /* Find the subsystem we have for this initial process */
68     KnownSubsys = SmpLocateKnownSubSysByType(MuSessionId,
69                                              ProcessInformation->
70                                              ImageInformation.SubSystemType);
71     if (KnownSubsys)
72     {
73         /* Duplicate the process handle into the message */
74         Status = NtDuplicateObject(NtCurrentProcess(),
75                                    ProcessInformation->ProcessHandle,
76                                    KnownSubsys->ProcessHandle,
77                                    &CreateSessionMsg->ProcessInfo.ProcessHandle,
78                                    PROCESS_ALL_ACCESS,
79                                    0,
80                                    0);
81         if (NT_SUCCESS(Status))
82         {
83             /* Duplicate the thread handle into the message */
84             Status = NtDuplicateObject(NtCurrentProcess(),
85                                        ProcessInformation->ThreadHandle,
86                                        KnownSubsys->ProcessHandle,
87                                        &CreateSessionMsg->ProcessInfo.ThreadHandle,
88                                        THREAD_ALL_ACCESS,
89                                        0,
90                                        0);
91             if (!NT_SUCCESS(Status))
92             {
93                 /* Close everything on failure */
94                 NtClose(ProcessInformation->ProcessHandle);
95                 NtClose(ProcessInformation->ThreadHandle);
96                 SmpDereferenceSubsystem(KnownSubsys);
97                 DPRINT1("SmpSbCreateSession: NtDuplicateObject (Thread) Failed %lx\n", Status);
98                 return Status;
99             }
100 
101             /* Close the original handles as they are no longer needed */
102             NtClose(ProcessInformation->ProcessHandle);
103             NtClose(ProcessInformation->ThreadHandle);
104 
105             /* Finally, allocate a new SMSS session ID for this session */
106             SessionId = SmpAllocateSessionId(KnownSubsys, OtherSubsystem);
107             CreateSessionMsg->SessionId = SessionId;
108 
109             /* Fill out the LPC message header and send it to the client! */
110             SbApiMsg.ApiNumber = SbpCreateSession;
111             SbApiMsg.h.u2.ZeroInit = 0;
112             SbApiMsg.h.u1.s1.DataLength = sizeof(SB_CREATE_SESSION_MSG) + 8;
113             SbApiMsg.h.u1.s1.TotalLength = sizeof(SbApiMsg);
114             Status = NtRequestWaitReplyPort(KnownSubsys->SbApiPort,
115                                             &SbApiMsg.h,
116                                             &SbApiMsg.h);
117             if (!NT_SUCCESS(Status))
118             {
119                 /* Bail out */
120                 DPRINT1("SmpSbCreateSession: NtRequestWaitReply Failed %lx\n", Status);
121             }
122             else
123             {
124                 /* If the API succeeded, get the result value from the LPC */
125                 Status = SbApiMsg.ReturnValue;
126             }
127 
128             /* Delete the session on any kind of failure */
129             if (!NT_SUCCESS(Status)) SmpDeleteSession(SessionId);
130         }
131         else
132         {
133             /* Close the handles on failure */
134             DPRINT1("SmpSbCreateSession: NtDuplicateObject (Process) Failed %lx\n", Status);
135             NtClose(ProcessInformation->ProcessHandle);
136             NtClose(ProcessInformation->ThreadHandle);
137         }
138 
139         /* Dereference the subsystem and return the status of the LPC call */
140         SmpDereferenceSubsystem(KnownSubsys);
141         return Status;
142     }
143 
144     /* If we don't yet have a subsystem, only native images can be launched */
145     if (ProcessInformation->ImageInformation.SubSystemType != IMAGE_SUBSYSTEM_NATIVE)
146     {
147         /* Fail */
148         DPRINT1("SMSS: %s SubSystem has not been started.\n",
149                 SmpSubSystemNames[ProcessInformation->ImageInformation.SubSystemType]);
150         Status = STATUS_UNSUCCESSFUL;
151         NtClose(ProcessInformation->ProcessHandle);
152         NtClose(ProcessInformation->ThreadHandle);
153         return Status;
154     }
155 
156 #if 0
157     /* This code handles debug applications, but it seems vestigial... */
158     if ((*(ULONGLONG)&CreateSessionMsg.ClientId) && (SmpDbgSsLoaded))
159     {
160         Process = RtlAllocateHeap(SmpHeap, SmBaseTag, sizeof(SMP_PROCESS));
161         if (!Process)
162         {
163             DPRINT1("Unable to initialize debugging for Native App %lx.%lx -- out of memory\n",
164                     ProcessInformation->ClientId.UniqueProcess,
165                     ProcessInformation->ClientId.UniqueThread);
166             NtClose(ProcessInformation->ProcessHandle);
167             NtClose(ProcessInformation->ThreadHandle);
168             return STATUS_NO_MEMORY;
169         }
170 
171         Process->DbgClientId = CreateSessionMsg->ClientId;
172         Process->ClientId = ProcessInformation->ClientId;
173         InsertHeadList(&NativeProcessList, &Process->Entry);
174         DPRINT1("Native Debug App %lx.%lx\n", Process->ClientId.UniqueProcess, Process->ClientId.UniqueThread);
175 
176         Status = NtSetInformationProcess(ProcessInformation->ProcessHandle, 7, &SmpDebugPort, 4);
177         ASSERT(NT_SUCCESS(Status));
178     }
179 #endif
180 
181     /* This is a native application being started as the initial command */
182     DPRINT("Subsystem active, starting thread\n");
183     NtClose(ProcessInformation->ProcessHandle);
184     NtResumeThread(ProcessInformation->ThreadHandle, NULL);
185     NtClose(ProcessInformation->ThreadHandle);
186     return STATUS_SUCCESS;
187 }
188