1236 lines
29 KiB
C++
1236 lines
29 KiB
C++
/**********************************************************************/
|
|
/** Microsoft Windows/NT **/
|
|
/** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
info.cpp
|
|
|
|
FILE HISTORY:
|
|
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
#include "infoi.h"
|
|
#include "rtrstr.h" // common router strings
|
|
#include "refresh.h"
|
|
#include "dvsview.h"
|
|
#include "machine.h"
|
|
#include "rtrutilp.h"
|
|
|
|
|
|
// Number of connections that we have made, this is used to
|
|
// generate the dwConnectionId
|
|
extern long s_cConnections;
|
|
|
|
DEBUG_DECLARE_INSTANCE_COUNTER(RefreshItem);
|
|
|
|
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
RouterObjectRefreshTimerProc
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
void RouterRefreshObjectTimerProc(LPARAM lParam, DWORD dwTime)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
// The lParam passed in is a pointer to the RouterRefreshObject
|
|
|
|
// Call through on the RouterRefreshObject to start the query
|
|
// object
|
|
((RouterRefreshObject *)lParam)->ExecuteRefresh();
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
RouterRefreshObjectGroup implementation
|
|
---------------------------------------------------------------------------*/
|
|
|
|
DEBUG_DECLARE_INSTANCE_COUNTER(RouterRefreshObjectGroup);
|
|
|
|
RouterRefreshObjectGroup::~RouterRefreshObjectGroup()
|
|
{
|
|
POSITION p = NULL;
|
|
RouterRefreshObject* pObj = NULL;
|
|
for(p = m_list.GetHeadPosition(); p != NULL; )
|
|
{
|
|
pObj = m_list.GetNext(p);
|
|
Assert(pObj != NULL);
|
|
pObj->SetGroup(NULL);
|
|
pObj->Release();
|
|
}
|
|
|
|
m_list.RemoveAll();
|
|
|
|
DEBUG_DECREMENT_INSTANCE_COUNTER(RouterRefreshObjectGroup);
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
RouterRefreshObjectGroup::Join
|
|
-
|
|
Author: WeiJiang
|
|
---------------------------------------------------------------------------*/
|
|
HRESULT RouterRefreshObjectGroup::Join(RouterRefreshObject* pRefresh)
|
|
{
|
|
Assert(pRefresh);
|
|
HRESULT hr = hrOK;
|
|
|
|
COM_PROTECT_TRY
|
|
{
|
|
m_list.AddTail(pRefresh);
|
|
pRefresh->AddRef();
|
|
pRefresh->SetGroup(this);
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
return hr;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
RouterRefreshObjectGroup::Leave
|
|
-
|
|
Author: WeiJiang
|
|
---------------------------------------------------------------------------*/
|
|
HRESULT RouterRefreshObjectGroup::Leave(RouterRefreshObject* pRefresh)
|
|
{
|
|
POSITION p = m_list.Find(pRefresh);
|
|
|
|
if (p)
|
|
{
|
|
Assert(pRefresh == m_list.GetAt(p));
|
|
m_list.RemoveAt(p);
|
|
pRefresh->SetGroup(NULL);
|
|
pRefresh->Release();
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
RouterRefreshObjectGroup::Refresh
|
|
call each member in the group to DoRefresh
|
|
Author: WeiJiang
|
|
---------------------------------------------------------------------------*/
|
|
HRESULT RouterRefreshObjectGroup::Refresh()
|
|
{
|
|
POSITION p = NULL;
|
|
RouterRefreshObject* pObj = NULL;
|
|
for(p = m_list.GetHeadPosition(); p != NULL; )
|
|
{
|
|
pObj = m_list.GetNext(p);
|
|
Assert(pObj != NULL);
|
|
pObj->DoRefresh();
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
RouterRefreshObject implementation
|
|
---------------------------------------------------------------------------*/
|
|
|
|
IMPLEMENT_ADDREF_RELEASE(RouterRefreshObject);
|
|
|
|
DEBUG_DECLARE_INSTANCE_COUNTER(RouterRefreshObject);
|
|
|
|
STDMETHODIMP RouterRefreshObject::QueryInterface(REFIID iid,void **ppv)
|
|
{
|
|
*ppv = 0;
|
|
if (iid == IID_IUnknown)
|
|
*ppv = (IUnknown *) (IRouterRefresh *) this;
|
|
else if (iid == IID_IRouterRefresh)
|
|
*ppv = (IRouterRefresh *) this;
|
|
else if (iid == IID_IRouterRefreshModify)
|
|
*ppv = (IRouterRefreshModify *) this;
|
|
else
|
|
return ThreadHandler::QueryInterface(iid, ppv);
|
|
|
|
((IUnknown *) *ppv)->AddRef();
|
|
return hrOK;
|
|
}
|
|
|
|
|
|
RouterRefreshObject::RouterRefreshObject(HWND hWndSync)
|
|
: m_hWndSync(hWndSync),
|
|
m_dwSeconds(DEFAULT_REFRESH_INTERVAL),
|
|
m_iEventId(-1),
|
|
m_pRefreshGroup(NULL),
|
|
m_fStarted(FALSE),
|
|
m_fInRefresh(FALSE)
|
|
{
|
|
DEBUG_INCREMENT_INSTANCE_COUNTER(RouterRefreshObject);
|
|
InitializeCriticalSection(&m_critsec);
|
|
}
|
|
|
|
RouterRefreshObject::~RouterRefreshObject()
|
|
{
|
|
// Shut down the timer if its started
|
|
Stop();
|
|
|
|
DEBUG_DECREMENT_INSTANCE_COUNTER(RouterRefreshObject);
|
|
|
|
DeleteCriticalSection(&m_critsec);
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
RouterRefreshObject::GetRefreshInterval
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
STDMETHODIMP RouterRefreshObject::GetRefreshInterval(DWORD *pdwSeconds)
|
|
{
|
|
RtrCriticalSection rtrCritSec(&m_critsec);
|
|
HRESULT hr = hrOK;
|
|
|
|
if (pdwSeconds == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
COM_PROTECT_TRY
|
|
{
|
|
if (pdwSeconds)
|
|
*pdwSeconds = m_dwSeconds;
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
return hr;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
RouterRefreshObject::GetRefreshInterval
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
STDMETHODIMP RouterRefreshObject::SetRefreshInterval(DWORD dwSeconds)
|
|
{
|
|
HRESULT hr = hrOK;
|
|
if (IsRefreshStarted() == hrOK)
|
|
{
|
|
Stop();
|
|
Start(dwSeconds);
|
|
}
|
|
else
|
|
{
|
|
RtrCriticalSection rtrCritSec(&m_critsec);
|
|
m_dwSeconds = dwSeconds;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
RouterRefreshObject::IsInRefresh
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
STDMETHODIMP RouterRefreshObject::IsInRefresh()
|
|
{
|
|
RtrCriticalSection rtrCritSec(&m_critsec);
|
|
HRESULT hr = hrOK;
|
|
COM_PROTECT_TRY
|
|
{
|
|
hr = (m_fInRefresh) ? hrOK : hrFalse;
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
return hr;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
RouterRefreshObject::Refresh
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
STDMETHODIMP RouterRefreshObject::Refresh()
|
|
{
|
|
if (m_pRefreshGroup)
|
|
{
|
|
return m_pRefreshGroup->Refresh();
|
|
}
|
|
else
|
|
{
|
|
return DoRefresh();
|
|
}
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
RouterRefreshObject::DoRefresh
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
HRESULT RouterRefreshObject::DoRefresh()
|
|
{
|
|
RtrCriticalSection rtrCritSec(&m_critsec);
|
|
HRESULT hr = hrOK;
|
|
COM_PROTECT_TRY
|
|
{
|
|
// If we are in a refresh cycle, return hrOK
|
|
if (m_fInRefresh)
|
|
goto Error;
|
|
|
|
// If we are not in a refresh cycle, then we start one
|
|
ExecuteRefresh();
|
|
|
|
|
|
COM_PROTECT_ERROR_LABEL;
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
return hr;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
RouterRefreshObject::Start
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
STDMETHODIMP RouterRefreshObject::Start(DWORD dwSeconds)
|
|
{
|
|
RtrCriticalSection rtrCritSec(&m_critsec);
|
|
HRESULT hr = hrOK;
|
|
COM_PROTECT_TRY
|
|
{
|
|
// If we are already started then end
|
|
if (m_fStarted)
|
|
goto Error;
|
|
|
|
// Start the timer going
|
|
m_fStarted = TRUE;
|
|
m_dwSeconds = dwSeconds;
|
|
m_iEventId = g_timerMgr.AllocateTimer(RouterRefreshObjectTimerProc,
|
|
(LPARAM) this,
|
|
dwSeconds * 1000);
|
|
if (m_iEventId == -1)
|
|
{
|
|
m_fStarted = FALSE;
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
}
|
|
|
|
COM_PROTECT_ERROR_LABEL;
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
return hr;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
RouterRefreshObject::Stop
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
STDMETHODIMP RouterRefreshObject::Stop()
|
|
{
|
|
RtrCriticalSection rtrCritSec(&m_critsec);
|
|
HRESULT hr = hrOK;
|
|
COM_PROTECT_TRY
|
|
{
|
|
if (!m_fStarted)
|
|
{
|
|
Assert(m_iEventId == -1);
|
|
goto Error;
|
|
}
|
|
|
|
// Stop the timer
|
|
if (m_iEventId != -1)
|
|
g_timerMgr.FreeTimer(m_iEventId);
|
|
m_iEventId = -1;
|
|
|
|
ReleaseThreadHandler();
|
|
WaitForThreadToExit();
|
|
|
|
m_fStarted = FALSE;
|
|
|
|
COM_PROTECT_ERROR_LABEL;
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
return hr;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
RouterRefreshObject::IsRefreshStarted
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
STDMETHODIMP RouterRefreshObject::IsRefreshStarted()
|
|
{
|
|
RtrCriticalSection rtrCritSec(&m_critsec);
|
|
HRESULT hr = hrOK;
|
|
COM_PROTECT_TRY
|
|
{
|
|
hr = m_fStarted ? hrOK : hrFalse;
|
|
Assert((m_fStarted == FALSE) || (m_iEventId != -1));
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
return hr;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
RouterRefreshObject::AdviseRefresh
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
STDMETHODIMP RouterRefreshObject::AdviseRefresh(IRtrAdviseSink *pRtrAdviseSink,
|
|
LONG_PTR *pdwConnection,
|
|
LPARAM lUserParam)
|
|
{
|
|
Assert(pRtrAdviseSink);
|
|
Assert(pdwConnection);
|
|
|
|
RtrCriticalSection rtrCritSec(&m_critsec);
|
|
DWORD dwConnId;
|
|
HRESULT hr = hrOK;
|
|
|
|
COM_PROTECT_TRY
|
|
{
|
|
dwConnId = (DWORD) InterlockedIncrement(&s_cConnections);
|
|
|
|
CORg( m_AdviseList.AddConnection(pRtrAdviseSink, dwConnId, lUserParam) );
|
|
|
|
*pdwConnection = dwConnId;
|
|
|
|
COM_PROTECT_ERROR_LABEL;
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
return hr;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
RouterRefreshObject::AddRouter
|
|
-
|
|
Author: WeiJiang
|
|
---------------------------------------------------------------------------*/
|
|
STDMETHODIMP RouterRefreshObject::AddRouterObject(REFIID riid, IUnknown *pUnk)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
IRouterInfo * pRouterInfo;
|
|
|
|
if (riid != IID_IRouterInfo)
|
|
return E_NOINTERFACE;
|
|
|
|
pRouterInfo = reinterpret_cast<IRouterInfo *>(pUnk);
|
|
|
|
COM_PROTECT_TRY
|
|
{
|
|
CRouterInfoRefreshItem* pRefreshItem =
|
|
new CRouterInfoRefreshItem(pRouterInfo);
|
|
|
|
if (pRefreshItem)
|
|
{
|
|
// check for duplicates
|
|
if (S_FALSE == m_listElements.AddRefreshItem(pRefreshItem))
|
|
delete pRefreshItem;
|
|
}
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
RouterRefreshObject::RemoveRouterObject
|
|
-
|
|
Author: WeiJiang
|
|
---------------------------------------------------------------------------*/
|
|
STDMETHODIMP RouterRefreshObject::RemoveRouterObject(REFIID riid, IUnknown *pUnk)
|
|
{
|
|
if (riid != IID_IRouterInfo)
|
|
return E_NOINTERFACE;
|
|
|
|
IRouterInfo * pRouterInfo = reinterpret_cast<IRouterInfo *>(pUnk);
|
|
|
|
CRouterInfoRefreshItem RefreshItem(pRouterInfo);
|
|
|
|
return m_listElements.RemoveRefreshItem(RefreshItem);
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
RouterRefreshObject::AddStatusNode
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
HRESULT RouterRefreshObject::AddStatusNode(DomainStatusHandler* pStatusHandler, ITFSNode *pServerNode)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
COM_PROTECT_TRY
|
|
{
|
|
CStatusNodeRefreshItem* pRefreshItem = new CStatusNodeRefreshItem(pStatusHandler, pServerNode);
|
|
|
|
if (pRefreshItem)
|
|
{
|
|
// Check for duplicates
|
|
if (S_FALSE == m_listElements.AddRefreshItem(pRefreshItem))
|
|
delete pRefreshItem;
|
|
}
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
RouterRefreshObject::RemoveRouter
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
HRESULT RouterRefreshObject::RemoveStatusNode(ITFSNode *pServerNode)
|
|
{
|
|
CStatusNodeRefreshItem RefreshItem((DomainStatusHandler *)0x1, pServerNode);
|
|
|
|
return m_listElements.RemoveRefreshItem(RefreshItem);
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
RouterRefreshObject::NotifyRefresh
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
STDMETHODIMP RouterRefreshObject::NotifyRefresh()
|
|
{
|
|
RtrCriticalSection rtrCritSec(&m_critsec);
|
|
HRESULT hr = hrOK;
|
|
COM_PROTECT_TRY
|
|
{
|
|
m_AdviseList.NotifyChange(ROUTER_REFRESH, 0, 0);
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
return hr;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
RouterRefreshObject::UnadviseRefresh
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
STDMETHODIMP RouterRefreshObject::UnadviseRefresh(LONG_PTR dwConnection)
|
|
{
|
|
RtrCriticalSection rtrCritSec(&m_critsec);
|
|
HRESULT hr = hrOK;
|
|
COM_PROTECT_TRY
|
|
{
|
|
hr = m_AdviseList.RemoveConnection(dwConnection);
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
return hr;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
RouterRefreshObject::ExecuteRefresh
|
|
-
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
void RouterRefreshObject::ExecuteRefresh()
|
|
{
|
|
SPITFSQueryObject spQuery;
|
|
RouterRefreshQueryObject * pQuery;
|
|
|
|
// Trace0("Refresh started\n");
|
|
|
|
if (m_fInRefresh)
|
|
return;
|
|
|
|
m_fInRefresh = TRUE;
|
|
|
|
// Create the Query Object
|
|
pQuery = new RouterRefreshQueryObject;
|
|
spQuery = pQuery;
|
|
|
|
pQuery->Init(&m_listElements);
|
|
|
|
// Need to start the background thread
|
|
Verify( StartBackgroundThread(NULL, m_hWndSync, spQuery) );
|
|
|
|
}
|
|
|
|
HRESULT RouterRefreshObject::OnNotifyError(LPARAM lParam)
|
|
{
|
|
return hrOK;
|
|
}
|
|
|
|
HRESULT RouterRefreshObject::OnNotifyHaveData(LPARAM lParam)
|
|
{
|
|
LONG_PTR RefreshItemKey = (LONG_PTR)lParam;
|
|
RouterRefreshQueryElement* pCur = NULL;
|
|
SPRouterRefreshQueryElement spPre;
|
|
HRESULT hr = S_OK;
|
|
|
|
// notify every one on the list, till lParam == Key of the refresh item
|
|
// enumerate and call TryNotify ...
|
|
if (RefreshItemKey)
|
|
{
|
|
do
|
|
{
|
|
pCur = m_listElements.Next(spPre);
|
|
if (pCur)
|
|
pCur->TryNotifyQueryResult();
|
|
|
|
spPre.Free();
|
|
spPre = pCur;
|
|
} while(pCur && pCur->GetRefreshItem()->GetKey() != RefreshItemKey);
|
|
}
|
|
return hrOK;
|
|
}
|
|
|
|
HRESULT RouterRefreshObject::OnNotifyExiting(LPARAM lParam)
|
|
{
|
|
// Trace0("RouterRefreshObject::OnNotifyExiting()\n");
|
|
|
|
// need to do the various actions at this point
|
|
// Merge the tree with the already existing tree
|
|
IRouterInfo* pRouter = (IRouterInfo*)lParam;
|
|
SPRouterRefreshQueryElement spPre;
|
|
RouterRefreshQueryElement* pCur = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
// notify every one on the list, till lParam == IRouterInfo*
|
|
// enumerate and call TryNotify ...
|
|
do
|
|
{
|
|
pCur = m_listElements.Next(spPre);
|
|
if (pCur)
|
|
pCur->TryNotifyQueryResult();
|
|
|
|
spPre.Free();
|
|
spPre = pCur;
|
|
} while(pCur);
|
|
|
|
// Now notify all of the registered handlers
|
|
NotifyRefresh();
|
|
|
|
ReleaseThreadHandler();
|
|
WaitForThreadToExit();
|
|
|
|
m_fInRefresh = FALSE;
|
|
return hrOK;
|
|
}
|
|
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
RtrRefreshTimerProc
|
|
This is used by the CTimerMgr as its callback proc. We then call
|
|
the Refresh code.
|
|
Author: KennT
|
|
---------------------------------------------------------------------------*/
|
|
void CALLBACK RtrRefreshTimerProc(HWND hWnd, UINT uMsg, UINT_PTR nIdEvent,
|
|
DWORD dwTime)
|
|
{
|
|
RtrCriticalSection rtrCritSec(&g_timerMgr.m_critsec);
|
|
|
|
CTimerDesc *pDesc = g_timerMgr.GetTimerDesc(nIdEvent);
|
|
if (pDesc)
|
|
{
|
|
(*(pDesc->refreshProc))(pDesc->lParam, dwTime);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
Global variable: g_timerMgr
|
|
---------------------------------------------------------------------------*/
|
|
CTimerMgr g_timerMgr;
|
|
|
|
DEBUG_DECLARE_INSTANCE_COUNTER(CTimerMgr);
|
|
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
CTimerMgr::CTimerMgr
|
|
-
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
CTimerMgr::CTimerMgr()
|
|
{
|
|
InitializeCriticalSection(&m_critsec);
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
CTimerMgr::~CTimerMgr
|
|
-
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
CTimerMgr::~CTimerMgr()
|
|
{
|
|
CTimerDesc * pTimerDesc;
|
|
|
|
for (int i = GetUpperBound(); i >= 0; --i)
|
|
{
|
|
pTimerDesc = GetAt(i);
|
|
if (pTimerDesc->uTimerId != 0)
|
|
FreeTimer(i);
|
|
|
|
delete pTimerDesc;
|
|
}
|
|
DeleteCriticalSection(&m_critsec);
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
CTimerMgr::AllocateTimer
|
|
-
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
int
|
|
CTimerMgr::AllocateTimer
|
|
(
|
|
REFRESHPROC RefreshProc,
|
|
LPARAM lParam,
|
|
UINT uTimerInterval
|
|
)
|
|
{
|
|
RtrCriticalSection rtrCritSec(&m_critsec);
|
|
|
|
CTimerDesc * pTimerDesc = NULL;
|
|
|
|
// look for an empty slot
|
|
for (int i = GetUpperBound(); i >= 0; --i)
|
|
{
|
|
pTimerDesc = GetAt(i);
|
|
if (pTimerDesc->uTimerId == 0)
|
|
break;
|
|
}
|
|
|
|
// did we find one? if not allocate one
|
|
if (i < 0)
|
|
{
|
|
pTimerDesc = new CTimerDesc;
|
|
pTimerDesc->lParam = 0;
|
|
pTimerDesc->uTimerInterval = 0;
|
|
pTimerDesc->refreshProc = NULL;
|
|
pTimerDesc->uTimerId = 0;
|
|
|
|
Add(pTimerDesc);
|
|
i = GetUpperBound();
|
|
}
|
|
|
|
pTimerDesc->uTimerId = SetTimer(NULL, 0, uTimerInterval, RtrRefreshTimerProc);
|
|
if (pTimerDesc->uTimerId == 0)
|
|
return -1;
|
|
|
|
pTimerDesc->lParam = lParam;
|
|
pTimerDesc->uTimerInterval = uTimerInterval;
|
|
pTimerDesc->refreshProc = RefreshProc;
|
|
|
|
return i;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
CTimerMgr::FreeTimer
|
|
-
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
void
|
|
CTimerMgr::FreeTimer
|
|
(
|
|
int uEventId
|
|
)
|
|
{
|
|
RtrCriticalSection rtrCritSec(&m_critsec);
|
|
|
|
CTimerDesc * pTimerDesc;
|
|
|
|
Assert(uEventId <= GetUpperBound());
|
|
if (uEventId > GetUpperBound())
|
|
return;
|
|
|
|
pTimerDesc = GetAt(uEventId);
|
|
::KillTimer(NULL, pTimerDesc->uTimerId);
|
|
|
|
pTimerDesc->lParam = 0;
|
|
pTimerDesc->uTimerId = 0;
|
|
pTimerDesc->uTimerInterval = 0;
|
|
pTimerDesc->refreshProc = NULL;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
CTimerMgr::GetTimerDesc
|
|
-
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
CTimerDesc *
|
|
CTimerMgr::GetTimerDesc
|
|
(
|
|
INT_PTR uTimerId
|
|
)
|
|
{
|
|
RtrCriticalSection rtrCritSec(&m_critsec);
|
|
|
|
CTimerDesc * pTimerDesc;
|
|
|
|
for (int i = GetUpperBound(); i >= 0; --i)
|
|
{
|
|
pTimerDesc = GetAt(i);
|
|
if (pTimerDesc->uTimerId == (UINT) uTimerId)
|
|
return pTimerDesc;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
CTimerMgr::ChangeInterval
|
|
-
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
void
|
|
CTimerMgr::ChangeInterval
|
|
(
|
|
int uEventId,
|
|
UINT uNewInterval
|
|
)
|
|
{
|
|
RtrCriticalSection rtrCritSec(&m_critsec);
|
|
|
|
Assert(uEventId <= GetUpperBound());
|
|
if (uEventId > GetUpperBound())
|
|
return;
|
|
|
|
CTimerDesc tempTimerDesc;
|
|
CTimerDesc * pTimerDesc;
|
|
|
|
pTimerDesc = GetAt(uEventId);
|
|
|
|
// kill the old timer
|
|
::KillTimer(NULL, pTimerDesc->uTimerId);
|
|
|
|
// set a new one with the new interval
|
|
pTimerDesc->uTimerId = ::SetTimer(NULL, 0, uNewInterval, RtrRefreshTimerProc);
|
|
}
|
|
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
RouterRefreshQueryObject implementation
|
|
---------------------------------------------------------------------------*/
|
|
|
|
DEBUG_DECLARE_INSTANCE_COUNTER(RouterRefreshQueryObject);
|
|
|
|
RouterRefreshQueryObject::RouterRefreshQueryObject()
|
|
{
|
|
}
|
|
|
|
STDMETHODIMP RouterRefreshQueryObject::Execute()
|
|
{
|
|
// for each router info in the queue, run load
|
|
// after each load of router info, post message
|
|
// WM_HIDDENWND_INDEX_HAVEDATA
|
|
SPRouterRefreshQueryElement spPre;
|
|
RouterRefreshQueryElement* pCur = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
// notify every one on the list, till lParam == IRouterInfo*
|
|
// enumerate and call TryNotify ...
|
|
Assert(m_plistElements);
|
|
do
|
|
{
|
|
pCur = m_plistElements->Next(spPre);
|
|
if (pCur)
|
|
pCur->DoQuery(m_hHiddenWnd, m_uMsgBase, m_spHandler);
|
|
|
|
spPre.Free();
|
|
spPre = pCur;
|
|
}while(pCur);
|
|
|
|
return hrFalse;
|
|
}
|
|
|
|
STDMETHODIMP RouterRefreshQueryObject::OnThreadExit()
|
|
{
|
|
::PostMessage(m_hHiddenWnd, m_uMsgBase + WM_HIDDENWND_INDEX_EXITING,
|
|
(WPARAM)(ITFSThreadHandler *)m_spHandler, 0);
|
|
// Trace0("Exiting RouterRefreshQueryObject::Execute()\n");
|
|
return hrOK;
|
|
}
|
|
|
|
|
|
|
|
//=========================================
|
|
// CRouterInfoRefreshItem implementation
|
|
//
|
|
|
|
DEBUG_DECLARE_INSTANCE_COUNTER(CRouterInfoRefreshItem);
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
CRouterInfoRefreshItem::NotifyQueryResult
|
|
-
|
|
Author: WeiJiang
|
|
---------------------------------------------------------------------------*/
|
|
HRESULT CRouterInfoRefreshItem::NotifyQueryResult()
|
|
{
|
|
// get the flag to see if need to notify, if not return S_FALSE
|
|
// TRACE(_T("\nAUTOREFRESH!!RouterInfoRefreshItem!!Merge on %8x\n"), GetKey());
|
|
// need to do the various actions at this point
|
|
// Merge the tree with the already existing tree
|
|
HRESULT hr = S_OK;
|
|
m_cs.Lock();
|
|
|
|
COM_PROTECT_TRY
|
|
{
|
|
hr = m_pRouter->Merge(m_spRouterNew);
|
|
m_spRouterNew->DoDisconnect();
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
|
|
m_cs.Unlock();
|
|
|
|
return hr;
|
|
};
|
|
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
CRouterInfoRefreshItem::DoQuery
|
|
-
|
|
Author: WeiJiang
|
|
---------------------------------------------------------------------------*/
|
|
HRESULT CRouterInfoRefreshItem::DoQuery(HWND hwndHidden, UINT uMsgBase, ITFSThreadHandler* pHandler) // this happens in background worker thread
|
|
{
|
|
// TRACE(_T("\nAUTOREFRESH!!RouterInfoRefreshItem!!Do query on %8x\n"), GetKey());
|
|
// create new RouterInfo, if newRouterInfo is NULL
|
|
// Create the dummy router info
|
|
HRESULT hr = S_OK;
|
|
|
|
m_cs.Lock();
|
|
|
|
COM_PROTECT_TRY
|
|
{
|
|
if (!m_spRouterNew)
|
|
hr = CreateRouterInfo(&m_spRouterNew, NULL, m_pRouter->GetMachineName());
|
|
|
|
// do query on newRouterInfo
|
|
Assert(m_pRouter);
|
|
if (hr == S_OK)
|
|
{
|
|
TransferCredentials ( m_pRouter, m_spRouterNew );
|
|
m_pRouter->DoDisconnect();
|
|
hr = m_spRouterNew->Load(m_pRouter->GetMachineName(), NULL);
|
|
|
|
}
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
|
|
m_cs.Unlock();
|
|
|
|
return hr;
|
|
};
|
|
|
|
|
|
//=========================================
|
|
// CMachineNodeDataRefreshItem implementation
|
|
|
|
DEBUG_DECLARE_INSTANCE_COUNTER(CStatusNodeRefreshItem);
|
|
|
|
CStatusNodeRefreshItem::CStatusNodeRefreshItem(DomainStatusHandler* pStatusHandler, ITFSNode *pServerNode)
|
|
: m_pNode(pServerNode) ,
|
|
m_pStatusHandler(pStatusHandler),
|
|
m_pData(NULL)
|
|
{
|
|
Assert(pStatusHandler);
|
|
Assert(pServerNode);
|
|
|
|
DMVNodeData *pData;
|
|
MachineNodeData *pMachineData;
|
|
|
|
pData = GET_DMVNODEDATA(m_pNode);
|
|
Assert(pData);
|
|
pMachineData = pData->m_spMachineData;
|
|
Assert(pMachineData);
|
|
|
|
m_strMachineName = pMachineData->m_stMachineName;
|
|
}
|
|
|
|
|
|
CStatusNodeRefreshItem::~CStatusNodeRefreshItem()
|
|
{
|
|
TerminateBlockingThread();
|
|
if (m_pData)
|
|
{
|
|
m_pData->Release();
|
|
m_pData = NULL;
|
|
}
|
|
};
|
|
|
|
|
|
HRESULT CStatusNodeRefreshItem::NotifyQueryResult()
|
|
{
|
|
// get the flag to see if need to notify, if not return S_FALSE
|
|
// TRACE(_T("\nAUTOREFRESH!!RouterInfoRefreshItem!!Sync node data on %8x\n"), GetKey());
|
|
HRESULT hr = S_OK;
|
|
|
|
m_cs.Lock();
|
|
|
|
COM_PROTECT_TRY
|
|
{
|
|
// set the new node data
|
|
DMVNodeData *pData;
|
|
pData = GET_DMVNODEDATA(m_pNode);
|
|
|
|
hr = pData->MergeMachineNodeData(m_pData);
|
|
if (hr == S_OK)
|
|
hr = m_pStatusHandler->UpdateSubItemUI(m_pNode);
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
|
|
m_cs.Unlock();
|
|
|
|
// ssync on the node
|
|
|
|
return hr;
|
|
};
|
|
|
|
HRESULT CStatusNodeRefreshItem::DoQuery(HWND hwndHidden, UINT uMsgBase, ITFSThreadHandler* pHandler) // this happens in background worker thread
|
|
{
|
|
// TRACE(_T("\nAUTOREFRESH!!RouterInfoRefreshItem!!Do query on %8x\n"), GetKey());
|
|
|
|
// create a new machine node data, load informaiton,
|
|
HRESULT hr = S_OK;
|
|
|
|
m_cs.Lock();
|
|
|
|
COM_PROTECT_TRY
|
|
{
|
|
if (!m_pData)
|
|
{
|
|
m_pData = new MachineNodeData;
|
|
m_pData->Init(m_strMachineName);
|
|
}
|
|
m_pData->Load();
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
|
|
m_cs.Unlock();
|
|
|
|
return hr;
|
|
};
|
|
|
|
//=========================================
|
|
// RouterRefreshQueryElement implementation
|
|
|
|
DEBUG_DECLARE_INSTANCE_COUNTER(RouterRefreshQueryElement);
|
|
|
|
HRESULT RouterRefreshQueryElement::SetRefreshItem(RefreshItem* pItem)
|
|
{
|
|
if (m_cs.Lock() == 0) return E_FAIL;
|
|
|
|
m_pItem = pItem;
|
|
|
|
m_cs.Unlock();
|
|
return S_OK;
|
|
};
|
|
|
|
RefreshItem* RouterRefreshQueryElement::GetRefreshItem()
|
|
{
|
|
RefreshItem* pItem;
|
|
m_cs.Lock();
|
|
|
|
pItem = m_pItem;
|
|
|
|
m_cs.Unlock();
|
|
return pItem;
|
|
};
|
|
|
|
|
|
/*!--------------------------------------------------------------------------
|
|
RouterRefreshQueryElement::TryNotifyQueryResult
|
|
to detect if the query done, yet to Notify
|
|
Author: WeiJiang
|
|
---------------------------------------------------------------------------*/
|
|
HRESULT RouterRefreshQueryElement::TryNotifyQueryResult()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
RefreshItem* pItem = NULL;
|
|
|
|
// get the flag to see if need to notify, if not return S_FALSE
|
|
|
|
if (GetStatus() == RouterQuery_ToNotify)
|
|
{
|
|
// TRACE(_T("\nAUTOREFRESH!!TryNotifyQueryResult on %8x\n"), m_pItem->GetKey());
|
|
// need to do the various actions at this point
|
|
// Merge the tree with the already existing tree
|
|
pItem = GetRefreshItem();
|
|
}
|
|
|
|
if(pItem)
|
|
{
|
|
hr = pItem->NotifyQueryResult();
|
|
|
|
// after notify, set the flag, return S_OK
|
|
SetStatus(RouterQuery_NoAction);
|
|
}
|
|
|
|
return hr;
|
|
};
|
|
|
|
void RouterRefreshQueryElement::PostNotify(HWND hwndHidden, UINT uMsgBase, ITFSThreadHandler* pHandler) // this happens in background worker thread
|
|
{
|
|
// set ready to notify flag
|
|
SetStatus(RouterQuery_ToNotify);
|
|
// Post done to hidden window
|
|
::PostMessage(hwndHidden, uMsgBase + WM_HIDDENWND_INDEX_HAVEDATA,
|
|
(WPARAM)pHandler, (LPARAM)m_pItem->GetKey());
|
|
}
|
|
|
|
HRESULT RouterRefreshQueryElement::DoQuery(HWND hwndHidden, UINT uMsgBase, ITFSThreadHandler* pHandler) // this happens in background worker thread
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// TRACE(_T("\nAUTOREFRESH!!Do query on %8x\n"), m_pItem->GetKey());
|
|
RefreshItem* pItem = GetRefreshItem();
|
|
|
|
COM_PROTECT_TRY
|
|
{
|
|
// asked to do query, do it anyway, no matter what's the status
|
|
|
|
// set blocking current thread, in case, this query blocks
|
|
pItem->SetBlockingThread(GetCurrentThread());
|
|
|
|
hr = pItem->DoQuery(hwndHidden, uMsgBase, pHandler);
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
PostNotify(hwndHidden, uMsgBase, pHandler);
|
|
}
|
|
|
|
// it's not blocked, reset it
|
|
pItem->ResetBlockingThread();
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
|
|
return hr;
|
|
};
|
|
|
|
RouterRefreshQueryElementList::~RouterRefreshQueryElementList()
|
|
{
|
|
POSITION p = NULL;
|
|
RouterRefreshQueryElement* pEle = NULL;
|
|
|
|
m_cs.Lock();
|
|
p = m_list.GetHeadPosition();
|
|
for(p = m_list.GetHeadPosition(); p != NULL; )
|
|
{
|
|
pEle = m_list.GetNext(p);
|
|
pEle->Release();
|
|
}
|
|
m_list.RemoveAll();
|
|
m_cs.Unlock();
|
|
}
|
|
|
|
HRESULT RouterRefreshQueryElementList::AddRefreshItem(RefreshItem* pItem) // no ref on IRouterInfo
|
|
{
|
|
POSITION p = NULL;
|
|
RouterRefreshQueryElement* pE = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
m_cs.Lock();
|
|
try{
|
|
for (p = m_list.GetHeadPosition(); p != NULL; )
|
|
{
|
|
pE = m_list.GetNext(p);
|
|
|
|
// already added, so only addRef
|
|
if (pItem->GetKey() == pE->GetRefreshItem()->GetKey())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (p != NULL) // found
|
|
{
|
|
pE->AddRef();
|
|
hr = S_FALSE; // we are not keeping the pItem
|
|
}
|
|
else
|
|
{
|
|
CComObject<RouterRefreshQueryElement>* pEle = NULL;
|
|
hr = CComObject<RouterRefreshQueryElement>::CreateInstance(&pEle);
|
|
if ( FHrSucceeded(hr) )
|
|
{
|
|
Assert(pEle);
|
|
pEle->SetRefreshItem(pItem);
|
|
pEle->AddRef();
|
|
m_list.AddTail(pEle);
|
|
}
|
|
}
|
|
}
|
|
catch(CMemoryException&)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
catch(...)
|
|
{
|
|
m_cs.Unlock();
|
|
throw;
|
|
}
|
|
|
|
m_cs.Unlock();
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT RouterRefreshQueryElementList::RemoveRefreshItem(RefreshItem& Item) // no ref on IRouterInfo
|
|
{
|
|
HRESULT hr = hrOK;
|
|
POSITION p = NULL;
|
|
POSITION cp = NULL;
|
|
RouterRefreshQueryElement* pE = NULL;
|
|
|
|
m_cs.Lock();
|
|
try{
|
|
for(p = m_list.GetHeadPosition(); p != NULL; )
|
|
{
|
|
cp = p;
|
|
pE = m_list.GetNext(p);
|
|
if (Item.GetKey() == pE->GetRefreshItem()->GetKey()) // already added, will release on Ele object
|
|
{
|
|
break;
|
|
}
|
|
|
|
// This is not the one we are looking for.
|
|
cp = NULL;
|
|
}
|
|
|
|
if (cp != NULL) // found
|
|
{
|
|
pE->Release(); //remove from the refresh list
|
|
m_list.RemoveAt(cp);
|
|
}
|
|
else
|
|
hr = S_FALSE;
|
|
}
|
|
catch(...)
|
|
{
|
|
m_cs.Unlock();
|
|
throw;
|
|
}
|
|
|
|
m_cs.Unlock();
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
RouterRefreshQueryElement* RouterRefreshQueryElementList::Next(RouterRefreshQueryElement* pEle) // AddRef on Ele Object
|
|
{
|
|
RouterRefreshQueryElement* pNext = NULL;
|
|
m_cs.Lock();
|
|
if (pEle == NULL)
|
|
{
|
|
if (m_list.GetCount() != 0) // asking for the first element
|
|
pNext = m_list.GetHead();
|
|
}
|
|
else
|
|
{
|
|
POSITION p;
|
|
// find the current one
|
|
for(p = m_list.GetHeadPosition(); p != NULL; )
|
|
{
|
|
if (pEle == m_list.GetNext(p))
|
|
{
|
|
if (p != NULL)
|
|
pNext = m_list.GetAt(p);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
m_cs.Unlock();
|
|
|
|
if (pNext)
|
|
pNext->AddRef();
|
|
|
|
return pNext;
|
|
}
|
|
|