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.

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