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.

1082 lines
55 KiB

  1. /*======================================================================================//
  2. | //
  3. |Copyright (c) 1998, 1999 Sequent Computer Systems, Incorporated //
  4. | //
  5. |Description: //
  6. | //
  7. |---------------------------------------------------------------------------------------//
  8. | This file is the ProcCon header file used only by the ProcCon NT Service //
  9. |---------------------------------------------------------------------------------------//
  10. | //
  11. |Created: //
  12. | //
  13. | Jarl McDonald 07-98 //
  14. | //
  15. |Revision History: //
  16. | //
  17. |=======================================================================================*/
  18. #include <windows.h>
  19. #include <winnt.h>
  20. #include <stddef.h>
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <tchar.h>
  24. #include <assert.h>
  25. #include <search.h>
  26. #include <time.h>
  27. #include <winver.h>
  28. #include "resource.h"
  29. #include "ProcConSvcMsg.h" // Message definitions
  30. #include "..\svclib\ProcConVersion.h"
  31. #include "..\library\ProcConAPI.h" // Client API definitions
  32. #include "..\library\ProcConClnt.h" // Definitions shared with client side library
  33. //================================================================================//
  34. // Various macros, defines, typedefs, etc...
  35. #define ENTRY_COUNT(x) (sizeof(x) / sizeof(x[0]))
  36. typedef TCHAR FULL_JOB_NAME[JOB_NAME_LEN + 7 + 1];
  37. #define HANDLE_FF_64 ((HANDLE) 0xffffffffffffffff)
  38. #define MEM_REJECT_REPORT_LIMIT 10
  39. //================================================================================//
  40. // Various global utility function prototypes...
  41. LPTSTR PCNTErrorText ( PCULONG32 error, LPTSTR buf, PCULONG32 size );
  42. void PCLogMessage ( const PCULONG32 msgCode,
  43. const WORD msgType,
  44. WORD numStrings,
  45. const void *msgStrings,
  46. PCULONG32 enData = 0,
  47. void *msgData = NULL );
  48. void PCLogUnExError ( const __int64 pid, const TCHAR *what );
  49. void PCLogUnExError ( const TCHAR *who, const TCHAR *what );
  50. PCULONG32 PCLogNoMemory ( const TCHAR *string, const PCULONG32 len );
  51. void CDECL PCLogStdout ( const PCULONG32 msgCode,
  52. ... );
  53. void PCLogErrStdout ( const PCULONG32 msgCode,
  54. const PCULONG32 errCode,
  55. const VOID **args );
  56. BOOL PCTestOSVersion ( void );
  57. BOOL PCSetIsRunning ( const TCHAR *who, const TCHAR *dispName );
  58. BOOL PCTestIsRunning ( const TCHAR *who, const TCHAR *dispName = NULL );
  59. void PCInstallService( int argc, TCHAR **argv );
  60. void PCRemoveService ( int argc, TCHAR **argv );
  61. void WINAPI PCServiceMain ( PCULONG32 Argc, LPTSTR *Argv );
  62. void WINAPI PCServiceControl( PCULONG32 dwCtrlCode );
  63. BOOL PCReportStatus ( PCULONG32 dwCurrentState, PCULONG32 dwWin32ExitCode, PCULONG32 dwWaitHint );
  64. void PCStartService ( PCULONG32 Argc, LPTSTR *Argv );
  65. VOID PCStopService ( void );
  66. #ifdef _DEBUG
  67. void PCConsoleService( int argc, TCHAR **argv );
  68. BOOL WINAPI PCControlHandler( PCULONG32 dwCtrlType );
  69. #endif
  70. BOOL PCValidName ( const TCHAR *name, const PCULONG32 len, const BOOL nullOK = FALSE );
  71. BOOL PCValidMatchType( const TCHAR type );
  72. PCULONG32 PCGetParmValue ( TCHAR *loc, TCHAR **end );
  73. __int64 PCGetParmValue64( TCHAR *loc, TCHAR **end );
  74. int PCSignof64 (__int64 x );
  75. const TCHAR *PCiStrStr( const TCHAR *it, const TCHAR *here );
  76. void PCBuildBaseKey ( TCHAR *key );
  77. void PCBuildParmKey ( TCHAR *key );
  78. void PCBuildMsgKey ( TCHAR *key );
  79. void PCLoadStrings ( void );
  80. BOOL PCSetPrivilege ( TCHAR *privilege, BOOL enable );
  81. PCULONG32 PCDeleteKeyTree ( HKEY hKey, const TCHAR *keyName );
  82. PCULONG32 PCBuildNullSecAttr ( SECURITY_ATTRIBUTES &secAttr );
  83. PCULONG32 PCBuildAdminSecAttr( SECURITY_ATTRIBUTES &secAttr );
  84. void PCFreeSecAttr ( SECURITY_ATTRIBUTES &secAttr );
  85. BOOL PCGetAdminGroupName( TCHAR *Name, PCULONG32 *NameLen );
  86. PCULONG32 PCMapPriorityToNT ( PRIORITY prio );
  87. PRIORITY PCMapPriorityToPC ( PCULONG32 prio );
  88. PRIORITY PCMapPriorityForAPI( PRIORITY prio );
  89. __int64 PCLargeIntToInt64 ( LARGE_INTEGER &in );
  90. __int64 PCFileTimeToInt64 ( FILETIME &in );
  91. BOOL PCIsProcManaged ( MGMT_PARMS &def, JOB_NAME *job );
  92. BOOL PCIsJobManaged ( MGMT_PARMS &def );
  93. LPCTSTR PCIsSetToStr (PC_MGMT_FLAGS field, PCMgmtFlags flag);
  94. int PCTestSetUnset ( DWORD field1, DWORD flag1, DWORD field2, DWORD flag2 );
  95. void PCFormatAffinityLimit (TCHAR *Buffer, UINT BufferLength, const MGMT_PARMS &def);
  96. void PCFormatPriorityLimit (TCHAR *Buffer, UINT BufferLength, const MGMT_PARMS &def);
  97. void PCFormatWorkingSetLimit (TCHAR *Buffer, UINT BufferLength, const MGMT_PARMS &def);
  98. void PCFormatSchedClassLimit (TCHAR *Buffer, UINT BufferLength, const MGMT_PARMS &def);
  99. void PCFormatProcessCountLimit (TCHAR *Buffer, UINT BufferLength, const MGMT_PARMS &def);
  100. void PCFormatProcTimeLimit (TCHAR *Buffer, UINT BufferLength, const MGMT_PARMS &def);
  101. void PCFormatJobTimeLimit (TCHAR *Buffer, UINT BufferLength, const MGMT_PARMS &def);
  102. void PCFormatProcMemLimit (TCHAR *Buffer, UINT BufferLength, const MGMT_PARMS &def);
  103. void PCFormatJobMemLimit (TCHAR *Buffer, UINT BufferLength, const MGMT_PARMS &def);
  104. void PCFormatEndofJobAction (TCHAR *Buffer, UINT BufferLength, const MGMT_PARMS &def);
  105. void PCFormatOnOrOffLimit (TCHAR *Buffer, UINT BufferLength, const MGMT_PARMS &def, PCMgmtFlags flag);
  106. PCULONG32 _stdcall PCProcServer ( void *context );
  107. PCULONG32 _stdcall PCUserServer ( void *context );
  108. PCULONG32 _stdcall PCClientThread( void *context );
  109. static int _cdecl CompareProcName( const void *left, const void *right ) {
  110. return _tcsnicmp( (TCHAR *) left, (TCHAR *) right, PROC_NAME_LEN );
  111. }
  112. static int _cdecl CompareJobName( const void *left, const void *right ) {
  113. return _tcsnicmp( (TCHAR *) left, (TCHAR *) right, JOB_NAME_LEN );
  114. }
  115. //================================================================================//
  116. // Mediator related constants and typedefs...
  117. //
  118. const static TCHAR * const PC_MEDIATOR_BASE_NAME = TEXT("ProcConMD8.exe"); // Name of mediator executable
  119. const static TCHAR * const PC_MEDIATOR_EXCLUSION = TEXT("ProcConMD8OnlyMe"); // Name to ensure only one mediator is running
  120. const static TCHAR * const PC_MEDIATOR_EVENT = TEXT("ProcConMD8Evt"); // Name of event for service->mediator signalling
  121. const static TCHAR * const PC_MEDIATOR_FILEMAP = TEXT("ProcConMD8Jobs"); // Name of file map for shared job list
  122. // For data fields below, (S) means only the Servie updates, (M) means only the mediator updates.
  123. // Jobs (groups) are never removed from the system since they accumulate useful statistics.
  124. // There are no synchronization issues due to strict field ownership and because the list only grows.
  125. // Contents of shared table entry. Each group block contains a set of these group entries.
  126. typedef struct _PCMediateEntry {
  127. FULL_JOB_NAME groupName; // (S) Name of this group (job object)
  128. ULONG_PTR groupKey; // (S) Completion port key associated with this group
  129. PCULONG32 groupFlags; // (S) Flags to control closing
  130. HANDLE mediatorHandle; // (M) For mediator's use
  131. } PCMediateEntry;
  132. #define PCMEDIATE_CLOSE_ME 0x00000001
  133. // Contents of group block. The header contains the first block. Subsequent blocks are created
  134. // mapped, and chained to the first one as needed. The entire structure should fit in 4K.
  135. typedef struct _PCMediateBlock {
  136. HANDLE svcNextBlockHandle; // (S) Service's next block handle or NULL
  137. struct _PCMediateBlock *svcNextBlockAddress; // (S) Service's next block address or NULL
  138. HANDLE medNextBlockHandle; // (M) Mediator's next block handle or NULL
  139. struct _PCMediateBlock *medNextBlockAddress; // (M) Mediator's next block address or NULL
  140. PCULONG32 groupCount; // (S) Number of groups in group list below
  141. PCMediateEntry group[24]; // Group list for this block (sized to fit in 4K block)
  142. } PCMediateBlock;
  143. // Shared table header. This table is shared by both the Service and Mediator via a named file mapping.
  144. // The first block of group names is part of the header. Additional blocks are chained off the first block.
  145. typedef struct _PCMediateHdr {
  146. // Can be called by Service or Mediator...
  147. PCMediateBlock *NextBlock( PCMediateBlock *blk ) {
  148. return GetCurrentProcessId() == svcPID? blk->svcNextBlockAddress :
  149. blk->medNextBlockAddress;
  150. }
  151. // Can be called by Service only, NOT Mediator...
  152. PCMediateBlock *SvcAddBlock( PCMediateBlock *lastBlk, SECURITY_ATTRIBUTES &secAttr ) {
  153. lastBlk->svcNextBlockHandle = CreateFileMapping( HANDLE_FF_64, &secAttr, PAGE_READWRITE,
  154. 0, sizeof(PCMediateBlock), NULL );
  155. if ( !lastBlk->svcNextBlockHandle ) {
  156. PCLogUnExError( TEXT("PCMediateBlock"), TEXT("CreateBlock") );
  157. return NULL;
  158. }
  159. lastBlk->svcNextBlockAddress = (PCMediateBlock *) MapViewOfFile( lastBlk->svcNextBlockHandle,
  160. FILE_MAP_WRITE, 0, 0, 0 );
  161. if ( !lastBlk->svcNextBlockAddress ) {
  162. CloseHandle( lastBlk->svcNextBlockHandle );
  163. lastBlk->svcNextBlockHandle = NULL;
  164. PCLogUnExError( TEXT("PCMediateBlock"), TEXT("MapBlock") );
  165. }
  166. return lastBlk->svcNextBlockAddress;
  167. }
  168. // Can be called by Service only, NOT Mediator...
  169. void SvcAddEntry( const FULL_JOB_NAME &name, const ULONG_PTR key, SECURITY_ATTRIBUTES &secAttr ) {
  170. // First see if in list marked closed -- simply unmark if found...
  171. for ( PCMediateBlock *blk = &groupBlock; blk; blk = NextBlock( blk ) ) {
  172. for ( PCULONG32 i = 0; i < blk->groupCount; ++i ) {
  173. if ( !CompareJobName(blk->group[i].groupName, &name ) ) {
  174. blk->group[i].groupFlags &= ~PCMEDIATE_CLOSE_ME;
  175. SetEvent( svcEventHandle );
  176. return;
  177. }
  178. }
  179. }
  180. // Not found -- add to end of list...
  181. PCMediateBlock *newBlk;
  182. for ( blk = &groupBlock; blk; blk = newBlk ) {
  183. if ( blk->groupCount < ENTRY_COUNT( blk->group ) ) {
  184. memcpy( blk->group[blk->groupCount].groupName, &name, sizeof(name) );
  185. blk->group[blk->groupCount++].groupKey = key;
  186. SetEvent( svcEventHandle );
  187. break;
  188. }
  189. newBlk = NextBlock( blk );
  190. if ( !newBlk ) newBlk = SvcAddBlock( blk, secAttr );
  191. }
  192. }
  193. // Can be called by Service only, NOT Mediator...
  194. void SvcCloseEntry( FULL_JOB_NAME &name ) {
  195. for ( PCMediateBlock *blk = &groupBlock; blk; blk = NextBlock( blk ) ) {
  196. for ( PCULONG32 i = 0; i < blk->groupCount; ++i ) {
  197. if ( !CompareJobName(blk->group[i].groupName, &name ) ) {
  198. blk->group[i].groupFlags |= PCMEDIATE_CLOSE_ME;
  199. SetEvent( svcEventHandle );
  200. return;
  201. }
  202. }
  203. }
  204. }
  205. // Can be called by Service or Mediator (but only Service uses)...
  206. ULONG_PTR NewKey( const TCHAR *name ) {
  207. for ( PCMediateBlock *blk = &groupBlock; blk; blk = NextBlock( blk ) ) {
  208. for ( PCULONG32 i = 0; i < blk->groupCount; ++i ) {
  209. if ( !_tcscmp( name, blk->group[i].groupName ) )
  210. return blk->group[i].groupKey;
  211. }
  212. }
  213. return ++lastCompKey;
  214. }
  215. // Can be called by Service only, NOT Mediator...
  216. void SvcChainBlocks( void ) {
  217. for ( PCMediateBlock *blk = &groupBlock; blk; blk = NextBlock( blk ) ) {
  218. if ( blk->medNextBlockHandle ) {
  219. if ( !DuplicateHandle( medProcessInfo.hProcess,
  220. blk->medNextBlockHandle,
  221. GetCurrentProcess(),
  222. &blk->svcNextBlockHandle,
  223. NULL,
  224. FALSE,
  225. DUPLICATE_SAME_ACCESS ) )
  226. PCLogUnExError( TEXT("PCMediateBlock"), TEXT("DupBlkHandle") );
  227. else {
  228. blk->svcNextBlockAddress = (PCMediateBlock *) MapViewOfFile( blk->svcNextBlockHandle,
  229. FILE_MAP_WRITE, 0, 0, 0 );
  230. if ( !blk->svcNextBlockAddress ) {
  231. PCLogUnExError( TEXT("PCMediateBlock"), TEXT("MapJobBlk") );
  232. CloseHandle( blk->svcNextBlockHandle );
  233. blk->svcNextBlockHandle = NULL;
  234. return;
  235. }
  236. }
  237. }
  238. }
  239. }
  240. // Can be called by Mediator only, NOT Service...
  241. void MedChainBlocks( BOOL doAll ) {
  242. HANDLE hSvcProc = OpenProcess( PROCESS_DUP_HANDLE, FALSE, (DWORD) svcPID ); // OpenProcess uses DWORD PID, thus truncation in WIN64
  243. if ( !hSvcProc ) {
  244. PCLogUnExError( svcPID, TEXT("OpenSvcProcFromMed") );
  245. return;
  246. }
  247. for ( PCMediateBlock *blk = &groupBlock; blk; blk = NextBlock( blk ) ) {
  248. if ( blk->svcNextBlockHandle && (doAll || !blk->medNextBlockAddress) ) {
  249. if ( !DuplicateHandle( hSvcProc,
  250. blk->svcNextBlockHandle,
  251. GetCurrentProcess(),
  252. &blk->medNextBlockHandle,
  253. NULL,
  254. FALSE,
  255. DUPLICATE_SAME_ACCESS ) )
  256. PCLogUnExError( TEXT("PCMediateBlock"), TEXT("DupServiceBlkHandle") );
  257. else {
  258. blk->medNextBlockAddress = (PCMediateBlock *) MapViewOfFile( blk->medNextBlockHandle,
  259. FILE_MAP_WRITE, 0, 0, 0 );
  260. if ( !blk->medNextBlockAddress ) {
  261. PCLogUnExError( TEXT("PCMediateBlock"), TEXT("MapServiceJobBlk") );
  262. CloseHandle( blk->medNextBlockHandle );
  263. blk->medNextBlockHandle = NULL;
  264. break;
  265. }
  266. }
  267. }
  268. }
  269. CloseHandle( hSvcProc );
  270. }
  271. ULONG_PTR lastCompKey; // (S) Last completion key assigned to a group (or 0)
  272. HANDLE svcPortHandle; // (S) Service's Completion port handle
  273. HANDLE svcEventHandle; // (S) Service's event handle for service->mediator signalling
  274. ULONG_PTR svcPID; // (S) Service's PID
  275. PROCESS_INFORMATION medProcessInfo; // (S) initially, (M) replaces IDs. Mediator process information
  276. HANDLE medPortHandle; // (M) Mediator's copy of completion port handle
  277. VERSION_STRING medProductVersion; // (M) Meidator's product version
  278. VERSION_STRING medFileVersion; // (M) Meidator's file version
  279. VERSION_STRING medFileFlags; // (M) Meidator's file flags
  280. PCMediateBlock groupBlock; // First data block
  281. } PCMediateHdr;
  282. //================================================================================//
  283. // Enable forward class references...
  284. class CProcCon;
  285. class CProcConDB;
  286. class CProcConMgr;
  287. class CProcConUser;
  288. //================================================================================//
  289. // Miscellaneous
  290. const static TCHAR * const PROCCON_SVC_NAME = TEXT("ProcCon"); // Service name
  291. const static TCHAR * const PROCCON_SVC_EXCLUSION = TEXT("ProcConSvcOnlyMe"); // Name to ensure only one service is running
  292. extern TCHAR PROCCON_SVC_DISP_NAME[128]; // Service display name (loaded)
  293. extern TCHAR PROCCON_MEDIATOR_DISP_NAME[128]; // Mediator display name (loaded)
  294. extern TCHAR PROCCON_UNKNOWN_PROCESS[32]; // Name used for process already terminated (loaded)
  295. extern TCHAR PROCCON_SERVICE_DESCRIPTION[256]; // The service description value (loaded string)
  296. extern TCHAR PROCCON_DEFAULT_NAMERULE_DESC[NAME_DESCRIPTION_LEN + 1]; // Description field for default alias rule
  297. extern TCHAR PROCCON_FLAG_ON[32]; // Name used to indicate behavior is set
  298. extern TCHAR PROCCON_FLAG_OFF[32]; // Name used to indicate behavior is not set
  299. extern TCHAR PROCCON_SYSTEM_PROCESS[32]; // Name used for 'System' process (loaded)
  300. extern TCHAR PROCCON_SYSTEM_IDLE[64]; // Name used for 'System Idle Process' (loaded)
  301. extern TCHAR PROCCON_SERVICE_USAGE[256];
  302. typedef struct _PCContext {
  303. CProcCon *cPC;
  304. CProcConMgr *cMgr;
  305. HANDLE mgrDoneEvent;
  306. CProcConUser *cUser;
  307. HANDLE userDoneEvent;
  308. CProcConDB *cDB;
  309. HANDLE completionPort;
  310. HANDLE mediatorEvent;
  311. HANDLE mediatorTableHandle;
  312. PCMediateHdr *mediatorTable;
  313. } PCContext;
  314. typedef struct _ClientContext {
  315. _ClientContext( PCULONG32 client, CProcCon *pcPC, CProcConDB *pcDB, CProcConUser *pcUser,
  316. PCULONG32 inSize, PCULONG32 outSize ) :
  317. clientNo( client ), hPipe( NULL ),
  318. cPC( pcPC ), cDB( pcDB ), cUser( pcUser ),
  319. inBufChars( inSize ), outBufChars( outSize )
  320. {
  321. };
  322. ~_ClientContext( void ) {
  323. };
  324. PCULONG32 clientNo;
  325. HANDLE hPipe;
  326. PCULONG32 inBufChars;
  327. PCULONG32 outBufChars;
  328. CProcCon *cPC;
  329. CProcConDB *cDB;
  330. CProcConUser *cUser;
  331. } ClientContext;
  332. typedef struct _PCJobDef {
  333. JOB_NAME jobName; // Job name associated with this definition
  334. PROFILE_NAME profileName; // Profile name associated with this definition
  335. PC_MGMT_FLAGS mFlags; // Flags indicating which mgmt data to actually apply
  336. AFFINITY affinity; // processor affinity to apply if flagged
  337. PRIORITY priority; // NT priority to apply if flagged
  338. MEMORY_VALUE minWS; // NT minimum working set to apply if flagged
  339. MEMORY_VALUE maxWS; // NT maximum working set to apply if flagged
  340. SCHEDULING_CLASS schedClass; // NT scheduling class to apply if flagged
  341. PCULONG32 procCountLimit; // Number of processes in the job (jobs only).
  342. TIME_VALUE procTimeLimitCNS; // Per process time limit in 100ns (CNS) units or 0.
  343. TIME_VALUE jobTimeLimitCNS; // Per job time limit in 100ns (CNS) units or 0.
  344. MEMORY_VALUE procMemoryLimit; // Hard memory commit limit per process (jobs only).
  345. MEMORY_VALUE jobMemoryLimit; // Hard memory commit limit per job (jobs only).
  346. } PCJobDef;
  347. typedef struct _PCProcDef {
  348. PROC_NAME procName; // Process name associated with this definition -- must be first
  349. PROFILE_NAME profileName; // Profile name associated with this definition
  350. JOB_NAME memberOfJob; // Job name to associate process with if flagged
  351. PC_MGMT_FLAGS mFlags; // Flags indicating which mgmt data to actually apply
  352. AFFINITY affinity; // processor affinity to apply if flagged
  353. PRIORITY priority; // NT priority to apply if flagged
  354. MEMORY_VALUE minWS; // NT minimum working set to apply if flagged
  355. MEMORY_VALUE maxWS; // NT maximum working set to apply if flagged
  356. } PCProcDef;
  357. //================================================================================//
  358. // Registry related constants...
  359. //
  360. // Registry Server Apps Key (to let us appear as a server app in MMC)...
  361. const static TCHAR * const PROCCON_SERVER_APP_KEY =
  362. TEXT("SYSTEM\\CurrentControlSet\\Control\\Server Applications");
  363. // Registry Base Key (full key will include added subkey)...
  364. const static TCHAR * const PROCCON_REG_SERVICE_BASE = // Base key for all registry data
  365. TEXT("SYSTEM\\CurrentControlSet\\Services\\");
  366. const static TCHAR * const PROCCON_SERVICE_DESCRIPTION_NAME = TEXT("Description"); // Name or the Service Description value
  367. //
  368. // Registry Subkeys...
  369. const static TCHAR * const PROCCON_REG_EVENTLOG_SUBKEY = TEXT("EventLog\\System\\"); // Subkey for event log parameters
  370. const static TCHAR * const PROCCON_REG_PARMS_SUBKEY = TEXT("Parameters"); // Subkey for ProcCon parameters
  371. const static TCHAR * const PROCCON_REG_PROCRULES_SUBKEY = TEXT("ProcessRules"); // Subkey for our job rules
  372. const static TCHAR * const PROCCON_REG_JOBRULES_SUBKEY = TEXT("GroupRules"); // Subkey for our process rules
  373. // Access test subkeys...
  374. const static TCHAR * const PROCCON_REG_KILLPROC_ACCTEST = TEXT("AccessControl\\KillProcess"); // To allow process kill
  375. const static TCHAR * const PROCCON_REG_KILLJOB_ACCTEST = TEXT("AccessControl\\KillGroup"); // To allow job kill
  376. const static TCHAR * const PROCCON_REG_REALTIME_ACCTEST = TEXT("AccessControl\\SetRealTimePriority");// To allow real time priority
  377. const static TCHAR * const PROCCON_REG_POLLRATE_ACCTEST = TEXT("AccessControl\\SetPollSeconds"); // To allow changing poll rate
  378. const static TCHAR * const PROCCON_REG_RESTORE_ACCTEST = TEXT("AccessControl\\Restore"); // To allow database restore
  379. const static TCHAR * const accessKeyList[] = {
  380. PROCCON_REG_KILLPROC_ACCTEST, PROCCON_REG_KILLJOB_ACCTEST,
  381. PROCCON_REG_REALTIME_ACCTEST, PROCCON_REG_POLLRATE_ACCTEST,
  382. PROCCON_REG_RESTORE_ACCTEST };
  383. //
  384. // Registry Value names...
  385. const static TCHAR * const PROCCON_SERVER_APP_VALUE_NAME = TEXT("{7cfc9f00-0641-11d2-8014-00104b9a3106}");
  386. const static TCHAR * const PROCCON_DATA_DEFAULTRULES = TEXT("DfltMgmt"); // Name of our dflt mgmt rules
  387. const static TCHAR * const PROCCON_DATA_DESCRIPTION = TEXT("Description"); // Name of our description value
  388. const static TCHAR * const PROCCON_DATA_VARDATA = TEXT("VarData"); // Name of our variable detail data
  389. const static TCHAR * const PROCCON_DATA_MEMBEROF = TEXT("MemberOf"); // Name of our member of value
  390. const static TCHAR * const PROCCON_DATA_NAMERULES = TEXT("NameRules"); // Name of our name rules table
  391. const static TCHAR * const PROCCON_DATA_POLLDELAY = TEXT("ProcessPollSeconds"); // Name of our poll rate value
  392. const static TCHAR * const EVENT_MSG_FILE_NAME = TEXT("EventMessageFile"); // message files in EventLog key
  393. const static TCHAR * const EVENT_MSG_TYPES_SUPPORT = TEXT("TypesSupported"); // types supported in EventLog key
  394. //================================================================================//
  395. // Globals //
  396. //
  397. extern BOOL svcStop;
  398. extern BOOL notService;
  399. extern SERVICE_STATUS_HANDLE ssHandle; // service control handler
  400. extern SERVICE_STATUS ssStatus; // current service status
  401. extern PCULONG32 ssErrCode; // error code for status reporting
  402. //================================================================================//
  403. // ProcCon classes...
  404. //------------------------------------------------------------------------------------------------//
  405. // This class is a ProcCon instance -- its job is to start ProcCon's threads and wait.
  406. //------------------------------------------------------------------------------------------------//
  407. class CProcCon {
  408. public:
  409. // Public methods
  410. CProcCon( void );
  411. ~CProcCon( void );
  412. BOOL ReadyToRun ( void );
  413. void Run ( void );
  414. void HardStop ( PCULONG32 ExitCode = 0 );
  415. void Stop ( void );
  416. PCULONG32 StartMediator( void );
  417. PCULONG32 StopMediator ( void );
  418. BOOL GotShutdown ( void ) { return m_shutDown; }
  419. HANDLE GetShutEvent ( void ) { return m_shutEvent; }
  420. PCUINT32 GetPageSize ( void ) { return m_PageSize; }
  421. PCUINT32 GetProcCount ( void ) { return m_NumberOfProcessors; }
  422. CProcConMgr *GetPCMgr ( void ) { return m_context.cMgr; }
  423. void GetPCSystemInfo( PCSystemInfo *data, PCINT16 *itemLen, PCINT16 *itemCount );
  424. private:
  425. // Private methods
  426. void LaunchProcServer( void ); // Starts the Process Management thread
  427. void LaunchUserServer( void ); // Starts the User Communication thread
  428. // Private attributes
  429. enum PCThreads { PROC_SERVER = 0, USER_SERVER = 1 };
  430. BOOL m_shutDown;
  431. HANDLE m_shutEvent;
  432. HANDLE m_endEvent;
  433. HANDLE m_hThread[2];
  434. SECURITY_ATTRIBUTES m_secAttr; // admin level security attrs
  435. BOOL m_ready;
  436. PCContext m_context;
  437. PCUINT32 m_NumberOfProcessors;
  438. PCUINT32 m_PageSize;
  439. CVersion *m_versionInfo;
  440. };
  441. //------------------------------------------------------------------------------------------------//
  442. // This class is ProcCon's user management thread. It waits for connections and establishes
  443. // the connecting user's environment -- including a client thread.
  444. //------------------------------------------------------------------------------------------------//
  445. class CProcConUser {
  446. public:
  447. // Public methods
  448. CProcConUser( PCContext *ctxt );
  449. ~CProcConUser( void );
  450. BOOL ReadyToRun( void );
  451. PCULONG32 Run ( void );
  452. PCULONG32 GetTimeout( void ) { return m_clientTimeout; }
  453. PCULONG32 SetTimeout( PCULONG32 newTimeout );
  454. private:
  455. // Private methods
  456. // Private attributes
  457. const static TCHAR *PIPENAME;
  458. CProcCon &m_cPC;
  459. CProcConDB &m_cDB;
  460. PCULONG32 m_outBufChars;
  461. PCULONG32 m_inBufChars;
  462. PCULONG32 m_clientTimeout;
  463. HANDLE m_hConnEvent;
  464. OVERLAPPED m_olConn; // for overlapped I/O on pipe connect
  465. PCULONG32 m_clientCount; // counts clients
  466. SECURITY_ATTRIBUTES m_secAttr; // security attributes for our pipe
  467. };
  468. //------------------------------------------------------------------------------------------------//
  469. // This class is a ProcCon client thread. There may be any number of clients connected at once.
  470. //------------------------------------------------------------------------------------------------//
  471. class CProcConClient {
  472. public:
  473. // Public methods
  474. CProcConClient( ClientContext *ctxt );
  475. ~CProcConClient( void );
  476. BOOL ReadyToRun( void );
  477. PCULONG32 Run ( void );
  478. private:
  479. // Private methods
  480. BOOL ProcessRequest ( PCULONG32 inLen, PCULONG32 *outLen );
  481. void PrimeResponse ( PCResponse *rsp, PCRequest *req );
  482. BOOL ErrorResponse ( PCULONG32 errCode, PCResponse *rsp, PCULONG32 *outLen );
  483. BOOL DoNameRules ( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen );
  484. BOOL DoJobSummary ( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen );
  485. BOOL DoProcSummary ( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen );
  486. BOOL DoProcList ( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen );
  487. BOOL DoJobList ( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen );
  488. BOOL DoProcDetail ( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen );
  489. BOOL DoJobDetail ( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen );
  490. BOOL DoServerInfo ( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen );
  491. BOOL DoServerParms ( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen );
  492. BOOL DoControl ( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen );
  493. BOOL Impersonate ( PCRequest *req );
  494. void UnImpersonate ( PCRequest *req );
  495. void GenerateJobDetail( PCProcDetail *reqDetail );
  496. // Private attributes
  497. CProcCon &m_cPC;
  498. CProcConDB &m_cDB;
  499. CProcConUser &m_cUser;
  500. HANDLE m_hPipe;
  501. BOOL m_impersonating;
  502. PCULONG32 m_clientNo;
  503. PCULONG32 m_outBufChars;
  504. PCULONG32 m_inBufChars;
  505. TCHAR *m_outBuf;
  506. TCHAR *m_inBuf;
  507. HANDLE m_hReadEvent;
  508. HANDLE m_hWriteEvent;
  509. OVERLAPPED m_olRead;
  510. OVERLAPPED m_olWrite;
  511. };
  512. //------------------------------------------------------------------------------------------------//
  513. // This class is ProcCon's management thread. It periodically discovers what's running and
  514. // manages the workload according to management definitions.
  515. //------------------------------------------------------------------------------------------------//
  516. class CProcConMgr {
  517. struct _ManagedJob;
  518. public:
  519. // Public methods
  520. CProcConMgr( PCContext *ctxt );
  521. ~CProcConMgr( void );
  522. BOOL ReadyToRun ( void );
  523. PCULONG32 Run ( void );
  524. PCULONG32 ExportActiveProcList( PCProcListItem **list );
  525. PCULONG32 ExportActiveJobList ( PCJobListItem **list );
  526. AFFINITY GetSystemMask ( void ) { return m_systemMask; }
  527. INT32 KillJob ( JOB_NAME &name );
  528. INT32 KillProcess ( ULONG_PTR pid, TIME_VALUE created );
  529. void JobIsEmpty ( struct _ManagedJob *job );
  530. private:
  531. // These structures are temporary lists of procs and jobs needing management...
  532. typedef struct _ManagedProcItem {
  533. PROC_STATISTICS pStats; // process Id, etc.
  534. PCProcDef *pDef; // process definition pointer.
  535. IMAGE_NAME imageName; // NT 'image' (exe) name
  536. } ManagedProcItem;
  537. typedef struct _ManagedJobItem {
  538. PCJobDef *jDef; // process definition pointer.
  539. } ManagedJobItem;
  540. // These structures describe running processes and jobs...
  541. typedef struct _ManagedJob {
  542. _ManagedJob( TCHAR *name, PCMediateHdr *mData ) :
  543. next( NULL ), jobHandle( NULL ), lastEojAction( 789123 ),
  544. sequence( 0 ), lastError( 0 ), curJobTimeLimitCNS( 0 ), dataErrorFlags( 0 ),
  545. memRejectReportTime( 0 ),
  546. timeExceededReported( FALSE ), hasComplPort( FALSE ), JOProcListInfo( NULL ) {
  547. memset( jName, 0, sizeof(jName) );
  548. memset( &jobParms, 0, sizeof(jobParms) );
  549. memset( fullJobName, 0, sizeof(fullJobName) );
  550. memset( &JOBasicAndIoAcctInfo, 0, sizeof(JOBasicAndIoAcctInfo) );
  551. memset( &JOExtendedLimitInfo, 0, sizeof(JOExtendedLimitInfo) );
  552. _tcscpy( jName, name ); // Save user supplied name
  553. _tcscpy( fullJobName, TEXT("MSjob_") ); // Full name includes constant
  554. _tcscat( fullJobName, name ); // and user supplied name
  555. compKey = mData->NewKey( fullJobName ); // Assign our completion key
  556. }
  557. ~_ManagedJob( void ) {
  558. if ( jobHandle ) CloseHandle( jobHandle );
  559. }
  560. JOB_NAME jName; // job name -- key.
  561. struct _ManagedJob *next; // next ManagedJob entry or NULL
  562. PCULONG32 sequence; // to detect when job updates have been done
  563. HANDLE jobHandle; // Job object handle
  564. BOOL hasComplPort; // TRUE if job has port association
  565. BOOL timeExceededReported; // Time excceed msg issued (post on time limit)
  566. PCULONG32 memRejectReportTime; // Last Tick Count of memory reject reporting
  567. PC_MGMT_FLAGS dataErrorFlags; // Flags to suppress duplicate error reporting
  568. ULONG_PTR compKey; // Key for completion port to find job
  569. PCULONG32 lastEojAction; // last setting for EOJ time lime reporting
  570. PCJobDef jobParms; // ProcCon job management parameters
  571. PCULONG32 lastError; // Last NT error accessing JO
  572. FULL_JOB_NAME fullJobName; // Fully decorated job name
  573. TIME_VALUE curJobTimeLimitCNS; // Our currently assigned job time limit
  574. JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION JOBasicAndIoAcctInfo; // JO acct info from last Discover() call
  575. JOBOBJECT_EXTENDED_LIMIT_INFORMATION JOExtendedLimitInfo; // JO ext limits from last Discover() call
  576. JOBOBJECT_BASIC_PROCESS_ID_LIST *JOProcListInfo; // JO proc list from last Discover() call
  577. } ManagedJob;
  578. typedef struct _ManagedProc {
  579. _ManagedProc( TCHAR *name, PID_VALUE pid, __int64 &createtime )
  580. : next( NULL ), sequence( 0 ),
  581. isInJob( FALSE ), reportAdd( FALSE ),
  582. passSkipFlags( 0 ), isAppliedFlags( 0 ),
  583. actualPriority( 0 ), actualAffinity( 0 ),
  584. pMJob( NULL )
  585. {
  586. memset( &pStats, 0, sizeof(pStats) );
  587. memset( &imageName, 0, sizeof(imageName) );
  588. memset( &procParms, 0, sizeof(procParms) );
  589. memset( &originalParms, 0, sizeof(originalParms) );
  590. memset( &lastAlreadyInJobErr, 0, sizeof(lastAlreadyInJobErr) );
  591. _tcscpy( pName, name );
  592. _i64tot( pid, pidAsString, 10 );
  593. pStats.pid = pid;
  594. pStats.createTime = createtime;
  595. }
  596. PROC_STATISTICS pStats; // pid, etc.
  597. PROC_NAME pName; // process name as assigned by ProcCon
  598. struct _ManagedProc *next; // next ManagedProc entry or NULL
  599. PCULONG32 sequence; // to detect when referenced proc has gone away
  600. PRIORITY actualPriority; // actual base priority
  601. AFFINITY actualAffinity; // actual affinity mask
  602. IMAGE_NAME imageName; // NT 'image' (exe) name
  603. BOOL isInJob; // TRUE if proc is assigned to job below
  604. BOOL reportAdd; // TRUE if job reporter should report as 'added to'
  605. PC_MGMT_FLAGS passSkipFlags; // Flags to suppress attempted re-application of limit
  606. PC_MGMT_FLAGS isAppliedFlags; // Flags to indicate whether limit is applied or not
  607. TCHAR pidAsString[16]; // string version of pId for log messages
  608. ManagedJob *pMJob; // ptr to Managed Job when isInJob
  609. FULL_JOB_NAME lastAlreadyInJobErr; // Last rejected job name due to already in above job
  610. PCProcDef procParms; // proc management parameters (used to apply settings)
  611. PCProcDef originalParms; // original process parameters (used to un-apply settings)
  612. } ManagedProc;
  613. // These structures are raw (unfiltered) lists of currently running jobs and procs...
  614. typedef struct _RawJobList {
  615. PROC_NAME jName; // job name.
  616. } RawJobList;
  617. typedef struct _RawProcList {
  618. ULONG_PTR pId; // process Id (PID).
  619. FILETIME createTime; // process create time
  620. FILETIME exitTime; // process exit time (we don't use)
  621. FILETIME userTime; // process user time
  622. FILETIME kernelTime; // process kernel time
  623. PROC_NAME pName; // process name.
  624. struct _ManagedJob *pMJob; // ptr to ManagedJob if in job or NULL if not in job
  625. PRIORITY actualPriority; // actual base priority
  626. AFFINITY actualAffinity; // actual affinity mask
  627. IMAGE_NAME imageName; // NT 'image' (exe) name
  628. } RawProcList;
  629. // Private methods
  630. void Discover ( void ); // Discovers running processes/jobs
  631. void Manage ( void ); // Applies mgmt rules to processes/jobs
  632. BOOL NotTooSoon ( ManagedJob *job, PCULONG32 limit );
  633. static PCULONG32 __stdcall JobReporter( void *inPtr );
  634. static int _cdecl CompareRawProcList( const void *left, const void *right ) {
  635. return PCSignof64(((RawProcList *) left )->pId - ((RawProcList *) right)->pId);
  636. }
  637. static int _cdecl CompareRawJobList( const void *left, const void *right ) {
  638. return CompareJobName( left, right ); // job name is first in raw structure
  639. }
  640. void DeleteOrphanProcEntries( void );
  641. void DeleteOrphanJobEntries ( void );
  642. ManagedProc *FindProcEntry ( PID_VALUE pid, __int64 &createTime );
  643. ManagedJob *FindJobEntry ( TCHAR *job, ManagedJob **plast = NULL );
  644. void UpdateProcEntry ( ManagedProc &proc, PCProcDef &item, BOOL newProc );
  645. void UpdateJobEntry ( ManagedJob &job, PCJobDef *item, BOOL newProc = FALSE );
  646. BOOL GetProcListForJob( ManagedJob &job );
  647. void UpdateJobObjInfo ( ManagedJob &job );
  648. BOOL ApplyJobMgmt ( ManagedJob &job );
  649. BOOL ApplyProcMgmt ( ManagedProc &proc, HANDLE hProc );
  650. HANDLE GetComplPort ( void ) { return m_assocPort.CompletionPort; }
  651. ManagedJob *GetJobAnchor ( void ) { return m_jobAnchor; }
  652. ManagedProc *GetProcAnchor ( void ) { return m_procAnchor; }
  653. PCULONG32 GetRawProcCount( void ) { return m_rawProcCount; }
  654. RawProcList &GetRawProcEntry( PCULONG32 i ) { return m_rawProcList[i]; }
  655. CRITICAL_SECTION *GetListCSPtr ( void ) { return &m_mgCSMgrLists; }
  656. // Private attributes
  657. private:
  658. CProcCon &m_cPC;
  659. CProcConDB &m_cDB;
  660. JOBOBJECT_ASSOCIATE_COMPLETION_PORT m_assocPort; // associated completion port structure
  661. HANDLE m_reportThread; // thread that monitors completion port
  662. ULONG_PTR m_systemMask; // NT system affinity mask: shows processors present
  663. PCULONG32 m_sequencer; // To detect when processes are no longer around
  664. CRITICAL_SECTION m_mgCSMgrLists; // to protect various process and job lists below
  665. SECURITY_ATTRIBUTES m_secAttr; // security attributes for our job objects
  666. RawProcList *m_rawProcList; // proc information from last process discovery or NULL
  667. PCULONG32 m_rawProcCount; // number of entries in raw rpoc list
  668. PCULONG32 m_jobManagedCount; // count of managed job entries in m_jobAnchor
  669. ManagedJob *m_jobAnchor; // linked list of currently managed jobs
  670. PCULONG32 m_procManagedCount; // count of managed proc entries in m_procAnchor;
  671. ManagedProc *m_procAnchor; // linked list of currently managed procs
  672. HANDLE m_mediatorEvent; // mediator signalling event
  673. PCMediateHdr *m_mediatorTable; // data shared with mediator
  674. };
  675. //------------------------------------------------------------------------------------------------//
  676. // This class is ProcCon's database control and owns all external data.
  677. // This class does not include a thread -- all database calls are synchronous from other threads.
  678. //------------------------------------------------------------------------------------------------//
  679. class CProcConDB {
  680. public:
  681. const enum LoadFlags { LOADFLAG_NAME_RULES = 0x00000001,
  682. LOADFLAG_PROC_RULES = 0x00000002,
  683. LOADFLAG_JOB_RULES = 0x00000004,
  684. LOADFLAG_ALL_RULES = 0x00000007,
  685. };
  686. // Public methods
  687. CProcConDB( PCUINT32 size );
  688. ~CProcConDB( void );
  689. BOOL ReadyToRun ( void );
  690. PCULONG32 LoadRules ( PCULONG32 which );
  691. HANDLE GetDbEvent ( void ) { return m_dbEvent; }
  692. PCULONG32 GetPollDelay ( void ) { return m_pollDelay; }
  693. PCULONG32 GetPollDelaySeconds( void ) { return m_pollDelay / 1000; }
  694. PCULONG32 SetPollDelaySeconds( PCULONG32 newDelay );
  695. void SetPCMgr ( CProcConMgr *pMgr ) { m_cMgr = pMgr; }
  696. void AssignProcName ( const TCHAR *path, PROC_NAME *name, IMAGE_NAME *iName );
  697. INT32 TestAccess ( const TCHAR *key );
  698. PCULONG32 GetJobMgmtDefs ( PCJobDef **pList, JOB_NAME *name = NULL );
  699. PCULONG32 GetProcMgmtDefs( PCProcDef **pList );
  700. BOOL GetNameRules ( const PCINT32 first, PCNameRule *pRules,
  701. const PCINT32 maxCount, PCINT16 *itemLen, PCINT16 *itemCount, PCINT32 *updCtr );
  702. PCULONG32 AddNameRule ( const PCNameRule *pRule, const BYTE version, const PCULONG32 index, const PCINT32 updCtr );
  703. PCULONG32 ReplNameRule ( const PCNameRule *pRule, const BYTE version, const PCULONG32 index, const PCINT32 updCtr );
  704. PCULONG32 DelNameRule ( const PCULONG32 index, const PCINT32 updCtr );
  705. PCULONG32 SwapNameRule ( const PCULONG32 index, const PCINT32 updCtr );
  706. BOOL GetJobSummary ( const PCJobSummary *pStart, PCUINT32 listFlags,
  707. PCJobSummary *pSummary, const PCINT32 maxCount, PCINT16 *itemLen, PCINT16 *itemCount );
  708. BOOL GetProcSummary( const PCProcSummary *pStart, PCUINT32 listFlags,
  709. PCProcSummary *pSummary, const PCINT32 maxCount, PCINT16 *itemLen, PCINT16 *itemCount );
  710. BOOL GetJobList ( const PCJobListItem *pStart, const PCUINT32 listFlags, PCJobListItem *pList,
  711. const PCINT32 maxCount, PCINT16 *itemLen, PCINT16 *itemCount );
  712. BOOL GetProcList ( const PCProcListItem *pStart, const PCUINT32 listFlags, PCProcListItem *pList,
  713. const PCINT32 maxCount, PCINT16 *itemLen, PCINT16 *itemCount );
  714. PCULONG32 GetProcDetail ( const PCProcDetail *pIn, PCProcDetail *pDetail, const BYTE version, PCINT32 *updCtr );
  715. PCULONG32 AddProcDetail ( const PCProcDetail *pDetail, const BYTE version );
  716. PCULONG32 ReplProcDetail( const PCProcDetail *pDetail, const BYTE version, const PCINT32 updCtr );
  717. PCULONG32 DelProcDetail ( const PCProcSummary *pSummary, const BYTE version );
  718. void LogProcSummaryChange( const PCProcSummary *pSummary, const BYTE version, const PCProcSummary *pOldSummary );
  719. PCULONG32 GetJobDetail ( const PCJobDetail *pIn, PCJobDetail *pDetail, const BYTE version, PCINT32 *updCtr );
  720. PCULONG32 AddJobDetail ( const PCJobDetail *pDetail, const BYTE version );
  721. PCULONG32 ReplJobDetail ( const PCJobDetail *pDetail, const BYTE version, const PCINT32 updCtr );
  722. PCULONG32 DelJobDetail ( const PCJobSummary *pSummary, const BYTE version );
  723. void LogJobSummaryChange( const PCJobSummary *pSummary, const BYTE version, const PCJobSummary *pOldSummary );
  724. PCULONG32 DeleteAllNameRules( void );
  725. PCULONG32 DeleteAllProcDefs ( void );
  726. PCULONG32 DeleteAllJobDefs ( void );
  727. private:
  728. // Private methods
  729. BOOL OpenProcKey ( void );
  730. BOOL OpenParmKey ( void );
  731. BOOL OpenJobKey ( void );
  732. PCULONG32 RegError ( const TCHAR *op, const TCHAR *what1 = NULL, const TCHAR *what2 = NULL );
  733. PCULONG32 RegDataError ( const TCHAR *what );
  734. PCULONG32 GetPCParm ( const TCHAR *name, PCULONG32 *data );
  735. PCULONG32 SetPCParm ( const TCHAR *name, PCULONG32 data );
  736. PCULONG32 CreateKeyAtHKLM ( const TCHAR *key, HKEY *hKey );
  737. BOOL BuildIntNameRules ( void );
  738. void BuildIntNameRule ( PCULONG32 index );
  739. BOOL NameMatch ( const BOOL compare, const BOOL hasWildcard, const TCHAR *str,
  740. const TCHAR **arg, const PCULONG32 argCt = 1, PCULONG32 *mIdx = NULL );
  741. void NameSet ( PROC_NAME *name, const BOOL isPattern, const TCHAR *pattern,
  742. const TCHAR *patArgP, const TCHAR *patArgN = NULL );
  743. int ExtStartLoc ( const TCHAR *name );
  744. void SetJobDefEntry ( PCJobDef *list, PCJobSummary &m_jobSummary );
  745. TCHAR *BuildProcKey ( TCHAR *key );
  746. TCHAR *BuildJobKey ( TCHAR *key );
  747. PCULONG32 LoadNameRules ( PCULONG32 *count );
  748. PCULONG32 StoreNameRules ( void );
  749. PCULONG32 NameRulesUpdated ( void );
  750. PCULONG32 LoadProcSummary ( void );
  751. PCULONG32 LoadJobSummary ( void );
  752. PCULONG32 LoadProcSummaryItem( const HKEY &hKeyTemp, PCProcSummary &summary );
  753. PCULONG32 LoadJobSummaryItem ( const HKEY &hKeyTemp, PCJobSummary &summary );
  754. PCULONG32 LoadMgmtRules ( const HKEY &hKey, MGMT_PARMS &parms );
  755. PCULONG32 LoadVariableData ( const HKEY &hKey, PCINT16 *vLength, TCHAR *vData );
  756. PCULONG32 StoreJobDetail ( const PCJobDetail &detail );
  757. PCULONG32 StoreProcDetail ( const PCProcDetail &detail );
  758. PCULONG32 StoreJobValues ( const HKEY &hKey, const PCJobDetail &detail );
  759. PCULONG32 StoreProcValues ( const HKEY &hKey, const PCProcDetail &detail );
  760. PCULONG32 StoreMgmtRules ( const HKEY &hKey, const MGMT_PARMS &parms );
  761. PCULONG32 StoreVariableData ( const HKEY &hKey, const PCINT16 vLength, const TCHAR *vData );
  762. static inline int _cdecl CompareProcSummary( const void *left, const void *right ) {
  763. int comp = _tcsnicmp( ((PCProcSummary *) left )->procName,
  764. ((PCProcSummary *) right)->procName, PROC_NAME_LEN );
  765. if ( !comp )
  766. return _tcsnicmp( ((PCProcSummary *) left )->mgmtParms.profileName,
  767. ((PCProcSummary *) right)->mgmtParms.profileName, PROFILE_NAME_LEN );
  768. else return comp;
  769. }
  770. static inline int _cdecl CompareJobSummary( const void *left, const void *right ) {
  771. int comp = _tcsnicmp( ((PCJobSummary *) left )->jobName,
  772. ((PCJobSummary *) right)->jobName, JOB_NAME_LEN );
  773. if ( !comp )
  774. return _tcsnicmp( ((PCJobSummary *) left )->mgmtParms.profileName,
  775. ((PCJobSummary *) right)->mgmtParms.profileName, PROFILE_NAME_LEN );
  776. else return comp;
  777. }
  778. static inline int _cdecl CompareProcListItemProcName( const void *left, const void *right ) {
  779. return _tcsnicmp( ((PCProcListItem *) left )->procName,
  780. ((PCProcListItem *) right)->procName, PROC_NAME_LEN );
  781. }
  782. static inline int _cdecl CompareProcListItemPidOptional( const void *left, const void *right ) {
  783. int cmp = CompareProcListItemProcName( left, right );
  784. if ( !cmp && ((PCProcListItem *) left )->procStats.pid ) {
  785. cmp = PCSignof64(((PCProcListItem *) left )->procStats.pid - ((PCProcListItem *) right )->procStats.pid);
  786. }
  787. return cmp;
  788. }
  789. static inline int _cdecl CompareProcListItem( const void *left, const void *right ) {
  790. int cmp = CompareProcListItemProcName( left, right );
  791. if ( !cmp ) cmp = PCSignof64(((PCProcListItem *) left )->procStats.pid - ((PCProcListItem *) right )->procStats.pid);
  792. return cmp;
  793. }
  794. static inline int _cdecl CompareProcListItemJobName( const void *left, const void *right ) {
  795. return _tcsnicmp( ((PCProcListItem *) left )->jobName,
  796. ((PCProcListItem *) right)->jobName, JOB_NAME_LEN );
  797. }
  798. static inline int _cdecl CompareJobListItem( const void *left, const void *right ) {
  799. return _tcsnicmp( ((PCJobListItem *) left )->jobName,
  800. ((PCJobListItem *) right)->jobName, JOB_NAME_LEN );
  801. }
  802. static inline int _cdecl CompareProcDef( const void *left, const void *right ) {
  803. return _tcsnicmp( ((PCProcDef *) left )->procName,
  804. ((PCProcDef *) right)->procName, PROC_NAME_LEN );
  805. }
  806. static inline int _cdecl CompareJobDef( const void *left, const void *right ) {
  807. return _tcsnicmp( ((PCJobDef *) left )->jobName,
  808. ((PCJobDef *) right)->jobName, JOB_NAME_LEN );
  809. }
  810. BOOL NameHasPattern( const TCHAR *name ) {
  811. for ( const TCHAR *pStart = _tcschr( name, NAME_IS_PGM[0] );
  812. pStart;
  813. pStart = _tcschr( pStart + 1, NAME_IS_PGM[0] ) ) {
  814. if ( _tcschr( PATTERN_CHARS, _totupper( *(pStart + 1) ) ) && *(pStart + 2) == NAME_IS_PGM[2] )
  815. return TRUE;
  816. }
  817. return FALSE;
  818. }
  819. BOOL JobBelongsInList( const PCJobListItem &li,
  820. const PCJobListItem *pStart,
  821. const PCUINT32 listFlags )
  822. {
  823. PCINT32 cmp = CompareJobListItem( pStart, li.jobName );
  824. BOOL inRange;
  825. if ( listFlags & PC_LIST_MATCH_ONLY ) inRange = cmp == 0;
  826. else if ( listFlags & PC_LIST_STARTING_WITH ) inRange = cmp <= 0;
  827. else inRange = cmp < 0;
  828. return *li.jobName && inRange &&
  829. (!(listFlags & PC_LIST_ONLY_RUNNING) || li.lFlags & PCLFLAG_IS_RUNNING);
  830. }
  831. BOOL ProcBelongsInList( const PCProcListItem &li,
  832. const PCProcListItem *pStart,
  833. const PCUINT32 listFlags )
  834. {
  835. if ( listFlags & PC_LIST_MEMBERS_OF && CompareProcListItemJobName( pStart, &li ) )
  836. return FALSE;
  837. BOOL inRange;
  838. int cmp = (listFlags & PC_LIST_MATCH_ONLY)?
  839. CompareProcListItemPidOptional( pStart, &li ) : CompareProcListItem( pStart, &li );
  840. if ( listFlags & PC_LIST_MATCH_ONLY ) inRange = cmp == 0;
  841. else if ( listFlags & PC_LIST_STARTING_WITH ) inRange = cmp <= 0;
  842. else inRange = cmp < 0;
  843. return *li.procName && inRange &&
  844. (!(listFlags & PC_LIST_ONLY_RUNNING) || li.lFlags & PCLFLAG_IS_RUNNING);
  845. }
  846. // Private attributes
  847. const enum MatchFlags { MFLAG_HAS_WILDCARD = 0x00000001,
  848. MFLAG_HAS_NAME_PATTERN = 0x00000002,
  849. MFLAG_HAS_EXTENSION = 0x00000004,
  850. };
  851. typedef struct _PCNameRuleInt {
  852. MATCH_TYPE mType; // value is MATCH_PGM, MATCH_DIR, or MATCH_ANY.
  853. PCULONG32 mFlags; // flags to indicate wildcards, derived name, etc.
  854. TCHAR mString[MAX_PATH]; // match string may include * and ? wildcard chars
  855. PROC_NAME mName; // process name to use when match succeeds.
  856. NAME_DESCRIPTION mDesc; // user's description of rule
  857. } PCNameRuleInt;
  858. const static TCHAR PCDB_PREFIX_FLAGS;
  859. const static TCHAR PCDB_PREFIX_AFFINITY;
  860. const static TCHAR PCDB_PREFIX_PRIORITY;
  861. const static TCHAR PCDB_PREFIX_MINWS;
  862. const static TCHAR PCDB_PREFIX_MAXWS;
  863. const static TCHAR PCDB_PREFIX_SCHEDCLASS;
  864. const static TCHAR PCDB_PREFIX_PROCTIME;
  865. const static TCHAR PCDB_PREFIX_JOBTIME;
  866. const static TCHAR PCDB_PREFIX_ACTIVEPROCS;
  867. const static TCHAR PCDB_PREFIX_PROCMEMORY;
  868. const static TCHAR PCDB_PREFIX_JOBMEMORY;
  869. const static TCHAR BEG_BRACKET; // leading char in rules stored in DB
  870. const static TCHAR END_BRACKET; // trailing char in rules stored in DB
  871. const static TCHAR FIELD_SEP; // separates fields in rules/values stored in DB
  872. const static TCHAR STRING_DELIM; // delimits text strings stored in DB
  873. const static TCHAR RULE_MATCHONE; // match any one characters
  874. const static TCHAR RULE_MATCHANY; // match any string of characters
  875. const static TCHAR NAME_IS_PGM[]; // variable name rule text == pgm name
  876. const static TCHAR NAME_IS_DIR[]; // variable name rule text == matched dir name
  877. const static TCHAR HIDE_PROC_PATTERN[]; // pattern meaning hide this proc from view/processing
  878. const static TCHAR PATTERN_CHARS[]; // the pattern characters allowed in process names
  879. static PCNameRule DEFAULT_NAME_RULE; // default rule -- always last in name rules tbl
  880. CProcConMgr *m_cMgr; // ProcCon Manager class for live data access
  881. CRITICAL_SECTION m_dbCSNameRule; // to protect name data access
  882. CRITICAL_SECTION m_dbCSProcRule; // to protect process data access
  883. CRITICAL_SECTION m_dbCSJobRule; // to protect job data access
  884. PCULONG32 m_lastRegError; // last error when accessing registry or ERROR_SUCCESS
  885. PCULONG32 m_pollDelay; // process space poll delay in millseconds
  886. const BOOL m_LogRuleEdits; // report each rule edit with an Event Log entry
  887. HKEY m_parmRegKey; // open key for registry parameter access or NULL
  888. HKEY m_procRegKey; // open key for registry proc rules access or NULL
  889. HKEY m_jobRegKey; // open key for registry job rules access or NULL
  890. PCNameRule *m_fmtNameRules; // name rules formatted into API structures or NULL
  891. PCNameRuleInt *m_intNameRules; // name rules formatted into our internal structure or NULL
  892. HANDLE m_dbEvent; // to signal interested parties when DB changes
  893. HANDLE m_parmEvent; // for NT to signal us on external DB change (should not happen)
  894. PCProcSummary *m_procSummary; // ptr to array of process rule summaries from DB or NULL
  895. PCJobSummary *m_jobSummary; // ptr to array of job rule summaries from DB or NULL
  896. SECURITY_ATTRIBUTES m_secAttr; // security attributes for our registry keys
  897. PCULONG32 m_numNameRules; // number of rules in m_raw/fmtNameRules arrays
  898. PCULONG32 m_numProcRules; // number of rules in m_procRules array
  899. PCULONG32 m_numJobRules; // number of rules in m_jobRules array
  900. PCINT32 m_updCtrName; // update counter for name rules
  901. PCINT32 m_updCtrProc; // update counter for proc rules
  902. PCINT32 m_updCtrJob; // update counter for job rules
  903. PCUINT32 m_pageSize; // page size for rounding memory values
  904. TCHAR m_curProfile[32]; // current profile (invalid implies DfltMgmt profile)
  905. };
  906. #ifdef _DEBUG
  907. inline void _cdecl DbgTrace(LPCSTR lpszFormat, ...)
  908. {
  909. va_list args;
  910. va_start(args, lpszFormat);
  911. int nBuf;
  912. char szBuffer[512];
  913. nBuf = _vsnprintf(szBuffer, sizeof(szBuffer), lpszFormat, args);
  914. assert(nBuf < sizeof(szBuffer)); //Output truncated as it was > sizeof(szBuffer)
  915. OutputDebugStringA(szBuffer);
  916. va_end(args);
  917. }
  918. #else
  919. inline void _cdecl DbgTrace(LPCSTR lpszFormat, ...) {}
  920. #endif
  921. // End of ProcConSvc.h
  922. //============================================================================J McDonald fecit====//