/*--------------------------------------------------------------------------- File: AgentMonitorDlg.cpp Comments: This dialog shows a list of the computers the agent is being dispatched to along with their status. (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 --------------------------------------------------------------------------- */// AgentMonitorDlg.cpp : implementation file // #include "stdafx.h" #include "resource.h" #include "MonDlg.h" #include "DetDlg.h" #include "scanlog.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #include "Common.hpp" #include "UString.hpp" #include "TNode.hpp" #include "ServList.hpp" #include "Monitor.h" #include "Globals.h" #include "ResStr.h" #include #include "helpid.h" #define COLUMN_COMPUTER 0 #define COLUMN_TIMESTAMP 1 #define COLUMN_STATUS 2 #define COLUMN_MESSAGE 3 #define SORT_COLUMN_BITS 0x03 #define SORT_REVERSE 0x80000000 BOOL bWaiting = FALSE; TCHAR* GetSystemDirectoryHelper(); // This is the sort function for the CListView int CALLBACK SortFunction(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) { int result = 0; TServerNode * n1 = (TServerNode*)lParam1; TServerNode * n2 = (TServerNode*)lParam2; if ( n1 && n2 ) { switch ( lParamSort & SORT_COLUMN_BITS ) { case COLUMN_COMPUTER: // Sort by names result = UStrICmp(n1->GetServer(),n2->GetServer()); break; case COLUMN_TIMESTAMP: result = UStrICmp(n1->GetTimeStamp(),n2->GetTimeStamp()); break; case COLUMN_STATUS: if ( n1->GetStatus() == n2->GetStatus() ) result = 0; else if ( n1->GetStatus() < n2->GetStatus() ) result = -1; else result = 1; break; case COLUMN_MESSAGE: result = UStrICmp(n1->GetMessageText(),n2->GetMessageText()); break; default: MCSVERIFY(FALSE); break; } } if ( lParamSort & SORT_REVERSE ) { result *= -1; } return result; } ///////////////////////////////////////////////////////////////////////////// // CAgentMonitorDlg dialog CAgentMonitorDlg::CAgentMonitorDlg(CWnd* pParent /*=NULL*/) : CPropertyPage(CAgentMonitorDlg::IDD) { //{{AFX_DATA_INIT(CAgentMonitorDlg) //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_SortColumn = 0; m_bReverseSort = FALSE; m_bSecTrans = TRUE; m_bReporting = FALSE; } void CAgentMonitorDlg::DoDataExchange(CDataExchange* pDX) { CPropertyPage::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAgentMonitorDlg) DDX_Control(pDX, IDC_DETAILS, m_DetailsButton); DDX_Control(pDX, IDC_SERVERLIST, m_ServerList); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CAgentMonitorDlg, CPropertyPage) //{{AFX_MSG_MAP(CAgentMonitorDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_NOTIFY(NM_DBLCLK, IDC_SERVERLIST, OnDblclkServerlist) ON_BN_CLICKED(IDC_VIEW_DISPATCH, OnViewDispatch) ON_BN_CLICKED(IDC_DETAILS, OnDetails) ON_NOTIFY(LVN_COLUMNCLICK, IDC_SERVERLIST, OnColumnclickServerlist) ON_NOTIFY(NM_CLICK, IDC_SERVERLIST, OnClickServerlist) ON_NOTIFY(LVN_GETDISPINFO, IDC_SERVERLIST, OnGetdispinfoServerlist) ON_NOTIFY(LVN_SETDISPINFO, IDC_SERVERLIST, OnSetdispinfoServerlist) ON_NOTIFY(HDN_ITEMCLICK, IDC_SERVERLIST, OnHeaderItemClickServerlist) ON_WM_HELPINFO() //}}AFX_MSG_MAP ON_MESSAGE(DCT_UPDATE_ENTRY, OnUpdateServerEntry) ON_MESSAGE(DCT_ERROR_ENTRY, OnServerError) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CAgentMonitorDlg message handlers BOOL CAgentMonitorDlg::OnInitDialog() { CPropertyPage::OnInitDialog(); // Setup the columns for the server list CString heading; heading.LoadString(IDS_ComputerColumnHeading); m_ServerList.InsertColumn(COLUMN_COMPUTER,heading,LVCFMT_LEFT,120); heading.LoadString(IDS_TimestampColumnHeading); m_ServerList.InsertColumn(COLUMN_TIMESTAMP,heading,LVCFMT_LEFT,120); heading.LoadString(IDS_StatusColumnHeading); m_ServerList.InsertColumn(COLUMN_STATUS,heading,LVCFMT_LEFT,120); heading.LoadString(IDS_MessageColumnHeading); m_ServerList.InsertColumn(COLUMN_MESSAGE,heading,LVCFMT_LEFT,200); // Read the server list to get any information we may have missed so far TNodeListEnum e; TServerList * pServerList = gData.GetUnsafeServerList(); TServerNode * pServer; gData.Lock(); for ( pServer = (TServerNode *)e.OpenFirst(pServerList) ; pServer ; pServer = (TServerNode *)e.Next() ) { if ( pServer->Include() ) { // OnUpdateServerEntry(0,(long)pServer); OnUpdateServerEntry(0,(LPARAM)pServer); } } e.Close(); gData.Unlock(); gData.SetListWindow(m_hWnd); m_DetailsButton.EnableWindow(m_ServerList.GetSelectedCount()); CString str; str.LoadString(IDS_WaitingMessage); m_ServerList.InsertItem(0,str); bWaiting = TRUE; return TRUE; // return TRUE unless you set the focus to a control } void CAgentMonitorDlg::OnSysCommand(UINT nID, LPARAM lParam) { CPropertyPage::OnSysCommand(nID, lParam); } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CAgentMonitorDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CPropertyPage::OnPaint(); } } // The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CAgentMonitorDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } //LRESULT CAgentMonitorDlg::OnUpdateServerEntry(UINT nID, long x) LRESULT CAgentMonitorDlg::OnUpdateServerEntry(UINT nID, LPARAM x) { TServerNode * pNode = (TServerNode *)x; LVFINDINFO findInfo; CString timestamp; CWaitCursor w; memset(&findInfo,0,(sizeof findInfo)); // This turns off the initial hourglass in the dispatch monitor if ( bWaiting ) { if ( pNode ) { AfxGetApp()->DoWaitCursor(-1); if ( m_ServerList.GetItemCount() == 1 ) { m_ServerList.DeleteItem(0); } } else { BOOL bLDone; gData.GetLogDone(&bLDone); if ( bLDone ) { AfxGetApp()->DoWaitCursor(-1); if ( m_ServerList.GetItemCount() == 1 ) { m_ServerList.DeleteItem(0); CString str; str.LoadString(IDS_NoServersMessage); m_ServerList.InsertItem(0,str); } } } } bWaiting = FALSE; if ( pNode ) { findInfo.flags = LVFI_STRING; findInfo.psz = pNode->GetServer(); int ndx = m_ServerList.FindItem(&findInfo); if ( ndx == -1 ) { // add the server to the list ndx = m_ServerList.GetItemCount(); // m_ServerList.InsertItem(LVIF_TEXT | LVIF_PARAM,ndx,pNode->GetServer(),0,0,0,(long)pNode); m_ServerList.InsertItem(LVIF_TEXT | LVIF_PARAM,ndx,pNode->GetServer(),0,0,0,(LPARAM)pNode); if ( m_bReverseSort ) { m_ServerList.SortItems(&SortFunction,m_SortColumn | SORT_REVERSE); } else { m_ServerList.SortItems(&SortFunction,m_SortColumn); } } m_ServerList.RedrawItems(ndx,ndx); } return 0; } //LRESULT CAgentMonitorDlg::OnServerError(UINT nID, long x) LRESULT CAgentMonitorDlg::OnServerError(UINT nID, LPARAM x) { TServerNode * pNode = (TServerNode *)x; LVFINDINFO findInfo; CString timestamp; CWaitCursor w; memset(&findInfo,0,(sizeof findInfo)); // This turns off the initial hourglass in the dispatch monitor if ( bWaiting ) { if ( pNode ) { AfxGetApp()->DoWaitCursor(-1); if ( m_ServerList.GetItemCount() == 1 ) { m_ServerList.DeleteItem(0); } } else { BOOL bLDone; gData.GetLogDone(&bLDone); if ( bLDone ) { AfxGetApp()->DoWaitCursor(-1); if ( m_ServerList.GetItemCount() == 1 ) { m_ServerList.DeleteItem(0); CString str; str.LoadString(IDS_NoServersMessage); m_ServerList.InsertItem(0,str); } } } } bWaiting = FALSE; findInfo.flags = LVFI_STRING; findInfo.psz = pNode->GetServer(); int ndx = m_ServerList.FindItem(&findInfo); if ( ndx == -1 ) { // add the server to the list ndx = m_ServerList.GetItemCount(); // m_ServerList.InsertItem(LVIF_TEXT | LVIF_PARAM,ndx,pNode->GetServer(),0,0,0,(long)pNode); m_ServerList.InsertItem(LVIF_TEXT | LVIF_PARAM,ndx,pNode->GetServer(),0,0,0,(LPARAM)pNode); if ( m_bReverseSort ) { m_ServerList.SortItems(&SortFunction,m_SortColumn | SORT_REVERSE); } else { m_ServerList.SortItems(&SortFunction,m_SortColumn); } } // the subitems will be callbacks m_ServerList.RedrawItems(ndx,ndx); return 0; } void CAgentMonitorDlg::OnDblclkServerlist(NMHDR* pNMHDR, LRESULT* pResult) { OnDetails(); *pResult = 0; } void CAgentMonitorDlg::OnViewDispatch() { WCHAR filename[MAX_PATH]; CString cmd; STARTUPINFO startupInfo; PROCESS_INFORMATION processInfo; TCHAR* pszSystemDirectoryName = NULL; CString message; CString title; memset(&startupInfo,0,(sizeof startupInfo)); startupInfo.cb = (sizeof startupInfo); gData.GetReadableLogFile(filename); pszSystemDirectoryName = GetSystemDirectoryHelper(); if(!pszSystemDirectoryName) { // we could not get the system directory name, we should bail out, otherwise we might launch // malicious process title.LoadString(IDS_MessageTitle); message.LoadString(IDS_LaunchNotePadFailed); MessageBox(message,title, MB_ICONERROR | MB_OK); return; } cmd.FormatMessage(IDS_NotepadCommandLine, pszSystemDirectoryName, filename); delete [] pszSystemDirectoryName; CreateProcess(NULL,cmd.GetBuffer(0),NULL,NULL,TRUE,0,NULL,NULL,&startupInfo,&processInfo); } void CAgentMonitorDlg::OnDetails() { const int NOT_FOUND = -1; //indicates no match in search - PRT const int WHOLE_LIST = -1; //index to start search of whole list - PRT UpdateData(TRUE); // POSITION p = m_ServerList.GetFirstSelectedItemPosition(); // if ( p ) // { // int ndx = m_ServerList.GetNextSelectedItem(p); //search whole list control for first (and only) selected item int ndx = m_ServerList.GetNextItem(WHOLE_LIST, LVNI_SELECTED); //PRT //if found selected item, disply it's details if (ndx != NOT_FOUND) //PRT { //PRT CString serverName; serverName = m_ServerList.GetItemText(ndx,0); if ( serverName.GetLength() ) { // Launch the details dialog CAgentDetailDlg det; gData.Lock(); TServerNode * s = gData.GetUnsafeServerList()->FindServer((LPCTSTR)serverName); gData.Unlock(); if ( s ) { det.SetNode(s); if ( ! m_bSecTrans ) { det.SetFormat(-1); } if ( m_bReporting ) { det.SetGatheringInfo(TRUE); } if ( s->IsFinished() && *s->GetJobFile() ) { DetailStats detailStats; WCHAR directory[MAX_PATH]; WCHAR filename[MAX_PATH]; CString plugInText; gData.GetResultDir(directory); memset(&detailStats,0,(sizeof detailStats)); swprintf(filename,GET_STRING(IDS_AgentResultFileFmt),s->GetJobFile()); if ( SUCCEEDED(CoInitialize(NULL)) ) { if ( ReadResults(s,directory,filename,&detailStats,plugInText,FALSE) ) { det.SetStats(&detailStats); det.SetPlugInText(plugInText); det.SetLogFile(s->GetLogPath()); det.SetLogFileValid(s->GetLogPathValid()); } CoUninitialize(); } } det.DoModal(); } } } UpdateData(FALSE); } void CAgentMonitorDlg::OnColumnclickServerlist(NMHDR* pNMHDR, LRESULT* pResult) { CWaitCursor w; NM_LISTVIEW * pNMListView = (NM_LISTVIEW*)pNMHDR; // sort by pNMListView->iSubItem if ( m_SortColumn == pNMListView->iSubItem ) { m_bReverseSort = ! m_bReverseSort; } else { m_bReverseSort = FALSE; } m_SortColumn = pNMListView->iSubItem; if ( m_bReverseSort ) { m_ServerList.SortItems(&SortFunction,m_SortColumn | SORT_REVERSE); } else { m_ServerList.SortItems(&SortFunction,m_SortColumn); } *pResult = 0; } void CAgentMonitorDlg::OnClickServerlist(NMHDR* pNMHDR, LRESULT* pResult) { const int NOT_FOUND = -1; //indicates no match in search - PRT const int WHOLE_LIST = -1; //index to start search of whole list - PRT UpdateData(TRUE); if ( m_ServerList.GetSelectedCount() ) { // POSITION p = m_ServerList.GetFirstSelectedItemPosition(); // if ( p ) // { //search whole list control for first (and only) selected item int ndx = m_ServerList.GetNextItem(WHOLE_LIST, LVNI_SELECTED); //PRT //if found selected item, disply it's details if (ndx != NOT_FOUND) //PRT { //PRT CString msg1; CString msg2; // int ndx = m_ServerList.GetNextSelectedItem(p); CString serverName; serverName = m_ServerList.GetItemText(ndx,0); msg1.LoadString(IDS_WaitingMessage); msg2.LoadString(IDS_NoServersMessage); if ( serverName.Compare(msg1) && serverName.Compare(msg2) ) { m_DetailsButton.EnableWindow(TRUE); } else { m_DetailsButton.EnableWindow(FALSE); } } } else { m_DetailsButton.EnableWindow(FALSE); } UpdateData(FALSE); *pResult = 0; } WCHAR gMessage[1000]; void CAgentMonitorDlg::OnGetdispinfoServerlist(NMHDR* pNMHDR, LRESULT* pResult) { LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR; // find iItem in the serverList, and set the pszText for the iSubItem appropriately CString status; TServerNode * pNode = NULL; CString timestamp; WCHAR * text = gMessage; CString serverName; WCHAR convertedTimestamp[MAX_PATH]; WCHAR* originalTimestamp; status.LoadString(IDS_Status_Unknown); serverName = m_ServerList.GetItemText(pDispInfo->item.iItem,0); if ( serverName.GetLength() ) { gData.Lock(); pNode = gData.GetUnsafeServerList()->FindServer(serverName.GetBuffer(0)); gData.Unlock(); if ( pNode ) { switch ( pDispInfo->item.iSubItem ) { case COLUMN_TIMESTAMP: originalTimestamp = pNode->GetTimeStamp(); timestamp = (ConvertToLocalUserDefault(originalTimestamp, convertedTimestamp, sizeof(convertedTimestamp)/sizeof(convertedTimestamp[0]))) ? convertedTimestamp : originalTimestamp; if ( timestamp.Right(1) == "\n" ) { timestamp = timestamp.Left(timestamp.GetLength() - 1); } //text = new char[timestamp.GetLength() + 1]; UStrCpy(text,timestamp.GetBuffer(0)); pDispInfo->item.pszText = text; break; case COLUMN_STATUS: if ( pNode->HasFailed() ) { status.LoadString(IDS_Status_InstallFailed); } if ( pNode->IsInstalled() ) { if ( ! pNode->HasFailed() ) status.LoadString(IDS_Status_Installed); else status.LoadString(IDS_Status_DidNotStart); } if ( pNode->GetStatus() & Agent_Status_Started ) { if ( ! pNode->HasFailed() ) status.LoadString(IDS_Status_Running); else status.LoadString(IDS_Status_Failed); } if ( pNode->IsFinished() ) { if (pNode->QueryFailed()) { // we show "Status Unknown" in the status field status.LoadString(IDS_Status_Unknown); } else if (!pNode->IsResultPullingTried() || (pNode->HasResult() && !pNode->IsResultProcessed())) { // if still pulling results or results not yet processed // we want to show the status of still running status.LoadString(IDS_Status_Running); } else { if (!pNode->HasResult()) { // if there is no result, we consider it an error status.LoadString(IDS_Status_Completed_With_Errors); } else if ( ! pNode->GetSeverity() ) { // if we have the result and no error happened during agent operation // we show the status of complete status.LoadString(IDS_Status_Completed); } else { // if we have the result, we set the status // based on the error/warning level switch ( pNode->GetSeverity() ) { case 1: status.LoadString(IDS_Status_Completed_With_Warnings); break; case 2: status.LoadString(IDS_Status_Completed_With_Errors); break; case 3: default: status.LoadString(IDS_Status_Completed_With_SErrors); break; } } } } UStrCpy(text,status); pDispInfo->item.pszText = text; break; case COLUMN_MESSAGE: { BOOL bUpdate = TRUE; if (pNode->IsFinished() && pNode->QueryFailed()) { // in this case, we show the error during the query status = pNode->GetMessageText(); } else if (pNode->IsFinished() && (!pNode->IsResultPullingTried() || (pNode->HasResult() && !pNode->IsResultProcessed()))) { // if agent has finished but result not yet pulled or processed, // we show the status of "still processing results" status.LoadString(IDS_Status_Processing_Results); } else if (pNode->IsFinished() && pNode->IsResultPullingTried() && !pNode->HasResult()) { // if agent finished but we cannot retrieve results // we show the status of "cannot retrieve results" status.LoadString(IDS_Status_Cannot_Retrieve_Results); } else if ( pNode->HasFailed() || pNode->QueryFailed() || pNode->GetSeverity() || pNode->IsFinished()) { // for these cases, we get the message stored on the node status = pNode->GetMessageText(); } else { bUpdate = FALSE; } if (bUpdate) { UStrCpy(text, (LPCTSTR)status); pDispInfo->item.pszText = text; } } break; } } } *pResult = 0; } BOOL CAgentMonitorDlg::OnSetActive() { BOOL rc = CPropertyPage::OnSetActive(); CancelToClose(); return rc; } void CAgentMonitorDlg::OnSetdispinfoServerlist(NMHDR* pNMHDR, LRESULT* pResult) { LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR; // TODO: Add your control notification handler code here *pResult = 0; } void CAgentMonitorDlg::OnHeaderItemClickServerlist(NMHDR* pNMHDR, LRESULT* pResult) { HD_NOTIFY *phdn = (HD_NOTIFY *) pNMHDR; // TODO: Add your control notification handler code here *pResult = 0; } void CAgentMonitorDlg::OnOK() { CPropertyPage::OnOK(); } BOOL CAgentMonitorDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) { LPNMHDR lpnm = (LPNMHDR) lParam; switch (lpnm->code) { case PSN_HELP : helpWrapper(m_hWnd, IDH_WINDOW_AGENT_SERVER_LIST ); break; } return CPropertyPage::OnNotify(wParam, lParam, pResult); } BOOL CAgentMonitorDlg::OnHelpInfo(HELPINFO* pHelpInfo) { helpWrapper(m_hWnd, IDH_WINDOW_AGENT_SERVER_LIST ); return CPropertyPage::OnHelpInfo(pHelpInfo); }