347 lines
17 KiB
C++
347 lines
17 KiB
C++
/*======================================================================================//
|
|
| //
|
|
|Copyright (c) 1998, 1999 Sequent Computer Systems, Incorporated. All rights reserved. //
|
|
| //
|
|
|Description: //
|
|
| //
|
|
|---------------------------------------------------------------------------------------//
|
|
| This file implements the CProcCon class methods defined in ProcConSvc.h //
|
|
|---------------------------------------------------------------------------------------//
|
|
| //
|
|
|Created: //
|
|
| //
|
|
| Jarl McDonald 07-98 //
|
|
| //
|
|
|Revision History: //
|
|
| //
|
|
|=======================================================================================*/
|
|
#include "ProcConSvc.h"
|
|
|
|
// CProcCon Constructor
|
|
// Note: this function runs as part of service start so keep it quick!
|
|
CProcCon::CProcCon( void ) : m_ready( FALSE ), m_shutEvent( NULL ), m_versionInfo( NULL ),
|
|
m_endEvent ( NULL ),
|
|
m_shutDown( FALSE )
|
|
{
|
|
memset( &m_context, 0, sizeof(m_context) );
|
|
|
|
m_hThread[USER_SERVER] = m_hThread[PROC_SERVER] = NULL;
|
|
SYSTEM_INFO si;
|
|
GetSystemInfo( &si );
|
|
m_NumberOfProcessors = si.dwNumberOfProcessors;
|
|
m_PageSize = si.dwPageSize;
|
|
|
|
m_versionInfo = new CVersion( GetModuleHandle( NULL ) );
|
|
|
|
PCBuildAdminSecAttr( m_secAttr );
|
|
|
|
m_context.cDB = new CProcConDB( m_PageSize );
|
|
|
|
if ( !m_context.cDB || !m_context.cDB->ReadyToRun() ||
|
|
!m_versionInfo || !m_secAttr.lpSecurityDescriptor ) {
|
|
PCLogMessage( PC_STARTUP_FAILED, EVENTLOG_ERROR_TYPE, 1, PROCCON_SVC_DISP_NAME );
|
|
return;
|
|
}
|
|
|
|
m_shutEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
|
|
m_endEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
|
|
m_context.mgrDoneEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
|
|
m_context.userDoneEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
|
|
m_context.mediatorEvent = CreateEvent( &m_secAttr, FALSE, FALSE, PC_MEDIATOR_EVENT );
|
|
if ( !m_shutEvent || !m_endEvent || !m_context.mgrDoneEvent || !m_context.userDoneEvent || !m_context.mediatorEvent ) {
|
|
PCLogUnExError( m_context.mediatorEvent? TEXT("PCEvent") : PC_MEDIATOR_EVENT, TEXT("CreateEvent") );
|
|
return;
|
|
}
|
|
|
|
// Allocate shared memory for mediator view of jobs...
|
|
m_context.mediatorTableHandle = CreateFileMapping( HANDLE_FF_64, &m_secAttr, PAGE_READWRITE,
|
|
0, sizeof(PCMediateHdr), PC_MEDIATOR_FILEMAP );
|
|
if ( !m_context.mediatorTableHandle ) {
|
|
PCLogUnExError( PC_MEDIATOR_FILEMAP, TEXT("CreateMediatorMapping") );
|
|
return;
|
|
}
|
|
m_context.mediatorTable = (PCMediateHdr *) MapViewOfFile( m_context.mediatorTableHandle,
|
|
FILE_MAP_WRITE, 0, 0, 0 );
|
|
if ( !m_context.mediatorTable ) {
|
|
CloseHandle( m_context.mediatorTableHandle );
|
|
m_context.mediatorTableHandle = NULL;
|
|
PCLogUnExError( PC_MEDIATOR_FILEMAP, TEXT("MapMediatorJobData") );
|
|
return;
|
|
}
|
|
|
|
m_context.mediatorTable->svcEventHandle = m_context.mediatorEvent;
|
|
m_context.mediatorTable->svcPID = GetCurrentProcessId();
|
|
|
|
// If mediator is not running, init shared memory, set up completion port, and start mediator...
|
|
if ( !PCTestIsRunning( PC_MEDIATOR_EXCLUSION ) ) {
|
|
memset( &m_context.mediatorTable->groupBlock, 0, sizeof(m_context.mediatorTable->groupBlock) );
|
|
m_context.mediatorTable->lastCompKey = 0;
|
|
m_context.completionPort = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, NULL, 0 );
|
|
if ( !m_context.completionPort )
|
|
PCLogUnExError( TEXT("PCInit"), TEXT("CreateIoCompletionPort") );
|
|
|
|
m_context.mediatorTable->svcPortHandle = m_context.completionPort;
|
|
|
|
StartMediator();
|
|
}
|
|
// If mediator is already running...
|
|
// recover our completion port by duplicating the handle...
|
|
else {
|
|
// Open mediator process so we can duplicate handles...
|
|
m_context.mediatorTable->medProcessInfo.hProcess =
|
|
OpenProcess( PROCESS_DUP_HANDLE, FALSE, m_context.mediatorTable->medProcessInfo.dwProcessId );
|
|
// Recover our completion port by duplicating the handle...
|
|
if ( !DuplicateHandle( m_context.mediatorTable->medProcessInfo.hProcess,
|
|
m_context.mediatorTable->medPortHandle,
|
|
GetCurrentProcess(),
|
|
&m_context.mediatorTable->svcPortHandle,
|
|
NULL,
|
|
FALSE,
|
|
DUPLICATE_SAME_ACCESS ) )
|
|
PCLogUnExError( TEXT("PCInit"), TEXT("DupMediatorPortHandle") );
|
|
m_context.completionPort = m_context.mediatorTable->svcPortHandle;
|
|
// Map all job table blocks by duplicating the handles...
|
|
m_context.mediatorTable->SvcChainBlocks();
|
|
}
|
|
|
|
CloseHandle( m_context.mediatorTable->medProcessInfo.hProcess );
|
|
|
|
m_context.cPC = this;
|
|
LaunchProcServer();
|
|
LaunchUserServer();
|
|
|
|
if (!ReadyToRun() )
|
|
HardStop();
|
|
}
|
|
|
|
// CProcCon Destructor
|
|
CProcCon::~CProcCon( void )
|
|
{
|
|
if ( m_context.cUser ) {
|
|
WaitForSingleObject( m_context.userDoneEvent, 5000 );
|
|
delete m_context.cUser;
|
|
m_context.cUser = NULL;
|
|
}
|
|
if ( m_context.cMgr ) {
|
|
WaitForSingleObject( m_context.mgrDoneEvent, 5000 );
|
|
delete m_context.cMgr;
|
|
m_context.cMgr = NULL;
|
|
}
|
|
if ( m_context.cDB ) {
|
|
delete m_context.cDB;
|
|
m_context.cDB = NULL;
|
|
}
|
|
if ( m_shutEvent ) {
|
|
CloseHandle( m_shutEvent );
|
|
m_shutEvent = NULL;
|
|
}
|
|
if ( m_endEvent ) {
|
|
CloseHandle( m_endEvent );
|
|
m_endEvent = NULL;
|
|
}
|
|
if ( m_versionInfo ) {
|
|
delete m_versionInfo;
|
|
m_versionInfo = NULL;
|
|
}
|
|
|
|
CloseHandle( m_context.mgrDoneEvent );
|
|
CloseHandle( m_context.userDoneEvent );
|
|
CloseHandle( m_context.mediatorEvent );
|
|
CloseHandle( m_context.mediatorTableHandle );
|
|
|
|
PCFreeSecAttr( m_secAttr );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------//
|
|
// Function to determine if all CProcCon initial conditions have been met //
|
|
// Input: None //
|
|
// Returns: TRUE if ready, FALSE if not //
|
|
//--------------------------------------------------------------------------------------------//
|
|
BOOL CProcCon::ReadyToRun( void )
|
|
{
|
|
return m_context.cDB &&
|
|
m_hThread[PROC_SERVER] &&
|
|
m_hThread[USER_SERVER] &&
|
|
m_secAttr.lpSecurityDescriptor;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------//
|
|
// Function to start the ProcCon Mediator Process //
|
|
// Input: None //
|
|
// Returns: NT or ProcCon Error code //
|
|
//--------------------------------------------------------------------------------------------//
|
|
PCULONG32 CProcCon::StartMediator( void )
|
|
{
|
|
// Don't start if already running...
|
|
if ( PCTestIsRunning( PC_MEDIATOR_EXCLUSION ) )
|
|
return PCERROR_MEDIATOR_ALREADY_RUNNING;
|
|
|
|
// Get our module name then replace base name with mediator base name...
|
|
// (Thus mediator exe must be in the same location as the service exe).
|
|
TCHAR path[MAX_PATH];
|
|
if ( !GetModuleFileName( NULL, path, MAX_PATH ) ) {
|
|
PCLogUnExError( TEXT("PCMediator"), TEXT("GetMediatorPath") );
|
|
path[0] = 0;
|
|
}
|
|
for ( int i = _tcslen( path ); i; --i ) {
|
|
if ( path[i] == TEXT('\\') ) { path[i + 1] = 0; break; }
|
|
}
|
|
_tcscat( path, PC_MEDIATOR_BASE_NAME );
|
|
|
|
// Start mediator process -- don't quit if this fails...
|
|
STARTUPINFO strtInfo;
|
|
memset( &strtInfo, 0, sizeof(strtInfo) );
|
|
strtInfo.cb = sizeof(strtInfo);
|
|
if ( !CreateProcess( path, NULL, &m_secAttr, &m_secAttr, FALSE,
|
|
CREATE_NEW_PROCESS_GROUP + CREATE_NO_WINDOW,
|
|
NULL, NULL, &strtInfo, &m_context.mediatorTable->medProcessInfo ) ) {
|
|
DWORD rc = GetLastError();
|
|
PCLogUnExError( TEXT("PCMediator"), TEXT("CreateMediator") );
|
|
return rc;
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------//
|
|
// Function to stop (kill) the ProcCon Mediator Process //
|
|
// Input: None //
|
|
// Returns: NT or ProcCon Error code //
|
|
//--------------------------------------------------------------------------------------------//
|
|
PCULONG32 CProcCon::StopMediator ( void )
|
|
{
|
|
DWORD rc = ERROR_SUCCESS;
|
|
HANDLE hProc = OpenProcess( PROCESS_TERMINATE, FALSE, m_context.mediatorTable->medProcessInfo.dwProcessId );
|
|
|
|
m_context.mediatorTable->medProcessInfo.hProcess = hProc;
|
|
|
|
if ( !hProc ) {
|
|
rc = GetLastError();
|
|
if (rc == ERROR_INVALID_PARAMETER) rc = PCERROR_MEDIATOR_NOT_RUNNING;
|
|
}
|
|
else if ( !TerminateProcess( m_context.mediatorTable->medProcessInfo.hProcess, PCERROR_KILLED_BY_REQUEST ) )
|
|
rc = GetLastError();
|
|
|
|
if ( hProc )
|
|
CloseHandle( hProc );
|
|
|
|
return rc;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------//
|
|
// Function to return system information //
|
|
// Input: Buffer for information, locations for size and count (always 1) //
|
|
// Returns: TRUE if shutdown requested, FALSE if not //
|
|
//--------------------------------------------------------------------------------------------//
|
|
void CProcCon::GetPCSystemInfo( PCSystemInfo *data, PCINT16 *itemLen, PCINT16 *itemCount )
|
|
{
|
|
*itemLen = sizeof(PCSystemInfo);
|
|
*itemCount = 1;
|
|
memset( data, 0, *itemLen );
|
|
|
|
_tcsncpy( data->fileVersion, m_versionInfo->GetFileVersion(), VERSION_STRING_LEN );
|
|
_tcsncpy( data->productVersion, m_versionInfo->GetProductVersion(), VERSION_STRING_LEN );
|
|
_tcsncpy( data->fileFlags, m_versionInfo->GetFileFlags(), VERSION_STRING_LEN );
|
|
|
|
_tcsncpy( data->medFileVersion, m_context.mediatorTable->medFileVersion, VERSION_STRING_LEN );
|
|
_tcsncpy( data->medProductVersion, m_context.mediatorTable->medProductVersion, VERSION_STRING_LEN );
|
|
_tcsncpy( data->medFileFlags, m_context.mediatorTable->medFileFlags, VERSION_STRING_LEN );
|
|
|
|
data->fixedSignature = m_versionInfo->GetFixedSignature();
|
|
data->fixedFileVersionMS = m_versionInfo->GetFixedFileVersionMS();
|
|
data->fixedFileVersionLS = m_versionInfo->GetFixedFileVersionLS();
|
|
data->fixedProductVersionMS = m_versionInfo->GetFixedProductVersionMS();
|
|
data->fixedProductVersionLS = m_versionInfo->GetFixedProductVersionLS();
|
|
data->fixedFileFlags = m_versionInfo->GetFixedFileFlags();
|
|
data->fixedFileOS = m_versionInfo->GetFixedFileOS();
|
|
data->fixedFileType = m_versionInfo->GetFixedFileType();
|
|
data->fixedFileSubtype = m_versionInfo->GetFixedFileSubtype();
|
|
data->fixedFileDateMS = m_versionInfo->GetFixedFileDateMS();
|
|
data->fixedFileDateLS = m_versionInfo->GetFixedFileDateLS();
|
|
|
|
data->sysParms.manageIntervalSeconds = m_context.cDB->GetPollDelaySeconds();
|
|
data->sysParms.timeoutValueMs = m_context.cUser->GetTimeout();
|
|
data->sysParms.numberOfProcessors = m_NumberOfProcessors;
|
|
data->sysParms.memoryPageSize = m_PageSize;
|
|
data->sysParms.processorMask = m_context.cMgr->GetSystemMask();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------//
|
|
// CProcCon thread function -- this function runs in its own thread //
|
|
// Input: None //
|
|
// Returns: Nothing //
|
|
// Note: All ProcCon work is done in the user communication and process management //
|
|
// threads so this fcn has only an oversight role. //
|
|
//--------------------------------------------------------------------------------------------//
|
|
void CProcCon::Run( void )
|
|
{
|
|
ResumeThread(m_hThread[USER_SERVER] );
|
|
ResumeThread(m_hThread[PROC_SERVER] );
|
|
|
|
WaitForSingleObject( m_endEvent, INFINITE );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------//
|
|
// CProcCon function to handle 'hard' stop: failure before threads are released //
|
|
// Input: Optional Thread Exit Code //
|
|
// Returns: Nothing //
|
|
// Note: This function forcefully close the user communication and process management //
|
|
// threads. //
|
|
//--------------------------------------------------------------------------------------------//
|
|
void CProcCon::HardStop( PCULONG32 ExitCode )
|
|
{
|
|
if ( m_hThread[USER_SERVER] ) {
|
|
TerminateThread(m_hThread[USER_SERVER], ExitCode );
|
|
m_hThread[USER_SERVER] = NULL;
|
|
}
|
|
if ( m_hThread[PROC_SERVER] ) {
|
|
TerminateThread(m_hThread[PROC_SERVER], ExitCode );
|
|
m_hThread[PROC_SERVER] = NULL;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------//
|
|
// Function called by service stop when stop requested //
|
|
// Input: None //
|
|
// Returns: Nothing //
|
|
// Note: this function runs as part of service stop //
|
|
//--------------------------------------------------------------------------------------------//
|
|
void CProcCon::Stop( void )
|
|
{
|
|
if ( m_shutEvent ) {
|
|
m_shutDown = TRUE;
|
|
SetEvent( m_shutEvent );
|
|
WaitForMultipleObjects( ENTRY_COUNT(m_hThread), m_hThread, TRUE, 30000 );
|
|
SetEvent( m_endEvent );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------//
|
|
// Function to start the Process Management thread //
|
|
// Input: None //
|
|
// Returns: Nothing //
|
|
// Note: this function runs as part of service start so it must be quick. //
|
|
//--------------------------------------------------------------------------------------------//
|
|
void CProcCon::LaunchProcServer( void )
|
|
{
|
|
m_hThread[PROC_SERVER] = CreateThread( NULL, 0, &PCProcServer, &m_context, CREATE_SUSPENDED, NULL );
|
|
if ( !m_hThread[PROC_SERVER] )
|
|
PCLogUnExError( TEXT("PCProcServer"), TEXT("CreateThread") );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------//
|
|
// Function to start the User Communication thread //
|
|
// Input: None //
|
|
// Returns: Nothing //
|
|
// Note: this function runs as part of service start so it must be quick. //
|
|
//--------------------------------------------------------------------------------------------//
|
|
void CProcCon::LaunchUserServer( void )
|
|
{
|
|
m_hThread[USER_SERVER] = CreateThread( NULL, 0, &PCUserServer, &m_context, CREATE_SUSPENDED, NULL );
|
|
if ( !m_hThread[USER_SERVER] )
|
|
PCLogUnExError( TEXT("PCUserServer"), TEXT("CreateThread") );
|
|
}
|
|
|
|
// End of CProcCon.cpp
|
|
//============================================================================J McDonald fecit====//
|