743 lines
34 KiB
C++
743 lines
34 KiB
C++
|
/*======================================================================================//
|
||
|
| //
|
||
|
|Copyright (c) 1998 Sequent Computer Systems, Incorporated //
|
||
|
| //
|
||
|
|Description: //
|
||
|
| //
|
||
|
|---------------------------------------------------------------------------------------//
|
||
|
| This file implements the CProcConClient class methods defined in ProcConSvc.h //
|
||
|
|---------------------------------------------------------------------------------------//
|
||
|
| //
|
||
|
|Created: //
|
||
|
| //
|
||
|
| Jarl McDonald 07-98 //
|
||
|
| //
|
||
|
|Revision History: //
|
||
|
| //
|
||
|
|=======================================================================================*/
|
||
|
#include "ProcConSvc.h"
|
||
|
|
||
|
const PCINT32 SIGNATURE = 0xd06eface;
|
||
|
|
||
|
// CProcConClient Constructor...
|
||
|
CProcConClient::CProcConClient( ClientContext *ctxt ) : m_impersonating( FALSE ),
|
||
|
m_cPC( *ctxt->cPC ), m_cDB( *ctxt->cDB ),
|
||
|
m_cUser( *ctxt->cUser ),
|
||
|
m_hPipe( ctxt->hPipe), m_clientNo( ctxt->clientNo ),
|
||
|
m_inBufChars( ctxt->inBufChars ), m_outBufChars( ctxt->outBufChars )
|
||
|
{
|
||
|
delete ctxt; // we're done with this
|
||
|
|
||
|
m_inBuf = (TCHAR *) new char[m_inBufChars];
|
||
|
if ( !m_inBuf ) PCLogNoMemory( TEXT("AllocInBuffer"), m_inBufChars );
|
||
|
|
||
|
m_outBuf = (TCHAR *) new char[m_outBufChars];
|
||
|
if ( !m_outBuf ) PCLogNoMemory( TEXT("AllocOutBuffer"), m_outBufChars );
|
||
|
|
||
|
m_hReadEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
|
||
|
if ( !m_hReadEvent )
|
||
|
PCLogUnExError( TEXT("PipeRead"), TEXT("CreateEvent") );
|
||
|
|
||
|
m_hWriteEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
|
||
|
if ( !m_hWriteEvent )
|
||
|
PCLogUnExError( TEXT("PipeWrite"), TEXT("CreateEvent") );
|
||
|
|
||
|
memset( &m_olRead, 0, sizeof(m_olRead ) );
|
||
|
memset( &m_olWrite, 0, sizeof(m_olWrite ) );
|
||
|
m_olRead.hEvent = m_hReadEvent;
|
||
|
m_olWrite.hEvent = m_hWriteEvent;
|
||
|
|
||
|
}
|
||
|
|
||
|
// CProcConClient Destructor...
|
||
|
CProcConClient::~CProcConClient( void )
|
||
|
{
|
||
|
if ( m_hPipe ) {
|
||
|
FlushFileBuffers( m_hPipe );
|
||
|
DisconnectNamedPipe( m_hPipe );
|
||
|
CloseHandle( m_hPipe );
|
||
|
m_hPipe = NULL;
|
||
|
if ( m_impersonating && !RevertToSelf() )
|
||
|
PCLogUnExError( TEXT("PCClient"), TEXT("RevertToSelf") );
|
||
|
}
|
||
|
|
||
|
if ( m_hReadEvent ) CloseHandle( m_hReadEvent );
|
||
|
if ( m_hWriteEvent ) CloseHandle( m_hWriteEvent );
|
||
|
if ( m_inBuf ) delete [] ((char *) m_inBuf);
|
||
|
if ( m_outBuf ) delete [] ((char *) m_outBuf);
|
||
|
m_hReadEvent = m_hWriteEvent = m_inBuf = m_outBuf = NULL;
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
// Function to determine if all CProcConClient initial conditions have been met //
|
||
|
// Input: None //
|
||
|
// Returns: TRUE if ready, FALSE if not //
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
BOOL CProcConClient::ReadyToRun( void ) {
|
||
|
return m_hPipe && m_hReadEvent && m_hWriteEvent && m_inBuf && m_outBuf;
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
// CProcConClient thread function -- this function runs in its own thread //
|
||
|
// This function handles all pipe reads, writes and processing for a single connection. //
|
||
|
// Input: None //
|
||
|
// Returns: 0 //
|
||
|
// Note: This thread owns the pipe that it is constructed with and terminates //
|
||
|
// when the pipe is closed by the client. //
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
PCULONG32 CProcConClient::Run( void )
|
||
|
{
|
||
|
PCULONG32 bytesDone, bytesToWrite, rc;
|
||
|
HANDLE waitList[] = { m_olRead.hEvent, m_olWrite.hEvent, m_cPC.GetShutEvent() };
|
||
|
BOOL inBufEmpty = TRUE, outBufEmpty = TRUE, reading = FALSE, writing = FALSE;
|
||
|
|
||
|
for ( BOOL quit = FALSE; !quit && !m_cPC.GotShutdown(); ) {
|
||
|
|
||
|
// Initiate pipe read if needed...
|
||
|
if ( !reading && inBufEmpty ) {
|
||
|
rc = ReadFile( m_hPipe, m_inBuf, m_inBufChars, &bytesDone, &m_olRead );
|
||
|
if ( !rc && GetLastError() != ERROR_IO_PENDING ) {
|
||
|
if ( GetLastError() != ERROR_BROKEN_PIPE )
|
||
|
PCLogUnExError( TEXT("PCClient"), TEXT("ReadPipe") );
|
||
|
quit = TRUE;
|
||
|
}
|
||
|
else reading = TRUE;
|
||
|
}
|
||
|
|
||
|
// Process any pending data...
|
||
|
if ( !writing && outBufEmpty && !inBufEmpty ) {
|
||
|
inBufEmpty = TRUE;
|
||
|
if ( ProcessRequest( bytesDone, &bytesToWrite ) )
|
||
|
outBufEmpty = FALSE;
|
||
|
}
|
||
|
|
||
|
// Initiate pipe write if needed...
|
||
|
if ( !writing && !outBufEmpty ) {
|
||
|
rc = WriteFile( m_hPipe, m_outBuf, bytesToWrite, &bytesDone, &m_olWrite );
|
||
|
if ( !rc && GetLastError() != ERROR_IO_PENDING ) {
|
||
|
if ( GetLastError() != ERROR_BROKEN_PIPE && GetLastError() != ERROR_NO_DATA )
|
||
|
PCLogUnExError( TEXT("PCClient"), TEXT("WritePipe") );
|
||
|
quit = TRUE;
|
||
|
}
|
||
|
else writing = TRUE;
|
||
|
}
|
||
|
|
||
|
// If we're quitting, don't enter wait...
|
||
|
if ( quit || m_cPC.GotShutdown() ) continue;
|
||
|
|
||
|
// Wait for something to happen...
|
||
|
rc = WaitForMultipleObjects( ENTRY_COUNT( waitList ), waitList, FALSE, INFINITE );
|
||
|
if ( rc == WAIT_FAILED ) {
|
||
|
PCLogUnExError( TEXT("PCClient"), TEXT("Wait") );
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Process wait completion...
|
||
|
switch ( rc - WAIT_OBJECT_0 ) {
|
||
|
case 0: // read completed
|
||
|
reading = inBufEmpty = FALSE;
|
||
|
if ( !GetOverlappedResult( m_hPipe, &m_olRead, &bytesDone, TRUE ) ) {
|
||
|
if ( GetLastError() != ERROR_BROKEN_PIPE && GetLastError() != ERROR_NO_DATA )
|
||
|
PCLogUnExError( TEXT("PCClient"), TEXT("ReadResult") );
|
||
|
quit = TRUE;
|
||
|
}
|
||
|
ResetEvent( m_olRead.hEvent );
|
||
|
break;
|
||
|
case 1: // write completed
|
||
|
writing = FALSE;
|
||
|
outBufEmpty = TRUE;
|
||
|
if ( !GetOverlappedResult( m_hPipe, &m_olWrite, &bytesDone, TRUE ) || bytesToWrite != bytesDone ) {
|
||
|
if ( GetLastError() != ERROR_BROKEN_PIPE && GetLastError() != ERROR_NO_DATA )
|
||
|
PCLogUnExError( TEXT("PCClient"), TEXT("WriteResult") );
|
||
|
quit = TRUE;
|
||
|
}
|
||
|
ResetEvent( m_olWrite.hEvent );
|
||
|
break;
|
||
|
case 2: // quit requested
|
||
|
break;
|
||
|
} // end switch
|
||
|
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
// Function to handle impersonation on a request by request basis. All decisions about which //
|
||
|
// types of requests require client impersonation are made in this function. //
|
||
|
// Input: request //
|
||
|
// Returns: TRUE if impersonation was properly set, FALSE otherwise //
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
BOOL CProcConClient::Impersonate( PCRequest *req ) {
|
||
|
switch (req->reqType) {
|
||
|
case PCTYPE_PROCLIST: // impersonation not required
|
||
|
break;
|
||
|
|
||
|
case PCTYPE_NAMERULE: // impersonation required
|
||
|
case PCTYPE_JOBSUMMARY:
|
||
|
case PCTYPE_PROCSUMMARY:
|
||
|
case PCTYPE_JOBLIST:
|
||
|
case PCTYPE_PROCDETAIL:
|
||
|
case PCTYPE_JOBDETAIL:
|
||
|
case PCTYPE_SERVERINFO:
|
||
|
case PCTYPE_SERVERPARMS:
|
||
|
case PCTYPE_CONTROL:
|
||
|
if ( !ImpersonateNamedPipeClient( m_hPipe ) ) {
|
||
|
PCLogUnExError( TEXT("PCClient"), TEXT("Impersonate") );
|
||
|
return FALSE;
|
||
|
}
|
||
|
m_impersonating = TRUE;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
SetLastError( PCERROR_INVALID_REQUEST );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
// Function to deactivate client impersonation on a request by request basis. This function //
|
||
|
// just uses the m_impersonation flag to determine if impersonation is currently in effect. //
|
||
|
// Input: request //
|
||
|
// Returns: //
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
void CProcConClient::UnImpersonate( PCRequest *req ) {
|
||
|
if (m_impersonating && !RevertToSelf()) {
|
||
|
PCLogUnExError( TEXT("PCClient"), TEXT("RevertToSelf") );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
// Function to process a request in the input buffer and build a response in the output buffer//
|
||
|
// Input: Number of bytes in the input buffer, location to store output buffer length //
|
||
|
// Returns: TRUE if output is to be written, else FALSE //
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
BOOL CProcConClient::ProcessRequest( PCULONG32 inLen, PCULONG32 *outLen ) {
|
||
|
|
||
|
PCRequest *req = (PCRequest *) m_inBuf;
|
||
|
PCResponse *rsp = (PCResponse *) m_outBuf;
|
||
|
PrimeResponse( rsp, req );
|
||
|
|
||
|
// Perform cursory checks on incoming request length and contents...
|
||
|
PCULONG32 hdrBytesExpected = sizeof(PCRequest) - sizeof(req->reqData);
|
||
|
if ( inLen < hdrBytesExpected ||
|
||
|
req->reqSignature != SIGNATURE ||
|
||
|
inLen < hdrBytesExpected + req->reqDataLen ) {
|
||
|
return ErrorResponse( PCERROR_INVALID_REQUEST, rsp, outLen );
|
||
|
}
|
||
|
|
||
|
if (!Impersonate( req )) {
|
||
|
PCLogUnExError( TEXT("PCClient"), TEXT("Impersonate") );
|
||
|
return ErrorResponse( GetLastError(), rsp, outLen );
|
||
|
}
|
||
|
|
||
|
ULONG rc = 0;
|
||
|
|
||
|
// Switch on requested data type to process it...
|
||
|
switch ( req->reqType ) {
|
||
|
case PCTYPE_NAMERULE:
|
||
|
rc = DoNameRules( req, rsp, outLen );
|
||
|
break;
|
||
|
|
||
|
case PCTYPE_JOBSUMMARY:
|
||
|
rc = DoJobSummary( req, rsp, outLen );
|
||
|
break;
|
||
|
|
||
|
case PCTYPE_PROCSUMMARY:
|
||
|
rc = DoProcSummary( req, rsp, outLen );
|
||
|
break;
|
||
|
|
||
|
case PCTYPE_PROCDETAIL:
|
||
|
rc = DoProcDetail( req, rsp, outLen );
|
||
|
break;
|
||
|
|
||
|
case PCTYPE_JOBDETAIL:
|
||
|
rc = DoJobDetail( req, rsp, outLen );
|
||
|
break;
|
||
|
|
||
|
case PCTYPE_PROCLIST:
|
||
|
rc = DoProcList( req, rsp, outLen );
|
||
|
break;
|
||
|
|
||
|
case PCTYPE_JOBLIST:
|
||
|
rc = DoJobList( req, rsp, outLen );
|
||
|
break;
|
||
|
|
||
|
case PCTYPE_SERVERINFO:
|
||
|
rc = DoServerInfo( req, rsp, outLen );
|
||
|
break;
|
||
|
|
||
|
case PCTYPE_SERVERPARMS:
|
||
|
rc = DoServerParms( req, rsp, outLen );
|
||
|
break;
|
||
|
|
||
|
case PCTYPE_CONTROL:
|
||
|
rc = DoControl( req, rsp, outLen );
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
rc = ErrorResponse( PCERROR_INVALID_REQUEST, rsp, outLen );
|
||
|
} // end switch
|
||
|
|
||
|
UnImpersonate( req );
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
// Function to prime a response structure with local data and request data //
|
||
|
// Input: pointers to request and response structures //
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
void CProcConClient::PrimeResponse( PCResponse *rsp, PCRequest *req ) {
|
||
|
|
||
|
memset( rsp, 0, sizeof(*rsp) );
|
||
|
|
||
|
rsp->rspReqSignature = SIGNATURE; // sanity check signature
|
||
|
rsp->rspReqSeq = req->reqSeq; // echo of requestor sequence number
|
||
|
rsp->rspReqOp = req->reqOp; // echo of original request operation
|
||
|
rsp->rspReqType = req->reqType; // echo of original request data type
|
||
|
rsp->rspReqVersion = req->reqVersion; // echo of original request data version
|
||
|
rsp->rspVersion = 1; // 1 for base version
|
||
|
rsp->rspTimeStamp = (PCINT32) time( NULL ); // $$ // time stamp associated with the data returned
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
// Function to build an error response in the output buffer //
|
||
|
// Input: Error code, request pointer, location to store output buffer length //
|
||
|
// Returns: TRUE if output is to be written, else FALSE //
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
BOOL CProcConClient::ErrorResponse( PCULONG32 errCode, PCResponse *rsp, PCULONG32 *outLen ) {
|
||
|
|
||
|
rsp->rspResult = (BYTE) (errCode & 0xf0000000 ? PCRESULT_PCERROR: PCRESULT_NTERROR);
|
||
|
rsp->rspError = errCode; // NT or PC error
|
||
|
rsp->rspDataItemCount = 0; // no data returned on error
|
||
|
rsp->rspDataItemLen = 0; // no data returned on error
|
||
|
|
||
|
*outLen = sizeof( *rsp ) - sizeof( rsp->rspData );
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
// Function to process a name rules request and build a response in the output buffer //
|
||
|
// Input: Request pointer, location to store output buffer length //
|
||
|
// Returns: TRUE if output is to be written, else FALSE //
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
BOOL CProcConClient::DoNameRules( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen ) {
|
||
|
|
||
|
PCULONG32 err = PCERROR_SUCCESS;
|
||
|
PCNameRule *rule = (PCNameRule *) req->reqData;
|
||
|
rule->matchType = _totupper( rule->matchType );
|
||
|
|
||
|
switch ( req->reqOp ) {
|
||
|
case PCOP_GET:
|
||
|
req->reqFlags |= PCREQFLAG_DOLIST; // just treat as list flag set
|
||
|
break;
|
||
|
case PCOP_ADD:
|
||
|
if ( !PCValidName( rule->procName, ENTRY_COUNT(rule->procName) ) )
|
||
|
return ErrorResponse( PCERROR_INVALID_NAME, rsp, outLen );
|
||
|
if ( !PCValidMatchType( rule->matchType ) )
|
||
|
return ErrorResponse( PCERROR_INVALID_PARAMETER, rsp, outLen );
|
||
|
err = m_cDB.AddNameRule( rule, req->reqVersion, (PCULONG32) req->reqIndex, req->reqUpdCtr );
|
||
|
break;
|
||
|
case PCOP_REP:
|
||
|
if ( !PCValidName( rule->procName, ENTRY_COUNT(rule->procName) ) )
|
||
|
return ErrorResponse( PCERROR_INVALID_NAME, rsp, outLen );
|
||
|
if ( !PCValidMatchType( rule->matchType ) )
|
||
|
return ErrorResponse( PCERROR_INVALID_PARAMETER, rsp, outLen );
|
||
|
err = m_cDB.ReplNameRule( rule, req->reqVersion, (PCULONG32) req->reqIndex, req->reqUpdCtr );
|
||
|
break;
|
||
|
case PCOP_DEL:
|
||
|
err = m_cDB.DelNameRule( (PCULONG32) req->reqIndex, req->reqUpdCtr );
|
||
|
break;
|
||
|
case PCOP_ORD:
|
||
|
err = m_cDB.SwapNameRule( (PCULONG32) req->reqIndex, req->reqUpdCtr );
|
||
|
break;
|
||
|
default:
|
||
|
err = PCERROR_INVALID_REQUEST;
|
||
|
break;
|
||
|
} // end switch operation
|
||
|
|
||
|
if ( err != PCERROR_SUCCESS )
|
||
|
return ErrorResponse( err, rsp, outLen );
|
||
|
|
||
|
if ( req->reqFlags & PCREQFLAG_DOLIST ) {
|
||
|
if ( m_cDB.GetNameRules( req->reqFirst, // start from here
|
||
|
(PCNameRule *) rsp->rspData, req->reqCount, // put data here with max count
|
||
|
&rsp->rspDataItemLen, &rsp->rspDataItemCount, // put item len and count here
|
||
|
&rsp->rspUpdCtr ) ) // put updctr here
|
||
|
rsp->rspFlags |= PCRSPFLAG_MOREDATA;
|
||
|
}
|
||
|
|
||
|
*outLen = offsetof(PCResponse, rspData) + rsp->rspDataItemCount * rsp->rspDataItemLen;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
// Function to handle a process list request and build a response in the output buffer //
|
||
|
// Input: Request pointer, location to store output buffer length //
|
||
|
// Returns: TRUE if output is to be written, else FALSE //
|
||
|
// Note: A process list consists of the names of all processes know to ProcCon: //
|
||
|
// 1) Process names appearing in name rules, //
|
||
|
// 2) Process names defined in ProcCon's database, //
|
||
|
// 3) Any processes currently running and visible to ProcCon. //
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
BOOL CProcConClient::DoProcList( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen ) {
|
||
|
|
||
|
INT32 err = PCERROR_SUCCESS;
|
||
|
|
||
|
PCProcListItem *start = (PCProcListItem *) req->reqData;
|
||
|
|
||
|
switch ( req->reqOp ) {
|
||
|
case PCOP_GET:
|
||
|
if ( !PCValidName( start->procName, ENTRY_COUNT(start->procName), TRUE ) )
|
||
|
return ErrorResponse( PCERROR_INVALID_NAME, rsp, outLen );
|
||
|
|
||
|
if ( m_cDB.GetProcList( start, (PCULONG32) req->reqIndex, // starting here with these flags
|
||
|
(PCProcListItem *) rsp->rspData, req->reqCount, // put data here with max count
|
||
|
&rsp->rspDataItemLen, &rsp->rspDataItemCount ) ) // put item len and count here
|
||
|
rsp->rspFlags |= PCRSPFLAG_MOREDATA;
|
||
|
break;
|
||
|
case PCOP_KILL:
|
||
|
err = m_cPC.GetPCMgr()->KillProcess( (ULONG_PTR) req->reqIndex, *((TIME_VALUE *) req->reqData) );
|
||
|
break;
|
||
|
default:
|
||
|
err = PCERROR_INVALID_REQUEST;
|
||
|
break;
|
||
|
} // end switch operation
|
||
|
|
||
|
if ( err != PCERROR_SUCCESS ) return ErrorResponse( err, rsp, outLen );
|
||
|
|
||
|
*outLen = offsetof(PCResponse, rspData) + rsp->rspDataItemCount * rsp->rspDataItemLen;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
// Function to handle a job list request and build a response in the output buffer //
|
||
|
// Input: Request pointer, location to store output buffer length //
|
||
|
// Returns: TRUE if output is to be written, else FALSE //
|
||
|
// Note: A job list consists of the names of all jobs know to ProcCon: //
|
||
|
// 1) Job names appearing in process definitions as "member of group", //
|
||
|
// 2) Job names defined in ProcCon's database, //
|
||
|
// 3) Any jobs currently running and visible to ProcCon. //
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
BOOL CProcConClient::DoJobList( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen ) {
|
||
|
|
||
|
INT32 err = PCERROR_SUCCESS;
|
||
|
|
||
|
PCJobListItem *start = (PCJobListItem *) req->reqData;
|
||
|
|
||
|
switch ( req->reqOp ) {
|
||
|
case PCOP_GET:
|
||
|
if ( !PCValidName( start->jobName, ENTRY_COUNT(start->jobName), TRUE ) )
|
||
|
return ErrorResponse( PCERROR_INVALID_NAME, rsp, outLen );
|
||
|
if ( m_cDB.GetJobList( start, (PCULONG32) req->reqIndex, // starting here with these flags
|
||
|
(PCJobListItem *) rsp->rspData, req->reqCount, // put data here with max count
|
||
|
&rsp->rspDataItemLen, &rsp->rspDataItemCount ) ) // put item len and count here
|
||
|
rsp->rspFlags |= PCRSPFLAG_MOREDATA;
|
||
|
break;
|
||
|
case PCOP_KILL:
|
||
|
err = m_cPC.GetPCMgr()->KillJob( *((JOB_NAME *) req->reqData) );
|
||
|
break;
|
||
|
default:
|
||
|
err = PCERROR_INVALID_REQUEST;
|
||
|
break;
|
||
|
} // end switch operation
|
||
|
|
||
|
if ( err != PCERROR_SUCCESS ) return ErrorResponse( err, rsp, outLen );
|
||
|
|
||
|
*outLen = offsetof(PCResponse, rspData) + rsp->rspDataItemCount * rsp->rspDataItemLen;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
// Function to handle a process summary data request and build a response in the output buffer//
|
||
|
// Input: Request pointer, location to store output buffer length //
|
||
|
// Returns: TRUE if output is to be written, else FALSE //
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
BOOL CProcConClient::DoProcSummary( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen ) {
|
||
|
|
||
|
INT32 err = PCERROR_SUCCESS;
|
||
|
|
||
|
PCProcSummary *start = (PCProcSummary *) req->reqData;
|
||
|
|
||
|
switch ( req->reqOp ) {
|
||
|
case PCOP_GET:
|
||
|
if ( !PCValidName( start->procName, ENTRY_COUNT(start->procName), TRUE ) )
|
||
|
return ErrorResponse( PCERROR_INVALID_NAME, rsp, outLen );
|
||
|
if ( m_cDB.GetProcSummary( start, (PCULONG32) req->reqIndex, // starting here with these flags
|
||
|
(PCProcSummary *) rsp->rspData, req->reqCount, // put data here with max count
|
||
|
&rsp->rspDataItemLen, &rsp->rspDataItemCount ) ) // put item len and count here
|
||
|
rsp->rspFlags |= PCRSPFLAG_MOREDATA;
|
||
|
break;
|
||
|
default:
|
||
|
err = PCERROR_INVALID_REQUEST;
|
||
|
break;
|
||
|
} // end switch operation
|
||
|
|
||
|
if ( err != PCERROR_SUCCESS ) return ErrorResponse( err, rsp, outLen );
|
||
|
|
||
|
*outLen = offsetof(PCResponse, rspData) + rsp->rspDataItemCount * rsp->rspDataItemLen;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
// Function to handle a job summary data request and build a response in the output buffer //
|
||
|
// Input: Request pointer, location to store output buffer length //
|
||
|
// Returns: TRUE if output is to be written, else FALSE //
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
BOOL CProcConClient::DoJobSummary( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen ) {
|
||
|
|
||
|
INT32 err = PCERROR_SUCCESS;
|
||
|
|
||
|
PCJobSummary *start = (PCJobSummary *) req->reqData;
|
||
|
|
||
|
switch ( req->reqOp ) {
|
||
|
case PCOP_GET:
|
||
|
if ( !PCValidName( start->jobName, ENTRY_COUNT(start->jobName), TRUE ) )
|
||
|
return ErrorResponse( PCERROR_INVALID_NAME, rsp, outLen );
|
||
|
if ( m_cDB.GetJobSummary( start, (PCULONG32) req->reqIndex, // starting here with these flags
|
||
|
(PCJobSummary *) rsp->rspData, req->reqCount, // put data here with max count
|
||
|
&rsp->rspDataItemLen, &rsp->rspDataItemCount ) ) // put item len and count here
|
||
|
rsp->rspFlags |= PCRSPFLAG_MOREDATA;
|
||
|
break;
|
||
|
default:
|
||
|
err = PCERROR_INVALID_REQUEST;
|
||
|
break;
|
||
|
} // end switch operation
|
||
|
|
||
|
if ( err != PCERROR_SUCCESS ) return ErrorResponse( err, rsp, outLen );
|
||
|
|
||
|
*outLen = offsetof(PCResponse, rspData) + rsp->rspDataItemCount * rsp->rspDataItemLen;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
// Function to process a process detail data request and build a response in the output buf //
|
||
|
// Input: Request pointer, location to store output buffer and length //
|
||
|
// Returns: TRUE if output is to be written, else FALSE //
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
BOOL CProcConClient::DoProcDetail( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen ) {
|
||
|
|
||
|
INT32 err = PCERROR_SUCCESS;
|
||
|
|
||
|
PCProcDetail *reqDetail = (PCProcDetail *) req->reqData;
|
||
|
PCProcDetail *rspDetail = (PCProcDetail *) rsp->rspData;
|
||
|
|
||
|
if ( !PCValidName( reqDetail->base.procName, ENTRY_COUNT(reqDetail->base.procName) ) )
|
||
|
return ErrorResponse( PCERROR_INVALID_NAME, rsp, outLen );
|
||
|
|
||
|
switch ( req->reqOp ) {
|
||
|
case PCOP_GET: {
|
||
|
// Set max length of variable data.
|
||
|
int maxVLen = req->maxReply - offsetof(PCProcDetail, vData);
|
||
|
reqDetail->vLength = (PCINT16) max( 0, maxVLen );
|
||
|
// Get detail data and set number (always only 1) and length of returned item.
|
||
|
err = m_cDB.GetProcDetail( reqDetail, rspDetail, req->reqVersion, &rsp->rspUpdCtr );
|
||
|
rsp->rspDataItemCount = 1;
|
||
|
rsp->rspDataItemLen = (PCINT16) (offsetof(PCProcDetail, vData) + rspDetail->vLength);
|
||
|
break;
|
||
|
}
|
||
|
case PCOP_ADD:
|
||
|
if ( !PCValidName( reqDetail->base.memberOfJobName, ENTRY_COUNT(reqDetail->base.memberOfJobName), TRUE ) )
|
||
|
return ErrorResponse( PCERROR_INVALID_NAME, rsp, outLen );
|
||
|
err = m_cDB.AddProcDetail( reqDetail, req->reqVersion);
|
||
|
if ( err == PCERROR_SUCCESS || err == PCERROR_EXISTS )
|
||
|
GenerateJobDetail( reqDetail );
|
||
|
break;
|
||
|
case PCOP_REP:
|
||
|
if ( !PCValidName( reqDetail->base.memberOfJobName, ENTRY_COUNT(reqDetail->base.memberOfJobName), TRUE ) )
|
||
|
return ErrorResponse( PCERROR_INVALID_NAME, rsp, outLen );
|
||
|
err = m_cDB.ReplProcDetail( reqDetail, req->reqVersion, req->reqUpdCtr );
|
||
|
if ( err == PCERROR_SUCCESS || err == ERROR_FILE_NOT_FOUND )
|
||
|
GenerateJobDetail( reqDetail );
|
||
|
break;
|
||
|
case PCOP_DEL:
|
||
|
err = m_cDB.DelProcDetail( &reqDetail->base, req->reqVersion);
|
||
|
break;
|
||
|
default:
|
||
|
err = PCERROR_INVALID_REQUEST;
|
||
|
break;
|
||
|
} // end switch operation
|
||
|
|
||
|
if ( err == ERROR_MORE_DATA )
|
||
|
rsp->rspFlags |= PCRSPFLAG_MOREDATA;
|
||
|
else if ( err != PCERROR_SUCCESS )
|
||
|
return ErrorResponse( err, rsp, outLen );
|
||
|
|
||
|
if ( req->reqFlags & PCREQFLAG_DOLIST )
|
||
|
m_cDB.GetProcSummary( (PCProcSummary *) req->reqData, PC_LIST_STARTING_WITH, // starting here
|
||
|
(PCProcSummary *) rsp->rspData, 1, // put data here with count = 1
|
||
|
&rsp->rspDataItemLen, &rsp->rspDataItemCount ); // put item len and count here
|
||
|
|
||
|
*outLen = offsetof(PCResponse, rspData) + rsp->rspDataItemCount * rsp->rspDataItemLen;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
// Function to generate job detail if needed and it doesn't exist //
|
||
|
// Input: Process detail that may refer to a job //
|
||
|
// Returns: nothing //
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
void CProcConClient::GenerateJobDetail( PCProcDetail *reqDetail ) {
|
||
|
if ( *reqDetail->base.memberOfJobName ) {
|
||
|
PCJobDetail jobDetail;
|
||
|
memset( &jobDetail, 0, sizeof(jobDetail) );
|
||
|
|
||
|
memcpy( jobDetail.base.jobName, reqDetail->base.memberOfJobName, sizeof(jobDetail.base.jobName) );
|
||
|
jobDetail.base.mgmtParms.priority = reqDetail->base.mgmtParms.priority;
|
||
|
jobDetail.base.mgmtParms.affinity = reqDetail->base.mgmtParms.affinity;
|
||
|
jobDetail.base.mgmtParms.schedClass = 5;
|
||
|
|
||
|
m_cDB.AddJobDetail( &jobDetail, 1 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
// Function to process a job detail request and build a response in the output buffer //
|
||
|
// Input: Request pointer, location to store output buffer length //
|
||
|
// Returns: TRUE if output is to be written, else FALSE //
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
BOOL CProcConClient::DoJobDetail( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen ) {
|
||
|
|
||
|
INT32 err = PCERROR_SUCCESS;
|
||
|
|
||
|
PCJobDetail *reqDetail = (PCJobDetail *) req->reqData;
|
||
|
PCJobDetail *rspDetail = (PCJobDetail *) rsp->rspData;
|
||
|
|
||
|
if ( !PCValidName( reqDetail->base.jobName, ENTRY_COUNT(reqDetail->base.jobName) ) )
|
||
|
return ErrorResponse( PCERROR_INVALID_NAME, rsp, outLen );
|
||
|
|
||
|
switch ( req->reqOp ) {
|
||
|
case PCOP_GET: {
|
||
|
// Set max length of variable data.
|
||
|
int maxVLen = req->maxReply - offsetof(PCJobDetail, vData);
|
||
|
rspDetail->vLength = (PCINT16) max( 0, maxVLen );
|
||
|
// Get detail data and set number (always only 1) and length of returned item.
|
||
|
err = m_cDB.GetJobDetail( reqDetail, rspDetail, req->reqVersion, &rsp->rspUpdCtr );
|
||
|
rsp->rspDataItemCount = 1;
|
||
|
rsp->rspDataItemLen = (PCINT16) (offsetof(PCJobDetail, vData) + rspDetail->vLength);
|
||
|
break;
|
||
|
}
|
||
|
case PCOP_ADD:
|
||
|
err = m_cDB.AddJobDetail( reqDetail, req->reqVersion);
|
||
|
break;
|
||
|
case PCOP_REP:
|
||
|
err = m_cDB.ReplJobDetail( reqDetail, req->reqVersion, req->reqUpdCtr );
|
||
|
break;
|
||
|
case PCOP_DEL:
|
||
|
err = m_cDB.DelJobDetail( &reqDetail->base, req->reqVersion);
|
||
|
break;
|
||
|
default:
|
||
|
err = PCERROR_INVALID_REQUEST;
|
||
|
break;
|
||
|
} // end switch operation
|
||
|
|
||
|
if ( err == ERROR_MORE_DATA )
|
||
|
rsp->rspFlags |= PCRSPFLAG_MOREDATA;
|
||
|
else if ( err != PCERROR_SUCCESS )
|
||
|
return ErrorResponse( err, rsp, outLen );
|
||
|
|
||
|
if ( req->reqFlags & PCREQFLAG_DOLIST )
|
||
|
m_cDB.GetJobSummary( (PCJobSummary *) req->reqData, PC_LIST_STARTING_WITH, // starting here
|
||
|
(PCJobSummary *) rsp->rspData, 1, // put data here with count = 1
|
||
|
&rsp->rspDataItemLen, &rsp->rspDataItemCount ); // put item len and count here
|
||
|
|
||
|
*outLen = offsetof(PCResponse, rspData) + rsp->rspDataItemCount * rsp->rspDataItemLen;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
// Function to handle a server information request and build a response in the output buffer //
|
||
|
// Input: Request and response pointers, location to store output buffer length //
|
||
|
// Returns: TRUE if output is to be written, else FALSE //
|
||
|
// Note: Server info consists of version info and system parameters. //
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
BOOL CProcConClient::DoServerInfo( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen ) {
|
||
|
|
||
|
INT32 err = PCERROR_SUCCESS;
|
||
|
|
||
|
switch ( req->reqOp ) {
|
||
|
case PCOP_GET:
|
||
|
m_cPC.GetPCSystemInfo( (PCSystemInfo *) rsp->rspData, // put data here
|
||
|
&rsp->rspDataItemLen, &rsp->rspDataItemCount ); // put item len and count here
|
||
|
break;
|
||
|
default:
|
||
|
err = PCERROR_INVALID_REQUEST;
|
||
|
break;
|
||
|
} // end switch operation
|
||
|
|
||
|
if ( err != PCERROR_SUCCESS ) return ErrorResponse( err, rsp, outLen );
|
||
|
|
||
|
*outLen = offsetof(PCResponse, rspData) + rsp->rspDataItemCount * rsp->rspDataItemLen;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
// Function to handle a server parameter request and build a response in the output buffer //
|
||
|
// Input: Request pointer, location to store output buffer length //
|
||
|
// Returns: TRUE if output is to be written, else FALSE //
|
||
|
// Note: Server info consists of version info and system parameters. //
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
BOOL CProcConClient::DoServerParms( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen ) {
|
||
|
|
||
|
INT32 err = PCERROR_SUCCESS;
|
||
|
|
||
|
switch ( req->reqOp ) {
|
||
|
case PCOP_REP:
|
||
|
err = m_cDB.SetPollDelaySeconds( (PCUINT32) (((PCSystemParms *) req->reqData)->manageIntervalSeconds) );
|
||
|
if ( err == PCERROR_SUCCESS )
|
||
|
err = m_cUser.SetTimeout( (PCUINT32) (((PCSystemParms *) req->reqData)->timeoutValueMs) );
|
||
|
break;
|
||
|
default:
|
||
|
err = PCERROR_INVALID_REQUEST;
|
||
|
break;
|
||
|
} // end switch operation
|
||
|
|
||
|
if ( err != PCERROR_SUCCESS ) return ErrorResponse( err, rsp, outLen );
|
||
|
|
||
|
*outLen = offsetof(PCResponse, rspData);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
// Function to handle a server control request and build a response in the output buffer //
|
||
|
// Input: Request pointer, location to store output buffer length //
|
||
|
// Returns: TRUE if output is to be written, else FALSE //
|
||
|
// Note: Server control consists of a series of bit commands and one piece of data. //
|
||
|
//--------------------------------------------------------------------------------------------//
|
||
|
BOOL CProcConClient::DoControl( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen ) {
|
||
|
|
||
|
INT32 err = PCERROR_SUCCESS;
|
||
|
|
||
|
if ( req->reqOp != PCOP_CTL ||
|
||
|
(req->reqIndex & PCCFLAG_SIGNATURE) != PCCFLAG_SIGNATURE ||
|
||
|
req->reqIndex & PCCFLAG_ANTI_SIGNATURE )
|
||
|
err = PCERROR_INVALID_REQUEST;
|
||
|
else {
|
||
|
if ( req->reqIndex & PCCFLAG_STOP_MEDIATOR )
|
||
|
err = m_cPC.StopMediator();
|
||
|
if ( err == PCERROR_SUCCESS && req->reqIndex & PCCFLAG_START_MEDIATOR )
|
||
|
err = m_cPC.StartMediator();
|
||
|
if ( err == PCERROR_SUCCESS && req->reqIndex & PCCFLAG_DELALL_NAME_RULES )
|
||
|
err = m_cDB.DeleteAllNameRules();
|
||
|
if ( err == PCERROR_SUCCESS && req->reqIndex & PCCFLAG_DELALL_PROC_DEFS )
|
||
|
err = m_cDB.DeleteAllProcDefs();
|
||
|
if ( err == PCERROR_SUCCESS && req->reqIndex & PCCFLAG_DELALL_JOB_DEFS )
|
||
|
err = m_cDB.DeleteAllJobDefs();
|
||
|
}
|
||
|
|
||
|
if ( err != PCERROR_SUCCESS ) return ErrorResponse( err, rsp, outLen );
|
||
|
|
||
|
*outLen = offsetof(PCResponse, rspData);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
// End of CProcClient.cpp
|
||
|
//============================================================================J McDonald fecit====//
|