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.

1867 lines
41 KiB

  1. /*++
  2. Copyright (c) 1994-1998 Microsoft Corporation
  3. Module Name :
  4. events.cpp
  5. Abstract:
  6. Handle snapin event notifications
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Project:
  10. Internet Services Manager
  11. Revision History:
  12. --*/
  13. //
  14. // Include Files
  15. //
  16. #include "stdafx.h"
  17. #include "inetmgr.h"
  18. #include "cinetmgr.h"
  19. //
  20. // Event handlers
  21. //
  22. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  23. HRESULT
  24. CSnapin::OnFolder(
  25. IN MMC_COOKIE cookie,
  26. IN LPARAM arg,
  27. IN LPARAM param
  28. )
  29. /*++
  30. Routine Description:
  31. 'Folder change' notification handler
  32. Arguments:
  33. MMC_COOKIE cookie : Selected item
  34. LPARAM arg : Notification Argument
  35. LPARAM param : Notification Parameter
  36. Return Value:
  37. HRESULT
  38. --*/
  39. {
  40. ASSERT(FALSE);
  41. return S_OK;
  42. }
  43. HRESULT
  44. CSnapin::OnAddImages(
  45. IN MMC_COOKIE cookie,
  46. IN LPARAM arg,
  47. IN LPARAM param
  48. )
  49. /*++
  50. Routine Description:
  51. 'Add Image' handler
  52. Arguments:
  53. MMC_COOKIE cookie : Selected item
  54. LPARAM arg : Notification Argument
  55. LPARAM param : Notification Parameter
  56. Return Value:
  57. HRESULT
  58. --*/
  59. {
  60. //
  61. // if cookie is from a different snapin
  62. // if (IsMyCookie(cookie) == FALSE)
  63. //
  64. if (0)
  65. {
  66. //
  67. // add the images for the scope tree only
  68. //
  69. CBitmap bmp16x16;
  70. CBitmap bmp32x32;
  71. LPIMAGELIST lpImageList = reinterpret_cast<LPIMAGELIST>(arg);
  72. //
  73. // Load the bitmaps from the dll
  74. //
  75. {
  76. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  77. bmp16x16.LoadBitmap(IDB_16x16);
  78. bmp32x32.LoadBitmap(IDB_32x32);
  79. }
  80. //
  81. // Set the images
  82. //
  83. lpImageList->ImageListSetStrip(
  84. reinterpret_cast<LONG_PTR*>(static_cast<HBITMAP>(bmp16x16)),
  85. reinterpret_cast<LONG_PTR*>(static_cast<HBITMAP>(bmp32x32)),
  86. 0, RGB(255, 0, 255)
  87. );
  88. lpImageList->Release();
  89. }
  90. else
  91. {
  92. InitializeBitmaps(cookie);
  93. }
  94. return S_OK;
  95. }
  96. HRESULT
  97. CSnapin::OnShow(
  98. IN MMC_COOKIE cookie,
  99. IN LPARAM arg,
  100. IN LPARAM param
  101. )
  102. /*++
  103. Routine Description:
  104. 'Show' notification handler
  105. Arguments:
  106. MMC_COOKIE cookie : Selected item
  107. LPARAM arg : Notification Argument
  108. LPARAM param : Notification Parameter
  109. Return Value:
  110. HRESULT
  111. --*/
  112. {
  113. //
  114. // Note - arg is TRUE when it is time to enumerate
  115. //
  116. if (arg)
  117. {
  118. //
  119. // Show the headers for this nodetype
  120. //
  121. InitializeHeaders(cookie);
  122. Enumerate(cookie, param);
  123. if (m_pControlbar)
  124. {
  125. SetToolbarStates(cookie);
  126. }
  127. }
  128. else
  129. {
  130. //
  131. // Free data associated with the result pane items, because
  132. // the node is no longer being displayed.
  133. // Note: The console will remove the items from the result pane
  134. //
  135. m_oblResultItems.RemoveAll();
  136. }
  137. return S_OK;
  138. }
  139. HRESULT
  140. CSnapin::OnActivate(
  141. IN MMC_COOKIE cookie,
  142. IN LPARAM arg,
  143. IN LPARAM param
  144. )
  145. /*++
  146. Routine Description:
  147. 'Activiation' notification handler
  148. Arguments:
  149. MMC_COOKIE cookie : Selected item
  150. LPARAM arg : Notification Argument
  151. LPARAM param : Notification Parameter
  152. Return Value:
  153. HRESULT
  154. --*/
  155. {
  156. return S_OK;
  157. }
  158. HRESULT
  159. CSnapin::OnResultItemClkOrDblClk(
  160. IN MMC_COOKIE cookie,
  161. IN BOOL fDblClick
  162. )
  163. /*++
  164. Routine Description:
  165. Result item click/double click notification handler
  166. Arguments:
  167. MMC_COOKIE cookie : Selected item
  168. BOOL fDblClick : TRUE if double click, FALSE for single click
  169. Return Value:
  170. HRESULT
  171. --*/
  172. {
  173. CIISObject * pObject = (CIISObject *)cookie;
  174. if (pObject && !pObject->IsMMCConfigurable() && pObject->IsLeafNode())
  175. {
  176. //
  177. // Special case: Down-level object -- not mmc configurable, but
  178. // configuration is the default verb, so fake it.
  179. //
  180. if (fDblClick)
  181. {
  182. ((CComponentDataImpl *)m_pComponentData)->DoConfigure(pObject);
  183. return S_OK;
  184. }
  185. }
  186. //
  187. // Use the default verb
  188. //
  189. return S_FALSE;
  190. }
  191. HRESULT
  192. CSnapin::OnMinimize(
  193. IN MMC_COOKIE cookie,
  194. IN LPARAM arg,
  195. IN LPARAM param
  196. )
  197. /*++
  198. Routine Description:
  199. 'Minimize' handler
  200. Arguments:
  201. MMC_COOKIE cookie : Selected item
  202. LPARAM arg : Notification Argument
  203. LPARAM param : Notification Parameter
  204. Return Value:
  205. HRESULT
  206. --*/
  207. {
  208. return S_OK;
  209. }
  210. HRESULT
  211. CSnapin::OnPropertyChange(
  212. IN LPDATAOBJECT lpDataObject
  213. )
  214. /*++
  215. Routine Description:
  216. 'Property change' notification handler
  217. Arguments:
  218. LPDATAOBJECT lpDataObject : Selected data object
  219. Return Value:
  220. HRESULT
  221. --*/
  222. {
  223. CIISObject * pObject = NULL;
  224. if (lpDataObject != NULL)
  225. {
  226. INTERNAL * pInternal = ExtractInternalFormat(lpDataObject);
  227. if (pInternal != NULL)
  228. {
  229. pObject = (CIISObject *)pInternal->m_cookie;
  230. SetToolbarStates((MMC_COOKIE)pObject);
  231. FREE_DATA(pInternal);
  232. }
  233. }
  234. return S_OK;
  235. }
  236. HRESULT
  237. CSnapin::OnUpdateView(
  238. IN LPDATAOBJECT lpDataObject
  239. )
  240. /*++
  241. Routine Description:
  242. 'Update View' notification handler
  243. Arguments:
  244. LPDATAOBJECT lpDataObject : Selected data object
  245. Return Value:
  246. HRESULT
  247. --*/
  248. {
  249. return OnPropertyChange(lpDataObject);
  250. }
  251. void
  252. CSnapin::Enumerate(
  253. IN MMC_COOKIE cookie,
  254. IN HSCOPEITEM hParent
  255. )
  256. /*++
  257. Routine Description:
  258. Scope item enumeration notification handler
  259. Arguments:
  260. MMC_COOKIE cookie : Selected cookie (i.e. IISObject *)
  261. HSCOPEITEM hParent : Scope item to be enumerated
  262. Return Value:
  263. None
  264. --*/
  265. {
  266. //
  267. // Add result view items
  268. //
  269. EnumerateResultPane(cookie);
  270. }
  271. void
  272. CSnapin::AddFileSystem(
  273. IN HSCOPEITEM hParent,
  274. IN LPCTSTR lpstrRoot,
  275. IN LPCTSTR lpstrMetaRoot,
  276. IN CIISInstance * pInstance,
  277. IN BOOL fGetDirs
  278. )
  279. /*++
  280. Routine Description:
  281. Add file system to result view.
  282. Arguments:
  283. HSCOPEITEM hParent Parent scope item
  284. LPCTSTR lpstrRoot Physical path
  285. LPCTSTR lpstrMetaRoot Meta root
  286. CIISInstance * pInstance Owning instance
  287. BOOL fGetDirs TRUE for directories, FALSE for files
  288. Return Value:
  289. None
  290. --*/
  291. {
  292. //
  293. // Save state - needed for CWaitCursor
  294. //
  295. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  296. DWORD dwBufferSize = 0L;
  297. int cChildren = 0;
  298. CError err;
  299. do
  300. {
  301. CWaitCursor();
  302. LPCTSTR lpstrOwner = pInstance->GetMachineName();
  303. ASSERT(lpstrOwner);
  304. CString strDir;
  305. if (::IsServerLocal(lpstrOwner) || ::IsUNCName(lpstrRoot))
  306. {
  307. //
  308. // Local directory, or already a unc path
  309. //
  310. strDir = lpstrRoot;
  311. }
  312. else
  313. {
  314. ::MakeUNCPath(strDir, lpstrOwner, lpstrRoot);
  315. }
  316. strDir.TrimLeft();
  317. strDir.TrimRight();
  318. if (strDir.IsEmpty())
  319. {
  320. //
  321. // Invalid path
  322. //
  323. break;
  324. }
  325. strDir += _T("\\*");
  326. WIN32_FIND_DATA w32data;
  327. HANDLE hFind = ::FindFirstFile(strDir, &w32data);
  328. if (hFind == INVALID_HANDLE_VALUE)
  329. {
  330. err.GetLastWinError();
  331. break;
  332. }
  333. //
  334. // Find metabase information to match up with
  335. // this entry
  336. //
  337. CWaitCursor wait;
  338. CString strRedirect;
  339. CString strBase;
  340. pInstance->BuildFullPath(strBase, TRUE);
  341. LPCTSTR lpPath = lpstrMetaRoot;
  342. while (lpPath && *lpPath && *lpPath != _T('/')) ++lpPath;
  343. if (lpPath && *lpPath)
  344. {
  345. strBase += lpPath;
  346. }
  347. TRACEEOLID("Opening: " << strBase);
  348. TRACEEOLID(lpstrMetaRoot);
  349. BOOL fCheckMetabase = TRUE;
  350. CMetaKey mk(
  351. lpstrOwner,
  352. METADATA_PERMISSION_READ,
  353. METADATA_MASTER_ROOT_HANDLE,
  354. strBase
  355. );
  356. CError errMB(mk.QueryResult());
  357. if (errMB.Win32Error() == ERROR_PATH_NOT_FOUND)
  358. {
  359. //
  360. // Metabase path not found, not a problem.
  361. //
  362. TRACEEOLID("Parent node not in metabase");
  363. fCheckMetabase = FALSE;
  364. errMB.Reset();
  365. }
  366. else if (!errMB.MessageBoxOnFailure())
  367. {
  368. //
  369. // Opened successfully, read redirect string.
  370. //
  371. DWORD dwAttr;
  372. errMB = mk.QueryValue(
  373. MD_HTTP_REDIRECT,
  374. strRedirect,
  375. NULL, // Inheritance override
  376. NULL, // Path
  377. &dwAttr
  378. );
  379. if (errMB.Succeeded())
  380. {
  381. if (IS_FLAG_SET(dwAttr, METADATA_INHERIT))
  382. {
  383. int nComma = strRedirect.Find(_T(','));
  384. if (nComma >= 0)
  385. {
  386. strRedirect.ReleaseBuffer(nComma);
  387. }
  388. }
  389. else
  390. {
  391. //
  392. // Yes, there's a redirect on the parent, but it's
  393. // not marked as inheritable, so it won't affect
  394. // the children.
  395. //
  396. strRedirect.Empty();
  397. }
  398. }
  399. }
  400. //
  401. // Loop through the file system
  402. //
  403. do
  404. {
  405. //
  406. // Check to see if this is a file or directory as desired.
  407. // Ignore anything starting with a dot.
  408. //
  409. TRACEEOLID(w32data.cFileName);
  410. BOOL fIsDir =
  411. ((w32data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
  412. if (fIsDir == fGetDirs && *w32data.cFileName != _T('.'))
  413. {
  414. CIISFileNode * pNode = new CIISFileNode(
  415. w32data.cFileName,
  416. w32data.dwFileAttributes,
  417. pInstance,
  418. strRedirect,
  419. fIsDir
  420. );
  421. if (pNode == NULL)
  422. {
  423. err = ERROR_NOT_ENOUGH_MEMORY;
  424. break;
  425. }
  426. //
  427. // For the result view -- only files, directories
  428. // get added automatically
  429. //
  430. ASSERT(!fIsDir);
  431. if (fCheckMetabase)
  432. {
  433. errMB = mk.DoesPathExist(w32data.cFileName);
  434. if (errMB.Succeeded())
  435. {
  436. //
  437. // Match up with metabase properties. If the item
  438. // is found in the metabase with a non-inherited vrpath,
  439. // than a virtual root with this name exists, and this
  440. // file/directory should not be shown.
  441. //
  442. BOOL fVirtualDirectory;
  443. CString strMetaRoot(lpstrMetaRoot);
  444. errMB = pNode->FetchMetaInformation(
  445. strMetaRoot,
  446. &fVirtualDirectory
  447. );
  448. if (errMB.Succeeded() && fVirtualDirectory)
  449. {
  450. TRACEEOLID("file/directory exists as vroot -- tossing"
  451. << w32data.cFileName);
  452. delete pNode;
  453. continue;
  454. }
  455. }
  456. }
  457. //
  458. // This better be unassigned -- one scope item per IISobject!
  459. // Note that the scope handle we're setting is actually the
  460. // _parent_'s scope handle.
  461. //
  462. ASSERT(pNode->GetScopeHandle() == NULL);
  463. pNode->SetScopeHandle(hParent, TRUE);
  464. //
  465. // Add the item
  466. //
  467. RESULTDATAITEM ri;
  468. ::ZeroMemory(&ri, sizeof(ri));
  469. ri.mask = RDI_STR | RDI_IMAGE | RDI_PARAM;
  470. ri.str = MMC_CALLBACK;
  471. ri.nImage = pNode->QueryBitmapIndex();
  472. ri.lParam = (LPARAM)pNode;
  473. m_pResult->InsertItem(&ri);
  474. //
  475. // Store
  476. //
  477. m_oblResultItems.AddTail(pNode);
  478. }
  479. }
  480. while(err.Succeeded() && FindNextFile(hFind, &w32data));
  481. ::FindClose(hFind);
  482. }
  483. while(FALSE);
  484. if (err.Failed())
  485. {
  486. //
  487. // Behaviour change: Display the errors always on the result
  488. // enumerator, and stop displaying them on the scope side
  489. // (this way we avoid double error messages)
  490. //
  491. err.MessageBoxFormat(
  492. IDS_ERR_ENUMERATE_FILES,
  493. MB_OK,
  494. NO_HELP_CONTEXT
  495. );
  496. }
  497. }
  498. void
  499. CSnapin::DestroyItem(
  500. IN LPDATAOBJECT lpDataObject
  501. )
  502. /*++
  503. Routine Description:
  504. Delete the contents of the given data object
  505. Arguments:
  506. LPDATAOBJECT lpDataObject : Data object to be destroyed
  507. Return Value:
  508. None
  509. --*/
  510. {
  511. CIISObject * pObject = NULL;
  512. if (lpDataObject)
  513. {
  514. INTERNAL * pInternal = ExtractInternalFormat(lpDataObject);
  515. if (pInternal)
  516. {
  517. pObject = (CIISObject *)pInternal->m_cookie;
  518. delete pObject;
  519. FREE_DATA(pInternal);
  520. }
  521. }
  522. }
  523. void
  524. CSnapin::EnumerateResultPane(
  525. IN MMC_COOKIE cookie
  526. )
  527. /*++
  528. Routine Description:
  529. Enumerate the result pane
  530. Arguments:
  531. MMC_COOKIE cookie : Parent CIISObject (scope side)
  532. Return Value:
  533. None
  534. --*/
  535. {
  536. //
  537. // Make sure we QI'ed for the interface
  538. //
  539. ASSERT(m_pResult != NULL);
  540. ASSERT(m_pComponentData != NULL);
  541. CIISObject * pObject = (CIISObject *)cookie;
  542. if (pObject == NULL)
  543. {
  544. //
  545. // Static root node -- owns no leaf nodes
  546. //
  547. return;
  548. }
  549. if (pObject->SupportsFileSystem())
  550. {
  551. CString strPhysicalPath, strMetaPath;
  552. pObject->BuildPhysicalPath(strPhysicalPath);
  553. pObject->BuildFullPath(strMetaPath, FALSE);
  554. AddFileSystem(
  555. pObject->GetScopeHandle(),
  556. strPhysicalPath,
  557. strMetaPath,
  558. pObject->FindOwnerInstance(),
  559. GET_FILES
  560. );
  561. }
  562. //m_pResult->Sort(0, 0, -1);
  563. }
  564. HSCOPEITEM
  565. CComponentDataImpl::AddIISObject(
  566. IN HSCOPEITEM hParent,
  567. IN CIISObject * pObject,
  568. IN HSCOPEITEM hSibling, OPTIONAL
  569. IN BOOL fNext OPTIONAL
  570. )
  571. /*++
  572. Routine Description:
  573. Insert IIS object to the scope view
  574. Arguments:
  575. HSCOPEITEM hParent : Parent scope handle
  576. CIISObject * pObject : Object to be added
  577. HSCOPEITEM hSibling : NULL, or otherwise next sibling item
  578. BOOL fNext : If hSibling != NULL, this is used to indicate
  579. : Next (TRUE), or Previous (FALSE).
  580. Return Value:
  581. Handle to scope item of the newly added item
  582. --*/
  583. {
  584. ASSERT(m_pScope != NULL);
  585. ASSERT(pObject != NULL);
  586. SCOPEDATAITEM item;
  587. ::ZeroMemory(&item, sizeof(SCOPEDATAITEM));
  588. item.mask = SDI_STR | SDI_IMAGE | SDI_OPENIMAGE | SDI_PARAM | SDI_CHILDREN;
  589. if (hSibling != NULL)
  590. {
  591. item.mask |= (fNext ? SDI_NEXT : SDI_PREVIOUS);
  592. item.relativeID = hSibling;
  593. }
  594. else
  595. {
  596. item.mask |= SDI_PARENT;
  597. item.relativeID = hParent;
  598. }
  599. //
  600. // No '+' sign if no child objects could possibly exist.
  601. // e.g. downlevel web services, etc.
  602. //
  603. item.cChildren =
  604. (pObject->SupportsFileSystem() || pObject->SupportsChildren())
  605. ? 1 : 0;
  606. item.displayname = MMC_CALLBACK;
  607. item.nOpenImage = item.nImage = pObject->QueryBitmapIndex();
  608. item.lParam = (LPARAM)pObject;
  609. m_pScope->InsertItem(&item);
  610. //
  611. // This better be unassigned -- one scope item per IISobject!
  612. //
  613. ASSERT(pObject->GetScopeHandle() == NULL);
  614. pObject->SetScopeHandle(item.ID);
  615. return item.ID;
  616. }
  617. BOOL
  618. CComponentDataImpl::KillChildren(
  619. IN HSCOPEITEM hParent,
  620. IN UINT nOpenErrorMsg,
  621. IN BOOL fFileNodesOnly,
  622. IN BOOL fContinueOnOpenSheet
  623. )
  624. /*++
  625. Routine Description:
  626. Kill all children of a given parent node.
  627. Arguments:
  628. HSCOPEITEM hParent : The infanticidal parent handle
  629. UINT nOpenErrorMsg : Error indicating open prop sheet
  630. BOOL fFileNodesOnly : TRUE to delete only file nodes
  631. BOOL fContinueOnOpenSheet : TRUE to continue on open sheet error
  632. Return Value:
  633. TRUE if the nodes were deleted successfully -- FALSE if an open property
  634. sheet prevents deletions.
  635. --*/
  636. {
  637. ASSERT(m_pScope != NULL);
  638. ASSERT(nOpenErrorMsg > 0);
  639. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  640. HSCOPEITEM hChildItem;
  641. MMC_COOKIE cookie;
  642. //
  643. // If a property sheet is open for this item, don't
  644. // allow deletion.
  645. //
  646. LPPROPERTYSHEETPROVIDER piPropertySheetProvider = NULL;
  647. CError err(m_pConsole->QueryInterface(
  648. IID_IPropertySheetProvider,
  649. (void **)&piPropertySheetProvider
  650. ));
  651. if (err.MessageBoxOnFailure())
  652. {
  653. return FALSE;
  654. }
  655. CWaitCursor wait;
  656. if (!fFileNodesOnly)
  657. {
  658. //
  659. // Loop through and find open property sheets on the
  660. // nodes.
  661. //
  662. err = m_pScope->GetChildItem(hParent, &hChildItem, &cookie);
  663. while (err.Succeeded() && hChildItem != NULL)
  664. {
  665. CIISObject * pObject = (CIISObject *)cookie;
  666. HSCOPEITEM hTarget = NULL;
  667. if (FindOpenPropSheetOnNodeAndDescendants(
  668. piPropertySheetProvider,
  669. cookie
  670. ))
  671. {
  672. ::AfxMessageBox(nOpenErrorMsg);
  673. if (!fContinueOnOpenSheet)
  674. {
  675. return FALSE;
  676. }
  677. }
  678. //
  679. // Advance to next child of the same parent.
  680. //
  681. err = m_pScope->GetNextItem(hChildItem, &hChildItem, &cookie);
  682. }
  683. }
  684. //
  685. // Having ensured that no relevant property sheets remain open,
  686. // we can start committing infanticide.
  687. //
  688. err = m_pScope->GetChildItem(hParent, &hChildItem, &cookie);
  689. while (err.Succeeded() && hChildItem != NULL)
  690. {
  691. CIISObject * pObject = (CIISObject *)cookie;
  692. TRACEEOLID("Deleting: " << pObject->GetNodeName());
  693. HSCOPEITEM hTarget = NULL;
  694. if (!fFileNodesOnly || pObject->IsFileSystemNode())
  695. {
  696. if (FindOpenPropSheetOnNodeAndDescendants(
  697. piPropertySheetProvider,
  698. cookie
  699. ))
  700. {
  701. //
  702. // Can't kill this one then, display error, but continue
  703. //
  704. TRACEEOLID("Unable to kill child -- sheet open shouldn't happen!");
  705. ASSERT(FALSE && "Should have been closed in the first pass");
  706. //
  707. // Message for retail. How did he do it?
  708. //
  709. ::AfxMessageBox(nOpenErrorMsg);
  710. if (!fContinueOnOpenSheet)
  711. {
  712. return FALSE;
  713. }
  714. }
  715. else
  716. {
  717. //
  718. // Remember that this one is to be deleted.
  719. //
  720. hTarget = hChildItem;
  721. }
  722. }
  723. //
  724. // Advance to next child of the same parent.
  725. //
  726. err = m_pScope->GetNextItem(hChildItem, &hChildItem, &cookie);
  727. if (hTarget)
  728. {
  729. //
  730. // Delete the item we remembered earlier. This has to be done
  731. // after the GetNextItem() otherwise the hChildItem would be
  732. // bogus
  733. //
  734. HRESULT hr2 = m_pScope->DeleteItem(pObject->GetScopeHandle(), TRUE);
  735. delete pObject;
  736. }
  737. }
  738. piPropertySheetProvider->Release();
  739. return TRUE;
  740. }
  741. HSCOPEITEM
  742. CComponentDataImpl::FindNextInstanceSibling(
  743. IN HSCOPEITEM hParent,
  744. IN CIISObject * pObject,
  745. OUT BOOL * pfNext
  746. )
  747. /*++
  748. Routine Descritpion:
  749. Find the 'next' or 'previous' instance sibling of the given object.
  750. That is, the instance we want to be inserted just in front of, or right
  751. after.
  752. Arguments:
  753. HSCOPEITEM hParent : Parent scope item
  754. CIISObject * pObject : IISObject to be placed
  755. BOOL * pfNext : Returns TRUE if sibling returned is Next, FALSE
  756. if sibling is previous, undetermined if sibling
  757. returned is NULL.
  758. Return Value:
  759. The 'next' or 'previous' sibling item (scope item handle) that the
  760. pObject is to be inserted in front of, or right after (check *pfNext),
  761. or else NULL.
  762. --*/
  763. {
  764. //
  765. // Want to group by service type. Find an appropriate
  766. // sibling. Second key is instance ID.
  767. //
  768. MMC_COOKIE cookie;
  769. int nResult;
  770. HSCOPEITEM hItem;
  771. HSCOPEITEM hSibling = NULL;
  772. LPCTSTR lpSvcName = pObject->GetServiceName();
  773. DWORD dwID = pObject->QueryInstanceID();
  774. *pfNext = TRUE;
  775. TRACEEOLID("Service name: " << lpSvcName);
  776. TRACEEOLID("Instance ID#: " << dwID);
  777. BOOL fFoundSvc = FALSE;
  778. HRESULT hr = m_pScope->GetChildItem(hParent, &hItem, &cookie);
  779. while (hr == S_OK && hItem != NULL)
  780. {
  781. CIISObject * p = (CIISObject *)cookie;
  782. ASSERT(p != NULL);
  783. TRACEEOLID("Comparing against service: " << p->GetServiceName());
  784. nResult = lstrcmpi(lpSvcName, p->GetServiceName());
  785. if (nResult == 0)
  786. {
  787. //
  788. // Found same service type, now sort on instance ID
  789. //
  790. fFoundSvc = TRUE;
  791. hSibling = hItem;
  792. *pfNext = FALSE;
  793. DWORD dw = p->QueryInstanceID();
  794. TRACEEOLID("Comparing against instance ID#: " << dw);
  795. if (dwID <= dw)
  796. {
  797. *pfNext = TRUE;
  798. break;
  799. }
  800. }
  801. else if (nResult < 0)
  802. {
  803. //
  804. // Needs to be inserted before this one.
  805. //
  806. if (!fFoundSvc)
  807. {
  808. hSibling = hItem;
  809. *pfNext = TRUE;
  810. }
  811. break;
  812. }
  813. hr = m_pScope->GetNextItem(hItem, &hItem, &cookie);
  814. }
  815. return hSibling;
  816. }
  817. HSCOPEITEM
  818. CComponentDataImpl::FindNextVDirSibling(
  819. IN HSCOPEITEM hParent,
  820. IN CIISObject * pObject
  821. )
  822. /*++
  823. Routine Descritpion:
  824. Find the 'next' virtual directory sibling of the given object. That is,
  825. the vdir we want to be inserted just in front of.
  826. Arguments:
  827. HSCOPEITEM hParent : Parent scope item
  828. CIISObject * pObject : IISObject to be placed
  829. Return Value:
  830. The 'next' sibling item (scope item handle) that the pObject is to be
  831. inserted in front of, or else NULL
  832. --*/
  833. {
  834. //
  835. // Since VDIRs always are at the top of their list, the first
  836. // item with a different GUID is our 'next' sibling
  837. //
  838. HSCOPEITEM hItem;
  839. MMC_COOKIE cookie;
  840. GUID guid1 = pObject->QueryGUID();
  841. HRESULT hr = m_pScope->GetChildItem(hParent, &hItem, &cookie);
  842. while (hr == S_OK && hItem != NULL)
  843. {
  844. CIISObject * p = (CIISObject *)cookie;
  845. ASSERT(p != NULL);
  846. GUID guid2 = p->QueryGUID();
  847. if (guid1 != guid2)
  848. {
  849. //
  850. // Want to insert before this one
  851. //
  852. return hItem;
  853. }
  854. hr = m_pScope->GetNextItem(hItem, &hItem, &cookie);
  855. }
  856. //
  857. // Nothing found
  858. //
  859. return NULL;
  860. }
  861. HSCOPEITEM
  862. CComponentDataImpl::FindServerInfoParent(
  863. IN HSCOPEITEM hParent,
  864. IN CServerInfo * pServerInfo
  865. )
  866. /*++
  867. Routine Description:
  868. Find server info parent object for this object. The server info
  869. parent depends on the type of view, and can be a machine node,
  870. or a service collector node.
  871. Arguments:
  872. HSCOPEITEM hParent : Parent scope
  873. CServerInfo * pServerInfo
  874. Return Value:
  875. The scope item handle of the appropriate parent object, or
  876. NULL if not found.
  877. --*/
  878. {
  879. ASSERT(m_pScope != NULL);
  880. //
  881. // Notes: The server info object parent is always a machine
  882. // node. Find the one that maches the computer name.
  883. //
  884. HSCOPEITEM hItem;
  885. MMC_COOKIE cookie;
  886. HRESULT hr = m_pScope->GetChildItem(hParent, &hItem, &cookie);
  887. while (hr == S_OK && hItem != NULL)
  888. {
  889. CIISObject * pObject = (CIISObject *)cookie;
  890. //
  891. // Skip objects that we don't own
  892. //
  893. if (pObject != NULL)
  894. {
  895. ASSERT(pObject->QueryGUID() == cMachineNode);
  896. //
  897. // Compare computer names
  898. //
  899. CIISMachine * pMachine = (CIISMachine *)pObject;
  900. if (::lstrcmpi(pServerInfo->QueryServerName(),
  901. pMachine->GetMachineName()) == 0)
  902. {
  903. //
  904. // Found the item
  905. //
  906. return hItem;
  907. }
  908. }
  909. //
  910. // Advance to next child of the same parent.
  911. //
  912. hr = m_pScope->GetNextItem(hItem, &hItem, &cookie);
  913. }
  914. //
  915. // Not found
  916. //
  917. return NULL;
  918. }
  919. HSCOPEITEM
  920. CComponentDataImpl::ForceAddServerInfoParent(
  921. IN HSCOPEITEM hParent,
  922. IN CServerInfo * pServerInfo
  923. )
  924. /*++
  925. Routine Description:
  926. Add a serverinfo object to the scope view
  927. Arguments:
  928. HSCOPEITEM hParent : Handle to parent scope item
  929. CServerInfo * pServerInfo : Server info object
  930. Return Value:
  931. Handle to the scope item of the newly inserted object
  932. --*/
  933. {
  934. //
  935. // Server info parents are always machine nodes now.
  936. //
  937. CIISMachine * pMachine = new CIISMachine(pServerInfo->QueryServerName());
  938. pMachine->m_fIsExtension = m_fIsExtension;
  939. return AddIISObject(hParent, pMachine);
  940. }
  941. HSCOPEITEM
  942. CComponentDataImpl::AddServerInfoParent(
  943. IN HSCOPEITEM hRootNode,
  944. IN CServerInfo * pServerInfo
  945. )
  946. /*++
  947. Routine Description:
  948. Add server info parent object appropriate for the given object. Look
  949. to see if one exists, otherwise add one. Return the handle to the
  950. parent object.
  951. Arguments:
  952. HSCOPEITEM hRootNode : Root of the scope view
  953. CServerInfo * pServerInfo : Server info object, whose parent we add
  954. Return Value:
  955. Scope view handle to a suitable server info parent object
  956. --*/
  957. {
  958. HSCOPEITEM hParent = FindServerInfoParent(hRootNode, pServerInfo);
  959. if (hParent == NULL)
  960. {
  961. //
  962. // Parent doesn't exist, add it
  963. //
  964. hParent = ForceAddServerInfoParent(hRootNode, pServerInfo);
  965. }
  966. return hParent;
  967. }
  968. HSCOPEITEM
  969. CComponentDataImpl::AddServerInfo(
  970. IN HSCOPEITEM hRootNode,
  971. IN CServerInfo * pServerInfo,
  972. IN BOOL fAddParent
  973. )
  974. /*++
  975. Routine Description:
  976. Add a serverinfo object to the scope view. Find suitable parent object,
  977. and attach to it.
  978. Arguments:
  979. HSCOPEITEM hRootNode : Parent scope item handle
  980. CServerInfo * pServerInfo : Server info object to be added.
  981. BOOL fAddParent : TRUE to add parent item, FALSE to add to
  982. the given parent scope item
  983. Return Value:
  984. Handle to the newly added object.
  985. --*/
  986. {
  987. HSCOPEITEM hItem = NULL;
  988. HSCOPEITEM hParent = fAddParent
  989. ? AddServerInfoParent(hRootNode, pServerInfo)
  990. : hRootNode;
  991. CError err;
  992. ASSERT(hParent != NULL);
  993. try
  994. {
  995. //
  996. // Add it underneath the parent
  997. //
  998. if (!pServerInfo->SupportsInstances())
  999. {
  1000. //
  1001. // No instance support for this service
  1002. // type. Add a single down-level instance
  1003. //
  1004. CIISInstance * pInstance = new CIISInstance(pServerInfo);
  1005. BOOL fNext;
  1006. HSCOPEITEM hSibling = FindNextInstanceSibling(
  1007. hParent,
  1008. pInstance,
  1009. &fNext
  1010. );
  1011. hItem = AddIISObject(hParent, pInstance, hSibling, fNext);
  1012. }
  1013. else
  1014. {
  1015. //
  1016. // Add all virtual hosts (instances) at the same level
  1017. // as a single instance item. Temporarily wrap this
  1018. // in a down-level instance.
  1019. //
  1020. CIISInstance inst(pServerInfo);
  1021. hItem = AddInstances(hParent, &inst);
  1022. }
  1023. }
  1024. catch(CMemoryException * e)
  1025. {
  1026. hItem = NULL;
  1027. err = ERROR_NOT_ENOUGH_MEMORY;
  1028. e->Delete();
  1029. }
  1030. if (err.Failed())
  1031. {
  1032. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  1033. err.MessageBox();
  1034. }
  1035. return hItem;
  1036. }
  1037. //
  1038. // CODEWORK: Mess, should merge with AddFileSystem in results
  1039. //
  1040. HSCOPEITEM
  1041. CComponentDataImpl::AddFileSystem(
  1042. IN HSCOPEITEM hParent,
  1043. IN LPCTSTR lpstrRoot,
  1044. IN LPCTSTR lpstrMetaRoot,
  1045. IN CIISInstance * pInstance,
  1046. IN BOOL fGetDirs,
  1047. IN BOOL fDeleteCurrentFileSystem
  1048. )
  1049. /*++
  1050. Routine Description:
  1051. Add file system objects on the scope side
  1052. Arguments:
  1053. HSCOPEITEM hParent : Parent scope item
  1054. LPCTSTR lpstrRoot : Phsysical root path
  1055. LPCTSTR lpstrMetaRoot : Meta root path
  1056. CIISInstance * pInstance : Owner instance
  1057. BOOL fGetDirs : TRUE to get directories, FALSE for files
  1058. BOOL fDeleteCurrentFileSystem : TRUE to remove the current file/dir tree first
  1059. Return Value:
  1060. Handle to the last scope item added.
  1061. --*/
  1062. {
  1063. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  1064. ASSERT(hParent != NULL);
  1065. CError err;
  1066. HSCOPEITEM hItem = NULL;
  1067. DWORD dwBufferSize = 0L;
  1068. int cChildren = 0;
  1069. do
  1070. {
  1071. if (fDeleteCurrentFileSystem)
  1072. {
  1073. TRACEEOLID("Deleting current file enumeration");
  1074. if (!KillChildren(
  1075. hParent,
  1076. IDS_PROP_OPEN_CONTINUE,
  1077. DELETE_FILES_ONLY,
  1078. CONTINUE_ON_OPEN_SHEET
  1079. ))
  1080. {
  1081. //
  1082. // Failed to remove the file system that was already enumerated
  1083. // here. An error message will already have been displayed, so
  1084. // quit gracefully here.
  1085. //
  1086. break;
  1087. }
  1088. }
  1089. LPCTSTR lpstrOwner = pInstance->GetMachineName();
  1090. ASSERT(lpstrOwner);
  1091. //
  1092. // Turn the path into a UNC path
  1093. //
  1094. CString strDir;
  1095. if (::IsServerLocal(lpstrOwner) || ::IsUNCName(lpstrRoot))
  1096. {
  1097. //
  1098. // Local directory, or already a unc path
  1099. //
  1100. strDir = lpstrRoot;
  1101. }
  1102. else
  1103. {
  1104. ::MakeUNCPath(strDir, lpstrOwner, lpstrRoot);
  1105. }
  1106. strDir.TrimLeft();
  1107. strDir.TrimRight();
  1108. if (strDir.IsEmpty())
  1109. {
  1110. //
  1111. // Invalid path
  1112. //
  1113. break;
  1114. }
  1115. strDir += _T("\\*");
  1116. WIN32_FIND_DATA w32data;
  1117. HANDLE hFind = ::FindFirstFile(strDir, &w32data);
  1118. if (hFind == INVALID_HANDLE_VALUE)
  1119. {
  1120. err.GetLastWinError();
  1121. break;
  1122. }
  1123. //
  1124. // See if the parent has a redirect on it
  1125. //
  1126. CWaitCursor wait;
  1127. CString strRedirect;
  1128. CString strBase;
  1129. pInstance->BuildFullPath(strBase, TRUE);
  1130. LPCTSTR lpPath = lpstrMetaRoot;
  1131. while (lpPath && *lpPath && *lpPath != _T('/')) ++lpPath;
  1132. if (lpPath && *lpPath)
  1133. {
  1134. strBase += lpPath;
  1135. }
  1136. TRACEEOLID("Opening: " << strBase);
  1137. TRACEEOLID(lpstrMetaRoot);
  1138. BOOL fCheckMetabase = TRUE;
  1139. CMetaKey mk(
  1140. lpstrOwner,
  1141. METADATA_PERMISSION_READ,
  1142. METADATA_MASTER_ROOT_HANDLE,
  1143. strBase
  1144. );
  1145. CError errMB(mk.QueryResult());
  1146. if (errMB.Win32Error() == ERROR_PATH_NOT_FOUND)
  1147. {
  1148. //
  1149. // Metabase path not found, not a problem.
  1150. //
  1151. TRACEEOLID("Parent node not in metabase");
  1152. fCheckMetabase = FALSE;
  1153. errMB.Reset();
  1154. }
  1155. else if (!errMB.MessageBoxOnFailure())
  1156. {
  1157. //
  1158. // Opened successfully, read redirect string.
  1159. //
  1160. DWORD dwAttr;
  1161. errMB = mk.QueryValue(
  1162. MD_HTTP_REDIRECT,
  1163. strRedirect,
  1164. NULL, // Inheritance override
  1165. NULL, // Path
  1166. &dwAttr
  1167. );
  1168. if (errMB.Succeeded())
  1169. {
  1170. if (IS_FLAG_SET(dwAttr, METADATA_INHERIT))
  1171. {
  1172. int nComma = strRedirect.Find(_T(','));
  1173. if (nComma >= 0)
  1174. {
  1175. strRedirect.ReleaseBuffer(nComma);
  1176. }
  1177. }
  1178. else
  1179. {
  1180. //
  1181. // Yes, there's a redirect on the parent, but it's
  1182. // not marked as inheritable, so it won't affect
  1183. // the children.
  1184. //
  1185. strRedirect.Empty();
  1186. }
  1187. }
  1188. }
  1189. //
  1190. // Loop through the file system
  1191. //
  1192. do
  1193. {
  1194. //
  1195. // Check to see if this is a file or directory/
  1196. // Ignore anything starting with a dot.
  1197. //
  1198. TRACEEOLID(w32data.cFileName);
  1199. BOOL fIsDir = ((w32data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
  1200. if (fIsDir == fGetDirs && *w32data.cFileName != _T('.'))
  1201. {
  1202. CIISFileNode * pNode = new CIISFileNode(
  1203. w32data.cFileName,
  1204. w32data.dwFileAttributes,
  1205. pInstance,
  1206. strRedirect,
  1207. fIsDir
  1208. );
  1209. if (pNode == NULL)
  1210. {
  1211. err = ERROR_NOT_ENOUGH_MEMORY;
  1212. break;
  1213. }
  1214. if (fCheckMetabase)
  1215. {
  1216. errMB = mk.DoesPathExist(w32data.cFileName);
  1217. ASSERT(errMB.Succeeded()
  1218. || errMB.Win32Error() == ERROR_PATH_NOT_FOUND);
  1219. if (errMB.Succeeded())
  1220. {
  1221. //
  1222. // Match up with metabase properties. If the item
  1223. // is found in the metabase with a non-inherited vrpath,
  1224. // than a virtual root with this name exists, and this
  1225. // file/directory should not be shown.
  1226. //
  1227. BOOL fVirtualDirectory;
  1228. CString strMetaRoot(lpstrMetaRoot);
  1229. if (pNode->FetchMetaInformation(
  1230. strMetaRoot,
  1231. &fVirtualDirectory
  1232. ) == ERROR_SUCCESS && fVirtualDirectory)
  1233. {
  1234. TRACEEOLID(
  1235. "file/directory exists as vroot -- tossing"
  1236. << w32data.cFileName
  1237. );
  1238. delete pNode;
  1239. continue;
  1240. }
  1241. }
  1242. }
  1243. //
  1244. // Always added on at the end
  1245. //
  1246. hItem = AddIISObject(hParent, pNode);
  1247. }
  1248. }
  1249. while(err.Succeeded() && FindNextFile(hFind, &w32data));
  1250. ::FindClose(hFind);
  1251. }
  1252. while(FALSE);
  1253. if (err.Failed())
  1254. {
  1255. //
  1256. // Don't display file system errors -- leave those to result side
  1257. // enumeration.
  1258. //
  1259. TRACEEOLID("Ate error message: " << err);
  1260. }
  1261. return hItem;
  1262. }
  1263. HSCOPEITEM
  1264. CComponentDataImpl::AddVirtualRoots(
  1265. IN HSCOPEITEM hParent,
  1266. IN LPCTSTR lpstrParentPath,
  1267. IN CIISInstance * pInstance
  1268. )
  1269. /*++
  1270. Routine Description:
  1271. Add virtual roots to the scope view
  1272. Arguments:
  1273. HSCOPEITEM hParent : Handle to parent scope item
  1274. LPCTSTR lpstrParentPath : Parent metabase path
  1275. CIISInstance * pInstance : Owner instance
  1276. Return Value:
  1277. Handle to the newly added scope item
  1278. --*/
  1279. {
  1280. ASSERT(hParent != NULL);
  1281. CServerInfo * pServerInfo = pInstance->GetServerInfo();
  1282. ASSERT(pServerInfo != NULL);
  1283. ISMCHILDINFO ii;
  1284. HSCOPEITEM hItem = NULL;
  1285. DWORD dwIndex = 0L;
  1286. CError err;
  1287. ZeroMemory(&ii, sizeof(ii));
  1288. ii.dwSize = sizeof(ii);
  1289. HANDLE hEnum = NULL;
  1290. FOREVER
  1291. {
  1292. DWORD dwID = pInstance->QueryID();
  1293. err = pServerInfo->ISMEnumerateChildren(
  1294. &ii,
  1295. &hEnum,
  1296. dwID,
  1297. lpstrParentPath
  1298. );
  1299. if (err.Failed())
  1300. {
  1301. break;
  1302. }
  1303. TRACEEOLID("Alias: " << ii.szAlias);
  1304. TRACEEOLID("Path : " << ii.szPath);
  1305. TRACEEOLID("Redir: " << ii.szRedirPath);
  1306. if (*ii.szPath)
  1307. {
  1308. CIISChildNode * pChild = new CIISChildNode(&ii, pInstance);
  1309. if (pChild == NULL)
  1310. {
  1311. err = ERROR_NOT_ENOUGH_MEMORY;
  1312. break;
  1313. }
  1314. //
  1315. // Always added on at the end
  1316. //
  1317. hItem = AddIISObject(hParent, pChild);
  1318. }
  1319. else
  1320. {
  1321. TRACEEOLID("Tossing child without vrpath");
  1322. }
  1323. }
  1324. if (err.Win32Error() == ERROR_NO_MORE_ITEMS)
  1325. {
  1326. //
  1327. // This is the normal way to end this
  1328. //
  1329. err.Reset();
  1330. }
  1331. if (err.Failed())
  1332. {
  1333. //
  1334. // Display error
  1335. //
  1336. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  1337. err.MessageBoxFormat(
  1338. IDS_ERR_ENUMERATE_CHILD,
  1339. MB_OK,
  1340. NO_HELP_CONTEXT,
  1341. (LPCTSTR)pServerInfo->GetServiceInfo()->GetShortName()
  1342. );
  1343. }
  1344. return hItem;
  1345. }
  1346. HSCOPEITEM
  1347. CComponentDataImpl::AddInstances(
  1348. IN HSCOPEITEM hParent,
  1349. IN CIISObject * pObject
  1350. )
  1351. /*++
  1352. Routine Description:
  1353. Add instances to the treeview
  1354. Arguments:
  1355. HSCOPEITEM hParent : Parent scope item handle
  1356. CIISObject * pObject : Owning object
  1357. Return Value:
  1358. Handle to the last instance added
  1359. --*/
  1360. {
  1361. ASSERT(hParent != NULL);
  1362. CServerInfo * pServerInfo = pObject->GetServerInfo();
  1363. ASSERT(pServerInfo != NULL);
  1364. ISMINSTANCEINFO ii;
  1365. HSCOPEITEM hItem = NULL;
  1366. DWORD dwIndex = 0L;
  1367. CError err;
  1368. ZeroMemory(&ii, sizeof(ii));
  1369. ii.dwSize = sizeof(ii);
  1370. HANDLE hEnum = NULL;
  1371. HSCOPEITEM hSibling = NULL;
  1372. FOREVER
  1373. {
  1374. //
  1375. // Loop through...
  1376. //
  1377. err = pServerInfo->ISMEnumerateInstances(&ii, &hEnum);
  1378. if (err.Failed())
  1379. {
  1380. break;
  1381. }
  1382. if (ii.dwError == ERROR_ACCESS_DENIED)
  1383. {
  1384. //
  1385. // No point in listing this one
  1386. //
  1387. continue;
  1388. }
  1389. CIISInstance * pInstance = new CIISInstance(&ii, pServerInfo);
  1390. if (pInstance == NULL)
  1391. {
  1392. err = ERROR_NOT_ENOUGH_MEMORY;
  1393. break;
  1394. }
  1395. //
  1396. // Add grouped by service type
  1397. //
  1398. BOOL fNext;
  1399. if (hSibling == NULL)
  1400. {
  1401. hSibling = FindNextInstanceSibling(
  1402. hParent,
  1403. pInstance,
  1404. &fNext
  1405. );
  1406. }
  1407. else
  1408. {
  1409. //
  1410. // Keep appending
  1411. //
  1412. fNext = FALSE;
  1413. }
  1414. hSibling = hItem = AddIISObject(
  1415. hParent,
  1416. pInstance,
  1417. hSibling,
  1418. fNext
  1419. );
  1420. }
  1421. if (err.Win32Error() == ERROR_NO_MORE_ITEMS)
  1422. {
  1423. //
  1424. // This is the normal way to end this
  1425. //
  1426. err.Reset();
  1427. }
  1428. if (err.Failed())
  1429. {
  1430. //
  1431. // Display error message
  1432. //
  1433. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  1434. switch(err.Win32Error())
  1435. {
  1436. //
  1437. // Non-fatal errors
  1438. //
  1439. case ERROR_PATH_NOT_FOUND:
  1440. case ERROR_NOT_ENOUGH_MEMORY:
  1441. case ERROR_FILE_NOT_FOUND:
  1442. ::AfxMessageBox(IDS_NON_FATAL_ERROR_INSTANCES);
  1443. err.Reset();
  1444. break;
  1445. default:
  1446. err.MessageBoxFormat(
  1447. IDS_ERR_ENUMERATE_INST,
  1448. MB_OK,
  1449. NO_HELP_CONTEXT,
  1450. (LPCTSTR)pServerInfo->GetServiceInfo()->GetShortName()
  1451. );
  1452. }
  1453. }
  1454. return hItem;
  1455. }