Source code of Windows XP (NT5)
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.

2756 lines
76 KiB

  1. /*++
  2. Module Name:
  3. MmcRoot.cpp
  4. Abstract:
  5. This module contains the implementation for CMmcDfsRoot. This is an class
  6. for MMC display related calls for the first level node(the DfsRoot nodes)
  7. Also contains members and method to be able to manipulate IDfsRoot object
  8. and add the same to the MMC Console
  9. --*/
  10. #include "stdafx.h"
  11. #include <winuser.h>
  12. #include "DfsGUI.h"
  13. #include "Utils.h" // For the LoadStringFromResource method
  14. #include "MenuEnum.h" // Contains the menu and toolbar command ids
  15. #include "resource.h" // For the Resource ID for strings, etc.
  16. #include "MmcAdmin.h" // For class CMmcDfsAdmin
  17. #include "MmcRoot.h"
  18. #include "MmcJP.h" // For deleteing the child Junction points in the destructor of the root object
  19. #include "MmcRep.h"
  20. #include "DfsEnums.h" // For DFS_TYPE_STANDALONE and other DfsRoot declarations
  21. #include "AddToDfs.h"
  22. #include "LinkFilt.h"
  23. #include "DfsNodes.h" // For Node GUIDs
  24. #include "DfsWiz.h" // For the wizard pages, CCreateDfsRootWizPage1, 2, ...
  25. #include <lmdfs.h>
  26. #include "permpage.h"
  27. #include "ldaputils.h"
  28. const int CMmcDfsRoot::m_iIMAGEINDEX = 0;
  29. const int CMmcDfsRoot::m_iOPENIMAGEINDEX = 0;
  30. //////////////////////////////////////////////////////////////////////////////////////////////////
  31. // Constructor For _JUNCTION_LIST
  32. JP_LIST_NODE :: JP_LIST_NODE (CMmcDfsJunctionPoint* i_pMmcJP)
  33. {
  34. pJPoint = i_pMmcJP;
  35. }
  36. //////////////////////////////////////////////////////////////////////////////////////////////////
  37. // destructor
  38. JP_LIST_NODE :: ~JP_LIST_NODE ()
  39. {
  40. SAFE_RELEASE(pJPoint);
  41. }
  42. CMmcDfsRoot::CMmcDfsRoot(
  43. IN IDfsRoot* i_pDfsRoot,
  44. IN CMmcDfsAdmin* i_pMmcDfsAdmin,
  45. IN LPCONSOLE2 i_lpConsole,
  46. IN ULONG i_ulLinkFilterMaxLimit, // = FILTERDFSLINKS_MAXLIMIT_DEFAULT,
  47. IN FILTERDFSLINKS_TYPE i_lLinkFilterType, // = FILTERDFSLINKS_TYPE_NO_FILTER,
  48. IN BSTR i_bstrLinkFilterName // = NULL
  49. )
  50. {
  51. dfsDebugOut((_T("CMmcDfsRoot::CMmcDfsRoot this=%p\n"), this));
  52. MMC_DISP_CTOR_RETURN_INVALIDARG_IF_NULL(i_pDfsRoot);
  53. MMC_DISP_CTOR_RETURN_INVALIDARG_IF_NULL(i_pMmcDfsAdmin);
  54. MMC_DISP_CTOR_RETURN_INVALIDARG_IF_NULL(i_lpConsole);
  55. HRESULT hr = S_OK;
  56. m_DfsRoot = i_pDfsRoot; // Save the IDfsRoot pointer
  57. m_pParent = i_pMmcDfsAdmin; // Save the parent pointer
  58. m_lpConsole = i_lpConsole; // Save the console pointer
  59. hr = m_DfsRoot->get_RootEntryPath(&m_bstrRootEntryPath); // Get the Root entrypath.
  60. MMC_DISP_CTOR_RETURN_HR_IF_FAILED(hr);
  61. hr = m_DfsRoot->get_DfsType((long *)&m_lDfsRootType); // Get dfsroot type from the IDfsRoot
  62. MMC_DISP_CTOR_RETURN_HR_IF_FAILED(hr);
  63. if (DFS_TYPE_FTDFS == m_lDfsRootType)
  64. {
  65. CComBSTR bstrDomainName;
  66. CComBSTR bstrDfsName;
  67. hr = m_DfsRoot->get_DomainName(&bstrDomainName);
  68. MMC_DISP_CTOR_RETURN_HR_IF_FAILED(hr);
  69. hr = m_DfsRoot->get_DfsName(&bstrDfsName);
  70. MMC_DISP_CTOR_RETURN_HR_IF_FAILED(hr);
  71. hr = GetDfsRootDisplayName(bstrDomainName, bstrDfsName, &m_bstrDisplayName);
  72. MMC_DISP_CTOR_RETURN_HR_IF_FAILED(hr);
  73. m_bNewSchema = (S_OK == GetSchemaVersionEx(bstrDomainName, FALSE));
  74. } else
  75. {
  76. m_bstrDisplayName = m_bstrRootEntryPath;
  77. MMC_DISP_CTOR_RETURN_OUTOFMEMORY_IF_NULL((BSTR)m_bstrDisplayName);
  78. CComBSTR bstrServer, bstrShare;
  79. hr = m_DfsRoot->GetOneDfsHost(&bstrServer, &bstrShare);
  80. MMC_DISP_CTOR_RETURN_HR_IF_FAILED(hr);
  81. m_bNewSchema = (S_OK == GetSchemaVersionEx(bstrServer));
  82. }
  83. m_lpConsoleNameSpace = NULL;
  84. m_CLSIDNodeType = s_guidDfsRootNodeType;
  85. m_bstrDNodeType = s_tchDfsRootNodeType;
  86. m_lRootJunctionState = DFS_JUNCTION_STATE_UNASSIGNED;
  87. m_ulLinkFilterMaxLimit = i_ulLinkFilterMaxLimit;
  88. m_lLinkFilterType = i_lLinkFilterType;
  89. if (i_bstrLinkFilterName)
  90. m_bstrLinkFilterName = i_bstrLinkFilterName;
  91. else
  92. m_bstrLinkFilterName.Empty();
  93. m_bShowFRS = FALSE;
  94. }
  95. CMmcDfsRoot::~CMmcDfsRoot(
  96. )
  97. {
  98. // Silently close all outstanding property sheets.
  99. CloseAllPropertySheets(TRUE);
  100. // Clean up display objects of children and result pane.
  101. CleanScopeChildren();
  102. CleanResultChildren();
  103. if ((IReplicaSet *)m_piReplicaSet)
  104. m_piReplicaSet.Release();
  105. dfsDebugOut((_T("CMmcDfsRoot::~CMmcDfsRoot this=%p\n"), this));
  106. }
  107. STDMETHODIMP
  108. CMmcDfsRoot::AddItemToScopePane(
  109. IN LPCONSOLENAMESPACE i_lpConsoleNameSpace,
  110. IN HSCOPEITEM i_hItemParent
  111. )
  112. /*++
  113. Routine Description:
  114. This routine adds the current item(itself) to the Scope pane.
  115. Arguments:
  116. lpConsoleNameSpace - The interface which tells add item to the scope pane. A callback
  117. hItemParent - The handle of the parent. The current item is added as this
  118. item's child
  119. --*/
  120. {
  121. RETURN_INVALIDARG_IF_NULL(i_lpConsoleNameSpace);
  122. RETURN_INVALIDARG_IF_NULL(i_hItemParent);
  123. HRESULT hr = S_OK;
  124. BOOL bReplicaSetExist = FALSE;
  125. hr = m_DfsRoot->get_ReplicaSetExist(&bReplicaSetExist);
  126. if (SUCCEEDED(hr))
  127. {
  128. SCOPEDATAITEM ScopeItemDfsRoot;
  129. ZeroMemory(&ScopeItemDfsRoot, sizeof(ScopeItemDfsRoot));
  130. ScopeItemDfsRoot.mask = SDI_IMAGE | SDI_OPENIMAGE | SDI_PARAM | SDI_STR | SDI_PARENT;
  131. ScopeItemDfsRoot.nImage = CMmcDfsRoot::m_iIMAGEINDEX + ((DFS_TYPE_FTDFS == m_lDfsRootType)? 4 : 0) + (bReplicaSetExist ? 4 : 0);
  132. ScopeItemDfsRoot.nOpenImage = CMmcDfsRoot::m_iOPENIMAGEINDEX + ((DFS_TYPE_FTDFS == m_lDfsRootType)? 4 : 0) + (bReplicaSetExist ? 4 : 0);
  133. ScopeItemDfsRoot.lParam = reinterpret_cast<LPARAM>(this);
  134. ScopeItemDfsRoot.displayname = (unsigned short *) MMC_CALLBACK;
  135. ScopeItemDfsRoot.relativeID = i_hItemParent;
  136. hr = i_lpConsoleNameSpace->InsertItem(&ScopeItemDfsRoot);
  137. RETURN_IF_FAILED(hr);
  138. m_hScopeItem = ScopeItemDfsRoot.ID;
  139. m_lpConsoleNameSpace = i_lpConsoleNameSpace;
  140. }
  141. return S_OK;
  142. }
  143. STDMETHODIMP
  144. CMmcDfsRoot::AddMenuItems(
  145. IN LPCONTEXTMENUCALLBACK i_lpContextMenuCallback,
  146. IN LPLONG i_lpInsertionAllowed
  147. )
  148. /*++
  149. Routine Description:
  150. This routine adds a context menu using the ContextMenuCallback provided.
  151. Arguments:
  152. lpContextMenuCallback - A callback(function pointer) that is used to add the menu items
  153. lpInsertionAllowed - Specifies what menus can be added and where they can be added.
  154. --*/
  155. {
  156. RETURN_INVALIDARG_IF_NULL(i_lpContextMenuCallback);
  157. // select the node to populate m_MmcRepList
  158. m_lpConsole->SelectScopeItem(m_hScopeItem);
  159. enum
  160. {
  161. IDM_CONTEXTMENU_COMMAND_MAX = IDM_ROOT_MAX,
  162. IDM_CONTEXTMENU_COMMAND_MIN = IDM_ROOT_MIN
  163. };
  164. LONG lInsertionPoints [IDM_CONTEXTMENU_COMMAND_MAX - IDM_CONTEXTMENU_COMMAND_MIN + 1] = {
  165. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  166. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  167. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  168. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  169. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  170. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  171. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  172. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  173. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  174. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  175. CCM_INSERTIONPOINTID_PRIMARY_TOP
  176. };
  177. BOOL bReplicaSetExist = FALSE;
  178. HRESULT hr = m_DfsRoot->get_ReplicaSetExist(&bReplicaSetExist);
  179. RETURN_IF_FAILED(hr);
  180. for (int iCommandID = IDM_CONTEXTMENU_COMMAND_MIN,iMenuResource = IDS_MENUS_ROOT_TOP_NEW_DFS_LINK;
  181. iCommandID <= IDM_CONTEXTMENU_COMMAND_MAX;
  182. iCommandID++,iMenuResource++ )
  183. {
  184. CONTEXTMENUITEM ContextMenuItem; // The structure which contains menu information
  185. ZeroMemory(&ContextMenuItem, sizeof(ContextMenuItem));
  186. switch (iCommandID)
  187. {
  188. case IDM_ROOT_TOP_NEW_ROOT_REPLICA:
  189. {
  190. if (DFS_TYPE_STANDALONE == m_lDfsRootType)
  191. continue;
  192. break;
  193. }
  194. case IDM_ROOT_TOP_DELETE_DISPLAYED_DFS_LINKS:
  195. {
  196. if (m_MmcJPList.empty())
  197. continue;
  198. break;
  199. }
  200. case IDM_ROOT_TOP_REPLICATION_TOPOLOGY:
  201. {
  202. if (bReplicaSetExist || (1 >= m_MmcRepList.size()) || (DFS_TYPE_STANDALONE == m_lDfsRootType))
  203. continue;
  204. break;
  205. }
  206. case IDM_ROOT_TOP_SHOW_REPLICATION:
  207. {
  208. if (!bReplicaSetExist || m_bShowFRS)
  209. continue;
  210. break;
  211. }
  212. case IDM_ROOT_TOP_HIDE_REPLICATION:
  213. {
  214. if (!bReplicaSetExist || !m_bShowFRS)
  215. continue;
  216. break;
  217. }
  218. case IDM_ROOT_TOP_STOP_REPLICATION:
  219. {
  220. if (!bReplicaSetExist)
  221. continue;
  222. break;
  223. }
  224. case IDM_ROOT_TOP_NEW_DFS_LINK:
  225. case IDM_ROOT_TOP_CHECK_STATUS:
  226. case IDM_ROOT_TOP_FILTER_DFS_LINKS:
  227. { // excluded when empty root container
  228. if (m_MmcRepList.empty())
  229. continue;
  230. break;
  231. }
  232. }
  233. CComBSTR bstrMenuText;
  234. CComBSTR bstrStatusBarText;
  235. hr = GetMenuResourceStrings(iMenuResource, &bstrMenuText, NULL, &bstrStatusBarText);
  236. RETURN_IF_FAILED(hr);
  237. ContextMenuItem.strName = bstrMenuText; // Assign the menu text
  238. ContextMenuItem.strStatusBarText = bstrStatusBarText; // Assign the menu help text
  239. ContextMenuItem.lInsertionPointID = lInsertionPoints[iCommandID - IDM_CONTEXTMENU_COMMAND_MIN];
  240. ContextMenuItem.lCommandID = iCommandID;
  241. LONG lInsertionFlag = 0;
  242. switch(ContextMenuItem.lInsertionPointID) // Checking for permission to add menus
  243. {
  244. case CCM_INSERTIONPOINTID_PRIMARY_TOP:
  245. lInsertionFlag = CCM_INSERTIONALLOWED_TOP;
  246. break;
  247. case CCM_INSERTIONPOINTID_PRIMARY_NEW:
  248. lInsertionFlag = CCM_INSERTIONALLOWED_NEW;
  249. break;
  250. case CCM_INSERTIONPOINTID_PRIMARY_TASK:
  251. lInsertionFlag = CCM_INSERTIONALLOWED_TASK;
  252. break;
  253. case CCM_INSERTIONPOINTID_PRIMARY_VIEW:
  254. lInsertionFlag = CCM_INSERTIONALLOWED_VIEW;
  255. break;
  256. default:
  257. break;
  258. }
  259. if (*i_lpInsertionAllowed & lInsertionFlag)
  260. {
  261. hr = i_lpContextMenuCallback->AddItem(&ContextMenuItem);
  262. RETURN_IF_FAILED(hr);
  263. }
  264. } // for
  265. return hr;
  266. }
  267. STDMETHODIMP
  268. CMmcDfsRoot::GetScopeDisplayInfo(
  269. IN OUT LPSCOPEDATAITEM io_pScopeDataItem
  270. )
  271. /*++
  272. Routine Description:
  273. Returns the information required for MMC display for this item.
  274. Arguments:
  275. i_pScopeDataItem - The ScopeItem which specifies what display information is required
  276. --*/
  277. {
  278. RETURN_INVALIDARG_IF_NULL(io_pScopeDataItem);
  279. HRESULT hr = S_OK;
  280. if (SDI_STR & io_pScopeDataItem->mask) // MMC wants the displaystring
  281. {
  282. ULONG ulTotalNumOfJPs = 0;
  283. hr = m_DfsRoot->get_CountOfDfsJunctionPoints((long*)&ulTotalNumOfJPs);
  284. RETURN_IF_FAILED(hr);
  285. if (m_lLinkFilterType != FILTERDFSLINKS_TYPE_NO_FILTER ||
  286. m_MmcJPList.size() < ulTotalNumOfJPs)
  287. {
  288. m_bstrFullDisplayName.Empty();
  289. hr = FormatMessageString(&m_bstrFullDisplayName,
  290. 0,
  291. IDS_DFSROOT_DISPLAY_STRING,
  292. m_bstrDisplayName);
  293. RETURN_IF_FAILED(hr);
  294. io_pScopeDataItem->displayname = m_bstrFullDisplayName;
  295. } else
  296. {
  297. io_pScopeDataItem->displayname = m_bstrDisplayName;
  298. }
  299. }
  300. if (SDI_IMAGE & io_pScopeDataItem->mask) // MMC wants the image index for the item
  301. io_pScopeDataItem->nImage = CMmcDfsRoot::m_iIMAGEINDEX + ((DFS_TYPE_FTDFS == m_lDfsRootType)? 4 : 0) + m_lRootJunctionState;
  302. if (SDI_OPENIMAGE & io_pScopeDataItem->mask) // MMC wants the image index for the item
  303. io_pScopeDataItem->nOpenImage = CMmcDfsRoot::m_iOPENIMAGEINDEX + ((DFS_TYPE_FTDFS == m_lDfsRootType)? 4 : 0) + m_lRootJunctionState;
  304. return hr;
  305. }
  306. STDMETHODIMP
  307. CMmcDfsRoot::GetResultDisplayInfo(
  308. IN OUT LPRESULTDATAITEM io_pResultDataItem
  309. )
  310. /*++
  311. Routine Description:
  312. Returns the information required for MMC display for this item.
  313. Arguments:
  314. io_pResultDataItem - The ResultItem which specifies what display information is required
  315. --*/
  316. {
  317. RETURN_INVALIDARG_IF_NULL(io_pResultDataItem);
  318. if (RDI_IMAGE & io_pResultDataItem->mask) // MMC wants the image index for the item
  319. io_pResultDataItem->nImage = CMmcDfsRoot::m_iIMAGEINDEX + ((DFS_TYPE_FTDFS == m_lDfsRootType)? 4 : 0) + m_lRootJunctionState;
  320. if (RDI_STR & io_pResultDataItem->mask) // MMC wants the text for the item
  321. {
  322. if (0 == io_pResultDataItem->nCol) // Return the Dfs Root display name
  323. io_pResultDataItem->str = m_bstrDisplayName;
  324. }
  325. return S_OK;
  326. }
  327. STDMETHODIMP
  328. CMmcDfsRoot::Command(
  329. IN LONG i_lCommandID
  330. )
  331. /*++
  332. Routine Description:
  333. Action to be taken on a context menu selection or click is takes place.
  334. Arguments:
  335. lCommandID - The Command ID of the menu for which action has to be taken
  336. --*/
  337. {
  338. HRESULT hr = S_OK;
  339. switch (i_lCommandID)
  340. {
  341. case IDM_ROOT_TOP_NEW_DFS_LINK:
  342. hr = OnCreateNewJunctionPoint ();
  343. break;
  344. case IDM_ROOT_TOP_NEW_ROOT_REPLICA:
  345. hr = OnNewRootReplica();
  346. break;
  347. case IDM_ROOT_TOP_CHECK_STATUS:
  348. hr = OnCheckStatus();
  349. break;
  350. case IDM_ROOT_TOP_DELETE_DISPLAYED_DFS_LINKS:
  351. hr = OnDeleteDisplayedDfsLinks();
  352. break;
  353. case IDM_ROOT_TOP_DELETE_DFS_ROOT: // Delete the Current dfs root
  354. hr = OnDeleteDfsRoot();
  355. break;
  356. case IDM_ROOT_TOP_DELETE_CONNECTION_TO_DFS_ROOT: // "Delete Connection to Dfs Root"
  357. hr = OnDeleteConnectionToDfsRoot();
  358. break;
  359. case IDM_ROOT_TOP_FILTER_DFS_LINKS:
  360. hr = OnFilterDfsLinks();
  361. break;
  362. case IDM_ROOT_TOP_REPLICATION_TOPOLOGY:
  363. hr = OnNewReplicaSet();
  364. break;
  365. case IDM_ROOT_TOP_SHOW_REPLICATION:
  366. case IDM_ROOT_TOP_HIDE_REPLICATION:
  367. m_bShowFRS = !m_bShowFRS;
  368. hr = OnShowReplication();
  369. break;
  370. case IDM_ROOT_TOP_STOP_REPLICATION:
  371. hr = OnStopReplication(TRUE);
  372. if (FAILED(hr))
  373. DisplayMessageBoxForHR(hr);
  374. break;
  375. default:
  376. hr = E_INVALIDARG;
  377. break;
  378. }
  379. return hr;
  380. }
  381. HRESULT CMmcDfsRoot::_InitReplicaSet()
  382. {
  383. HRESULT hr = S_OK;
  384. if (m_lDfsRootType != DFS_TYPE_FTDFS)
  385. return S_FALSE; // no replica set associate with standalone root
  386. BOOL bReplicaSetExist = FALSE;
  387. CComBSTR bstrDC;
  388. hr = m_DfsRoot->get_ReplicaSetExistEx(&bstrDC, &bReplicaSetExist);
  389. RETURN_IF_FAILED(hr);
  390. if (!bReplicaSetExist)
  391. {
  392. if ((IReplicaSet *)m_piReplicaSet)
  393. m_piReplicaSet.Release();
  394. return S_FALSE; // no replica set associate with it
  395. }
  396. if ((IReplicaSet *)m_piReplicaSet)
  397. {
  398. CComBSTR bstrTargetedDC;
  399. hr = m_piReplicaSet->get_TargetedDC(&bstrTargetedDC);
  400. if (FAILED(hr) || lstrcmpi(bstrTargetedDC, bstrDC))
  401. {
  402. // something is wrong or we're using a different DC, re-init m_piReplicaSet
  403. m_piReplicaSet.Release();
  404. }
  405. }
  406. if (!m_piReplicaSet)
  407. {
  408. CComBSTR bstrDomain;
  409. hr = m_DfsRoot->get_DomainName(&bstrDomain);
  410. RETURN_IF_FAILED(hr);
  411. CComBSTR bstrReplicaSetDN;
  412. hr = m_DfsRoot->get_ReplicaSetDN(&bstrReplicaSetDN);
  413. RETURN_IF_FAILED(hr);
  414. //
  415. // read info of the replica set from DS
  416. //
  417. hr = CoCreateInstance(CLSID_ReplicaSet, NULL, CLSCTX_INPROC_SERVER, IID_IReplicaSet, (void**) &m_piReplicaSet);
  418. RETURN_IF_FAILED(hr);
  419. hr = m_piReplicaSet->Initialize(bstrDomain, bstrReplicaSetDN);
  420. if (FAILED(hr))
  421. {
  422. m_piReplicaSet.Release();
  423. return hr;
  424. }
  425. }
  426. return hr;
  427. }
  428. HRESULT CMmcDfsRoot::OnNewReplicaSet()
  429. {
  430. //
  431. // refresh to pick up possible namespace updates on targets by others
  432. //
  433. HRESULT hr = OnRefresh();
  434. if (S_FALSE == hr)
  435. {
  436. // this root has been deleted by others, no more reference
  437. DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_INVALID_ROOT);
  438. return hr;
  439. }
  440. CWaitCursor wait;
  441. BOOL bReplicaSetExist = FALSE;
  442. m_DfsRoot->get_ReplicaSetExist(&bReplicaSetExist);
  443. if (bReplicaSetExist) // replica set exist, return
  444. return S_OK;
  445. CComBSTR bstrDomain;
  446. hr = m_DfsRoot->get_DomainName(&bstrDomain);
  447. RETURN_IF_FAILED(hr);
  448. CComBSTR bstrReplicaSetDN;
  449. hr = m_DfsRoot->get_ReplicaSetDN(&bstrReplicaSetDN);
  450. RETURN_IF_FAILED(hr);
  451. CNewReplicaSet ReplicaSetInfo;
  452. hr = ReplicaSetInfo.Initialize(bstrDomain, bstrReplicaSetDN, &m_MmcRepList);
  453. RETURN_IF_FAILED(hr);
  454. CNewReplicaSetPage0 WizPage0;
  455. CNewReplicaSetPage1 WizPage1(&ReplicaSetInfo);
  456. CNewReplicaSetPage2 WizPage2(&ReplicaSetInfo, IsNewSchema());
  457. //CNewReplicaSetPage3 WizPage3(&ReplicaSetInfo);
  458. CComPtr<IPropertySheetCallback> pPropSheetCallback; // MMC Callback used to add pages
  459. hr = m_lpConsole->QueryInterface(IID_IPropertySheetCallback, reinterpret_cast<void**>(&pPropSheetCallback));
  460. RETURN_IF_FAILED(hr);
  461. CComPtr<IPropertySheetProvider> pPropSheetProvider; // MMC callback used to handle wizard
  462. hr = m_lpConsole->QueryInterface(IID_IPropertySheetProvider, reinterpret_cast<void**>(&pPropSheetProvider));
  463. RETURN_IF_FAILED(hr);
  464. //
  465. // Create the wizard
  466. //
  467. hr = pPropSheetProvider->CreatePropertySheet(
  468. _T(""), // title
  469. FALSE, // Wizard and not property sheet.
  470. 0, // Cookie
  471. NULL, // IDataobject
  472. MMC_PSO_NEWWIZARDTYPE); // Creation flags
  473. RETURN_IF_FAILED(hr);
  474. hr = pPropSheetCallback->AddPage(WizPage0.Create());
  475. RETURN_IF_FAILED(hr);
  476. hr = pPropSheetCallback->AddPage(WizPage1.Create());
  477. RETURN_IF_FAILED(hr);
  478. hr = pPropSheetCallback->AddPage(WizPage2.Create());
  479. RETURN_IF_FAILED(hr);
  480. /*hr = pPropSheetCallback->AddPage(WizPage3.Create());
  481. RETURN_IF_FAILED(hr); */
  482. // Ask the provider to use the pages from the callback
  483. hr = pPropSheetProvider->AddPrimaryPages(
  484. //(IComponentData *)(m_pParent->m_pScopeManager),
  485. NULL,
  486. TRUE, // Don't create a notify handle
  487. NULL,
  488. TRUE // Scope pane (not result pane)
  489. );
  490. RETURN_IF_FAILED(hr);
  491. //
  492. // Display the wizard
  493. //
  494. HWND hwndParent = NULL;
  495. hr = m_lpConsole->GetMainWindow(&hwndParent);
  496. RETURN_IF_FAILED(hr);
  497. hr = pPropSheetProvider->Show((LONG_PTR)hwndParent, 0);
  498. RETURN_IF_FAILED(hr);
  499. //
  500. // handle th result
  501. //
  502. if (S_OK == ReplicaSetInfo.m_hr)
  503. {
  504. //
  505. // store the interface pointer
  506. //
  507. m_piReplicaSet = ReplicaSetInfo.m_piReplicaSet;
  508. m_DfsRoot->put_ReplicaSetExist(TRUE);
  509. //
  510. // update icon
  511. //
  512. SCOPEDATAITEM ScopeDataItem;
  513. ZeroMemory(&ScopeDataItem, sizeof(SCOPEDATAITEM));
  514. ScopeDataItem.mask = SDI_IMAGE | SDI_OPENIMAGE;
  515. ScopeDataItem.ID = m_hScopeItem;
  516. hr = m_lpConsoleNameSpace->GetItem(&ScopeDataItem);
  517. RETURN_IF_FAILED(hr);
  518. if (SUCCEEDED(hr))
  519. {
  520. ScopeDataItem.nImage += 4;
  521. ScopeDataItem.nOpenImage += 4;
  522. hr = m_lpConsoleNameSpace->SetItem(&ScopeDataItem);
  523. }
  524. m_lpConsole->SelectScopeItem(m_hScopeItem);
  525. }
  526. return hr;
  527. }
  528. HRESULT CMmcDfsRoot::OnShowReplication()
  529. {
  530. BOOL bShowFRS = m_bShowFRS; // save it because refresh will reset it to FALSE
  531. //
  532. // refresh to pick up possible namespace updates on targets by others
  533. //
  534. HRESULT hr = OnRefresh();
  535. if (S_FALSE == hr)
  536. {
  537. // this root has been deleted by others, no more reference
  538. DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_INVALID_ROOT);
  539. return hr;
  540. }
  541. CWaitCursor wait;
  542. DFS_REPLICA_LIST::iterator i;
  543. if (bShowFRS)
  544. {
  545. //
  546. // init m_piReplicaSet
  547. //
  548. hr = _InitReplicaSet();
  549. if (S_OK != hr) // no replica set, do nothing and return
  550. return S_OK;
  551. //
  552. // fill in each alternate m_bstrFRSColumnText and m_bstrStatusText
  553. //
  554. for (i = m_MmcRepList.begin(); i != m_MmcRepList.end(); i++)
  555. {
  556. ((*i)->pReplica)->ShowReplicationInfo(m_piReplicaSet);
  557. }
  558. m_bShowFRS = TRUE;
  559. }
  560. m_lpConsole->UpdateAllViews((IDataObject*)this, 0, 1);
  561. m_lpConsole->SelectScopeItem(m_hScopeItem);
  562. return hr;
  563. }
  564. HRESULT
  565. CMmcDfsRoot::OnStopReplication(BOOL bConfirm /* = FALSE */)
  566. {
  567. //
  568. // refresh to pick up possible namespace updates on targets by others
  569. //
  570. HRESULT hr = OnRefresh();
  571. if (S_FALSE == hr)
  572. {
  573. // this root has been deleted by others, no more reference
  574. DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_INVALID_ROOT);
  575. return hr;
  576. }
  577. CWaitCursor wait;
  578. BOOL bReplicaSetExist = FALSE;
  579. m_DfsRoot->get_ReplicaSetExist(&bReplicaSetExist);
  580. if (!bReplicaSetExist) // replica set doesn't exist, return
  581. return S_OK;
  582. if (bConfirm)
  583. {
  584. hr = ConfirmOperationOnDfsRoot(IDS_MSG_STOP_REPLICATION);
  585. if (S_OK != hr) return hr;
  586. }
  587. //
  588. // init m_piReplicaSet
  589. //
  590. hr = _InitReplicaSet();
  591. if (S_OK != hr) // no replica set, return
  592. return hr;
  593. hr = m_piReplicaSet->Delete();
  594. if (SUCCEEDED(hr))
  595. {
  596. m_piReplicaSet.Release();
  597. hr = m_DfsRoot->put_ReplicaSetExist(FALSE);
  598. SCOPEDATAITEM ScopeDataItem;
  599. ZeroMemory(&ScopeDataItem, sizeof(SCOPEDATAITEM));
  600. ScopeDataItem.mask = SDI_IMAGE | SDI_OPENIMAGE;
  601. ScopeDataItem.ID = m_hScopeItem;
  602. hr = m_lpConsoleNameSpace->GetItem(&ScopeDataItem);
  603. if (SUCCEEDED(hr))
  604. {
  605. ScopeDataItem.nImage -= 4;
  606. ScopeDataItem.nOpenImage -= 4;
  607. (void) m_lpConsoleNameSpace->SetItem(&ScopeDataItem);
  608. }
  609. m_lpConsole->SelectScopeItem(m_hScopeItem);
  610. }
  611. return hr;
  612. }
  613. STDMETHODIMP
  614. CMmcDfsRoot::OnNewRootReplica(
  615. )
  616. /*++
  617. Routine Description:
  618. Action to be taken on menu command "New Root Replica Member".
  619. Here is a wizard is used to guide the user through the process of
  620. Deciding a new server and share.
  621. --*/
  622. {
  623. // Select this node to make sure m_MmcRepList populated
  624. m_lpConsole->SelectScopeItem(m_hScopeItem);
  625. RETURN_INVALIDARG_IF_NULL((IConsole*)m_lpConsole);
  626. CREATEDFSROOTWIZINFO CreateWizInfo; // 0 initializes all members to 0. Necessary
  627. CreateWizInfo.pMMCAdmin = m_pParent;
  628. CreateWizInfo.bRootReplica = true; // Set the flag that says this is for root replica
  629. // Set the domain name and the dfs type
  630. HRESULT hr = m_DfsRoot->get_DomainName(&CreateWizInfo.bstrSelectedDomain);
  631. RETURN_IF_FAILED(hr);
  632. CreateWizInfo.DfsType = DFS_TYPE_FTDFS;
  633. hr = m_DfsRoot->get_DfsName(&CreateWizInfo.bstrDfsRootName);
  634. RETURN_IF_FAILED(hr);
  635. CCreateDfsRootWizPage4 WizPage4(&CreateWizInfo);
  636. CCreateDfsRootWizPage5 WizPage5(&CreateWizInfo);
  637. CCreateDfsRootWizPage7 WizPage7(&CreateWizInfo);
  638. // Get the required interfaces from IConsole2.
  639. CComPtr<IPropertySheetCallback> pPropSheetCallback; // MMC Callback used to add pages
  640. hr = m_lpConsole->QueryInterface(IID_IPropertySheetCallback, reinterpret_cast<void**>(&pPropSheetCallback));
  641. RETURN_IF_FAILED(hr);
  642. CComPtr<IPropertySheetProvider> pPropSheetProvider; // MMC callback used to handle wizard
  643. hr = m_lpConsole->QueryInterface(IID_IPropertySheetProvider, reinterpret_cast<void**>(&pPropSheetProvider));
  644. RETURN_IF_FAILED(hr);
  645. // Create the wizard
  646. hr = pPropSheetProvider->CreatePropertySheet(
  647. _T(""), // Property sheet title. Should not be null so send empty string.
  648. FALSE, // Wizard and not property sheet.
  649. 0, // Cookie
  650. NULL, // IDataobject
  651. MMC_PSO_NEWWIZARDTYPE); // Creation flags
  652. RETURN_IF_FAILED(hr);
  653. // Create the pages for the wizard. Use the handle return to add to our wizard
  654. hr = pPropSheetCallback->AddPage(WizPage4.Create());
  655. RETURN_IF_FAILED(hr);
  656. hr = pPropSheetCallback->AddPage(WizPage5.Create());
  657. RETURN_IF_FAILED(hr);
  658. hr = pPropSheetCallback->AddPage(WizPage7.Create());
  659. RETURN_IF_FAILED(hr);
  660. _ASSERT(NULL != (m_pParent->m_pScopeManager));
  661. // Ask the provider to use the pages from the callback
  662. hr = pPropSheetProvider->AddPrimaryPages( (IComponentData *)(m_pParent->m_pScopeManager),
  663. TRUE, // Don't create a notify handle
  664. NULL,
  665. TRUE // Scope pane (not result pane)
  666. );
  667. RETURN_IF_FAILED(hr);
  668. HWND hwndMainWin = 0; // MMC main window. Used to make it modal
  669. hr = m_lpConsole->GetMainWindow(&hwndMainWin); // Get the main MMC window
  670. RETURN_IF_FAILED(hr);
  671. // Display the wizard
  672. hr = pPropSheetProvider->Show((LONG_PTR)hwndMainWin, // Parent window of the wizard
  673. 0 // Starting page
  674. );
  675. RETURN_IF_FAILED(hr);
  676. if (CreateWizInfo.bDfsSetupSuccess)
  677. {
  678. return OnRefresh(); // to pick the most recent root targets and links
  679. }
  680. return (S_OK);
  681. }
  682. STDMETHODIMP
  683. CMmcDfsRoot::SetColumnHeader(
  684. IN LPHEADERCTRL2 i_piHeaderControl
  685. )
  686. {
  687. RETURN_INVALIDARG_IF_NULL(i_piHeaderControl);
  688. CComBSTR bstrColumn0;
  689. HRESULT hr = LoadStringFromResource(IDS_RESULT_COLUMN_ROOTREPLICA, &bstrColumn0);
  690. RETURN_IF_FAILED(hr);
  691. i_piHeaderControl->InsertColumn(0, bstrColumn0, LVCFMT_LEFT, DFS_NAME_COLUMN_WIDTH);
  692. if (m_bShowFRS)
  693. {
  694. CComBSTR bstrColumn1;
  695. hr = LoadStringFromResource(IDS_RESULT_COLUMN_FRS, &bstrColumn1);
  696. RETURN_IF_FAILED(hr);
  697. i_piHeaderControl->InsertColumn(1, bstrColumn1, LVCFMT_LEFT, MMCLV_AUTO);
  698. }
  699. return hr;
  700. }
  701. STDMETHODIMP
  702. CMmcDfsRoot::OnDeleteConnectionToDfsRoot(
  703. BOOLEAN i_bForRemoveDfs
  704. )
  705. /*++
  706. Routine Description:
  707. Used to delete the current object. Both to remove from Scope and from list
  708. --*/
  709. {
  710. // check outstanding property sheet, discontinue if any.
  711. HRESULT hr = CloseAllPropertySheets(FALSE);
  712. if (S_OK != hr)
  713. return hr;
  714. // Confirm with the user, if he wants to delete this connection
  715. hr = ConfirmOperationOnDfsRoot(i_bForRemoveDfs ? IDS_MSG_DELETE_DFSROOT : IDS_MSG_DELETE_CONNECTION_TO_DFSROOT);
  716. if (S_OK != hr) return hr;
  717. // select the root node
  718. m_lpConsole->SelectScopeItem(m_hScopeItem);
  719. CWaitCursor wait;
  720. CleanScopeChildren();
  721. // Delete the item from Scope Pane
  722. hr = m_lpConsoleNameSpace->DeleteItem(m_hScopeItem, TRUE);
  723. RETURN_IF_FAILED(hr);
  724. // Delete it from the internal list
  725. hr = m_pParent->DeleteMmcRootNode(this);
  726. RETURN_IF_FAILED(hr);
  727. Release(); // delete this CMmcDfsRoot object
  728. return S_OK;
  729. }
  730. // Delete the node from m_MmcJPList
  731. STDMETHODIMP
  732. CMmcDfsRoot::DeleteMmcJPNode(
  733. IN CMmcDfsJunctionPoint* i_pJPoint
  734. )
  735. {
  736. RETURN_INVALIDARG_IF_NULL(i_pJPoint);
  737. dfsDebugOut((_T("CMmcDfsRoot::DeleteMmcJPNode %p, size=%d\n"), i_pJPoint, m_MmcJPList.size()));
  738. for (DFS_JUNCTION_LIST::iterator i = m_MmcJPList.begin(); i != m_MmcJPList.end(); i++)
  739. {
  740. if ((*i)->pJPoint == i_pJPoint)
  741. {
  742. m_MmcJPList.erase(i);
  743. break;
  744. }
  745. }
  746. return(S_OK);
  747. }
  748. HRESULT
  749. CMmcDfsRoot::ConfirmOperationOnDfsRoot(int idString)
  750. /*++
  751. Routine Description:
  752. Used to confirm with the user, if he wants to delete the connection to the Dfs Root
  753. Return value:
  754. S_OK, if the user wants to delete.
  755. S_FALSE, if the user decided not to continue with the operation.
  756. --*/
  757. {
  758. // Confirm delete operation
  759. CComBSTR bstrAppName;
  760. HRESULT hr = LoadStringFromResource(IDS_APPLICATION_NAME, &bstrAppName);
  761. RETURN_IF_FAILED(hr);
  762. CComBSTR bstrFormattedMessage;
  763. hr = FormatResourceString(idString, m_bstrDisplayName, &bstrFormattedMessage);
  764. RETURN_IF_FAILED(hr);
  765. // Return now, if the user doesn't want to continue
  766. CThemeContextActivator activator;
  767. if (IDYES != ::MessageBox(::GetActiveWindow(), bstrFormattedMessage, bstrAppName, MB_YESNO | MB_ICONEXCLAMATION | MB_APPLMODAL))
  768. {
  769. return S_FALSE;
  770. }
  771. return S_OK;
  772. }
  773. HRESULT
  774. CMmcDfsRoot::ConfirmDeleteDisplayedDfsLinks(
  775. )
  776. {
  777. // Confirm delete operation
  778. CComBSTR bstrAppName;
  779. HRESULT hr = LoadStringFromResource(IDS_APPLICATION_NAME, &bstrAppName);
  780. RETURN_IF_FAILED(hr);
  781. CComBSTR bstrMessage;
  782. hr = LoadStringFromResource(IDS_MSG_DELETE_DISPLAYEDDFSLINKS, &bstrMessage);
  783. RETURN_IF_FAILED(hr);
  784. // Return now, if the user doesn't want to continue
  785. CThemeContextActivator activator;
  786. if (IDYES != ::MessageBox(::GetActiveWindow(), bstrMessage, bstrAppName, MB_YESNO | MB_ICONEXCLAMATION | MB_APPLMODAL))
  787. {
  788. return S_FALSE;
  789. }
  790. return S_OK;
  791. }
  792. STDMETHODIMP
  793. CMmcDfsRoot::EnumerateScopePane(
  794. IN LPCONSOLENAMESPACE i_lpConsoleNameSpace,
  795. IN HSCOPEITEM i_hParent
  796. )
  797. /*++
  798. Routine Description:
  799. To eumerate(add) items in the scope pane. Junction points in this case
  800. Arguments:
  801. i_lpConsoleNameSpace - The callback used to add items to the Scope pane
  802. i_hParent - HSCOPEITEM of the parent under which all the items will be added.
  803. --*/
  804. {
  805. RETURN_INVALIDARG_IF_NULL(i_lpConsoleNameSpace);
  806. RETURN_INVALIDARG_IF_NULL(i_hParent);
  807. HRESULT hr = m_DfsRoot->put_EnumFilterType(m_lLinkFilterType);
  808. RETURN_IF_FAILED(hr);
  809. if (m_lLinkFilterType != FILTERDFSLINKS_TYPE_NO_FILTER)
  810. {
  811. hr = m_DfsRoot->put_EnumFilter(m_bstrLinkFilterName);
  812. RETURN_IF_FAILED(hr);
  813. }
  814. CComPtr<IEnumVARIANT> pJPEnum;
  815. hr = m_DfsRoot->get__NewEnum((IUnknown**) (&pJPEnum));
  816. RETURN_IF_FAILED(hr);
  817. hr = m_DfsRoot->get_CountOfDfsJunctionPointsFiltered((long*)&m_ulCountOfDfsJunctionPointsFiltered);
  818. RETURN_IF_FAILED(hr);
  819. VARIANT varJPObject;
  820. VariantInit(&varJPObject);
  821. ULONG ulCount = 0;
  822. while ( ulCount < m_ulLinkFilterMaxLimit && S_OK == (hr = pJPEnum->Next(1, &varJPObject, NULL)) )
  823. {
  824. CComPtr<IDfsJunctionPoint> pDfsJPObject;
  825. pDfsJPObject = (IDfsJunctionPoint*) varJPObject.pdispVal;
  826. // Create the object to be used for MMC display
  827. CMmcDfsJunctionPoint* pMMCJPObject = new CMmcDfsJunctionPoint (pDfsJPObject, this, i_lpConsoleNameSpace);
  828. if (!pMMCJPObject)
  829. {
  830. hr = E_OUTOFMEMORY;
  831. } else
  832. {
  833. hr = pMMCJPObject->m_hrValueFromCtor;
  834. if (SUCCEEDED(hr))
  835. hr = pMMCJPObject->AddItemToScopePane(i_hParent);
  836. if (SUCCEEDED(hr))
  837. {
  838. JP_LIST_NODE *pJPList = new JP_LIST_NODE (pMMCJPObject);
  839. if (!pJPList)
  840. hr = E_OUTOFMEMORY;
  841. else
  842. m_MmcJPList.push_back(pJPList);
  843. }
  844. if (FAILED(hr))
  845. delete pMMCJPObject;
  846. }
  847. VariantClear(&varJPObject);
  848. if (FAILED(hr))
  849. break;
  850. ulCount++;
  851. }
  852. return hr;
  853. }
  854. STDMETHODIMP
  855. CMmcDfsRoot::SetConsoleVerbs(
  856. IN LPCONSOLEVERB i_lpConsoleVerb
  857. )
  858. /*++
  859. Routine Description:
  860. Routine used to set the console verb settings.
  861. Sets all of them except Open off.
  862. For all scope pane items, default verb is "open'. For result items,
  863. it is "properties"
  864. Arguments:
  865. i_lpConsoleVerb - The callback used to handle console verbs
  866. --*/
  867. {
  868. RETURN_INVALIDARG_IF_NULL(i_lpConsoleVerb);
  869. i_lpConsoleVerb->SetVerbState(MMC_VERB_COPY, HIDDEN, TRUE);
  870. i_lpConsoleVerb->SetVerbState(MMC_VERB_PASTE, HIDDEN, TRUE);
  871. i_lpConsoleVerb->SetVerbState(MMC_VERB_RENAME, HIDDEN, TRUE);
  872. i_lpConsoleVerb->SetVerbState(MMC_VERB_PRINT, HIDDEN, TRUE);
  873. i_lpConsoleVerb->SetVerbState(MMC_VERB_DELETE, HIDDEN, TRUE);
  874. i_lpConsoleVerb->SetVerbState(MMC_VERB_OPEN, HIDDEN, TRUE);
  875. i_lpConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, TRUE);
  876. i_lpConsoleVerb->SetVerbState(MMC_VERB_REFRESH, ENABLED, TRUE);
  877. i_lpConsoleVerb->SetDefaultVerb(MMC_VERB_OPEN); //For scope items, default verb is "open"
  878. return S_OK;
  879. }
  880. STDMETHODIMP
  881. CMmcDfsRoot :: OnCreateNewJunctionPoint(
  882. )
  883. /*++
  884. Routine Description:
  885. This method handles the creation of new Junction Points.
  886. Display a dialog box to get the user input.
  887. --*/
  888. {
  889. CAddToDfs AddToDfsDlg; //Add To Dfs Dialog Object
  890. HRESULT hr = AddToDfsDlg.put_ParentPath(m_bstrRootEntryPath);
  891. RETURN_IF_FAILED(hr);
  892. hr = AddToDfsDlg.DoModal(); // Display the dialog box
  893. RETURN_IF_NOT_S_OK(hr);
  894. hr = OnRefresh();
  895. if (S_FALSE == hr)
  896. {
  897. //
  898. // this root has been deleted by other means, scope pane has been refreshed,
  899. // ask user to retry
  900. //
  901. DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_INVALID_ROOT);
  902. return hr;
  903. }
  904. CWaitCursor wait;
  905. CComBSTR bstrJPName;
  906. hr = AddToDfsDlg.get_JPName(&bstrJPName);
  907. RETURN_IF_FAILED(hr);
  908. CComBSTR bstrServerName;
  909. hr = AddToDfsDlg.get_Server(&bstrServerName);
  910. RETURN_IF_FAILED(hr);
  911. CComBSTR bstrShareName;
  912. hr = AddToDfsDlg.get_Share(&bstrShareName);
  913. RETURN_IF_FAILED(hr);
  914. CComBSTR bstrComment;
  915. hr = AddToDfsDlg.get_Comment(&bstrComment);
  916. RETURN_IF_FAILED(hr);
  917. long lTimeout = 0;
  918. hr = AddToDfsDlg.get_Time(&lTimeout);
  919. RETURN_IF_FAILED(hr);
  920. /* we allow interlink at the junction level
  921. // Is it a Dfs based path? These are not allowed.
  922. if (IsDfsPath(bstrSharePath))
  923. {
  924. DisplayMessageBoxWithOK(IDS_MSG_MID_JUNCTION, bstrSharePath);
  925. return(S_OK);
  926. }
  927. */
  928. hr = OnCreateNewJunctionPoint(bstrJPName, bstrServerName, bstrShareName, bstrComment, lTimeout);
  929. if (FAILED(hr))
  930. {
  931. DisplayMessageBox(::GetActiveWindow(), MB_OK, hr, IDS_MSG_FAILED_TO_CREATE_JUNCTION_POINT);
  932. }
  933. return hr;
  934. }
  935. STDMETHODIMP
  936. CMmcDfsRoot :: OnCreateNewJunctionPoint(
  937. IN LPCTSTR i_szJPName,
  938. IN LPCTSTR i_szServerName,
  939. IN LPCTSTR i_szShareName,
  940. IN LPCTSTR i_szComment,
  941. IN long i_lTimeout
  942. )
  943. /*++
  944. Routine Description:
  945. This method handles the creation of new Junction Points.
  946. It is called by the method that display the message box
  947. --*/
  948. {
  949. RETURN_INVALIDARG_IF_NULL(i_szJPName);
  950. RETURN_INVALIDARG_IF_NULL(i_szServerName);
  951. RETURN_INVALIDARG_IF_NULL(i_szShareName);
  952. RETURN_INVALIDARG_IF_NULL(i_szComment);
  953. VARIANT varJPObject;
  954. VariantInit(&varJPObject);
  955. HRESULT hr = m_DfsRoot->CreateJunctionPoint(
  956. (LPTSTR)i_szJPName,
  957. (LPTSTR)i_szServerName,
  958. (LPTSTR)i_szShareName,
  959. (LPTSTR)i_szComment,
  960. i_lTimeout,
  961. &varJPObject);
  962. RETURN_IF_FAILED(hr);
  963. // Add the newly created junction point to scope pane if matches the filter
  964. if ( m_MmcJPList.size() < m_ulLinkFilterMaxLimit &&
  965. FilterMatch(i_szJPName, m_lLinkFilterType, m_bstrLinkFilterName) )
  966. {
  967. m_ulCountOfDfsJunctionPointsFiltered++;
  968. CComPtr<IDfsJunctionPoint> pDfsJPObject = (IDfsJunctionPoint*)varJPObject.pdispVal;
  969. // Create the object to be used for MMC display
  970. CMmcDfsJunctionPoint* pMMCJPObject = new CMmcDfsJunctionPoint(pDfsJPObject, this, m_lpConsoleNameSpace);
  971. if (!pMMCJPObject)
  972. {
  973. hr = E_OUTOFMEMORY;
  974. } else
  975. {
  976. hr = pMMCJPObject->m_hrValueFromCtor;
  977. if (SUCCEEDED(hr))
  978. hr = pMMCJPObject->AddItemToScopePane(m_hScopeItem);
  979. if (SUCCEEDED(hr))
  980. {
  981. JP_LIST_NODE* pJPList = new JP_LIST_NODE(pMMCJPObject);
  982. if (!pJPList)
  983. hr = E_OUTOFMEMORY;
  984. else
  985. m_MmcJPList.push_back(pJPList);
  986. }
  987. // Select the newly added scope item.
  988. if (SUCCEEDED(hr))
  989. {
  990. m_lpConsole->SelectScopeItem(pMMCJPObject->m_hScopeItem);
  991. } else
  992. delete pMMCJPObject;
  993. }
  994. }
  995. VariantClear(&varJPObject);
  996. return hr;
  997. }
  998. STDMETHODIMP
  999. CMmcDfsRoot::DoDelete()
  1000. /*++
  1001. Routine Description:
  1002. This method allows the item to delete itself.
  1003. Called when DEL key is pressed or when the "Delete" context menu
  1004. item is selected.
  1005. --*/
  1006. {
  1007. return OnDeleteConnectionToDfsRoot();
  1008. }
  1009. STDMETHODIMP CMmcDfsRoot::OnDeleteDfsRoot()
  1010. {
  1011. // Select this node to make sure m_MmcRepList populated
  1012. m_lpConsole->SelectScopeItem(m_hScopeItem);
  1013. // check outstanding property sheet, discontinue if any.
  1014. HRESULT hr = CloseAllPropertySheets(FALSE);
  1015. if (S_OK != hr)
  1016. return hr;
  1017. if (DFS_TYPE_STANDALONE == m_lDfsRootType)
  1018. {
  1019. hr = OnDeleteConnectionToDfsRoot(true);
  1020. if (S_OK == hr)
  1021. {
  1022. CComBSTR bstrDfsServer;
  1023. CComBSTR bstrRootShare;
  1024. hr = m_DfsRoot->GetOneDfsHost(&bstrDfsServer, &bstrRootShare);
  1025. if (SUCCEEDED(hr))
  1026. return _DeleteDfsRoot(bstrDfsServer, bstrRootShare, NULL);
  1027. }
  1028. if (FAILED(hr))
  1029. DisplayMessageBoxForHR(hr);
  1030. return hr;
  1031. }
  1032. // Confirm with the user, if he wants to delete this dfs root
  1033. hr = ConfirmOperationOnDfsRoot(IDS_MSG_DELETE_DFSROOT);
  1034. if (S_OK != hr) return hr;
  1035. //
  1036. // delete the replica set associated with the root (the internal link)
  1037. //
  1038. hr = OnStopReplication();
  1039. if (S_FALSE == hr)
  1040. {
  1041. // this root has already been deleted by others, no more reference
  1042. // OnStopReplication has already called OnRefresh and popped up the msgbox
  1043. return hr;
  1044. }
  1045. //
  1046. // delete the rest of replica sets related to this Dfs root
  1047. //
  1048. (void)m_DfsRoot->DeleteAllReplicaSets();
  1049. //
  1050. // remove root alternates
  1051. //
  1052. UINT nSize = m_MmcRepList.size();
  1053. DFS_REPLICA_LIST::iterator i;
  1054. while (nSize >= 1)
  1055. {
  1056. i = m_MmcRepList.begin();
  1057. hr = (*i)->pReplica->RemoveReplica();
  1058. BREAK_IF_FAILED(hr);
  1059. nSize--;
  1060. }
  1061. if (FAILED(hr))
  1062. DisplayMessageBoxForHR(hr);
  1063. return hr;
  1064. }
  1065. STDMETHODIMP CMmcDfsRoot::OnDeleteDisplayedDfsLinks()
  1066. {
  1067. // make sure all property pages are closed
  1068. HRESULT hr = ClosePropertySheetsOfAllLinks(FALSE);
  1069. if (S_OK != hr)
  1070. return hr; // property page found, discontinue
  1071. // Confirm with the user, if he wants to delete all the displayed dfs links
  1072. hr = ConfirmDeleteDisplayedDfsLinks();
  1073. if (S_OK != hr) return hr;
  1074. //
  1075. // refresh to pick up possible namespace updates by other means on root targets
  1076. //
  1077. hr = OnRefresh();
  1078. if (S_FALSE == hr)
  1079. {
  1080. //
  1081. // this root has been deleted by other means, scope pane has been refreshed,
  1082. // ask user to retry
  1083. //
  1084. DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_INVALID_ROOT);
  1085. return hr;
  1086. }
  1087. CWaitCursor wait;
  1088. ULONG ulSize = m_MmcJPList.size();
  1089. BOOL bSetNoFilter = TRUE;
  1090. if (m_lLinkFilterType != FILTERDFSLINKS_TYPE_NO_FILTER)
  1091. {
  1092. ULONG ulNumOfJPsFiltered = 0;
  1093. m_DfsRoot->get_CountOfDfsJunctionPointsFiltered((long*)&ulNumOfJPsFiltered);
  1094. if (ulNumOfJPsFiltered > ulSize)
  1095. bSetNoFilter = FALSE;
  1096. }
  1097. DFS_JUNCTION_LIST::iterator i;
  1098. while (ulSize >= 1)
  1099. {
  1100. i = m_MmcJPList.begin();
  1101. hr = ((*i)->pJPoint)->OnRemoveJP(FALSE);
  1102. BREAK_IF_FAILED(hr);
  1103. ulSize--;
  1104. }
  1105. if (FAILED(hr))
  1106. {
  1107. DisplayMessageBoxForHR(hr);
  1108. } else
  1109. {
  1110. if (bSetNoFilter)
  1111. m_lLinkFilterType = FILTERDFSLINKS_TYPE_NO_FILTER;
  1112. // Enumerate Junction points
  1113. (void)EnumerateScopePane(m_lpConsoleNameSpace, m_hScopeItem);
  1114. m_lpConsole->UpdateAllViews((IDataObject*)this, 0, 1);
  1115. m_lpConsole->SelectScopeItem(m_hScopeItem);
  1116. }
  1117. return hr;
  1118. }
  1119. STDMETHODIMP
  1120. CMmcDfsRoot :: OnFilterDfsLinks(
  1121. )
  1122. /*++
  1123. Routine Description:
  1124. This method handles the link filter options.
  1125. Display a dialog box to get the user input.
  1126. --*/
  1127. {
  1128. HRESULT hr = ClosePropertySheetsOfAllLinks(FALSE);
  1129. if (S_OK != hr)
  1130. return hr; // property sheet found, discontinue
  1131. CFilterDfsLinks FilterDfsLinksDlg;
  1132. hr = FilterDfsLinksDlg.put_EnumFilterType(m_lLinkFilterType);
  1133. RETURN_IF_FAILED(hr);
  1134. if (m_lLinkFilterType != FILTERDFSLINKS_TYPE_NO_FILTER)
  1135. {
  1136. hr = FilterDfsLinksDlg.put_EnumFilter(m_bstrLinkFilterName);
  1137. RETURN_IF_FAILED(hr);
  1138. }
  1139. hr = FilterDfsLinksDlg.put_MaxLimit(m_ulLinkFilterMaxLimit);
  1140. RETURN_IF_FAILED(hr);
  1141. hr = FilterDfsLinksDlg.DoModal();
  1142. RETURN_IF_NOT_S_OK(hr);
  1143. CWaitCursor wait;
  1144. ULONG ulMaxLimit = 0;
  1145. hr = FilterDfsLinksDlg.get_MaxLimit(&ulMaxLimit);
  1146. RETURN_IF_FAILED(hr);
  1147. FILTERDFSLINKS_TYPE lLinkFilterType = FILTERDFSLINKS_TYPE_NO_FILTER;
  1148. hr = FilterDfsLinksDlg.get_EnumFilterType(&lLinkFilterType);
  1149. RETURN_IF_FAILED(hr);
  1150. CComBSTR bstrFilterName;
  1151. if (lLinkFilterType != FILTERDFSLINKS_TYPE_NO_FILTER)
  1152. {
  1153. hr = FilterDfsLinksDlg.get_EnumFilter(&bstrFilterName);
  1154. RETURN_IF_FAILED(hr);
  1155. }
  1156. m_lLinkFilterType = lLinkFilterType;
  1157. m_bstrLinkFilterName = bstrFilterName;
  1158. m_ulLinkFilterMaxLimit = ulMaxLimit;
  1159. dfsDebugOut((_T("m_lLinkFilterType=%d, m_bstrLinkFilterName=%s, m_ulLinkFilterMaxLimit=%d\n"),
  1160. m_lLinkFilterType,
  1161. m_bstrLinkFilterName,
  1162. m_ulLinkFilterMaxLimit));
  1163. return OnRefresh();
  1164. }
  1165. HRESULT
  1166. CMmcDfsRoot::SetDescriptionBarText(
  1167. IN LPRESULTDATA i_lpResultData
  1168. )
  1169. /*++
  1170. Routine Description:
  1171. A routine used set the text in the Description bar above
  1172. the result view.
  1173. Arguments:
  1174. i_lpResultData - Pointer to the IResultData callback which is
  1175. used to set the description text
  1176. --*/
  1177. {
  1178. RETURN_INVALIDARG_IF_NULL(i_lpResultData);
  1179. CComBSTR bstrTextForDescriptionBar;
  1180. HRESULT hr = FormatResourceString(IDS_DESCRIPTION_BAR_TEXT_ROOT, m_bstrDisplayName, &bstrTextForDescriptionBar);
  1181. if (SUCCEEDED(hr))
  1182. hr = i_lpResultData->SetDescBarText(bstrTextForDescriptionBar);
  1183. return hr;
  1184. }
  1185. HRESULT
  1186. CMmcDfsRoot::SetStatusText(
  1187. IN LPCONSOLE2 i_lpConsole
  1188. )
  1189. /*++
  1190. Routine Description:
  1191. Set the text in the Status bar.
  1192. Arguments:
  1193. i_lpConsole - IConsole2 from IComponent
  1194. --*/
  1195. {
  1196. RETURN_INVALIDARG_IF_NULL(i_lpConsole);
  1197. HRESULT hr = S_OK;
  1198. ULONG ulTotalNumOfJPs = 0;
  1199. hr = m_DfsRoot->get_CountOfDfsJunctionPoints((long*)&ulTotalNumOfJPs);
  1200. RETURN_IF_FAILED(hr);
  1201. ULONG ulDisplayedNumOfJPs = m_MmcJPList.size();
  1202. CComBSTR bstrText;
  1203. hr = FormatMessageString(&bstrText, 0,
  1204. IDS_STATUS_BAR_TEXT_ROOT, ulDisplayedNumOfJPs, ulTotalNumOfJPs);
  1205. if (SUCCEEDED(hr))
  1206. hr = i_lpConsole->SetStatusText(bstrText);
  1207. return hr;
  1208. }
  1209. STDMETHODIMP
  1210. CMmcDfsRoot::EnumerateResultPane(
  1211. IN OUT IResultData* io_pResultData
  1212. )
  1213. /*++
  1214. Routine Description:
  1215. To eumerate(add) items in the result pane. Root level Replicas in this case
  1216. Arguments:
  1217. io_pResultData - The callback used to add items to the Result pane
  1218. --*/
  1219. {
  1220. RETURN_INVALIDARG_IF_NULL(io_pResultData);
  1221. HRESULT hr = S_OK;
  1222. if (m_MmcRepList.empty())
  1223. {
  1224. CComPtr<IEnumVARIANT> pRepEnum;
  1225. hr = m_DfsRoot->get_RootReplicaEnum((IUnknown**) &pRepEnum);
  1226. RETURN_IF_FAILED(hr);
  1227. VARIANT varReplicaObject;
  1228. VariantInit(&varReplicaObject);
  1229. while ( S_OK == (hr = pRepEnum->Next(1, &varReplicaObject, NULL)) )
  1230. {
  1231. CComPtr<IDfsReplica> pReplicaObject = (IDfsReplica*) varReplicaObject.pdispVal;
  1232. CMmcDfsReplica* pMMCReplicaObject = new CMmcDfsReplica(pReplicaObject, this);
  1233. if (!pMMCReplicaObject)
  1234. {
  1235. hr = E_OUTOFMEMORY;
  1236. } else
  1237. {
  1238. hr = pMMCReplicaObject->m_hrValueFromCtor;
  1239. if (SUCCEEDED(hr))
  1240. hr = pMMCReplicaObject->AddItemToResultPane(io_pResultData);
  1241. if (SUCCEEDED(hr))
  1242. {
  1243. REP_LIST_NODE* pRepNode = new REP_LIST_NODE (pMMCReplicaObject);
  1244. if (!pRepNode)
  1245. hr = E_OUTOFMEMORY;
  1246. else
  1247. m_MmcRepList.push_back(pRepNode);
  1248. }
  1249. if (FAILED(hr))
  1250. delete pMMCReplicaObject;
  1251. }
  1252. VariantClear(&varReplicaObject);
  1253. if (FAILED(hr))
  1254. break;
  1255. } // while
  1256. }
  1257. else
  1258. {
  1259. // The replicas of this junction are already enumerated,
  1260. // and the list exists, just add result items.
  1261. for (DFS_REPLICA_LIST::iterator i = m_MmcRepList.begin(); i != m_MmcRepList.end(); i++)
  1262. {
  1263. hr = ((*i)->pReplica)->AddItemToResultPane(io_pResultData);
  1264. BREAK_IF_FAILED(hr);
  1265. }
  1266. }
  1267. return hr;
  1268. }
  1269. STDMETHODIMP
  1270. CMmcDfsRoot::QueryPagesFor(
  1271. )
  1272. /*++
  1273. Routine Description:
  1274. Used to decide whether the object wants to display property pages.
  1275. Returning S_OK typically results in a call to CreatePropertyPages.
  1276. --*/
  1277. {
  1278. //
  1279. // refresh to pick up possible namespace updates by others
  1280. //
  1281. HRESULT hr = OnRefresh();
  1282. if (S_FALSE == hr)
  1283. {
  1284. // this root has been deleted by others, no more reference
  1285. DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_INVALID_ROOT);
  1286. return hr; // no property page
  1287. }
  1288. return S_OK; // since we want to display a propertysheet.
  1289. }
  1290. // Creates and passes back the pages to be displayed
  1291. STDMETHODIMP
  1292. CMmcDfsRoot::CreatePropertyPages(
  1293. IN LPPROPERTYSHEETCALLBACK i_lpPropSheetCallback,
  1294. IN LONG_PTR i_lNotifyHandle
  1295. )
  1296. /*++
  1297. Routine Description:
  1298. Used to display the property sheet pages
  1299. Arguments:
  1300. i_lpPropSheetCallback - The callback used to create the propertysheet.
  1301. i_lNotifyHandle - Notify handle used by the property page
  1302. Return value:
  1303. S_OK since we want to display a propertysheet.
  1304. --*/
  1305. {
  1306. RETURN_INVALIDARG_IF_NULL(i_lpPropSheetCallback);
  1307. m_lpConsole->SelectScopeItem(m_hScopeItem);
  1308. CWaitCursor WaitCursor;
  1309. HRESULT hr = S_OK;
  1310. do {
  1311. hr = m_PropPage.Initialize((IDfsRoot*)m_DfsRoot, NULL);
  1312. BREAK_IF_FAILED(hr);
  1313. // Create the page for the replica set.
  1314. // Pass it to the Callback
  1315. HPROPSHEETPAGE h_proppage = m_PropPage.Create();
  1316. if (!h_proppage)
  1317. hr = HRESULT_FROM_WIN32(::GetLastError());
  1318. BREAK_IF_FAILED(hr);
  1319. // Pass on the notify data to the Property Page
  1320. hr = m_PropPage.SetNotifyData(i_lNotifyHandle, (LPARAM)this);
  1321. BREAK_IF_FAILED(hr);
  1322. hr = i_lpPropSheetCallback->AddPage(h_proppage);
  1323. BREAK_IF_FAILED(hr);
  1324. //
  1325. // Create "Replica Set" page
  1326. //
  1327. hr = CreateFrsPropertyPage(i_lpPropSheetCallback, i_lNotifyHandle);
  1328. if (FAILED(hr))
  1329. {
  1330. DisplayMessageBox(::GetActiveWindow(), MB_OK, hr, IDS_REPPAGE_ERROR);
  1331. hr = S_OK; // allow the other tabs to be brought up
  1332. }
  1333. //
  1334. // Create "Publish" page
  1335. //
  1336. hr = CreatePublishPropertyPage(i_lpPropSheetCallback, i_lNotifyHandle);
  1337. if (FAILED(hr))
  1338. {
  1339. DisplayMessageBox(::GetActiveWindow(), MB_OK, hr, IDS_PUBLISHPAGE_ERROR);
  1340. hr = S_OK; // allow the other tabs to be brought up
  1341. }
  1342. /*
  1343. //
  1344. // Create Security property page for Fault Tolerance DFS root
  1345. //
  1346. if (DFS_TYPE_FTDFS == m_lDfsRootType)
  1347. {
  1348. LPTSTR lpszLDAPRoot = NULL;
  1349. PLDAP pldap = NULL;
  1350. do {
  1351. CComBSTR bstrDomainName;
  1352. hr = m_DfsRoot->get_DomainName(&bstrDomainName);
  1353. BREAK_IF_FAILED(hr);
  1354. CComBSTR bstrDfsName;
  1355. hr = m_DfsRoot->get_DfsName(&bstrDfsName);
  1356. BREAK_IF_FAILED(hr);
  1357. CComBSTR bstrServerName;
  1358. hr = ConnectToDS(bstrDomainName, &pldap, &bstrServerName);
  1359. BREAK_IF_FAILED(hr);
  1360. hr = GetLDAPRootPath(pldap, &lpszLDAPRoot);
  1361. BREAK_IF_FAILED(hr);
  1362. CComBSTR bstrSystemDN;
  1363. CComBSTR bstrDfsConfigDN;
  1364. CComBSTR bstrFTRootDN;
  1365. if (FAILED(hr = ExtendDN(CN_SYSTEM, lpszLDAPRoot, &bstrSystemDN)) ||
  1366. FAILED(hr = ExtendDN(CN_DFSCONFIGURATION, bstrSystemDN, &bstrDfsConfigDN)) ||
  1367. FAILED(hr = ExtendDN(bstrDfsName, bstrDfsConfigDN, &bstrFTRootDN)) )
  1368. break;
  1369. CComBSTR bstrObjectPath;
  1370. bstrObjectPath = _T("LDAP://");
  1371. bstrObjectPath += bstrServerName;
  1372. bstrObjectPath += _T("/");
  1373. bstrObjectPath += bstrFTRootDN;
  1374. hr = CreateDfsSecurityPage(
  1375. i_lpPropSheetCallback,
  1376. bstrObjectPath,
  1377. NULL,
  1378. DSSI_IS_ROOT);
  1379. } while (0);
  1380. if (pldap) CloseConnectionToDS(pldap);
  1381. if (lpszLDAPRoot) free(lpszLDAPRoot);
  1382. }
  1383. */
  1384. } while (0);
  1385. if (FAILED(hr))
  1386. DisplayMessageBoxForHR(hr);
  1387. return hr;
  1388. }
  1389. STDMETHODIMP
  1390. CMmcDfsRoot::CreateFrsPropertyPage
  1391. (
  1392. IN LPPROPERTYSHEETCALLBACK i_lpPropSheetCallback,
  1393. IN LONG_PTR i_lNotifyHandle
  1394. )
  1395. {
  1396. //
  1397. // init m_piReplicaSet
  1398. //
  1399. HRESULT hr = _InitReplicaSet();
  1400. if (S_OK != hr) return hr;
  1401. CComBSTR bstrType;
  1402. hr = m_piReplicaSet->get_Type(&bstrType);
  1403. RETURN_IF_FAILED(hr);
  1404. if (lstrcmpi(bstrType, FRS_RSTYPE_DFS))
  1405. return hr;
  1406. //
  1407. // set initial values on the property page
  1408. //
  1409. hr = m_frsPropPage.Initialize(m_piReplicaSet);
  1410. RETURN_IF_FAILED(hr);
  1411. //
  1412. // create the property page
  1413. //
  1414. HPROPSHEETPAGE h_frsproppage = m_frsPropPage.Create();
  1415. if (!h_frsproppage)
  1416. return HRESULT_FROM_WIN32(::GetLastError());
  1417. //
  1418. // pass on the notify data to the Property Page
  1419. //
  1420. hr = m_frsPropPage.SetNotifyData(i_lNotifyHandle, (LPARAM)this);
  1421. RETURN_IF_FAILED(hr);
  1422. //
  1423. // AddPage
  1424. //
  1425. return i_lpPropSheetCallback->AddPage(h_frsproppage);
  1426. }
  1427. STDMETHODIMP
  1428. CMmcDfsRoot::CreatePublishPropertyPage
  1429. (
  1430. IN LPPROPERTYSHEETCALLBACK i_lpPropSheetCallback,
  1431. IN LONG_PTR i_lNotifyHandle
  1432. )
  1433. {
  1434. //
  1435. // check schema version
  1436. //
  1437. if (!m_bNewSchema)
  1438. return S_FALSE;
  1439. //
  1440. // check group policy
  1441. //
  1442. if (!CheckPolicyOnSharePublish())
  1443. return S_FALSE;
  1444. //
  1445. // create the property page
  1446. //
  1447. HPROPSHEETPAGE hpage = m_publishPropPage.Create();
  1448. if (!hpage)
  1449. return HRESULT_FROM_WIN32(::GetLastError());
  1450. m_publishPropPage.Initialize(m_DfsRoot);
  1451. //
  1452. // pass on the notify data to the Property Page
  1453. //
  1454. HRESULT hr = m_publishPropPage.SetNotifyData(i_lNotifyHandle, (LPARAM)this);
  1455. RETURN_IF_FAILED(hr);
  1456. //
  1457. // AddPage
  1458. //
  1459. return i_lpPropSheetCallback->AddPage(hpage);
  1460. }
  1461. STDMETHODIMP
  1462. CMmcDfsRoot::PropertyChanged(
  1463. )
  1464. /*++
  1465. Routine Description:
  1466. Used to update the properties.
  1467. --*/
  1468. {
  1469. return S_OK;
  1470. }
  1471. HRESULT
  1472. CMmcDfsRoot::ToolbarSelect(
  1473. IN const LONG i_lArg,
  1474. IN IToolbar* i_pToolBar
  1475. )
  1476. /*++
  1477. Routine Description:
  1478. Handle a select event for a toolbar
  1479. Create a toolbar, it it doesn't exist.
  1480. Attach the toolbar and enable the buttons, if the event for a selection.
  1481. Disable the buttons, if the event was for a deselection
  1482. Arguments:
  1483. i_lArg - The argument passed to the actual method.
  1484. i_pToolBar - Pointer to Toolbar.
  1485. --*/
  1486. {
  1487. RETURN_INVALIDARG_IF_NULL(i_pToolBar);
  1488. BOOL bSelect = (BOOL) HIWORD(i_lArg); // Is the event for selection?
  1489. EnableToolbarButtons(i_pToolBar, IDT_ROOT_MIN, IDT_ROOT_MAX, bSelect);
  1490. if (bSelect) // Should we disable or enable the toolbar?
  1491. {
  1492. BOOL bReplicaSetExist = FALSE;
  1493. HRESULT hr = m_DfsRoot->get_ReplicaSetExist(&bReplicaSetExist);
  1494. RETURN_IF_FAILED(hr);
  1495. if(DFS_TYPE_STANDALONE == m_lDfsRootType)
  1496. {
  1497. i_pToolBar->SetButtonState(IDT_ROOT_NEW_ROOT_REPLICA, ENABLED, FALSE);
  1498. i_pToolBar->SetButtonState(IDT_ROOT_NEW_ROOT_REPLICA, HIDDEN, TRUE);
  1499. }
  1500. if (m_MmcJPList.empty())
  1501. {
  1502. i_pToolBar->SetButtonState(IDT_ROOT_DELETE_DISPLAYED_DFS_LINKS, ENABLED, FALSE);
  1503. i_pToolBar->SetButtonState(IDT_ROOT_DELETE_DISPLAYED_DFS_LINKS, HIDDEN, TRUE);
  1504. }
  1505. if (bReplicaSetExist || 1 >= m_MmcRepList.size())
  1506. {
  1507. i_pToolBar->SetButtonState(IDT_ROOT_REPLICATION_TOPOLOGY, ENABLED, FALSE);
  1508. i_pToolBar->SetButtonState(IDT_ROOT_REPLICATION_TOPOLOGY, HIDDEN, TRUE);
  1509. }
  1510. if (!bReplicaSetExist)
  1511. {
  1512. i_pToolBar->SetButtonState(IDT_ROOT_SHOW_REPLICATION, ENABLED, FALSE);
  1513. i_pToolBar->SetButtonState(IDT_ROOT_SHOW_REPLICATION, HIDDEN, TRUE);
  1514. i_pToolBar->SetButtonState(IDT_ROOT_HIDE_REPLICATION, ENABLED, FALSE);
  1515. i_pToolBar->SetButtonState(IDT_ROOT_HIDE_REPLICATION, HIDDEN, TRUE);
  1516. i_pToolBar->SetButtonState(IDT_ROOT_STOP_REPLICATION, ENABLED, FALSE);
  1517. i_pToolBar->SetButtonState(IDT_ROOT_STOP_REPLICATION, HIDDEN, TRUE);
  1518. } else
  1519. {
  1520. if (m_bShowFRS)
  1521. {
  1522. i_pToolBar->SetButtonState(IDT_ROOT_SHOW_REPLICATION, ENABLED, FALSE);
  1523. i_pToolBar->SetButtonState(IDT_ROOT_SHOW_REPLICATION, HIDDEN, TRUE);
  1524. } else
  1525. {
  1526. i_pToolBar->SetButtonState(IDT_ROOT_HIDE_REPLICATION, ENABLED, FALSE);
  1527. i_pToolBar->SetButtonState(IDT_ROOT_HIDE_REPLICATION, HIDDEN, TRUE);
  1528. }
  1529. }
  1530. // excluded when empty root container
  1531. if (m_MmcRepList.empty())
  1532. {
  1533. i_pToolBar->SetButtonState(IDT_ROOT_NEW_DFS_LINK, ENABLED, FALSE);
  1534. i_pToolBar->SetButtonState(IDT_ROOT_NEW_DFS_LINK, HIDDEN, TRUE);
  1535. i_pToolBar->SetButtonState(IDT_ROOT_CHECK_STATUS, ENABLED, FALSE);
  1536. i_pToolBar->SetButtonState(IDT_ROOT_CHECK_STATUS, HIDDEN, TRUE);
  1537. i_pToolBar->SetButtonState(IDT_ROOT_FILTER_DFS_LINKS, ENABLED, FALSE);
  1538. i_pToolBar->SetButtonState(IDT_ROOT_FILTER_DFS_LINKS, HIDDEN, TRUE);
  1539. }
  1540. }
  1541. return S_OK;
  1542. }
  1543. HRESULT
  1544. CMmcDfsRoot::CreateToolbar(
  1545. IN const LPCONTROLBAR i_pControlbar,
  1546. IN const LPEXTENDCONTROLBAR i_lExtendControlbar,
  1547. OUT IToolbar** o_ppToolBar
  1548. )
  1549. /*++
  1550. Routine Description:
  1551. Create the toolbar.
  1552. Involves the actual toolbar creation call, creating the bitmap and adding it
  1553. and finally adding the buttons to the toolbar
  1554. Arguments:
  1555. i_pControlbar - The controlbar used to create toolbar.
  1556. i_lExtendControlbar - The object implementing IExtendControlbar. This is
  1557. the class exposed to MMC.
  1558. o_ppToolBar - The Toolbar pointer.
  1559. --*/
  1560. {
  1561. RETURN_INVALIDARG_IF_NULL(i_pControlbar);
  1562. RETURN_INVALIDARG_IF_NULL(i_lExtendControlbar);
  1563. RETURN_INVALIDARG_IF_NULL(o_ppToolBar);
  1564. // Create the toolbar
  1565. HRESULT hr = i_pControlbar->Create(TOOLBAR, i_lExtendControlbar, reinterpret_cast<LPUNKNOWN*>(o_ppToolBar));
  1566. RETURN_IF_FAILED(hr);
  1567. // Add the bitmap to the toolbar
  1568. hr = AddBitmapToToolbar(*o_ppToolBar, IDB_ROOT_TOOLBAR);
  1569. RETURN_IF_FAILED(hr);
  1570. int iButtonPosition = 0; // The first button position
  1571. for (int iCommandID = IDT_ROOT_MIN, iMenuResource = IDS_MENUS_ROOT_TOP_NEW_DFS_LINK;
  1572. iCommandID <= IDT_ROOT_MAX;
  1573. iCommandID++,iMenuResource++,iButtonPosition++)
  1574. {
  1575. CComBSTR bstrMenuText;
  1576. CComBSTR bstrToolTipText;
  1577. hr = GetMenuResourceStrings(iMenuResource, &bstrMenuText, &bstrToolTipText, NULL);
  1578. RETURN_IF_FAILED(hr);
  1579. MMCBUTTON ToolbarButton;
  1580. ZeroMemory(&ToolbarButton, sizeof ToolbarButton);
  1581. ToolbarButton.nBitmap = iButtonPosition;
  1582. ToolbarButton.idCommand = iCommandID;
  1583. ToolbarButton.fsState = TBSTATE_ENABLED;
  1584. ToolbarButton.fsType = TBSTYLE_BUTTON;
  1585. ToolbarButton.lpButtonText = bstrMenuText; // not used anyway
  1586. ToolbarButton.lpTooltipText = bstrToolTipText;
  1587. // Add the button to the toolbar
  1588. hr = (*o_ppToolBar)->InsertButton(iButtonPosition, &ToolbarButton);
  1589. BREAK_IF_FAILED(hr);
  1590. }
  1591. return hr;
  1592. }
  1593. STDMETHODIMP
  1594. CMmcDfsRoot::ToolbarClick(
  1595. IN const LPCONTROLBAR i_pControlbar,
  1596. IN const LPARAM i_lParam
  1597. )
  1598. /*++
  1599. Routine Description:
  1600. Action to take on a click on a toolbar
  1601. Arguments:
  1602. i_pControlbar - The controlbar used to create toolbar.
  1603. i_lParam - The lparam to the actual notify. This is the command id of
  1604. the button on which a click occurred.
  1605. --*/
  1606. {
  1607. RETURN_INVALIDARG_IF_NULL(i_pControlbar);
  1608. HRESULT hr = S_OK;
  1609. switch(i_lParam)
  1610. {
  1611. case IDT_ROOT_NEW_DFS_LINK:
  1612. hr = OnCreateNewJunctionPoint ();
  1613. break;
  1614. case IDT_ROOT_NEW_ROOT_REPLICA:
  1615. hr = OnNewRootReplica();
  1616. break;
  1617. case IDT_ROOT_CHECK_STATUS:
  1618. hr = OnCheckStatus();
  1619. break;
  1620. case IDT_ROOT_DELETE_DISPLAYED_DFS_LINKS:
  1621. hr = OnDeleteDisplayedDfsLinks();
  1622. break;
  1623. case IDT_ROOT_DELETE_CONNECTION_TO_DFS_ROOT:
  1624. hr = OnDeleteConnectionToDfsRoot();
  1625. break;
  1626. case IDT_ROOT_DELETE_DFS_ROOT:
  1627. hr = OnDeleteDfsRoot();
  1628. break;
  1629. case IDT_ROOT_FILTER_DFS_LINKS:
  1630. hr = OnFilterDfsLinks();
  1631. break;
  1632. case IDT_ROOT_REPLICATION_TOPOLOGY:
  1633. hr = OnNewReplicaSet();
  1634. break;
  1635. case IDT_ROOT_SHOW_REPLICATION:
  1636. case IDT_ROOT_HIDE_REPLICATION:
  1637. m_bShowFRS = !m_bShowFRS;
  1638. hr = OnShowReplication();
  1639. break;
  1640. case IDT_ROOT_STOP_REPLICATION:
  1641. hr = OnStopReplication(TRUE);
  1642. if (FAILED(hr))
  1643. DisplayMessageBoxForHR(hr);
  1644. break;
  1645. default:
  1646. hr = E_INVALIDARG;
  1647. break;
  1648. };
  1649. return hr;
  1650. }
  1651. HRESULT
  1652. CMmcDfsRoot::ClosePropertySheet(BOOL bSilent)
  1653. {
  1654. if (!m_PropPage.m_hWnd && !m_frsPropPage.m_hWnd && !m_publishPropPage.m_hWnd)
  1655. return S_OK; // no outstanding property sheet, return S_OK;
  1656. //
  1657. // handle property sheet for the root
  1658. //
  1659. CComPtr<IPropertySheetProvider> pPropSheetProvider;
  1660. HRESULT hr = m_lpConsole->QueryInterface(IID_IPropertySheetProvider, reinterpret_cast<void**>(&pPropSheetProvider));
  1661. if (FAILED(hr))
  1662. {
  1663. hr = S_OK; // ignore the QI failure
  1664. } else
  1665. {
  1666. //
  1667. // find outstanding property sheet and bring it to foreground
  1668. //
  1669. hr = pPropSheetProvider->FindPropertySheet((MMC_COOKIE)m_hScopeItem, NULL, this);
  1670. if (S_OK == hr)
  1671. {
  1672. if (!bSilent)
  1673. {
  1674. //
  1675. // ask user to close it, return S_FALSE to quit user's operation
  1676. //
  1677. DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_PROPERTYPAGE_NOTCLOSED);
  1678. return S_FALSE;
  1679. } else
  1680. {
  1681. //
  1682. // silently close the property sheet, return S_OK
  1683. //
  1684. if (m_PropPage.m_hWnd)
  1685. ::SendMessage(m_PropPage.m_hWnd, WM_PARENT_NODE_CLOSING, 0, 0);
  1686. if (m_frsPropPage.m_hWnd)
  1687. ::SendMessage(m_frsPropPage.m_hWnd, WM_PARENT_NODE_CLOSING, 0, 0);
  1688. if (m_publishPropPage.m_hWnd)
  1689. ::SendMessage(m_publishPropPage.m_hWnd, WM_PARENT_NODE_CLOSING, 0, 0);
  1690. }
  1691. } else
  1692. {
  1693. hr = S_OK; // no outstanding property sheet, return S_OK
  1694. }
  1695. }
  1696. //
  1697. // reset HWND
  1698. //
  1699. m_PropPage.m_hWnd = NULL;
  1700. m_frsPropPage.m_hWnd = NULL;
  1701. m_publishPropPage.m_hWnd = NULL;
  1702. return hr;
  1703. }
  1704. HRESULT
  1705. CMmcDfsRoot::ClosePropertySheetsOfAllLinks(BOOL bSilent)
  1706. {
  1707. HRESULT hr = S_OK;
  1708. //
  1709. // handle property sheets for its links
  1710. //
  1711. if (!m_MmcJPList.empty())
  1712. {
  1713. for (DFS_JUNCTION_LIST::iterator i = m_MmcJPList.begin(); i != m_MmcJPList.end(); i++)
  1714. {
  1715. hr = ((*i)->pJPoint)->ClosePropertySheet(bSilent);
  1716. if (!bSilent && S_FALSE == hr)
  1717. return S_FALSE; // found an outstanding one for a link, return S_FALSE to quit user's operation
  1718. }
  1719. }
  1720. return S_OK;
  1721. }
  1722. // Close all outstanding property sheets for its own and its links
  1723. // Return: S_OK if there is no open property sheet, or they have all been closed silently
  1724. // Return: S_FALSE if an open sheet is found and msgbox poped up to remind user of closing it
  1725. HRESULT
  1726. CMmcDfsRoot::CloseAllPropertySheets(BOOL bSilent)
  1727. {
  1728. //
  1729. // handle property sheet for the root
  1730. //
  1731. HRESULT hr = ClosePropertySheet(bSilent);
  1732. if (!bSilent && S_FALSE == hr)
  1733. return S_FALSE;
  1734. //
  1735. // handle property sheets for its links
  1736. //
  1737. return ClosePropertySheetsOfAllLinks(bSilent);
  1738. }
  1739. HRESULT
  1740. CMmcDfsRoot::OnRefresh()
  1741. {
  1742. // Select this node first
  1743. m_lpConsole->SelectScopeItem(m_hScopeItem);
  1744. CWaitCursor wait;
  1745. HRESULT hr = S_OK;
  1746. // silently close outstanding property sheet.
  1747. CloseAllPropertySheets(TRUE);
  1748. CleanScopeChildren();
  1749. CleanResultChildren();
  1750. m_bShowFRS = FALSE;
  1751. if ((IReplicaSet *)m_piReplicaSet)
  1752. m_piReplicaSet.Release();
  1753. // Re-Initialize!
  1754. hr = m_DfsRoot->Initialize(m_bstrRootEntryPath);
  1755. if (S_OK != hr) // failt to init the root, or no such root any more, we have to stop managing the root
  1756. {
  1757. if (FAILED(hr))
  1758. DisplayMessageBox(::GetActiveWindow(), MB_OK, hr, IDS_STOP_MANAGING_ROOT);
  1759. // Delete the item from Scope Pane
  1760. (void)m_lpConsoleNameSpace->DeleteItem(m_hScopeItem, TRUE);
  1761. // Delete it from the internal list
  1762. (void)m_pParent->DeleteMmcRootNode(this);
  1763. Release(); // delete this CMmcDfsRoot object
  1764. return S_FALSE;
  1765. }
  1766. BOOL bReplicaSetExist = FALSE;
  1767. CComBSTR bstrDC;
  1768. (void)m_DfsRoot->get_ReplicaSetExistEx(&bstrDC, &bReplicaSetExist);
  1769. // Enumerate Junction points
  1770. (void)EnumerateScopePane(m_lpConsoleNameSpace, m_hScopeItem);
  1771. // set the root icon
  1772. if (m_lpConsoleNameSpace != NULL)
  1773. {
  1774. SCOPEDATAITEM ScopeDataItem;
  1775. ZeroMemory(&ScopeDataItem, sizeof(SCOPEDATAITEM));
  1776. ScopeDataItem.ID = m_hScopeItem;
  1777. hr = m_lpConsoleNameSpace->GetItem(&ScopeDataItem);
  1778. if (SUCCEEDED(hr))
  1779. {
  1780. ScopeDataItem.mask = SDI_IMAGE | SDI_OPENIMAGE;
  1781. ScopeDataItem.nImage = CMmcDfsRoot::m_iIMAGEINDEX + ((DFS_TYPE_FTDFS == m_lDfsRootType)? 4 : 0) + (bReplicaSetExist ? 4 : 0);
  1782. ScopeDataItem.nOpenImage = CMmcDfsRoot::m_iIMAGEINDEX + ((DFS_TYPE_FTDFS == m_lDfsRootType)? 4 : 0) + (bReplicaSetExist ? 4 : 0);
  1783. m_lpConsoleNameSpace->SetItem(&ScopeDataItem);
  1784. }
  1785. }
  1786. // Re-Display Result Pane.
  1787. m_lpConsole->UpdateAllViews((IDataObject*)this, 0, 1);
  1788. // Set the selected item in scope pane to this node
  1789. m_lpConsole->SelectScopeItem(m_hScopeItem);
  1790. return S_OK;
  1791. }
  1792. HRESULT
  1793. CMmcDfsRoot::OnRefreshFilteredLinks()
  1794. {
  1795. // Select this node first
  1796. m_lpConsole->SelectScopeItem(m_hScopeItem);
  1797. CWaitCursor wait;
  1798. HRESULT hr = S_OK;
  1799. CleanScopeChildren();
  1800. CleanResultChildren();
  1801. m_bShowFRS = FALSE;
  1802. if ((IReplicaSet *)m_piReplicaSet)
  1803. m_piReplicaSet.Release();
  1804. BOOL bReplicaSetExist = FALSE;
  1805. CComBSTR bstrDC;
  1806. hr = m_DfsRoot->get_ReplicaSetExistEx(&bstrDC, &bReplicaSetExist);
  1807. if (FAILED(hr))
  1808. {
  1809. return OnRefresh(); // fail to access info, see if the root can be contacted or not
  1810. }
  1811. // Enumerate Junction points
  1812. (void)EnumerateScopePane(m_lpConsoleNameSpace, m_hScopeItem);
  1813. // set the root icon
  1814. if (m_lpConsoleNameSpace != NULL)
  1815. {
  1816. SCOPEDATAITEM ScopeDataItem;
  1817. ZeroMemory(&ScopeDataItem, sizeof(SCOPEDATAITEM));
  1818. ScopeDataItem.ID = m_hScopeItem;
  1819. hr = m_lpConsoleNameSpace->GetItem(&ScopeDataItem);
  1820. if (SUCCEEDED(hr))
  1821. {
  1822. ScopeDataItem.mask = SDI_IMAGE | SDI_OPENIMAGE;
  1823. ScopeDataItem.nImage = CMmcDfsRoot::m_iIMAGEINDEX + ((DFS_TYPE_FTDFS == m_lDfsRootType)? 4 : 0) + (bReplicaSetExist ? 4 : 0);
  1824. ScopeDataItem.nOpenImage = CMmcDfsRoot::m_iIMAGEINDEX + ((DFS_TYPE_FTDFS == m_lDfsRootType)? 4 : 0) + (bReplicaSetExist ? 4 : 0);
  1825. m_lpConsoleNameSpace->SetItem(&ScopeDataItem);
  1826. }
  1827. }
  1828. // re-display the result pane items
  1829. m_lpConsole->UpdateAllViews((IDataObject*)this, 0, 1);
  1830. // Set the selected item in scope pane to this node
  1831. m_lpConsole->SelectScopeItem(m_hScopeItem);
  1832. return S_OK;
  1833. }
  1834. HRESULT
  1835. CMmcDfsRoot::_DeleteDfsRoot(
  1836. IN BSTR i_bstrServerName,
  1837. IN BSTR i_bstrShareName,
  1838. IN BSTR i_bstrFtDfsName
  1839. )
  1840. {
  1841. /*++
  1842. Routine Description:
  1843. Helper member function to actually delete (Stop hosting) the Dfs Root.
  1844. This is also called to delete root level replica.
  1845. Arguments:
  1846. i_bstrServerName - The server on which the Dfs has to be torn down.
  1847. i_bRootReplica - This DfsRoot is been torn down as Root Replica.
  1848. i_bstrFtDfsName - The FtDfs name of the Dfs. NULL for Standalone Dfs.
  1849. --*/
  1850. RETURN_INVALIDARG_IF_NULL(i_bstrServerName);
  1851. RETURN_INVALIDARG_IF_NULL(i_bstrShareName);
  1852. CWaitCursor WaitCursor; // Display the wait cursor
  1853. HRESULT hr = m_DfsRoot->DeleteDfsHost(i_bstrServerName, i_bstrShareName, FALSE);
  1854. BOOL bFTDfs = (i_bstrFtDfsName && *i_bstrFtDfsName);
  1855. if (bFTDfs)
  1856. {
  1857. if (FAILED(hr) && HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) != hr)
  1858. {
  1859. if (IDYES == DisplayMessageBox(
  1860. GetActiveWindow(),
  1861. MB_YESNO | MB_ICONEXCLAMATION,
  1862. hr,
  1863. IDS_MSG_WIZ_DELETE_FAILURE_RETRY,
  1864. i_bstrServerName))
  1865. {
  1866. // force delete
  1867. hr = m_DfsRoot->DeleteDfsHost(i_bstrServerName, i_bstrShareName, TRUE);
  1868. } else
  1869. {
  1870. // leave it alone
  1871. hr = S_FALSE;
  1872. }
  1873. }
  1874. }
  1875. if (FAILED(hr))
  1876. DisplayMessageBox(::GetActiveWindow(), MB_OK, hr, IDS_MSG_WIZ_DELETE_FAILURE, i_bstrServerName);
  1877. //
  1878. // delete volume object if it's standalone
  1879. //
  1880. if (SUCCEEDED(hr) && !bFTDfs)
  1881. {
  1882. (void) ModifySharePublishInfoOnSARoot(
  1883. i_bstrServerName,
  1884. i_bstrShareName,
  1885. FALSE,
  1886. NULL,
  1887. NULL,
  1888. NULL,
  1889. NULL
  1890. );
  1891. }
  1892. return hr;
  1893. }
  1894. STDMETHODIMP CMmcDfsRoot::CleanScopeChildren()
  1895. {
  1896. HRESULT hr = S_OK;
  1897. if (!m_MmcJPList.empty())
  1898. {
  1899. // clean up the display objects
  1900. for (DFS_JUNCTION_LIST::iterator i = m_MmcJPList.begin(); i != m_MmcJPList.end(); i++)
  1901. {
  1902. delete (*i);
  1903. }
  1904. m_MmcJPList.erase(m_MmcJPList.begin(), m_MmcJPList.end());
  1905. // Delete all child items from scope pane.
  1906. if (m_lpConsoleNameSpace)
  1907. {
  1908. HSCOPEITEM hChild = NULL;
  1909. MMC_COOKIE lCookie = 0;
  1910. while (SUCCEEDED(hr = m_lpConsoleNameSpace->GetChildItem(m_hScopeItem, &hChild, &lCookie)) && hChild)
  1911. {
  1912. (void)m_lpConsoleNameSpace->DeleteItem(hChild, TRUE);
  1913. }
  1914. }
  1915. }
  1916. return S_OK;
  1917. }
  1918. STDMETHODIMP CMmcDfsRoot::CleanResultChildren(
  1919. )
  1920. {
  1921. if (!m_MmcRepList.empty())
  1922. {
  1923. // delete display object
  1924. for (DFS_REPLICA_LIST::iterator i = m_MmcRepList.begin(); i != m_MmcRepList.end(); i++)
  1925. {
  1926. delete (*i);
  1927. }
  1928. m_MmcRepList.erase(m_MmcRepList.begin(), m_MmcRepList.end());
  1929. // delete result pane items
  1930. m_lpConsole->UpdateAllViews((IDataObject*)this, 0, 0);
  1931. }
  1932. return(S_OK);
  1933. }
  1934. STDMETHODIMP CMmcDfsRoot::RefreshResultChildren(
  1935. )
  1936. {
  1937. CleanResultChildren();
  1938. m_DfsRoot->RefreshRootReplicas();
  1939. // Send View change notification for all veiws.
  1940. m_lpConsole->UpdateAllViews((IDataObject*)this, 0, 1);
  1941. return(S_OK);
  1942. }
  1943. STDMETHODIMP CMmcDfsRoot::ViewChange(
  1944. IResultData* i_pResultData,
  1945. LONG_PTR i_lHint
  1946. )
  1947. /*++
  1948. Routine Description:
  1949. This method handles the MMCN_VIEW_CHANGE notification.
  1950. This updates the result view for the scope node on which the
  1951. UpdateAllViews was called.
  1952. if (0 == i_lHint) clean result pane only.
  1953. --*/
  1954. {
  1955. RETURN_INVALIDARG_IF_NULL(i_pResultData);
  1956. i_pResultData->DeleteAllRsltItems();
  1957. if (i_lHint)
  1958. EnumerateResultPane(i_pResultData);
  1959. return(S_OK);
  1960. }
  1961. STDMETHODIMP CMmcDfsRoot::AddResultPaneItem(
  1962. CMmcDfsReplica* i_pReplicaDispObject
  1963. )
  1964. /*++
  1965. Routine Description:
  1966. This method adds a new replica object to the list of replicas displayed
  1967. in the result view.
  1968. Arguments:
  1969. i_pReplicaDispObject - The CMmcReplica display object pointer..
  1970. --*/
  1971. {
  1972. REP_LIST_NODE* pNewReplica = new REP_LIST_NODE(i_pReplicaDispObject);
  1973. if (!pNewReplica)
  1974. return E_OUTOFMEMORY;
  1975. m_MmcRepList.push_back(pNewReplica);
  1976. // Re-display to display this item.
  1977. m_lpConsole->UpdateAllViews((IDataObject*)this, 0, 1);
  1978. return S_OK;
  1979. }
  1980. //
  1981. // This function is called when deleting a link from the scope pane
  1982. //
  1983. STDMETHODIMP CMmcDfsRoot::RemoveJP(LPCTSTR i_pszDisplayName)
  1984. {
  1985. if (!i_pszDisplayName)
  1986. return E_INVALIDARG;
  1987. //
  1988. // refresh to pick up possible namespace updates on links by other means
  1989. //
  1990. HRESULT hr = OnRefresh();
  1991. if (S_FALSE == hr)
  1992. {
  1993. // this root has already been deleted by others, no more reference
  1994. DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_INVALID_ROOT);
  1995. return hr;
  1996. }
  1997. CWaitCursor wait;
  1998. //
  1999. // locate the correct link to remove, then call back.
  2000. //
  2001. for (DFS_JUNCTION_LIST::iterator i = m_MmcJPList.begin(); i != m_MmcJPList.end(); i++)
  2002. {
  2003. if (!lstrcmpi((*i)->pJPoint->m_bstrDisplayName, i_pszDisplayName))
  2004. {
  2005. hr = (*i)->pJPoint->OnRemoveJP();
  2006. break;
  2007. }
  2008. }
  2009. return hr;
  2010. }
  2011. //
  2012. // This function is called when removing a target from the result pane
  2013. //
  2014. STDMETHODIMP CMmcDfsRoot::RemoveReplica(LPCTSTR i_pszDisplayName)
  2015. {
  2016. if (!i_pszDisplayName)
  2017. return E_INVALIDARG;
  2018. //
  2019. // refresh to pick up possible namespace updates on root targets by other means
  2020. //
  2021. HRESULT hr = OnRefresh();
  2022. if (S_FALSE == hr)
  2023. {
  2024. // this root has already been deleted by others, no more reference
  2025. DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_INVALID_ROOT);
  2026. return hr;
  2027. }
  2028. CWaitCursor wait;
  2029. //
  2030. // locate the correct target to remove, then call back
  2031. //
  2032. for (DFS_REPLICA_LIST::iterator i = m_MmcRepList.begin(); i != m_MmcRepList.end(); i++)
  2033. {
  2034. if (!lstrcmpi((*i)->pReplica->m_bstrDisplayName, i_pszDisplayName))
  2035. {
  2036. hr = (*i)->pReplica->RemoveReplica();
  2037. break;
  2038. }
  2039. }
  2040. return hr;
  2041. }
  2042. STDMETHODIMP CMmcDfsRoot::RemoveResultPaneItem(
  2043. CMmcDfsReplica* i_pReplicaDispObject
  2044. )
  2045. /*++
  2046. Routine Description:
  2047. This method removes a replica object from the list of replicas displayed
  2048. in the result view.
  2049. Arguments:
  2050. i_pReplicaDispObject - The CMmcReplica display object pointer..
  2051. --*/
  2052. {
  2053. dfsDebugOut((_T("CMmcDfsRoot::RemoveResultPaneItem jplist=%d, replist=%d\n"),
  2054. m_MmcJPList.size(), m_MmcRepList.size()));
  2055. // Remove item from list.
  2056. for (DFS_REPLICA_LIST::iterator i = m_MmcRepList.begin(); i != m_MmcRepList.end(); i++)
  2057. {
  2058. if ((*i)->pReplica == i_pReplicaDispObject)
  2059. {
  2060. delete (*i);
  2061. m_MmcRepList.erase(i);
  2062. break;
  2063. }
  2064. }
  2065. // Last node is removed.
  2066. if (m_MmcRepList.empty())
  2067. {
  2068. // silently close any open property sheet
  2069. CloseAllPropertySheets(TRUE);
  2070. CleanScopeChildren();
  2071. // Delete the item from Scope Pane
  2072. HRESULT hr = m_lpConsoleNameSpace->DeleteItem(m_hScopeItem, TRUE);
  2073. RETURN_IF_FAILED(hr);
  2074. // Delete it from the internal list
  2075. hr = m_pParent->DeleteMmcRootNode(this);
  2076. RETURN_IF_FAILED(hr);
  2077. Release(); // delete this CMmsDfsRoot object
  2078. }
  2079. else
  2080. {
  2081. // Re-display to remove this item.
  2082. m_lpConsole->UpdateAllViews((IDataObject*)this, 0, 1);
  2083. }
  2084. return S_OK;
  2085. }
  2086. STDMETHODIMP
  2087. CMmcDfsRoot::OnCheckStatus()
  2088. {
  2089. //
  2090. // refresh to pick up possible namespace updates on targets by others
  2091. //
  2092. HRESULT hr = OnRefresh();
  2093. if (S_FALSE == hr)
  2094. {
  2095. // this root has been deleted by others, no more reference
  2096. DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_INVALID_ROOT);
  2097. return hr;
  2098. }
  2099. CWaitCursor wait;
  2100. UINT nTotal = m_MmcRepList.size();
  2101. _ASSERT(nTotal != 0);
  2102. UINT nMappingOn = 0;
  2103. UINT nMappingOff = 0;
  2104. UINT nUnreachable = 0;
  2105. // Update state of all replicas also.
  2106. for (DFS_REPLICA_LIST::iterator i = m_MmcRepList.begin(); i != m_MmcRepList.end(); i++)
  2107. {
  2108. (*i)->pReplica->OnCheckStatus();
  2109. switch ((*i)->pReplica->m_lReplicaState)
  2110. {
  2111. case DFS_REPLICA_STATE_ONLINE:
  2112. nMappingOn++;
  2113. break;
  2114. case DFS_REPLICA_STATE_OFFLINE:
  2115. nMappingOff++;
  2116. break;
  2117. case DFS_REPLICA_STATE_UNREACHABLE:
  2118. nUnreachable++;
  2119. break;
  2120. default:
  2121. _ASSERT(FALSE);
  2122. break;
  2123. }
  2124. }
  2125. long lDfsState = DFS_STATE_REACHABLE;
  2126. hr = m_DfsRoot->get_State(&lDfsState);
  2127. RETURN_IF_FAILED(hr);
  2128. if (DFS_STATE_REACHABLE == lDfsState)
  2129. {
  2130. if (nTotal == nMappingOn)
  2131. {
  2132. m_lRootJunctionState = DFS_JUNCTION_STATE_ALL_REP_OK;
  2133. } else if (nTotal != (nMappingOff + nUnreachable))
  2134. {
  2135. m_lRootJunctionState = DFS_JUNCTION_STATE_NOT_ALL_REP_OK;
  2136. } else
  2137. {
  2138. m_lRootJunctionState = DFS_JUNCTION_STATE_UNREACHABLE;
  2139. }
  2140. } else
  2141. {
  2142. m_lRootJunctionState = DFS_JUNCTION_STATE_UNREACHABLE;
  2143. }
  2144. BOOL bReplicaSetExist = FALSE;
  2145. hr = m_DfsRoot->get_ReplicaSetExist(&bReplicaSetExist);
  2146. RETURN_IF_FAILED(hr);
  2147. if (m_lpConsoleNameSpace)
  2148. {
  2149. SCOPEDATAITEM ScopeDataItem;
  2150. ZeroMemory(&ScopeDataItem, sizeof(SCOPEDATAITEM));
  2151. ScopeDataItem.ID = m_hScopeItem;
  2152. hr = m_lpConsoleNameSpace->GetItem(&ScopeDataItem);// Get the item data
  2153. RETURN_IF_FAILED(hr);
  2154. ScopeDataItem.mask = SDI_IMAGE | SDI_OPENIMAGE; // Set the image flag
  2155. ScopeDataItem.nImage = CMmcDfsRoot::m_iIMAGEINDEX + ((DFS_TYPE_FTDFS == m_lDfsRootType)? 4 : 0) + (bReplicaSetExist ? 4 : 0) + m_lRootJunctionState; // Specify the bitmap to use
  2156. ScopeDataItem.nOpenImage = CMmcDfsRoot::m_iIMAGEINDEX + ((DFS_TYPE_FTDFS == m_lDfsRootType)? 4 : 0) + (bReplicaSetExist ? 4 : 0) + m_lRootJunctionState; // Specify the bitmap to use
  2157. hr = m_lpConsoleNameSpace->SetItem(&ScopeDataItem); // set the updated item data
  2158. RETURN_IF_FAILED(hr);
  2159. }
  2160. return hr;
  2161. }
  2162. HRESULT CMmcDfsRoot::GetIReplicaSetPtr(IReplicaSet** o_ppiReplicaSet)
  2163. {
  2164. RETURN_INVALIDARG_IF_NULL(o_ppiReplicaSet);
  2165. HRESULT hr = _InitReplicaSet();
  2166. if (S_OK == hr)
  2167. {
  2168. m_piReplicaSet->AddRef();
  2169. *o_ppiReplicaSet = m_piReplicaSet;
  2170. }
  2171. return hr;
  2172. }