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