|
|
/*======================================================================================//
| //
|Copyright (c) 1998, 1999 Sequent Computer Systems, Incorporated //
| //
|Description: //
| //
|---------------------------------------------------------------------------------------//
| This file implements the CProcConDB class methods defined in ProcConSvc.h //
|---------------------------------------------------------------------------------------//
| //
|Created: //
| //
| Jarl McDonald 07-98 //
| //
|Revision History: //
| Paul Skoglund 04-2001 //
| -Support Microsoft feature request to add event log reporting for all Proccon //
| rule editing. //
| -Fix bug with restore not flushing old process and group execution rules. //
| Problem appeared if the restore didn't include any process execution rules //
| or group execution rules. //
| Paul Skoglund 05-2001 //
| -Remove rounding to page boundry of working set min and max values. This is //
| now done in the apply functions; this is consistent with the handling of //
| process and job committed memory limits. //
|=======================================================================================*/ #include "ProcConSvc.h"
const TCHAR CProcConDB::PCDB_PREFIX_FLAGS = TEXT('F'); const TCHAR CProcConDB::PCDB_PREFIX_AFFINITY = TEXT('A'); const TCHAR CProcConDB::PCDB_PREFIX_PRIORITY = TEXT('P'); const TCHAR CProcConDB::PCDB_PREFIX_MINWS = TEXT('L'); const TCHAR CProcConDB::PCDB_PREFIX_MAXWS = TEXT('H'); const TCHAR CProcConDB::PCDB_PREFIX_SCHEDCLASS = TEXT('S'); const TCHAR CProcConDB::PCDB_PREFIX_PROCTIME = TEXT('T'); const TCHAR CProcConDB::PCDB_PREFIX_JOBTIME = TEXT('U'); const TCHAR CProcConDB::PCDB_PREFIX_ACTIVEPROCS = TEXT('C'); const TCHAR CProcConDB::PCDB_PREFIX_PROCMEMORY = TEXT('M'); const TCHAR CProcConDB::PCDB_PREFIX_JOBMEMORY = TEXT('N');
const TCHAR CProcConDB::BEG_BRACKET = TEXT('{'); // leading char in rules stored in DB
const TCHAR CProcConDB::END_BRACKET = TEXT('}'); // trailing char in rules stored in DB
const TCHAR CProcConDB::FIELD_SEP = TEXT(','); // separates fields in rules stored in DB
const TCHAR CProcConDB::STRING_DELIM = TEXT('"'); // delimits text strings stored in DB
const TCHAR CProcConDB::RULE_MATCHONE = TEXT('?'); const TCHAR CProcConDB::RULE_MATCHANY = TEXT('*'); const TCHAR CProcConDB::NAME_IS_PGM[] = COPY_PGM_NAME; const TCHAR CProcConDB::NAME_IS_DIR[] = COPY_DIR_NAME; const TCHAR CProcConDB::HIDE_PROC_PATTERN[] = HIDE_THIS_PROC; const TCHAR CProcConDB::PATTERN_CHARS[] = TEXT("PDH"); PCNameRule CProcConDB::DEFAULT_NAME_RULE = { { RULE_MATCHANY, 0 }, COPY_PGM_NAME, { 0 }, MATCH_PGM };
// CProcConDB Constructor
// Note: this runs as part of service start so keep it quick!
CProcConDB::CProcConDB( PCUINT32 pageSize ) : m_fmtNameRules( NULL ), m_intNameRules( NULL ), m_parmRegKey( NULL ), m_procRegKey( NULL ), m_jobRegKey( NULL ), m_dbEvent( NULL ), m_parmEvent( NULL ), m_procSummary( NULL ), m_jobSummary( NULL ), m_numNameRules( 0 ), m_numProcRules( 0 ), m_numJobRules( 0 ), m_updCtrName( 1 ), m_updCtrProc( 1 ), m_updCtrJob( 1 ), m_pollDelay( 60 ), m_pageSize( pageSize ), m_cMgr( NULL ), m_LogRuleEdits( TRUE ) {
InitializeCriticalSection( &m_dbCSNameRule ); InitializeCriticalSection( &m_dbCSProcRule ); InitializeCriticalSection( &m_dbCSJobRule ); memset( m_curProfile, 0, sizeof(m_curProfile) );
memcpy( DEFAULT_NAME_RULE.description, PROCCON_DEFAULT_NAMERULE_DESC, sizeof(DEFAULT_NAME_RULE.description) );
if ( !PCBuildAdminSecAttr( m_secAttr ) ) return;
if ( !OpenParmKey() ) return; if ( !OpenProcKey() ) return; if ( !OpenJobKey() ) return;
// Get (or set to default if it doesn't exist) basic parameters...
PCULONG32 dfltPoll = m_pollDelay; // save default
m_lastRegError = GetPCParm( PROCCON_DATA_POLLDELAY, &m_pollDelay ); if ( m_lastRegError != ERROR_SUCCESS ) { RegError( TEXT("Load/Set Parameter"), PROCCON_DATA_POLLDELAY ); return; } if ( m_pollDelay < PC_MIN_POLL_DELAY || m_pollDelay > PC_MAX_POLL_DELAY ) // ensure sanity
m_pollDelay = dfltPoll; m_pollDelay *= 1000; // convert to milliseconds
m_dbEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); m_parmEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); if ( !m_dbEvent || !m_parmEvent ) { // Should never happen
PCLogUnExError( m_dbEvent? TEXT("RegEvent") : TEXT("DBEvent"), TEXT("CreateEvent") ); return; }
m_lastRegError = RegNotifyChangeKeyValue( m_parmRegKey, TRUE, REG_NOTIFY_CHANGE_NAME + REG_NOTIFY_CHANGE_LAST_SET, m_parmEvent, TRUE ); if ( m_lastRegError != ERROR_SUCCESS ) { // Should never happen
RegError( TEXT("RegNotifyChangeKeyValue") ); CloseHandle( m_parmEvent ); m_parmEvent = NULL; return; } }
// CProcConDB Destructor
CProcConDB::~CProcConDB( void ) { if ( m_fmtNameRules ) delete [] m_fmtNameRules; if ( m_intNameRules ) delete [] m_intNameRules;
if ( m_parmRegKey ) RegCloseKey( m_parmRegKey ); if ( m_procRegKey ) RegCloseKey( m_procRegKey ); if ( m_jobRegKey ) RegCloseKey( m_jobRegKey ); if ( m_dbEvent ) CloseHandle( m_dbEvent ); if ( m_parmEvent ) CloseHandle( m_parmEvent );
PCFreeSecAttr( m_secAttr );
DeleteCriticalSection( &m_dbCSNameRule ); DeleteCriticalSection( &m_dbCSProcRule ); DeleteCriticalSection( &m_dbCSJobRule ); }
//--------------------------------------------------------------------------------------------//
// Function to determine if all CProcConDB initial conditions have been met //
// Input: None //
// Returns: TRUE if ready, FALSE if not //
//--------------------------------------------------------------------------------------------//
BOOL CProcConDB::ReadyToRun( void ) { return m_parmRegKey && m_procRegKey && m_jobRegKey && m_dbEvent && m_parmEvent && m_secAttr.lpSecurityDescriptor; }
//--------------------------------------------------------------------------------------------//
// Function to create/open a registry key at HKEY_LOCAL_MACHINE level //
// Input: key name, location of opened key //
// Returns: ERROR_SUCCESS if successful, error code if not //
// Note: key is created with DB security attributes (established in constructor). //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::CreateKeyAtHKLM( const TCHAR *key, HKEY *hKey ) { if ( !*hKey ) { PCULONG32 regDisp; m_lastRegError = RegCreateKeyEx( HKEY_LOCAL_MACHINE, key, 0, TEXT(""), 0, KEY_READ + KEY_WRITE, &m_secAttr, hKey, ®Disp ); if ( m_lastRegError != ERROR_SUCCESS ) // Should never happen
return RegError( TEXT("RegCreateKeyEx"), key ); } return ERROR_SUCCESS; }
//--------------------------------------------------------------------------------------------//
// Function to drive the loading of all ProcCon rules from the database (NT registry) //
// Input: which rules to load flags //
// Returns: ERROR_SUCCESS if successful, NT error code if not //
// Note: if an error is returned, an error event has been logged. //
// if success is returned, a database event has been pulsed to wake those that care.//
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::LoadRules( PCULONG32 which ) { PCULONG32 rc = ERROR_SUCCESS;
if ( which & LOADFLAG_NAME_RULES ) { EnterCriticalSection( &m_dbCSNameRule ); ++m_updCtrName; rc = LoadNameRules( &m_numNameRules ); LeaveCriticalSection( &m_dbCSNameRule ); }
if ( rc == ERROR_SUCCESS && which & LOADFLAG_PROC_RULES ) { EnterCriticalSection( &m_dbCSProcRule ); ++m_updCtrProc; rc = LoadProcSummary(); LeaveCriticalSection( &m_dbCSProcRule ); } if ( rc == ERROR_SUCCESS && which & LOADFLAG_JOB_RULES ) { EnterCriticalSection( &m_dbCSJobRule ); ++m_updCtrJob; rc = LoadJobSummary(); LeaveCriticalSection( &m_dbCSJobRule ); } if ( rc != ERROR_SUCCESS ) { SetLastError( rc ); PCLogUnExError( TEXT("PCDataBase"), TEXT("LoadRules") ); } else PulseEvent( m_dbEvent ); // Tell others database may have changed
return rc; }
//--------------------------------------------------------------------------------------------//
// Function to load all ProcCon name rules from the database //
// Input: pointer to rule count location, //
// Returns: ERROR_SUCCESS if successful, NT error code if not //
// Note: If an error is returned, an error event has been logged. //
// N.B.: The appropriate critical section mast be held by the CALLER. //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::LoadNameRules( PCULONG32 *count ) {
// Determine size of data and validate type of data...
// If data is missing or of invalid type, set to default (empty) value.
PCULONG32 vType, vSize;
vSize = 0; m_lastRegError = RegQueryValueEx( m_parmRegKey, PROCCON_DATA_NAMERULES, NULL, &vType, NULL, &vSize ); if ( m_lastRegError != ERROR_SUCCESS && m_lastRegError != ERROR_FILE_NOT_FOUND ) return RegError( TEXT("RegQueryValueEx"), PROCCON_DATA_NAMERULES );
if ( vType != REG_MULTI_SZ || m_lastRegError == ERROR_FILE_NOT_FOUND ) { vType = REG_MULTI_SZ; vSize = 2 * sizeof(TCHAR); m_lastRegError = RegSetValueEx( m_parmRegKey, PROCCON_DATA_NAMERULES, NULL, vType, (UCHAR *) TEXT("\0\0"), vSize ); if ( m_lastRegError != ERROR_SUCCESS ) return RegDataError( PROCCON_DATA_NAMERULES ); }
// Allocate space for raw rules...
*count = 0; TCHAR *rawNameRules = new TCHAR[vSize / sizeof(TCHAR)]; if ( !rawNameRules ) return PCLogNoMemory( TEXT("AllocNameRules"), vSize / sizeof(TCHAR) );
// Load the rule data...
m_lastRegError = RegQueryValueEx( m_parmRegKey, PROCCON_DATA_NAMERULES, NULL, &vType, (UCHAR *) rawNameRules, &vSize ); if ( m_lastRegError != ERROR_SUCCESS ) { delete [] rawNameRules; return RegError( TEXT("RegQueryValueEx"), PROCCON_DATA_NAMERULES ); }
// Count strings in the data...
PCULONG32 i, len; TCHAR *p, *end = rawNameRules + vSize / sizeof(TCHAR); if ( *rawNameRules ) { for ( p = rawNameRules; p < end; ++*count, p += _tcslen( p ) + 1 ) ; --*count; // uncount null entry at end due to double-NULL
}
// Delete old copy of rules, if any, and allocate and zero new......
if ( m_fmtNameRules ) delete [] m_fmtNameRules; if ( m_intNameRules ) { delete [] m_intNameRules; m_intNameRules = NULL; } m_fmtNameRules = new PCNameRule[*count + 1]; // include an entry for our default rule
if ( !m_fmtNameRules ) { delete [] rawNameRules; return PCLogNoMemory( TEXT("AllocFmtNameRules"), sizeof(PCNameRule) * (*count + 1) ); }
memset( m_fmtNameRules, 0, sizeof(PCNameRule) * (*count + 1) );
// Build formatted copy from raw copy...
for ( i = 0, p = rawNameRules; i < *count; ++i, p += len + 1 ) { len = _tcslen( p ); // length of this rule
TCHAR *beg = p; // start of rule
TCHAR *end = beg + len; // first byte past rule
if ( *beg++ != BEG_BRACKET || *--end != END_BRACKET ) { delete [] rawNameRules; return RegDataError( PROCCON_DATA_NAMERULES ); } m_fmtNameRules[i].matchType = *beg++; // get type, point to separator
if ( *--end == STRING_DELIM ) { // if we have description, extract it
TCHAR *strend = --end; while ( *end != STRING_DELIM && end > beg ) --end; // find matching delimiter
PCULONG32 len = (PCULONG32) (strend - end); memcpy( m_fmtNameRules[i].description, end + 1, len * sizeof(TCHAR) ); if ( end > beg ) end -= 2; }
TCHAR *procEnd = end; while ( *end != FIELD_SEP && end > beg ) --end; // find last separator in rule
if ( *beg != FIELD_SEP || *end != FIELD_SEP || beg == end ) { delete [] rawNameRules; return RegDataError( PROCCON_DATA_NAMERULES ); }
memcpy( m_fmtNameRules[i].matchString, beg + 1, (UINT32) (end - beg - 1) * sizeof(TCHAR) ); memcpy( m_fmtNameRules[i].procName, end + 1, (UINT32) (procEnd - end) * sizeof(TCHAR) ); }
delete [] rawNameRules; // done with raw data
// Add our default rule at end...
memcpy( &m_fmtNameRules[*count], &DEFAULT_NAME_RULE, sizeof(DEFAULT_NAME_RULE) ); ++*count; // count the default rule
return ERROR_SUCCESS; }
//--------------------------------------------------------------------------------------------//
// Function to store all ProcCon name rules in the database //
// Input: none -- m_fmtNameRules and m_numNameRules are the data source //
// Returns: ERROR_SUCCESS if successful, NT error code if not //
// Notes: 1) If an error is returned, an error event has been logged. //
// 2) The appropriate critical section must be held by the CALLER. //
// 3) The default rule, last in the list, is not stored in the database. //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::StoreNameRules( void ) { TCHAR *rawNameRules = (TCHAR *) new char[(sizeof(PCNameRule) + 10) * m_numNameRules]; if ( !rawNameRules ) return PCLogNoMemory( TEXT("AllocNameRules"), sizeof(PCNameRule) * m_numNameRules ); // Build raw (all character) format of all but last rule.mgmtParms...
TCHAR *loc = rawNameRules; for ( PCULONG32 i = 0; i < m_numNameRules - 1; ++i ) { loc += _stprintf( loc, TEXT("%c%c%c%.*s%c%.*s%c%c%.*s%c%c"), BEG_BRACKET, m_fmtNameRules[i].matchType, FIELD_SEP, MATCH_STRING_LEN, m_fmtNameRules[i].matchString, FIELD_SEP, PROC_NAME_LEN, m_fmtNameRules[i].procName, FIELD_SEP, STRING_DELIM, NAME_DESCRIPTION_LEN, m_fmtNameRules[i].description, STRING_DELIM, END_BRACKET ); *loc++ = 0; // terminate substring with NULL
} *loc++ = 0; // terminated all data by a second NULL
// Store the rule data...
m_lastRegError = RegSetValueEx( m_parmRegKey, PROCCON_DATA_NAMERULES, NULL, REG_MULTI_SZ, (UCHAR *) rawNameRules, (ULONG32) ((UCHAR *) loc - (UCHAR *) rawNameRules) ); delete [] ((char *) rawNameRules);
if ( m_lastRegError != ERROR_SUCCESS ) return RegError( TEXT("RegSetValueEx"), PROCCON_DATA_NAMERULES );
return ERROR_SUCCESS; }
//--------------------------------------------------------------------------------------------//
// Function to load ProcCon process summary data from the database //
// Input: none //
// Returns: ERROR_SUCCESS if successful, NT error code if not //
// Note: If an error is returned, an error event has been logged. //
// N.B.: The appropriate critical section mast be held by the CALLER. //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::LoadProcSummary( void ) { // Delete old data, if any...
if ( m_procSummary ) { delete [] m_procSummary; m_procSummary = NULL; } m_numProcRules = 0;
// Determine how many rules we have, done if none...
m_lastRegError = RegQueryInfoKey( m_procRegKey, NULL, NULL, NULL, &m_numProcRules, NULL, NULL, NULL, NULL, NULL, NULL, NULL ); if ( m_lastRegError != ERROR_SUCCESS ) { // Should never happen
TCHAR key[MAX_PATH]; return RegError( TEXT("RegQueryInfoKey"), BuildProcKey( key ) ); }
// Allocate storage for rules to be loaded...
m_procSummary = new PCProcSummary[m_numProcRules]; if ( !m_procSummary ) { m_numProcRules = 0; return PCLogNoMemory( TEXT("LoadProcessRules"), sizeof(PCProcSummary) * m_numProcRules ); } memset( m_procSummary, 0, sizeof(PCProcSummary) * m_numProcRules );
for ( PCULONG32 i = 0, err = 0; i < m_numProcRules; ++i ) {
PCProcSummary &item = (m_procSummary)[i];
// Get next subkey (proc name)...
FILETIME keyLastWrite; PCULONG32 nameLen = ENTRY_COUNT(item.procName); m_lastRegError = RegEnumKeyEx( m_procRegKey, i, item.procName, &nameLen, NULL, NULL, NULL, &keyLastWrite ); if ( m_lastRegError != ERROR_SUCCESS ) { TCHAR key[MAX_PATH]; err = RegError( TEXT("RegEnumKeyEx"), BuildProcKey( key ) ); break; }
// Open the subkey to get proc details...
HKEY hKeyTemp; m_lastRegError = RegOpenKeyEx( m_procRegKey, item.procName, 0, KEY_READ + KEY_WRITE, &hKeyTemp ); if ( m_lastRegError != ERROR_SUCCESS ) { // Should never happen
TCHAR key[MAX_PATH]; err = RegError( TEXT("RegOpenKeyEx"), BuildProcKey( key ), item.procName ); break; }
err = LoadProcSummaryItem( hKeyTemp, item ); RegCloseKey( hKeyTemp ); }
if ( err ) { delete [] m_procSummary; m_procSummary = NULL; m_numProcRules = 0; } else if ( m_numProcRules > 1 ) qsort( m_procSummary, m_numProcRules, sizeof(PCProcSummary), CompareProcSummary );
return err; }
//--------------------------------------------------------------------------------------------//
// Function to load summary data for a process from the database //
// Input: registry key to use, //
// summary structure to complete //
// Returns: nothing (errors are handled by flagging the rule) //
// Note: NT error code //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::LoadProcSummaryItem( const HKEY &hKey, PCProcSummary &item ) {
// Get job membership information if this is a process name and MemberOf is present and valid..
PCULONG32 byteType, workLen = sizeof(item.memberOfJobName); if ( RegQueryValueEx( hKey, PROCCON_DATA_MEMBEROF, NULL, &byteType, (UCHAR *)item.memberOfJobName, &workLen ) == ERROR_SUCCESS && byteType == REG_SZ ) item.mgmtParms.mFlags |= PCMFLAG_PROC_HAS_JOB_REFERENCE;
return LoadMgmtRules( hKey, item.mgmtParms );
}
//--------------------------------------------------------------------------------------------//
// Function to load job summary data from the database //
// Input: none //
// Returns: ERROR_SUCCESS if successful, NT error code if not //
// Note: If an error is returned, an error event has been logged. //
// N.B.: The appropriate critical section mast be held by the CALLER. //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::LoadJobSummary( void ) { // Delete old data, if any...
if ( m_jobSummary ) { delete [] m_jobSummary; m_jobSummary = NULL; } m_numJobRules = 0;
// Determine how many rules we have, done if none...
m_lastRegError = RegQueryInfoKey( m_jobRegKey, NULL, NULL, NULL, &m_numJobRules, NULL, NULL, NULL, NULL, NULL, NULL, NULL ); if ( m_lastRegError != ERROR_SUCCESS ) { // Should never happen
TCHAR key[MAX_PATH]; return RegError( TEXT("RegQueryInfoKey"), BuildJobKey( key ) ); }
// Allocate storage for rules to be loaded...
m_jobSummary = new PCJobSummary[m_numJobRules]; if ( !m_jobSummary ) { m_numJobRules = 0; return PCLogNoMemory( TEXT("LoadJobessRules"), sizeof(PCJobSummary) * m_numJobRules ); } memset( m_jobSummary, 0, sizeof(PCJobSummary) * m_numJobRules );
for ( PCULONG32 i = 0, err = 0; i < m_numJobRules; ++i ) {
PCJobSummary &item = (m_jobSummary)[i];
// Get next subkey (job name)...
FILETIME keyLastWrite; PCULONG32 nameLen = ENTRY_COUNT(item.jobName); m_lastRegError = RegEnumKeyEx( m_jobRegKey, i, item.jobName, &nameLen, NULL, NULL, NULL, &keyLastWrite ); if ( m_lastRegError != ERROR_SUCCESS ) { TCHAR key[MAX_PATH]; err = RegError( TEXT("RegEnumKeyEx"), BuildJobKey( key ) ); break; }
// Open the subkey to get job details...
HKEY hKeyTemp; m_lastRegError = RegOpenKeyEx( m_jobRegKey, item.jobName, 0, KEY_READ + KEY_WRITE, &hKeyTemp ); if ( m_lastRegError != ERROR_SUCCESS ) { // Should never happen
TCHAR key[MAX_PATH]; err = RegError( TEXT("RegOpenKeyEx"), BuildJobKey( key ), item.jobName ); break; }
err = LoadJobSummaryItem( hKeyTemp, item ); RegCloseKey( hKeyTemp ); }
if ( err ) { delete [] m_jobSummary; m_jobSummary = NULL; m_numJobRules = 0; } else if ( m_numJobRules > 1 ) qsort( m_jobSummary, m_numJobRules, sizeof(PCJobSummary), CompareJobSummary );
return err; }
//--------------------------------------------------------------------------------------------//
// Function to load summary data for a job from the database //
// Input: registry key to use, //
// summary structure to complete //
// Returns: nothing (errors are handled by flagging the rule) //
// Note: NT error code //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::LoadJobSummaryItem( const HKEY &hKey, PCJobSummary &item ) {
return LoadMgmtRules( hKey, item.mgmtParms ); }
//--------------------------------------------------------------------------------------------//
// Function to load management data from the database //
// Input: registry key to use, //
// parameter structure to complete //
// Returns: nothing (errors are handled by flagging the rule) //
// Note: NT or PC error code //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::LoadMgmtRules( const HKEY &hKey, MGMT_PARMS &parms ) {
ULONG byteType; TCHAR work[1024]; PCULONG32 workLen; BOOL gotdata = FALSE;
parms.affinity = parms.minWS = parms.maxWS = 0; parms.mFlags &= ~PCMFLAG_SAVEABLE_BITS; // clear database bits
parms.priority = parms.schedClass = 0; memset( parms.description, 0, sizeof(parms.description) ); memset( parms.future, 0, sizeof(parms.future) );
// If we have a profile name, attempt to retrieve parameters for this profile..
if ( *parms.profileName ) { workLen = sizeof(work); m_lastRegError = RegQueryValueEx( hKey, parms.profileName, NULL, &byteType, ( UCHAR *)work, &workLen ); if ( m_lastRegError == ERROR_SUCCESS ) gotdata = TRUE; else if ( m_lastRegError != ERROR_FILE_NOT_FOUND ) return RegError( TEXT("RegQueryValueEx"), parms.profileName ); }
// If no profile-based data, attempt to retrieve parameters via default name..
if ( !gotdata ) { workLen = sizeof(work); m_lastRegError = RegQueryValueEx( hKey, PROCCON_DATA_DEFAULTRULES, NULL, &byteType, (UCHAR *)work, &workLen );
if ( m_lastRegError != ERROR_SUCCESS ) { parms.mFlags |= PCMFLAG_NORULES; return RegError( TEXT("RegQueryValueEx"), PROCCON_DATA_DEFAULTRULES ); } }
// Verify basic format --- data between braces '{}'...
TCHAR *beg = work, *end = work + workLen / sizeof(TCHAR) - 1; if ( *beg++ != BEG_BRACKET || *--end != END_BRACKET ) { parms.mFlags |= PCMFLAG_BADRULES; return PCERROR_BAD_DATABASE_DATA; } if ( beg == end ) return PCERROR_SUCCESS; // just an entry of "{}"
for ( TCHAR *e = beg; *e; ++e ) { switch ( *e ) { case PCDB_PREFIX_FLAGS: parms.mFlags |= PCGetParmValue( e + 1, &e ); break; case PCDB_PREFIX_AFFINITY: parms.affinity = PCGetParmValue64( e + 1, &e ); break; case PCDB_PREFIX_PRIORITY: parms.priority = PCGetParmValue( e + 1, &e ); break; case PCDB_PREFIX_MINWS: parms.minWS = PCGetParmValue64( e + 1, &e ); break; case PCDB_PREFIX_MAXWS: parms.maxWS = PCGetParmValue64( e + 1, &e ); break; case PCDB_PREFIX_SCHEDCLASS: parms.schedClass = PCGetParmValue( e + 1, &e ); break; case PCDB_PREFIX_PROCTIME: parms.procTimeLimitCNS = PCGetParmValue64( e + 1, &e ); break; case PCDB_PREFIX_JOBTIME: parms.jobTimeLimitCNS = PCGetParmValue64( e + 1, &e ); break; case PCDB_PREFIX_ACTIVEPROCS: parms.procCountLimit = PCGetParmValue( e + 1, &e ); break; case PCDB_PREFIX_PROCMEMORY: parms.procMemoryLimit = PCGetParmValue64( e + 1, &e ); break; case PCDB_PREFIX_JOBMEMORY: parms.jobMemoryLimit = PCGetParmValue64( e + 1, &e ); break; default: parms.mFlags |= PCMFLAG_BADRULES; return PCERROR_BAD_DATABASE_DATA; }
if ( *e != END_BRACKET && *e != FIELD_SEP ) { parms.mFlags |= PCMFLAG_BADRULES; return PCERROR_BAD_DATABASE_DATA; } }
// Load description, if any...
workLen = sizeof(work); m_lastRegError = RegQueryValueEx( hKey, PROCCON_DATA_DESCRIPTION, NULL, &byteType, (UCHAR *)work, &workLen ); if ( m_lastRegError == ERROR_SUCCESS ) _tcsncpy( parms.description, work, RULE_DESCRIPTION_LEN ); else if ( m_lastRegError != ERROR_FILE_NOT_FOUND ) return RegError( TEXT("RegQueryValueEx"), PROCCON_DATA_DESCRIPTION );
return PCERROR_SUCCESS; }
//--------------------------------------------------------------------------------------------//
// Function to store ProcCon process detail management rule in the database //
// Input: ref to data to store. //
// Returns: ERROR_SUCCESS if successful, NT or PC error code if not //
// Note: If an error is returned, an error event has been logged. //
// Note: The appropriate critical section mast be held by the CALLER. //
// Note: key is created with DB security attributes (established in constructor). //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::StoreProcDetail( const PCProcDetail &rule ) { // Open or create and open the process subkey...
HKEY hKeyTemp; PCULONG32 regDisp; m_lastRegError = RegCreateKeyEx( m_procRegKey, rule.base.procName, 0, TEXT(""), 0, KEY_READ + KEY_WRITE, &m_secAttr, &hKeyTemp, ®Disp ); if ( m_lastRegError != ERROR_SUCCESS ) // Should never happen
return RegError( TEXT("RegCreateKeyEx"), rule.base.procName );
PCULONG32 err = StoreProcValues( hKeyTemp, rule ); RegCloseKey( hKeyTemp );
return err; }
//--------------------------------------------------------------------------------------------//
// Function to store values for a job or process management rule in the database //
// Input: registry key to use, //
// management rule structure to store //
// Returns: ERROR_SUCCESS if successful, NT or PC error code if not //
// Note: Data errors lead to default behavior, not failure. //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::StoreProcValues( const HKEY &hKey, const PCProcDetail &rule ) {
PCULONG32 err = 0;
// Set/delete job membership information as needed...
PCULONG32 len = _tcslen( rule.base.memberOfJobName ); if ( len ) { m_lastRegError = RegSetValueEx( hKey, PROCCON_DATA_MEMBEROF, NULL, REG_SZ, (UCHAR *) rule.base.memberOfJobName, (len + 1) * sizeof(TCHAR) ); if ( m_lastRegError != ERROR_SUCCESS ) // Should never happen
err = RegError( TEXT("RegSetValueEx"), PROCCON_DATA_MEMBEROF ); } else { m_lastRegError = RegDeleteValue( hKey, PROCCON_DATA_MEMBEROF ); if ( m_lastRegError != ERROR_SUCCESS && m_lastRegError != ERROR_FILE_NOT_FOUND ) err = RegError( TEXT("RegDeleteValue"), PROCCON_DATA_MEMBEROF ); }
// Set management data under profile name (or default)...
if ( !err ) err = StoreMgmtRules( hKey, rule.base.mgmtParms );
// Set variable data...
if ( !err && rule.vLength) err = StoreVariableData( hKey, rule.vLength, rule.vData );
return err; }
//--------------------------------------------------------------------------------------------//
// Function to store ProcCon job detail definition in the database //
// Input: ref to data to store. //
// Returns: ERROR_SUCCESS if successful, NT or PC error code if not //
// Note: If an error is returned, an error event has been logged. //
// Note: The appropriate critical section mast be held by the CALLER. //
// Note: key is created with DB security attributes (established in constructor). //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::StoreJobDetail( const PCJobDetail &rule ) { // Open or create and open the job subkey...
HKEY hKeyTemp; PCULONG32 regDisp; m_lastRegError = RegCreateKeyEx( m_jobRegKey, rule.base.jobName, 0, TEXT(""), 0, KEY_READ + KEY_WRITE, &m_secAttr, &hKeyTemp, ®Disp ); if ( m_lastRegError != ERROR_SUCCESS ) // Should never happen
return RegError( TEXT("RegCreateKeyEx"), rule.base.jobName );
PCULONG32 err = StoreJobValues( hKeyTemp, rule ); RegCloseKey( hKeyTemp );
return err; }
//--------------------------------------------------------------------------------------------//
// Function to store values for a job management rule in the database //
// Input: registry key to use, //
// management rule structure to store //
// Returns: ERROR_SUCCESS if successful, NT or PC error code if not //
// Note: Data errors lead to default behavior, not failure. //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::StoreJobValues( const HKEY &hKey, const PCJobDetail &rule ) {
PCULONG32 err = 0;
// Set management data under profile name (or default)...
err = StoreMgmtRules( hKey, rule.base.mgmtParms );
// Set variable data...
if ( !err && rule.vLength) err = StoreVariableData( hKey, rule.vLength, rule.vData );
return err; }
//--------------------------------------------------------------------------------------------//
// Function to store management rules for a job or process in the database //
// Input: registry key to use, profile name to use, //
// management rule structure to store. //
// Returns: NT error code //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::StoreMgmtRules( const HKEY &hKey, const MGMT_PARMS &parms ) {
PCULONG32 err = ERROR_SUCCESS; const TCHAR * const name = *parms.profileName? parms.profileName : PROCCON_DATA_DEFAULTRULES; TCHAR buf[512];
// Set 'normal' setting for data to keep unacceptable data out of the DB.
PRIORITY priority = parms.priority; SCHEDULING_CLASS schedCls = parms.schedClass; if ( !priority ) priority = PCPrioNormal; if ( schedCls > 9 ) schedCls = 5;
// Determine if caller is authorized to set various parameters...
if ( PCMapPriorityToNT( parms.priority ) == REALTIME_PRIORITY_CLASS && TestAccess( PROCCON_REG_REALTIME_ACCTEST ) != ERROR_SUCCESS ) return GetLastError();
// Build parameter string to store in database...
PCULONG32 len = _stprintf( buf, TEXT("%c") TEXT("%c0x%x%c") // flgs
TEXT("%c0x%I64x%c") // aff
TEXT("%c0x%x%c") // prio
TEXT("%c0x%I64x%c") // min WS
TEXT("%c0x%I64x%c") // max WS
TEXT("%c0x%x%c") // sched cls
TEXT("%c0x%I64x%c") // proc time
TEXT("%c0x%I64x%c") // job time
TEXT("%c0x%x%c") // proc ct
TEXT("%c0x%I64x%c") // proc mem
TEXT("%c0x%I64x%c"), // job mem
BEG_BRACKET, PCDB_PREFIX_FLAGS, parms.mFlags & PCMFLAG_SAVEABLE_BITS, FIELD_SEP, PCDB_PREFIX_AFFINITY, parms.affinity, FIELD_SEP, PCDB_PREFIX_PRIORITY, priority, FIELD_SEP, PCDB_PREFIX_MINWS, parms.minWS, FIELD_SEP, PCDB_PREFIX_MAXWS, parms.maxWS, FIELD_SEP, PCDB_PREFIX_SCHEDCLASS, schedCls, FIELD_SEP, PCDB_PREFIX_PROCTIME, parms.procTimeLimitCNS, FIELD_SEP, PCDB_PREFIX_JOBTIME, parms.jobTimeLimitCNS, FIELD_SEP, PCDB_PREFIX_ACTIVEPROCS, parms.procCountLimit, FIELD_SEP, PCDB_PREFIX_PROCMEMORY, parms.procMemoryLimit, FIELD_SEP, PCDB_PREFIX_JOBMEMORY, parms.jobMemoryLimit, END_BRACKET );
// Store the string...
m_lastRegError = RegSetValueEx( hKey, name, NULL, REG_SZ, (UCHAR *) buf, (len + 1) *sizeof(TCHAR) ); if ( m_lastRegError != ERROR_SUCCESS ) // Should never happen
err = RegError( TEXT("RegSetValueEx"), name );
// Store the description, or, if none, delete any existing description...
if ( *parms.description ) { m_lastRegError = RegSetValueEx( hKey, PROCCON_DATA_DESCRIPTION, NULL, REG_SZ, (UCHAR *) parms.description, (_tcslen(parms.description) + 1) * sizeof(parms.description[0]) ); if ( m_lastRegError != ERROR_SUCCESS ) // Should never happen
err = RegError( TEXT("RegSetValueEx"), PROCCON_DATA_DESCRIPTION ); } else m_lastRegError = RegDeleteValue( hKey, PROCCON_DATA_DESCRIPTION );
return err; }
//--------------------------------------------------------------------------------------------//
// Function to load variable detail data for a job or process in the database //
// Input: registry key to use, data length, data pointer //
// Returns: NT error code //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::LoadVariableData( const HKEY &hKey, PCINT16 *length, TCHAR *data ) {
PCULONG32 err = ERROR_SUCCESS, regType, regLen = *length; *length = 0;
m_lastRegError = RegQueryValueEx( hKey, PROCCON_DATA_VARDATA, NULL, ®Type, (UCHAR *) data, ®Len );
if ( m_lastRegError == ERROR_MORE_DATA ) return m_lastRegError;
if ( m_lastRegError == ERROR_SUCCESS ) *length = (PCINT16) regLen; else if ( m_lastRegError != ERROR_FILE_NOT_FOUND ) err = RegError( TEXT("RegQueryValueEx"), PROCCON_DATA_VARDATA );
return err; }
//--------------------------------------------------------------------------------------------//
// Function to store variable detail data for a job or process in the database //
// Input: registry key to use, data length, data pointer //
// Returns: NT error code //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::StoreVariableData( const HKEY &hKey, const PCINT16 vLength, const TCHAR *vData ) {
PCULONG32 err = ERROR_SUCCESS;
m_lastRegError = RegSetValueEx( hKey, PROCCON_DATA_VARDATA, NULL, REG_BINARY, (UCHAR *) vData, vLength ); if ( m_lastRegError != ERROR_SUCCESS ) err = RegError( TEXT("RegSetValueEx"), PROCCON_DATA_VARDATA );
return err; }
//--------------------------------------------------------------------------------------------//
// Function to perform updates after name rules are updated //
// Input: none -- m_fmtNameRules and m_numNameRules are the data source //
// Returns: ERROR_SUCCESS if successful, NT error code if not //
// Note: The appropriate critical section mast be held by the CALLER. //
// If successful, a database event is pulsed to wake those that care. //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::NameRulesUpdated( void ) { ++m_updCtrName; PCULONG32 err = StoreNameRules(); if ( err == ERROR_SUCCESS ) PulseEvent( m_dbEvent ); // Tell others data may have changed
return err; }
//--------------------------------------------------------------------------------------------//
// Functions to open (or create) the registry key names for various keys //
// Input: none -- updates member data //
// Returns: TRUE on success, else FALSE //
//--------------------------------------------------------------------------------------------//
BOOL CProcConDB::OpenParmKey( void ) { TCHAR key[MAX_PATH]; PCBuildParmKey( key );
m_lastRegError = CreateKeyAtHKLM( key, &m_parmRegKey ); if ( m_lastRegError != ERROR_SUCCESS ) { // Indicates not properly installed
PCLogMessage( PC_DB_OPEN_FAILED, EVENTLOG_ERROR_TYPE, 1, TEXT("CreateParmKey") , sizeof(m_lastRegError), &m_lastRegError ); return FALSE; }
return TRUE; }
BOOL CProcConDB::OpenProcKey( void ) { TCHAR key[MAX_PATH]; BuildProcKey( key );
m_lastRegError = CreateKeyAtHKLM( key, &m_procRegKey ); if ( m_lastRegError != ERROR_SUCCESS ) { // Indicates not properly installed
PCLogMessage( PC_DB_OPEN_FAILED, EVENTLOG_ERROR_TYPE, 1, TEXT("CreateProcKey") , sizeof(m_lastRegError), &m_lastRegError ); return FALSE; }
return TRUE; }
BOOL CProcConDB::OpenJobKey( void ) { TCHAR key[MAX_PATH]; BuildJobKey( key );
m_lastRegError = CreateKeyAtHKLM( key, &m_jobRegKey ); if ( m_lastRegError != ERROR_SUCCESS ) { // Indicates not properly installed
PCLogMessage( PC_DB_OPEN_FAILED, EVENTLOG_ERROR_TYPE, 1, TEXT("CreateGroupKey") , sizeof(m_lastRegError), &m_lastRegError ); return FALSE; }
return TRUE; }
//--------------------------------------------------------------------------------------------//
// Functions to build the registry key names for various keys //
// Input: location to build key and, for the name keys, the name //
// Returns: nothing (cannot fail) //
//--------------------------------------------------------------------------------------------//
TCHAR *CProcConDB::BuildProcKey( TCHAR *key ) { PCBuildParmKey( key ); _tcscat( key, TEXT("\\") ); _tcscat( key, PROCCON_REG_PROCRULES_SUBKEY ); return key; }
TCHAR *CProcConDB::BuildJobKey( TCHAR *key ) { PCBuildParmKey( key ); _tcscat( key, TEXT("\\") ); _tcscat( key, PROCCON_REG_JOBRULES_SUBKEY ); return key; }
//--------------------------------------------------------------------------------------------//
// Function to report a registry function error //
// Input: name of operation that failed, optional additional string //
// Returns: original error //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::RegError( const TCHAR *op, const TCHAR *what1, const TCHAR *what2 ) { TCHAR str[MAX_PATH]; _tcscpy( str, what1? what1 : TEXT("") ); if ( what2 ) _tcscat( str, what2 ); const TCHAR *strings[] = { op, str }; PCLogMessage( PC_UNEXPECTED_REGISTRY_ERROR, EVENTLOG_ERROR_TYPE, 2, strings, sizeof(m_lastRegError), &m_lastRegError ); return m_lastRegError; }
//--------------------------------------------------------------------------------------------//
// Function to report a registry data error //
// Input: name associated with data //
// Returns: NT error ERROR_INVALID_DATA //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::RegDataError( const TCHAR *what ) { PCULONG32 dummy = ERROR_INVALID_DATA; PCLogMessage( PC_INVALID_DATA_ERROR, EVENTLOG_ERROR_TYPE, 1, what, sizeof(dummy), &dummy ); return dummy; }
//--------------------------------------------------------------------------------------------//
// Function to set a new poll delay //
// Input: proposed new delay //
// Returns: NT or PC error code //
// Note: lower and upper limits on poll delay are a bit arbitrary (2 secs to 15 mins OK) //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::SetPollDelaySeconds( PCULONG32 newDelay ) { if ( TestAccess( PROCCON_REG_POLLRATE_ACCTEST ) != ERROR_SUCCESS ) return GetLastError();
if ( newDelay >= PC_MIN_POLL_DELAY && newDelay <= PC_MAX_POLL_DELAY ) { m_pollDelay = newDelay * 1000; // convert to milliseconds
return SetPCParm( PROCCON_DATA_POLLDELAY, newDelay ); } else return PCERROR_INVALID_PARAMETER; }
//--------------------------------------------------------------------------------------------//
// Functions to get or set DWORD values in the registry (parms, etc.) //
// Input: name of parameter, pointer to data location //
// Returns: registry function error or success //
// Note: If a parameter cannot be retrieved or is not a REG_DWORD, it is replaced with //
// the supplied value as a default. //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::GetPCParm( const TCHAR *name, PCULONG32 *data ) { PCULONG32 byteType, lastLen = sizeof(PCULONG32 ); UCHAR *addr = (UCHAR *) data; PCULONG32 rc = RegQueryValueEx( m_parmRegKey, name, NULL, &byteType, addr, &lastLen ); if ( rc != ERROR_SUCCESS || byteType != REG_DWORD) rc = RegSetValueEx( m_parmRegKey, name, NULL, REG_DWORD, addr, sizeof(PCULONG32) ); return rc; }
PCULONG32 CProcConDB::SetPCParm( const TCHAR *name, PCULONG32 data ) { return RegSetValueEx( m_parmRegKey, name, NULL, REG_DWORD, (UCHAR *) &data, sizeof(PCULONG32) ); }
PCULONG32 CProcConDB::DeleteAllNameRules( void ) { if ( TestAccess( PROCCON_REG_RESTORE_ACCTEST ) != ERROR_SUCCESS ) // delete all preceeds restore
return GetLastError();
PCULONG32 rc;
EnterCriticalSection( &m_dbCSNameRule );
m_lastRegError = RegDeleteValue( m_parmRegKey, PROCCON_DATA_NAMERULES ); if ( m_lastRegError != ERROR_SUCCESS && m_lastRegError != ERROR_FILE_NOT_FOUND ) rc = RegError( TEXT("RegDeleteValue"), PROCCON_DATA_NAMERULES ); else { PCLogMessage( PC_SERVICE_DEL_ALL_NAME_RULES, EVENTLOG_INFORMATION_TYPE, 0, NULL ); rc = LoadRules( LOADFLAG_NAME_RULES ); }
LeaveCriticalSection( &m_dbCSNameRule );
return rc; }
PCULONG32 CProcConDB::DeleteAllProcDefs( void ) {
if ( TestAccess( PROCCON_REG_RESTORE_ACCTEST ) != ERROR_SUCCESS ) // delete all preceeds restore
return GetLastError();
PCULONG32 rc = ERROR_SUCCESS; EnterCriticalSection( &m_dbCSProcRule );
if ( m_procRegKey ) RegCloseKey( m_procRegKey ); m_procRegKey = NULL;
m_lastRegError = PCDeleteKeyTree( m_parmRegKey, PROCCON_REG_PROCRULES_SUBKEY ); if ( m_lastRegError != ERROR_SUCCESS && m_lastRegError != ERROR_FILE_NOT_FOUND ) rc = RegError( TEXT("RegDeleteValue"), PROCCON_REG_PROCRULES_SUBKEY ); else { PCLogMessage( PC_SERVICE_DEL_ALL_PROC_RULES, EVENTLOG_INFORMATION_TYPE, 0, NULL ); if ( !OpenProcKey() ) rc = m_lastRegError; // should not fail since worked at startup
else rc = LoadRules( LOADFLAG_PROC_RULES ); }
LeaveCriticalSection( &m_dbCSProcRule ); return rc; }
PCULONG32 CProcConDB::DeleteAllJobDefs( void ) { if ( TestAccess( PROCCON_REG_RESTORE_ACCTEST ) != ERROR_SUCCESS ) // delete all preceeds restore
return GetLastError();
PCULONG32 rc = ERROR_SUCCESS; EnterCriticalSection( &m_dbCSJobRule );
if ( m_jobRegKey ) RegCloseKey( m_jobRegKey ); m_jobRegKey = NULL;
m_lastRegError = PCDeleteKeyTree( m_parmRegKey, PROCCON_REG_JOBRULES_SUBKEY ); if ( m_lastRegError != ERROR_SUCCESS && m_lastRegError != ERROR_FILE_NOT_FOUND ) rc = RegError( TEXT("RegDeleteValue"), PROCCON_REG_JOBRULES_SUBKEY ); else { PCLogMessage( PC_SERVICE_DEL_ALL_JOB_RULES, EVENTLOG_INFORMATION_TYPE, 0, NULL ); if ( !OpenJobKey() ) rc = m_lastRegError; // should not fail since worked at startup
else rc = LoadRules( LOADFLAG_JOB_RULES ); }
LeaveCriticalSection( &m_dbCSJobRule ); return rc; }
//--------------------------------------------------------------------------------------------//
// Functions to get job management data in internal (non-API) format //
// Input: location to store list pointer, name to locate or NULL //
// Returns: count of entries //
// Note: if name supplied, only thet entry is located and listed, else all are listed //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::GetJobMgmtDefs( PCJobDef **pList, JOB_NAME *name ) { EnterCriticalSection( &m_dbCSJobRule );
PCULONG32 numRules = name? 1 : m_numJobRules; // copy count for use outside CS
if ( !numRules ) { // 7/28/2000 bugfix to prevent leak when no rules
*pList = NULL; LeaveCriticalSection( &m_dbCSJobRule ); return 0; }
*pList = new PCJobDef[numRules]; if ( !*pList ) { PCLogNoMemory( TEXT("AllocInternalJobDefs"), numRules * sizeof(PCJobDef) ); LeaveCriticalSection( &m_dbCSJobRule ); return 0; } memset( *pList, 0, numRules * sizeof(PCJobDef) );
// copy summary data to buffer until end of data...
PCJobDef *list = *pList;
// If looking for a specific entry, locate it and build one entry...
if ( name ) { for ( PCULONG32 i = 0; i < m_numJobRules; ++i ) { if ( !CompareJobName( m_jobSummary[i].jobName, name ) ) { SetJobDefEntry( list, m_jobSummary[i] ); break; } } // If entry not found -- delete list, set 0 count...
if ( i >= m_numJobRules ) { delete [] *pList; *pList = NULL; numRules = 0; } } else for ( PCULONG32 i = 0; i < numRules; ++i, ++list ) { SetJobDefEntry( list, m_jobSummary[i] ); }
LeaveCriticalSection( &m_dbCSJobRule );
if ( numRules > 1 ) qsort( *pList, numRules, sizeof(PCJobDef), CompareJobDef );
return numRules; }
void CProcConDB::SetJobDefEntry( PCJobDef *list, PCJobSummary &m_jobSummary ) { memcpy( list->jobName, m_jobSummary.jobName, sizeof(list->jobName) ); memcpy( list->profileName, m_jobSummary.mgmtParms.profileName, sizeof(list->profileName) ); list->mFlags = m_jobSummary.mgmtParms.mFlags; list->affinity = m_jobSummary.mgmtParms.affinity; list->priority = m_jobSummary.mgmtParms.priority; list->minWS = m_jobSummary.mgmtParms.minWS; list->maxWS = m_jobSummary.mgmtParms.maxWS; list->schedClass = m_jobSummary.mgmtParms.schedClass; list->procCountLimit = m_jobSummary.mgmtParms.procCountLimit; list->procTimeLimitCNS = m_jobSummary.mgmtParms.procTimeLimitCNS; list->jobTimeLimitCNS = m_jobSummary.mgmtParms.jobTimeLimitCNS; list->procMemoryLimit = m_jobSummary.mgmtParms.procMemoryLimit; list->jobMemoryLimit = m_jobSummary.mgmtParms.jobMemoryLimit; } //--------------------------------------------------------------------------------------------//
// Functions to get process management data in internal (non-API) format //
// Input: location to store list pointer //
// Returns: count of entries //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::GetProcMgmtDefs( PCProcDef **pList ) { EnterCriticalSection( &m_dbCSProcRule );
PCULONG32 numRules = m_numProcRules; // copy count for use outside CS
if ( !numRules ) { // 7/28/2000 bugfix to prevent leak when no rules
*pList = NULL; LeaveCriticalSection( &m_dbCSProcRule ); return 0; }
*pList = new PCProcDef[numRules]; if ( !*pList ) { PCLogNoMemory( TEXT("AllocInternalProcDefs"), numRules * sizeof(PCProcDef) ); LeaveCriticalSection( &m_dbCSProcRule ); return 0; }
// copy summary data to buffer until end of data...
PCProcDef *list = *pList; for ( PCULONG32 i = 0; i < numRules; ++i, ++list ) { memcpy( list->procName, m_procSummary[i].procName, sizeof(list->procName) ); memcpy( list->memberOfJob, m_procSummary[i].memberOfJobName, sizeof(list->memberOfJob) ); memcpy( list->profileName, m_procSummary[i].mgmtParms.profileName, sizeof(list->profileName) ); list->mFlags = m_procSummary[i].mgmtParms.mFlags; list->affinity = m_procSummary[i].mgmtParms.affinity; list->priority = m_procSummary[i].mgmtParms.priority; list->minWS = m_procSummary[i].mgmtParms.minWS; list->maxWS = m_procSummary[i].mgmtParms.maxWS; }
LeaveCriticalSection( &m_dbCSProcRule );
if ( numRules > 1 ) qsort( *pList, numRules, sizeof(PCProcDef), CompareProcDef );
return numRules; }
//--------------------------------------------------------------------------------------------//
// Functions to get proc summary list data in API format //
// Input: start point and target loc, max count, item len return, item count return //
// Returns: TRUE if more data exists, else FALSE (there are no error conditions) //
//--------------------------------------------------------------------------------------------//
BOOL CProcConDB::GetProcSummary( const PCProcSummary *pStart, PCUINT32 listFlags, PCProcSummary *pSummary, const PCINT32 maxCount, PCINT16 *itemLen, PCINT16 *itemCount ) { EnterCriticalSection( &m_dbCSProcRule );
*itemLen = sizeof(PCProcSummary);
PCULONG32 numRules = m_numProcRules; // copy count for use outside CS
if ( listFlags & PC_LIST_MATCH_ONLY ) // if match only, set starting point to same
listFlags |= PC_LIST_STARTING_WITH;
// locate copy start point...
for ( PCULONG32 i = 0; i < numRules; ++i ) { int cmp = CompareProcSummary( pStart, &m_procSummary[i] ); if ( (listFlags & PC_LIST_STARTING_WITH) && cmp <= 0 ) break; else if ( cmp < 0 ) break; }
// copy data to buffer until end of data or max requested hit...
for ( *itemCount = 0; i < numRules && *itemCount < maxCount; ++i, ++*itemCount ) { if ( (listFlags & PC_LIST_MATCH_ONLY) && CompareProcSummary( pStart, &m_procSummary[i] ) ) break; memcpy( pSummary++, &m_procSummary[i], *itemLen ); }
LeaveCriticalSection( &m_dbCSProcRule );
return (listFlags & PC_LIST_MATCH_ONLY)? FALSE : i < numRules; }
//--------------------------------------------------------------------------------------------//
// Functions to get job summary list data in API format //
// Input: start point and target loc, max count, item len return, item count return //
// Returns: TRUE if more data exists, else FALSE (there are no error conditions) //
//--------------------------------------------------------------------------------------------//
BOOL CProcConDB::GetJobSummary( const PCJobSummary *pStart, PCUINT32 listFlags, PCJobSummary *pSummary, const PCINT32 maxCount, PCINT16 *itemLen, PCINT16 *itemCount ) { EnterCriticalSection( &m_dbCSJobRule );
*itemLen = sizeof(PCJobSummary);
PCULONG32 numRules = m_numJobRules; // copy count for use outside CS
if ( listFlags & PC_LIST_MATCH_ONLY ) // if match only, set starting point to same
listFlags |= PC_LIST_STARTING_WITH;
// locate copy start point (first entry greater than supplied)...
for ( PCULONG32 i = 0; i < numRules; ++i ) { int cmp = CompareJobSummary( pStart, &m_jobSummary[i] ); if ( (listFlags & PC_LIST_STARTING_WITH) && cmp <= 0 ) break; else if ( cmp < 0 ) break; }
// copy data to buffer until end of data or max requested hit...
for ( *itemCount = 0; i < numRules && *itemCount < maxCount; ++i, ++*itemCount ) { if ( (listFlags & PC_LIST_MATCH_ONLY) && CompareJobSummary( pStart, &m_jobSummary[i] ) ) break; memcpy( pSummary++, &m_jobSummary[i], *itemLen ); }
LeaveCriticalSection( &m_dbCSJobRule );
return (listFlags & PC_LIST_MATCH_ONLY)? FALSE : i < numRules; }
//--------------------------------------------------------------------------------------------//
// Functions to get process detail data in API format //
// Input: request input and output detail buffers, data version code, update counter to set//
// Returns: PC or NT error code or PCERROR_SUCCESS //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::GetProcDetail( const PCProcDetail *pIn, PCProcDetail *pDetail, const BYTE version, PCINT32 *updateCtr ) { PCULONG32 err = ERROR_SUCCESS;
EnterCriticalSection( &m_dbCSProcRule );
if ( updateCtr ) *updateCtr = m_updCtrProc;
// Open the process subkey...
HKEY hKeyTemp; m_lastRegError = RegOpenKeyEx( m_procRegKey, pIn->base.procName, 0, KEY_READ + KEY_WRITE, &hKeyTemp ); if ( m_lastRegError != ERROR_SUCCESS ) if ( m_lastRegError != ERROR_FILE_NOT_FOUND ) err = RegError( TEXT("RegOpenKeyEx"), pIn->base.procName ); else err = PCERROR_DOES_NOT_EXIST;
if ( err == ERROR_SUCCESS ) { memcpy( pDetail, pIn, sizeof(*pDetail) ); // prime name fields with supplied names
err = LoadProcSummaryItem( hKeyTemp, pDetail->base );
if ( err == ERROR_SUCCESS ) err = LoadVariableData( hKeyTemp, &pDetail->vLength, pDetail->vData );
RegCloseKey( hKeyTemp ); }
LeaveCriticalSection( &m_dbCSProcRule );
return err; }
//--------------------------------------------------------------------------------------------//
// Functions to add process detail data from API format //
// Input: detail buffer, data version code //
// Returns: PC or NT error code or PCERROR_SUCCESS //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::AddProcDetail( const PCProcDetail *pDetail, const BYTE version ) { EnterCriticalSection( &m_dbCSProcRule );
// Open the process subkey...
HKEY hKeyTemp; PCULONG32 err = RegOpenKeyEx( m_procRegKey, pDetail->base.procName, 0, KEY_READ + KEY_WRITE, &hKeyTemp ); if ( err != ERROR_FILE_NOT_FOUND ) { if ( err == ERROR_SUCCESS ) { err = PCERROR_EXISTS; RegCloseKey( hKeyTemp ); } else { m_lastRegError = err; RegError( TEXT("RegOpenKeyEx"), pDetail->base.procName ); } } else err = StoreProcDetail( *pDetail ); if ( !err ) err = LoadRules( LOADFLAG_PROC_RULES );
LeaveCriticalSection( &m_dbCSProcRule );
if ( err == PCERROR_SUCCESS && m_LogRuleEdits ) LogProcSummaryChange(&pDetail->base, version, NULL);
return err; }
//--------------------------------------------------------------------------------------------//
// Functions to replace process detail data in API format //
// Input: detail buffer, data version code, update counter to verify //
// Returns: PC or NT error code or PCERROR_SUCCESS //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::ReplProcDetail( const PCProcDetail *pDetail, const BYTE version, const PCINT32 updateCtr ) { PCULONG32 err = ERROR_SUCCESS; PCProcSummary oldProcSummary; PCINT16 itemsReturned = 0; PCINT16 itemLen = sizeof(oldProcSummary);
EnterCriticalSection( &m_dbCSProcRule );
if ( updateCtr != m_updCtrProc ) err = PCERROR_UPDATE_OCCURRED; else { // Open the process subkey...
HKEY hKeyTemp; err = RegOpenKeyEx( m_procRegKey, pDetail->base.procName, 0, KEY_READ + KEY_WRITE, &hKeyTemp ); if ( err == ERROR_SUCCESS ) { GetProcSummary(&pDetail->base, PC_LIST_MATCH_ONLY, &oldProcSummary, 1, &itemLen, &itemsReturned ); err = StoreProcValues( hKeyTemp, *pDetail ); RegCloseKey( hKeyTemp ); if ( !err ) err = LoadRules( LOADFLAG_PROC_RULES ); } else { if ( err != ERROR_FILE_NOT_FOUND ) { m_lastRegError = err; RegError( TEXT("RegOpenKeyEx"), pDetail->base.procName ); } else err = PCERROR_DOES_NOT_EXIST; } }
LeaveCriticalSection( &m_dbCSProcRule );
if ( err == PCERROR_SUCCESS && itemsReturned == 1 && m_LogRuleEdits ) LogProcSummaryChange(&pDetail->base, version, &oldProcSummary);
return err; }
//--------------------------------------------------------------------------------------------//
// Functions to delete process detail data from API format //
// Input: summary portion of detail buffer, data version code //
// Returns: PC or NT error code or PCERROR_SUCCESS //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::DelProcDetail( const PCProcSummary *pSummary, const BYTE version ) { EnterCriticalSection( &m_dbCSProcRule );
PCULONG32 err;
// Delete just the profile data if profile name supplied...
if ( *pSummary->mgmtParms.profileName ) { HKEY hKeyTemp; err = RegOpenKeyEx( m_procRegKey, pSummary->procName, 0, KEY_READ + KEY_WRITE, &hKeyTemp ); if ( err == ERROR_SUCCESS ) { err = RegDeleteValue( hKeyTemp, pSummary->mgmtParms.profileName ); RegCloseKey( hKeyTemp ); } } // Otherwise delete the entire process detail key...
else err = RegDeleteKey( m_procRegKey, pSummary->procName ); // Handle result...
if ( err != ERROR_SUCCESS && err != ERROR_FILE_NOT_FOUND ) { m_lastRegError = err; RegError( TEXT("DelProcDetail"), pSummary->procName ); } else if ( err == ERROR_SUCCESS ) err = LoadRules( LOADFLAG_PROC_RULES );
LeaveCriticalSection( &m_dbCSProcRule );
if ( err == ERROR_SUCCESS && m_LogRuleEdits ) PCLogMessage( PC_SERVICE_DEL_PROC_EXECUTION_RULE, EVENTLOG_INFORMATION_TYPE, 1, pSummary->procName );
return err; }
//--------------------------------------------------------------------------------------------//
// Function to Log a replace or add change to a process execution rule //
// Input: summary portion of detail buffer, data version code, orignal(old) summary //
// portion of detail buffer prior to the change //
// Returns: nothing //
//--------------------------------------------------------------------------------------------//
void CProcConDB::LogProcSummaryChange( const PCProcSummary *pNewSummary, const BYTE version, const PCProcSummary *pOldSummary ) { // description
// member of job
// affinity
TCHAR toAffinity[32], fromAffinity[32] = { 0 }; PCFormatAffinityLimit(toAffinity, ENTRY_COUNT(toAffinity), pNewSummary->mgmtParms); if ( pOldSummary ) PCFormatAffinityLimit(fromAffinity, ENTRY_COUNT(fromAffinity), pOldSummary->mgmtParms);
// priority
TCHAR toPriority[32], fromPriority[32] = { 0 }; PCFormatPriorityLimit(toPriority, ENTRY_COUNT(toPriority), pNewSummary->mgmtParms); if ( pOldSummary ) PCFormatPriorityLimit(fromPriority, ENTRY_COUNT(fromPriority), pOldSummary->mgmtParms);
// working set
TCHAR toWS[64], fromWS[64]; PCFormatWorkingSetLimit(toWS, ENTRY_COUNT(toWS), pNewSummary->mgmtParms); if ( pOldSummary ) PCFormatWorkingSetLimit(fromWS, ENTRY_COUNT(fromWS), pOldSummary->mgmtParms);
if ( !pOldSummary ) { const TCHAR *msgs[] = { pNewSummary->procName, pNewSummary->mgmtParms.description, PCIsSetToStr(pNewSummary->mgmtParms.mFlags, PCMFLAG_APPLY_JOB_MEMBERSHIP), pNewSummary->memberOfJobName, toAffinity, toPriority, toWS }; PCLogMessage( PC_SERVICE_ADD_PROC_EXECUTION_RULE, EVENTLOG_INFORMATION_TYPE, ENTRY_COUNT(msgs), msgs );
} else {
const TCHAR *msgs[] = { pNewSummary->procName, pNewSummary->mgmtParms.description, pOldSummary->mgmtParms.description, PCIsSetToStr(pNewSummary->mgmtParms.mFlags, PCMFLAG_APPLY_JOB_MEMBERSHIP), pNewSummary->memberOfJobName, PCIsSetToStr(pOldSummary->mgmtParms.mFlags, PCMFLAG_APPLY_JOB_MEMBERSHIP), pOldSummary->memberOfJobName, toAffinity, fromAffinity, toPriority, fromPriority, toWS, fromWS }; PCLogMessage( PC_SERVICE_REPL_PROC_EXECUTION_RULE, EVENTLOG_INFORMATION_TYPE, ENTRY_COUNT(msgs), msgs ); }
}
//--------------------------------------------------------------------------------------------//
// Functions to get job detail data in API format //
// Input: detail buffer, data version code, update counter to set //
// Returns: PC or NT error code or PCERROR_SUCCESS //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::GetJobDetail( const PCJobDetail *pIn, PCJobDetail *pDetail, const BYTE version, PCINT32 *updateCtr ) { PCULONG32 err = ERROR_SUCCESS;
EnterCriticalSection( &m_dbCSJobRule );
if ( updateCtr ) *updateCtr = m_updCtrJob;
// Open the job subkey...
HKEY hKeyTemp; m_lastRegError = RegOpenKeyEx( m_jobRegKey, pIn->base.jobName, 0, KEY_READ + KEY_WRITE, &hKeyTemp ); if ( m_lastRegError != ERROR_SUCCESS ) if ( m_lastRegError != ERROR_FILE_NOT_FOUND ) err = RegError( TEXT("RegOpenKeyEx"), pIn->base.jobName ); else err = PCERROR_DOES_NOT_EXIST;
if ( err == ERROR_SUCCESS ) { memcpy( pDetail, pIn, sizeof(*pDetail) ); // prime name fields with supplied names
err = LoadJobSummaryItem( hKeyTemp, pDetail->base );
if ( err == ERROR_SUCCESS ) err = LoadVariableData( hKeyTemp, &pDetail->vLength, pDetail->vData );
RegCloseKey( hKeyTemp ); }
LeaveCriticalSection( &m_dbCSJobRule );
return err; }
//--------------------------------------------------------------------------------------------//
// Functions to add job detail data from API format //
// Input: detail buffer, data version code //
// Returns: PC or NT error code or PCERROR_SUCCESS //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::AddJobDetail( const PCJobDetail *pDetail, const BYTE version ) { EnterCriticalSection( &m_dbCSJobRule );
// Open the job subkey...
HKEY hKeyTemp; PCULONG32 err = RegOpenKeyEx( m_jobRegKey, pDetail->base.jobName, 0, KEY_READ + KEY_WRITE, &hKeyTemp ); if ( err != ERROR_FILE_NOT_FOUND ) { if ( err == ERROR_SUCCESS ) { err = PCERROR_EXISTS; RegCloseKey( hKeyTemp ); } else { m_lastRegError = err; RegError( TEXT("RegOpenKeyEx"), pDetail->base.jobName ); } } else err = StoreJobDetail( *pDetail ); if ( !err ) err = LoadRules( LOADFLAG_JOB_RULES );
LeaveCriticalSection( &m_dbCSJobRule );
if ( err == ERROR_SUCCESS && m_LogRuleEdits ) LogJobSummaryChange(&pDetail->base, version, NULL);
return err; }
//--------------------------------------------------------------------------------------------//
// Functions to replace job detail data in API format //
// Input: detail buffer, data version code //
// Returns: PC or NT error code or PCERROR_SUCCESS //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::ReplJobDetail( const PCJobDetail *pDetail, const BYTE version, const PCINT32 updateCtr ) { PCULONG32 err = ERROR_SUCCESS; PCJobSummary oldJobSummary; PCINT16 itemsReturned = 0; PCINT16 itemLen = sizeof(oldJobSummary);
EnterCriticalSection( &m_dbCSJobRule );
if ( updateCtr != m_updCtrJob ) err = PCERROR_UPDATE_OCCURRED; else { // Open the job subkey...
HKEY hKeyTemp; err = RegOpenKeyEx( m_jobRegKey, pDetail->base.jobName, 0, KEY_READ + KEY_WRITE, &hKeyTemp ); if ( err == ERROR_SUCCESS ) { GetJobSummary(&pDetail->base, PC_LIST_MATCH_ONLY, &oldJobSummary, 1, &itemLen, &itemsReturned ); err = StoreJobValues( hKeyTemp, *pDetail ); RegCloseKey( hKeyTemp ); if ( !err ) err = LoadRules( LOADFLAG_JOB_RULES ); } else { if ( err != ERROR_FILE_NOT_FOUND ) { m_lastRegError = err; RegError( TEXT("RegOpenKeyEx"), pDetail->base.jobName ); } else err = PCERROR_DOES_NOT_EXIST; } }
LeaveCriticalSection( &m_dbCSJobRule );
if ( err == ERROR_SUCCESS && itemsReturned == 1 && m_LogRuleEdits ) LogJobSummaryChange(&pDetail->base, version, &oldJobSummary);
return err; } //--------------------------------------------------------------------------------------------//
// Functions to delete job detail data from API format //
// Input: summary portion of detail buffer, data version code //
// Returns: PC or NT error code or PCERROR_SUCCESS //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::DelJobDetail( const PCJobSummary *pSummary, const BYTE version ) { EnterCriticalSection( &m_dbCSJobRule );
PCULONG32 err;
// Delete just the profile data if profile name supplied...
if ( *pSummary->mgmtParms.profileName ) { HKEY hKeyTemp; err = RegOpenKeyEx( m_jobRegKey, pSummary->jobName, 0, KEY_READ + KEY_WRITE, &hKeyTemp ); if ( err == ERROR_SUCCESS ) { err = RegDeleteValue( hKeyTemp, pSummary->mgmtParms.profileName ); RegCloseKey( hKeyTemp ); } } // Otherwise delete the entire job detail key...
else err = RegDeleteKey( m_jobRegKey, pSummary->jobName ); // Handle result...
if ( err != ERROR_SUCCESS && err != ERROR_FILE_NOT_FOUND ) { m_lastRegError = err; RegError( TEXT("DelJobDetail"), pSummary->jobName ); } else if ( err == ERROR_SUCCESS ) err = LoadRules( LOADFLAG_JOB_RULES );
LeaveCriticalSection( &m_dbCSJobRule );
if ( err == ERROR_SUCCESS && m_LogRuleEdits ) PCLogMessage( PC_SERVICE_DEL_JOB_EXECUTION_RULE, EVENTLOG_INFORMATION_TYPE, 1, pSummary->jobName );
return err; }
//--------------------------------------------------------------------------------------------//
// Function to Log a replace or add change to a group execution rule //
// Input: summary portion of detail buffer, data version code, orignal(old) summary //
// portion of detail buffer prior to the change //
// Returns: nothing //
//--------------------------------------------------------------------------------------------//
void CProcConDB::LogJobSummaryChange( const PCJobSummary *pNewSummary, const BYTE version, const PCJobSummary *pOldSummary ) { // description
// affinity
TCHAR toAffinity[32], fromAffinity[32] = { 0 }; PCFormatAffinityLimit(toAffinity, ENTRY_COUNT(toAffinity), pNewSummary->mgmtParms); if ( pOldSummary ) PCFormatAffinityLimit(fromAffinity, ENTRY_COUNT(fromAffinity), pOldSummary->mgmtParms);
// priority
TCHAR toPriority[32], fromPriority[32] = { 0 }; PCFormatPriorityLimit(toPriority, ENTRY_COUNT(toPriority), pNewSummary->mgmtParms); if ( pOldSummary ) PCFormatPriorityLimit(fromPriority, ENTRY_COUNT(fromPriority), pOldSummary->mgmtParms);
// working set
TCHAR toWS[64], fromWS[64] = { 0 }; PCFormatWorkingSetLimit(toWS, ENTRY_COUNT(toWS), pNewSummary->mgmtParms); if ( pOldSummary ) PCFormatWorkingSetLimit(fromWS, ENTRY_COUNT(fromWS), pOldSummary->mgmtParms);
// scheduling class
TCHAR toSch[32], fromSch[32] = { 0 }; PCFormatSchedClassLimit(toSch, ENTRY_COUNT(toSch), pNewSummary->mgmtParms); if ( pOldSummary ) PCFormatSchedClassLimit(fromSch, ENTRY_COUNT(fromSch), pOldSummary->mgmtParms);
// process count
TCHAR toProcCount[32], fromProcCount[32] = { 0 }; PCFormatProcessCountLimit(toProcCount, ENTRY_COUNT(toProcCount), pNewSummary->mgmtParms); if ( pOldSummary ) PCFormatProcessCountLimit(fromProcCount, ENTRY_COUNT(fromProcCount), pOldSummary->mgmtParms);
// process committed memory
TCHAR toProcMemory[32], fromProcMemory[32] = { 0 }; PCFormatProcMemLimit(toProcMemory, ENTRY_COUNT(toProcMemory), pNewSummary->mgmtParms); if ( pOldSummary ) PCFormatProcMemLimit(fromProcMemory, ENTRY_COUNT(fromProcMemory), pOldSummary->mgmtParms);
// job committed memory
TCHAR toJobMemory[32], fromJobMemory[32] = { 0 }; PCFormatJobMemLimit(toJobMemory, ENTRY_COUNT(toJobMemory), pNewSummary->mgmtParms); if ( pOldSummary ) PCFormatJobMemLimit(fromJobMemory, ENTRY_COUNT(fromJobMemory), pOldSummary->mgmtParms);
// per process user time
TCHAR toProcTime[32], fromProcTime[32] = { 0 }; PCFormatProcTimeLimit(toProcTime, ENTRY_COUNT(toProcTime), pNewSummary->mgmtParms); if ( pOldSummary ) PCFormatProcTimeLimit(fromProcTime, ENTRY_COUNT(fromProcTime), pOldSummary->mgmtParms);
// job user time
TCHAR toJobTime[32], fromJobTime[32] = { 0 }; PCFormatJobTimeLimit(toJobTime, ENTRY_COUNT(toJobTime), pNewSummary->mgmtParms); if ( pOldSummary ) PCFormatJobTimeLimit(fromJobTime, ENTRY_COUNT(fromJobTime), pOldSummary->mgmtParms);
// job user time action
TCHAR toEndofJobTimeAction[128], fromEndofJobTimeAction[128] = { 0 }; PCFormatEndofJobAction(toEndofJobTimeAction, ENTRY_COUNT(toEndofJobTimeAction), pNewSummary->mgmtParms); if ( pOldSummary ) PCFormatEndofJobAction(fromEndofJobTimeAction, ENTRY_COUNT(fromEndofJobTimeAction), pOldSummary->mgmtParms);
// end job when no process in job
TCHAR toEndJobEmpty[16], fromEndJobEmpty[16] = { 0 }; PCFormatOnOrOffLimit(toEndJobEmpty, ENTRY_COUNT(toEndJobEmpty), pNewSummary->mgmtParms, PCMFLAG_END_JOB_WHEN_EMPTY); if ( pOldSummary ) PCFormatOnOrOffLimit(fromEndJobEmpty, ENTRY_COUNT(fromEndJobEmpty), pOldSummary->mgmtParms, PCMFLAG_END_JOB_WHEN_EMPTY);
// die on unhandled exception
TCHAR toDieUHExcept[16], fromDieUHExcept[16] = { 0 }; PCFormatOnOrOffLimit(toDieUHExcept, ENTRY_COUNT(toDieUHExcept), pNewSummary->mgmtParms, PCMFLAG_SET_DIE_ON_UH_EXCEPTION); if ( pOldSummary ) PCFormatOnOrOffLimit(fromDieUHExcept, ENTRY_COUNT(fromDieUHExcept), pOldSummary->mgmtParms, PCMFLAG_SET_DIE_ON_UH_EXCEPTION);
// silent breakaway
TCHAR toSilentBrkAwayAct[16], fromSilentBrkAwayAct[16] = { 0 }; PCFormatOnOrOffLimit(toSilentBrkAwayAct, ENTRY_COUNT(toSilentBrkAwayAct), pNewSummary->mgmtParms, PCMFLAG_SET_SILENT_BREAKAWAY); if ( pOldSummary ) PCFormatOnOrOffLimit(fromSilentBrkAwayAct, ENTRY_COUNT(fromSilentBrkAwayAct), pOldSummary->mgmtParms, PCMFLAG_SET_SILENT_BREAKAWAY);
// breakaway OK
TCHAR toBrkAwayOKAct[16], fromBrkAwayOKAct[16] = { 0 }; PCFormatOnOrOffLimit(toBrkAwayOKAct, ENTRY_COUNT(toBrkAwayOKAct), pNewSummary->mgmtParms, PCMFLAG_SET_PROC_BREAKAWAY_OK); if ( pOldSummary ) PCFormatOnOrOffLimit(fromBrkAwayOKAct, ENTRY_COUNT(fromBrkAwayOKAct), pOldSummary->mgmtParms, PCMFLAG_SET_PROC_BREAKAWAY_OK);
if ( !pOldSummary ) { const TCHAR *msgs[] = { pNewSummary->jobName, pNewSummary->mgmtParms.description, toAffinity, toPriority, toWS, toSch, toProcCount, toProcMemory, toJobMemory, toProcTime, toJobTime, toEndofJobTimeAction, toEndJobEmpty, toDieUHExcept, toSilentBrkAwayAct, toBrkAwayOKAct }; PCLogMessage( PC_SERVICE_ADD_JOB_EXECUTION_RULE, EVENTLOG_INFORMATION_TYPE, ENTRY_COUNT(msgs), msgs );
} else {
const TCHAR *msgs[] = { pNewSummary->jobName, pNewSummary->mgmtParms.description, pOldSummary->mgmtParms.description, toAffinity, fromAffinity, toPriority, fromPriority, toWS, fromWS, toSch, fromSch, toProcCount, fromProcCount, toProcMemory, fromProcMemory, toJobMemory, fromJobMemory, toProcTime, fromProcTime, toJobTime, fromJobTime, toEndofJobTimeAction, fromEndofJobTimeAction, toEndJobEmpty, fromEndJobEmpty, toDieUHExcept, fromDieUHExcept, toSilentBrkAwayAct, fromSilentBrkAwayAct, toBrkAwayOKAct, fromBrkAwayOKAct }; PCLogMessage( PC_SERVICE_REPL_JOB_EXECUTION_RULE, EVENTLOG_INFORMATION_TYPE, ENTRY_COUNT(msgs), msgs ); }
}
//--------------------------------------------------------------------------------------------//
// Functions to get name rules in API format //
// Input: start point, target loc, conts, etc. -- see below //
// Returns: TRUE if more data exists, else FALSE (there are no error conditions) //
//--------------------------------------------------------------------------------------------//
BOOL CProcConDB::GetNameRules( const PCINT32 first, PCNameRule *pRules, const PCINT32 maxCount, PCINT16 *itemLen, PCINT16 *itemCount, PCINT32 *updCtr ) { EnterCriticalSection( &m_dbCSNameRule );
*itemLen = sizeof(PCNameRule); *itemCount = 0; *updCtr = m_updCtrName;
// copy data to buffer until end of data or max requested hit
for ( PCULONG32 i = first, numRules = m_numNameRules; i < numRules && *itemCount < maxCount; ++i, ++*itemCount ) memcpy( pRules++, &m_fmtNameRules[i], *itemLen );
LeaveCriticalSection( &m_dbCSNameRule );
return i < numRules; }
//--------------------------------------------------------------------------------------------//
// Function to add a name rule //
// Input: new rule, data version, new index ("add before index"), update counter //
// Returns: PCERROR_SUCCESS if successful, error code if not //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::AddNameRule( const PCNameRule *pRule, const BYTE version, const PCULONG32 index, const PCINT32 updCtr ) { PCINT32 APIerr = PCERROR_SUCCESS; PROC_NAME procName = { 0 };
EnterCriticalSection( &m_dbCSNameRule );
if ( updCtr != m_updCtrName ) APIerr = PCERROR_UPDATE_OCCURRED; else if ( index >= m_numNameRules ) APIerr = PCERROR_INDEX_OUT_OF_RANGE; else { PCNameRule *newRules = new PCNameRule[m_numNameRules + 1]; PCULONG32 newSize = sizeof(PCNameRule) * (m_numNameRules + 1); if ( !newRules ) { PCLogNoMemory( TEXT("AllocFmtNameRules"), newSize ); APIerr = PCERROR_SERVER_INTERNAL_ERROR; } else { memcpy(procName, &m_fmtNameRules[index].procName, sizeof(procName)); memset( newRules, 0, newSize ); for ( PCULONG32 i = 0, j = 0; i < m_numNameRules; ++i ) { if ( index == i ) memcpy( &newRules[j++], pRule, sizeof(newRules[0]) ); memcpy( &newRules[j++], &m_fmtNameRules[i], sizeof(newRules[0]) ); } if ( m_intNameRules ) { delete [] m_intNameRules; m_intNameRules = NULL; } PCNameRule *oldRules = m_fmtNameRules; m_fmtNameRules = newRules; ++m_numNameRules; APIerr = NameRulesUpdated(); if ( APIerr != ERROR_SUCCESS ) { m_fmtNameRules = oldRules; --m_numNameRules; delete [] newRules; } else delete [] oldRules; } }
LeaveCriticalSection( &m_dbCSNameRule );
if ( APIerr == PCERROR_SUCCESS && m_LogRuleEdits ) { TCHAR indexString1[16], indexString2[16]; TCHAR matchTypeAsString[] = { pRule->matchType, 0}; _ultot( index, indexString1, 10 ); _ultot( index + 1, indexString2, 10 ); const TCHAR *msgs[] = { indexString1, pRule->procName, indexString2, procName, pRule->description, pRule->matchString, matchTypeAsString };
PCLogMessage( PC_SERVICE_ADD_ALIAS_RULE, EVENTLOG_INFORMATION_TYPE, ENTRY_COUNT(msgs), msgs); }
return APIerr; }
//--------------------------------------------------------------------------------------------//
// Function to replace a name rule //
// Input: new rule, data version, index of rule to replace, update counter //
// Returns: PCERROR_SUCCESS if successful, error code if not //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::ReplNameRule( const PCNameRule *pRule, const BYTE version, const PCULONG32 index, const PCINT32 updCtr ) { PCINT32 APIerr = PCERROR_SUCCESS; PCNameRule oldRule;
EnterCriticalSection( &m_dbCSNameRule );
if ( updCtr != m_updCtrName ) APIerr = PCERROR_UPDATE_OCCURRED; else if ( index >= m_numNameRules - 1 ) APIerr = PCERROR_INDEX_OUT_OF_RANGE; else { memcpy( &oldRule, &m_fmtNameRules[index], sizeof(oldRule) ); memcpy( &m_fmtNameRules[index], pRule, sizeof(m_fmtNameRules[index]) ); BuildIntNameRule( index ); APIerr = NameRulesUpdated(); }
LeaveCriticalSection( &m_dbCSNameRule );
if ( APIerr == PCERROR_SUCCESS && m_LogRuleEdits ) { TCHAR indexAsString[16]; TCHAR matchTypeAsString[] = { pRule->matchType, 0 }; TCHAR matchType2AsString[] = { oldRule.matchType, 0 }; _ultot( index, indexAsString, 10 ); const TCHAR *msgs[] = { indexAsString, pRule->procName, oldRule.procName, pRule->description, oldRule.description, pRule->matchString, oldRule.matchString, matchTypeAsString, matchType2AsString, };
PCLogMessage( PC_SERVICE_REPL_ALIAS_RULE, EVENTLOG_INFORMATION_TYPE, ENTRY_COUNT(msgs), msgs); }
return APIerr; }
//--------------------------------------------------------------------------------------------//
// Function to delete a name rule //
// Input: index of rule to delete, update counter //
// Returns: PCERROR_SUCCESS if successful, error code if not //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::DelNameRule( const PCULONG32 index, const PCINT32 updCtr ) { PCINT32 APIerr = PCERROR_SUCCESS; PROC_NAME procName = { 0 };
EnterCriticalSection( &m_dbCSNameRule );
if ( updCtr != m_updCtrName ) APIerr = PCERROR_UPDATE_OCCURRED; else if ( index >= m_numNameRules - 1 ) APIerr = PCERROR_INDEX_OUT_OF_RANGE; else { PCNameRule *newRules = new PCNameRule[m_numNameRules - 1]; memcpy(procName, &m_fmtNameRules[index].procName, sizeof(procName)); if ( !newRules ) { PCLogNoMemory( TEXT("AllocFmtNameRules"), sizeof(PCNameRule) * (m_numNameRules - 1) ); APIerr = PCERROR_SERVER_INTERNAL_ERROR; } else { for ( PCULONG32 i = 0, j = 0; i < m_numNameRules; ++i ) { if ( index != i ) memcpy( &newRules[j++], &m_fmtNameRules[i], sizeof(m_fmtNameRules[i]) ); } delete [] m_fmtNameRules; if ( m_intNameRules ) { delete [] m_intNameRules; m_intNameRules = NULL; } m_fmtNameRules = newRules; --m_numNameRules; APIerr = NameRulesUpdated(); } }
LeaveCriticalSection( &m_dbCSNameRule );
if ( APIerr == PCERROR_SUCCESS && m_LogRuleEdits ) PCLogMessage( PC_SERVICE_DEL_ALIAS_RULE, EVENTLOG_INFORMATION_TYPE, 1, procName ); return APIerr; }
//--------------------------------------------------------------------------------------------//
// Function to swap adjacent name rules //
// Input: index of rule to swap with following rule, update counter //
// Returns: PCERROR_SUCCESS if successful, error code if not //
//--------------------------------------------------------------------------------------------//
PCULONG32 CProcConDB::SwapNameRule( const PCULONG32 index, const PCINT32 updCtr ) { PCINT32 APIerr = PCERROR_SUCCESS; PROC_NAME procName1 = { 0 }; PROC_NAME procName2 = { 0 };
EnterCriticalSection( &m_dbCSNameRule );
if ( updCtr != m_updCtrName ) APIerr = PCERROR_UPDATE_OCCURRED; else if ( index >= m_numNameRules - 2 ) APIerr = PCERROR_INDEX_OUT_OF_RANGE; else { PCNameRule rule; memcpy(procName1, &m_fmtNameRules[index].procName, sizeof(procName1)); memcpy(procName2, &m_fmtNameRules[index+1].procName, sizeof(procName2)); memcpy( &rule, &m_fmtNameRules[index], sizeof(rule) ); memcpy( &m_fmtNameRules[index], &m_fmtNameRules[index + 1], sizeof(rule) ); memcpy( &m_fmtNameRules[index + 1], &rule, sizeof(rule) ); BuildIntNameRule( index ); BuildIntNameRule( index + 1 ); APIerr = NameRulesUpdated(); }
LeaveCriticalSection( &m_dbCSNameRule );
if ( APIerr == PCERROR_SUCCESS && m_LogRuleEdits ) { TCHAR indexString1[16], indexString2[16]; _ultot( index, indexString1, 10 ); _ultot( index + 1, indexString2, 10 ); const TCHAR *msgs[] = { indexString1, procName1, indexString2, procName2 }; PCLogMessage( PC_SERVICE_SWAP_ALIAS_RULE, EVENTLOG_INFORMATION_TYPE, ENTRY_COUNT(msgs), msgs ); } return APIerr; }
//--------------------------------------------------------------------------------------------//
// Functions to get proc list data in API format //
// Input: start point and target loc, max count, item len return, item count return //
// Returns: TRUE if more data exists, else FALSE (there are no error conditions) //
//--------------------------------------------------------------------------------------------//
BOOL CProcConDB::GetProcList( const PCProcListItem *pStart, const PCUINT32 listFlags, PCProcListItem *pList, const PCINT32 maxCount, PCINT16 *itemLen, PCINT16 *itemCount ) {
*itemLen = sizeof(PCProcListItem); *itemCount = 0;
PCULONG32 procEntries = 0, nameEntries = 0, activeEntries = 0; PCProcListItem *procList = NULL, *nameList = NULL;
// Get process definition rule data...
EnterCriticalSection( &m_dbCSProcRule );
procEntries = m_numProcRules;
// allocate space for process definition list...
procList = new PCProcListItem[ procEntries ]; if ( !procList ) { PCLogNoMemory( TEXT("AllocProcList1"), sizeof(PCProcListItem) * procEntries ); procEntries = 0; } memset( procList, 0, sizeof(PCProcListItem) * procEntries );
// Add names of defined processes...
for ( PCULONG32 i = 0; i < procEntries; ++i ) { memcpy( procList[i].procName, m_procSummary[i].procName, sizeof(procList->procName) ); procList[i].lFlags = PCLFLAG_IS_DEFINED; if ( m_procSummary[i].mgmtParms.mFlags & PCMFLAG_PROC_HAS_JOB_REFERENCE ) { procList[i].lFlags |= PCLFLAG_HAS_MEMBER_OF_JOB; memcpy( procList[i].jobName, m_procSummary[i].memberOfJobName, sizeof(procList->jobName) ); } if ( PCIsProcManaged( m_procSummary[i].mgmtParms, &m_procSummary[i].memberOfJobName ) ) procList[i].lFlags |= PCLFLAG_IS_MANAGED; }
LeaveCriticalSection( &m_dbCSProcRule );
// Get name rule data...
EnterCriticalSection( &m_dbCSNameRule );
PCULONG32 names = m_numNameRules - 1; // exclude default rule which is last
// allocate space for name list...
nameList = new PCProcListItem[ names ]; if ( !nameList ) { PCLogNoMemory( TEXT("AllocProcList2"), sizeof(PCProcListItem) * names ); names = 0; } memset( nameList, 0, sizeof(PCProcListItem) * names );
// Add names from name rules...
for ( i = 0; i < names; ++i ) { if ( !NameHasPattern( m_fmtNameRules[i].procName ) ) { memcpy( nameList[nameEntries].procName, m_fmtNameRules[i].procName, sizeof(nameList->procName) ); nameList[nameEntries++].lFlags = PCLFLAG_HAS_NAME_RULE; } }
LeaveCriticalSection( &m_dbCSNameRule );
// Get running process data--------------------------------------------------------
PCProcListItem *activeList; activeEntries = m_cMgr->ExportActiveProcList( &activeList );
// Build full list...
PCULONG32 entries = procEntries + nameEntries + activeEntries; PCProcListItem *fullList = new PCProcListItem[ entries ]; if ( !fullList ) { PCLogNoMemory( TEXT("AllocProcList3"), sizeof(PCProcListItem) * entries ); entries = procEntries = nameEntries = activeEntries = 0; }
if ( procEntries ) memcpy( fullList, procList, sizeof(PCProcListItem) * procEntries ); if ( nameEntries ) memcpy( fullList + procEntries, nameList, sizeof(PCProcListItem) * nameEntries ); if ( activeEntries ) memcpy( fullList + procEntries + nameEntries, activeList, sizeof(PCProcListItem) * activeEntries );
delete [] procList; delete [] nameList; delete [] activeList;
qsort( fullList, entries, *itemLen, CompareProcListItem );
// copy data to buffer until end of data or max requested hit...
int rc; PC_LIST_FLAGS lastFlags = 0; PCProcListItem li; // list item being built
memset( &li, 0, sizeof(li) );
for ( i = 0, *itemCount = 0; i < entries && *itemCount < maxCount; lastFlags = fullList[i++].lFlags ) { // if name changed or both have pids we have a new process...
if ( (rc = CompareProcName( li.procName, fullList[i].procName )) || (li.procStats.pid && fullList[i].procStats.pid) ) { // See if new name belongs in the list and, if so, wrap up last entry and start new...
if ( ProcBelongsInList( li, pStart, listFlags ) ) { memcpy( pList, &li, *itemLen ); pList->lFlags |= lastFlags; ++pList; ++*itemCount; } PC_LIST_FLAGS savedFlags = li.lFlags; memcpy( &li, &fullList[i], *itemLen ); li.actualPriority = PCMapPriorityForAPI( li.actualPriority ); if ( !rc ) li.lFlags = savedFlags; } else { li.lFlags |= fullList[i].lFlags; if ( fullList[i].lFlags & PCLFLAG_IS_RUNNING ) { memcpy( &li.procStats, &fullList[i].procStats, sizeof(li.procStats) ); memcpy( li.imageName, fullList[i].imageName, sizeof(li.imageName) ); memcpy( li.jobName, fullList[i].jobName, sizeof(li.jobName) ); li.actualPriority = PCMapPriorityForAPI( fullList[i].actualPriority ); li.actualAffinity = fullList[i].actualAffinity; } if ( fullList[i].lFlags & PCLFLAG_HAS_MEMBER_OF_JOB ) memcpy( li.jobName, fullList[i].jobName, sizeof(li.jobName) ); } } if ( *itemCount < maxCount && ProcBelongsInList( li, pStart, listFlags ) ) { memcpy( pList, &li, *itemLen ); pList->lFlags |= lastFlags; ++*itemCount; }
delete [] fullList;
return i < entries; }
//--------------------------------------------------------------------------------------------//
// Functions to get job list data in API format //
// Input: start point and target loc, max count, item len return, item count return //
// Returns: TRUE if more data exists, else FALSE (there are no error conditions) //
//--------------------------------------------------------------------------------------------//
BOOL CProcConDB::GetJobList( const PCJobListItem *pStart, const PCUINT32 listFlags, PCJobListItem *pList, const PCINT32 maxCount, PCINT16 *itemLen, PCINT16 *itemCount ) {
*itemLen = sizeof(PCJobListItem); *itemCount = 0;
PCULONG32 jobEntries = 0, jrefEntries = 0, activeEntries = 0; PCJobListItem *jobList = NULL, *jrefList = NULL;
// Get job definition rule data...
EnterCriticalSection( &m_dbCSJobRule );
jobEntries = m_numJobRules;
// allocate space for job definition list...
jobList = new PCJobListItem[ jobEntries ]; if ( !jobList ) { PCLogNoMemory( TEXT("AllocJobList1"), sizeof(PCJobListItem) * jobEntries ); jobEntries = 0; } else memset( jobList, 0, sizeof(PCJobListItem) * jobEntries );
// Add names of defined jobs...
for ( PCULONG32 i = 0; i < jobEntries; ++i ) { memcpy( jobList[i].jobName, m_jobSummary[i].jobName, sizeof(jobList->jobName) ); jobList[i].lFlags = PCLFLAG_IS_DEFINED; if ( PCIsJobManaged( m_jobSummary[i].mgmtParms ) ) jobList[i].lFlags |= PCLFLAG_IS_MANAGED; }
LeaveCriticalSection( &m_dbCSJobRule );
EnterCriticalSection( &m_dbCSProcRule );
jrefEntries = m_numProcRules;
// allocate space for job reference list...
jrefList = new PCJobListItem[ jrefEntries ]; if ( !jrefList ) { PCLogNoMemory( TEXT("AllocJobList2"), sizeof(PCJobListItem) * jrefEntries ); jrefEntries = 0; } else memset( jrefList, 0, sizeof(PCJobListItem) * jrefEntries );
// Add names from process definitions...
PCULONG32 ctr = 0; for ( i = 0; i < jrefEntries; ++i ) { if ( *(m_procSummary[i].memberOfJobName) ) { memcpy( jrefList[ctr].jobName, m_procSummary[i].memberOfJobName, sizeof(jrefList->jobName) ); jrefList[ctr].lFlags = PCLFLAG_HAS_MEMBER_OF_JOB; ++ctr; } } jrefEntries = ctr;
LeaveCriticalSection( &m_dbCSProcRule );
// Add names of running jobs...
PCJobListItem *activeList; activeEntries = m_cMgr->ExportActiveJobList( &activeList );
// Build full list...
PCULONG32 entries = jobEntries + jrefEntries + activeEntries; PCJobListItem *fullList = new PCJobListItem[ entries ]; if ( !fullList ) { PCLogNoMemory( TEXT("AllocJobList3"), sizeof(PCJobListItem) * entries ); entries = jobEntries = jrefEntries = activeEntries = 0; } if ( jobEntries ) memcpy( fullList, jobList, sizeof(PCJobListItem) * jobEntries ); if ( jrefEntries ) memcpy( fullList + jobEntries, jrefList, sizeof(PCJobListItem) * jrefEntries ); if ( activeEntries ) memcpy( fullList + jobEntries + jrefEntries, activeList, sizeof(PCJobListItem) * activeEntries );
delete [] jobList; delete [] jrefList; delete [] activeList;
// Sort full list...
qsort( fullList, entries, *itemLen, CompareJobListItem );
// copy data to buffer until end of data or max requested hit...
PCJobListItem li; // list item being built
memset( &li, 0, sizeof(li) );
for ( i = 0, *itemCount = 0; i < entries && *itemCount < maxCount; ++i ) { // if name changed we have a new job...
if ( CompareJobName( li.jobName, fullList[i].jobName ) ) { if ( JobBelongsInList( li, pStart, listFlags ) ) { memcpy( pList++, &li, *itemLen ); ++*itemCount; } memcpy( &li, &fullList[i], *itemLen ); li.actualPriority = PCMapPriorityForAPI( li.actualPriority ); } else { li.lFlags |= fullList[i].lFlags; if ( fullList[i].lFlags & PCLFLAG_IS_RUNNING ) { li.actualPriority = PCMapPriorityForAPI( fullList[i].actualPriority ); li.actualAffinity = fullList[i].actualAffinity; li.actualSchedClass = fullList[i].actualSchedClass; memcpy( &li.jobStats, &fullList[i].jobStats, sizeof(li.jobStats) ); } } } if ( *itemCount < maxCount && *li.jobName && JobBelongsInList( li, pStart, listFlags ) ) { memcpy( pList, &li, *itemLen ); ++*itemCount; }
delete [] fullList;
return i < entries; }
//--------------------------------------------------------------------------------------------//
// Functions to assign a process name given a path+exe name //
// Input: path name, location to build proc name //
// Returns: nothing -- cannot fail due to default name rule //
//--------------------------------------------------------------------------------------------//
void CProcConDB::AssignProcName( const TCHAR *path, PROC_NAME *name, IMAGE_NAME *iName ) {
// First parse path name into nodes and exe name...
TCHAR pCopy[MAX_PATH]; TCHAR *nodes[MAX_PATH / 2], *p = pCopy; _tcscpy( pCopy, path );
if ( *(p + 1) == TEXT('?') ) // skip if we have a \??\ prefix
p += 4;
// jump over leading drive letter or computer and share (UNC) name...
if ( *(p + 1) == TEXT(':') ) p += 2; else if ( *(p + 1) == TEXT('\\') ) { p = _tcschr( p + 2, TEXT('\\') ); // scan for end of computer name
if ( p ) p = _tcschr( p + 1, TEXT('\\') ); // scan for end of share name
if ( p ) ++p; // advance to first of path name
}
if ( p && *p == TEXT('\\') ) ++p; // skip \ if we start at root
// locate and save start of each node, setting '\' to null to get szstrings...
for ( PCULONG32 nodeCt = 0; p && nodeCt < ENTRY_COUNT(nodes); ++nodeCt ) { nodes[nodeCt] = p; p = _tcschr( p, TEXT('\\') ); if ( p ) *p++ = 0; } if ( !nodeCt ) { // should not occur
_tcscpy( (TCHAR *) name, TEXT("<err>") ); _tcscpy( (TCHAR *) iName, TEXT("<err>") ); return; }
// set exe name pointer and extension location...
TCHAR *exeName = nodes[--nodeCt]; _tcsncpy( (TCHAR *) iName, exeName, IMAGE_NAME_LEN ); const int extStart = ExtStartLoc( exeName );
// Gain control over rules and build internal version if needed...
EnterCriticalSection( &m_dbCSNameRule );
if ( !m_intNameRules && !BuildIntNameRules() ) { LeaveCriticalSection( &m_dbCSNameRule ); return; }
// scan rules until we have a match...
for ( PCULONG32 i = 0, done = FALSE; !done && i < m_numNameRules; ++i ) { switch ( m_intNameRules[i].mType ) { case MATCH_PGM: if ( !(m_intNameRules[i].mFlags & MFLAG_HAS_EXTENSION) && extStart ) exeName[extStart] = 0; if ( NameMatch( TRUE, m_intNameRules[i].mFlags & MFLAG_HAS_WILDCARD, m_intNameRules[i].mString, (const TCHAR **) &exeName ) ) { NameSet( name, m_intNameRules[i].mFlags & MFLAG_HAS_NAME_PATTERN, m_intNameRules[i].mName, exeName ); done = TRUE; } if ( !(m_intNameRules[i].mFlags & MFLAG_HAS_EXTENSION) && extStart ) exeName[extStart] = TEXT('.'); break; case MATCH_DIR: { PCULONG32 matchNode; if ( NameMatch( TRUE, m_intNameRules[i].mFlags & MFLAG_HAS_WILDCARD, m_intNameRules[i].mString, (const TCHAR **) nodes, nodeCt, &matchNode ) ) { NameSet( name, m_intNameRules[i].mFlags & MFLAG_HAS_NAME_PATTERN, m_intNameRules[i].mName, exeName, nodes[matchNode] ); done = TRUE; } break; } case MATCH_ANY: if ( NameMatch( FALSE, m_intNameRules[i].mFlags & MFLAG_HAS_WILDCARD, m_intNameRules[i].mString, &path ) ) { NameSet( name, m_intNameRules[i].mFlags & MFLAG_HAS_NAME_PATTERN, m_intNameRules[i].mName, exeName ); done = TRUE; } break; } // end switch
} // end for
LeaveCriticalSection( &m_dbCSNameRule );
if ( !done ) // should not occur
_tcscpy( (TCHAR *) name, TEXT("<err>") ); }
BOOL CProcConDB::NameMatch( const BOOL compare, // TRUE for compare operation, FALSE for scan
const BOOL hasWildcard, // string contains wildcard character(s)
const TCHAR *str, // string to match against
const TCHAR **arg, // path name argument(s)
const PCULONG32 argCt, // number of arguments
PCULONG32 *mIdx ) { // where to store matching arg index or NULL
BOOL good = FALSE;
// Compare against every match argument supplied...
for ( PCULONG32 i = 0; !good && i < argCt; ++i, ++arg ) { // for wildcard compares scan character by character...
if ( hasWildcard ) { good = TRUE; for ( const TCHAR *p = str, *a = *arg; good && *p && *p != TEXT('*'); ++p, ++a ) good = (*a && *p == TEXT('?')) || _totupper( *p ) == _totupper( *a ); } // for non-wildcard compares just do straight compare or scan...
else good = ( compare && !_tcsicmp( *arg, str ) ) || ( !compare && PCiStrStr( *arg, str ) ); }
if ( good && mIdx ) *mIdx = i -1;
return good; }
void CProcConDB::NameSet( PROC_NAME *name, // where to put name
const BOOL isPattern, // string contains <x> pattern(s)
const TCHAR *pattern, // where to get name
const TCHAR *patArgP, // where to get pgm pattern substitution
const TCHAR *patArgN ) { // where to get node pattern substitution or NULL
memset( name, 0, sizeof(*name) );
if ( !isPattern ) _tcsncpy( (TCHAR *) name, pattern, ENTRY_COUNT(*name) - 1 ); else { TCHAR out[MAX_PATH * 2]; memset( out, 0, sizeof(out) ); TCHAR *outp = out; for ( PCULONG32 i = 0; *pattern; ++i ) { if ( !_tcsnicmp( pattern, NAME_IS_PGM, 3 ) ) { _tcscpy( outp, patArgP ); outp += _tcslen( patArgP ); pattern += 3; } else if ( !_tcsnicmp( pattern, HIDE_PROC_PATTERN, 3 ) ) { *name[0] = 0; return; } else if ( patArgN && !_tcsnicmp( pattern, NAME_IS_DIR, 3 ) ) { _tcscpy( outp, patArgN ); outp += _tcslen( patArgN ); pattern += 3; } else *outp++ = *pattern++; } _tcsncpy( (TCHAR *) name, out, ENTRY_COUNT(*name) - 1 ); } }
int CProcConDB::ExtStartLoc( const TCHAR *name ) { // Find start of name extension or 0
int len = _tcslen( name ); for ( int i = len - 1; i > 0 && i > len - 4; --i ) if ( name[i] == TEXT('.') ) break; return ( i > 0 && name[i] == TEXT('.') )? i : 0; }
//--------------------------------------------------------------------------------------------//
// Functions to build internal format name rules based on API format name rules //
// Input: nothing -- operates on member data //
// Returns: TRUE if successful, else FALSE //
// Note: caller must hold the name rule critical section //
//--------------------------------------------------------------------------------------------//
BOOL CProcConDB::BuildIntNameRules( void ) {
if ( m_intNameRules ) delete [] m_intNameRules; m_intNameRules = new PCNameRuleInt[m_numNameRules];
if ( !m_intNameRules ) { PCLogNoMemory( TEXT("AllocIntNameRules"), m_numNameRules * sizeof(PCNameRuleInt) ); return FALSE; }
for ( PCULONG32 i = 0; i < m_numNameRules; ++i ) BuildIntNameRule( i );
return TRUE; }
void CProcConDB::BuildIntNameRule( PCULONG32 index ) {
if ( !m_intNameRules || index >= m_numNameRules ) return;
PCNameRuleInt &iRule = m_intNameRules[index]; PCNameRule &fRule = m_fmtNameRules[index]; memset( &iRule, 0, sizeof(iRule) );
// Copy match type...
iRule.mType = fRule.matchType;
// Copy/expand match string...
ExpandEnvironmentStrings( fRule.matchString, iRule.mString, ENTRY_COUNT(iRule.mString) );
// Flag if match string contains wildcards * or ?...
if ( _tcschr( iRule.mString, TEXT('*') ) || _tcschr( iRule.mString, TEXT('?') ) ) iRule.mFlags |= MFLAG_HAS_WILDCARD; // Flag if match string contains extension...
if ( ExtStartLoc( iRule.mString ) ) iRule.mFlags |= MFLAG_HAS_EXTENSION;
// Copy name and flag if name contains pattern (assume pattern if '<' present)...
memcpy( iRule.mName, fRule.procName, sizeof(iRule.mName) ); if ( NameHasPattern( iRule.mName ) ) iRule.mFlags |= MFLAG_HAS_NAME_PATTERN; // Copy description...
memcpy( iRule.mDesc, fRule.description, sizeof(iRule.mDesc) ); }
//--------------------------------------------------------------------------------------------//
// Function to test users right to perform an action //
// Input: action name ptr //
// Returns: ERROR_SUCCESS if access is allowed, else an error code //
// Note: access tests are implemented as READ tests against a registry key in PARAMETERS. //
// Also, any failure is reported as access denied in the spirit of reporting little //
// information in case of security failures. //
//--------------------------------------------------------------------------------------------//
INT32 CProcConDB::TestAccess( const TCHAR *key ) { HKEY outKey;
DWORD err = RegOpenKeyEx( m_parmRegKey, key, NULL, KEY_QUERY_VALUE, &outKey ); if ( err == ERROR_SUCCESS ) RegCloseKey( outKey ); else { err = ERROR_ACCESS_DENIED; // always use access denied to report failure
SetLastError( err ); }
return err; }
// End of CProcConDB.cpp
//============================================================================J McDonald fecit====//
|