1083 lines
55 KiB
C
1083 lines
55 KiB
C
|
/*======================================================================================//
|
||
|
| //
|
||
|
|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 <windows.h>
|
||
|
#include <winnt.h>
|
||
|
#include <stddef.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <tchar.h>
|
||
|
#include <assert.h>
|
||
|
#include <search.h>
|
||
|
#include <time.h>
|
||
|
#include <winver.h>
|
||
|
#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====//
|
||
|
|