/**********************************************************************/ /** 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(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(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* pEle = NULL; hr = CComObject::CreateInstance(&pEle); if ( FHrSucceeded(hr) ) { Assert(pEle); pEle->SetRefreshItem(pItem); pEle->AddRef(); m_list.AddTail(pEle); } } } catch(CMemoryException* pException) { pException->Delete(); 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; }