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