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.

573 lines
19 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. /////////////////////////////////////////////////////////////////////////////
  3. //
  4. // CRootNode
  5. //
  6. /////////////////////////////////////////////////////////////////////////////
  7. /////////////////////////////////////////////////////////////////////////////
  8. #include "stdafx.h"
  9. // Access to the snapin
  10. #include "pop3.h"
  11. #include "pop3snap.h"
  12. // Access to Nodes that we use
  13. #include "RootNode.h"
  14. #include "ServerNode.h"
  15. // Access to the dialog to connect a remote server
  16. #include "ConnServerDlg.h"
  17. // The first version did not exist... it was saving some server properties
  18. // that needed to be defined elsewhere. From now on, we will query the
  19. // version.
  20. #define SNAPIN_VERSION (DWORD)100
  21. static const GUID CRootNodeGUID_NODETYPE =
  22. { 0x5c0afaad, 0xab69, 0x4a34, { 0xa9, 0xe, 0x92, 0xf1, 0x10, 0x56, 0xda, 0xce } };
  23. const GUID* CRootNode::m_NODETYPE = &CRootNodeGUID_NODETYPE;
  24. const OLECHAR* CRootNode::m_SZNODETYPE = OLESTR("5C0AFAAD-AB69-4a34-A90E-92F11056DACE");
  25. const OLECHAR* CRootNode::m_SZDISPLAY_NAME = NULL;
  26. const CLSID* CRootNode::m_SNAPIN_CLASSID = &CLSID_POP3ServerSnap;
  27. /////////////////////////////////////////////////////////////////////////
  28. //
  29. // Class implementation
  30. //
  31. /////////////////////////////////////////////////////////////////////////
  32. /////////////////////////////////////////////////////////////////////////
  33. // CRootNode::CRootNode
  34. //
  35. // Constructor : Base Node for POP3
  36. CRootNode::CRootNode()
  37. {
  38. // Initialize the Scope Pane information
  39. memset( &m_scopeDataItem, 0, sizeof(m_scopeDataItem) );
  40. m_scopeDataItem.mask = SDI_STR | SDI_IMAGE | SDI_OPENIMAGE | SDI_PARAM;
  41. m_scopeDataItem.displayname = L"";
  42. m_scopeDataItem.nImage = 0;
  43. m_scopeDataItem.nOpenImage = 0;
  44. m_scopeDataItem.lParam = (LPARAM) this;
  45. // Initialize the Result Pane Information
  46. memset( &m_resultDataItem, 0, sizeof(m_resultDataItem) );
  47. m_resultDataItem.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
  48. m_resultDataItem.str = L"";
  49. m_resultDataItem.nImage = 0;
  50. m_resultDataItem.lParam = (LPARAM) this;
  51. // Initialize the Snapin Name
  52. tstring strTemp = StrLoadString( IDS_SNAPINNAME );
  53. m_bstrDisplayName = strTemp.c_str();
  54. // Add our Local Server always for now
  55. CServerNode* spServerNode = new CServerNode(CComBSTR(_T("")), this, TRUE);
  56. if( spServerNode )
  57. {
  58. m_lServers.push_back(spServerNode);
  59. }
  60. }
  61. CRootNode::~CRootNode()
  62. {
  63. for(SERVERLIST::iterator iter = m_lServers.begin(); iter != m_lServers.end(); iter++)
  64. {
  65. delete (*iter);
  66. }
  67. m_lServers.clear();
  68. }
  69. HRESULT CRootNode::DeleteServer(CServerNode* pServerNode)
  70. {
  71. if( !pServerNode ) return E_INVALIDARG;
  72. // Update our list
  73. m_lServers.remove(pServerNode);
  74. return S_OK;
  75. }
  76. HRESULT CRootNode::GetScopePaneInfo(SCOPEDATAITEM *pScopeDataItem)
  77. {
  78. if( !pScopeDataItem ) return E_INVALIDARG;
  79. if( pScopeDataItem->mask & SDI_STR )
  80. pScopeDataItem->displayname = m_bstrDisplayName;
  81. if( pScopeDataItem->mask & SDI_IMAGE )
  82. pScopeDataItem->nImage = 0;
  83. if( pScopeDataItem->mask & SDI_OPENIMAGE )
  84. pScopeDataItem->nOpenImage = 0;
  85. if( pScopeDataItem->mask & SDI_PARAM )
  86. pScopeDataItem->lParam = m_scopeDataItem.lParam;
  87. if( pScopeDataItem->mask & SDI_STATE )
  88. pScopeDataItem->nState = m_scopeDataItem.nState;
  89. return S_OK;
  90. }
  91. HRESULT CRootNode::GetResultPaneInfo(RESULTDATAITEM *pResultDataItem)
  92. {
  93. if( !pResultDataItem ) return E_INVALIDARG;
  94. if( pResultDataItem->bScopeItem )
  95. {
  96. if( pResultDataItem->mask & RDI_STR )
  97. pResultDataItem->str = m_bstrDisplayName;
  98. if( pResultDataItem->mask & RDI_IMAGE )
  99. pResultDataItem->nImage = 0;
  100. if( pResultDataItem->mask & RDI_PARAM )
  101. pResultDataItem->lParam = m_scopeDataItem.lParam;
  102. return S_OK;
  103. }
  104. if( pResultDataItem->mask & RDI_STR )
  105. pResultDataItem->str = m_bstrDisplayName;
  106. if( pResultDataItem->mask & RDI_IMAGE )
  107. pResultDataItem->nImage = 0;
  108. if( pResultDataItem->mask & RDI_PARAM )
  109. pResultDataItem->lParam = m_resultDataItem.lParam;
  110. if( pResultDataItem->mask & RDI_INDEX )
  111. pResultDataItem->nIndex = m_resultDataItem.nIndex;
  112. return S_OK;
  113. }
  114. HRESULT CRootNode::GetResultViewType( LPOLESTR* ppViewType, long* pViewOptions )
  115. {
  116. if( !ppViewType ) return E_POINTER;
  117. if( !IsAdmin() )
  118. {
  119. // show standard MMC OCX with message in the result pane
  120. return StringFromCLSID(CLSID_MessageView, ppViewType);
  121. }
  122. return S_FALSE;
  123. }
  124. HRESULT CRootNode::Notify( MMC_NOTIFY_TYPE event,
  125. LPARAM arg,
  126. LPARAM param,
  127. IComponentData* pComponentData,
  128. IComponent* pComponent,
  129. DATA_OBJECT_TYPES type)
  130. {
  131. if( (event != MMCN_SHOW) && !IsAdmin() ) return E_ACCESSDENIED;
  132. HRESULT hr = S_FALSE;
  133. _ASSERTE(pComponentData != NULL || pComponent != NULL);
  134. CComPtr<IConsole> spConsole = NULL;
  135. if( pComponentData )
  136. {
  137. spConsole = ((CPOP3ServerSnapData*)pComponentData)->m_spConsole;
  138. }
  139. else if( pComponent )
  140. {
  141. spConsole = ((CPOP3ServerSnapComponent*)pComponent)->m_spConsole;
  142. }
  143. if( !spConsole ) return E_INVALIDARG;
  144. switch( event )
  145. {
  146. case MMCN_SHOW:
  147. {
  148. hr = S_OK;
  149. if( !IsAdmin() )
  150. {
  151. // configure the ocx message in the result pane
  152. IMessageView* pIMessageView = NULL;
  153. LPUNKNOWN pIUnk = NULL;
  154. hr = spConsole->QueryResultView(&pIUnk);
  155. if( SUCCEEDED(hr) )
  156. {
  157. hr = pIUnk->QueryInterface(_uuidof(IMessageView), reinterpret_cast<void**>(&pIMessageView));
  158. }
  159. if( SUCCEEDED(hr) )
  160. {
  161. hr = pIMessageView->SetIcon(Icon_Information);
  162. }
  163. if( SUCCEEDED(hr) )
  164. {
  165. tstring strTitle = StrLoadString( IDS_SNAPINNAME );
  166. hr = pIMessageView->SetTitleText( strTitle.c_str() );
  167. }
  168. if( SUCCEEDED(hr) )
  169. {
  170. tstring strMessage = StrLoadString( IDS_ERROR_ADMINONLY );
  171. hr = pIMessageView->SetBodyText( strMessage.c_str() );
  172. }
  173. if( pIMessageView )
  174. {
  175. pIMessageView->Release();
  176. pIMessageView = NULL;
  177. }
  178. if( pIUnk )
  179. {
  180. pIUnk->Release();
  181. pIUnk = NULL;
  182. }
  183. return hr;
  184. }
  185. if(arg)
  186. {
  187. tstring strHeader;
  188. CComQIPtr<IHeaderCtrl2> spHeaderCtrl = spConsole;
  189. CComQIPtr<IResultData> spResultData = spConsole;
  190. if( !spResultData || !spHeaderCtrl ) return E_NOINTERFACE;
  191. hr = spResultData->DeleteAllRsltItems();
  192. if( SUCCEEDED(hr) )
  193. {
  194. strHeader = StrLoadString(IDS_HEADER_SERVER_NAME);
  195. hr = spHeaderCtrl->InsertColumn(0, strHeader.c_str(), LVCFMT_LEFT, 100);
  196. }
  197. if( SUCCEEDED(hr) )
  198. {
  199. strHeader = StrLoadString(IDS_HEADER_SERVER_AUTH);
  200. hr = spHeaderCtrl->InsertColumn(1, strHeader.c_str(), LVCFMT_LEFT, 100);
  201. }
  202. if( SUCCEEDED(hr) )
  203. {
  204. strHeader = StrLoadString(IDS_HEADER_SERVER_ROOT);
  205. hr = spHeaderCtrl->InsertColumn(2, strHeader.c_str(), LVCFMT_LEFT, 100);
  206. }
  207. if( SUCCEEDED(hr) )
  208. {
  209. strHeader = StrLoadString(IDS_HEADER_SERVER_PORT);
  210. hr = spHeaderCtrl->InsertColumn(3, strHeader.c_str(), LVCFMT_LEFT, 100);
  211. }
  212. if( SUCCEEDED(hr) )
  213. {
  214. strHeader = StrLoadString(IDS_HEADER_SERVER_LOG);
  215. hr = spHeaderCtrl->InsertColumn(4, strHeader.c_str(), LVCFMT_LEFT, 100);
  216. }
  217. if( SUCCEEDED(hr) )
  218. {
  219. strHeader = StrLoadString(IDS_HEADER_SERVER_STATUS);
  220. hr = spHeaderCtrl->InsertColumn(5, strHeader.c_str(), LVCFMT_LEFT, 100);
  221. }
  222. if( SUCCEEDED(hr) )
  223. {
  224. CComQIPtr<IConsole2> spCons2 = spConsole;
  225. if( spCons2 )
  226. {
  227. // Output the number of servers we added
  228. tstring strMessage = StrLoadString(IDS_ROOT_STATUSBAR);
  229. OLECHAR pszStatus[1024] = {0};
  230. _sntprintf( pszStatus, 1023, strMessage.c_str(), m_lServers.size() );
  231. spCons2->SetStatusText( pszStatus );
  232. }
  233. }
  234. }
  235. break;
  236. }
  237. case MMCN_EXPAND:
  238. {
  239. hr = S_OK;
  240. // The Parameter is our inserted ID
  241. m_scopeDataItem.ID = (HSCOPEITEM)param;
  242. CComQIPtr<IConsoleNameSpace> spConsoleNameSpace = spConsole;
  243. if( !spConsoleNameSpace ) return E_NOINTERFACE;
  244. // If we have any children, delete them all from the namespace
  245. HSCOPEITEM hChild = NULL;
  246. MMC_COOKIE cookie = 0;
  247. hr = spConsoleNameSpace->GetChildItem( m_scopeDataItem.ID, &hChild, &cookie );
  248. if( SUCCEEDED(hr) && hChild )
  249. {
  250. hr = spConsoleNameSpace->DeleteItem(m_scopeDataItem.ID, FALSE);
  251. }
  252. if( FAILED(hr) || !arg )
  253. {
  254. // Error, or we are Contracting
  255. return hr;
  256. }
  257. for(SERVERLIST::iterator iter = m_lServers.begin(); iter != m_lServers.end(); iter++)
  258. {
  259. CServerNode* pServer = *iter;
  260. pServer->m_scopeDataItem.mask |= SDI_PARENT;
  261. pServer->m_scopeDataItem.relativeID = param;
  262. hr = spConsoleNameSpace->InsertItem( &(pServer->m_scopeDataItem) );
  263. if( FAILED(hr) ) return hr;
  264. }
  265. break;
  266. }
  267. case MMCN_ADD_IMAGES:
  268. {
  269. IImageList* pImageList = (IImageList*)arg;
  270. if( !pImageList ) return E_INVALIDARG;
  271. hr = LoadImages(pImageList);
  272. break;
  273. }
  274. case MMCN_SELECT:
  275. {
  276. // if selecting node
  277. if( HIWORD(arg) )
  278. {
  279. hr = S_OK;
  280. // get the verb interface and enable rename
  281. CComPtr<IConsoleVerb> spConsVerb;
  282. if( spConsole->QueryConsoleVerb(&spConsVerb) == S_OK )
  283. {
  284. // Enable the Refresh Menu
  285. hr = spConsVerb->SetVerbState(MMC_VERB_REFRESH, ENABLED, TRUE);
  286. if( FAILED(hr) ) return hr;
  287. hr = spConsVerb->SetVerbState(MMC_VERB_REFRESH, HIDDEN, FALSE);
  288. if( FAILED(hr) ) return hr;
  289. }
  290. }
  291. break;
  292. }
  293. case MMCN_RENAME:
  294. {
  295. // Allow mmc to rename node
  296. hr = S_OK;
  297. break;
  298. }
  299. case MMCN_CONTEXTHELP:
  300. {
  301. hr = S_OK;
  302. TCHAR szWindowsDir[MAX_PATH+1] = {0};
  303. tstring strHelpFile = _T("");
  304. tstring strHelpFileName = StrLoadString(IDS_HELPFILE);
  305. tstring strHelpTopicName = StrLoadString(IDS_HELPTOPIC);
  306. if( strHelpFileName.empty() || strHelpTopicName.empty() )
  307. {
  308. return E_FAIL;
  309. }
  310. // Build path to d:\windows\help
  311. UINT nSize = GetSystemWindowsDirectory( szWindowsDir, MAX_PATH );
  312. if( nSize == 0 || nSize > MAX_PATH )
  313. {
  314. return E_FAIL;
  315. }
  316. strHelpFile = szWindowsDir; // D:\windows
  317. strHelpFile += _T("\\Help\\"); // \help
  318. strHelpFile += strHelpFileName; // \filename.chm
  319. strHelpFile += _T("::/"); // ::/
  320. strHelpFile += strHelpTopicName; // index.htm
  321. // Show the Help topic
  322. CComQIPtr<IDisplayHelp> spHelp = spConsole;
  323. if( !spHelp ) return E_NOINTERFACE;
  324. hr = spHelp->ShowTopic( (LPTSTR)strHelpFile.c_str() );
  325. break;
  326. }
  327. }// switch
  328. return hr;
  329. }
  330. HRESULT CRootNode::AddMenuItems(LPCONTEXTMENUCALLBACK piCallback, long* pInsertionAllowed, DATA_OBJECT_TYPES type )
  331. {
  332. if( !piCallback || !pInsertionAllowed ) return E_INVALIDARG;
  333. HRESULT hr = S_OK;
  334. tstring strMenu = _T("");
  335. tstring strDesc = _T("");
  336. // Connecting to a remote server happens on top
  337. if( (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP) && IsAdmin() )
  338. {
  339. CComQIPtr<IContextMenuCallback2> spContext2 = piCallback;
  340. if( !spContext2 ) return E_NOINTERFACE;
  341. CONTEXTMENUITEM2 singleMenuItem;
  342. ZeroMemory(&singleMenuItem, sizeof(CONTEXTMENUITEM2));
  343. strMenu = StrLoadString(IDS_MENU_POP3_CONNECT);
  344. strDesc = StrLoadString(IDS_MENU_POP3_CONNECT_DESC);
  345. singleMenuItem.fFlags = MF_ENABLED;
  346. singleMenuItem.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_TOP;
  347. singleMenuItem.strName = (LPWSTR)strMenu.c_str();
  348. singleMenuItem.strStatusBarText = (LPWSTR)strDesc.c_str();
  349. singleMenuItem.strLanguageIndependentName = L"POP3_CONNECT";
  350. singleMenuItem.lCommandID = IDM_POP3_TOP_CONNECT;
  351. if( !strMenu.empty() )
  352. {
  353. hr = spContext2->AddItem( &singleMenuItem );
  354. }
  355. }
  356. return hr;
  357. }
  358. HRESULT CRootNode::OnConnect( bool& bHandled, CSnapInObjectRootBase* pObj )
  359. {
  360. if( !pObj ) return E_INVALIDARG;
  361. bHandled = true;
  362. HRESULT hr = S_OK;
  363. // Load a dialog that asks for a Server Name
  364. CConnectServerDlg dlg;
  365. if( dlg.DoModal() == IDOK )
  366. {
  367. HWND hWnd = NULL;
  368. CComPtr<IConsole> spConsole = NULL;
  369. hr = GetConsole(pObj, &spConsole);
  370. if( FAILED(hr) || !spConsole ) return E_NOINTERFACE;
  371. spConsole->GetMainWindow( &hWnd );
  372. // Check if the server is already connected.
  373. for(SERVERLIST::iterator iter = m_lServers.begin(); iter != m_lServers.end(); iter++)
  374. {
  375. if( (_tcsicmp((*iter)->m_bstrDisplayName, dlg.m_strName.c_str()) == 0) ||
  376. (_tcsicmp(_T("localhost"), dlg.m_strName.c_str()) == 0) )
  377. {
  378. // Server already connected
  379. tstring strMessage = StrLoadString(IDS_ERROR_SERVERNAMEEXISTS);
  380. tstring strTitle = StrLoadString(IDS_SNAPINNAME);
  381. ::MessageBox( hWnd, strMessage.c_str(), strTitle.c_str(), MB_OK | MB_ICONWARNING );
  382. return E_FAIL;
  383. }
  384. }
  385. // Add the new Domain to our list of domains
  386. CComBSTR bstrName = dlg.m_strName.c_str();
  387. CServerNode* spServerNode = new CServerNode( bstrName, this );
  388. if( spServerNode && SUCCEEDED(spServerNode->m_hrValidServer) )
  389. {
  390. spServerNode->m_scopeDataItem.relativeID = m_scopeDataItem.ID;
  391. m_lServers.push_back(spServerNode);
  392. // Add the new domain into the namespace
  393. // Insert it into the result tree
  394. CComQIPtr<IConsoleNameSpace2> spNameSpace = spConsole;
  395. if( !spNameSpace ) return E_NOINTERFACE;
  396. hr = spNameSpace->InsertItem(&(spServerNode->m_scopeDataItem));
  397. }
  398. else
  399. {
  400. delete spServerNode;
  401. if( spServerNode->m_hrValidServer != E_ACCESSDENIED )
  402. {
  403. // Invalid Server Name
  404. tstring strMessage = StrLoadString(IDS_ERROR_SERVERNAMEBAD);
  405. tstring strTitle = StrLoadString(IDS_SNAPINNAME);
  406. ::MessageBox( hWnd, strMessage.c_str(), strTitle.c_str(), MB_OK | MB_ICONWARNING );
  407. }
  408. else
  409. {
  410. // No Access to Server
  411. tstring strMessage = StrLoadString(IDS_ERROR_SERVERACCESS);
  412. tstring strTitle = StrLoadString(IDS_SNAPINNAME);
  413. ::MessageBox( hWnd, strMessage.c_str(), strTitle.c_str(), MB_OK | MB_ICONWARNING );
  414. }
  415. return E_FAIL;
  416. }
  417. }
  418. return hr;
  419. }
  420. HRESULT CRootNode::Load(IStream *pStream)
  421. {
  422. if( !pStream ) return E_INVALIDARG;
  423. // Name, Local Server, and State of User creation checkbox are what we currently save.
  424. tstring strServerName = _T("");
  425. BOOL bLocalServer = FALSE;
  426. DWORD dwVersion = 0;
  427. // New functionality to read the version.
  428. *pStream >> dwVersion;
  429. *pStream >> strServerName;
  430. while( strServerName != _T("-1") )
  431. {
  432. // For now we will put one entry.
  433. *pStream >> bLocalServer;
  434. if( !bLocalServer )
  435. {
  436. CServerNode* spServerNode = new CServerNode(CComBSTR(strServerName.c_str()), this);
  437. if( spServerNode )
  438. {
  439. m_lServers.push_back(spServerNode);
  440. }
  441. }
  442. *pStream >> strServerName;
  443. }
  444. return S_OK;
  445. }
  446. HRESULT CRootNode::Save(IStream *pStream)
  447. {
  448. if( !pStream ) return E_INVALIDARG;
  449. // Name, Local Server, and State of User creation checkbox are what we currently save.
  450. *pStream << SNAPIN_VERSION;
  451. tstring strName = _T("");
  452. for(SERVERLIST::iterator iter = m_lServers.begin(); iter != m_lServers.end(); iter++)
  453. {
  454. strName = (*iter)->m_bstrDisplayName;
  455. *pStream << strName;
  456. *pStream << (BOOL)(iter == m_lServers.begin());
  457. }
  458. strName = _T("-1");
  459. *pStream << strName;
  460. return S_OK;
  461. }