mirror of https://github.com/lianthony/NT4.0
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
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;
|
|
}
|