Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

451 lines
11 KiB

/*++
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;
}