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.

1027 lines
27 KiB

  1. /*++
  2. Module Name:
  3. MmcAdmin.cpp
  4. Abstract:
  5. This module contains the implementation for CMmcDfsAdmin. This is an class
  6. for MMC display related calls for the static node(the DFS Admin root node)
  7. --*/
  8. #include "stdafx.h"
  9. #include "DfsGUI.h"
  10. #include "Utils.h" // For the LoadStringFromResource method
  11. #include "resource.h" // Contains the menu and toolbar command ids
  12. #include "MenuEnum.h" // Contains the menu command ids
  13. #include "MmcRoot.h" // CMmcDfsRoot class
  14. #include "MmcAdmin.h"
  15. #include "DfsEnums.h" // for common enums, typedefs, etc
  16. #include "DfsWiz.h" // For the wizard pages, CCreateDfsRootWizPage1, 2, ...
  17. #include "DfsNodes.h" // For Node GUIDs
  18. #include "DfsScope.h"
  19. #include "mroots.h"
  20. static const TCHAR s_szWhack[] = _T("\\");
  21. static const TCHAR s_szWhackWhack[] = _T("\\\\");
  22. CMmcDfsAdmin::CMmcDfsAdmin(
  23. CDfsSnapinScopeManager* pScopeManager
  24. )
  25. :m_hItemParent(NULL), m_bDirty(false), m_lpConsole(NULL)
  26. {
  27. dfsDebugOut((_T("CMmcDfsAdmin::CMmcDfsAdmin this=%p\n"), this));
  28. m_CLSIDNodeType = s_guidDfsAdminNodeType;
  29. m_bstrDNodeType = s_tchDfsAdminNodeType;
  30. m_pScopeManager = pScopeManager;
  31. }
  32. CMmcDfsAdmin::~CMmcDfsAdmin()
  33. /*++
  34. Routine Description:
  35. The dtor for CMmcDfsAdmin. This removes the list of DfsRoots being administered.
  36. --*/
  37. {
  38. CleanScopeChildren();
  39. dfsDebugOut((_T("CMmcDfsAdmin::~CMmcDfsAdmin this=%p\n"), this));
  40. }
  41. STDMETHODIMP
  42. CMmcDfsAdmin::AddMenuItems(
  43. IN LPCONTEXTMENUCALLBACK i_lpContextMenuCallback,
  44. IN LPLONG i_lpInsertionAllowed
  45. )
  46. /*++
  47. Routine Description:
  48. This routine adds a context menu using the ContextMenuCallback provided.
  49. Arguments:
  50. lpContextMenuCallback - A callback(function pointer) that is used to add the menu items
  51. lpInsertionAllowed - Specifies what menus can be added and where they can be added.
  52. --*/
  53. {
  54. RETURN_INVALIDARG_IF_NULL(i_lpContextMenuCallback);
  55. enum
  56. {
  57. IDM_CONTEXTMENU_COMMAND_MAX = IDM_STATIC_MAX,
  58. IDM_CONTEXTMENU_COMMAND_MIN = IDM_STATIC_MIN
  59. };
  60. LONG lInsertionPoints [IDM_CONTEXTMENU_COMMAND_MAX - IDM_CONTEXTMENU_COMMAND_MIN + 1] = {
  61. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  62. CCM_INSERTIONPOINTID_PRIMARY_TOP
  63. };
  64. HRESULT hr = S_OK;
  65. for (int iCommandID = IDM_CONTEXTMENU_COMMAND_MIN, iMenuResource = IDS_MENUS_STATIC_TOP_NEW_DFSROOT;
  66. iCommandID <= IDM_CONTEXTMENU_COMMAND_MAX;
  67. iCommandID++,iMenuResource++)
  68. {
  69. CComBSTR bstrMenuText;
  70. CComBSTR bstrStatusBarText;
  71. hr = GetMenuResourceStrings(iMenuResource, &bstrMenuText, NULL, &bstrStatusBarText);
  72. RETURN_IF_FAILED(hr);
  73. CONTEXTMENUITEM ContextMenuItem; // The structure which contains menu information
  74. ZeroMemory(&ContextMenuItem, sizeof(ContextMenuItem));
  75. ContextMenuItem.strName = bstrMenuText;
  76. ContextMenuItem.strStatusBarText = bstrStatusBarText;
  77. ContextMenuItem.lInsertionPointID = lInsertionPoints[iCommandID - IDM_CONTEXTMENU_COMMAND_MIN];
  78. ContextMenuItem.lCommandID = iCommandID;
  79. LONG lInsertionFlag = 0; // Use to check if we have permission to add this menu.
  80. switch(ContextMenuItem.lInsertionPointID)
  81. {
  82. case CCM_INSERTIONPOINTID_PRIMARY_TOP:
  83. lInsertionFlag = CCM_INSERTIONALLOWED_TOP;
  84. break;
  85. case CCM_INSERTIONPOINTID_PRIMARY_NEW:
  86. lInsertionFlag = CCM_INSERTIONALLOWED_NEW;
  87. break;
  88. case CCM_INSERTIONPOINTID_PRIMARY_TASK:
  89. lInsertionFlag = CCM_INSERTIONALLOWED_TASK;
  90. break;
  91. case CCM_INSERTIONPOINTID_PRIMARY_VIEW:
  92. lInsertionFlag = CCM_INSERTIONALLOWED_VIEW;
  93. break;
  94. default:
  95. break;
  96. }
  97. if (*i_lpInsertionAllowed & lInsertionFlag) // Add the menu item we have have the permission
  98. {
  99. hr = i_lpContextMenuCallback->AddItem(&ContextMenuItem);
  100. RETURN_IF_FAILED(hr);
  101. }
  102. } // for
  103. return hr;
  104. }
  105. STDMETHODIMP
  106. CMmcDfsAdmin::SetColumnHeader(
  107. IN LPHEADERCTRL2 i_piHeaderControl
  108. )
  109. {
  110. //
  111. // the static node will dispay the messageview in the result pane
  112. //
  113. return E_NOTIMPL;
  114. }
  115. STDMETHODIMP
  116. CMmcDfsAdmin::Command(
  117. IN LONG i_lCommandID
  118. )
  119. /*++
  120. Routine Description:
  121. Action to be taken on a context menu selection or click is takes place.
  122. Arguments:
  123. lCommandID - The Command ID of the menu for which action has to be taken
  124. --*/
  125. {
  126. HRESULT hr = S_OK;
  127. switch (i_lCommandID)
  128. {
  129. case IDM_STATIC_TOP_CONNECTTO:
  130. hr = OnConnectTo();
  131. break;
  132. case IDM_STATIC_TOP_NEW_DFSROOT:
  133. hr = OnNewDfsRoot();
  134. break;
  135. default:
  136. hr = E_INVALIDARG;
  137. break;
  138. }
  139. return hr;
  140. };
  141. STDMETHODIMP
  142. CMmcDfsAdmin::OnConnectTo(
  143. )
  144. /*++
  145. Routine Description:
  146. Action to be taken on menu command "Connect To Dfs Root"
  147. --*/
  148. {
  149. // Display the ConnectTo dialog
  150. CConnectToDialog ConnectTo; // Connect To Dialog.
  151. HRESULT hr = ConnectTo.DoModal();
  152. ::ShowCursor(FALSE);
  153. SetCursor(::LoadCursor(NULL, IDC_ARROW));
  154. ::ShowCursor(TRUE);
  155. if (hr != S_OK) // Mostly an error or cancel operation
  156. return hr;
  157. // Get the Dfs Root selected by the user
  158. CComBSTR bstrUserEnteredText;
  159. hr = ConnectTo.get_DfsRoot(&bstrUserEnteredText);
  160. RETURN_IF_FAILED(hr);
  161. CWaitCursor WaitCursor;
  162. if (S_OK == CheckUNCPath(bstrUserEnteredText))
  163. {
  164. //
  165. // user has entered the fully spelled out root entry path
  166. // add it to scope pane directly
  167. //
  168. hr = AddDfsRoot(bstrUserEnteredText);
  169. } else
  170. {
  171. //
  172. // user has entered only a domain or server name, we need user to further
  173. // determine the roots he wants to display in the scope pane
  174. //
  175. CComBSTR bstrScopeWithWhacks;
  176. PTSTR pszScopeWithNoWhacks = NULL;
  177. if (!mylstrncmpi(bstrUserEnteredText, _T("\\\\"), 2))
  178. {
  179. pszScopeWithNoWhacks = bstrUserEnteredText + 2;
  180. bstrScopeWithWhacks = bstrUserEnteredText;
  181. } else
  182. {
  183. pszScopeWithNoWhacks = bstrUserEnteredText;
  184. bstrScopeWithWhacks = _T("\\\\");
  185. bstrScopeWithWhacks += bstrUserEnteredText;
  186. }
  187. bstrScopeWithWhacks += _T("\\");
  188. ROOTINFOLIST DfsRootList;
  189. if (S_OK == GetMultiDfsRoots(&DfsRootList, pszScopeWithNoWhacks) && !DfsRootList.empty())
  190. {
  191. ROOTINFOLIST::iterator i = DfsRootList.begin();
  192. CComBSTR bstrRoot;
  193. if (1 == DfsRootList.size())
  194. {
  195. //
  196. // this domain or server only hosts one root, add it to scope pane directly
  197. //
  198. bstrRoot = bstrScopeWithWhacks;
  199. bstrRoot += (*i)->bstrRootName;
  200. hr = AddDfsRoot(bstrRoot);
  201. } else
  202. {
  203. //
  204. // invoke the multi roots dialog
  205. //
  206. CMultiRoots mroots;
  207. hr = mroots.Init(pszScopeWithNoWhacks, &DfsRootList);
  208. if (SUCCEEDED(hr))
  209. hr = mroots.DoModal();
  210. if (S_OK == hr)
  211. {
  212. //
  213. // user has OK'ed the dialog, add each selected root to scope pane
  214. //
  215. NETNAMELIST *pList = NULL;
  216. mroots.get_SelectedRootList(&pList);
  217. for (NETNAMELIST::iterator j = pList->begin(); j != pList->end(); j++)
  218. {
  219. bstrRoot = bstrScopeWithWhacks;
  220. bstrRoot += (*j)->bstrNetName;
  221. hr = AddDfsRoot(bstrRoot);
  222. if (FAILED(hr))
  223. break;
  224. }
  225. } else if (S_FALSE == hr)
  226. {
  227. //
  228. // user has cancelled the dialog, reset it to S_OK to avoid msg popup
  229. //
  230. hr = S_OK;
  231. }
  232. }
  233. } else
  234. {
  235. //
  236. // could be downlevel server, try to add it to scope pane
  237. //
  238. hr = AddDfsRoot(bstrUserEnteredText);
  239. }
  240. FreeRootInfoList(&DfsRootList);
  241. }
  242. if (S_FALSE == hr)
  243. DisplayMessageBoxWithOK(IDS_DFSROOT_NOT_EXIST, NULL);
  244. if (FAILED(hr))
  245. DisplayMessageBoxForHR(hr);
  246. return hr;
  247. }
  248. STDMETHODIMP
  249. CMmcDfsAdmin::EnumerateScopePane(
  250. IN LPCONSOLENAMESPACE i_lpConsoleNameSpace,
  251. IN HSCOPEITEM i_hItemParent
  252. )
  253. /*++
  254. Routine Description:
  255. To eumerate(add) items in the scope pane. Dfs Roots in this case
  256. Arguments:
  257. i_lpConsoleNameSpace - The callback used to add items to the Scope pane
  258. i_hItemParent - HSCOPEITEM of the parent under which all the items will be added.
  259. --*/
  260. {
  261. RETURN_INVALIDARG_IF_NULL(i_hItemParent);
  262. RETURN_INVALIDARG_IF_NULL(i_lpConsoleNameSpace);
  263. m_hItemParent = i_hItemParent;
  264. m_lpConsoleNameSpace = i_lpConsoleNameSpace;
  265. CWaitCursor WaitCursor;
  266. for (DFS_ROOT_LIST::iterator i = m_RootList.begin(); i != m_RootList.end(); i++)
  267. {
  268. (void)((*i)->m_pMmcDfsRoot)->AddItemToScopePane(m_lpConsoleNameSpace, m_hItemParent);
  269. }
  270. return S_OK;
  271. }
  272. STDMETHODIMP
  273. CMmcDfsAdmin::AddDfsRoot(
  274. IN BSTR i_bstrDfsRootName
  275. )
  276. /*++
  277. Routine Description:
  278. Adds the DfsRoot to the internal list and to the Scope pane.
  279. Arguments:
  280. i_bstrDfsRootName - The full path(display name) of the DfsRoot to be created.
  281. Example, ComputerName\\DfsRootName or DomainName\DfsRootName
  282. --*/
  283. {
  284. RETURN_INVALIDARG_IF_NULL(i_bstrDfsRootName);
  285. CWaitCursor wait;
  286. // Create the IDfsRoot object
  287. CComPtr<IDfsRoot> pDfsRoot;
  288. HRESULT hr = CoCreateInstance (CLSID_DfsRoot, NULL, CLSCTX_INPROC_SERVER, IID_IDfsRoot, (void**) &pDfsRoot);
  289. RETURN_IF_FAILED(hr);
  290. hr = pDfsRoot->Initialize(i_bstrDfsRootName);
  291. if (S_OK != hr)
  292. return hr;
  293. // Get the server hosting Dfs.
  294. CComBSTR bstrDfsRootEntryPath;
  295. hr = pDfsRoot->get_RootEntryPath(&bstrDfsRootEntryPath);
  296. RETURN_IF_FAILED(hr);
  297. // If already present in the list, just display a message and return
  298. CMmcDfsRoot *pMmcDfsRoot = NULL;
  299. hr = IsAlreadyInList(bstrDfsRootEntryPath, &pMmcDfsRoot);
  300. if (S_OK == hr)
  301. {
  302. pMmcDfsRoot->OnRefresh(); // refresh to pick up other root replicas
  303. return hr;
  304. }
  305. // Add the IDfsRoot object to the list and to Scope Pane
  306. hr = AddDfsRootToList(pDfsRoot);
  307. RETURN_IF_FAILED(hr);
  308. m_bDirty = true; // Dirty is true as we now have a new node in the list
  309. return hr;
  310. }
  311. STDMETHODIMP
  312. CMmcDfsAdmin::AddDfsRootToList(
  313. IN IDfsRoot* i_pDfsRoot,
  314. IN ULONG i_ulLinkFilterMaxLimit, // = FILTERDFSLINKS_MAXLIMIT_DEFAULT,
  315. IN FILTERDFSLINKS_TYPE i_lLinkFilterType, // = FILTERDFSLINKS_TYPE_NO_FILTER,
  316. IN BSTR i_bstrLinkFilterName // = NULL
  317. )
  318. /*++
  319. Routine Description:
  320. To add a new DFSRoot only to the list.
  321. Arguments:
  322. i_pDfsRoot - The IDfsRoot object being added to the list
  323. --*/
  324. {
  325. RETURN_INVALIDARG_IF_NULL(i_pDfsRoot);
  326. CMmcDfsRoot* pMmcDfsRoot = new CMmcDfsRoot(i_pDfsRoot, this, m_lpConsole,
  327. i_ulLinkFilterMaxLimit, i_lLinkFilterType, i_bstrLinkFilterName);
  328. RETURN_OUTOFMEMORY_IF_NULL(pMmcDfsRoot);
  329. HRESULT hr = S_OK;
  330. if ( FAILED(hr = pMmcDfsRoot->m_hrValueFromCtor) )
  331. {
  332. delete pMmcDfsRoot;
  333. return hr;
  334. }
  335. CComBSTR bstrRootEntryPath;
  336. hr = i_pDfsRoot->get_RootEntryPath(&bstrRootEntryPath);
  337. if (FAILED(hr))
  338. {
  339. delete pMmcDfsRoot;
  340. return hr;
  341. }
  342. // Create a new node for storing Dfs Root information.
  343. DFS_ROOT_NODE* pNewDfsRootNode = new DFS_ROOT_NODE(pMmcDfsRoot, bstrRootEntryPath);
  344. if (!pNewDfsRootNode || !pNewDfsRootNode->m_bstrRootEntryPath)
  345. {
  346. delete pMmcDfsRoot;
  347. delete pNewDfsRootNode;
  348. return E_OUTOFMEMORY;
  349. }
  350. m_RootList.push_back(pNewDfsRootNode);
  351. // Add this DfsRoot to scope pane. Need item parent to be non null
  352. if (m_hItemParent)
  353. {
  354. hr = (pNewDfsRootNode->m_pMmcDfsRoot)->AddItemToScopePane(m_lpConsoleNameSpace, m_hItemParent);
  355. RETURN_IF_FAILED(hr);
  356. }
  357. m_bDirty = true; // Dirty is true as we now have a new node in the list
  358. return hr;
  359. }
  360. // This method returns the pointer to the list containing information of all DfsRoots
  361. // added to the Snapin. The caller SHOULD NOT free the list.
  362. STDMETHODIMP
  363. CMmcDfsAdmin::GetList(
  364. OUT DFS_ROOT_LIST** o_pList
  365. )
  366. {
  367. RETURN_INVALIDARG_IF_NULL(o_pList);
  368. *o_pList = &m_RootList;
  369. return S_OK;
  370. }
  371. STDMETHODIMP
  372. CMmcDfsAdmin::IsAlreadyInList(
  373. IN BSTR i_bstrDfsRootEntryPath,
  374. OUT CMmcDfsRoot **o_ppMmcDfsRoot
  375. )
  376. /*++
  377. Routine Description:
  378. Routine used to check if the DfsRoot is already in the list
  379. Arguments:
  380. i_bstrDfsRootEntryPath - The Server name of the DfsRoot object
  381. Return value:
  382. S_OK, if node is present in the list.
  383. S_FALSE, if the node doesn't exist in the list
  384. --*/
  385. {
  386. for (DFS_ROOT_LIST::iterator i = m_RootList.begin(); i != m_RootList.end(); i++)
  387. {
  388. if (!lstrcmpi((*i)->m_bstrRootEntryPath, i_bstrDfsRootEntryPath))
  389. {
  390. if (o_ppMmcDfsRoot)
  391. *o_ppMmcDfsRoot = (*i)->m_pMmcDfsRoot;
  392. return S_OK;
  393. }
  394. }
  395. return S_FALSE;
  396. }
  397. HRESULT
  398. CMmcDfsAdmin::OnRefresh(
  399. )
  400. {
  401. // Select this node first
  402. m_lpConsole->SelectScopeItem(m_hItemParent);
  403. CWaitCursor WaitCursor;
  404. HRESULT hr = S_OK;
  405. NETNAMELIST listRootEntryPaths;
  406. if (!m_RootList.empty())
  407. {
  408. for (DFS_ROOT_LIST::iterator i = m_RootList.begin(); i != m_RootList.end(); i++)
  409. {
  410. // silently close all property pages
  411. ((*i)->m_pMmcDfsRoot)->CloseAllPropertySheets(TRUE);
  412. NETNAME *pName = new NETNAME;
  413. BREAK_OUTOFMEMORY_IF_NULL(pName, &hr);
  414. pName->bstrNetName = (*i)->m_bstrRootEntryPath;
  415. BREAK_OUTOFMEMORY_IF_NULL((BSTR)(pName->bstrNetName), &hr);
  416. listRootEntryPaths.push_back(pName);
  417. }
  418. }
  419. if (FAILED(hr))
  420. {
  421. FreeNetNameList(&listRootEntryPaths);
  422. return hr;
  423. }
  424. if (listRootEntryPaths.empty())
  425. return hr;
  426. CleanScopeChildren();
  427. for (NETNAMELIST::iterator i = listRootEntryPaths.begin(); i != listRootEntryPaths.end(); i++)
  428. {
  429. (void)AddDfsRoot((*i)->bstrNetName);
  430. }
  431. FreeNetNameList(&listRootEntryPaths);
  432. return hr;
  433. }
  434. HRESULT
  435. CMmcDfsAdmin::OnAddImages(IImageList *pImageList, HSCOPEITEM hsi)
  436. {
  437. return S_OK; // no listview on the static node
  438. }
  439. // Delete the node from m_RootList
  440. STDMETHODIMP
  441. CMmcDfsAdmin::DeleteMmcRootNode(
  442. IN CMmcDfsRoot* i_pMmcDfsRoot
  443. )
  444. {
  445. RETURN_INVALIDARG_IF_NULL(i_pMmcDfsRoot);
  446. dfsDebugOut((_T("CMmcDfsAdmin::DeleteMmcRootNode %p\n"), i_pMmcDfsRoot));
  447. for (DFS_ROOT_LIST::iterator i = m_RootList.begin(); i != m_RootList.end(); i++)
  448. {
  449. if ((*i)->m_pMmcDfsRoot == i_pMmcDfsRoot)
  450. {
  451. m_RootList.erase(i);
  452. m_bDirty = true;
  453. break;
  454. }
  455. }
  456. return S_OK;
  457. }
  458. STDMETHODIMP
  459. CMmcDfsAdmin::SetConsoleVerbs(
  460. IN LPCONSOLEVERB i_lpConsoleVerb
  461. )
  462. /*++
  463. Routine Description:
  464. Routine used to set the console verb settings.
  465. Sets all of them except Open off.
  466. For all scope pane items, default verb is "open'. For result items,
  467. it is "properties"
  468. Arguments:
  469. i_lpConsoleVerb - The callback used to handle console verbs
  470. --*/
  471. {
  472. RETURN_INVALIDARG_IF_NULL(i_lpConsoleVerb);
  473. i_lpConsoleVerb->SetVerbState(MMC_VERB_COPY, HIDDEN, TRUE);
  474. i_lpConsoleVerb->SetVerbState(MMC_VERB_PASTE, HIDDEN, TRUE);
  475. i_lpConsoleVerb->SetVerbState(MMC_VERB_RENAME, HIDDEN, TRUE);
  476. i_lpConsoleVerb->SetVerbState(MMC_VERB_PRINT, HIDDEN, TRUE);
  477. i_lpConsoleVerb->SetVerbState(MMC_VERB_DELETE, HIDDEN, TRUE);
  478. i_lpConsoleVerb->SetVerbState(MMC_VERB_OPEN, HIDDEN, TRUE);
  479. i_lpConsoleVerb->SetVerbState(MMC_VERB_REFRESH, ENABLED, TRUE);
  480. i_lpConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, HIDDEN, TRUE);
  481. i_lpConsoleVerb->SetDefaultVerb(MMC_VERB_OPEN); //For scope items, default verb is "open"
  482. return S_OK;
  483. }
  484. /*
  485. Used by CMmcDfsAdmin::OnNewDfsRoot()
  486. */
  487. class CMmcNewDfsWizard : public CMmcDfsAdmin
  488. {
  489. public:
  490. CMmcNewDfsWizard( CDfsSnapinScopeManager* i_pScopeManager );
  491. virtual ~CMmcNewDfsWizard();
  492. // Checks whether the object has pages to display
  493. STDMETHODIMP QueryPagesFor(
  494. ) { return S_OK; };
  495. // Creates and passes back the pages to be displayed
  496. STDMETHODIMP CreatePropertyPages(
  497. IN LPPROPERTYSHEETCALLBACK i_lpPropSheetCallback,
  498. IN LONG_PTR i_lNotifyHandle
  499. );
  500. };
  501. CMmcNewDfsWizard::CMmcNewDfsWizard( CDfsSnapinScopeManager* i_pScopeManager )
  502. : CMmcDfsAdmin( i_pScopeManager )
  503. {
  504. }
  505. CMmcNewDfsWizard::~CMmcNewDfsWizard()
  506. {
  507. }
  508. // Creates and passes back the pages to be displayed
  509. STDMETHODIMP
  510. CMmcNewDfsWizard::CreatePropertyPages(
  511. IN LPPROPERTYSHEETCALLBACK i_lpPropSheetCallback,
  512. IN LONG_PTR i_lNotifyHandle
  513. )
  514. /*++
  515. Routine Description:
  516. Used to display the property sheet pages
  517. Arguments:
  518. i_lpPropSheetCallback - The callback used to create the propertysheet.
  519. i_lNotifyHandle - Notify handle used by the property page
  520. --*/
  521. {
  522. RETURN_INVALIDARG_IF_NULL(i_lpPropSheetCallback);
  523. return S_OK; // since we want to display a propertysheet
  524. }
  525. STDMETHODIMP
  526. CMmcDfsAdmin::OnNewDfsRoot(
  527. )
  528. /*++
  529. Routine Description:
  530. Action to be taken on menu command "New Dfs Root".
  531. Here is a wizard is used to guide the user through the process of creating a new
  532. dfs root.
  533. Arguments:
  534. None
  535. --*/
  536. {
  537. CMmcNewDfsWizard* pNewDfsWizard = new CMmcNewDfsWizard( m_pScopeManager );
  538. RETURN_OUTOFMEMORY_IF_NULL(pNewDfsWizard);
  539. CComPtr<IDataObject> spDfsWizardDataObject = (IDataObject*)pNewDfsWizard;
  540. CREATEDFSROOTWIZINFO CreateWizInfo;// 0 initializes all members to 0. Necessary
  541. CreateWizInfo.pMMCAdmin = this;
  542. CCreateDfsRootWizPage1 WizPage1(&CreateWizInfo); // Wizard pages
  543. CCreateDfsRootWizPage2 WizPage2(&CreateWizInfo);
  544. CCreateDfsRootWizPage3 WizPage3(&CreateWizInfo);
  545. CCreateDfsRootWizPage4 WizPage4(&CreateWizInfo);
  546. CCreateDfsRootWizPage6 WizPage6(&CreateWizInfo);
  547. CCreateDfsRootWizPage5 WizPage5(&CreateWizInfo);
  548. CCreateDfsRootWizPage7 WizPage7(&CreateWizInfo);
  549. // Get the required interfaces from IConsole2.
  550. CComPtr<IPropertySheetCallback> pPropSheetCallback; // MMC Callback used to add pages
  551. HRESULT hr = m_lpConsole->QueryInterface( IID_IPropertySheetCallback,
  552. reinterpret_cast<void**>(&pPropSheetCallback));
  553. RETURN_IF_FAILED(hr);
  554. CComPtr<IPropertySheetProvider> pPropSheetProvider; // MMC callback used to handle wizard
  555. hr = m_lpConsole->QueryInterface( IID_IPropertySheetProvider,
  556. reinterpret_cast<void**>(&pPropSheetProvider));
  557. RETURN_IF_FAILED(hr);
  558. // Create the wizard
  559. // JonN 2/14/98 Currently MMC-based wizards don't work unless you call AddPrimaryPages.
  560. hr = pPropSheetProvider->CreatePropertySheet(
  561. _T(""), // Property sheet title. Should not be null so send empty string.
  562. FALSE, // Wizard and not property sheet.
  563. 0, // Cookie
  564. (LPDATAOBJECT)spDfsWizardDataObject, // IDataobject
  565. MMC_PSO_NEWWIZARDTYPE); // Creation flags
  566. RETURN_IF_FAILED(hr);
  567. // Create the pages for the wizard. Use the handle return to add to our wizard
  568. hr = pPropSheetCallback->AddPage(WizPage1.Create());
  569. RETURN_IF_FAILED(hr);
  570. hr = pPropSheetCallback->AddPage(WizPage2.Create());
  571. RETURN_IF_FAILED(hr);
  572. hr = pPropSheetCallback->AddPage(WizPage3.Create());
  573. RETURN_IF_FAILED(hr);
  574. hr = pPropSheetCallback->AddPage(WizPage4.Create());
  575. RETURN_IF_FAILED(hr);
  576. hr = pPropSheetCallback->AddPage(WizPage6.Create());
  577. RETURN_IF_FAILED(hr);
  578. hr = pPropSheetCallback->AddPage(WizPage5.Create());
  579. RETURN_IF_FAILED(hr);
  580. hr = pPropSheetCallback->AddPage(WizPage7.Create());
  581. RETURN_IF_FAILED(hr);
  582. // Ask the provider to use the pages from the callback
  583. hr = pPropSheetProvider->AddPrimaryPages( (IComponentData *)(m_pScopeManager),
  584. TRUE, // Don't create a notify handle
  585. NULL,
  586. TRUE // Scope pane (not result pane)
  587. );
  588. RETURN_IF_FAILED(hr);
  589. HWND hwndMainWin = 0; // MMC main window. Used to make it modal
  590. hr = m_lpConsole->GetMainWindow(&hwndMainWin); // Get the main MMC window
  591. RETURN_IF_FAILED(hr);
  592. // Display the wizard
  593. hr = pPropSheetProvider->Show( (LONG_PTR)hwndMainWin, // Parent window of the wizard
  594. 0 // Starting page
  595. );
  596. RETURN_IF_FAILED(hr);
  597. if (CreateWizInfo.bDfsSetupSuccess)
  598. {
  599. CComBSTR bstrRootEntryPath = _T("\\\\");
  600. if (CreateWizInfo.DfsType == DFS_TYPE_FTDFS)
  601. bstrRootEntryPath += CreateWizInfo.bstrSelectedDomain;
  602. else
  603. bstrRootEntryPath += CreateWizInfo.bstrSelectedServer;
  604. bstrRootEntryPath += _T("\\");
  605. bstrRootEntryPath += CreateWizInfo.bstrDfsRootName;
  606. hr = AddDfsRoot(bstrRootEntryPath);
  607. }
  608. return hr;
  609. }
  610. HRESULT
  611. CMmcDfsAdmin::PutConsolePtr(
  612. IN const LPCONSOLE2 i_lpConsole
  613. )
  614. /*++
  615. Routine Description:
  616. A routine used just to set the lpconsole pointer.
  617. This is used later by display object
  618. Arguments:
  619. i_lpConsole - Console pointer.
  620. --*/
  621. {
  622. RETURN_INVALIDARG_IF_NULL(i_lpConsole);
  623. m_lpConsole = i_lpConsole;
  624. return S_OK;
  625. }
  626. HRESULT
  627. CMmcDfsAdmin::SetDescriptionBarText(
  628. IN LPRESULTDATA i_lpResultData
  629. )
  630. /*++
  631. Routine Description:
  632. A routine used set the text in the Description bar above
  633. the result view.
  634. Arguments:
  635. i_lpResultData - Pointer to the IResultData callback which is
  636. used to set the description text
  637. --*/
  638. {
  639. RETURN_INVALIDARG_IF_NULL(i_lpResultData);
  640. CComBSTR bstrTextForDescriptionBar;
  641. HRESULT hr = LoadStringFromResource(IDS_DESCRIPTION_BAR_TEXT_ADMIN, &bstrTextForDescriptionBar);
  642. if (SUCCEEDED(hr))
  643. hr = i_lpResultData->SetDescBarText(bstrTextForDescriptionBar);
  644. return hr;
  645. }
  646. HRESULT
  647. CMmcDfsAdmin::ToolbarSelect(
  648. IN const LONG i_lArg,
  649. IN IToolbar* i_pToolBar
  650. )
  651. /*++
  652. Routine Description:
  653. Handle a select event for a toolbar
  654. Enable the buttons, if the event for a selection.
  655. Disable the buttons, if the event was for a deselection
  656. Arguments:
  657. i_lArg - The argument passed to the actual method.
  658. o_pToolBar - The Toolbar pointer.
  659. --*/
  660. {
  661. RETURN_INVALIDARG_IF_NULL(i_pToolBar);
  662. BOOL bSelect = (BOOL) HIWORD(i_lArg); // Is the event for selection?
  663. EnableToolbarButtons(i_pToolBar, IDT_ADMIN_MIN, IDT_ADMIN_MAX, bSelect);
  664. return S_OK;
  665. }
  666. HRESULT
  667. CMmcDfsAdmin::CreateToolbar(
  668. IN const LPCONTROLBAR i_pControlbar,
  669. IN const LPEXTENDCONTROLBAR i_lExtendControlbar,
  670. OUT IToolbar** o_pToolBar
  671. )
  672. /*++
  673. Routine Description:
  674. Create the toolbar.
  675. Involves the actual toolbar creation call, creating the bitmap and adding it
  676. and finally adding the buttons to the toolbar
  677. Arguments:
  678. i_pControlbar - The controlbar used to create toolbar.
  679. i_lExtendControlbar - The object implementing IExtendControlbar. This is
  680. the class exposed to MMC.
  681. o_pToolBar - The Toolbar pointer.
  682. --*/
  683. {
  684. RETURN_INVALIDARG_IF_NULL(i_pControlbar);
  685. RETURN_INVALIDARG_IF_NULL(i_lExtendControlbar);
  686. RETURN_INVALIDARG_IF_NULL(o_pToolBar);
  687. // Create the toolbar
  688. HRESULT hr = i_pControlbar->Create(TOOLBAR, i_lExtendControlbar, reinterpret_cast<LPUNKNOWN*>(o_pToolBar));
  689. RETURN_IF_FAILED(hr);
  690. // Add the bitmap to the toolbar
  691. hr = AddBitmapToToolbar(*o_pToolBar, IDB_ADMIN_TOOLBAR);
  692. RETURN_IF_FAILED(hr);
  693. int iButtonPosition = 0; // The first button position
  694. for (int iCommandID = IDT_ADMIN_MIN, iMenuResource = IDS_MENUS_STATIC_TOP_NEW_DFSROOT;
  695. iCommandID <= IDT_ADMIN_MAX;
  696. iCommandID++,iMenuResource++,iButtonPosition++)
  697. {
  698. CComBSTR bstrMenuText;
  699. CComBSTR bstrToolTipText;
  700. hr = GetMenuResourceStrings(iMenuResource, &bstrMenuText, &bstrToolTipText, NULL);
  701. RETURN_IF_FAILED(hr);
  702. // Add all the buttons to the toolbar
  703. MMCBUTTON ToolbarButton;
  704. ZeroMemory(&ToolbarButton, sizeof ToolbarButton);
  705. ToolbarButton.nBitmap = iButtonPosition;
  706. ToolbarButton.idCommand = iCommandID;
  707. ToolbarButton.fsState = TBSTATE_ENABLED;
  708. ToolbarButton.fsType = TBSTYLE_BUTTON;
  709. ToolbarButton.lpButtonText = bstrMenuText;
  710. ToolbarButton.lpTooltipText = bstrToolTipText;
  711. // Add the button to the toolbar
  712. hr = (*o_pToolBar)->InsertButton(iButtonPosition, &ToolbarButton);
  713. RETURN_IF_FAILED(hr);
  714. }
  715. return hr;
  716. }
  717. STDMETHODIMP
  718. CMmcDfsAdmin::ToolbarClick(
  719. IN const LPCONTROLBAR i_pControlbar,
  720. IN const LPARAM i_lParam
  721. )
  722. /*++
  723. Routine Description:
  724. Action to take on a click on a toolbar
  725. Arguments:
  726. i_pControlbar - The controlbar used to create toolbar.
  727. i_lParam - The lparam to the actual notify. This is the command id of
  728. the button on which a click occurred.
  729. --*/
  730. {
  731. RETURN_INVALIDARG_IF_NULL(i_pControlbar);
  732. HRESULT hr = S_OK;
  733. switch(i_lParam) // What button did the user click on.
  734. {
  735. case IDT_ADMIN_CONNECTTO:
  736. hr = OnConnectTo();
  737. break;
  738. case IDT_ADMIN_NEW_DFSROOT:
  739. hr = OnNewDfsRoot();
  740. break;
  741. default:
  742. hr = E_INVALIDARG;
  743. break;
  744. };
  745. return hr;
  746. }
  747. STDMETHODIMP CMmcDfsAdmin::CleanScopeChildren(
  748. )
  749. {
  750. /*++
  751. Routine Description:
  752. Recursively deletes all Scope pane children display objects.
  753. --*/
  754. HRESULT hr = S_OK;
  755. if (!m_RootList.empty())
  756. {
  757. // clean up display objects
  758. for (DFS_ROOT_LIST::iterator i = m_RootList.begin(); i != m_RootList.end(); i++)
  759. {
  760. delete (*i);
  761. }
  762. m_RootList.erase(m_RootList.begin(), m_RootList.end());
  763. // Delete all child items from scope pane
  764. if (m_lpConsoleNameSpace)
  765. {
  766. HSCOPEITEM hChild = NULL;
  767. MMC_COOKIE lCookie = 0;
  768. while (SUCCEEDED(hr = m_lpConsoleNameSpace->GetChildItem(m_hItemParent, &hChild, &lCookie)) && hChild)
  769. {
  770. (void) m_lpConsoleNameSpace->DeleteItem(hChild, TRUE);
  771. }
  772. }
  773. }
  774. return S_OK;
  775. }