Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1635 lines
38 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. #include "impexp.h"
  23. #include "tracker.h"
  24. #ifdef _DEBUG
  25. #undef THIS_FILE
  26. static char BASED_CODE THIS_FILE[] = __FILE__;
  27. #endif
  28. #define new DEBUG_NEW
  29. extern CPropertySheetTracker g_OpenPropertySheetTracker;
  30. //
  31. // CIISSite implementation
  32. //
  33. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  34. //
  35. // Site Result View definition
  36. //
  37. /* static */ int
  38. CIISSite::_rgnLabels[COL_TOTAL] =
  39. {
  40. IDS_RESULT_SERVICE_DESCRIPTION,
  41. IDS_RESULT_SERVICE_ID,
  42. IDS_RESULT_SERVICE_STATE,
  43. IDS_RESULT_SERVICE_DOMAIN_NAME,
  44. IDS_RESULT_SERVICE_IP_ADDRESS,
  45. IDS_RESULT_SERVICE_TCP_PORT,
  46. IDS_RESULT_SERVICE_SSL_PORT,
  47. IDS_RESULT_STATUS,
  48. };
  49. int
  50. CIISSite::_rgnLabels2[COL_TOTAL2] =
  51. {
  52. IDS_RESULT_SERVICE_DESCRIPTION,
  53. IDS_RESULT_SERVICE_ID,
  54. IDS_RESULT_SERVICE_STATE,
  55. // 0, // blank
  56. IDS_RESULT_SERVICE_IP_ADDRESS,
  57. IDS_RESULT_SERVICE_TCP_PORT,
  58. // 0, // blank
  59. IDS_RESULT_STATUS,
  60. };
  61. /* static */ int
  62. CIISSite::_rgnWidths[COL_TOTAL] =
  63. {
  64. 180,
  65. 90,
  66. 70,
  67. 120,
  68. 105,
  69. 40,
  70. 60,
  71. 200,
  72. };
  73. /* static */ int
  74. CIISSite::_rgnWidths2[COL_TOTAL2] =
  75. {
  76. 180,
  77. 90,
  78. 70,
  79. // 0, // blank
  80. 105,
  81. 40,
  82. // 0, // blank
  83. 200,
  84. };
  85. /* static */ CComBSTR CIISSite::_bstrStarted;
  86. /* static */ CComBSTR CIISSite::_bstrStopped;
  87. /* static */ CComBSTR CIISSite::_bstrPaused;
  88. /* static */ CComBSTR CIISSite::_bstrUnknown;
  89. /* static */ CComBSTR CIISSite::_bstrPending;
  90. /* static */ CComBSTR CIISSite::_bstrAllUnassigned;
  91. /* static */ BOOL CIISSite::_fStaticsLoaded = FALSE;
  92. /* static */
  93. void
  94. CIISSite::LoadStatics()
  95. {
  96. if (!_fStaticsLoaded)
  97. {
  98. _fStaticsLoaded =
  99. _bstrStarted.LoadString(IDS_STARTED) &&
  100. _bstrStopped.LoadString(IDS_STOPPED) &&
  101. _bstrPaused.LoadString(IDS_PAUSED) &&
  102. _bstrUnknown.LoadString(IDS_UNKNOWN) &&
  103. _bstrPending.LoadString(IDS_PENDING) &&
  104. _bstrAllUnassigned.LoadString(IDS_IP_ALL_UNASSIGNED);
  105. }
  106. }
  107. /* static */
  108. void
  109. CIISSite::InitializeHeaders(LPHEADERCTRL lpHeader)
  110. /*++
  111. Routine Description:
  112. Initialize the result headers
  113. Arguments:
  114. LPHEADERCTRL lpHeader : Header control
  115. Return Value:
  116. None
  117. --*/
  118. {
  119. CIISObject::BuildResultView(lpHeader, COL_TOTAL, _rgnLabels, _rgnWidths);
  120. // CIISDirectory::InitializeHeaders(lpHeader);
  121. LoadStatics();
  122. }
  123. void
  124. CIISSite::InitializeHeaders2(LPHEADERCTRL lpHeader)
  125. /*++
  126. Routine Description:
  127. Initialize the result headers
  128. Arguments:
  129. LPHEADERCTRL lpHeader : Header control
  130. Return Value:
  131. None
  132. --*/
  133. {
  134. CIISObject::BuildResultView(lpHeader, COL_TOTAL2, _rgnLabels2, _rgnWidths2);
  135. // CIISDirectory::InitializeHeaders(lpHeader);
  136. LoadStatics();
  137. }
  138. /* virtual */
  139. void
  140. CIISSite::InitializeChildHeaders(
  141. IN LPHEADERCTRL lpHeader
  142. )
  143. /*++
  144. Routine Description:
  145. Build result view for immediate descendant type
  146. Arguments:
  147. LPHEADERCTRL lpHeader : Header control
  148. Return Value:
  149. None
  150. --*/
  151. {
  152. CIISDirectory::InitializeHeaders(lpHeader);
  153. }
  154. CIISSite::CIISSite(
  155. IN CIISMachine * pOwner,
  156. IN CIISService * pService,
  157. IN LPCTSTR szNodeName
  158. )
  159. /*++
  160. Routine Description:
  161. Constructor. Determine if the given service is administrable,
  162. and resolve the details
  163. Arguments:
  164. CIISMachine * pOwner : Owner machine object
  165. CIISService * pService : Service type
  166. LPCTSTR szNodeName : Node name (numeric)
  167. Return Value:
  168. N/A
  169. Notes:
  170. This constructor does not immediately resolve the display name of the
  171. site. It will only resolve its display information when asked
  172. --*/
  173. : CIISMBNode(pOwner, szNodeName),
  174. m_pService(pService),
  175. m_fResolved(FALSE),
  176. m_strDisplayName(),
  177. //
  178. // Data members -- plonk in some defaults
  179. //
  180. m_dwState(MD_SERVER_STATE_INVALID),
  181. m_fWolfPackEnabled(FALSE),
  182. m_fFrontPageWeb(FALSE),
  183. m_sPort(80),
  184. m_sSSLPort(443),
  185. m_dwID(::_ttol(szNodeName)),
  186. m_dwIPAddress(0L),
  187. m_dwWin32Error(ERROR_SUCCESS),
  188. m_dwEnumError(ERROR_SUCCESS),
  189. m_bstrHostHeaderName(),
  190. m_bstrComment(),
  191. m_fUsingActiveDir(FALSE)
  192. {
  193. ASSERT_PTR(m_pService);
  194. m_pService->AddRef();
  195. }
  196. CIISSite::CIISSite(
  197. IN CIISMachine * pOwner,
  198. IN CIISService * pService,
  199. IN LPCTSTR szNodeName,
  200. IN DWORD dwState,
  201. IN BOOL fClusterEnabled,
  202. IN USHORT sPort,
  203. IN DWORD dwID,
  204. IN DWORD dwIPAddress,
  205. IN DWORD dwWin32Error,
  206. IN LPOLESTR szHostHeaderName,
  207. IN LPOLESTR szComment
  208. )
  209. /*++
  210. Routine Description:
  211. Construct with full information
  212. Arguments:
  213. CIISMachine * pOwner : Owner machine object
  214. CIISService * pService : Service type
  215. LPCTSTR szNodeName : Node name (numeric)
  216. plus datamembers
  217. Return Value:
  218. N/A
  219. --*/
  220. : CIISMBNode(pOwner, szNodeName),
  221. m_pService(pService),
  222. m_fResolved(TRUE),
  223. m_strDisplayName(),
  224. //
  225. // Data Members
  226. //
  227. m_dwState(dwState),
  228. m_fWolfPackEnabled(fClusterEnabled),
  229. m_sPort(sPort),
  230. m_dwID(dwID),
  231. m_dwIPAddress(dwIPAddress),
  232. m_dwWin32Error(dwWin32Error),
  233. m_bstrHostHeaderName(szHostHeaderName),
  234. m_bstrComment(szComment),
  235. m_fUsingActiveDir(FALSE)
  236. {
  237. ASSERT_PTR(m_pService);
  238. m_pService->AddRef();
  239. }
  240. CIISSite::~CIISSite()
  241. {
  242. m_pService->Release();
  243. }
  244. /* virtual */
  245. HRESULT
  246. CIISSite::RefreshData()
  247. /*++
  248. Routine Description:
  249. Refresh relevant configuration data required for display.
  250. Arguments:
  251. None
  252. Return Value:
  253. HRESULT
  254. --*/
  255. {
  256. CError err;
  257. CWaitCursor wait;
  258. CComBSTR bstrPath;
  259. CMetaKey * pKey = NULL;
  260. do
  261. {
  262. err = BuildMetaPath(bstrPath);
  263. BREAK_ON_ERR_FAILURE(err);
  264. // We need instance key here
  265. CString path_inst;
  266. CMetabasePath::GetInstancePath(bstrPath, path_inst);
  267. BOOL fContinue = TRUE;
  268. while (fContinue)
  269. {
  270. fContinue = FALSE;
  271. if (NULL == (pKey = new CMetaKey(QueryInterface(), path_inst)))
  272. {
  273. TRACEEOLID("RefreshData: OOM");
  274. err = ERROR_NOT_ENOUGH_MEMORY;
  275. break;
  276. }
  277. err = pKey->QueryResult();
  278. if (IsLostInterface(err))
  279. {
  280. SAFE_DELETE(pKey);
  281. fContinue = OnLostInterface(err);
  282. }
  283. }
  284. BREAK_ON_ERR_FAILURE(err);
  285. CInstanceProps inst(pKey, _T(""), m_dwID);
  286. err = inst.LoadData();
  287. BREAK_ON_ERR_FAILURE(err);
  288. m_dwState = inst.m_dwState;
  289. //
  290. // Don't be confused -- cluster enabled refers
  291. // to wolfpack and has nothing to do with app server
  292. //
  293. m_fWolfPackEnabled = inst.IsClusterEnabled();
  294. m_sPort = (SHORT)inst.m_nTCPPort;
  295. m_dwID = inst.QueryInstance();
  296. m_dwIPAddress = inst.m_iaIpAddress;
  297. m_dwWin32Error = inst.m_dwWin32Error;
  298. m_bstrHostHeaderName = inst.m_strDomainName;
  299. m_bstrComment = inst.m_strComment;
  300. m_strDisplayName.Empty();
  301. {
  302. CStringListEx list;
  303. pKey->QueryValue(MD_SECURE_BINDINGS, list);
  304. UINT port = 0;
  305. CInstanceProps::FindMatchingSecurePort(list, inst.m_iaIpAddress, port);
  306. m_sSSLPort = (USHORT)port;
  307. }
  308. // Check if it is Frontpage controlled site
  309. pKey->QueryValue(MD_FRONTPAGE_WEB, m_fFrontPageWeb);
  310. // check if it's using ActiveDirectory...
  311. if (IsFtpSite())
  312. {
  313. INT iFtpUserIsolation = 0;
  314. m_fUsingActiveDir = FALSE;
  315. pKey->QueryValue(MD_USER_ISOLATION, iFtpUserIsolation);
  316. if (2 == iFtpUserIsolation)
  317. {
  318. m_fUsingActiveDir = TRUE;
  319. }
  320. }
  321. CChildNodeProps child(pKey, SZ_MBN_ROOT);
  322. err = child.LoadData();
  323. BREAK_ON_ERR_FAILURE(err);
  324. m_strRedirectPath = child.GetRedirectedPath();
  325. }
  326. while(FALSE);
  327. SAFE_DELETE(pKey);
  328. m_dwEnumError = err.Win32Error();
  329. return err;
  330. }
  331. /* virtual */
  332. int
  333. CIISSite::QueryImage() const
  334. /*++
  335. Routine Description:
  336. Return bitmap index for the site
  337. Arguments:
  338. None
  339. Return Value:
  340. Bitmap index
  341. --*/
  342. {
  343. ASSERT_PTR(m_pService);
  344. if (!m_fResolved)
  345. {
  346. TRACEEOLID("Resolving name for site #" << QueryNodeName());
  347. if (m_hScopeItem == NULL)
  348. {
  349. //
  350. // BUGBUG:
  351. //
  352. // This is probably related to MMC bug #324519
  353. // where we're asked for the display info immediately
  354. // after adding the item to the console view. This
  355. // appears to fail only on refresh because the scope
  356. // item handle is missing, and we can't build a metabase
  357. // path yet.
  358. //
  359. TRACEEOLID("BUGBUG: Prematurely asked for display information");
  360. //ASSERT(FALSE);
  361. return iError;
  362. }
  363. CIISSite * that = (CIISSite *)this;
  364. CError err = that->RefreshData();
  365. that->m_fResolved = err.Succeeded();
  366. }
  367. if (!m_fResolved || m_pService == NULL)
  368. {
  369. return iError;
  370. }
  371. if (FAILED(m_dwWin32Error))
  372. {
  373. return m_pService->QuerySiteImageErr();
  374. }
  375. else
  376. {
  377. if (m_dwState == MD_SERVER_STATE_STOPPED)
  378. {
  379. return m_pService->QuerySiteImageStopped();
  380. }
  381. else
  382. {
  383. return m_pService->QuerySiteImage();
  384. }
  385. }
  386. }
  387. /* virtual */
  388. LPOLESTR
  389. CIISSite::QueryDisplayName()
  390. /*++
  391. Routine Description:
  392. Return primary display name of this site.
  393. Arguments:
  394. None
  395. Return Value:
  396. The display name
  397. --*/
  398. {
  399. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  400. if (!m_fResolved)
  401. {
  402. TRACEEOLID("Resolving name for site #" << QueryNodeName());
  403. if (m_hScopeItem == NULL)
  404. {
  405. //
  406. // BUGBUG:
  407. //
  408. // This is probably related to MMC bug #324519
  409. // where we're asked for the display info immediately
  410. // after adding the item to the console view. This
  411. // appears to fail only on refresh because the scope
  412. // item handle is missing, and we can't build a metabase
  413. // path yet.
  414. //
  415. TRACEEOLID("BUGBUG: Prematurely asked for display information");
  416. //ASSERT(FALSE);
  417. return OLESTR("");
  418. }
  419. CError err = RefreshData();
  420. m_fResolved = err.Succeeded();
  421. }
  422. if (m_strDisplayName.IsEmpty())
  423. {
  424. CIPAddress ia(m_dwIPAddress);
  425. CInstanceProps::GetDisplayText(
  426. m_strDisplayName,
  427. m_bstrComment,
  428. m_bstrHostHeaderName,
  429. ia,
  430. m_sPort,
  431. m_dwID
  432. );
  433. }
  434. CString buf = m_strDisplayName;
  435. if (m_dwState == MD_SERVER_STATE_STOPPED)
  436. {
  437. buf.Format(IDS_STOPPED_SITE_FMT, m_strDisplayName);
  438. }
  439. else if (m_dwState == MD_SERVER_STATE_PAUSED)
  440. {
  441. buf.Format(IDS_PAUSED_SITE_FMT, m_strDisplayName);
  442. }
  443. m_bstrDisplayNameStatus = buf;
  444. // return (LPTSTR)(LPCTSTR)m_strDisplayName;
  445. return m_bstrDisplayNameStatus;
  446. }
  447. /* virtual */
  448. LPOLESTR
  449. CIISSite::GetResultPaneColInfo(int nCol)
  450. /*++
  451. Routine Description:
  452. Return result pane string for the given column number
  453. Arguments:
  454. int nCol : Column number
  455. Return Value:
  456. String
  457. --*/
  458. {
  459. ASSERT(_fStaticsLoaded);
  460. TCHAR sz[255];
  461. if(IsFtpSite())
  462. {
  463. switch(nCol)
  464. {
  465. case COL_ID2:
  466. nCol = COL_ID;
  467. break;
  468. case COL_DESCRIPTION2:
  469. nCol = COL_DESCRIPTION;
  470. break;
  471. case COL_STATE2:
  472. nCol = COL_STATE;
  473. break;
  474. case COL_IP_ADDRESS2:
  475. nCol = COL_IP_ADDRESS;
  476. break;
  477. case COL_TCP_PORT2:
  478. nCol = COL_TCP_PORT;
  479. break;
  480. case COL_STATUS2:
  481. nCol = COL_STATUS;
  482. break;
  483. default:
  484. nCol = 0;
  485. break;
  486. }
  487. }
  488. switch(nCol)
  489. {
  490. case COL_ID:
  491. {
  492. CString buf;
  493. buf.Format(_T("%u"), m_dwID);
  494. _bstrResult = buf;
  495. return _bstrResult;
  496. }
  497. case COL_DESCRIPTION:
  498. return QueryDisplayName();
  499. case COL_STATE:
  500. switch(m_dwState)
  501. {
  502. case MD_SERVER_STATE_STARTED:
  503. return _bstrStarted;
  504. case MD_SERVER_STATE_PAUSED:
  505. return _bstrPaused;
  506. case MD_SERVER_STATE_STOPPED:
  507. return _bstrStopped;
  508. case MD_SERVER_STATE_STARTING:
  509. case MD_SERVER_STATE_PAUSING:
  510. case MD_SERVER_STATE_CONTINUING:
  511. case MD_SERVER_STATE_STOPPING:
  512. return _bstrPending;
  513. }
  514. return OLESTR("");
  515. case COL_DOMAIN_NAME:
  516. return m_bstrHostHeaderName;
  517. case COL_IP_ADDRESS:
  518. {
  519. CIPAddress ia(m_dwIPAddress);
  520. if (ia.IsZeroValue())
  521. {
  522. _bstrResult = _bstrAllUnassigned;
  523. }
  524. else
  525. {
  526. _bstrResult = ia;
  527. }
  528. }
  529. return _bstrResult;
  530. case COL_SSL_PORT:
  531. if (m_sSSLPort != 0)
  532. {
  533. _bstrResult = ::_itot(m_sSSLPort, sz, 10);
  534. return _bstrResult;
  535. }
  536. else
  537. return OLESTR("");
  538. case COL_TCP_PORT:
  539. _bstrResult = ::_itot(m_sPort, sz, 10);
  540. return _bstrResult;
  541. case COL_STATUS:
  542. {
  543. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  544. CError err(m_dwWin32Error);
  545. if (err.Succeeded())
  546. {
  547. return OLESTR("");
  548. }
  549. SetErrorOverrides(err, TRUE);
  550. _bstrResult = err;
  551. }
  552. return _bstrResult;
  553. }
  554. ASSERT_MSG("Bad column number");
  555. return OLESTR("");
  556. }
  557. /* virtual */
  558. int
  559. CIISSite::CompareResultPaneItem(CIISObject * pObject, int nCol)
  560. /*++
  561. Routine Description:
  562. Compare two CIISObjects on sort item criteria
  563. Arguments:
  564. CIISObject * pObject : Object to compare against
  565. int nCol : Column number to sort on
  566. Return Value:
  567. 0 if the two objects are identical
  568. <0 if this object is less than pObject
  569. >0 if this object is greater than pObject
  570. --*/
  571. {
  572. ASSERT_READ_PTR(pObject);
  573. if (nCol == 0)
  574. {
  575. return CompareScopeItem(pObject);
  576. }
  577. //
  578. // First criteria is object type
  579. //
  580. int n1 = QuerySortWeight();
  581. int n2 = pObject->QuerySortWeight();
  582. if (n1 != n2)
  583. {
  584. return n1 - n2;
  585. }
  586. //
  587. // Both are CIISSite objects
  588. //
  589. CIISSite * pSite = (CIISSite *)pObject;
  590. if(IsFtpSite())
  591. {
  592. switch(nCol)
  593. {
  594. case COL_ID2:
  595. nCol = COL_ID;
  596. break;
  597. case COL_DESCRIPTION2:
  598. nCol = COL_DESCRIPTION;
  599. break;
  600. case COL_STATE2:
  601. nCol = COL_STATE;
  602. break;
  603. case COL_IP_ADDRESS2:
  604. nCol = COL_IP_ADDRESS;
  605. break;
  606. case COL_TCP_PORT2:
  607. nCol = COL_TCP_PORT;
  608. break;
  609. case COL_STATUS2:
  610. nCol = COL_STATUS;
  611. break;
  612. default:
  613. nCol = 0;
  614. break;
  615. }
  616. }
  617. switch(nCol)
  618. {
  619. //
  620. // Special case columns
  621. //
  622. case COL_IP_ADDRESS:
  623. {
  624. CIPAddress ia1(m_dwIPAddress);
  625. CIPAddress ia2(pSite->QueryIPAddress());
  626. return ia1.CompareItem(ia2);
  627. }
  628. case COL_ID:
  629. n1 = GetInstance();
  630. n2 = pSite->GetInstance();
  631. return n1 - n2;
  632. case COL_TCP_PORT:
  633. n1 = QueryPort();
  634. n2 = pSite->QueryPort();
  635. return n1 - n2;
  636. case COL_SSL_PORT:
  637. n1 = QuerySSLPort();
  638. n2 = pSite->QuerySSLPort();
  639. return n1 - n2;
  640. case COL_STATUS:
  641. {
  642. DWORD dw1 = QueryWin32Error();
  643. DWORD dw2 = pSite->QueryWin32Error();
  644. return dw1 - dw2;
  645. }
  646. case COL_DESCRIPTION:
  647. case COL_STATE:
  648. case COL_DOMAIN_NAME:
  649. default:
  650. //
  651. // Lexical sort
  652. //
  653. return ::lstrcmpi(
  654. GetResultPaneColInfo(nCol),
  655. pObject->GetResultPaneColInfo(nCol)
  656. );
  657. }
  658. }
  659. /* virtual */
  660. HRESULT
  661. CIISSite::BuildURL(CComBSTR & bstrURL) const
  662. /*++
  663. Routine Description:
  664. Recursively build up the URL from the current node
  665. and its parents. For a site node, add the machine name.
  666. Arguments:
  667. CComBSTR & bstrURL : Returns URL
  668. Return Value:
  669. HRESULT
  670. --*/
  671. {
  672. HRESULT hr = S_OK;
  673. //
  674. // Prepend parent portion (protocol in this case)
  675. //
  676. CIISMBNode * pNode = GetParentNode();
  677. if (pNode)
  678. {
  679. hr = pNode->BuildURL(bstrURL);
  680. }
  681. if (SUCCEEDED(hr))
  682. {
  683. CString strOwner;
  684. ///////////////////////////////////////////////////////////////////////////
  685. //
  686. // Try to build an URL. Use in order of priority:
  687. //
  688. // Domain name:port/root
  689. // ip address:port/root
  690. // computer name:port/root
  691. //
  692. if (m_bstrHostHeaderName.Length())
  693. {
  694. strOwner = m_bstrHostHeaderName;
  695. }
  696. else if (m_dwIPAddress != 0L)
  697. {
  698. CIPAddress ia(m_dwIPAddress);
  699. ia.QueryIPAddress(strOwner);
  700. }
  701. else
  702. {
  703. if (IsLocal())
  704. {
  705. //
  706. // Security reasons restrict this to "localhost" oftentimes
  707. //
  708. strOwner = _bstrLocalHost;
  709. }
  710. else
  711. {
  712. LPOLESTR lpOwner = QueryMachineName();
  713. strOwner = PURE_COMPUTER_NAME(lpOwner);
  714. }
  715. }
  716. TCHAR szPort[6]; // 65536 max.
  717. _itot(m_sPort, szPort, 10);
  718. strOwner += _T(":");
  719. strOwner += szPort;
  720. bstrURL.Append(strOwner);
  721. }
  722. return hr;
  723. }
  724. /*virtual*/
  725. HRESULT
  726. CIISSite::AddMenuItems(
  727. LPCONTEXTMENUCALLBACK piCallback,
  728. long * pInsertionAllowed,
  729. DATA_OBJECT_TYPES type
  730. )
  731. {
  732. ASSERT_READ_PTR(piCallback);
  733. //
  734. // Add base menu items
  735. //
  736. HRESULT hr = CIISObject::AddMenuItems(
  737. piCallback,
  738. pInsertionAllowed,
  739. type
  740. );
  741. if (SUCCEEDED(hr))
  742. {
  743. ASSERT(pInsertionAllowed != NULL);
  744. if ((*pInsertionAllowed & CCM_INSERTIONALLOWED_NEW) != 0)
  745. {
  746. AddMenuSeparator(piCallback);
  747. if (IsFtpSite())
  748. {
  749. if (GetOwner()->CanAddInstance() && !GetOwner()->IsWorkstation())
  750. {
  751. AddMenuItemByCommand(piCallback, IDM_NEW_FTP_SITE);
  752. if (IsConfigImportExportable())
  753. {
  754. AddMenuItemByCommand(piCallback, IDM_NEW_FTP_SITE_FROM_FILE);
  755. }
  756. }
  757. AddMenuItemByCommand(piCallback, IDM_NEW_FTP_VDIR);
  758. if (IsConfigImportExportable())
  759. {
  760. AddMenuItemByCommand(piCallback, IDM_NEW_FTP_VDIR_FROM_FILE);
  761. }
  762. }
  763. else if (IsWebSite())
  764. {
  765. if (GetOwner()->CanAddInstance() && !GetOwner()->IsWorkstation())
  766. {
  767. AddMenuItemByCommand(piCallback, IDM_NEW_WEB_SITE);
  768. if (IsConfigImportExportable())
  769. {
  770. AddMenuItemByCommand(piCallback, IDM_NEW_WEB_SITE_FROM_FILE);
  771. }
  772. }
  773. AddMenuItemByCommand(piCallback, IDM_NEW_WEB_VDIR);
  774. if (IsConfigImportExportable())
  775. {
  776. AddMenuItemByCommand(piCallback, IDM_NEW_WEB_VDIR_FROM_FILE);
  777. }
  778. }
  779. }
  780. if (IsConfigImportExportable() && (*pInsertionAllowed & CCM_INSERTIONALLOWED_TASK) != 0)
  781. {
  782. AddMenuSeparator(piCallback);
  783. AddMenuItemByCommand(piCallback, IDM_TASK_EXPORT_CONFIG_WIZARD);
  784. }
  785. }
  786. return hr;
  787. }
  788. HRESULT
  789. CIISSite::InsertNewInstance(DWORD inst)
  790. {
  791. return m_pService->InsertNewInstance(inst);
  792. }
  793. HRESULT
  794. CIISSite::InsertNewAlias(CString alias)
  795. {
  796. CError err;
  797. if (!IsExpanded())
  798. {
  799. SelectScopeItem();
  800. IConsoleNameSpace2 * pConsoleNameSpace
  801. = (IConsoleNameSpace2 *)GetConsoleNameSpace();
  802. pConsoleNameSpace->Expand(QueryScopeItem());
  803. HSCOPEITEM hChildItem = NULL;
  804. LONG_PTR cookie;
  805. HRESULT hr = pConsoleNameSpace->GetChildItem(m_hScopeItem, &hChildItem, &cookie);
  806. while(SUCCEEDED(hr) && hChildItem)
  807. {
  808. CIISObject * pItem = (CIISObject *)cookie;
  809. ASSERT_PTR(pItem);
  810. if (0 == alias.Compare(pItem->QueryDisplayName()))
  811. {
  812. pItem->SelectScopeItem();
  813. break;
  814. }
  815. hr = pConsoleNameSpace->GetNextItem(hChildItem, &hChildItem, &cookie);
  816. }
  817. }
  818. else
  819. {
  820. // Now we should insert and select this new site
  821. CIISDirectory * pAlias = new CIISDirectory(m_pOwner, m_pService, alias);
  822. if (pAlias != NULL)
  823. {
  824. pAlias->AddRef();
  825. err = pAlias->AddToScopePaneSorted(QueryScopeItem(), FALSE);
  826. if (err.Succeeded())
  827. {
  828. VERIFY(SUCCEEDED(pAlias->SelectScopeItem()));
  829. }
  830. else
  831. {
  832. pAlias->Release();
  833. }
  834. }
  835. else
  836. {
  837. err = ERROR_NOT_ENOUGH_MEMORY;
  838. }
  839. }
  840. return err;
  841. }
  842. /* virtual */
  843. HRESULT
  844. CIISSite::Command(
  845. long lCommandID,
  846. CSnapInObjectRootBase * pObj,
  847. DATA_OBJECT_TYPES type
  848. )
  849. /*++
  850. Routine Description:
  851. Handle command from context menu.
  852. Arguments:
  853. long lCommandID : Command ID
  854. CSnapInObjectRootBase * pObj : Base object
  855. DATA_OBJECT_TYPES type : Data object type
  856. Return Value:
  857. HRESULT
  858. --*/
  859. {
  860. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  861. HRESULT hr = S_OK;
  862. DWORD dwCommand = 0;
  863. DWORD inst = 0;
  864. CError err;
  865. CString alias;
  866. CComBSTR bstrMetaPath;
  867. BOOL bNeedMetabase = FALSE;
  868. BOOL bHaveMetabase = FALSE;
  869. switch (lCommandID)
  870. {
  871. case IDM_STOP:
  872. case IDM_START:
  873. case IDM_PAUSE:
  874. case IDM_NEW_FTP_SITE:
  875. case IDM_NEW_FTP_VDIR:
  876. case IDM_NEW_WEB_SITE:
  877. case IDM_NEW_WEB_VDIR:
  878. bNeedMetabase = TRUE;
  879. break;
  880. default:
  881. bNeedMetabase = FALSE;
  882. }
  883. if (bNeedMetabase)
  884. {
  885. // WARNING:bstrMetaPath will be used by switch statement below
  886. VERIFY(SUCCEEDED(BuildMetaPath(bstrMetaPath)));
  887. err = CheckForMetabaseAccess(METADATA_PERMISSION_READ,this,TRUE,bstrMetaPath);
  888. if (!IsLostInterface(err))
  889. {
  890. // reset error if an other error other than No interface
  891. err.Reset();
  892. }
  893. if (err.Succeeded())
  894. {
  895. bHaveMetabase = TRUE;
  896. }
  897. }
  898. switch (lCommandID)
  899. {
  900. case IDM_STOP:
  901. if (bHaveMetabase)
  902. {
  903. dwCommand = MD_SERVER_COMMAND_STOP;
  904. }
  905. break;
  906. case IDM_START:
  907. if (bHaveMetabase)
  908. {
  909. dwCommand = m_dwState == MD_SERVER_STATE_PAUSED ?
  910. MD_SERVER_COMMAND_CONTINUE : MD_SERVER_COMMAND_START;
  911. }
  912. break;
  913. case IDM_PAUSE:
  914. if (bHaveMetabase)
  915. {
  916. dwCommand = m_dwState == MD_SERVER_STATE_PAUSED ?
  917. MD_SERVER_COMMAND_CONTINUE : MD_SERVER_COMMAND_PAUSE;
  918. }
  919. break;
  920. case IDM_NEW_FTP_SITE:
  921. if (bHaveMetabase)
  922. {
  923. hr = AddFTPSite(pObj, type, &inst);
  924. if (inst != 0)
  925. {
  926. hr = InsertNewInstance(inst);
  927. }
  928. }
  929. break;
  930. case IDM_NEW_FTP_VDIR:
  931. if (bHaveMetabase)
  932. {
  933. hr = CIISMBNode::AddFTPVDir(pObj, type, alias);
  934. if (!alias.IsEmpty())
  935. {
  936. hr = InsertNewAlias(alias);
  937. }
  938. }
  939. break;
  940. case IDM_NEW_WEB_SITE:
  941. if (bHaveMetabase)
  942. {
  943. hr = AddWebSite(pObj, type, &inst,
  944. m_pOwner->QueryMajorVersion(), m_pOwner->QueryMinorVersion());
  945. if (inst != 0)
  946. {
  947. hr = InsertNewInstance(inst);
  948. }
  949. }
  950. break;
  951. case IDM_NEW_WEB_VDIR:
  952. if (bHaveMetabase)
  953. {
  954. hr = CIISMBNode::AddWebVDir(pObj, type, alias,
  955. m_pOwner->QueryMajorVersion(), m_pOwner->QueryMinorVersion());
  956. if (!alias.IsEmpty())
  957. {
  958. hr = InsertNewAlias(alias);
  959. }
  960. }
  961. break;
  962. //
  963. // Pass on to base class
  964. //
  965. default:
  966. hr = CIISMBNode::Command(lCommandID, pObj, type);
  967. }
  968. if (dwCommand)
  969. {
  970. DWORD svc_mode, svc_state;
  971. CString name, buf;
  972. hr = m_pService->GetServiceState(svc_mode, svc_state, name);
  973. if (FAILED(hr))
  974. {
  975. return hr;
  976. }
  977. switch (svc_mode)
  978. {
  979. case SERVICE_DISABLED:
  980. AfxFormatString1(buf, IDS_NO_START_SERVICE_DISABLED, name);
  981. if (IDYES == AfxMessageBox(buf, MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON1))
  982. {
  983. hr = m_pService->EnableService();
  984. break;
  985. }
  986. return hr;
  987. case SERVICE_DEMAND_START:
  988. AfxFormatString1(buf, IDS_NO_START_SERVICE_MANUAL, name);
  989. if (svc_state != SERVICE_RUNNING)
  990. {
  991. if (IDYES == AfxMessageBox(buf, MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON1))
  992. {
  993. hr = m_pService->StartService();
  994. break;
  995. }
  996. return hr;
  997. }
  998. break;
  999. default:
  1000. break;
  1001. }
  1002. hr = ChangeState(dwCommand);
  1003. // make sure if a site has been started,
  1004. // that the service is shown as started too...
  1005. if (SUCCEEDED(m_pService->RefreshData()))
  1006. {
  1007. m_pService->RefreshDisplay(FALSE);
  1008. // Refresh our data if we refreshed the service level one...
  1009. RefreshDisplay();
  1010. }
  1011. }
  1012. return hr;
  1013. }
  1014. /* virtual */
  1015. HRESULT
  1016. CIISSite::CreatePropertyPages(
  1017. LPPROPERTYSHEETCALLBACK lpProvider,
  1018. LONG_PTR handle,
  1019. IUnknown * pUnk,
  1020. DATA_OBJECT_TYPES type
  1021. )
  1022. /*++
  1023. Routine Description:
  1024. Create the property pages for the given object
  1025. Arguments:
  1026. LPPROPERTYSHEETCALLBACK lpProvider : Provider
  1027. LONG_PTR handle : Handle.
  1028. IUnknown * pUnk,
  1029. DATA_OBJECT_TYPES type
  1030. Return Value:
  1031. HRESULT
  1032. --*/
  1033. {
  1034. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  1035. CError err;
  1036. if (S_FALSE == (HRESULT)(err = CIISMBNode::CreatePropertyPages(lpProvider, handle, pUnk, type)))
  1037. {
  1038. return S_OK;
  1039. }
  1040. if (ERROR_ALREADY_EXISTS == err.Win32Error())
  1041. {
  1042. return S_FALSE;
  1043. }
  1044. if (err.Succeeded())
  1045. {
  1046. CComBSTR bstrPath;
  1047. err = BuildMetaPath(bstrPath);
  1048. if (err.Succeeded())
  1049. {
  1050. err = CheckForMetabaseAccess(METADATA_PERMISSION_READ,this,TRUE,bstrPath);
  1051. if (err.Succeeded())
  1052. {
  1053. // cache handle for user in MMCPropertyChangeNotify
  1054. m_ppHandle = handle;
  1055. err = ShowPropertiesDlg(
  1056. lpProvider, QueryAuthInfo(), bstrPath,
  1057. GetMainWindow(GetConsole()), (LPARAM)this, (LPARAM)GetParentNode(), handle
  1058. );
  1059. }
  1060. }
  1061. }
  1062. err.MessageBoxOnFailure();
  1063. return err;
  1064. }
  1065. HRESULT
  1066. CIISSite::ChangeState(DWORD dwCommand)
  1067. /*++
  1068. Routine Description:
  1069. Change the state of this instance (started/stopped/paused)
  1070. Arguments:
  1071. DWORD dwCommand : MD_SERVER_COMMAND_START, etc.
  1072. Return Value:
  1073. HRESULT
  1074. --*/
  1075. {
  1076. CError err;
  1077. CComBSTR bstrPath;
  1078. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  1079. SetErrorOverrides(err);
  1080. do
  1081. {
  1082. CWaitCursor wait;
  1083. err = BuildMetaPath(bstrPath);
  1084. // We need instance key here
  1085. CString path_inst;
  1086. CMetabasePath::GetInstancePath(bstrPath, path_inst);
  1087. BREAK_ON_ERR_FAILURE(err)
  1088. CInstanceProps ip(QueryAuthInfo(), path_inst);
  1089. err = ip.LoadData();
  1090. BREAK_ON_ERR_FAILURE(err)
  1091. err = ip.ChangeState(dwCommand);
  1092. BREAK_ON_ERR_FAILURE(err)
  1093. err = RefreshData();
  1094. if (err.Succeeded())
  1095. {
  1096. err = RefreshDisplay();
  1097. }
  1098. }
  1099. while(FALSE);
  1100. if (ERROR_ALREADY_EXISTS == err.Win32Error())
  1101. {
  1102. // if the service is trying to start
  1103. // and the Port is already in use by another
  1104. // site then it will report this error...
  1105. if (MD_SERVER_COMMAND_START == dwCommand ||
  1106. MD_SERVER_COMMAND_CONTINUE == dwCommand)
  1107. {
  1108. ::AfxMessageBox(IDS_ERR_PORT_USED,MB_ICONEXCLAMATION);
  1109. }
  1110. else
  1111. {
  1112. err.MessageBoxOnFailure();
  1113. }
  1114. }
  1115. else
  1116. {
  1117. err.MessageBoxOnFailure();
  1118. }
  1119. return err;
  1120. }
  1121. /* virtual */
  1122. HRESULT
  1123. CIISSite::EnumerateScopePane(HSCOPEITEM hParent)
  1124. {
  1125. m_dwEnumError = 0;
  1126. CError err = EnumerateVDirs(hParent, m_pService);
  1127. if (err.Succeeded() && !IsFtpSite() && m_strRedirectPath.IsEmpty())
  1128. {
  1129. if (m_dwEnumError == ERROR_SUCCESS)
  1130. {
  1131. err = EnumerateWebDirs(hParent, m_pService);
  1132. }
  1133. }
  1134. if (err.Failed())
  1135. {
  1136. m_dwEnumError = err.Win32Error();
  1137. RefreshDisplay();
  1138. }
  1139. return err;
  1140. }
  1141. /*virtual*/
  1142. HRESULT
  1143. CIISSite::EnumerateResultPane(BOOL fExp, IHeaderCtrl * pHdr, IResultData * pResData, BOOL bForRefresh)
  1144. {
  1145. m_dwEnumError = 0;
  1146. CError err = CIISObject::EnumerateResultPane(fExp, pHdr, pResData, bForRefresh);
  1147. if ( err.Succeeded()
  1148. // && QueryWin32Error() == ERROR_SUCCESS
  1149. && !IsFtpSite()
  1150. && m_strRedirectPath.IsEmpty()
  1151. )
  1152. {
  1153. err = CIISMBNode::EnumerateResultPane_(fExp, pHdr, pResData, m_pService);
  1154. if (err.Failed())
  1155. {
  1156. m_dwEnumError = err.Win32Error();
  1157. }
  1158. }
  1159. return err;
  1160. }
  1161. /* virtual */
  1162. HRESULT
  1163. CIISSite::BuildMetaPath(CComBSTR & bstrPath) const
  1164. /*++
  1165. Routine Description:
  1166. Recursively build up the metabase path from the current node
  1167. and its parents
  1168. Arguments:
  1169. CComBSTR & bstrPath : Returns metabase path
  1170. Return Value:
  1171. HRESULT
  1172. Notes:
  1173. This will return the home directory path, e.g. "lm/w3svc/2/root",
  1174. not the path of the instance.
  1175. --*/
  1176. {
  1177. //
  1178. // Build instance path
  1179. //
  1180. HRESULT hr = CIISMBNode::BuildMetaPath(bstrPath);
  1181. if (SUCCEEDED(hr))
  1182. {
  1183. //
  1184. // Add root directory path
  1185. //
  1186. bstrPath.Append(_cszSeparator);
  1187. bstrPath.Append(g_cszRoot);
  1188. }
  1189. return hr;
  1190. }
  1191. // CODEWORK: make it work from CIISMBNode::DeleteNode
  1192. HRESULT
  1193. CIISSite::DeleteNode(IResultData * pResult)
  1194. {
  1195. CError err;
  1196. CComBSTR path;
  1197. // check if they have the property sheet open on it.
  1198. if (IsMyPropertySheetOpen())
  1199. {
  1200. ::AfxMessageBox(IDS_CLOSE_PROPERTY_SHEET);
  1201. return S_OK;
  1202. }
  1203. // this could be an orphaned property sheet
  1204. // check if an orphaned property sheet is open on this item.
  1205. CIISObject * pAlreadyOpenProp = NULL;
  1206. if (TRUE == g_OpenPropertySheetTracker.FindAlreadyOpenPropertySheet(this,&pAlreadyOpenProp))
  1207. {
  1208. // Bring it to the foreground, and bail
  1209. HWND hHwnd = 0;
  1210. if (pAlreadyOpenProp)
  1211. {
  1212. if (hHwnd = pAlreadyOpenProp->IsMyPropertySheetOpen())
  1213. {
  1214. if (hHwnd && (hHwnd != (HWND) 1))
  1215. {
  1216. // Perhapse we should cancel the already
  1217. // opened property sheet...just a thought
  1218. if (!SetForegroundWindow(hHwnd))
  1219. {
  1220. // wasn't able to bring this property sheet to
  1221. // the foreground, the propertysheet must not
  1222. // exist anymore. let's just clean the hwnd
  1223. // so that the user will be able to open propertysheet
  1224. pAlreadyOpenProp->SetMyPropertySheetOpen(0);
  1225. }
  1226. else
  1227. {
  1228. ::AfxMessageBox(IDS_CLOSE_PROPERTY_SHEET);
  1229. return S_OK;
  1230. }
  1231. }
  1232. }
  1233. }
  1234. }
  1235. err = CIISMBNode::BuildMetaPath(path);
  1236. if (err.Succeeded())
  1237. {
  1238. err = CheckForMetabaseAccess(METADATA_PERMISSION_WRITE,this,TRUE,path);
  1239. if (!IsLostInterface(err))
  1240. {
  1241. // reset error if an other error other than No interface
  1242. err.Reset();
  1243. }
  1244. }
  1245. if (err.Succeeded())
  1246. {
  1247. if (!NoYesMessageBox(IDS_CONFIRM_DELETE))
  1248. return err;
  1249. do
  1250. {
  1251. CMetaInterface * pInterface = QueryInterface();
  1252. ASSERT(pInterface != NULL);
  1253. path.Empty();
  1254. err = CIISMBNode::BuildMetaPath(path);
  1255. if (err.Failed())
  1256. {
  1257. TRACEEOLID("BuildMetaPath failed path=" << path);
  1258. break;
  1259. }
  1260. CMetaKey mk(pInterface, METADATA_MASTER_ROOT_HANDLE, METADATA_PERMISSION_WRITE);
  1261. if (!mk.Succeeded())
  1262. {
  1263. break;
  1264. }
  1265. err = mk.DeleteKey(path);
  1266. if (err.Failed())
  1267. {
  1268. TRACEEOLID("BuildMetaPath DeleteKey path=" << path);
  1269. break;
  1270. }
  1271. // don't hold the Metabasekey open
  1272. // (RemoveScopeItem may do a lot of things,and lock the metabase for other read requests)
  1273. mk.Close();
  1274. err = RemoveScopeItem();
  1275. if (!IsFtpSite())
  1276. {
  1277. // Also, if we delete a w3svc site, it's probably using
  1278. // a application, so we have to refresh that stuff too
  1279. // this CAppPoolsContainer will only be here if it's iis6
  1280. CIISMachine * pOwner = GetOwner();
  1281. if (pOwner)
  1282. {
  1283. CAppPoolsContainer * pPools = pOwner->QueryAppPoolsContainer();
  1284. if (pPools)
  1285. {
  1286. if (pPools->IsExpanded())
  1287. {
  1288. pPools->RefreshData();
  1289. pPools->RefreshDataChildren(_T(""),FALSE); // refresh all app pools, who knows..
  1290. }
  1291. }
  1292. }
  1293. }
  1294. } while (FALSE);
  1295. }
  1296. if (err.Failed())
  1297. {
  1298. DisplayError(err);
  1299. }
  1300. return err;
  1301. }
  1302. //
  1303. // We are not supporting empty comments on sites. Even if it is OK for
  1304. // metabase, it will bring more problems in UI. Empty name will be displayed
  1305. // as [Site #N] in UI, and when user will try to rename it again, it could be
  1306. // stored in metabase in this format.
  1307. //
  1308. HRESULT
  1309. CIISSite::RenameItem(LPOLESTR new_name)
  1310. {
  1311. CString strNewName(new_name);
  1312. CComBSTR path;
  1313. CError err;
  1314. if (new_name != NULL && lstrlen(new_name) > 0)
  1315. {
  1316. err = BuildMetaPath(path);
  1317. if (err.Succeeded())
  1318. {
  1319. // We need instance key here
  1320. CString path_inst;
  1321. CMetabasePath::GetInstancePath(path, path_inst);
  1322. CMetaKey mk(QueryInterface(), path_inst, METADATA_PERMISSION_WRITE);
  1323. err = mk.QueryResult();
  1324. if (err.Succeeded())
  1325. {
  1326. // remove extra string that was added to
  1327. // the end for display purposes...
  1328. if (m_dwState == MD_SERVER_STATE_STOPPED || m_dwState == MD_SERVER_STATE_PAUSED)
  1329. {
  1330. // These stopped and paused sites will
  1331. // Add on to the end of the string (Stopped) or (Paused),
  1332. // take it out.
  1333. CString buf = _T(".");
  1334. if (m_dwState == MD_SERVER_STATE_STOPPED)
  1335. {buf.Format(IDS_STOPPED_SITE_FMT, _T(" "));}
  1336. else
  1337. {buf.Format(IDS_PAUSED_SITE_FMT, _T(" "));}
  1338. buf.TrimLeft();
  1339. buf.TrimRight();
  1340. // Take it out from the new string if it's there...
  1341. if (strNewName.GetLength() >= buf.GetLength())
  1342. {
  1343. CString buf2;
  1344. buf2 = strNewName.Right(buf.GetLength());
  1345. if (0 == buf2.Compare(buf))
  1346. {
  1347. // Found it, Trim it off
  1348. buf2 = strNewName.Left(strNewName.GetLength() - buf.GetLength());
  1349. strNewName = buf2;
  1350. }
  1351. }
  1352. }
  1353. err = mk.SetValue(MD_SERVER_COMMENT, strNewName);
  1354. if (err.Succeeded())
  1355. {
  1356. m_strDisplayName = strNewName;
  1357. }
  1358. }
  1359. }
  1360. }
  1361. return err;
  1362. }