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
SmpSbCreateSession(IN PVOID Reserved,IN PSMP_SUBSYSTEM OtherSubsystem,IN PRTL_USER_PROCESS_INFORMATION ProcessInformation,IN ULONG DbgSessionId,IN PCLIENT_ID DbgUiClientId)36 SmpSbCreateSession(IN PVOID Reserved,
37 IN PSMP_SUBSYSTEM OtherSubsystem,
38 IN PRTL_USER_PROCESS_INFORMATION ProcessInformation,
39 IN ULONG DbgSessionId,
40 IN PCLIENT_ID DbgUiClientId)
41 {
42 NTSTATUS Status;
43 ULONG SubSystemType = ProcessInformation->ImageInformation.SubSystemType;
44 ULONG MuSessionId;
45 ULONG SessionId;
46 PSMP_SUBSYSTEM KnownSubsys;
47 SB_API_MSG SbApiMsg = {0};
48 PSB_CREATE_SESSION_MSG CreateSessionMsg = &SbApiMsg.u.CreateSession;
49
50 /* Write out the create session message including its initial process */
51 CreateSessionMsg->ProcessInfo = *ProcessInformation;
52 CreateSessionMsg->DbgSessionId = DbgSessionId;
53 if (DbgUiClientId)
54 {
55 CreateSessionMsg->DbgUiClientId = *DbgUiClientId;
56 }
57 else
58 {
59 CreateSessionMsg->DbgUiClientId.UniqueThread = NULL;
60 CreateSessionMsg->DbgUiClientId.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 suitable 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 /*
173 * This code is part of the LPC-based legacy debugging support for native
174 * applications, implemented with the debug client interface (DbgUi) and
175 * debug subsystem (DbgSs). It is now vestigial since WinXP+ and is here
176 * for informational purposes only.
177 */
178 if ((*(ULONGLONG)&CreateSessionMsg.DbgUiClientId) && SmpDbgSsLoaded)
179 {
180 Process = RtlAllocateHeap(SmpHeap, SmBaseTag, sizeof(SMP_PROCESS));
181 if (!Process)
182 {
183 DPRINT1("Unable to initialize debugging for Native App %lx.%lx -- out of memory\n",
184 ProcessInformation->ClientId.UniqueProcess,
185 ProcessInformation->ClientId.UniqueThread);
186 NtClose(ProcessInformation->ProcessHandle);
187 NtClose(ProcessInformation->ThreadHandle);
188 return STATUS_NO_MEMORY;
189 }
190
191 Process->DbgUiClientId = CreateSessionMsg->DbgUiClientId;
192 Process->ClientId = ProcessInformation->ClientId;
193 InsertHeadList(&NativeProcessList, &Process->Entry);
194 DPRINT1("Native Debug App %lx.%lx\n",
195 Process->ClientId.UniqueProcess,
196 Process->ClientId.UniqueThread);
197
198 Status = NtSetInformationProcess(ProcessInformation->ProcessHandle,
199 ProcessDebugPort,
200 &SmpDebugPort,
201 sizeof(SmpDebugPort));
202 ASSERT(NT_SUCCESS(Status));
203 }
204 #endif
205
206 /* This is a native application being started as the initial command */
207 DPRINT("Subsystem active, starting thread\n");
208 NtClose(ProcessInformation->ProcessHandle);
209 NtResumeThread(ProcessInformation->ThreadHandle, NULL);
210 NtClose(ProcessInformation->ThreadHandle);
211 return STATUS_SUCCESS;
212 }
213