// RemoteAdminDoc.cpp : implementation of the CRemoteAdminDoc class
//
#include "stdafx.h"
#include "RemoteAdminDoc.h"
#include "MachineInfo.h"
#include "GlobalMFCHelperFunc.h"
#include "GlobalHelperFunc.h"
#include "MachineView.h"
#include "resource.h"
#include "RemoteAdminView.h"
#include "MainFrame.h"
#include "RemoteAdmin.h"
#include "ProgressWndThread.h"
#include "ProcessUpdate.h"
#include "ConnectionThread.h"
#include <process.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
extern CRITICAL_SECTION g_CriticalSection;
/////////////////////////////////////////////////////////////////////////////
// CRemoteAdminDoc
IMPLEMENT_DYNCREATE(CRemoteAdminDoc, CDocument)
BEGIN_MESSAGE_MAP(CRemoteAdminDoc, CDocument)
//{{AFX_MSG_MAP(CRemoteAdminDoc)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CRemoteAdminDoc construction/destruction
CRemoteAdminDoc::CRemoteAdminDoc()
{
m_hUpdateProcessList = NULL;
m_pVisualProgressThread = NULL;
}
CRemoteAdminDoc::~CRemoteAdminDoc()
{
}
BOOL CRemoteAdminDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
unsigned int threadID;
/*
m_threadForUpdateProcessList = ::AfxBeginThread(
UpdateProcessListForAllMachines,
this,
THREAD_PRIORITY_NORMAL,
0,
CREATE_SUSPENDED
*/ // );
// Prepare the SDocView structure to pass wrapped pointers values of the
// document, view(s), mainframe. They are being sent this way as a worker thread
// can't call the functions UI (GetMachineView, GetMainFrame etc)
// involving windows, because of crashes, hence this workaround!
SDocView* pDocView = new SDocView;
pDocView->pDoc = this;
pDocView->pMachineView = MFC_DocView::GetMachineView();
pDocView->pRemoteAdminView = MFC_DocView::GetRemoteAdminView();
m_hUpdateProcessList = reinterpret_cast<HANDLE>(::_beginthreadex(
NULL,
0,
ProcessUpdate::UpdateProcessListForAllMachines,
pDocView,
CREATE_SUSPENDED,
&threadID)
);
return TRUE;
}
void CRemoteAdminDoc::CreateVisualThread()
{
if (m_pVisualProgressThread == NULL)
{
m_pVisualProgressThread = static_cast<CProgressWndThread*>(::AfxBeginThread(RUNTIME_CLASS(CProgressWndThread), THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED));
if (m_pVisualProgressThread != NULL)
{
m_pVisualProgressThread->SetDocument(this);
m_pVisualProgressThread->ResumeThread();
}
}
}
/////////////////////////////////////////////////////////////////////////////
// CRemoteAdminDoc serialization
void CRemoteAdminDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
CString* pstrConnctedMachinesIP = NULL;
int iNumberOfConnectedMachines = 0;
GetConnectedMachinesIP(&pstrConnctedMachinesIP, &iNumberOfConnectedMachines);
// Serialize the number of machines last beging monitored
ar << iNumberOfConnectedMachines;
// Serialize the Machine Informations
for (int i = 0; i < iNumberOfConnectedMachines; ++i)
{
CMachineInfo* pMachineInfo = m_RemoteAdministrator.GetMachineInfo(pstrConnctedMachinesIP[i]);
ar << pMachineInfo;
}
// Free memory
if (pstrConnctedMachinesIP != NULL)
{
delete[] pstrConnctedMachinesIP;
}
}
else
{
m_milInfoReadFromArchiveList = new CMachineInfoList;
int iNumberOfConnectedMachines = 0;
CMachineInfo* pMachineInfo = NULL;
ar >> iNumberOfConnectedMachines;
for (int i = 0; i < iNumberOfConnectedMachines; ++i)
{
ar >> pMachineInfo;
m_milInfoReadFromArchiveList->AddTail(pMachineInfo);
}
}
}
/////////////////////////////////////////////////////////////////////////////
// CRemoteAdminDoc diagnostics
#ifdef _DEBUG
void CRemoteAdminDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CRemoteAdminDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
void CRemoteAdminDoc::AddMachine(CMachineInfo& miMachineInfo)
{
m_RemoteAdministrator.AddMachine(miMachineInfo);
}
void CRemoteAdminDoc::DeleteMachine(CMachineInfo& miMachineInfo)
{
m_RemoteAdministrator.DeleteMachine(miMachineInfo);
}
BOOL CRemoteAdminDoc::CheckIfMachinePresent(CString strIP)
{
BOOL bSuccess = m_RemoteAdministrator.CheckIfMachinePresent(strIP);
return bSuccess;
}
BOOL CRemoteAdminDoc::EstablishAllConnections(CString strRemoteMachineIP, CString strPwd, BOOL bEstablish, CMachineView* pMachineView, CRemoteAdminView* pRemoteAdminView)
{
ASSERT(pRemoteAdminView);
ASSERT(pMachineView);
BOOL bConnectionSuccess = FALSE;
BOOL bCopyServiceExe = FALSE;
BOOL bStartAndInstallService = FALSE;
BOOL bConnectToRemoteService = FALSE;
// The service may be running already, so try to connect directly
bConnectToRemoteService = ConnectToRemoteService(strRemoteMachineIP, strPwd, pMachineView, pRemoteAdminView);
if (!bConnectToRemoteService)
{
bConnectionSuccess = m_RemoteAdministrator.EstablishAllConnections(strRemoteMachineIP, strPwd, bEstablish);
if (!bConnectionSuccess)
{
CString strFormattedErrorMsg = ErrorHandling::ConvertStringTableIDToErrorMsg(strRemoteMachineIP, IDS_CONNECTION_NOT_ESTABLISHED);
//CRemoteAdminApp* pApp = static_cast<CRemoteAdminApp*>(::AfxGetApp());
(MFC_DocView::GetApp())->ShowBalloonMsgInTray(_T("Remote connection error !"), strFormattedErrorMsg);
}
bCopyServiceExe = m_RemoteAdministrator.CopyServiceExeToRemoteMachine(strRemoteMachineIP);
if (!bCopyServiceExe)
{
CString strFormattedErrorMsg = ErrorHandling::ConvertStringTableIDToErrorMsg(strRemoteMachineIP, IDS_NOT_COPY_SERVICE_EXE);
//CRemoteAdminApp* pApp = static_cast<CRemoteAdminApp*>(::AfxGetApp());
(MFC_DocView::GetApp())->ShowBalloonMsgInTray(_T("Service executable copying error !"), strFormattedErrorMsg);
}
bStartAndInstallService = m_RemoteAdministrator.InstallAndStartRemoteService(strRemoteMachineIP);
if (!bStartAndInstallService)
{
CString strFormattedErrorMsg = ErrorHandling::ConvertStringTableIDToErrorMsg(strRemoteMachineIP, IDS_NOT_START_SERVICE);
//CRemoteAdminApp* pApp = static_cast<CRemoteAdminApp*>(::AfxGetApp());
(MFC_DocView::GetApp())->ShowBalloonMsgInTray(_T("Remote service starting error !"), strFormattedErrorMsg);
}
// Do some time pass, for stabilization at the remote end
::Sleep(2000);
bConnectToRemoteService = ConnectToRemoteService(strRemoteMachineIP, strPwd, pMachineView, pRemoteAdminView);
if (!bConnectToRemoteService)
{
CString strFormattedErrorMsg = ErrorHandling::ConvertStringTableIDToErrorMsg(strRemoteMachineIP, IDS_NO_CONNECT_TO_REMOTE_SERVICE);
//CRemoteAdminApp* pApp = static_cast<CRemoteAdminApp*>(::AfxGetApp());
(MFC_DocView::GetApp())->ShowBalloonMsgInTray(_T("Connection error !"), strFormattedErrorMsg);
}
if (bConnectionSuccess && bCopyServiceExe && bStartAndInstallService && bConnectToRemoteService)
{
return TRUE;
}
}
return bConnectToRemoteService;
}
BOOL CRemoteAdminDoc::CopyServiceExeToRemoteMachine(CString strRemoteMachineIP)
{
return m_RemoteAdministrator.CopyServiceExeToRemoteMachine(strRemoteMachineIP);
}
void CRemoteAdminDoc::RefreshProcessList(CString strRemoteMachineIP, CProcessInfoList& pilList)
{
m_RemoteAdministrator.RefreshProcessList(strRemoteMachineIP, pilList);
}
CProcessInfoList* CRemoteAdminDoc::GetProcessInfoList(CString strRemoteMachineIP)
{
return m_RemoteAdministrator.GetProcessInfoList(strRemoteMachineIP);
}
void CRemoteAdminDoc::DeleteAndDisconnectAllMachines()
{
m_RemoteAdministrator.DeleteAndDisconnectAllMachines();
}
void CRemoteAdminDoc::DeleteAndDisconnectMachine(CString strRemoteAdminMachine)
{
m_RemoteAdministrator.DeleteAndDisconnectMachine(strRemoteAdminMachine);
}
void CRemoteAdminDoc::OnCloseDocument()
{
DeleteAndDisconnectAllMachines();
CDocument::OnCloseDocument();
}
BOOL CRemoteAdminDoc::ConnectToRemoteService(CString strRemoteMachineIP, CString strPwd, CMachineView* pMachineView, CRemoteAdminView* pRemoteAdminView)
{
CMachineInfo* pMachineInfo = new CMachineInfo;
pMachineInfo->SetLogon(_T("Administrator"));
pMachineInfo->SetIP(strRemoteMachineIP);
pMachineInfo->SetPassword(strPwd);
m_RemoteAdministrator.AddMachine(*pMachineInfo);
BOOL bConnectToRemoteService = FALSE;
bConnectToRemoteService = m_RemoteAdministrator.ConnectToRemoteService(strRemoteMachineIP, 1, 0);
if (bConnectToRemoteService)
{
pMachineView->ShowNewMachine(strRemoteMachineIP, pMachineInfo);
HTREEITEM h = pMachineView->GetTreeItemForText(strRemoteMachineIP);
if (h != NULL)
{
pMachineView->GetTreeCtrl().Select(h, TVGN_CARET);
pRemoteAdminView->GetListCtrl().DeleteAllItems();
pRemoteAdminView->GetListCtrl().InsertItem(0, _T("Refreshing process list..."));
::Sleep(2000);
if (pMachineInfo)
{
delete pMachineInfo;
}
return TRUE;
}
else
{
if (pMachineInfo)
{
delete pMachineInfo;
}
return FALSE;
}
}
else
{
m_RemoteAdministrator.DeleteMachine(*pMachineInfo);
if (pMachineInfo)
{
delete pMachineInfo;
}
return FALSE;
}
}
void CRemoteAdminDoc::GetConnectedMachinesIP(CString** pstrConnctedMachinesIP /*out*/, int* piNumberOfConnectedMachines/*out*/)
{
m_RemoteAdministrator.GetConnectedMachinesIP(pstrConnctedMachinesIP, piNumberOfConnectedMachines);
}
int CRemoteAdminDoc::GetTotalMachinesMonitored()
{
return m_RemoteAdministrator.GetTotalMachinesMonitored();
}
BOOL CRemoteAdminDoc::AddToConnectionPendingList(CString strIP)
{
return m_RemoteAdministrator.AddToConnectionPendingList(strIP);
}
BOOL CRemoteAdminDoc::RemoveFromConnecionPendingList(CString strIP)
{
return m_RemoteAdministrator.RemoveFromConnecionPendingList(strIP);
}
BOOL CRemoteAdminDoc::IsConnectionPending(CString strIP)
{
return m_RemoteAdministrator.IsConnectionPending(strIP);
}
BOOL CRemoteAdminDoc::OnSaveDocument(LPCTSTR lpszPathName)
{
return CDocument::OnSaveDocument(lpszPathName);
}
BOOL CRemoteAdminDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
// << BLOCK start
// << Commented by Prateek Kaul on July 28, 2003.
// It is better to make a clean exit (making the thread return), rather than terminating
// the thread forcefully.
// Kill the thread that is updating the process list
/*if (m_hUpdateProcessList != NULL)
{
::TerminateThread(m_hUpdateProcessList, 0);
m_hUpdateProcessList = NULL;
}*/
// << BLOCK end
// Make the ProcessUpdate::UpdateProcessListForAllMachines(), i.e the thread function
// that updates the process list for all machines end (return gracefully)
// by setting the flag, rather terminate it forcefully
extern BOOL g_bUpdateProcessList;
g_bUpdateProcessList = FALSE;
// Wait for few secs to allow the thread terminate, it may be in the middle of a
// calculation
::Sleep(3000);
// No need to keep a track of the ProcessUpdate::UpdateProcessListForAllMachines() thread handle
if (m_hUpdateProcessList != NULL)
{
m_hUpdateProcessList = NULL;
}
// Close all connections and clean up the data structures for all
// connected machines
DeleteAndDisconnectAllMachines();
// Allow the new ProcessUpdate::UpdateProcessListForAllMachines() thread function, which will
// be triggered below, to proceed gracefully.
g_bUpdateProcessList = TRUE;
if (!CDocument::OnOpenDocument(lpszPathName))
return FALSE;
// Since the MachineInfo List has been serailzed from
// the archive, we need to make connections for the machines
// in the list.
CMachineInfo* pMachineInfo = NULL;
POSITION pos = m_milInfoReadFromArchiveList->GetHeadPosition();
// Start connections to the Machines whose CMachineInfo class have
// been read from the archive. They have been read in the m_milInfoReadFromArchiveList.
while (pos != NULL)
{
pMachineInfo = m_milInfoReadFromArchiveList->GetNext(pos);
SConnectInfo* pConnectInfo = new SConnectInfo;
pConnectInfo->pDoc = MFC_DocView::GetAppDocument();
pConnectInfo->pMachineView = MFC_DocView::GetMachineView();
pConnectInfo->pRemoteAdminView = MFC_DocView::GetRemoteAdminView();
pConnectInfo->strIP = pMachineInfo->GetIP();
pConnectInfo->strPwd = pMachineInfo->GetPassword();
// Start the thread that will process the connection
unsigned threadID = 0;
::_beginthreadex(NULL, 0, ThreadConnection::ConnectToMachine, pConnectInfo, 0, &threadID);
}
// Since all machines have been read from the archive, dispose off the list.
if (m_milInfoReadFromArchiveList != NULL)
{
CMachineInfo* pMachineInfo = NULL;
POSITION pos = m_milInfoReadFromArchiveList->GetHeadPosition();
while (pos != NULL)
{
pMachineInfo = m_milInfoReadFromArchiveList->GetNext(pos);
ASSERT(pMachineInfo != NULL);
if (pMachineInfo != NULL)
{
delete pMachineInfo;
}
}
delete m_milInfoReadFromArchiveList;
m_milInfoReadFromArchiveList = NULL;
}
// Now start the thread that retrieves the processes running on the remotely
// connected machines, in suspended state
unsigned int threadID;
SDocView* pDocView = new SDocView;
pDocView->pDoc = this;
pDocView->pMachineView = MFC_DocView::GetMachineView();
pDocView->pRemoteAdminView = MFC_DocView::GetRemoteAdminView();
m_hUpdateProcessList = reinterpret_cast<HANDLE>(::_beginthreadex(
NULL,
0,
ProcessUpdate::UpdateProcessListForAllMachines,
pDocView,
CREATE_SUSPENDED,
&threadID)
);
CreateVisualThread();
return TRUE;
}
void CRemoteAdminDoc::DeleteContents()
{
DeleteAndDisconnectAllMachines();
CDocument::DeleteContents();
}
BOOL CRemoteAdminDoc::CanCloseFrame(CFrameWnd* pFrame)
{
// TODO: Add your specialized code here and/or call the base class
return CDocument::CanCloseFrame(pFrame);
}
CString CRemoteAdminDoc::GetPasswordForMachine(CString strIP)
{
return m_RemoteAdministrator.GetPassword(strIP);
}
BOOL CRemoteAdminDoc::AreConnectionsStillPending()
{
UINT iMachines = m_RemoteAdministrator.GetNumberOfMachineConnectionsStillInProgress();
if (iMachines == 0) // No connections pending...
{
return FALSE;
}
return TRUE;
}
UINT CRemoteAdminDoc::GetNumberOfMachineConnectionsStillInProgress()
{
return m_RemoteAdministrator.GetNumberOfMachineConnectionsStillInProgress();
}
CString CRemoteAdminDoc::GetComputerNameFromIP(CString& strIP)
{
return m_RemoteAdministrator.GetComputerNameFromIP(strIP);
}
CString CRemoteAdminDoc::GetComputerIPFromName(CString& strComputerName)
{
return m_RemoteAdministrator.GetComputerIPFromName(strComputerName);
}