windows-nt/Source/XPSP1/NT/sdktools/proccon/service/cprocconclient.cpp
2020-09-26 16:20:57 +08:00

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====//