/*======================================================================================// | // |Copyright (c) 1998, 1999 Sequent Computer Systems, Incorporated // | // |Description: // | // |---------------------------------------------------------------------------------------// | This file is the ProcCon header file used only by the ProcCon NT Service // |---------------------------------------------------------------------------------------// | // |Created: // | // | Jarl McDonald 07-98 // | // |Revision History: // | // |=======================================================================================*/ #include #include #include #include #include #include #include #include #include #include #include "resource.h" #include "ProcConSvcMsg.h" // Message definitions #include "..\svclib\ProcConVersion.h" #include "..\library\ProcConAPI.h" // Client API definitions #include "..\library\ProcConClnt.h" // Definitions shared with client side library //================================================================================// // Various macros, defines, typedefs, etc... #define ENTRY_COUNT(x) (sizeof(x) / sizeof(x[0])) typedef TCHAR FULL_JOB_NAME[JOB_NAME_LEN + 7 + 1]; #define HANDLE_FF_64 ((HANDLE) 0xffffffffffffffff) #define MEM_REJECT_REPORT_LIMIT 10 //================================================================================// // Various global utility function prototypes... LPTSTR PCNTErrorText ( PCULONG32 error, LPTSTR buf, PCULONG32 size ); void PCLogMessage ( const PCULONG32 msgCode, const WORD msgType, WORD numStrings, const void *msgStrings, PCULONG32 enData = 0, void *msgData = NULL ); void PCLogUnExError ( const __int64 pid, const TCHAR *what ); void PCLogUnExError ( const TCHAR *who, const TCHAR *what ); PCULONG32 PCLogNoMemory ( const TCHAR *string, const PCULONG32 len ); void CDECL PCLogStdout ( const PCULONG32 msgCode, ... ); void PCLogErrStdout ( const PCULONG32 msgCode, const PCULONG32 errCode, const VOID **args ); BOOL PCTestOSVersion ( void ); BOOL PCSetIsRunning ( const TCHAR *who, const TCHAR *dispName ); BOOL PCTestIsRunning ( const TCHAR *who, const TCHAR *dispName = NULL ); void PCInstallService( int argc, TCHAR **argv ); void PCRemoveService ( int argc, TCHAR **argv ); void WINAPI PCServiceMain ( PCULONG32 Argc, LPTSTR *Argv ); void WINAPI PCServiceControl( PCULONG32 dwCtrlCode ); BOOL PCReportStatus ( PCULONG32 dwCurrentState, PCULONG32 dwWin32ExitCode, PCULONG32 dwWaitHint ); void PCStartService ( PCULONG32 Argc, LPTSTR *Argv ); VOID PCStopService ( void ); #ifdef _DEBUG void PCConsoleService( int argc, TCHAR **argv ); BOOL WINAPI PCControlHandler( PCULONG32 dwCtrlType ); #endif BOOL PCValidName ( const TCHAR *name, const PCULONG32 len, const BOOL nullOK = FALSE ); BOOL PCValidMatchType( const TCHAR type ); PCULONG32 PCGetParmValue ( TCHAR *loc, TCHAR **end ); __int64 PCGetParmValue64( TCHAR *loc, TCHAR **end ); int PCSignof64 (__int64 x ); const TCHAR *PCiStrStr( const TCHAR *it, const TCHAR *here ); void PCBuildBaseKey ( TCHAR *key ); void PCBuildParmKey ( TCHAR *key ); void PCBuildMsgKey ( TCHAR *key ); void PCLoadStrings ( void ); BOOL PCSetPrivilege ( TCHAR *privilege, BOOL enable ); PCULONG32 PCDeleteKeyTree ( HKEY hKey, const TCHAR *keyName ); PCULONG32 PCBuildNullSecAttr ( SECURITY_ATTRIBUTES &secAttr ); PCULONG32 PCBuildAdminSecAttr( SECURITY_ATTRIBUTES &secAttr ); void PCFreeSecAttr ( SECURITY_ATTRIBUTES &secAttr ); BOOL PCGetAdminGroupName( TCHAR *Name, PCULONG32 *NameLen ); PCULONG32 PCMapPriorityToNT ( PRIORITY prio ); PRIORITY PCMapPriorityToPC ( PCULONG32 prio ); PRIORITY PCMapPriorityForAPI( PRIORITY prio ); __int64 PCLargeIntToInt64 ( LARGE_INTEGER &in ); __int64 PCFileTimeToInt64 ( FILETIME &in ); BOOL PCIsProcManaged ( MGMT_PARMS &def, JOB_NAME *job ); BOOL PCIsJobManaged ( MGMT_PARMS &def ); LPCTSTR PCIsSetToStr (PC_MGMT_FLAGS field, PCMgmtFlags flag); int PCTestSetUnset ( DWORD field1, DWORD flag1, DWORD field2, DWORD flag2 ); void PCFormatAffinityLimit (TCHAR *Buffer, UINT BufferLength, const MGMT_PARMS &def); void PCFormatPriorityLimit (TCHAR *Buffer, UINT BufferLength, const MGMT_PARMS &def); void PCFormatWorkingSetLimit (TCHAR *Buffer, UINT BufferLength, const MGMT_PARMS &def); void PCFormatSchedClassLimit (TCHAR *Buffer, UINT BufferLength, const MGMT_PARMS &def); void PCFormatProcessCountLimit (TCHAR *Buffer, UINT BufferLength, const MGMT_PARMS &def); void PCFormatProcTimeLimit (TCHAR *Buffer, UINT BufferLength, const MGMT_PARMS &def); void PCFormatJobTimeLimit (TCHAR *Buffer, UINT BufferLength, const MGMT_PARMS &def); void PCFormatProcMemLimit (TCHAR *Buffer, UINT BufferLength, const MGMT_PARMS &def); void PCFormatJobMemLimit (TCHAR *Buffer, UINT BufferLength, const MGMT_PARMS &def); void PCFormatEndofJobAction (TCHAR *Buffer, UINT BufferLength, const MGMT_PARMS &def); void PCFormatOnOrOffLimit (TCHAR *Buffer, UINT BufferLength, const MGMT_PARMS &def, PCMgmtFlags flag); PCULONG32 _stdcall PCProcServer ( void *context ); PCULONG32 _stdcall PCUserServer ( void *context ); PCULONG32 _stdcall PCClientThread( void *context ); static int _cdecl CompareProcName( const void *left, const void *right ) { return _tcsnicmp( (TCHAR *) left, (TCHAR *) right, PROC_NAME_LEN ); } static int _cdecl CompareJobName( const void *left, const void *right ) { return _tcsnicmp( (TCHAR *) left, (TCHAR *) right, JOB_NAME_LEN ); } //================================================================================// // Mediator related constants and typedefs... // const static TCHAR * const PC_MEDIATOR_BASE_NAME = TEXT("ProcConMD8.exe"); // Name of mediator executable const static TCHAR * const PC_MEDIATOR_EXCLUSION = TEXT("ProcConMD8OnlyMe"); // Name to ensure only one mediator is running const static TCHAR * const PC_MEDIATOR_EVENT = TEXT("ProcConMD8Evt"); // Name of event for service->mediator signalling const static TCHAR * const PC_MEDIATOR_FILEMAP = TEXT("ProcConMD8Jobs"); // Name of file map for shared job list // For data fields below, (S) means only the Servie updates, (M) means only the mediator updates. // Jobs (groups) are never removed from the system since they accumulate useful statistics. // There are no synchronization issues due to strict field ownership and because the list only grows. // Contents of shared table entry. Each group block contains a set of these group entries. typedef struct _PCMediateEntry { FULL_JOB_NAME groupName; // (S) Name of this group (job object) ULONG_PTR groupKey; // (S) Completion port key associated with this group PCULONG32 groupFlags; // (S) Flags to control closing HANDLE mediatorHandle; // (M) For mediator's use } PCMediateEntry; #define PCMEDIATE_CLOSE_ME 0x00000001 // Contents of group block. The header contains the first block. Subsequent blocks are created // mapped, and chained to the first one as needed. The entire structure should fit in 4K. typedef struct _PCMediateBlock { HANDLE svcNextBlockHandle; // (S) Service's next block handle or NULL struct _PCMediateBlock *svcNextBlockAddress; // (S) Service's next block address or NULL HANDLE medNextBlockHandle; // (M) Mediator's next block handle or NULL struct _PCMediateBlock *medNextBlockAddress; // (M) Mediator's next block address or NULL PCULONG32 groupCount; // (S) Number of groups in group list below PCMediateEntry group[24]; // Group list for this block (sized to fit in 4K block) } PCMediateBlock; // Shared table header. This table is shared by both the Service and Mediator via a named file mapping. // The first block of group names is part of the header. Additional blocks are chained off the first block. typedef struct _PCMediateHdr { // Can be called by Service or Mediator... PCMediateBlock *NextBlock( PCMediateBlock *blk ) { return GetCurrentProcessId() == svcPID? blk->svcNextBlockAddress : blk->medNextBlockAddress; } // Can be called by Service only, NOT Mediator... PCMediateBlock *SvcAddBlock( PCMediateBlock *lastBlk, SECURITY_ATTRIBUTES &secAttr ) { lastBlk->svcNextBlockHandle = CreateFileMapping( HANDLE_FF_64, &secAttr, PAGE_READWRITE, 0, sizeof(PCMediateBlock), NULL ); if ( !lastBlk->svcNextBlockHandle ) { PCLogUnExError( TEXT("PCMediateBlock"), TEXT("CreateBlock") ); return NULL; } lastBlk->svcNextBlockAddress = (PCMediateBlock *) MapViewOfFile( lastBlk->svcNextBlockHandle, FILE_MAP_WRITE, 0, 0, 0 ); if ( !lastBlk->svcNextBlockAddress ) { CloseHandle( lastBlk->svcNextBlockHandle ); lastBlk->svcNextBlockHandle = NULL; PCLogUnExError( TEXT("PCMediateBlock"), TEXT("MapBlock") ); } return lastBlk->svcNextBlockAddress; } // Can be called by Service only, NOT Mediator... void SvcAddEntry( const FULL_JOB_NAME &name, const ULONG_PTR key, SECURITY_ATTRIBUTES &secAttr ) { // First see if in list marked closed -- simply unmark if found... for ( PCMediateBlock *blk = &groupBlock; blk; blk = NextBlock( blk ) ) { for ( PCULONG32 i = 0; i < blk->groupCount; ++i ) { if ( !CompareJobName(blk->group[i].groupName, &name ) ) { blk->group[i].groupFlags &= ~PCMEDIATE_CLOSE_ME; SetEvent( svcEventHandle ); return; } } } // Not found -- add to end of list... PCMediateBlock *newBlk; for ( blk = &groupBlock; blk; blk = newBlk ) { if ( blk->groupCount < ENTRY_COUNT( blk->group ) ) { memcpy( blk->group[blk->groupCount].groupName, &name, sizeof(name) ); blk->group[blk->groupCount++].groupKey = key; SetEvent( svcEventHandle ); break; } newBlk = NextBlock( blk ); if ( !newBlk ) newBlk = SvcAddBlock( blk, secAttr ); } } // Can be called by Service only, NOT Mediator... void SvcCloseEntry( FULL_JOB_NAME &name ) { for ( PCMediateBlock *blk = &groupBlock; blk; blk = NextBlock( blk ) ) { for ( PCULONG32 i = 0; i < blk->groupCount; ++i ) { if ( !CompareJobName(blk->group[i].groupName, &name ) ) { blk->group[i].groupFlags |= PCMEDIATE_CLOSE_ME; SetEvent( svcEventHandle ); return; } } } } // Can be called by Service or Mediator (but only Service uses)... ULONG_PTR NewKey( const TCHAR *name ) { for ( PCMediateBlock *blk = &groupBlock; blk; blk = NextBlock( blk ) ) { for ( PCULONG32 i = 0; i < blk->groupCount; ++i ) { if ( !_tcscmp( name, blk->group[i].groupName ) ) return blk->group[i].groupKey; } } return ++lastCompKey; } // Can be called by Service only, NOT Mediator... void SvcChainBlocks( void ) { for ( PCMediateBlock *blk = &groupBlock; blk; blk = NextBlock( blk ) ) { if ( blk->medNextBlockHandle ) { if ( !DuplicateHandle( medProcessInfo.hProcess, blk->medNextBlockHandle, GetCurrentProcess(), &blk->svcNextBlockHandle, NULL, FALSE, DUPLICATE_SAME_ACCESS ) ) PCLogUnExError( TEXT("PCMediateBlock"), TEXT("DupBlkHandle") ); else { blk->svcNextBlockAddress = (PCMediateBlock *) MapViewOfFile( blk->svcNextBlockHandle, FILE_MAP_WRITE, 0, 0, 0 ); if ( !blk->svcNextBlockAddress ) { PCLogUnExError( TEXT("PCMediateBlock"), TEXT("MapJobBlk") ); CloseHandle( blk->svcNextBlockHandle ); blk->svcNextBlockHandle = NULL; return; } } } } } // Can be called by Mediator only, NOT Service... void MedChainBlocks( BOOL doAll ) { HANDLE hSvcProc = OpenProcess( PROCESS_DUP_HANDLE, FALSE, (DWORD) svcPID ); // OpenProcess uses DWORD PID, thus truncation in WIN64 if ( !hSvcProc ) { PCLogUnExError( svcPID, TEXT("OpenSvcProcFromMed") ); return; } for ( PCMediateBlock *blk = &groupBlock; blk; blk = NextBlock( blk ) ) { if ( blk->svcNextBlockHandle && (doAll || !blk->medNextBlockAddress) ) { if ( !DuplicateHandle( hSvcProc, blk->svcNextBlockHandle, GetCurrentProcess(), &blk->medNextBlockHandle, NULL, FALSE, DUPLICATE_SAME_ACCESS ) ) PCLogUnExError( TEXT("PCMediateBlock"), TEXT("DupServiceBlkHandle") ); else { blk->medNextBlockAddress = (PCMediateBlock *) MapViewOfFile( blk->medNextBlockHandle, FILE_MAP_WRITE, 0, 0, 0 ); if ( !blk->medNextBlockAddress ) { PCLogUnExError( TEXT("PCMediateBlock"), TEXT("MapServiceJobBlk") ); CloseHandle( blk->medNextBlockHandle ); blk->medNextBlockHandle = NULL; break; } } } } CloseHandle( hSvcProc ); } ULONG_PTR lastCompKey; // (S) Last completion key assigned to a group (or 0) HANDLE svcPortHandle; // (S) Service's Completion port handle HANDLE svcEventHandle; // (S) Service's event handle for service->mediator signalling ULONG_PTR svcPID; // (S) Service's PID PROCESS_INFORMATION medProcessInfo; // (S) initially, (M) replaces IDs. Mediator process information HANDLE medPortHandle; // (M) Mediator's copy of completion port handle VERSION_STRING medProductVersion; // (M) Meidator's product version VERSION_STRING medFileVersion; // (M) Meidator's file version VERSION_STRING medFileFlags; // (M) Meidator's file flags PCMediateBlock groupBlock; // First data block } PCMediateHdr; //================================================================================// // Enable forward class references... class CProcCon; class CProcConDB; class CProcConMgr; class CProcConUser; //================================================================================// // Miscellaneous const static TCHAR * const PROCCON_SVC_NAME = TEXT("ProcCon"); // Service name const static TCHAR * const PROCCON_SVC_EXCLUSION = TEXT("ProcConSvcOnlyMe"); // Name to ensure only one service is running extern TCHAR PROCCON_SVC_DISP_NAME[128]; // Service display name (loaded) extern TCHAR PROCCON_MEDIATOR_DISP_NAME[128]; // Mediator display name (loaded) extern TCHAR PROCCON_UNKNOWN_PROCESS[32]; // Name used for process already terminated (loaded) extern TCHAR PROCCON_SERVICE_DESCRIPTION[256]; // The service description value (loaded string) extern TCHAR PROCCON_DEFAULT_NAMERULE_DESC[NAME_DESCRIPTION_LEN + 1]; // Description field for default alias rule extern TCHAR PROCCON_FLAG_ON[32]; // Name used to indicate behavior is set extern TCHAR PROCCON_FLAG_OFF[32]; // Name used to indicate behavior is not set extern TCHAR PROCCON_SYSTEM_PROCESS[32]; // Name used for 'System' process (loaded) extern TCHAR PROCCON_SYSTEM_IDLE[64]; // Name used for 'System Idle Process' (loaded) extern TCHAR PROCCON_SERVICE_USAGE[256]; typedef struct _PCContext { CProcCon *cPC; CProcConMgr *cMgr; HANDLE mgrDoneEvent; CProcConUser *cUser; HANDLE userDoneEvent; CProcConDB *cDB; HANDLE completionPort; HANDLE mediatorEvent; HANDLE mediatorTableHandle; PCMediateHdr *mediatorTable; } PCContext; typedef struct _ClientContext { _ClientContext( PCULONG32 client, CProcCon *pcPC, CProcConDB *pcDB, CProcConUser *pcUser, PCULONG32 inSize, PCULONG32 outSize ) : clientNo( client ), hPipe( NULL ), cPC( pcPC ), cDB( pcDB ), cUser( pcUser ), inBufChars( inSize ), outBufChars( outSize ) { }; ~_ClientContext( void ) { }; PCULONG32 clientNo; HANDLE hPipe; PCULONG32 inBufChars; PCULONG32 outBufChars; CProcCon *cPC; CProcConDB *cDB; CProcConUser *cUser; } ClientContext; typedef struct _PCJobDef { JOB_NAME jobName; // Job name associated with this definition PROFILE_NAME profileName; // Profile name associated with this definition PC_MGMT_FLAGS mFlags; // Flags indicating which mgmt data to actually apply AFFINITY affinity; // processor affinity to apply if flagged PRIORITY priority; // NT priority to apply if flagged MEMORY_VALUE minWS; // NT minimum working set to apply if flagged MEMORY_VALUE maxWS; // NT maximum working set to apply if flagged SCHEDULING_CLASS schedClass; // NT scheduling class to apply if flagged PCULONG32 procCountLimit; // Number of processes in the job (jobs only). TIME_VALUE procTimeLimitCNS; // Per process time limit in 100ns (CNS) units or 0. TIME_VALUE jobTimeLimitCNS; // Per job time limit in 100ns (CNS) units or 0. MEMORY_VALUE procMemoryLimit; // Hard memory commit limit per process (jobs only). MEMORY_VALUE jobMemoryLimit; // Hard memory commit limit per job (jobs only). } PCJobDef; typedef struct _PCProcDef { PROC_NAME procName; // Process name associated with this definition -- must be first PROFILE_NAME profileName; // Profile name associated with this definition JOB_NAME memberOfJob; // Job name to associate process with if flagged PC_MGMT_FLAGS mFlags; // Flags indicating which mgmt data to actually apply AFFINITY affinity; // processor affinity to apply if flagged PRIORITY priority; // NT priority to apply if flagged MEMORY_VALUE minWS; // NT minimum working set to apply if flagged MEMORY_VALUE maxWS; // NT maximum working set to apply if flagged } PCProcDef; //================================================================================// // Registry related constants... // // Registry Server Apps Key (to let us appear as a server app in MMC)... const static TCHAR * const PROCCON_SERVER_APP_KEY = TEXT("SYSTEM\\CurrentControlSet\\Control\\Server Applications"); // Registry Base Key (full key will include added subkey)... const static TCHAR * const PROCCON_REG_SERVICE_BASE = // Base key for all registry data TEXT("SYSTEM\\CurrentControlSet\\Services\\"); const static TCHAR * const PROCCON_SERVICE_DESCRIPTION_NAME = TEXT("Description"); // Name or the Service Description value // // Registry Subkeys... const static TCHAR * const PROCCON_REG_EVENTLOG_SUBKEY = TEXT("EventLog\\System\\"); // Subkey for event log parameters const static TCHAR * const PROCCON_REG_PARMS_SUBKEY = TEXT("Parameters"); // Subkey for ProcCon parameters const static TCHAR * const PROCCON_REG_PROCRULES_SUBKEY = TEXT("ProcessRules"); // Subkey for our job rules const static TCHAR * const PROCCON_REG_JOBRULES_SUBKEY = TEXT("GroupRules"); // Subkey for our process rules // Access test subkeys... const static TCHAR * const PROCCON_REG_KILLPROC_ACCTEST = TEXT("AccessControl\\KillProcess"); // To allow process kill const static TCHAR * const PROCCON_REG_KILLJOB_ACCTEST = TEXT("AccessControl\\KillGroup"); // To allow job kill const static TCHAR * const PROCCON_REG_REALTIME_ACCTEST = TEXT("AccessControl\\SetRealTimePriority");// To allow real time priority const static TCHAR * const PROCCON_REG_POLLRATE_ACCTEST = TEXT("AccessControl\\SetPollSeconds"); // To allow changing poll rate const static TCHAR * const PROCCON_REG_RESTORE_ACCTEST = TEXT("AccessControl\\Restore"); // To allow database restore const static TCHAR * const accessKeyList[] = { PROCCON_REG_KILLPROC_ACCTEST, PROCCON_REG_KILLJOB_ACCTEST, PROCCON_REG_REALTIME_ACCTEST, PROCCON_REG_POLLRATE_ACCTEST, PROCCON_REG_RESTORE_ACCTEST }; // // Registry Value names... const static TCHAR * const PROCCON_SERVER_APP_VALUE_NAME = TEXT("{7cfc9f00-0641-11d2-8014-00104b9a3106}"); const static TCHAR * const PROCCON_DATA_DEFAULTRULES = TEXT("DfltMgmt"); // Name of our dflt mgmt rules const static TCHAR * const PROCCON_DATA_DESCRIPTION = TEXT("Description"); // Name of our description value const static TCHAR * const PROCCON_DATA_VARDATA = TEXT("VarData"); // Name of our variable detail data const static TCHAR * const PROCCON_DATA_MEMBEROF = TEXT("MemberOf"); // Name of our member of value const static TCHAR * const PROCCON_DATA_NAMERULES = TEXT("NameRules"); // Name of our name rules table const static TCHAR * const PROCCON_DATA_POLLDELAY = TEXT("ProcessPollSeconds"); // Name of our poll rate value const static TCHAR * const EVENT_MSG_FILE_NAME = TEXT("EventMessageFile"); // message files in EventLog key const static TCHAR * const EVENT_MSG_TYPES_SUPPORT = TEXT("TypesSupported"); // types supported in EventLog key //================================================================================// // Globals // // extern BOOL svcStop; extern BOOL notService; extern SERVICE_STATUS_HANDLE ssHandle; // service control handler extern SERVICE_STATUS ssStatus; // current service status extern PCULONG32 ssErrCode; // error code for status reporting //================================================================================// // ProcCon classes... //------------------------------------------------------------------------------------------------// // This class is a ProcCon instance -- its job is to start ProcCon's threads and wait. //------------------------------------------------------------------------------------------------// class CProcCon { public: // Public methods CProcCon( void ); ~CProcCon( void ); BOOL ReadyToRun ( void ); void Run ( void ); void HardStop ( PCULONG32 ExitCode = 0 ); void Stop ( void ); PCULONG32 StartMediator( void ); PCULONG32 StopMediator ( void ); BOOL GotShutdown ( void ) { return m_shutDown; } HANDLE GetShutEvent ( void ) { return m_shutEvent; } PCUINT32 GetPageSize ( void ) { return m_PageSize; } PCUINT32 GetProcCount ( void ) { return m_NumberOfProcessors; } CProcConMgr *GetPCMgr ( void ) { return m_context.cMgr; } void GetPCSystemInfo( PCSystemInfo *data, PCINT16 *itemLen, PCINT16 *itemCount ); private: // Private methods void LaunchProcServer( void ); // Starts the Process Management thread void LaunchUserServer( void ); // Starts the User Communication thread // Private attributes enum PCThreads { PROC_SERVER = 0, USER_SERVER = 1 }; BOOL m_shutDown; HANDLE m_shutEvent; HANDLE m_endEvent; HANDLE m_hThread[2]; SECURITY_ATTRIBUTES m_secAttr; // admin level security attrs BOOL m_ready; PCContext m_context; PCUINT32 m_NumberOfProcessors; PCUINT32 m_PageSize; CVersion *m_versionInfo; }; //------------------------------------------------------------------------------------------------// // This class is ProcCon's user management thread. It waits for connections and establishes // the connecting user's environment -- including a client thread. //------------------------------------------------------------------------------------------------// class CProcConUser { public: // Public methods CProcConUser( PCContext *ctxt ); ~CProcConUser( void ); BOOL ReadyToRun( void ); PCULONG32 Run ( void ); PCULONG32 GetTimeout( void ) { return m_clientTimeout; } PCULONG32 SetTimeout( PCULONG32 newTimeout ); private: // Private methods // Private attributes const static TCHAR *PIPENAME; CProcCon &m_cPC; CProcConDB &m_cDB; PCULONG32 m_outBufChars; PCULONG32 m_inBufChars; PCULONG32 m_clientTimeout; HANDLE m_hConnEvent; OVERLAPPED m_olConn; // for overlapped I/O on pipe connect PCULONG32 m_clientCount; // counts clients SECURITY_ATTRIBUTES m_secAttr; // security attributes for our pipe }; //------------------------------------------------------------------------------------------------// // This class is a ProcCon client thread. There may be any number of clients connected at once. //------------------------------------------------------------------------------------------------// class CProcConClient { public: // Public methods CProcConClient( ClientContext *ctxt ); ~CProcConClient( void ); BOOL ReadyToRun( void ); PCULONG32 Run ( void ); private: // Private methods BOOL ProcessRequest ( PCULONG32 inLen, PCULONG32 *outLen ); void PrimeResponse ( PCResponse *rsp, PCRequest *req ); BOOL ErrorResponse ( PCULONG32 errCode, PCResponse *rsp, PCULONG32 *outLen ); BOOL DoNameRules ( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen ); BOOL DoJobSummary ( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen ); BOOL DoProcSummary ( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen ); BOOL DoProcList ( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen ); BOOL DoJobList ( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen ); BOOL DoProcDetail ( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen ); BOOL DoJobDetail ( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen ); BOOL DoServerInfo ( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen ); BOOL DoServerParms ( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen ); BOOL DoControl ( PCRequest *req, PCResponse *rsp, PCULONG32 *outLen ); BOOL Impersonate ( PCRequest *req ); void UnImpersonate ( PCRequest *req ); void GenerateJobDetail( PCProcDetail *reqDetail ); // Private attributes CProcCon &m_cPC; CProcConDB &m_cDB; CProcConUser &m_cUser; HANDLE m_hPipe; BOOL m_impersonating; PCULONG32 m_clientNo; PCULONG32 m_outBufChars; PCULONG32 m_inBufChars; TCHAR *m_outBuf; TCHAR *m_inBuf; HANDLE m_hReadEvent; HANDLE m_hWriteEvent; OVERLAPPED m_olRead; OVERLAPPED m_olWrite; }; //------------------------------------------------------------------------------------------------// // This class is ProcCon's management thread. It periodically discovers what's running and // manages the workload according to management definitions. //------------------------------------------------------------------------------------------------// class CProcConMgr { struct _ManagedJob; public: // Public methods CProcConMgr( PCContext *ctxt ); ~CProcConMgr( void ); BOOL ReadyToRun ( void ); PCULONG32 Run ( void ); PCULONG32 ExportActiveProcList( PCProcListItem **list ); PCULONG32 ExportActiveJobList ( PCJobListItem **list ); AFFINITY GetSystemMask ( void ) { return m_systemMask; } INT32 KillJob ( JOB_NAME &name ); INT32 KillProcess ( ULONG_PTR pid, TIME_VALUE created ); void JobIsEmpty ( struct _ManagedJob *job ); private: // These structures are temporary lists of procs and jobs needing management... typedef struct _ManagedProcItem { PROC_STATISTICS pStats; // process Id, etc. PCProcDef *pDef; // process definition pointer. IMAGE_NAME imageName; // NT 'image' (exe) name } ManagedProcItem; typedef struct _ManagedJobItem { PCJobDef *jDef; // process definition pointer. } ManagedJobItem; // These structures describe running processes and jobs... typedef struct _ManagedJob { _ManagedJob( TCHAR *name, PCMediateHdr *mData ) : next( NULL ), jobHandle( NULL ), lastEojAction( 789123 ), sequence( 0 ), lastError( 0 ), curJobTimeLimitCNS( 0 ), dataErrorFlags( 0 ), memRejectReportTime( 0 ), timeExceededReported( FALSE ), hasComplPort( FALSE ), JOProcListInfo( NULL ) { memset( jName, 0, sizeof(jName) ); memset( &jobParms, 0, sizeof(jobParms) ); memset( fullJobName, 0, sizeof(fullJobName) ); memset( &JOBasicAndIoAcctInfo, 0, sizeof(JOBasicAndIoAcctInfo) ); memset( &JOExtendedLimitInfo, 0, sizeof(JOExtendedLimitInfo) ); _tcscpy( jName, name ); // Save user supplied name _tcscpy( fullJobName, TEXT("MSjob_") ); // Full name includes constant _tcscat( fullJobName, name ); // and user supplied name compKey = mData->NewKey( fullJobName ); // Assign our completion key } ~_ManagedJob( void ) { if ( jobHandle ) CloseHandle( jobHandle ); } JOB_NAME jName; // job name -- key. struct _ManagedJob *next; // next ManagedJob entry or NULL PCULONG32 sequence; // to detect when job updates have been done HANDLE jobHandle; // Job object handle BOOL hasComplPort; // TRUE if job has port association BOOL timeExceededReported; // Time excceed msg issued (post on time limit) PCULONG32 memRejectReportTime; // Last Tick Count of memory reject reporting PC_MGMT_FLAGS dataErrorFlags; // Flags to suppress duplicate error reporting ULONG_PTR compKey; // Key for completion port to find job PCULONG32 lastEojAction; // last setting for EOJ time lime reporting PCJobDef jobParms; // ProcCon job management parameters PCULONG32 lastError; // Last NT error accessing JO FULL_JOB_NAME fullJobName; // Fully decorated job name TIME_VALUE curJobTimeLimitCNS; // Our currently assigned job time limit JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION JOBasicAndIoAcctInfo; // JO acct info from last Discover() call JOBOBJECT_EXTENDED_LIMIT_INFORMATION JOExtendedLimitInfo; // JO ext limits from last Discover() call JOBOBJECT_BASIC_PROCESS_ID_LIST *JOProcListInfo; // JO proc list from last Discover() call } ManagedJob; typedef struct _ManagedProc { _ManagedProc( TCHAR *name, PID_VALUE pid, __int64 &createtime ) : next( NULL ), sequence( 0 ), isInJob( FALSE ), reportAdd( FALSE ), passSkipFlags( 0 ), isAppliedFlags( 0 ), actualPriority( 0 ), actualAffinity( 0 ), pMJob( NULL ) { memset( &pStats, 0, sizeof(pStats) ); memset( &imageName, 0, sizeof(imageName) ); memset( &procParms, 0, sizeof(procParms) ); memset( &originalParms, 0, sizeof(originalParms) ); memset( &lastAlreadyInJobErr, 0, sizeof(lastAlreadyInJobErr) ); _tcscpy( pName, name ); _i64tot( pid, pidAsString, 10 ); pStats.pid = pid; pStats.createTime = createtime; } PROC_STATISTICS pStats; // pid, etc. PROC_NAME pName; // process name as assigned by ProcCon struct _ManagedProc *next; // next ManagedProc entry or NULL PCULONG32 sequence; // to detect when referenced proc has gone away PRIORITY actualPriority; // actual base priority AFFINITY actualAffinity; // actual affinity mask IMAGE_NAME imageName; // NT 'image' (exe) name BOOL isInJob; // TRUE if proc is assigned to job below BOOL reportAdd; // TRUE if job reporter should report as 'added to' PC_MGMT_FLAGS passSkipFlags; // Flags to suppress attempted re-application of limit PC_MGMT_FLAGS isAppliedFlags; // Flags to indicate whether limit is applied or not TCHAR pidAsString[16]; // string version of pId for log messages ManagedJob *pMJob; // ptr to Managed Job when isInJob FULL_JOB_NAME lastAlreadyInJobErr; // Last rejected job name due to already in above job PCProcDef procParms; // proc management parameters (used to apply settings) PCProcDef originalParms; // original process parameters (used to un-apply settings) } ManagedProc; // These structures are raw (unfiltered) lists of currently running jobs and procs... typedef struct _RawJobList { PROC_NAME jName; // job name. } RawJobList; typedef struct _RawProcList { ULONG_PTR pId; // process Id (PID). FILETIME createTime; // process create time FILETIME exitTime; // process exit time (we don't use) FILETIME userTime; // process user time FILETIME kernelTime; // process kernel time PROC_NAME pName; // process name. struct _ManagedJob *pMJob; // ptr to ManagedJob if in job or NULL if not in job PRIORITY actualPriority; // actual base priority AFFINITY actualAffinity; // actual affinity mask IMAGE_NAME imageName; // NT 'image' (exe) name } RawProcList; // Private methods void Discover ( void ); // Discovers running processes/jobs void Manage ( void ); // Applies mgmt rules to processes/jobs BOOL NotTooSoon ( ManagedJob *job, PCULONG32 limit ); static PCULONG32 __stdcall JobReporter( void *inPtr ); static int _cdecl CompareRawProcList( const void *left, const void *right ) { return PCSignof64(((RawProcList *) left )->pId - ((RawProcList *) right)->pId); } static int _cdecl CompareRawJobList( const void *left, const void *right ) { return CompareJobName( left, right ); // job name is first in raw structure } void DeleteOrphanProcEntries( void ); void DeleteOrphanJobEntries ( void ); ManagedProc *FindProcEntry ( PID_VALUE pid, __int64 &createTime ); ManagedJob *FindJobEntry ( TCHAR *job, ManagedJob **plast = NULL ); void UpdateProcEntry ( ManagedProc &proc, PCProcDef &item, BOOL newProc ); void UpdateJobEntry ( ManagedJob &job, PCJobDef *item, BOOL newProc = FALSE ); BOOL GetProcListForJob( ManagedJob &job ); void UpdateJobObjInfo ( ManagedJob &job ); BOOL ApplyJobMgmt ( ManagedJob &job ); BOOL ApplyProcMgmt ( ManagedProc &proc, HANDLE hProc ); HANDLE GetComplPort ( void ) { return m_assocPort.CompletionPort; } ManagedJob *GetJobAnchor ( void ) { return m_jobAnchor; } ManagedProc *GetProcAnchor ( void ) { return m_procAnchor; } PCULONG32 GetRawProcCount( void ) { return m_rawProcCount; } RawProcList &GetRawProcEntry( PCULONG32 i ) { return m_rawProcList[i]; } CRITICAL_SECTION *GetListCSPtr ( void ) { return &m_mgCSMgrLists; } // Private attributes private: CProcCon &m_cPC; CProcConDB &m_cDB; JOBOBJECT_ASSOCIATE_COMPLETION_PORT m_assocPort; // associated completion port structure HANDLE m_reportThread; // thread that monitors completion port ULONG_PTR m_systemMask; // NT system affinity mask: shows processors present PCULONG32 m_sequencer; // To detect when processes are no longer around CRITICAL_SECTION m_mgCSMgrLists; // to protect various process and job lists below SECURITY_ATTRIBUTES m_secAttr; // security attributes for our job objects RawProcList *m_rawProcList; // proc information from last process discovery or NULL PCULONG32 m_rawProcCount; // number of entries in raw rpoc list PCULONG32 m_jobManagedCount; // count of managed job entries in m_jobAnchor ManagedJob *m_jobAnchor; // linked list of currently managed jobs PCULONG32 m_procManagedCount; // count of managed proc entries in m_procAnchor; ManagedProc *m_procAnchor; // linked list of currently managed procs HANDLE m_mediatorEvent; // mediator signalling event PCMediateHdr *m_mediatorTable; // data shared with mediator }; //------------------------------------------------------------------------------------------------// // This class is ProcCon's database control and owns all external data. // This class does not include a thread -- all database calls are synchronous from other threads. //------------------------------------------------------------------------------------------------// class CProcConDB { public: const enum LoadFlags { LOADFLAG_NAME_RULES = 0x00000001, LOADFLAG_PROC_RULES = 0x00000002, LOADFLAG_JOB_RULES = 0x00000004, LOADFLAG_ALL_RULES = 0x00000007, }; // Public methods CProcConDB( PCUINT32 size ); ~CProcConDB( void ); BOOL ReadyToRun ( void ); PCULONG32 LoadRules ( PCULONG32 which ); HANDLE GetDbEvent ( void ) { return m_dbEvent; } PCULONG32 GetPollDelay ( void ) { return m_pollDelay; } PCULONG32 GetPollDelaySeconds( void ) { return m_pollDelay / 1000; } PCULONG32 SetPollDelaySeconds( PCULONG32 newDelay ); void SetPCMgr ( CProcConMgr *pMgr ) { m_cMgr = pMgr; } void AssignProcName ( const TCHAR *path, PROC_NAME *name, IMAGE_NAME *iName ); INT32 TestAccess ( const TCHAR *key ); PCULONG32 GetJobMgmtDefs ( PCJobDef **pList, JOB_NAME *name = NULL ); PCULONG32 GetProcMgmtDefs( PCProcDef **pList ); BOOL GetNameRules ( const PCINT32 first, PCNameRule *pRules, const PCINT32 maxCount, PCINT16 *itemLen, PCINT16 *itemCount, PCINT32 *updCtr ); PCULONG32 AddNameRule ( const PCNameRule *pRule, const BYTE version, const PCULONG32 index, const PCINT32 updCtr ); PCULONG32 ReplNameRule ( const PCNameRule *pRule, const BYTE version, const PCULONG32 index, const PCINT32 updCtr ); PCULONG32 DelNameRule ( const PCULONG32 index, const PCINT32 updCtr ); PCULONG32 SwapNameRule ( const PCULONG32 index, const PCINT32 updCtr ); BOOL GetJobSummary ( const PCJobSummary *pStart, PCUINT32 listFlags, PCJobSummary *pSummary, const PCINT32 maxCount, PCINT16 *itemLen, PCINT16 *itemCount ); BOOL GetProcSummary( const PCProcSummary *pStart, PCUINT32 listFlags, PCProcSummary *pSummary, const PCINT32 maxCount, PCINT16 *itemLen, PCINT16 *itemCount ); BOOL GetJobList ( const PCJobListItem *pStart, const PCUINT32 listFlags, PCJobListItem *pList, const PCINT32 maxCount, PCINT16 *itemLen, PCINT16 *itemCount ); BOOL GetProcList ( const PCProcListItem *pStart, const PCUINT32 listFlags, PCProcListItem *pList, const PCINT32 maxCount, PCINT16 *itemLen, PCINT16 *itemCount ); PCULONG32 GetProcDetail ( const PCProcDetail *pIn, PCProcDetail *pDetail, const BYTE version, PCINT32 *updCtr ); PCULONG32 AddProcDetail ( const PCProcDetail *pDetail, const BYTE version ); PCULONG32 ReplProcDetail( const PCProcDetail *pDetail, const BYTE version, const PCINT32 updCtr ); PCULONG32 DelProcDetail ( const PCProcSummary *pSummary, const BYTE version ); void LogProcSummaryChange( const PCProcSummary *pSummary, const BYTE version, const PCProcSummary *pOldSummary ); PCULONG32 GetJobDetail ( const PCJobDetail *pIn, PCJobDetail *pDetail, const BYTE version, PCINT32 *updCtr ); PCULONG32 AddJobDetail ( const PCJobDetail *pDetail, const BYTE version ); PCULONG32 ReplJobDetail ( const PCJobDetail *pDetail, const BYTE version, const PCINT32 updCtr ); PCULONG32 DelJobDetail ( const PCJobSummary *pSummary, const BYTE version ); void LogJobSummaryChange( const PCJobSummary *pSummary, const BYTE version, const PCJobSummary *pOldSummary ); PCULONG32 DeleteAllNameRules( void ); PCULONG32 DeleteAllProcDefs ( void ); PCULONG32 DeleteAllJobDefs ( void ); private: // Private methods BOOL OpenProcKey ( void ); BOOL OpenParmKey ( void ); BOOL OpenJobKey ( void ); PCULONG32 RegError ( const TCHAR *op, const TCHAR *what1 = NULL, const TCHAR *what2 = NULL ); PCULONG32 RegDataError ( const TCHAR *what ); PCULONG32 GetPCParm ( const TCHAR *name, PCULONG32 *data ); PCULONG32 SetPCParm ( const TCHAR *name, PCULONG32 data ); PCULONG32 CreateKeyAtHKLM ( const TCHAR *key, HKEY *hKey ); BOOL BuildIntNameRules ( void ); void BuildIntNameRule ( PCULONG32 index ); BOOL NameMatch ( const BOOL compare, const BOOL hasWildcard, const TCHAR *str, const TCHAR **arg, const PCULONG32 argCt = 1, PCULONG32 *mIdx = NULL ); void NameSet ( PROC_NAME *name, const BOOL isPattern, const TCHAR *pattern, const TCHAR *patArgP, const TCHAR *patArgN = NULL ); int ExtStartLoc ( const TCHAR *name ); void SetJobDefEntry ( PCJobDef *list, PCJobSummary &m_jobSummary ); TCHAR *BuildProcKey ( TCHAR *key ); TCHAR *BuildJobKey ( TCHAR *key ); PCULONG32 LoadNameRules ( PCULONG32 *count ); PCULONG32 StoreNameRules ( void ); PCULONG32 NameRulesUpdated ( void ); PCULONG32 LoadProcSummary ( void ); PCULONG32 LoadJobSummary ( void ); PCULONG32 LoadProcSummaryItem( const HKEY &hKeyTemp, PCProcSummary &summary ); PCULONG32 LoadJobSummaryItem ( const HKEY &hKeyTemp, PCJobSummary &summary ); PCULONG32 LoadMgmtRules ( const HKEY &hKey, MGMT_PARMS &parms ); PCULONG32 LoadVariableData ( const HKEY &hKey, PCINT16 *vLength, TCHAR *vData ); PCULONG32 StoreJobDetail ( const PCJobDetail &detail ); PCULONG32 StoreProcDetail ( const PCProcDetail &detail ); PCULONG32 StoreJobValues ( const HKEY &hKey, const PCJobDetail &detail ); PCULONG32 StoreProcValues ( const HKEY &hKey, const PCProcDetail &detail ); PCULONG32 StoreMgmtRules ( const HKEY &hKey, const MGMT_PARMS &parms ); PCULONG32 StoreVariableData ( const HKEY &hKey, const PCINT16 vLength, const TCHAR *vData ); static inline int _cdecl CompareProcSummary( const void *left, const void *right ) { int comp = _tcsnicmp( ((PCProcSummary *) left )->procName, ((PCProcSummary *) right)->procName, PROC_NAME_LEN ); if ( !comp ) return _tcsnicmp( ((PCProcSummary *) left )->mgmtParms.profileName, ((PCProcSummary *) right)->mgmtParms.profileName, PROFILE_NAME_LEN ); else return comp; } static inline int _cdecl CompareJobSummary( const void *left, const void *right ) { int comp = _tcsnicmp( ((PCJobSummary *) left )->jobName, ((PCJobSummary *) right)->jobName, JOB_NAME_LEN ); if ( !comp ) return _tcsnicmp( ((PCJobSummary *) left )->mgmtParms.profileName, ((PCJobSummary *) right)->mgmtParms.profileName, PROFILE_NAME_LEN ); else return comp; } static inline int _cdecl CompareProcListItemProcName( const void *left, const void *right ) { return _tcsnicmp( ((PCProcListItem *) left )->procName, ((PCProcListItem *) right)->procName, PROC_NAME_LEN ); } static inline int _cdecl CompareProcListItemPidOptional( const void *left, const void *right ) { int cmp = CompareProcListItemProcName( left, right ); if ( !cmp && ((PCProcListItem *) left )->procStats.pid ) { cmp = PCSignof64(((PCProcListItem *) left )->procStats.pid - ((PCProcListItem *) right )->procStats.pid); } return cmp; } static inline int _cdecl CompareProcListItem( const void *left, const void *right ) { int cmp = CompareProcListItemProcName( left, right ); if ( !cmp ) cmp = PCSignof64(((PCProcListItem *) left )->procStats.pid - ((PCProcListItem *) right )->procStats.pid); return cmp; } static inline int _cdecl CompareProcListItemJobName( const void *left, const void *right ) { return _tcsnicmp( ((PCProcListItem *) left )->jobName, ((PCProcListItem *) right)->jobName, JOB_NAME_LEN ); } static inline int _cdecl CompareJobListItem( const void *left, const void *right ) { return _tcsnicmp( ((PCJobListItem *) left )->jobName, ((PCJobListItem *) right)->jobName, JOB_NAME_LEN ); } static inline int _cdecl CompareProcDef( const void *left, const void *right ) { return _tcsnicmp( ((PCProcDef *) left )->procName, ((PCProcDef *) right)->procName, PROC_NAME_LEN ); } static inline int _cdecl CompareJobDef( const void *left, const void *right ) { return _tcsnicmp( ((PCJobDef *) left )->jobName, ((PCJobDef *) right)->jobName, JOB_NAME_LEN ); } BOOL NameHasPattern( const TCHAR *name ) { for ( const TCHAR *pStart = _tcschr( name, NAME_IS_PGM[0] ); pStart; pStart = _tcschr( pStart + 1, NAME_IS_PGM[0] ) ) { if ( _tcschr( PATTERN_CHARS, _totupper( *(pStart + 1) ) ) && *(pStart + 2) == NAME_IS_PGM[2] ) return TRUE; } return FALSE; } BOOL JobBelongsInList( const PCJobListItem &li, const PCJobListItem *pStart, const PCUINT32 listFlags ) { PCINT32 cmp = CompareJobListItem( pStart, li.jobName ); BOOL inRange; if ( listFlags & PC_LIST_MATCH_ONLY ) inRange = cmp == 0; else if ( listFlags & PC_LIST_STARTING_WITH ) inRange = cmp <= 0; else inRange = cmp < 0; return *li.jobName && inRange && (!(listFlags & PC_LIST_ONLY_RUNNING) || li.lFlags & PCLFLAG_IS_RUNNING); } BOOL ProcBelongsInList( const PCProcListItem &li, const PCProcListItem *pStart, const PCUINT32 listFlags ) { if ( listFlags & PC_LIST_MEMBERS_OF && CompareProcListItemJobName( pStart, &li ) ) return FALSE; BOOL inRange; int cmp = (listFlags & PC_LIST_MATCH_ONLY)? CompareProcListItemPidOptional( pStart, &li ) : CompareProcListItem( pStart, &li ); if ( listFlags & PC_LIST_MATCH_ONLY ) inRange = cmp == 0; else if ( listFlags & PC_LIST_STARTING_WITH ) inRange = cmp <= 0; else inRange = cmp < 0; return *li.procName && inRange && (!(listFlags & PC_LIST_ONLY_RUNNING) || li.lFlags & PCLFLAG_IS_RUNNING); } // Private attributes const enum MatchFlags { MFLAG_HAS_WILDCARD = 0x00000001, MFLAG_HAS_NAME_PATTERN = 0x00000002, MFLAG_HAS_EXTENSION = 0x00000004, }; typedef struct _PCNameRuleInt { MATCH_TYPE mType; // value is MATCH_PGM, MATCH_DIR, or MATCH_ANY. PCULONG32 mFlags; // flags to indicate wildcards, derived name, etc. TCHAR mString[MAX_PATH]; // match string may include * and ? wildcard chars PROC_NAME mName; // process name to use when match succeeds. NAME_DESCRIPTION mDesc; // user's description of rule } PCNameRuleInt; const static TCHAR PCDB_PREFIX_FLAGS; const static TCHAR PCDB_PREFIX_AFFINITY; const static TCHAR PCDB_PREFIX_PRIORITY; const static TCHAR PCDB_PREFIX_MINWS; const static TCHAR PCDB_PREFIX_MAXWS; const static TCHAR PCDB_PREFIX_SCHEDCLASS; const static TCHAR PCDB_PREFIX_PROCTIME; const static TCHAR PCDB_PREFIX_JOBTIME; const static TCHAR PCDB_PREFIX_ACTIVEPROCS; const static TCHAR PCDB_PREFIX_PROCMEMORY; const static TCHAR PCDB_PREFIX_JOBMEMORY; const static TCHAR BEG_BRACKET; // leading char in rules stored in DB const static TCHAR END_BRACKET; // trailing char in rules stored in DB const static TCHAR FIELD_SEP; // separates fields in rules/values stored in DB const static TCHAR STRING_DELIM; // delimits text strings stored in DB const static TCHAR RULE_MATCHONE; // match any one characters const static TCHAR RULE_MATCHANY; // match any string of characters const static TCHAR NAME_IS_PGM[]; // variable name rule text == pgm name const static TCHAR NAME_IS_DIR[]; // variable name rule text == matched dir name const static TCHAR HIDE_PROC_PATTERN[]; // pattern meaning hide this proc from view/processing const static TCHAR PATTERN_CHARS[]; // the pattern characters allowed in process names static PCNameRule DEFAULT_NAME_RULE; // default rule -- always last in name rules tbl CProcConMgr *m_cMgr; // ProcCon Manager class for live data access CRITICAL_SECTION m_dbCSNameRule; // to protect name data access CRITICAL_SECTION m_dbCSProcRule; // to protect process data access CRITICAL_SECTION m_dbCSJobRule; // to protect job data access PCULONG32 m_lastRegError; // last error when accessing registry or ERROR_SUCCESS PCULONG32 m_pollDelay; // process space poll delay in millseconds const BOOL m_LogRuleEdits; // report each rule edit with an Event Log entry HKEY m_parmRegKey; // open key for registry parameter access or NULL HKEY m_procRegKey; // open key for registry proc rules access or NULL HKEY m_jobRegKey; // open key for registry job rules access or NULL PCNameRule *m_fmtNameRules; // name rules formatted into API structures or NULL PCNameRuleInt *m_intNameRules; // name rules formatted into our internal structure or NULL HANDLE m_dbEvent; // to signal interested parties when DB changes HANDLE m_parmEvent; // for NT to signal us on external DB change (should not happen) PCProcSummary *m_procSummary; // ptr to array of process rule summaries from DB or NULL PCJobSummary *m_jobSummary; // ptr to array of job rule summaries from DB or NULL SECURITY_ATTRIBUTES m_secAttr; // security attributes for our registry keys PCULONG32 m_numNameRules; // number of rules in m_raw/fmtNameRules arrays PCULONG32 m_numProcRules; // number of rules in m_procRules array PCULONG32 m_numJobRules; // number of rules in m_jobRules array PCINT32 m_updCtrName; // update counter for name rules PCINT32 m_updCtrProc; // update counter for proc rules PCINT32 m_updCtrJob; // update counter for job rules PCUINT32 m_pageSize; // page size for rounding memory values TCHAR m_curProfile[32]; // current profile (invalid implies DfltMgmt profile) }; #ifdef _DEBUG inline void _cdecl DbgTrace(LPCSTR lpszFormat, ...) { va_list args; va_start(args, lpszFormat); int nBuf; char szBuffer[512]; nBuf = _vsnprintf(szBuffer, sizeof(szBuffer), lpszFormat, args); assert(nBuf < sizeof(szBuffer)); //Output truncated as it was > sizeof(szBuffer) OutputDebugStringA(szBuffer); va_end(args); } #else inline void _cdecl DbgTrace(LPCSTR lpszFormat, ...) {} #endif // End of ProcConSvc.h //============================================================================J McDonald fecit====//