/**********************************************************************/ /** Microsoft Windows/NT **/ /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/ /**********************************************************************/ /* server.cpp WINS server node information. FILE HISTORY: */ #include "stdafx.h" #include "winssnap.h" #include "root.h" #include "Srvlatpp.h" #include "actreg.h" #include "reppart.h" #include "server.h" #include "svrstats.h" #include "shlobj.h" #include "cprogdlg.h" #include "status.h" #include "tregkey.h" #include "verify.h" #include "pushtrig.h" #include "ipadddlg.h" #include #define NB_NAME_MAX_LENGTH 16 // Max length for NetBIOS names #define LM_NAME_MAX_LENGTH 15 // Maximum length for Lanman-compatible // NetBIOS Name. #define DOMAINNAME_LENGTH 255 #define HOSTNAME_LENGTH 16 CNameCache g_NameCache; int BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData) { int i; switch (uMsg) { case BFFM_INITIALIZED: SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData); break; } return 0; } /*--------------------------------------------------------------------------- CNameThread Background thread that resolves names Author: EricDav ---------------------------------------------------------------------------*/ CNameThread::CNameThread() { m_bAutoDelete = FALSE; m_hEventHandle = NULL; m_pServerInfoArray = NULL; } CNameThread::~CNameThread() { if (m_hEventHandle != NULL) { VERIFY(::CloseHandle(m_hEventHandle)); m_hEventHandle = NULL; } } void CNameThread::Init(CServerInfoArray * pServerInfoArray) { m_pServerInfoArray = pServerInfoArray; } BOOL CNameThread::Start() { ASSERT(m_hEventHandle == NULL); // cannot call start twice or reuse the same C++ object m_hEventHandle = ::CreateEvent(NULL,TRUE /*bManualReset*/,FALSE /*signalled*/, NULL); if (m_hEventHandle == NULL) return FALSE; return CreateThread(); } void CNameThread::Abort(BOOL fAutoDelete) { if (!IsRunning() && fAutoDelete) { delete this; } else { m_bAutoDelete = fAutoDelete; SetEvent(m_hEventHandle); } } void CNameThread::AbortAndWait() { Abort(FALSE); WaitForSingleObject(m_hThread, INFINITE); } BOOL CNameThread::IsRunning() { if (WaitForSingleObject(m_hThread, 0) == WAIT_OBJECT_0) { return FALSE; } else { return TRUE; } } int CNameThread::Run() { Assert(m_pServerInfoArray); // // fill in the host names for each owner in the list // UpdateNameCache(); if (FCheckForAbort()) return 29; for (int i = 0; i < m_pServerInfoArray->GetSize(); i++) { if (FCheckForAbort()) break; DWORD dwIp = m_pServerInfoArray->GetAt(i).m_dwIp; if (dwIp != 0) { CString strName; if (!GetNameFromCache(dwIp, strName)) { GetHostName(dwIp, strName); CNameCacheEntry cacheEntry; cacheEntry.m_dwIp = dwIp; cacheEntry.m_strName = strName; cacheEntry.m_timeLastUpdate.GetCurrentTime(); g_NameCache.Add(cacheEntry); Trace2("CNameThread::Run - GetHostName for %lx returned %s\n", dwIp, strName); } if (FCheckForAbort()) break; (*m_pServerInfoArray)[i].m_strName = strName; } } return 29; // exit code so I can tell when the thread goes away } BOOL CNameThread::FCheckForAbort() { if (WaitForSingleObject(m_hEventHandle, 0) == WAIT_OBJECT_0) { Trace0("CNameThread::Run - abort detected, exiting...\n"); return TRUE; } else { return FALSE; } } void CNameThread::UpdateNameCache() { CTime time; time = CTime::GetCurrentTime(); CTimeSpan timespan(0, 1, 0, 0); // 1 hour for (int i = 0; i < g_NameCache.GetSize(); i++) { if (g_NameCache[i].m_timeLastUpdate < (time - timespan)) { CString strName; GetHostName(g_NameCache[i].m_dwIp, strName); g_NameCache[i].m_strName = strName; if (FCheckForAbort()) break; } } } BOOL CNameThread::GetNameFromCache(DWORD dwIp, CString & strName) { BOOL fFound = FALSE; for (int i = 0; i < g_NameCache.GetSize(); i++) { if (g_NameCache[i].m_dwIp == dwIp) { strName = g_NameCache[i].m_strName; fFound = TRUE; break; } } return fFound; } /*--------------------------------------------------------------------------- Constructor and destructor Description Author: EricDav ---------------------------------------------------------------------------*/ CWinsServerHandler::CWinsServerHandler ( ITFSComponentData * pComponentData, LPCWSTR pServerName, BOOL fConnected, DWORD dwIp, DWORD dwFlags, DWORD dwRefreshInterval ) : CMTWinsHandler(pComponentData), m_dwFlags(dwFlags), m_dwRefreshInterval(dwRefreshInterval), m_hBinding(NULL) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); m_strServerAddress = pServerName; m_fConnected = fConnected; m_dwIPAdd = dwIp; m_hBinding = NULL; m_bExtension = FALSE; m_pNameThread = NULL; strcpy(szIPMon, ""); } /*--------------------------------------------------------------------------- Constructor and destructor Description Author: EricDav ---------------------------------------------------------------------------*/ CWinsServerHandler::~CWinsServerHandler() { HWND hStatsWnd; // Check to see if this node has a stats sheet up. hStatsWnd = m_dlgStats.GetSafeHwnd(); if (hStatsWnd != NULL) { m_dlgStats.KillRefresherThread(); } // diconnect from server and make the handle invalid DisConnectFromWinsServer(); // kill the name query thread if exists if (m_pNameThread) { m_pNameThread->AbortAndWait(); delete m_pNameThread; } } /*!-------------------------------------------------------------------------- CWinsServerHandler::InitializeNode Initializes node specific data Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CWinsServerHandler::InitializeNode ( ITFSNode * pNode ) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); CString IPAdd; CString strDisp; if (m_dwIPAdd != 0) { MakeIPAddress(m_dwIPAdd, IPAdd); strDisp.Format(IDS_SERVER_NAME_FORMAT, m_strServerAddress, IPAdd); } else { strDisp = m_strServerAddress; } SetDisplayName(strDisp); if (m_fConnected) { m_nState = loaded; } else { m_nState = notLoaded; } pNode->SetData(TFS_DATA_IMAGEINDEX, GetImageIndex(FALSE)); pNode->SetData(TFS_DATA_OPENIMAGEINDEX, GetImageIndex(TRUE)); // Make the node immediately visible pNode->SetVisibilityState(TFS_VIS_SHOW); pNode->SetData(TFS_DATA_COOKIE, (LPARAM) pNode); pNode->SetData(TFS_DATA_USER, (LPARAM) this); pNode->SetData(TFS_DATA_TYPE, WINSSNAP_SERVER); SetColumnStringIDs(&aColumns[WINSSNAP_SERVER][0]); SetColumnWidths(&aColumnWidths[WINSSNAP_SERVER][0]); return hrOK; } /*--------------------------------------------------------------------------- CWinsServerHandler::OnCreateNodeId2 Returns a unique string for this node Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CWinsServerHandler::OnCreateNodeId2(ITFSNode * pNode, CString & strId, DWORD * dwFlags) { const GUID * pGuid = pNode->GetNodeType(); CString strGuid; StringFromGUID2(*pGuid, strGuid.GetBuffer(256), 256); strGuid.ReleaseBuffer(); strId = m_strServerAddress + strGuid; return hrOK; } /*--------------------------------------------------------------------------- CWinsServerHandler::GetImageIndex Description Author: EricDav ---------------------------------------------------------------------------*/ int CWinsServerHandler::GetImageIndex(BOOL bOpenImage) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); int nIndex = 0; switch (m_nState) { case notLoaded: nIndex = ICON_IDX_SERVER; break; case loaded: nIndex = ICON_IDX_SERVER_CONNECTED; m_strConnected.LoadString(IDS_SERVER_CONNECTED); break; case unableToLoad: if (m_dwErr == ERROR_ACCESS_DENIED) { nIndex = ICON_IDX_SERVER_NO_ACCESS; } else { nIndex = ICON_IDX_SERVER_LOST_CONNECTION; } m_strConnected.LoadString(IDS_SERVER_NOTCONNECTED); break; case loading: nIndex = ICON_IDX_SERVER_BUSY; break; default: ASSERT(FALSE); } return nIndex; } /*--------------------------------------------------------------------------- CWinsServerHandler::OnHaveData Description Author: EricDav ---------------------------------------------------------------------------*/ void CWinsServerHandler::OnHaveData ( ITFSNode * pParentNode, ITFSNode * pNewNode ) { // expand the node so that child nodes appear correctly LONG_PTR dwType = pNewNode->GetData(TFS_DATA_TYPE); switch (dwType) { case WINSSNAP_ACTIVE_REGISTRATIONS: { CActiveRegistrationsHandler * pActReg = GETHANDLER(CActiveRegistrationsHandler, pNewNode); pActReg->SetServer(pParentNode); m_spActiveReg.Set(pNewNode); } break; case WINSSNAP_REPLICATION_PARTNERS: m_spReplicationPartner.Set(pNewNode); break; default: Assert("Invalid node types passed back to server handler!"); break; } pParentNode->AddChild(pNewNode); // now tell the view to update themselves ExpandNode(pParentNode, TRUE); } /*--------------------------------------------------------------------------- CWinsServerHandler::OnHaveData Description Author: EricDav ---------------------------------------------------------------------------*/ void CWinsServerHandler::OnHaveData ( ITFSNode * pParentNode, LPARAM Data, LPARAM Type ) { // This is how we get non-node data back from the background thread. AFX_MANAGE_STATE(AfxGetStaticModuleState( )); switch (Type) { case WINS_QDATA_SERVER_INFO: { CServerData * pServerInfo = (CServerData *) Data; DisConnectFromWinsServer(); m_hBinding = pServerInfo->m_hBinding; m_dwIPAdd = pServerInfo->m_dwServerIp; m_strServerAddress = pServerInfo->m_strServerName; m_cConfig = pServerInfo->m_config; // update the name string if (!m_bExtension) { SPITFSNode spRoot; CWinsRootHandler * pRoot; m_spNodeMgr->GetRootNode(&spRoot); pRoot = GETHANDLER(CWinsRootHandler, spRoot); SetDisplay(pParentNode, pRoot->GetShowLongName()); } delete pServerInfo; } break; } } /*--------------------------------------------------------------------------- Overridden base handler functions ---------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------- CWinsServerHandler::OnAddMenuItems Description Author: EricDav ---------------------------------------------------------------------------*/ STDMETHODIMP CWinsServerHandler::OnAddMenuItems ( ITFSNode * pNode, LPCONTEXTMENUCALLBACK pContextMenuCallback, LPDATAOBJECT lpDataObject, DATA_OBJECT_TYPES type, DWORD dwType, long * pInsertionAllowed ) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); LONG fFlags = 0, fLoadingFlags = 0, f351Flags = 0, fAdminFlags = 0; HRESULT hr = S_OK; CString strMenuItem; BOOL b351 = FALSE; if ( m_nState != loaded ) { fFlags |= MF_GRAYED; } if ( m_nState == loading) { fLoadingFlags = MF_GRAYED; } if (!m_cConfig.IsAdmin()) { fAdminFlags = MF_GRAYED; } if (type == CCT_SCOPE) { if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP) { strMenuItem.LoadString(IDS_SHOW_SERVER_STATS); hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, IDS_SHOW_SERVER_STATS, CCM_INSERTIONPOINTID_PRIMARY_TOP, fFlags ); ASSERT( SUCCEEDED(hr) ); // separator hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, 0, CCM_INSERTIONPOINTID_PRIMARY_TOP, MF_SEPARATOR); ASSERT( SUCCEEDED(hr) ); // scavenge strMenuItem.LoadString(IDS_SERVER_SCAVENGE); hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, IDS_SERVER_SCAVENGE, CCM_INSERTIONPOINTID_PRIMARY_TOP, fFlags ); ASSERT( SUCCEEDED(hr) ); // check if 351 server is being managed if ( m_nState == loaded ) b351 = CheckIfNT351Server(); // yes? grey out the consistency check items if(b351) f351Flags |= MF_GRAYED; else f351Flags &= ~MF_GRAYED; // only available to admins strMenuItem.LoadString(IDS_DO_CONSISTENCY_CHECK); hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, IDS_DO_CONSISTENCY_CHECK, CCM_INSERTIONPOINTID_PRIMARY_TOP, f351Flags | fFlags | fAdminFlags); ASSERT( SUCCEEDED(hr) ); // only available to admins strMenuItem.LoadString(IDS_CHECK_VERSION_CONSISTENCY); hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, IDS_CHECK_VERSION_CONSISTENCY, CCM_INSERTIONPOINTID_PRIMARY_TOP, f351Flags | fFlags | fAdminFlags); ASSERT( SUCCEEDED(hr) ); // separator hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, 0, CCM_INSERTIONPOINTID_PRIMARY_TOP, MF_SEPARATOR); ASSERT( SUCCEEDED(hr) ); // replication triggers strMenuItem.LoadString(IDS_REP_SEND_PUSH_TRIGGER); hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, IDS_REP_SEND_PUSH_TRIGGER, CCM_INSERTIONPOINTID_PRIMARY_TOP, fFlags ); ASSERT( SUCCEEDED(hr) ); strMenuItem.LoadString(IDS_REP_SEND_PULL_TRIGGER); hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, IDS_REP_SEND_PULL_TRIGGER, CCM_INSERTIONPOINTID_PRIMARY_TOP, fFlags ); ASSERT( SUCCEEDED(hr) ); // separator hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, 0, CCM_INSERTIONPOINTID_PRIMARY_TOP, MF_SEPARATOR); ASSERT( SUCCEEDED(hr) ); // enable backp and restore database only for local servers if(IsLocalConnection() && m_nState == loaded) fFlags &= ~MF_GRAYED; else fFlags |= MF_GRAYED; strMenuItem.LoadString(IDS_SERVER_BACKUP); hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, IDS_SERVER_BACKUP, CCM_INSERTIONPOINTID_PRIMARY_TOP, fFlags ); ASSERT( SUCCEEDED(hr) ); // default is to not show this item fFlags |= MF_GRAYED; BOOL fServiceRunning = TRUE; ::TFSIsServiceRunning(m_strServerAddress, _T("WINS"), &fServiceRunning); if (IsLocalConnection() && m_cConfig.IsAdmin()) { // the service call can be costly if doing it remotely, so only do it // when we really need to. if (!fServiceRunning) fFlags &= ~MF_GRAYED; } strMenuItem.LoadString(IDS_SERVER_RESTORE); hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, IDS_SERVER_RESTORE, CCM_INSERTIONPOINTID_PRIMARY_TOP, fFlags ); ASSERT( SUCCEEDED(hr) ); } if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TASK) { // start/stop service menu items if ( m_nState == notLoaded || m_nState == loading) { fFlags = MF_GRAYED; } else { fFlags = 0; } DWORD dwServiceStatus, dwErrorCode, dwErr; dwErr = ::TFSGetServiceStatus(m_strServerAddress, _T("wins"), &dwServiceStatus, &dwErrorCode); if (dwErr != ERROR_SUCCESS) fFlags |= MF_GRAYED; // determining the restart state is the same as the stop flag LONG lStartFlag = (dwServiceStatus == SERVICE_STOPPED) ? 0 : MF_GRAYED; LONG lStopFlag = ( (dwServiceStatus == SERVICE_RUNNING) || (dwServiceStatus == SERVICE_PAUSED) ) ? 0 : MF_GRAYED; LONG lPauseFlag = ( (dwServiceStatus == SERVICE_RUNNING) || ( (dwServiceStatus != SERVICE_PAUSED) && (dwServiceStatus != SERVICE_STOPPED) ) ) ? 0 : MF_GRAYED; LONG lResumeFlag = (dwServiceStatus == SERVICE_PAUSED) ? 0 : MF_GRAYED; strMenuItem.LoadString(IDS_SERVER_START_SERVICE); hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, IDS_SERVER_START_SERVICE, CCM_INSERTIONPOINTID_PRIMARY_TASK, fFlags | lStartFlag); strMenuItem.LoadString(IDS_SERVER_STOP_SERVICE); hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, IDS_SERVER_STOP_SERVICE, CCM_INSERTIONPOINTID_PRIMARY_TASK, fFlags | lStopFlag); strMenuItem.LoadString(IDS_SERVER_PAUSE_SERVICE); hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, IDS_SERVER_PAUSE_SERVICE, CCM_INSERTIONPOINTID_PRIMARY_TASK, fFlags | lPauseFlag); strMenuItem.LoadString(IDS_SERVER_RESUME_SERVICE); hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, IDS_SERVER_RESUME_SERVICE, CCM_INSERTIONPOINTID_PRIMARY_TASK, fFlags | lResumeFlag); strMenuItem.LoadString(IDS_SERVER_RESTART_SERVICE); hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, IDS_SERVER_RESTART_SERVICE, CCM_INSERTIONPOINTID_PRIMARY_TASK, fFlags | lStopFlag); /* Don't do this in the snapin, go back to the old command prompt way strMenuItem.LoadString(IDS_SERVER_COMPACT); hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, IDS_SERVER_COMPACT, CCM_INSERTIONPOINTID_PRIMARY_TASK, fFlags ); ASSERT( SUCCEEDED(hr) ); */ } } return hr; } /*--------------------------------------------------------------------------- CWinsServerHandler::OnCommand Description Author: EricDav ---------------------------------------------------------------------------*/ STDMETHODIMP CWinsServerHandler::OnCommand ( ITFSNode * pNode, long nCommandId, DATA_OBJECT_TYPES type, LPDATAOBJECT pDataObject, DWORD dwType ) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); HRESULT hr = S_OK; switch (nCommandId) { case IDS_SHOW_SERVER_STATS: ShowServerStatDialog(pNode); break; case IDS_SERVER_BACKUP: DoDBBackup(pNode); break; case IDS_SERVER_SCAVENGE: DoDBScavenge(pNode); break; case IDS_SERVER_COMPACT: DoDBCompact(pNode); break; case IDS_SERVER_RESTORE: DoDBRestore(pNode); break; case IDS_DO_CONSISTENCY_CHECK: OnDoConsistencyCheck(pNode); break; case IDS_CHECK_VERSION_CONSISTENCY: OnDoVersionConsistencyCheck(pNode); break; case IDS_REP_SEND_PUSH_TRIGGER: hr = OnSendPushTrigger(pNode); break; case IDS_REP_SEND_PULL_TRIGGER: hr = OnSendPullTrigger(pNode); break; case IDS_SERVER_STOP_SERVICE: hr = OnControlService(pNode, FALSE); break; case IDS_SERVER_START_SERVICE: hr = OnControlService(pNode, TRUE); break; case IDS_SERVER_PAUSE_SERVICE: hr = OnPauseResumeService(pNode, TRUE); break; case IDS_SERVER_RESUME_SERVICE: hr = OnPauseResumeService(pNode, FALSE); break; case IDS_SERVER_RESTART_SERVICE: hr = OnRestartService(pNode); break; default: break; } return hr; } /*!-------------------------------------------------------------------------- CWinsServerHandler::HasPropertyPages Implementation of ITFSNodeHandler::HasPropertyPages NOTE: the root node handler has to over-ride this function to handle the snapin manager property page (wizard) case!!! Author: KennT ---------------------------------------------------------------------------*/ STDMETHODIMP CWinsServerHandler::HasPropertyPages ( ITFSNode * pNode, LPDATAOBJECT pDataObject, DATA_OBJECT_TYPES type, DWORD dwType ) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); HRESULT hr = hrOK; if (dwType & TFS_COMPDATA_CREATE) { // This is the case where we are asked to bring up property // pages when the user is adding a new snapin. These calls // are forwarded to the root node to handle. hr = hrOK; Assert(FALSE); // should never get here } else { // we have property pages in the normal case, but don't put the // menu up if we are not loaded yet if ( m_nState != loaded ) { hr = hrFalse; } else { hr = hrOK; } } return hr; } /*--------------------------------------------------------------------------- CWinsServerHandler::CreatePropertyPages Description Author: EricDav ---------------------------------------------------------------------------*/ STDMETHODIMP CWinsServerHandler::CreatePropertyPages ( ITFSNode * pNode, LPPROPERTYSHEETCALLBACK lpProvider, LPDATAOBJECT pDataObject, LONG_PTR handle, DWORD dwType ) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); HRESULT hr = hrOK; HPROPSHEETPAGE hPage; SPIComponentData spComponentData; Assert(pNode->GetData(TFS_DATA_COOKIE) != 0); // // Object gets deleted when the page is destroyed // m_spNodeMgr->GetComponentData(&spComponentData); ConnectToWinsServer(pNode); // to read the values from the registry DWORD err = m_cConfig.Load(GetBinding()); // unable to read the registry if (err != ERROR_SUCCESS) { ::WinsMessageBox(WIN32_FROM_HRESULT(err)); return hrOK; } CServerProperties * pServerProp = new CServerProperties(pNode, spComponentData, m_spTFSCompData, NULL); pServerProp->m_pageGeneral.m_uImage = GetImageIndex(FALSE); pServerProp->SetConfig(&m_cConfig); Assert(lpProvider != NULL); return pServerProp->CreateModelessSheet(lpProvider, handle); } /*--------------------------------------------------------------------------- CWinsServerHandler::OnPropertyChange Description Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CWinsServerHandler::OnPropertyChange ( ITFSNode * pNode, LPDATAOBJECT pDataobject, DWORD dwType, LPARAM arg, LPARAM lParam ) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); CServerProperties * pServerProp = reinterpret_cast(lParam); LONG_PTR changeMask = 0; // tell the property page to do whatever now that we are back on the // main thread pServerProp->OnPropertyChange(TRUE, &changeMask); pServerProp->AcknowledgeNotify(); if (changeMask) pNode->ChangeNode(changeMask); return hrOK; } /*!-------------------------------------------------------------------------- CWinsServer::Command Handles commands for the current view Author: EricDav ---------------------------------------------------------------------------*/ STDMETHODIMP CWinsServerHandler::Command ( ITFSComponent * pComponent, MMC_COOKIE cookie, int nCommandID, LPDATAOBJECT pDataObject ) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); HRESULT hr = S_OK; switch (nCommandID) { case MMCC_STANDARD_VIEW_SELECT: break; // this may have come from the scope pane handler, so pass it up default: hr = HandleScopeCommand(cookie, nCommandID, pDataObject); break; } return hr; } /*!-------------------------------------------------------------------------- CWinsServer::AddMenuItems Over-ride this to add our view menu item Author: EricDav ---------------------------------------------------------------------------*/ STDMETHODIMP CWinsServerHandler::AddMenuItems ( ITFSComponent * pComponent, MMC_COOKIE cookie, LPDATAOBJECT pDataObject, LPCONTEXTMENUCALLBACK pContextMenuCallback, long * pInsertionAllowed ) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); HRESULT hr = S_OK; // figure out if we need to pass this to the scope pane menu handler hr = HandleScopeMenus(cookie, pDataObject, pContextMenuCallback, pInsertionAllowed); return hr; } /*--------------------------------------------------------------------------- Command handlers ---------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------- CWinsServerHandler::ShowServerStatDialog(ITFSNode* pNode) Displays the ServerStatistics Window Author: v-shubk ---------------------------------------------------------------------------*/ HRESULT CWinsServerHandler::ShowServerStatDialog(ITFSNode* pNode) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); m_dlgStats.SetNode(pNode); m_dlgStats.SetServer(m_strServerAddress); CreateNewStatisticsWindow(&m_dlgStats, ::FindMMCMainWindow(), IDD_STATS_NARROW); HRESULT hr = hrOK; return hr; } /*!-------------------------------------------------------------------------- CWinsServerHandler::OnDelete The base handler calls this when MMC sends a MMCN_DELETE for a scope pane item. We just call our delete command handler. Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CWinsServerHandler::OnDelete ( ITFSNode * pNode, LPARAM arg, LPARAM lParam ) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); HRESULT hr = S_OK; LONG err = 0 ; CString strMessage, strTemp; SPITFSNode spParent; CWinsStatusHandler *pStat = NULL; CWinsRootHandler *pRoot = NULL; strTemp = m_strServerAddress; AfxFormatString1(strMessage, IDS_DELETE_SERVER, m_strServerAddress); if (AfxMessageBox(strMessage, MB_YESNO) != IDYES) return NOERROR; pNode->GetParent(&spParent); pRoot = GETHANDLER(CWinsRootHandler, spParent); // remove the node from the status node as well pStat = GETHANDLER(CWinsStatusHandler, pRoot->m_spStatusNode); pStat->DeleteNode(pRoot->m_spStatusNode, this); // remove this node from the list, there's nothing we need to tell // the server, it's just our local list of servers spParent->RemoveChild(pNode); return hr; } /*--------------------------------------------------------------------------- CWinsServerHandler::LoadColumns() Description Author: v-shubk ---------------------------------------------------------------------------*/ HRESULT CWinsServerHandler::LoadColumns(ITFSComponent * pComponent, MMC_COOKIE cookie, LPARAM arg, LPARAM lParam) { HRESULT hr = hrOK; AFX_MANAGE_STATE(AfxGetStaticModuleState()); SPIHeaderCtrl spHeaderCtrl; pComponent->GetHeaderCtrl(&spHeaderCtrl); CString str; int i = 0; CString strTemp; strTemp = m_strServerAddress; while( i< ARRAYLEN(aColumnWidths[1])) { if (i == 0) { AfxFormatString1(str, IDS_WINSSERVER_NAME, strTemp); int nTest = spHeaderCtrl->InsertColumn(i, const_cast((LPCWSTR)str), LVCFMT_LEFT, aColumnWidths[1][0]); i++; } else { str.LoadString(IDS_DESCRIPTION); int nTest = spHeaderCtrl->InsertColumn(1, const_cast((LPCWSTR)str), LVCFMT_LEFT, aColumnWidths[1][1]); i++; } if(aColumns[0][i] == 0) break; } return hrOK; } /*!-------------------------------------------------------------------------- CWinsServerHandler::GetStatistics() Gets the statistics from the server Author: v-shubk ---------------------------------------------------------------------------*/ DWORD CWinsServerHandler::GetStatistics(ITFSNode * pNode, PWINSINTF_RESULTS_T * ppStats) { DWORD dwStatus = ERROR_SUCCESS; CString strName, strIP; if (ppStats) *ppStats = NULL; if (m_dwStatus != ERROR_SUCCESS) m_dwStatus = ConnectToWinsServer(pNode); if (m_dwStatus == ERROR_SUCCESS) { m_wrResults.WinsStat.NoOfPnrs = 0; m_wrResults.WinsStat.pRplPnrs = 0; m_wrResults.NoOfWorkerThds = 1; #ifdef WINS_CLIENT_APIS dwStatus = ::WinsStatus(m_hBinding, WINSINTF_E_STAT, &m_wrResults); #else dwStatus = ::WinsStatus(WINSINTF_E_STAT, &m_wrResults); #endif WINS_CLIENT_APIS if (dwStatus == ERROR_SUCCESS) { if (ppStats) *ppStats = &m_wrResults; } } else { dwStatus = m_dwStatus; } return dwStatus; } /*!-------------------------------------------------------------------------- CWinsServerHandler::ClearStatistics() Clears the statistics from the server Author: v-shubk ---------------------------------------------------------------------------*/ DWORD CWinsServerHandler::ClearStatistics(ITFSNode *pNode) { DWORD dwStatus = ERROR_SUCCESS; CString strName, strIP; if (m_dwStatus != ERROR_SUCCESS) m_dwStatus = ConnectToWinsServer(pNode); if (m_dwStatus == ERROR_SUCCESS) { #ifdef WINS_CLIENT_APIS dwStatus = ::WinsResetCounters(m_hBinding); #else dwStatus = ::WinsResetCounters(); #endif WINS_CLIENT_APIS } else { dwStatus = m_dwStatus; } return dwStatus; } /*--------------------------------------------------------------------------- CWinsServerHandler::ConnectToWinsServer() Connects to the wins server Author: v-shubk ---------------------------------------------------------------------------*/ DWORD CWinsServerHandler::ConnectToWinsServer(ITFSNode *pNode) { HRESULT hr = hrOK; CString strServerName, strIP; DWORD dwStatus = ERROR_SUCCESS; WINSINTF_ADD_T waWinsAddress; WINSINTF_BIND_DATA_T wbdBindData; // build some information about the server strServerName = GetServerAddress(); DWORD dwIP = GetServerIP(); MakeIPAddress(dwIP, strIP); DisConnectFromWinsServer(); // now that the server name and ip are valid, call // WINSBind function directly. do { char szNetBIOSName[128] = {0}; // call WinsBind function with the IP address wbdBindData.fTcpIp = 1; wbdBindData.pPipeName = NULL; wbdBindData.pServerAdd = (LPSTR) (LPCTSTR) strIP; BEGIN_WAIT_CURSOR if ((m_hBinding = ::WinsBind(&wbdBindData)) == NULL) { m_dwStatus = ::GetLastError(); break; } #ifdef WINS_CLIENT_APIS m_dwStatus = ::WinsGetNameAndAdd(m_hBinding, &waWinsAddress, (LPBYTE) szNetBIOSName); #else m_dwStatus = ::WinsGetNameAndAdd(&waWinsAddress, (LPBYTE) szNetBIOSName); #endif WINS_CLIENT_APIS END_WAIT_CURSOR } while (FALSE); return m_dwStatus; } /*--------------------------------------------------------------------------- CWinsServerHandler::DoDBBackup() backs up the database Author: v-shubk ---------------------------------------------------------------------------*/ HRESULT CWinsServerHandler::DoDBBackup(ITFSNode *pNode) { HRESULT hr = hrOK; DWORD dwStatus = ConnectToWinsServer(pNode); CString strBackupPath; CString strHelpText; strHelpText.LoadString(IDS_SELECT_BACKUP_FOLDER); if (GetFolderName(strBackupPath, strHelpText)) { dwStatus = BackupDatabase(strBackupPath); if (dwStatus == ERROR_SUCCESS) { AfxMessageBox(IDS_DB_BACKUP_SUCCESS, MB_ICONINFORMATION | MB_OK); // don't update the default path just because they selected a path here //if (m_cConfig.m_strBackupPath.CompareNoCase(strBackupPath) != 0) //{ // m_cConfig.m_strBackupPath = strBackupPath; // m_cConfig.Store(); //} } else { ::WinsMessageBox(dwStatus, MB_OK); } } return HRESULT_FROM_WIN32(dwStatus); } /*--------------------------------------------------------------------------- CWinsServerHandler::BackupDatabase(CString strBackupPath) Calls WINS API for backing the database Author: v-shubk ---------------------------------------------------------------------------*/ DWORD CWinsServerHandler::BackupDatabase(CString strBackupPath) { BOOL fIncremental = FALSE; BOOL fDefaultCharUsed = FALSE; DWORD dwStatus = ERROR_SUCCESS; char szTemp[MAX_PATH] = {0}; // INTL$ Should this be ACP or OEMCP? WideToMBCS(strBackupPath, szTemp, CP_ACP, 0, &fDefaultCharUsed); if (fDefaultCharUsed) { // could not convert this string... error out dwStatus = IDS_ERR_CANT_CONVERT_STRING; } else { BEGIN_WAIT_CURSOR #ifdef WINS_CLIENT_APIS dwStatus = ::WinsBackup(m_hBinding, (unsigned char *)szTemp, (short)fIncremental); #else dwStatus = ::WinsBackup((unsigned char *)szTemp, (short)fIncremental); #endif WINS_CLIENT_APIS END_WAIT_CURSOR } return dwStatus; } /*--------------------------------------------------------------------------- CWinsServerHandler::DoDBCompact() backs up the database Author: v-shubk ---------------------------------------------------------------------------*/ HRESULT CWinsServerHandler::DoDBCompact(ITFSNode *pNode) { HRESULT hr = hrOK; // tell the user that we need to stop WINS in order to do this if (AfxMessageBox(IDS_WARN_SERVICE_STOP, MB_YESNO) == IDNO) return hr; CDBCompactProgress dlgCompactProgress; dlgCompactProgress.m_dwIpAddress = m_dwIPAdd; dlgCompactProgress.m_strServerName = m_strServerAddress; dlgCompactProgress.m_hBinding = GetBinding(); dlgCompactProgress.m_pConfig = &m_cConfig; dlgCompactProgress.DoModal(); // since the service gets restarted, the new binding handle is in the object m_hBinding = dlgCompactProgress.m_hBinding; return hr; } /*--------------------------------------------------------------------------- CWinsServerHandler::DoDBRestore() Restores the database Author:v-shubk ---------------------------------------------------------------------------*/ HRESULT CWinsServerHandler::DoDBRestore(ITFSNode *pNode) { DWORD dwStatus = 0; DWORD err = ERROR_SUCCESS; HRESULT hr = hrOK; CString strRestorePath; CString strHelpText; strHelpText.LoadString(IDS_SELECT_RESTORE_FOLDER); if (GetFolderName(strRestorePath, strHelpText)) { BOOL fOldBackup = m_cConfig.m_fBackupOnTermination; if (!strRestorePath.IsEmpty()) { BEGIN_WAIT_CURSOR // need to disable backup on shutdown since we need to shutdown // the server to do this and we don't want it to backup and stomp // over what we may want to restore. if (fOldBackup) { m_cConfig.m_fBackupOnTermination = FALSE; m_cConfig.Store(); } DisConnectFromWinsServer(); // convert the string from unicode to DBCS for the WINS API char szTemp[MAX_PATH * 2] = {0}; BOOL fDefaultCharUsed = FALSE; // INTL$ should this be ACP or OEMCP? WideToMBCS(strRestorePath, szTemp, CP_ACP, 0, &fDefaultCharUsed); // if there is no code page available for conversion, error out if (fDefaultCharUsed) { dwStatus = IDS_ERR_CANT_CONVERT_STRING; } else { dwStatus = ::WinsRestore((LPBYTE) szTemp); } END_WAIT_CURSOR if (dwStatus == ERROR_SUCCESS) { // re-start the WINS service that was stopped CString strServiceDesc; strServiceDesc.LoadString(IDS_SERVICE_NAME); err = TFSStartServiceEx(m_strServerAddress, _T("wins"), _T("WINS Service"), strServiceDesc); // connect to the server again ConnectToWinsServer(pNode); // let the user know everything went OK. AfxMessageBox(IDS_DB_RESTORE_SUCCESS, MB_ICONINFORMATION | MB_OK); } else { ::WinsMessageBox(dwStatus, MB_OK); } hr = HRESULT_FROM_WIN32(dwStatus); // restore the backup on shutdown flag if necessary if (fOldBackup) { m_cConfig.m_fBackupOnTermination = TRUE; m_cConfig.Store(); } if (SUCCEEDED(hr)) { // need to refresh the server node because this can only be triggered // if the service wasn't running if (m_pNameThread) { m_pNameThread->Abort(); m_pNameThread = NULL; } OnRefresh(pNode, NULL, 0, 0, 0); } } } return hr; } /*--------------------------------------------------------------------------- CWinsServerHandler::OnControlService - Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CWinsServerHandler::OnControlService ( ITFSNode * pNode, BOOL fStart ) { HRESULT hr = hrOK; DWORD err = ERROR_SUCCESS; CString strServiceDesc; strServiceDesc.LoadString(IDS_SERVICE_NAME); if (fStart) { err = TFSStartServiceEx(m_strServerAddress, _T("wins"), _T("WINS Service"), strServiceDesc); } else { err = TFSStopServiceEx(m_strServerAddress, _T("wins"), _T("WINS Service"), strServiceDesc); } if (err == ERROR_SUCCESS) { // need to refresh the server node because this can only be triggered // if the service wasn't running if (m_pNameThread) { m_pNameThread->Abort(); m_pNameThread = NULL; } if (!fStart) m_fSilent = TRUE; OnRefresh(pNode, NULL, 0, 0, 0); } else { WinsMessageBox(err); hr = HRESULT_FROM_WIN32(err); } return hr; } /*--------------------------------------------------------------------------- CWinsServerHandler::OnPauseResumeService - Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CWinsServerHandler::OnPauseResumeService ( ITFSNode * pNode, BOOL fPause ) { HRESULT hr = hrOK; DWORD err = ERROR_SUCCESS; CString strServiceDesc; strServiceDesc.LoadString(IDS_SERVICE_NAME); if (fPause) { err = TFSPauseService(m_strServerAddress, _T("wins"), strServiceDesc); } else { err = TFSResumeService(m_strServerAddress, _T("wins"), strServiceDesc); } if (err != ERROR_SUCCESS) { WinsMessageBox(err); hr = HRESULT_FROM_WIN32(err); } return hr; } /*--------------------------------------------------------------------------- CWinsServerHandler::OnRestartService - Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CWinsServerHandler::OnRestartService ( ITFSNode * pNode ) { HRESULT hr = hrOK; DWORD err = ERROR_SUCCESS; CString strServiceDesc; strServiceDesc.LoadString(IDS_SERVICE_NAME); err = TFSStopServiceEx(m_strServerAddress, _T("wins"), _T("WINS Service"), strServiceDesc); if (err != ERROR_SUCCESS) { WinsMessageBox(err); hr = HRESULT_FROM_WIN32(err); } if (SUCCEEDED(hr)) { err = TFSStartServiceEx(m_strServerAddress, _T("wins"), _T("WINS Service"), strServiceDesc); if (err != ERROR_SUCCESS) { WinsMessageBox(err); hr = HRESULT_FROM_WIN32(err); } } // refresh OnRefresh(pNode, NULL, 0, 0, 0); return hr; } /*--------------------------------------------------------------------------- CWinsServerHandler::UpdateStatistics Notification that stats are now available. Update stats for the server node and give all subnodes a chance to update. Author: EricDav ---------------------------------------------------------------------------*/ DWORD CWinsServerHandler::UpdateStatistics ( ITFSNode * pNode ) { HRESULT hr = hrOK; SPITFSNodeEnum spNodeEnum; SPITFSNode spCurrentNode; ULONG nNumReturned; HWND hStatsWnd; BOOL bChangeIcon = FALSE; // Check to see if this node has a stats sheet up. hStatsWnd = m_dlgStats.GetSafeHwnd(); if (hStatsWnd != NULL) { PostMessage(hStatsWnd, WM_NEW_STATS_AVAILABLE, 0, 0); } return hr; } /*--------------------------------------------------------------------------- CWinsServerHandler::DoDBScavenge() Scavenges the database Author: v-shubk ---------------------------------------------------------------------------*/ HRESULT CWinsServerHandler::DoDBScavenge(ITFSNode *pNode) { HRESULT hr = hrOK; DWORD dwStatus; if (m_dwStatus != ERROR_SUCCESS) { dwStatus = ConnectToWinsServer(pNode); } #ifdef WINS_CLIENT_APIS dwStatus = ::WinsDoScavenging(m_hBinding); #else dwStatus = ::WinsDoScavenging(); #endif WINS_CLIENT_APIS if (dwStatus == ERROR_SUCCESS) { CString strDisp; CString strTemp; strTemp.LoadString(IDS_SCAVENGE_COMMAND); AfxFormatString1(strDisp, IDS_QUEUED_MESSAGE, strTemp); AfxMessageBox(strDisp, MB_ICONINFORMATION|MB_OK); BEGIN_WAIT_CURSOR // refresh the stats m_wrResults.WinsStat.NoOfPnrs = 0; m_wrResults.WinsStat.pRplPnrs = 0; m_wrResults.NoOfWorkerThds = 1; #ifdef WINS_CLIENT_APIS dwStatus = ::WinsStatus(m_hBinding, WINSINTF_E_CONFIG, &m_wrResults); #else dwStatus = ::WinsStatus(WINSINTF_E_CONFIG, &m_wrResults); #endif WINS_CLIENT_APIS UpdateStatistics(pNode); END_WAIT_CURSOR } else { ::WinsMessageBox(dwStatus, MB_OK); } return HRESULT_FROM_WIN32(dwStatus); } /*--------------------------------------------------------------------------- CWinsServerHandler::IsValidNetBIOSName Determine if the given netbios is valid, and pre-pend a double backslash if not already present (and the address is otherwise valid). ---------------------------------------------------------------------------*/ BOOL CWinsServerHandler::IsValidNetBIOSName ( CString & strAddress, BOOL fLanmanCompatible, BOOL fWackwack // expand slashes if not present ) { TCHAR szWacks[] = _T("\\\\"); if (strAddress.IsEmpty()) { return FALSE; } if (strAddress[0] == _T('\\')) { if (strAddress.GetLength() < 3) { return FALSE; } if (strAddress[1] != _T('\\')) { // One slash only? Not valid return FALSE; } } else { if (fWackwack) { // Add the backslashes strAddress = szWacks + strAddress; } } int nMaxAllowedLength = fLanmanCompatible ? LM_NAME_MAX_LENGTH : NB_NAME_MAX_LENGTH; if (fLanmanCompatible) { strAddress.MakeUpper(); } return strAddress.GetLength() <= nMaxAllowedLength + 2; } /*--------------------------------------------------------------------------- CWinsServerHandler::OnResultRefresh Refreshes the data relating to the server Author: v-shubk ---------------------------------------------------------------------------*/ HRESULT CWinsServerHandler::OnResultRefresh ( ITFSComponent * pComponent, LPDATAOBJECT pDataObject, MMC_COOKIE cookie, LPARAM arg, LPARAM lParam ) { HRESULT hr = hrOK; SPITFSNode spNode; CORg (m_spNodeMgr->FindNode(cookie, &spNode)); if (m_pNameThread) { m_pNameThread->Abort(); m_pNameThread = NULL; } OnRefresh(spNode, pDataObject, 0, arg, lParam); Error: return hr; } /*--------------------------------------------------------------------------- CWinsServerHandler::OnDoConsistencyCheck(ITFSNode *pNode) Consisntency Check for WINS Author - v-shubk ---------------------------------------------------------------------------*/ HRESULT CWinsServerHandler::OnDoConsistencyCheck(ITFSNode *pNode) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); HRESULT hr = hrOK; if(IDYES != AfxMessageBox(IDS_CONSISTENCY_CONFIRM, MB_YESNO)) return hrFalse; WINSINTF_SCV_REQ_T ScvReq; ScvReq.Age = 0; // check all the replicas ScvReq.fForce = FALSE; ScvReq.Opcode_e = WINSINTF_E_SCV_VERIFY; #ifdef WINS_CLIENT_APIS DWORD dwStatus = ::WinsDoScavengingNew(m_hBinding, &ScvReq); #else DWORD dwStatus = ::WinsDoScavengingNew(&ScvReq); #endif WINS_CLIENT_APIS if(dwStatus == ERROR_SUCCESS) { CString strDisp, strJob; strJob.Format(IDS_DO_CONSISTENCY_CHECK_STR); AfxFormatString1(strDisp,IDS_QUEUED_MESSAGE, strJob); AfxMessageBox(strDisp, MB_OK); } else { ::WinsMessageBox(dwStatus, MB_OK); } return hr; } /*--------------------------------------------------------------------------- CWInsServerHandler::OnDoVersionConsistencyCheck(ITFSNode *pNode) Performs the version number consistency check Author: v-shubk ---------------------------------------------------------------------------*/ HRESULT CWinsServerHandler::OnDoVersionConsistencyCheck(ITFSNode *pNode) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); HRESULT hr = hrOK; if (IDYES != AfxMessageBox(IDS_VERSION_CONSIS_CHECK_WARNING, MB_YESNO)) return hrOK; CCheckVersionProgress dlgCheckVersions; dlgCheckVersions.m_dwIpAddress = m_dwIPAdd; dlgCheckVersions.m_hBinding = GetBinding(); dlgCheckVersions.DoModal(); return hr; } /*--------------------------------------------------------------------------- CWinsServerHandler::OnSendPushTrigger() Sends Push replication trigger ---------------------------------------------------------------------------*/ HRESULT CWinsServerHandler::OnSendPushTrigger(ITFSNode * pNode) { HRESULT hr = hrOK; DWORD err = ERROR_SUCCESS; CPushTrig dlgPushTrig; CGetTriggerPartner dlgTrigPartner; if (dlgTrigPartner.DoModal() != IDOK) return hr; if (dlgPushTrig.DoModal() != IDOK) return hr; err = ::SendTrigger(GetBinding(), (LONG) dlgTrigPartner.m_dwServerIp, TRUE, dlgPushTrig.GetPropagate()); if (err == ERROR_SUCCESS) { AfxMessageBox(IDS_REPL_QUEUED, MB_ICONINFORMATION); } else { WinsMessageBox(err); } return HRESULT_FROM_WIN32(err); } /*--------------------------------------------------------------------------- CWinsServerHandler::OnSendPullTrigger() Sends Pull replication trigger ---------------------------------------------------------------------------*/ HRESULT CWinsServerHandler::OnSendPullTrigger(ITFSNode * pNode) { HRESULT hr = hrOK; DWORD err = ERROR_SUCCESS; CPullTrig dlgPullTrig; CGetTriggerPartner dlgTrigPartner; if (dlgTrigPartner.DoModal() != IDOK) return hr; if (dlgPullTrig.DoModal() != IDOK) return hr; err = ::SendTrigger(GetBinding(), (LONG) dlgTrigPartner.m_dwServerIp, FALSE, FALSE); if (err == ERROR_SUCCESS) { AfxMessageBox(IDS_REPL_QUEUED, MB_ICONINFORMATION); } else { ::WinsMessageBox(err); } return HRESULT_FROM_WIN32(err); } /*--------------------------------------------------------------------------- CWinsServerHandler::GetFolderName(CString& strPath) Returns the folder name after displaying the File Dialog ---------------------------------------------------------------------------*/ BOOL CWinsServerHandler::GetFolderName(CString& strPath, CString& strHelpText) { BOOL fOk = FALSE; TCHAR szBuffer[MAX_PATH]; TCHAR szExpandedPath[MAX_PATH * 2]; CString strStartingPath = m_cConfig.m_strBackupPath; if (strStartingPath.IsEmpty()) { strStartingPath = _T("%SystemDrive%\\"); } ExpandEnvironmentStrings(strStartingPath, szExpandedPath, sizeof(szExpandedPath) / sizeof(TCHAR)); LPITEMIDLIST pidlPrograms = NULL; SHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &pidlPrograms); BROWSEINFO browseInfo; browseInfo.hwndOwner = ::FindMMCMainWindow(); browseInfo.pidlRoot = pidlPrograms; browseInfo.pszDisplayName = szBuffer; browseInfo.lpszTitle = strHelpText; browseInfo.ulFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS ; browseInfo.lpfn = BrowseCallbackProc; browseInfo.lParam = (LPARAM) szExpandedPath; LPITEMIDLIST pidlBrowse = SHBrowseForFolder(&browseInfo); fOk = SHGetPathFromIDList(pidlBrowse, szBuffer); CString strBackupPath(szBuffer); strPath = strBackupPath; LPMALLOC pMalloc = NULL; if (pidlPrograms && SUCCEEDED(SHGetMalloc(&pMalloc))) { if (pMalloc) pMalloc->Free(pidlPrograms); } return fOk; } /*--------------------------------------------------------------------------- CWinsServerHandler::SetExtensionName() - Author: EricDav ---------------------------------------------------------------------------*/ void CWinsServerHandler::SetExtensionName() { SetDisplayName(_T("WINS")); m_bExtension = TRUE; } /*--------------------------------------------------------------------------- CWinsServerHandler::IsLocalConnection() Checks if the local server is being managed Author: v-shubk ---------------------------------------------------------------------------*/ BOOL CWinsServerHandler::IsLocalConnection() { // get the server netbios name CString strServerName = m_strServerAddress; TCHAR lpBuffer[MAX_COMPUTERNAME_LENGTH + 1]; // address of name buffer DWORD nSize = MAX_COMPUTERNAME_LENGTH + 1; ::GetComputerName(lpBuffer,&nSize); CString strCompName(lpBuffer); if(strCompName.CompareNoCase(strServerName) == 0) return TRUE; return FALSE; } /*--------------------------------------------------------------------------- CWinsServerHandler:: DeleteWinsServer(CWinsServerObj* pws) Calls WinsAPI to delete the server Author: v-shubk ---------------------------------------------------------------------------*/ DWORD CWinsServerHandler:: DeleteWinsServer ( DWORD dwIpAddress ) { DWORD err = ERROR_SUCCESS; WINSINTF_ADD_T WinsAdd; WinsAdd.Len = 4; WinsAdd.Type = 0; WinsAdd.IPAdd = dwIpAddress; #ifdef WINS_CLIENT_APIS err = ::WinsDeleteWins(GetBinding(), &WinsAdd); #else err = ::WinsDeleteWins(&WinsAdd); #endif WINS_CLIENT_APIS return err; } /*--------------------------------------------------------------------------- CWinsServerHandler::DisConnectFromWinsServer() Calls WinsUnbind and makes the binding handle invalid ---------------------------------------------------------------------------*/ void CWinsServerHandler::DisConnectFromWinsServer() { if (m_hBinding) { CString strIP; WINSINTF_BIND_DATA_T wbdBindData; DWORD dwIP = GetServerIP(); MakeIPAddress(dwIP, strIP); wbdBindData.fTcpIp = 1; wbdBindData.pPipeName = NULL; wbdBindData.pServerAdd = (LPSTR) (LPCTSTR) strIP; ::WinsUnbind(&wbdBindData, m_hBinding); m_hBinding = NULL; } } /*--------------------------------------------------------------------------- CWinsServerHandler::CheckIfNT351Server() Checks if a 351 server is being managed ---------------------------------------------------------------------------*/ BOOL CWinsServerHandler::CheckIfNT351Server() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); DWORD err = ERROR_SUCCESS; CString lpstrRoot; CString lpstrVersion; CString strVersion; BOOL f351 = FALSE; // don't go to the registry each time -- we have the info in our config object // 7/8/98 - EricDav /* // connect to the registry of the server to find if // it's a 351 server lpstrRoot = _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"); lpstrVersion = _T("CurrentVersion"); RegKey rk; err = rk.Open(HKEY_LOCAL_MACHINE, lpstrRoot, KEY_READ, m_strServerAddress); // Get the count of items if (!err) err = rk.QueryValue(lpstrVersion,strVersion) ; if(strVersion.CompareNoCase(_T("3.51")) == 0 ) return TRUE; return FALSE; */ if (m_cConfig.m_dwMajorVersion < 4) { f351 = TRUE; } return f351; } /*--------------------------------------------------------------------------- CWinsServerHandler::SetDisplay() Sets the node name to either the host name or FQDN ---------------------------------------------------------------------------*/ void CWinsServerHandler::SetDisplay(ITFSNode * pNode, BOOL fFQDN) { CHAR szHostName[MAX_PATH] = {0}; CString strIPAdd, strDisplay; ::MakeIPAddress(m_dwIPAdd, strIPAdd); if (fFQDN) { // check if the server name was resolved and added if (m_dwIPAdd != 0) { // default is ACP. This should use ACP because winsock uses ACP WideToMBCS(m_strServerAddress, szHostName); HOSTENT * pHostent = ::gethostbyname((CHAR *) szHostName); if (pHostent) { CString strFQDN; MBCSToWide(pHostent->h_name, strFQDN); strFQDN.MakeLower(); strDisplay.Format(IDS_SERVER_NAME_FORMAT, strFQDN, strIPAdd); SetDisplayName(strDisplay); if (pNode) pNode->ChangeNode(SCOPE_PANE_CHANGE_ITEM_DATA); } } } // if not FQDN else { if (m_dwIPAdd != 0) { strDisplay.Format(IDS_SERVER_NAME_FORMAT, m_strServerAddress, strIPAdd); } else { strDisplay = m_strServerAddress; } SetDisplayName(strDisplay); if (pNode) pNode->ChangeNode(SCOPE_PANE_CHANGE_ITEM_DATA); } } void CWinsServerHandler::GetErrorInfo(CString & strTitle, CString & strBody, IconIdentifier * pIcon) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); TCHAR szBuffer[MAX_PATH * 2]; // build the body text LoadMessage(m_dwErr, szBuffer, sizeof(szBuffer) / sizeof(TCHAR)); AfxFormatString1(strBody, IDS_SERVER_MESSAGE_BODY, szBuffer); CString strTemp; strTemp.LoadString(IDS_SERVER_MESSAGE_BODY_REFRESH); strBody += strTemp; // get the title strTitle.LoadString(IDS_SERVER_MESSAGE_TITLE); // and the icon if (pIcon) { *pIcon = Icon_Error; } } /*--------------------------------------------------------------------------- Background thread functionality ---------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------- CWinsServerHandler::OnCreateQuery Description Author: EricDav ---------------------------------------------------------------------------*/ ITFSQueryObject* CWinsServerHandler::OnCreateQuery(ITFSNode * pNode) { CWinsServerQueryObj* pQuery = NULL; HRESULT hr = hrOK; COM_PROTECT_TRY { m_pNameThread = new CNameThread(); pQuery = new CWinsServerQueryObj(m_spTFSCompData, m_spNodeMgr); pQuery->m_strServer = GetServerAddress(); pQuery->m_dwIPAdd = m_dwIPAdd; pQuery->m_pNameThread = m_pNameThread; pQuery->m_pServerInfoArray = &m_ServerInfoArray; } COM_PROTECT_CATCH return pQuery; } /*--------------------------------------------------------------------------- CWinsServerHandler::OnEventAbort Description Author: EricDav ---------------------------------------------------------------------------*/ void CWinsServerQueryObj::OnEventAbort ( DWORD dwData, DWORD dwType ) { if (dwType == WINS_QDATA_SERVER_INFO) { Trace0("CWinsServerHandler::OnEventAbort - deleting version"); delete ULongToPtr(dwData); } } /*--------------------------------------------------------------------------- CWinsServerQueryObj::Execute() Enumerates everything about a server Author: EricDav ---------------------------------------------------------------------------*/ STDMETHODIMP CWinsServerQueryObj::Execute() { HRESULT hr = hrOK; WINSINTF_BIND_DATA_T wbdBindData; CString strName, strIp; DWORD dwStatus = ERROR_SUCCESS; DWORD dwIp; CServerData * pServerInfo; // need to get the server name and IP address if the server is added // with Do not connect option dwStatus = ::VerifyWinsServer(m_strServer, strName, dwIp); if (dwStatus != ERROR_SUCCESS) { Trace1("CWinsServerQueryObj::Execute() - VerifyWinsServer failed! %d\n", dwStatus); // Use the existing information we have to try and connect if (m_dwIPAdd) { // we couldn't resolve the name so just use what we have and try to connect strName = m_strServer; dwIp = m_dwIPAdd; } else { // we don't have an IP for this and we can't resolve the name, so error out PostError(dwStatus); return hrFalse; } } pServerInfo = new CServerData; ::MakeIPAddress(dwIp, strIp); pServerInfo->m_strServerName = strName; pServerInfo->m_dwServerIp = dwIp; pServerInfo->m_hBinding = NULL; // get a binding for this server wbdBindData.fTcpIp = 1; wbdBindData.pPipeName = NULL; wbdBindData.pServerAdd = (LPSTR) (LPCTSTR) strIp; if ((pServerInfo->m_hBinding = ::WinsBind(&wbdBindData)) == NULL) { dwStatus = ::GetLastError(); // send what info we have back to the main thread AddToQueue((LPARAM) pServerInfo, WINS_QDATA_SERVER_INFO); Trace1("CWinsServerQueryObj::Execute() - WinsBind failed! %d\n", dwStatus); PostError(dwStatus); return hrFalse; } // load the configuration object //pServerInfo->m_config.SetOwner(strName); pServerInfo->m_config.SetOwner(strIp); dwStatus = pServerInfo->m_config.Load(pServerInfo->m_hBinding); if (dwStatus != ERROR_SUCCESS) { // send what info we have back to the main thread AddToQueue((LPARAM) pServerInfo, WINS_QDATA_SERVER_INFO); Trace1("CWinsServerQueryObj::Execute() - Load configuration failed! %d\n", dwStatus); PostError(dwStatus); return hrFalse; } // send all of the information back to the main thread here handle_t hBinding = pServerInfo->m_hBinding; AddToQueue((LPARAM) pServerInfo, WINS_QDATA_SERVER_INFO); // build the child nodes AddNodes(hBinding); return hrFalse; } /*--------------------------------------------------------------------------- CWinsServerQueryObj::AddNodes Creates the active registrations and replication partners nodes Author: EricDav ---------------------------------------------------------------------------*/ void CWinsServerQueryObj::AddNodes(handle_t hBinding) { HRESULT hr = hrOK; SPITFSNode spActReg, spRepPart; CServerInfoArray * pServerInfoArray; // // active registrations node // CActiveRegistrationsHandler *pActRegHand = NULL; try { pActRegHand = new CActiveRegistrationsHandler(m_spTFSCompData); } catch(...) { hr = E_OUTOFMEMORY; } // // Create the actreg container information // CreateContainerTFSNode(&spActReg, &GUID_WinsActiveRegNodeType, pActRegHand, pActRegHand, m_spNodeMgr); // Tell the handler to initialize any specific data pActRegHand->InitializeNode((ITFSNode *) spActReg); // load the name type mapping from the registry pActRegHand->m_NameTypeMap.SetMachineName(m_strServer); pActRegHand->m_NameTypeMap.Load(); // build the owner mapping pActRegHand->m_pServerInfoArray = m_pServerInfoArray; pActRegHand->BuildOwnerArray(hBinding); // Post this node back to the main thread AddToQueue(spActReg); pActRegHand->Release(); // // replication partners node // CReplicationPartnersHandler *pReplicationHand = NULL; try { pReplicationHand = new CReplicationPartnersHandler (m_spTFSCompData); } catch(...) { hr = E_OUTOFMEMORY; } // Create the actreg container information CreateContainerTFSNode(&spRepPart, &GUID_WinsReplicationNodeType, pReplicationHand, pReplicationHand, m_spNodeMgr); // Tell the handler to initialize any specific data pReplicationHand->InitializeNode((ITFSNode *) spRepPart); // Post this node back to the main thread AddToQueue(spRepPart); pReplicationHand->Release(); // kick off the name query thread m_pNameThread->Init(m_pServerInfoArray); m_pNameThread->Start(); }