diff options
Diffstat (limited to 'private/sm/server/smloop.c')
-rw-r--r-- | private/sm/server/smloop.c | 451 |
1 files changed, 451 insertions, 0 deletions
diff --git a/private/sm/server/smloop.c b/private/sm/server/smloop.c new file mode 100644 index 000000000..d54d470bd --- /dev/null +++ b/private/sm/server/smloop.c @@ -0,0 +1,451 @@ +/*++ + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + smloop.c + +Abstract: + + Session Manager Listen and API loops + +Author: + + Mark Lucovsky (markl) 04-Oct-1989 + +Revision History: + +--*/ + +#include "smsrvp.h" + + +NTSTATUS +SmpHandleConnectionRequest( + IN HANDLE ConnectionPort, + IN PSBAPIMSG Message + ); + + +PSMAPI SmpApiDispatch[SmMaxApiNumber] = { + SmpCreateForeignSession, + SmpSessionComplete, + SmpTerminateForeignSession, + SmpExecPgm, + SmpLoadDeferedSubsystem + }; + + +#if DBG +PSZ SmpApiName[ SmMaxApiNumber+1 ] = { + "SmCreateForeignSession", + "SmSessionComplete", + "SmTerminateForeignSession", + "SmExecPgm", + "SmLoadDeferedSubsystem", + "Unknown Sm Api Number" +}; +#endif // DBG + +EXCEPTION_DISPOSITION +DbgpUnhandledExceptionFilter( + struct _EXCEPTION_POINTERS *ExceptionInfo + ); + + +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; +} + + +NTSTATUS +SmpHandleConnectionRequest( + IN HANDLE ConnectionPort, + IN PSBAPIMSG Message + ) + +/*++ + +Routine Description: + + This routine handles connection requests from either known subsystems, + or other clients. Other clients are admin processes. + + The protocol for connection from a known subsystem is: + + capture the name of the sub systems Sb API port + + Accept the connection + + Connect to the subsystems Sb API port + + Store the communication port handle in the known subsystem database + + signal the event associated with the known subsystem + + The protocol for others is to simply validate and accept the connection + request. + +Arguments: + +Return Value: + + None. + +--*/ + +{ + NTSTATUS st; + HANDLE CommunicationPort; + REMOTE_PORT_VIEW ClientView; + PSBCONNECTINFO ConnectInfo; + ULONG ConnectInfoLength; + PSMPKNOWNSUBSYS KnownSubSys; + BOOLEAN Accept; + UNICODE_STRING SubSystemPort; + SECURITY_QUALITY_OF_SERVICE DynamicQos; + PSMP_CLIENT_CONTEXT ClientContext; + + // + // Set up the security quality of service parameters to use over the + // sb API port. Use the most efficient (least overhead) - which is dynamic + // rather than static tracking. + // + + DynamicQos.ImpersonationLevel = SecurityIdentification; + DynamicQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; + DynamicQos.EffectiveOnly = TRUE; + + + ConnectInfo = &Message->ConnectionRequest; + KnownSubSys = SmpLocateKnownSubSysByCid(&Message->h.ClientId); + + if ( KnownSubSys ) { + + if ( SmpLocateKnownSubSysByType(ConnectInfo->SubsystemImageType) == + KnownSubSys ) { + Accept = FALSE; + KdPrint(("SMSS: Connection from SubSystem rejected\n")); + KdPrint(("SMSS: Image type already being served\n")); + } else { + Accept = TRUE; + KnownSubSys->ImageType = ConnectInfo->SubsystemImageType; + } + } else { + + // + // Authenticate the SOB + // + + Accept = TRUE; + + } + + if (Accept) { + ClientContext = RtlAllocateHeap(SmpHeap, MAKE_TAG( SM_TAG ), sizeof(SMP_CLIENT_CONTEXT)); + ClientContext->KnownSubSys = KnownSubSys; + } + + ClientView.Length = sizeof(ClientView); + st = NtAcceptConnectPort( + &CommunicationPort, + ClientContext, + (PPORT_MESSAGE)Message, + Accept, + NULL, + &ClientView + ); + ASSERT( NT_SUCCESS(st) ); + + if ( Accept ) { + + if ( KnownSubSys ) { + KnownSubSys->SmApiCommunicationPort = CommunicationPort; + } + + st = NtCompleteConnectPort(CommunicationPort); + ASSERT( NT_SUCCESS(st) ); + + // + // Connect Back to subsystem + // + + if ( KnownSubSys ) { + RtlCreateUnicodeString( &SubSystemPort, + ConnectInfo->EmulationSubSystemPortName + ); + ConnectInfoLength = sizeof( *ConnectInfo ); + + st = NtConnectPort( + &KnownSubSys->SbApiCommunicationPort, + &SubSystemPort, + &DynamicQos, + NULL, + NULL, + NULL, + NULL, + NULL + ); + if ( !NT_SUCCESS(st) ) { + KdPrint(("SMSS: Connect back to Sb %wZ failed %lx\n",&SubSystemPort,st)); + } + + RtlFreeUnicodeString( &SubSystemPort ); + NtSetEvent(KnownSubSys->Active,NULL); + } + } + + return st; +} + + +PSMPKNOWNSUBSYS +SmpLocateKnownSubSysByCid( + IN PCLIENT_ID ClientId + ) + +/*++ + +Routine Description: + + This function scans the known sub system table looking for + a matching client id (just UniqueProcess portion). If found, + than the connection request is from a known subsystem and + accept is always granted. Otherwise, it must be an administrative + process. + +Arguments: + + ClientId - Supplies the ClientId whose UniqueProcess field is to be used + in the known subsystem scan. + +Return Value: + + NULL - The ClientId does not match a known subsystem. + + NON-NULL - Returns the address of the known subsystem. + +--*/ + +{ + + PSMPKNOWNSUBSYS KnownSubSys = NULL; + PLIST_ENTRY Next; + + // + // Aquire known subsystem lock + // + + RtlEnterCriticalSection(&SmpKnownSubSysLock); + + Next = SmpKnownSubSysHead.Flink; + + while ( Next != &SmpKnownSubSysHead ) { + + KnownSubSys = CONTAINING_RECORD(Next,SMPKNOWNSUBSYS,Links); + Next = Next->Flink; + + if ( KnownSubSys->InitialClientId.UniqueProcess == ClientId->UniqueProcess ) { + break; + } else { + KnownSubSys = NULL; + } + } + + // + // Unlock known subsystems + // + + RtlLeaveCriticalSection(&SmpKnownSubSysLock); + + return KnownSubSys; +} + + +PSMPKNOWNSUBSYS +SmpLocateKnownSubSysByType( + IN ULONG ImageType + ) + +/*++ + +Routine Description: + + This function scans the known sub system table looking for + a matching image type. + +Arguments: + + ImageType - Supplies the image type whose sub system is to be located. + +Return Value: + + NULL - The image type does not match a known subsystem. + + NON-NULL - Returns the address of the known subsystem. + +--*/ + +{ + + PSMPKNOWNSUBSYS KnownSubSys = NULL; + PLIST_ENTRY Next; + + // + // Aquire known subsystem lock + // + + RtlEnterCriticalSection(&SmpKnownSubSysLock); + + Next = SmpKnownSubSysHead.Flink; + + while ( Next != &SmpKnownSubSysHead ) { + + KnownSubSys = CONTAINING_RECORD(Next,SMPKNOWNSUBSYS,Links); + Next = Next->Flink; + + if ( KnownSubSys->ImageType == ImageType ) { + break; + } else { + KnownSubSys = NULL; + } + } + + // + // Unlock known subsystems + // + + RtlLeaveCriticalSection(&SmpKnownSubSysLock); + + return KnownSubSys; +} |