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.
400 lines
12 KiB
400 lines
12 KiB
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
conthrds.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the Server Listen&Request threads
|
|
procedures for the Console Session.
|
|
|
|
Author:
|
|
|
|
Avi Nathan (avin) 17-Jul-1991
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "os2srv.h"
|
|
#define NTOS2_ONLY
|
|
#include "sesport.h"
|
|
#include "os2win.h"
|
|
|
|
|
|
extern OS2_SES_GROUP_PARMS ServerSesGrp;
|
|
|
|
VOID
|
|
Os2SessionHandleConnectionRequest(
|
|
POS2SESREQUESTMSG Message
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
HANDLE Os2SessionCommPortHandle;
|
|
APIRET Rc;
|
|
POS2_THREAD Thread;
|
|
POS2_SESSION Session;
|
|
POS2_PROCESS Process;
|
|
BOOLEAN AcceptConnection;
|
|
POS2SESCONNECTINFO ConnectionInfoIn = &Message->ConnectionRequest;
|
|
REMOTE_PORT_VIEW ClientView;
|
|
HANDLE TmpWin32ForegroundWindow;
|
|
|
|
//
|
|
// sync with other server threads
|
|
//
|
|
Os2AcquireStructureLock();
|
|
|
|
TmpWin32ForegroundWindow = ConnectionInfoIn->In.Win32ForegroundWindow;
|
|
if (ConnectionInfoIn->In.ExpectedVersion > OS2_SS_VERSION)
|
|
{
|
|
KdPrint(( "OS2SRV: Os2SessionHandleConnectionRequest received old version (%u intead of %u)\n",
|
|
ConnectionInfoIn->In.ExpectedVersion, OS2_SS_VERSION));
|
|
AcceptConnection = FALSE;
|
|
} else
|
|
{
|
|
AcceptConnection = TRUE;
|
|
#if DBG
|
|
if (ConnectionInfoIn->In.SessionDbg)
|
|
{
|
|
Os2Debug |= OS2_DEBUG_BRK;
|
|
KdPrint(( "OS2SRV: Breakpoint caused by OS2 /B\n" ));
|
|
DbgBreakPoint();
|
|
} else
|
|
{
|
|
Os2Debug &= ~(OS2_DEBUG_BRK);
|
|
}
|
|
#endif // DBG
|
|
ConnectionInfoIn->Out.CurrentVersion = OS2_SS_VERSION;
|
|
}
|
|
|
|
if ( !AcceptConnection )
|
|
{
|
|
// Reject
|
|
failConnect:
|
|
Status = NtAcceptConnectPort(
|
|
&Os2SessionCommPortHandle,
|
|
NULL,
|
|
(PPORT_MESSAGE)Message,
|
|
(BOOLEAN)FALSE,
|
|
NULL,
|
|
NULL
|
|
);
|
|
} else
|
|
{
|
|
//
|
|
// See if this Unique Id already exist (execed by DosExecPgm)
|
|
// if not, create a new session and give it as a port handle
|
|
//
|
|
|
|
Thread = Os2LocateThreadByClientId( NULL, &Message->h.ClientId );
|
|
if (Thread == NULL)
|
|
{
|
|
//
|
|
// new session
|
|
//
|
|
Session = Os2AllocateSession(NULL, 0L, &Rc);
|
|
ConnectionInfoIn->Out.SessionUniqueID = (ULONG)Session;
|
|
if (Session == NULL)
|
|
{
|
|
KdPrint(( "OS2SRV: Os2SessionHandleConnectionRequest fails to allocate session\n"));
|
|
goto failConnect;
|
|
}
|
|
ConnectionInfoIn->Out.IsNewSession = OS2SS_NEW_SESSION;
|
|
if ((Process = Os2AllocateProcess()) == NULL)
|
|
{
|
|
// free the session
|
|
KdPrint(( "OS2SRV: Os2SessionHandleConnectionRequest fails to allocate process\n"));
|
|
goto failConnect;
|
|
}
|
|
Session->Process = Process;
|
|
ConnectionInfoIn->Out.ProcessUniqueID = (ULONG)Process;
|
|
} else
|
|
{
|
|
/*
|
|
* a child session
|
|
*/
|
|
|
|
if ((Process = Thread->Process) == NULL)
|
|
{
|
|
// free the session
|
|
KdPrint(( "OS2SRV: Os2SessionHandleConnectionRequest fails to find process for child session\n"));
|
|
goto failConnect;
|
|
}
|
|
Session = Process->Session;
|
|
if (Session == NULL)
|
|
{
|
|
KdPrint(( "OS2SRV: Os2SessionHandleConnectionRequestfails to find child session\n"));
|
|
goto failConnect;
|
|
}
|
|
|
|
//
|
|
// This process was execed by os/2, use process handle as uniqueid
|
|
//
|
|
ConnectionInfoIn->Out.SessionUniqueID = (ULONG)Session;
|
|
ConnectionInfoIn->Out.ProcessUniqueID = (ULONG)Process;
|
|
//
|
|
// indicate to os2.exe that this is not a new session
|
|
//
|
|
if( Session->Process == NULL )
|
|
{
|
|
/*
|
|
* a child session
|
|
*/
|
|
|
|
ASSERT(Session->ReferenceCount == 1);
|
|
|
|
Session->Process = Process;
|
|
ConnectionInfoIn->Out.IsNewSession = OS2SS_CHILD_SESSION;
|
|
} else
|
|
{
|
|
/*
|
|
* a child process
|
|
*/
|
|
|
|
//
|
|
// indicate to os2.exe that this is not a new session
|
|
//
|
|
ConnectionInfoIn->Out.IsNewSession = OS2SS_CHILD_PROCESS;
|
|
}
|
|
}
|
|
Session->Win32ForegroundWindow = TmpWin32ForegroundWindow;
|
|
ConnectionInfoIn->Out.Os2SrvId = GetCurrentProcessId();
|
|
ConnectionInfoIn->Out.Od2Debug = 0;
|
|
#if DBG
|
|
ConnectionInfoIn->Out.Od2Debug = Os2Debug;
|
|
#endif
|
|
|
|
/*
|
|
* Os2SessionCommPortHandle is not used for Reply. Instead,
|
|
* the port is created with ReceiveAny==TRUE and we wait
|
|
* on the connection port.
|
|
*/
|
|
|
|
ClientView.Length = sizeof( ClientView );
|
|
ClientView.ViewSize = 0;
|
|
ClientView.ViewBase = 0;
|
|
Status = NtAcceptConnectPort(
|
|
& Os2SessionCommPortHandle,
|
|
(PVOID)Process,
|
|
(PPORT_MESSAGE)Message,
|
|
(BOOLEAN)TRUE,
|
|
NULL,
|
|
&ClientView
|
|
);
|
|
#if DBG
|
|
IF_OS2_DEBUG( LPC )
|
|
{
|
|
KdPrint(( "OS2SRV: listen - ClientView: Base=%lx, Size=%lx, PortHandle %lx\n",
|
|
ClientView.ViewBase, ClientView.ViewSize, Os2SessionCommPortHandle));
|
|
}
|
|
#endif
|
|
Process->ClientPort = Os2SessionCommPortHandle;
|
|
Process->ClientViewBase = (PCH)ClientView.ViewBase;
|
|
Process->ClientViewBounds = (PCH)ClientView.ViewBase + ClientView.ViewSize;
|
|
|
|
if ( !NT_SUCCESS(Status) )
|
|
{
|
|
// free the session
|
|
|
|
Os2DereferenceSession((POS2_SESSION)ConnectionInfoIn->Out.SessionUniqueID, NULL, (BOOLEAN)TRUE);
|
|
if ((Thread != NULL) && (Thread->Process->Session->ReferenceCount != 1))
|
|
{
|
|
// BUGBUG: free the process
|
|
}
|
|
} else
|
|
{
|
|
Status = NtCompleteConnectPort( Os2SessionCommPortHandle );
|
|
ASSERT( NT_SUCCESS( Status) );
|
|
}
|
|
}
|
|
Os2ReleaseStructureLock();
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
CheckOs2Port(POS2SESREQUESTMSG pReceiveMsg)
|
|
{
|
|
NTSTATUS Status;
|
|
SCCONNECTINFO ConnectionInfoOut;
|
|
ULONG ConnectionInfoOutLength, i;
|
|
UNICODE_STRING SessionPortName_U;
|
|
SECURITY_QUALITY_OF_SERVICE DynamicQos;
|
|
WCHAR SessionName_U[U_OS2_SES_BASE_PORT_NAME_LENGTH];
|
|
POS2_SES_GROUP_PARMS SesGrp;
|
|
HANDLE SectionHandle;
|
|
ULONG ViewSize;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
POS2_SESSION Session = (POS2_SESSION)(pReceiveMsg->Session);
|
|
HANDLE SessionPortHandle;
|
|
|
|
//
|
|
// Connect to the OS2SES port, then call it with
|
|
// the ommunication to be used during the session
|
|
// to call os2ses
|
|
//
|
|
|
|
ConnectionInfoOutLength = sizeof( ConnectionInfoOut );
|
|
|
|
CONSTRUCT_U_OS2_SES_NAME(SessionName_U, U_OS2_SES_BASE_PORT_PREFIX, (ULONG)(pReceiveMsg->Session));
|
|
RtlInitUnicodeString( &SessionPortName_U, SessionName_U );
|
|
|
|
DynamicQos.ImpersonationLevel = SecurityImpersonation;
|
|
DynamicQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
|
|
DynamicQos.EffectiveOnly = TRUE;
|
|
|
|
//
|
|
// get the session communication port handle. this handle will be used
|
|
// to send session requests to os2ses.exe for this session.
|
|
//
|
|
|
|
Status = NtConnectPort( &SessionPortHandle,
|
|
&SessionPortName_U,
|
|
&DynamicQos,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
(PVOID) &ConnectionInfoOut,
|
|
& ConnectionInfoOutLength
|
|
);
|
|
if (!NT_SUCCESS( Status ))
|
|
{
|
|
#if DBG
|
|
KdPrint(( "OS2SS: Unable to connect to OS2 - Status == %X\n",
|
|
Status
|
|
));
|
|
#endif
|
|
Os2DereferenceSession(Session, NULL, (BOOLEAN)TRUE);
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// A new session - save handles to process and thread
|
|
//
|
|
|
|
Session->ConsolePort = SessionPortHandle;
|
|
|
|
SessionPortName_U.Buffer[sizeof(U_OS2_SES_BASE_PORT_NAME) / 2] = U_OS2_SES_GROUP_PREFIX;
|
|
|
|
InitializeObjectAttributes( &ObjectAttributes,
|
|
&SessionPortName_U,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
|
|
Status = NtOpenSection ( &SectionHandle,
|
|
SECTION_MAP_WRITE,
|
|
&ObjectAttributes);
|
|
|
|
if ( !NT_SUCCESS( Status ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "OS2SRV: Os2CheckPort can't open SesGrp section - Status == %X\n",
|
|
Status));
|
|
#endif
|
|
Os2DereferenceSession(Session, NULL, (BOOLEAN)TRUE);
|
|
return(Status);
|
|
}
|
|
|
|
/*
|
|
* Let MM locate the view
|
|
*/
|
|
|
|
SesGrp = (POS2_SES_GROUP_PARMS)NULL;
|
|
ViewSize = 0L;
|
|
|
|
Status = NtMapViewOfSection( SectionHandle,
|
|
NtCurrentProcess(),
|
|
(PVOID *)&SesGrp,
|
|
0L,
|
|
0L,
|
|
NULL,
|
|
&ViewSize,
|
|
ViewUnmap,
|
|
0L,
|
|
PAGE_READWRITE);
|
|
|
|
if ( !NT_SUCCESS( Status ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "OS2SRV: Os2CheckPort can't map view of SesGrp section - Status == %X\n",
|
|
Status));
|
|
#endif
|
|
Os2DereferenceSession(Session, NULL, (BOOLEAN)TRUE);
|
|
NtClose (SectionHandle);
|
|
return(Status);
|
|
}
|
|
|
|
/*
|
|
* copy data to session
|
|
*/
|
|
|
|
for ( i = 0 ; i < sizeof(OS2_SES_GROUP_PARMS) ; i++ )
|
|
{
|
|
if (((PUCHAR)&ServerSesGrp)[i])
|
|
{
|
|
((PUCHAR)SesGrp)[i] = ((PUCHAR)&ServerSesGrp)[i];
|
|
}
|
|
}
|
|
|
|
Session->SesGrpAddress = (PVOID)SesGrp;
|
|
Session->SesGrpHandle = SectionHandle;
|
|
return(Status);
|
|
}
|
|
|
|
|
|
VOID
|
|
HandleOs2ConRequest(IN PVOID pApiReceiveMsg,
|
|
OUT PVOID *PReplyMsg
|
|
)
|
|
{
|
|
POS2SESREQUESTMSG pReceiveMsg = pApiReceiveMsg;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
*PReplyMsg = pApiReceiveMsg;
|
|
|
|
switch ( pReceiveMsg->Request)
|
|
{
|
|
case SesCheckPortAndConCreate:
|
|
//
|
|
// Connect to the OS2SES port, then call it with
|
|
// the ommunication to be used during the session
|
|
// to call os2ses
|
|
//
|
|
Status = CheckOs2Port(pReceiveMsg);
|
|
if ( !NT_SUCCESS( Status ) )
|
|
{
|
|
break;
|
|
}
|
|
|
|
case SesConCreate:
|
|
Status = Os2CreateConSession(
|
|
pReceiveMsg
|
|
);
|
|
break;
|
|
|
|
case SesConSignal:
|
|
Status = Os2CtrlSignalHandler(
|
|
pReceiveMsg,
|
|
NULL);
|
|
break;
|
|
|
|
case SesConFocus:
|
|
Status = Os2SessionFocusSet(
|
|
pReceiveMsg);
|
|
break;
|
|
|
|
default:
|
|
Status = 0;
|
|
#if DBG
|
|
KdPrint(( "OS2SS: Unknown Session request = %X\n",
|
|
pReceiveMsg->Request));
|
|
#endif
|
|
}
|
|
|
|
pReceiveMsg->Status = Status;
|
|
return;
|
|
}
|