937 lines
41 KiB
C++
937 lines
41 KiB
C++
/*======================================================================================//
|
|
| Windows 2000 Process Control //
|
|
| //
|
|
|Copyright (c) 1998, 1999 Sequent Computer Systems, Incorporated. All rights reserved //
|
|
| //
|
|
|File Name: ProcConLib.cpp //
|
|
| //
|
|
|Description: This implements the ProcCon client side API in a static library //
|
|
| //
|
|
|Created: Jarl McDonald 08-98 //
|
|
| //
|
|
|Rev History: //
|
|
| //
|
|
|=======================================================================================*/
|
|
#include <windows.h>
|
|
#include <stddef.h>
|
|
#include <stdlib.h>
|
|
#include <tchar.h>
|
|
#include <time.h>
|
|
#include "ProcConAPI.h"
|
|
#include "ProcConClnt.h"
|
|
|
|
#define ENTRY_COUNT(x) (sizeof(x) / sizeof(x[0]))
|
|
|
|
typedef struct _PCConnection {
|
|
TCHAR name[MAX_PATH];
|
|
HANDLE handle;
|
|
PCUINT32 connCount;
|
|
time_t connTime;
|
|
PCUINT32 flags;
|
|
PCUINT32 lastError;
|
|
PCINT32 reqSeq;
|
|
char *buffer;
|
|
PCINT32 bufSize;
|
|
DWORD timeout;
|
|
OVERLAPPED overlap;
|
|
} PCConnection;
|
|
|
|
typedef enum _PCConnFlags {
|
|
PCAPIFLAG_FREEBUFFER = 0x01000000,
|
|
};
|
|
|
|
const PCINT32 SIGNATURE = 0xd06eface;
|
|
const TCHAR *PIPENAME = TEXT("\\pipe\\ProcConPip");
|
|
|
|
static PCConnection connTbl[128];
|
|
static PCid nextId = 0;
|
|
|
|
//======================================================================================//
|
|
// Library internal functions
|
|
//======================================================================================//
|
|
static PCINT32 PCMaxItemCount( PCid target,
|
|
PCINT32 bufSize,
|
|
PCINT32 itemSize )
|
|
{
|
|
PCINT32 maxUsrBuf = bufSize / itemSize;
|
|
PCINT32 maxIOBuf = (connTbl[target].bufSize - offsetof(PCResponse, rspData)) / itemSize;
|
|
|
|
return min(maxUsrBuf, maxIOBuf);
|
|
}
|
|
|
|
static BOOL PCIsValidPCId( PCid target )
|
|
{
|
|
if ( target <= 0 || target >= ENTRY_COUNT(connTbl) )
|
|
connTbl[0].lastError = PCERROR_INVALID_PCID;
|
|
else if ( !connTbl[target].handle )
|
|
connTbl[target].lastError = PCERROR_INVALID_PCID;
|
|
else return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
static void PCBuildReq( PCid target,
|
|
BYTE op,
|
|
BYTE itemType,
|
|
void *pItem = NULL,
|
|
PCINT16 itemSize = 0,
|
|
PCINT32 maxReply = 0,
|
|
PCINT64 index = 0,
|
|
PCINT32 count = 1,
|
|
PCINT32 first = 0,
|
|
PCINT32 updateCtr = 0 )
|
|
{
|
|
PCRequest *req = (PCRequest *) connTbl[target].buffer;
|
|
connTbl[target].lastError = PCERROR_SUCCESS;
|
|
|
|
memset( req, 0, sizeof( *req ) );
|
|
|
|
req->reqSignature = SIGNATURE; // sanity check signature
|
|
req->reqSeq = ++connTbl[target].reqSeq; // requestor sequence number
|
|
req->reqOp = op; // requested operation: get
|
|
req->reqType = itemType; // requested data type: name rule
|
|
req->reqVersion = 1; // expected data version code
|
|
req->reqUpdCtr = updateCtr; // requestor's update counter from get
|
|
req->reqIndex = index; // requestor's insert point, etc.
|
|
req->reqCount = count; // requestor's returned data item max count
|
|
req->reqFirst = first; // requestor's first index to retrieve
|
|
req->maxReply = min( (PCUINT32) maxReply,
|
|
(PCUINT32) connTbl[target].bufSize - offsetof(PCResponse, rspData) );
|
|
req->reqDataLen = itemSize; // data length that follows.
|
|
if ( pItem ) memcpy( req->reqData, pItem, itemSize );
|
|
}
|
|
|
|
static BOOL PCReopen( PCid id )
|
|
{
|
|
++connTbl[id].connCount;
|
|
connTbl[id].connTime = time( NULL );
|
|
connTbl[id].handle = INVALID_HANDLE_VALUE;
|
|
|
|
// Connect to desired server and pipe...
|
|
if ( WaitNamedPipe( connTbl[id].name, NMPWAIT_USE_DEFAULT_WAIT ) )
|
|
connTbl[id].handle = CreateFile( connTbl[id].name, GENERIC_READ + GENERIC_WRITE, 0,
|
|
NULL, OPEN_EXISTING,
|
|
SECURITY_SQOS_PRESENT + SECURITY_IMPERSONATION + FILE_FLAG_OVERLAPPED,
|
|
NULL );
|
|
|
|
// Update table entry...
|
|
connTbl[id].lastError = connTbl[id].handle == INVALID_HANDLE_VALUE? GetLastError() : PCERROR_SUCCESS;
|
|
|
|
// return success or fail indication...
|
|
return connTbl[id].lastError == PCERROR_SUCCESS;
|
|
}
|
|
|
|
static BOOL PCRetryCode( PCid id )
|
|
{
|
|
static PCUINT32 retryCodes[] = { ERROR_BAD_PIPE, ERROR_PIPE_BUSY, ERROR_NO_DATA,
|
|
ERROR_PIPE_NOT_CONNECTED, ERROR_BROKEN_PIPE, ERROR_SEM_TIMEOUT,
|
|
ERROR_NETNAME_DELETED, ERROR_INVALID_HANDLE };
|
|
for ( PCUINT32 i = 0; i < ENTRY_COUNT(retryCodes); ++i )
|
|
if ( connTbl[id].lastError == retryCodes[i] ) return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
static void PCSetReqFlag( PCid target, PCINT32 flag )
|
|
{
|
|
((PCRequest *) connTbl[target].buffer)->reqFlags |= flag;
|
|
}
|
|
|
|
static BOOL PCTestResponse( PCid target,
|
|
PCUINT32 bytesActual )
|
|
{
|
|
PCResponse *rsp = (PCResponse *) connTbl[target].buffer;
|
|
PCUINT32 hdrBytesExpected = sizeof(PCResponse) - sizeof(rsp->rspData);
|
|
if ( bytesActual < hdrBytesExpected ) {
|
|
connTbl[target].lastError = PCERROR_INVALID_RESPONSE_LENGTH;
|
|
return FALSE;
|
|
}
|
|
|
|
if ( rsp->rspReqSignature != SIGNATURE || rsp->rspReqSeq != connTbl[target].reqSeq ) {
|
|
connTbl[target].lastError = PCERROR_INVALID_RESPONSE;
|
|
return FALSE;
|
|
}
|
|
|
|
PCUINT32 dataBytesReceived = rsp->rspDataItemCount * rsp->rspDataItemLen;
|
|
if ( bytesActual < hdrBytesExpected + dataBytesReceived ) {
|
|
connTbl[target].lastError = PCERROR_INVALID_RESPONSE_LENGTH;
|
|
return FALSE;
|
|
}
|
|
|
|
if ( rsp->rspResult != PCRESULT_SUCCESS ) {
|
|
connTbl[target].lastError = rsp->rspError;
|
|
return FALSE;
|
|
}
|
|
|
|
connTbl[target].lastError = PCERROR_SUCCESS;
|
|
return TRUE;
|
|
}
|
|
|
|
static PCINT32 PCCopyData( PCid target,
|
|
void *pData,
|
|
PCINT32 maxItemsRequested,
|
|
PCUINT32 maxLen,
|
|
PCINT32 *nUpdateCtr = NULL )
|
|
{
|
|
PCResponse *rsp = (PCResponse *) connTbl[target].buffer;
|
|
|
|
if ( rsp->rspFlags & PCRSPFLAG_MOREDATA ) connTbl[target].lastError = PCERROR_MORE_DATA;
|
|
|
|
if ( nUpdateCtr ) *nUpdateCtr = rsp->rspUpdCtr;
|
|
|
|
PCUINT32 items = min( rsp->rspDataItemCount, maxItemsRequested );
|
|
PCUINT32 copyLen = items * rsp->rspDataItemLen;
|
|
|
|
if ( copyLen > maxLen ) {
|
|
connTbl[target].lastError = PCERROR_TRUNCATED;
|
|
items = maxLen / rsp->rspDataItemLen;
|
|
copyLen = items * rsp->rspDataItemLen;
|
|
}
|
|
|
|
memcpy( pData, rsp->rspData, copyLen );
|
|
|
|
return items;
|
|
}
|
|
|
|
static BOOL PCReadRsp( PCid target )
|
|
{
|
|
BOOL test;
|
|
|
|
do {
|
|
PCULONG32 bytesRead;
|
|
ResetEvent( connTbl[target].overlap.hEvent );
|
|
PCULONG32 rc = ReadFile( connTbl[target].handle,
|
|
connTbl[target].buffer, connTbl[target].bufSize,
|
|
&bytesRead, &connTbl[target].overlap );
|
|
if ( !rc && GetLastError() != ERROR_IO_PENDING ) {
|
|
connTbl[target].lastError = GetLastError();
|
|
return FALSE;
|
|
}
|
|
if ( WAIT_TIMEOUT == WaitForSingleObject( connTbl[target].overlap.hEvent, connTbl[target].timeout ) ) {
|
|
CancelIo( connTbl[target].handle );
|
|
connTbl[target].lastError = PCERROR_REQUEST_TIMED_OUT;
|
|
return FALSE;
|
|
}
|
|
else if ( !GetOverlappedResult( connTbl[target].handle, &connTbl[target].overlap, &bytesRead, FALSE ) ) {
|
|
connTbl[target].lastError = GetLastError();
|
|
return FALSE;
|
|
}
|
|
test = PCTestResponse( target, bytesRead );
|
|
} while ( !test && PCGetLastError( target ) == PCERROR_INVALID_RESPONSE );
|
|
|
|
return test;
|
|
}
|
|
|
|
static BOOL PCSendReceive( PCid target )
|
|
{
|
|
PCRequest *req = (PCRequest *) connTbl[target].buffer;
|
|
PCULONG32 bytesActual, bytesToWrite = sizeof(PCRequest) - sizeof(req->reqData) + req->reqDataLen;
|
|
|
|
ResetEvent( connTbl[target].overlap.hEvent );
|
|
for ( int retryCt = 0; retryCt < PC_MAX_RETRIES + 1; ++retryCt ) {
|
|
PCULONG32 rc = WriteFile( connTbl[target].handle, req, bytesToWrite, &bytesActual, &connTbl[target].overlap );
|
|
if ( rc || GetLastError() == ERROR_IO_PENDING ) break;
|
|
else {
|
|
connTbl[target].lastError = GetLastError();
|
|
if ( PCRetryCode( target ) ) Sleep( rand() * 300 / RAND_MAX );
|
|
else return FALSE;
|
|
PCReopen( target );
|
|
}
|
|
}
|
|
if ( WAIT_TIMEOUT == WaitForSingleObject( connTbl[target].overlap.hEvent, connTbl[target].timeout ) ) {
|
|
CancelIo( connTbl[target].handle );
|
|
connTbl[target].lastError = PCERROR_REQUEST_TIMED_OUT;
|
|
return FALSE;
|
|
}
|
|
else if ( !GetOverlappedResult( connTbl[target].handle, &connTbl[target].overlap, &bytesActual, FALSE ) ) {
|
|
connTbl[target].lastError = GetLastError();
|
|
return FALSE;
|
|
}
|
|
|
|
if ( retryCt >= PC_MAX_RETRIES + 1 ) return FALSE;
|
|
|
|
if ( bytesToWrite != bytesActual ) {
|
|
connTbl[target].lastError = PCERROR_IO_INCOMPLETE;
|
|
return FALSE;
|
|
}
|
|
|
|
return PCReadRsp( target );
|
|
}
|
|
|
|
//======================================================================================//
|
|
// PCOpen -- establish connection to PC on named machine.
|
|
// Returns: PCid to use with future PC calls or 0 on error (use PCGetLastError).
|
|
// Arguments: 0) pointer to target computer name or NULL to use local machine,
|
|
// 1) buffer to be used in server communication or NULL (library allocates).
|
|
// 2) size of buffer supplied or to be allocated in bytes.
|
|
//======================================================================================//
|
|
PCid PCOpen( const TCHAR *targetComputer, char *buffer, PCUINT32 bufSize )
|
|
{
|
|
|
|
if ( bufSize < PC_MIN_BUF_SIZE || bufSize > PC_MAX_BUF_SIZE ) {
|
|
connTbl[0].lastError = PCERROR_INVALID_PARAMETER;
|
|
return 0;
|
|
}
|
|
|
|
TCHAR pipe[MAX_PATH];
|
|
_tcscpy( pipe, TEXT("\\\\") );
|
|
_tcscat( pipe, targetComputer? targetComputer : TEXT(".") );
|
|
_tcscat( pipe, PIPENAME );
|
|
|
|
// Connect to desired server and pipe...
|
|
if ( WaitNamedPipe( pipe, NMPWAIT_USE_DEFAULT_WAIT ) ) {
|
|
HANDLE hPipe = CreateFile( pipe, GENERIC_READ + GENERIC_WRITE, 0,
|
|
NULL, OPEN_EXISTING,
|
|
SECURITY_SQOS_PRESENT + SECURITY_IMPERSONATION + FILE_FLAG_OVERLAPPED,
|
|
NULL );
|
|
|
|
// Map result to local handle table and return index...
|
|
if ( hPipe != INVALID_HANDLE_VALUE ) {
|
|
if ( ++nextId >= ENTRY_COUNT(connTbl) ) nextId = 1;
|
|
for ( int i = nextId, ctr = 1;
|
|
ctr++ < ENTRY_COUNT(connTbl) && connTbl[i].handle;
|
|
i = i >= ENTRY_COUNT(connTbl)? 1 : i + 1 ) ;
|
|
if ( ctr >= ENTRY_COUNT(connTbl) ) {
|
|
connTbl[0].lastError = PCERROR_TOO_MANY_CONNECTIONS;
|
|
CloseHandle( hPipe );
|
|
return 0;
|
|
}
|
|
if ( !buffer ) {
|
|
buffer = new char[bufSize];
|
|
if ( buffer ) connTbl[i].flags |= PCAPIFLAG_FREEBUFFER;
|
|
else {
|
|
connTbl[0].lastError = ERROR_NOT_ENOUGH_MEMORY;
|
|
CloseHandle( hPipe );
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
_tcscpy( connTbl[i].name, pipe );
|
|
connTbl[i].handle = hPipe;
|
|
connTbl[i].connCount = 1;
|
|
connTbl[i].connTime = time( NULL );
|
|
connTbl[i].lastError = PCERROR_SUCCESS;
|
|
connTbl[i].buffer = buffer;
|
|
connTbl[i].bufSize = bufSize;
|
|
connTbl[i].timeout = 5000;
|
|
memset( &connTbl[i].overlap, 0, sizeof(connTbl[i].overlap) );
|
|
connTbl[i].overlap.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
|
|
return i;
|
|
}
|
|
}
|
|
|
|
DWORD lErr = GetLastError();
|
|
connTbl[0].lastError = (lErr == ERROR_FILE_NOT_FOUND)? PCERROR_SERVICE_NOT_RUNNING : lErr;
|
|
return 0;
|
|
}
|
|
|
|
//======================================================================================//
|
|
// PCClose -- break connection to PC on previously connected machine.
|
|
// Returns: TRUE on success.
|
|
// FALSE on failure, use PCGetLastError.
|
|
// Arguments: 0) PCid from PCOpen,
|
|
//======================================================================================//
|
|
BOOL PCClose( PCid target )
|
|
{
|
|
BOOL rc = PCIsValidPCId( target );
|
|
|
|
if ( rc ) {
|
|
if ( !CloseHandle( connTbl[target].handle ) ) {
|
|
connTbl[target].lastError = GetLastError();
|
|
rc = FALSE;
|
|
}
|
|
if ( connTbl[target].flags & PCAPIFLAG_FREEBUFFER ) {
|
|
delete [] connTbl[target].buffer;
|
|
}
|
|
connTbl[target].handle = connTbl[target].buffer = NULL;
|
|
connTbl[target].flags = connTbl[target].bufSize = 0;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
//======================================================================================//
|
|
// PCGetLastError -- return last error reported for a target
|
|
// Returns: last PC API error for this client.
|
|
// Arguments: 0) PCid from PCOpen,
|
|
//======================================================================================//
|
|
PCULONG32 PCGetLastError( PCid target )
|
|
{
|
|
if ( target >= 0 && target < ENTRY_COUNT(connTbl) )
|
|
return connTbl[target].lastError;
|
|
else
|
|
return PCERROR_INVALID_PCID;
|
|
}
|
|
|
|
//======================================================================================//
|
|
// PCGetServiceInfo -- get ProcCon Service indentification and parameters.
|
|
// Returns: TRUE on success.
|
|
// FALSE on failure, use PCGetLastError.
|
|
// Arguments: 0) PCid from PCOpen,
|
|
// 1) pointer to area to receive system information,
|
|
// 2) size of this area in bytes,
|
|
//======================================================================================//
|
|
BOOL PCGetServiceInfo( PCid target, PCSystemInfo *sysInfo, PCINT32 nByteCount )
|
|
{
|
|
if ( !PCIsValidPCId( target ) ) return FALSE;
|
|
|
|
// Build request...
|
|
PCBuildReq( target, PCOP_GET, PCTYPE_SERVERINFO );
|
|
|
|
// Send request, receive response and verify success...
|
|
if ( !PCSendReceive( target ) ) return FALSE;
|
|
|
|
// Pass appropriate data back to caller...
|
|
PCCopyData( target, sysInfo, 1, nByteCount );
|
|
return TRUE;
|
|
}
|
|
|
|
//======================================================================================//
|
|
// PCControlFunction -- various ProcCon control functions to support restore, etc.
|
|
// Returns: TRUE on success.
|
|
// FALSE on failure, use PCGetLastError.
|
|
// Arguments: 0) PCid from PCOpen,
|
|
// 1) control flags to describe desired control functions,
|
|
// 2) [optional] data that modifies control function.
|
|
//======================================================================================//
|
|
BOOL PCControlFunction( PCid target, PCINT32 ctlFlags, PCINT32 ctlData )
|
|
{
|
|
if ( !PCIsValidPCId( target ) ) return FALSE;
|
|
|
|
// Build request...
|
|
PCBuildReq( target, PCOP_CTL, PCTYPE_CONTROL, NULL, 0, 0, ctlFlags, ctlData );
|
|
|
|
// Send request, receive response and pass back result...
|
|
return PCSendReceive( target );
|
|
}
|
|
|
|
//======================================================================================//
|
|
// PCSetServiceParms -- set ProcCon Service parameters.
|
|
// Returns: TRUE on success.
|
|
// FALSE on failure, use PCGetLastError.
|
|
// Arguments: 0) PCid from PCOpen,
|
|
// 1) pointer to area containing new system parameters,
|
|
// 2) size of this area in bytes,
|
|
//======================================================================================//
|
|
BOOL PCSetServiceParms( PCid target, PCSystemParms *sysParms, PCINT32 nByteCount )
|
|
{
|
|
if ( !PCIsValidPCId( target ) ) return FALSE;
|
|
|
|
// Apply timeout locally...
|
|
// We apply our value right away so that it covers this call...
|
|
// If out of range, reject it and skip calling the server.
|
|
if ( sysParms->timeoutValueMs < PC_MIN_TIMEOUT ||
|
|
sysParms->timeoutValueMs > PC_MAX_TIMEOUT ) {
|
|
connTbl[target].lastError = PCERROR_INVALID_PARAMETER;
|
|
return FALSE;
|
|
}
|
|
else
|
|
connTbl[target].timeout = sysParms->timeoutValueMs;
|
|
|
|
// Build request...
|
|
PCBuildReq( target, PCOP_REP, PCTYPE_SERVERPARMS, sysParms,
|
|
sizeof(PCSystemParms), nByteCount );
|
|
|
|
// Send request, receive response and pass back result...
|
|
BOOL rc = PCSendReceive( target );
|
|
return rc;
|
|
}
|
|
|
|
//======================================================================================//
|
|
// PCKillProcess -- kill the specified process
|
|
// Returns: TRUE on success.
|
|
// FALSE on failure, use PCGetLastError.
|
|
// Arguments: 0) PCid from PCOpen,
|
|
// 1) Pid of the process to kill from PCGetProcList statistics,
|
|
// 2) Create time of the process to kill from PCGetProcList statistics.
|
|
//======================================================================================//
|
|
BOOL PCKillProcess( PCid target, PID_VALUE processPid, TIME_VALUE createTime )
|
|
{
|
|
if ( !PCIsValidPCId( target ) ) return FALSE;
|
|
|
|
// Build request...
|
|
PCBuildReq( target, PCOP_KILL, PCTYPE_PROCLIST, &createTime, sizeof(createTime), 0, processPid );
|
|
|
|
// Send request, receive response and pass back result...
|
|
return PCSendReceive( target );
|
|
}
|
|
|
|
//======================================================================================//
|
|
// PCKillJob -- kill the specified job
|
|
// Returns: TRUE on success.
|
|
// FALSE on failure, use PCGetLastError.
|
|
// Arguments: 0) PCid from PCOpen,
|
|
// 1) Name of the job to kill.
|
|
//======================================================================================//
|
|
BOOL PCKillJob( PCid target, JOB_NAME jobName )
|
|
{
|
|
if ( !PCIsValidPCId( target ) ) return FALSE;
|
|
|
|
// Build request...
|
|
PCBuildReq( target, PCOP_KILL, PCTYPE_JOBLIST, jobName, sizeof(JOB_NAME) );
|
|
|
|
// Send request, receive response and pass back result...
|
|
return PCSendReceive( target );
|
|
}
|
|
|
|
//======================================================================================//
|
|
// PCGetNameRules -- get fixed-format table containing name rules, one entry per rule.
|
|
// Returns: 1 or greater to indicate the number of items in the response (may be incomplete).
|
|
// -1 on failure, use PCGetLastError.
|
|
// Arguments: 0) PCid from PCOpen,
|
|
// 1) pointer to table to receive name rule list,
|
|
// 2) size of this table in bytes,
|
|
// 3) [optional, default is 0] index of first entry to return (0-relative),
|
|
// 4) [optional] location to store update counter to be supplied on update.
|
|
// Notes: If PCGetLastError returns PCERROR_MORE_DATA, there is more data to retrieve.
|
|
// Name rule order is significant: rules are executed from top to bottom.
|
|
//======================================================================================//
|
|
PCINT32 PCGetNameRules( PCid target, PCNameRule *pRuleList, PCINT32 nByteCount,
|
|
PCINT32 nFirst, PCINT32 *nUpdateCtr )
|
|
{
|
|
if ( !PCIsValidPCId( target ) ) return -1;
|
|
|
|
// Build request...
|
|
PCINT32 maxItemsRequested = PCMaxItemCount( target, nByteCount, sizeof(PCNameRule) );
|
|
PCBuildReq( target, PCOP_GET, PCTYPE_NAMERULE,
|
|
pRuleList, sizeof(PCNameRule), nByteCount,
|
|
0, maxItemsRequested, nFirst );
|
|
|
|
// Send request, receive response and verify success...
|
|
if ( !PCSendReceive( target ) ) return -1;
|
|
|
|
// Pass appropriate data back to caller...
|
|
return PCCopyData( target, pRuleList, maxItemsRequested, nByteCount, nUpdateCtr );
|
|
}
|
|
|
|
//======================================================================================//
|
|
// PCGetProcSummary -- get fixed-format table summarizing all defined processes.
|
|
// Returns: 0 or greater to indicate the number of items in the response (may be incomplete).
|
|
// -1 on failure, use PCGetLastError.
|
|
// Arguments: 0) PCid from PCOpen,
|
|
// 1) pointer to table to receive rule summary list, first entry indicates start point,
|
|
// 2) size of this table in bytes.
|
|
// 3) a set of flags used to further specify or limit list operation.
|
|
// Notes: If PCGetLastError returns PCERROR_MORE_DATA, there is more data to retrieve.
|
|
// List entries are in alphabetic order by process name.
|
|
//======================================================================================//
|
|
PCINT32 PCGetProcSummary( PCid target, PCProcSummary *pProcList, PCINT32 nByteCount, PCUINT32 listFlags )
|
|
{
|
|
if ( !PCIsValidPCId( target ) ) return -1;
|
|
|
|
// Build request...
|
|
PCINT32 maxItemsRequested = PCMaxItemCount( target, nByteCount, sizeof(PCProcSummary) );
|
|
PCBuildReq( target, PCOP_GET, PCTYPE_PROCSUMMARY,
|
|
pProcList, sizeof(PCProcSummary), nByteCount, listFlags, maxItemsRequested );
|
|
|
|
// Send request, receive response and verify success...
|
|
if ( !PCSendReceive( target ) ) return -1;
|
|
|
|
// Pass appropriate data back to caller...
|
|
return PCCopyData( target, pProcList, maxItemsRequested, nByteCount );
|
|
}
|
|
|
|
//======================================================================================//
|
|
// PCGetJobSummary -- get fixed-format table summarizing all defined jobs.
|
|
// Returns: 0 or greater to indicate the number of items in the response (may be incomplete).
|
|
// -1 on failure, use PCGetLastError.
|
|
// Arguments: 0) PCid from PCOpen,
|
|
// 1) pointer to table to receive rule summary list, first entry indicates start point,
|
|
// 2) size of this table in bytes.
|
|
// 3) a set of flags used to further specify or limit list operation.
|
|
// Notes: If PCGetLastError returns PCERROR_MORE_DATA, there is more data to retrieve.
|
|
// List entries are in alphabetic order by job name.
|
|
//======================================================================================//
|
|
PCINT32 PCGetJobSummary( PCid target, PCJobSummary *pJobList, PCINT32 nByteCount, PCUINT32 listFlags )
|
|
{
|
|
if ( !PCIsValidPCId( target ) ) return -1;
|
|
|
|
// Build request...
|
|
PCINT32 maxItemsRequested = PCMaxItemCount( target, nByteCount, sizeof(PCJobSummary) );
|
|
PCBuildReq( target, PCOP_GET, PCTYPE_JOBSUMMARY,
|
|
pJobList, sizeof(PCJobSummary), nByteCount, listFlags, maxItemsRequested );
|
|
|
|
// Send request, receive response and verify success...
|
|
if ( !PCSendReceive( target ) ) return -1;
|
|
|
|
// Pass appropriate data back to caller...
|
|
return PCCopyData( target, pJobList, maxItemsRequested, nByteCount );
|
|
}
|
|
|
|
//======================================================================================//
|
|
// PCGetJobList -- get list of all defined jobs, both running and not.
|
|
// Returns: 0 or greater to indicate the number of items in the response (may be incomplete).
|
|
// -1 on failure, use PCGetLastError.
|
|
// Arguments: 0) PCid from PCOpen,
|
|
// 1) pointer to structure to receive job list,
|
|
// 2) size of this structure in bytes.
|
|
// 3) a TRUE/FALSE flag indicating if only running jobs should be included.
|
|
// Notes: If PCGetLastError returns PCERROR_MORE_DATA, there is more data to retrieve.
|
|
// List entries are in alphabetic order by job name.
|
|
//======================================================================================//
|
|
PCINT32 PCGetJobList( PCid target, PCJobListItem *pJobList, PCINT32 nByteCount, PCUINT32 listFlags )
|
|
{
|
|
if ( !PCIsValidPCId( target ) ) return -1;
|
|
|
|
// Build request...
|
|
PCINT32 maxItemsRequested = PCMaxItemCount( target, nByteCount, sizeof(PCJobListItem) );
|
|
PCBuildReq( target, PCOP_GET, PCTYPE_JOBLIST,
|
|
pJobList, sizeof(PCJobListItem), nByteCount, listFlags, maxItemsRequested );
|
|
|
|
// Send request, receive response and verify success...
|
|
if ( !PCSendReceive( target ) ) return -1;
|
|
|
|
// Pass appropriate data back to caller...
|
|
return PCCopyData( target, pJobList, maxItemsRequested, nByteCount );
|
|
}
|
|
|
|
//======================================================================================//
|
|
// PCGetProcList -- get list of all defined process names, both running and not.
|
|
// Returns: 0 or greater to indicate the number of items in the response (may be incomplete).
|
|
// -1 on failure, use PCGetLastError.
|
|
// Arguments: 0) PCid from PCOpen,
|
|
// 1) pointer to structure to receive process list,
|
|
// 2) size of this structure in bytes.
|
|
// 3) a TRUE/FALSE flag indicating if only running jobs should be included.
|
|
// Notes: If PCGetLastError returns PCERROR_MORE_DATA, there is more data to retrieve.
|
|
// List entries are in alphabetic order by process name.
|
|
//======================================================================================//
|
|
PCINT32 PCGetProcList( PCid target, PCProcListItem *pProcList, PCINT32 nByteCount, PCUINT32 listFlags )
|
|
{
|
|
if ( !PCIsValidPCId( target ) ) return -1;
|
|
|
|
// Build request...
|
|
PCINT32 maxItemsRequested = PCMaxItemCount( target, nByteCount, sizeof(PCProcListItem) );
|
|
PCBuildReq( target, PCOP_GET, PCTYPE_PROCLIST,
|
|
pProcList, sizeof(PCProcListItem), nByteCount, listFlags, maxItemsRequested );
|
|
|
|
// Send request, receive response and verify success...
|
|
if ( !PCSendReceive( target ) ) return -1;
|
|
|
|
// Pass appropriate data back to caller...
|
|
return PCCopyData( target, pProcList, maxItemsRequested, nByteCount );
|
|
}
|
|
|
|
//======================================================================================//
|
|
// PCGetProcDetail -- get full management and descriptive data associated with a process name.
|
|
// Returns: TRUE on success.
|
|
// FALSE on failure, use PCGetLastError.
|
|
// Arguments: 0) PCid from PCOpen,
|
|
// 1) pointer to structure to receive process data,
|
|
// 2) size of this structure in bytes,
|
|
// 3) [optional] location to store update counter to be supplied on update.
|
|
// Note: If the process is a member of a job, the job's management rules will be
|
|
// used instead of the process rules unless the job definition is missing.
|
|
//======================================================================================//
|
|
BOOL PCGetProcDetail( PCid target, PCProcDetail *pProcDetail, PCINT32 nByteCount, PCINT32 *nUpdateCtr )
|
|
{
|
|
if ( !PCIsValidPCId( target ) ) return FALSE;
|
|
|
|
// Build request...
|
|
PCBuildReq( target, PCOP_GET, PCTYPE_PROCDETAIL, pProcDetail,
|
|
offsetof(PCProcDetail, vLength), nByteCount );
|
|
|
|
// Send request, receive response and verify success...
|
|
if ( !PCSendReceive( target ) ) return FALSE;
|
|
|
|
// Pass appropriate data back to caller...
|
|
PCCopyData( target, pProcDetail, 1, nByteCount, nUpdateCtr );
|
|
return TRUE;
|
|
}
|
|
|
|
//======================================================================================//
|
|
// PCGetJobDetail -- get full management and descriptive data associated with a job name.
|
|
// Returns: TRUE on success.
|
|
// FALSE on failure, use PCGetLastError.
|
|
// Arguments: 0) PCid from PCOpen,
|
|
// 1) pointer to structure to receive job data,
|
|
// 2) size of this structure in bytes,
|
|
// 3) [optional] location to store update counter to be supplied on update.
|
|
//======================================================================================//
|
|
BOOL PCGetJobDetail( PCid target, PCJobDetail *pJobDetail, PCINT32 nByteCount, PCINT32 *nUpdateCtr )
|
|
{
|
|
if ( !PCIsValidPCId( target ) ) return FALSE;
|
|
|
|
// Build request...
|
|
PCBuildReq( target, PCOP_GET, PCTYPE_JOBDETAIL, pJobDetail,
|
|
offsetof(PCProcDetail, vLength), nByteCount );
|
|
|
|
// Send request, receive response and verify success...
|
|
if ( !PCSendReceive( target ) ) return FALSE;
|
|
|
|
// Pass appropriate data back to caller...
|
|
PCCopyData( target, pJobDetail, 1, nByteCount, nUpdateCtr );
|
|
return TRUE;
|
|
}
|
|
|
|
//======================================================================================//
|
|
// PCAddNameRule -- add a name rule to the name rule table.
|
|
// Returns: 0 or greater to indicate the number of items in the response (may be incomplete).
|
|
// -1 on failure, use PCGetLastError.
|
|
// Arguments: 0) PCid from PCOpen,
|
|
// 1) pointer to name rule to add,
|
|
// 2) index of name rule line BEFORE which this addition is to occur (0-based),
|
|
// 3) update counter returned from PCGetNameRules,
|
|
// 4-6) [optional] same args as PCGetNameRules to return updated name rule table.
|
|
//======================================================================================//
|
|
PCINT32 PCAddNameRule( PCid target, PCNameRule *pRule, PCINT32 nIndex, PCINT32 nUpdateCtr,
|
|
PCNameRule *pRuleList, PCINT32 nByteCount, PCINT32 nFirst, PCINT32 *nNewUpdateCtr )
|
|
{
|
|
if ( !PCIsValidPCId( target ) ) return -1;
|
|
|
|
// Build request...
|
|
PCINT32 maxItemsRequested = PCMaxItemCount( target, nByteCount, sizeof(PCNameRule) );
|
|
PCBuildReq( target, PCOP_ADD, PCTYPE_NAMERULE,
|
|
pRule, sizeof(PCNameRule), nByteCount,
|
|
nIndex, maxItemsRequested, nFirst, nUpdateCtr );
|
|
if ( pRuleList ) PCSetReqFlag( target, PCREQFLAG_DOLIST );
|
|
|
|
// Send request, receive response and verify success...
|
|
if ( !PCSendReceive( target ) ) return -1;
|
|
|
|
// Pass appropriate data back to caller...
|
|
if ( pRuleList )
|
|
return PCCopyData( target, pRuleList, maxItemsRequested, nByteCount, nNewUpdateCtr );
|
|
else return 0;
|
|
}
|
|
|
|
//======================================================================================//
|
|
// PCReplNameRule -- Replace a name rule in the name rule table.
|
|
// Returns: 0 or greater to indicate the number of items in the response (may be incomplete).
|
|
// -1 on failure, use PCGetLastError.
|
|
// Arguments: 0) PCid from PCOpen,
|
|
// 1) pointer to name rule replacement data,
|
|
// 2) index of name rule line to replace (0-based),
|
|
// 3) update counter returned from PCGetNameRules,
|
|
// 4-6) [optional] same args as PCGetNameRules to return updated name rule table.
|
|
//======================================================================================//
|
|
PCINT32 PCReplNameRule( PCid target, PCNameRule *pRule, PCINT32 nIndex, PCINT32 nUpdateCtr,
|
|
PCNameRule *pRuleList, PCINT32 nByteCount, PCINT32 nFirst, PCINT32 *nNewUpdateCtr )
|
|
{
|
|
if ( !PCIsValidPCId( target ) ) return -1;
|
|
|
|
// Build request...
|
|
PCINT32 maxItemsRequested = PCMaxItemCount( target, nByteCount, sizeof(PCNameRule) );
|
|
PCBuildReq( target, PCOP_REP, PCTYPE_NAMERULE,
|
|
pRule, sizeof(PCNameRule), nByteCount,
|
|
nIndex, maxItemsRequested, nFirst, nUpdateCtr );
|
|
if ( pRuleList ) PCSetReqFlag( target, PCREQFLAG_DOLIST );
|
|
|
|
// Send request, receive response and verify success...
|
|
if ( !PCSendReceive( target ) ) return -1;
|
|
|
|
// Pass appropriate data back to caller...
|
|
if ( pRuleList )
|
|
return PCCopyData( target, pRuleList, maxItemsRequested, nByteCount, nNewUpdateCtr );
|
|
else return 0;
|
|
}
|
|
|
|
//======================================================================================//
|
|
// PCDeleteNameRule -- Delete a name rule from the name rule table.
|
|
// Returns: 0 or greater to indicate the number of items in the response (may be incomplete).
|
|
// -1 on failure, use PCGetLastError.
|
|
// Arguments: 0) PCid from PCOpen,
|
|
// 1) index of name rule line to delete (0-based),
|
|
// 2) update counter returned from PCGetNameRules,
|
|
// 3-5) [optional] same args as PCGetNameRules to return updated name rule table.
|
|
//======================================================================================//
|
|
PCINT32 PCDeleteNameRule( PCid target, PCINT32 nIndex, PCINT32 nUpdateCtr,
|
|
PCNameRule *pRuleList, PCINT32 nByteCount, PCINT32 nFirst, PCINT32 *nNewUpdateCtr )
|
|
{
|
|
if ( !PCIsValidPCId( target ) ) return -1;
|
|
|
|
// Build request...
|
|
PCINT32 maxItemsRequested = PCMaxItemCount( target, nByteCount, sizeof(PCNameRule) );
|
|
PCBuildReq( target, PCOP_DEL, PCTYPE_NAMERULE,
|
|
NULL, 0, nByteCount,
|
|
nIndex, maxItemsRequested, nFirst, nUpdateCtr );
|
|
if ( pRuleList ) PCSetReqFlag( target, PCREQFLAG_DOLIST );
|
|
|
|
// Send request, receive response and verify success...
|
|
if ( !PCSendReceive( target ) ) return -1;
|
|
|
|
// Pass appropriate data back to caller...
|
|
if ( pRuleList )
|
|
return PCCopyData( target, pRuleList, maxItemsRequested, nByteCount, nNewUpdateCtr );
|
|
else return 0;
|
|
}
|
|
|
|
//======================================================================================//
|
|
// PCSwapNameRules -- Swap the order of two adjacent entries in the name rule table.
|
|
// Note: This API is needed because the order of entires in the table is significant.
|
|
// Returns: 0 or greater to indicate the number of items in the response (may be incomplete).
|
|
// -1 on failure, use PCGetLastError.
|
|
// Arguments: 0) PCid from PCOpen,
|
|
// 1) index of name rule line to swap with line index+1 (0-based),
|
|
// 2) update counter returned from PCGetNameRules,
|
|
// 3-5) [optional] same args as PCGetNameRules to return updated name rule table.
|
|
//======================================================================================//
|
|
PCINT32 PCSwapNameRules( PCid target, PCINT32 nIndex, PCINT32 nUpdateCtr,
|
|
PCNameRule *pRuleList, PCINT32 nByteCount, PCINT32 nFirst, PCINT32 *nNewUpdateCtr )
|
|
{
|
|
if ( !PCIsValidPCId( target ) ) return -1;
|
|
|
|
// Build request...
|
|
PCINT32 maxItemsRequested = PCMaxItemCount( target, nByteCount, sizeof(PCNameRule) );
|
|
PCBuildReq( target, PCOP_ORD, PCTYPE_NAMERULE,
|
|
NULL, 0, nByteCount, nIndex, maxItemsRequested, nFirst, nUpdateCtr );
|
|
if ( pRuleList ) PCSetReqFlag( target, PCREQFLAG_DOLIST );
|
|
|
|
// Send request, receive response and verify success...
|
|
if ( !PCSendReceive( target ) ) return -1;
|
|
|
|
// Pass appropriate data back to caller...
|
|
if ( pRuleList )
|
|
return PCCopyData( target, pRuleList, maxItemsRequested, nByteCount, nNewUpdateCtr );
|
|
else return 0;
|
|
}
|
|
|
|
//======================================================================================//
|
|
// PCAddProcDetail -- add a new process to the process management database.
|
|
// Returns: TRUE on success.
|
|
// FALSE on failure, use PCGetLastError.
|
|
// Arguments: 0) PCid from PCOpen,
|
|
// 1) pointer to process detail to add, name must not exist.
|
|
// 2) [optional] pointer to buffer to retrieve updated proc summary for this entry.
|
|
// Note: No update counter is needed for adding detail since add fails if the name
|
|
// exists.
|
|
//======================================================================================//
|
|
BOOL PCAddProcDetail( PCid target, PCProcDetail *pProcDetail, PCProcSummary *pProcList )
|
|
{
|
|
if ( !PCIsValidPCId( target ) ) return FALSE;
|
|
|
|
// Build request...
|
|
PCBuildReq( target, PCOP_ADD, PCTYPE_PROCDETAIL, pProcDetail,
|
|
(PCINT16) (offsetof(PCProcDetail, vData) + pProcDetail->vLength) );
|
|
if ( pProcList ) PCSetReqFlag( target, PCREQFLAG_DOLIST );
|
|
|
|
// Send request, receive response and verify success...
|
|
if ( !PCSendReceive( target ) ) return FALSE;
|
|
|
|
// Pass appropriate data back to caller...
|
|
if ( pProcList )
|
|
PCCopyData( target, pProcList, 1, sizeof(PCProcSummary) );
|
|
return TRUE;
|
|
}
|
|
|
|
//======================================================================================//
|
|
// PCDeleteProcDetail -- Delete a process from the process management database.
|
|
// Returns: TRUE on success.
|
|
// FALSE on failure, use PCGetLastError.
|
|
// Arguments: 0) PCid from PCOpen,
|
|
// 1) pointer to process detail to Delete, name must exist,
|
|
// Note: No update counter is needed for deleting since delete fails if the name
|
|
// doesn't exist.
|
|
//======================================================================================//
|
|
BOOL PCDeleteProcDetail( PCid target, PCProcDetail *pProcDetail )
|
|
{
|
|
if ( !PCIsValidPCId( target ) ) return FALSE;
|
|
|
|
// Build request (note that only the summary portion is included)...
|
|
PCBuildReq( target, PCOP_DEL, PCTYPE_PROCDETAIL, pProcDetail, sizeof( PCProcSummary ) );
|
|
|
|
// Send request, receive response and verify success...
|
|
return PCSendReceive( target );
|
|
}
|
|
|
|
//======================================================================================//
|
|
// PCReplProcDetail -- Replace a process in the process management database.
|
|
// Returns: TRUE on success.
|
|
// FALSE on failure, use PCGetLastError.
|
|
// Arguments: 0) PCid from PCOpen,
|
|
// 1) pointer to process detail to replace, name must exist,
|
|
// 2) update counter from PCGetProcDetail.
|
|
// 3) [optional] pointer to buffer to retrieve updated proc summary for this entry.
|
|
//======================================================================================//
|
|
BOOL PCReplProcDetail( PCid target, PCProcDetail *pProcDetail, PCINT32 nUpdateCtr, PCProcSummary *pProcList )
|
|
{
|
|
if ( !PCIsValidPCId( target ) ) return FALSE;
|
|
|
|
// Build request...
|
|
PCBuildReq( target, PCOP_REP, PCTYPE_PROCDETAIL, pProcDetail,
|
|
(PCINT16) (offsetof(PCProcDetail, vData) + pProcDetail->vLength), 0, 0, 1, 0, nUpdateCtr );
|
|
if ( pProcList ) PCSetReqFlag( target, PCREQFLAG_DOLIST );
|
|
|
|
// Send request, receive response and verify success...
|
|
if ( !PCSendReceive( target ) ) return FALSE;
|
|
|
|
// Pass appropriate data back to caller...
|
|
if ( pProcList )
|
|
PCCopyData( target, pProcList, 1, sizeof(PCProcSummary) );
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//======================================================================================//
|
|
// PCAddJobDetail -- add a new job definition to the job management database.
|
|
// Returns: 1 on success (treat as TRUE or as a count if summary item requested).
|
|
// FALSE on failure, use PCGetLastError.
|
|
// Arguments: 0) PCid from PCOpen,
|
|
// 1) pointer to job detail to add, name must not exist,
|
|
// 2) [optional] pointer to buffer to retrieve updated job summary for this entry.
|
|
// Note: No update counter is needed for adding since add fails if the name
|
|
// exists.
|
|
//======================================================================================//
|
|
BOOL PCAddJobDetail( PCid target, PCJobDetail *pJobDetail, PCJobSummary *pJobList )
|
|
{
|
|
if ( !PCIsValidPCId( target ) ) return FALSE;
|
|
|
|
// Build request...
|
|
PCBuildReq( target, PCOP_ADD, PCTYPE_JOBDETAIL, pJobDetail,
|
|
(PCINT16) (offsetof(PCJobDetail, vData) + pJobDetail->vLength) );
|
|
if ( pJobList ) PCSetReqFlag( target, PCREQFLAG_DOLIST );
|
|
|
|
// Send request, receive response and verify success...
|
|
if ( !PCSendReceive( target ) ) return FALSE;
|
|
|
|
// Pass appropriate data back to caller...
|
|
if ( pJobList )
|
|
PCCopyData( target, pJobList, 1, sizeof(PCJobSummary) );
|
|
return TRUE;
|
|
}
|
|
|
|
//======================================================================================//
|
|
// PCDeleteJobDetail -- Delete a job from the job management database.
|
|
// Returns: TRUE on success.
|
|
// FALSE on failure, use PCGetLastError.
|
|
// Arguments: 0) PCid from PCOpen,
|
|
// 1) pointer to job detail to Delete, name must exist,
|
|
// Note: No update counter is needed for deleting since delete fails if the name
|
|
// doesn't exist.
|
|
//======================================================================================//
|
|
BOOL PCDeleteJobDetail( PCid target, PCJobDetail *pJobDetail )
|
|
{
|
|
if ( !PCIsValidPCId( target ) ) return FALSE;
|
|
|
|
// Build request (note that only the summary portion is included)...
|
|
PCBuildReq( target, PCOP_DEL, PCTYPE_JOBDETAIL, pJobDetail, sizeof( PCJobSummary ) );
|
|
|
|
// Send request, receive response and verify success...
|
|
return PCSendReceive( target );
|
|
}
|
|
|
|
//======================================================================================//
|
|
// PCReplJobDetail -- Replace a job in the job management database.
|
|
// Returns: TRUE on success.
|
|
// FALSE on failure, use PCGetLastError.
|
|
// Arguments: 0) PCid from PCOpen,
|
|
// 1) pointer to job detail to replace, name must exist,
|
|
// 2) update counter from PCGetJobDetail.
|
|
// 3) [optional] pointer to buffer to retrieve updated job summary for this entry.
|
|
//======================================================================================//
|
|
BOOL PCReplJobDetail( PCid target, PCJobDetail *pJobDetail, PCINT32 nUpdateCtr, PCJobSummary *pJobList )
|
|
{
|
|
if ( !PCIsValidPCId( target ) ) return FALSE;
|
|
|
|
// Build request...
|
|
PCBuildReq( target, PCOP_REP, PCTYPE_JOBDETAIL, pJobDetail,
|
|
(PCINT16) (offsetof(PCJobDetail, vData) + pJobDetail->vLength), 0, 0, 1, 0, nUpdateCtr );
|
|
if ( pJobList ) PCSetReqFlag( target, PCREQFLAG_DOLIST );
|
|
|
|
// Send request, receive response and verify success...
|
|
if ( !PCSendReceive( target ) ) return FALSE;
|
|
|
|
// Pass appropriate data back to caller...
|
|
if ( pJobList )
|
|
PCCopyData( target, pJobList, 1, sizeof(PCJobSummary) );
|
|
return TRUE;
|
|
}
|