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.

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