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.
1650 lines
46 KiB
1650 lines
46 KiB
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ntinitss.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the code to establish the connection between
|
|
the session console process and the OS2 Emulation Subsystem.
|
|
|
|
Author:
|
|
|
|
Avi Nathan (avin) 17-Jul-1991
|
|
|
|
Environment:
|
|
|
|
User Mode Only
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#define NTOS2_ONLY
|
|
#include "os2ses.h"
|
|
#include "os2tile.h"
|
|
#if PMNT
|
|
#define INCL_32BIT
|
|
#include "pmnt.h"
|
|
#endif
|
|
#include <winerror.h>
|
|
|
|
#define OD2_PORT_MEMORY_SIZE 0x10000
|
|
|
|
extern PVOID Od2PortHeap;
|
|
extern ULONG Od2PortMemoryRemoteDelta;
|
|
extern PSZ Od2PgmFilePath;
|
|
extern HANDLE Od2PortHandle;
|
|
|
|
#if PMNT
|
|
extern ULONG PMSubprocSem32;
|
|
extern BOOLEAN Ow2WriteBackCloseEvent();
|
|
extern APIRET DosSemClear(ULONG hsem);
|
|
#endif //PMNT
|
|
|
|
HANDLE
|
|
CreateEventW(
|
|
PVOID lpEventAttributes,
|
|
BOOL bManualReset,
|
|
BOOL bInitialState,
|
|
LPCWSTR lpName
|
|
);
|
|
|
|
ULONG
|
|
KbdInitAfterSesGrp(IN VOID);
|
|
|
|
APIRET
|
|
Od2WaitForSingleObject(
|
|
IN HANDLE Handle,
|
|
IN BOOLEAN Alertable,
|
|
IN PLARGE_INTEGER Timeout OPTIONAL
|
|
);
|
|
|
|
BOOLEAN
|
|
Od2InitCreateProcessMessage(
|
|
OUT PSCREQ_CREATE pCreate
|
|
);
|
|
|
|
VOID
|
|
Od2HandleCreateProcessRespond(
|
|
IN PSCREQ_CREATE pCreate
|
|
);
|
|
|
|
VOID
|
|
ExitThread(
|
|
ULONG dwExitCode
|
|
);
|
|
|
|
APIRET
|
|
OpenLVBsection(VOID);
|
|
|
|
DWORD
|
|
GetCurrentDirectoryW(
|
|
DWORD nBufferLength,
|
|
LPWSTR lpBuffer
|
|
);
|
|
|
|
BOOLEAN
|
|
InitializeSecurityDescriptor (
|
|
PSECURITY_DESCRIPTOR pSecurityDescriptor,
|
|
DWORD dwRevision
|
|
);
|
|
|
|
BOOLEAN
|
|
SetSecurityDescriptorDacl (
|
|
PSECURITY_DESCRIPTOR pSecurityDescriptor,
|
|
BOOLEAN bDaclPresent,
|
|
PACL pDacl,
|
|
BOOLEAN bDaclDefaulted
|
|
);
|
|
|
|
// Defined in <winbase.h> but we can't include it in this file
|
|
typedef struct _SECURITY_ATTRIBUTES {
|
|
DWORD nLength;
|
|
PVOID lpSecurityDescriptor;
|
|
BOOL bInheritHandle;
|
|
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
|
|
|
|
BOOLEAN Ow2ExitInProcess = (BOOLEAN)FALSE;
|
|
HANDLE hOs2Srv;
|
|
ULONG Ow2bNewSession = 0;
|
|
OEM_STRING Ow2CommandLineString;
|
|
|
|
HANDLE CtrlDataSemaphore;
|
|
HANDLE KbdDataSemaphore;
|
|
HANDLE FocusSemaphore;
|
|
HANDLE MouDataSemaphore;
|
|
HANDLE PopUpSemaphore;
|
|
HANDLE ScreenLockSemaphore;
|
|
HANDLE Od2StdHandleLockHandle;
|
|
HANDLE Od2VioWriteSemHandle;
|
|
|
|
BOOLEAN Od2ReceivedSignalAtInit = FALSE;
|
|
ULONG Od2InitSignalType;
|
|
|
|
BYTE NtInitssFail[] = "OS2SES(ntinitss) - error %X at %s\n";
|
|
|
|
/*
|
|
* This is the table of Secions to initialize.
|
|
*
|
|
* Section
|
|
* SectionSize - the size of the section (0 - no section, -1 - for LVB)
|
|
* DataNamePrefix - the prefix added to get section name
|
|
* SectionDataBaseAddress - where to put the base address of the section
|
|
* SectionDataHandle - where to put the handle of the section
|
|
*/
|
|
|
|
struct
|
|
{
|
|
ULONG SectionSize;
|
|
WCHAR DataNamePrefix;
|
|
PVOID *SectionDataBaseAddress;
|
|
HANDLE *SectionDataHandle;
|
|
} PORT_TABLE[] =
|
|
{
|
|
{
|
|
OS2SES_CTRL_SECTION_SIZE,
|
|
U_OS2_SES_BASE_DATA_PREFIX,
|
|
&Os2SessionCtrlDataBaseAddress,
|
|
&Os2SessionCtrlDataSectionHandle
|
|
},
|
|
{
|
|
OS2SES_GROUP_SECTION_SIZE,
|
|
U_OS2_SES_GROUP_PREFIX,
|
|
&Os2SessionDataBaseAddress,
|
|
&Os2SessionSesGrpDataSectionHandle
|
|
},
|
|
{
|
|
// Warning: MUST BE THE LAST ENTRY OF THE TABLE
|
|
|
|
(ULONG)(-1L),
|
|
U_OS2_SES_BASE_LVB_PREFIX,
|
|
&(PVOID)(LVBBuffer),
|
|
&LVBHandle
|
|
},
|
|
{
|
|
0, // End of Table
|
|
0,
|
|
NULL,
|
|
NULL
|
|
}
|
|
};
|
|
|
|
/*
|
|
* This is a table of semaphores to create (and close).
|
|
* All (but PauseEvent which is Event) are Semaphores.
|
|
*/
|
|
|
|
struct
|
|
{
|
|
WCHAR NamePrefix;
|
|
HANDLE * SemaphoreHandle;
|
|
} SEMAPHORE_TABLE [] =
|
|
{
|
|
{
|
|
U_OS2_SES_CTRL_PORT_SEMAPHORE_PREFIX,
|
|
&CtrlDataSemaphore,
|
|
},
|
|
{
|
|
U_OS2_SES_KBD_PORT_SEMAPHORE_PREFIX,
|
|
&KbdDataSemaphore,
|
|
},
|
|
{
|
|
U_OS2_SES_KBD_FOCUS_SEMAPHORE_PREFIX,
|
|
&FocusSemaphore,
|
|
},
|
|
{
|
|
U_OS2_SES_MOU_PORT_SEMAPHORE_PREFIX,
|
|
&MouDataSemaphore,
|
|
},
|
|
{
|
|
U_OS2_SES_POPUP_SEMAPHORE_PREFIX,
|
|
&PopUpSemaphore,
|
|
},
|
|
{
|
|
U_OS2_SES_SLOCK_SEMAPHORE_PREFIX,
|
|
&ScreenLockSemaphore,
|
|
},
|
|
{
|
|
U_OS2_SES_STD_HANDLE_LOCK_PREFIX,
|
|
&Od2StdHandleLockHandle,
|
|
},
|
|
{
|
|
U_OS2_SES_PAUSE_EVENT_PREFIX,
|
|
&PauseEvent,
|
|
},
|
|
{
|
|
U_OS2_SES_VIOWRITE_SEMAPHORE_PREFIX,
|
|
&Od2VioWriteSemHandle,
|
|
},
|
|
{
|
|
0,
|
|
NULL
|
|
}
|
|
};
|
|
|
|
#if DBG
|
|
PSZ SEMAPHORE_NAME_TABLE[] =
|
|
{
|
|
"CtrlDataSemaphore",
|
|
"KbdDataSemaphore",
|
|
"FocusSemaphore",
|
|
"MouDataSemaphore",
|
|
"PopUpSemaphore",
|
|
"ScreenLockSemaphore",
|
|
"PauseEvent",
|
|
"VioWriteSemaphore",
|
|
NULL
|
|
};
|
|
#endif
|
|
|
|
//
|
|
// A routine that wait for os2srv to connect
|
|
//
|
|
|
|
NTSTATUS
|
|
CtrlListen()
|
|
{
|
|
NTSTATUS Status;
|
|
PSCCONNECTINFO ConnectionInfo;
|
|
SCREQUESTMSG ConnectionRequest;
|
|
HANDLE CommPortHandle;
|
|
|
|
|
|
/*
|
|
* Listen to the os2ss connection and then too all
|
|
* processes created in this session.
|
|
*/
|
|
|
|
// Non-alertable, indefinite wait listen
|
|
Status = NtListenPort( Ow2hOs2sesPort,
|
|
(PPORT_MESSAGE) &ConnectionRequest);
|
|
if (!NT_SUCCESS( Status ))
|
|
{
|
|
KdPrint(( NtInitssFail, Status, "NtListenPort"));
|
|
return Status;
|
|
} else
|
|
{
|
|
|
|
// ??? Any reply
|
|
ConnectionInfo = &ConnectionRequest.ConnectionRequest;
|
|
ConnectionInfo->dummy = 0;
|
|
|
|
// BUGBUG!
|
|
// ServerView.Length = sizeof(ServerView);
|
|
// ServerView.SectionOffset = 0L;
|
|
// ServerView.ViewSize = 0L;
|
|
|
|
Status = NtAcceptConnectPort(
|
|
& CommPortHandle,
|
|
NULL,
|
|
(PPORT_MESSAGE) &ConnectionRequest,
|
|
(BOOLEAN)TRUE,
|
|
NULL, // &ServerView,
|
|
NULL);
|
|
|
|
if ( !NT_SUCCESS(Status) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( NtInitssFail, Status, "NtAcceptConnectPort"));
|
|
#endif
|
|
return Status;
|
|
} else
|
|
{
|
|
/*
|
|
* Record the view section address in a global variable.
|
|
*/
|
|
// BUGBUG! Os2SesConPortBaseAddress = ServerView.ViewBase;
|
|
Status = NtCompleteConnectPort( CommPortHandle );
|
|
ASSERT( NT_SUCCESS( Status) );
|
|
|
|
return Status;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
DWORD
|
|
SessionRequestThread(IN PVOID Parameter)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
UNREFERENCED_PARAMETER(Parameter);
|
|
|
|
try {
|
|
//
|
|
// Listen and accept session request port
|
|
//
|
|
|
|
Status = CtrlListen();
|
|
if ( !NT_SUCCESS( Status ))
|
|
{
|
|
#if DBG
|
|
KdPrint(( NtInitssFail, Status, "CtrlListen"));
|
|
ASSERT( FALSE );
|
|
#endif
|
|
Ow2Exit( 0, NULL, 1);
|
|
}
|
|
|
|
ServeSessionRequests();
|
|
}
|
|
//
|
|
// if Os2Debug is on, and ntsd is attached, it will get the second chance
|
|
//
|
|
#if DBG
|
|
except( (Os2Debug ? Ow2FaultFilter(EXCEPTION_CONTINUE_SEARCH, GetExceptionInformation()):
|
|
|
|
Ow2FaultFilter(EXCEPTION_EXECUTE_HANDLER, GetExceptionInformation())) ) {
|
|
#else
|
|
except( Ow2FaultFilter(EXCEPTION_EXECUTE_HANDLER, GetExceptionInformation()) ) {
|
|
#endif
|
|
|
|
#if DBG
|
|
KdPrint(("OS2SES: Internal error - Exception occured in EventServerThread\n"));
|
|
#endif
|
|
Ow2DisplayExceptionInfo();
|
|
ExitThread(1L);
|
|
}
|
|
ExitThread(0L);
|
|
return(0L);
|
|
}
|
|
|
|
CONST WCHAR OS2SSInitializationEvent[] = U_OS2_SS_INITIALIZATION_EVENT;
|
|
|
|
/*
|
|
* OS2 Session console - protocol with OS2SS
|
|
*
|
|
* Connect
|
|
* 1. OS2SES ----------> OS2SRV
|
|
*
|
|
*
|
|
* Accept
|
|
* 2. OS2SES <---------- OS2SRV
|
|
* session
|
|
*
|
|
*
|
|
* Create process
|
|
* (also checkport for root process)
|
|
* 3. OS2SES ----------> OS2SRV
|
|
* session
|
|
*
|
|
* / Connect
|
|
* | 4. OS2SES <---------- OS2SRV
|
|
* root only by |
|
|
* ServerRequest|
|
|
* | Accept
|
|
* | 5. OS2SES ----------> OS2SRV
|
|
* \
|
|
*
|
|
* Returns:
|
|
* 0L - problem with resources, like memory
|
|
* -1L - problem connecting to os2srv
|
|
* 01L - OK
|
|
*
|
|
*/
|
|
|
|
DWORD
|
|
InitOs2ssSessionPort()
|
|
{
|
|
NTSTATUS Status;
|
|
ULONG ConnectionInfoLen, i, j, ViewSize = 0L;
|
|
HANDLE SessionUniqueId;
|
|
OS2SESCONNECTINFO ConnectionInfo;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
LARGE_INTEGER SectionSize;
|
|
UNICODE_STRING Name_U;
|
|
HANDLE SectionHandle;
|
|
HANDLE hCurrentProcess;
|
|
HANDLE hOs2srvProcess = NULL;
|
|
PWSTR BasePrefix;
|
|
PVOID PhyKbd;
|
|
REMOTE_PORT_VIEW ServerView;
|
|
PORT_VIEW ClientView;
|
|
OS2SESREQUESTMSG RequestMsg, ReplyMsg;
|
|
WCHAR SessionName_U[U_OS2_SES_BASE_PORT_NAME_LENGTH];
|
|
SECURITY_QUALITY_OF_SERVICE DynamicQos;
|
|
ULONG Length;
|
|
#if DBG
|
|
BOOLEAN DebugOnStartup = FALSE;
|
|
#endif
|
|
HANDLE InitialEventHandle;
|
|
DWORD NonFirstClient;
|
|
DWORD WaitState;
|
|
SECURITY_ATTRIBUTES Sa;
|
|
CHAR localSecurityDescriptor[SECURITY_DESCRIPTOR_MIN_LENGTH];
|
|
|
|
//
|
|
// Create a section to contain the Port Memory. Port Memory is private
|
|
// memory that is shared between the OS/2 client and server processes.
|
|
// This allows data that is too large to fit into an API request message
|
|
// to be passed to the OS/2 server.
|
|
//
|
|
// Create the client section now, to pass is to the server on the
|
|
// connection request.
|
|
//
|
|
|
|
SectionSize.HighPart = 0L;
|
|
SectionSize.LowPart = OD2_PORT_MEMORY_SIZE;
|
|
Status = NtCreateSection( &SectionHandle,
|
|
SECTION_ALL_ACCESS,
|
|
NULL,
|
|
&SectionSize,
|
|
PAGE_READWRITE,
|
|
SEC_RESERVE,
|
|
NULL
|
|
);
|
|
if (!NT_SUCCESS( Status ))
|
|
{
|
|
#if DBG
|
|
KdPrint(( NtInitssFail, Status, "NtCreateSection"));
|
|
ASSERT( FALSE );
|
|
#endif
|
|
return( 0L );
|
|
}
|
|
|
|
/*
|
|
* connect to OS2SS and notify of the new session and the port associated
|
|
* with it.
|
|
*/
|
|
|
|
#if DBG
|
|
if ( fBrkOnStart )
|
|
{
|
|
ConnectionInfo.In.SessionDbg = TRUE;
|
|
} else
|
|
{
|
|
ConnectionInfo.In.SessionDbg = FALSE;
|
|
}
|
|
#else
|
|
ConnectionInfo.In.SessionDbg = FALSE;
|
|
#endif
|
|
ConnectionInfo.In.ExpectedVersion = OS2_SS_VERSION;
|
|
ConnectionInfo.In.Win32ForegroundWindow = Ow2ForegroundWindow;
|
|
ConnectionInfoLen = sizeof(ConnectionInfo);
|
|
|
|
RtlInitUnicodeString( &Name_U, U_OS2_SS_SESSION_PORT_NAME );
|
|
|
|
//
|
|
// Set up the security quality of service parameters to use over the
|
|
// port. Use the most efficient (least overhead) - which is dynamic
|
|
// rather than static tracking.
|
|
//
|
|
|
|
DynamicQos.ImpersonationLevel = SecurityImpersonation;
|
|
DynamicQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
|
|
DynamicQos.EffectiveOnly = TRUE;
|
|
|
|
ClientView.Length = sizeof( ClientView );
|
|
ClientView.SectionHandle = SectionHandle;
|
|
ClientView.SectionOffset = 0;
|
|
ClientView.ViewSize = OD2_PORT_MEMORY_SIZE;
|
|
ClientView.ViewBase = 0;
|
|
ClientView.ViewRemoteBase = 0;
|
|
|
|
ServerView.Length = sizeof( ServerView );
|
|
ServerView.ViewSize = 0;
|
|
ServerView.ViewBase = 0;
|
|
|
|
// Create security attribute record granting access to all
|
|
Sa.nLength = sizeof(Sa);
|
|
Sa.bInheritHandle = TRUE;
|
|
|
|
Status = RtlCreateSecurityDescriptor( (PSECURITY_DESCRIPTOR)
|
|
&localSecurityDescriptor,
|
|
SECURITY_DESCRIPTOR_REVISION );
|
|
if (!NT_SUCCESS( Status ))
|
|
{
|
|
#if DBG
|
|
KdPrint(("OS2SES: failed at RtlCreateSecurityDescriptor %x\n", Status));
|
|
ASSERT(FALSE);
|
|
#endif
|
|
return 0L;
|
|
}
|
|
|
|
Status = RtlSetDaclSecurityDescriptor( (PSECURITY_DESCRIPTOR)
|
|
&localSecurityDescriptor,
|
|
(BOOLEAN)TRUE,
|
|
(PACL) NULL,
|
|
(BOOLEAN)FALSE );
|
|
|
|
if (!NT_SUCCESS( Status ))
|
|
{
|
|
#if DBG
|
|
KdPrint(("OS2SES: failed at RtlSetDaclSecurityDescriptor %x\n", Status));
|
|
ASSERT(FALSE);
|
|
#endif
|
|
return 0L;
|
|
}
|
|
Sa.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR) &localSecurityDescriptor;
|
|
|
|
InitialEventHandle = CreateEventW(
|
|
&Sa,
|
|
TRUE, // Notification event
|
|
FALSE, // Nonsignaled
|
|
OS2SSInitializationEvent
|
|
);
|
|
if ((NonFirstClient = GetLastError()) || !InitialEventHandle) {
|
|
if (NonFirstClient != ERROR_ALREADY_EXISTS) {
|
|
#if DBG
|
|
KdPrint(("OS2SES: Cannot create initialization event, error %d\n", NonFirstClient));
|
|
#endif
|
|
return 0L;
|
|
}
|
|
}
|
|
|
|
if (!NonFirstClient) {
|
|
Status = (NTSTATUS) CreateOS2SRV(&hOs2srvProcess);
|
|
if (!NT_SUCCESS(Status) || !hOs2srvProcess) {
|
|
#if DBG
|
|
KdPrint(("OS2SES: Fail to start server process, status %x\n", Status));
|
|
#endif
|
|
return 0L;
|
|
}
|
|
NtClose(hOs2srvProcess);
|
|
}
|
|
|
|
//
|
|
// Wait for server. We want to see messages printed in debugger in the case that
|
|
// client waits too much (or may be it will wait forever).
|
|
//
|
|
|
|
while (TRUE) {
|
|
WaitState = WaitForSingleObject(
|
|
InitialEventHandle,
|
|
(DWORD) 4900L
|
|
);
|
|
if (WaitState == STATUS_TIMEOUT) {
|
|
#ifdef DBG
|
|
KdPrint(("OS2SES: Waiting for server\n"));
|
|
#endif
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (WaitState != WAIT_OBJECT_0) {
|
|
#if DBG
|
|
KdPrint(("OS2SES: Initialization event wasn't set by the server, wait_state %d\n", WaitState));
|
|
#endif
|
|
return (DWORD) -1L;
|
|
}
|
|
|
|
CloseHandle(InitialEventHandle);
|
|
|
|
Status = NtConnectPort(
|
|
&Ow2hOs2srvPort,
|
|
&Name_U,
|
|
&DynamicQos, // Security Quality
|
|
&ClientView,
|
|
&ServerView,
|
|
NULL, // MaxMessageLength,
|
|
(PVOID) &ConnectionInfo,
|
|
&ConnectionInfoLen
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
#if DBG
|
|
KdPrint(("OS2SES: Fail to connect to port, status %x\n", Status));
|
|
#endif
|
|
return (DWORD) -1L;
|
|
}
|
|
|
|
NtClose( SectionHandle );
|
|
|
|
//
|
|
// Now capture the fact if we were exec'd with the DEBUG command
|
|
//
|
|
#if DBG
|
|
if (ConnectionInfo.Out.Od2Debug)
|
|
{
|
|
Os2Debug |= ConnectionInfo.Out.Od2Debug;
|
|
DebugOnStartup = TRUE;
|
|
}
|
|
#endif
|
|
|
|
Od2PortMemoryRemoteDelta = (ULONG)ClientView.ViewRemoteBase -
|
|
(ULONG)ClientView.ViewBase;
|
|
|
|
#if DBG
|
|
IF_OD2_DEBUG( LPC )
|
|
{
|
|
KdPrint(( "OS2: ClientView: Base=%lX RemoteBase=%lX Delta: %lX Size=%lX\n",
|
|
(ULONG)ClientView.ViewBase, (ULONG)ClientView.ViewRemoteBase,
|
|
Od2PortMemoryRemoteDelta, (ULONG)ClientView.ViewSize
|
|
));
|
|
}
|
|
#endif
|
|
|
|
SessionUniqueId = (HANDLE)(ConnectionInfo.Out.SessionUniqueID);
|
|
Ow2bNewSession = ConnectionInfo.Out.IsNewSession;
|
|
|
|
Od2PortHeap = RtlCreateHeap( 0,
|
|
ClientView.ViewBase,
|
|
ClientView.ViewSize,
|
|
0,
|
|
0,
|
|
0
|
|
);
|
|
if (Od2PortHeap == NULL)
|
|
{
|
|
#if DBG
|
|
KdPrint(( NtInitssFail, Status, "RtlCreateHeap"));
|
|
ASSERT( FALSE );
|
|
#endif
|
|
return 0L;
|
|
}
|
|
|
|
hOs2Srv = OpenProcess(
|
|
PROCESS_DUP_HANDLE,
|
|
FALSE, // no inherit
|
|
(DWORD)(ConnectionInfo.Out.Os2SrvId));
|
|
if (!hOs2Srv){
|
|
#if DBG
|
|
KdPrint(( NtInitssFail, GetLastError(), "OpenProcess"));
|
|
#endif
|
|
return((DWORD)-1L);
|
|
}
|
|
|
|
#if DBG
|
|
if ( fVerbose )
|
|
{
|
|
KdPrint(("OS2SES: id =%d, Unique id=%d\n",
|
|
ConnectionInfo.Out.ProcessUniqueID, (ULONG)SessionUniqueId));
|
|
}
|
|
#endif
|
|
|
|
CONSTRUCT_U_OS2_SES_NAME(SessionName_U, U_OS2_SES_BASE_PORT_PREFIX, (ULONG)SessionUniqueId);
|
|
RtlInitUnicodeString( &Name_U, SessionName_U );
|
|
|
|
/*
|
|
* used later to fix to the data section/port name
|
|
*/
|
|
|
|
BasePrefix = &Name_U.Buffer[sizeof(U_OS2_SES_BASE_PORT_NAME) / 2];
|
|
|
|
#if DBG
|
|
IF_OD2_DEBUG( OS2_EXE )
|
|
{
|
|
PRTL_USER_PROCESS_PARAMETERS ProcessParameters =
|
|
(NtCurrentPeb())->ProcessParameters;
|
|
|
|
KdPrint(( "OS2SES(Win-Handles): hConsole %lx, StdIn %lx, StdOut %lx, StdErr %lx\n",
|
|
ProcessParameters->ConsoleHandle,
|
|
ProcessParameters->StandardInput,
|
|
ProcessParameters->StandardOutput,
|
|
ProcessParameters->StandardError ));
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Create 7 NT Semaphore and 1 Event that will be used to:
|
|
*
|
|
* 1. mutex use of CtrlDataSection
|
|
* 2. mutex use of KbdDataSection
|
|
* 3. focus the Kbd-handle
|
|
* 4. mutex enable PopUp
|
|
* 5. mutex screen lock
|
|
* 6. Pause event
|
|
* 7. mutex read Mouse Event
|
|
*/
|
|
|
|
for ( i = 0, j = 0 ; SEMAPHORE_TABLE[i].NamePrefix ;)
|
|
{
|
|
*BasePrefix = SEMAPHORE_TABLE[i].NamePrefix;
|
|
|
|
InitializeObjectAttributes( &ObjectAttributes,
|
|
&Name_U,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
|
|
if ( OS2SS_IS_SESSION( Ow2bNewSession ))
|
|
{
|
|
if (*BasePrefix == U_OS2_SES_PAUSE_EVENT_PREFIX)
|
|
{
|
|
Status = NtCreateEvent( SEMAPHORE_TABLE[i].SemaphoreHandle,
|
|
EVENT_ALL_ACCESS,
|
|
&ObjectAttributes,
|
|
1,
|
|
(BOOLEAN)1);
|
|
} else if ((*BasePrefix == U_OS2_SES_VIOWRITE_SEMAPHORE_PREFIX) ||
|
|
(*BasePrefix == U_OS2_SES_KBD_PORT_SEMAPHORE_PREFIX) ||
|
|
(*BasePrefix == U_OS2_SES_MOU_PORT_SEMAPHORE_PREFIX))
|
|
{
|
|
Status = NtCreateMutant( SEMAPHORE_TABLE[i].SemaphoreHandle,
|
|
MUTANT_ALL_ACCESS,
|
|
&ObjectAttributes,
|
|
FALSE); // not owned
|
|
} else
|
|
{
|
|
Status = NtCreateSemaphore( SEMAPHORE_TABLE[i].SemaphoreHandle,
|
|
SEMAPHORE_ALL_ACCESS,
|
|
&ObjectAttributes,
|
|
1,
|
|
1);
|
|
}
|
|
} else
|
|
{
|
|
if (*BasePrefix == U_OS2_SES_PAUSE_EVENT_PREFIX)
|
|
{
|
|
Status = NtOpenEvent( SEMAPHORE_TABLE[i].SemaphoreHandle,
|
|
EVENT_ALL_ACCESS,
|
|
&ObjectAttributes);
|
|
} else if ((*BasePrefix == U_OS2_SES_VIOWRITE_SEMAPHORE_PREFIX) ||
|
|
(*BasePrefix == U_OS2_SES_KBD_PORT_SEMAPHORE_PREFIX) ||
|
|
(*BasePrefix == U_OS2_SES_MOU_PORT_SEMAPHORE_PREFIX))
|
|
{
|
|
Status = NtOpenMutant( SEMAPHORE_TABLE[i].SemaphoreHandle,
|
|
MUTANT_ALL_ACCESS,
|
|
&ObjectAttributes);
|
|
} else
|
|
{
|
|
Status = NtOpenSemaphore( SEMAPHORE_TABLE[i].SemaphoreHandle,
|
|
SEMAPHORE_ALL_ACCESS,
|
|
&ObjectAttributes);
|
|
}
|
|
}
|
|
|
|
if ( ! NT_SUCCESS( Status ) )
|
|
{
|
|
if (i==0 && OS2SS_IS_SESSION( Ow2bNewSession ) &&
|
|
Status == STATUS_OBJECT_NAME_COLLISION )
|
|
{
|
|
//
|
|
// A previous sesssion with the same cookie is being cleaned up - wait
|
|
// 30 seconds (600 times 50 ms is 30 seconds)
|
|
//
|
|
j++;
|
|
if (j<600)
|
|
{
|
|
#if DBG
|
|
if (j == 1)
|
|
{
|
|
KdPrint(( "OS2SES(ntinitss) - waiting for previous os2 session cleanup\n"));
|
|
}
|
|
else {
|
|
KdPrint(( "."));
|
|
|
|
}
|
|
#endif
|
|
Sleep(50L);
|
|
continue;
|
|
}
|
|
|
|
}
|
|
#if DBG
|
|
KdPrint(( "OS2SES(ntinitss) - error %X at NtCreate/OpenSemaphore/Event #%u (%c-%s)\n",
|
|
Status, i, SEMAPHORE_TABLE[i].NamePrefix, SEMAPHORE_NAME_TABLE[i]));
|
|
ASSERT( FALSE );
|
|
#endif
|
|
return(0L);
|
|
}
|
|
//
|
|
// increment i only if the create/open above was successful
|
|
//
|
|
i++;
|
|
}
|
|
|
|
/*
|
|
* Map the the whole section to virtual address.
|
|
* Let MM locate the view.
|
|
*
|
|
* The Vio case is different, since it has to be mapped
|
|
* into app space below 512M
|
|
*/
|
|
|
|
Os2SessionCtrlDataBaseAddress = 0L;
|
|
Os2SessionDataBaseAddress = 0L;
|
|
LVBBuffer = (PUCHAR)(VIOSECTION_BASE);
|
|
|
|
for ( i = 0 ; PORT_TABLE[i].SectionSize ; i++ )
|
|
{
|
|
|
|
/*
|
|
* create 3 sections to be shared by all client processes runing in this
|
|
* session: Ctrl, SesGrp & LVB.
|
|
*/
|
|
|
|
//
|
|
// Only for LVB the section size is unknon until OS2 is started.
|
|
// For the LVB< there is -1 at the SectionSize field in the table
|
|
//
|
|
|
|
if ( PORT_TABLE[i].SectionSize != -1L )
|
|
{
|
|
SectionSize.LowPart = PORT_TABLE[i].SectionSize;
|
|
} else
|
|
{
|
|
//
|
|
// This is the time to continue initiliziation: SesGrp
|
|
// is available.
|
|
//
|
|
|
|
SesGrp = (POS2_SES_GROUP_PARMS)Os2SessionDataBaseAddress;
|
|
PortMessageHeaderSize = sizeof(PORT_MESSAGE);
|
|
|
|
if (OS2SS_IS_PROCESS( Ow2bNewSession ))
|
|
{
|
|
if ((PhyKbd = StartEventHandler()) == NULL)
|
|
{
|
|
return(0);
|
|
}
|
|
} else
|
|
{
|
|
RtlZeroMemory(SesGrp, sizeof(OS2_SES_GROUP_PARMS));
|
|
if ((PhyKbd = StartEventHandlerForSession()) == NULL)
|
|
{
|
|
return(0);
|
|
}
|
|
SesGrp->PhyKbd = PhyKbd;
|
|
}
|
|
SectionSize.LowPart = SesGrp->MaxLVBsize; // LVB Buffer
|
|
}
|
|
|
|
ViewSize = 0L;
|
|
|
|
/*
|
|
* Get a private ID for the session data.
|
|
*/
|
|
|
|
*BasePrefix = PORT_TABLE[i].DataNamePrefix;
|
|
|
|
/*
|
|
* create a 64k section.
|
|
* BUGBUG! - cruiser apis allow io of more then 64k
|
|
*/
|
|
|
|
if (OS2SS_IS_SESSION( Ow2bNewSession ))
|
|
{
|
|
SECURITY_DESCRIPTOR SecurityDescriptor;
|
|
|
|
Status = RtlCreateSecurityDescriptor( &SecurityDescriptor,
|
|
SECURITY_DESCRIPTOR_REVISION );
|
|
if (!NT_SUCCESS(Status)) {
|
|
#if DBG
|
|
KdPrint(( NtInitssFail, Status, "RtlCreateSecurityDescriptor"));
|
|
ASSERT( FALSE );
|
|
#endif
|
|
return(0L);
|
|
}
|
|
|
|
Status = RtlSetDaclSecurityDescriptor( &SecurityDescriptor,
|
|
TRUE,
|
|
NULL,
|
|
FALSE );
|
|
if (!NT_SUCCESS(Status)) {
|
|
#if DBG
|
|
KdPrint(( NtInitssFail, Status, "RtlSetDaclSecurityDescriptor"));
|
|
ASSERT(FALSE);
|
|
#endif
|
|
return(0L);
|
|
}
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&Name_U,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
&SecurityDescriptor);
|
|
|
|
Status = NtCreateSection ( &SectionHandle,
|
|
/* BUGBUG! SECTION_ALL_ACCESS, */ SECTION_MAP_WRITE,
|
|
&ObjectAttributes,
|
|
&SectionSize,
|
|
PAGE_READWRITE,
|
|
SEC_COMMIT,
|
|
NULL);
|
|
} else
|
|
{
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&Name_U,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
|
|
Status = NtOpenSection ( &SectionHandle,
|
|
SECTION_MAP_WRITE,
|
|
&ObjectAttributes);
|
|
|
|
}
|
|
|
|
if ( !NT_SUCCESS( Status ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( NtInitssFail, Status, "NtCreate/OpenSection"));
|
|
ASSERT( FALSE );
|
|
#endif
|
|
return(0L);
|
|
}
|
|
|
|
//
|
|
// Map the the whole section to virtual address.
|
|
//
|
|
|
|
Status = NtMapViewOfSection( SectionHandle,
|
|
NtCurrentProcess(),
|
|
PORT_TABLE[i].SectionDataBaseAddress,
|
|
0L,
|
|
0L,
|
|
NULL,
|
|
&ViewSize,
|
|
ViewUnmap,
|
|
0L,
|
|
PAGE_READWRITE);
|
|
|
|
if ( !NT_SUCCESS( Status ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( NtInitssFail, Status, "NtMapViewOfSection"));
|
|
ASSERT( FALSE );
|
|
#endif
|
|
return(0L);
|
|
}
|
|
|
|
*(PORT_TABLE[i].SectionDataHandle) = SectionHandle;
|
|
}
|
|
|
|
OpenLVBsection();
|
|
|
|
Ow2hOs2sesPort = NULL;
|
|
|
|
//
|
|
// Connect to the OS/2 Emulation Subsystem server. Also pass information
|
|
// the OS/2 server needs in the connection information structure.
|
|
//
|
|
|
|
/*
|
|
* Set Header info
|
|
*/
|
|
|
|
PORT_MSG_DATA_LENGTH(RequestMsg) = sizeof(RequestMsg) - sizeof(PORT_MESSAGE);
|
|
PORT_MSG_TOTAL_LENGTH(RequestMsg) = sizeof(RequestMsg); // BUGBUG! too much
|
|
PORT_MSG_ZERO_INIT(RequestMsg) = 0L;
|
|
|
|
RequestMsg.PortType = 1;
|
|
RequestMsg.Request = SesConCreate;
|
|
RequestMsg.d.Create.d.In.IsNewSession = Ow2bNewSession;
|
|
|
|
if ( !Od2InitCreateProcessMessage(&RequestMsg.d.Create) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( NtInitssFail, Status, "Od2InitCreateProcessMessage"));
|
|
#endif
|
|
return(0L);
|
|
}
|
|
|
|
/*
|
|
* for all request pass the session handle
|
|
*/
|
|
|
|
RequestMsg.Session = SessionUniqueId;
|
|
|
|
strncpy(&RequestMsg.d.Create.d.In.ApplName[0],
|
|
Od2PgmFilePath,
|
|
OS2_MAX_APPL_NAME
|
|
);
|
|
RequestMsg.d.Create.d.In.ApplName[OS2_MAX_APPL_NAME - 1] = '\0';
|
|
|
|
// server doesn't need the LPC, except for
|
|
// the root process in the session, so we'll create port only for it.
|
|
|
|
if (OS2SS_IS_SESSION( Ow2bNewSession ))
|
|
{
|
|
CHAR sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
|
|
PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR)&sd;
|
|
|
|
*BasePrefix = U_OS2_SES_BASE_PORT_PREFIX;
|
|
|
|
/*
|
|
* create (session) LPC port to be connected to all client processes
|
|
* runing in this session for Kbd, Mou, Mon, Tm and Prt.
|
|
*/
|
|
|
|
InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION);
|
|
SetSecurityDescriptorDacl(psd, TRUE, NULL, FALSE); // NULL DACL means access free to all
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&Name_U,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
psd);
|
|
|
|
Status = NtCreatePort( &Ow2hOs2sesPort,
|
|
&ObjectAttributes,
|
|
sizeof( SCCONNECTINFO ),
|
|
U_OS2_SES_BASE_PORT_PREFIX,
|
|
32 * U_OS2_SES_BASE_PORT_PREFIX);
|
|
|
|
if ( ! NT_SUCCESS( Status ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( NtInitssFail, Status, "NtCreatePort"));
|
|
ASSERT( FALSE );
|
|
#endif
|
|
return(0L);
|
|
}
|
|
|
|
//
|
|
// create 2 threads: one to read input from console
|
|
// and second to server requsets thru LPC
|
|
//
|
|
|
|
if (timing)
|
|
{
|
|
printf("Os2 time before CreateServerThreads is %d\n", (GetTickCount()) - timing);
|
|
}
|
|
if (CreateServerThreads())
|
|
{
|
|
#if DBG
|
|
KdPrint(( NtInitssFail, GetLastError(), "CreateServerThread"));
|
|
ASSERT( FALSE );
|
|
#endif
|
|
return(0L);
|
|
}
|
|
|
|
/*
|
|
* Set request info
|
|
*/
|
|
|
|
RequestMsg.Request = SesCheckPortAndConCreate;
|
|
|
|
//
|
|
// duplicate handles for os2srv,
|
|
//
|
|
|
|
if (timing)
|
|
{
|
|
printf("Os2 time before DuplicateHandle is %d\n", (GetTickCount()) - timing);
|
|
}
|
|
hCurrentProcess = GetCurrentProcess();
|
|
//
|
|
// duplicate process and thread handles for os2srv
|
|
//
|
|
|
|
if (OS2SS_IS_NEW_SESSION( Ow2bNewSession ))
|
|
{
|
|
/*
|
|
* a new session, which isn't a child session
|
|
*/
|
|
|
|
if (!DuplicateHandle(
|
|
hCurrentProcess,
|
|
hCurrentProcess,
|
|
hOs2Srv,
|
|
&RequestMsg.d.Create.d.In.hProcess,
|
|
0,
|
|
FALSE,
|
|
DUPLICATE_SAME_ACCESS
|
|
))
|
|
{
|
|
#if DBG
|
|
KdPrint(( NtInitssFail, GetLastError(), "DuplicateHandle(Process)"));
|
|
#endif
|
|
}
|
|
if (!DuplicateHandle(
|
|
hCurrentProcess,
|
|
GetCurrentThread(),
|
|
hOs2Srv,
|
|
&RequestMsg.d.Create.d.In.hThread,
|
|
0,
|
|
FALSE,
|
|
DUPLICATE_SAME_ACCESS
|
|
))
|
|
{
|
|
#if DBG
|
|
KdPrint(( NtInitssFail, GetLastError(), "DuplicateHandle(Thread)"));
|
|
#endif
|
|
}
|
|
}
|
|
//
|
|
// Duplicate the event thread handle, so os2srv can debug it
|
|
//
|
|
if (!DuplicateHandle(
|
|
hCurrentProcess,
|
|
EventServerThreadHandle,
|
|
hOs2Srv,
|
|
&RequestMsg.d.Create.d.In.hEventThread,
|
|
0,
|
|
FALSE,
|
|
DUPLICATE_SAME_ACCESS
|
|
))
|
|
{
|
|
#if DBG
|
|
KdPrint(( NtInitssFail, GetLastError(), "DuplicateHandle(EventServerThread)"));
|
|
#endif
|
|
}
|
|
//
|
|
// Duplicate the session request thread handle, so os2srv can debug it
|
|
//
|
|
if (!DuplicateHandle(
|
|
hCurrentProcess,
|
|
Ow2hSessionRequestThread,
|
|
hOs2Srv,
|
|
&RequestMsg.d.Create.d.In.hSessionRequestThread,
|
|
0,
|
|
FALSE,
|
|
DUPLICATE_SAME_ACCESS
|
|
))
|
|
{
|
|
#if DBG
|
|
KdPrint(( NtInitssFail, GetLastError(), "DuplicateHandle(SessionRequestTread)"));
|
|
#endif
|
|
}
|
|
}
|
|
|
|
Status = NtRequestWaitReplyPort( Ow2hOs2srvPort,
|
|
(PPORT_MESSAGE) &RequestMsg,
|
|
(PPORT_MESSAGE) &ReplyMsg);
|
|
|
|
if ( !NT_SUCCESS( Status ))
|
|
{
|
|
#if DBG
|
|
KdPrint(( NtInitssFail, Status, "NtRequestWaitReplyPort"));
|
|
ASSERT( FALSE );
|
|
#endif
|
|
return((DWORD)-1L );
|
|
}
|
|
|
|
if (!NT_SUCCESS(ReplyMsg.Status)){
|
|
//
|
|
// Could not initiate with os2srv - exit
|
|
//
|
|
#if DBG
|
|
KdPrint(( NtInitssFail, ReplyMsg.Status, "Os2ConCreate"));
|
|
#endif
|
|
return( (DWORD)-1L );
|
|
}
|
|
|
|
//
|
|
// Now capture the fact if we were exec'd with the DEBUG command
|
|
//
|
|
#if DBG
|
|
if (DebugOnStartup)
|
|
{
|
|
DbgBreakPoint();
|
|
}
|
|
#endif
|
|
|
|
Od2HandleCreateProcessRespond(&ReplyMsg.d.Create);
|
|
|
|
Ow2hSession = SessionUniqueId;
|
|
|
|
if (OS2SS_IS_SESSION( Ow2bNewSession ))
|
|
{
|
|
/*
|
|
* Complete all initializations that are depend on SesGrp from os2srv
|
|
*/
|
|
|
|
if (timing)
|
|
{
|
|
printf("Os2 time before KbdInitAfterSesGrp is %d\n", (GetTickCount()) - timing);
|
|
}
|
|
if( KbdInitAfterSesGrp() )
|
|
{
|
|
#if DBG
|
|
KdPrint(( NtInitssFail, GetLastError(), "KbdInitAfterSesGrp"));
|
|
ASSERT( FALSE );
|
|
#endif
|
|
return( 0L );
|
|
}
|
|
|
|
/*
|
|
* Complete NLS initialization
|
|
*/
|
|
|
|
if (timing)
|
|
{
|
|
printf("Os2 time before NlsInit is %d\n", (GetTickCount()) - timing);
|
|
}
|
|
if( NLSInit() )
|
|
{
|
|
#if DBG
|
|
KdPrint(( NtInitssFail, GetLastError(), "NlsInit"));
|
|
ASSERT( FALSE );
|
|
#endif
|
|
return( 0L );
|
|
}
|
|
|
|
//
|
|
// resume remaining threads
|
|
//
|
|
|
|
if (timing)
|
|
{
|
|
printf("Os2 time before ResumeServerThreads is %d\n", (GetTickCount()) - timing);
|
|
}
|
|
if (ResumeServerThreads())
|
|
{
|
|
#if DBG
|
|
KdPrint(( NtInitssFail, GetLastError(), "ReleaseServerThreads"));
|
|
ASSERT( FALSE );
|
|
#endif
|
|
return( 0L );
|
|
}
|
|
}
|
|
|
|
Length = SesGrp->LVBsize;
|
|
Ow2VioGetLVBBuf(&Length);
|
|
|
|
/*
|
|
* Don't put parameters into SesGrp before this point
|
|
* (since it's clear by the server when coping the NLS definitions).
|
|
*/
|
|
|
|
return ( 1L );
|
|
}
|
|
|
|
|
|
VOID TerminateSession(VOID)
|
|
{
|
|
//NTSTATUS Status;
|
|
|
|
Ow2ExitInProcess = (BOOLEAN)TRUE;
|
|
if (timing)
|
|
{
|
|
printf("Os2 main->Exit time is %d\n", (GetTickCount()) - timing);
|
|
}
|
|
|
|
/*
|
|
* remove event handler so we don't try to send a message
|
|
* for a dying session.
|
|
*/
|
|
|
|
SetEventHandlers( FALSE );
|
|
|
|
if (OS2SS_IS_SESSION( Ow2bNewSession ))
|
|
{
|
|
RestoreWin32ParmsBeforeTermination();
|
|
}
|
|
|
|
// Close the named objects: port, section
|
|
|
|
NtClose(Ow2hOs2srvPort);
|
|
NtClose(Os2SessionCtrlDataSectionHandle);
|
|
NtClose(Os2SessionSesGrpDataSectionHandle);
|
|
NtClose(Ow2hOs2sesPort);
|
|
NtClose(hOs2Srv);
|
|
// Jul-2-1995 YosefD:
|
|
// Od2PortHandle is the same value as Ow2hOs2srvPort. This handle is already closed. An
|
|
// attemt to close it once more is a bug. On build 1096 this cause exception and
|
|
// process termination. The return value of the terminated process isn't right in this
|
|
// case.
|
|
//NtClose(Od2PortHandle);
|
|
|
|
/* =>? what about the following handles:
|
|
|
|
HANDLE hConsoleInput;
|
|
HANDLE hConsoleOutput;
|
|
HANDLE hConsoleStdIn; if diff from hConsoleInput
|
|
HANDLE hConsoleStdOut; if diff from hConsoleOutput
|
|
HANDLE hConsoleStdErr;
|
|
HANDLE hPopUpOutput; if not NULL
|
|
HANDLE LVBHandle;
|
|
HANDLE PauseEvent;
|
|
HANDLE CtrlDataSemaphore;
|
|
HANDLE KbdDataSemaphore;
|
|
HANDLE FocusSemaphore;
|
|
HANDLE MouDataSemaphore;
|
|
HANDLE PopUpSemaphore;
|
|
HANDLE ScreenLockSemaphore;
|
|
HANDLE EventServerThreadHandle;
|
|
HANDLE Ow2hSessionRequestThread;
|
|
|
|
*/
|
|
// notify OS2SS
|
|
|
|
// Cleanup TaskMan stuff
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
SendSignalToOs2Srv(
|
|
IN int SignalType
|
|
)
|
|
{
|
|
OS2SESREQUESTMSG RequestMsg;
|
|
OS2SESREQUESTMSG ReplyMsg;
|
|
NTSTATUS Status;
|
|
|
|
#if DBG
|
|
IF_OD2_DEBUG2( OS2_EXE, SIG )
|
|
{
|
|
KdPrint(("OS2SES(SendSignalToOs2Srv): Signal %u\n", SignalType));
|
|
}
|
|
#endif
|
|
/*
|
|
* Set Header info
|
|
*/
|
|
PORT_MSG_DATA_LENGTH(RequestMsg) = sizeof(RequestMsg) - sizeof(PORT_MESSAGE);
|
|
PORT_MSG_TOTAL_LENGTH(RequestMsg) = sizeof(RequestMsg); // BUGBUG! too much
|
|
PORT_MSG_ZERO_INIT(RequestMsg) = 0L;
|
|
RequestMsg.PortType = 1;
|
|
|
|
RequestMsg.Request = SesConSignal;
|
|
RequestMsg.Session = Ow2hSession;
|
|
RequestMsg.d.Signal.Type = SignalType;
|
|
|
|
Status = NtRequestWaitReplyPort( Ow2hOs2srvPort,
|
|
(PPORT_MESSAGE) &RequestMsg,
|
|
(PPORT_MESSAGE) &ReplyMsg);
|
|
|
|
if ( !NT_SUCCESS( Status ))
|
|
{
|
|
#if DBG
|
|
KdPrint(( "OS2SES: Unable to send signal - Status == %X\n",
|
|
Status));
|
|
#endif
|
|
|
|
TerminateSession();
|
|
Ow2Exit(0, NULL, 15);
|
|
}
|
|
|
|
ASSERT ( PORT_MSG_TYPE(ReplyMsg) == LPC_REPLY );
|
|
|
|
if ( Ow2ExitInProcess )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
EventHandlerRoutine (IN ULONG CtrlType)
|
|
{
|
|
int SignalType;
|
|
BOOL Rc;
|
|
ULONG i=0;
|
|
|
|
//
|
|
// If Ow2hSession is null - os2srv is not ready yet to kill,
|
|
// wait so we don't loose the signal
|
|
//
|
|
|
|
if (!Od2SignalEnabled)
|
|
{
|
|
#if DBG
|
|
IF_OD2_DEBUG2( OS2_EXE, SIG )
|
|
{
|
|
KdPrint(("OS2SES(EventHandlerRoutine): Ctr-Type %u before loading completed, handle later\n", CtrlType));
|
|
}
|
|
#endif
|
|
Od2ReceivedSignalAtInit = TRUE;
|
|
Od2InitSignalType = CtrlType;
|
|
return(TRUE);
|
|
}
|
|
|
|
#if DBG
|
|
IF_OD2_DEBUG2( OS2_EXE, SIG )
|
|
{
|
|
KdPrint(("OS2SES(EventHandlerRoutine): Ctr-Type %u\n", CtrlType));
|
|
}
|
|
#endif
|
|
|
|
switch (CtrlType) {
|
|
case CTRL_C_EVENT:
|
|
if ((SesGrp->ModeFlag & 1 ) || // ^C in binary mode
|
|
SesGrp->WinProcessNumberInSession ) // There is a child Win process
|
|
{
|
|
return (TRUE);
|
|
}
|
|
SignalType = XCPT_SIGNAL_INTR;
|
|
break;
|
|
case CTRL_BREAK_EVENT:
|
|
if (SesGrp->WinProcessNumberInSession ) // There is a child Win process
|
|
{
|
|
return (TRUE);
|
|
}
|
|
SignalType = XCPT_SIGNAL_BREAK;
|
|
break;
|
|
case CTRL_CLOSE_EVENT:
|
|
SignalType = XCPT_SIGNAL_KILLPROC;
|
|
#if PMNT
|
|
CloseApp:
|
|
//
|
|
// PM apps handling
|
|
//
|
|
if (ProcessIsPMProcess())
|
|
{
|
|
// Regular app (i.e. not PMShell)
|
|
if (!ProcessIsPMShell())
|
|
{
|
|
if (Ow2WriteBackCloseEvent())
|
|
{
|
|
Sleep(7900L);
|
|
if (Ow2ExitInProcess)
|
|
return(FALSE);
|
|
else
|
|
return(TRUE);
|
|
}
|
|
else
|
|
{
|
|
// We failed to write-back a close event:
|
|
// must be DosExecPgm proc; Pass event through semaphore
|
|
DosSemClear(PMSubprocSem32);
|
|
Sleep(7900L);
|
|
if (Ow2ExitInProcess)
|
|
return(FALSE);
|
|
else
|
|
return(TRUE);
|
|
}
|
|
return(TRUE);
|
|
}
|
|
else // PMSHELL
|
|
{
|
|
if (Ow2WriteBackCloseEvent())
|
|
{
|
|
return(TRUE);
|
|
}
|
|
}
|
|
}
|
|
#endif // PMNT
|
|
break;
|
|
case CTRL_LOGOFF_EVENT:
|
|
if (fService) // Are we running as a service ?
|
|
{
|
|
#if DBG
|
|
DbgPrint("OS2: service - ignoring CTRL_LOGOFF_EVENT !\n");
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
SignalType = XCPT_SIGNAL_KILLPROC;
|
|
#if PMNT
|
|
// Jump to CloseApp only for PM apps !
|
|
if (ProcessIsPMProcess())
|
|
goto CloseApp;
|
|
#endif // PMNT
|
|
break;
|
|
case CTRL_SHUTDOWN_EVENT:
|
|
SignalType = XCPT_SIGNAL_KILLPROC;
|
|
#if PMNT
|
|
// Jump to CloseApp only for PM apps !
|
|
if (ProcessIsPMProcess())
|
|
goto CloseApp;
|
|
#endif // PMNT
|
|
break;
|
|
default:
|
|
#if DBG
|
|
IF_OD2_DEBUG2( OS2_EXE, SIG )
|
|
{
|
|
KdPrint(("OS2SES(EventHandlerRoutine): Unknown CtrlType %lu\n", CtrlType));
|
|
}
|
|
#endif
|
|
SignalType = CtrlType;
|
|
break;
|
|
}
|
|
//if (OS2SS_IS_SESSION( Ow2bNewSession )){
|
|
if (SesGrp->InTermination == 0){
|
|
|
|
//
|
|
// The root process of a session handles singals with os2srv
|
|
// always. child processes in the session only need to send
|
|
// the signal if they where in initialization when a CtrlC/CtrlBrk
|
|
// happened (server ignore signal in this case)
|
|
//
|
|
|
|
Rc = SendSignalToOs2Srv(SignalType);
|
|
} else{
|
|
Rc = TRUE;
|
|
}
|
|
|
|
if (Rc && ((CtrlType == CTRL_CLOSE_EVENT) ||
|
|
(CtrlType == CTRL_LOGOFF_EVENT) ||
|
|
(CtrlType == CTRL_SHUTDOWN_EVENT)))
|
|
{
|
|
//
|
|
// Cmd wait 10 sec before it popup a time-out fail message
|
|
// We are waiting 5 sec to give the application (client)
|
|
// time to clean-up before we return TRUE.
|
|
|
|
Sleep(5000);
|
|
if ( Ow2ExitInProcess )
|
|
{
|
|
Rc = FALSE;
|
|
}
|
|
} else if (Rc && SesGrp->InTermination && Od2SignalEnabled) {
|
|
Rc = SendSignalToOs2Srv(SignalType);
|
|
}
|
|
|
|
return (Rc);
|
|
}
|
|
|
|
|
|
ULONG
|
|
Ow2GetProcessIdFromLPCMessage(
|
|
IN PVOID LPCMessage
|
|
)
|
|
{
|
|
return((ULONG) ((PPORT_MESSAGE)LPCMessage)->ClientId.UniqueProcess);
|
|
}
|
|
|
|
|
|
DWORD
|
|
Ow2CommandLineWToCommandLineA(
|
|
IN LPWSTR CommandLineW,
|
|
OUT PSZ *CommandLineA
|
|
)
|
|
{
|
|
UNICODE_STRING CommandLine_U;
|
|
UNICODE_STRING CommandLineUpcase;
|
|
UNICODE_STRING CurrentDir_U;
|
|
UNICODE_STRING CurrentDirUpcase;
|
|
WCHAR CurrentDirectory[MAX_PATH];
|
|
WCHAR *pWchar;
|
|
NTSTATUS Status;
|
|
|
|
RtlInitUnicodeString(
|
|
&CommandLine_U,
|
|
CommandLineW
|
|
);
|
|
|
|
if (GetCurrentDirectoryW((DWORD)MAX_PATH, CurrentDirectory))
|
|
{
|
|
RtlInitUnicodeString(
|
|
&CurrentDir_U,
|
|
CurrentDirectory
|
|
);
|
|
|
|
//
|
|
// Prepare the structures for upcase strings and then upcase.
|
|
//
|
|
if (NULL == (CommandLineUpcase.Buffer =
|
|
RtlAllocateHeap(RtlProcessHeap(), 0, CommandLine_U.MaximumLength))) {
|
|
KdPrint(( NtInitssFail, 0, "RtlAllocateHeap(CommandLine)"));
|
|
return ((DWORD)-1L);
|
|
}
|
|
if (NULL == (CurrentDirUpcase.Buffer =
|
|
RtlAllocateHeap(RtlProcessHeap(), 0, CurrentDir_U.MaximumLength))) {
|
|
KdPrint(( NtInitssFail, 0, "RtlAllocateHeap(CurrentDir)"));
|
|
RtlFreeHeap(RtlProcessHeap(), 0, CommandLineUpcase.Buffer);
|
|
return ((DWORD)-1L);
|
|
}
|
|
|
|
CurrentDirUpcase.Length = CurrentDir_U.Length;
|
|
CurrentDirUpcase.MaximumLength = CurrentDir_U.MaximumLength;
|
|
Status = RtlUpcaseUnicodeString(&CurrentDirUpcase, &CurrentDir_U, FALSE);
|
|
if (!NT_SUCCESS(Status)) {
|
|
KdPrint(( NtInitssFail, 0, "RtlUpcaseUnicodeString(CurrentDirUpcase)"));
|
|
RtlFreeHeap(RtlProcessHeap(), 0, CommandLineUpcase.Buffer);
|
|
RtlFreeHeap(RtlProcessHeap(), 0, CurrentDirUpcase.Buffer);
|
|
return ((DWORD)-1L);
|
|
}
|
|
|
|
CommandLineUpcase.Length = CommandLine_U.Length;
|
|
CommandLineUpcase.MaximumLength = CommandLine_U.MaximumLength;
|
|
Status = RtlUpcaseUnicodeString(&CommandLineUpcase, &CommandLine_U, FALSE);
|
|
if (!NT_SUCCESS(Status)) {
|
|
KdPrint(( NtInitssFail, 0, "RtlUpcaseUnicodeString(CommandLineUpcase)"));
|
|
RtlFreeHeap(RtlProcessHeap(), 0, CommandLineUpcase.Buffer);
|
|
RtlFreeHeap(RtlProcessHeap(), 0, CurrentDirUpcase.Buffer);
|
|
return ((DWORD)-1L);
|
|
}
|
|
|
|
//
|
|
// Initialize pWchar and append NULL to the end of the upcased strings
|
|
// for the search of wsstr().
|
|
//
|
|
pWchar = CommandLineUpcase.Buffer;
|
|
CurrentDirUpcase.Buffer[CurrentDirUpcase.Length / 2] = (WCHAR)NULL;
|
|
CommandLineUpcase.Buffer[CommandLineUpcase.Length / 2] = (WCHAR)NULL;
|
|
|
|
//
|
|
// Replace every prefix of the current directory in the command
|
|
// line with what GetCurrentDirectoryW() returned. This resolves
|
|
// problems caused by apps transfering the command line in
|
|
// apper/lower case.
|
|
//
|
|
while ((pWchar < &CommandLineUpcase.Buffer[CommandLineUpcase.Length / 2]) &&
|
|
(pWchar = wcsstr(pWchar, CurrentDirUpcase.Buffer))) {
|
|
wcsncpy(&CommandLine_U.Buffer[pWchar - CommandLineUpcase.Buffer],
|
|
CurrentDirectory,
|
|
CurrentDirUpcase.Length / 2);
|
|
pWchar += CurrentDirUpcase.Length / 2;
|
|
}
|
|
|
|
//
|
|
// Free the allocated buffers.
|
|
//
|
|
RtlFreeHeap(RtlProcessHeap(), 0, CommandLineUpcase.Buffer);
|
|
RtlFreeHeap(RtlProcessHeap(), 0, CurrentDirUpcase.Buffer);
|
|
}
|
|
|
|
Status = RtlUnicodeStringToOemString(
|
|
&Ow2CommandLineString,
|
|
&CommandLine_U,
|
|
TRUE
|
|
);
|
|
if (!NT_SUCCESS( Status ))
|
|
{
|
|
KdPrint(( NtInitssFail, Status, "CommandLine-UnicodeToOemString"));
|
|
return ((DWORD)-1L);
|
|
}
|
|
|
|
*CommandLineA = Ow2CommandLineString.Buffer;
|
|
|
|
return(0L);
|
|
}
|
|
#if PMNT
|
|
|
|
|
|
// Returns true if process is the root process of a session
|
|
// otherwise returns false
|
|
// This procedure was written to enable 16 Bit dll init routine (PMWIN)
|
|
// to check if the it is executed from the root process of a session.
|
|
APIRET PMNTIsSessionRoot()
|
|
{
|
|
|
|
if ( OS2SS_IS_SESSION( Ow2bNewSession ))
|
|
return(TRUE);
|
|
else
|
|
return(FALSE);
|
|
}
|
|
|
|
#endif // PMNT
|