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