Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygensmloop.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Windows-Compatible Session Manager 00003 * LICENSE: BSD 2-Clause License 00004 * FILE: base/system/smss/smss.c 00005 * PURPOSE: Main SMSS Code 00006 * PROGRAMMERS: Alex Ionescu 00007 */ 00008 00009 /* INCLUDES *******************************************************************/ 00010 00011 #include "smss.h" 00012 #define NDEBUG 00013 #include "debug.h" 00014 00015 /* GLOBALS ********************************************************************/ 00016 00017 typedef struct _SMP_CLIENT_CONTEXT 00018 { 00019 PVOID Subsystem; 00020 HANDLE ProcessHandle; 00021 HANDLE PortHandle; 00022 ULONG dword10; 00023 } SMP_CLIENT_CONTEXT, *PSMP_CLIENT_CONTEXT; 00024 00025 typedef 00026 NTSTATUS 00027 (NTAPI *PSM_API_HANDLER)( 00028 IN PSM_API_MSG SmApiMsg, 00029 IN PSMP_CLIENT_CONTEXT ClientContext, 00030 IN HANDLE SmApiPort 00031 ); 00032 00033 volatile LONG SmTotalApiThreads; 00034 HANDLE SmUniqueProcessId; 00035 00036 /* API HANDLERS ***************************************************************/ 00037 00038 NTSTATUS 00039 NTAPI 00040 SmpCreateForeignSession(IN PSM_API_MSG SmApiMsg, 00041 IN PSMP_CLIENT_CONTEXT ClientContext, 00042 IN HANDLE SmApiPort) 00043 { 00044 DPRINT1("%s is not yet implemented\n", __FUNCTION__); 00045 return STATUS_NOT_IMPLEMENTED; 00046 } 00047 00048 NTSTATUS 00049 NTAPI 00050 SmpSessionComplete(IN PSM_API_MSG SmApiMsg, 00051 IN PSMP_CLIENT_CONTEXT ClientContext, 00052 IN HANDLE SmApiPort) 00053 { 00054 DPRINT1("%s is not yet implemented\n", __FUNCTION__); 00055 return STATUS_NOT_IMPLEMENTED; 00056 } 00057 00058 NTSTATUS 00059 NTAPI 00060 SmpTerminateForeignSession(IN PSM_API_MSG SmApiMsg, 00061 IN PSMP_CLIENT_CONTEXT ClientContext, 00062 IN HANDLE SmApiPort) 00063 { 00064 DPRINT1("%s is not yet implemented\n", __FUNCTION__); 00065 return STATUS_NOT_IMPLEMENTED; 00066 } 00067 00068 NTSTATUS 00069 NTAPI 00070 SmpExecPgm(IN PSM_API_MSG SmApiMsg, 00071 IN PSMP_CLIENT_CONTEXT ClientContext, 00072 IN HANDLE SmApiPort) 00073 { 00074 HANDLE ProcessHandle; 00075 NTSTATUS Status; 00076 PSM_EXEC_PGM_MSG SmExecPgm; 00077 RTL_USER_PROCESS_INFORMATION ProcessInformation; 00078 OBJECT_ATTRIBUTES ObjectAttributes; 00079 00080 /* Open the client process */ 00081 InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); 00082 Status = NtOpenProcess(&ProcessHandle, 00083 PROCESS_DUP_HANDLE, 00084 &ObjectAttributes, 00085 &SmApiMsg->h.ClientId); 00086 if (!NT_SUCCESS(Status)) 00087 { 00088 /* Fail */ 00089 DPRINT1("SmExecPgm: NtOpenProcess Failed %lx\n", Status); 00090 return Status; 00091 } 00092 00093 /* Copy the process information out of the message */ 00094 SmExecPgm = &SmApiMsg->u.ExecPgm; 00095 ProcessInformation = SmExecPgm->ProcessInformation; 00096 00097 /* Duplicate the process handle */ 00098 Status = NtDuplicateObject(ProcessHandle, 00099 SmExecPgm->ProcessInformation.ProcessHandle, 00100 NtCurrentProcess(), 00101 &ProcessInformation.ProcessHandle, 00102 PROCESS_ALL_ACCESS, 00103 0, 00104 0); 00105 if (!NT_SUCCESS(Status)) 00106 { 00107 /* Close the handle and fail */ 00108 NtClose(ProcessHandle); 00109 DPRINT1("SmExecPgm: NtDuplicateObject (Process) Failed %lx\n", Status); 00110 return Status; 00111 } 00112 00113 /* Duplicate the thread handle */ 00114 Status = NtDuplicateObject(ProcessHandle, 00115 SmExecPgm->ProcessInformation.ThreadHandle, 00116 NtCurrentProcess(), 00117 &ProcessInformation.ThreadHandle, 00118 THREAD_ALL_ACCESS, 00119 0, 00120 0); 00121 if (!NT_SUCCESS(Status)) 00122 { 00123 /* Close both handles and fail */ 00124 NtClose(ProcessInformation.ProcessHandle); 00125 NtClose(ProcessHandle); 00126 DPRINT1("SmExecPgm: NtDuplicateObject (Thread) Failed %lx\n", Status); 00127 return Status; 00128 } 00129 00130 /* Close the process handle and call the internal client API */ 00131 NtClose(ProcessHandle); 00132 return SmpSbCreateSession(NULL, 00133 NULL, 00134 &ProcessInformation, 00135 0, 00136 SmExecPgm->DebugFlag ? &SmApiMsg->h.ClientId : NULL); 00137 } 00138 00139 NTSTATUS 00140 NTAPI 00141 SmpLoadDeferedSubsystem(IN PSM_API_MSG SmApiMsg, 00142 IN PSMP_CLIENT_CONTEXT ClientContext, 00143 IN HANDLE SmApiPort) 00144 { 00145 DPRINT1("%s is not yet implemented\n", __FUNCTION__); 00146 return STATUS_NOT_IMPLEMENTED; 00147 } 00148 00149 NTSTATUS 00150 NTAPI 00151 SmpStartCsr(IN PSM_API_MSG SmApiMsg, 00152 IN PSMP_CLIENT_CONTEXT ClientContext, 00153 IN HANDLE SmApiPort) 00154 { 00155 DPRINT1("%s is not yet implemented\n", __FUNCTION__); 00156 return STATUS_NOT_IMPLEMENTED; 00157 } 00158 00159 NTSTATUS 00160 NTAPI 00161 SmpStopCsr(IN PSM_API_MSG SmApiMsg, 00162 IN PSMP_CLIENT_CONTEXT ClientContext, 00163 IN HANDLE SmApiPort) 00164 { 00165 DPRINT1("%s is not yet implemented\n", __FUNCTION__); 00166 return STATUS_NOT_IMPLEMENTED; 00167 } 00168 00169 PSM_API_HANDLER SmpApiDispatch[SmMaxApiNumber] = 00170 { 00171 SmpCreateForeignSession, 00172 SmpSessionComplete, 00173 SmpTerminateForeignSession, 00174 SmpExecPgm, 00175 SmpLoadDeferedSubsystem, 00176 SmpStartCsr, 00177 SmpStopCsr 00178 }; 00179 00180 /* FUNCTIONS ******************************************************************/ 00181 00182 NTSTATUS 00183 NTAPI 00184 SmpHandleConnectionRequest(IN HANDLE SmApiPort, 00185 IN PSB_API_MSG SbApiMsg) 00186 { 00187 BOOLEAN Accept = TRUE; 00188 HANDLE PortHandle, ProcessHandle; 00189 ULONG SessionId; 00190 UNICODE_STRING SubsystemPort; 00191 SMP_CLIENT_CONTEXT *ClientContext; 00192 NTSTATUS Status; 00193 OBJECT_ATTRIBUTES ObjectAttributes; 00194 REMOTE_PORT_VIEW PortView; 00195 SECURITY_QUALITY_OF_SERVICE SecurityQos; 00196 PSMP_SUBSYSTEM CidSubsystem, TypeSubsystem; 00197 00198 /* Initialize QoS data */ 00199 SecurityQos.ImpersonationLevel = SecurityIdentification; 00200 SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; 00201 SecurityQos.EffectiveOnly = TRUE; 00202 00203 /* Check if this is SM connecting to itself */ 00204 if (SbApiMsg->h.ClientId.UniqueProcess == SmUniqueProcessId) 00205 { 00206 /* No need to get any handle -- assume session 0 */ 00207 ProcessHandle = NULL; 00208 SessionId = 0; 00209 } 00210 else 00211 { 00212 /* Reference the foreign process */ 00213 InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); 00214 Status = NtOpenProcess(&ProcessHandle, 00215 PROCESS_QUERY_INFORMATION, 00216 &ObjectAttributes, 00217 &SbApiMsg->h.ClientId); 00218 if (!NT_SUCCESS(Status)) Accept = FALSE; 00219 00220 /* Get its session ID */ 00221 SmpGetProcessMuSessionId(ProcessHandle, &SessionId); 00222 } 00223 00224 /* See if we already know about the caller's subystem */ 00225 CidSubsystem = SmpLocateKnownSubSysByCid(&SbApiMsg->h.ClientId); 00226 if ((CidSubsystem) && (Accept)) 00227 { 00228 /* Check if we already have a subsystem for this kind of image */ 00229 TypeSubsystem = SmpLocateKnownSubSysByType(SessionId, 00230 SbApiMsg->ConnectionInfo.SubsystemType); 00231 if (TypeSubsystem == CidSubsystem) 00232 { 00233 /* Someone is trying to take control of an existing subsystem, fail */ 00234 Accept = FALSE; 00235 DPRINT1("SMSS: Connection from SubSystem rejected\n"); 00236 DPRINT1("SMSS: Image type already being served\n"); 00237 } 00238 else 00239 { 00240 /* Set this image type as the type for this subsystem */ 00241 CidSubsystem->ImageType = SbApiMsg->ConnectionInfo.SubsystemType; 00242 } 00243 00244 /* Drop the reference we had acquired */ 00245 if (TypeSubsystem) SmpDereferenceSubsystem(TypeSubsystem); 00246 } 00247 00248 /* Check if we'll be accepting the connection */ 00249 if (Accept) 00250 { 00251 /* We will, so create a client context for it */ 00252 ClientContext = RtlAllocateHeap(SmpHeap, 0, sizeof(SMP_CLIENT_CONTEXT)); 00253 if (ClientContext) 00254 { 00255 ClientContext->ProcessHandle = ProcessHandle; 00256 ClientContext->Subsystem = CidSubsystem; 00257 ClientContext->dword10 = 0; 00258 ClientContext->PortHandle = NULL; 00259 } 00260 else 00261 { 00262 /* Failed to allocate a client context, so reject the connection */ 00263 DPRINT1("Rejecting connectiond due to lack of memory\n"); 00264 Accept = FALSE; 00265 } 00266 } 00267 else 00268 { 00269 /* Use a bogus context since we're going to reject the message */ 00270 ClientContext = (PSMP_CLIENT_CONTEXT)SbApiMsg; 00271 } 00272 00273 /* Now send the actual accept reply (which could be a rejection) */ 00274 PortView.Length = sizeof(PortView); 00275 Status = NtAcceptConnectPort(&PortHandle, 00276 ClientContext, 00277 &SbApiMsg->h, 00278 Accept, 00279 NULL, 00280 &PortView); 00281 if (!(Accept) || !(NT_SUCCESS(Status))) 00282 { 00283 /* Close the process handle, reference the subsystem, and exit */ 00284 DPRINT1("Accept failed or rejected: %lx\n", Status); 00285 if (ClientContext != (PVOID)SbApiMsg) RtlFreeHeap(SmpHeap, 0, ClientContext); 00286 if (ProcessHandle) NtClose(ProcessHandle); 00287 if (CidSubsystem) SmpDereferenceSubsystem(CidSubsystem); 00288 return Status; 00289 } 00290 00291 /* Save the port handle now that we've accepted it */ 00292 if (ClientContext) ClientContext->PortHandle = PortHandle; 00293 if (CidSubsystem) CidSubsystem->PortHandle = PortHandle; 00294 00295 /* Complete the port connection */ 00296 Status = NtCompleteConnectPort(PortHandle); 00297 if ((NT_SUCCESS(Status)) && (CidSubsystem)) 00298 { 00299 /* This was an actual subsystem, so connect back to it */ 00300 SbApiMsg->ConnectionInfo.SbApiPortName[119] = UNICODE_NULL; 00301 RtlCreateUnicodeString(&SubsystemPort, 00302 SbApiMsg->ConnectionInfo.SbApiPortName); 00303 Status = NtConnectPort(&CidSubsystem->SbApiPort, 00304 &SubsystemPort, 00305 &SecurityQos, 00306 NULL, 00307 NULL, 00308 NULL, 00309 NULL, 00310 NULL); 00311 if (!NT_SUCCESS(Status)) 00312 { 00313 DPRINT1("SMSS: Connect back to Sb %wZ failed %lx\n", &SubsystemPort, Status); 00314 } 00315 RtlFreeUnicodeString(&SubsystemPort); 00316 00317 /* Now that we're connected, signal the event handle */ 00318 NtSetEvent(CidSubsystem->Event, NULL); 00319 } 00320 else if (CidSubsystem) 00321 { 00322 /* We failed to complete the connection, so clear the port handle */ 00323 DPRINT1("Completing the connection failed: %lx\n", Status); 00324 CidSubsystem->PortHandle = NULL; 00325 } 00326 00327 /* Dereference the subsystem and return the result */ 00328 if (CidSubsystem) SmpDereferenceSubsystem(CidSubsystem); 00329 return Status; 00330 } 00331 00332 ULONG 00333 NTAPI 00334 SmpApiLoop(IN PVOID Parameter) 00335 { 00336 HANDLE SmApiPort = (HANDLE)Parameter; 00337 NTSTATUS Status; 00338 PSMP_CLIENT_CONTEXT ClientContext; 00339 PSM_API_MSG ReplyMsg = NULL; 00340 SM_API_MSG RequestMsg; 00341 PROCESS_BASIC_INFORMATION ProcessInformation; 00342 LARGE_INTEGER Timeout; 00343 00344 /* Increase the number of API threads for throttling code for later */ 00345 _InterlockedExchangeAdd(&SmTotalApiThreads, 1); 00346 00347 /* Mark us critical */ 00348 RtlSetThreadIsCritical(TRUE, NULL, TRUE); 00349 00350 /* Set the PID of the SM process itself for later checking */ 00351 NtQueryInformationProcess(NtCurrentProcess(), 00352 ProcessBasicInformation, 00353 &ProcessInformation, 00354 sizeof(ProcessInformation), 00355 NULL); 00356 SmUniqueProcessId = (HANDLE)ProcessInformation.UniqueProcessId; 00357 00358 /* Now process incoming messages */ 00359 while (TRUE) 00360 { 00361 /* Begin waiting on a request */ 00362 Status = NtReplyWaitReceivePort(SmApiPort, 00363 (PVOID*)&ClientContext, 00364 &ReplyMsg->h, 00365 &RequestMsg.h); 00366 if (Status == STATUS_NO_MEMORY) 00367 { 00368 /* Ran out of memory, so do a little timeout and try again */ 00369 if (ReplyMsg) DPRINT1("SMSS: Failed to reply to calling thread, retrying.\n"); 00370 Timeout.QuadPart = -50000000; 00371 NtDelayExecution(FALSE, &Timeout); 00372 continue; 00373 } 00374 00375 /* Check what kind of request we received */ 00376 switch (RequestMsg.h.u2.s2.Type) 00377 { 00378 /* A new connection */ 00379 case LPC_CONNECTION_REQUEST: 00380 /* Create the right structures for it */ 00381 SmpHandleConnectionRequest(SmApiPort, (PSB_API_MSG)&RequestMsg); 00382 ReplyMsg = NULL; 00383 break; 00384 00385 /* A closed connection */ 00386 case LPC_PORT_CLOSED: 00387 /* Destroy any state we had for this client */ 00388 DPRINT1("Port closed\n"); 00389 //if (ClientContext) SmpPushDeferredClientContext(ClientContext); 00390 ReplyMsg = NULL; 00391 break; 00392 00393 /* An actual API message */ 00394 default: 00395 if (!ClientContext) 00396 { 00397 ReplyMsg = NULL; 00398 break; 00399 } 00400 00401 RequestMsg.ReturnValue = STATUS_PENDING; 00402 00403 /* Check if the API is valid */ 00404 if (RequestMsg.ApiNumber >= SmMaxApiNumber) 00405 { 00406 /* It isn't, fail */ 00407 DPRINT1("Invalid API: %lx\n", RequestMsg.ApiNumber); 00408 Status = STATUS_NOT_IMPLEMENTED; 00409 } 00410 else if ((RequestMsg.ApiNumber <= SmTerminateForeignSessionApi) && 00411 !(ClientContext->Subsystem)) 00412 { 00413 /* It's valid, but doesn't have a subsystem with it */ 00414 DPRINT1("Invalid session API\n"); 00415 Status = STATUS_INVALID_PARAMETER; 00416 } 00417 else 00418 { 00419 /* It's totally okay, so call the dispatcher for it */ 00420 Status = SmpApiDispatch[RequestMsg.ApiNumber](&RequestMsg, 00421 ClientContext, 00422 SmApiPort); 00423 } 00424 00425 /* Write the result valud and return the message back */ 00426 RequestMsg.ReturnValue = Status; 00427 ReplyMsg = &RequestMsg; 00428 break; 00429 } 00430 } 00431 return STATUS_SUCCESS; 00432 } Generated on Sat May 26 2012 04:17:44 for ReactOS by
1.7.6.1
|