/**********************************************************************/ /** Microsoft Windows/NT **/ /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/ /**********************************************************************/ /* actreg.cpp WINS active registrations node information. FILE HISTORY: */ #include "stdafx.h" #include "nodes.h" #include "actreg.h" #include "server.h" #include "Queryobj.h" #include "statmapp.h" #include "fndrcdlg.h" #include #include "pushtrig.h" #include "tregkey.h" #include "chkrgdlg.h" #include "dynrecpp.h" #include "vrfysrv.h" #include "delrcdlg.h" #include "delowner.h" #include "cprogdlg.h" #include "loadrecs.h" #include "verify.h" WORD gwUnicodeHeader = 0xFEFF; #define INFINITE_EXPIRATION 0x7FFFFFFF #define BADNAME_CHAR _T('-') // This char is substituted for bad characters // NetBIOS names. UINT guActregMessageStrings[] = { IDS_ACTREG_MESSAGE_BODY1, IDS_ACTREG_MESSAGE_BODY2, IDS_ACTREG_MESSAGE_BODY3, -1 }; BOOL WinsIsPrint(char * pChar) { WORD charType; // isprint isn't working for thai characters, so use the GetStringType // API and figure it out ourselves. BOOL fRet = GetStringTypeA(LOCALE_SYSTEM_DEFAULT, CT_CTYPE1, pChar, 1, &charType); if (!fRet) return 0; return !(charType & C1_CNTRL) ? 1 : 0; } /*--------------------------------------------------------------------------- class CSortWorker ---------------------------------------------------------------------------*/ CSortWorker::CSortWorker(IWinsDatabase * pCurrentDatabase, int nColumn, DWORD dwSortOptions) { m_pCurrentDatabase = pCurrentDatabase; m_nColumn = nColumn; m_dwSortOptions = dwSortOptions; } CSortWorker::~CSortWorker() { } void CSortWorker::OnDoAction() { #ifdef DEBUG CString strType; CTime timeStart, timeFinish; timeStart = CTime::GetCurrentTime(); #endif WINSDB_SORT_TYPE uSortType = WINSDB_SORT_BY_NAME; switch (m_nColumn) { case ACTREG_COL_NAME: uSortType = WINSDB_SORT_BY_NAME; break; case ACTREG_COL_TYPE: uSortType = WINSDB_SORT_BY_TYPE; break; case ACTREG_COL_IPADDRESS: uSortType = WINSDB_SORT_BY_IP; break; case ACTREG_COL_STATE: uSortType = WINSDB_SORT_BY_STATE; break; case ACTREG_COL_STATIC: uSortType = WINSDB_SORT_BY_STATIC; break; case ACTREG_COL_VERSION: uSortType = WINSDB_SORT_BY_VERSION; break; case ACTREG_COL_EXPIRATION: uSortType = WINSDB_SORT_BY_EXPIRATION; break; case ACTREG_COL_OWNER: uSortType = WINSDB_SORT_BY_OWNER; break; } BEGIN_WAIT_CURSOR m_pCurrentDatabase->Sort(uSortType, m_dwSortOptions); END_WAIT_CURSOR #ifdef DEBUG timeFinish = CTime::GetCurrentTime(); CTimeSpan timeDelta = timeFinish - timeStart; CString str = timeDelta.Format(_T("%H:%M:%S")); Trace2("Record Sorting for the column: %d, total time %s\n", uSortType, str); #endif } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::CActiveRegistrationsHandler Description Author: EricDav ---------------------------------------------------------------------------*/ CActiveRegistrationsHandler::CActiveRegistrationsHandler(ITFSComponentData *pCompData) : CMTWinsHandler(pCompData), m_dlgLoadRecords(IDS_VIEW_RECORDS) { m_winsdbState = WINSDB_NORMAL; m_bExpanded = FALSE; m_pCurrentDatabase = NULL; m_fFindNameOrIP = TRUE; m_NonBlocking = 1; m_pServerInfoArray = NULL; m_fLoadedOnce = FALSE; m_fFindLoaded = FALSE; m_fDbLoaded = FALSE; m_fForceReload = TRUE; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::~CActiveRegistrationsHandler Description ---------------------------------------------------------------------------*/ CActiveRegistrationsHandler::~CActiveRegistrationsHandler() { } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::DestroyHandler Release and pointers we have here Author: EricDav ----------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::DestroyHandler ( ITFSNode * pNode ) { m_spServerNode.Set(NULL); return hrOK; } /*!-------------------------------------------------------------------------- CActiveRegistrationsHandler::InitializeNode Initializes node specific data ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::InitializeNode ( ITFSNode * pNode ) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); HRESULT hr = hrOK; CString strTemp; m_strActiveReg.LoadString(IDS_ACTIVEREG); SetDisplayName(m_strActiveReg); m_strDesp.LoadString(IDS_ACTIVEREG_DISC); // Make the node immediately visible pNode->SetData(TFS_DATA_COOKIE, (LPARAM) pNode); pNode->SetData(TFS_DATA_IMAGEINDEX, GetImageIndex(FALSE)); pNode->SetData(TFS_DATA_OPENIMAGEINDEX, GetImageIndex(TRUE)); pNode->SetData(TFS_DATA_USER, (LPARAM) this); pNode->SetData(TFS_DATA_TYPE, WINSSNAP_ACTIVE_REGISTRATIONS); pNode->SetData(TFS_DATA_SCOPE_LEAF_NODE, TRUE); SetColumnStringIDs(&aColumns[WINSSNAP_ACTIVE_REGISTRATIONS][0]); SetColumnWidths(&aColumnWidths[WINSSNAP_ACTIVE_REGISTRATIONS][0]); if (g_strStaticTypeUnique.IsEmpty()) { g_strStaticTypeUnique.LoadString(IDS_STATIC_RECORD_TYPE_UNIQUE); g_strStaticTypeDomainName.LoadString(IDS_STATIC_RECORD_TYPE_DOMAIN_NAME); g_strStaticTypeMultihomed.LoadString(IDS_STATIC_RECORD_TYPE_MULTIHOMED); g_strStaticTypeGroup.LoadString(IDS_STATIC_RECORD_TYPE_GROUP); g_strStaticTypeInternetGroup.LoadString(IDS_STATIC_RECORD_TYPE_INTERNET_GROUP); g_strStaticTypeUnknown.LoadString(IDS_STATIC_RECORD_TYPE_UNKNOWN); } return hr; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::OnCreateNodeId2 Returns a unique string for this node Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::OnCreateNodeId2(ITFSNode * pNode, CString & strId, DWORD * dwFlags) { const GUID * pGuid = pNode->GetNodeType(); CString strGuid; StringFromGUID2(*pGuid, strGuid.GetBuffer(256), 256); strGuid.ReleaseBuffer(); SPITFSNode spServerNode; pNode->GetParent(&spServerNode); CWinsServerHandler * pServer = GETHANDLER(CWinsServerHandler, spServerNode); strId = pServer->m_strServerAddress + strGuid; return hrOK; } /*--------------------------------------------------------------------------- Overridden base handler functions ---------------------------------------------------------------------------*/ /*!-------------------------------------------------------------------------- CActiveRegistrationsHandler::GetString Implementation of ITFSNodeHandler::GetString Author: KennT ---------------------------------------------------------------------------*/ STDMETHODIMP_(LPCTSTR) CActiveRegistrationsHandler::GetString ( ITFSNode * pNode, int nCol ) { if (nCol == 0 || nCol == -1) { return GetDisplayName(); } else if (nCol ==1) { return m_strDesp; } else { return NULL; } } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::OnExpand Description ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::OnExpand ( ITFSNode * pNode, LPDATAOBJECT pDataObject, DWORD dwType, LPARAM arg, LPARAM param ) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); HRESULT hr = hrOK; SPITFSNode spNode; SPITFSNodeHandler spHandler; ITFSQueryObject * pQuery = NULL; CString strIP; DWORD dwIP; CString strMachineName; SPITFSNode spServerNode; pNode->GetParent(&spServerNode); CWinsServerHandler * pServer = GETHANDLER(CWinsServerHandler, spServerNode); // get the config info for later m_Config = pServer->GetConfig(); m_RecList.RemoveAll(); if (m_bExpanded) { return hr; } strMachineName = _T("\\\\") + pServer->GetServerAddress(); // load the name type mapping from the registry m_NameTypeMap.SetMachineName(strMachineName); m_NameTypeMap.Load(); // start the database download for the surrent owner if (!m_spWinsDatabase) { dwIP = pServer->GetServerIP(); MakeIPAddress(dwIP, strIP); m_dlgLoadRecords.ResetFiltering(); CORg(CreateWinsDatabase(strIP, strIP, &m_spWinsDatabase)); // set the owner to the current owner m_spWinsDatabase->SetApiInfo( dwIP, NULL, FALSE); } m_bExpanded = TRUE; COM_PROTECT_ERROR_LABEL; return hr; } /*--------------------------------------------------------------------------- CWinsServerHandler::OnResultRefresh Refreshes the data realting to the server Author: v-shubk ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::OnResultRefresh ( ITFSComponent * pComponent, LPDATAOBJECT pDataObject, MMC_COOKIE cookie, LPARAM arg, LPARAM lParam ) { HRESULT hr = hrOK; SPITFSNode spNode; CORg (m_spNodeMgr->FindNode(cookie, &spNode)); // get the stae of the databse if not normal, ie in the loading or filtering state // don't let refresh if (m_winsdbState != WINSDB_NORMAL) { return hrOK; } RefreshResults(spNode); Error: return hr; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::OnCreateQuery Description Author: v-shubk ---------------------------------------------------------------------------*/ ITFSQueryObject * CActiveRegistrationsHandler::OnCreateQuery(ITFSNode * pNode) { CNodeTimerQueryObject * pQObj = new CNodeTimerQueryObject(); pQObj->SetTimerInterval(2000); return pQObj; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::OnHaveData Description Author: EricDav ---------------------------------------------------------------------------*/ void CActiveRegistrationsHandler::OnHaveData ( ITFSNode * pParentNode, LPARAM Data, LPARAM Type ) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); // This is how we get non-node data back from the background thread. HRESULT hr = hrOK; WINSDB_STATE uState; COM_PROTECT_TRY { if (Type == QDATA_TIMER) { BOOL bDone; m_spWinsDatabase->GetCurrentState(&uState); bDone = (m_winsdbState == WINSDB_LOADING && uState != WINSDB_LOADING) || (m_winsdbState == WINSDB_FILTERING && uState != WINSDB_LOADING); // if records per owner are downloaded, clear and redraw the // items as the records are inserted, rather than being added. //if (TRUE /*m_dwOwnerFilter != -1*/) //{ // UpdateCurrentView(pParentNode); //} // call into the WinsDatbase object and check the count. // if we need to update call..UpdateAllViews UpdateListboxCount(pParentNode); UpdateCurrentView(pParentNode); if (m_nState != loading) { m_nState = loading; OnChangeState(pParentNode); } // take care of the tomer in case of the filetr records case if (bDone) { Trace0("ActiveRegHandler::OnHaveData - Done loading DB\n"); DatabaseLoadingCleanup(); if ( (m_nState != loaded) && (m_nState != unableToLoad) ) { m_nState = loaded; m_dwErr = 0; OnChangeState(pParentNode); } } } } COM_PROTECT_CATCH return; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::CActiveRegistrationsHandler Description Author: v-shubk ---------------------------------------------------------------------------*/ int CActiveRegistrationsHandler::GetImageIndex(BOOL bOpenImage) { int nIndex = 0; switch (m_nState) { case notLoaded: case loaded: case unableToLoad: if (bOpenImage) nIndex = ICON_IDX_ACTREG_FOLDER_OPEN; else nIndex = ICON_IDX_ACTREG_FOLDER_CLOSED; break; case loading: if (bOpenImage) nIndex = ICON_IDX_ACTREG_FOLDER_OPEN_BUSY; else nIndex = ICON_IDX_ACTREG_FOLDER_CLOSED_BUSY; break; default: ASSERT(FALSE); } return nIndex; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::OnAddMenuItems Description Author: EricDav ---------------------------------------------------------------------------*/ STDMETHODIMP CActiveRegistrationsHandler::OnAddMenuItems ( ITFSNode * pNode, LPCONTEXTMENUCALLBACK pContextMenuCallback, LPDATAOBJECT lpDataObject, DATA_OBJECT_TYPES type, DWORD dwType, long * pInsertionAllowed ) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); HRESULT hr = S_OK; LONG lFlags = 0; CString strMenuItem; if (!m_Config.IsAdmin()) { lFlags = MF_GRAYED; } if (type == CCT_SCOPE) { // these menu items go in the new menu, // only visible from scope pane if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP) { // find record //strMenuItem.LoadString(IDS_ACTIVEREG_FIND_RECORD); //hr = LoadAndAddMenuItem( pContextMenuCallback, // strMenuItem, // IDS_ACTIVEREG_FIND_RECORD, // CCM_INSERTIONPOINTID_PRIMARY_TOP, // 0 ); //ASSERT( SUCCEEDED(hr) ); // start database load if th state is normal if (m_winsdbState == WINSDB_NORMAL) { strMenuItem.LoadString(IDS_DATABASE_LOAD_START); hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, IDS_DATABASE_LOAD_START, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0 ); ASSERT( SUCCEEDED(hr) ); } else { strMenuItem.LoadString(IDS_DATABASE_LOAD_STOP); hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, IDS_DATABASE_LOAD_STOP, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0 ); ASSERT( SUCCEEDED(hr) ); } // separator hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, 0, CCM_INSERTIONPOINTID_PRIMARY_TOP, MF_SEPARATOR); ASSERT( SUCCEEDED(hr) ); // create static mapping strMenuItem.LoadString(IDS_ACTIVEREG_CREATE_STATIC_MAPPING); hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, IDS_ACTIVEREG_CREATE_STATIC_MAPPING, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0 ); ASSERT( SUCCEEDED(hr) ); // separator hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, 0, CCM_INSERTIONPOINTID_PRIMARY_TOP, MF_SEPARATOR); ASSERT( SUCCEEDED(hr) ); // import LMHOSTS file strMenuItem.LoadString(IDS_ACTIVEREG_IMPORT_LMHOSTS); hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, IDS_ACTIVEREG_IMPORT_LMHOSTS, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0 ); ASSERT( SUCCEEDED(hr) ); // only available to admins strMenuItem.LoadString(IDS_ACTREG_CHECK_REG_NAMES); hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, IDS_ACTREG_CHECK_REG_NAMES, CCM_INSERTIONPOINTID_PRIMARY_TOP, lFlags ); ASSERT( SUCCEEDED(hr) ); strMenuItem.LoadString(IDS_ACTREG_DELETE_OWNER); hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, IDS_ACTREG_DELETE_OWNER, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0 ); ASSERT( SUCCEEDED(hr) ); } } return hr; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::OnCommand Description Author: EricDav ---------------------------------------------------------------------------*/ STDMETHODIMP CActiveRegistrationsHandler::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_ACTIVEREG_CREATE_STATIC_MAPPING: OnCreateMapping(pNode); break; case IDS_DATABASE_LOAD_START: OnDatabaseLoadStart(pNode); break; case IDS_DATABASE_LOAD_STOP: OnDatabaseLoadStop(pNode); break; case IDS_ACTIVEREG_IMPORT_LMHOSTS: OnImportLMHOSTS(pNode); break; case IDS_ACTIVEREG_EXPORT_WINSENTRIES: OnExportEntries(); break; case IDS_ACTREG_CHECK_REG_NAMES: OnCheckRegNames(pNode); break; case IDS_ACTREG_DELETE_OWNER: OnDeleteOwner(pNode); break; default: break; } return hr; } /*!-------------------------------------------------------------------------- CActiveRegistrationsHandler::AddMenuItems Over-ride this to add our view menu item Author: EricDav ---------------------------------------------------------------------------*/ STDMETHODIMP CActiveRegistrationsHandler::AddMenuItems ( ITFSComponent * pComponent, MMC_COOKIE cookie, LPDATAOBJECT pDataObject, LPCONTEXTMENUCALLBACK pContextMenuCallback, long * pInsertionAllowed ) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); HRESULT hr = S_OK; CString strMenuItem; LONG lFlags = 0; // figure out if we need to pass this to the scope pane menu handler hr = HandleScopeMenus(cookie, pDataObject, pContextMenuCallback, pInsertionAllowed); if (*pInsertionAllowed & CCM_INSERTIONALLOWED_VIEW) { if (m_fLoadedOnce) { lFlags = MF_CHECKED|MFT_RADIOCHECK; } else { lFlags = 0; } strMenuItem.LoadString(IDS_ACTREG_SHOW_ENTIRE); hr = LoadAndAddMenuItem( pContextMenuCallback, strMenuItem, IDM_FILTER_DATABASE, CCM_INSERTIONPOINTID_PRIMARY_VIEW, lFlags); ASSERT( SUCCEEDED(hr) ); } return hr; } /*!-------------------------------------------------------------------------- CActiveRegistrationsHandler::Command Handles commands for the current view Author: EricDav ---------------------------------------------------------------------------*/ STDMETHODIMP CActiveRegistrationsHandler::Command ( ITFSComponent * pComponent, MMC_COOKIE cookie, int nCommandID, LPDATAOBJECT pDataObject ) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); HRESULT hr = S_OK; SPITFSNode spNode; CORg (m_spNodeMgr->FindNode(cookie, &spNode)); switch (nCommandID) { case IDM_FILTER_DATABASE: if (m_fDbLoaded) { UpdateCurrentView(spNode); } else { OnDatabaseLoadStart(spNode); } break; // this may have come from the scope pane handler, so pass it up default: hr = HandleScopeCommand(cookie, nCommandID, pDataObject); break; } Error: return hr; } /*!-------------------------------------------------------------------------- CActiveRegistrationsHandler::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!!! ---------------------------------------------------------------------------*/ STDMETHODIMP CActiveRegistrationsHandler::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 = hrFalse; } else { // we have property pages in the normal case hr = hrOK; } return hr; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::CreatePropertyPages The active registrations node (scope pane) doesn't have any property pages. We should never get here. ---------------------------------------------------------------------------*/ STDMETHODIMP CActiveRegistrationsHandler::CreatePropertyPages ( ITFSNode * pNode, LPPROPERTYSHEETCALLBACK lpProvider, LPDATAOBJECT pDataObject, LONG_PTR handle, DWORD dwType ) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); // we use this to create static mappings, but we don't show it // through the properties verb. We invoke this mechanism when the // user selects create static mapping HRESULT hr = hrOK; // Object gets deleted when the page is destroyed SPIComponentData spComponentData; m_spNodeMgr->GetComponentData(&spComponentData); // show the same page as the statis mapping properties CStaticMappingProperties * pMapping = new CStaticMappingProperties (pNode, spComponentData, NULL, NULL, TRUE); pMapping->m_ppageGeneral->m_uImage = ICON_IDX_CLIENT; pMapping->CreateModelessSheet(lpProvider, handle); return hr; } /*!-------------------------------------------------------------------------- CActiveRegistrationsHandler::HasPropertyPages Implementation of ITFSResultHandler::HasPropertyPages Author: KennT ---------------------------------------------------------------------------*/ STDMETHODIMP CActiveRegistrationsHandler::HasPropertyPages ( ITFSComponent * pComponent, MMC_COOKIE cookie, LPDATAOBJECT pDataObject ) { return hrOK; } /*!-------------------------------------------------------------------------- CActiveRegistrationsHandler::CreatePropertyPages Implementation of ITFSResultHandler::CreatePropertyPages Author: KennT ---------------------------------------------------------------------------*/ STDMETHODIMP CActiveRegistrationsHandler::CreatePropertyPages ( ITFSComponent * pComponent, MMC_COOKIE cookie, LPPROPERTYSHEETCALLBACK lpProvider, LPDATAOBJECT pDataObject, LONG_PTR handle ) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); HRESULT hr = hrOK; HPROPSHEETPAGE hPage; SPINTERNAL spInternal; SPIComponentData spComponentData; SPIComponent spComponent; SPITFSNode spNode; SPIResultData spResultData; int nIndex ; HROW hRowSel; WinsRecord wRecord; WinsStrRecord *pwstrRecord; int nCount; // get the resultdata interface CORg (pComponent->GetResultData(&spResultData)); spInternal = ExtractInternalFormat(pDataObject); // virtual listbox notifications come to the handler of the node // that is selected. check to see if this notification is for a // virtual listbox item or the active registrations node itself. if (spInternal->HasVirtualIndex()) { // we gotta do special stuff for the virtual index items m_spNodeMgr->FindNode(cookie, &spNode); CORg(spComponent.HrQuery(pComponent)); Assert(spComponent); m_nSelectedIndex = spInternal->GetVirtualIndex(); nIndex = m_nSelectedIndex; // if an invalid index, return m_pCurrentDatabase->GetCurrentCount(&nCount); if (nIndex < 0 || nIndex >= nCount) { return hrOK; } // get the correct data for the record selected m_spWinsDatabase->GetHRow(nIndex, &hRowSel); m_spWinsDatabase->GetData(hRowSel, &wRecord); GetRecordOwner(spNode, &wRecord); // put up different page depending on wheter static or dynamic if (wRecord.dwState & WINSDB_REC_STATIC) { m_CurrentRecord = wRecord; CStaticMappingProperties * pStat = new CStaticMappingProperties(spNode, spComponent, NULL, &wRecord, FALSE); pStat->m_ppageGeneral->m_uImage = GetVirtualImage(nIndex); Assert(lpProvider != NULL); return pStat->CreateModelessSheet(lpProvider, handle); } // dynamic case else { CDynamicMappingProperties *pDyn = new CDynamicMappingProperties(spNode, spComponent, NULL, &wRecord); pDyn->m_pageGeneral.m_uImage = GetVirtualImage(nIndex); Assert(lpProvider != NULL); return pDyn->CreateModelessSheet(lpProvider, handle); } } else { Assert(FALSE); } COM_PROTECT_ERROR_LABEL; return hr; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::OnPropertyChange Description Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::OnPropertyChange ( ITFSNode * pNode, LPDATAOBJECT pDataobject, DWORD dwType, LPARAM arg, LPARAM lParam ) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); CStaticMappingProperties * pProp = reinterpret_cast(lParam); LONG_PTR changeMask = 0; // tell the property page to do whatever now that we are back on the // main thread pProp->OnPropertyChange(TRUE, &changeMask); pProp->AcknowledgeNotify(); // refresh the result pane if (changeMask) UpdateListboxCount(pNode); return hrOK; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::OnResultPropertyChange Description Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::OnResultPropertyChange ( ITFSComponent * pComponent, LPDATAOBJECT pDataObject, MMC_COOKIE cookie, LPARAM arg, LPARAM param ) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); HRESULT hr = hrOK; SPINTERNAL spInternal; SPITFSNode spNode; m_spNodeMgr->FindNode(cookie, &spNode); CStaticMappingProperties * pProp = reinterpret_cast(param); LONG_PTR changeMask = 0; // tell the property page to do whatever now that we are back on the // main thread pProp->SetComponent(pComponent); pProp->OnPropertyChange(TRUE, &changeMask); pProp->AcknowledgeNotify(); // refresh the result pane if (changeMask) UpdateListboxCount(spNode); return hr; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::OnResultDelete Description Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::OnResultDelete ( ITFSComponent * pComponent, LPDATAOBJECT pDataObject, MMC_COOKIE cookie, LPARAM arg, LPARAM lParam ) { HRESULT hr = hrOK; Trace0("CActiveRegistrationsHandler::OnResultDelete received\n"); SPINTERNAL spInternal; spInternal = ExtractInternalFormat(pDataObject); // virtual listbox notifications come to the handler of the node // that is selected. check to see if this notification is for a // virtual listbox item or the active registrations node itself. if (spInternal->HasVirtualIndex()) { // we gotta do special stuff for the virtual index items DeleteRegistration(pComponent, spInternal->GetVirtualIndex()); } else { // just call the base class to update verbs for the CMTWinsHandler::OnResultDelete(pComponent, pDataObject, cookie, arg, lParam); } return hr; } /*!-------------------------------------------------------------------------- CActiveRegistrationsHandler::OnResultSelect Handles the MMCN_SELECT notifcation Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::OnResultSelect ( ITFSComponent * pComponent, LPDATAOBJECT pDataObject, MMC_COOKIE cookie, LPARAM arg, LPARAM lParam ) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); HRESULT hr = hrOK; int i; WINSDB_STATE uState = WINSDB_LOADING; SPINTERNAL spInternal; SPIConsoleVerb spConsoleVerb; SPIConsole spConsole; BOOL bStates[ARRAYLEN(g_ConsoleVerbs)]; SPITFSNode spNode; // show the result pane message if (!m_fLoadedOnce) { CString strTitle, strBody, strTemp; m_spResultNodeMgr->FindNode(cookie, &spNode); strTitle.LoadString(IDS_ACTREG_MESSAGE_TITLE); for (i = 0; ; i++) { if (guActregMessageStrings[i] == -1) break; strTemp.LoadString(guActregMessageStrings[i]); strBody += strTemp; } ShowMessage(spNode, strTitle, strBody, Icon_Information); } else { ULARGE_INTEGER data, *pData; // fill in the result pane if (m_spWinsDatabase) { m_spWinsDatabase->GetCurrentState(&uState); // check to see if we are done if (m_winsdbState == WINSDB_LOADING && uState != WINSDB_LOADING) { Trace0("ActiveRegHandler::OnResultSelect - Done loading DB\n"); DatabaseLoadingCleanup(); } } if (m_pCurrentDatabase) { // Get the count from the database CORg (m_pCurrentDatabase->GetCurrentScanned((int*)&data.LowPart)); CORg (m_pCurrentDatabase->GetCurrentCount((int*)&data.HighPart)); pData = &data; } else { pData = NULL; } // now notify the virtual listbox CORg ( m_spNodeMgr->GetConsole(&spConsole) ); CORg ( spConsole->UpdateAllViews(pDataObject, (LPARAM)pData, RESULT_PANE_SET_VIRTUAL_LB_SIZE) ); } // now update the verbs... spInternal = ExtractInternalFormat(pDataObject); Assert(spInternal); // virtual listbox notifications come to the handler of the node // that is selected.check to see if this notification is for a // virtual listbox item or the active registrations node itself. if (spInternal->HasVirtualIndex()) { // is this a multiselect? BOOL fMultiSelect = spInternal->m_cookie == MMC_MULTI_SELECT_COOKIE ? TRUE : FALSE; if (!fMultiSelect) { // when something is selected in the result pane we want the default verb to be properties m_verbDefault = MMC_VERB_PROPERTIES; } else { // we don't support multi-select properties m_verbDefault = MMC_VERB_NONE; } // we gotta do special stuff for the virtual index items CORg (pComponent->GetConsoleVerb(&spConsoleVerb)); UpdateConsoleVerbs(spConsoleVerb, WINSSNAP_REGISTRATION, fMultiSelect); } else { // when the active registrations node itself is selected, default should be open m_verbDefault = MMC_VERB_OPEN; g_ConsoleVerbStates[WINSSNAP_ACTIVE_REGISTRATIONS][6] = ENABLED; // just call the base class to update verbs for the CMTWinsHandler::OnResultSelect(pComponent, pDataObject, cookie, arg, lParam); } COM_PROTECT_ERROR_LABEL; return hr; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::DatabaseLoadingCleanup Description Author: ericdav ---------------------------------------------------------------------------*/ void CActiveRegistrationsHandler::DatabaseLoadingCleanup() { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); m_winsdbState = WINSDB_NORMAL; // check for any errors HRESULT hrLastError; m_spWinsDatabase->GetLastError(&hrLastError); // Kill the timer thread if (m_spQuery) { // Signal the thread to abort m_spQuery->SetAbortEvent(); } if (FAILED(hrLastError)) { CString strError, strIp; LPTSTR pBuf = strIp.GetBuffer(256); m_spWinsDatabase->GetIP(pBuf, 256); strIp.ReleaseBuffer(); AfxFormatString1(strError, IDS_ERR_LOADING_DB, strIp); theApp.MessageBox(strError, WIN32_FROM_HRESULT(hrLastError)); m_fForceReload = TRUE; } WaitForThreadToExit(); } void CActiveRegistrationsHandler::FilterCleanup(ITFSNode *pNode) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); m_winsdbState = WINSDB_NORMAL; // check for any errors HRESULT hrLastError; m_spWinsDatabase->GetLastError(&hrLastError); // Kill the timer thread if (m_spQuery) { // Signal the thread to abort m_spQuery->SetAbortEvent(); } if (FAILED(hrLastError)) { CString strError, strIp; LPTSTR pBuf = strIp.GetBuffer(256); m_spWinsDatabase->GetIP(pBuf, 256); strIp.ReleaseBuffer(); AfxFormatString1(strError, IDS_ERR_LOADING_DB, strIp); theApp.MessageBox(strError, WIN32_FROM_HRESULT(hrLastError)); m_fForceReload = TRUE; } WaitForThreadToExit(); // change the icon to normal pNode->SetData(TFS_DATA_IMAGEINDEX, GetImageIndex(FALSE)); pNode->SetData(TFS_DATA_OPENIMAGEINDEX, GetImageIndex(TRUE)); pNode->ChangeNode(SCOPE_PANE_CHANGE_ITEM); } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::UpdateListboxCount Description ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::UpdateListboxCount(ITFSNode * pNode, BOOL bClear) { HRESULT hr = hrOK; SPIComponentData spCompData; SPIConsole spConsole; IDataObject* pDataObject; LONG_PTR hint; // need to pass up two counter values:one is the total number of records scanned // the other is the total number of records filtered. I put these two in a 64 bit // value: the most significant 32bits is the number of records actually filtered // the less significant 32bits is the total number of records scanned. ULARGE_INTEGER data; ULARGE_INTEGER *pData; COM_PROTECT_TRY { if (!m_pCurrentDatabase) { pData = NULL; hint = RESULT_PANE_CLEAR_VIRTUAL_LB; } else { CORg (m_pCurrentDatabase->GetCurrentScanned((int*)&data.LowPart)); CORg (m_pCurrentDatabase->GetCurrentCount((int*)&data.HighPart)); hint = RESULT_PANE_SET_VIRTUAL_LB_SIZE; pData = &data; } m_spNodeMgr->GetComponentData(&spCompData); CORg ( spCompData->QueryDataObject((MMC_COOKIE) pNode, CCT_RESULT, &pDataObject) ); CORg ( m_spNodeMgr->GetConsole(&spConsole) ); CORg ( spConsole->UpdateAllViews(pDataObject, (LPARAM)pData, hint) ); pDataObject->Release(); COM_PROTECT_ERROR_LABEL; } COM_PROTECT_CATCH return hr; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::UpdateVerbs Description ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::UpdateVerbs(ITFSNode * pNode) { HRESULT hr = hrOK; LONG_PTR hint; int i; COM_PROTECT_TRY { g_ConsoleVerbStates[WINSSNAP_ACTIVE_REGISTRATIONS][6] = ENABLED; if (!pNode) { hint = WINSSNAP_REGISTRATION; } else { hint = WINSSNAP_ACTIVE_REGISTRATIONS; } UpdateStandardVerbs(pNode, hint); } COM_PROTECT_CATCH return hr; } /*--------------------------------------------------------------------------- Command handlers ---------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::GetServerIP Description Author: v-shubk ---------------------------------------------------------------------------*/ void CActiveRegistrationsHandler::GetServerIP(ITFSNode * pNode, DWORD &dwIP, CString &strIP) { SPITFSNode spServerNode; pNode->GetParent(&spServerNode); CWinsServerHandler * pServer = GETHANDLER(CWinsServerHandler, spServerNode); dwIP = pServer->GetServerIP(); ::MakeIPAddress(dwIP, strIP); } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::OnCreateMapping Description Author: v-shubk ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::OnCreateMapping(ITFSNode *pNode) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); HRESULT hr = hrOK; // Object gets deleted when the page is destroyed SPIComponentData spComponentData; m_spNodeMgr->GetComponentData(&spComponentData); // HACK WARNING: because we do this in a MMC provided property sheet, we // need to invoke the correct mechanism so we get a callback handle. // otherwise when we create the static mapping, we're on another thread // and it can do bad things when we try to update the UI hr = DoPropertiesOurselvesSinceMMCSucks(pNode, spComponentData, _T("")); return hr; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::OnDatabaseLoadStart Description ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::OnDatabaseLoadStart(ITFSNode *pNode) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); HRESULT hr = hrOK; SPITFSNode spNode; SPITFSNodeHandler spHandler; ITFSQueryObject * pQuery = NULL; SPITFSNode spServerNode; DWORD dwIP; CString strIP; BOOL fReload = FALSE; int nCount, pos; CTypeFilterInfo typeFilterInfo; pNode->GetParent(&spServerNode); CWinsServerHandler * pServer = GETHANDLER(CWinsServerHandler, spServerNode); dwIP = pServer->GetServerIP(); if (!m_bExpanded) { m_dlgLoadRecords.ResetFiltering(); } if (m_dlgLoadRecords.m_pageTypes.m_arrayTypeFilter.GetSize() == 0) { fReload = TRUE; // initialize the record type filter array for (nCount = 0; nCount < m_NameTypeMap.GetSize(); nCount++) { if (m_NameTypeMap[nCount].dwWinsType == -1) { typeFilterInfo.dwType = m_NameTypeMap[nCount].dwNameType; typeFilterInfo.fShow = TRUE; m_dlgLoadRecords.m_pageTypes.m_arrayTypeFilter.Add(typeFilterInfo); } } } // if a download is running, ask the user if they want to stop it if (m_winsdbState != WINSDB_NORMAL) { OnDatabaseLoadStop(pNode); } // bring up the Owner Dialog // fill in the owner page info GetOwnerInfo(m_dlgLoadRecords.m_pageOwners.m_ServerInfoArray); // fill in the type filter page info m_dlgLoadRecords.m_pageTypes.m_pNameTypeMap = &m_NameTypeMap; // save the original number of owners. In case this is one // and several other are added, will reload the database. //------------------Display popup ---------------------------- if (m_dlgLoadRecords.DoModal() != IDOK) return hrFalse; SetLoadedOnce(pNode); m_fDbLoaded = TRUE; Lock(); MakeIPAddress(dwIP, strIP); // stop the database if we were loading or create one if we haven't yet if (!m_spWinsDatabase) { CORg (CreateWinsDatabase(strIP, strIP, &m_spWinsDatabase)); fReload = TRUE; } else { CORg (m_spWinsDatabase->Stop()); } //~~~~~~~~~~~~~~~~~~~~~~~~~ need to revise the logic for reloading ~~~~~~~~~~~~~~~~~~~~~~~~~ // // we try to make the decision whether the records we already loaded (if we did) are sufficient // to apply the new filters: set fReload to TRUE if reload is needed or to FALSE otherwise. // Since fReload could have been already set go into this process only if reloading is not yet // decided. Assume reload will eventualy be decided and break out as soon as this is confirmed // If the end of the "while" block is reached, this means database doesn't need to be reloaded // so break out. while(!fReload) { BOOL bDbCacheEnabled; // assume a reload will be needed fReload = TRUE; // if reload imposed by external causes (first time call or refresh was done), break out if (m_fForceReload) break; m_spWinsDatabase->GetCachingFlag(&bDbCacheEnabled); if (bDbCacheEnabled) { BOOL bReload; // currently the database is loaded with "enable caching" checked. This means: // if db "owner" api setting is set (non 0xffffffff) then // all records owned by "owner" are loaded (case 1) // else --> "owner" is set to "multiple" (0xffffffff) // if db "name" api is set (non null) then // all records prefixed with "name" are loaded (case 2) // else // entire database is loaded (case 3) // . // . // if (case 1) applies then // if we want to filter on a different or no owner then // reload SUGGESTED // else // reload NOT SUGGESTED // . // else if (case 2) applies then // if we want to filter on a different or no name prefix then // reload SUGGESTED // else // reload NOT SUGGESTED // . // else if (case 3) applies) // reload NOT SUGGESTED // . // // This logic is followed in CheckApiInfoCovered call from below m_spWinsDatabase->ReloadSuggested( m_dlgLoadRecords.m_pageOwners.GetOwnerForApi(), m_dlgLoadRecords.m_pageIpAddress.GetNameForApi(), &bReload); if (bReload) break; } else { // currently the database is loaded without "enable caching" checked. This means: // the records currentLy in the database match all the filters as they were specified // in the filtering dialog before it was popped-up. Consequently, if any of these // filters (owner, name, ipaddr, type) changed, database has to be reloaded. Otherwise, // since the filters are the same. if (m_dlgLoadRecords.m_pageIpAddress.m_bDirtyName || m_dlgLoadRecords.m_pageIpAddress.m_bDirtyAddr || m_dlgLoadRecords.m_pageIpAddress.m_bDirtyMask || m_dlgLoadRecords.m_pageOwners.m_bDirtyOwners || m_dlgLoadRecords.m_pageTypes.m_bDirtyTypes) break; } // if we are here it means reload is not actually needed, so reset the flag back and // break the loop fReload = FALSE; break; }; // if the final decision is to reload the db, then prepare this operation if (fReload) { m_fForceReload = FALSE; m_spWinsDatabase->Clear(); // set the Api parameters to be used by the database m_spWinsDatabase->SetApiInfo( m_dlgLoadRecords.m_pageOwners.GetOwnerForApi(), m_dlgLoadRecords.m_pageIpAddress.GetNameForApi(), m_dlgLoadRecords.m_bEnableCache); } // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ UpdateCurrentView(pNode); // start loading records if necessary if (fReload) { // start loading records CORg (m_spWinsDatabase->Init()); // update our internal state m_winsdbState = WINSDB_LOADING; // update the node's icon OnChangeState(pNode); // kick off the background thread to do the timer updates pQuery = OnCreateQuery(pNode); Assert(pQuery); Verify(StartBackgroundThread(pNode, m_spTFSCompData->GetHiddenWnd(), pQuery)); pQuery->Release(); } // fill in any record type filter information nCount = (int)m_dlgLoadRecords.m_pageTypes.m_arrayTypeFilter.GetSize(); m_spWinsDatabase->ClearFilter(WINSDB_FILTER_BY_TYPE); for (pos = 0; pos < nCount; pos++) { m_spWinsDatabase->AddFilter(WINSDB_FILTER_BY_TYPE, m_dlgLoadRecords.m_pageTypes.m_arrayTypeFilter[pos].dwType, m_dlgLoadRecords.m_pageTypes.m_arrayTypeFilter[pos].fShow, NULL); } // fill in any owner filter information nCount = (int)m_dlgLoadRecords.m_pageOwners.m_dwaOwnerFilter.GetSize(); m_spWinsDatabase->ClearFilter(WINSDB_FILTER_BY_OWNER); for (pos = 0; pos < nCount; pos++) { m_spWinsDatabase->AddFilter(WINSDB_FILTER_BY_OWNER, m_dlgLoadRecords.m_pageOwners.m_dwaOwnerFilter[pos], 0, NULL); } // fill in any ip address filter information m_spWinsDatabase->ClearFilter(WINSDB_FILTER_BY_IPADDR); if (m_dlgLoadRecords.m_pageIpAddress.m_bFilterIpAddr) { nCount = (int)m_dlgLoadRecords.m_pageIpAddress.m_dwaIPAddrs.GetSize(); for (pos = 0; pos < nCount; pos++) { m_spWinsDatabase->AddFilter(WINSDB_FILTER_BY_IPADDR, m_dlgLoadRecords.m_pageIpAddress.m_dwaIPAddrs[pos], m_dlgLoadRecords.m_pageIpAddress.GetIPMaskForFilter(pos), NULL); } } // fill in any name filter information m_spWinsDatabase->ClearFilter(WINSDB_FILTER_BY_NAME); if (m_dlgLoadRecords.m_pageIpAddress.m_bFilterName) { m_spWinsDatabase->AddFilter(WINSDB_FILTER_BY_NAME, m_dlgLoadRecords.m_pageIpAddress.m_bMatchCase, 0, m_dlgLoadRecords.m_pageIpAddress.m_strName); } // now that the filters are all set database can start downloading if (fReload) // start loading records CORg (m_spWinsDatabase->Start()); BEGIN_WAIT_CURSOR Sleep(100); // filter any records that may have been downloaded before we set the // filter information (in the case when we had to reload the database). // any records that come in after we set the // filter info will be filtered correctly. m_spWinsDatabase->FilterRecords(WINSDB_FILTER_BY_TYPE, 0,0); END_WAIT_CURSOR if (fReload) { // do the initial update of the virutal listbox OnHaveData(pNode, 0, QDATA_TIMER); } else { // just a filter changed, just need to update the result pane UpdateListboxCount(pNode); } COM_PROTECT_ERROR_LABEL; return hr; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::OnDatabaseLoadStop Description ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::OnDatabaseLoadStop(ITFSNode *pNode) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); HRESULT hr = hrOK; if (IDYES != AfxMessageBox(IDS_STOP_DB_LOAD_CONFIRM, MB_YESNO)) { return hrFalse; } if (m_spWinsDatabase) { CORg (m_spWinsDatabase->Stop()); DatabaseLoadingCleanup(); UpdateListboxCount(pNode); } m_fForceReload = TRUE; COM_PROTECT_ERROR_LABEL; return hr; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::OnGetResultViewType Description ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::OnGetResultViewType ( ITFSComponent * pComponent, MMC_COOKIE cookie, LPOLESTR * ppViewType, long * pViewOptions ) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); HRESULT hr = S_FALSE; if (cookie != NULL) { // call the base class to see if it is handling this if (CMTWinsHandler::OnGetResultViewType(pComponent, cookie, ppViewType, pViewOptions) != S_OK) { *pViewOptions = MMC_VIEW_OPTIONS_OWNERDATALIST | MMC_VIEW_OPTIONS_MULTISELECT; hr = S_FALSE; } } return hr; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::GetVirtualImage Description Author: EricDav ---------------------------------------------------------------------------*/ int CActiveRegistrationsHandler::GetVirtualImage ( int nIndex ) { HRESULT hr = hrOK; WinsRecord ws; HROW hrow; int nImage = ICON_IDX_CLIENT; COM_PROTECT_TRY { if (!m_pCurrentDatabase) return -1; CORg (m_pCurrentDatabase->GetHRow(nIndex, &hrow)); CORg (m_pCurrentDatabase->GetData(hrow, &ws)); if (HIWORD(ws.dwType) != WINSINTF_E_UNIQUE) { nImage = ICON_IDX_CLIENT_GROUP; } COM_PROTECT_ERROR_LABEL; } COM_PROTECT_CATCH return nImage; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::GetVirtualString Description Author: EricDav ---------------------------------------------------------------------------*/ LPCWSTR CActiveRegistrationsHandler::GetVirtualString ( int nIndex, int nCol ) { HRESULT hr; int nCount; if (m_pCurrentDatabase) { // check if nIndex is within limits, if not crashes when the last // record deleted and properties chosen. m_pCurrentDatabase->GetCurrentCount(&nCount); // 0 based index if (nIndex < 0 || nIndex >= nCount) { return NULL; } } // check our cache to see if we have this one. WinsStrRecord * pwsr = m_RecList.FindItem(nIndex); if (pwsr == NULL) { Trace1("ActRegHandler::GetVirtualString - Index %d not in string cache\n", nIndex); // doesn't exist in our cache, need to add this one. pwsr = BuildWinsStrRecord(nIndex); if (pwsr) m_RecList.AddTail(pwsr); } if (pwsr) { switch (nCol) { case ACTREG_COL_NAME: return pwsr->strName; break; case ACTREG_COL_TYPE: return pwsr->strType; break; case ACTREG_COL_IPADDRESS: return pwsr->strIPAdd; break; case ACTREG_COL_STATE: return pwsr->strActive; break; case ACTREG_COL_STATIC: return pwsr->strStatic; break; case ACTREG_COL_OWNER: return pwsr->strOwner; break; case ACTREG_COL_VERSION: return pwsr->strVersion; break; case ACTREG_COL_EXPIRATION: return pwsr->strExpiration; break; default: Panic0("ActRegHandler::GetVirtualString - Unknown column!\n"); break; } } return NULL; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::BuildWinsStrRecord Description Author: EricDav ---------------------------------------------------------------------------*/ WinsStrRecord * CActiveRegistrationsHandler::BuildWinsStrRecord(int nIndex) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); int nCount; HRESULT hr = hrOK; WinsStrRecord * pwsr = NULL; WinsRecord ws; HROW hrow; CString strTemp; if (!m_pCurrentDatabase) { return NULL; } if (FAILED(m_pCurrentDatabase->GetHRow(nIndex, &hrow))) return NULL; if (FAILED(m_pCurrentDatabase->GetData(hrow, &ws))) return NULL; COM_PROTECT_TRY { pwsr = new WinsStrRecord; // set the index for this record pwsr->nIndex = nIndex; // build the name string CleanNetBIOSName(ws.szRecordName, pwsr->strName, TRUE, // Expand TRUE, // Truncate IsLanManCompatible(), TRUE, // name is OEM FALSE, // No double backslash ws.dwNameLen); // now the type CString strValue; strValue.Format(_T("[%02Xh] "), ((int) ws.szRecordName[15] & 0x000000FF)); CString strName; DWORD dwNameType = (0x000000FF & ws.szRecordName[15]); m_NameTypeMap.TypeToCString(dwNameType, MAKELONG(HIWORD(ws.dwType), 0), strName); pwsr->strType = strValue + strName; // IP address // Gets changed in the case of static records of the type Special Group, // where the first IP address in the list of IP addresses is of the Owner if ( (ws.dwState & WINSDB_REC_UNIQUE) || (ws.dwState & WINSDB_REC_NORM_GROUP) ) { MakeIPAddress(ws.dwIpAdd[0], pwsr->strIPAdd); } else { if (ws.dwNoOfAddrs > 0) { if (ws.dwIpAdd[1] == 0) { pwsr->strIPAdd.Empty(); } else { MakeIPAddress(ws.dwIpAdd[1], pwsr->strIPAdd); } } else { pwsr->strIPAdd.Empty(); } } // active status GetStateString(ws.dwState, pwsr->strActive); // static flag if (ws.dwState & WINSDB_REC_STATIC) { pwsr->strStatic = _T("x"); } else { pwsr->strStatic = _T(""); } // expiration time if (ws.dwExpiration == INFINITE_EXPIRATION) { Verify(pwsr->strExpiration.LoadString(IDS_INFINITE)); } else { CTime time(ws.dwExpiration); FormatDateTime(pwsr->strExpiration, time); } // version GetVersionInfo(ws.liVersion.LowPart, ws.liVersion.HighPart, pwsr->strVersion); // owner if (m_Config.FSupportsOwnerId()) { MakeIPAddress(ws.dwOwner, pwsr->strOwner); } } COM_PROTECT_CATCH return pwsr; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::GetStateString Description Returns the state of the record, Active, Tomstoned, realeased or deleted Author: v-shubk ---------------------------------------------------------------------------*/ void CActiveRegistrationsHandler::GetStateString(DWORD dwState, CString& strState) { if (dwState & WINSDB_REC_ACTIVE ) { strState.LoadString(IDS_RECORD_STATE_ACTIVE); } else if (dwState & WINSDB_REC_DELETED ) { strState.LoadString(IDS_RECORD_STATE_DELETED); } else if (dwState & WINSDB_REC_RELEASED ) { strState.LoadString(IDS_RECORD_STATE_RELEASED); } else if (dwState & WINSDB_REC_TOMBSTONE ) { strState.LoadString(IDS_RECORD_STATE_TOMBSTONED); } else { strState.LoadString(IDS_RECORD_STATE_UNKNOWN); } } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::GetStateString Description Returns the static type for the record, Unique, Multihomed, Inetrne Group, Normal Group, Multihomed Author: v-shubk ---------------------------------------------------------------------------*/ void CActiveRegistrationsHandler::GetStaticTypeString(DWORD dwState, CString& strStaticType) { if (dwState & WINSDB_REC_UNIQUE ) { strStaticType = g_strStaticTypeUnique; } else if (dwState & WINSDB_REC_SPEC_GROUP ) { strStaticType = g_strStaticTypeDomainName; } else if (dwState & WINSDB_REC_MULTIHOMED ) { strStaticType = g_strStaticTypeMultihomed; } else if (dwState & WINSDB_REC_NORM_GROUP ) { strStaticType = g_strStaticTypeGroup; } else { strStaticType = g_strStaticTypeUnknown; } } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::GetVersionInfo Description Gives the version INfo as string in Hex Notation Author: v-shubk ---------------------------------------------------------------------------*/ void CActiveRegistrationsHandler::GetVersionInfo(LONG lLowWord, LONG lHighWord, CString& strVersionCount) { strVersionCount.Empty(); TCHAR sz[20]; TCHAR *pch = sz; ::wsprintf(sz, _T("%08lX%08lX"), lHighWord, lLowWord); // Kill leading zero's while (*pch == '0') { ++pch; } // At least one digit... if (*pch == '\0') { --pch; } strVersionCount = pch; } BOOL CActiveRegistrationsHandler::IsLanManCompatible() { BOOL fCompatible = TRUE; if (m_spServerNode) { CWinsServerHandler * pServer = GETHANDLER(CWinsServerHandler, m_spServerNode); fCompatible = (pServer->m_dwFlags & FLAG_LANMAN_COMPATIBLE) ? TRUE : FALSE; } return fCompatible; } // // Convert the netbios name to a displayable format, with // beginning slashes, the unprintable characters converted // to '-' characters, and the 16th character displayed in brackets. // Convert the string to ANSI/Unicode before displaying it. // // void CActiveRegistrationsHandler::CleanNetBIOSName ( LPCSTR lpszSrc, CString & strDest, BOOL fExpandChars, BOOL fTruncate, BOOL fLanmanCompatible, BOOL fOemName, BOOL fWackwack, int nLength ) { static CHAR szWacks[] = "\\\\"; BYTE ch16 = 0; if (!lpszSrc || (strcmp(lpszSrc, "") == 0) ) { strDest = _T("---------"); return; } int nLen, nDisplayLen; int nMaxDisplayLen = fLanmanCompatible ? 15 : 16; if (!fWackwack && fLanmanCompatible) { // // Don't want backslahes, but if they do exist, // remove them. // if (!::strncmp(lpszSrc, szWacks, ::strlen(szWacks))) { lpszSrc += ::strlen(szWacks); if (nLength) { nLength -= 2; } } } if ((nDisplayLen = nLen = nLength ? nLength : ::strlen(lpszSrc)) > 15) { ch16 = (BYTE)lpszSrc[15]; nDisplayLen = fTruncate ? nMaxDisplayLen : nLen; } char szTarget[MAX_PATH] = {0}; char szRestore[MAX_PATH] = {0}; char * pTarget = &szTarget[0]; if (fWackwack) { ::strcpy(pTarget, szWacks); pTarget += ::strlen(szWacks); } if (lpszSrc == NULL) { int i = 1; } if (fOemName) { ::OemToCharBuffA(lpszSrc, pTarget, nLen); } else { ::memcpy(pTarget, lpszSrc, nLen); } int n = 0; while (n < nDisplayLen) { if (fExpandChars) { #ifdef FE_SB if (::IsDBCSLeadByte(*pTarget)) { ++n; ++pTarget; } else if (!WinsIsPrint(pTarget)) #else if (!WinsIsPrint(pTarget)) #endif // FE_SB { *pTarget = BADNAME_CHAR; } } ++n; ++pTarget; } if (fLanmanCompatible) { // // Back up over the spaces. // while (*(--pTarget) == ' ') /**/ ; ++pTarget; } // if there's a scope name attached, append the scope name // to the strTarget before returning. // check the length of lpSrc, if greater than NetBIOS name // length, it has a scope name attached if (nLength > 16) { if (lpszSrc[0x10] == '.') { ::OemToCharBuffA(&lpszSrc[0x10], szRestore, sizeof(szRestore)); memcpy(pTarget, szRestore, nLength - 16); pTarget += (nLength - 16); } } *pTarget = '\0'; // convert the string to unicode. We've already done the oem to ansi // conversion so use the Ansi code page now MBCSToWide(szTarget, strDest, CP_ACP); } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::CacheHint Description Author: EricDav ---------------------------------------------------------------------------*/ STDMETHODIMP CActiveRegistrationsHandler::CacheHint ( int nStartIndex, int nEndIndex ) { HRESULT hr = hrOK; HROW hrow; Trace2("CacheHint - Start %d, End %d\n", nStartIndex, nEndIndex); m_RecList.RemoveAllEntries(); WinsRecord ws; WinsStrRecord * pwsr; for (int i = nStartIndex; i <= nEndIndex; i++) { pwsr = BuildWinsStrRecord(i); if (pwsr) m_RecList.AddTail(pwsr); } return hr; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::SortItems Description Author: EricDav, v-shubk ---------------------------------------------------------------------------*/ STDMETHODIMP CActiveRegistrationsHandler::SortItems ( int nColumn, DWORD dwSortOptions, LPARAM lUserParam ) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); HRESULT hr = hrOK; WINSDB_STATE uState = WINSDB_NORMAL; if (!m_pCurrentDatabase) { return hr; } m_pCurrentDatabase->GetCurrentState(&uState); if (uState != WINSDB_NORMAL) { AfxMessageBox(IDS_RECORDS_DOWNLOADING, MB_OK|MB_ICONINFORMATION); return hr; } // put up the busy dialog CSortWorker * pWorker = new CSortWorker(m_pCurrentDatabase, nColumn, dwSortOptions); CLongOperationDialog dlgBusy(pWorker, IDR_AVI2); dlgBusy.LoadTitleString(IDS_SNAPIN_DESC); dlgBusy.LoadDescriptionString(IDS_SORTING); // disable the system menu and the cancel buttons dlgBusy.EnableCancel(FALSE); dlgBusy.DoModal(); return hr; } /*!-------------------------------------------------------------------------- CActiveRegistrationsHandler::SetVirtualLbSize Sets the virtual listbox count. Over-ride this if you need to specify and options. Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::SetVirtualLbSize ( ITFSComponent * pComponent, LPARAM data ) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); HRESULT hr = hrOK; SPIResultData spResultData; CString strDescBarText; CString strData; ULARGE_INTEGER nullData; ULARGE_INTEGER *pData = (ULARGE_INTEGER *)data; nullData.HighPart = nullData.LowPart = 0; pData = (data == NULL)? &nullData : (ULARGE_INTEGER*)data; // just to avoid those cases when filtered shows up larger than scanned if (pData->LowPart < pData->HighPart) pData->HighPart = pData->LowPart; strDescBarText.Empty(); strDescBarText.LoadString(IDS_RECORDS_FILTERED); strData.Format(_T(" %d -- "), pData->HighPart); strDescBarText += strData; strData.LoadString(IDS_RECORDS_SCANNED); strDescBarText += strData; strData.Format(_T(" %d"), pData->LowPart); strDescBarText += strData; CORg (pComponent->GetResultData(&spResultData)); if (pData->HighPart == 0) { //CORg (spResultData->DeleteAllRsltItems()); CORg (spResultData->SetItemCount((int) pData->HighPart, MMCLV_UPDATE_NOSCROLL)); } else { CORg (spResultData->SetItemCount((int) pData->HighPart, MMCLV_UPDATE_NOSCROLL)); } CORg (spResultData->SetDescBarText((LPTSTR) (LPCTSTR) strDescBarText)); Error: return hr; } /*!-------------------------------------------------------------------------- CActiveRegistrationsHandler::UpdateCurrentView Updates the current view -- the MenuButton control and the result pane. Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::UpdateCurrentView ( ITFSNode * pNode ) { HRESULT hr = hrOK; SPIComponentData spCompData; SPIConsole spConsole; IDataObject* pDataObject; // update our current database to point to the correct one m_pCurrentDatabase = m_spWinsDatabase; // update our current database to point to the correct one m_spWinsDatabase->SetActiveView(WINSDB_VIEW_FILTERED_DATABASE); // Need to tell all of the views up update themselves with the new state. m_spNodeMgr->GetComponentData(&spCompData); CORg ( spCompData->QueryDataObject((MMC_COOKIE) pNode, CCT_RESULT, &pDataObject) ); CORg ( m_spNodeMgr->GetConsole(&spConsole) ); pDataObject->Release(); // update the listbox with the correct count for this view UpdateListboxCount(pNode); UpdateVerbs(pNode); Error: return hr; } /*!-------------------------------------------------------------------------- CActiveRegistrationsHandler::CompareRecName Checks if the name matches the Find record criterion Author: EricDav, v-shubk ---------------------------------------------------------------------------*/ BOOL CActiveRegistrationsHandler::CompareRecName(LPSTR szNewName) { // convert the MBCS name to a wide string using the OEM // code page so we can do the compare. CString strTemp; MBCSToWide(szNewName, strTemp, WINS_NAME_CODE_PAGE); // when some invalid records get passed if (strTemp.IsEmpty()) { return FALSE; } CString strFindNameU = m_strFindName; if (!m_fMatchCase) { strTemp.MakeUpper(); } int nLen = strFindNameU.GetLength(); for (int nPos = 0; nPos < nLen; nPos++) { if (strFindNameU[nPos] == _T('*')) { break; } // the passed record has a smaller string length if (nPos >= strTemp.GetLength()) { return FALSE; } if (strTemp[nPos] != strFindNameU[nPos]) { return FALSE; } } return TRUE; } /*!-------------------------------------------------------------------------- CActiveRegistrationsHandler::DeleteRegistration Removes a registration from the server and the virtual listbox. Need to remove the entry from both the find database and the full database. Author: v-shubk ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::DeleteRegistration ( ITFSComponent * pComponent, int nIndex ) { HRESULT hr = hrOK; DWORD err = 0; CVirtualIndexArray arraySelectedIndicies; int i; int nCurrentCount; WinsRecord ws; int nCount; SPIConsole spConsole; LPDATAOBJECT pDataObject= NULL; BOOL fDelete; // ask whether to delete or tombstone the record CDeleteRecordDlg dlgDel; SPIResultData spResultData; SPITFSNode spNode; CORg (pComponent->GetResultData(&spResultData)); // build a list of the selected indicies in the virtual listbox CORg (BuildVirtualSelectedItemList(pComponent, &arraySelectedIndicies)); nCount = (int)arraySelectedIndicies.GetSize(); dlgDel.m_fMultiple = (nCount > 1) ? TRUE : FALSE; if (IDOK != dlgDel.DoModal()) { return hrOK; } fDelete = (dlgDel.m_nDeleteRecord == 0); BEGIN_WAIT_CURSOR for (i = 0; i < nCount; i++) { HROW hrowDel; // remove each selected index int nDelIndex = arraySelectedIndicies.GetAt(nCount -1 - i); // from internal storage CORg(m_spWinsDatabase->GetHRow(nDelIndex, &hrowDel)); CORg(m_spWinsDatabase->GetData(hrowDel, &ws)); if (fDelete) { // delete this record err = DeleteMappingFromServer(pComponent, &ws, nDelIndex); } else { // tombstone the record err = TombstoneRecords(pComponent, &ws); } // if a particular record could not be deleted, see if they want to cancel if (err != ERROR_SUCCESS) { // put up if (WinsMessageBox(err, MB_OKCANCEL) == IDCANCEL) { break; } } else { // remove from local storage if we are deleting this record if (fDelete) { CORg(m_spWinsDatabase->DeleteRecord(hrowDel)); } // remove from UI if delete is selected, othewise update the state (tombstone) if (dlgDel.m_nDeleteRecord == 0) { CORg(spResultData->DeleteItem(nDelIndex, 0)); } else { UpdateRecord(pComponent, &ws, nDelIndex); } } } END_WAIT_CURSOR // get the actreg node and redraw the list box pComponent->GetSelectedNode(&spNode); // now set the count.. this effectively redraws the contents CORg (m_pCurrentDatabase->GetCurrentCount(&nCurrentCount)); UpdateListboxCount(spNode); // if we are tombstoning, then there will still be selections // in the result pane. In this case we need to pass in NULL // for the node type so that the verbs get updated correctly. if (!fDelete) spNode.Set(NULL); // update the cuurent view UpdateCurrentView(spNode); Error: return hr; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler:: AddMapping(ITFSNode* pNode) Adds a new Mapping to the server Author: v-shubk ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::AddMapping(ITFSNode* pNode) { HRESULT hr = hrOK; DWORD err = ERROR_SUCCESS; // get the server SPITFSNode spServerNode; pNode->GetParent(&spServerNode); CWinsServerHandler * pServer = GETHANDLER(CWinsServerHandler, spServerNode); BOOL fInternetGroup = FALSE; if (m_strStaticMappingType.CompareNoCase(g_strStaticTypeInternetGroup) == 0) { fInternetGroup = TRUE; } CString strName(m_strStaticMappingName); // check if valid NetBIOSNAme if (pServer->IsValidNetBIOSName(strName, IsLanManCompatible(), FALSE)) { m_Multiples.SetNetBIOSName(m_strStaticMappingName); m_Multiples.SetNetBIOSNameLength(m_strStaticMappingName.GetLength()); int nMappings = 0; int i; switch(m_nStaticMappingType) { case WINSINTF_E_UNIQUE: case WINSINTF_E_NORM_GROUP: { nMappings = 1; LONG l; m_Multiples.SetIpAddress(m_lArrayIPAddress.GetAt(0)); } break; case WINSINTF_E_SPEC_GROUP: case WINSINTF_E_MULTIHOMED: nMappings = (int)m_lArrayIPAddress.GetSize(); ASSERT(nMappings <= WINSINTF_MAX_MEM); if (!fInternetGroup && nMappings == 0) { //return E_FAIL; } for (i = 0; i < nMappings; ++i) { m_Multiples.SetIpAddress(i,m_lArrayIPAddress.GetAt(i) ); } break; default: ASSERT(0 && "Invalid mapping type!"); } BEGIN_WAIT_CURSOR // add to the server err = AddMappingToServer(pNode, m_nStaticMappingType, nMappings, m_Multiples); END_WAIT_CURSOR if (err == ERROR_SUCCESS) { // // Added succesfully // } else { // // WINS disallowed the mapping. Put up the // error message, and highlight the name // return HRESULT_FROM_WIN32(err); } } return hr; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::EditMappingToServer( ITFSNode* pNode, int nType, int nCount, CMultipleIpNamePair& mipnp, BOOL fEdit, WinsRecord *pRecord ) Edits the maping stored in the server database, WinsRecordAction is called Author: v-shubk ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::EditMappingToServer( ITFSNode* pNode, int nType, int nCount, CMultipleIpNamePair& mipnp, BOOL fEdit, // Editing existing mapping? WinsRecord *pRecord ) { SPITFSNode spNode; pNode->GetParent(&spNode); CWinsServerHandler* pServer = GETHANDLER(CWinsServerHandler, spNode); HRESULT hr = hrOK; WINSINTF_RECORD_ACTION_T RecAction; PWINSINTF_RECORD_ACTION_T pRecAction; DWORD dwLastStatus; ASSERT(nType >= WINSINTF_E_UNIQUE && nType <= WINSINTF_E_MULTIHOMED); ZeroMemory(&RecAction, sizeof(RecAction)); RecAction.TypOfRec_e = nType; RecAction.Cmd_e = WINSINTF_E_INSERT; RecAction.pAdd = NULL; RecAction.pName = NULL; pRecAction = &RecAction; if (nType == WINSINTF_E_UNIQUE || nType == WINSINTF_E_NORM_GROUP) { RecAction.NoOfAdds = 1; RecAction.Add.IPAdd = (LONG)mipnp.GetIpAddress(); RecAction.Add.Type = 0; RecAction.Add.Len = 4; } else { ASSERT(nCount <= WINSINTF_MAX_MEM); RecAction.pAdd = (WINSINTF_ADD_T *)::WinsAllocMem( sizeof(WINSINTF_ADD_T) * nCount); if (RecAction.pAdd == NULL) { return ERROR_NOT_ENOUGH_MEMORY; } RecAction.NoOfAdds = nCount; int i; for (i = 0; i < nCount; ++i) { (RecAction.pAdd+i)->IPAdd = (LONG)mipnp.GetIpAddress(i); (RecAction.pAdd+i)->Type = 0; (RecAction.pAdd+i)->Len = 4; } RecAction.NodeTyp = WINSINTF_E_PNODE; } RecAction.fStatic = TRUE; // Don't copy the beginning slashes when adding. // int nLen = pRecord->dwNameLen; // // Must have at least enough room for 16 character string // RecAction.pName = (LPBYTE)::WinsAllocMem(nLen + 1); if (RecAction.pName == NULL) { if (RecAction.pAdd) { ::WinsFreeMem(RecAction.pAdd); } return ERROR_NOT_ENOUGH_MEMORY; } if (fEdit) { // // No need to convert if already existing in the database. // // convert to ASCII string and copy ::memcpy((char *)RecAction.pName, (LPCSTR) pRecord->szRecordName, nLen+1 ); RecAction.NameLen = nLen; } else { ::CharToOemBuff(mipnp.GetNetBIOSName(), (char *)RecAction.pName, nLen ); } #ifdef WINS_CLIENT_APIS dwLastStatus = ::WinsRecordAction(pServer->GetBinding(), &pRecAction); #else dwLastStatus = ::WinsRecordAction(&pRecAction); #endif WINS_CLIENT_APIS if (RecAction.pName != NULL) { ::WinsFreeMem(RecAction.pName); } if (RecAction.pAdd != NULL) { ::WinsFreeMem(RecAction.pAdd); } return dwLastStatus; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::AddMappingToServer( ITFSNode* pNode, int nType, int nCount, CMultipleIpNamePair& mipnp, BOOL fEdit ) Adds the cleaned record to the server, WinsRecordAction acalled with WINSINTF_INSERT option Author: v-shubk ---------------------------------------------------------------------------*/ DWORD CActiveRegistrationsHandler::AddMappingToServer( ITFSNode* pNode, int nType, int nCount, CMultipleIpNamePair& mipnp, BOOL fEdit ) { HRESULT hr = hrOK; WINSINTF_RECORD_ACTION_T RecAction; PWINSINTF_RECORD_ACTION_T pRecAction; SPITFSNode spNode; pNode->GetParent(&spNode); CWinsServerHandler *pServer = GETHANDLER(CWinsServerHandler, spNode); DWORD dwLastStatus; ASSERT(nType >= WINSINTF_E_UNIQUE && nType <= WINSINTF_E_MULTIHOMED); ZeroMemory(&RecAction, sizeof(RecAction)); RecAction.TypOfRec_e = nType; RecAction.Cmd_e = WINSINTF_E_INSERT; RecAction.pAdd = NULL; RecAction.pName = NULL; pRecAction = &RecAction; if (nType == WINSINTF_E_UNIQUE || nType == WINSINTF_E_NORM_GROUP) { RecAction.NoOfAdds = 1; RecAction.Add.IPAdd = (LONG)mipnp.GetIpAddress(); RecAction.Add.Type = 0; RecAction.Add.Len = 4; } else { ASSERT(nCount <= WINSINTF_MAX_MEM); RecAction.pAdd = (WINSINTF_ADD_T *)::WinsAllocMem( sizeof(WINSINTF_ADD_T) * nCount); if (RecAction.pAdd == NULL) { return ERROR_NOT_ENOUGH_MEMORY; } RecAction.NoOfAdds = nCount; int i; for (i = 0; i < nCount; ++i) { (RecAction.pAdd+i)->IPAdd = (LONG)mipnp.GetIpAddress(i); (RecAction.pAdd+i)->Type = 0; (RecAction.pAdd+i)->Len = 4; } RecAction.NodeTyp = WINSINTF_E_PNODE; } RecAction.fStatic = TRUE; // // Don't copy the beginning slashes when adding. // int nLen = mipnp.GetNetBIOSNameLength(); // // Must have at least enough room for 256 character string, // includes the scope name too // RecAction.pName = (LPBYTE)::WinsAllocMem(257); if (RecAction.pName == NULL) { return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); } ZeroMemory(RecAction.pName, 257); LPSTR szTemp = (char *) alloca(100); CString strTemp = mipnp.GetNetBIOSName(); // This should be OEM WideToMBCS(strTemp, szTemp, WINS_NAME_CODE_PAGE); nLen = strlen(szTemp); ::memcpy((char *)RecAction.pName, (LPCSTR) szTemp, nLen+1 ); if (nLen < 16) { if (nType == WINSINTF_E_SPEC_GROUP) { ::memset(RecAction.pName+nLen, (int)' ',16-nLen); RecAction.pName[15] = 0x1C; RecAction.pName[16] = '\0'; RecAction.NameLen = nLen = 16; char szAppend[MAX_PATH]; if (!m_strStaticMappingScope.IsEmpty()) { AppendScopeName((LPSTR)RecAction.pName, (LPSTR)szAppend); strcpy((LPSTR)RecAction.pName, (LPSTR)szAppend); RecAction.NameLen = nLen = strlen((LPSTR)RecAction.pName); } pRecAction = &RecAction; #ifdef WINS_CLIENT_APIS dwLastStatus = ::WinsRecordAction(pServer->GetBinding(), &pRecAction); #else dwLastStatus = ::WinsRecordAction(&pRecAction); #endif WINS_CLIENT_APIS if (dwLastStatus != ERROR_SUCCESS) { } else { HRESULT hr = hrOK; // query the server for correct info PWINSINTF_RECORD_ACTION_T pRecAction1 = QueryForName(pNode, pRecAction); if (pRecAction1 == NULL) { //add it to the m_spWinsDatabase hr = AddToLocalStorage(pRecAction, pNode); } else { // the record found and correct info displayed //add it to the m_spWinsDatabase hr = AddToLocalStorage(pRecAction1, pNode); free(pRecAction1->pName); } } } else if (nType == WINSINTF_E_NORM_GROUP) { ::memset(RecAction.pName+nLen, (int)' ',16-nLen); RecAction.pName[15] = 0x1E; RecAction.pName[16] = '\0'; RecAction.NameLen = nLen = 16; char szAppend[MAX_PATH]; if (!m_strStaticMappingScope.IsEmpty()) { AppendScopeName((LPSTR)RecAction.pName, (LPSTR)szAppend); strcpy((LPSTR)RecAction.pName, (LPSTR)szAppend); RecAction.NameLen = nLen = strlen((LPSTR)RecAction.pName); } pRecAction = &RecAction; #ifdef WINS_CLIENT_APIS dwLastStatus = ::WinsRecordAction(pServer->GetBinding(),&pRecAction); #else dwLastStatus = ::WinsRecordAction(&pRecAction); #endif WINS_CLIENT_APIS if (dwLastStatus != ERROR_SUCCESS) { } else { // query the server for correct info PWINSINTF_RECORD_ACTION_T pRecAction1 = QueryForName(pNode, pRecAction); if (pRecAction1 == NULL) { hr = AddToLocalStorage(pRecAction, pNode); } else { // the record found and correct info displayed //add it to the m_spWinsDatabase hr = AddToLocalStorage(pRecAction1, pNode); free(pRecAction1->pName); } } } else { // // NOTICE:: When lanman compatible, the name is added // three times - once each as worksta, server // and messenger. This will change when we allow // different 16th bytes to be set. // if (IsLanManCompatible() && !fEdit) { BYTE ab[] = { 0x00, 0x03, 0x20 }; ::memset(RecAction.pName + nLen, (int)' ', 16-nLen); int i; for (i = 0; i < sizeof(ab) / sizeof(ab[0]); ++i) { *(RecAction.pName+15) = ab[i]; *(RecAction.pName+16) = '\0'; RecAction.NameLen = nLen = 16; // append the scope name here, if present if (!m_strStaticMappingScope.IsEmpty()) { // don't allow the scope to be appended if the 16th char is 00, // consistent with WinsCL if (i != 0) { char *lpAppend = new char [MAX_PATH]; AppendScopeName((LPSTR)RecAction.pName, (LPSTR)lpAppend); strcpy((LPSTR)RecAction.pName, (LPSTR)lpAppend); RecAction.NameLen = nLen = strlen((LPSTR)RecAction.pName); delete [] lpAppend; } } pRecAction = &RecAction; #ifdef WINS_CLIENT_APIS dwLastStatus = ::WinsRecordAction(pServer->GetBinding(),&pRecAction); #else dwLastStatus = ::WinsRecordAction(&pRecAction); #endif WINS_CLIENT_APIS Trace1("WinsRecAction suceeded for '%lx'\n", ab[i]); if (dwLastStatus != ERROR_SUCCESS) { break; } else { // query the server for correct info PWINSINTF_RECORD_ACTION_T pRecAction1 = QueryForName(pNode, pRecAction); if (pRecAction1 == NULL) { //add it to the m_spWinsDatabase hr = AddToLocalStorage(pRecAction, pNode); } else { // the record found and correct info displayed //add it to the m_spWinsDatabase hr = AddToLocalStorage(pRecAction1, pNode); free(pRecAction1->pName); } } } } else { ::memset(RecAction.pName+nLen, (int)'\0',16-nLen); *(RecAction.pName+15) = 0x20; *(RecAction.pName+16) = '\0'; RecAction.NameLen = nLen; char szAppend[MAX_PATH]; if (!m_strStaticMappingScope.IsEmpty()) { AppendScopeName((LPSTR)RecAction.pName, (LPSTR)szAppend); strcpy((LPSTR)RecAction.pName, (LPSTR)szAppend); RecAction.NameLen = nLen = strlen((LPSTR)RecAction.pName); } #ifdef WINS_CLIENT_APIS dwLastStatus = ::WinsRecordAction(pServer->GetBinding(),&pRecAction); #else dwLastStatus = ::WinsRecordAction(&pRecAction); #endif WINS_CLIENT_APIS if (dwLastStatus != ERROR_SUCCESS) { } else { // query the server for correct info PWINSINTF_RECORD_ACTION_T pRecAction1 = QueryForName(pNode, pRecAction); if (pRecAction1 == NULL) { //add it to the m_spWinsDatabase hr = AddToLocalStorage(pRecAction, pNode); } else { // the record found and correct info displayed //add it to the m_spWinsDatabase hr = AddToLocalStorage(pRecAction1, pNode); free(pRecAction1->pName); } } } } } else { RecAction.NameLen = nLen; #ifdef WINS_CLIENT_APIS dwLastStatus = ::WinsRecordAction(pServer->GetBinding(),&pRecAction); #else dwLastStatus = ::WinsRecordAction(&pRecAction); #endif WINS_CLIENT_APIS if (dwLastStatus != ERROR_SUCCESS) { } else { // query the server for correct info PWINSINTF_RECORD_ACTION_T pRecAction1 = QueryForName(pNode, pRecAction); if (pRecAction1 == NULL) { //add it to the m_spWinsDatabase hr = AddToLocalStorage(pRecAction, pNode); } else { // the record found and correct info displayed //add it to the m_spWinsDatabase hr = AddToLocalStorage(pRecAction1, pNode); free(pRecAction1->pName); } } } if (RecAction.pName != NULL) { ::WinsFreeMem(RecAction.pName); } if (RecAction.pAdd != NULL) { ::WinsFreeMem(RecAction.pAdd); } return dwLastStatus; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::AddToLocalStorage( PWINSINTF_RECORD_ACTION_T pRecAction, ITFSNode* pNode ) add it to the m_spWinsDatabase, after getting all the information(Version, Exp etc) from the server Author: v-shubk ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::AddToLocalStorage(PWINSINTF_RECORD_ACTION_T pRecAction, ITFSNode* pNode) { HRESULT hr = hrOK; BOOL bIPOk = FALSE; WinsRecord ws; // convert WINS_RECORD_ACTION to internal record WinsIntfToWinsRecord(pRecAction, ws); if (pRecAction->OwnerId < (UINT) m_pServerInfoArray->GetSize()) ws.dwOwner = (*m_pServerInfoArray)[pRecAction->OwnerId].m_dwIp; if (m_spWinsDatabase) { hr = m_spWinsDatabase->AddRecord(&ws); } return hr; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::OnImportLMHOSTS(ITFSNode* pNode) Command Handler for Import LMHosts Author: v-shubk ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::OnImportLMHOSTS(ITFSNode* pNode) { HRESULT hr = hrOK; CString strTitle; CString strFilter; strFilter.LoadString(IDS_ALL_FILES); // put up the file dlg to get the file CFileDialog dlgFile(TRUE, NULL, NULL, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, strFilter); dlgFile.m_ofn.lpstrTitle = strTitle; DWORD err = ERROR_SUCCESS; if (dlgFile.DoModal() == IDOK) { // // If this is a local connection, we copy the file to // temporary name (the source may be on a remote drive // which is not accessible to the WINS service. // // If this is not a local connection, attempt to copy // the file to a temp name on C$ of the WINS server // BEGIN_WAIT_CURSOR CString strMappingFile(dlgFile.GetPathName()); do { if (IsLocalConnection(pNode)) { CString strWins; strWins.LoadString(IDS_WINS); CString strTmpFile(_tempnam(NULL, "WINS")); // // First copy file to a temporary name (since the file // could be remote), and then import and delete this file // if (!CopyFile(strMappingFile, strTmpFile, TRUE)) { err = ::GetLastError(); break; } // // Now import the temporary file, and delete the file // afterwards. // err = ImportStaticMappingsFile(pNode, strTmpFile, TRUE); } else { // // Try copying to the remote machine C: drive // CString strServerName; GetServerName(pNode, strServerName); CString strWins; strWins.LoadString(IDS_WINS); CString strTemp; strTemp.Format(_T("\\\\%s\\C$"), strServerName); // Find a suitable remote file name CString strRemoteFile; DWORD dwErr = RemoteTmp(strTemp, strWins, strRemoteFile); if (dwErr != ERROR_SUCCESS) { CString strError, strMessage; ::GetSystemMessage(dwErr, strError.GetBuffer(1024), 1024); strError.ReleaseBuffer(); AfxFormatString1(strMessage, IDS_ERR_REMOTE_IMPORT, strError); AfxMessageBox(strMessage); goto Error; } // // First copy file to a temporary name (since the file // could be remote), and then import and delete this file // if (!CopyFile(strMappingFile, strRemoteFile, TRUE)) { err = ::GetLastError(); break; } // // fixup the filename so it looks local to the wins server // LPTSTR pch = strRemoteFile.GetBuffer(256); // // Now replace the remote path with a local path // for the remote WINS server // while (*pch != '$') { ++pch; } *pch = ':'; --pch; CString strRemoteFileNew(pch); strRemoteFile.ReleaseBuffer(); // // Now import the temporary file, and delete the file // afterwards. // err = ImportStaticMappingsFile(pNode, strRemoteFileNew, TRUE); } } while(FALSE); END_WAIT_CURSOR if (err == ERROR_SUCCESS) { AfxMessageBox(IDS_MSG_IMPORT, MB_ICONINFORMATION); // refresh the result pane now. RefreshResults(pNode); } else { ::WinsMessageBox(err, MB_OK); } // refresh the server statistics SPITFSNode spServerNode; pNode->GetParent(&spServerNode); CWinsServerHandler * pServer = GETHANDLER(CWinsServerHandler, spServerNode); // rferesh the statistics pServer->GetStatistics(spServerNode, NULL); } Error: return err; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::IsLocalConnection(ITFSNode *pNode) Check if the loacl machine is being managed Author: v-shubk ---------------------------------------------------------------------------*/ BOOL CActiveRegistrationsHandler::IsLocalConnection(ITFSNode *pNode) { // get the server netbios name CString strServerName; GetServerName(pNode,strServerName); // address of name buffer TCHAR szBuffer[MAX_COMPUTERNAME_LENGTH + 1]; DWORD nSize = MAX_COMPUTERNAME_LENGTH + 1 ; ::GetComputerName(szBuffer, &nSize); CString strCompName(szBuffer); if (strCompName == strServerName) { return TRUE; } return FALSE; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::GetServerName(ITFSNode * pNode, CString &strServerName) Talk to the parent node and get the server name we are managing Author: v-shubk ---------------------------------------------------------------------------*/ void CActiveRegistrationsHandler::GetServerName(ITFSNode * pNode, CString &strServerName) { SPITFSNode spServerNode; pNode->GetParent(&spServerNode); CWinsServerHandler * pServer = GETHANDLER(CWinsServerHandler, spServerNode); strServerName = pServer->GetServerAddress(); } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::ImportStaticMappingsFile(CString strFile, BOOL fDelete) Call the WINS API to import the statis mappings text file Author: v-shubk ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::ImportStaticMappingsFile(ITFSNode *pNode, CString strFile, BOOL fDelete) { HRESULT hr = hrOK; SPITFSNode spServerNode; pNode->GetParent(&spServerNode); CWinsServerHandler * pServer = GETHANDLER(CWinsServerHandler, spServerNode); LPTSTR lpszTemp = strFile.GetBuffer(MAX_PATH * 2); #ifdef WINS_CLIENT_APIS DWORD dwLastStatus = ::WinsDoStaticInit(pServer->GetBinding(), (LPTSTR)lpszTemp, fDelete); #else DWORD dwLastStatus = ::WinsDoStaticInit((LPTSTR)lpszTemp, fDelete); #endif WINS_CLIENT_APIS strFile.ReleaseBuffer(); return dwLastStatus; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::RemoteTmp(CString strDir,CString strPrefix ) Get a temporary file on a remote drive Author: v-shubk ---------------------------------------------------------------------------*/ DWORD CActiveRegistrationsHandler::RemoteTmp(CString & strDir, CString & strPrefix, CString & strRemoteFile) { DWORD dwErr = ERROR_SUCCESS; CString strReturn; int n = 0; while (TRUE) { strReturn.Format(_T("%s\\%s%d"), strDir, strPrefix, ++n); if (GetFileAttributes(strReturn) == -1) { dwErr = GetLastError(); if (dwErr == ERROR_FILE_NOT_FOUND) { strRemoteFile = strReturn; dwErr = ERROR_SUCCESS; } break; } } return dwErr; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::DeleteMappingFromServer(ITFSComponent * pComponent, WinsRecord *pws,int nIndex) Deletes wins record from the Wins Server Author: v-shubk ---------------------------------------------------------------------------*/ DWORD CActiveRegistrationsHandler::DeleteMappingFromServer ( ITFSComponent * pComponent, WinsRecord * pws, int nIndex ) { HRESULT hr = hrOK; //check if the record is static WINSINTF_RECORD_ACTION_T RecAction; PWINSINTF_RECORD_ACTION_T pRecAction; ZeroMemory(&RecAction, sizeof(RecAction)); SPITFSNode spNode; pComponent->GetSelectedNode(&spNode); SPITFSNode spParentNode; spNode->GetParent(&spParentNode); CWinsServerHandler* pServer = GETHANDLER(CWinsServerHandler, spParentNode); if (pws->dwState & WINSDB_REC_STATIC) { RecAction.fStatic = TRUE; if (pws->dwState & WINSDB_REC_UNIQUE) { RecAction.TypOfRec_e = WINSINTF_E_UNIQUE; } else if (pws->dwState & WINSDB_REC_SPEC_GROUP) { RecAction.TypOfRec_e = WINSINTF_E_SPEC_GROUP; } else if (pws->dwState & WINSDB_REC_NORM_GROUP) { RecAction.TypOfRec_e = WINSINTF_E_NORM_GROUP; } else if (pws->dwState & WINSDB_REC_MULTIHOMED) { RecAction.TypOfRec_e = WINSINTF_E_MULTIHOMED; } } else { RecAction.fStatic = FALSE; } RecAction.Cmd_e = WINSINTF_E_DELETE; RecAction.State_e = WINSINTF_E_DELETED; RecAction.pName = NULL; RecAction.pAdd = NULL; pRecAction = &RecAction; RecAction.pName = (LPBYTE)::WinsAllocMem(pws->dwNameLen+1); if (RecAction.pName == NULL) { return ::GetLastError(); } ZeroMemory(RecAction.pName, pws->dwNameLen+1); memcpy(RecAction.pName, pws->szRecordName, pws->dwNameLen); if (pws->dwNameLen) { RecAction.NameLen = pws->dwNameLen; } else { RecAction.NameLen = ::strlen((LPSTR)RecAction.pName); } RecAction.OwnerId = pws->dwOwner; DWORD dwLastStatus = ERROR_SUCCESS; #ifdef WINS_CLIENT_APIS dwLastStatus = ::WinsRecordAction(pServer->GetBinding(), &pRecAction); #else dwLastStatus = ::WinsRecordAction(&pRecAction); #endif WINS_CLIENT_APIS if (RecAction.pName != NULL) { ::WinsFreeMem(RecAction.pName); } if (RecAction.pAdd != NULL) { ::WinsFreeMem(RecAction.pAdd); } return dwLastStatus; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::EditMapping(ITFSNode *pNode) Edit the already mapping , the user might have changed the IP address Author: v-shubk ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::EditMapping(ITFSNode *pNode, ITFSComponent *pComponent, int nIndex) { HRESULT hr = hrOK; DWORD err = ERROR_SUCCESS; int i; int nCurrentCount; // get the server SPITFSNode spServerNode; pNode->GetParent(&spServerNode); CWinsServerHandler * pServer = GETHANDLER(CWinsServerHandler, spServerNode); BOOL fInternetGroup = FALSE; if (m_strStaticMappingType.CompareNoCase(g_strStaticTypeInternetGroup) == 0) { fInternetGroup = TRUE; } // create the multiple IPNamePr if (pServer->IsValidNetBIOSName(m_strStaticMappingName, IsLanManCompatible(), FALSE)) { m_Multiples.SetNetBIOSName(m_strStaticMappingName); m_Multiples.SetNetBIOSNameLength(m_strStaticMappingName.GetLength()); int nMappings = 0; int i; switch(m_nStaticMappingType) { case WINSINTF_E_UNIQUE: case WINSINTF_E_NORM_GROUP: { nMappings = 1; LONG l; m_Multiples.SetIpAddress(m_lArrayIPAddress.GetAt(0)); } break; case WINSINTF_E_SPEC_GROUP: case WINSINTF_E_MULTIHOMED: nMappings = (int)m_lArrayIPAddress.GetSize(); ASSERT(nMappings <= WINSINTF_MAX_MEM); if (!fInternetGroup && nMappings == 0) { //return E_FAIL; } for (i = 0; i < nMappings; ++i) { m_Multiples.SetIpAddress(i,m_lArrayIPAddress.GetAt(i) ); } break; default: ASSERT(0 && "Invalid mapping type!"); } HROW hrowDel; WinsRecord ws; // from internal storage CORg(m_spWinsDatabase->GetHRow(m_nSelectedIndex, &hrowDel)); CORg(m_spWinsDatabase->GetData(hrowDel, &ws)); if (m_nStaticMappingType == WINSINTF_E_SPEC_GROUP || m_nStaticMappingType == WINSINTF_E_MULTIHOMED) { // // An internet group being edited cannot simply be // re-added, since it will add ip addresses, not // overwrite them, so it must first be removed. // err = DeleteMappingFromServer(pComponent, &ws, m_nSelectedIndex); } // // We edit the mapping by merely re-adding it, which // has the same effect. // if (err == ERROR_SUCCESS) { err = EditMappingToServer(pNode, m_nStaticMappingType, nMappings, m_Multiples, TRUE, &m_CurrentRecord); } if (err != ERROR_SUCCESS) { return err; } WINSINTF_ADD_T OwnAdd; // // Fill in current owner // OwnAdd.Len = 4; OwnAdd.Type = 0; OwnAdd.IPAdd = pServer->GetServerIP(); WINSINTF_RECS_T Recs; Recs.pRow = NULL; #ifdef WINS_CLIENT_APIS err = ::WinsGetDbRecsByName(pServer->GetBinding(), &OwnAdd, WINSINTF_BEGINNING, (LPBYTE) ws.szRecordName, ws.dwNameLen, 1, (ws.dwState & WINSDB_REC_STATIC) ? WINSINTF_STATIC : WINSINTF_DYNAMIC, &Recs); #else err = ::WinsGetDbRecsByName(&OwnAdd, WINSINTF_BEGINNING, (LPBYTE) ws.szRecordName, ws.dwNameLen, 1, (ws.dwState & WINSDB_REC_STATIC) ? WINSINTF_STATIC : WINSINTF_DYNAMIC, &Recs); #endif WINS_CLIENT_APIS if (err == ERROR_SUCCESS) { TRY { ASSERT(Recs.NoOfRecs == 1); if (Recs.NoOfRecs == 0) { // // the record can not be found. // This should not happen! // //Trace("Unable to find the record to refresh:\n"); return ERROR_REC_NON_EXISTENT; } PWINSINTF_RECORD_ACTION_T pRow1 = Recs.pRow; WinsRecord wRecord; WinsIntfToWinsRecord(pRow1, wRecord); if (pRow1->OwnerId < (UINT) m_pServerInfoArray->GetSize()) wRecord.dwOwner = (*m_pServerInfoArray)[pRow1->OwnerId].m_dwIp; // RefreshData(Recs.pRow), delete this particular record and add it again; // from internal storage CORg(m_spWinsDatabase->DeleteRecord(hrowDel)); CORg(m_spWinsDatabase->AddRecord(&wRecord)); // now set the count.. this effectively redraws the contents CORg (m_pCurrentDatabase->GetCurrentCount(&nCurrentCount)); UpdateCurrentView(pNode); } CATCH_ALL(e) { return ::GetLastError(); } END_CATCH_ALL; } if (Recs.pRow != NULL) { ::WinsFreeMem(Recs.pRow); } } Error: return err; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::QueryForName() queries WINS server given the name and gets info to be displayed in the result pane Author: v-shubk ---------------------------------------------------------------------------*/ PWINSINTF_RECORD_ACTION_T CActiveRegistrationsHandler::QueryForName ( ITFSNode * pNode, PWINSINTF_RECORD_ACTION_T pRecAction, BOOL fStatic ) { SPITFSNode spNode; pNode->GetParent(&spNode); CWinsServerHandler *pServer = GETHANDLER(CWinsServerHandler, spNode); HRESULT hr = hrOK; pRecAction->pAdd = NULL; pRecAction->NoOfAdds = 0; pRecAction->fStatic = fStatic; pRecAction->Cmd_e = WINSINTF_E_QUERY; #ifdef WINS_CLIENT_APIS DWORD dwStatus = WinsRecordAction(pServer->GetBinding(), &pRecAction); #else DWORD dwStatus = WinsRecordAction(&pRecAction); #endif WINS_CLIENT_APIS // when we query for a record, the string length must not include the null terminator. // in the normal case using GetDbRecs, wins returns the name length as length + 1 // for the null terminator. Since all of the code expects any WINSINTFS_RECORD_ACTION_T // struct to be in that format, let's touch things up a bit and make a copy. if (dwStatus == 0) { pRecAction->NameLen++; LPBYTE pNew = (LPBYTE) malloc(pRecAction->NameLen); if (pNew) { ZeroMemory(pNew, pRecAction->NameLen); memcpy(pNew, pRecAction->pName, pRecAction->NameLen - 1); pRecAction->pName = pNew; } return pRecAction; } else { return NULL; } } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::ToString(DWORD dwParam, CString& strParam) converts DWORD to CString Author v-shubk ---------------------------------------------------------------------------*/ void CActiveRegistrationsHandler::ToString(DWORD dwParam, CString& strParam) { TCHAR szStr[20]; _ltot((LONG)dwParam, szStr, 10); CString str(szStr); strParam = str; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::OnExportEntries() Command Handler for Export Database Author v-shubk ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::OnExportEntries() { HRESULT hr = hrOK; WinsRecord ws; HROW hrow; if (!m_pCurrentDatabase) { return NULL; } // Bring up the Save Dialog CString strType; strType.LoadString(IDS_FILE_EXTENSION); CString strDefFileName; strDefFileName.LoadString(IDS_FILE_DEFNAME); CString strFilter; strFilter.LoadString(IDS_STR_EXPORTFILE_FILTER); // put up the dlg to get the file name CFileDialog cFileDlg(FALSE, strType, strDefFileName, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, strFilter); CString strTitle; strTitle.LoadString(IDS_EXPFILE_TITLE); cFileDlg.m_ofn.lpstrTitle = strTitle; if ( cFileDlg.DoModal() != IDOK ) { return hrFalse; } // getthe entire path CString strFileName = cFileDlg.GetPathName(); COM_PROTECT_TRY { int nCount; m_pCurrentDatabase->GetCurrentCount(&nCount); CString strContent; strContent.Empty(); CString strTemp; strTemp.Empty(); CString strLine; strLine.Empty(); CString strDelim = _T(','); CString strNewLine = _T("\r\n"); // create a file named "WinsExp.txt" in the current directory CFile cFileExp(strFileName, CFile::modeCreate | CFile::modeRead | CFile::modeWrite); // this is a unicode file, write the unicde lead bytes (2) cFileExp.Write(&gwUnicodeHeader, sizeof(WORD)); CString strHead; strHead.LoadString(IDS_STRING_HEAD); strHead += strNewLine; cFileExp.Write(strHead, strHead.GetLength()*sizeof(TCHAR)); BEGIN_WAIT_CURSOR #ifdef DEBUG CTime timeStart, timeFinish; timeStart = CTime::GetCurrentTime(); #endif for (int i = 0; i < nCount; i++) { strLine.Empty(); strTemp.Empty(); hr = m_pCurrentDatabase->GetHRow(i, &hrow); hr = m_pCurrentDatabase->GetData(hrow, &ws); // build the name string CleanNetBIOSName(ws.szRecordName, // input char * strTemp, // output LPTSTR TRUE, // Expand TRUE, // Truncate IsLanManCompatible(), TRUE, // name is OEM FALSE, // No double backslash ws.dwNameLen); strLine += strTemp; strLine += strDelim; // now the type m_NameTypeMap.TypeToCString((DWORD)ws.szRecordName[15], MAKELONG(HIWORD(ws.dwType), 0), strTemp); strLine += strTemp; strLine += strDelim; // IP address if ( (ws.dwState & WINSDB_REC_UNIQUE) || (ws.dwState & WINSDB_REC_NORM_GROUP) ) { MakeIPAddress(ws.dwIpAdd[0], strTemp); strLine += strTemp; } else { CString strTemp2; // this record has multiple addresses. The addresses are in the form of: // owner wins, then IP address // out put will look like address - owner IP;address - owner ip for (DWORD i = 0; i < ws.dwNoOfAddrs; i++) { if (i != 0) strLine += _T(";"); // owner ::MakeIPAddress(ws.dwIpAdd[i++], strTemp); // actual address ::MakeIPAddress(ws.dwIpAdd[i], strTemp2); strTemp2 += _T(" - "); strTemp2 += strTemp; strLine += strTemp2; } } strLine += strDelim; // active status GetStateString(ws.dwState, strTemp); strLine += strTemp; strLine += strDelim; // static flag if (ws.dwState & WINSDB_REC_STATIC) strTemp.LoadString(IDS_ACTIVEREG_STATIC); else strTemp = _T(""); strLine += strTemp; strLine += strDelim; // version GetVersionInfo(ws.liVersion.LowPart, ws.liVersion.HighPart, strTemp); strLine += strTemp; strLine += strDelim; // expiration time if (ws.dwExpiration == INFINITE_EXPIRATION) { Verify(strTemp.LoadString(IDS_INFINITE)); } else { strTemp = TMST(ws.dwExpiration); } strLine += strTemp; strLine += strNewLine; strContent += strLine; //optimize // write to the file for every 1000 records converted if ( i % 1000 == 0) { cFileExp.Write(strContent, strContent.GetLength() * (sizeof(TCHAR)) ); cFileExp.SeekToEnd(); // clear all the strings now strContent.Empty(); } } // write to the file cFileExp.Write(strContent, strContent.GetLength() * (sizeof(TCHAR)) ); cFileExp.Close(); #ifdef DEBUG timeFinish = CTime::GetCurrentTime(); CTimeSpan timeDelta = timeFinish - timeStart; CString strTempTime = timeDelta.Format(_T("%H:%M:%S")); Trace2("WINS DB - Export Entries: %d records read, total time %s\n", i, strTempTime); #endif END_WAIT_CURSOR } COM_PROTECT_CATCH CString strDisp; AfxFormatString1(strDisp, IDS_EXPORT_SUCCESS, strFileName); AfxMessageBox(strDisp, MB_ICONINFORMATION ); return hr; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::BuildOwnerArray(ITFSNode *pNode) Builds the list of owners in the server Author: v-shubk ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::BuildOwnerArray(handle_t hBinding) { HRESULT hr = hrOK; DWORD err = 0; CWinsResults winsResults; err = winsResults.Update(hBinding); if (err == ERROR_SUCCESS) { m_pServerInfoArray->RemoveAll(); LARGE_INTEGER liVersion; DWORD dwIP; CString strName; BOOL fGetHostName = TRUE; for (int i = 0; i < winsResults.AddVersMaps.GetSize(); i++) { liVersion = winsResults.AddVersMaps[i].VersNo; dwIP = winsResults.AddVersMaps[i].Add.IPAdd; CServerInfo serverInfo(dwIP, strName, liVersion); int nIndex = (int)m_pServerInfoArray->Add(serverInfo); } } return HRESULT_FROM_WIN32(err); } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::OnCheckRegNames(ITFSNode* pNode) Command Handler for Check Registered names Author: v-shubk ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::OnCheckRegNames(ITFSNode* pNode) { HRESULT hr = hrOK; CCheckRegNames dlgRegName; if (IDOK != dlgRegName.DoModal()) { return hr; } CCheckNamesProgress dlgCheckNames; dlgCheckNames.m_strNameArray.Copy(dlgRegName.m_strNameArray); dlgCheckNames.m_strServerArray.Copy(dlgRegName.m_strServerArray); dlgCheckNames.m_fVerifyWithPartners = dlgRegName.m_fVerifyWithPartners; dlgCheckNames.DoModal(); return hr; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::OnDeleteOwner(ITFSNode* pNode) Command Handler for Tombstone all records Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::OnDeleteOwner(ITFSNode* pNode) { HRESULT hr = hrOK; CDeleteOwner dlgDeleteOwner(pNode); DWORD dwErr, dwIp; CString strText, strIp; if (dlgDeleteOwner.DoModal() == IDOK) { BEGIN_WAIT_CURSOR if (dlgDeleteOwner.m_fDeleteRecords) { SPITFSNode spServerNode; pNode->GetParent(&spServerNode); CWinsServerHandler * pServer = GETHANDLER(CWinsServerHandler, spServerNode); dwErr = pServer->DeleteWinsServer(dlgDeleteOwner.m_dwSelectedOwner); if (dwErr == ERROR_SUCCESS) { // remove from list for (int i = 0; i < m_pServerInfoArray->GetSize(); i++) { if (m_pServerInfoArray->GetAt(i).m_dwIp == dlgDeleteOwner.m_dwSelectedOwner) { m_pServerInfoArray->RemoveAt(i); break; } } } } else { dwErr = TombstoneAllRecords(dlgDeleteOwner.m_dwSelectedOwner, pNode); } END_WAIT_CURSOR if (dwErr != ERROR_SUCCESS) { WinsMessageBox(dwErr); } // TODO trigger an update of whatever is in the active registrations result pane } return hr; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::AppendScopeName(char* lpName, char* lpScopeAppended) Appends the scope name to the record name, when there isa scope name attached to the record ---------------------------------------------------------------------------*/ void CActiveRegistrationsHandler::AppendScopeName(char* lpName, char* lpScopeAppended) { strcpy(lpScopeAppended, lpName); char szTemp[MAX_PATH]; CString strScope = _T(".") + m_strStaticMappingScope; // INTL$ Should the scope name be OEM as well? WideToMBCS(strScope, szTemp, WINS_NAME_CODE_PAGE, WC_COMPOSITECHECK); strcat(lpScopeAppended, szTemp); } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::TombstoneRecords() Handles Tomsstoning of records Author: v-shubk ---------------------------------------------------------------------------*/ DWORD CActiveRegistrationsHandler::TombstoneRecords ( ITFSComponent * pComponent, WinsRecord * pws ) { DWORD err = ERROR_SUCCESS; // get the server node to retrive the handle for the WINS api SPITFSNode spNode; pComponent->GetSelectedNode(&spNode); SPITFSNode spParentNode; spNode->GetParent(&spParentNode); CWinsServerHandler* pServer = GETHANDLER(CWinsServerHandler, spParentNode); WINSINTF_VERS_NO_T MinVersNo; WINSINTF_VERS_NO_T MaxVersNo; MinVersNo = pws->liVersion; MaxVersNo = MinVersNo; // gotta get the owner of this record WINSINTF_RECORD_ACTION_T recAction; WINSINTF_RECORD_ACTION_T * precAction = &recAction; ZeroMemory(&recAction, sizeof(recAction)); BYTE * pName = (BYTE*) WinsAllocMem(pws->dwNameLen + 1); if (pName == NULL) { return ERROR_OUTOFMEMORY; } memset(pName, 0, pws->dwNameLen + 1); memcpy(pName, pws->szRecordName, pws->dwNameLen); recAction.pName = pName; recAction.Cmd_e = WINSINTF_E_QUERY; recAction.TypOfRec_e = HIWORD(pws->dwType); recAction.fStatic = (pws->dwState & WINSDB_REC_STATIC) ? TRUE : FALSE; recAction.pAdd = NULL; recAction.NoOfAdds = 0; recAction.NameLen = pws->dwNameLen; // get the OwnerId for the mapping // have to do this because the OwnerId in the raw data is bogus #ifdef WINS_CLIENT_APIS err = ::WinsRecordAction(pServer->GetBinding(), &precAction); #else err = ::WinsRecordAction(&precAction); #endif WINS_CLIENT_APIS WinsFreeMem(pName); if (err != WINSINTF_SUCCESS ) { return err; } WINSINTF_ADD_T WinsAdd; WinsAdd.Len = 4; WinsAdd.Type = 0; //WinsAdd.IPAdd = m_dwArrayOwner[precAction->OwnerId]; WinsAdd.IPAdd = (*m_pServerInfoArray)[precAction->OwnerId].m_dwIp; #ifdef WINS_CLIENT_APIS err = ::WinsTombstoneDbRecs(pServer->GetBinding(), &WinsAdd, MinVersNo, MaxVersNo); #else err = ::WinsTombstoneDbRecs(&WinsAdd, MinVersNo, MaxVersNo); #endif return err; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::TombstoneAllRecords() Tombstones all records owned by this server Author: EricDav ---------------------------------------------------------------------------*/ DWORD CActiveRegistrationsHandler::TombstoneAllRecords(DWORD dwServerIpAddress, ITFSNode * pNode) { WINSINTF_VERS_NO_T MinVersNo; WINSINTF_VERS_NO_T MaxVersNo; WINSINTF_ADD_T WinsAdd; SPITFSNode spParentNode; pNode->GetParent(&spParentNode); CWinsServerHandler * pServer = GETHANDLER(CWinsServerHandler, spParentNode); DWORD err; CWinsResults winsResults; err = winsResults.Update(pServer->GetBinding()); if (err != ERROR_SUCCESS) return err; MinVersNo.QuadPart = 0; for (UINT i = 0; i < winsResults.NoOfOwners; i++) { if (winsResults.AddVersMaps[i].Add.IPAdd == dwServerIpAddress) { MaxVersNo.QuadPart = winsResults.AddVersMaps[i].VersNo.QuadPart; break; } } // build the IP address WinsAdd.Len = 4; WinsAdd.Type = 0; WinsAdd.IPAdd = dwServerIpAddress; #ifdef WINS_CLIENT_APIS err = ::WinsTombstoneDbRecs(pServer->GetBinding(), &WinsAdd, MinVersNo, MaxVersNo); #else err = ::WinsTombstoneDbRecs(&WinsAdd, MinVersNo, MaxVersNo); #endif return err; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::UpdateRecord(ITFSComponent *pComponent, WinsRecord *pws, int nDelIndex) Called to update the record on the result pane when a records has been tombstoned Author: v-shubk ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::UpdateRecord(ITFSComponent *pComponent, WinsRecord *pws, int nDelIndex) { HRESULT hr = hrOK; WINSINTF_RECORD_ACTION_T RecAction; PWINSINTF_RECORD_ACTION_T pRecAction; PWINSINTF_RECORD_ACTION_T pRecActionRet; DWORD dwStatus = ERROR_SUCCESS; int nLen; BYTE bLast; SPITFSNode spNode; SPITFSNode spParentNode; WinsRecord wsNew; HROW hrowDel; pComponent->GetSelectedNode(&spNode); // get it's parent, which happens to be the server node spNode->GetParent(&spParentNode); // get the pointer to the server handler CWinsServerHandler *pServer = GETHANDLER(CWinsServerHandler, spParentNode); ZeroMemory(&RecAction, sizeof(RecAction)); // form the PWINSINTFrecord from the info in WinsRecord //RecAction.TypOfRec_e = nType; RecAction.Cmd_e = WINSINTF_E_QUERY; RecAction.pAdd = NULL; RecAction.pName = NULL; RecAction.NoOfAdds = 0; RecAction.NameLen = nLen = pws->dwNameLen; bLast = LOBYTE(LOWORD(pws->dwType)); pRecAction = &RecAction; RecAction.pName = (LPBYTE)::WinsAllocMem(nLen + 1); if (RecAction.pName == NULL) { return ERROR_NOT_ENOUGH_MEMORY; } // copy the name memset(pRecAction->pName, 0, nLen + 1); (void)memcpy(pRecAction->pName, pws->szRecordName, nLen); // now query for this particular record pRecActionRet = QueryForName(spNode, pRecAction); // if the function is successful, update the listbox if (pRecActionRet != NULL) { // convert PWinsINTF record to WinsRecord so that it can be added to the local storage WinsIntfToWinsRecord(pRecActionRet, wsNew); if (pRecActionRet->OwnerId < (UINT) m_pServerInfoArray->GetSize()) wsNew.dwOwner = (*m_pServerInfoArray)[pRecActionRet->OwnerId].m_dwIp; free(pRecActionRet->pName); // delete this particular record and add it back again to the local storage CORg(m_pCurrentDatabase->GetHRow(nDelIndex, &hrowDel)); CORg(m_pCurrentDatabase->DeleteRecord(hrowDel)); // add it to database m_pCurrentDatabase->AddRecord(&wsNew); } Error: if (RecAction.pName) { WinsFreeMem(RecAction.pName); } return hr; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::RefreshResults(ITFSNode *pNode) Refreshes the result pane of the active registrations node ---------------------------------------------------------------------------*/ HRESULT CActiveRegistrationsHandler::RefreshResults(ITFSNode *pNode) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); HRESULT hr = hrOK; SPITFSNode spNode; SPITFSNodeHandler spHandler; ITFSQueryObject * pQuery = NULL; SPITFSNode spServerNode; DWORD dwIP; CString strIP ; CWinsServerHandler* pServer = NULL; CString strMachineName; int nCount, pos; // if being loaded if (m_spWinsDatabase) { CORg (m_spWinsDatabase->Stop()); DatabaseLoadingCleanup(); UpdateListboxCount(pNode); } pNode->GetParent(&spServerNode); pServer = GETHANDLER(CWinsServerHandler, spServerNode); Lock(); strMachineName = _T("\\\\") + pServer->GetServerAddress(); dwIP = pServer->GetServerIP(); MakeIPAddress(dwIP, strIP); if (!m_spWinsDatabase) { CORg(CreateWinsDatabase(strIP, strIP, &m_spWinsDatabase)); } m_spWinsDatabase->SetApiInfo( m_dlgLoadRecords.m_pageOwners.GetOwnerForApi(), m_dlgLoadRecords.m_pageIpAddress.GetNameForApi(), m_dlgLoadRecords.m_bEnableCache); // start loading records CORg (m_spWinsDatabase->Init()); UpdateCurrentView(pNode); // update our internal state m_winsdbState = WINSDB_LOADING; // update the node's icon OnChangeState(pNode); // kick off the background thread to do the timer updates pQuery = OnCreateQuery(pNode); Assert(pQuery); Verify(StartBackgroundThread(pNode, m_spTFSCompData->GetHiddenWnd(), pQuery)); pQuery->Release(); // fill in any record type filter information nCount = (int)m_dlgLoadRecords.m_pageTypes.m_arrayTypeFilter.GetSize(); m_spWinsDatabase->ClearFilter(WINSDB_FILTER_BY_TYPE); for (pos = 0; pos < nCount; pos++) { m_spWinsDatabase->AddFilter(WINSDB_FILTER_BY_TYPE, m_dlgLoadRecords.m_pageTypes.m_arrayTypeFilter[pos].dwType, m_dlgLoadRecords.m_pageTypes.m_arrayTypeFilter[pos].fShow, NULL); } // fill in any owner filter information nCount = (int)m_dlgLoadRecords.m_pageOwners.m_dwaOwnerFilter.GetSize(); m_spWinsDatabase->ClearFilter(WINSDB_FILTER_BY_OWNER); for (pos = 0; pos < nCount; pos++) { m_spWinsDatabase->AddFilter(WINSDB_FILTER_BY_OWNER, m_dlgLoadRecords.m_pageOwners.m_dwaOwnerFilter[pos], 0, NULL); } // fill in any ip address filter information m_spWinsDatabase->ClearFilter(WINSDB_FILTER_BY_IPADDR); if (m_dlgLoadRecords.m_pageIpAddress.m_bFilterIpAddr) { nCount = (int)m_dlgLoadRecords.m_pageIpAddress.m_dwaIPAddrs.GetSize(); for (pos = 0; pos < nCount; pos++) { m_spWinsDatabase->AddFilter(WINSDB_FILTER_BY_IPADDR, m_dlgLoadRecords.m_pageIpAddress.m_dwaIPAddrs[pos], m_dlgLoadRecords.m_pageIpAddress.GetIPMaskForFilter(pos), NULL); } } // fill in any name filter information m_spWinsDatabase->ClearFilter(WINSDB_FILTER_BY_NAME); if (m_dlgLoadRecords.m_pageIpAddress.m_bFilterName) { m_spWinsDatabase->AddFilter(WINSDB_FILTER_BY_NAME, m_dlgLoadRecords.m_pageIpAddress.m_bMatchCase, 0, m_dlgLoadRecords.m_pageIpAddress.m_strName); } // start loading records CORg (m_spWinsDatabase->Start()); BEGIN_WAIT_CURSOR // filter any records that may have been downloaded before we set the // filter information (in the case when we had to reload the database). // any records that come in after we set the // filter info will be filtered correctly. m_spWinsDatabase->FilterRecords(WINSDB_FILTER_BY_TYPE, 0,0); END_WAIT_CURSOR // do the initial update of the virutal listbox OnHaveData(pNode, 0, QDATA_TIMER); COM_PROTECT_ERROR_LABEL; return hr; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::GetRecordOwner() Gets the owner IP Address for a given record Author: EricDav ---------------------------------------------------------------------------*/ BOOL CActiveRegistrationsHandler::GetRecordOwner(ITFSNode * pNode, WinsRecord * pWinsRecord) { BOOL fSuccess = TRUE; SPITFSNode spServerNode; pNode->GetParent(&spServerNode); CWinsServerHandler * pServer = GETHANDLER(CWinsServerHandler, spServerNode); CConfiguration config = pServer->GetConfig(); if (!config.FSupportsOwnerId()) { // query the server for correct info WINSINTF_RECORD_ACTION_T RecAction; ZeroMemory(&RecAction, sizeof(RecAction)); // // Must have at least enough room for 256 character string, // includes the scope name too // RecAction.pName = (LPBYTE)::WinsAllocMem(257); if (RecAction.pName == NULL) { //return ERROR_NOT_ENOUGH_MEMORY; Trace0("GetRecordOwner - WinsAllocMemFailed!!\n"); return FALSE; } // fill in the record action struct ::memset(RecAction.pName, 0, 257); ::memcpy((char *)RecAction.pName, (LPCSTR) pWinsRecord->szRecordName, pWinsRecord->dwNameLen); RecAction.NameLen = strlen((char *) RecAction.pName); // for name records of type 0x00 or records that somehow have a NULL in the name // strlen will return an invalid string length. So, if the length < 16 then set // the length to 16. // name lengths with scopes will calculate correctly. if (RecAction.NameLen < 0x10) { RecAction.NameLen = 0x10; } BOOL fStatic = (pWinsRecord->dwState & WINSDB_REC_STATIC) ? TRUE : FALSE; // now query for the name PWINSINTF_RECORD_ACTION_T pRecActionResult = QueryForName(pNode, &RecAction, fStatic); if (pRecActionResult) { free(pRecActionResult->pName); } else { pWinsRecord->dwOwner = INVALID_OWNER_ID; } } return fSuccess; } /*--------------------------------------------------------------------------- CActiveRegistrationsHandler::GetOwnerInfo() Gets the owner info array Author: EricDav ---------------------------------------------------------------------------*/ void CActiveRegistrationsHandler::GetOwnerInfo(CServerInfoArray & serverInfoArray) { serverInfoArray.RemoveAll(); serverInfoArray.Copy(*m_pServerInfoArray); } void CActiveRegistrationsHandler::SetLoadedOnce(ITFSNode * pNode) { if (m_fLoadedOnce) return; m_fLoadedOnce = TRUE; // clear the result pane message ClearMessage(pNode); }