NTSTATUS SmpApiLoop ( IN PVOID ThreadParameter ) /*++ Routine Description: This is the main Session Manager API Loop. It services session manager API requests. Arguments: ThreadParameter - Supplies a handle to the API port used to receive session manager API requests. Return Value: None. --*/ { PSMAPIMSG SmApiReplyMsg; SMMESSAGE_SIZE MsgBuf; PSMAPIMSG SmApiMsg; NTSTATUS Status; HANDLE ConnectionPort; PSMP_CLIENT_CONTEXT ClientContext; PSMPKNOWNSUBSYS KnownSubSys; ConnectionPort = (HANDLE) ThreadParameter; SmApiMsg = (PSMAPIMSG)&MsgBuf; SmApiReplyMsg = NULL; try { for(;;) { Status = NtReplyWaitReceivePort( ConnectionPort, (PVOID *) &ClientContext, (PPORT_MESSAGE) SmApiReplyMsg, (PPORT_MESSAGE) SmApiMsg ); if ( !NT_SUCCESS(Status) ) { SmApiReplyMsg = NULL; continue; } else if ( SmApiMsg->h.u2.s2.Type == LPC_CONNECTION_REQUEST ) { SmpHandleConnectionRequest( ConnectionPort, (PSBAPIMSG) SmApiMsg ); SmApiReplyMsg = NULL; } else if ( SmApiMsg->h.u2.s2.Type == LPC_DEBUG_EVENT ) { ASSERT(SmpDbgSsLoaded); DbgSsHandleKmApiMsg((PDBGKM_APIMSG)SmApiMsg,NULL); SmApiReplyMsg = NULL; } else if ( SmApiMsg->h.u2.s2.Type == LPC_PORT_CLOSED ) { SmApiReplyMsg = NULL; } else { KnownSubSys = ClientContext->KnownSubSys; SmApiMsg->ReturnedStatus = STATUS_PENDING; #if DBG && 0 if (SmApiMsg->ApiNumber >= SmMaxApiNumber ) { SmApiMsg->ApiNumber = SmMaxApiNumber; } KdPrint(( "SMSS: %s Api Request received from %lx.%lx\n", SmpApiName[ SmApiMsg->ApiNumber ], SmApiMsg->h.ClientId.UniqueProcess, SmApiMsg->h.ClientId.UniqueThread )); #endif // DBG if (SmApiMsg->ApiNumber >= SmMaxApiNumber ) { Status = STATUS_NOT_IMPLEMENTED; } else { switch (SmApiMsg->ApiNumber) { case SmExecPgmApi : Status = (SmpApiDispatch[SmApiMsg->ApiNumber])( SmApiMsg, ClientContext, ConnectionPort); break; case SmLoadDeferedSubsystemApi : Status = (SmpApiDispatch[SmApiMsg->ApiNumber])( SmApiMsg, ClientContext, ConnectionPort); break; case SmCreateForeignSessionApi : case SmSessionCompleteApi : case SmTerminateForeignSessionApi : if (!KnownSubSys) { Status = STATUS_INVALID_PARAMETER; } else { Status = (SmpApiDispatch[SmApiMsg->ApiNumber])( SmApiMsg, ClientContext, ConnectionPort); } break; } } SmApiMsg->ReturnedStatus = Status; SmApiReplyMsg = SmApiMsg; } } } except (DbgpUnhandledExceptionFilter( GetExceptionInformation() )) { ; } // // Make the compiler happy // return STATUS_UNSUCCESSFUL; }
ULONG NTAPI SmpApiLoop(IN PVOID Parameter) { HANDLE SmApiPort = (HANDLE)Parameter; NTSTATUS Status; PSMP_CLIENT_CONTEXT ClientContext; PSM_API_MSG ReplyMsg = NULL; SM_API_MSG RequestMsg; PROCESS_BASIC_INFORMATION ProcessInformation; LARGE_INTEGER Timeout; /* Increase the number of API threads for throttling code for later */ _InterlockedExchangeAdd(&SmTotalApiThreads, 1); /* Mark us critical */ RtlSetThreadIsCritical(TRUE, NULL, TRUE); /* Set the PID of the SM process itself for later checking */ NtQueryInformationProcess(NtCurrentProcess(), ProcessBasicInformation, &ProcessInformation, sizeof(ProcessInformation), NULL); SmUniqueProcessId = (HANDLE)ProcessInformation.UniqueProcessId; /* Now process incoming messages */ while (TRUE) { /* Begin waiting on a request */ Status = NtReplyWaitReceivePort(SmApiPort, (PVOID*)&ClientContext, &ReplyMsg->h, &RequestMsg.h); if (Status == STATUS_NO_MEMORY) { /* Ran out of memory, so do a little timeout and try again */ if (ReplyMsg) DPRINT1("SMSS: Failed to reply to calling thread, retrying.\n"); Timeout.QuadPart = -50000000; NtDelayExecution(FALSE, &Timeout); continue; } /* Check what kind of request we received */ switch (RequestMsg.h.u2.s2.Type) { /* A new connection */ case LPC_CONNECTION_REQUEST: /* Create the right structures for it */ SmpHandleConnectionRequest(SmApiPort, (PSB_API_MSG)&RequestMsg); ReplyMsg = NULL; break; /* A closed connection */ case LPC_PORT_CLOSED: /* Destroy any state we had for this client */ DPRINT1("Port closed\n"); //if (ClientContext) SmpPushDeferredClientContext(ClientContext); ReplyMsg = NULL; break; /* An actual API message */ default: if (!ClientContext) { ReplyMsg = NULL; break; } RequestMsg.ReturnValue = STATUS_PENDING; /* Check if the API is valid */ if (RequestMsg.ApiNumber >= SmpMaxApiNumber) { /* It isn't, fail */ DPRINT1("Invalid API: %lx\n", RequestMsg.ApiNumber); Status = STATUS_NOT_IMPLEMENTED; } else if ((RequestMsg.ApiNumber <= SmpTerminateForeignSessionApi) && !(ClientContext->Subsystem)) { /* It's valid, but doesn't have a subsystem with it */ DPRINT1("Invalid session API\n"); Status = STATUS_INVALID_PARAMETER; } else { /* It's totally okay, so call the dispatcher for it */ Status = SmpApiDispatch[RequestMsg.ApiNumber](&RequestMsg, ClientContext, SmApiPort); } /* Write the result valud and return the message back */ RequestMsg.ReturnValue = Status; ReplyMsg = &RequestMsg; break; } } return STATUS_SUCCESS; }