///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // // CServerNode // ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include #include // Access to Snapin #include "pop3.h" #include "pop3snap.h" // Access to Nodes we use #include "ServerNode.h" #include "DomainNode.h" // Access to dialogs we'll display #include "NewDomainDlg.h" #include "ServerProp.h" static const GUID CServerNodeGUID_NODETYPE = { 0x4c30b06c, 0x1dc3, 0x4c0d, { 0x87, 0xb4, 0x64, 0xbf, 0xe8, 0x22, 0xf4, 0x50 } }; const GUID* CServerNode::m_NODETYPE = &CServerNodeGUID_NODETYPE; const OLECHAR* CServerNode::m_SZNODETYPE = OLESTR("4C30B06C-1DC3-4c0d-87B4-64BFE822F450"); const OLECHAR* CServerNode::m_SZDISPLAY_NAME = OLESTR(""); const CLSID* CServerNode::m_SNAPIN_CLASSID = &CLSID_POP3ServerSnap; ///////////////////////////////////////////////////////////////////////// // // Class implementation // ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// // CServerNode::CServerNode // // Constructor : Uses servername for remote Servers CServerNode::CServerNode(BSTR strServerName, CRootNode* pParent, BOOL bLocalServer) : m_lRefCount(1), m_hrValidServer(S_OK), m_bstrAuthentication(_T("")), m_bstrMailRoot(_T("")), m_bstrPort(_T("")), m_bstrLogLevel(_T("")), m_bstrServiceStatus(_T("")) { // Initialize our Scope item memset( &m_scopeDataItem, 0, sizeof(m_scopeDataItem) ); m_scopeDataItem.mask = SDI_STR | SDI_IMAGE | SDI_OPENIMAGE | SDI_PARAM; m_scopeDataItem.displayname = MMC_CALLBACK; m_scopeDataItem.nImage = 0; m_scopeDataItem.nOpenImage = 0; m_scopeDataItem.lParam = (LPARAM) this; // Initialize our Result item memset( &m_resultDataItem, 0, sizeof(m_resultDataItem) ); m_resultDataItem.mask = RDI_STR | RDI_IMAGE | RDI_PARAM; m_resultDataItem.str = MMC_CALLBACK; m_resultDataItem.nImage = 0; m_resultDataItem.lParam = (LPARAM) this; if( bLocalServer ) { // We are the local server for now. TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH+1] = {0}; DWORD dwBuffer = MAX_COMPUTERNAME_LENGTH+1; if( GetComputerName(szComputerName, &dwBuffer) ) { m_bstrDisplayName = szComputerName; } else { #if DBG m_bstrDisplayName = CComBSTR("Local Server"); #else m_bstrDisplayName = CComBSTR(""); #endif } } // Get Parent Information m_pParent = pParent; // Open our Pop3 Admin Interface and store it HRESULT hr = CoCreateInstance(__uuidof(P3Config), NULL, CLSCTX_ALL, __uuidof(IP3Config), (LPVOID*)&m_spConfig); if( FAILED(hr) || !m_spConfig ) { m_hrValidServer = FAILED(hr) ? hr : E_FAIL; return; } if( !bLocalServer ) { // Configure our remote computer setup m_bstrDisplayName = strServerName; hr = m_spConfig->put_MachineName( strServerName ); if( FAILED(hr) ) { // Invalid Server Name! m_hrValidServer = hr; return; } } // Do our User creation property DWORD dwValue = 0; RegQueryCreateUser( dwValue, m_bstrDisplayName ); m_bCreateUser = dwValue; } ///////////////////////////////////////////////////////////////////////// // CServerNode::~CServerNode // // Destructor : Make sure to clean up our member-list CServerNode::~CServerNode() { for(DOMAINLIST::iterator iter = m_lDomains.begin(); iter != m_lDomains.end(); iter++) { delete (*iter); } m_lDomains.clear(); } ///////////////////////////////////////////////////////////////////////// // CServerNode::DeleteDomain // // Helper function to delete a child domain from all of POP3 HRESULT CServerNode::DeleteDomain(CDomainNode* pDomainNode) { if( !pDomainNode ) return E_INVALIDARG; if( !m_spConfig ) return E_FAIL; // Delete from POP3 Admin Interface CComPtr spDomains; HRESULT hr = m_spConfig->get_Domains( &spDomains ); // Update the P3Admin Interface if( SUCCEEDED(hr) ) { hr = spDomains->Remove( pDomainNode->m_bstrDisplayName ); } // Update our list if( SUCCEEDED(hr) ) { m_lDomains.remove(pDomainNode); } return hr; } ///////////////////////////////////////////////////////////////////////// // CServerNode::OnExpand // // Helper function to refresh list of domains and insert them HRESULT CServerNode::OnExpand(BOOL bExpand, HSCOPEITEM hScopeItem, IConsole* pConsole) { if( !hScopeItem || !pConsole ) return E_INVALIDARG; if( !m_spConfig ) return E_FAIL; HRESULT hr = S_OK; CComQIPtr spConsoleNameSpace = pConsole; if( !spConsoleNameSpace ) return E_NOINTERFACE; // If we have any children, delete them all from the namespace HSCOPEITEM hChild = NULL; MMC_COOKIE cookie = 0; hr = spConsoleNameSpace->GetChildItem(m_scopeDataItem.ID, &hChild, &cookie); if( SUCCEEDED(hr) && hChild ) { hr = spConsoleNameSpace->DeleteItem(m_scopeDataItem.ID, FALSE); } if( SUCCEEDED(hr) ) { // then delete all of our member-list of domains for(DOMAINLIST::iterator iter = m_lDomains.begin(); iter != m_lDomains.end(); iter++) { delete (*iter); } m_lDomains.clear(); } if( FAILED(hr) || !bExpand ) { // Error, or we are Contracting return S_OK; } // Expanding // Fill in our list of domains CComPtr spDomains; CComPtr spDomainEnum; // Get the Domains hr = m_spConfig->get_Domains( &spDomains ); // Get an Enumerator for the Domains if( SUCCEEDED(hr) ) { hr = spDomains->get__NewEnum( &spDomainEnum ); } // Loop through the domains, and add each new domain if( SUCCEEDED(hr) ) { CComVariant var; ULONG lResult = 0; VariantInit( &var ); while ( spDomainEnum->Next(1, &var, &lResult) == S_OK ) { if ( lResult == 1 ) { CComQIPtr spDomain; spDomain = V_DISPATCH(&var); CDomainNode* spDomainNode = new CDomainNode(spDomain, this); if( spDomainNode ) { m_lDomains.push_back(spDomainNode); } } VariantClear(&var); } } if( SUCCEEDED(hr) ) { for(DOMAINLIST::iterator iter = m_lDomains.begin(); iter != m_lDomains.end(); iter++) { CDomainNode* pDomain = *iter; pDomain->m_scopeDataItem.mask |= SDI_PARENT; pDomain->m_scopeDataItem.relativeID = m_scopeDataItem.ID; hr = spConsoleNameSpace->InsertItem( &(pDomain->m_scopeDataItem) ); if( FAILED(hr) ) return hr; } } if( SUCCEEDED(hr) ) { CComQIPtr spCons2 = pConsole; if( spCons2 ) { // Output the number of servers we added tstring strMessage = StrLoadString(IDS_SERVER_STATUSBAR); OLECHAR pszStatus[1024] = {0}; _sntprintf( pszStatus, 1023, strMessage.c_str(), m_lDomains.size() ); spCons2->SetStatusText( pszStatus ); } } return hr; } ///////////////////////////////////////////////////////////////////////// // // SnapInItemImpl // ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// // CServerNode::GetScopePaneInfo // // Callback used to get Scope-Pane display information by MMC HRESULT CServerNode::GetScopePaneInfo(SCOPEDATAITEM *pScopeDataItem) { if( !pScopeDataItem ) return E_INVALIDARG; if( pScopeDataItem->mask & SDI_STR ) pScopeDataItem->displayname = m_bstrDisplayName; if( pScopeDataItem->mask & SDI_IMAGE ) pScopeDataItem->nImage = m_scopeDataItem.nImage; if( pScopeDataItem->mask & SDI_OPENIMAGE ) pScopeDataItem->nOpenImage = m_scopeDataItem.nOpenImage; if( pScopeDataItem->mask & SDI_PARAM ) pScopeDataItem->lParam = m_scopeDataItem.lParam; if( pScopeDataItem->mask & SDI_STATE ) pScopeDataItem->nState = m_scopeDataItem.nState; return S_OK; } ///////////////////////////////////////////////////////////////////////// // CServerNode::GetResultPaneInfo // // Callback used to get Result Pane display information by MMC HRESULT CServerNode::GetResultPaneInfo(RESULTDATAITEM *pResultDataItem) { if( !pResultDataItem ) return E_INVALIDARG; if( pResultDataItem->bScopeItem ) { if( pResultDataItem->mask & RDI_STR ) pResultDataItem->str = GetResultPaneColInfo(pResultDataItem->nCol); if( pResultDataItem->mask & RDI_IMAGE ) pResultDataItem->nImage = m_scopeDataItem.nImage; if( pResultDataItem->mask & RDI_PARAM ) pResultDataItem->lParam = m_scopeDataItem.lParam; return S_OK; } if( pResultDataItem->mask & RDI_STR ) pResultDataItem->str = GetResultPaneColInfo(pResultDataItem->nCol); if( pResultDataItem->mask & RDI_IMAGE ) pResultDataItem->nImage = m_resultDataItem.nImage; if( pResultDataItem->mask & RDI_PARAM ) pResultDataItem->lParam = m_resultDataItem.lParam; if( pResultDataItem->mask & RDI_INDEX ) pResultDataItem->nIndex = m_resultDataItem.nIndex; return S_OK; } ///////////////////////////////////////////////////////////////////////// // CServerNode::GetResultPaneColInfo // // Helper function used as part of the GetResultPaneInfo. This function // will supply the text for the different columns. LPOLESTR CServerNode::GetResultPaneColInfo(int nCol) { if( !m_spConfig ) return L""; switch( nCol ) { case 0: // Name { return m_bstrDisplayName; } case 1: // Authentication Type { CComPtr spMethods; CComPtr spAuth; CComVariant var; HRESULT hr = m_spConfig->get_Authentication( &spMethods ); if( SUCCEEDED(hr) ) { hr = spMethods->get_CurrentAuthMethod( &var ); } if( SUCCEEDED(hr) ) { hr = spMethods->get_Item( var, &spAuth ); } if( SUCCEEDED(hr) ) { hr = spAuth->get_Name( &m_bstrAuthentication ); } if( FAILED(hr) ) { #if DBG m_bstrAuthentication = _T("Unknown"); #else m_bstrAuthentication = _T(""); #endif } return m_bstrAuthentication; } case 2: // Root Mail Directory { HRESULT hr = m_spConfig->get_MailRoot( &m_bstrMailRoot ); if( FAILED(hr) ) { #if DBG m_bstrMailRoot = _T("Unknown"); #else m_bstrMailRoot = _T(""); #endif } return m_bstrMailRoot; } case 3: // Port { long lPort = 0; CComPtr spService; HRESULT hr = m_spConfig->get_Service( &spService ); if( SUCCEEDED(hr) ) { hr = spService->get_Port( &lPort ); if( FAILED(hr) ) { lPort = 0; } } // 1K buffer: Not likely we'll exceed that many digits TCHAR szNum[1024] = {0}; _sntprintf( szNum, 1023, _T("%d"), lPort ); m_bstrPort = szNum; return m_bstrPort; } case 4: // Logging Level { long lLevel = 0; HRESULT hr = m_spConfig->get_LoggingLevel( &lLevel ); switch( lLevel ) { case 0: { m_bstrLogLevel = StrLoadString(IDS_SERVERPROP_LOG_0).c_str(); break; } case 1: { m_bstrLogLevel = StrLoadString(IDS_SERVERPROP_LOG_1).c_str(); break; } case 2: { m_bstrLogLevel = StrLoadString(IDS_SERVERPROP_LOG_2).c_str(); break; } case 3: { m_bstrLogLevel = StrLoadString(IDS_SERVERPROP_LOG_3).c_str(); break; } default: { m_bstrLogLevel = StrLoadString(IDS_SERVERPROP_LOG_0).c_str(); break; } } return m_bstrLogLevel; } case 5: // Service Status { CComPtr spService = NULL; long lServiceStatus = 0; HRESULT hr = m_spConfig->get_Service( &spService ); if( SUCCEEDED(hr) ) { hr = spService->get_POP3ServiceStatus( &lServiceStatus ); } switch( lServiceStatus ) { case SERVICE_STOPPED: { m_bstrServiceStatus = StrLoadString(IDS_STATE_STOPPED).c_str(); break; } case SERVICE_RUNNING: { m_bstrServiceStatus = StrLoadString(IDS_STATE_RUNNING).c_str(); break; } case SERVICE_PAUSED: { m_bstrServiceStatus = StrLoadString(IDS_STATE_PAUSED).c_str(); break; } default: { m_bstrServiceStatus = StrLoadString(IDS_STATE_PENDING).c_str(); break; } } return m_bstrServiceStatus; } default: { #if DBG return L"No Information"; #else return L""; #endif } } } ///////////////////////////////////////////////////////////////////////// // CServerNode::GetResultViewType // // Sets the Result Pane to be: // 0 Domains : Message View // Non-0 Domains : List View HRESULT CServerNode::GetResultViewType( LPOLESTR* ppViewType, long* pViewOptions ) { // Get the Count of Domains CComPtr spDomains = NULL; long lDomains = 0; // Get the Domains HRESULT hr = m_spConfig->get_Domains( &spDomains ); if( SUCCEEDED(hr) ) { spDomains->get_Count( &lDomains ); } if( lDomains == 0 ) { // Message View return StringFromCLSID(CLSID_MessageView, ppViewType); } return S_FALSE; // Default List View } ///////////////////////////////////////////////////////////////////////// // CServerNode::Notify // // Core callback functionality of this Node. MMC will use this function // for all MMC provided functionality, such as Expanding, Renaming, and // Context Help HRESULT CServerNode::Notify( MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param, IComponentData* pComponentData, IComponent* pComponent, DATA_OBJECT_TYPES type) { HRESULT hr = S_FALSE; _ASSERTE(pComponentData != NULL || pComponent != NULL); CComPtr spConsole = NULL; if( pComponentData ) { spConsole = ((CPOP3ServerSnapData*)pComponentData)->m_spConsole; } else if( pComponent ) { spConsole = ((CPOP3ServerSnapComponent*)pComponent)->m_spConsole; } if( !spConsole ) return E_INVALIDARG; switch( event ) { case MMCN_SHOW: { tstring strHeader; CComQIPtr spHeaderCtrl = spConsole; CComQIPtr spResultData = spConsole; if( !spHeaderCtrl || !spResultData ) return E_NOINTERFACE; hr = spResultData->DeleteAllRsltItems(); if( arg ) { if( m_lDomains.empty() ) { // configure the ocx message in the result pane IMessageView* pIMessageView = NULL; LPUNKNOWN pIUnk = NULL; hr = spConsole->QueryResultView(&pIUnk); if( SUCCEEDED(hr) ) { hr = pIUnk->QueryInterface(_uuidof(IMessageView), reinterpret_cast(&pIMessageView)); } if( SUCCEEDED(hr) ) { hr = pIMessageView->SetIcon(Icon_Information); } if( SUCCEEDED(hr) ) { tstring strTitle = StrLoadString( IDS_SNAPINNAME ); hr = pIMessageView->SetTitleText( strTitle.c_str() ); } if( SUCCEEDED(hr) ) { tstring strMessage = StrLoadString( IDS_ERROR_NODOMAIN ); hr = pIMessageView->SetBodyText( strMessage.c_str() ); } if( pIMessageView ) { pIMessageView->Release(); pIMessageView = NULL; } if( pIUnk ) { pIUnk->Release(); pIUnk = NULL; } return hr; } else { if( SUCCEEDED(hr) ) { strHeader = StrLoadString(IDS_HEADER_DOMAIN_NAME); hr = spHeaderCtrl->InsertColumn(0, strHeader.c_str(), LVCFMT_LEFT, 100); } if( SUCCEEDED(hr) ) { strHeader = StrLoadString(IDS_HEADER_DOMAIN_NUMBOX); hr = spHeaderCtrl->InsertColumn(1, strHeader.c_str(), LVCFMT_LEFT, 100); } if( SUCCEEDED(hr) ) { strHeader = StrLoadString(IDS_HEADER_DOMAIN_SIZE); hr = spHeaderCtrl->InsertColumn(2, strHeader.c_str(), LVCFMT_LEFT, 100); } if( SUCCEEDED(hr) ) { strHeader = StrLoadString(IDS_HEADER_DOMAIN_NUMMES); hr = spHeaderCtrl->InsertColumn(3, strHeader.c_str(), LVCFMT_LEFT, 100); } if( SUCCEEDED(hr) ) { strHeader = StrLoadString(IDS_HEADER_DOMAIN_LOCKED); hr = spHeaderCtrl->InsertColumn(4, strHeader.c_str(), LVCFMT_LEFT, 100); } if( SUCCEEDED(hr) ) { CComQIPtr spCons2 = spConsole; if( spCons2 ) { // Output the number of servers we added tstring strMessage = StrLoadString(IDS_SERVER_STATUSBAR); OLECHAR pszStatus[1024] = {0}; _sntprintf( pszStatus, 1023, strMessage.c_str(), m_lDomains.size() ); spCons2->SetStatusText( pszStatus ); } } } } break; } case MMCN_EXPAND: { hr = OnExpand(arg, m_scopeDataItem.ID, spConsole); break; } case MMCN_ADD_IMAGES: { IImageList* pImageList = (IImageList*)arg; if( !pImageList ) return E_INVALIDARG; hr = LoadImages(pImageList); break; } case MMCN_REFRESH: { hr = OnExpand(TRUE, m_scopeDataItem.ID, spConsole); if( SUCCEEDED(hr) ) { CComQIPtr spCons2 = spConsole; if( spCons2 ) { // Output the number of servers we added tstring strMessage = StrLoadString(IDS_SERVER_STATUSBAR); OLECHAR pszStatus[1024] = {0}; _sntprintf( pszStatus, 1023, strMessage.c_str(), m_lDomains.size() ); spCons2->SetStatusText( pszStatus ); } } break; } case MMCN_SELECT: { // if selecting node if( HIWORD(arg) ) { hr = S_OK; // get the verb interface and enable rename CComPtr spConsVerb; if( spConsole->QueryConsoleVerb(&spConsVerb) == S_OK ) { // Enable the Properties Menu hr = spConsVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, TRUE); if( FAILED(hr) ) return hr; hr = spConsVerb->SetVerbState(MMC_VERB_PROPERTIES, HIDDEN, FALSE); if( FAILED(hr) ) return hr; // Enable the Refresh Menu hr = spConsVerb->SetVerbState(MMC_VERB_REFRESH, ENABLED, TRUE); if( FAILED(hr) ) return hr; hr = spConsVerb->SetVerbState(MMC_VERB_REFRESH, HIDDEN, FALSE); if( FAILED(hr) ) return hr; } } break; } case MMCN_VIEW_CHANGE: { if( (param == NAV_ADD) || (param == NAV_DELETE) ) { CComQIPtr spCons2 = spConsole; if( spCons2 ) { hr = spCons2->SelectScopeItem( m_scopeDataItem.ID ); } } break; } case MMCN_CONTEXTHELP: { hr = S_OK; TCHAR szWindowsDir[MAX_PATH+1] = {0}; tstring strHelpFile = _T(""); tstring strHelpFileName = StrLoadString(IDS_HELPFILE); tstring strHelpTopicName = StrLoadString(IDS_HELPTOPIC); if( strHelpFileName.empty() || strHelpTopicName.empty() ) { return E_FAIL; } // Build path to d:\windows\help UINT nSize = GetSystemWindowsDirectory( szWindowsDir, MAX_PATH ); if( nSize == 0 || nSize > MAX_PATH ) { return E_FAIL; } strHelpFile = szWindowsDir; // D:\windows strHelpFile += _T("\\Help\\"); // \help strHelpFile += strHelpFileName; // \filename.chm strHelpFile += _T("::/"); // ::/ strHelpFile += strHelpTopicName; // index.htm // Show the Help topic CComQIPtr spHelp = spConsole; if( !spHelp ) return E_NOINTERFACE; hr = spHelp->ShowTopic( (LPTSTR)strHelpFile.c_str() ); break; } }// switch return hr; } ///////////////////////////////////////////////////////////////////////// // // ContextMenuImpl // ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// // CServerNode::AddMenuItems // // Adds our context menus into the appropriate MMC provided menu // locations. HRESULT CServerNode::AddMenuItems(LPCONTEXTMENUCALLBACK piCallback, long* pInsertionAllowed, DATA_OBJECT_TYPES type ) { if( !piCallback || !pInsertionAllowed ) return E_INVALIDARG; if( !m_spConfig ) return E_FAIL; HRESULT hr = S_OK; tstring strMenu = _T(""); tstring strDesc = _T(""); CComQIPtr spContext2 = piCallback; if( !spContext2 ) return E_NOINTERFACE; CONTEXTMENUITEM2 singleMenuItem; ZeroMemory(&singleMenuItem, sizeof(CONTEXTMENUITEM2)); singleMenuItem.fFlags = MF_ENABLED; // Add the Disconnect Menu to the "Top" part of the MMC Context Menu if( *pInsertionAllowed & CCM_INSERTIONALLOWED_TOP ) { strMenu = StrLoadString(IDS_MENU_SERVER_DISCON); strDesc = StrLoadString(IDS_MENU_SERVER_DISCON_DESC); singleMenuItem.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_TOP; singleMenuItem.strName = (LPWSTR)strMenu.c_str(); singleMenuItem.strStatusBarText = (LPWSTR)strDesc.c_str(); singleMenuItem.strLanguageIndependentName = L"SERVER_DISCONNECT"; singleMenuItem.lCommandID = IDM_SERVER_TOP_DISCONNECT; if( !strMenu.empty() ) { hr = spContext2->AddItem( &singleMenuItem ); if( FAILED(hr) ) return hr; } } // Add the Domain Menu to the "New" part of the MMC Context Menu if( (*pInsertionAllowed & CCM_INSERTIONALLOWED_NEW) ) { strMenu = StrLoadString(IDS_MENU_SERVER_NEWDOM); strDesc = StrLoadString(IDS_MENU_SERVER_NEWDOM_DESC); singleMenuItem.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_NEW; singleMenuItem.strName = (LPWSTR)strMenu.c_str(); singleMenuItem.strStatusBarText = (LPWSTR)strDesc.c_str(); singleMenuItem.strLanguageIndependentName = L"NEW_DOMAIN"; singleMenuItem.lCommandID = IDM_SERVER_NEW_DOMAIN; if( !strMenu.empty() ) { hr = spContext2->AddItem( &singleMenuItem ); if( FAILED(hr) ) return hr; } } // Add the Service Operation Menus to the "Task" part of the MMC Context Menu if( *pInsertionAllowed & CCM_INSERTIONALLOWED_TASK ) { CComPtr spService; hr = m_spConfig->get_Service( &spService ); if( FAILED(hr) ) return hr; long lServiceStatus = 0; hr = spService->get_POP3ServiceStatus( &lServiceStatus ); if( FAILED(hr) ) return hr; singleMenuItem.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_TASK; if( lServiceStatus == SERVICE_STOPPED ) { strMenu = StrLoadString(IDS_MENU_SERVER_START); strDesc = StrLoadString(IDS_MENU_SERVER_START_DESC); singleMenuItem.strName = (LPWSTR)strMenu.c_str(); singleMenuItem.strStatusBarText = (LPWSTR)strDesc.c_str(); singleMenuItem.strLanguageIndependentName = L"SERVER_START"; singleMenuItem.lCommandID = IDM_SERVER_TASK_START; if( !strMenu.empty() ) { hr = spContext2->AddItem( &singleMenuItem ); if( FAILED(hr) ) return hr; } } if( lServiceStatus == SERVICE_PAUSED ) { strMenu = StrLoadString(IDS_MENU_SERVER_RESUME); strDesc = StrLoadString(IDS_MENU_SERVER_RESUME_DESC); singleMenuItem.strName = (LPWSTR)strMenu.c_str(); singleMenuItem.strStatusBarText = (LPWSTR)strDesc.c_str(); singleMenuItem.strLanguageIndependentName = L"SERVER_RESUME"; singleMenuItem.lCommandID = IDM_SERVER_TASK_RESUME; if( !strMenu.empty() ) { hr = spContext2->AddItem( &singleMenuItem ); if( FAILED(hr) ) return hr; } } if( lServiceStatus == SERVICE_RUNNING ) { strMenu = StrLoadString(IDS_MENU_SERVER_PAUSE); strDesc = StrLoadString(IDS_MENU_SERVER_PAUSE_DESC); singleMenuItem.strName = (LPWSTR)strMenu.c_str(); singleMenuItem.strStatusBarText = (LPWSTR)strDesc.c_str(); singleMenuItem.strLanguageIndependentName = L"SERVER_PAUSE"; singleMenuItem.lCommandID = IDM_SERVER_TASK_PAUSE; if( !strMenu.empty() ) { hr = spContext2->AddItem( &singleMenuItem ); if( FAILED(hr) ) return hr; } } if( (lServiceStatus == SERVICE_RUNNING) || (lServiceStatus == SERVICE_PAUSED) ) { strMenu = StrLoadString(IDS_MENU_SERVER_STOP); strDesc = StrLoadString(IDS_MENU_SERVER_STOP_DESC); singleMenuItem.strName = (LPWSTR)strMenu.c_str(); singleMenuItem.strStatusBarText = (LPWSTR)strDesc.c_str(); singleMenuItem.strLanguageIndependentName = L"SERVER_STOP"; singleMenuItem.lCommandID = IDM_SERVER_TASK_STOP; if( !strMenu.empty() ) { hr = spContext2->AddItem( &singleMenuItem ); if( FAILED(hr) ) return hr; } } if( (lServiceStatus == SERVICE_RUNNING) || (lServiceStatus == SERVICE_PAUSED) ) { strMenu = StrLoadString(IDS_MENU_SERVER_RESTART); strDesc = StrLoadString(IDS_MENU_SERVER_RESTART_DESC); singleMenuItem.strName = (LPWSTR)strMenu.c_str(); singleMenuItem.strStatusBarText = (LPWSTR)strDesc.c_str(); singleMenuItem.strLanguageIndependentName = L"SERVER_RESTART"; singleMenuItem.lCommandID = IDM_SERVER_TASK_RESTART; if( !strMenu.empty() ) { hr = spContext2->AddItem( &singleMenuItem ); if( FAILED(hr) ) return hr; } } } return hr; } ///////////////////////////////////////////////////////////////////////// // CServerNode::OnNewDomain // // Display a NewDomain dialog, and add the new domain HRESULT CServerNode::OnNewDomain( bool& bHandled, CSnapInObjectRootBase* pObj ) { if( !pObj ) return E_INVALIDARG; if( !m_spConfig ) return E_FAIL; bHandled = true; HRESULT hr = S_OK; // Load a dialog that asks for a Domain Name CNewDomainDlg dlg; if( dlg.DoModal() == IDOK ) { HWND hWnd = NULL; CComPtr spConsole = NULL; // Get a window handle hr = GetConsole( pObj, &spConsole ); if( FAILED(hr) || !spConsole ) return E_NOINTERFACE; spConsole->GetMainWindow(&hWnd); // Access our POP3 Domain list CComPtr spDomains; hr = m_spConfig->get_Domains( &spDomains ); // Add our domain to the POP3 Admin domainlist if( SUCCEEDED(hr) ) { CComBSTR bstrName = dlg.m_strName.c_str(); hr = spDomains->Add( bstrName ); } // Check for weird pre-existance condition if( hr == ERROR_FILE_EXISTS ) { tstring strMessage = StrLoadString( IDS_WARNING_DOMAINEXISTS ); tstring strTitle = StrLoadString(IDS_SNAPINNAME); MessageBox( hWnd, strMessage.c_str(), strTitle.c_str(), MB_OK | MB_ICONWARNING ); } if( SUCCEEDED(hr) ) { CComVariant var; CComPtr spDomain = NULL; CDomainNode* pDomainNode = NULL; // Get a grasp of the Domain interface to pass to the node VariantInit(&var); var = dlg.m_strName.c_str(); hr = spDomains->get_Item( var, &spDomain ); if( SUCCEEDED(hr) ) { // Add the new Domain to our list of domains pDomainNode = new CDomainNode( spDomain, this ); if( !pDomainNode ) hr = E_OUTOFMEMORY; } if( SUCCEEDED(hr) ) { pDomainNode->m_scopeDataItem.mask |= SDI_PARENT; pDomainNode->m_scopeDataItem.relativeID = m_scopeDataItem.ID; m_lDomains.push_back( pDomainNode ); // Add the new domain into the namespace // Insert it into the result tree CComQIPtr spNameSpace = spConsole; if( !spNameSpace ) return E_NOINTERFACE; hr = spNameSpace->InsertItem( &(pDomainNode->m_scopeDataItem) ); } if( SUCCEEDED(hr) ) { // Get our Data Object CComPtr spDataObject = NULL; GetDataObject(&spDataObject, CCT_SCOPE); if( !spDataObject ) return E_FAIL; // Call the Update, but don't update return result spConsole->UpdateAllViews( spDataObject, 0, (LONG_PTR)NAV_ADD ); } } if( FAILED(hr) ) { // Failed to add the Domain tstring strMessage = StrLoadString(IDS_ERROR_CREATEDOMAIN); tstring strTitle = StrLoadString(IDS_SNAPINNAME); DisplayError( hWnd, strMessage.c_str(), strTitle.c_str(), hr ); } } return hr; } ///////////////////////////////////////////////////////////////////////// // CServerNode::OnDisconnect // // Disconnect is essentially deleting ourselves from the list of servers HRESULT CServerNode::OnDisconnect( bool& bHandled, CSnapInObjectRootBase* pObj ) { if( !pObj ) return E_INVALIDARG; if( !m_pParent ) return E_FAIL; bHandled = true; HRESULT hr = S_OK; // Get the Window Handle HWND hWnd = NULL; CComPtr spConsole = NULL; hr = GetConsole( pObj, &spConsole ); if( FAILED(hr) || !spConsole ) return E_NOINTERFACE; spConsole->GetMainWindow(&hWnd); // Load the message box tstring strDeleteWarning = StrLoadString( IDS_SERVER_CONFIRMDISCONNECT ); tstring strTitle = StrLoadString( IDS_SNAPINNAME ); tstring strPropPageOpen = StrLoadString( IDS_WARNING_PROP_PAGE_OPEN ); if(1!=m_lRefCount) { MessageBox(hWnd, strPropPageOpen.c_str(),strTitle.c_str(),MB_OK); return hr; //Not error case } if( MessageBox(hWnd, strDeleteWarning.c_str(), strTitle.c_str(), MB_YESNO | MB_ICONWARNING ) == IDYES ) { // Remove ourselves from the tree CComQIPtr spNameSpace = spConsole; if( !spNameSpace ) return E_NOINTERFACE; hr = spNameSpace->DeleteItem( m_scopeDataItem.ID, TRUE ); // The parent needs to do the deletion if( SUCCEEDED(hr) ) { hr = m_pParent->DeleteServer(this); } if( SUCCEEDED(hr) ) { delete this; } } return hr; } ///////////////////////////////////////////////////////////////////////// // CServerNode::OnServerService // // Function to handle the Start/Stop/Pause/Restart of the POP3 Service // on this computer HRESULT CServerNode::OnServerService( UINT nID, bool& bHandled, CSnapInObjectRootBase* pObj ) { if( !m_spConfig ) return E_FAIL; bHandled = true; HCURSOR hOldCursor = NULL; HCURSOR hWaitCursor = ::LoadCursor(NULL, IDC_WAIT); if (hWaitCursor) { hOldCursor = ::SetCursor(hWaitCursor); } // Get the Window Handle HWND hWnd = NULL; CComPtr spConsole = NULL; tstring strTitle = StrLoadString( IDS_SNAPINNAME ); tstring strMessage = _T(""); HRESULT hr = GetConsole( pObj, &spConsole ); if( FAILED(hr) || !spConsole ) return E_NOINTERFACE; spConsole->GetMainWindow(&hWnd); // Get the POP3 Service CComPtr spService = NULL; hr = m_spConfig->get_Service( &spService ); // Do the appropriate service operation switch( nID ) { case IDM_SERVER_TASK_START: { if( SUCCEEDED(hr) ) { hr = spService->StartPOP3Service(); } // Used for both Start failure, and Service retreival failure if( FAILED(hr) ) { strMessage = StrLoadString( IDS_ERROR_STARTSERVICE ); DisplayError( hWnd, strMessage.c_str(), strTitle.c_str(), hr ); } break; } case IDM_SERVER_TASK_RESUME: { if( SUCCEEDED(hr) ) { hr = spService->ResumePOP3Service(); } // Used for both Start failure, and Service retreival failure if( FAILED(hr) ) { strMessage = StrLoadString( IDS_ERROR_RESUMESERVICE ); DisplayError( hWnd, strMessage.c_str(), strTitle.c_str(), hr ); } break; } case IDM_SERVER_TASK_STOP: { if( SUCCEEDED(hr) ) { hr = spService->StopPOP3Service(); } // Used for both Start failure, and Service retreival failure if( FAILED(hr) ) { strMessage = StrLoadString( IDS_ERROR_STOPSERVICE ); DisplayError( hWnd, strMessage.c_str(), strTitle.c_str(), hr ); } break; } case IDM_SERVER_TASK_PAUSE: { if( SUCCEEDED(hr) ) { hr = spService->PausePOP3Service(); } if( FAILED(hr) ) { strMessage = StrLoadString( IDS_ERROR_PAUSESERVICE ); DisplayError( hWnd, strMessage.c_str(), strTitle.c_str(), hr ); } break; } case IDM_SERVER_TASK_RESTART: { if( SUCCEEDED(hr) ) { hr = spService->StopPOP3Service(); } if( SUCCEEDED(hr) ) { hr = spService->StartPOP3Service(); } // Used for both Start failure, and Service retreival failure if( FAILED(hr) ) { strMessage = StrLoadString( IDS_ERROR_RESTARTSERVICE ); DisplayError( hWnd, strMessage.c_str(), strTitle.c_str(), hr ); } break; } } ::SetCursor(hOldCursor); if( SUCCEEDED(hr) ) { CComQIPtr spNameSpace = spConsole; if( spNameSpace ) { spNameSpace->SetItem( &m_scopeDataItem ); } } return hr; } ///////////////////////////////////////////////////////////////////////// // // PropertyPageImpl // ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// // CServerNode::CreatePropertyPages // // Fills MMC's callback with our property pages HRESULT CServerNode::CreatePropertyPages(LPPROPERTYSHEETCALLBACK lpProvider, LONG_PTR handle, IUnknown* pUnk, DATA_OBJECT_TYPES type) { if( !lpProvider ) return E_INVALIDARG; if( !m_spConfig ) return E_FAIL; HRESULT hr = E_FAIL; // Load our Server's General page HPROPSHEETPAGE hpageGen = NULL; InterlockedIncrement(&m_lRefCount); CServerGeneralPage* pGenPage = new CServerGeneralPage(m_spConfig, handle, this); if( pGenPage != NULL ) { hpageGen = pGenPage->Create(); } // Add it to the list of pages if( hpageGen ) { hr = lpProvider->AddPage(hpageGen); } // Destruct correctly if failure results if( FAILED(hr) ) { InterlockedDecrement(&m_lRefCount); if( hpageGen ) { DestroyPropertySheetPage(hpageGen); } else if (pGenPage) { delete pGenPage; pGenPage = NULL; } } return hr; } ///////////////////////////////////////////////////////////////////////// // // Helper Functions // ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// // CServerNode::GetAuth // // pbHashPW : Return Boolean for Hash Password Authentication // pbSAM : Return Boolean for Local SAM Authentication HRESULT CServerNode::GetAuth(BOOL* pbHashPW, BOOL* pbSAM) { if( !m_spConfig ) return E_FAIL; CComPtr spMethods; CComPtr spAuth; CComVariant var; CComBSTR bstrID; long lCurrent = 0L; HRESULT hr = m_spConfig->get_Authentication( &spMethods ); if ( SUCCEEDED(hr) ) { hr = spMethods->get_CurrentAuthMethod( &var ); } if ( SUCCEEDED(hr) ) { hr = spMethods->get_Item( var, &spAuth ); } if( SUCCEEDED(hr) ) { hr = spAuth->get_ID( &bstrID ); } if( SUCCEEDED(hr) && pbHashPW ) { *pbHashPW = (_tcsicmp(bstrID, SZ_AUTH_ID_MD5_HASH) == 0); } if( SUCCEEDED(hr) && pbSAM ) { *pbSAM = (_tcsicmp(bstrID, SZ_AUTH_ID_LOCAL_SAM) == 0); } return hr; } ///////////////////////////////////////////////////////////////////////// // CServerNode::GetConfirmAddUser // // pbConfirm : Return Boolean for User Add Confirmation HRESULT CServerNode::GetConfirmAddUser( BOOL *pbConfirm ) { if( !m_spConfig ) return E_POINTER; return m_spConfig->get_ConfirmAddUser( pbConfirm ); } ///////////////////////////////////////////////////////////////////////// // CServerNode::SetConfirmAddUser // // pbConfirm : New Boolean Value for User Add Confirmation HRESULT CServerNode::SetConfirmAddUser( BOOL bConfirm ) { if( !m_spConfig ) return E_POINTER; return m_spConfig->put_ConfirmAddUser( bConfirm ); } void CServerNode::Release() { InterlockedDecrement(&m_lRefCount); if(m_lRefCount<1) InterlockedIncrement(&m_lRefCount); }