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.

1124 lines
22 KiB

  1. /*++
  2. Copyright (c) 1994-2000 Microsoft Corporation
  3. Module Name :
  4. app_pools.cpp
  5. Abstract:
  6. IIS Application Pools nodes
  7. Author:
  8. Sergei Antonov (sergeia)
  9. Project:
  10. Internet Services Manager
  11. Revision History:
  12. 11/03/2000 sergeia Initial creation
  13. --*/
  14. #include "stdafx.h"
  15. #include "common.h"
  16. #include "inetprop.h"
  17. #include "InetMgrApp.h"
  18. #include "iisobj.h"
  19. #include "shts.h"
  20. #include "app_pool_sheet.h"
  21. #ifdef _DEBUG
  22. #undef THIS_FILE
  23. static char BASED_CODE THIS_FILE[] = __FILE__;
  24. #endif
  25. #define new DEBUG_NEW
  26. CAppPoolsContainer::CAppPoolsContainer(
  27. CIISMachine * pOwner,
  28. CIISService * pService
  29. )
  30. : CIISMBNode(pOwner, SZ_MBN_APP_POOLS),
  31. m_pWebService(pService)
  32. {
  33. VERIFY(m_bstrDisplayName.LoadString(IDS_APP_POOLS));
  34. }
  35. CAppPoolsContainer::~CAppPoolsContainer()
  36. {
  37. }
  38. /* static */ int
  39. CAppPoolsContainer::_rgnLabels[COL_TOTAL] =
  40. {
  41. IDS_RESULT_SERVICE_DESCRIPTION,
  42. IDS_RESULT_SERVICE_STATE,
  43. };
  44. /* static */ int
  45. CAppPoolsContainer::_rgnWidths[COL_TOTAL] =
  46. {
  47. 180,
  48. 70,
  49. };
  50. /* virtual */
  51. HRESULT
  52. CAppPoolsContainer::EnumerateScopePane(HSCOPEITEM hParent)
  53. {
  54. CError err;
  55. CMetaEnumerator * pme = NULL;
  56. CString strPool;
  57. err = CreateEnumerator(pme);
  58. while (err.Succeeded())
  59. {
  60. CAppPoolNode * pPool;
  61. err = pme->Next(strPool);
  62. if (err.Succeeded())
  63. {
  64. TRACEEOLID("Enumerating node: " << strPool);
  65. CString key_type;
  66. CMetabasePath path(FALSE, pme->QueryMetaPath(), strPool);
  67. CMetaKey mk(pme, path);
  68. mk.QueryValue(MD_KEY_TYPE, key_type);
  69. if (mk.Succeeded() && 0 == key_type.CompareNoCase(_T("IIsApplicationPool")))
  70. {
  71. if (NULL == (pPool = new CAppPoolNode(m_pOwner, this, strPool)))
  72. {
  73. err = ERROR_NOT_ENOUGH_MEMORY;
  74. break;
  75. }
  76. err = pPool->AddToScopePane(hParent);
  77. }
  78. }
  79. }
  80. SAFE_DELETE(pme);
  81. if (err.Win32Error() == ERROR_NO_MORE_ITEMS)
  82. {
  83. err.Reset();
  84. }
  85. if (err.Failed())
  86. {
  87. DisplayError(err);
  88. }
  89. SetInterfaceError(err);
  90. return err;
  91. }
  92. HRESULT
  93. CAppPoolsContainer::EnumerateAppPools(CPoolList * pList)
  94. {
  95. CError err;
  96. CMetaEnumerator * pme = NULL;
  97. CString strPool;
  98. err = CreateEnumerator(pme);
  99. while (err.Succeeded())
  100. {
  101. err = pme->Next(strPool);
  102. if (err.Succeeded())
  103. {
  104. CString key_type;
  105. CMetabasePath path(FALSE, pme->QueryMetaPath(), strPool);
  106. CMetaKey mk(pme, path);
  107. mk.QueryValue(MD_KEY_TYPE, key_type);
  108. if (mk.Succeeded() && 0 == key_type.CompareNoCase(_T("IIsApplicationPool")))
  109. {
  110. CAppPoolNode * pPool;
  111. if (NULL == (pPool = new CAppPoolNode(m_pOwner, this, strPool)))
  112. {
  113. err = ERROR_NOT_ENOUGH_MEMORY;
  114. break;
  115. }
  116. pList->AddTail(pPool);
  117. }
  118. }
  119. }
  120. SAFE_DELETE(pme);
  121. if (err.Win32Error() == ERROR_NO_MORE_ITEMS)
  122. {
  123. err.Reset();
  124. }
  125. return err;
  126. }
  127. /* virtual */
  128. void
  129. CAppPoolsContainer::InitializeChildHeaders(
  130. IN LPHEADERCTRL lpHeader
  131. )
  132. /*++
  133. Routine Description:
  134. Build result view for immediate descendant type
  135. Arguments:
  136. LPHEADERCTRL lpHeader : Header control
  137. Return Value:
  138. None
  139. --*/
  140. {
  141. CIISObject::BuildResultView(lpHeader, COL_TOTAL, _rgnLabels, _rgnWidths);
  142. }
  143. /* virtual */
  144. HRESULT
  145. CAppPoolsContainer::CreatePropertyPages(
  146. IN LPPROPERTYSHEETCALLBACK lpProvider,
  147. IN LONG_PTR handle,
  148. IN IUnknown * pUnk,
  149. IN DATA_OBJECT_TYPES type
  150. )
  151. /*++
  152. Routine Description:
  153. Create the property pages for the given object
  154. Arguments:
  155. LPPROPERTYSHEETCALLBACK lpProvider : Provider
  156. LONG_PTR handle : Handle.
  157. IUnknown * pUnk,
  158. DATA_OBJECT_TYPES type
  159. Return Value:
  160. HRESULT
  161. --*/
  162. {
  163. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  164. CError err;
  165. CComBSTR path;
  166. err = BuildMetaPath(path);
  167. if (err.Failed())
  168. return err;
  169. CAppPoolSheet * pSheet = new CAppPoolSheet(
  170. QueryAuthInfo(), path, GetMainWindow(), (LPARAM)this, handle
  171. );
  172. if (pSheet != NULL)
  173. {
  174. pSheet->SetModeless();
  175. // err = AddMMCPage(lpProvider, new CAppPoolGeneral(pSheet));
  176. err = AddMMCPage(lpProvider, new CAppPoolRecycle(pSheet));
  177. err = AddMMCPage(lpProvider, new CAppPoolPerf(pSheet));
  178. err = AddMMCPage(lpProvider, new CAppPoolHealth(pSheet));
  179. err = AddMMCPage(lpProvider, new CAppPoolDebug(pSheet));
  180. err = AddMMCPage(lpProvider, new CAppPoolIdent(pSheet));
  181. }
  182. return err;
  183. }
  184. /* virtual */
  185. HRESULT
  186. CAppPoolsContainer::BuildMetaPath(
  187. OUT CComBSTR & bstrPath
  188. ) const
  189. /*++
  190. Routine Description:
  191. Recursively build up the metabase path from the current node
  192. and its parents. We cannot use CIISMBNode method because AppPools
  193. is located under w3svc, but rendered after machine.
  194. Arguments:
  195. CComBSTR & bstrPath : Returns metabase path
  196. Return Value:
  197. HRESULT
  198. --*/
  199. {
  200. HRESULT hr = S_OK;
  201. ASSERT(m_pWebService != NULL);
  202. hr = m_pWebService->BuildMetaPath(bstrPath);
  203. if (SUCCEEDED(hr))
  204. {
  205. bstrPath.Append(_cszSeparator);
  206. bstrPath.Append(QueryNodeName());
  207. return hr;
  208. }
  209. //
  210. // No service node
  211. //
  212. ASSERT_MSG("No WebService pointer");
  213. return E_UNEXPECTED;
  214. }
  215. HRESULT
  216. CAppPoolsContainer::QueryDefaultPoolId(CString& id)
  217. //
  218. // Returns pool id which is set on master node for web service
  219. //
  220. {
  221. CError err;
  222. CComBSTR path;
  223. CString service;
  224. BuildMetaPath(path);
  225. CMetabasePath::GetServicePath(path, service);
  226. CMetaKey mk(QueryAuthInfo(), service, METADATA_PERMISSION_READ);
  227. err = mk.QueryResult();
  228. if (err.Succeeded())
  229. {
  230. err = mk.QueryValue(MD_APP_APPPOOL_ID, id);
  231. }
  232. return err;
  233. }
  234. /* virtual */
  235. HRESULT
  236. CAppPoolsContainer::AddMenuItems(
  237. IN LPCONTEXTMENUCALLBACK lpContextMenuCallback,
  238. IN OUT long * pInsertionAllowed,
  239. IN DATA_OBJECT_TYPES type
  240. )
  241. {
  242. ASSERT_READ_PTR(lpContextMenuCallback);
  243. //
  244. // Add base menu items
  245. //
  246. HRESULT hr = CIISObject::AddMenuItems(
  247. lpContextMenuCallback,
  248. pInsertionAllowed,
  249. type
  250. );
  251. if (SUCCEEDED(hr))
  252. {
  253. ASSERT(pInsertionAllowed != NULL);
  254. if (IsAdministrator() && (*pInsertionAllowed & CCM_INSERTIONALLOWED_NEW) != 0)
  255. {
  256. AddMenuSeparator(lpContextMenuCallback);
  257. AddMenuItemByCommand(lpContextMenuCallback, IDM_NEW_APP_POOL);
  258. }
  259. }
  260. return hr;
  261. }
  262. HRESULT
  263. CAppPoolsContainer::Command(
  264. long lCommandID,
  265. CSnapInObjectRootBase * pObj,
  266. DATA_OBJECT_TYPES type
  267. )
  268. {
  269. HRESULT hr = S_OK;
  270. CString name;
  271. switch (lCommandID)
  272. {
  273. case IDM_NEW_APP_POOL:
  274. if ( SUCCEEDED(hr = AddAppPool(pObj, type, this, name))
  275. && !name.IsEmpty()
  276. )
  277. {
  278. hr = InsertNewPool(name);
  279. }
  280. break;
  281. //
  282. // Pass on to base class
  283. //
  284. default:
  285. hr = CIISMBNode::Command(lCommandID, pObj, type);
  286. }
  287. return hr;
  288. }
  289. HRESULT
  290. CAppPoolsContainer::InsertNewPool(CString& id)
  291. {
  292. CError err;
  293. // Now we should insert and select this new site
  294. CAppPoolNode * pPool = new CAppPoolNode(m_pOwner, this, id);
  295. if (pPool != NULL)
  296. {
  297. err = pPool->RefreshData();
  298. if (err.Succeeded())
  299. {
  300. // If item is not expanded we will get error and no effect
  301. if (!IsExpanded())
  302. {
  303. SelectScopeItem();
  304. IConsoleNameSpace2 * pConsole
  305. = (IConsoleNameSpace2 *)GetConsoleNameSpace();
  306. pConsole->Expand(QueryScopeItem());
  307. }
  308. err = pPool->AddToScopePaneSorted(QueryScopeItem(), FALSE);
  309. if (err.Succeeded())
  310. {
  311. VERIFY(SUCCEEDED(pPool->SelectScopeItem()));
  312. }
  313. }
  314. }
  315. else
  316. {
  317. err = ERROR_NOT_ENOUGH_MEMORY;
  318. }
  319. return err;
  320. }
  321. ////////////////////////////////////////////////////////////////////////////////
  322. // CAppPoolNode implementation
  323. //
  324. // App Pool Result View definition
  325. //
  326. /* static */ int
  327. CAppPoolNode::_rgnLabels[COL_TOTAL] =
  328. {
  329. IDS_RESULT_SERVICE_DESCRIPTION,
  330. IDS_RESULT_PATH,
  331. };
  332. /* static */ int
  333. CAppPoolNode::_rgnWidths[COL_TOTAL] =
  334. {
  335. 180,
  336. 200,
  337. };
  338. CAppPoolNode::CAppPoolNode(
  339. CIISMachine * pOwner,
  340. CAppPoolsContainer * pContainer,
  341. LPCTSTR name
  342. )
  343. : CIISMBNode(pOwner, name),
  344. m_pContainer(pContainer)
  345. {
  346. }
  347. CAppPoolNode::~CAppPoolNode()
  348. {
  349. }
  350. #if 0
  351. // This is too expensive
  352. BOOL
  353. CAppPoolNode::IsDeletable() const
  354. {
  355. // We could delete node if it is empty and it is not default app pool
  356. BOOL bRes = TRUE;
  357. CComBSTR path;
  358. CStringListEx apps;
  359. BuildMetaPath(path);
  360. CIISMBNode * that = (CIISMBNode *)this;
  361. CIISAppPool pool(that->QueryAuthInfo(), (LPCTSTR)path);
  362. HRESULT hr = pool.EnumerateApplications(apps);
  363. bRes = (SUCCEEDED(hr) && apps.GetCount() == 0);
  364. if (bRes)
  365. {
  366. CString buf;
  367. hr = m_pContainer->QueryDefaultPoolId(buf);
  368. bRes = buf.CompareNoCase(QueryNodeName()) != 0;
  369. }
  370. return bRes;
  371. }
  372. #endif
  373. HRESULT
  374. CAppPoolNode::DeleteNode(IResultData * pResult)
  375. {
  376. CError err;
  377. CComBSTR path;
  378. BuildMetaPath(path);
  379. CIISAppPool pool(QueryAuthInfo(), (LPCTSTR)path);
  380. err = pool.Delete(GetNodeName());
  381. if (err.Succeeded())
  382. {
  383. err = RemoveScopeItem();
  384. }
  385. if (err.Win32Error() == ERROR_NOT_EMPTY)
  386. {
  387. CString msg;
  388. msg.LoadString(IDS_ERR_NONEMPTY_APPPOOL);
  389. AfxMessageBox(msg);
  390. }
  391. else
  392. {
  393. err.MessageBoxOnFailure();
  394. }
  395. return err;
  396. }
  397. /* virtual */
  398. HRESULT
  399. CAppPoolNode::BuildMetaPath(CComBSTR & bstrPath) const
  400. {
  401. HRESULT hr = S_OK;
  402. ASSERT(m_pContainer != NULL);
  403. hr = m_pContainer->BuildMetaPath(bstrPath);
  404. if (SUCCEEDED(hr))
  405. {
  406. bstrPath.Append(_cszSeparator);
  407. bstrPath.Append(QueryNodeName());
  408. return hr;
  409. }
  410. //
  411. // No service node
  412. //
  413. ASSERT_MSG("No pointer to container");
  414. return E_UNEXPECTED;
  415. }
  416. /* virtual */
  417. LPOLESTR
  418. CAppPoolNode::GetResultPaneColInfo(
  419. IN int nCol
  420. )
  421. /*++
  422. Routine Description:
  423. Return result pane string for the given column number
  424. Arguments:
  425. int nCol : Column number
  426. Return Value:
  427. String
  428. --*/
  429. {
  430. switch(nCol)
  431. {
  432. case COL_DESCRIPTION:
  433. return QueryDisplayName();
  434. case COL_STATE:
  435. return OLESTR("");
  436. }
  437. ASSERT_MSG("Bad column number");
  438. return OLESTR("");
  439. }
  440. /* virtual */
  441. int
  442. CAppPoolNode::QueryImage() const
  443. /*++
  444. Routine Description:
  445. Return bitmap index for the site
  446. Arguments:
  447. None
  448. Return Value:
  449. Bitmap index
  450. --*/
  451. {
  452. return iFolder;
  453. }
  454. /* virtual */
  455. LPOLESTR
  456. CAppPoolNode::QueryDisplayName()
  457. /*++
  458. Routine Description:
  459. Return primary display name of this site.
  460. Arguments:
  461. None
  462. Return Value:
  463. The display name
  464. --*/
  465. {
  466. if (m_strDisplayName.IsEmpty())
  467. {
  468. CComBSTR path;
  469. BuildMetaPath(path);
  470. CMetaKey mk(QueryInterface(), path);
  471. if (mk.Succeeded())
  472. {
  473. mk.QueryValue(MD_APPPOOL_FRIENDLY_NAME, m_strDisplayName);
  474. }
  475. }
  476. return (LPTSTR)(LPCTSTR)m_strDisplayName;
  477. }
  478. /*virtual*/
  479. HRESULT
  480. CAppPoolNode::RenameItem(LPOLESTR new_name)
  481. {
  482. CComBSTR path;
  483. CError err;
  484. if (new_name != NULL && lstrlen(new_name) > 0)
  485. {
  486. BuildMetaPath(path);
  487. CMetaKey mk(QueryInterface(), path, METADATA_PERMISSION_WRITE);
  488. CError err(mk.QueryResult());
  489. if (err.Succeeded())
  490. {
  491. err = mk.SetValue(MD_APPPOOL_FRIENDLY_NAME, CString(new_name));
  492. if (err.Succeeded())
  493. {
  494. m_strDisplayName = new_name;
  495. }
  496. }
  497. }
  498. return err;
  499. }
  500. /* virtual */
  501. HRESULT
  502. CAppPoolNode::RefreshData()
  503. /*++
  504. Routine Description:
  505. Refresh relevant configuration data required for display.
  506. Arguments:
  507. None
  508. Return Value:
  509. HRESULT
  510. --*/
  511. {
  512. CError err;
  513. // CWaitCursor wait;
  514. CComBSTR path;
  515. CMetaKey * pKey = NULL;
  516. do
  517. {
  518. ASSERT_PTR(_lpConsoleNameSpace);
  519. err = BuildMetaPath(path);
  520. if (err.Failed())
  521. {
  522. break;
  523. }
  524. BOOL fContinue = TRUE;
  525. while (fContinue)
  526. {
  527. fContinue = FALSE;
  528. if (NULL == (pKey = new CMetaKey(QueryInterface(), path)))
  529. {
  530. TRACEEOLID("RefreshData: Out Of Memory");
  531. err = ERROR_NOT_ENOUGH_MEMORY;
  532. break;
  533. }
  534. err = pKey->QueryResult();
  535. if (IsLostInterface(err))
  536. {
  537. SAFE_DELETE(pKey);
  538. fContinue = OnLostInterface(err);
  539. }
  540. }
  541. if (err.Failed())
  542. {
  543. break;
  544. }
  545. CAppPoolProps pool(pKey, _T(""));
  546. err = pool.LoadData();
  547. if (err.Failed())
  548. {
  549. break;
  550. }
  551. // Assign the data
  552. }
  553. while(FALSE);
  554. SAFE_DELETE(pKey);
  555. return err;
  556. }
  557. /* virtual */
  558. int
  559. CAppPoolNode::CompareResultPaneItem(
  560. IN CIISObject * pObject,
  561. IN int nCol
  562. )
  563. /*++
  564. Routine Description:
  565. Compare two CIISObjects on sort item criteria
  566. Arguments:
  567. CIISObject * pObject : Object to compare against
  568. int nCol : Column number to sort on
  569. Return Value:
  570. 0 if the two objects are identical
  571. <0 if this object is less than pObject
  572. >0 if this object is greater than pObject
  573. --*/
  574. {
  575. ASSERT_READ_PTR(pObject);
  576. if (nCol == 0)
  577. {
  578. return CompareScopeItem(pObject);
  579. }
  580. //
  581. // First criteria is object type
  582. //
  583. int n1 = QuerySortWeight();
  584. int n2 = pObject->QuerySortWeight();
  585. if (n1 != n2)
  586. {
  587. return n1 - n2;
  588. }
  589. //
  590. // Both are CAppPoolNode objects
  591. //
  592. CAppPoolNode * pPool = (CAppPoolNode *)pObject;
  593. switch(nCol)
  594. {
  595. case COL_DESCRIPTION:
  596. case COL_STATE:
  597. default:
  598. //
  599. // Lexical sort
  600. //
  601. return ::lstrcmpi(
  602. GetResultPaneColInfo(nCol),
  603. pObject->GetResultPaneColInfo(nCol)
  604. );
  605. }
  606. }
  607. /* virtual */
  608. void
  609. CAppPoolNode::InitializeChildHeaders(
  610. IN LPHEADERCTRL lpHeader
  611. )
  612. /*++
  613. Routine Description:
  614. Build result view for immediate descendant type
  615. Arguments:
  616. LPHEADERCTRL lpHeader : Header control
  617. Return Value:
  618. None
  619. --*/
  620. {
  621. CIISObject::BuildResultView(lpHeader, COL_TOTAL, _rgnLabels, _rgnWidths);
  622. }
  623. /* virtual */
  624. HRESULT
  625. CAppPoolNode::EnumerateScopePane(
  626. IN HSCOPEITEM hParent
  627. )
  628. /*++
  629. Routine Description:
  630. Enumerate scope child items.
  631. Arguments:
  632. HSCOPEITEM hParent : Parent console handle
  633. Return Value:
  634. HRESULT
  635. --*/
  636. {
  637. HRESULT hr = S_OK;
  638. CComBSTR path;
  639. BuildMetaPath(path);
  640. CIISAppPool pool(QueryAuthInfo(), path);
  641. if (pool.Succeeded())
  642. {
  643. CStringListEx apps;
  644. hr = pool.EnumerateApplications(apps);
  645. if (SUCCEEDED(hr) && apps.GetCount() > 0)
  646. {
  647. POSITION pos = apps.GetHeadPosition();
  648. while ( pos != NULL)
  649. {
  650. CString app = apps.GetNext(pos);
  651. DWORD i = CMetabasePath::GetInstanceNumber(app);
  652. if (i > 0)
  653. {
  654. CString name;
  655. CMetabasePath::CleanMetaPath(app);
  656. CMetabasePath::GetLastNodeName(app, name);
  657. CApplicationNode * app_node = new CApplicationNode(
  658. GetOwner(), app, name);
  659. if (app_node != NULL)
  660. {
  661. app_node->AddToScopePane(m_hScopeItem, TRUE, TRUE, FALSE);
  662. }
  663. else
  664. hr = ERROR_NOT_ENOUGH_MEMORY;
  665. }
  666. }
  667. }
  668. }
  669. return hr;
  670. }
  671. /* virtual */
  672. HRESULT
  673. CAppPoolNode::CreatePropertyPages(
  674. IN LPPROPERTYSHEETCALLBACK lpProvider,
  675. IN LONG_PTR handle,
  676. IN IUnknown * pUnk,
  677. IN DATA_OBJECT_TYPES type
  678. )
  679. /*++
  680. Routine Description:
  681. Create the property pages for the given object
  682. Arguments:
  683. LPPROPERTYSHEETCALLBACK lpProvider : Provider
  684. LONG_PTR handle : Handle.
  685. IUnknown * pUnk,
  686. DATA_OBJECT_TYPES type
  687. Return Value:
  688. HRESULT
  689. --*/
  690. {
  691. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  692. CComBSTR path;
  693. CError err(BuildMetaPath(path));
  694. if (err.Succeeded())
  695. {
  696. CAppPoolSheet * pSheet = new CAppPoolSheet(
  697. QueryAuthInfo(), path, GetMainWindow(), (LPARAM)this, handle
  698. );
  699. if (pSheet != NULL)
  700. {
  701. pSheet->SetModeless();
  702. // err = AddMMCPage(lpProvider, new CAppPoolGeneral(pSheet));
  703. err = AddMMCPage(lpProvider, new CAppPoolRecycle(pSheet));
  704. err = AddMMCPage(lpProvider, new CAppPoolPerf(pSheet));
  705. err = AddMMCPage(lpProvider, new CAppPoolHealth(pSheet));
  706. err = AddMMCPage(lpProvider, new CAppPoolDebug(pSheet));
  707. err = AddMMCPage(lpProvider, new CAppPoolIdent(pSheet));
  708. }
  709. }
  710. err.MessageBoxOnFailure();
  711. return err;
  712. }
  713. /* virtual */
  714. HRESULT
  715. CAppPoolNode::AddMenuItems(
  716. IN LPCONTEXTMENUCALLBACK lpContextMenuCallback,
  717. IN OUT long * pInsertionAllowed,
  718. IN DATA_OBJECT_TYPES type
  719. )
  720. {
  721. ASSERT_READ_PTR(lpContextMenuCallback);
  722. //
  723. // Add base menu items
  724. //
  725. HRESULT hr = CIISObject::AddMenuItems(
  726. lpContextMenuCallback,
  727. pInsertionAllowed,
  728. type
  729. );
  730. if (SUCCEEDED(hr))
  731. {
  732. ASSERT(pInsertionAllowed != NULL);
  733. if ((*pInsertionAllowed & CCM_INSERTIONALLOWED_NEW) != 0)
  734. {
  735. AddMenuSeparator(lpContextMenuCallback);
  736. AddMenuItemByCommand(lpContextMenuCallback, IDM_NEW_APP_POOL);
  737. }
  738. }
  739. return hr;
  740. }
  741. /* virtual */
  742. HRESULT
  743. CAppPoolNode::Command(
  744. IN long lCommandID,
  745. IN CSnapInObjectRootBase * pObj,
  746. IN DATA_OBJECT_TYPES type
  747. )
  748. /*++
  749. Routine Description:
  750. Handle command from context menu.
  751. Arguments:
  752. long lCommandID : Command ID
  753. CSnapInObjectRootBase * pObj : Base object
  754. DATA_OBJECT_TYPES type : Data object type
  755. Return Value:
  756. HRESULT
  757. --*/
  758. {
  759. HRESULT hr = S_OK;
  760. CString name;
  761. switch (lCommandID)
  762. {
  763. case IDM_NEW_APP_POOL:
  764. if ( SUCCEEDED(hr = AddAppPool(pObj, type, m_pContainer, name))
  765. && !name.IsEmpty()
  766. )
  767. {
  768. hr = m_pContainer->InsertNewPool(name);
  769. }
  770. break;
  771. //
  772. // Pass on to base class
  773. //
  774. default:
  775. hr = CIISMBNode::Command(lCommandID, pObj, type);
  776. }
  777. return hr;
  778. }
  779. ////////////////////////////////////////////////////////////////////////
  780. LPOLESTR
  781. CApplicationNode::QueryDisplayName()
  782. /*++
  783. Routine Description:
  784. Return primary display name of this site.
  785. Arguments:
  786. None
  787. Return Value:
  788. The display name
  789. --*/
  790. {
  791. if (m_strDisplayName.IsEmpty())
  792. {
  793. CMetaKey mk(QueryInterface(), m_meta_path);
  794. if (mk.Succeeded())
  795. {
  796. mk.QueryValue(MD_APP_FRIENDLY_NAME, m_strDisplayName);
  797. if (m_strDisplayName.IsEmpty())
  798. {
  799. m_strDisplayName = QueryNodeName();
  800. }
  801. }
  802. }
  803. return (LPTSTR)(LPCTSTR)m_strDisplayName;
  804. }
  805. HRESULT
  806. CApplicationNode::BuildMetaPath(CComBSTR& path) const
  807. {
  808. path = m_meta_path;
  809. return S_OK;
  810. }
  811. LPOLESTR
  812. CApplicationNode::GetResultPaneColInfo(
  813. IN int nCol
  814. )
  815. /*++
  816. Routine Description:
  817. Return result pane string for the given column number
  818. Arguments:
  819. int nCol : Column number
  820. Return Value:
  821. String
  822. --*/
  823. {
  824. switch(nCol)
  825. {
  826. case COL_ALIAS:
  827. return QueryDisplayName();
  828. case COL_PATH:
  829. {
  830. CString buf;
  831. return (LPTSTR)(LPCTSTR)FriendlyAppRoot(m_meta_path, buf);
  832. }
  833. }
  834. ASSERT_MSG("Bad column number");
  835. return OLESTR("");
  836. }
  837. LPCTSTR
  838. CApplicationNode::FriendlyAppRoot(
  839. LPCTSTR lpAppRoot,
  840. CString & strFriendly
  841. )
  842. /*++
  843. Routine Description:
  844. Convert the metabase app root path to a friendly display name
  845. format.
  846. Arguments:
  847. LPCTSTR lpAppRoot : App root
  848. CString & strFriendly : Output friendly app root format
  849. Return Value:
  850. Reference to the output string
  851. Notes:
  852. App root must have been cleaned from WAM format prior
  853. to calling this function (see first ASSERT below)
  854. --*/
  855. {
  856. if (lpAppRoot != NULL && *lpAppRoot != 0)
  857. {
  858. //
  859. // Make sure we cleaned up WAM format
  860. //
  861. ASSERT(*lpAppRoot != _T('/'));
  862. strFriendly.Empty();
  863. CInstanceProps prop(QueryAuthInfo(), lpAppRoot);
  864. HRESULT hr = prop.LoadData();
  865. if (SUCCEEDED(hr))
  866. {
  867. CString root, tail;
  868. strFriendly.Format(_T("<%s>"), prop.GetDisplayText(root));
  869. CMetabasePath::GetRootPath(lpAppRoot, root, &tail);
  870. if (!tail.IsEmpty())
  871. {
  872. //
  873. // Add rest of dir path
  874. //
  875. strFriendly += _T("/");
  876. strFriendly += tail;
  877. }
  878. //
  879. // Now change forward slashes in the path to backward slashes
  880. //
  881. // CvtPathToDosStyle(strFriendly);
  882. return strFriendly;
  883. }
  884. }
  885. //
  886. // Bogus
  887. //
  888. VERIFY(strFriendly.LoadString(IDS_APPROOT_UNKNOWN));
  889. return strFriendly;
  890. }
  891. //////////////////////////////////////////////////////////////////////////