Sync with trunk r63831.
[reactos.git] / base / system / smss / smsbapi.c
1 /*
2 * PROJECT: ReactOS Windows-Compatible Session Manager
3 * LICENSE: BSD 2-Clause License
4 * FILE: base/system/smss/smss.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 DbgPrint("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 DPRINT1("Subsystem active, starting thread\n");
183 NtClose(ProcessInformation->ProcessHandle);
184 NtResumeThread(ProcessInformation->ThreadHandle, NULL);
185 NtClose(ProcessInformation->ThreadHandle);
186 return STATUS_SUCCESS;
187 }