Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2522 lines
112 KiB

  1. /*======================================================================================//
  2. | //
  3. |Copyright (c) 1998, 1999 Sequent Computer Systems, Incorporated //
  4. | //
  5. |Description: //
  6. | //
  7. |---------------------------------------------------------------------------------------//
  8. | This file implements the CProcConDB class methods defined in ProcConSvc.h //
  9. |---------------------------------------------------------------------------------------//
  10. | //
  11. |Created: //
  12. | //
  13. | Jarl McDonald 07-98 //
  14. | //
  15. |Revision History: //
  16. | Paul Skoglund 04-2001 //
  17. | -Support Microsoft feature request to add event log reporting for all Proccon //
  18. | rule editing. //
  19. | -Fix bug with restore not flushing old process and group execution rules. //
  20. | Problem appeared if the restore didn't include any process execution rules //
  21. | or group execution rules. //
  22. | Paul Skoglund 05-2001 //
  23. | -Remove rounding to page boundry of working set min and max values. This is //
  24. | now done in the apply functions; this is consistent with the handling of //
  25. | process and job committed memory limits. //
  26. |=======================================================================================*/
  27. #include "ProcConSvc.h"
  28. const TCHAR CProcConDB::PCDB_PREFIX_FLAGS = TEXT('F');
  29. const TCHAR CProcConDB::PCDB_PREFIX_AFFINITY = TEXT('A');
  30. const TCHAR CProcConDB::PCDB_PREFIX_PRIORITY = TEXT('P');
  31. const TCHAR CProcConDB::PCDB_PREFIX_MINWS = TEXT('L');
  32. const TCHAR CProcConDB::PCDB_PREFIX_MAXWS = TEXT('H');
  33. const TCHAR CProcConDB::PCDB_PREFIX_SCHEDCLASS = TEXT('S');
  34. const TCHAR CProcConDB::PCDB_PREFIX_PROCTIME = TEXT('T');
  35. const TCHAR CProcConDB::PCDB_PREFIX_JOBTIME = TEXT('U');
  36. const TCHAR CProcConDB::PCDB_PREFIX_ACTIVEPROCS = TEXT('C');
  37. const TCHAR CProcConDB::PCDB_PREFIX_PROCMEMORY = TEXT('M');
  38. const TCHAR CProcConDB::PCDB_PREFIX_JOBMEMORY = TEXT('N');
  39. const TCHAR CProcConDB::BEG_BRACKET = TEXT('{'); // leading char in rules stored in DB
  40. const TCHAR CProcConDB::END_BRACKET = TEXT('}'); // trailing char in rules stored in DB
  41. const TCHAR CProcConDB::FIELD_SEP = TEXT(','); // separates fields in rules stored in DB
  42. const TCHAR CProcConDB::STRING_DELIM = TEXT('"'); // delimits text strings stored in DB
  43. const TCHAR CProcConDB::RULE_MATCHONE = TEXT('?');
  44. const TCHAR CProcConDB::RULE_MATCHANY = TEXT('*');
  45. const TCHAR CProcConDB::NAME_IS_PGM[] = COPY_PGM_NAME;
  46. const TCHAR CProcConDB::NAME_IS_DIR[] = COPY_DIR_NAME;
  47. const TCHAR CProcConDB::HIDE_PROC_PATTERN[] = HIDE_THIS_PROC;
  48. const TCHAR CProcConDB::PATTERN_CHARS[] = TEXT("PDH");
  49. PCNameRule CProcConDB::DEFAULT_NAME_RULE = { { RULE_MATCHANY, 0 }, COPY_PGM_NAME, { 0 }, MATCH_PGM };
  50. // CProcConDB Constructor
  51. // Note: this runs as part of service start so keep it quick!
  52. CProcConDB::CProcConDB( PCUINT32 pageSize ) :
  53. m_fmtNameRules( NULL ), m_intNameRules( NULL ),
  54. m_parmRegKey( NULL ), m_procRegKey( NULL ), m_jobRegKey( NULL ),
  55. m_dbEvent( NULL ), m_parmEvent( NULL ),
  56. m_procSummary( NULL ), m_jobSummary( NULL ),
  57. m_numNameRules( 0 ), m_numProcRules( 0 ), m_numJobRules( 0 ),
  58. m_updCtrName( 1 ), m_updCtrProc( 1 ), m_updCtrJob( 1 ),
  59. m_pollDelay( 60 ), m_pageSize( pageSize ), m_cMgr( NULL ),
  60. m_LogRuleEdits( TRUE )
  61. {
  62. InitializeCriticalSection( &m_dbCSNameRule );
  63. InitializeCriticalSection( &m_dbCSProcRule );
  64. InitializeCriticalSection( &m_dbCSJobRule );
  65. memset( m_curProfile, 0, sizeof(m_curProfile) );
  66. memcpy( DEFAULT_NAME_RULE.description, PROCCON_DEFAULT_NAMERULE_DESC, sizeof(DEFAULT_NAME_RULE.description) );
  67. if ( !PCBuildAdminSecAttr( m_secAttr ) ) return;
  68. if ( !OpenParmKey() ) return;
  69. if ( !OpenProcKey() ) return;
  70. if ( !OpenJobKey() ) return;
  71. // Get (or set to default if it doesn't exist) basic parameters...
  72. PCULONG32 dfltPoll = m_pollDelay; // save default
  73. m_lastRegError = GetPCParm( PROCCON_DATA_POLLDELAY, &m_pollDelay );
  74. if ( m_lastRegError != ERROR_SUCCESS ) {
  75. RegError( TEXT("Load/Set Parameter"), PROCCON_DATA_POLLDELAY );
  76. return;
  77. }
  78. if ( m_pollDelay < PC_MIN_POLL_DELAY || m_pollDelay > PC_MAX_POLL_DELAY ) // ensure sanity
  79. m_pollDelay = dfltPoll;
  80. m_pollDelay *= 1000; // convert to milliseconds
  81. m_dbEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
  82. m_parmEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
  83. if ( !m_dbEvent || !m_parmEvent ) { // Should never happen
  84. PCLogUnExError( m_dbEvent? TEXT("RegEvent") : TEXT("DBEvent"), TEXT("CreateEvent") );
  85. return;
  86. }
  87. m_lastRegError = RegNotifyChangeKeyValue( m_parmRegKey, TRUE,
  88. REG_NOTIFY_CHANGE_NAME + REG_NOTIFY_CHANGE_LAST_SET,
  89. m_parmEvent, TRUE );
  90. if ( m_lastRegError != ERROR_SUCCESS ) { // Should never happen
  91. RegError( TEXT("RegNotifyChangeKeyValue") );
  92. CloseHandle( m_parmEvent );
  93. m_parmEvent = NULL;
  94. return;
  95. }
  96. }
  97. // CProcConDB Destructor
  98. CProcConDB::~CProcConDB( void )
  99. {
  100. if ( m_fmtNameRules ) delete [] m_fmtNameRules;
  101. if ( m_intNameRules ) delete [] m_intNameRules;
  102. if ( m_parmRegKey ) RegCloseKey( m_parmRegKey );
  103. if ( m_procRegKey ) RegCloseKey( m_procRegKey );
  104. if ( m_jobRegKey ) RegCloseKey( m_jobRegKey );
  105. if ( m_dbEvent ) CloseHandle( m_dbEvent );
  106. if ( m_parmEvent ) CloseHandle( m_parmEvent );
  107. PCFreeSecAttr( m_secAttr );
  108. DeleteCriticalSection( &m_dbCSNameRule );
  109. DeleteCriticalSection( &m_dbCSProcRule );
  110. DeleteCriticalSection( &m_dbCSJobRule );
  111. }
  112. //--------------------------------------------------------------------------------------------//
  113. // Function to determine if all CProcConDB initial conditions have been met //
  114. // Input: None //
  115. // Returns: TRUE if ready, FALSE if not //
  116. //--------------------------------------------------------------------------------------------//
  117. BOOL CProcConDB::ReadyToRun( void )
  118. {
  119. return m_parmRegKey &&
  120. m_procRegKey &&
  121. m_jobRegKey &&
  122. m_dbEvent &&
  123. m_parmEvent &&
  124. m_secAttr.lpSecurityDescriptor;
  125. }
  126. //--------------------------------------------------------------------------------------------//
  127. // Function to create/open a registry key at HKEY_LOCAL_MACHINE level //
  128. // Input: key name, location of opened key //
  129. // Returns: ERROR_SUCCESS if successful, error code if not //
  130. // Note: key is created with DB security attributes (established in constructor). //
  131. //--------------------------------------------------------------------------------------------//
  132. PCULONG32 CProcConDB::CreateKeyAtHKLM( const TCHAR *key, HKEY *hKey ) {
  133. if ( !*hKey ) {
  134. PCULONG32 regDisp;
  135. m_lastRegError = RegCreateKeyEx( HKEY_LOCAL_MACHINE, key, 0, TEXT(""), 0,
  136. KEY_READ + KEY_WRITE, &m_secAttr, hKey, &regDisp );
  137. if ( m_lastRegError != ERROR_SUCCESS ) // Should never happen
  138. return RegError( TEXT("RegCreateKeyEx"), key );
  139. }
  140. return ERROR_SUCCESS;
  141. }
  142. //--------------------------------------------------------------------------------------------//
  143. // Function to drive the loading of all ProcCon rules from the database (NT registry) //
  144. // Input: which rules to load flags //
  145. // Returns: ERROR_SUCCESS if successful, NT error code if not //
  146. // Note: if an error is returned, an error event has been logged. //
  147. // if success is returned, a database event has been pulsed to wake those that care.//
  148. //--------------------------------------------------------------------------------------------//
  149. PCULONG32 CProcConDB::LoadRules( PCULONG32 which )
  150. {
  151. PCULONG32 rc = ERROR_SUCCESS;
  152. if ( which & LOADFLAG_NAME_RULES ) {
  153. EnterCriticalSection( &m_dbCSNameRule );
  154. ++m_updCtrName;
  155. rc = LoadNameRules( &m_numNameRules );
  156. LeaveCriticalSection( &m_dbCSNameRule );
  157. }
  158. if ( rc == ERROR_SUCCESS && which & LOADFLAG_PROC_RULES ) {
  159. EnterCriticalSection( &m_dbCSProcRule );
  160. ++m_updCtrProc;
  161. rc = LoadProcSummary();
  162. LeaveCriticalSection( &m_dbCSProcRule );
  163. }
  164. if ( rc == ERROR_SUCCESS && which & LOADFLAG_JOB_RULES ) {
  165. EnterCriticalSection( &m_dbCSJobRule );
  166. ++m_updCtrJob;
  167. rc = LoadJobSummary();
  168. LeaveCriticalSection( &m_dbCSJobRule );
  169. }
  170. if ( rc != ERROR_SUCCESS ) {
  171. SetLastError( rc );
  172. PCLogUnExError( TEXT("PCDataBase"), TEXT("LoadRules") );
  173. }
  174. else
  175. PulseEvent( m_dbEvent ); // Tell others database may have changed
  176. return rc;
  177. }
  178. //--------------------------------------------------------------------------------------------//
  179. // Function to load all ProcCon name rules from the database //
  180. // Input: pointer to rule count location, //
  181. // Returns: ERROR_SUCCESS if successful, NT error code if not //
  182. // Note: If an error is returned, an error event has been logged. //
  183. // N.B.: The appropriate critical section mast be held by the CALLER. //
  184. //--------------------------------------------------------------------------------------------//
  185. PCULONG32 CProcConDB::LoadNameRules( PCULONG32 *count )
  186. {
  187. // Determine size of data and validate type of data...
  188. // If data is missing or of invalid type, set to default (empty) value.
  189. PCULONG32 vType, vSize;
  190. vSize = 0;
  191. m_lastRegError = RegQueryValueEx( m_parmRegKey, PROCCON_DATA_NAMERULES,
  192. NULL, &vType, NULL, &vSize );
  193. if ( m_lastRegError != ERROR_SUCCESS && m_lastRegError != ERROR_FILE_NOT_FOUND )
  194. return RegError( TEXT("RegQueryValueEx"), PROCCON_DATA_NAMERULES );
  195. if ( vType != REG_MULTI_SZ || m_lastRegError == ERROR_FILE_NOT_FOUND ) {
  196. vType = REG_MULTI_SZ;
  197. vSize = 2 * sizeof(TCHAR);
  198. m_lastRegError = RegSetValueEx( m_parmRegKey, PROCCON_DATA_NAMERULES, NULL, vType,
  199. (UCHAR *) TEXT("\0\0"), vSize );
  200. if ( m_lastRegError != ERROR_SUCCESS )
  201. return RegDataError( PROCCON_DATA_NAMERULES );
  202. }
  203. // Allocate space for raw rules...
  204. *count = 0;
  205. TCHAR *rawNameRules = new TCHAR[vSize / sizeof(TCHAR)];
  206. if ( !rawNameRules )
  207. return PCLogNoMemory( TEXT("AllocNameRules"), vSize / sizeof(TCHAR) );
  208. // Load the rule data...
  209. m_lastRegError = RegQueryValueEx( m_parmRegKey, PROCCON_DATA_NAMERULES,
  210. NULL, &vType, (UCHAR *) rawNameRules, &vSize );
  211. if ( m_lastRegError != ERROR_SUCCESS ) {
  212. delete [] rawNameRules;
  213. return RegError( TEXT("RegQueryValueEx"), PROCCON_DATA_NAMERULES );
  214. }
  215. // Count strings in the data...
  216. PCULONG32 i, len;
  217. TCHAR *p, *end = rawNameRules + vSize / sizeof(TCHAR);
  218. if ( *rawNameRules ) {
  219. for ( p = rawNameRules; p < end; ++*count, p += _tcslen( p ) + 1 ) ;
  220. --*count; // uncount null entry at end due to double-NULL
  221. }
  222. // Delete old copy of rules, if any, and allocate and zero new......
  223. if ( m_fmtNameRules ) delete [] m_fmtNameRules;
  224. if ( m_intNameRules ) { delete [] m_intNameRules; m_intNameRules = NULL; }
  225. m_fmtNameRules = new PCNameRule[*count + 1]; // include an entry for our default rule
  226. if ( !m_fmtNameRules ) {
  227. delete [] rawNameRules;
  228. return PCLogNoMemory( TEXT("AllocFmtNameRules"), sizeof(PCNameRule) * (*count + 1) );
  229. }
  230. memset( m_fmtNameRules, 0, sizeof(PCNameRule) * (*count + 1) );
  231. // Build formatted copy from raw copy...
  232. for ( i = 0, p = rawNameRules; i < *count; ++i, p += len + 1 ) {
  233. len = _tcslen( p ); // length of this rule
  234. TCHAR *beg = p; // start of rule
  235. TCHAR *end = beg + len; // first byte past rule
  236. if ( *beg++ != BEG_BRACKET || *--end != END_BRACKET ) {
  237. delete [] rawNameRules;
  238. return RegDataError( PROCCON_DATA_NAMERULES );
  239. }
  240. m_fmtNameRules[i].matchType = *beg++; // get type, point to separator
  241. if ( *--end == STRING_DELIM ) { // if we have description, extract it
  242. TCHAR *strend = --end;
  243. while ( *end != STRING_DELIM && end > beg ) --end; // find matching delimiter
  244. PCULONG32 len = (PCULONG32) (strend - end);
  245. memcpy( m_fmtNameRules[i].description, end + 1, len * sizeof(TCHAR) );
  246. if ( end > beg ) end -= 2;
  247. }
  248. TCHAR *procEnd = end;
  249. while ( *end != FIELD_SEP && end > beg ) --end; // find last separator in rule
  250. if ( *beg != FIELD_SEP || *end != FIELD_SEP || beg == end ) {
  251. delete [] rawNameRules;
  252. return RegDataError( PROCCON_DATA_NAMERULES );
  253. }
  254. memcpy( m_fmtNameRules[i].matchString, beg + 1, (UINT32) (end - beg - 1) * sizeof(TCHAR) );
  255. memcpy( m_fmtNameRules[i].procName, end + 1, (UINT32) (procEnd - end) * sizeof(TCHAR) );
  256. }
  257. delete [] rawNameRules; // done with raw data
  258. // Add our default rule at end...
  259. memcpy( &m_fmtNameRules[*count], &DEFAULT_NAME_RULE, sizeof(DEFAULT_NAME_RULE) );
  260. ++*count; // count the default rule
  261. return ERROR_SUCCESS;
  262. }
  263. //--------------------------------------------------------------------------------------------//
  264. // Function to store all ProcCon name rules in the database //
  265. // Input: none -- m_fmtNameRules and m_numNameRules are the data source //
  266. // Returns: ERROR_SUCCESS if successful, NT error code if not //
  267. // Notes: 1) If an error is returned, an error event has been logged. //
  268. // 2) The appropriate critical section must be held by the CALLER. //
  269. // 3) The default rule, last in the list, is not stored in the database. //
  270. //--------------------------------------------------------------------------------------------//
  271. PCULONG32 CProcConDB::StoreNameRules( void )
  272. {
  273. TCHAR *rawNameRules = (TCHAR *) new char[(sizeof(PCNameRule) + 10) * m_numNameRules];
  274. if ( !rawNameRules )
  275. return PCLogNoMemory( TEXT("AllocNameRules"), sizeof(PCNameRule) * m_numNameRules );
  276. // Build raw (all character) format of all but last rule.mgmtParms...
  277. TCHAR *loc = rawNameRules;
  278. for ( PCULONG32 i = 0; i < m_numNameRules - 1; ++i ) {
  279. loc += _stprintf( loc, TEXT("%c%c%c%.*s%c%.*s%c%c%.*s%c%c"),
  280. BEG_BRACKET,
  281. m_fmtNameRules[i].matchType, FIELD_SEP,
  282. MATCH_STRING_LEN, m_fmtNameRules[i].matchString, FIELD_SEP,
  283. PROC_NAME_LEN, m_fmtNameRules[i].procName, FIELD_SEP,
  284. STRING_DELIM, NAME_DESCRIPTION_LEN, m_fmtNameRules[i].description, STRING_DELIM,
  285. END_BRACKET );
  286. *loc++ = 0; // terminate substring with NULL
  287. }
  288. *loc++ = 0; // terminated all data by a second NULL
  289. // Store the rule data...
  290. m_lastRegError = RegSetValueEx( m_parmRegKey, PROCCON_DATA_NAMERULES,
  291. NULL, REG_MULTI_SZ, (UCHAR *) rawNameRules,
  292. (ULONG32) ((UCHAR *) loc - (UCHAR *) rawNameRules) );
  293. delete [] ((char *) rawNameRules);
  294. if ( m_lastRegError != ERROR_SUCCESS )
  295. return RegError( TEXT("RegSetValueEx"), PROCCON_DATA_NAMERULES );
  296. return ERROR_SUCCESS;
  297. }
  298. //--------------------------------------------------------------------------------------------//
  299. // Function to load ProcCon process summary data from the database //
  300. // Input: none //
  301. // Returns: ERROR_SUCCESS if successful, NT error code if not //
  302. // Note: If an error is returned, an error event has been logged. //
  303. // N.B.: The appropriate critical section mast be held by the CALLER. //
  304. //--------------------------------------------------------------------------------------------//
  305. PCULONG32 CProcConDB::LoadProcSummary( void )
  306. {
  307. // Delete old data, if any...
  308. if ( m_procSummary ) {
  309. delete [] m_procSummary;
  310. m_procSummary = NULL;
  311. }
  312. m_numProcRules = 0;
  313. // Determine how many rules we have, done if none...
  314. m_lastRegError = RegQueryInfoKey( m_procRegKey, NULL, NULL, NULL, &m_numProcRules,
  315. NULL, NULL, NULL, NULL, NULL, NULL, NULL );
  316. if ( m_lastRegError != ERROR_SUCCESS ) { // Should never happen
  317. TCHAR key[MAX_PATH];
  318. return RegError( TEXT("RegQueryInfoKey"), BuildProcKey( key ) );
  319. }
  320. // Allocate storage for rules to be loaded...
  321. m_procSummary = new PCProcSummary[m_numProcRules];
  322. if ( !m_procSummary ) {
  323. m_numProcRules = 0;
  324. return PCLogNoMemory( TEXT("LoadProcessRules"), sizeof(PCProcSummary) * m_numProcRules );
  325. }
  326. memset( m_procSummary, 0, sizeof(PCProcSummary) * m_numProcRules );
  327. for ( PCULONG32 i = 0, err = 0; i < m_numProcRules; ++i ) {
  328. PCProcSummary &item = (m_procSummary)[i];
  329. // Get next subkey (proc name)...
  330. FILETIME keyLastWrite;
  331. PCULONG32 nameLen = ENTRY_COUNT(item.procName);
  332. m_lastRegError = RegEnumKeyEx( m_procRegKey, i, item.procName, &nameLen, NULL, NULL, NULL, &keyLastWrite );
  333. if ( m_lastRegError != ERROR_SUCCESS ) {
  334. TCHAR key[MAX_PATH];
  335. err = RegError( TEXT("RegEnumKeyEx"), BuildProcKey( key ) );
  336. break;
  337. }
  338. // Open the subkey to get proc details...
  339. HKEY hKeyTemp;
  340. m_lastRegError = RegOpenKeyEx( m_procRegKey, item.procName, 0, KEY_READ + KEY_WRITE, &hKeyTemp );
  341. if ( m_lastRegError != ERROR_SUCCESS ) { // Should never happen
  342. TCHAR key[MAX_PATH];
  343. err = RegError( TEXT("RegOpenKeyEx"), BuildProcKey( key ), item.procName );
  344. break;
  345. }
  346. err = LoadProcSummaryItem( hKeyTemp, item );
  347. RegCloseKey( hKeyTemp );
  348. }
  349. if ( err ) {
  350. delete [] m_procSummary;
  351. m_procSummary = NULL;
  352. m_numProcRules = 0;
  353. }
  354. else if ( m_numProcRules > 1 )
  355. qsort( m_procSummary, m_numProcRules, sizeof(PCProcSummary), CompareProcSummary );
  356. return err;
  357. }
  358. //--------------------------------------------------------------------------------------------//
  359. // Function to load summary data for a process from the database //
  360. // Input: registry key to use, //
  361. // summary structure to complete //
  362. // Returns: nothing (errors are handled by flagging the rule) //
  363. // Note: NT error code //
  364. //--------------------------------------------------------------------------------------------//
  365. PCULONG32 CProcConDB::LoadProcSummaryItem( const HKEY &hKey, PCProcSummary &item ) {
  366. // Get job membership information if this is a process name and MemberOf is present and valid..
  367. PCULONG32 byteType, workLen = sizeof(item.memberOfJobName);
  368. if ( RegQueryValueEx( hKey, PROCCON_DATA_MEMBEROF, NULL, &byteType, (UCHAR *)item.memberOfJobName, &workLen )
  369. == ERROR_SUCCESS && byteType == REG_SZ )
  370. item.mgmtParms.mFlags |= PCMFLAG_PROC_HAS_JOB_REFERENCE;
  371. return LoadMgmtRules( hKey, item.mgmtParms );
  372. }
  373. //--------------------------------------------------------------------------------------------//
  374. // Function to load job summary data from the database //
  375. // Input: none //
  376. // Returns: ERROR_SUCCESS if successful, NT error code if not //
  377. // Note: If an error is returned, an error event has been logged. //
  378. // N.B.: The appropriate critical section mast be held by the CALLER. //
  379. //--------------------------------------------------------------------------------------------//
  380. PCULONG32 CProcConDB::LoadJobSummary( void )
  381. {
  382. // Delete old data, if any...
  383. if ( m_jobSummary ) {
  384. delete [] m_jobSummary;
  385. m_jobSummary = NULL;
  386. }
  387. m_numJobRules = 0;
  388. // Determine how many rules we have, done if none...
  389. m_lastRegError = RegQueryInfoKey( m_jobRegKey, NULL, NULL, NULL, &m_numJobRules,
  390. NULL, NULL, NULL, NULL, NULL, NULL, NULL );
  391. if ( m_lastRegError != ERROR_SUCCESS ) { // Should never happen
  392. TCHAR key[MAX_PATH];
  393. return RegError( TEXT("RegQueryInfoKey"), BuildJobKey( key ) );
  394. }
  395. // Allocate storage for rules to be loaded...
  396. m_jobSummary = new PCJobSummary[m_numJobRules];
  397. if ( !m_jobSummary ) {
  398. m_numJobRules = 0;
  399. return PCLogNoMemory( TEXT("LoadJobessRules"), sizeof(PCJobSummary) * m_numJobRules );
  400. }
  401. memset( m_jobSummary, 0, sizeof(PCJobSummary) * m_numJobRules );
  402. for ( PCULONG32 i = 0, err = 0; i < m_numJobRules; ++i ) {
  403. PCJobSummary &item = (m_jobSummary)[i];
  404. // Get next subkey (job name)...
  405. FILETIME keyLastWrite;
  406. PCULONG32 nameLen = ENTRY_COUNT(item.jobName);
  407. m_lastRegError = RegEnumKeyEx( m_jobRegKey, i, item.jobName, &nameLen, NULL, NULL, NULL, &keyLastWrite );
  408. if ( m_lastRegError != ERROR_SUCCESS ) {
  409. TCHAR key[MAX_PATH];
  410. err = RegError( TEXT("RegEnumKeyEx"), BuildJobKey( key ) );
  411. break;
  412. }
  413. // Open the subkey to get job details...
  414. HKEY hKeyTemp;
  415. m_lastRegError = RegOpenKeyEx( m_jobRegKey, item.jobName, 0, KEY_READ + KEY_WRITE, &hKeyTemp );
  416. if ( m_lastRegError != ERROR_SUCCESS ) { // Should never happen
  417. TCHAR key[MAX_PATH];
  418. err = RegError( TEXT("RegOpenKeyEx"), BuildJobKey( key ), item.jobName );
  419. break;
  420. }
  421. err = LoadJobSummaryItem( hKeyTemp, item );
  422. RegCloseKey( hKeyTemp );
  423. }
  424. if ( err ) {
  425. delete [] m_jobSummary;
  426. m_jobSummary = NULL;
  427. m_numJobRules = 0;
  428. }
  429. else if ( m_numJobRules > 1 )
  430. qsort( m_jobSummary, m_numJobRules, sizeof(PCJobSummary), CompareJobSummary );
  431. return err;
  432. }
  433. //--------------------------------------------------------------------------------------------//
  434. // Function to load summary data for a job from the database //
  435. // Input: registry key to use, //
  436. // summary structure to complete //
  437. // Returns: nothing (errors are handled by flagging the rule) //
  438. // Note: NT error code //
  439. //--------------------------------------------------------------------------------------------//
  440. PCULONG32 CProcConDB::LoadJobSummaryItem( const HKEY &hKey, PCJobSummary &item ) {
  441. return LoadMgmtRules( hKey, item.mgmtParms );
  442. }
  443. //--------------------------------------------------------------------------------------------//
  444. // Function to load management data from the database //
  445. // Input: registry key to use, //
  446. // parameter structure to complete //
  447. // Returns: nothing (errors are handled by flagging the rule) //
  448. // Note: NT or PC error code //
  449. //--------------------------------------------------------------------------------------------//
  450. PCULONG32 CProcConDB::LoadMgmtRules( const HKEY &hKey, MGMT_PARMS &parms ) {
  451. ULONG byteType;
  452. TCHAR work[1024];
  453. PCULONG32 workLen;
  454. BOOL gotdata = FALSE;
  455. parms.affinity = parms.minWS = parms.maxWS = 0;
  456. parms.mFlags &= ~PCMFLAG_SAVEABLE_BITS; // clear database bits
  457. parms.priority = parms.schedClass = 0;
  458. memset( parms.description, 0, sizeof(parms.description) );
  459. memset( parms.future, 0, sizeof(parms.future) );
  460. // If we have a profile name, attempt to retrieve parameters for this profile..
  461. if ( *parms.profileName ) {
  462. workLen = sizeof(work);
  463. m_lastRegError = RegQueryValueEx( hKey, parms.profileName, NULL, &byteType, (
  464. UCHAR *)work, &workLen );
  465. if ( m_lastRegError == ERROR_SUCCESS )
  466. gotdata = TRUE;
  467. else if ( m_lastRegError != ERROR_FILE_NOT_FOUND )
  468. return RegError( TEXT("RegQueryValueEx"), parms.profileName );
  469. }
  470. // If no profile-based data, attempt to retrieve parameters via default name..
  471. if ( !gotdata ) {
  472. workLen = sizeof(work);
  473. m_lastRegError = RegQueryValueEx( hKey, PROCCON_DATA_DEFAULTRULES, NULL, &byteType,
  474. (UCHAR *)work, &workLen );
  475. if ( m_lastRegError != ERROR_SUCCESS ) {
  476. parms.mFlags |= PCMFLAG_NORULES;
  477. return RegError( TEXT("RegQueryValueEx"), PROCCON_DATA_DEFAULTRULES );
  478. }
  479. }
  480. // Verify basic format --- data between braces '{}'...
  481. TCHAR *beg = work, *end = work + workLen / sizeof(TCHAR) - 1;
  482. if ( *beg++ != BEG_BRACKET || *--end != END_BRACKET ) {
  483. parms.mFlags |= PCMFLAG_BADRULES;
  484. return PCERROR_BAD_DATABASE_DATA;
  485. }
  486. if ( beg == end ) return PCERROR_SUCCESS; // just an entry of "{}"
  487. for ( TCHAR *e = beg; *e; ++e ) {
  488. switch ( *e ) {
  489. case PCDB_PREFIX_FLAGS:
  490. parms.mFlags |= PCGetParmValue( e + 1, &e );
  491. break;
  492. case PCDB_PREFIX_AFFINITY:
  493. parms.affinity = PCGetParmValue64( e + 1, &e );
  494. break;
  495. case PCDB_PREFIX_PRIORITY:
  496. parms.priority = PCGetParmValue( e + 1, &e );
  497. break;
  498. case PCDB_PREFIX_MINWS:
  499. parms.minWS = PCGetParmValue64( e + 1, &e );
  500. break;
  501. case PCDB_PREFIX_MAXWS:
  502. parms.maxWS = PCGetParmValue64( e + 1, &e );
  503. break;
  504. case PCDB_PREFIX_SCHEDCLASS:
  505. parms.schedClass = PCGetParmValue( e + 1, &e );
  506. break;
  507. case PCDB_PREFIX_PROCTIME:
  508. parms.procTimeLimitCNS = PCGetParmValue64( e + 1, &e );
  509. break;
  510. case PCDB_PREFIX_JOBTIME:
  511. parms.jobTimeLimitCNS = PCGetParmValue64( e + 1, &e );
  512. break;
  513. case PCDB_PREFIX_ACTIVEPROCS:
  514. parms.procCountLimit = PCGetParmValue( e + 1, &e );
  515. break;
  516. case PCDB_PREFIX_PROCMEMORY:
  517. parms.procMemoryLimit = PCGetParmValue64( e + 1, &e );
  518. break;
  519. case PCDB_PREFIX_JOBMEMORY:
  520. parms.jobMemoryLimit = PCGetParmValue64( e + 1, &e );
  521. break;
  522. default:
  523. parms.mFlags |= PCMFLAG_BADRULES;
  524. return PCERROR_BAD_DATABASE_DATA;
  525. }
  526. if ( *e != END_BRACKET && *e != FIELD_SEP ) {
  527. parms.mFlags |= PCMFLAG_BADRULES;
  528. return PCERROR_BAD_DATABASE_DATA;
  529. }
  530. }
  531. // Load description, if any...
  532. workLen = sizeof(work);
  533. m_lastRegError = RegQueryValueEx( hKey, PROCCON_DATA_DESCRIPTION, NULL, &byteType,
  534. (UCHAR *)work, &workLen );
  535. if ( m_lastRegError == ERROR_SUCCESS )
  536. _tcsncpy( parms.description, work, RULE_DESCRIPTION_LEN );
  537. else if ( m_lastRegError != ERROR_FILE_NOT_FOUND )
  538. return RegError( TEXT("RegQueryValueEx"), PROCCON_DATA_DESCRIPTION );
  539. return PCERROR_SUCCESS;
  540. }
  541. //--------------------------------------------------------------------------------------------//
  542. // Function to store ProcCon process detail management rule in the database //
  543. // Input: ref to data to store. //
  544. // Returns: ERROR_SUCCESS if successful, NT or PC error code if not //
  545. // Note: If an error is returned, an error event has been logged. //
  546. // Note: The appropriate critical section mast be held by the CALLER. //
  547. // Note: key is created with DB security attributes (established in constructor). //
  548. //--------------------------------------------------------------------------------------------//
  549. PCULONG32 CProcConDB::StoreProcDetail( const PCProcDetail &rule )
  550. {
  551. // Open or create and open the process subkey...
  552. HKEY hKeyTemp;
  553. PCULONG32 regDisp;
  554. m_lastRegError = RegCreateKeyEx( m_procRegKey, rule.base.procName, 0, TEXT(""), 0,
  555. KEY_READ + KEY_WRITE, &m_secAttr, &hKeyTemp, &regDisp );
  556. if ( m_lastRegError != ERROR_SUCCESS ) // Should never happen
  557. return RegError( TEXT("RegCreateKeyEx"), rule.base.procName );
  558. PCULONG32 err = StoreProcValues( hKeyTemp, rule );
  559. RegCloseKey( hKeyTemp );
  560. return err;
  561. }
  562. //--------------------------------------------------------------------------------------------//
  563. // Function to store values for a job or process management rule in the database //
  564. // Input: registry key to use, //
  565. // management rule structure to store //
  566. // Returns: ERROR_SUCCESS if successful, NT or PC error code if not //
  567. // Note: Data errors lead to default behavior, not failure. //
  568. //--------------------------------------------------------------------------------------------//
  569. PCULONG32 CProcConDB::StoreProcValues( const HKEY &hKey, const PCProcDetail &rule ) {
  570. PCULONG32 err = 0;
  571. // Set/delete job membership information as needed...
  572. PCULONG32 len = _tcslen( rule.base.memberOfJobName );
  573. if ( len ) {
  574. m_lastRegError = RegSetValueEx( hKey, PROCCON_DATA_MEMBEROF, NULL, REG_SZ,
  575. (UCHAR *) rule.base.memberOfJobName, (len + 1) * sizeof(TCHAR) );
  576. if ( m_lastRegError != ERROR_SUCCESS ) // Should never happen
  577. err = RegError( TEXT("RegSetValueEx"), PROCCON_DATA_MEMBEROF );
  578. }
  579. else {
  580. m_lastRegError = RegDeleteValue( hKey, PROCCON_DATA_MEMBEROF );
  581. if ( m_lastRegError != ERROR_SUCCESS && m_lastRegError != ERROR_FILE_NOT_FOUND )
  582. err = RegError( TEXT("RegDeleteValue"), PROCCON_DATA_MEMBEROF );
  583. }
  584. // Set management data under profile name (or default)...
  585. if ( !err ) err = StoreMgmtRules( hKey, rule.base.mgmtParms );
  586. // Set variable data...
  587. if ( !err && rule.vLength) err = StoreVariableData( hKey, rule.vLength, rule.vData );
  588. return err;
  589. }
  590. //--------------------------------------------------------------------------------------------//
  591. // Function to store ProcCon job detail definition in the database //
  592. // Input: ref to data to store. //
  593. // Returns: ERROR_SUCCESS if successful, NT or PC error code if not //
  594. // Note: If an error is returned, an error event has been logged. //
  595. // Note: The appropriate critical section mast be held by the CALLER. //
  596. // Note: key is created with DB security attributes (established in constructor). //
  597. //--------------------------------------------------------------------------------------------//
  598. PCULONG32 CProcConDB::StoreJobDetail( const PCJobDetail &rule )
  599. {
  600. // Open or create and open the job subkey...
  601. HKEY hKeyTemp;
  602. PCULONG32 regDisp;
  603. m_lastRegError = RegCreateKeyEx( m_jobRegKey, rule.base.jobName, 0, TEXT(""), 0,
  604. KEY_READ + KEY_WRITE, &m_secAttr, &hKeyTemp, &regDisp );
  605. if ( m_lastRegError != ERROR_SUCCESS ) // Should never happen
  606. return RegError( TEXT("RegCreateKeyEx"), rule.base.jobName );
  607. PCULONG32 err = StoreJobValues( hKeyTemp, rule );
  608. RegCloseKey( hKeyTemp );
  609. return err;
  610. }
  611. //--------------------------------------------------------------------------------------------//
  612. // Function to store values for a job management rule in the database //
  613. // Input: registry key to use, //
  614. // management rule structure to store //
  615. // Returns: ERROR_SUCCESS if successful, NT or PC error code if not //
  616. // Note: Data errors lead to default behavior, not failure. //
  617. //--------------------------------------------------------------------------------------------//
  618. PCULONG32 CProcConDB::StoreJobValues( const HKEY &hKey, const PCJobDetail &rule ) {
  619. PCULONG32 err = 0;
  620. // Set management data under profile name (or default)...
  621. err = StoreMgmtRules( hKey, rule.base.mgmtParms );
  622. // Set variable data...
  623. if ( !err && rule.vLength) err = StoreVariableData( hKey, rule.vLength, rule.vData );
  624. return err;
  625. }
  626. //--------------------------------------------------------------------------------------------//
  627. // Function to store management rules for a job or process in the database //
  628. // Input: registry key to use, profile name to use, //
  629. // management rule structure to store. //
  630. // Returns: NT error code //
  631. //--------------------------------------------------------------------------------------------//
  632. PCULONG32 CProcConDB::StoreMgmtRules( const HKEY &hKey, const MGMT_PARMS &parms ) {
  633. PCULONG32 err = ERROR_SUCCESS;
  634. const TCHAR * const name = *parms.profileName? parms.profileName : PROCCON_DATA_DEFAULTRULES;
  635. TCHAR buf[512];
  636. // Set 'normal' setting for data to keep unacceptable data out of the DB.
  637. PRIORITY priority = parms.priority;
  638. SCHEDULING_CLASS schedCls = parms.schedClass;
  639. if ( !priority ) priority = PCPrioNormal;
  640. if ( schedCls > 9 ) schedCls = 5;
  641. // Determine if caller is authorized to set various parameters...
  642. if ( PCMapPriorityToNT( parms.priority ) == REALTIME_PRIORITY_CLASS &&
  643. TestAccess( PROCCON_REG_REALTIME_ACCTEST ) != ERROR_SUCCESS )
  644. return GetLastError();
  645. // Build parameter string to store in database...
  646. PCULONG32 len = _stprintf( buf, TEXT("%c")
  647. TEXT("%c0x%x%c") // flgs
  648. TEXT("%c0x%I64x%c") // aff
  649. TEXT("%c0x%x%c") // prio
  650. TEXT("%c0x%I64x%c") // min WS
  651. TEXT("%c0x%I64x%c") // max WS
  652. TEXT("%c0x%x%c") // sched cls
  653. TEXT("%c0x%I64x%c") // proc time
  654. TEXT("%c0x%I64x%c") // job time
  655. TEXT("%c0x%x%c") // proc ct
  656. TEXT("%c0x%I64x%c") // proc mem
  657. TEXT("%c0x%I64x%c"), // job mem
  658. BEG_BRACKET,
  659. PCDB_PREFIX_FLAGS, parms.mFlags & PCMFLAG_SAVEABLE_BITS, FIELD_SEP,
  660. PCDB_PREFIX_AFFINITY, parms.affinity, FIELD_SEP,
  661. PCDB_PREFIX_PRIORITY, priority, FIELD_SEP,
  662. PCDB_PREFIX_MINWS, parms.minWS, FIELD_SEP,
  663. PCDB_PREFIX_MAXWS, parms.maxWS, FIELD_SEP,
  664. PCDB_PREFIX_SCHEDCLASS, schedCls, FIELD_SEP,
  665. PCDB_PREFIX_PROCTIME, parms.procTimeLimitCNS, FIELD_SEP,
  666. PCDB_PREFIX_JOBTIME, parms.jobTimeLimitCNS, FIELD_SEP,
  667. PCDB_PREFIX_ACTIVEPROCS, parms.procCountLimit, FIELD_SEP,
  668. PCDB_PREFIX_PROCMEMORY, parms.procMemoryLimit, FIELD_SEP,
  669. PCDB_PREFIX_JOBMEMORY, parms.jobMemoryLimit,
  670. END_BRACKET );
  671. // Store the string...
  672. m_lastRegError = RegSetValueEx( hKey, name, NULL, REG_SZ, (UCHAR *) buf, (len + 1) *sizeof(TCHAR) );
  673. if ( m_lastRegError != ERROR_SUCCESS ) // Should never happen
  674. err = RegError( TEXT("RegSetValueEx"), name );
  675. // Store the description, or, if none, delete any existing description...
  676. if ( *parms.description ) {
  677. m_lastRegError = RegSetValueEx( hKey, PROCCON_DATA_DESCRIPTION, NULL, REG_SZ,
  678. (UCHAR *) parms.description,
  679. (_tcslen(parms.description) + 1) * sizeof(parms.description[0]) );
  680. if ( m_lastRegError != ERROR_SUCCESS ) // Should never happen
  681. err = RegError( TEXT("RegSetValueEx"), PROCCON_DATA_DESCRIPTION );
  682. }
  683. else
  684. m_lastRegError = RegDeleteValue( hKey, PROCCON_DATA_DESCRIPTION );
  685. return err;
  686. }
  687. //--------------------------------------------------------------------------------------------//
  688. // Function to load variable detail data for a job or process in the database //
  689. // Input: registry key to use, data length, data pointer //
  690. // Returns: NT error code //
  691. //--------------------------------------------------------------------------------------------//
  692. PCULONG32 CProcConDB::LoadVariableData( const HKEY &hKey, PCINT16 *length, TCHAR *data ) {
  693. PCULONG32 err = ERROR_SUCCESS, regType, regLen = *length;
  694. *length = 0;
  695. m_lastRegError = RegQueryValueEx( hKey, PROCCON_DATA_VARDATA, NULL,
  696. &regType, (UCHAR *) data, &regLen );
  697. if ( m_lastRegError == ERROR_MORE_DATA ) return m_lastRegError;
  698. if ( m_lastRegError == ERROR_SUCCESS )
  699. *length = (PCINT16) regLen;
  700. else if ( m_lastRegError != ERROR_FILE_NOT_FOUND )
  701. err = RegError( TEXT("RegQueryValueEx"), PROCCON_DATA_VARDATA );
  702. return err;
  703. }
  704. //--------------------------------------------------------------------------------------------//
  705. // Function to store variable detail data for a job or process in the database //
  706. // Input: registry key to use, data length, data pointer //
  707. // Returns: NT error code //
  708. //--------------------------------------------------------------------------------------------//
  709. PCULONG32 CProcConDB::StoreVariableData( const HKEY &hKey, const PCINT16 vLength, const TCHAR *vData ) {
  710. PCULONG32 err = ERROR_SUCCESS;
  711. m_lastRegError = RegSetValueEx( hKey, PROCCON_DATA_VARDATA, NULL, REG_BINARY, (UCHAR *) vData, vLength );
  712. if ( m_lastRegError != ERROR_SUCCESS )
  713. err = RegError( TEXT("RegSetValueEx"), PROCCON_DATA_VARDATA );
  714. return err;
  715. }
  716. //--------------------------------------------------------------------------------------------//
  717. // Function to perform updates after name rules are updated //
  718. // Input: none -- m_fmtNameRules and m_numNameRules are the data source //
  719. // Returns: ERROR_SUCCESS if successful, NT error code if not //
  720. // Note: The appropriate critical section mast be held by the CALLER. //
  721. // If successful, a database event is pulsed to wake those that care. //
  722. //--------------------------------------------------------------------------------------------//
  723. PCULONG32 CProcConDB::NameRulesUpdated( void )
  724. {
  725. ++m_updCtrName;
  726. PCULONG32 err = StoreNameRules();
  727. if ( err == ERROR_SUCCESS )
  728. PulseEvent( m_dbEvent ); // Tell others data may have changed
  729. return err;
  730. }
  731. //--------------------------------------------------------------------------------------------//
  732. // Functions to open (or create) the registry key names for various keys //
  733. // Input: none -- updates member data //
  734. // Returns: TRUE on success, else FALSE //
  735. //--------------------------------------------------------------------------------------------//
  736. BOOL CProcConDB::OpenParmKey( void ) {
  737. TCHAR key[MAX_PATH];
  738. PCBuildParmKey( key );
  739. m_lastRegError = CreateKeyAtHKLM( key, &m_parmRegKey );
  740. if ( m_lastRegError != ERROR_SUCCESS ) { // Indicates not properly installed
  741. PCLogMessage( PC_DB_OPEN_FAILED, EVENTLOG_ERROR_TYPE,
  742. 1, TEXT("CreateParmKey") ,
  743. sizeof(m_lastRegError), &m_lastRegError );
  744. return FALSE;
  745. }
  746. return TRUE;
  747. }
  748. BOOL CProcConDB::OpenProcKey( void ) {
  749. TCHAR key[MAX_PATH];
  750. BuildProcKey( key );
  751. m_lastRegError = CreateKeyAtHKLM( key, &m_procRegKey );
  752. if ( m_lastRegError != ERROR_SUCCESS ) { // Indicates not properly installed
  753. PCLogMessage( PC_DB_OPEN_FAILED, EVENTLOG_ERROR_TYPE,
  754. 1, TEXT("CreateProcKey") ,
  755. sizeof(m_lastRegError), &m_lastRegError );
  756. return FALSE;
  757. }
  758. return TRUE;
  759. }
  760. BOOL CProcConDB::OpenJobKey( void ) {
  761. TCHAR key[MAX_PATH];
  762. BuildJobKey( key );
  763. m_lastRegError = CreateKeyAtHKLM( key, &m_jobRegKey );
  764. if ( m_lastRegError != ERROR_SUCCESS ) { // Indicates not properly installed
  765. PCLogMessage( PC_DB_OPEN_FAILED, EVENTLOG_ERROR_TYPE,
  766. 1, TEXT("CreateGroupKey") ,
  767. sizeof(m_lastRegError), &m_lastRegError );
  768. return FALSE;
  769. }
  770. return TRUE;
  771. }
  772. //--------------------------------------------------------------------------------------------//
  773. // Functions to build the registry key names for various keys //
  774. // Input: location to build key and, for the name keys, the name //
  775. // Returns: nothing (cannot fail) //
  776. //--------------------------------------------------------------------------------------------//
  777. TCHAR *CProcConDB::BuildProcKey( TCHAR *key ) {
  778. PCBuildParmKey( key );
  779. _tcscat( key, TEXT("\\") );
  780. _tcscat( key, PROCCON_REG_PROCRULES_SUBKEY );
  781. return key;
  782. }
  783. TCHAR *CProcConDB::BuildJobKey( TCHAR *key ) {
  784. PCBuildParmKey( key );
  785. _tcscat( key, TEXT("\\") );
  786. _tcscat( key, PROCCON_REG_JOBRULES_SUBKEY );
  787. return key;
  788. }
  789. //--------------------------------------------------------------------------------------------//
  790. // Function to report a registry function error //
  791. // Input: name of operation that failed, optional additional string //
  792. // Returns: original error //
  793. //--------------------------------------------------------------------------------------------//
  794. PCULONG32 CProcConDB::RegError( const TCHAR *op, const TCHAR *what1, const TCHAR *what2 ) {
  795. TCHAR str[MAX_PATH];
  796. _tcscpy( str, what1? what1 : TEXT("") );
  797. if ( what2 ) _tcscat( str, what2 );
  798. const TCHAR *strings[] = { op, str };
  799. PCLogMessage( PC_UNEXPECTED_REGISTRY_ERROR, EVENTLOG_ERROR_TYPE,
  800. 2, strings, sizeof(m_lastRegError), &m_lastRegError );
  801. return m_lastRegError;
  802. }
  803. //--------------------------------------------------------------------------------------------//
  804. // Function to report a registry data error //
  805. // Input: name associated with data //
  806. // Returns: NT error ERROR_INVALID_DATA //
  807. //--------------------------------------------------------------------------------------------//
  808. PCULONG32 CProcConDB::RegDataError( const TCHAR *what ) {
  809. PCULONG32 dummy = ERROR_INVALID_DATA;
  810. PCLogMessage( PC_INVALID_DATA_ERROR, EVENTLOG_ERROR_TYPE,
  811. 1, what, sizeof(dummy), &dummy );
  812. return dummy;
  813. }
  814. //--------------------------------------------------------------------------------------------//
  815. // Function to set a new poll delay //
  816. // Input: proposed new delay //
  817. // Returns: NT or PC error code //
  818. // Note: lower and upper limits on poll delay are a bit arbitrary (2 secs to 15 mins OK) //
  819. //--------------------------------------------------------------------------------------------//
  820. PCULONG32 CProcConDB::SetPollDelaySeconds( PCULONG32 newDelay )
  821. {
  822. if ( TestAccess( PROCCON_REG_POLLRATE_ACCTEST ) != ERROR_SUCCESS )
  823. return GetLastError();
  824. if ( newDelay >= PC_MIN_POLL_DELAY && newDelay <= PC_MAX_POLL_DELAY ) {
  825. m_pollDelay = newDelay * 1000; // convert to milliseconds
  826. return SetPCParm( PROCCON_DATA_POLLDELAY, newDelay );
  827. }
  828. else
  829. return PCERROR_INVALID_PARAMETER;
  830. }
  831. //--------------------------------------------------------------------------------------------//
  832. // Functions to get or set DWORD values in the registry (parms, etc.) //
  833. // Input: name of parameter, pointer to data location //
  834. // Returns: registry function error or success //
  835. // Note: If a parameter cannot be retrieved or is not a REG_DWORD, it is replaced with //
  836. // the supplied value as a default. //
  837. //--------------------------------------------------------------------------------------------//
  838. PCULONG32 CProcConDB::GetPCParm( const TCHAR *name, PCULONG32 *data )
  839. {
  840. PCULONG32 byteType, lastLen = sizeof(PCULONG32 );
  841. UCHAR *addr = (UCHAR *) data;
  842. PCULONG32 rc = RegQueryValueEx( m_parmRegKey, name, NULL, &byteType, addr, &lastLen );
  843. if ( rc != ERROR_SUCCESS || byteType != REG_DWORD)
  844. rc = RegSetValueEx( m_parmRegKey, name, NULL, REG_DWORD, addr, sizeof(PCULONG32) );
  845. return rc;
  846. }
  847. PCULONG32 CProcConDB::SetPCParm( const TCHAR *name, PCULONG32 data )
  848. {
  849. return RegSetValueEx( m_parmRegKey, name, NULL, REG_DWORD, (UCHAR *) &data, sizeof(PCULONG32) );
  850. }
  851. PCULONG32 CProcConDB::DeleteAllNameRules( void ) {
  852. if ( TestAccess( PROCCON_REG_RESTORE_ACCTEST ) != ERROR_SUCCESS ) // delete all preceeds restore
  853. return GetLastError();
  854. PCULONG32 rc;
  855. EnterCriticalSection( &m_dbCSNameRule );
  856. m_lastRegError = RegDeleteValue( m_parmRegKey, PROCCON_DATA_NAMERULES );
  857. if ( m_lastRegError != ERROR_SUCCESS && m_lastRegError != ERROR_FILE_NOT_FOUND )
  858. rc = RegError( TEXT("RegDeleteValue"), PROCCON_DATA_NAMERULES );
  859. else {
  860. PCLogMessage( PC_SERVICE_DEL_ALL_NAME_RULES, EVENTLOG_INFORMATION_TYPE, 0, NULL );
  861. rc = LoadRules( LOADFLAG_NAME_RULES );
  862. }
  863. LeaveCriticalSection( &m_dbCSNameRule );
  864. return rc;
  865. }
  866. PCULONG32 CProcConDB::DeleteAllProcDefs( void ) {
  867. if ( TestAccess( PROCCON_REG_RESTORE_ACCTEST ) != ERROR_SUCCESS ) // delete all preceeds restore
  868. return GetLastError();
  869. PCULONG32 rc = ERROR_SUCCESS;
  870. EnterCriticalSection( &m_dbCSProcRule );
  871. if ( m_procRegKey ) RegCloseKey( m_procRegKey );
  872. m_procRegKey = NULL;
  873. m_lastRegError = PCDeleteKeyTree( m_parmRegKey, PROCCON_REG_PROCRULES_SUBKEY );
  874. if ( m_lastRegError != ERROR_SUCCESS && m_lastRegError != ERROR_FILE_NOT_FOUND )
  875. rc = RegError( TEXT("RegDeleteValue"), PROCCON_REG_PROCRULES_SUBKEY );
  876. else {
  877. PCLogMessage( PC_SERVICE_DEL_ALL_PROC_RULES, EVENTLOG_INFORMATION_TYPE, 0, NULL );
  878. if ( !OpenProcKey() )
  879. rc = m_lastRegError; // should not fail since worked at startup
  880. else
  881. rc = LoadRules( LOADFLAG_PROC_RULES );
  882. }
  883. LeaveCriticalSection( &m_dbCSProcRule );
  884. return rc;
  885. }
  886. PCULONG32 CProcConDB::DeleteAllJobDefs( void ) {
  887. if ( TestAccess( PROCCON_REG_RESTORE_ACCTEST ) != ERROR_SUCCESS ) // delete all preceeds restore
  888. return GetLastError();
  889. PCULONG32 rc = ERROR_SUCCESS;
  890. EnterCriticalSection( &m_dbCSJobRule );
  891. if ( m_jobRegKey ) RegCloseKey( m_jobRegKey );
  892. m_jobRegKey = NULL;
  893. m_lastRegError = PCDeleteKeyTree( m_parmRegKey, PROCCON_REG_JOBRULES_SUBKEY );
  894. if ( m_lastRegError != ERROR_SUCCESS && m_lastRegError != ERROR_FILE_NOT_FOUND )
  895. rc = RegError( TEXT("RegDeleteValue"), PROCCON_REG_JOBRULES_SUBKEY );
  896. else {
  897. PCLogMessage( PC_SERVICE_DEL_ALL_JOB_RULES, EVENTLOG_INFORMATION_TYPE, 0, NULL );
  898. if ( !OpenJobKey() )
  899. rc = m_lastRegError; // should not fail since worked at startup
  900. else
  901. rc = LoadRules( LOADFLAG_JOB_RULES );
  902. }
  903. LeaveCriticalSection( &m_dbCSJobRule );
  904. return rc;
  905. }
  906. //--------------------------------------------------------------------------------------------//
  907. // Functions to get job management data in internal (non-API) format //
  908. // Input: location to store list pointer, name to locate or NULL //
  909. // Returns: count of entries //
  910. // Note: if name supplied, only thet entry is located and listed, else all are listed //
  911. //--------------------------------------------------------------------------------------------//
  912. PCULONG32 CProcConDB::GetJobMgmtDefs( PCJobDef **pList, JOB_NAME *name )
  913. {
  914. EnterCriticalSection( &m_dbCSJobRule );
  915. PCULONG32 numRules = name? 1 : m_numJobRules; // copy count for use outside CS
  916. if ( !numRules ) { // 7/28/2000 bugfix to prevent leak when no rules
  917. *pList = NULL;
  918. LeaveCriticalSection( &m_dbCSJobRule );
  919. return 0;
  920. }
  921. *pList = new PCJobDef[numRules];
  922. if ( !*pList ) {
  923. PCLogNoMemory( TEXT("AllocInternalJobDefs"), numRules * sizeof(PCJobDef) );
  924. LeaveCriticalSection( &m_dbCSJobRule );
  925. return 0;
  926. }
  927. memset( *pList, 0, numRules * sizeof(PCJobDef) );
  928. // copy summary data to buffer until end of data...
  929. PCJobDef *list = *pList;
  930. // If looking for a specific entry, locate it and build one entry...
  931. if ( name ) {
  932. for ( PCULONG32 i = 0; i < m_numJobRules; ++i ) {
  933. if ( !CompareJobName( m_jobSummary[i].jobName, name ) ) {
  934. SetJobDefEntry( list, m_jobSummary[i] );
  935. break;
  936. }
  937. }
  938. // If entry not found -- delete list, set 0 count...
  939. if ( i >= m_numJobRules ) {
  940. delete [] *pList;
  941. *pList = NULL;
  942. numRules = 0;
  943. }
  944. }
  945. else for ( PCULONG32 i = 0; i < numRules; ++i, ++list ) {
  946. SetJobDefEntry( list, m_jobSummary[i] );
  947. }
  948. LeaveCriticalSection( &m_dbCSJobRule );
  949. if ( numRules > 1 ) qsort( *pList, numRules, sizeof(PCJobDef), CompareJobDef );
  950. return numRules;
  951. }
  952. void CProcConDB::SetJobDefEntry( PCJobDef *list, PCJobSummary &m_jobSummary ) {
  953. memcpy( list->jobName, m_jobSummary.jobName, sizeof(list->jobName) );
  954. memcpy( list->profileName, m_jobSummary.mgmtParms.profileName, sizeof(list->profileName) );
  955. list->mFlags = m_jobSummary.mgmtParms.mFlags;
  956. list->affinity = m_jobSummary.mgmtParms.affinity;
  957. list->priority = m_jobSummary.mgmtParms.priority;
  958. list->minWS = m_jobSummary.mgmtParms.minWS;
  959. list->maxWS = m_jobSummary.mgmtParms.maxWS;
  960. list->schedClass = m_jobSummary.mgmtParms.schedClass;
  961. list->procCountLimit = m_jobSummary.mgmtParms.procCountLimit;
  962. list->procTimeLimitCNS = m_jobSummary.mgmtParms.procTimeLimitCNS;
  963. list->jobTimeLimitCNS = m_jobSummary.mgmtParms.jobTimeLimitCNS;
  964. list->procMemoryLimit = m_jobSummary.mgmtParms.procMemoryLimit;
  965. list->jobMemoryLimit = m_jobSummary.mgmtParms.jobMemoryLimit;
  966. }
  967. //--------------------------------------------------------------------------------------------//
  968. // Functions to get process management data in internal (non-API) format //
  969. // Input: location to store list pointer //
  970. // Returns: count of entries //
  971. //--------------------------------------------------------------------------------------------//
  972. PCULONG32 CProcConDB::GetProcMgmtDefs( PCProcDef **pList )
  973. {
  974. EnterCriticalSection( &m_dbCSProcRule );
  975. PCULONG32 numRules = m_numProcRules; // copy count for use outside CS
  976. if ( !numRules ) { // 7/28/2000 bugfix to prevent leak when no rules
  977. *pList = NULL;
  978. LeaveCriticalSection( &m_dbCSProcRule );
  979. return 0;
  980. }
  981. *pList = new PCProcDef[numRules];
  982. if ( !*pList ) {
  983. PCLogNoMemory( TEXT("AllocInternalProcDefs"), numRules * sizeof(PCProcDef) );
  984. LeaveCriticalSection( &m_dbCSProcRule );
  985. return 0;
  986. }
  987. // copy summary data to buffer until end of data...
  988. PCProcDef *list = *pList;
  989. for ( PCULONG32 i = 0; i < numRules; ++i, ++list ) {
  990. memcpy( list->procName, m_procSummary[i].procName, sizeof(list->procName) );
  991. memcpy( list->memberOfJob, m_procSummary[i].memberOfJobName, sizeof(list->memberOfJob) );
  992. memcpy( list->profileName, m_procSummary[i].mgmtParms.profileName, sizeof(list->profileName) );
  993. list->mFlags = m_procSummary[i].mgmtParms.mFlags;
  994. list->affinity = m_procSummary[i].mgmtParms.affinity;
  995. list->priority = m_procSummary[i].mgmtParms.priority;
  996. list->minWS = m_procSummary[i].mgmtParms.minWS;
  997. list->maxWS = m_procSummary[i].mgmtParms.maxWS;
  998. }
  999. LeaveCriticalSection( &m_dbCSProcRule );
  1000. if ( numRules > 1 ) qsort( *pList, numRules, sizeof(PCProcDef), CompareProcDef );
  1001. return numRules;
  1002. }
  1003. //--------------------------------------------------------------------------------------------//
  1004. // Functions to get proc summary list data in API format //
  1005. // Input: start point and target loc, max count, item len return, item count return //
  1006. // Returns: TRUE if more data exists, else FALSE (there are no error conditions) //
  1007. //--------------------------------------------------------------------------------------------//
  1008. BOOL CProcConDB::GetProcSummary( const PCProcSummary *pStart,
  1009. PCUINT32 listFlags,
  1010. PCProcSummary *pSummary,
  1011. const PCINT32 maxCount,
  1012. PCINT16 *itemLen,
  1013. PCINT16 *itemCount )
  1014. {
  1015. EnterCriticalSection( &m_dbCSProcRule );
  1016. *itemLen = sizeof(PCProcSummary);
  1017. PCULONG32 numRules = m_numProcRules; // copy count for use outside CS
  1018. if ( listFlags & PC_LIST_MATCH_ONLY ) // if match only, set starting point to same
  1019. listFlags |= PC_LIST_STARTING_WITH;
  1020. // locate copy start point...
  1021. for ( PCULONG32 i = 0; i < numRules; ++i ) {
  1022. int cmp = CompareProcSummary( pStart, &m_procSummary[i] );
  1023. if ( (listFlags & PC_LIST_STARTING_WITH) && cmp <= 0 ) break;
  1024. else if ( cmp < 0 ) break;
  1025. }
  1026. // copy data to buffer until end of data or max requested hit...
  1027. for ( *itemCount = 0; i < numRules && *itemCount < maxCount; ++i, ++*itemCount ) {
  1028. if ( (listFlags & PC_LIST_MATCH_ONLY) && CompareProcSummary( pStart, &m_procSummary[i] ) )
  1029. break;
  1030. memcpy( pSummary++, &m_procSummary[i], *itemLen );
  1031. }
  1032. LeaveCriticalSection( &m_dbCSProcRule );
  1033. return (listFlags & PC_LIST_MATCH_ONLY)? FALSE : i < numRules;
  1034. }
  1035. //--------------------------------------------------------------------------------------------//
  1036. // Functions to get job summary list data in API format //
  1037. // Input: start point and target loc, max count, item len return, item count return //
  1038. // Returns: TRUE if more data exists, else FALSE (there are no error conditions) //
  1039. //--------------------------------------------------------------------------------------------//
  1040. BOOL CProcConDB::GetJobSummary( const PCJobSummary *pStart,
  1041. PCUINT32 listFlags,
  1042. PCJobSummary *pSummary,
  1043. const PCINT32 maxCount,
  1044. PCINT16 *itemLen,
  1045. PCINT16 *itemCount )
  1046. {
  1047. EnterCriticalSection( &m_dbCSJobRule );
  1048. *itemLen = sizeof(PCJobSummary);
  1049. PCULONG32 numRules = m_numJobRules; // copy count for use outside CS
  1050. if ( listFlags & PC_LIST_MATCH_ONLY ) // if match only, set starting point to same
  1051. listFlags |= PC_LIST_STARTING_WITH;
  1052. // locate copy start point (first entry greater than supplied)...
  1053. for ( PCULONG32 i = 0; i < numRules; ++i ) {
  1054. int cmp = CompareJobSummary( pStart, &m_jobSummary[i] );
  1055. if ( (listFlags & PC_LIST_STARTING_WITH) && cmp <= 0 ) break;
  1056. else if ( cmp < 0 ) break;
  1057. }
  1058. // copy data to buffer until end of data or max requested hit...
  1059. for ( *itemCount = 0; i < numRules && *itemCount < maxCount; ++i, ++*itemCount ) {
  1060. if ( (listFlags & PC_LIST_MATCH_ONLY) && CompareJobSummary( pStart, &m_jobSummary[i] ) )
  1061. break;
  1062. memcpy( pSummary++, &m_jobSummary[i], *itemLen );
  1063. }
  1064. LeaveCriticalSection( &m_dbCSJobRule );
  1065. return (listFlags & PC_LIST_MATCH_ONLY)? FALSE : i < numRules;
  1066. }
  1067. //--------------------------------------------------------------------------------------------//
  1068. // Functions to get process detail data in API format //
  1069. // Input: request input and output detail buffers, data version code, update counter to set//
  1070. // Returns: PC or NT error code or PCERROR_SUCCESS //
  1071. //--------------------------------------------------------------------------------------------//
  1072. PCULONG32 CProcConDB::GetProcDetail( const PCProcDetail *pIn,
  1073. PCProcDetail *pDetail,
  1074. const BYTE version,
  1075. PCINT32 *updateCtr )
  1076. {
  1077. PCULONG32 err = ERROR_SUCCESS;
  1078. EnterCriticalSection( &m_dbCSProcRule );
  1079. if ( updateCtr ) *updateCtr = m_updCtrProc;
  1080. // Open the process subkey...
  1081. HKEY hKeyTemp;
  1082. m_lastRegError = RegOpenKeyEx( m_procRegKey, pIn->base.procName, 0,
  1083. KEY_READ + KEY_WRITE, &hKeyTemp );
  1084. if ( m_lastRegError != ERROR_SUCCESS )
  1085. if ( m_lastRegError != ERROR_FILE_NOT_FOUND )
  1086. err = RegError( TEXT("RegOpenKeyEx"), pIn->base.procName );
  1087. else err = PCERROR_DOES_NOT_EXIST;
  1088. if ( err == ERROR_SUCCESS ) {
  1089. memcpy( pDetail, pIn, sizeof(*pDetail) ); // prime name fields with supplied names
  1090. err = LoadProcSummaryItem( hKeyTemp, pDetail->base );
  1091. if ( err == ERROR_SUCCESS )
  1092. err = LoadVariableData( hKeyTemp, &pDetail->vLength, pDetail->vData );
  1093. RegCloseKey( hKeyTemp );
  1094. }
  1095. LeaveCriticalSection( &m_dbCSProcRule );
  1096. return err;
  1097. }
  1098. //--------------------------------------------------------------------------------------------//
  1099. // Functions to add process detail data from API format //
  1100. // Input: detail buffer, data version code //
  1101. // Returns: PC or NT error code or PCERROR_SUCCESS //
  1102. //--------------------------------------------------------------------------------------------//
  1103. PCULONG32 CProcConDB::AddProcDetail( const PCProcDetail *pDetail,
  1104. const BYTE version )
  1105. {
  1106. EnterCriticalSection( &m_dbCSProcRule );
  1107. // Open the process subkey...
  1108. HKEY hKeyTemp;
  1109. PCULONG32 err = RegOpenKeyEx( m_procRegKey, pDetail->base.procName, 0, KEY_READ + KEY_WRITE, &hKeyTemp );
  1110. if ( err != ERROR_FILE_NOT_FOUND ) {
  1111. if ( err == ERROR_SUCCESS ) {
  1112. err = PCERROR_EXISTS;
  1113. RegCloseKey( hKeyTemp );
  1114. }
  1115. else {
  1116. m_lastRegError = err;
  1117. RegError( TEXT("RegOpenKeyEx"), pDetail->base.procName );
  1118. }
  1119. } else
  1120. err = StoreProcDetail( *pDetail );
  1121. if ( !err )
  1122. err = LoadRules( LOADFLAG_PROC_RULES );
  1123. LeaveCriticalSection( &m_dbCSProcRule );
  1124. if ( err == PCERROR_SUCCESS && m_LogRuleEdits )
  1125. LogProcSummaryChange(&pDetail->base, version, NULL);
  1126. return err;
  1127. }
  1128. //--------------------------------------------------------------------------------------------//
  1129. // Functions to replace process detail data in API format //
  1130. // Input: detail buffer, data version code, update counter to verify //
  1131. // Returns: PC or NT error code or PCERROR_SUCCESS //
  1132. //--------------------------------------------------------------------------------------------//
  1133. PCULONG32 CProcConDB::ReplProcDetail( const PCProcDetail *pDetail,
  1134. const BYTE version,
  1135. const PCINT32 updateCtr )
  1136. {
  1137. PCULONG32 err = ERROR_SUCCESS;
  1138. PCProcSummary oldProcSummary;
  1139. PCINT16 itemsReturned = 0;
  1140. PCINT16 itemLen = sizeof(oldProcSummary);
  1141. EnterCriticalSection( &m_dbCSProcRule );
  1142. if ( updateCtr != m_updCtrProc ) err = PCERROR_UPDATE_OCCURRED;
  1143. else {
  1144. // Open the process subkey...
  1145. HKEY hKeyTemp;
  1146. err = RegOpenKeyEx( m_procRegKey, pDetail->base.procName, 0, KEY_READ + KEY_WRITE, &hKeyTemp );
  1147. if ( err == ERROR_SUCCESS ) {
  1148. GetProcSummary(&pDetail->base, PC_LIST_MATCH_ONLY, &oldProcSummary, 1, &itemLen, &itemsReturned );
  1149. err = StoreProcValues( hKeyTemp, *pDetail );
  1150. RegCloseKey( hKeyTemp );
  1151. if ( !err )
  1152. err = LoadRules( LOADFLAG_PROC_RULES );
  1153. } else {
  1154. if ( err != ERROR_FILE_NOT_FOUND ) {
  1155. m_lastRegError = err;
  1156. RegError( TEXT("RegOpenKeyEx"), pDetail->base.procName );
  1157. }
  1158. else err = PCERROR_DOES_NOT_EXIST;
  1159. }
  1160. }
  1161. LeaveCriticalSection( &m_dbCSProcRule );
  1162. if ( err == PCERROR_SUCCESS && itemsReturned == 1 && m_LogRuleEdits )
  1163. LogProcSummaryChange(&pDetail->base, version, &oldProcSummary);
  1164. return err;
  1165. }
  1166. //--------------------------------------------------------------------------------------------//
  1167. // Functions to delete process detail data from API format //
  1168. // Input: summary portion of detail buffer, data version code //
  1169. // Returns: PC or NT error code or PCERROR_SUCCESS //
  1170. //--------------------------------------------------------------------------------------------//
  1171. PCULONG32 CProcConDB::DelProcDetail( const PCProcSummary *pSummary,
  1172. const BYTE version )
  1173. {
  1174. EnterCriticalSection( &m_dbCSProcRule );
  1175. PCULONG32 err;
  1176. // Delete just the profile data if profile name supplied...
  1177. if ( *pSummary->mgmtParms.profileName ) {
  1178. HKEY hKeyTemp;
  1179. err = RegOpenKeyEx( m_procRegKey, pSummary->procName, 0, KEY_READ + KEY_WRITE, &hKeyTemp );
  1180. if ( err == ERROR_SUCCESS ) {
  1181. err = RegDeleteValue( hKeyTemp, pSummary->mgmtParms.profileName );
  1182. RegCloseKey( hKeyTemp );
  1183. }
  1184. }
  1185. // Otherwise delete the entire process detail key...
  1186. else
  1187. err = RegDeleteKey( m_procRegKey, pSummary->procName );
  1188. // Handle result...
  1189. if ( err != ERROR_SUCCESS && err != ERROR_FILE_NOT_FOUND ) {
  1190. m_lastRegError = err;
  1191. RegError( TEXT("DelProcDetail"), pSummary->procName );
  1192. }
  1193. else if ( err == ERROR_SUCCESS )
  1194. err = LoadRules( LOADFLAG_PROC_RULES );
  1195. LeaveCriticalSection( &m_dbCSProcRule );
  1196. if ( err == ERROR_SUCCESS && m_LogRuleEdits )
  1197. PCLogMessage( PC_SERVICE_DEL_PROC_EXECUTION_RULE, EVENTLOG_INFORMATION_TYPE,
  1198. 1, pSummary->procName );
  1199. return err;
  1200. }
  1201. //--------------------------------------------------------------------------------------------//
  1202. // Function to Log a replace or add change to a process execution rule //
  1203. // Input: summary portion of detail buffer, data version code, orignal(old) summary //
  1204. // portion of detail buffer prior to the change //
  1205. // Returns: nothing //
  1206. //--------------------------------------------------------------------------------------------//
  1207. void CProcConDB::LogProcSummaryChange( const PCProcSummary *pNewSummary,
  1208. const BYTE version,
  1209. const PCProcSummary *pOldSummary )
  1210. {
  1211. // description
  1212. // member of job
  1213. // affinity
  1214. TCHAR toAffinity[32], fromAffinity[32] = { 0 };
  1215. PCFormatAffinityLimit(toAffinity, ENTRY_COUNT(toAffinity), pNewSummary->mgmtParms);
  1216. if ( pOldSummary )
  1217. PCFormatAffinityLimit(fromAffinity, ENTRY_COUNT(fromAffinity), pOldSummary->mgmtParms);
  1218. // priority
  1219. TCHAR toPriority[32], fromPriority[32] = { 0 };
  1220. PCFormatPriorityLimit(toPriority, ENTRY_COUNT(toPriority), pNewSummary->mgmtParms);
  1221. if ( pOldSummary )
  1222. PCFormatPriorityLimit(fromPriority, ENTRY_COUNT(fromPriority), pOldSummary->mgmtParms);
  1223. // working set
  1224. TCHAR toWS[64], fromWS[64];
  1225. PCFormatWorkingSetLimit(toWS, ENTRY_COUNT(toWS), pNewSummary->mgmtParms);
  1226. if ( pOldSummary )
  1227. PCFormatWorkingSetLimit(fromWS, ENTRY_COUNT(fromWS), pOldSummary->mgmtParms);
  1228. if ( !pOldSummary ) {
  1229. const TCHAR *msgs[] = { pNewSummary->procName,
  1230. pNewSummary->mgmtParms.description,
  1231. PCIsSetToStr(pNewSummary->mgmtParms.mFlags, PCMFLAG_APPLY_JOB_MEMBERSHIP), pNewSummary->memberOfJobName,
  1232. toAffinity, toPriority, toWS
  1233. };
  1234. PCLogMessage( PC_SERVICE_ADD_PROC_EXECUTION_RULE, EVENTLOG_INFORMATION_TYPE,
  1235. ENTRY_COUNT(msgs), msgs );
  1236. }
  1237. else {
  1238. const TCHAR *msgs[] = { pNewSummary->procName,
  1239. pNewSummary->mgmtParms.description, pOldSummary->mgmtParms.description,
  1240. PCIsSetToStr(pNewSummary->mgmtParms.mFlags, PCMFLAG_APPLY_JOB_MEMBERSHIP), pNewSummary->memberOfJobName,
  1241. PCIsSetToStr(pOldSummary->mgmtParms.mFlags, PCMFLAG_APPLY_JOB_MEMBERSHIP), pOldSummary->memberOfJobName,
  1242. toAffinity, fromAffinity,
  1243. toPriority, fromPriority,
  1244. toWS, fromWS
  1245. };
  1246. PCLogMessage( PC_SERVICE_REPL_PROC_EXECUTION_RULE, EVENTLOG_INFORMATION_TYPE,
  1247. ENTRY_COUNT(msgs), msgs );
  1248. }
  1249. }
  1250. //--------------------------------------------------------------------------------------------//
  1251. // Functions to get job detail data in API format //
  1252. // Input: detail buffer, data version code, update counter to set //
  1253. // Returns: PC or NT error code or PCERROR_SUCCESS //
  1254. //--------------------------------------------------------------------------------------------//
  1255. PCULONG32 CProcConDB::GetJobDetail( const PCJobDetail *pIn,
  1256. PCJobDetail *pDetail,
  1257. const BYTE version,
  1258. PCINT32 *updateCtr )
  1259. {
  1260. PCULONG32 err = ERROR_SUCCESS;
  1261. EnterCriticalSection( &m_dbCSJobRule );
  1262. if ( updateCtr ) *updateCtr = m_updCtrJob;
  1263. // Open the job subkey...
  1264. HKEY hKeyTemp;
  1265. m_lastRegError = RegOpenKeyEx( m_jobRegKey, pIn->base.jobName, 0,
  1266. KEY_READ + KEY_WRITE, &hKeyTemp );
  1267. if ( m_lastRegError != ERROR_SUCCESS )
  1268. if ( m_lastRegError != ERROR_FILE_NOT_FOUND )
  1269. err = RegError( TEXT("RegOpenKeyEx"), pIn->base.jobName );
  1270. else err = PCERROR_DOES_NOT_EXIST;
  1271. if ( err == ERROR_SUCCESS ) {
  1272. memcpy( pDetail, pIn, sizeof(*pDetail) ); // prime name fields with supplied names
  1273. err = LoadJobSummaryItem( hKeyTemp, pDetail->base );
  1274. if ( err == ERROR_SUCCESS )
  1275. err = LoadVariableData( hKeyTemp, &pDetail->vLength, pDetail->vData );
  1276. RegCloseKey( hKeyTemp );
  1277. }
  1278. LeaveCriticalSection( &m_dbCSJobRule );
  1279. return err;
  1280. }
  1281. //--------------------------------------------------------------------------------------------//
  1282. // Functions to add job detail data from API format //
  1283. // Input: detail buffer, data version code //
  1284. // Returns: PC or NT error code or PCERROR_SUCCESS //
  1285. //--------------------------------------------------------------------------------------------//
  1286. PCULONG32 CProcConDB::AddJobDetail( const PCJobDetail *pDetail,
  1287. const BYTE version )
  1288. {
  1289. EnterCriticalSection( &m_dbCSJobRule );
  1290. // Open the job subkey...
  1291. HKEY hKeyTemp;
  1292. PCULONG32 err = RegOpenKeyEx( m_jobRegKey, pDetail->base.jobName, 0, KEY_READ + KEY_WRITE, &hKeyTemp );
  1293. if ( err != ERROR_FILE_NOT_FOUND ) {
  1294. if ( err == ERROR_SUCCESS ) {
  1295. err = PCERROR_EXISTS;
  1296. RegCloseKey( hKeyTemp );
  1297. }
  1298. else {
  1299. m_lastRegError = err;
  1300. RegError( TEXT("RegOpenKeyEx"), pDetail->base.jobName );
  1301. }
  1302. } else
  1303. err = StoreJobDetail( *pDetail );
  1304. if ( !err )
  1305. err = LoadRules( LOADFLAG_JOB_RULES );
  1306. LeaveCriticalSection( &m_dbCSJobRule );
  1307. if ( err == ERROR_SUCCESS && m_LogRuleEdits )
  1308. LogJobSummaryChange(&pDetail->base, version, NULL);
  1309. return err;
  1310. }
  1311. //--------------------------------------------------------------------------------------------//
  1312. // Functions to replace job detail data in API format //
  1313. // Input: detail buffer, data version code //
  1314. // Returns: PC or NT error code or PCERROR_SUCCESS //
  1315. //--------------------------------------------------------------------------------------------//
  1316. PCULONG32 CProcConDB::ReplJobDetail( const PCJobDetail *pDetail,
  1317. const BYTE version,
  1318. const PCINT32 updateCtr )
  1319. {
  1320. PCULONG32 err = ERROR_SUCCESS;
  1321. PCJobSummary oldJobSummary;
  1322. PCINT16 itemsReturned = 0;
  1323. PCINT16 itemLen = sizeof(oldJobSummary);
  1324. EnterCriticalSection( &m_dbCSJobRule );
  1325. if ( updateCtr != m_updCtrJob ) err = PCERROR_UPDATE_OCCURRED;
  1326. else {
  1327. // Open the job subkey...
  1328. HKEY hKeyTemp;
  1329. err = RegOpenKeyEx( m_jobRegKey, pDetail->base.jobName, 0, KEY_READ + KEY_WRITE, &hKeyTemp );
  1330. if ( err == ERROR_SUCCESS ) {
  1331. GetJobSummary(&pDetail->base, PC_LIST_MATCH_ONLY, &oldJobSummary, 1, &itemLen, &itemsReturned );
  1332. err = StoreJobValues( hKeyTemp, *pDetail );
  1333. RegCloseKey( hKeyTemp );
  1334. if ( !err )
  1335. err = LoadRules( LOADFLAG_JOB_RULES );
  1336. } else {
  1337. if ( err != ERROR_FILE_NOT_FOUND ) {
  1338. m_lastRegError = err;
  1339. RegError( TEXT("RegOpenKeyEx"), pDetail->base.jobName );
  1340. }
  1341. else err = PCERROR_DOES_NOT_EXIST;
  1342. }
  1343. }
  1344. LeaveCriticalSection( &m_dbCSJobRule );
  1345. if ( err == ERROR_SUCCESS && itemsReturned == 1 && m_LogRuleEdits )
  1346. LogJobSummaryChange(&pDetail->base, version, &oldJobSummary);
  1347. return err;
  1348. }
  1349. //--------------------------------------------------------------------------------------------//
  1350. // Functions to delete job detail data from API format //
  1351. // Input: summary portion of detail buffer, data version code //
  1352. // Returns: PC or NT error code or PCERROR_SUCCESS //
  1353. //--------------------------------------------------------------------------------------------//
  1354. PCULONG32 CProcConDB::DelJobDetail( const PCJobSummary *pSummary,
  1355. const BYTE version )
  1356. {
  1357. EnterCriticalSection( &m_dbCSJobRule );
  1358. PCULONG32 err;
  1359. // Delete just the profile data if profile name supplied...
  1360. if ( *pSummary->mgmtParms.profileName ) {
  1361. HKEY hKeyTemp;
  1362. err = RegOpenKeyEx( m_jobRegKey, pSummary->jobName, 0, KEY_READ + KEY_WRITE, &hKeyTemp );
  1363. if ( err == ERROR_SUCCESS ) {
  1364. err = RegDeleteValue( hKeyTemp, pSummary->mgmtParms.profileName );
  1365. RegCloseKey( hKeyTemp );
  1366. }
  1367. }
  1368. // Otherwise delete the entire job detail key...
  1369. else
  1370. err = RegDeleteKey( m_jobRegKey, pSummary->jobName );
  1371. // Handle result...
  1372. if ( err != ERROR_SUCCESS && err != ERROR_FILE_NOT_FOUND ) {
  1373. m_lastRegError = err;
  1374. RegError( TEXT("DelJobDetail"), pSummary->jobName );
  1375. }
  1376. else if ( err == ERROR_SUCCESS )
  1377. err = LoadRules( LOADFLAG_JOB_RULES );
  1378. LeaveCriticalSection( &m_dbCSJobRule );
  1379. if ( err == ERROR_SUCCESS && m_LogRuleEdits )
  1380. PCLogMessage( PC_SERVICE_DEL_JOB_EXECUTION_RULE, EVENTLOG_INFORMATION_TYPE,
  1381. 1, pSummary->jobName );
  1382. return err;
  1383. }
  1384. //--------------------------------------------------------------------------------------------//
  1385. // Function to Log a replace or add change to a group execution rule //
  1386. // Input: summary portion of detail buffer, data version code, orignal(old) summary //
  1387. // portion of detail buffer prior to the change //
  1388. // Returns: nothing //
  1389. //--------------------------------------------------------------------------------------------//
  1390. void CProcConDB::LogJobSummaryChange( const PCJobSummary *pNewSummary,
  1391. const BYTE version,
  1392. const PCJobSummary *pOldSummary )
  1393. {
  1394. // description
  1395. // affinity
  1396. TCHAR toAffinity[32], fromAffinity[32] = { 0 };
  1397. PCFormatAffinityLimit(toAffinity, ENTRY_COUNT(toAffinity), pNewSummary->mgmtParms);
  1398. if ( pOldSummary )
  1399. PCFormatAffinityLimit(fromAffinity, ENTRY_COUNT(fromAffinity), pOldSummary->mgmtParms);
  1400. // priority
  1401. TCHAR toPriority[32], fromPriority[32] = { 0 };
  1402. PCFormatPriorityLimit(toPriority, ENTRY_COUNT(toPriority), pNewSummary->mgmtParms);
  1403. if ( pOldSummary )
  1404. PCFormatPriorityLimit(fromPriority, ENTRY_COUNT(fromPriority), pOldSummary->mgmtParms);
  1405. // working set
  1406. TCHAR toWS[64], fromWS[64] = { 0 };
  1407. PCFormatWorkingSetLimit(toWS, ENTRY_COUNT(toWS), pNewSummary->mgmtParms);
  1408. if ( pOldSummary )
  1409. PCFormatWorkingSetLimit(fromWS, ENTRY_COUNT(fromWS), pOldSummary->mgmtParms);
  1410. // scheduling class
  1411. TCHAR toSch[32], fromSch[32] = { 0 };
  1412. PCFormatSchedClassLimit(toSch, ENTRY_COUNT(toSch), pNewSummary->mgmtParms);
  1413. if ( pOldSummary )
  1414. PCFormatSchedClassLimit(fromSch, ENTRY_COUNT(fromSch), pOldSummary->mgmtParms);
  1415. // process count
  1416. TCHAR toProcCount[32], fromProcCount[32] = { 0 };
  1417. PCFormatProcessCountLimit(toProcCount, ENTRY_COUNT(toProcCount), pNewSummary->mgmtParms);
  1418. if ( pOldSummary )
  1419. PCFormatProcessCountLimit(fromProcCount, ENTRY_COUNT(fromProcCount), pOldSummary->mgmtParms);
  1420. // process committed memory
  1421. TCHAR toProcMemory[32], fromProcMemory[32] = { 0 };
  1422. PCFormatProcMemLimit(toProcMemory, ENTRY_COUNT(toProcMemory), pNewSummary->mgmtParms);
  1423. if ( pOldSummary )
  1424. PCFormatProcMemLimit(fromProcMemory, ENTRY_COUNT(fromProcMemory), pOldSummary->mgmtParms);
  1425. // job committed memory
  1426. TCHAR toJobMemory[32], fromJobMemory[32] = { 0 };
  1427. PCFormatJobMemLimit(toJobMemory, ENTRY_COUNT(toJobMemory), pNewSummary->mgmtParms);
  1428. if ( pOldSummary )
  1429. PCFormatJobMemLimit(fromJobMemory, ENTRY_COUNT(fromJobMemory), pOldSummary->mgmtParms);
  1430. // per process user time
  1431. TCHAR toProcTime[32], fromProcTime[32] = { 0 };
  1432. PCFormatProcTimeLimit(toProcTime, ENTRY_COUNT(toProcTime), pNewSummary->mgmtParms);
  1433. if ( pOldSummary )
  1434. PCFormatProcTimeLimit(fromProcTime, ENTRY_COUNT(fromProcTime), pOldSummary->mgmtParms);
  1435. // job user time
  1436. TCHAR toJobTime[32], fromJobTime[32] = { 0 };
  1437. PCFormatJobTimeLimit(toJobTime, ENTRY_COUNT(toJobTime), pNewSummary->mgmtParms);
  1438. if ( pOldSummary )
  1439. PCFormatJobTimeLimit(fromJobTime, ENTRY_COUNT(fromJobTime), pOldSummary->mgmtParms);
  1440. // job user time action
  1441. TCHAR toEndofJobTimeAction[128], fromEndofJobTimeAction[128] = { 0 };
  1442. PCFormatEndofJobAction(toEndofJobTimeAction, ENTRY_COUNT(toEndofJobTimeAction), pNewSummary->mgmtParms);
  1443. if ( pOldSummary )
  1444. PCFormatEndofJobAction(fromEndofJobTimeAction, ENTRY_COUNT(fromEndofJobTimeAction), pOldSummary->mgmtParms);
  1445. // end job when no process in job
  1446. TCHAR toEndJobEmpty[16], fromEndJobEmpty[16] = { 0 };
  1447. PCFormatOnOrOffLimit(toEndJobEmpty, ENTRY_COUNT(toEndJobEmpty), pNewSummary->mgmtParms, PCMFLAG_END_JOB_WHEN_EMPTY);
  1448. if ( pOldSummary )
  1449. PCFormatOnOrOffLimit(fromEndJobEmpty, ENTRY_COUNT(fromEndJobEmpty), pOldSummary->mgmtParms, PCMFLAG_END_JOB_WHEN_EMPTY);
  1450. // die on unhandled exception
  1451. TCHAR toDieUHExcept[16], fromDieUHExcept[16] = { 0 };
  1452. PCFormatOnOrOffLimit(toDieUHExcept, ENTRY_COUNT(toDieUHExcept), pNewSummary->mgmtParms, PCMFLAG_SET_DIE_ON_UH_EXCEPTION);
  1453. if ( pOldSummary )
  1454. PCFormatOnOrOffLimit(fromDieUHExcept, ENTRY_COUNT(fromDieUHExcept), pOldSummary->mgmtParms, PCMFLAG_SET_DIE_ON_UH_EXCEPTION);
  1455. // silent breakaway
  1456. TCHAR toSilentBrkAwayAct[16], fromSilentBrkAwayAct[16] = { 0 };
  1457. PCFormatOnOrOffLimit(toSilentBrkAwayAct, ENTRY_COUNT(toSilentBrkAwayAct), pNewSummary->mgmtParms, PCMFLAG_SET_SILENT_BREAKAWAY);
  1458. if ( pOldSummary )
  1459. PCFormatOnOrOffLimit(fromSilentBrkAwayAct, ENTRY_COUNT(fromSilentBrkAwayAct), pOldSummary->mgmtParms, PCMFLAG_SET_SILENT_BREAKAWAY);
  1460. // breakaway OK
  1461. TCHAR toBrkAwayOKAct[16], fromBrkAwayOKAct[16] = { 0 };
  1462. PCFormatOnOrOffLimit(toBrkAwayOKAct, ENTRY_COUNT(toBrkAwayOKAct), pNewSummary->mgmtParms, PCMFLAG_SET_PROC_BREAKAWAY_OK);
  1463. if ( pOldSummary )
  1464. PCFormatOnOrOffLimit(fromBrkAwayOKAct, ENTRY_COUNT(fromBrkAwayOKAct), pOldSummary->mgmtParms, PCMFLAG_SET_PROC_BREAKAWAY_OK);
  1465. if ( !pOldSummary ) {
  1466. const TCHAR *msgs[] = { pNewSummary->jobName,
  1467. pNewSummary->mgmtParms.description,
  1468. toAffinity,
  1469. toPriority,
  1470. toWS,
  1471. toSch,
  1472. toProcCount,
  1473. toProcMemory,
  1474. toJobMemory,
  1475. toProcTime,
  1476. toJobTime,
  1477. toEndofJobTimeAction,
  1478. toEndJobEmpty,
  1479. toDieUHExcept,
  1480. toSilentBrkAwayAct,
  1481. toBrkAwayOKAct
  1482. };
  1483. PCLogMessage( PC_SERVICE_ADD_JOB_EXECUTION_RULE, EVENTLOG_INFORMATION_TYPE,
  1484. ENTRY_COUNT(msgs), msgs );
  1485. }
  1486. else {
  1487. const TCHAR *msgs[] = { pNewSummary->jobName,
  1488. pNewSummary->mgmtParms.description, pOldSummary->mgmtParms.description,
  1489. toAffinity, fromAffinity,
  1490. toPriority, fromPriority,
  1491. toWS, fromWS,
  1492. toSch, fromSch,
  1493. toProcCount, fromProcCount,
  1494. toProcMemory, fromProcMemory,
  1495. toJobMemory, fromJobMemory,
  1496. toProcTime, fromProcTime,
  1497. toJobTime, fromJobTime,
  1498. toEndofJobTimeAction, fromEndofJobTimeAction,
  1499. toEndJobEmpty, fromEndJobEmpty,
  1500. toDieUHExcept, fromDieUHExcept,
  1501. toSilentBrkAwayAct, fromSilentBrkAwayAct,
  1502. toBrkAwayOKAct, fromBrkAwayOKAct
  1503. };
  1504. PCLogMessage( PC_SERVICE_REPL_JOB_EXECUTION_RULE, EVENTLOG_INFORMATION_TYPE,
  1505. ENTRY_COUNT(msgs), msgs );
  1506. }
  1507. }
  1508. //--------------------------------------------------------------------------------------------//
  1509. // Functions to get name rules in API format //
  1510. // Input: start point, target loc, conts, etc. -- see below //
  1511. // Returns: TRUE if more data exists, else FALSE (there are no error conditions) //
  1512. //--------------------------------------------------------------------------------------------//
  1513. BOOL CProcConDB::GetNameRules( const PCINT32 first,
  1514. PCNameRule *pRules,
  1515. const PCINT32 maxCount,
  1516. PCINT16 *itemLen,
  1517. PCINT16 *itemCount,
  1518. PCINT32 *updCtr )
  1519. {
  1520. EnterCriticalSection( &m_dbCSNameRule );
  1521. *itemLen = sizeof(PCNameRule);
  1522. *itemCount = 0;
  1523. *updCtr = m_updCtrName;
  1524. // copy data to buffer until end of data or max requested hit
  1525. for ( PCULONG32 i = first, numRules = m_numNameRules;
  1526. i < numRules && *itemCount < maxCount;
  1527. ++i, ++*itemCount )
  1528. memcpy( pRules++, &m_fmtNameRules[i], *itemLen );
  1529. LeaveCriticalSection( &m_dbCSNameRule );
  1530. return i < numRules;
  1531. }
  1532. //--------------------------------------------------------------------------------------------//
  1533. // Function to add a name rule //
  1534. // Input: new rule, data version, new index ("add before index"), update counter //
  1535. // Returns: PCERROR_SUCCESS if successful, error code if not //
  1536. //--------------------------------------------------------------------------------------------//
  1537. PCULONG32 CProcConDB::AddNameRule( const PCNameRule *pRule,
  1538. const BYTE version,
  1539. const PCULONG32 index,
  1540. const PCINT32 updCtr )
  1541. {
  1542. PCINT32 APIerr = PCERROR_SUCCESS;
  1543. PROC_NAME procName = { 0 };
  1544. EnterCriticalSection( &m_dbCSNameRule );
  1545. if ( updCtr != m_updCtrName ) APIerr = PCERROR_UPDATE_OCCURRED;
  1546. else if ( index >= m_numNameRules ) APIerr = PCERROR_INDEX_OUT_OF_RANGE;
  1547. else {
  1548. PCNameRule *newRules = new PCNameRule[m_numNameRules + 1];
  1549. PCULONG32 newSize = sizeof(PCNameRule) * (m_numNameRules + 1);
  1550. if ( !newRules ) {
  1551. PCLogNoMemory( TEXT("AllocFmtNameRules"), newSize );
  1552. APIerr = PCERROR_SERVER_INTERNAL_ERROR;
  1553. }
  1554. else {
  1555. memcpy(procName, &m_fmtNameRules[index].procName, sizeof(procName));
  1556. memset( newRules, 0, newSize );
  1557. for ( PCULONG32 i = 0, j = 0; i < m_numNameRules; ++i ) {
  1558. if ( index == i ) memcpy( &newRules[j++], pRule, sizeof(newRules[0]) );
  1559. memcpy( &newRules[j++], &m_fmtNameRules[i], sizeof(newRules[0]) );
  1560. }
  1561. if ( m_intNameRules ) { delete [] m_intNameRules; m_intNameRules = NULL; }
  1562. PCNameRule *oldRules = m_fmtNameRules;
  1563. m_fmtNameRules = newRules;
  1564. ++m_numNameRules;
  1565. APIerr = NameRulesUpdated();
  1566. if ( APIerr != ERROR_SUCCESS ) {
  1567. m_fmtNameRules = oldRules;
  1568. --m_numNameRules;
  1569. delete [] newRules;
  1570. }
  1571. else
  1572. delete [] oldRules;
  1573. }
  1574. }
  1575. LeaveCriticalSection( &m_dbCSNameRule );
  1576. if ( APIerr == PCERROR_SUCCESS && m_LogRuleEdits )
  1577. {
  1578. TCHAR indexString1[16], indexString2[16];
  1579. TCHAR matchTypeAsString[] = { pRule->matchType, 0};
  1580. _ultot( index, indexString1, 10 );
  1581. _ultot( index + 1, indexString2, 10 );
  1582. const TCHAR *msgs[] = { indexString1, pRule->procName,
  1583. indexString2, procName,
  1584. pRule->description,
  1585. pRule->matchString,
  1586. matchTypeAsString
  1587. };
  1588. PCLogMessage( PC_SERVICE_ADD_ALIAS_RULE, EVENTLOG_INFORMATION_TYPE,
  1589. ENTRY_COUNT(msgs), msgs);
  1590. }
  1591. return APIerr;
  1592. }
  1593. //--------------------------------------------------------------------------------------------//
  1594. // Function to replace a name rule //
  1595. // Input: new rule, data version, index of rule to replace, update counter //
  1596. // Returns: PCERROR_SUCCESS if successful, error code if not //
  1597. //--------------------------------------------------------------------------------------------//
  1598. PCULONG32 CProcConDB::ReplNameRule( const PCNameRule *pRule,
  1599. const BYTE version,
  1600. const PCULONG32 index,
  1601. const PCINT32 updCtr )
  1602. {
  1603. PCINT32 APIerr = PCERROR_SUCCESS;
  1604. PCNameRule oldRule;
  1605. EnterCriticalSection( &m_dbCSNameRule );
  1606. if ( updCtr != m_updCtrName ) APIerr = PCERROR_UPDATE_OCCURRED;
  1607. else if ( index >= m_numNameRules - 1 ) APIerr = PCERROR_INDEX_OUT_OF_RANGE;
  1608. else {
  1609. memcpy( &oldRule, &m_fmtNameRules[index], sizeof(oldRule) );
  1610. memcpy( &m_fmtNameRules[index], pRule, sizeof(m_fmtNameRules[index]) );
  1611. BuildIntNameRule( index );
  1612. APIerr = NameRulesUpdated();
  1613. }
  1614. LeaveCriticalSection( &m_dbCSNameRule );
  1615. if ( APIerr == PCERROR_SUCCESS && m_LogRuleEdits )
  1616. {
  1617. TCHAR indexAsString[16];
  1618. TCHAR matchTypeAsString[] = { pRule->matchType, 0 };
  1619. TCHAR matchType2AsString[] = { oldRule.matchType, 0 };
  1620. _ultot( index, indexAsString, 10 );
  1621. const TCHAR *msgs[] = { indexAsString,
  1622. pRule->procName, oldRule.procName,
  1623. pRule->description, oldRule.description,
  1624. pRule->matchString, oldRule.matchString,
  1625. matchTypeAsString, matchType2AsString,
  1626. };
  1627. PCLogMessage( PC_SERVICE_REPL_ALIAS_RULE, EVENTLOG_INFORMATION_TYPE,
  1628. ENTRY_COUNT(msgs), msgs);
  1629. }
  1630. return APIerr;
  1631. }
  1632. //--------------------------------------------------------------------------------------------//
  1633. // Function to delete a name rule //
  1634. // Input: index of rule to delete, update counter //
  1635. // Returns: PCERROR_SUCCESS if successful, error code if not //
  1636. //--------------------------------------------------------------------------------------------//
  1637. PCULONG32 CProcConDB::DelNameRule( const PCULONG32 index,
  1638. const PCINT32 updCtr )
  1639. {
  1640. PCINT32 APIerr = PCERROR_SUCCESS;
  1641. PROC_NAME procName = { 0 };
  1642. EnterCriticalSection( &m_dbCSNameRule );
  1643. if ( updCtr != m_updCtrName ) APIerr = PCERROR_UPDATE_OCCURRED;
  1644. else if ( index >= m_numNameRules - 1 ) APIerr = PCERROR_INDEX_OUT_OF_RANGE;
  1645. else {
  1646. PCNameRule *newRules = new PCNameRule[m_numNameRules - 1];
  1647. memcpy(procName, &m_fmtNameRules[index].procName, sizeof(procName));
  1648. if ( !newRules ) {
  1649. PCLogNoMemory( TEXT("AllocFmtNameRules"), sizeof(PCNameRule) * (m_numNameRules - 1) );
  1650. APIerr = PCERROR_SERVER_INTERNAL_ERROR;
  1651. }
  1652. else {
  1653. for ( PCULONG32 i = 0, j = 0; i < m_numNameRules; ++i ) {
  1654. if ( index != i )
  1655. memcpy( &newRules[j++], &m_fmtNameRules[i], sizeof(m_fmtNameRules[i]) );
  1656. }
  1657. delete [] m_fmtNameRules;
  1658. if ( m_intNameRules ) { delete [] m_intNameRules; m_intNameRules = NULL; }
  1659. m_fmtNameRules = newRules;
  1660. --m_numNameRules;
  1661. APIerr = NameRulesUpdated();
  1662. }
  1663. }
  1664. LeaveCriticalSection( &m_dbCSNameRule );
  1665. if ( APIerr == PCERROR_SUCCESS && m_LogRuleEdits )
  1666. PCLogMessage( PC_SERVICE_DEL_ALIAS_RULE, EVENTLOG_INFORMATION_TYPE,
  1667. 1, procName );
  1668. return APIerr;
  1669. }
  1670. //--------------------------------------------------------------------------------------------//
  1671. // Function to swap adjacent name rules //
  1672. // Input: index of rule to swap with following rule, update counter //
  1673. // Returns: PCERROR_SUCCESS if successful, error code if not //
  1674. //--------------------------------------------------------------------------------------------//
  1675. PCULONG32 CProcConDB::SwapNameRule( const PCULONG32 index,
  1676. const PCINT32 updCtr )
  1677. {
  1678. PCINT32 APIerr = PCERROR_SUCCESS;
  1679. PROC_NAME procName1 = { 0 };
  1680. PROC_NAME procName2 = { 0 };
  1681. EnterCriticalSection( &m_dbCSNameRule );
  1682. if ( updCtr != m_updCtrName ) APIerr = PCERROR_UPDATE_OCCURRED;
  1683. else if ( index >= m_numNameRules - 2 ) APIerr = PCERROR_INDEX_OUT_OF_RANGE;
  1684. else {
  1685. PCNameRule rule;
  1686. memcpy(procName1, &m_fmtNameRules[index].procName, sizeof(procName1));
  1687. memcpy(procName2, &m_fmtNameRules[index+1].procName, sizeof(procName2));
  1688. memcpy( &rule, &m_fmtNameRules[index], sizeof(rule) );
  1689. memcpy( &m_fmtNameRules[index], &m_fmtNameRules[index + 1], sizeof(rule) );
  1690. memcpy( &m_fmtNameRules[index + 1], &rule, sizeof(rule) );
  1691. BuildIntNameRule( index );
  1692. BuildIntNameRule( index + 1 );
  1693. APIerr = NameRulesUpdated();
  1694. }
  1695. LeaveCriticalSection( &m_dbCSNameRule );
  1696. if ( APIerr == PCERROR_SUCCESS && m_LogRuleEdits )
  1697. {
  1698. TCHAR indexString1[16], indexString2[16];
  1699. _ultot( index, indexString1, 10 );
  1700. _ultot( index + 1, indexString2, 10 );
  1701. const TCHAR *msgs[] = { indexString1, procName1, indexString2, procName2 };
  1702. PCLogMessage( PC_SERVICE_SWAP_ALIAS_RULE, EVENTLOG_INFORMATION_TYPE,
  1703. ENTRY_COUNT(msgs), msgs );
  1704. }
  1705. return APIerr;
  1706. }
  1707. //--------------------------------------------------------------------------------------------//
  1708. // Functions to get proc list data in API format //
  1709. // Input: start point and target loc, max count, item len return, item count return //
  1710. // Returns: TRUE if more data exists, else FALSE (there are no error conditions) //
  1711. //--------------------------------------------------------------------------------------------//
  1712. BOOL CProcConDB::GetProcList( const PCProcListItem *pStart,
  1713. const PCUINT32 listFlags,
  1714. PCProcListItem *pList,
  1715. const PCINT32 maxCount,
  1716. PCINT16 *itemLen,
  1717. PCINT16 *itemCount )
  1718. {
  1719. *itemLen = sizeof(PCProcListItem);
  1720. *itemCount = 0;
  1721. PCULONG32 procEntries = 0, nameEntries = 0, activeEntries = 0;
  1722. PCProcListItem *procList = NULL, *nameList = NULL;
  1723. // Get process definition rule data...
  1724. EnterCriticalSection( &m_dbCSProcRule );
  1725. procEntries = m_numProcRules;
  1726. // allocate space for process definition list...
  1727. procList = new PCProcListItem[ procEntries ];
  1728. if ( !procList ) {
  1729. PCLogNoMemory( TEXT("AllocProcList1"), sizeof(PCProcListItem) * procEntries );
  1730. procEntries = 0;
  1731. }
  1732. memset( procList, 0, sizeof(PCProcListItem) * procEntries );
  1733. // Add names of defined processes...
  1734. for ( PCULONG32 i = 0; i < procEntries; ++i ) {
  1735. memcpy( procList[i].procName, m_procSummary[i].procName, sizeof(procList->procName) );
  1736. procList[i].lFlags = PCLFLAG_IS_DEFINED;
  1737. if ( m_procSummary[i].mgmtParms.mFlags & PCMFLAG_PROC_HAS_JOB_REFERENCE ) {
  1738. procList[i].lFlags |= PCLFLAG_HAS_MEMBER_OF_JOB;
  1739. memcpy( procList[i].jobName, m_procSummary[i].memberOfJobName, sizeof(procList->jobName) );
  1740. }
  1741. if ( PCIsProcManaged( m_procSummary[i].mgmtParms, &m_procSummary[i].memberOfJobName ) )
  1742. procList[i].lFlags |= PCLFLAG_IS_MANAGED;
  1743. }
  1744. LeaveCriticalSection( &m_dbCSProcRule );
  1745. // Get name rule data...
  1746. EnterCriticalSection( &m_dbCSNameRule );
  1747. PCULONG32 names = m_numNameRules - 1; // exclude default rule which is last
  1748. // allocate space for name list...
  1749. nameList = new PCProcListItem[ names ];
  1750. if ( !nameList ) {
  1751. PCLogNoMemory( TEXT("AllocProcList2"), sizeof(PCProcListItem) * names );
  1752. names = 0;
  1753. }
  1754. memset( nameList, 0, sizeof(PCProcListItem) * names );
  1755. // Add names from name rules...
  1756. for ( i = 0; i < names; ++i ) {
  1757. if ( !NameHasPattern( m_fmtNameRules[i].procName ) ) {
  1758. memcpy( nameList[nameEntries].procName, m_fmtNameRules[i].procName, sizeof(nameList->procName) );
  1759. nameList[nameEntries++].lFlags = PCLFLAG_HAS_NAME_RULE;
  1760. }
  1761. }
  1762. LeaveCriticalSection( &m_dbCSNameRule );
  1763. // Get running process data--------------------------------------------------------
  1764. PCProcListItem *activeList;
  1765. activeEntries = m_cMgr->ExportActiveProcList( &activeList );
  1766. // Build full list...
  1767. PCULONG32 entries = procEntries + nameEntries + activeEntries;
  1768. PCProcListItem *fullList = new PCProcListItem[ entries ];
  1769. if ( !fullList ) {
  1770. PCLogNoMemory( TEXT("AllocProcList3"), sizeof(PCProcListItem) * entries );
  1771. entries = procEntries = nameEntries = activeEntries = 0;
  1772. }
  1773. if ( procEntries )
  1774. memcpy( fullList, procList, sizeof(PCProcListItem) * procEntries );
  1775. if ( nameEntries )
  1776. memcpy( fullList + procEntries, nameList, sizeof(PCProcListItem) * nameEntries );
  1777. if ( activeEntries )
  1778. memcpy( fullList + procEntries + nameEntries, activeList, sizeof(PCProcListItem) * activeEntries );
  1779. delete [] procList;
  1780. delete [] nameList;
  1781. delete [] activeList;
  1782. qsort( fullList, entries, *itemLen, CompareProcListItem );
  1783. // copy data to buffer until end of data or max requested hit...
  1784. int rc;
  1785. PC_LIST_FLAGS lastFlags = 0;
  1786. PCProcListItem li; // list item being built
  1787. memset( &li, 0, sizeof(li) );
  1788. for ( i = 0, *itemCount = 0;
  1789. i < entries && *itemCount < maxCount;
  1790. lastFlags = fullList[i++].lFlags ) {
  1791. // if name changed or both have pids we have a new process...
  1792. if ( (rc = CompareProcName( li.procName, fullList[i].procName )) ||
  1793. (li.procStats.pid && fullList[i].procStats.pid) ) {
  1794. // See if new name belongs in the list and, if so, wrap up last entry and start new...
  1795. if ( ProcBelongsInList( li, pStart, listFlags ) ) {
  1796. memcpy( pList, &li, *itemLen );
  1797. pList->lFlags |= lastFlags;
  1798. ++pList;
  1799. ++*itemCount;
  1800. }
  1801. PC_LIST_FLAGS savedFlags = li.lFlags;
  1802. memcpy( &li, &fullList[i], *itemLen );
  1803. li.actualPriority = PCMapPriorityForAPI( li.actualPriority );
  1804. if ( !rc ) li.lFlags = savedFlags;
  1805. }
  1806. else {
  1807. li.lFlags |= fullList[i].lFlags;
  1808. if ( fullList[i].lFlags & PCLFLAG_IS_RUNNING ) {
  1809. memcpy( &li.procStats, &fullList[i].procStats, sizeof(li.procStats) );
  1810. memcpy( li.imageName, fullList[i].imageName, sizeof(li.imageName) );
  1811. memcpy( li.jobName, fullList[i].jobName, sizeof(li.jobName) );
  1812. li.actualPriority = PCMapPriorityForAPI( fullList[i].actualPriority );
  1813. li.actualAffinity = fullList[i].actualAffinity;
  1814. }
  1815. if ( fullList[i].lFlags & PCLFLAG_HAS_MEMBER_OF_JOB )
  1816. memcpy( li.jobName, fullList[i].jobName, sizeof(li.jobName) );
  1817. }
  1818. }
  1819. if ( *itemCount < maxCount && ProcBelongsInList( li, pStart, listFlags ) ) {
  1820. memcpy( pList, &li, *itemLen );
  1821. pList->lFlags |= lastFlags;
  1822. ++*itemCount;
  1823. }
  1824. delete [] fullList;
  1825. return i < entries;
  1826. }
  1827. //--------------------------------------------------------------------------------------------//
  1828. // Functions to get job list data in API format //
  1829. // Input: start point and target loc, max count, item len return, item count return //
  1830. // Returns: TRUE if more data exists, else FALSE (there are no error conditions) //
  1831. //--------------------------------------------------------------------------------------------//
  1832. BOOL CProcConDB::GetJobList( const PCJobListItem *pStart,
  1833. const PCUINT32 listFlags,
  1834. PCJobListItem *pList,
  1835. const PCINT32 maxCount,
  1836. PCINT16 *itemLen,
  1837. PCINT16 *itemCount )
  1838. {
  1839. *itemLen = sizeof(PCJobListItem);
  1840. *itemCount = 0;
  1841. PCULONG32 jobEntries = 0, jrefEntries = 0, activeEntries = 0;
  1842. PCJobListItem *jobList = NULL, *jrefList = NULL;
  1843. // Get job definition rule data...
  1844. EnterCriticalSection( &m_dbCSJobRule );
  1845. jobEntries = m_numJobRules;
  1846. // allocate space for job definition list...
  1847. jobList = new PCJobListItem[ jobEntries ];
  1848. if ( !jobList ) {
  1849. PCLogNoMemory( TEXT("AllocJobList1"), sizeof(PCJobListItem) * jobEntries );
  1850. jobEntries = 0;
  1851. }
  1852. else memset( jobList, 0, sizeof(PCJobListItem) * jobEntries );
  1853. // Add names of defined jobs...
  1854. for ( PCULONG32 i = 0; i < jobEntries; ++i ) {
  1855. memcpy( jobList[i].jobName, m_jobSummary[i].jobName, sizeof(jobList->jobName) );
  1856. jobList[i].lFlags = PCLFLAG_IS_DEFINED;
  1857. if ( PCIsJobManaged( m_jobSummary[i].mgmtParms ) )
  1858. jobList[i].lFlags |= PCLFLAG_IS_MANAGED;
  1859. }
  1860. LeaveCriticalSection( &m_dbCSJobRule );
  1861. EnterCriticalSection( &m_dbCSProcRule );
  1862. jrefEntries = m_numProcRules;
  1863. // allocate space for job reference list...
  1864. jrefList = new PCJobListItem[ jrefEntries ];
  1865. if ( !jrefList ) {
  1866. PCLogNoMemory( TEXT("AllocJobList2"), sizeof(PCJobListItem) * jrefEntries );
  1867. jrefEntries = 0;
  1868. }
  1869. else memset( jrefList, 0, sizeof(PCJobListItem) * jrefEntries );
  1870. // Add names from process definitions...
  1871. PCULONG32 ctr = 0;
  1872. for ( i = 0; i < jrefEntries; ++i ) {
  1873. if ( *(m_procSummary[i].memberOfJobName) ) {
  1874. memcpy( jrefList[ctr].jobName, m_procSummary[i].memberOfJobName, sizeof(jrefList->jobName) );
  1875. jrefList[ctr].lFlags = PCLFLAG_HAS_MEMBER_OF_JOB;
  1876. ++ctr;
  1877. }
  1878. }
  1879. jrefEntries = ctr;
  1880. LeaveCriticalSection( &m_dbCSProcRule );
  1881. // Add names of running jobs...
  1882. PCJobListItem *activeList;
  1883. activeEntries = m_cMgr->ExportActiveJobList( &activeList );
  1884. // Build full list...
  1885. PCULONG32 entries = jobEntries + jrefEntries + activeEntries;
  1886. PCJobListItem *fullList = new PCJobListItem[ entries ];
  1887. if ( !fullList ) {
  1888. PCLogNoMemory( TEXT("AllocJobList3"), sizeof(PCJobListItem) * entries );
  1889. entries = jobEntries = jrefEntries = activeEntries = 0;
  1890. }
  1891. if ( jobEntries )
  1892. memcpy( fullList, jobList, sizeof(PCJobListItem) * jobEntries );
  1893. if ( jrefEntries )
  1894. memcpy( fullList + jobEntries, jrefList, sizeof(PCJobListItem) * jrefEntries );
  1895. if ( activeEntries )
  1896. memcpy( fullList + jobEntries + jrefEntries, activeList, sizeof(PCJobListItem) * activeEntries );
  1897. delete [] jobList;
  1898. delete [] jrefList;
  1899. delete [] activeList;
  1900. // Sort full list...
  1901. qsort( fullList, entries, *itemLen, CompareJobListItem );
  1902. // copy data to buffer until end of data or max requested hit...
  1903. PCJobListItem li; // list item being built
  1904. memset( &li, 0, sizeof(li) );
  1905. for ( i = 0, *itemCount = 0; i < entries && *itemCount < maxCount; ++i ) {
  1906. // if name changed we have a new job...
  1907. if ( CompareJobName( li.jobName, fullList[i].jobName ) ) {
  1908. if ( JobBelongsInList( li, pStart, listFlags ) ) {
  1909. memcpy( pList++, &li, *itemLen );
  1910. ++*itemCount;
  1911. }
  1912. memcpy( &li, &fullList[i], *itemLen );
  1913. li.actualPriority = PCMapPriorityForAPI( li.actualPriority );
  1914. }
  1915. else {
  1916. li.lFlags |= fullList[i].lFlags;
  1917. if ( fullList[i].lFlags & PCLFLAG_IS_RUNNING ) {
  1918. li.actualPriority = PCMapPriorityForAPI( fullList[i].actualPriority );
  1919. li.actualAffinity = fullList[i].actualAffinity;
  1920. li.actualSchedClass = fullList[i].actualSchedClass;
  1921. memcpy( &li.jobStats, &fullList[i].jobStats, sizeof(li.jobStats) );
  1922. }
  1923. }
  1924. }
  1925. if ( *itemCount < maxCount && *li.jobName && JobBelongsInList( li, pStart, listFlags ) ) {
  1926. memcpy( pList, &li, *itemLen );
  1927. ++*itemCount;
  1928. }
  1929. delete [] fullList;
  1930. return i < entries;
  1931. }
  1932. //--------------------------------------------------------------------------------------------//
  1933. // Functions to assign a process name given a path+exe name //
  1934. // Input: path name, location to build proc name //
  1935. // Returns: nothing -- cannot fail due to default name rule //
  1936. //--------------------------------------------------------------------------------------------//
  1937. void CProcConDB::AssignProcName( const TCHAR *path, PROC_NAME *name, IMAGE_NAME *iName ) {
  1938. // First parse path name into nodes and exe name...
  1939. TCHAR pCopy[MAX_PATH];
  1940. TCHAR *nodes[MAX_PATH / 2], *p = pCopy;
  1941. _tcscpy( pCopy, path );
  1942. if ( *(p + 1) == TEXT('?') ) // skip if we have a \??\ prefix
  1943. p += 4;
  1944. // jump over leading drive letter or computer and share (UNC) name...
  1945. if ( *(p + 1) == TEXT(':') )
  1946. p += 2;
  1947. else if ( *(p + 1) == TEXT('\\') ) {
  1948. p = _tcschr( p + 2, TEXT('\\') ); // scan for end of computer name
  1949. if ( p ) p = _tcschr( p + 1, TEXT('\\') ); // scan for end of share name
  1950. if ( p ) ++p; // advance to first of path name
  1951. }
  1952. if ( p && *p == TEXT('\\') ) ++p; // skip \ if we start at root
  1953. // locate and save start of each node, setting '\' to null to get szstrings...
  1954. for ( PCULONG32 nodeCt = 0; p && nodeCt < ENTRY_COUNT(nodes); ++nodeCt ) {
  1955. nodes[nodeCt] = p;
  1956. p = _tcschr( p, TEXT('\\') );
  1957. if ( p ) *p++ = 0;
  1958. }
  1959. if ( !nodeCt ) { // should not occur
  1960. _tcscpy( (TCHAR *) name, TEXT("<err>") );
  1961. _tcscpy( (TCHAR *) iName, TEXT("<err>") );
  1962. return;
  1963. }
  1964. // set exe name pointer and extension location...
  1965. TCHAR *exeName = nodes[--nodeCt];
  1966. _tcsncpy( (TCHAR *) iName, exeName, IMAGE_NAME_LEN );
  1967. const int extStart = ExtStartLoc( exeName );
  1968. // Gain control over rules and build internal version if needed...
  1969. EnterCriticalSection( &m_dbCSNameRule );
  1970. if ( !m_intNameRules && !BuildIntNameRules() ) {
  1971. LeaveCriticalSection( &m_dbCSNameRule );
  1972. return;
  1973. }
  1974. // scan rules until we have a match...
  1975. for ( PCULONG32 i = 0, done = FALSE; !done && i < m_numNameRules; ++i ) {
  1976. switch ( m_intNameRules[i].mType ) {
  1977. case MATCH_PGM:
  1978. if ( !(m_intNameRules[i].mFlags & MFLAG_HAS_EXTENSION) && extStart )
  1979. exeName[extStart] = 0;
  1980. if ( NameMatch( TRUE, m_intNameRules[i].mFlags & MFLAG_HAS_WILDCARD,
  1981. m_intNameRules[i].mString, (const TCHAR **) &exeName ) ) {
  1982. NameSet( name,
  1983. m_intNameRules[i].mFlags & MFLAG_HAS_NAME_PATTERN,
  1984. m_intNameRules[i].mName, exeName );
  1985. done = TRUE;
  1986. }
  1987. if ( !(m_intNameRules[i].mFlags & MFLAG_HAS_EXTENSION) && extStart )
  1988. exeName[extStart] = TEXT('.');
  1989. break;
  1990. case MATCH_DIR: {
  1991. PCULONG32 matchNode;
  1992. if ( NameMatch( TRUE, m_intNameRules[i].mFlags & MFLAG_HAS_WILDCARD,
  1993. m_intNameRules[i].mString, (const TCHAR **) nodes, nodeCt, &matchNode ) ) {
  1994. NameSet( name,
  1995. m_intNameRules[i].mFlags & MFLAG_HAS_NAME_PATTERN,
  1996. m_intNameRules[i].mName, exeName, nodes[matchNode] );
  1997. done = TRUE;
  1998. }
  1999. break;
  2000. }
  2001. case MATCH_ANY:
  2002. if ( NameMatch( FALSE, m_intNameRules[i].mFlags & MFLAG_HAS_WILDCARD,
  2003. m_intNameRules[i].mString, &path ) ) {
  2004. NameSet( name,
  2005. m_intNameRules[i].mFlags & MFLAG_HAS_NAME_PATTERN,
  2006. m_intNameRules[i].mName, exeName );
  2007. done = TRUE;
  2008. }
  2009. break;
  2010. } // end switch
  2011. } // end for
  2012. LeaveCriticalSection( &m_dbCSNameRule );
  2013. if ( !done ) // should not occur
  2014. _tcscpy( (TCHAR *) name, TEXT("<err>") );
  2015. }
  2016. BOOL CProcConDB::NameMatch( const BOOL compare, // TRUE for compare operation, FALSE for scan
  2017. const BOOL hasWildcard, // string contains wildcard character(s)
  2018. const TCHAR *str, // string to match against
  2019. const TCHAR **arg, // path name argument(s)
  2020. const PCULONG32 argCt, // number of arguments
  2021. PCULONG32 *mIdx ) { // where to store matching arg index or NULL
  2022. BOOL good = FALSE;
  2023. // Compare against every match argument supplied...
  2024. for ( PCULONG32 i = 0; !good && i < argCt; ++i, ++arg ) {
  2025. // for wildcard compares scan character by character...
  2026. if ( hasWildcard ) {
  2027. good = TRUE;
  2028. for ( const TCHAR *p = str, *a = *arg; good && *p && *p != TEXT('*'); ++p, ++a )
  2029. good = (*a && *p == TEXT('?')) || _totupper( *p ) == _totupper( *a );
  2030. }
  2031. // for non-wildcard compares just do straight compare or scan...
  2032. else
  2033. good = ( compare && !_tcsicmp( *arg, str ) ) ||
  2034. ( !compare && PCiStrStr( *arg, str ) );
  2035. }
  2036. if ( good && mIdx ) *mIdx = i -1;
  2037. return good;
  2038. }
  2039. void CProcConDB::NameSet( PROC_NAME *name, // where to put name
  2040. const BOOL isPattern, // string contains <x> pattern(s)
  2041. const TCHAR *pattern, // where to get name
  2042. const TCHAR *patArgP, // where to get pgm pattern substitution
  2043. const TCHAR *patArgN ) { // where to get node pattern substitution or NULL
  2044. memset( name, 0, sizeof(*name) );
  2045. if ( !isPattern )
  2046. _tcsncpy( (TCHAR *) name, pattern, ENTRY_COUNT(*name) - 1 );
  2047. else {
  2048. TCHAR out[MAX_PATH * 2];
  2049. memset( out, 0, sizeof(out) );
  2050. TCHAR *outp = out;
  2051. for ( PCULONG32 i = 0; *pattern; ++i ) {
  2052. if ( !_tcsnicmp( pattern, NAME_IS_PGM, 3 ) )
  2053. {
  2054. _tcscpy( outp, patArgP );
  2055. outp += _tcslen( patArgP );
  2056. pattern += 3;
  2057. }
  2058. else if ( !_tcsnicmp( pattern, HIDE_PROC_PATTERN, 3 ) )
  2059. {
  2060. *name[0] = 0;
  2061. return;
  2062. }
  2063. else if ( patArgN && !_tcsnicmp( pattern, NAME_IS_DIR, 3 ) )
  2064. {
  2065. _tcscpy( outp, patArgN );
  2066. outp += _tcslen( patArgN );
  2067. pattern += 3;
  2068. }
  2069. else
  2070. *outp++ = *pattern++;
  2071. }
  2072. _tcsncpy( (TCHAR *) name, out, ENTRY_COUNT(*name) - 1 );
  2073. }
  2074. }
  2075. int CProcConDB::ExtStartLoc( const TCHAR *name ) { // Find start of name extension or 0
  2076. int len = _tcslen( name );
  2077. for ( int i = len - 1; i > 0 && i > len - 4; --i )
  2078. if ( name[i] == TEXT('.') ) break;
  2079. return ( i > 0 && name[i] == TEXT('.') )? i : 0;
  2080. }
  2081. //--------------------------------------------------------------------------------------------//
  2082. // Functions to build internal format name rules based on API format name rules //
  2083. // Input: nothing -- operates on member data //
  2084. // Returns: TRUE if successful, else FALSE //
  2085. // Note: caller must hold the name rule critical section //
  2086. //--------------------------------------------------------------------------------------------//
  2087. BOOL CProcConDB::BuildIntNameRules( void ) {
  2088. if ( m_intNameRules ) delete [] m_intNameRules;
  2089. m_intNameRules = new PCNameRuleInt[m_numNameRules];
  2090. if ( !m_intNameRules ) {
  2091. PCLogNoMemory( TEXT("AllocIntNameRules"), m_numNameRules * sizeof(PCNameRuleInt) );
  2092. return FALSE;
  2093. }
  2094. for ( PCULONG32 i = 0; i < m_numNameRules; ++i )
  2095. BuildIntNameRule( i );
  2096. return TRUE;
  2097. }
  2098. void CProcConDB::BuildIntNameRule( PCULONG32 index ) {
  2099. if ( !m_intNameRules || index >= m_numNameRules )
  2100. return;
  2101. PCNameRuleInt &iRule = m_intNameRules[index];
  2102. PCNameRule &fRule = m_fmtNameRules[index];
  2103. memset( &iRule, 0, sizeof(iRule) );
  2104. // Copy match type...
  2105. iRule.mType = fRule.matchType;
  2106. // Copy/expand match string...
  2107. ExpandEnvironmentStrings( fRule.matchString, iRule.mString, ENTRY_COUNT(iRule.mString) );
  2108. // Flag if match string contains wildcards * or ?...
  2109. if ( _tcschr( iRule.mString, TEXT('*') ) || _tcschr( iRule.mString, TEXT('?') ) )
  2110. iRule.mFlags |= MFLAG_HAS_WILDCARD;
  2111. // Flag if match string contains extension...
  2112. if ( ExtStartLoc( iRule.mString ) )
  2113. iRule.mFlags |= MFLAG_HAS_EXTENSION;
  2114. // Copy name and flag if name contains pattern (assume pattern if '<' present)...
  2115. memcpy( iRule.mName, fRule.procName, sizeof(iRule.mName) );
  2116. if ( NameHasPattern( iRule.mName ) )
  2117. iRule.mFlags |= MFLAG_HAS_NAME_PATTERN;
  2118. // Copy description...
  2119. memcpy( iRule.mDesc, fRule.description, sizeof(iRule.mDesc) );
  2120. }
  2121. //--------------------------------------------------------------------------------------------//
  2122. // Function to test users right to perform an action //
  2123. // Input: action name ptr //
  2124. // Returns: ERROR_SUCCESS if access is allowed, else an error code //
  2125. // Note: access tests are implemented as READ tests against a registry key in PARAMETERS. //
  2126. // Also, any failure is reported as access denied in the spirit of reporting little //
  2127. // information in case of security failures. //
  2128. //--------------------------------------------------------------------------------------------//
  2129. INT32 CProcConDB::TestAccess( const TCHAR *key ) {
  2130. HKEY outKey;
  2131. DWORD err = RegOpenKeyEx( m_parmRegKey, key, NULL, KEY_QUERY_VALUE, &outKey );
  2132. if ( err == ERROR_SUCCESS ) RegCloseKey( outKey );
  2133. else {
  2134. err = ERROR_ACCESS_DENIED; // always use access denied to report failure
  2135. SetLastError( err );
  2136. }
  2137. return err;
  2138. }
  2139. // End of CProcConDB.cpp
  2140. //============================================================================J McDonald fecit====//