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.

1214 lines
24 KiB

  1. /*++
  2. Copyright (c) 1994-2001 Microsoft Corporation
  3. Module Name :
  4. iissite.cpp
  5. Abstract:
  6. IIS Site Object
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Sergei Antonov (sergeia)
  10. Project:
  11. Internet Services Manager
  12. Revision History:
  13. 10/28/2000 sergeia Split from iisobj.cpp
  14. --*/
  15. #include "stdafx.h"
  16. #include "common.h"
  17. #include "inetprop.h"
  18. #include "InetMgrApp.h"
  19. #include "iisobj.h"
  20. #include "machsht.h"
  21. #include "errors.h"
  22. #ifdef _DEBUG
  23. #undef THIS_FILE
  24. static char BASED_CODE THIS_FILE[] = __FILE__;
  25. #endif
  26. #define new DEBUG_NEW
  27. //
  28. // CIISSite implementation
  29. //
  30. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  31. //
  32. // Site Result View definition
  33. //
  34. /* static */ int
  35. CIISSite::_rgnLabels[COL_TOTAL] =
  36. {
  37. IDS_RESULT_SERVICE_DESCRIPTION,
  38. IDS_RESULT_SERVICE_STATE,
  39. IDS_RESULT_SERVICE_DOMAIN_NAME,
  40. IDS_RESULT_SERVICE_IP_ADDRESS,
  41. IDS_RESULT_SERVICE_TCP_PORT,
  42. IDS_RESULT_STATUS,
  43. };
  44. /* static */ int
  45. CIISSite::_rgnWidths[COL_TOTAL] =
  46. {
  47. 180,
  48. 70,
  49. 120,
  50. 105,
  51. 40,
  52. 200,
  53. };
  54. /* static */ CComBSTR CIISSite::_bstrStarted;
  55. /* static */ CComBSTR CIISSite::_bstrStopped;
  56. /* static */ CComBSTR CIISSite::_bstrPaused;
  57. /* static */ CComBSTR CIISSite::_bstrUnknown;
  58. /* static */ CComBSTR CIISSite::_bstrPending;
  59. /* static */ CComBSTR CIISSite::_bstrAllUnassigned;
  60. /* static */ BOOL CIISSite::_fStaticsLoaded = FALSE;
  61. /* static */
  62. void
  63. CIISSite::InitializeHeaders(LPHEADERCTRL lpHeader)
  64. /*++
  65. Routine Description:
  66. Initialize the result headers
  67. Arguments:
  68. LPHEADERCTRL lpHeader : Header control
  69. Return Value:
  70. None
  71. --*/
  72. {
  73. CIISObject::BuildResultView(lpHeader, COL_TOTAL, _rgnLabels, _rgnWidths);
  74. // CIISDirectory::InitializeHeaders(lpHeader);
  75. if (!_fStaticsLoaded)
  76. {
  77. _fStaticsLoaded =
  78. _bstrStarted.LoadString(IDS_STARTED) &&
  79. _bstrStopped.LoadString(IDS_STOPPED) &&
  80. _bstrPaused.LoadString(IDS_PAUSED) &&
  81. _bstrUnknown.LoadString(IDS_UNKNOWN) &&
  82. _bstrPending.LoadString(IDS_PENDING) &&
  83. _bstrAllUnassigned.LoadString(IDS_IP_ALL_UNASSIGNED);
  84. }
  85. }
  86. /* virtual */
  87. void
  88. CIISSite::InitializeChildHeaders(
  89. IN LPHEADERCTRL lpHeader
  90. )
  91. /*++
  92. Routine Description:
  93. Build result view for immediate descendant type
  94. Arguments:
  95. LPHEADERCTRL lpHeader : Header control
  96. Return Value:
  97. None
  98. --*/
  99. {
  100. CIISDirectory::InitializeHeaders(lpHeader);
  101. }
  102. CIISSite::CIISSite(
  103. IN CIISMachine * pOwner,
  104. IN CIISService * pService,
  105. IN LPCTSTR szNodeName
  106. )
  107. /*++
  108. Routine Description:
  109. Constructor. Determine if the given service is administrable,
  110. and resolve the details
  111. Arguments:
  112. CIISMachine * pOwner : Owner machine object
  113. CIISService * pService : Service type
  114. LPCTSTR szNodeName : Node name (numeric)
  115. Return Value:
  116. N/A
  117. Notes:
  118. This constructor does not immediately resolve the display name of the
  119. site. It will only resolve its display information when asked
  120. --*/
  121. : CIISMBNode(pOwner, szNodeName),
  122. m_pService(pService),
  123. m_fResolved(FALSE),
  124. m_strDisplayName(),
  125. //
  126. // Data members -- plonk in some defaults
  127. //
  128. m_dwState(MD_SERVER_STATE_INVALID),
  129. m_fDeletable(FALSE),
  130. m_fWolfPackEnabled(FALSE),
  131. m_fFrontPageWeb(FALSE),
  132. m_sPort(80),
  133. m_dwID(::_ttol(szNodeName)),
  134. m_dwIPAddress(0L),
  135. m_dwWin32Error(ERROR_SUCCESS),
  136. m_bstrHostHeaderName(),
  137. m_bstrComment()
  138. {
  139. ASSERT_PTR(m_pService);
  140. }
  141. CIISSite::CIISSite(
  142. IN CIISMachine * pOwner,
  143. IN CIISService * pService,
  144. IN LPCTSTR szNodeName,
  145. IN DWORD dwState,
  146. IN BOOL fDeletable,
  147. IN BOOL fClusterEnabled,
  148. IN USHORT sPort,
  149. IN DWORD dwID,
  150. IN DWORD dwIPAddress,
  151. IN DWORD dwWin32Error,
  152. IN LPOLESTR szHostHeaderName,
  153. IN LPOLESTR szComment
  154. )
  155. /*++
  156. Routine Description:
  157. Construct with full information
  158. Arguments:
  159. CIISMachine * pOwner : Owner machine object
  160. CIISService * pService : Service type
  161. LPCTSTR szNodeName : Node name (numeric)
  162. plus datamembers
  163. Return Value:
  164. N/A
  165. --*/
  166. : CIISMBNode(pOwner, szNodeName),
  167. m_pService(pService),
  168. m_fResolved(TRUE),
  169. m_strDisplayName(),
  170. //
  171. // Data Members
  172. //
  173. m_dwState(dwState),
  174. m_fDeletable(fDeletable),
  175. m_fWolfPackEnabled(fClusterEnabled),
  176. m_sPort(sPort),
  177. m_dwID(dwID),
  178. m_dwIPAddress(dwIPAddress),
  179. m_dwWin32Error(dwWin32Error),
  180. m_bstrHostHeaderName(szHostHeaderName),
  181. m_bstrComment(szComment)
  182. {
  183. ASSERT_PTR(m_pService);
  184. }
  185. CIISSite::~CIISSite()
  186. /*++
  187. Routine Description:
  188. Destructor
  189. Arguments:
  190. N/A
  191. Return Value:
  192. N/A
  193. --*/
  194. {
  195. }
  196. /* virtual */
  197. HRESULT
  198. CIISSite::RefreshData()
  199. /*++
  200. Routine Description:
  201. Refresh relevant configuration data required for display.
  202. Arguments:
  203. None
  204. Return Value:
  205. HRESULT
  206. --*/
  207. {
  208. CError err;
  209. CWaitCursor wait;
  210. CComBSTR bstrPath;
  211. CMetaKey * pKey = NULL;
  212. do
  213. {
  214. ASSERT_PTR(_lpConsoleNameSpace);
  215. err = BuildMetaPath(bstrPath);
  216. BREAK_ON_ERR_FAILURE(err);
  217. // We need instance key here
  218. CString path_inst;
  219. CMetabasePath::GetInstancePath(bstrPath, path_inst);
  220. BOOL fContinue = TRUE;
  221. while (fContinue)
  222. {
  223. fContinue = FALSE;
  224. if (NULL == (pKey = new CMetaKey(QueryInterface(), path_inst)))
  225. {
  226. TRACEEOLID("RefreshData: OOM");
  227. err = ERROR_NOT_ENOUGH_MEMORY;
  228. break;
  229. }
  230. err = pKey->QueryResult();
  231. if (IsLostInterface(err))
  232. {
  233. SAFE_DELETE(pKey);
  234. fContinue = OnLostInterface(err);
  235. }
  236. }
  237. BREAK_ON_ERR_FAILURE(err);
  238. CInstanceProps inst(pKey, _T(""), m_dwID);
  239. err = inst.LoadData();
  240. BREAK_ON_ERR_FAILURE(err);
  241. m_dwState = inst.m_dwState;
  242. m_fDeletable = !inst.m_fNotDeletable;
  243. //
  244. // Don't be confused -- cluster enabled refers
  245. // to wolfpack and has nothing to do with app server
  246. //
  247. m_fWolfPackEnabled = inst.IsClusterEnabled();
  248. m_sPort = (SHORT)inst.m_nTCPPort;
  249. m_dwID = inst.QueryInstance();
  250. m_dwIPAddress = inst.m_iaIpAddress;
  251. m_dwWin32Error = inst.m_dwWin32Error;
  252. m_bstrHostHeaderName = inst.m_strDomainName;
  253. m_bstrComment = inst.m_strComment;
  254. m_strDisplayName.Empty();
  255. // Check if it is Frontpage controlled site
  256. pKey->QueryValue(MD_FRONTPAGE_WEB, m_fFrontPageWeb);
  257. CChildNodeProps child(pKey, SZ_MBN_ROOT);
  258. err = child.LoadData();
  259. BREAK_ON_ERR_FAILURE(err);
  260. m_strRedirectPath = child.GetRedirectedPath();
  261. }
  262. while(FALSE);
  263. SAFE_DELETE(pKey);
  264. if (m_dwWin32Error == ERROR_SUCCESS)
  265. {
  266. m_dwWin32Error = err.Win32Error();
  267. }
  268. return err;
  269. }
  270. /* virtual */
  271. int
  272. CIISSite::QueryImage() const
  273. /*++
  274. Routine Description:
  275. Return bitmap index for the site
  276. Arguments:
  277. None
  278. Return Value:
  279. Bitmap index
  280. --*/
  281. {
  282. ASSERT_PTR(m_pService);
  283. if (!m_fResolved)
  284. {
  285. TRACEEOLID("Resolving name for site #" << QueryNodeName());
  286. if (m_hScopeItem == NULL)
  287. {
  288. //
  289. // BUGBUG:
  290. //
  291. // This is probably related to MMC bug #324519
  292. // where we're asked for the display info immediately
  293. // after adding the item to the console view. This
  294. // appears to fail only on refresh because the scope
  295. // item handle is missing, and we can't build a metabase
  296. // path yet.
  297. //
  298. TRACEEOLID("BUGBUG: Prematurely asked for display information");
  299. //ASSERT(FALSE);
  300. return iError;
  301. }
  302. CIISSite * that = (CIISSite *)this;
  303. CError err = that->RefreshData();
  304. that->m_fResolved = err.Succeeded();
  305. }
  306. return !m_dwWin32Error && m_pService ? m_pService->QuerySiteImage() : iError;
  307. }
  308. /* virtual */
  309. LPOLESTR
  310. CIISSite::QueryDisplayName()
  311. /*++
  312. Routine Description:
  313. Return primary display name of this site.
  314. Arguments:
  315. None
  316. Return Value:
  317. The display name
  318. --*/
  319. {
  320. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  321. if (!m_fResolved)
  322. {
  323. TRACEEOLID("Resolving name for site #" << QueryNodeName());
  324. if (m_hScopeItem == NULL)
  325. {
  326. //
  327. // BUGBUG:
  328. //
  329. // This is probably related to MMC bug #324519
  330. // where we're asked for the display info immediately
  331. // after adding the item to the console view. This
  332. // appears to fail only on refresh because the scope
  333. // item handle is missing, and we can't build a metabase
  334. // path yet.
  335. //
  336. TRACEEOLID("BUGBUG: Prematurely asked for display information");
  337. //ASSERT(FALSE);
  338. return OLESTR("");
  339. }
  340. CError err = RefreshData();
  341. m_fResolved = err.Succeeded();
  342. }
  343. if (m_strDisplayName.IsEmpty())
  344. {
  345. CIPAddress ia(m_dwIPAddress);
  346. CInstanceProps::GetDisplayText(
  347. m_strDisplayName,
  348. m_bstrComment,
  349. m_bstrHostHeaderName,
  350. ia,
  351. m_sPort,
  352. m_dwID
  353. );
  354. }
  355. CString buf = m_strDisplayName;
  356. if (m_dwState == MD_SERVER_STATE_STOPPED)
  357. {
  358. buf.Format(IDS_STOPPED_SITE_FMT, m_strDisplayName);
  359. }
  360. else if (m_dwState == MD_SERVER_STATE_PAUSED)
  361. {
  362. buf.Format(IDS_PAUSED_SITE_FMT, m_strDisplayName);
  363. }
  364. m_bstrDisplayNameStatus = buf;
  365. // return (LPTSTR)(LPCTSTR)m_strDisplayName;
  366. return m_bstrDisplayNameStatus;
  367. }
  368. /* virtual */
  369. LPOLESTR
  370. CIISSite::GetResultPaneColInfo(int nCol)
  371. /*++
  372. Routine Description:
  373. Return result pane string for the given column number
  374. Arguments:
  375. int nCol : Column number
  376. Return Value:
  377. String
  378. --*/
  379. {
  380. ASSERT(_fStaticsLoaded);
  381. TCHAR sz[255];
  382. switch(nCol)
  383. {
  384. case COL_DESCRIPTION:
  385. return QueryDisplayName();
  386. case COL_STATE:
  387. switch(m_dwState)
  388. {
  389. case MD_SERVER_STATE_STARTED:
  390. return _bstrStarted;
  391. case MD_SERVER_STATE_PAUSED:
  392. return _bstrPaused;
  393. case MD_SERVER_STATE_STOPPED:
  394. return _bstrStopped;
  395. case MD_SERVER_STATE_STARTING:
  396. case MD_SERVER_STATE_PAUSING:
  397. case MD_SERVER_STATE_CONTINUING:
  398. case MD_SERVER_STATE_STOPPING:
  399. return _bstrPending;
  400. }
  401. return OLESTR("");
  402. case COL_DOMAIN_NAME:
  403. return m_bstrHostHeaderName;
  404. case COL_IP_ADDRESS:
  405. {
  406. CIPAddress ia(m_dwIPAddress);
  407. if (ia.IsZeroValue())
  408. {
  409. _bstrResult = _bstrAllUnassigned;
  410. }
  411. else
  412. {
  413. _bstrResult = ia;
  414. }
  415. }
  416. return _bstrResult;
  417. case COL_TCP_PORT:
  418. _bstrResult = ::_itot(m_sPort, sz, 10);
  419. return _bstrResult;
  420. case COL_STATUS:
  421. {
  422. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  423. CError err(m_dwWin32Error);
  424. if (err.Succeeded())
  425. {
  426. return OLESTR("");
  427. }
  428. _bstrResult = err;
  429. }
  430. return _bstrResult;
  431. }
  432. ASSERT_MSG("Bad column number");
  433. return OLESTR("");
  434. }
  435. /* virtual */
  436. int
  437. CIISSite::CompareResultPaneItem(CIISObject * pObject, int nCol)
  438. /*++
  439. Routine Description:
  440. Compare two CIISObjects on sort item criteria
  441. Arguments:
  442. CIISObject * pObject : Object to compare against
  443. int nCol : Column number to sort on
  444. Return Value:
  445. 0 if the two objects are identical
  446. <0 if this object is less than pObject
  447. >0 if this object is greater than pObject
  448. --*/
  449. {
  450. ASSERT_READ_PTR(pObject);
  451. if (nCol == 0)
  452. {
  453. return CompareScopeItem(pObject);
  454. }
  455. //
  456. // First criteria is object type
  457. //
  458. int n1 = QuerySortWeight();
  459. int n2 = pObject->QuerySortWeight();
  460. if (n1 != n2)
  461. {
  462. return n1 - n2;
  463. }
  464. //
  465. // Both are CIISSite objects
  466. //
  467. CIISSite * pSite = (CIISSite *)pObject;
  468. switch(nCol)
  469. {
  470. //
  471. // Special case columns
  472. //
  473. case COL_IP_ADDRESS:
  474. {
  475. CIPAddress ia1(m_dwIPAddress);
  476. CIPAddress ia2(pSite->QueryIPAddress());
  477. return ia1.CompareItem(ia2);
  478. }
  479. case COL_TCP_PORT:
  480. n1 = QueryPort();
  481. n2 = pSite->QueryPort();
  482. return n1 - n2;
  483. case COL_STATUS:
  484. {
  485. DWORD dw1 = QueryWin32Error();
  486. DWORD dw2 = pSite->QueryWin32Error();
  487. return dw1 - dw2;
  488. }
  489. case COL_DESCRIPTION:
  490. case COL_STATE:
  491. case COL_DOMAIN_NAME:
  492. default:
  493. //
  494. // Lexical sort
  495. //
  496. return ::lstrcmpi(
  497. GetResultPaneColInfo(nCol),
  498. pObject->GetResultPaneColInfo(nCol)
  499. );
  500. }
  501. }
  502. /* virtual */
  503. HRESULT
  504. CIISSite::BuildURL(CComBSTR & bstrURL) const
  505. /*++
  506. Routine Description:
  507. Recursively build up the URL from the current node
  508. and its parents. For a site node, add the machine name.
  509. Arguments:
  510. CComBSTR & bstrURL : Returns URL
  511. Return Value:
  512. HRESULT
  513. --*/
  514. {
  515. HRESULT hr = S_OK;
  516. //
  517. // Prepend parent portion (protocol in this case)
  518. //
  519. CIISMBNode * pNode = GetParentNode();
  520. if (pNode)
  521. {
  522. hr = pNode->BuildURL(bstrURL);
  523. }
  524. if (SUCCEEDED(hr))
  525. {
  526. CString strOwner;
  527. ///////////////////////////////////////////////////////////////////////////
  528. //
  529. // Try to build an URL. Use in order of priority:
  530. //
  531. // Domain name:port/root
  532. // ip address:port/root
  533. // computer name:port/root
  534. //
  535. if (m_bstrHostHeaderName.Length())
  536. {
  537. strOwner = m_bstrHostHeaderName;
  538. }
  539. else if (m_dwIPAddress != 0L)
  540. {
  541. CIPAddress ia(m_dwIPAddress);
  542. ia.QueryIPAddress(strOwner);
  543. }
  544. else
  545. {
  546. if (IsLocal())
  547. {
  548. //
  549. // Security reasons restrict this to "localhost" oftentimes
  550. //
  551. strOwner = _bstrLocalHost;
  552. }
  553. else
  554. {
  555. LPOLESTR lpOwner = QueryMachineName();
  556. strOwner = PURE_COMPUTER_NAME(lpOwner);
  557. }
  558. }
  559. TCHAR szPort[6]; // 65536 max.
  560. _itot(m_sPort, szPort, 10);
  561. strOwner += _T(":");
  562. strOwner += szPort;
  563. bstrURL.Append(strOwner);
  564. }
  565. return hr;
  566. }
  567. /*virtual*/
  568. HRESULT
  569. CIISSite::AddMenuItems(
  570. LPCONTEXTMENUCALLBACK piCallback,
  571. long * pInsertionAllowed,
  572. DATA_OBJECT_TYPES type
  573. )
  574. {
  575. ASSERT_READ_PTR(piCallback);
  576. //
  577. // Add base menu items
  578. //
  579. HRESULT hr = CIISObject::AddMenuItems(
  580. piCallback,
  581. pInsertionAllowed,
  582. type
  583. );
  584. if (SUCCEEDED(hr))
  585. {
  586. ASSERT(pInsertionAllowed != NULL);
  587. if ((*pInsertionAllowed & CCM_INSERTIONALLOWED_NEW) != 0)
  588. {
  589. AddMenuSeparator(piCallback);
  590. if (IsFtpSite())
  591. {
  592. if (GetOwner()->CanAddInstance() && !GetOwner()->Has10ConnectionsLimit())
  593. {
  594. AddMenuItemByCommand(piCallback, IDM_NEW_FTP_SITE);
  595. }
  596. AddMenuItemByCommand(piCallback, IDM_NEW_FTP_VDIR);
  597. }
  598. else if (IsWebSite())
  599. {
  600. if (GetOwner()->CanAddInstance() && !GetOwner()->Has10ConnectionsLimit())
  601. {
  602. AddMenuItemByCommand(piCallback, IDM_NEW_WEB_SITE);
  603. }
  604. AddMenuItemByCommand(piCallback, IDM_NEW_WEB_VDIR);
  605. }
  606. }
  607. if (!m_fFrontPageWeb && (*pInsertionAllowed & CCM_INSERTIONALLOWED_TASK) != 0)
  608. {
  609. AddMenuSeparator(piCallback);
  610. AddMenuItemByCommand(piCallback, IDM_TASK_SECURITY_WIZARD);
  611. }
  612. }
  613. return hr;
  614. }
  615. HRESULT
  616. CIISSite::InsertNewInstance(DWORD inst)
  617. {
  618. return m_pService->InsertNewInstance(inst);
  619. }
  620. HRESULT
  621. CIISSite::InsertNewAlias(CString alias)
  622. {
  623. CError err;
  624. // Now we should insert and select this new site
  625. CIISDirectory * pAlias = new CIISDirectory(m_pOwner, m_pService, alias);
  626. if (pAlias != NULL)
  627. {
  628. // If item is not expanded we will get error and no effect
  629. if (!IsExpanded())
  630. {
  631. SelectScopeItem();
  632. IConsoleNameSpace2 * pConsole
  633. = (IConsoleNameSpace2 *)GetConsoleNameSpace();
  634. pConsole->Expand(QueryScopeItem());
  635. }
  636. err = pAlias->AddToScopePaneSorted(QueryScopeItem(), FALSE);
  637. if (err.Succeeded())
  638. {
  639. VERIFY(SUCCEEDED(pAlias->SelectScopeItem()));
  640. }
  641. }
  642. else
  643. {
  644. err = ERROR_NOT_ENOUGH_MEMORY;
  645. }
  646. return err;
  647. }
  648. /* virtual */
  649. HRESULT
  650. CIISSite::Command(
  651. long lCommandID,
  652. CSnapInObjectRootBase * pObj,
  653. DATA_OBJECT_TYPES type
  654. )
  655. /*++
  656. Routine Description:
  657. Handle command from context menu.
  658. Arguments:
  659. long lCommandID : Command ID
  660. CSnapInObjectRootBase * pObj : Base object
  661. DATA_OBJECT_TYPES type : Data object type
  662. Return Value:
  663. HRESULT
  664. --*/
  665. {
  666. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  667. HRESULT hr = S_OK;
  668. DWORD dwCommand = 0;
  669. DWORD inst;
  670. CString alias;
  671. switch (lCommandID)
  672. {
  673. case IDM_STOP:
  674. dwCommand = MD_SERVER_COMMAND_STOP;
  675. break;
  676. case IDM_START:
  677. dwCommand = m_dwState == MD_SERVER_STATE_PAUSED ?
  678. MD_SERVER_COMMAND_CONTINUE : MD_SERVER_COMMAND_START;
  679. break;
  680. case IDM_PAUSE:
  681. dwCommand = m_dwState == MD_SERVER_STATE_PAUSED ?
  682. MD_SERVER_COMMAND_CONTINUE : MD_SERVER_COMMAND_PAUSE;
  683. break;
  684. case IDM_NEW_FTP_SITE:
  685. if (SUCCEEDED(hr = AddFTPSite(pObj, type, &inst)))
  686. {
  687. hr = InsertNewInstance(inst);
  688. }
  689. break;
  690. case IDM_NEW_FTP_VDIR:
  691. if (SUCCEEDED(hr = CIISMBNode::AddFTPVDir(pObj, type, alias)))
  692. {
  693. hr = InsertNewAlias(alias);
  694. }
  695. break;
  696. case IDM_NEW_WEB_SITE:
  697. if (SUCCEEDED(hr = CIISMBNode::AddWebSite(pObj, type, &inst)))
  698. {
  699. hr = InsertNewInstance(inst);
  700. }
  701. break;
  702. case IDM_NEW_WEB_VDIR:
  703. if (SUCCEEDED(hr = CIISMBNode::AddWebVDir(pObj, type, alias)))
  704. {
  705. hr = InsertNewAlias(alias);
  706. }
  707. break;
  708. //
  709. // Pass on to base class
  710. //
  711. default:
  712. hr = CIISMBNode::Command(lCommandID, pObj, type);
  713. }
  714. if (dwCommand)
  715. {
  716. hr = ChangeState(dwCommand);
  717. }
  718. return hr;
  719. }
  720. /* virtual */
  721. HRESULT
  722. CIISSite::CreatePropertyPages(
  723. IN LPPROPERTYSHEETCALLBACK lpProvider,
  724. IN LONG_PTR handle,
  725. IN IUnknown * pUnk,
  726. IN DATA_OBJECT_TYPES type
  727. )
  728. /*++
  729. Routine Description:
  730. Create the property pages for the given object
  731. Arguments:
  732. LPPROPERTYSHEETCALLBACK lpProvider : Provider
  733. LONG_PTR handle : Handle.
  734. IUnknown * pUnk,
  735. DATA_OBJECT_TYPES type
  736. Return Value:
  737. HRESULT
  738. --*/
  739. {
  740. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  741. CComBSTR bstrPath;
  742. //
  743. // CODEWORK: What to do with m_err? This might be
  744. // a bad machine object in the first place. Aborting
  745. // when the machine object has an error code isn't
  746. // such a bad solution here.
  747. //
  748. /*
  749. if (m_err.Failed())
  750. {
  751. m_err.MessageBox();
  752. return m_err;
  753. }
  754. */
  755. CError err(BuildMetaPath(bstrPath));
  756. if (err.Succeeded())
  757. {
  758. err = ShowPropertiesDlg(
  759. lpProvider,
  760. QueryAuthInfo(),
  761. bstrPath,
  762. GetMainWindow(),
  763. (LPARAM)this,
  764. handle
  765. );
  766. }
  767. err.MessageBoxOnFailure();
  768. return err;
  769. }
  770. HRESULT
  771. CIISSite::ChangeState(DWORD dwCommand)
  772. /*++
  773. Routine Description:
  774. Change the state of this instance (started/stopped/paused)
  775. Arguments:
  776. DWORD dwCommand : MD_SERVER_COMMAND_START, etc.
  777. Return Value:
  778. HRESULT
  779. --*/
  780. {
  781. CError err;
  782. CComBSTR bstrPath;
  783. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  784. do
  785. {
  786. CWaitCursor wait;
  787. err = BuildMetaPath(bstrPath);
  788. // We need instance key here
  789. CString path_inst;
  790. CMetabasePath::GetInstancePath(bstrPath, path_inst);
  791. BREAK_ON_ERR_FAILURE(err)
  792. CInstanceProps ip(QueryAuthInfo(), path_inst);
  793. err = ip.LoadData();
  794. BREAK_ON_ERR_FAILURE(err)
  795. err = ip.ChangeState(dwCommand);
  796. BREAK_ON_ERR_FAILURE(err)
  797. err = RefreshData();
  798. if (err.Succeeded())
  799. {
  800. err = RefreshDisplay();
  801. }
  802. }
  803. while(FALSE);
  804. err.MessageBoxOnFailure();
  805. return err;
  806. }
  807. /* virtual */
  808. HRESULT
  809. CIISSite::EnumerateScopePane(HSCOPEITEM hParent)
  810. /*++
  811. Routine Description:
  812. Enumerate scope child items.
  813. Arguments:
  814. HSCOPEITEM hParent : Parent console handle
  815. Return Value:
  816. HRESULT
  817. --*/
  818. {
  819. CError err = EnumerateVDirs(hParent, m_pService);
  820. if (err.Succeeded() && !IsFtpSite() && m_strRedirectPath.IsEmpty())
  821. {
  822. if (m_dwWin32Error == ERROR_SUCCESS)
  823. {
  824. err = EnumerateWebDirs(hParent, m_pService);
  825. }
  826. }
  827. if (err.Failed())
  828. {
  829. m_dwWin32Error = err.Win32Error();
  830. RefreshDisplay();
  831. }
  832. return err;
  833. }
  834. /*virtual*/
  835. HRESULT
  836. CIISSite::EnumerateResultPane(BOOL fExp, IHeaderCtrl * pHdr, IResultData * pResData)
  837. {
  838. CError err = CIISObject::EnumerateResultPane(fExp, pHdr, pResData);
  839. if ( err.Succeeded()
  840. && QueryWin32Error() == ERROR_SUCCESS
  841. && !IsFtpSite()
  842. && m_strRedirectPath.IsEmpty()
  843. )
  844. {
  845. err = CIISMBNode::EnumerateResultPane_(fExp, pHdr, pResData, m_pService);
  846. if (err.Failed())
  847. {
  848. m_dwWin32Error = err.Win32Error();
  849. }
  850. }
  851. return err;
  852. }
  853. /* virtual */
  854. HRESULT
  855. CIISSite::BuildMetaPath(CComBSTR & bstrPath) const
  856. /*++
  857. Routine Description:
  858. Recursively build up the metabase path from the current node
  859. and its parents
  860. Arguments:
  861. CComBSTR & bstrPath : Returns metabase path
  862. Return Value:
  863. HRESULT
  864. Notes:
  865. This will return the home directory path, e.g. "lm/w3svc/2/root",
  866. not the path of the instance.
  867. --*/
  868. {
  869. //
  870. // Build instance path
  871. //
  872. HRESULT hr = CIISMBNode::BuildMetaPath(bstrPath);
  873. if (SUCCEEDED(hr))
  874. {
  875. //
  876. // Add root directory path
  877. //
  878. bstrPath.Append(_cszSeparator);
  879. bstrPath.Append(g_cszRoot);
  880. }
  881. return hr;
  882. }
  883. // CODEWORK: make it work from CIISMBNode::DeleteNode
  884. HRESULT
  885. CIISSite::DeleteNode(IResultData * pResult)
  886. {
  887. CError err;
  888. if (!NoYesMessageBox(IDS_CONFIRM_DELETE))
  889. return err;
  890. do
  891. {
  892. CComBSTR path;
  893. CMetaInterface * pInterface = QueryInterface();
  894. ASSERT(pInterface != NULL);
  895. err = CIISMBNode::BuildMetaPath(path);
  896. if (err.Failed())
  897. break;
  898. CMetaKey mk(pInterface, METADATA_MASTER_ROOT_HANDLE, METADATA_PERMISSION_WRITE);
  899. if (!mk.Succeeded())
  900. break;
  901. err = mk.DeleteKey(path);
  902. if (err.Failed())
  903. break;
  904. err = RemoveScopeItem();
  905. } while (FALSE);
  906. if (err.Failed())
  907. {
  908. DisplayError(err);
  909. }
  910. return err;
  911. }
  912. //
  913. // We are not supporting empty comments on sites. Even if it is OK for
  914. // metabase, it will bring more problems in UI. Empty name will be displayed
  915. // as [Site #N] in UI, and when user will try to rename it again, it could be
  916. // stored in metabase in this format.
  917. //
  918. HRESULT
  919. CIISSite::RenameItem(LPOLESTR new_name)
  920. {
  921. CComBSTR path;
  922. CError err;
  923. if (new_name != NULL && lstrlen(new_name) > 0)
  924. {
  925. err = BuildMetaPath(path);
  926. if (err.Succeeded())
  927. {
  928. // We need instance key here
  929. CString path_inst;
  930. CMetabasePath::GetInstancePath(path, path_inst);
  931. CMetaKey mk(QueryInterface(), path_inst, METADATA_PERMISSION_WRITE);
  932. err = mk.QueryResult();
  933. if (err.Succeeded())
  934. {
  935. err = mk.SetValue(MD_SERVER_COMMENT, CString(new_name));
  936. if (err.Succeeded())
  937. {
  938. m_strDisplayName = new_name;
  939. }
  940. }
  941. }
  942. }
  943. return err;
  944. }