/**********************************************************************/ /** Microsoft Windows/NT **/ /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/ /**********************************************************************/ /* DialIn Interface node information FILE HISTORY: */ #include "stdafx.h" #include "dialin.h" #include "ifadmin.h" #include "rtrstrm.h" // for RouterAdminConfigStream #include "rtrlib.h" // ContainerColumnInfo #include "coldlg.h" // ColumnDlg #include "column.h" // ComponentConfigStream #include "refresh.h" // IRouterRefresh #include "iface.h" // for interfacenode data #include "conndlg.h" // CConnDlg - connection dialog #include "msgdlg.h" // CMessageDlg #include "dmvcomp.h" DialInNodeData::DialInNodeData() { #ifdef DEBUG StrCpyA(m_szDebug, "DialInNodeData"); #endif } DialInNodeData::~DialInNodeData() { } /*!-------------------------------------------------------------------------- DialInNodeData::InitAdminNodeData - Author: KennT ---------------------------------------------------------------------------*/ HRESULT DialInNodeData::InitAdminNodeData(ITFSNode *pNode, RouterAdminConfigStream *pConfigStream) { HRESULT hr = hrOK; DialInNodeData * pData = NULL; pData = new DialInNodeData; SET_DIALINNODEDATA(pNode, pData); // Need to connect to the router to get this data return hr; } /*!-------------------------------------------------------------------------- DialInNodeData::FreeAdminNodeData - Author: KennT ---------------------------------------------------------------------------*/ HRESULT DialInNodeData::FreeAdminNodeData(ITFSNode *pNode) { DialInNodeData * pData = GET_DIALINNODEDATA(pNode); delete pData; SET_DIALINNODEDATA(pNode, NULL); return hrOK; } HRESULT DialInNodeData::LoadHandle(LPCTSTR pszMachineName) { m_stMachineName = pszMachineName; return HResultFromWin32(::MprAdminServerConnect((LPTSTR) pszMachineName, &m_sphDdmHandle)); } HANDLE DialInNodeData::GetHandle() { if (!m_sphDdmHandle) { LoadHandle(m_stMachineName); } return m_sphDdmHandle; } void DialInNodeData::ReleaseHandles() { m_sphDdmHandle.Release(); } STDMETHODIMP DialInNodeHandler::QueryInterface(REFIID riid, LPVOID *ppv) { // Is the pointer bad? if (ppv == NULL) return E_INVALIDARG; // Place NULL in *ppv in case of failure *ppv = NULL; // This is the non-delegating IUnknown implementation if (riid == IID_IUnknown) *ppv = (LPVOID) this; else if (riid == IID_IRtrAdviseSink) *ppv = &m_IRtrAdviseSink; else return CHandler::QueryInterface(riid, ppv); // If we're going to return an interface, AddRef it first if (*ppv) { ((LPUNKNOWN) *ppv)->AddRef(); return hrOK; } else return E_NOINTERFACE; } /*--------------------------------------------------------------------------- NodeHandler implementation ---------------------------------------------------------------------------*/ extern const ContainerColumnInfo s_rgDialInColumnInfo[]; const ContainerColumnInfo s_rgDialInColumnInfo[] = { { IDS_DIALIN_COL_USERNAME, CON_SORT_BY_STRING, TRUE, COL_STRING}, { IDS_DIALIN_COL_DURATION, CON_SORT_BY_DWORD, TRUE, COL_DURATION}, { IDS_DIALIN_COL_NUMBEROFPORTS, CON_SORT_BY_DWORD, TRUE, COL_SMALL_NUM}, }; #define NUM_FOLDERS 1 DialInNodeHandler::DialInNodeHandler(ITFSComponentData *pCompData) : BaseContainerHandler(pCompData, DM_COLUMNS_DIALIN, s_rgDialInColumnInfo), m_bExpanded(FALSE), m_pConfigStream(NULL), m_ulConnId(0), m_ulRefreshConnId(0), m_ulPartialRefreshConnId(0) { // Setup the verb states for this node m_rgButtonState[MMC_VERB_REFRESH_INDEX] = ENABLED; m_bState[MMC_VERB_REFRESH_INDEX] = TRUE; } /*!-------------------------------------------------------------------------- DialInNodeHandler::Init - Author: KennT ---------------------------------------------------------------------------*/ HRESULT DialInNodeHandler::Init(IRouterInfo *pRouterInfo, RouterAdminConfigStream *pConfigStream) { HRESULT hr = hrOK; SPIRouterRefresh spRefresh; // If we don't have a router info then we probably failed to load // or failed to connect. Bail out of this. if (!pRouterInfo) CORg( E_FAIL ); m_spRouterInfo.Set(pRouterInfo); // Also need to register for change notifications m_spRouterInfo->RtrAdvise(&m_IRtrAdviseSink, &m_ulConnId, 0); m_pConfigStream = pConfigStream; // register the partial refhersh notifications if( 0 == m_ulPartialRefreshConnId ) { m_spRouterInfo->GetRefreshObject(&spRefresh); if(spRefresh) spRefresh->AdviseRefresh(&m_IRtrAdviseSink, &m_ulPartialRefreshConnId, 0); } Error: return hrOK; } /*!-------------------------------------------------------------------------- DialInNodeHandler::DestroyHandler Implementation of ITFSNodeHandler::DestroyHandler Author: KennT ---------------------------------------------------------------------------*/ STDMETHODIMP DialInNodeHandler::DestroyHandler(ITFSNode *pNode) { DialInNodeData::FreeAdminNodeData(pNode); m_spDataObject.Release(); if (m_ulRefreshConnId || m_ulPartialRefreshConnId) { SPIRouterRefresh spRefresh; if (m_spRouterInfo) m_spRouterInfo->GetRefreshObject(&spRefresh); if (spRefresh) { if(m_ulRefreshConnId) spRefresh->UnadviseRefresh(m_ulRefreshConnId); if(m_ulPartialRefreshConnId) spRefresh->UnadviseRefresh(m_ulPartialRefreshConnId); } } m_ulRefreshConnId = 0; m_ulPartialRefreshConnId = 0; if (m_spRouterInfo) { m_spRouterInfo->RtrUnadvise(m_ulConnId); m_spRouterInfo.Release(); } return hrOK; } /*!-------------------------------------------------------------------------- DialInNodeHandler::HasPropertyPages Implementation of ITFSNodeHandler::HasPropertyPages ---------------------------------------------------------------------------*/ STDMETHODIMP DialInNodeHandler::HasPropertyPages ( ITFSNode * pNode, LPDATAOBJECT pDataObject, DATA_OBJECT_TYPES type, DWORD dwType ) { // we have no property pages in the normal case return hrFalse; } /*--------------------------------------------------------------------------- Menu data structure for our menus ---------------------------------------------------------------------------*/ static const SRouterNodeMenu s_rgDialInNodeMenu[] = { // Add items that are primary go here { IDS_MENU_DIALIN_SENDALL, DialInNodeHandler::GetSendAllMenuFlags, CCM_INSERTIONPOINTID_PRIMARY_TOP }, // Add items that go on the "Create new" menu here // Add items that go on the "Task" menu here }; ULONG DialInNodeHandler::GetSendAllMenuFlags(const SRouterNodeMenu *pMenuData, INT_PTR pUserData) { ULONG ulFlags = 0; SMenuData * pData = reinterpret_cast(pUserData); if (pData) { int iVis, iTotal; pData->m_spNode->GetChildCount(&iVis, &iTotal); if (iTotal == 0) ulFlags = MF_GRAYED; } return ulFlags; } /*!-------------------------------------------------------------------------- DialInNodeHandler::OnAddMenuItems Implementation of ITFSNodeHandler::OnAddMenuItems Author: KennT ---------------------------------------------------------------------------*/ STDMETHODIMP DialInNodeHandler::OnAddMenuItems( ITFSNode *pNode, LPCONTEXTMENUCALLBACK pContextMenuCallback, LPDATAOBJECT lpDataObject, DATA_OBJECT_TYPES type, DWORD dwType, long *pInsertionAllowed) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); HRESULT hr = S_OK; DialInNodeHandler::SMenuData menuData; COM_PROTECT_TRY { menuData.m_spNode.Set(pNode); hr = AddArrayOfMenuItems(pNode, s_rgDialInNodeMenu, DimensionOf(s_rgDialInNodeMenu), pContextMenuCallback, *pInsertionAllowed, reinterpret_cast(&menuData)); } COM_PROTECT_CATCH; return hr; } /*!-------------------------------------------------------------------------- DialInNodeHandler::OnCommand Implementation of ITFSNodeHandler::OnCommand Author: KennT ---------------------------------------------------------------------------*/ STDMETHODIMP DialInNodeHandler::OnCommand(ITFSNode *pNode, long nCommandId, DATA_OBJECT_TYPES type, LPDATAOBJECT pDataObject, DWORD dwType) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); if (nCommandId == IDS_MENU_DIALIN_SENDALL) { WCHAR * pswzComputerName; // Get the machine name out of the data object pswzComputerName = ExtractComputerName(pDataObject); CMessageDlg dlg(m_spRouterInfo->GetMachineName(), W2CT(pswzComputerName), NULL); dlg.DoModal(); } return hrOK; } /*!-------------------------------------------------------------------------- DialInNodeHandler::GetString Implementation of ITFSNodeHandler::GetString Author: KennT ---------------------------------------------------------------------------*/ STDMETHODIMP_(LPCTSTR) DialInNodeHandler::GetString(ITFSNode *pNode, int nCol) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); HRESULT hr = hrOK; COM_PROTECT_TRY { if (m_stTitle.IsEmpty()) m_stTitle.LoadString(IDS_DIALIN_USERS); } COM_PROTECT_CATCH; return m_stTitle; } /*!-------------------------------------------------------------------------- DialInNodeHandler::OnCreateDataObject Implementation of ITFSNodeHandler::OnCreateDataObject Author: KennT ---------------------------------------------------------------------------*/ STDMETHODIMP DialInNodeHandler::OnCreateDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, IDataObject **ppDataObject) { HRESULT hr = hrOK; COM_PROTECT_TRY { if (!m_spDataObject) { CORg( CreateDataObjectFromRouterInfo(m_spRouterInfo, m_spRouterInfo->GetMachineName(), type, cookie, m_spTFSCompData, &m_spDataObject, NULL, FALSE) ); Assert(m_spDataObject); } *ppDataObject = m_spDataObject; (*ppDataObject)->AddRef(); COM_PROTECT_ERROR_LABEL; } COM_PROTECT_CATCH; return hr; } /*!-------------------------------------------------------------------------- DialInNodeHandler::OnExpand - Author: KennT ---------------------------------------------------------------------------*/ HRESULT DialInNodeHandler::OnExpand(ITFSNode *pNode, LPDATAOBJECT pDataObject, DWORD dwType, LPARAM arg, LPARAM lParam) { HRESULT hr = hrOK; SPIEnumInterfaceInfo spEnumIf; SPIInterfaceInfo spIf; // If we don't have a router object, then we don't have any info, don't // try to expand. if (!m_spRouterInfo) return hrOK; if (m_bExpanded) return hrOK; COM_PROTECT_TRY { SynchronizeNodeData(pNode); m_bExpanded = TRUE; } COM_PROTECT_CATCH; return hr; } /*!-------------------------------------------------------------------------- DialInNodeHandler::OnResultShow - Author: KennT ---------------------------------------------------------------------------*/ HRESULT DialInNodeHandler::OnResultShow(ITFSComponent *pTFSComponent, MMC_COOKIE cookie, LPARAM arg, LPARAM lParam) { BOOL bSelect = (BOOL) arg; HRESULT hr = hrOK; SPIRouterRefresh spRefresh; SPITFSNode spNode; BaseContainerHandler::OnResultShow(pTFSComponent, cookie, arg, lParam); if (bSelect) { // Call synchronize on this node m_spNodeMgr->FindNode(cookie, &spNode); if (spNode) SynchronizeNodeData(spNode); } // Un/Register for refresh advises if (m_spRouterInfo) m_spRouterInfo->GetRefreshObject(&spRefresh); if (spRefresh) { if (bSelect) { if (m_ulRefreshConnId == 0) spRefresh->AdviseRefresh(&m_IRtrAdviseSink, &m_ulRefreshConnId, 0); if (m_ulPartialRefreshConnId) { spRefresh->UnadviseRefresh(m_ulPartialRefreshConnId); m_ulPartialRefreshConnId = 0; } } else { if (m_ulRefreshConnId) spRefresh->UnadviseRefresh(m_ulRefreshConnId); m_ulRefreshConnId = 0; if (m_ulPartialRefreshConnId == 0) spRefresh->AdviseRefresh(&m_IRtrAdviseSink, &m_ulPartialRefreshConnId, 0); } } return hr; } /*!-------------------------------------------------------------------------- DialInNodeHandler::ConstructNode Initializes the Domain node (sets it up). Author: KennT ---------------------------------------------------------------------------*/ HRESULT DialInNodeHandler::ConstructNode(ITFSNode *pNode) { HRESULT hr = hrOK; DialInNodeData * pNodeData; if (pNode == NULL) return hrOK; COM_PROTECT_TRY { // Need to initialize the data for the Domain node pNode->SetData(TFS_DATA_IMAGEINDEX, IMAGE_IDX_INTERFACES); pNode->SetData(TFS_DATA_OPENIMAGEINDEX, IMAGE_IDX_INTERFACES); pNode->SetData(TFS_DATA_SCOPEID, 0); // This is a leaf node in the scope pane pNode->SetData(TFS_DATA_SCOPE_LEAF_NODE, TRUE); m_cookie = reinterpret_cast(pNode); pNode->SetData(TFS_DATA_COOKIE, m_cookie); pNode->SetNodeType(&GUID_RouterDialInNodeType); DialInNodeData::InitAdminNodeData(pNode, m_pConfigStream); pNodeData = GET_DIALINNODEDATA(pNode); Assert(pNodeData); // Ignore the error, we should be able to deal with the // case of a stopped router. pNodeData->LoadHandle(m_spRouterInfo->GetMachineName()); PartialSynchronizeNodeData(pNode); } COM_PROTECT_CATCH return hr; } /*!-------------------------------------------------------------------------- DialInNodeHandler::SynchronizeNodeData - Author: KennT ---------------------------------------------------------------------------*/ HRESULT DialInNodeHandler::SynchronizeNodeData(ITFSNode *pThisNode) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); Assert(pThisNode); SPITFSNodeEnum spEnum; int i; HRESULT hr = hrOK; DWORD dwTotalCount = 0; DialInNodeData * pNodeData; DialInList dialinList; DialInList newDialInList; DialInListEntry * pDialIn; BOOL fFound; POSITION pos; SPITFSNode spChildNode; InterfaceNodeData * pChildData; int nChildCount; COM_PROTECT_TRY { // Get the status data from the running router pNodeData = GET_DIALINNODEDATA(pThisNode); if (pNodeData == NULL) { // Remove all of the nodes, we can't connect so we can't // get any running data. UnmarkAllNodes(pThisNode, spEnum); RemoveAllUnmarkedNodes(pThisNode, spEnum); m_stTitle.LoadString(IDS_DIALIN_USERS); pThisNode->ChangeNode(SCOPE_PANE_CHANGE_ITEM_DATA); return hrOK; } // Unmark all of the nodes pThisNode->GetEnum(&spEnum); UnmarkAllNodes(pThisNode, spEnum); // Go out and grab the data, merge the the new data in with // the old data. CORg( GenerateListOfUsers(pThisNode, &dialinList, &dwTotalCount) ); pos = dialinList.GetHeadPosition(); while (pos) { pDialIn = & dialinList.GetNext(pos); // Look for this entry in our current list of nodes spEnum->Reset(); spChildNode.Release(); fFound = FALSE; for (;spEnum->Next(1, &spChildNode, NULL) == hrOK; spChildNode.Release()) { pChildData = GET_INTERFACENODEDATA(spChildNode); Assert(pChildData); if (pChildData->m_rgData[DIALIN_SI_CONNECTION].m_ulData == reinterpret_cast(pDialIn->m_rc0.hConnection)) { // Ok, this user already exists, update the metric // and mark it Assert(pChildData->dwMark == FALSE); pChildData->dwMark = TRUE; fFound = TRUE; SetUserData(spChildNode, *pDialIn); // Force MMC to redraw the node spChildNode->ChangeNode(RESULT_PANE_CHANGE_ITEM_DATA); break; } } if (!fFound) newDialInList.AddTail(*pDialIn); } // In case of an error (such as we cannot contact the server) // we want to remove the unmarked nodes. COM_PROTECT_ERROR_LABEL; // Remove all nodes that were not marked RemoveAllUnmarkedNodes(pThisNode, spEnum); // Now iterate through the list of new users, adding them all in. pos = newDialInList.GetHeadPosition(); while (pos) { pDialIn = & newDialInList.GetNext(pos); AddDialInUserNode(pThisNode, *pDialIn); } // NT BUG #163162, put the connected client count into the // title of the node if (FHrSucceeded(hr)) m_stTitle.Format(IDS_DIALIN_USERS_NUM, dwTotalCount); else m_stTitle.Format(IDS_DIALIN_USERS); pThisNode->ChangeNode(SCOPE_PANE_CHANGE_ITEM_DATA); } COM_PROTECT_CATCH; return hr; } /*!-------------------------------------------------------------------------- DialInNodeHandler::PartialSynchronizeNodeData - Description: For Bug #163162 Only refresh dialin user count on the the node title Author: NSun ---------------------------------------------------------------------------*/ HRESULT DialInNodeHandler::PartialSynchronizeNodeData(ITFSNode *pThisNode) { Assert(pThisNode); SPITFSNodeEnum spEnum; int i; HRESULT hr = hrOK; DWORD dwCount = 0; DialInNodeData * pNodeData; int iFormat; COM_PROTECT_TRY { // Get the status data from the running router pNodeData = GET_DIALINNODEDATA(pThisNode); if (pNodeData == NULL) { // Remove all of the nodes, we can't connect so we can't // get any running data. iFormat = IDS_DIALIN_USERS; } else { // Get the count of dial-in clients and put the number // in the node title hr = GenerateListOfUsers(pThisNode, NULL, &dwCount); if (FHrSucceeded(hr)) iFormat = IDS_DIALIN_USERS_NUM; else iFormat = IDS_DIALIN_USERS; } m_stTitle.Format(iFormat, dwCount); pThisNode->ChangeNode(SCOPE_PANE_CHANGE_ITEM_DATA); } COM_PROTECT_CATCH; return hr; } /*!-------------------------------------------------------------------------- DialInNodeHandler::SetUserData - Author: KennT ---------------------------------------------------------------------------*/ HRESULT DialInNodeHandler::SetUserData(ITFSNode *pNode, const DialInListEntry& entry) { HRESULT hr = hrOK; InterfaceNodeData * pData; TCHAR szNumber[32]; CString st; pData = GET_INTERFACENODEDATA(pNode); Assert(pData); if (entry.m_rc0.dwInterfaceType != ROUTER_IF_TYPE_CLIENT) { pData->m_rgData[DIALIN_SI_USERNAME].m_stData = entry.m_rc0.wszInterfaceName; } else { if (StrLenW(entry.m_rc0.wszLogonDomain)) { if (StrLenW(entry.m_rc0.wszUserName)) st.Format(IDS_DIALINUSR_DOMAIN_AND_NAME, entry.m_rc0.wszLogonDomain, entry.m_rc0.wszUserName); else st.Format(IDS_DIALINUSR_DOMAIN_ONLY, entry.m_rc0.wszLogonDomain); } else st = entry.m_rc0.wszUserName; pData->m_rgData[DIALIN_SI_USERNAME].m_stData = st; } pData->m_rgData[DIALIN_SI_DOMAIN].m_stData = entry.m_rc0.wszLogonDomain; pData->m_rgData[DIALIN_SI_CONNECTION].m_ulData = reinterpret_cast(entry.m_rc0.hConnection); FormatDuration(entry.m_rc0.dwConnectDuration, pData->m_rgData[DIALIN_SI_DURATION].m_stData, UNIT_SECONDS); pData->m_rgData[DIALIN_SI_DURATION].m_dwData = entry.m_rc0.dwConnectDuration; FormatNumber(entry.m_cPorts, szNumber, DimensionOf(szNumber), FALSE); pData->m_rgData[DIALIN_SI_NUMBEROFPORTS].m_dwData = entry.m_cPorts; pData->m_rgData[DIALIN_SI_NUMBEROFPORTS].m_stData = szNumber; return hr; } /*!-------------------------------------------------------------------------- DialInNodeHandler::GenerateListOfUsers - Author: KennT Note: If pList is NULL, then only the count of items is returned ---------------------------------------------------------------------------*/ HRESULT DialInNodeHandler::GenerateListOfUsers(ITFSNode *pNode, DialInList *pList, DWORD *pdwCount) { DialInListEntry entry; DialInNodeData * pDialInData; DWORD dwTotal; DWORD rc0Count; RAS_CONNECTION_0 *rc0Table; HRESULT hr = hrOK; DWORD i; RAS_PORT_0 * rp0Table; DWORD rp0Count; SPMprAdminBuffer spMpr; POSITION pos; DialInListEntry * pEntry; DWORD dwClientCount; pDialInData = GET_DIALINNODEDATA(pNode); Assert(pDialInData); // Fill in the list with all of the current connections CWRg( ::MprAdminConnectionEnum(pDialInData->GetHandle(), 0, (BYTE **) &rc0Table, (DWORD) -1, &rc0Count, &dwTotal, NULL )); Assert(rc0Table); spMpr = (LPBYTE) rc0Table; dwClientCount = 0; // Add a new DialInListEntry for each connection for (i=0; iAddTail(entry); } } spMpr.Free(); if( pdwCount != NULL ) *pdwCount = dwClientCount; //if pList is NULL, we are only intereted in the count if( NULL == pList ) goto Error; // If the list is empty, there is no need to enumerate the ports // to match them up to the connections. // ---------------------------------------------------------------- if (!pList->IsEmpty()) { // Now go through the ports, matching them up against the connections CWRg( ::MprAdminPortEnum( pDialInData->GetHandle(), 0, INVALID_HANDLE_VALUE, (BYTE **) &rp0Table, (DWORD) -1, &rp0Count, &dwTotal, NULL) ); spMpr = (LPBYTE) rp0Table; for (i=0; iGetHeadPosition(); while (pos) { pEntry = & pList->GetNext(pos); if (pEntry->m_rc0.hConnection == rp0Table[i].hConnection) { pEntry->m_cPorts++; break; } } } } Error: return hr; } ImplementEmbeddedUnknown(DialInNodeHandler, IRtrAdviseSink) STDMETHODIMP DialInNodeHandler::EIRtrAdviseSink::OnChange(LONG_PTR ulConn, DWORD dwChangeType, DWORD dwObjectType, LPARAM lUserParam, LPARAM lParam) { InitPThis(DialInNodeHandler, IRtrAdviseSink); SPITFSNode spThisNode; HRESULT hr = hrOK; COM_PROTECT_TRY { pThis->m_spNodeMgr->FindNode(pThis->m_cookie, &spThisNode); if (dwChangeType == ROUTER_REFRESH) { //(nsun) Bug 163162, We have two Refresh Connection ID for this node and we only // partially refresh (just refresh the node title) if this node is not at focus if( ulConn == pThis->m_ulRefreshConnId ) { // Ok, just call the synchronize on this node pThis->SynchronizeNodeData(spThisNode); } else if( ulConn == pThis->m_ulPartialRefreshConnId ) { pThis->PartialSynchronizeNodeData(spThisNode); } } else if (dwChangeType == ROUTER_DO_DISCONNECT) { DialInNodeData * pNodeData; pNodeData = GET_DIALINNODEDATA(spThisNode); Assert(pNodeData); // Release the handle pNodeData->ReleaseHandles(); } } COM_PROTECT_CATCH; return hr; } /*!-------------------------------------------------------------------------- DialInNodeHandler::CompareItems Implementation of ITFSResultHandler::CompareItems Author: KennT ---------------------------------------------------------------------------*/ STDMETHODIMP_(int) DialInNodeHandler::CompareItems( ITFSComponent * pComponent, MMC_COOKIE cookieA, MMC_COOKIE cookieB, int nCol) { // Get the strings from the nodes and use that as a basis for // comparison. SPITFSNode spNode; SPITFSResultHandler spResult; m_spNodeMgr->FindNode(cookieA, &spNode); spNode->GetResultHandler(&spResult); return spResult->CompareItems(pComponent, cookieA, cookieB, nCol); } /*--------------------------------------------------------------------------- This is the set of menus that will appear when a right-click is done on the blank area of the result pane. ---------------------------------------------------------------------------*/ static const SRouterNodeMenu s_rgDialInResultNodeMenu[] = { // Add items that go on the "Create New" menu here { IDS_MENU_DIALIN_SENDALL, DialInNodeHandler::GetSendAllMenuFlags, CCM_INSERTIONPOINTID_PRIMARY_TOP }, }; /*!-------------------------------------------------------------------------- DialInNodeHandler::AddMenuItems Implementation of ITFSResultHandler::AddMenuItems Use this to add commands to the context menu of the blank areas of the result pane. Author: KennT ---------------------------------------------------------------------------*/ STDMETHODIMP DialInNodeHandler::AddMenuItems(ITFSComponent *pComponent, MMC_COOKIE cookie, LPDATAOBJECT pDataObject, LPCONTEXTMENUCALLBACK pCallback, long *pInsertionAllowed) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); HRESULT hr = hrOK; SPITFSNode spNode; DialInNodeHandler::SMenuData menuData; COM_PROTECT_TRY { m_spNodeMgr->FindNode(cookie, &spNode); menuData.m_spNode.Set(spNode); hr = AddArrayOfMenuItems(spNode, s_rgDialInResultNodeMenu, DimensionOf(s_rgDialInResultNodeMenu), pCallback, *pInsertionAllowed, reinterpret_cast(&menuData)); } COM_PROTECT_CATCH; return hr; } /*!-------------------------------------------------------------------------- DialInNodeHandler::Command - Author: KennT ---------------------------------------------------------------------------*/ STDMETHODIMP DialInNodeHandler::Command(ITFSComponent *pComponent, MMC_COOKIE cookie, int nCommandID, LPDATAOBJECT pDataObject) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); SPITFSNode spNode; HRESULT hr = hrOK; m_spNodeMgr->FindNode(cookie, &spNode); hr = OnCommand(spNode, nCommandID, CCT_RESULT, pDataObject, TFS_COMPDATA_CHILD_CONTEXTMENU); return hr; } /*!-------------------------------------------------------------------------- DialInNodeHandler::AddDialInUserNode Adds a user to the UI. This will create a new result item node for each interface. Author: KennT ---------------------------------------------------------------------------*/ HRESULT DialInNodeHandler::AddDialInUserNode(ITFSNode *pParent, const DialInListEntry& dialinEntry) { DialInUserHandler * pHandler; SPITFSResultHandler spHandler; SPITFSNode spNode; HRESULT hr = hrOK; pHandler = new DialInUserHandler(m_spTFSCompData); spHandler = pHandler; CORg( pHandler->Init(m_spRouterInfo, pParent) ); CORg( CreateLeafTFSNode(&spNode, NULL, static_cast(pHandler), static_cast(pHandler), m_spNodeMgr) ); CORg( pHandler->ConstructNode(spNode, NULL, &dialinEntry) ); SetUserData(spNode, dialinEntry); // Make the node immediately visible CORg( spNode->SetVisibilityState(TFS_VIS_SHOW) ); CORg( pParent->AddChild(spNode) ); Error: return hr; } /*!-------------------------------------------------------------------------- DialInNodeHandler::UnmarkAllNodes - Author: KennT ---------------------------------------------------------------------------*/ HRESULT DialInNodeHandler::UnmarkAllNodes(ITFSNode *pNode, ITFSNodeEnum *pEnum) { SPITFSNode spChildNode; InterfaceNodeData * pNodeData; pEnum->Reset(); for ( ;pEnum->Next(1, &spChildNode, NULL) == hrOK; spChildNode.Release()) { pNodeData = GET_INTERFACENODEDATA(spChildNode); Assert(pNodeData); pNodeData->dwMark = FALSE; } return hrOK; } /*!-------------------------------------------------------------------------- DialInNodeHandler::RemoveAllUnmarkedNodes - Author: KennT ---------------------------------------------------------------------------*/ HRESULT DialInNodeHandler::RemoveAllUnmarkedNodes(ITFSNode *pNode, ITFSNodeEnum *pEnum) { HRESULT hr = hrOK; SPITFSNode spChildNode; InterfaceNodeData * pNodeData; pEnum->Reset(); for ( ;pEnum->Next(1, &spChildNode, NULL) == hrOK; spChildNode.Release()) { pNodeData = GET_INTERFACENODEDATA(spChildNode); Assert(pNodeData); if (pNodeData->dwMark == FALSE) { pNode->RemoveChild(spChildNode); spChildNode->Destroy(); } } return hr; } /*--------------------------------------------------------------------------- DialInUserHandler implementation ---------------------------------------------------------------------------*/ DEBUG_DECLARE_INSTANCE_COUNTER(DialInUserHandler) IMPLEMENT_ADDREF_RELEASE(DialInUserHandler) STDMETHODIMP DialInUserHandler::QueryInterface(REFIID riid, LPVOID *ppv) { // Is the pointer bad? if (ppv == NULL) return E_INVALIDARG; // Place NULL in *ppv in case of failure *ppv = NULL; // This is the non-delegating IUnknown implementation if (riid == IID_IUnknown) *ppv = (LPVOID) this; else if (riid == IID_IRtrAdviseSink) *ppv = &m_IRtrAdviseSink; else return CBaseResultHandler::QueryInterface(riid, ppv); // If we're going to return an interface, AddRef it first if (*ppv) { ((LPUNKNOWN) *ppv)->AddRef(); return hrOK; } else return E_NOINTERFACE; } /*--------------------------------------------------------------------------- NodeHandler implementation ---------------------------------------------------------------------------*/ DialInUserHandler::DialInUserHandler(ITFSComponentData *pCompData) : BaseRouterHandler(pCompData), m_ulConnId(0) { DEBUG_INCREMENT_INSTANCE_COUNTER(DialInUserHandler); // Setup the verb states for this node // ---------------------------------------------------------------- m_rgButtonState[MMC_VERB_REFRESH_INDEX] = ENABLED; m_bState[MMC_VERB_REFRESH_INDEX] = TRUE; } /*!-------------------------------------------------------------------------- DialInUserHandler::Init - Author: KennT ---------------------------------------------------------------------------*/ HRESULT DialInUserHandler::Init(IRouterInfo *pInfo, ITFSNode *pParent) { m_spRouterInfo.Set(pInfo); return hrOK; } /*!-------------------------------------------------------------------------- DialInUserHandler::DestroyResultHandler - Author: KennT ---------------------------------------------------------------------------*/ STDMETHODIMP DialInUserHandler::DestroyResultHandler(MMC_COOKIE cookie) { SPITFSNode spNode; m_spNodeMgr->FindNode(cookie, &spNode); InterfaceNodeData::Free(spNode); CHandler::DestroyResultHandler(cookie); return hrOK; } static DWORD s_rgInterfaceImageMap[] = { ROUTER_IF_TYPE_HOME_ROUTER, IMAGE_IDX_WAN_CARD, ROUTER_IF_TYPE_FULL_ROUTER, IMAGE_IDX_WAN_CARD, ROUTER_IF_TYPE_CLIENT, IMAGE_IDX_WAN_CARD, ROUTER_IF_TYPE_DEDICATED, IMAGE_IDX_LAN_CARD, ROUTER_IF_TYPE_INTERNAL, IMAGE_IDX_LAN_CARD, ROUTER_IF_TYPE_LOOPBACK, IMAGE_IDX_LAN_CARD, -1, IMAGE_IDX_WAN_CARD, // sentinel value }; /*!-------------------------------------------------------------------------- DialInUserHandler::ConstructNode Initializes the Domain node (sets it up). Author: KennT ---------------------------------------------------------------------------*/ HRESULT DialInUserHandler::ConstructNode(ITFSNode *pNode, IInterfaceInfo *pIfInfo, const DialInListEntry *pEntry) { HRESULT hr = hrOK; int i; Assert(pEntry); if (pNode == NULL) return hrOK; COM_PROTECT_TRY { // Need to initialize the data for the Domain node pNode->SetData(TFS_DATA_IMAGEINDEX, IMAGE_IDX_INTERFACES); pNode->SetData(TFS_DATA_OPENIMAGEINDEX, IMAGE_IDX_INTERFACES); pNode->SetData(TFS_DATA_SCOPEID, 0); pNode->SetData(TFS_DATA_COOKIE, reinterpret_cast(pNode)); //$ Review: kennt, what are the different type of interfaces // do we distinguish based on the same list as above? (i.e. the // one for image indexes). pNode->SetNodeType(&GUID_RouterDialInResultNodeType); m_entry = *pEntry; InterfaceNodeData::Init(pNode, pIfInfo); } COM_PROTECT_CATCH return hr; } /*!-------------------------------------------------------------------------- DialInUserHandler::GetString - Author: KennT ---------------------------------------------------------------------------*/ STDMETHODIMP_(LPCTSTR) DialInUserHandler::GetString(ITFSComponent * pComponent, MMC_COOKIE cookie, int nCol) { Assert(m_spNodeMgr); SPITFSNode spNode; InterfaceNodeData * pData; ConfigStream * pConfig; m_spNodeMgr->FindNode(cookie, &spNode); Assert(spNode); pData = GET_INTERFACENODEDATA(spNode); Assert(pData); pComponent->GetUserData((LONG_PTR *) &pConfig); Assert(pConfig); return pData->m_rgData[pConfig->MapColumnToSubitem(DM_COLUMNS_DIALIN, nCol)].m_stData; } /*!-------------------------------------------------------------------------- DialInUserHandler::CompareItems - Author: KennT ---------------------------------------------------------------------------*/ STDMETHODIMP_(int) DialInUserHandler::CompareItems(ITFSComponent * pComponent, MMC_COOKIE cookieA, MMC_COOKIE cookieB, int nCol) { ConfigStream * pConfig; pComponent->GetUserData((LONG_PTR *) &pConfig); Assert(pConfig); int nSubItem = pConfig->MapColumnToSubitem(DM_COLUMNS_DIALIN, nCol); if (pConfig->GetSortCriteria(DM_COLUMNS_DIALIN, nCol) == CON_SORT_BY_DWORD) { SPITFSNode spNodeA, spNodeB; InterfaceNodeData * pNodeDataA = NULL; InterfaceNodeData * pNodeDataB = NULL; m_spNodeMgr->FindNode(cookieA, &spNodeA); m_spNodeMgr->FindNode(cookieB, &spNodeB); pNodeDataA = GET_INTERFACENODEDATA(spNodeA); Assert(pNodeDataA); pNodeDataB = GET_INTERFACENODEDATA(spNodeB); Assert(pNodeDataB); // Note: if the values are both zero, we need to do // a string comparison (to distinuguish true zero // from a NULL data). // e.g. "0" vs. "-" if ((pNodeDataA->m_rgData[nSubItem].m_dwData == 0 ) && (pNodeDataB->m_rgData[nSubItem].m_dwData == 0)) { return StriCmpW(GetString(pComponent, cookieA, nCol), GetString(pComponent, cookieB, nCol)); } else return pNodeDataA->m_rgData[nSubItem].m_dwData - pNodeDataB->m_rgData[nSubItem].m_dwData; } else return StriCmpW(GetString(pComponent, cookieA, nCol), GetString(pComponent, cookieB, nCol)); } static const SRouterNodeMenu s_rgIfNodeMenu[] = { { IDS_MENU_DIALIN_STATUS, 0, CCM_INSERTIONPOINTID_PRIMARY_TOP}, { IDS_MENU_DIALIN_DISCONNECT, 0, CCM_INSERTIONPOINTID_PRIMARY_TOP}, { IDS_MENU_DIALIN_SENDMSG, DialInUserHandler::GetSendMsgMenuFlags, CCM_INSERTIONPOINTID_PRIMARY_TOP}, { IDS_MENU_DIALIN_SENDALL, 0, CCM_INSERTIONPOINTID_PRIMARY_TOP}, }; ULONG DialInUserHandler::GetSendMsgMenuFlags(const SRouterNodeMenu *, INT_PTR pUserData) { SMenuData * pData = reinterpret_cast(pUserData); if (pData->m_pDialin->m_entry.m_rc0.dwInterfaceType == ROUTER_IF_TYPE_CLIENT) return 0; else return MF_GRAYED; } /*!-------------------------------------------------------------------------- DialInUserHandler::AddMenuItems Implementation of ITFSResultHandler::OnAddMenuItems Author: KennT ---------------------------------------------------------------------------*/ STDMETHODIMP DialInUserHandler::AddMenuItems(ITFSComponent *pComponent, MMC_COOKIE cookie, LPDATAOBJECT lpDataObject, LPCONTEXTMENUCALLBACK pContextMenuCallback, long *pInsertionAllowed) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); HRESULT hr = S_OK; SPITFSNode spNode; DialInUserHandler::SMenuData menuData; COM_PROTECT_TRY { m_spNodeMgr->FindNode(cookie, &spNode); // Now go through and add our menu items menuData.m_spNode.Set(spNode); menuData.m_pDialin = this; hr = AddArrayOfMenuItems(spNode, s_rgIfNodeMenu, DimensionOf(s_rgIfNodeMenu), pContextMenuCallback, *pInsertionAllowed, reinterpret_cast(&menuData)); } COM_PROTECT_CATCH; return hr; } /*!-------------------------------------------------------------------------- DialInUserHandler::Command - Author: KennT ---------------------------------------------------------------------------*/ STDMETHODIMP DialInUserHandler::Command(ITFSComponent *pComponent, MMC_COOKIE cookie, int nCommandId, LPDATAOBJECT pDataObject) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); HRESULT hr = S_OK; SPITFSNode spNode; SPITFSNode spNodeParent; SPITFSNodeHandler spParentHandler; DialInNodeData * pData; LPCWSTR pswzComputerName; USES_CONVERSION; COM_PROTECT_TRY { switch (nCommandId) { case IDS_MENU_DIALIN_STATUS: { // Get the hServer and hPort m_spNodeMgr->FindNode(cookie, &spNode); spNode->GetParent(&spNodeParent); pData = GET_DIALINNODEDATA(spNodeParent); CConnDlg conndlg(pData->GetHandle(), m_entry.m_rc0.hConnection, spNodeParent); conndlg.DoModal(); // if (conndlg.m_bChanged) RefreshInterface(cookie); } break; case IDS_MENU_DIALIN_DISCONNECT: { // Get the hServer and hPort m_spNodeMgr->FindNode(cookie, &spNode); spNode->GetParent(&spNodeParent); pData = GET_DIALINNODEDATA(spNodeParent); ::MprAdminInterfaceDisconnect( pData->GetHandle(), m_entry.m_rc0.hInterface); // Refresh this node RefreshInterface(cookie); } break; case IDS_MENU_DIALIN_SENDMSG: { // If this is a client inteface, don't allow sending // to this. if (m_entry.m_rc0.dwInterfaceType != ROUTER_IF_TYPE_CLIENT) break; // If the messenger flags are set, then don't bother // trying to send the message to this client if (!(m_entry.m_rc0.dwConnectionFlags & RAS_FLAGS_MESSENGER_PRESENT)) { AfxMessageBox(IDS_ERR_NO_MESSENGER, MB_OK | MB_ICONINFORMATION); break; } // Send a message to a single user // ------------------------------------------------ CMessageDlg dlg(m_spRouterInfo->GetMachineName(), W2CT(m_entry.m_rc0.wszUserName), W2CT(m_entry.m_rc0.wszRemoteComputer), m_entry.m_rc0.hConnection, NULL); dlg.DoModal(); } break; case IDS_MENU_DIALIN_SENDALL: { // Get the hServer and hPort m_spNodeMgr->FindNode(cookie, &spNode); ForwardCommandToParent(spNode, IDS_MENU_DIALIN_SENDALL, CCT_RESULT, pDataObject, 0); } break; default: Panic0("DialInUserHandler: Unknown menu command!"); break; } } COM_PROTECT_CATCH; return hr; } ImplementEmbeddedUnknown(DialInUserHandler, IRtrAdviseSink) STDMETHODIMP DialInUserHandler::EIRtrAdviseSink::OnChange(LONG_PTR ulConn, DWORD dwChangeType, DWORD dwObjectType, LPARAM lUserParam, LPARAM lParam) { InitPThis(DialInUserHandler, IRtrAdviseSink); HRESULT hr = hrOK; return hr; } /*!-------------------------------------------------------------------------- DialInUserHandler::OnCreateDataObject Implementation of ITFSResultHandler::OnCreateDataObject Author: KennT ---------------------------------------------------------------------------*/ STDMETHODIMP DialInUserHandler::OnCreateDataObject(ITFSComponent *pComp, MMC_COOKIE cookie, DATA_OBJECT_TYPES type, IDataObject **ppDataObject) { HRESULT hr = hrOK; COM_PROTECT_TRY { CORg( CreateDataObjectFromRouterInfo(m_spRouterInfo, m_spRouterInfo->GetMachineName(), type, cookie, m_spTFSCompData, ppDataObject, NULL, FALSE) ); COM_PROTECT_ERROR_LABEL; } COM_PROTECT_CATCH; return hr; } STDMETHODIMP DialInUserHandler::HasPropertyPages ( ITFSComponent *pComp, MMC_COOKIE cookie, LPDATAOBJECT pDataObject) { return hrFalse; } /*!-------------------------------------------------------------------------- DialInUserHandler::RefreshInterface - Author: KennT ---------------------------------------------------------------------------*/ void DialInUserHandler::RefreshInterface(MMC_COOKIE cookie) { ForceGlobalRefresh(m_spRouterInfo); } /*!-------------------------------------------------------------------------- DialInUserHandler::OnResultItemClkOrDblClk - Author: KennT ---------------------------------------------------------------------------*/ HRESULT DialInUserHandler::OnResultItemClkOrDblClk(ITFSComponent *pComponent, MMC_COOKIE cookie, LPARAM arg, LPARAM lParam, BOOL bDoubleClick) { HRESULT hr = hrOK; if (bDoubleClick) { // Bring up the status dialog on this port CORg( Command(pComponent, cookie, IDS_MENU_DIALIN_STATUS, NULL) ); } Error: return hr; }