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.
1091 lines
26 KiB
1091 lines
26 KiB
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
srvsm.c
|
|
|
|
Abstract:
|
|
|
|
Session API
|
|
|
|
Author:
|
|
|
|
Mark Lucovsky (markl) 10-Jul-1990
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#define INCL_OS2V20_SESSIONMGR
|
|
#define INCL_OS2V20_TASKING
|
|
#define INCL_OS2V20_ERRORS
|
|
#define INCL_OS2V20_EXCEPTIONS
|
|
#include "os2srv.h"
|
|
#define NTOS2_ONLY
|
|
#include "sesport.h"
|
|
#include "os2win.h"
|
|
|
|
|
|
extern ULONG Os2GlobalInfoSeg;
|
|
|
|
ULONG
|
|
WaitOnWinSessionObject(
|
|
IN ULONG Parm
|
|
);
|
|
|
|
VOID
|
|
StopSessionAndChildSessions(
|
|
IN POS2_SESSION Session
|
|
);
|
|
|
|
BOOLEAN
|
|
CheckSessionIfChild(
|
|
IN POS2_SESSION ParentSession,
|
|
IN POS2_SESSION ChildSession
|
|
);
|
|
|
|
BOOLEAN
|
|
Os2WaitNewSession(
|
|
IN OS2_WAIT_REASON WaitReason,
|
|
IN POS2_THREAD WaitingThread,
|
|
IN POS2_API_MSG WaitReplyMessage,
|
|
IN PVOID WaitParameter,
|
|
IN PVOID SatisfyParameter1,
|
|
IN PVOID SatisfyParameter2
|
|
);
|
|
|
|
VOID
|
|
Os2SessionWaitCheck(
|
|
POS2_SESSION Session,
|
|
ULONG RetCode
|
|
);
|
|
|
|
APIRET
|
|
Os2CheckIfSessionTreeInFG(
|
|
IN POS2_SESSION Session
|
|
);
|
|
|
|
#if DBG
|
|
VOID
|
|
DumpSessionEntry(
|
|
IN PSZ Str,
|
|
IN POS2_SESSION Session
|
|
);
|
|
|
|
VOID
|
|
DumpSessionTable(
|
|
IN PSZ Str
|
|
);
|
|
#endif
|
|
|
|
POS2_SESSION
|
|
Os2AllocateSession(
|
|
POS2_DOSSTARTSESSION_INFO SessionInfo OPTIONAL,
|
|
ULONG UniqueId,
|
|
PAPIRET ApiRet
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function allocates and initializes an OS/2 session control
|
|
block.
|
|
|
|
Arguments:
|
|
|
|
SessionInfo - Supplies the session information
|
|
|
|
ApiRet - If a session was not created, ApiRet returns the reason the
|
|
session creation failed.
|
|
|
|
Return Value:
|
|
|
|
NON-NULL - Returns the address of the referenced and allocated session.
|
|
NULL - No session was created
|
|
|
|
--*/
|
|
|
|
{
|
|
POS2_SESSION Session;
|
|
POS2_QUEUE TerminationQueue = NULL;
|
|
ULONG i;
|
|
|
|
*ApiRet = NO_ERROR;
|
|
|
|
if (UniqueId && (Session = Os2GetSessionByUniqueId(UniqueId)))
|
|
{
|
|
// This call is done by conthrds.c for session which was started
|
|
// by DosStartSession. Instead of allocating a new session, returns
|
|
// the session with the same UniqueId.
|
|
|
|
return(Session);
|
|
}
|
|
|
|
Session = RtlAllocateHeap( Os2Heap, 0, sizeof( OS2_SESSION ) );
|
|
if ( Session == NULL )
|
|
{
|
|
#if DBG
|
|
IF_OS2_DEBUG( SESSIONMGR )
|
|
KdPrint(("Os2AllocateSession: cannot allocate session\n"));
|
|
#endif
|
|
*ApiRet = ERROR_NOT_ENOUGH_MEMORY;
|
|
return NULL;
|
|
}
|
|
|
|
RtlZeroMemory(Session, sizeof( OS2_SESSION ));
|
|
Session->ReferenceCount = 1;
|
|
|
|
//
|
|
// Needs more work...
|
|
// session attributes, termination queue...
|
|
//
|
|
|
|
if ( ARGUMENT_PRESENT(SessionInfo) )
|
|
{
|
|
if ( SessionInfo->QueueHandleIndex )
|
|
{
|
|
SessionInfo->QueueHandleIndex &= 0x7fffffff;
|
|
TerminationQueue = Os2OpenQueueByHandle( (HQUEUE)SessionInfo->QueueHandleIndex );
|
|
|
|
if ( TerminationQueue )
|
|
{
|
|
Session->TerminationQueue = TerminationQueue;
|
|
Session->TerminationQueueHandle = SessionInfo->QueueHandleIndex;
|
|
} else
|
|
{
|
|
*ApiRet = ERROR_QUE_NAME_NOT_EXIST;
|
|
RtlFreeHeap( Os2Heap, 0, Session );
|
|
#if DBG
|
|
IF_OS2_DEBUG( SESSIONMGR )
|
|
KdPrint(("Os2AllocateSession: cannot open queue 0x%lx\n",
|
|
SessionInfo->QueueHandleIndex));
|
|
#endif
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
for ( i = 0 ; (i < OS2_MAX_SESSION) && SessionTable[i].Session ; i++ ) ;
|
|
|
|
if (i == OS2_MAX_SESSION)
|
|
{
|
|
*ApiRet = ERROR_TOO_MANY_SESS;
|
|
|
|
if ( TerminationQueue )
|
|
{
|
|
Os2CloseQueueByHandle(
|
|
(HQUEUE)Session->TerminationQueueHandle,
|
|
1,
|
|
(PID)(-1), // (-1) means ignore this parameter
|
|
Os2RootProcess);
|
|
}
|
|
|
|
#if DBG
|
|
IF_OS2_DEBUG( SESSIONMGR )
|
|
KdPrint(("Os2AllocateSession: too many session 0x%lx\n",
|
|
OS2_MAX_SESSION));
|
|
#endif
|
|
RtlFreeHeap( Os2Heap, 0, Session );
|
|
return NULL;
|
|
}
|
|
|
|
SessionTable[i].Session = Session;
|
|
Session->SessionId = i + 1;
|
|
Session->Selectable = TRUE;
|
|
//Session->ProcessId = 0;
|
|
//Session->BindSession = NULL;
|
|
//Session->RelatedSession = NULL;
|
|
//Session->InheritOpt = 0;
|
|
//Session->FgBg = 0;
|
|
//Session->ChildSession = FALSE;
|
|
//Session->ConsolePort = NULL;
|
|
//Session->Thread = NULL;
|
|
InitializeListHead(&(SessionTable[i].Waiters));
|
|
|
|
InsertHeadList( &Os2SessionList, &Session->SessionLink );
|
|
|
|
if ( ARGUMENT_PRESENT(SessionInfo) )
|
|
{
|
|
SessionInfo->ResultSessionId = Session->SessionId;
|
|
//Session->InheritOpt = SessionInfo->InheritOpt;
|
|
//Session->FgBg = SessionInfo->FgBg;
|
|
}
|
|
|
|
#if DBG
|
|
IF_OS2_DEBUG( SESSIONMGR )
|
|
{
|
|
DumpSessionEntry("Os2AllocateSession", Session);
|
|
DumpSessionTable("Os2AllocateSession");
|
|
}
|
|
#endif
|
|
|
|
return( Session );
|
|
}
|
|
|
|
|
|
VOID
|
|
Os2ReferenceSession(
|
|
POS2_SESSION Session
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called for each new process that does not create
|
|
a new session. Its function is to increment the sessions reference
|
|
count to account for the new process.
|
|
|
|
Arguments:
|
|
|
|
Session - Supplies the address of the session being referenced.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
APIRET Rc = NO_ERROR;
|
|
|
|
try
|
|
{
|
|
if (( Session->SessionId == 0 ) ||
|
|
( Session->SessionId > OS2_MAX_SESSION ) ||
|
|
( Session->ReferenceCount == 0 ) ||
|
|
( SessionTable[Session->SessionId - 1].Session != Session ))
|
|
{
|
|
ASSERT( FALSE );
|
|
Rc = ERROR_SMG_SESSION_NOT_FOUND;
|
|
}
|
|
} except ( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
Rc = ERROR_SMG_SESSION_NOT_FOUND;
|
|
}
|
|
|
|
if (Rc)
|
|
{
|
|
return ;
|
|
}
|
|
|
|
Session->ReferenceCount++;
|
|
|
|
#if DBG
|
|
IF_OS2_DEBUG( SESSIONMGR )
|
|
DumpSessionEntry("Os2ReferenceSession", Session);
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
POS2_SESSION
|
|
Os2DereferenceSession(
|
|
POS2_SESSION Session,
|
|
POS2_TERMINATEPROCESS_MSG msg,
|
|
BOOLEAN Bailout
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called for each process termination to release the
|
|
processes reference to the session. If this is the last process in
|
|
a session to terminate, the reference count will go to zero freeing
|
|
the session and sending a session termination status code.
|
|
|
|
Arguments:
|
|
|
|
Session - Supplies the address of the session being dereferenced.
|
|
|
|
msg - Exit message from Client
|
|
|
|
Bailout - Supplies a flag which if set inhibits reporting of
|
|
session termination.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
OS2_DOSWRITEQUEUE_MSG a;
|
|
ULONG i;
|
|
APIRET Rc = NO_ERROR;
|
|
ULONG SessionId;
|
|
|
|
if (Session == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
try
|
|
{
|
|
if (( Session->SessionId == 0 ) ||
|
|
( Session->SessionId > OS2_MAX_SESSION ) ||
|
|
( Session->ReferenceCount == 0 ) ||
|
|
( SessionTable[Session->SessionId - 1].Session != Session ))
|
|
{
|
|
ASSERT( FALSE );
|
|
Rc = ERROR_SMG_SESSION_NOT_FOUND;
|
|
}
|
|
} except ( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
Rc = ERROR_SMG_SESSION_NOT_FOUND;
|
|
}
|
|
|
|
if (Rc)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
#if DBG
|
|
IF_OS2_DEBUG( SESSIONMGR )
|
|
DumpSessionEntry("Os2DereferenceSession", Session);
|
|
#endif
|
|
|
|
if (--Session->ReferenceCount == 0)
|
|
{
|
|
|
|
#if DBG
|
|
IF_OS2_DEBUG( SESSIONMGR )
|
|
KdPrint(("Os2DereferenceSession - exit\n"));
|
|
#endif
|
|
|
|
SessionTable[Session->SessionId - 1].Session = NULL;
|
|
Session->ProcessId = 0;
|
|
SessionId = Session->SessionId;
|
|
Session->SessionId = 0;
|
|
Session->ReferenceCount = (ULONG)-1;
|
|
RemoveEntryList( &Session->SessionLink );
|
|
|
|
//if (Session->hWaitThread)
|
|
//{
|
|
//NtAlertThread(Session->hWaitThread);
|
|
//TerminateThread(Session->hWaitThread, 0L);
|
|
//WaitForSingleObject(Session->hWaitThread, (ULONG) SEM_INDEFINITE_WAIT);
|
|
//CloseHandle(Session->hWaitThread);
|
|
//Session->hWaitThread = NULL;
|
|
//}
|
|
|
|
if (( Session->RelatedSession ) && ( Session->RelatedSession->BindSession == Session ))
|
|
{
|
|
Session->RelatedSession->BindSession = NULL;
|
|
}
|
|
|
|
for ( i = 0 ; i < OS2_MAX_SESSION ; i++ )
|
|
{
|
|
if ( SessionTable[i].Session &&
|
|
( SessionTable[i].Session->RelatedSession == Session ))
|
|
{
|
|
SessionTable[i].Session->RelatedSession = NULL;
|
|
StopSessionAndChildSessions(SessionTable[i].Session);
|
|
}
|
|
}
|
|
|
|
//
|
|
// If it's a win32 session, terminate child sessions, by pid.
|
|
//
|
|
if (Session->WinSession)
|
|
{
|
|
for ( i = 0 ; i < OS2_MAX_SESSION ; i++ )
|
|
{
|
|
if ( SessionTable[i].Session &&
|
|
( SessionTable[i].Session->dwParentProcessId == Session->dwProcessId ))
|
|
{
|
|
StopSessionAndChildSessions(SessionTable[i].Session);
|
|
}
|
|
}
|
|
}
|
|
Session->dwProcessId = 0;
|
|
Session->dwParentProcessId = 0;
|
|
|
|
if ( Session->TerminationQueue )
|
|
{
|
|
|
|
if ( !Bailout )
|
|
{
|
|
|
|
//
|
|
// I guess I really have to allocate vm. This is
|
|
// dumb. I would propose using data/data length as
|
|
// sid, result code
|
|
//
|
|
|
|
a.QueueHandle = (HQUEUE)Session->TerminationQueueHandle;
|
|
a.SenderData = 0L;
|
|
a.DataLength = 0x80000000 | SessionId;
|
|
a.Data = (PVOID) msg->ExitResult;
|
|
a.ElementPriority = 0;
|
|
|
|
Os2WriteQueueByHandle(&a,Os2RootProcess->ProcessId);
|
|
}
|
|
|
|
Os2CloseQueueByHandle( (HQUEUE)Session->TerminationQueueHandle,
|
|
1,
|
|
(PID)(-1), // (-1) means ignore this parameter
|
|
Os2RootProcess
|
|
);
|
|
}
|
|
|
|
if (Session->SesGrpAddress)
|
|
{
|
|
NtUnmapViewOfSection( NtCurrentProcess(),
|
|
Session->SesGrpAddress);
|
|
}
|
|
|
|
if (Session->SesGrpHandle)
|
|
{
|
|
NtClose( Session->SesGrpHandle );
|
|
}
|
|
|
|
if ( Session->ConsolePort != NULL )
|
|
{
|
|
if ( msg != NULL )
|
|
{
|
|
Os2TerminateConSession(Session, msg);
|
|
}
|
|
NtClose(Session->ConsolePort);
|
|
}
|
|
|
|
if ( !IsListEmpty(&(SessionTable[Session->SessionId - 1].Waiters)) )
|
|
{
|
|
Os2NotifyWait(WaitSession, (PVOID)ERROR_SYS_INTERNAL, (PVOID)ERROR_SYS_INTERNAL);
|
|
}
|
|
|
|
if (Os2SrvExitNow)
|
|
{
|
|
for ( i = 0 ; (i < OS2_MAX_SESSION) && SessionTable[i].Session ; i++ ) ;
|
|
|
|
if ( i == OS2_MAX_SESSION )
|
|
{
|
|
Os2SrvExitProcess(0);
|
|
}
|
|
}
|
|
|
|
RtlFreeHeap( Os2Heap, 0, Session );
|
|
#if DBG
|
|
IF_OS2_DEBUG( SESSIONMGR )
|
|
DumpSessionTable("Os2DereferenceSession");
|
|
#endif // DBG
|
|
return NULL;
|
|
}
|
|
return Session;
|
|
}
|
|
|
|
|
|
POS2_SESSION
|
|
Os2GetSessionByUniqueId(
|
|
ULONG UniqueId
|
|
)
|
|
{
|
|
ULONG i;
|
|
|
|
for ( i = 0 ; ( i < OS2_MAX_SESSION ) ; i++ )
|
|
{
|
|
if ( SessionTable[i].Session == (POS2_SESSION)UniqueId )
|
|
{
|
|
return (SessionTable[i].Session);
|
|
}
|
|
}
|
|
|
|
return (NULL);
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
Os2DosStartSession(
|
|
IN POS2_THREAD t,
|
|
IN POS2_API_MSG m
|
|
)
|
|
{
|
|
POS2_DOSEXECPGM_MSG a = &m->u.DosStartSession.ExecPgmInformation;
|
|
POS2_DOSSTARTSESSION_INFO b = &m->u.DosStartSession.StartSessionInformation;
|
|
POS2_THREAD NewThread = NULL;
|
|
POS2_SESSION Session;
|
|
NTSTATUS Status;
|
|
APIRET RetCode;
|
|
ULONG Tid;
|
|
|
|
Session = Os2AllocateSession(b, 0, &RetCode);
|
|
|
|
if ( !Session )
|
|
{
|
|
#if DBG
|
|
IF_OS2_DEBUG( SESSIONMGR )
|
|
KdPrint(("Os2DosStartSession: can't allocate\n"));
|
|
#endif
|
|
m->ReturnedErrorValue = RetCode;
|
|
return( TRUE );
|
|
}
|
|
|
|
Session->ChildSession = TRUE;
|
|
Session->Thread = (PVOID)t;
|
|
Session->WinSession = b->WinSession;
|
|
|
|
m->ReturnedErrorValue = Os2CreateProcess(
|
|
NULL,
|
|
t,
|
|
a,
|
|
Session,
|
|
&NewThread
|
|
);
|
|
|
|
if ( m->ReturnedErrorValue == NO_ERROR )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "OS2SRV: Starting new session for 16-bit program - %s\n",
|
|
a->ApplName));
|
|
#endif // DBG
|
|
|
|
if (b->Related)
|
|
{
|
|
Session->RelatedSession = t->Process->Session;
|
|
t->Process->Session->BindSession = Session;
|
|
}
|
|
|
|
#if DBG
|
|
IF_OS2_DEBUG( SESSIONMGR )
|
|
DumpSessionEntry("Os2DosStartSession(after Os2CreateProcess)", Session);
|
|
#endif
|
|
|
|
if(Session->WinSession)
|
|
{
|
|
Session->hProcess = a->hProcess;
|
|
Session->dwProcessId = b->dwProcessId;
|
|
|
|
if((Session->hWaitThread = CreateThread(
|
|
NULL,
|
|
0,
|
|
WaitOnWinSessionObject,
|
|
(PVOID)Session,
|
|
0,
|
|
&Tid )) == NULL)
|
|
{
|
|
#if DBG
|
|
KdPrint(("OS2SRV: CreateThread for WinSession error %lu\n",
|
|
m->ReturnedErrorValue = GetLastError()));
|
|
ASSERT( FALSE );
|
|
#endif
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
if (!b->FgBg)
|
|
{
|
|
// ForeGround
|
|
|
|
OS2SESREQUESTMSG RequestMsg;
|
|
|
|
RequestMsg.Session = Session;
|
|
RequestMsg.d.FocusSet = 1;
|
|
Os2SessionFocusSet(&RequestMsg);
|
|
}
|
|
|
|
Status = NtResumeThread( NewThread->ThreadHandle, NULL );
|
|
ASSERT(NT_SUCCESS(Status));
|
|
return( TRUE );
|
|
} else
|
|
{
|
|
#if DBG
|
|
IF_OS2_DEBUG( SESSIONMGR )
|
|
KdPrint(("Os2DosStartSession: can't Os2CreateProcesst\n"));
|
|
#endif
|
|
//m->ReturnedErrorValue = ERROR_NOT_ENOUGH_MEMORY;
|
|
//Os2DeallocateThread( NewThread );
|
|
//Os2DeallocateProcess( NewThread->Process );
|
|
//NtClose(m->u.DosExecPgm.hThread);
|
|
//NtClose(m->u.DosExecPgm.hProcess);
|
|
|
|
Os2DereferenceSession(Session, 0, (BOOLEAN)TRUE);
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
|
|
ULONG
|
|
WaitOnWinSessionObject(
|
|
IN ULONG Parm
|
|
)
|
|
{
|
|
POS2_SESSION Session = (POS2_SESSION)Parm;
|
|
ULONG ExitCode = 0;
|
|
HANDLE hCurrThread = Session->hWaitThread;
|
|
OS2_TERMINATEPROCESS_MSG a;
|
|
NTSTATUS Status;
|
|
|
|
if (NtTestAlert() != STATUS_ALERTED)
|
|
{
|
|
Status = NtWaitForSingleObject( Session->hProcess, TRUE, NULL );
|
|
#if DBG
|
|
IF_OS2_DEBUG( SESSIONMGR )
|
|
KdPrint(("WaitOnWinSessionObject: Wait for Win32 process, status=0x%0X\n", Status));
|
|
#endif // DBG
|
|
if (Status != STATUS_ALERTED)
|
|
{
|
|
if (!GetExitCodeProcess(Session->hProcess, &ExitCode))
|
|
{
|
|
ExitCode = GetLastError();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TerminateProcess(Session->hProcess, 0);
|
|
}
|
|
}
|
|
|
|
CloseHandle(Session->hProcess);
|
|
|
|
if (Session->ReferenceCount)
|
|
{
|
|
Session->hWaitThread = NULL;
|
|
a.ExitResult = ExitCode;
|
|
a.ExitReason = 0;
|
|
a.ErrorText[0] = '\0';
|
|
Os2DereferenceSession(Session, &a, FALSE);
|
|
}
|
|
|
|
CloseHandle(hCurrThread);
|
|
ExitThread(0L);
|
|
return(0L);
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
Os2DosSelectSession(
|
|
IN POS2_THREAD t,
|
|
IN POS2_API_MSG m
|
|
)
|
|
{
|
|
ULONG SessionId = m->u.DosSelectSession.SessionId;
|
|
POS2_SESSION Session;
|
|
//NTSTATUS Status;
|
|
//SCREQUESTMSG Request;
|
|
BOOLEAN RetVal;
|
|
|
|
if ( SessionId == 0 )
|
|
{
|
|
Session = t->Process->Session;
|
|
} else
|
|
{
|
|
if (( SessionId > OS2_MAX_SESSION ) ||
|
|
(( Session = SessionTable[SessionId - 1].Session ) == NULL ) ||
|
|
( Session->RelatedSession != t->Process->Session ))
|
|
{
|
|
m->ReturnedErrorValue = ERROR_SMG_SESSION_NOT_PARENT;
|
|
return( TRUE );
|
|
}
|
|
}
|
|
|
|
if (m->ReturnedErrorValue = Os2CheckIfSessionTreeInFG(t->Process->Session))
|
|
{
|
|
return( TRUE );
|
|
}
|
|
|
|
m->ReturnedErrorValue = NO_ERROR;
|
|
|
|
if (!Session->WinSession)
|
|
{
|
|
if (Session->Win32ForegroundWindow != NULL) {
|
|
RetVal = OpenIcon(Session->Win32ForegroundWindow) &&
|
|
SetForegroundWindow(Session->Win32ForegroundWindow);
|
|
if (RetVal) {
|
|
// ForeGround
|
|
|
|
OS2SESREQUESTMSG RequestMsg;
|
|
|
|
RequestMsg.Session = Session;
|
|
RequestMsg.d.FocusSet = 1;
|
|
Os2SessionFocusSet(&RequestMsg);
|
|
}
|
|
}
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
Os2DosSetSession(
|
|
IN POS2_THREAD t,
|
|
IN POS2_API_MSG m
|
|
)
|
|
{
|
|
POS2_DOSSETSESSION_MSG a = &m->u.DosSetSession;
|
|
POS2_SESSION Session;
|
|
BOOLEAN Selectable;
|
|
|
|
if ( !a->SessionId ||
|
|
( a->SessionId > OS2_MAX_SESSION ) ||
|
|
(( Session = SessionTable[a->SessionId - 1].Session ) == NULL ) ||
|
|
( Session->RelatedSession != t->Process->Session ))
|
|
{
|
|
m->ReturnedErrorValue = ERROR_SMG_SESSION_NOT_PARENT;
|
|
return( TRUE );
|
|
}
|
|
|
|
if (m->ReturnedErrorValue = Os2CheckIfSessionTreeInFG(Session))
|
|
{
|
|
return( TRUE );
|
|
}
|
|
|
|
m->ReturnedErrorValue = NO_ERROR;
|
|
|
|
if (( a->StatusData.Length >= 4 ) &&
|
|
( a->StatusData.SelectInd != TARGET_UNCHANGED ))
|
|
{
|
|
Selectable = (BOOLEAN)((a->StatusData.SelectInd == TARGET_SELECTABLE ) ?
|
|
TRUE : FALSE);
|
|
if ( Selectable != Session->Selectable )
|
|
{
|
|
Session->Selectable = Selectable;
|
|
|
|
// BUGBUG - send request to OS2.EXE
|
|
}
|
|
}
|
|
|
|
if (( a->StatusData.Length >= 6 ) &&
|
|
( a->StatusData.BondInd != BOND_UNCHANGED ))
|
|
{
|
|
if ( a->StatusData.BondInd == BOND_CHILD )
|
|
{
|
|
if ( t->Process->Session->BindSession != Session )
|
|
{
|
|
// BUGBUG - send request to OS2.EXE
|
|
|
|
t->Process->Session->BindSession = Session;
|
|
}
|
|
} else
|
|
{
|
|
if ( t->Process->Session->BindSession == NULL )
|
|
{
|
|
m->ReturnedErrorValue = ERROR_SMG_NOT_BOUND;
|
|
} else
|
|
{
|
|
|
|
// BUGBUG - send request to OS2.EXE
|
|
|
|
t->Process->Session->BindSession = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
Os2DosStopSession(
|
|
IN POS2_THREAD t,
|
|
IN POS2_API_MSG m
|
|
)
|
|
{
|
|
POS2_DOSSTOPSESSION_MSG a = &m->u.DosStopSession;
|
|
POS2_SESSION Session = t->Process->Session;
|
|
ULONG i;
|
|
|
|
if ( a->fScope == DSS_SESSION )
|
|
{
|
|
if ( !a->SessionId ||
|
|
( a->SessionId > OS2_MAX_SESSION ) ||
|
|
(( Session = SessionTable[a->SessionId - 1].Session ) == NULL ) ||
|
|
( Session->RelatedSession != t->Process->Session ))
|
|
{
|
|
m->ReturnedErrorValue ==ERROR_SMG_INVALID_SESSION_ID;
|
|
//m->ReturnedErrorValue ==ERROR_SMG_SESSION_NOT_FOUND;
|
|
return( TRUE );
|
|
}
|
|
|
|
StopSessionAndChildSessions(Session);
|
|
m->ReturnedErrorValue = NO_ERROR;
|
|
} else
|
|
{
|
|
m->ReturnedErrorValue = ERROR_SMG_SESSION_NOT_FOUND;
|
|
|
|
for ( i = 0 ; i < OS2_MAX_SESSION ; i++ )
|
|
{
|
|
if (( SessionTable[i].Session != NULL ) &&
|
|
( SessionTable[i].Session->RelatedSession == Session ))
|
|
{
|
|
StopSessionAndChildSessions(SessionTable[i].Session);
|
|
m->ReturnedErrorValue = NO_ERROR;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
VOID
|
|
StopSessionAndChildSessions(
|
|
IN POS2_SESSION Session
|
|
)
|
|
{
|
|
ULONG i;
|
|
OS2SESREQUESTMSG RequestMsg;
|
|
HANDLE hThread;
|
|
|
|
/*
|
|
* stop all child sessions
|
|
*/
|
|
|
|
if (!Session->WinSession)
|
|
{
|
|
for ( i = 0 ; i < OS2_MAX_SESSION ; i++ )
|
|
{
|
|
if (( SessionTable[i].Session != NULL ) &&
|
|
( SessionTable[i].Session->RelatedSession == Session ))
|
|
{
|
|
StopSessionAndChildSessions(SessionTable[i].Session);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* stop current session
|
|
*/
|
|
|
|
if (Session->SesGrpAddress)
|
|
((POS2_SES_GROUP_PARMS)Session->SesGrpAddress)->InTermination |= 2;
|
|
RequestMsg.d.Signal.Type = XCPT_SIGNAL_KILLPROC;
|
|
RequestMsg.Session = Session;
|
|
|
|
Os2CtrlSignalHandler(&RequestMsg, NULL);
|
|
} else
|
|
{
|
|
//TerminateProcess(Session->hProcess, 0);
|
|
GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, Session->dwProcessId);
|
|
if (hThread = Session->hWaitThread)
|
|
{
|
|
|
|
#if DBG
|
|
DbgPrint("OS2SRV: ALERT !!! StopSessionAndChildSessions NtAlertThread(%x)\n",
|
|
hThread);
|
|
#endif
|
|
NtAlertThread(hThread);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
Os2DosSmSetTitle(
|
|
IN POS2_THREAD t,
|
|
IN POS2_API_MSG m
|
|
)
|
|
{
|
|
// POS2_SESSION Session;
|
|
// NTSTATUS Status;
|
|
// APIRET RetCode;
|
|
// ULONG UniqueId;
|
|
// HANDLE SessionPort;
|
|
// SCREQUESTMSG Request;
|
|
|
|
UNREFERENCED_PARAMETER(t);
|
|
|
|
m->ReturnedErrorValue = NO_ERROR;
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
Os2DosGetCtrlPortForSessionID(
|
|
IN POS2_THREAD t,
|
|
IN POS2_API_MSG m
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function finds and returns an OS/2 session according to the session
|
|
ID and duplicate the control port handle for the process.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
hControlPort field <= NULL - No session was found
|
|
NON-NULL - Returns the address of the required session
|
|
|
|
--*/
|
|
|
|
{
|
|
POS2_DOSGETCTRLPORTFORSESSION_MSG a = &m->u.DosGetCtrlPortForSession;
|
|
POS2_SESSION Session;
|
|
NTSTATUS Status;
|
|
|
|
#if DBG
|
|
IF_OS2_DEBUG( SESSIONMGR )
|
|
{
|
|
DumpSessionTable("Os2DosGetCtrlPortForSessionID");
|
|
}
|
|
#endif
|
|
|
|
Session = Os2GetSessionByUniqueId(a->SessionUniqueId);
|
|
|
|
if ( Session == NULL )
|
|
{
|
|
#if DBG
|
|
IF_OS2_DEBUG( SESSIONMGR )
|
|
{
|
|
KdPrint(("Os2DosGetCtrlPortForSessionID: not found 0x%lx\n",
|
|
a->SessionUniqueId));
|
|
}
|
|
#endif
|
|
a->hControlPort = NULL;
|
|
} else
|
|
{
|
|
#if DBG
|
|
IF_OS2_DEBUG( SESSIONMGR )
|
|
{
|
|
KdPrint(("Os2DosGetCtrlPortForSessionID: Session %lx for Id 0x%lx\n",
|
|
Session, a->SessionUniqueId));
|
|
}
|
|
#endif
|
|
Status = NtDuplicateObject( NtCurrentProcess(),
|
|
Session->ConsolePort,
|
|
t->Process->ProcessHandle,
|
|
&a->hControlPort,
|
|
0,
|
|
0,
|
|
DUPLICATE_SAME_ACCESS |
|
|
DUPLICATE_SAME_ATTRIBUTES
|
|
);
|
|
|
|
if( !NT_SUCCESS( Status ) )
|
|
{
|
|
ASSERT( FALSE );
|
|
a->hControlPort = NULL;
|
|
}
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
Os2SessionFocusSet(
|
|
IN OUT PVOID RequestMsg
|
|
)
|
|
{
|
|
POS2_SESSION Session = (POS2_SESSION) ((POS2SESREQUESTMSG)RequestMsg)->Session;
|
|
ULONG FocusSet = ((POS2SESREQUESTMSG)RequestMsg)->d.FocusSet;
|
|
GINFOSEG *pGlobalInfo = (GINFOSEG *) Os2GlobalInfoSeg;
|
|
|
|
#if DBG
|
|
IF_OS2_DEBUG( SESSIONMGR )
|
|
{
|
|
KdPrint(("Os2SessionFocusSet: Session %d (%p), state %x (%s), sgCurrent %d\n",
|
|
Session->SessionId, Session,
|
|
FocusSet, ((FocusSet) ? "Set" : "Reset"),
|
|
pGlobalInfo->sgCurrent));
|
|
}
|
|
#endif
|
|
|
|
if (FocusSet)
|
|
{
|
|
#if DBG
|
|
IF_OS2_DEBUG( SESSIONMGR )
|
|
{
|
|
KdPrint(("Os2SessionFocusSet: set focus\n"));
|
|
}
|
|
#endif
|
|
pGlobalInfo->sgCurrent = (UCHAR)Session->SessionId;
|
|
} else if (pGlobalInfo->sgCurrent == (UCHAR)Session->SessionId)
|
|
{
|
|
#if DBG
|
|
IF_OS2_DEBUG( SESSIONMGR )
|
|
{
|
|
KdPrint(("Os2SessionFocusSet: reset focus to none\n"));
|
|
}
|
|
#endif
|
|
pGlobalInfo->sgCurrent = 0;
|
|
} else
|
|
{
|
|
#if DBG
|
|
IF_OS2_DEBUG( SESSIONMGR )
|
|
{
|
|
KdPrint(("Os2SessionFocusSet: no reset focus\n"));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
return(0L);
|
|
}
|
|
|
|
|
|
APIRET
|
|
Os2CheckIfSessionTreeInFG(
|
|
IN POS2_SESSION Session
|
|
)
|
|
{
|
|
// BUGBUG - check if any of the descendant is currently in the foreground
|
|
|
|
POS2_SESSION NextSession;
|
|
ULONG SessionId = (ULONG)((GINFOSEG *) Os2GlobalInfoSeg)->sgCurrent;
|
|
|
|
if (( SessionId > OS2_MAX_SESSION ) || !SessionId ||
|
|
(( NextSession = SessionTable[SessionId - 1].Session ) == NULL ))
|
|
{
|
|
return( ERROR_SMG_SESSION_NOT_PARENT );
|
|
}
|
|
|
|
while (( NextSession != Session ) &&
|
|
( NextSession->RelatedSession ))
|
|
{
|
|
NextSession = NextSession->RelatedSession;
|
|
}
|
|
|
|
if ( NextSession == Session )
|
|
{
|
|
return( NO_ERROR );
|
|
}
|
|
return( ERROR_SMG_PROCESS_NOT_PARENT );
|
|
}
|
|
|
|
|
|
#if DBG
|
|
VOID
|
|
DumpSessionEntry(
|
|
IN PSZ Str,
|
|
IN POS2_SESSION Session
|
|
)
|
|
{
|
|
ULONG Id = Session->SessionId;
|
|
KdPrint(("\n*** %s SESSION ENTRY st 0x%lx (%lx) ***\n", Str, Session, Id));
|
|
KdPrint((" Id 0x%lx, RefCnt 0x%lx, Related 0x%lx, Port 0x%lx, PId 0x%lx\n",
|
|
Session->SessionId, Session->ReferenceCount, Session->RelatedSession ,
|
|
Session->ConsolePort, Session->ProcessId));
|
|
if (( Id && (Id <= OS2_MAX_SESSION ) && SessionTable[Id].Session ))
|
|
{
|
|
KdPrint((" SessionTable-Waiters 0x%lx\n", SessionTable[Id - 1].Waiters.Flink->Flink));
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
DumpSessionTable(
|
|
IN PSZ Str
|
|
)
|
|
{
|
|
ULONG i;
|
|
|
|
KdPrint(("\n*** %s SESSION TABLE st ***\n", Str));
|
|
KdPrint(("Ent Session Waiters\n"));
|
|
for ( i = 0 ; i < 8 ; i++ )
|
|
{
|
|
KdPrint(("%1.1lx. %8.8lx %8.8lx\n",
|
|
i + 1, SessionTable[i].Session,
|
|
(SessionTable[i].Session) ? SessionTable[i].Waiters.Flink->Flink : NULL));
|
|
}
|
|
KdPrint(("*** End Table ***\n"));
|
|
}
|
|
#endif
|