|
|
/*---------------------------------------------------------------------------
File: Monitor.cpp
Comments: Functions to monitor the status of the DCT Agents.
This involves spawning a thread which periodically reads the dispatch log, and scans the result directory for result files.
(c) Copyright 1999, Mission Critical Software, Inc., All Rights Reserved Proprietary and confidential to Mission Critical Software, Inc.
REVISION LOG ENTRY Revision By: Christy Boles Revised on 03/15/99 15:43:35
--------------------------------------------------------------------------- */
#include "StdAfx.h"
#include "Resource.h"
#include "Common.hpp"
#include "Err.hpp"
#include "UString.hpp"
#include "TNode.hpp"
#include "ServList.hpp"
#include "Globals.h"
#include "Monitor.h"
#include "ResStr.h"
#include <lm.h> // to remove result share
//#import "\bin\McsVarSetMin.tlb" no_namespace , named_guids
//#import "\bin\DBManager.tlb" no_namespace, named_guids
#import "VarSet.tlb" no_namespace , named_guids rename("property", "aproperty")
#import "DBMgr.tlb" no_namespace, named_guids
//#include "..\Common\Include\McsPI.h"
#include "McsPI.h"
#include "McsPI_i.c"
#include "afxdao.h"
void LookForResults(WCHAR * dir = NULL); void WaitForMoreResults(WCHAR * dir); void ProcessResults(TServerNode * pServer, WCHAR const * directory, WCHAR const * filename);
GlobalData gData;
DWORD __stdcall ResultMonitorFn(void * arg) { WCHAR logdir[MAX_PATH] = L""; BOOL bFirstPassDone;
CoInitialize(NULL);
gData.GetFirstPassDone(&bFirstPassDone);
// wait until the other monitoring thread has a chance to build the server list,
// so we can check for pre-existing input files before using the changenotify mechanism
while ( ! bFirstPassDone || !*logdir ) { Sleep(500); gData.GetFirstPassDone(&bFirstPassDone); gData.GetResultDir(logdir); } LookForResults(logdir); WaitForMoreResults(logdir);
CoUninitialize();
return 0; }
void WaitForMoreResults(WCHAR * logdir) { WCHAR resultWC[MAX_PATH]; HANDLE hFind = INVALID_HANDLE_VALUE; BOOL bDone; long nIntervalSeconds;
safecopy(resultWC,logdir);
gData.GetDone(&bDone); gData.GetWaitInterval(&nIntervalSeconds); while (! bDone) { if (hFind == INVALID_HANDLE_VALUE) { hFind = FindFirstChangeNotification(resultWC, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME); }
if (hFind != INVALID_HANDLE_VALUE) WaitForSingleObject(hFind,nIntervalSeconds * 1000 ); else Sleep(nIntervalSeconds * 1000); LookForResults(logdir);
if (hFind != INVALID_HANDLE_VALUE) { if (! FindNextChangeNotification(hFind)) { FindCloseChangeNotification(hFind); hFind = INVALID_HANDLE_VALUE; } } gData.GetDone(&bDone); // we still listen to global done
// in case that we use it to force a stop
gData.GetWaitInterval(&nIntervalSeconds);
ComputerStats stats; gData.GetComputerStats(&stats);
// if all agents either finished or failed, we consider it done
if (stats.numFinished + stats.numError >= stats.total) break; }
if (hFind != INVALID_HANDLE_VALUE) FindCloseChangeNotification(hFind); gData.SetDone(TRUE); }
void LookForResults(WCHAR * arglogdir) { TNodeListEnum e; TServerNode * s; DWORD nInstalled = 0; DWORD nRunning = 0; DWORD nFinished = 0; DWORD nError = 0; HWND gListWnd; HWND gSummaryWnd; WCHAR logdir[MAX_PATH];
if ( ! (arglogdir && *arglogdir) ) { gData.GetResultDir(logdir); } else { safecopy(logdir,arglogdir); }
for ( s = (TServerNode*)e.OpenFirst(gData.GetUnsafeServerList()) ; s ; gData.Lock(),s = (TServerNode*)e.Next(),gData.Unlock() ) { if ( s->IsInstalled() ) nInstalled++; if (s->HasFailed()) nError++; // only when result has been processed do we consider it finished
else if (s->IsFinished() && s->IsResultPullingTried() && (!s->HasResult() || s->IsResultProcessed())) nFinished++; else nRunning++;
// Check jobs that finished, got result pulled but not yet processed
if ( *s->GetJobFile() && s->IsFinished() && s->IsResultPullingTried() && s->HasResult() && !s->IsResultProcessed() ) { // Look for results
WCHAR resultWC[MAX_PATH]; HANDLE hFind; WIN32_FIND_DATA fdata; WCHAR sTime[32];
if ( logdir[UStrLen(logdir)-1] == L'\\' ) { swprintf(resultWC,L"%s%s.result",logdir,s->GetJobFile()); } else { swprintf(resultWC,L"%s\\%s.result",logdir,s->GetJobFile()); } hFind = FindFirstFile(resultWC,&fdata);
s->SetTimeStamp(gTTime.FormatIsoLcl( gTTime.Now( NULL ), sTime ));
if ( hFind != INVALID_HANDLE_VALUE ) { ProcessResults(s,logdir,fdata.cFileName); s->SetResultProcessed(TRUE); nRunning--; nFinished++; FindClose(hFind); } gData.GetListWindow(&gListWnd); SendMessage(gListWnd,DCT_UPDATE_ENTRY,NULL,(LPARAM)s); } } e.Close(); // Update the summary window
ComputerStats stat;
// get the total servers number
gData.GetComputerStats(&stat); stat.numError = nError; stat.numFinished = nFinished; stat.numRunning = nRunning; stat.numInstalled = nInstalled;
gData.SetComputerStats(&stat);
gData.GetSummaryWindow(&gSummaryWnd); SendMessage(gSummaryWnd,DCT_UPDATE_COUNTS,0,(LPARAM)&stat); }
BOOL // ret- TRUE if successful
ReadResults( TServerNode * pServer, // in - pointer to server node containing server name
WCHAR const * directory, // in - directory where results files are stored
WCHAR const * filename, // in - filename for this agent's job
DetailStats * pStats, // out- counts of items processed by the agent
CString & plugInText, // out- text results from plug-ins
BOOL bStore // in - bool, whether to store plug-in text
) { AFX_MANAGE_STATE(AfxGetStaticModuleState());
WCHAR path[MAX_PATH]; HRESULT hr = S_OK; BOOL bSuccess = FALSE;
if ( directory[UStrLen(directory)-1] == '\\' ) { swprintf(path,L"%ls%ls",directory,filename); } else { swprintf(path,L"%ls\\%ls",directory,filename); }
// Read the varset data from the file
IVarSetPtr pVarSet; IStoragePtr store;
// attempt to open result file
for (int nTries = 0; nTries < 6; nTries++) { hr = StgOpenStorage(path, NULL, STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, 0, &store);
// if sharing or lock violation then...
if ((hr == STG_E_SHAREVIOLATION) || (hr == STG_E_LOCKVIOLATION)) { // wait one second before trying again
Sleep(1000); } else { // otherwise stop trying
break; } }
if (SUCCEEDED(hr)) { // load VarSet from file
hr = OleLoad(store, IID_IVarSet, NULL, (void**)&pVarSet); }
if ( SUCCEEDED(hr) ) { pStats->directoriesChanged = (long)pVarSet->get(GET_BSTR(DCTVS_Stats_Directories_Changed)); pStats->directoriesExamined = (long)pVarSet->get(GET_BSTR(DCTVS_Stats_Directories_Examined)); pStats->directoriesUnchanged = (pStats->directoriesExamined - pStats->directoriesChanged);
pStats->filesChanged = (long)pVarSet->get(GET_BSTR(DCTVS_Stats_Files_Changed)); pStats->filesExamined = (long)pVarSet->get(GET_BSTR(DCTVS_Stats_Files_Examined)); pStats->filesUnchanged = (pStats->filesExamined - pStats->filesChanged );
pStats->sharesChanged = (long)pVarSet->get(GET_BSTR(DCTVS_Stats_Shares_Changed)); pStats->sharesExamined = (long)pVarSet->get(GET_BSTR(DCTVS_Stats_Shares_Examined)); pStats->sharesUnchanged = (pStats->sharesExamined - pStats->sharesChanged );
pStats->membersChanged = (long)pVarSet->get(GET_BSTR(DCTVS_Stats_Members_Changed)); pStats->membersExamined = (long)pVarSet->get(GET_BSTR(DCTVS_Stats_Members_Examined)); pStats->membersUnchanged = (pStats->membersExamined - pStats->membersChanged );
pStats->rightsChanged = (long)pVarSet->get(GET_BSTR(DCTVS_Stats_UserRights_Changed)); pStats->rightsExamined = (long)pVarSet->get(GET_BSTR(DCTVS_Stats_UserRights_Examined)); pStats->rightsUnchanged = (pStats->rightsExamined - pStats->rightsChanged );
long level = pVarSet->get(GET_BSTR(DCTVS_Results_ErrorLevel)); _bstr_t logfile = pVarSet->get(GET_BSTR(DCTVS_Results_LogFile)); _bstr_t logfileIsInvalid = pVarSet->get(GET_BSTR(DCTVS_Results_LogFileIsInvalid)); BOOL bLogfileIsInvalid = (!logfileIsInvalid == false && !UStrICmp(logfileIsInvalid, GET_STRING(IDS_YES))) ? TRUE : FALSE;
if ( level > 2 ) { CString message;
message.FormatMessage(IDS_SeeLogForAgentErrors_S,(WCHAR*)logfile);
pServer->SetMessageText(message.GetBuffer(0)); } pServer->SetSeverity(level); // build the UNC path for the log file
WCHAR logPath[MAX_PATH]; swprintf(logPath,L"\\\\%s\\%c$\\%s",pServer->GetServer(),((WCHAR*)logfile)[0],((WCHAR*)logfile) + 3);
if (bLogfileIsInvalid) { pServer->SetLogPath(logfile); pServer->SetLogPathValid(FALSE); } else { pServer->SetLogPath(logPath); pServer->SetLogPathValid(TRUE); } bSuccess = TRUE; // Try to get information from any plug-ins that ran
// create the COM object for each plug-in
_bstr_t bStrGuid; WCHAR key[300]; CLSID clsid;
for ( int i = 0 ; ; i++ ) { swprintf(key,L"Plugin.%ld",i); bStrGuid = pVarSet->get(key); if ( bStrGuid.length() == 0 ) break;
IMcsDomPlugIn * pPlugIn = NULL; hr = CLSIDFromString(bStrGuid,&clsid); if ( SUCCEEDED(hr) ) { hr = CoCreateInstance(clsid,NULL,CLSCTX_ALL,IID_IMcsDomPlugIn,(void**)&pPlugIn); if ( SUCCEEDED(hr) ) { BSTR name = NULL; BSTR result = NULL; hr = pPlugIn->GetName(&name); if ( SUCCEEDED(hr) ) { hr = pPlugIn->GetResultString(pVarSet,&result); if ( SUCCEEDED(hr) ) { plugInText += (WCHAR*)name; plugInText += L"\n"; plugInText += (WCHAR*)result; plugInText += L"\n\n"; SysFreeString(result); } SysFreeString(name); if ( bStore ) { pVarSet->put(L"LocalServer",pServer->GetServer()); pPlugIn->StoreResults(pVarSet); } } pPlugIn->Release(); } } }
} else { CString message; CString title;
if ( hr != STG_E_SHAREVIOLATION && hr != STG_E_LOCKVIOLATION ) { message.FormatMessage(IDS_FailedToLoadResults,filename,hr); title.LoadString(IDS_MessageTitle); if ( hr != STG_E_FILENOTFOUND ) MessageBox(NULL,message,title,MB_OK | MB_ICONERROR); } else { // the agent has still not finished writing its results file, for some reason
// we'll check it again later
pServer->SetStatus(pServer->GetStatus() & ~Agent_Status_Finished); } } return bSuccess; }
void ProcessSecRefs( TServerNode * pServer, WCHAR const * directory, WCHAR const * filename ) { AFX_MANAGE_STATE(AfxGetStaticModuleState());
const DWORD NOREF = 0;
WCHAR path[MAX_PATH]; DWORD rc = 0; BOOL bSuccess = FALSE; FILE * pFile; WCHAR * pDot;
if ( directory[UStrLen(directory)-1] == '\\' ) { swprintf(path,L"%ls%ls",directory,filename); } else { swprintf(path,L"%ls\\%ls",directory,filename); } // check to see if a secrefs file was written
pDot = wcsrchr(path,L'.'); if ( pDot ) { UStrCpy(pDot,L".secrefs"); pFile = _wfopen(path,L"rb"); if ( pFile ) { IIManageDBPtr pDB;
rc = pDB.CreateInstance(CLSID_IManageDB); if ( SUCCEEDED(rc) ) { // there are some secrefs here, load them into the database
WCHAR account[300] = L""; WCHAR type[100] = L""; DWORD nOwner = 0; DWORD nGroup = 0; DWORD nDacl = 0; DWORD nSacl = 0; WCHAR domPart[300]; WCHAR acctPart[300]; WCHAR acctSid[300] = L""; WCHAR * slash; CString typeString;
//remove any old references for this machine in the table
_variant_t var; WCHAR sFilter[MAX_PATH]; wsprintf(sFilter, L"Server = \"%s\"", pServer->GetServer()); var = sFilter; rc = pDB->raw_ClearTable(L"AccountRefs", var);
//move past the UNICODE Byte Order Mark
fgetwc(pFile);
//get entries
while ( 7 == fwscanf(pFile,L"%[^,],%[^,],%[^,],%ld,%ld,%ld,%ld\r\n",account,acctSid,type,&nOwner,&nGroup,&nDacl,&nSacl) ) { safecopy(domPart,account); slash = wcschr(domPart,L'\\'); if ( slash ) { *slash = 0; UStrCpy(acctPart,slash+1); } else { domPart[0] = 0; safecopy(acctPart,account); }
//for sIDs with no resolvable account, change domain and account to (Unknown)
if ((wcsstr(account, L"S-") == account) && (domPart[0] == 0)) { wcscpy(acctPart, GET_STRING(IDS_UnknownSid)); wcscpy(domPart, GET_STRING(IDS_UnknownSid)); }
if (nOwner != NOREF) { typeString.FormatMessage(IDS_OwnerRef_S,type); rc = pDB->raw_AddAcctRef(domPart,acctPart,acctSid,pServer->GetServer(),nOwner,typeString.AllocSysString()); } if (nGroup != NOREF) { typeString.FormatMessage(IDS_GroupRef_S,type); rc = pDB->raw_AddAcctRef(domPart,acctPart,acctSid,pServer->GetServer(),nGroup,typeString.AllocSysString()); }
if (nDacl != NOREF) { //since local group members are not referenced in DACL, but we use that
//field to keep track of reference, use a different type string
if (!UStrCmp(type, GET_STRING(IDS_STReference_Member))) typeString.FormatMessage(IDS_MemberRef_S); else typeString.FormatMessage(IDS_DACLRef_S,type); rc = pDB->raw_AddAcctRef(domPart,acctPart,acctSid,pServer->GetServer(),nDacl,typeString.AllocSysString()); }
if (nSacl != NOREF) { typeString.FormatMessage(IDS_SACLRef_S,type); rc = pDB->raw_AddAcctRef(domPart,acctPart,acctSid,pServer->GetServer(),nSacl,typeString.AllocSysString()); }
// make sure there's not any data left over in these
account[0] = 0; type[0] = 0; acctSid[0] = 0; nOwner = 0; nGroup = 0; nDacl = 0; nSacl = 0; } } fclose(pFile); } }
}
void ProcessResults( TServerNode * pServer, WCHAR const * directory, WCHAR const * filename ) { HRESULT hr = S_OK; DetailStats stats; HWND hWnd; CString PLText; memset(&stats,0,(sizeof stats));
if ( ReadResults(pServer,directory,filename,&stats,PLText,TRUE) ) { if ( ! pServer->HasFailed() && ! pServer->GetSeverity() ) { pServer->SetMessageText(L""); } gData.AddDetailStats(&stats); gData.GetSummaryWindow(&hWnd); // get the stats for this job, and send them to the summary window
// SendMessage(hWnd, DCT_UPDATE_TOTALS, 0, (long)&stats);
SendMessage(hWnd, DCT_UPDATE_TOTALS, 0, (LPARAM)&stats); }
// also get import the security references
if (pServer->IsAccountReferenceResultExpected()) ProcessSecRefs(pServer,directory,filename); }
|