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.

1804 lines
49 KiB

  1. /*++
  2. Module Name:
  3. MmcJP.cpp
  4. Abstract:
  5. This module contains the implementation for CMmcDfsJP. This is an class
  6. for MMC display related calls for the second level node(the Junction Point nodes)
  7. --*/
  8. #include "stdafx.h"
  9. #include "Utils.h" // For the LoadStringFromResource method
  10. #include "resource.h" // For the Resource ID for strings, etc.
  11. #include "DfsGUI.h"
  12. #include "MmcAdmin.h"
  13. #include "MmcRoot.h"
  14. #include "MmcRep.h"
  15. #include "MenuEnum.h" // Contains the menu and toolbar command ids
  16. #include "AddToDfs.h"
  17. #include "AddRep.h"
  18. #include "MmcJP.h"
  19. #include "DfsNodes.h" // For Node GUIDs
  20. #include "DfsEnums.h" // For DFS_TYPE_STANDALONE and other DfsRoot declarations
  21. #include "NewFrs.h"
  22. const int CMmcDfsJunctionPoint::m_iIMAGEINDEX = 12;
  23. const int CMmcDfsJunctionPoint::m_iOPENIMAGEINDEX = 12;
  24. CMmcDfsJunctionPoint::CMmcDfsJunctionPoint(
  25. IN IDfsJunctionPoint* i_pDfsJPObject,
  26. IN CMmcDfsRoot* i_pDfsParentRoot,
  27. IN LPCONSOLENAMESPACE i_lpConsoleNameSpace
  28. )
  29. {
  30. dfsDebugOut((_T("CMmcDfsJunctionPoint::CMmcDfsJunctionPoint this=%p\n"), this));
  31. MMC_DISP_CTOR_RETURN_INVALIDARG_IF_NULL(i_pDfsJPObject);
  32. MMC_DISP_CTOR_RETURN_INVALIDARG_IF_NULL(i_pDfsParentRoot);
  33. MMC_DISP_CTOR_RETURN_INVALIDARG_IF_NULL(i_lpConsoleNameSpace);
  34. HRESULT hr = S_OK;
  35. m_pDfsJPObject = i_pDfsJPObject;
  36. m_pDfsParentRoot = i_pDfsParentRoot;
  37. hr = m_pDfsJPObject->get_EntryPath(&m_bstrEntryPath);
  38. MMC_DISP_CTOR_RETURN_HR_IF_FAILED(hr);
  39. hr = m_pDfsJPObject->get_JunctionName(FALSE, &m_bstrDisplayName);
  40. MMC_DISP_CTOR_RETURN_HR_IF_FAILED(hr);
  41. m_lJunctionState = DFS_JUNCTION_STATE_UNASSIGNED;
  42. m_lpConsoleNameSpace = i_lpConsoleNameSpace; // The Callback used to do Scope Pane operations
  43. m_lpConsole = m_pDfsParentRoot->m_lpConsole;
  44. m_hScopeItem = NULL; // Scopeitem handle
  45. m_CLSIDNodeType = s_guidDfsJPNodeType;
  46. m_bstrDNodeType = s_tchDfsJPNodeType;
  47. m_bShowFRS = FALSE;
  48. m_bDirty = false;
  49. }
  50. CMmcDfsJunctionPoint :: ~CMmcDfsJunctionPoint(
  51. )
  52. {
  53. // Silently close outstanding property sheet.
  54. ClosePropertySheet(TRUE);
  55. CleanResultChildren();
  56. if ((IReplicaSet *)m_piReplicaSet)
  57. m_piReplicaSet.Release();
  58. dfsDebugOut((_T("CMmcDfsJunctionPoint::~CMmcDfsJunctionPoint this=%p\n"), this));
  59. }
  60. STDMETHODIMP
  61. CMmcDfsJunctionPoint::AddMenuItems(
  62. IN LPCONTEXTMENUCALLBACK i_lpContextMenuCallback,
  63. IN LPLONG i_lpInsertionAllowed
  64. )
  65. /*++
  66. Routine Description:
  67. This routine adds the context menu for Junction point nodes using the ContextMenuCallback
  68. provided.
  69. Arguments:
  70. lpContextMenuCallback - A callback(function pointer) that is used to add the menu items
  71. lpInsertionAllowed - Specifies what menus can be added and where they can be added.
  72. --*/
  73. {
  74. RETURN_INVALIDARG_IF_NULL(i_lpContextMenuCallback);
  75. enum
  76. {
  77. IDM_CONTEXTMENU_COMMAND_MAX = IDM_JUNCTION_MAX,
  78. IDM_CONTEXTMENU_COMMAND_MIN = IDM_JUNCTION_MIN
  79. };
  80. LONG lInsertionPoints [IDM_CONTEXTMENU_COMMAND_MAX - IDM_CONTEXTMENU_COMMAND_MIN + 1] = {
  81. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  82. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  83. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  84. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  85. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  86. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  87. CCM_INSERTIONPOINTID_PRIMARY_TOP
  88. };
  89. BOOL bReplicaSetExist = FALSE;
  90. HRESULT hr = m_pDfsJPObject->get_ReplicaSetExist(&bReplicaSetExist);
  91. RETURN_IF_FAILED(hr);
  92. // we start with the first menu command id and continue till the last.
  93. for (int iCommandID = IDM_CONTEXTMENU_COMMAND_MIN, iMenuResource = IDS_MENUS_JUNCTION_TOP_NEW_DFS_REPLICA ;
  94. iCommandID <= IDM_CONTEXTMENU_COMMAND_MAX;
  95. iCommandID++,iMenuResource++)
  96. {
  97. CONTEXTMENUITEM ContextMenuItem;
  98. ZeroMemory(&ContextMenuItem, sizeof(ContextMenuItem));
  99. switch (iCommandID)
  100. {
  101. case IDM_JUNCTION_TOP_REPLICATION_TOPOLOGY:
  102. {
  103. if (bReplicaSetExist || (1 >= m_MmcRepList.size()) ||
  104. (DFS_TYPE_STANDALONE == m_pDfsParentRoot->m_lDfsRootType))
  105. continue;
  106. break;
  107. }
  108. case IDM_JUNCTION_TOP_SHOW_REPLICATION:
  109. {
  110. if (!bReplicaSetExist || m_bShowFRS)
  111. continue;
  112. break;
  113. }
  114. case IDM_JUNCTION_TOP_HIDE_REPLICATION:
  115. {
  116. if (!bReplicaSetExist || !m_bShowFRS)
  117. continue;
  118. break;
  119. }
  120. case IDM_JUNCTION_TOP_STOP_REPLICATION:
  121. {
  122. if (!bReplicaSetExist)
  123. continue;
  124. break;
  125. }
  126. }
  127. CComBSTR bstrMenuText;
  128. CComBSTR bstrStatusBarText;
  129. hr = GetMenuResourceStrings(iMenuResource, &bstrMenuText, NULL, &bstrStatusBarText);
  130. RETURN_IF_FAILED(hr);
  131. ContextMenuItem.strName = bstrMenuText;
  132. ContextMenuItem.strStatusBarText = bstrStatusBarText;
  133. ContextMenuItem.lInsertionPointID = lInsertionPoints[iCommandID - IDM_CONTEXTMENU_COMMAND_MIN];
  134. ContextMenuItem.lCommandID = iCommandID;
  135. LONG lInsertionFlag = 0;
  136. switch(ContextMenuItem.lInsertionPointID)
  137. {
  138. case CCM_INSERTIONPOINTID_PRIMARY_TOP:
  139. lInsertionFlag = CCM_INSERTIONALLOWED_TOP;
  140. break;
  141. case CCM_INSERTIONPOINTID_PRIMARY_NEW:
  142. lInsertionFlag = CCM_INSERTIONALLOWED_NEW;
  143. break;
  144. case CCM_INSERTIONPOINTID_PRIMARY_TASK:
  145. lInsertionFlag = CCM_INSERTIONALLOWED_TASK;
  146. break;
  147. case CCM_INSERTIONPOINTID_PRIMARY_VIEW:
  148. lInsertionFlag = CCM_INSERTIONALLOWED_VIEW;
  149. break;
  150. default:
  151. break;
  152. }
  153. if (*i_lpInsertionAllowed & lInsertionFlag)
  154. {
  155. hr = i_lpContextMenuCallback->AddItem(&ContextMenuItem);
  156. RETURN_IF_FAILED(hr);
  157. }
  158. }
  159. return hr;
  160. }
  161. STDMETHODIMP
  162. CMmcDfsJunctionPoint::Command(
  163. IN LONG i_lCommandID
  164. )
  165. /*++
  166. Routine Description:
  167. Action to be taken on a context menu selection or click is takes place.
  168. Arguments:
  169. lCommandID - The Command ID of the menu for which action has to be taken
  170. --*/
  171. {
  172. HRESULT hr = S_OK;
  173. switch (i_lCommandID)
  174. {
  175. case IDM_JUNCTION_TOP_NEW_DFS_REPLICA: // "Add a replica to the Dfs Junction Point"
  176. hr = OnNewReplica();
  177. break;
  178. case IDM_JUNCTION_TOP_REMOVE_FROM_DFS: // "Delete the junction point"
  179. hr = DoDelete();
  180. break;
  181. case IDM_JUNCTION_TOP_REPLICATION_TOPOLOGY:
  182. hr = OnNewReplicaSet();
  183. break;
  184. case IDM_JUNCTION_TOP_SHOW_REPLICATION:
  185. case IDM_JUNCTION_TOP_HIDE_REPLICATION:
  186. m_bShowFRS = !m_bShowFRS;
  187. hr = OnShowReplication();
  188. break;
  189. case IDM_JUNCTION_TOP_STOP_REPLICATION:
  190. hr = OnStopReplication(TRUE);
  191. if (FAILED(hr))
  192. DisplayMessageBoxForHR(hr);
  193. break;
  194. case IDM_JUNCTION_TOP_CHECK_STATUS:
  195. hr = OnCheckStatus();
  196. break;
  197. default:
  198. hr = E_INVALIDARG;
  199. break;
  200. }
  201. return hr;
  202. }
  203. HRESULT CMmcDfsJunctionPoint::_InitReplicaSet()
  204. {
  205. DFS_TYPE lDfsType = DFS_TYPE_UNASSIGNED;
  206. HRESULT hr = GetDfsType((long *)&lDfsType);
  207. RETURN_IF_FAILED(hr);
  208. if (lDfsType != DFS_TYPE_FTDFS)
  209. return S_FALSE; // no replica set associate with standalone root
  210. BOOL bReplicaSetExist = FALSE;
  211. CComBSTR bstrDC;
  212. hr = m_pDfsJPObject->get_ReplicaSetExistEx(&bstrDC, &bReplicaSetExist);
  213. RETURN_IF_FAILED(hr);
  214. if (!bReplicaSetExist)
  215. {
  216. if ((IReplicaSet *)m_piReplicaSet)
  217. m_piReplicaSet.Release();
  218. return S_FALSE; // no replica set associate with it
  219. }
  220. if ((IReplicaSet *)m_piReplicaSet)
  221. {
  222. CComBSTR bstrTargetedDC;
  223. hr = m_piReplicaSet->get_TargetedDC(&bstrTargetedDC);
  224. if (FAILED(hr) || lstrcmpi(bstrTargetedDC, bstrDC))
  225. {
  226. // something is wrong or we're using a different DC, re-init m_piReplicaSet
  227. m_piReplicaSet.Release();
  228. }
  229. }
  230. //
  231. // read info of the replica set from DS
  232. //
  233. if (!m_piReplicaSet)
  234. {
  235. CComBSTR bstrDomain;
  236. hr = GetDomainName(&bstrDomain);
  237. RETURN_IF_FAILED(hr);
  238. CComBSTR bstrReplicaSetDN;
  239. hr = m_pDfsJPObject->get_ReplicaSetDN(&bstrReplicaSetDN);
  240. RETURN_IF_FAILED(hr);
  241. hr = CoCreateInstance(CLSID_ReplicaSet, NULL, CLSCTX_INPROC_SERVER, IID_IReplicaSet, (void**) &m_piReplicaSet);
  242. RETURN_IF_FAILED(hr);
  243. hr = m_piReplicaSet->Initialize(bstrDomain, bstrReplicaSetDN);
  244. if (FAILED(hr))
  245. {
  246. m_piReplicaSet.Release();
  247. return hr;
  248. }
  249. }
  250. return hr;
  251. }
  252. HRESULT
  253. CMmcDfsJunctionPoint::OnNewReplicaSet()
  254. {
  255. //
  256. // refresh to pick up possible namespace updates on targets by others
  257. //
  258. HRESULT hr = OnRefresh();
  259. if (S_FALSE == hr)
  260. {
  261. // this link has been deleted by others, no more reference
  262. DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_INVALID_LINK);
  263. return hr;
  264. }
  265. CWaitCursor wait;
  266. BOOL bReplicaSetExist = FALSE;
  267. m_pDfsJPObject->get_ReplicaSetExist(&bReplicaSetExist);
  268. if (bReplicaSetExist) // replica set exist, return
  269. return S_OK;
  270. CComBSTR bstrDomain;
  271. hr = GetDomainName(&bstrDomain);
  272. RETURN_IF_FAILED(hr);
  273. CComBSTR bstrReplicaSetDN;
  274. hr = m_pDfsJPObject->get_ReplicaSetDN(&bstrReplicaSetDN);
  275. RETURN_IF_FAILED(hr);
  276. CNewReplicaSet ReplicaSetInfo;
  277. hr = ReplicaSetInfo.Initialize(bstrDomain, bstrReplicaSetDN, &m_MmcRepList);
  278. RETURN_IF_FAILED(hr);
  279. if (S_FALSE == hr) // more than one targets on the same computer
  280. {
  281. if (IDYES != DisplayMessageBox(::GetActiveWindow(), MB_YESNO, 0, IDS_MSG_TARGETS_ONSAMECOMPUTER))
  282. return hr;
  283. }
  284. CNewReplicaSetPage0 WizPage0;
  285. CNewReplicaSetPage1 WizPage1(&ReplicaSetInfo);
  286. CNewReplicaSetPage2 WizPage2(&ReplicaSetInfo, IsNewSchema());
  287. //CNewReplicaSetPage3 WizPage3(&ReplicaSetInfo);
  288. CComPtr<IPropertySheetCallback> pPropSheetCallback; // MMC Callback used to add pages
  289. hr = m_lpConsole->QueryInterface(IID_IPropertySheetCallback, reinterpret_cast<void**>(&pPropSheetCallback));
  290. RETURN_IF_FAILED(hr);
  291. CComPtr<IPropertySheetProvider> pPropSheetProvider; // MMC callback used to handle wizard
  292. hr = m_lpConsole->QueryInterface(IID_IPropertySheetProvider, reinterpret_cast<void**>(&pPropSheetProvider));
  293. RETURN_IF_FAILED(hr);
  294. //
  295. // Create the wizard
  296. //
  297. hr = pPropSheetProvider->CreatePropertySheet(
  298. _T(""), // title
  299. FALSE, // Wizard and not property sheet.
  300. 0, // Cookie
  301. NULL, // IDataobject
  302. MMC_PSO_NEWWIZARDTYPE); // Creation flags
  303. RETURN_IF_FAILED(hr);
  304. hr = pPropSheetCallback->AddPage(WizPage0.Create());
  305. RETURN_IF_FAILED(hr);
  306. hr = pPropSheetCallback->AddPage(WizPage1.Create());
  307. RETURN_IF_FAILED(hr);
  308. hr = pPropSheetCallback->AddPage(WizPage2.Create());
  309. RETURN_IF_FAILED(hr);
  310. /*hr = pPropSheetCallback->AddPage(WizPage3.Create());
  311. RETURN_IF_FAILED(hr);*/
  312. // Ask the provider to use the pages from the callback
  313. hr = pPropSheetProvider->AddPrimaryPages(
  314. //(IComponentData *)(m_pParent->m_pScopeManager),
  315. NULL,
  316. TRUE, // Don't create a notify handle
  317. NULL,
  318. TRUE // Scope pane (not result pane)
  319. );
  320. RETURN_IF_FAILED(hr);
  321. //
  322. // Display the wizard
  323. //
  324. HWND hwndParent = NULL;
  325. hr = m_lpConsole->GetMainWindow(&hwndParent);
  326. RETURN_IF_FAILED(hr);
  327. hr = pPropSheetProvider->Show((LONG_PTR)hwndParent, 0);
  328. RETURN_IF_FAILED(hr);
  329. //
  330. // handle th result
  331. //
  332. if (S_OK == ReplicaSetInfo.m_hr)
  333. {
  334. //
  335. // store the interface pointer
  336. //
  337. m_piReplicaSet = ReplicaSetInfo.m_piReplicaSet;
  338. m_pDfsJPObject->put_ReplicaSetExist(TRUE);
  339. //
  340. // update icon
  341. //
  342. SCOPEDATAITEM ScopeDataItem;
  343. ZeroMemory(&ScopeDataItem, sizeof(SCOPEDATAITEM));
  344. ScopeDataItem.mask = SDI_IMAGE | SDI_OPENIMAGE;
  345. ScopeDataItem.ID = m_hScopeItem;
  346. hr = m_lpConsoleNameSpace->GetItem(&ScopeDataItem);
  347. RETURN_IF_FAILED(hr);
  348. if (SUCCEEDED(hr))
  349. {
  350. ScopeDataItem.nImage += 4;
  351. ScopeDataItem.nOpenImage += 4;
  352. hr = m_lpConsoleNameSpace->SetItem(&ScopeDataItem);
  353. }
  354. m_lpConsole->SelectScopeItem(m_hScopeItem);
  355. }
  356. return hr;
  357. }
  358. HRESULT CMmcDfsJunctionPoint::OnShowReplication()
  359. {
  360. BOOL bShowFRS = m_bShowFRS; // save it because refresh will reset it to FALSE
  361. //
  362. // refresh to pick up possible namespace updates on targets by others
  363. //
  364. HRESULT hr = OnRefresh();
  365. if (S_FALSE == hr)
  366. {
  367. // this link has been deleted by others, no more reference
  368. DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_INVALID_LINK);
  369. return hr;
  370. }
  371. CWaitCursor wait;
  372. DFS_REPLICA_LIST::iterator i;
  373. if (bShowFRS)
  374. {
  375. hr = _InitReplicaSet();
  376. if (S_OK != hr) // no replica set, do nothing and return
  377. return S_OK;
  378. //
  379. // fill in each alternate m_bstrFRSColumnText and m_bstrStatusText
  380. //
  381. for (i = m_MmcRepList.begin(); i != m_MmcRepList.end(); i++)
  382. {
  383. ((*i)->pReplica)->ShowReplicationInfo(m_piReplicaSet);
  384. }
  385. m_bShowFRS = TRUE;
  386. }
  387. m_lpConsole->UpdateAllViews((IDataObject*)this, 0, 1);
  388. m_lpConsole->SelectScopeItem(m_hScopeItem);
  389. return hr;
  390. }
  391. HRESULT
  392. CMmcDfsJunctionPoint::OnStopReplication(BOOL bConfirm /* = FALSE */)
  393. {
  394. //
  395. // refresh to pick up possible namespace updates on targets by others
  396. //
  397. HRESULT hr = OnRefresh();
  398. if (S_FALSE == hr)
  399. {
  400. // this link has been deleted by others, no more reference
  401. DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_INVALID_LINK);
  402. return hr;
  403. }
  404. CWaitCursor wait;
  405. BOOL bReplicaSetExist = FALSE;
  406. m_pDfsJPObject->get_ReplicaSetExist(&bReplicaSetExist);
  407. if (!bReplicaSetExist) // replica set doesn't exist, return
  408. return S_OK;
  409. if (bConfirm)
  410. {
  411. hr = ConfirmOperationOnDfsLink(IDS_MSG_STOP_REPLICATION);
  412. if (S_OK != hr) return hr;
  413. }
  414. //
  415. // init m_piReplicaSet
  416. //
  417. hr = _InitReplicaSet();
  418. if (S_OK != hr) // no replica set, return
  419. return hr;
  420. hr = m_piReplicaSet->Delete();
  421. if (SUCCEEDED(hr))
  422. {
  423. m_piReplicaSet.Release();
  424. hr = m_pDfsJPObject->put_ReplicaSetExist(FALSE);
  425. SCOPEDATAITEM ScopeDataItem;
  426. ZeroMemory(&ScopeDataItem, sizeof(SCOPEDATAITEM));
  427. ScopeDataItem.mask = SDI_IMAGE | SDI_OPENIMAGE;
  428. ScopeDataItem.ID = m_hScopeItem;
  429. hr = m_lpConsoleNameSpace->GetItem(&ScopeDataItem);
  430. if (SUCCEEDED(hr))
  431. {
  432. ScopeDataItem.nImage -= 4;
  433. ScopeDataItem.nOpenImage -= 4;
  434. m_lpConsoleNameSpace->SetItem(&ScopeDataItem);
  435. }
  436. m_lpConsole->SelectScopeItem(m_hScopeItem);
  437. if (m_bShowFRS)
  438. {
  439. m_bShowFRS = FALSE;
  440. OnShowReplication();
  441. }
  442. }
  443. return hr;
  444. }
  445. STDMETHODIMP
  446. CMmcDfsJunctionPoint::SetColumnHeader(
  447. IN LPHEADERCTRL2 i_piHeaderControl
  448. )
  449. {
  450. RETURN_INVALIDARG_IF_NULL(i_piHeaderControl);
  451. CComBSTR bstrColumn0;
  452. HRESULT hr = LoadStringFromResource(IDS_RESULT_COLUMN_REPLICA, &bstrColumn0);
  453. RETURN_IF_FAILED(hr);
  454. i_piHeaderControl->InsertColumn(0, bstrColumn0, LVCFMT_LEFT, DFS_NAME_COLUMN_WIDTH);
  455. if (m_bShowFRS)
  456. {
  457. CComBSTR bstrColumn1;
  458. hr = LoadStringFromResource(IDS_RESULT_COLUMN_FRS, &bstrColumn1);
  459. RETURN_IF_FAILED(hr);
  460. i_piHeaderControl->InsertColumn(1, bstrColumn1, LVCFMT_LEFT, MMCLV_AUTO);
  461. }
  462. return hr;
  463. }
  464. STDMETHODIMP
  465. CMmcDfsJunctionPoint::GetResultDisplayInfo(
  466. IN OUT LPRESULTDATAITEM io_pResultDataItem
  467. )
  468. /*++
  469. Routine Description:
  470. Returns the information required for MMC display for this item.
  471. Arguments:
  472. io_pResultDataItem - The ResultItem which specifies what display information is required
  473. --*/
  474. {
  475. RETURN_INVALIDARG_IF_NULL(io_pResultDataItem);
  476. if (RDI_IMAGE & io_pResultDataItem->mask)
  477. io_pResultDataItem->nImage = CMmcDfsJunctionPoint::m_iIMAGEINDEX + m_lJunctionState;
  478. if (RDI_STR & io_pResultDataItem->mask)
  479. {
  480. if (0 == io_pResultDataItem->nCol)
  481. io_pResultDataItem->str = m_bstrDisplayName;
  482. }
  483. return S_OK;
  484. }
  485. STDMETHODIMP
  486. CMmcDfsJunctionPoint::GetScopeDisplayInfo(
  487. IN OUT LPSCOPEDATAITEM io_pScopeDataItem
  488. )
  489. /*++
  490. Routine Description:
  491. Returns the information required for MMC display for this item.
  492. Arguments:
  493. i_pScopeDataItem - The ScopeItem which specifies what display information is required
  494. --*/
  495. {
  496. RETURN_INVALIDARG_IF_NULL(io_pScopeDataItem);
  497. if (SDI_STR & io_pScopeDataItem->mask)
  498. io_pScopeDataItem->displayname = m_bstrDisplayName;
  499. if (SDI_IMAGE & io_pScopeDataItem->mask)
  500. io_pScopeDataItem->nImage = CMmcDfsJunctionPoint::m_iIMAGEINDEX + m_lJunctionState;
  501. if (SDI_OPENIMAGE & io_pScopeDataItem->mask)
  502. io_pScopeDataItem->nOpenImage = CMmcDfsRoot::m_iOPENIMAGEINDEX + m_lJunctionState;
  503. return S_OK;
  504. };
  505. STDMETHODIMP
  506. CMmcDfsJunctionPoint::EnumerateScopePane(
  507. IN LPCONSOLENAMESPACE i_lpConsoleNameSpace,
  508. IN HSCOPEITEM i_hParent
  509. )
  510. {
  511. return S_OK; // no scope pane children
  512. }
  513. STDMETHODIMP
  514. CMmcDfsJunctionPoint::EnumerateResultPane(
  515. IN OUT IResultData* io_pResultData
  516. )
  517. /*++
  518. Routine Description:
  519. To eumerate(add) items in the result pane. Replicas in this case
  520. Arguments:
  521. io_pResultData - The callback used to add items to the Result pane
  522. --*/
  523. {
  524. RETURN_INVALIDARG_IF_NULL(io_pResultData);
  525. HRESULT hr = S_OK;
  526. if (m_MmcRepList.empty())
  527. {
  528. CComPtr<IEnumVARIANT> pRepEnum;
  529. hr = m_pDfsJPObject->get__NewEnum ((IUnknown**) &pRepEnum);
  530. RETURN_IF_FAILED(hr);
  531. VARIANT varReplicaObject;
  532. VariantInit(&varReplicaObject);
  533. while ( S_OK == (hr = pRepEnum->Next(1, &varReplicaObject, NULL)) )
  534. {
  535. CComPtr<IDfsReplica> pReplicaObject;
  536. pReplicaObject = (IDfsReplica*) varReplicaObject.pdispVal;
  537. CMmcDfsReplica* pMMCReplicaObject = new CMmcDfsReplica(pReplicaObject, this);
  538. if (!pMMCReplicaObject)
  539. {
  540. hr = E_OUTOFMEMORY;
  541. } else
  542. {
  543. hr = pMMCReplicaObject->m_hrValueFromCtor;
  544. if (SUCCEEDED(hr))
  545. {
  546. hr = pMMCReplicaObject->AddItemToResultPane(io_pResultData);
  547. if (SUCCEEDED(hr))
  548. {
  549. REP_LIST_NODE* pRepNode = new REP_LIST_NODE(pMMCReplicaObject);
  550. if (!pRepNode)
  551. {
  552. hr = E_OUTOFMEMORY;
  553. } else
  554. {
  555. m_MmcRepList.push_back(pRepNode);
  556. }
  557. }
  558. }
  559. if (FAILED(hr))
  560. delete pMMCReplicaObject;
  561. }
  562. VariantClear(&varReplicaObject);
  563. if (FAILED(hr))
  564. break;
  565. }
  566. }
  567. else
  568. {
  569. // The replicas of this junction are already enumerated,
  570. // and the list exists, just add result items.
  571. for (DFS_REPLICA_LIST::iterator i = m_MmcRepList.begin(); i != m_MmcRepList.end(); i++)
  572. {
  573. hr = ((*i)->pReplica)->AddItemToResultPane(io_pResultData);
  574. BREAK_IF_FAILED(hr);
  575. }
  576. }
  577. return hr;
  578. }
  579. STDMETHODIMP
  580. CMmcDfsJunctionPoint::SetConsoleVerbs(
  581. IN LPCONSOLEVERB i_lpConsoleVerb
  582. )
  583. /*++
  584. Routine Description:
  585. Routine used to set the console verb settings.
  586. Sets all of them except Open off.
  587. For all scope pane items, default verb is "open'. For result items,
  588. it is "properties"
  589. Arguments:
  590. i_lpConsoleVerb - The callback used to handle console verbs
  591. --*/
  592. {
  593. RETURN_INVALIDARG_IF_NULL(i_lpConsoleVerb);
  594. i_lpConsoleVerb->SetVerbState(MMC_VERB_COPY, HIDDEN, TRUE);
  595. i_lpConsoleVerb->SetVerbState(MMC_VERB_PASTE, HIDDEN, TRUE);
  596. i_lpConsoleVerb->SetVerbState(MMC_VERB_RENAME, HIDDEN, TRUE);
  597. i_lpConsoleVerb->SetVerbState(MMC_VERB_PRINT, HIDDEN, TRUE);
  598. i_lpConsoleVerb->SetVerbState(MMC_VERB_DELETE, HIDDEN, TRUE);
  599. i_lpConsoleVerb->SetVerbState(MMC_VERB_OPEN, HIDDEN, TRUE);
  600. i_lpConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, TRUE);
  601. i_lpConsoleVerb->SetVerbState(MMC_VERB_REFRESH, ENABLED, TRUE);
  602. i_lpConsoleVerb->SetDefaultVerb(MMC_VERB_OPEN); //For scope items, default verb is "open"
  603. return S_OK;
  604. }
  605. /*
  606. Case1: add to a n-targets-link (repOn or repOff) which has actually been deleted by another DfsGui instance
  607. result: refresh the root (the whole namespace), put up the retry message
  608. Case2: add to a n-targets-link (repOn) whose targets have been partly deleted and whose replication has been turned off by another DfsGui instance
  609. result: refresh the link, add the new target, if (checked && #targets>1), invoke the RepCfg wizard
  610. Case3: add to a n-targets-link (repOn) whose targets have been partly deleted and whose replication has still been kept on by another DfsGui instance
  611. result: refresh the link, add the new target, if (checked && #targets>1), join the new target to replication set
  612. Case4: add to a n-targets-link (repOn), no other DfsGui instances are involved
  613. result: refresh the link, add the new target, if (checked && #targets>1), join the new target to replication set
  614. Case5: add to a n-targets-link (repOff), no other DfsGui instances are involved
  615. result: refresh the link, add the new target, if (checked && #targets>1), invoke the RepCfg wizard
  616. */
  617. STDMETHODIMP
  618. CMmcDfsJunctionPoint::OnNewReplica(
  619. )
  620. /*++
  621. Routine Description:
  622. Adds a new replica to the Junction Point.
  623. --*/
  624. {
  625. HRESULT hr = S_OK;
  626. CAddRep AddRepDlg;
  627. CComBSTR bstrServerName;
  628. CComBSTR bstrShareName;
  629. CComBSTR bstrNetPath;
  630. AddRepDlg.put_EntryPath(m_bstrEntryPath);
  631. AddRepDlg.put_DfsType(m_pDfsParentRoot->m_lDfsRootType);
  632. hr = AddRepDlg.DoModal();
  633. if (S_OK != hr)
  634. return hr;
  635. AddRepDlg.get_Server(&bstrServerName);
  636. AddRepDlg.get_Share(&bstrShareName);
  637. AddRepDlg.get_NetPath(&bstrNetPath);
  638. /* bug#290375: both UI and core should allow interlink to have multiple targets
  639. // Is it a dfs based path? These are not allowed.
  640. if (IsDfsPath(bstrNetPath))
  641. {
  642. DisplayMessageBoxWithOK( IDS_MSG_MID_JUNCTION, bstrNetPath);
  643. return(S_OK);
  644. }
  645. */
  646. //
  647. // refresh to pick up possible namespace updates on this link or link targets
  648. //
  649. hr = OnRefresh();
  650. if (S_FALSE == hr)
  651. {
  652. //
  653. // this link has been deleted by other means, scope pane has been refreshed,
  654. // ask user to retry
  655. //
  656. DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_INVALID_LINK);
  657. return hr;
  658. }
  659. CWaitCursor wait;
  660. CComPtr<IDfsReplica> pReplicaObject;
  661. CMmcDfsReplica* pMMCReplicaObject = NULL;
  662. VARIANT varReplicaObject;
  663. VariantInit(&varReplicaObject);
  664. hr = m_pDfsJPObject->AddReplica(bstrServerName, bstrShareName, &varReplicaObject);
  665. if (FAILED(hr))
  666. {
  667. DisplayMessageBox(::GetActiveWindow(), MB_OK, hr, IDS_MSG_FAILED_TO_CREATE_REPLICA);
  668. return hr;
  669. }
  670. // Get the IDfsReplica interface.
  671. pReplicaObject = (IDfsReplica*) varReplicaObject.pdispVal;
  672. // Create display object.
  673. pMMCReplicaObject = new CMmcDfsReplica(pReplicaObject, this);
  674. if (!pMMCReplicaObject)
  675. return E_OUTOFMEMORY;
  676. // Add item to replica list and update
  677. // Result view.
  678. AddResultPaneItem(pMMCReplicaObject);
  679. m_bDirty = true;
  680. //
  681. // If requested and the link has more than 1 target, configure file replication
  682. //
  683. if (CAddRep::NORMAL_REPLICATION == AddRepDlg.get_ReplicationType() && (m_MmcRepList.size() > 1))
  684. {
  685. BOOL bReplicaSetExist = FALSE;
  686. hr = m_pDfsJPObject->get_ReplicaSetExist(&bReplicaSetExist);
  687. RETURN_IF_FAILED(hr);
  688. if (!bReplicaSetExist)
  689. {
  690. if (IDYES == DisplayMessageBox(::GetActiveWindow(), MB_YESNO, 0, IDS_MSG_NEWFRS_NOW))
  691. hr = OnNewReplicaSet();
  692. } else
  693. {
  694. hr = pMMCReplicaObject->OnReplicate();
  695. }
  696. }
  697. return hr;
  698. }
  699. STDMETHODIMP
  700. CMmcDfsJunctionPoint::AddItemToScopePane(
  701. IN HSCOPEITEM i_hParent
  702. )
  703. {
  704. HRESULT hr = S_OK;
  705. BOOL bReplicaSetExist = FALSE;
  706. hr = m_pDfsJPObject->get_ReplicaSetExist(&bReplicaSetExist);
  707. if (SUCCEEDED(hr))
  708. {
  709. SCOPEDATAITEM JPScopeDataItem;
  710. memset (&JPScopeDataItem, 0, sizeof(SCOPEDATAITEM));
  711. JPScopeDataItem.mask = SDI_PARENT | SDI_IMAGE | SDI_OPENIMAGE | SDI_PARAM | SDI_STR | SDI_CHILDREN;
  712. JPScopeDataItem.relativeID = i_hParent; //ID of DfsRoot Node
  713. JPScopeDataItem.nImage = CMmcDfsJunctionPoint::m_iIMAGEINDEX + (bReplicaSetExist ? 4 : 0);
  714. JPScopeDataItem.nOpenImage = CMmcDfsJunctionPoint::m_iOPENIMAGEINDEX + (bReplicaSetExist ? 4 : 0);
  715. JPScopeDataItem.lParam = reinterpret_cast<LPARAM> (this);
  716. JPScopeDataItem.displayname = MMC_CALLBACK ;
  717. hr = m_lpConsoleNameSpace->InsertItem(&JPScopeDataItem);
  718. if (SUCCEEDED(hr))
  719. m_hScopeItem = JPScopeDataItem.ID;
  720. }
  721. return hr;
  722. }
  723. STDMETHODIMP
  724. CMmcDfsJunctionPoint :: OnRemoveJP (IN BOOL bConfirm)
  725. /*++
  726. Routine Description:
  727. This internal method handles the removal of Junction Points.
  728. --*/
  729. {
  730. // check outstanding property sheet.
  731. HRESULT hr = ClosePropertySheet(!bConfirm);
  732. if (bConfirm)
  733. {
  734. if (S_OK != hr) // open property page found, discontinue
  735. return hr;
  736. hr = ConfirmOperationOnDfsLink(IDS_MSG_REMOVE_JP);
  737. if(S_OK != hr) // Error or User decided to abort the operation
  738. return hr;
  739. }
  740. // 5/12/2001: no need to select the scope node when deleting link
  741. //m_lpConsole->SelectScopeItem(m_hScopeItem);
  742. CWaitCursor WaitCursor; // Display the wait cursor
  743. // Delete the associated replica set
  744. hr = _InitReplicaSet();
  745. if (S_OK == hr)
  746. {
  747. m_piReplicaSet->Delete();
  748. m_pDfsJPObject->put_ReplicaSetExist(FALSE);
  749. m_piReplicaSet.Release();
  750. }
  751. // Remove the actual junction point(from DS)
  752. hr = m_pDfsParentRoot->m_DfsRoot->DeleteJunctionPoint(m_bstrDisplayName);
  753. RETURN_IF_FAILED(hr);
  754. hr = m_pDfsParentRoot->DeleteMmcJPNode(this);
  755. RETURN_IF_FAILED(hr);
  756. // Remove it from MMC console
  757. hr = m_lpConsoleNameSpace->DeleteItem(m_hScopeItem, TRUE);
  758. RETURN_IF_FAILED(hr);
  759. Release(); // Release (delete) this Object
  760. return (hr);
  761. }
  762. HRESULT
  763. CMmcDfsJunctionPoint::ClosePropertySheet(BOOL bSilent)
  764. {
  765. if (!m_PropPage.m_hWnd && !m_frsPropPage.m_hWnd)
  766. return S_OK; // no outstanding property sheet, return S_OK;
  767. CComPtr<IPropertySheetProvider> pPropSheetProvider;
  768. HRESULT hr = m_lpConsole->QueryInterface(IID_IPropertySheetProvider, reinterpret_cast<void**>(&pPropSheetProvider));
  769. if (FAILED(hr))
  770. {
  771. hr = S_OK; // ignore the QI failure
  772. } else
  773. {
  774. //
  775. // find the outstanding property sheet and bring it to foreground
  776. //
  777. hr = pPropSheetProvider->FindPropertySheet((MMC_COOKIE)m_hScopeItem, NULL, this);
  778. if (S_OK == hr)
  779. {
  780. if (bSilent)
  781. {
  782. //
  783. // silently close outstanding property sheet, and return S_OK to continue user's operation
  784. //
  785. if (m_PropPage.m_hWnd)
  786. ::SendMessage(m_PropPage.m_hWnd, WM_PARENT_NODE_CLOSING, 0, 0);
  787. if (m_frsPropPage.m_hWnd)
  788. ::SendMessage(m_frsPropPage.m_hWnd, WM_PARENT_NODE_CLOSING, 0, 0);
  789. } else
  790. {
  791. //
  792. // ask user to close it, return S_FALSE to quit user's operation
  793. //
  794. DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_PROPERTYPAGE_NOTCLOSED);
  795. return S_FALSE;
  796. }
  797. } else
  798. {
  799. hr = S_OK; // no outstanding property sheet, return S_OK
  800. }
  801. }
  802. //
  803. // reset HWND
  804. //
  805. m_PropPage.m_hWnd = NULL;
  806. m_frsPropPage.m_hWnd = NULL;
  807. return hr;
  808. }
  809. STDMETHODIMP
  810. CMmcDfsJunctionPoint::ConfirmOperationOnDfsLink(int idString)
  811. /*++
  812. Routine Description:
  813. Asks the user for confirmation of whether he really wants to remove the particular
  814. Junction point.
  815. Return value:
  816. S_OK, if the user chooses YES,
  817. S_FALSE, if the user chooses NO.
  818. --*/
  819. {
  820. CComBSTR bstrAppName;
  821. HRESULT hr = LoadStringFromResource (IDS_APPLICATION_NAME, &bstrAppName);
  822. RETURN_IF_FAILED(hr);
  823. CComBSTR bstrFormattedMessage;
  824. hr = FormatResourceString(idString, m_bstrEntryPath, &bstrFormattedMessage);
  825. RETURN_IF_FAILED(hr);
  826. CThemeContextActivator activator;
  827. if (IDNO == ::MessageBox(::GetActiveWindow(), bstrFormattedMessage, bstrAppName, MB_YESNO | MB_ICONEXCLAMATION | MB_APPLMODAL))
  828. return S_FALSE;
  829. return S_OK;
  830. }
  831. //
  832. // Call the root's RemoveJP() method to:
  833. // 1. refresh the root node to pick up possible namespace updates by others
  834. // 2. then locate the appropriate link to actually perform the removal operation
  835. //
  836. STDMETHODIMP
  837. CMmcDfsJunctionPoint::DoDelete(
  838. )
  839. {
  840. HRESULT hr = m_pDfsParentRoot->RemoveJP(m_bstrDisplayName);
  841. if(FAILED(hr))
  842. DisplayMessageBox(::GetActiveWindow(), MB_OK, hr, IDS_MSG_WIZ_DELETE_JP_FAILURE, m_bstrDisplayName);
  843. return hr;
  844. }
  845. STDMETHODIMP
  846. CMmcDfsJunctionPoint::QueryPagesFor(
  847. )
  848. /*++
  849. Routine Description:
  850. Used to decide whether the object wants to display property pages.
  851. Returning S_OK typically results in a call to CreatePropertyPages.
  852. --*/
  853. {
  854. //
  855. // refresh to pick up possible namespace updates by others
  856. //
  857. HRESULT hr = OnRefresh();
  858. if (S_FALSE == hr)
  859. {
  860. // this link has been deleted by others, no more reference
  861. DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_INVALID_LINK);
  862. return hr; // no property page
  863. }
  864. return S_OK; // yes, we want to display a propertysheet
  865. }
  866. // Creates and passes back the pages to be displayed
  867. STDMETHODIMP
  868. CMmcDfsJunctionPoint::CreatePropertyPages(
  869. IN LPPROPERTYSHEETCALLBACK i_lpPropSheetCallback,
  870. IN LONG_PTR i_lNotifyHandle
  871. )
  872. /*++
  873. Routine Description:
  874. Used to display the property sheet pages
  875. Arguments:
  876. i_lpPropSheetCallback - The callback used to create the propertysheet.
  877. i_lNotifyHandle - Notify handle used by the property page
  878. --*/
  879. {
  880. RETURN_INVALIDARG_IF_NULL(i_lpPropSheetCallback);
  881. m_lpConsole->SelectScopeItem(m_hScopeItem);
  882. CWaitCursor WaitCursor;
  883. HRESULT hr = S_OK;
  884. do {
  885. hr = m_PropPage.Initialize(NULL, (IDfsJunctionPoint*)m_pDfsJPObject);
  886. BREAK_IF_FAILED(hr);
  887. // Create the page for the replica set.
  888. // Pass it to the Callback
  889. HPROPSHEETPAGE h_proppage = m_PropPage.Create();
  890. if (!h_proppage)
  891. {
  892. hr = HRESULT_FROM_WIN32(::GetLastError());
  893. break;
  894. }
  895. // Pass on the notify data to the Property Page
  896. hr = m_PropPage.SetNotifyData(i_lNotifyHandle, (LPARAM)this);
  897. BREAK_IF_FAILED (hr);
  898. hr = i_lpPropSheetCallback->AddPage(h_proppage);
  899. BREAK_IF_FAILED (hr);
  900. //
  901. // Add "Replica Set" page
  902. //
  903. hr = CreateFrsPropertyPage(i_lpPropSheetCallback, i_lNotifyHandle);
  904. if (FAILED(hr))
  905. {
  906. DisplayMessageBox(::GetActiveWindow(), MB_OK, hr, IDS_REPPAGE_ERROR);
  907. hr = S_OK; // allow the other tabs to be brought up
  908. }
  909. } while (0);
  910. if (FAILED(hr))
  911. DisplayMessageBoxForHR(hr);
  912. return hr;
  913. }
  914. STDMETHODIMP
  915. CMmcDfsJunctionPoint::CreateFrsPropertyPage
  916. (
  917. IN LPPROPERTYSHEETCALLBACK i_lpPropSheetCallback,
  918. IN LONG_PTR i_lNotifyHandle
  919. )
  920. {
  921. HRESULT hr = _InitReplicaSet();
  922. if (S_OK != hr)
  923. return hr;
  924. CComBSTR bstrType;
  925. hr = m_piReplicaSet->get_Type(&bstrType);
  926. RETURN_IF_FAILED(hr);
  927. if (lstrcmpi(bstrType, FRS_RSTYPE_DFS))
  928. return hr;
  929. //
  930. // set initial values on the property page
  931. //
  932. hr = m_frsPropPage.Initialize(m_piReplicaSet);
  933. RETURN_IF_FAILED(hr);
  934. //
  935. // create the property page
  936. //
  937. HPROPSHEETPAGE h_frsproppage = m_frsPropPage.Create();
  938. if (!h_frsproppage)
  939. return HRESULT_FROM_WIN32(::GetLastError());
  940. //
  941. // pass on the notify data to the Property Page
  942. //
  943. hr = m_frsPropPage.SetNotifyData(i_lNotifyHandle, (LPARAM)this);
  944. RETURN_IF_FAILED(hr);
  945. //
  946. // AddPage
  947. //
  948. return i_lpPropSheetCallback->AddPage(h_frsproppage);
  949. }
  950. STDMETHODIMP
  951. CMmcDfsJunctionPoint::PropertyChanged(
  952. )
  953. /*++
  954. Routine Description:
  955. Used to update the properties.
  956. --*/
  957. {
  958. return S_OK;
  959. }
  960. HRESULT
  961. CMmcDfsJunctionPoint::SetDescriptionBarText(
  962. IN LPRESULTDATA i_lpResultData
  963. )
  964. /*++
  965. Routine Description:
  966. A routine used set the text in the Description bar above
  967. the result view.
  968. Arguments:
  969. i_lpResultData - Pointer to the IResultData callback which is
  970. used to set the description text
  971. --*/
  972. {
  973. RETURN_INVALIDARG_IF_NULL(i_lpResultData);
  974. CComBSTR bstrTextForDescriptionBar; // Text to be shown in the Result view Description bar
  975. HRESULT hr = FormatResourceString(IDS_DESCRIPTION_BAR_TEXT_JUNCTIONPOINT, m_bstrEntryPath, &bstrTextForDescriptionBar);
  976. RETURN_IF_FAILED(hr);
  977. hr = i_lpResultData->SetDescBarText(bstrTextForDescriptionBar);
  978. return hr;
  979. }
  980. HRESULT
  981. CMmcDfsJunctionPoint::ToolbarSelect(
  982. IN const LONG i_lArg,
  983. IN IToolbar* i_pToolBar
  984. )
  985. /*++
  986. Routine Description:
  987. Handle a select event for a toolbar
  988. Create a toolbar, it it doesn't exist.
  989. Attach the toolbar and enable the buttons, if the event for a selection.
  990. Disable the buttons, if the event was for a deselection
  991. Arguments:
  992. i_lArg - The argument passed to the actual method.
  993. o_pToolBar - The Toolbar pointer.
  994. --*/
  995. {
  996. RETURN_INVALIDARG_IF_NULL(i_pToolBar);
  997. BOOL bSelect = (BOOL) HIWORD(i_lArg); // Is the event for selection?
  998. EnableToolbarButtons(i_pToolBar, IDT_JP_MIN, IDT_JP_MAX, bSelect);
  999. if (bSelect)
  1000. {
  1001. BOOL bReplicaSetExist = FALSE;
  1002. HRESULT hr = m_pDfsJPObject->get_ReplicaSetExist(&bReplicaSetExist);
  1003. RETURN_IF_FAILED(hr);
  1004. if (bReplicaSetExist || (1 >= m_MmcRepList.size()) ||
  1005. (DFS_TYPE_STANDALONE == m_pDfsParentRoot->m_lDfsRootType))
  1006. {
  1007. i_pToolBar->SetButtonState(IDT_JP_REPLICATION_TOPOLOGY, ENABLED, FALSE);
  1008. i_pToolBar->SetButtonState(IDT_JP_REPLICATION_TOPOLOGY, HIDDEN, TRUE);
  1009. }
  1010. if (!bReplicaSetExist)
  1011. {
  1012. i_pToolBar->SetButtonState(IDT_JP_SHOW_REPLICATION, ENABLED, FALSE);
  1013. i_pToolBar->SetButtonState(IDT_JP_SHOW_REPLICATION, HIDDEN, TRUE);
  1014. i_pToolBar->SetButtonState(IDT_JP_HIDE_REPLICATION, ENABLED, FALSE);
  1015. i_pToolBar->SetButtonState(IDT_JP_HIDE_REPLICATION, HIDDEN, TRUE);
  1016. i_pToolBar->SetButtonState(IDT_JP_STOP_REPLICATION, ENABLED, FALSE);
  1017. i_pToolBar->SetButtonState(IDT_JP_STOP_REPLICATION, HIDDEN, TRUE);
  1018. } else
  1019. {
  1020. if (m_bShowFRS)
  1021. {
  1022. i_pToolBar->SetButtonState(IDT_JP_SHOW_REPLICATION, ENABLED, FALSE);
  1023. i_pToolBar->SetButtonState(IDT_JP_SHOW_REPLICATION, HIDDEN, TRUE);
  1024. } else
  1025. {
  1026. i_pToolBar->SetButtonState(IDT_JP_HIDE_REPLICATION, ENABLED, FALSE);
  1027. i_pToolBar->SetButtonState(IDT_JP_HIDE_REPLICATION, HIDDEN, TRUE);
  1028. }
  1029. }
  1030. }
  1031. return S_OK;
  1032. }
  1033. HRESULT
  1034. CMmcDfsJunctionPoint::CreateToolbar(
  1035. IN const LPCONTROLBAR i_pControlbar,
  1036. IN const LPEXTENDCONTROLBAR i_lExtendControlbar,
  1037. OUT IToolbar** o_pToolBar
  1038. )
  1039. /*++
  1040. Routine Description:
  1041. Create the toolbar.
  1042. Involves the actual toolbar creation call, creating the bitmap and adding it
  1043. and finally adding the buttons to the toolbar
  1044. Arguments:
  1045. i_pControlbar - The controlbar used to create toolbar.
  1046. i_lExtendControlbar - The object implementing IExtendControlbar. This is
  1047. the class exposed to MMC.
  1048. --*/
  1049. {
  1050. RETURN_INVALIDARG_IF_NULL(i_pControlbar);
  1051. RETURN_INVALIDARG_IF_NULL(i_lExtendControlbar);
  1052. RETURN_INVALIDARG_IF_NULL(o_pToolBar);
  1053. HRESULT hr = E_FAIL;
  1054. CComBSTR bstrAllTheMenuText;
  1055. int iButtonPosition = 0; // The first button position
  1056. // Create the toolbar
  1057. hr = i_pControlbar->Create(TOOLBAR, i_lExtendControlbar, reinterpret_cast<LPUNKNOWN*>(o_pToolBar));
  1058. RETURN_IF_FAILED(hr);
  1059. // Add the bitmap to the toolbar
  1060. hr = AddBitmapToToolbar(*o_pToolBar, IDB_JP_TOOLBAR);
  1061. RETURN_IF_FAILED(hr);
  1062. for (int iCommandID = IDT_JP_MIN, iMenuResource = IDS_MENUS_JUNCTION_TOP_NEW_DFS_REPLICA;
  1063. iCommandID <= IDT_JP_MAX;
  1064. iCommandID++,iMenuResource++,iButtonPosition++)
  1065. {
  1066. CComBSTR bstrMenuText;
  1067. CComBSTR bstrToolTipText;
  1068. hr = GetMenuResourceStrings(iMenuResource, &bstrMenuText, &bstrToolTipText, NULL);
  1069. RETURN_IF_FAILED(hr);
  1070. MMCBUTTON ToolbarButton;
  1071. ZeroMemory(&ToolbarButton, sizeof ToolbarButton);
  1072. ToolbarButton.nBitmap = iButtonPosition;
  1073. ToolbarButton.idCommand = iCommandID;
  1074. ToolbarButton.fsState = TBSTATE_ENABLED;
  1075. ToolbarButton.fsType = TBSTYLE_BUTTON;
  1076. ToolbarButton.lpButtonText = bstrMenuText;
  1077. ToolbarButton.lpTooltipText = bstrToolTipText;
  1078. // Add the button to the toolbar
  1079. hr = (*o_pToolBar)->InsertButton(iButtonPosition, &ToolbarButton);
  1080. _ASSERTE(S_OK == hr); // Assert, but continue as we want to try other buttons
  1081. }
  1082. return S_OK;
  1083. }
  1084. STDMETHODIMP
  1085. CMmcDfsJunctionPoint::ToolbarClick(
  1086. IN const LPCONTROLBAR i_pControlbar,
  1087. IN const LPARAM i_lParam
  1088. )
  1089. /*++
  1090. Routine Description:
  1091. Action to take on a click on a toolbar
  1092. Arguments:
  1093. i_pControlbar - The controlbar used to create toolbar.
  1094. i_lParam - The lparam to the actual notify. This is the command id of
  1095. the button on which a click occurred.
  1096. Return value:
  1097. S_OK, if successful.
  1098. E_INVALID_ARG, if any of the arguments is null
  1099. Another other value returned from the called methods.
  1100. --*/
  1101. {
  1102. RETURN_INVALIDARG_IF_NULL(i_pControlbar);
  1103. HRESULT hr = S_OK;
  1104. switch(i_lParam) // What button did the user click on.
  1105. {
  1106. case IDT_JP_NEW_DFS_REPLICA: // "New Replica"
  1107. hr = OnNewReplica();
  1108. break;
  1109. case IDT_JP_REMOVE_FROM_DFS: // "Remove Junction Point"
  1110. hr = DoDelete();
  1111. break;
  1112. case IDT_JP_REPLICATION_TOPOLOGY: // "Replication Topology"
  1113. hr = OnNewReplicaSet();
  1114. break;
  1115. case IDT_JP_SHOW_REPLICATION:
  1116. case IDT_JP_HIDE_REPLICATION:
  1117. m_bShowFRS = !m_bShowFRS;
  1118. hr = OnShowReplication();
  1119. break;
  1120. case IDT_JP_STOP_REPLICATION:
  1121. hr = OnStopReplication(TRUE);
  1122. if (FAILED(hr))
  1123. DisplayMessageBoxForHR(hr);
  1124. break;
  1125. case IDT_JP_CHECK_STATUS: // "Check Status"
  1126. hr = OnCheckStatus ();
  1127. break;
  1128. default:
  1129. hr = E_INVALIDARG;
  1130. break;
  1131. };
  1132. return hr;
  1133. }
  1134. HRESULT
  1135. CMmcDfsJunctionPoint::OnRefresh(
  1136. )
  1137. /*++
  1138. Routine Description:
  1139. Refreshes the junction point.
  1140. --*/
  1141. {
  1142. // Select this node first
  1143. m_lpConsole->SelectScopeItem(m_hScopeItem);
  1144. CWaitCursor WaitCursor; // Display the wait cursor
  1145. HRESULT hr = S_OK;
  1146. // silently close outstanding property sheet.
  1147. ClosePropertySheet(TRUE);
  1148. // Re-Initialize!
  1149. BOOL bReplicaSetExist = FALSE;
  1150. CComBSTR bstrDC;
  1151. (void)m_pDfsJPObject->get_ReplicaSetExistEx(&bstrDC, &bReplicaSetExist);
  1152. CComBSTR bstrReplicaSetDN;
  1153. if (bReplicaSetExist)
  1154. {
  1155. (void)m_pDfsJPObject->get_ReplicaSetDN(&bstrReplicaSetDN);
  1156. }
  1157. m_bShowFRS = FALSE;
  1158. if ((IReplicaSet *)m_piReplicaSet)
  1159. m_piReplicaSet.Release();
  1160. CleanResultChildren();
  1161. hr = m_pDfsJPObject->Initialize((IUnknown *)(m_pDfsParentRoot->m_DfsRoot), m_bstrEntryPath, bReplicaSetExist, bstrReplicaSetDN);
  1162. if (S_OK != hr) // fail to init the link or no such link any more, refresh the whole root
  1163. {
  1164. m_pDfsParentRoot->OnRefresh();
  1165. return S_FALSE; // indicate the current m_pDfsJPObject should NOT be used any more
  1166. }
  1167. // set the link icon
  1168. if (m_lpConsoleNameSpace != NULL)
  1169. {
  1170. SCOPEDATAITEM ScopeDataItem;
  1171. ZeroMemory(&ScopeDataItem, sizeof(SCOPEDATAITEM));
  1172. ScopeDataItem.ID = m_hScopeItem;
  1173. hr = m_lpConsoleNameSpace->GetItem(&ScopeDataItem);
  1174. if (SUCCEEDED(hr))
  1175. {
  1176. ScopeDataItem.mask = SDI_IMAGE | SDI_OPENIMAGE;
  1177. ScopeDataItem.nImage = CMmcDfsJunctionPoint::m_iIMAGEINDEX + (bReplicaSetExist ? 4 : 0);
  1178. ScopeDataItem.nOpenImage = CMmcDfsJunctionPoint::m_iIMAGEINDEX + (bReplicaSetExist ? 4 : 0);
  1179. m_lpConsoleNameSpace->SetItem(&ScopeDataItem);
  1180. }
  1181. }
  1182. // re-display the result pane
  1183. m_lpConsole->UpdateAllViews((IDataObject*)this, 0, 1);
  1184. // Set the selected item in scope pane to this node
  1185. m_lpConsole->SelectScopeItem(m_hScopeItem);
  1186. return S_OK;
  1187. }
  1188. STDMETHODIMP CMmcDfsJunctionPoint::CleanResultChildren(
  1189. )
  1190. {
  1191. if (!m_MmcRepList.empty())
  1192. {
  1193. // clean up display objects
  1194. for (DFS_REPLICA_LIST::iterator i = m_MmcRepList.begin(); i != m_MmcRepList.end(); i++)
  1195. {
  1196. delete (*i);
  1197. }
  1198. m_MmcRepList.erase(m_MmcRepList.begin(), m_MmcRepList.end());
  1199. // delete result pane items
  1200. m_lpConsole->UpdateAllViews((IDataObject*)this, 0, 0);
  1201. }
  1202. return(S_OK);
  1203. }
  1204. STDMETHODIMP
  1205. CMmcDfsJunctionPoint::OnCheckStatus(
  1206. )
  1207. /*++
  1208. Routine Description:
  1209. This method checks the state of the replica.
  1210. --*/
  1211. {
  1212. //
  1213. // refresh to pick up possible namespace updates on targets by others
  1214. //
  1215. HRESULT hr = OnRefresh();
  1216. if (S_FALSE == hr)
  1217. {
  1218. // this link has been deleted by others, no more reference
  1219. DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_INVALID_LINK);
  1220. return hr;
  1221. }
  1222. CWaitCursor wait;
  1223. UINT nTotal = m_MmcRepList.size();
  1224. _ASSERT(nTotal != 0);
  1225. UINT nMappingOn = 0;
  1226. UINT nMappingOff = 0;
  1227. UINT nUnreachable = 0;
  1228. // Update state of all replicas also.
  1229. for (DFS_REPLICA_LIST::iterator i = m_MmcRepList.begin(); i != m_MmcRepList.end(); i++)
  1230. {
  1231. (*i)->pReplica->OnCheckStatus();
  1232. switch ((*i)->pReplica->m_lReplicaState)
  1233. {
  1234. case DFS_REPLICA_STATE_ONLINE:
  1235. nMappingOn++;
  1236. break;
  1237. case DFS_REPLICA_STATE_OFFLINE:
  1238. nMappingOff++;
  1239. break;
  1240. case DFS_REPLICA_STATE_UNREACHABLE:
  1241. nUnreachable++;
  1242. break;
  1243. default:
  1244. _ASSERT(FALSE);
  1245. break;
  1246. }
  1247. }
  1248. long lDfsState = DFS_STATE_REACHABLE;
  1249. hr = m_pDfsJPObject->get_State(&lDfsState);
  1250. RETURN_IF_FAILED(hr);
  1251. if (DFS_STATE_REACHABLE == lDfsState)
  1252. {
  1253. if (nTotal == nMappingOn)
  1254. {
  1255. m_lJunctionState = DFS_JUNCTION_STATE_ALL_REP_OK;
  1256. } else if (nTotal != (nMappingOff + nUnreachable))
  1257. {
  1258. m_lJunctionState = DFS_JUNCTION_STATE_NOT_ALL_REP_OK;
  1259. } else
  1260. {
  1261. m_lJunctionState = DFS_JUNCTION_STATE_UNREACHABLE;
  1262. }
  1263. } else
  1264. {
  1265. m_lJunctionState = DFS_JUNCTION_STATE_UNREACHABLE;
  1266. }
  1267. BOOL bReplicaSetExist = FALSE;
  1268. hr = m_pDfsJPObject->get_ReplicaSetExist(&bReplicaSetExist);
  1269. RETURN_IF_FAILED(hr);
  1270. if (m_lpConsoleNameSpace != NULL)
  1271. {
  1272. SCOPEDATAITEM ScopeDataItem;
  1273. ZeroMemory(&ScopeDataItem, sizeof(SCOPEDATAITEM));
  1274. ScopeDataItem.ID = m_hScopeItem;
  1275. hr = m_lpConsoleNameSpace->GetItem(&ScopeDataItem);
  1276. RETURN_IF_FAILED(hr);
  1277. ScopeDataItem.mask = SDI_IMAGE | SDI_OPENIMAGE;
  1278. ScopeDataItem.nImage = CMmcDfsJunctionPoint::m_iIMAGEINDEX + (bReplicaSetExist ? 4 : 0) + m_lJunctionState;
  1279. ScopeDataItem.nOpenImage = CMmcDfsJunctionPoint::m_iIMAGEINDEX + (bReplicaSetExist ? 4 : 0) + m_lJunctionState;
  1280. hr = m_lpConsoleNameSpace->SetItem(&ScopeDataItem);
  1281. RETURN_IF_FAILED(hr);
  1282. }
  1283. return hr;
  1284. }
  1285. STDMETHODIMP CMmcDfsJunctionPoint::ViewChange(
  1286. IResultData* i_pResultData,
  1287. LONG_PTR i_lHint
  1288. )
  1289. /*++
  1290. Routine Description:
  1291. This method handles the MMCN_VIEW_CHANGE notification.
  1292. This updates the result view for the scope node on which the
  1293. UpdateAllViews was called.
  1294. if (0 == i_lHint) clean result pane only.
  1295. --*/
  1296. {
  1297. RETURN_INVALIDARG_IF_NULL(i_pResultData);
  1298. i_pResultData->DeleteAllRsltItems();
  1299. // Re-display the view
  1300. if (i_lHint)
  1301. EnumerateResultPane(i_pResultData);
  1302. return(S_OK);
  1303. }
  1304. STDMETHODIMP CMmcDfsJunctionPoint::AddResultPaneItem(
  1305. CMmcDfsReplica* i_pReplicaDispObject
  1306. )
  1307. /*++
  1308. Routine Description:
  1309. This method adds a new replica object to the list of replicas displayed
  1310. in the result view.
  1311. Arguments:
  1312. i_pReplicaDispObject - The CMmcReplica display object pointer..
  1313. --*/
  1314. {
  1315. REP_LIST_NODE* pNewReplica = new REP_LIST_NODE(i_pReplicaDispObject);
  1316. if (!pNewReplica)
  1317. return E_OUTOFMEMORY;
  1318. // Sort isnert. Find insertion position.
  1319. for (DFS_REPLICA_LIST::iterator j = m_MmcRepList.begin(); j != m_MmcRepList.end(); j++)
  1320. {
  1321. if (lstrcmpi(pNewReplica->pReplica->m_bstrDisplayName, (*j)->pReplica->m_bstrDisplayName) <= 0)
  1322. break;
  1323. }
  1324. m_MmcRepList.insert(j, pNewReplica);
  1325. BOOL bReplicaSetExist = FALSE;
  1326. m_pDfsJPObject->get_ReplicaSetExist(&bReplicaSetExist);
  1327. if (bReplicaSetExist && m_bShowFRS)
  1328. {
  1329. i_pReplicaDispObject->ShowReplicationInfo(m_piReplicaSet);
  1330. }
  1331. // Re-display to display this item.
  1332. m_lpConsole->UpdateAllViews((IDataObject*)this, 0, 1);
  1333. return S_OK;
  1334. }
  1335. //
  1336. // This function is called when removing a target from the result pane
  1337. //
  1338. STDMETHODIMP CMmcDfsJunctionPoint::RemoveReplica(LPCTSTR i_pszDisplayName)
  1339. {
  1340. if (!i_pszDisplayName)
  1341. return E_INVALIDARG;
  1342. //
  1343. // refresh to pick up possible namespace updates on targets by other means
  1344. //
  1345. HRESULT hr = OnRefresh();
  1346. if (S_FALSE == hr)
  1347. {
  1348. // this link has already been deleted by others, no more reference
  1349. DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_INVALID_LINK);
  1350. return hr;
  1351. }
  1352. CWaitCursor wait;
  1353. //
  1354. // locate the correct target to remove, then call back.
  1355. //
  1356. for (DFS_REPLICA_LIST::iterator i = m_MmcRepList.begin(); i != m_MmcRepList.end(); i++)
  1357. {
  1358. if (!lstrcmpi((*i)->pReplica->m_bstrDisplayName, i_pszDisplayName))
  1359. {
  1360. hr = (*i)->pReplica->RemoveReplica();
  1361. break;
  1362. }
  1363. }
  1364. return hr;
  1365. }
  1366. STDMETHODIMP CMmcDfsJunctionPoint::RemoveResultPaneItem(
  1367. CMmcDfsReplica* i_pReplicaDispObject
  1368. )
  1369. /*++
  1370. Routine Description:
  1371. This method adds a new replica object to the list of replicas displayed
  1372. in the result view.
  1373. Arguments:
  1374. i_pReplicaDispObject - The CMmcReplica display object pointer..
  1375. --*/
  1376. {
  1377. dfsDebugOut((_T("CMmcDfsJunctionPoint::RemoveResultPaneItem replist=%d\n"), m_MmcRepList.size()));
  1378. // Remove item from list.
  1379. for (DFS_REPLICA_LIST::iterator i = m_MmcRepList.begin(); i != m_MmcRepList.end(); i++)
  1380. {
  1381. if ((*i)->pReplica == i_pReplicaDispObject)
  1382. {
  1383. delete (*i);
  1384. m_MmcRepList.erase(i);
  1385. break;
  1386. }
  1387. }
  1388. // Last node is removed.
  1389. if (m_MmcRepList.empty())
  1390. {
  1391. // silently close any open property sheet
  1392. ClosePropertySheet(TRUE);
  1393. // Delete the item from Scope Pane
  1394. HRESULT hr = m_lpConsoleNameSpace->DeleteItem(m_hScopeItem, TRUE);
  1395. RETURN_IF_FAILED(hr);
  1396. // Remove the actual junction point(from DS)
  1397. hr = m_pDfsParentRoot->m_DfsRoot->DeleteJunctionPoint(m_bstrDisplayName);
  1398. RETURN_IF_FAILED(hr);
  1399. // Delete it from the internal list
  1400. hr = m_pDfsParentRoot->DeleteMmcJPNode(this);
  1401. RETURN_IF_FAILED(hr);
  1402. Release(); // delete this CMmcDfsJunctionPoint object
  1403. }
  1404. else
  1405. {
  1406. // Re-display to remove this item.
  1407. m_lpConsole->UpdateAllViews((IDataObject*)this, 0, 1);
  1408. }
  1409. return S_OK;
  1410. }
  1411. HRESULT CMmcDfsJunctionPoint::GetIReplicaSetPtr(IReplicaSet** o_ppiReplicaSet)
  1412. {
  1413. RETURN_INVALIDARG_IF_NULL(o_ppiReplicaSet);
  1414. HRESULT hr = _InitReplicaSet();
  1415. if (S_OK == hr)
  1416. {
  1417. m_piReplicaSet->AddRef();
  1418. *o_ppiReplicaSet = m_piReplicaSet;
  1419. }
  1420. return hr;
  1421. }