Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1009 lines
33 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. /////////////////////////////////////////////////////////////////////////////
  3. //
  4. // CDomainNode
  5. //
  6. /////////////////////////////////////////////////////////////////////////////
  7. /////////////////////////////////////////////////////////////////////////////
  8. #include "stdafx.h"
  9. #include "pop3.h"
  10. #include "pop3snap.h"
  11. #include "DomainNode.h"
  12. #include "ServerNode.h"
  13. #include "NewUserDlg.h"
  14. static const GUID CDomainNodeGUID_NODETYPE =
  15. { 0xa30bd5b4, 0xf3f1, 0x4b42, { 0xba, 0x27, 0x62, 0x23, 0x9a, 0xd, 0xc1, 0x43 } };
  16. const GUID* CDomainNode::m_NODETYPE = &CDomainNodeGUID_NODETYPE;
  17. const OLECHAR* CDomainNode::m_SZNODETYPE = OLESTR("A30BD5B4-F3F1-4b42-BA27-62239A0DC143");
  18. const OLECHAR* CDomainNode::m_SZDISPLAY_NAME = OLESTR("");
  19. const CLSID* CDomainNode::m_SNAPIN_CLASSID = &CLSID_POP3ServerSnap;
  20. /////////////////////////////////////////////////////////////////////////
  21. //
  22. // Class implementation
  23. //
  24. /////////////////////////////////////////////////////////////////////////
  25. /////////////////////////////////////////////////////////////////////////
  26. // CDomainNode::CDomainNode
  27. //
  28. // Constructor : Uses Domain interface for initialization
  29. CDomainNode::CDomainNode(IP3Domain* pDomain, CServerNode* pParent)
  30. {
  31. // Initialize our domain
  32. m_spDomain = pDomain;
  33. m_pParent = pParent;
  34. BOOL bLocked = FALSE;
  35. HRESULT hr = E_FAIL;
  36. if( m_spDomain )
  37. {
  38. // Get our initial lock state for icon display
  39. m_spDomain->get_Lock( &bLocked );
  40. // Get our name
  41. hr = m_spDomain->get_Name( &m_bstrDisplayName );
  42. }
  43. if( FAILED(hr) )
  44. {
  45. m_bstrDisplayName = _T("");
  46. }
  47. // Initialize our column information
  48. m_bstrNumBoxes = _T("");
  49. m_bstrSize = _T("");
  50. m_bstrNumMessages = _T("");
  51. m_bstrState = _T("");
  52. // Initialize our Scope item
  53. memset(&m_scopeDataItem, 0, sizeof(SCOPEDATAITEM));
  54. m_scopeDataItem.mask = SDI_STR | SDI_IMAGE | SDI_OPENIMAGE | SDI_PARAM | SDI_CHILDREN;
  55. m_scopeDataItem.cChildren = 0;
  56. m_scopeDataItem.displayname = MMC_CALLBACK;
  57. m_scopeDataItem.nImage = (bLocked ? DOMAINNODE_LOCKED_ICON : DOMAINNODE_ICON);
  58. m_scopeDataItem.nOpenImage = (bLocked ? DOMAINNODE_LOCKED_ICON : DOMAINNODE_ICON);
  59. m_scopeDataItem.lParam = (LPARAM) this;
  60. // Initialize our Result item
  61. memset(&m_resultDataItem, 0, sizeof(RESULTDATAITEM));
  62. m_resultDataItem.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
  63. m_resultDataItem.str = MMC_CALLBACK;
  64. m_resultDataItem.nImage = (bLocked ? DOMAINNODE_LOCKED_ICON : DOMAINNODE_ICON);
  65. m_resultDataItem.lParam = (LPARAM) this;
  66. }
  67. /////////////////////////////////////////////////////////////////////////
  68. // CDomainNode::~CDomainNode
  69. //
  70. // Destructor : Clean up our member-list of Users
  71. CDomainNode::~CDomainNode()
  72. {
  73. for(USERLIST::iterator iter = m_lUsers.begin(); iter != m_lUsers.end(); iter++)
  74. {
  75. delete (*iter);
  76. }
  77. m_lUsers.clear();
  78. }
  79. /////////////////////////////////////////////////////////////////////////
  80. // CDomainNode::DeleteUser
  81. //
  82. // Helper function to delete a user from all of POP3
  83. HRESULT CDomainNode::DeleteUser(CUserNode* pUser, BOOL bDeleteAccount)
  84. {
  85. if( !pUser ) return E_INVALIDARG;
  86. if( !m_spDomain ) return E_FAIL;
  87. // Delete from POP3 Admin Interface
  88. // Get the User Container object
  89. CComPtr<IP3Users> spUsers;
  90. HRESULT hr = m_spDomain->get_Users( &spUsers );
  91. if( SUCCEEDED(hr) )
  92. {
  93. // Delete the User from the container
  94. if( bDeleteAccount )
  95. {
  96. hr = spUsers->RemoveEx( pUser->m_bstrDisplayName );
  97. }
  98. else
  99. {
  100. hr = spUsers->Remove( pUser->m_bstrDisplayName );
  101. }
  102. }
  103. if( SUCCEEDED(hr) )
  104. {
  105. // Update our list
  106. m_lUsers.remove(pUser);
  107. }
  108. return hr;
  109. }
  110. /////////////////////////////////////////////////////////////////////////
  111. // CDomainNode::IsLocked
  112. //
  113. // Helper function to Allow children to not show their locks if the
  114. // domain is locked
  115. BOOL CDomainNode::IsLocked()
  116. {
  117. if( !m_spDomain ) return TRUE;
  118. BOOL bLocked = TRUE;
  119. m_spDomain->get_Lock( &bLocked );
  120. return bLocked;
  121. }
  122. /////////////////////////////////////////////////////////////////////////
  123. // CDomainNode::BuildUsers
  124. //
  125. // Helper function to refresh list of users and insert them
  126. HRESULT CDomainNode::BuildUsers()
  127. {
  128. if( !m_spDomain ) return E_FAIL;
  129. HRESULT hr = S_OK;
  130. HWND hWnd = NULL;
  131. // Delete our Users
  132. for(USERLIST::iterator iter = m_lUsers.begin(); iter != m_lUsers.end(); iter++)
  133. {
  134. delete (*iter);
  135. }
  136. m_lUsers.clear();
  137. // Fill in all of our users
  138. CComPtr<IP3Users> spUsers;
  139. CComPtr<IEnumVARIANT> spUserEnum;
  140. // Get the User Container object
  141. hr = m_spDomain->get_Users( &spUsers );
  142. if( FAILED(hr) ) return hr;
  143. // Get the enumeration of the users
  144. hr = spUsers->get__NewEnum( &spUserEnum );
  145. if( FAILED(hr) ) return hr;
  146. // Loop through all users, and add them to our vector
  147. CComVariant var;
  148. ULONG lResult = 0;
  149. VariantInit( &var );
  150. while ( spUserEnum->Next(1, &var, &lResult) == S_OK )
  151. {
  152. if ( lResult == 1 )
  153. {
  154. CComQIPtr<IP3User> spUser;
  155. spUser = V_DISPATCH(&var);
  156. if( !spUser ) continue;
  157. CUserNode* spUserNode = new CUserNode(spUser, this);
  158. if( !spUserNode ) continue;
  159. m_lUsers.push_back(spUserNode);
  160. }
  161. VariantClear(&var);
  162. }
  163. return hr;
  164. }
  165. /////////////////////////////////////////////////////////////////////////
  166. //
  167. // SnapInItemImpl
  168. //
  169. /////////////////////////////////////////////////////////////////////////
  170. /////////////////////////////////////////////////////////////////////////
  171. // CDomainNode::GetScopePaneInfo
  172. //
  173. // Callback used to get Scope-Pane display information by MMC
  174. HRESULT CDomainNode::GetScopePaneInfo(SCOPEDATAITEM *pScopeDataItem)
  175. {
  176. if( !pScopeDataItem ) return E_INVALIDARG;
  177. if( !m_spDomain ) return E_FAIL;
  178. BOOL bLocked = FALSE;
  179. m_spDomain->get_Lock( &bLocked );
  180. if( pScopeDataItem->mask & SDI_STR )
  181. pScopeDataItem->displayname = m_bstrDisplayName;
  182. if( pScopeDataItem->mask & SDI_IMAGE )
  183. pScopeDataItem->nImage = (bLocked ? DOMAINNODE_LOCKED_ICON : DOMAINNODE_ICON);
  184. if( pScopeDataItem->mask & SDI_OPENIMAGE )
  185. pScopeDataItem->nOpenImage = (bLocked ? DOMAINNODE_LOCKED_ICON : DOMAINNODE_ICON);
  186. if( pScopeDataItem->mask & SDI_PARAM )
  187. pScopeDataItem->lParam = m_scopeDataItem.lParam;
  188. if( pScopeDataItem->mask & SDI_STATE )
  189. pScopeDataItem->nState = m_scopeDataItem.nState;
  190. if( pScopeDataItem->mask & SDI_CHILDREN )
  191. pScopeDataItem->cChildren = 0;
  192. return S_OK;
  193. }
  194. /////////////////////////////////////////////////////////////////////////
  195. // CServerNode::GetResultPaneInfo
  196. //
  197. // Callback used to get Result Pane display information by MMC
  198. HRESULT CDomainNode::GetResultPaneInfo(RESULTDATAITEM *pResultDataItem)
  199. {
  200. if( !pResultDataItem ) return E_INVALIDARG;
  201. if( !m_spDomain ) return E_FAIL;
  202. BOOL bLocked = FALSE;
  203. m_spDomain->get_Lock( &bLocked );
  204. if( pResultDataItem->bScopeItem )
  205. {
  206. if( pResultDataItem->mask & RDI_STR )
  207. pResultDataItem->str = GetResultPaneColInfo(pResultDataItem->nCol);
  208. if( pResultDataItem->mask & RDI_IMAGE )
  209. pResultDataItem->nImage = (bLocked ? DOMAINNODE_LOCKED_ICON : DOMAINNODE_ICON);
  210. if( pResultDataItem->mask & RDI_PARAM )
  211. pResultDataItem->lParam = m_scopeDataItem.lParam;
  212. return S_OK;
  213. }
  214. if( pResultDataItem->mask & RDI_STR )
  215. pResultDataItem->str = GetResultPaneColInfo(pResultDataItem->nCol);
  216. if( pResultDataItem->mask & RDI_IMAGE )
  217. pResultDataItem->nImage = (bLocked ? DOMAINNODE_LOCKED_ICON : DOMAINNODE_ICON);
  218. if( pResultDataItem->mask & RDI_PARAM )
  219. pResultDataItem->lParam = m_resultDataItem.lParam;
  220. if( pResultDataItem->mask & RDI_INDEX )
  221. pResultDataItem->nIndex = m_resultDataItem.nIndex;
  222. return S_OK;
  223. }
  224. /////////////////////////////////////////////////////////////////////////
  225. // CServerNode::GetResultPaneColInfo
  226. //
  227. // Helper function used as part of the GetResultPaneInfo. This function
  228. // will supply the text for the different columns.
  229. LPOLESTR CDomainNode::GetResultPaneColInfo(int nCol)
  230. {
  231. if( !m_spDomain ) return L"";
  232. switch( nCol )
  233. {
  234. case 0: // Name
  235. {
  236. return m_bstrDisplayName;
  237. }
  238. case 1: // Number of Mailboxes
  239. {
  240. long lCount = 0L;
  241. // Get the Users container object for this domain
  242. CComPtr<IP3Users> spUsers;
  243. HRESULT hr = m_spDomain->get_Users( &spUsers );
  244. if( SUCCEEDED(hr) )
  245. {
  246. // Get the number of mailboxes
  247. hr = spUsers->get_Count( &lCount );
  248. }
  249. if( FAILED(hr) )
  250. {
  251. lCount = 0; // Make sure we put in a valid error value.
  252. }
  253. // 1K buffer: Not likely we'll exceed that many digits
  254. TCHAR szNum[1024] = {0};
  255. _sntprintf( szNum, 1023, _T("%d"), lCount );
  256. m_bstrNumBoxes = szNum;
  257. return m_bstrNumBoxes;
  258. }
  259. case 2: // Domain Size (MB)
  260. {
  261. // We want our result in Megabytes
  262. long lFactor = 0;
  263. long lUsage = 0;
  264. HRESULT hr = m_spDomain->get_MessageDiskUsage( &lFactor, &lUsage );
  265. if( FAILED(hr) )
  266. {
  267. lUsage = 0; // Make sure we have a valid error value
  268. }
  269. // Convert to KiloBytes
  270. __int64 i64Usage = lFactor * lUsage;
  271. i64Usage /= 1024;
  272. // 1K buffer: Not likely we'll exceed that many digits
  273. tstring strKiloByte = StrLoadString( IDS_KILOBYTE_EXTENSION );
  274. TCHAR szNum[1024] = {0};
  275. _sntprintf( szNum, 1023, strKiloByte.c_str(), i64Usage );
  276. m_bstrSize = szNum;
  277. return m_bstrSize;
  278. }
  279. case 3: // Number of Messages
  280. {
  281. long lCount = 0;
  282. HRESULT hr = m_spDomain->get_MessageCount( &lCount );
  283. // 1K buffer: Not likely we'll exceed that many digits
  284. TCHAR szNum[1024] = {0};
  285. _sntprintf( szNum, 1023, _T("%d"), lCount );
  286. m_bstrNumMessages = szNum;
  287. return m_bstrNumMessages;
  288. }
  289. case 4: // State of Domain
  290. {
  291. BOOL bLocked = FALSE;
  292. m_spDomain->get_Lock( &bLocked );
  293. m_bstrState.LoadString( bLocked ? IDS_STATE_LOCKED : IDS_STATE_UNLOCKED );
  294. return m_bstrState;
  295. }
  296. default:
  297. {
  298. return L"";
  299. }
  300. }
  301. }
  302. /////////////////////////////////////////////////////////////////////////
  303. // CServerNode::Notify
  304. //
  305. // Core callback functionality of this Node. MMC will use this function
  306. // for all MMC provided functionality, such as Expanding, Renaming, and
  307. // Context Help
  308. HRESULT CDomainNode::Notify( MMC_NOTIFY_TYPE event,
  309. LPARAM arg,
  310. LPARAM param,
  311. IComponentData* pComponentData,
  312. IComponent* pComponent,
  313. DATA_OBJECT_TYPES type)
  314. {
  315. HRESULT hr = S_FALSE;
  316. _ASSERT(pComponentData != NULL || pComponent != NULL);
  317. // Get a pointer to the console
  318. CComPtr<IConsole> spConsole = NULL;
  319. if( pComponentData )
  320. {
  321. spConsole = ((CPOP3ServerSnapData*)pComponentData)->m_spConsole;
  322. }
  323. else if( pComponent )
  324. {
  325. spConsole = ((CPOP3ServerSnapComponent*)pComponent)->m_spConsole;
  326. }
  327. if( !spConsole ) return E_INVALIDARG;
  328. switch( event )
  329. {
  330. case MMCN_SHOW:
  331. {
  332. hr = S_OK;
  333. CComQIPtr<IHeaderCtrl2> spHeaderCtrl = spConsole;
  334. if( !spHeaderCtrl ) return E_NOINTERFACE;
  335. tstring strHeader = _T("");
  336. strHeader = StrLoadString(IDS_HEADER_USER_NAME);
  337. spHeaderCtrl->InsertColumn(0, strHeader.c_str(), LVCFMT_LEFT, 100);
  338. strHeader = StrLoadString(IDS_HEADER_USER_SIZE);
  339. spHeaderCtrl->InsertColumn(1, strHeader.c_str(), LVCFMT_LEFT, 100);
  340. strHeader = StrLoadString(IDS_HEADER_USER_NUMMES);
  341. spHeaderCtrl->InsertColumn(2, strHeader.c_str(), LVCFMT_LEFT, 100);
  342. strHeader = StrLoadString(IDS_HEADER_USER_LOCKED);
  343. spHeaderCtrl->InsertColumn(3, strHeader.c_str(), LVCFMT_LEFT, 100);
  344. CComQIPtr<IResultData> spResultData = spConsole;
  345. if( !spResultData ) return E_NOINTERFACE;
  346. // Showing the list
  347. if( arg )
  348. {
  349. // Empty? Then build the list.
  350. if( m_lUsers.empty() )
  351. {
  352. hr = BuildUsers();
  353. }
  354. if( SUCCEEDED(hr) )
  355. {
  356. // Display our users
  357. for(USERLIST::iterator iter = m_lUsers.begin(); iter != m_lUsers.end(); iter++)
  358. {
  359. CUserNode* pUser = *iter;
  360. hr = spResultData->InsertItem(&(pUser->m_resultDataItem));
  361. if( FAILED(hr) ) break;
  362. }
  363. }
  364. if( SUCCEEDED(hr) )
  365. {
  366. CComQIPtr<IConsole2> spCons2 = spConsole;
  367. if( spCons2 )
  368. {
  369. // Output the number of servers we added
  370. tstring strMessage = StrLoadString(IDS_DOMAIN_STATUSBAR);
  371. OLECHAR pszStatus[1024] = {0};
  372. _sntprintf( pszStatus, 1023, strMessage.c_str(), m_lUsers.size() );
  373. spCons2->SetStatusText( pszStatus );
  374. }
  375. }
  376. }
  377. else
  378. {
  379. // We should delete our items
  380. hr = spResultData->DeleteAllRsltItems();
  381. }
  382. break;
  383. }
  384. case MMCN_ADD_IMAGES:
  385. {
  386. IImageList* pImageList = (IImageList*)arg;
  387. if( !pImageList ) return E_INVALIDARG;
  388. hr = LoadImages(pImageList);
  389. break;
  390. }
  391. case MMCN_VIEW_CHANGE:
  392. {
  393. CComQIPtr<IResultData> spResultData = spConsole;
  394. if( !spResultData ) return E_NOINTERFACE;
  395. if( param == NAV_REFRESH )
  396. {
  397. // The "arg" controls clearing, for refresh
  398. if( arg )
  399. {
  400. // Clear out the list
  401. hr = spResultData->DeleteAllRsltItems();
  402. }
  403. else
  404. {
  405. // Re-Add to our list
  406. for(USERLIST::iterator iter = m_lUsers.begin(); iter != m_lUsers.end(); iter++)
  407. {
  408. CUserNode* pUser = *iter;
  409. hr = spResultData->InsertItem(&(pUser->m_resultDataItem));
  410. if( FAILED(hr) ) break;
  411. }
  412. }
  413. }
  414. if( param == NAV_ADD )
  415. {
  416. CUserNode* pUser = (CUserNode*)arg;
  417. if( !pUser ) return E_INVALIDARG;
  418. hr = spResultData->InsertItem(&(pUser->m_resultDataItem));
  419. }
  420. if( param == NAV_DELETE )
  421. {
  422. HRESULTITEM hrItem;
  423. hr = spResultData->FindItemByLParam( arg, &hrItem );
  424. if( SUCCEEDED(hr) )
  425. {
  426. hr = spResultData->DeleteItem( hrItem, 0 );
  427. }
  428. }
  429. if( param == NAV_REFRESHCHILD )
  430. {
  431. CUserNode* pUser = (CUserNode*)arg;
  432. if( !pUser ) return E_INVALIDARG;
  433. RESULTDATAITEM rdi;
  434. ZeroMemory( &rdi, sizeof(rdi) );
  435. rdi.mask = RDI_IMAGE;
  436. hr = pUser->GetResultPaneInfo( &rdi );
  437. if( SUCCEEDED(hr) )
  438. {
  439. hr = spResultData->FindItemByLParam( arg, &(rdi.itemID) );
  440. }
  441. if( SUCCEEDED(hr) )
  442. {
  443. hr = spResultData->UpdateItem( rdi.itemID );
  444. }
  445. if( SUCCEEDED(hr) )
  446. {
  447. // In order to actually update the icon, we have to do a set item
  448. hr = spResultData->SetItem( &rdi );
  449. }
  450. }
  451. if( SUCCEEDED(hr) )
  452. {
  453. CComQIPtr<IConsole2> spCons2 = spConsole;
  454. if( spCons2 )
  455. {
  456. // Output the number of servers we added
  457. tstring strMessage = StrLoadString(IDS_DOMAIN_STATUSBAR);
  458. OLECHAR pszStatus[1024] = {0};
  459. _sntprintf( pszStatus, 1023, strMessage.c_str(), m_lUsers.size() );
  460. spCons2->SetStatusText( pszStatus );
  461. }
  462. }
  463. break;
  464. }
  465. case MMCN_REFRESH:
  466. {
  467. hr = S_OK;
  468. // Get our Data Object
  469. CComPtr<IDataObject> spDataObject = NULL;
  470. GetDataObject(&spDataObject, CCT_SCOPE);
  471. if( !spDataObject ) return E_FAIL;
  472. // Update all the Views to have them remove their lists
  473. hr = spConsole->UpdateAllViews( spDataObject, 1, (LONG_PTR)NAV_REFRESH );
  474. if( FAILED(hr) ) return E_FAIL;
  475. // Rebuild the users list
  476. hr = BuildUsers();
  477. if( FAILED(hr) ) return hr;
  478. // Update all the Views to have them re-Add their lists
  479. hr = spConsole->UpdateAllViews( spDataObject, 0, (LONG_PTR)NAV_REFRESH );
  480. break;
  481. }
  482. case MMCN_DELETE:
  483. {
  484. hr = S_OK;
  485. tstring strMessage = _T("");
  486. HWND hWnd = NULL;
  487. spConsole->GetMainWindow(&hWnd);
  488. strMessage = StrLoadString(IDS_DOMAIN_CONFIRMDELETE);
  489. tstring strTitle = StrLoadString(IDS_SNAPINNAME);
  490. if( MessageBox(hWnd, strMessage.c_str(), strTitle.c_str(), MB_YESNO | MB_ICONWARNING ) == IDYES )
  491. {
  492. hr = E_FAIL;
  493. // The parent needs to do the deletion
  494. if( m_pParent )
  495. {
  496. hr = m_pParent->DeleteDomain(this);
  497. }
  498. // Check for non-existance condition
  499. if( hr == ERROR_PATH_NOT_FOUND )
  500. {
  501. strMessage = StrLoadString( IDS_WARNING_DOMAINMISSING );
  502. MessageBox( hWnd, strMessage.c_str(), strTitle.c_str(), MB_OK | MB_ICONWARNING );
  503. }
  504. if( SUCCEEDED(hr) )
  505. {
  506. hr = E_FAIL;
  507. // Remove ourselves from the tree
  508. CComQIPtr<IConsoleNameSpace2> spNameSpace = spConsole;
  509. if( spNameSpace )
  510. {
  511. hr = spNameSpace->DeleteItem( m_scopeDataItem.ID, TRUE );
  512. }
  513. }
  514. if( SUCCEEDED(hr) )
  515. {
  516. // Update our parent node, but ignore the result
  517. CComPtr<IDataObject> spDataObject = NULL;
  518. hr = m_pParent->GetDataObject( &spDataObject, CCT_SCOPE );
  519. if( spDataObject )
  520. {
  521. spConsole->UpdateAllViews( spDataObject, (LPARAM)this, (LONG_PTR)NAV_DELETE );
  522. }
  523. }
  524. if( SUCCEEDED(hr) )
  525. {
  526. delete this;
  527. }
  528. if( FAILED(hr) )
  529. {
  530. strMessage = StrLoadString(IDS_ERROR_DELETEDOMAIN);
  531. DisplayError( hWnd, strMessage.c_str(), strTitle.c_str(), hr );
  532. }
  533. }
  534. break;
  535. }
  536. case MMCN_SELECT:
  537. {
  538. // if selecting node
  539. if( HIWORD(arg) )
  540. {
  541. hr = S_OK;
  542. // get the verb interface and enable rename
  543. CComPtr<IConsoleVerb> spConsVerb;
  544. if( spConsole->QueryConsoleVerb(&spConsVerb) == S_OK )
  545. {
  546. // Enable the Refresh Menu
  547. hr = spConsVerb->SetVerbState(MMC_VERB_REFRESH, ENABLED, TRUE);
  548. if( FAILED(hr) ) return hr;
  549. hr = spConsVerb->SetVerbState(MMC_VERB_REFRESH, HIDDEN, FALSE);
  550. if( FAILED(hr) ) return hr;
  551. // Enable the Delete Menu
  552. hr = spConsVerb->SetVerbState(MMC_VERB_DELETE, ENABLED, TRUE);
  553. if( FAILED(hr) ) return hr;
  554. hr = spConsVerb->SetVerbState(MMC_VERB_DELETE, HIDDEN, FALSE);
  555. if( FAILED(hr) ) return hr;
  556. }
  557. }
  558. break;
  559. }
  560. case MMCN_CONTEXTHELP:
  561. {
  562. hr = S_OK;
  563. TCHAR szWindowsDir[MAX_PATH+1] = {0};
  564. tstring strHelpFile = _T("");
  565. tstring strHelpFileName = StrLoadString(IDS_HELPFILE);
  566. tstring strHelpTopicName = StrLoadString(IDS_HELPTOPIC);
  567. if( strHelpFileName.empty() || strHelpTopicName.empty() )
  568. {
  569. return E_FAIL;
  570. }
  571. // Build path to %systemroot%\help
  572. UINT nSize = GetSystemWindowsDirectory( szWindowsDir, MAX_PATH );
  573. if( nSize == 0 || nSize > MAX_PATH )
  574. {
  575. return E_FAIL;
  576. }
  577. strHelpFile = szWindowsDir; // D:\windows
  578. strHelpFile += _T("\\Help\\"); // \help
  579. strHelpFile += strHelpFileName; // \filename.chm
  580. strHelpFile += _T("::/"); // ::/
  581. strHelpFile += strHelpTopicName; // index.htm
  582. // Show the Help topic
  583. CComQIPtr<IDisplayHelp> spHelp = spConsole;
  584. if( !spHelp ) return E_NOINTERFACE;
  585. hr = spHelp->ShowTopic( (LPTSTR)strHelpFile.c_str() );
  586. break;
  587. }
  588. }// switch
  589. return hr;
  590. }
  591. /////////////////////////////////////////////////////////////////////////
  592. //
  593. // ContextMenuImpl
  594. //
  595. /////////////////////////////////////////////////////////////////////////
  596. /////////////////////////////////////////////////////////////////////////
  597. // CDomainNode::AddMenuItems
  598. //
  599. // Adds our context menus into the appropriate MMC provided menu
  600. // locations.
  601. HRESULT CDomainNode::AddMenuItems(LPCONTEXTMENUCALLBACK piCallback, long* pInsertionAllowed, DATA_OBJECT_TYPES type )
  602. {
  603. if( !pInsertionAllowed || !piCallback ) return E_INVALIDARG;
  604. if( !m_spDomain ) return E_FAIL;
  605. HRESULT hr = S_OK;
  606. tstring strMenu = _T("");
  607. tstring strDesc = _T("");
  608. CONTEXTMENUITEM2 singleMenuItem;
  609. ZeroMemory(&singleMenuItem, sizeof(CONTEXTMENUITEM2));
  610. CComQIPtr<IContextMenuCallback2> spContext2 = piCallback;
  611. if( !spContext2 ) return E_NOINTERFACE;
  612. // Add the Lock or Unlock Menu to the "Top" part of the MMC Context Menu
  613. if( *pInsertionAllowed & CCM_INSERTIONALLOWED_TOP )
  614. {
  615. singleMenuItem.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_TOP;
  616. singleMenuItem.fFlags = MF_ENABLED;
  617. singleMenuItem.fSpecialFlags = 0;
  618. // Query the state of this domain to see which menu to load
  619. BOOL bLocked = FALSE;
  620. m_spDomain->get_Lock( &bLocked );
  621. if( bLocked )
  622. {
  623. strMenu = StrLoadString(IDS_MENU_DOMAIN_UNLOCK);
  624. strDesc = StrLoadString(IDS_MENU_DOMAIN_UNLOCK_DESC);
  625. singleMenuItem.strName = (LPWSTR)strMenu.c_str();
  626. singleMenuItem.strStatusBarText = (LPWSTR)strDesc.c_str();
  627. singleMenuItem.strLanguageIndependentName = L"DOMAIN_UNLOCK";
  628. singleMenuItem.lCommandID = IDM_DOMAIN_TOP_UNLOCK;
  629. }
  630. else
  631. {
  632. strMenu = StrLoadString(IDS_MENU_DOMAIN_LOCK);
  633. strDesc = StrLoadString(IDS_MENU_DOMAIN_LOCK_DESC);
  634. singleMenuItem.strName = (LPWSTR)strMenu.c_str();
  635. singleMenuItem.strStatusBarText = (LPWSTR)strDesc.c_str();
  636. singleMenuItem.strLanguageIndependentName = L"DOMAIN_LOCK";
  637. singleMenuItem.lCommandID = IDM_DOMAIN_TOP_LOCK;
  638. }
  639. if( !strMenu.empty() )
  640. {
  641. hr = spContext2->AddItem( &singleMenuItem );
  642. if( FAILED(hr) ) return hr;
  643. }
  644. }
  645. // Add the User Menu to the "New" part of the MMC Context Menu
  646. if( (*pInsertionAllowed & CCM_INSERTIONALLOWED_NEW) )
  647. {
  648. singleMenuItem.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_NEW;
  649. singleMenuItem.fFlags = MF_ENABLED;
  650. singleMenuItem.fSpecialFlags = 0;
  651. strMenu = StrLoadString(IDS_MENU_DOMAIN_NEWUSER);
  652. strDesc = StrLoadString(IDS_MENU_DOMAIN_NEWUSER_DESC);
  653. singleMenuItem.strName = (LPWSTR)strMenu.c_str();
  654. singleMenuItem.strStatusBarText = (LPWSTR)strDesc.c_str();
  655. singleMenuItem.strLanguageIndependentName = L"NEW_USER";
  656. singleMenuItem.lCommandID = IDM_DOMAIN_NEW_USER;
  657. if( !strMenu.empty() )
  658. {
  659. hr = spContext2->AddItem( &singleMenuItem );
  660. if( FAILED(hr) ) return hr;
  661. }
  662. }
  663. return hr;
  664. }
  665. /////////////////////////////////////////////////////////////////////////
  666. // CDomainNode::OnDomainLock
  667. //
  668. // Lock or unlock the domain, depending on its current state
  669. HRESULT CDomainNode::OnDomainLock( bool& bHandled, CSnapInObjectRootBase* pObj )
  670. {
  671. bHandled = true;
  672. if( !pObj ) return E_INVALIDARG;
  673. if( !m_spDomain ) return E_FAIL;
  674. // Lock this domain
  675. HRESULT hr = S_OK;
  676. BOOL bLocked = FALSE;
  677. CComPtr<IConsole> spConsole = NULL;
  678. hr = GetConsole( pObj, &spConsole );
  679. if( FAILED(hr) || !spConsole ) return E_NOINTERFACE;
  680. hr = m_spDomain->get_Lock( &bLocked );
  681. bLocked = !bLocked;
  682. if( SUCCEEDED(hr) )
  683. {
  684. hr = m_spDomain->put_Lock( bLocked );
  685. }
  686. if( SUCCEEDED(hr) )
  687. {
  688. // Set our icons here
  689. m_scopeDataItem.nImage = (bLocked ? DOMAINNODE_LOCKED_ICON : DOMAINNODE_ICON);
  690. m_scopeDataItem.nOpenImage = (bLocked ? DOMAINNODE_LOCKED_ICON : DOMAINNODE_ICON);
  691. m_resultDataItem.nImage = (bLocked ? DOMAINNODE_LOCKED_ICON : DOMAINNODE_ICON);
  692. // Insert it into the scope tree
  693. CComQIPtr<IConsoleNameSpace2> spConsoleNameSpace = spConsole;
  694. if( !spConsoleNameSpace ) return E_NOINTERFACE;
  695. hr = spConsoleNameSpace->SetItem(&m_scopeDataItem);
  696. }
  697. // Do a FULL Refresh to update the user lists.
  698. // Get our Data Object
  699. CComPtr<IDataObject> spDataObject = NULL;
  700. GetDataObject(&spDataObject, CCT_SCOPE);
  701. if( !spDataObject ) return E_FAIL;
  702. // Update all the Views to have them remove their lists
  703. hr = spConsole->UpdateAllViews( spDataObject, 1, (LONG_PTR)NAV_REFRESH );
  704. if( FAILED(hr) ) return E_FAIL;
  705. // Rebuild the users list
  706. hr = BuildUsers();
  707. if( FAILED(hr) ) return hr;
  708. // Update all the Views to have them re-Add their lists
  709. hr = spConsole->UpdateAllViews( spDataObject, 0, (LONG_PTR)NAV_REFRESH );
  710. return hr;
  711. }
  712. /////////////////////////////////////////////////////////////////////////
  713. // CDomainNode::OnNewUser
  714. //
  715. // Display the New User Dialog, and use the info to create a new POP3
  716. // user/mailbox and update the Result view
  717. HRESULT CDomainNode::OnNewUser( bool& bHandled, CSnapInObjectRootBase* pObj )
  718. {
  719. bHandled = true;
  720. if( !pObj ) return E_INVALIDARG;
  721. if( !m_pParent || !m_spDomain ) return E_FAIL;
  722. // Grab our Current Authentication method
  723. HRESULT hr = S_OK;
  724. HWND hWnd = NULL;
  725. CComPtr<IConsole> spConsole = NULL;
  726. hr = GetConsole( pObj, &spConsole );
  727. if( FAILED(hr) || !spConsole ) return E_NOINTERFACE;
  728. CComQIPtr<IConsole2> spConsole2 = spConsole;
  729. if( !spConsole2 ) return E_NOINTERFACE;
  730. spConsole2->GetMainWindow(&hWnd);
  731. BOOL bSAM = FALSE;
  732. BOOL bHash = FALSE;
  733. BOOL bConfirm = TRUE;
  734. hr = GetAuth(&bHash, &bSAM);
  735. if( FAILED(hr) )
  736. {
  737. // bail out here
  738. tstring strMessage = StrLoadString(IDS_ERROR_RETRIEVEAUTH);
  739. tstring strTitle = StrLoadString(IDS_SNAPINNAME);
  740. ::MessageBox( hWnd, strMessage.c_str(), strTitle.c_str(), MB_OK | MB_ICONWARNING );
  741. return hr;
  742. }
  743. // Get the username and load a Dialog box that asks for a user name, and user email name
  744. CComPtr<IP3Users> spUsers;
  745. hr = m_spDomain->get_Users( &spUsers );
  746. if ( S_OK == hr )
  747. hr = GetConfirmAddUser( &bConfirm );
  748. if( FAILED(hr) )
  749. {
  750. // Failed to add the user
  751. tstring strMessage = StrLoadString(IDS_ERROR_CREATEMAIL);
  752. tstring strTitle = StrLoadString(IDS_SNAPINNAME);
  753. DisplayError( hWnd, strMessage.c_str(), strTitle.c_str(), hr );
  754. return hr;
  755. }
  756. CNewUserDlg dlg(spUsers, m_bstrDisplayName, m_pParent->m_bCreateUser, bHash, bSAM, bConfirm );
  757. if( dlg.DoModal() == IDOK )
  758. {
  759. if ( dlg.isHideDoNotShow() )
  760. SetConfirmAddUser( FALSE );
  761. CComVariant var;
  762. CComPtr<IP3User> spUser;
  763. VariantInit(&var);
  764. var = dlg.m_strName.c_str();
  765. hr = spUsers->get_Item( var, &spUser );
  766. CUserNode* pUserNode = new CUserNode(spUser, this);
  767. if( pUserNode )
  768. {
  769. m_lUsers.push_back( pUserNode );
  770. }
  771. // Re-Select our node to update the result
  772. // Get our Data Object
  773. CComPtr<IDataObject> spDataObject = NULL;
  774. GetDataObject(&spDataObject, CCT_SCOPE);
  775. if( !spDataObject ) return E_FAIL;
  776. hr = spConsole2->UpdateAllViews( spDataObject, (LPARAM)pUserNode, (LONG_PTR)NAV_ADD );
  777. }
  778. return hr;
  779. }
  780. /////////////////////////////////////////////////////////////////////////
  781. //
  782. // Helper Functions
  783. //
  784. /////////////////////////////////////////////////////////////////////////
  785. /////////////////////////////////////////////////////////////////////////
  786. // CDomainNode::GetAuth
  787. //
  788. // pbHashPW : Return Boolean for Hash Password Authentication
  789. // pbSAM : Return Boolean for Local SAM Authentication
  790. HRESULT CDomainNode::GetAuth(BOOL* pbHashPW, BOOL* pbSAM)
  791. {
  792. if( !m_pParent ) return E_FAIL;
  793. return m_pParent->GetAuth(pbHashPW, pbSAM);
  794. }
  795. /////////////////////////////////////////////////////////////////////////
  796. // CDomainNode::GetConfirmAddUser
  797. //
  798. // pbConfirm : Return Boolean for User Add Confirmation
  799. HRESULT CDomainNode::GetConfirmAddUser( BOOL *pbConfirm )
  800. {
  801. if( !m_pParent ) return E_POINTER;
  802. return m_pParent->GetConfirmAddUser( pbConfirm );
  803. }
  804. /////////////////////////////////////////////////////////////////////////
  805. // CDomainNode::SetConfirmAddUser
  806. //
  807. // bConfirm : New Boolean Value for User Add Confirmation
  808. HRESULT CDomainNode::SetConfirmAddUser( BOOL bConfirm )
  809. {
  810. if( !m_pParent ) return E_POINTER;
  811. return m_pParent->SetConfirmAddUser( bConfirm );
  812. }