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.

5061 lines
88 KiB

  1. /*++
  2. Copyright (c) 1994-1998 Microsoft Corporation
  3. Module Name :
  4. iisobj.cpp
  5. Abstract:
  6. IIS Objects
  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 "comprop.h"
  18. #include "inetmgr.h"
  19. #include "iisobj.h"
  20. #include "machine.h"
  21. #include <shlwapi.h>
  22. #include "guids.h"
  23. #ifdef _DEBUG
  24. #undef THIS_FILE
  25. static char BASED_CODE THIS_FILE[] = __FILE__;
  26. #endif
  27. //
  28. // Static initialization
  29. //
  30. BOOL CIISObject::m_fIsExtension = FALSE;
  31. CString CIISObject::s_strProperties;
  32. CString CIISObject::s_strRunning;
  33. CString CIISObject::s_strPaused;
  34. CString CIISObject::s_strStopped;
  35. CString CIISObject::s_strUnknown;
  36. CString CIISObject::s_strYes;
  37. CString CIISObject::s_strNo;
  38. CString CIISObject::s_strTCPIP;
  39. CString CIISObject::s_strNetBIOS;
  40. CString CIISObject::s_strDefaultIP;
  41. CString CIISObject::s_strRedirect;
  42. time_t CIISObject::s_lExpirationTime = (5L * 60L); // 5 Minutes
  43. LPCONSOLENAMESPACE CIISObject::s_lpcnsScopeView = NULL;
  44. //
  45. // Backup/restore taskpad gif resource
  46. //
  47. #define RES_TASKPAD_BACKUP _T("/img\\backup.gif")
  48. LPCTSTR
  49. PrependParentPath(
  50. IN OUT CString & strPath,
  51. IN LPCTSTR lpszParent,
  52. IN TCHAR chSep
  53. )
  54. /*++
  55. Routine Description:
  56. Helper function to prepend a new parent to the given path
  57. Arguments:
  58. CString & strPath : Current path
  59. LPCTSTR lpszParent : Parent to be prepended
  60. TCHAR chSep : Separator character
  61. Return Value:
  62. Pointer to the path
  63. --*/
  64. {
  65. if (strPath.IsEmpty())
  66. {
  67. strPath = lpszParent;
  68. }
  69. else
  70. {
  71. CString strTail(strPath);
  72. strPath = lpszParent;
  73. strPath += chSep;
  74. strPath += strTail;
  75. }
  76. TRACEEOLID("PrependParentPath: " << strPath);
  77. return strPath;
  78. }
  79. HRESULT
  80. ShellExecuteDirectory(
  81. IN LPCTSTR lpszCommand,
  82. IN LPCTSTR lpszOwner,
  83. IN LPCTSTR lpszDirectory
  84. )
  85. /*++
  86. Routine Description:
  87. Shell Open or explore on a given directory path
  88. Arguments:
  89. LPCTSTR lpszCommand : "open" or "explore"
  90. LPCTSTR lpszOwner : Owner server
  91. LPCTSTR lpszDirectory : Directory path
  92. Return Value:
  93. Error return code.
  94. --*/
  95. {
  96. CString strDir;
  97. if (::IsServerLocal(lpszOwner) || ::IsUNCName(lpszDirectory))
  98. {
  99. //
  100. // Local directory, or already a unc path
  101. //
  102. strDir = lpszDirectory;
  103. }
  104. else
  105. {
  106. ::MakeUNCPath(strDir, lpszOwner, lpszDirectory);
  107. }
  108. TRACEEOLID("Attempting to " << lpszCommand << " Path: " << strDir);
  109. CError err;
  110. {
  111. //
  112. // AFX_MANAGE_STATE required for wait cursor
  113. //
  114. AFX_MANAGE_STATE(::AfxGetStaticModuleState() );
  115. CWaitCursor wait;
  116. if (::ShellExecute(
  117. NULL,
  118. lpszCommand,
  119. strDir,
  120. NULL,
  121. _T(""),
  122. SW_SHOW
  123. ) <= (HINSTANCE)32)
  124. {
  125. err.GetLastWinError();
  126. }
  127. }
  128. return err;
  129. }
  130. /* static */
  131. void
  132. CIISObject::BuildResultView(
  133. IN LPHEADERCTRL pHeader,
  134. IN int cColumns,
  135. IN int * pnIDS,
  136. IN int * pnWidths
  137. )
  138. /*++
  139. Routine Description:
  140. Build the result view columns
  141. Routine Description:
  142. LPHEADERCTRL pHeader : Header control
  143. int cColumns : Number of columns
  144. int * pnIDS : Array of column header strings
  145. int * pnWidths : Array of column widths
  146. Routine Description:
  147. None
  148. --*/
  149. {
  150. ASSERT(pHeader != NULL);
  151. //
  152. // Needed for loadstring
  153. //
  154. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  155. CString str;
  156. for (int n = 0; n < cColumns; ++n)
  157. {
  158. VERIFY(str.LoadString(pnIDS[n]));
  159. pHeader->InsertColumn(n, str, LVCFMT_LEFT, pnWidths[n]);
  160. }
  161. }
  162. /* static */
  163. BOOL
  164. CIISObject::CanAddInstance(
  165. IN LPCTSTR lpszMachineName
  166. )
  167. /*++
  168. Routine Description:
  169. Helper function to determine if instances may be added on
  170. this machine
  171. Arguments:
  172. LPCTSTR lpszMachineName : Machine name
  173. Return Value:
  174. TRUE if instances can be added
  175. --*/
  176. {
  177. //
  178. // Assume W3svc and ftpsvc have the same capabilities.
  179. //
  180. CServerCapabilities * pcap;
  181. pcap = new CServerCapabilities(lpszMachineName, SZ_MBN_WEB);
  182. if (!pcap)
  183. {
  184. return FALSE;
  185. }
  186. if (FAILED(pcap->LoadData()))
  187. {
  188. //
  189. // Try ftp
  190. //
  191. delete pcap;
  192. pcap = new CServerCapabilities(lpszMachineName, SZ_MBN_FTP);
  193. }
  194. if (!pcap || FAILED(pcap->LoadData()))
  195. {
  196. if (pcap)
  197. {
  198. delete pcap;
  199. }
  200. return FALSE;
  201. }
  202. BOOL fCanAdd = pcap->HasMultipleSites();
  203. delete pcap;
  204. return fCanAdd;
  205. }
  206. BOOL
  207. CIISObject::IsScopeSelected()
  208. /*++
  209. Routine Description:
  210. Return TRUE if the scope is currently selected
  211. Arguments:
  212. None
  213. Return Value:
  214. TRUE if the item is currently selected, FALSE otherwise
  215. --*/
  216. {
  217. ASSERT(s_lpcnsScopeView != NULL);
  218. HSCOPEITEM hItem = GetScopeHandle();
  219. ASSERT(hItem != NULL);
  220. if (hItem != NULL)
  221. {
  222. SCOPEDATAITEM item;
  223. ::ZeroMemory(&item, sizeof(SCOPEDATAITEM));
  224. item.mask = SDI_STATE;
  225. item.nState = MMC_SCOPE_ITEM_STATE_EXPANDEDONCE;
  226. item.ID = hItem;
  227. HRESULT hr = s_lpcnsScopeView->GetItem(&item);
  228. if (SUCCEEDED(hr))
  229. {
  230. return (item.nState & MMC_SCOPE_ITEM_STATE_EXPANDEDONCE) != 0;
  231. }
  232. }
  233. return FALSE;
  234. }
  235. void
  236. CIISObject::RefreshDisplayInfo()
  237. /*++
  238. Routine Description:
  239. Refresh the display info parameters in the scope view
  240. Arguments:
  241. None
  242. Return Value:
  243. None
  244. --*/
  245. {
  246. if (IsLeafNode())
  247. {
  248. //
  249. // Not supported on result items
  250. //
  251. return;
  252. }
  253. ASSERT(s_lpcnsScopeView != NULL);
  254. HSCOPEITEM hItem = GetScopeHandle();
  255. ASSERT(hItem != NULL);
  256. SCOPEDATAITEM item;
  257. ::ZeroMemory(&item, sizeof(SCOPEDATAITEM));
  258. //
  259. // Since we're using a callback, this is
  260. // all we need to do here
  261. //
  262. item.mask = SDI_STR | SDI_IMAGE | SDI_OPENIMAGE;
  263. item.displayname = MMC_CALLBACK;
  264. item.nOpenImage = item.nImage = QueryBitmapIndex();
  265. item.ID = hItem;
  266. s_lpcnsScopeView->SetItem(&item);
  267. }
  268. CIISObject::CIISObject(
  269. IN const GUID guid,
  270. IN LPCTSTR lpszNodeName, OPTIONAL
  271. IN LPCTSTR lpszPhysicalPath OPTIONAL
  272. )
  273. /*++
  274. Routine Description:
  275. Constructor for CIISObject. Initialise static member functions
  276. if not yet initialized. This is a protected constructor of
  277. an abstract base class.
  278. Arguments:
  279. const GUID guid : GUID of the object
  280. LPCTSTR lpszNodeName : Node name
  281. LPCTSTR lpszPhysicalPath : Physical path (or empty)
  282. Return Value:
  283. N/A
  284. --*/
  285. : m_hScopeItem(NULL),
  286. m_guid(guid),
  287. m_strNodeName(lpszNodeName),
  288. m_strPhysicalPath(lpszPhysicalPath),
  289. m_strRedirPath(),
  290. m_fChildOnlyRedir(FALSE),
  291. m_fIsParentScope(FALSE),
  292. m_tmChildrenExpanded(0L)
  293. {
  294. //
  295. // Initialize static members
  296. //
  297. if (CIISObject::s_strRunning.IsEmpty())
  298. {
  299. //
  300. // AFX_MANAGE_STATE required for resource load
  301. //
  302. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  303. TRACEEOLID("Initializing static strings");
  304. VERIFY(CIISObject::s_strRunning.LoadString(IDS_RUNNING));
  305. VERIFY(CIISObject::s_strPaused.LoadString(IDS_PAUSED));
  306. VERIFY(CIISObject::s_strStopped.LoadString(IDS_STOPPED));
  307. VERIFY(CIISObject::s_strUnknown.LoadString(IDS_UNKNOWN));
  308. VERIFY(CIISObject::s_strProperties.LoadString(IDS_MENU_PROPERTIES));
  309. VERIFY(CIISObject::s_strYes.LoadString(IDS_YES));
  310. VERIFY(CIISObject::s_strNo.LoadString(IDS_NO));
  311. VERIFY(CIISObject::s_strTCPIP.LoadString(IDS_TCPIP));
  312. VERIFY(CIISObject::s_strNetBIOS.LoadString(IDS_NETBIOS));
  313. VERIFY(CIISObject::s_strDefaultIP.LoadString(IDS_DEFAULT_IP));
  314. VERIFY(CIISObject::s_strRedirect.LoadString(IDS_REDIRECTED));
  315. }
  316. }
  317. BOOL CIISObject::IsValidObject() const
  318. {
  319. // CIISObject could have only one of the following GUIDs
  320. GUID guid = QueryGUID();
  321. if ( guid == cInternetRootNode
  322. || guid == cMachineNode
  323. || guid == cServiceCollectorNode
  324. || guid == cInstanceCollectorNode
  325. || guid == cInstanceNode
  326. || guid == cChildNode
  327. || guid == cFileNode
  328. )
  329. return TRUE;
  330. return FALSE;
  331. }
  332. CIISObject::operator LPCTSTR()
  333. /*++
  334. Routine Description:
  335. Typecast operator to call out the display text
  336. Arguments:
  337. N/A
  338. Return Value:
  339. Display text
  340. --*/
  341. {
  342. static CString strText;
  343. return GetDisplayText(strText);
  344. }
  345. //
  346. // Separator menu item definition
  347. //
  348. CONTEXTMENUITEM menuSep =
  349. {
  350. NULL,
  351. NULL,
  352. -1,
  353. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  354. 0,
  355. CCM_SPECIAL_SEPARATOR
  356. };
  357. //
  358. // Menu item definition that uses resource definitions, and
  359. // provides some additional information for taskpads.
  360. //
  361. typedef struct tagCONTEXTMENUITEM_RC
  362. {
  363. UINT nNameID;
  364. UINT nStatusID;
  365. UINT nDescriptionID;
  366. LONG lCmdID;
  367. LONG lInsertionPointID;
  368. LONG fSpecialFlags;
  369. LPCTSTR lpszMouseOverBitmap;
  370. LPCTSTR lpszMouseOffBitmap;
  371. } CONTEXTMENUITEM_RC;
  372. //
  373. // Important! The array indices below must ALWAYS be one
  374. // less than the menu ID -- keep in sync with enumeration
  375. // in inetmgr.h!!!!
  376. //
  377. static CONTEXTMENUITEM_RC menuItemDefs[] =
  378. {
  379. //
  380. // Menu Commands in toolbar order
  381. //
  382. { IDS_MENU_CONNECT, IDS_MENU_TT_CONNECT, -1, IDM_CONNECT, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, NULL, NULL, },
  383. { IDS_MENU_DISCOVER, IDS_MENU_TT_DISCOVER, -1, IDM_DISCOVER, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, NULL, NULL, },
  384. { IDS_MENU_START, IDS_MENU_TT_START, -1, IDM_START, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, NULL, NULL, },
  385. { IDS_MENU_STOP, IDS_MENU_TT_STOP, -1, IDM_STOP, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, NULL, NULL, },
  386. { IDS_MENU_PAUSE, IDS_MENU_TT_PAUSE, -1, IDM_PAUSE, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, NULL, NULL, },
  387. //
  388. // These are menu commands that do not show up in the toolbar
  389. //
  390. { IDS_MENU_EXPLORE, IDS_MENU_TT_EXPLORE, -1, IDM_EXPLORE, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, NULL, NULL, },
  391. { IDS_MENU_OPEN, IDS_MENU_TT_OPEN, -1, IDM_OPEN, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, NULL, NULL, },
  392. { IDS_MENU_BROWSE, IDS_MENU_TT_BROWSE, -1, IDM_BROWSE, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, NULL, NULL, },
  393. { IDS_MENU_PROPERTIES, IDS_MENU_TT_PROPERTIES, -1, IDM_CONFIGURE, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, NULL, NULL, },
  394. { IDS_MENU_DISCONNECT, IDS_MENU_TT_DISCONNECT, -1, IDM_DISCONNECT, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, NULL, NULL, },
  395. { IDS_MENU_BACKUP, IDS_MENU_TT_BACKUP, IDS_MENU_TT_BACKUP, IDM_METABACKREST, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, NULL, NULL, },
  396. { IDS_MENU_SHUTDOWN_IIS, IDS_MENU_TT_SHUTDOWN_IIS, -1, IDM_SHUTDOWN, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, NULL, NULL, },
  397. { IDS_MENU_NEWVROOT, IDS_MENU_TT_NEWVROOT, IDS_MENU_DS_NEWVROOT, IDM_NEW_VROOT, CCM_INSERTIONPOINTID_PRIMARY_NEW, 0, RES_TASKPAD_NEWVROOT, RES_TASKPAD_NEWVROOT, },
  398. { IDS_MENU_NEWINSTANCE, IDS_MENU_TT_NEWINSTANCE, IDS_MENU_DS_NEWINSTANCE, IDM_NEW_INSTANCE, CCM_INSERTIONPOINTID_PRIMARY_NEW, 0, RES_TASKPAD_NEWSITE, RES_TASKPAD_NEWSITE, },
  399. { IDS_MENU_TASKPAD, IDS_MENU_TT_TASKPAD, -1, IDM_VIEW_TASKPAD, CCM_INSERTIONPOINTID_PRIMARY_VIEW, 0, NULL, NULL, },
  400. { IDS_MENU_SECURITY_WIZARD, IDS_MENU_TT_SECURITY_WIZARD, IDS_MENU_TT_SECURITY_WIZARD, IDM_TASK_SECURITY_WIZARD, CCM_INSERTIONPOINTID_PRIMARY_TASK, 0, RES_TASKPAD_SECWIZ, RES_TASKPAD_SECWIZ, },
  401. };
  402. /* static */
  403. HRESULT
  404. CIISObject::AddMenuItemByCommand(
  405. IN LPCONTEXTMENUCALLBACK lpContextMenuCallback,
  406. IN LONG lCmdID,
  407. IN LONG fFlags
  408. )
  409. /*++
  410. Routine Description:
  411. Add menu item by command
  412. Arguments:
  413. LPCONTEXTMENUCALLBACK lpContextMenuCallback : Callback pointer
  414. LONG lCmdID : Command ID
  415. LONG fFlags : Flags
  416. Return Value:
  417. HRESULT
  418. --*/
  419. {
  420. ASSERT(lpContextMenuCallback != NULL);
  421. //
  422. // Offset 1 menu commands
  423. //
  424. LONG l = lCmdID -1;
  425. CString strName;
  426. CString strStatus;
  427. {
  428. //
  429. // AFX_MANAGE_STATE required for resource load
  430. //
  431. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  432. VERIFY(strName.LoadString(menuItemDefs[l].nNameID));
  433. VERIFY(strStatus.LoadString(menuItemDefs[l].nStatusID));
  434. }
  435. CONTEXTMENUITEM cmi;
  436. cmi.strName = strName.GetBuffer(0);
  437. cmi.strStatusBarText = strStatus.GetBuffer(0);
  438. cmi.lCommandID = menuItemDefs[l].lCmdID;
  439. cmi.lInsertionPointID = menuItemDefs[l].lInsertionPointID;
  440. cmi.fFlags = fFlags;
  441. cmi.fSpecialFlags = menuItemDefs[l].fSpecialFlags;
  442. return lpContextMenuCallback->AddItem(&cmi);
  443. }
  444. /* static */
  445. HRESULT
  446. CIISObject::AddTaskpadItemByInfo(
  447. OUT MMC_TASK * pTask,
  448. IN LONG lCommandID,
  449. IN LPCTSTR lpszMouseOn,
  450. IN LPCTSTR lpszMouseOff,
  451. IN LPCTSTR lpszText,
  452. IN LPCTSTR lpszHelpString
  453. )
  454. /*++
  455. Routine Description:
  456. Add taskpad item from the information given
  457. Arguments:
  458. MMC_TASK * pTask : Task info
  459. LPCTSTR lpszMouseOn : Mouse on URL
  460. LPCTSTR lpszMouseOff : Mouse off URL
  461. LPCTSTR lpszText : Text to be displayed
  462. LPCTSTR lpszHelpString : Help string
  463. Return Value:
  464. HRESULT
  465. --*/
  466. {
  467. TRACEEOLID(lpszMouseOn);
  468. TRACEEOLID(lpszMouseOff);
  469. pTask->sDisplayObject.eDisplayType = MMC_TASK_DISPLAY_TYPE_VANILLA_GIF;
  470. pTask->sDisplayObject.uBitmap.szMouseOverBitmap
  471. = CoTaskDupString((LPCOLESTR)lpszMouseOn);
  472. pTask->sDisplayObject.uBitmap.szMouseOffBitmap
  473. = CoTaskDupString((LPCOLESTR)lpszMouseOff);
  474. pTask->szText = CoTaskDupString((LPCOLESTR)lpszText);
  475. pTask->szHelpString = CoTaskDupString((LPCOLESTR)lpszHelpString);
  476. if (pTask->sDisplayObject.uBitmap.szMouseOverBitmap
  477. && pTask->sDisplayObject.uBitmap.szMouseOffBitmap
  478. && pTask->szText
  479. && pTask->szHelpString
  480. )
  481. {
  482. //
  483. // Add action
  484. //
  485. pTask->eActionType = MMC_ACTION_ID;
  486. pTask->nCommandID = lCommandID;
  487. return S_OK;
  488. }
  489. //
  490. // Failed
  491. //
  492. CoTaskStringFree(pTask->sDisplayObject.uBitmap.szMouseOverBitmap);
  493. CoTaskStringFree(pTask->sDisplayObject.uBitmap.szMouseOffBitmap);
  494. CoTaskStringFree(pTask->szText);
  495. CoTaskStringFree(pTask->szHelpString);
  496. return S_FALSE;
  497. }
  498. /* static */
  499. HRESULT
  500. CIISObject::AddTaskpadItemByCommand(
  501. IN LONG lCmdID,
  502. OUT MMC_TASK * pTask,
  503. IN HINSTANCE hInstance OPTIONAL
  504. )
  505. /*++
  506. Routine Description:
  507. Add taskpad item by command
  508. Arguments:
  509. LONG lCmdID : Command ID
  510. CString & strResURL : Resource ID
  511. MMC_TASK * pTask : Task structure to be filled in
  512. Return Value:
  513. HRESULT
  514. --*/
  515. {
  516. ASSERT(pTask != NULL);
  517. //
  518. // Offset 1 menu commands
  519. //
  520. LONG l = lCmdID -1;
  521. CString strName;
  522. CString strStatus;
  523. CString strResURL;
  524. HRESULT hr = BuildResURL(strResURL, hInstance);
  525. if (FAILED(hr))
  526. {
  527. return hr;
  528. }
  529. {
  530. //
  531. // AFX_MANAGE_STATE required for resource load
  532. //
  533. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  534. VERIFY(strName.LoadString(menuItemDefs[l].nStatusID));
  535. VERIFY(strStatus.LoadString(menuItemDefs[l].nDescriptionID));
  536. }
  537. //
  538. // Make sure this menu command was intended to go onto a taskpad
  539. //
  540. ASSERT(menuItemDefs[l].lpszMouseOverBitmap != NULL);
  541. ASSERT(menuItemDefs[l].lpszMouseOffBitmap != NULL);
  542. //
  543. // Fill out bitmap URL (use defaults if nothing provided)
  544. //
  545. CString strMouseOn(strResURL);
  546. CString strMouseOff(strResURL);
  547. strMouseOn += menuItemDefs[l].lpszMouseOverBitmap;
  548. strMouseOff += menuItemDefs[l].lpszMouseOffBitmap;
  549. return AddTaskpadItemByInfo(
  550. pTask,
  551. menuItemDefs[l].lCmdID,
  552. strMouseOn,
  553. strMouseOff,
  554. strName,
  555. strStatus
  556. );
  557. }
  558. /* virtual */
  559. HRESULT
  560. CIISObject::AddMenuItems(
  561. IN LPCONTEXTMENUCALLBACK lpContextMenuCallback
  562. )
  563. /*++
  564. Routine Description:
  565. Add menu items to the context that are valid for this
  566. object
  567. Arguments:
  568. LPCONTEXTMENUCALLBACK lpContextMenuCallback : Callback
  569. Return Value:
  570. HRESULT
  571. --*/
  572. {
  573. if (IsConnectable() && !m_fIsExtension)
  574. {
  575. AddMenuItemByCommand(lpContextMenuCallback, IDM_CONNECT);
  576. AddMenuItemByCommand(lpContextMenuCallback, IDM_DISCONNECT);
  577. }
  578. if (IsExplorable())
  579. {
  580. lpContextMenuCallback->AddItem(&menuSep);
  581. AddMenuItemByCommand(lpContextMenuCallback, IDM_EXPLORE);
  582. }
  583. if (IsOpenable())
  584. {
  585. AddMenuItemByCommand(lpContextMenuCallback, IDM_OPEN);
  586. }
  587. if (IsBrowsable())
  588. {
  589. AddMenuItemByCommand(lpContextMenuCallback, IDM_BROWSE);
  590. }
  591. if (IsControllable())
  592. {
  593. lpContextMenuCallback->AddItem(&menuSep);
  594. UINT nPauseFlags = IsPausable() ? 0 : MF_GRAYED;
  595. if (IsPaused())
  596. {
  597. nPauseFlags |= MF_CHECKED;
  598. }
  599. AddMenuItemByCommand(lpContextMenuCallback, IDM_START, IsStartable() ? 0 : MF_GRAYED);
  600. AddMenuItemByCommand(lpContextMenuCallback, IDM_STOP, IsStoppable() ? 0 : MF_GRAYED);
  601. AddMenuItemByCommand(lpContextMenuCallback, IDM_PAUSE, nPauseFlags);
  602. }
  603. #ifdef MMC_PAGES
  604. //
  605. // Bring up private config menu item only if not
  606. // configurable through MMC
  607. //
  608. if (IsConfigurable() && !IsMMCConfigurable())
  609. {
  610. lpContextMenuCallback->AddItem(&menuSep);
  611. AddMenuItemByCommand(lpContextMenuCallback, IDM_CONFIGURE);
  612. }
  613. #else
  614. if (IsConfigurable())
  615. {
  616. lpContextMenuCallback->AddItem(&menuSep);
  617. AddMenuItemByCommand(lpContextMenuCallback, IDM_CONFIGURE);
  618. }
  619. #endif // MMC_PAGES
  620. return S_OK;
  621. }
  622. /* virtual */
  623. HRESULT
  624. CIISObject::AddNextTaskpadItem(
  625. OUT MMC_TASK * pTask
  626. )
  627. /*++
  628. Routine Description:
  629. Add next taskpad item
  630. Arguments:
  631. MMC_TASK * pTask : Task structure to fill in
  632. Return Value:
  633. HRESULT
  634. --*/
  635. {
  636. //
  637. // CODEWORK: Because of enumeration, this isn't easy
  638. // to handle the way menu items are handled
  639. //
  640. ASSERT(FALSE);
  641. return S_FALSE;
  642. }
  643. /* virtual */
  644. CIISObject *
  645. CIISObject::GetParentObject() const
  646. /*++
  647. Routine Description:
  648. Get the parent object (in the scope view) of this object.
  649. Arguments:
  650. None
  651. Return Value:
  652. Pointer to the parent object, or NULL if not found
  653. --*/
  654. {
  655. MMC_COOKIE cookie;
  656. HSCOPEITEM hParent;
  657. HRESULT hr = GetScopeView()->GetParentItem(
  658. GetScopeHandle(),
  659. &hParent,
  660. &cookie
  661. );
  662. if (hParent == NULL || cookie == 0L || FAILED(hr))
  663. {
  664. //
  665. // None found
  666. //
  667. return NULL;
  668. }
  669. return (CIISObject *)cookie;
  670. }
  671. LPCTSTR
  672. CIISObject::BuildParentPath(
  673. OUT CString & strParent,
  674. IN BOOL fMetabasePath
  675. ) const
  676. /*++
  677. Routine Description:
  678. Walk up the parent nodes to build either a metabase path,
  679. or a physical path to the parent of this node.
  680. Arguments:
  681. CString & strParent : Returns the parent path
  682. BOOL fMetabasePath : If TRUE want full metabse path
  683. If FALSE, relative path from the instance only
  684. Return Value:
  685. Pointer to the path
  686. --*/
  687. {
  688. const CIISObject * pObject = this;
  689. //
  690. // Walk up the tree to build a proper parent path
  691. //
  692. for (;;)
  693. {
  694. if (pObject->IsTerminalPoint(fMetabasePath))
  695. {
  696. break;
  697. }
  698. pObject = pObject->GetParentObject();
  699. if (pObject == NULL)
  700. {
  701. //
  702. // Should have stopped before this.
  703. //
  704. ASSERT(FALSE);
  705. break;
  706. }
  707. PrependParentPath(
  708. strParent,
  709. pObject->QueryNodeName(fMetabasePath),
  710. g_chSep
  711. );
  712. //
  713. // Keep looking
  714. //
  715. }
  716. TRACEEOLID("BuildParentPath: " << strParent);
  717. return strParent;
  718. }
  719. LPCTSTR
  720. CIISObject::BuildFullPath(
  721. OUT CString & strPath,
  722. IN BOOL fMetabasePath
  723. ) const
  724. /*++
  725. Routine Description:
  726. Build complete path for the current object. Either a metabase path or
  727. a directory path.
  728. Arguments:
  729. Return Value:
  730. Pointer to the path
  731. --*/
  732. {
  733. strPath = QueryNodeName(fMetabasePath);
  734. BuildParentPath(strPath, fMetabasePath);
  735. TRACEEOLID("CIISObject::BuildFullPath:" << strPath);
  736. return strPath;
  737. }
  738. LPCTSTR
  739. CIISObject::BuildPhysicalPath(
  740. OUT CString & strPhysicalPath
  741. ) const
  742. /*++
  743. Routine Description:
  744. Build a physical path for the current node. Starting with the current
  745. node, walk up the tree appending node names until a virtual directory
  746. with a real physical path is found
  747. Arguments:
  748. CString & strPhysicalPath : Returns file path
  749. Return Value:
  750. Pointer to path
  751. --*/
  752. {
  753. const CIISObject * pObject = this;
  754. //
  755. // Walk up the tree to build a physical path
  756. //
  757. for (;;)
  758. {
  759. if (pObject->IsVirtualDirectory())
  760. {
  761. //
  762. // Path is properly terminated here
  763. //
  764. PrependParentPath(
  765. strPhysicalPath,
  766. pObject->QueryPhysicalPath(),
  767. _T('\\')
  768. );
  769. break;
  770. }
  771. PrependParentPath(
  772. strPhysicalPath,
  773. pObject->QueryNodeName(),
  774. _T('\\')
  775. );
  776. pObject = pObject->GetParentObject();
  777. if (pObject == NULL)
  778. {
  779. //
  780. // Should have stopped before this.
  781. //
  782. ASSERT(FALSE);
  783. break;
  784. }
  785. //
  786. // Keep looking
  787. //
  788. }
  789. TRACEEOLID("BuildPhysicalPath: " << strPhysicalPath);
  790. return strPhysicalPath;
  791. }
  792. DWORD
  793. CIISObject::QueryInstanceID()
  794. /*++
  795. Routine Description:
  796. Return the ID of the owner instance
  797. Arguments:
  798. None
  799. Return Value:
  800. Owner instance ID or 0xffffffff
  801. --*/
  802. {
  803. CIISInstance * pInstance = FindOwnerInstance();
  804. return pInstance ? pInstance->QueryID() : 0xffffffff;
  805. }
  806. HRESULT
  807. CIISObject::Open()
  808. /*++
  809. Routine Description:
  810. Open the physical path of the current node in the explorer
  811. Arguments:
  812. None
  813. Return Value:
  814. Error return code
  815. --*/
  816. {
  817. CString strPath;
  818. BuildPhysicalPath(strPath);
  819. return ShellExecuteDirectory(_T("open"), GetMachineName(), strPath);
  820. }
  821. HRESULT
  822. CIISObject::Explore()
  823. /*++
  824. Routine Description:
  825. "explore" the physical path of the current node
  826. Arguments:
  827. None
  828. Return Value:
  829. Error return code
  830. --*/
  831. {
  832. CString strPath;
  833. BuildPhysicalPath(strPath);
  834. return ShellExecuteDirectory(_T("explore"), GetMachineName(), strPath);
  835. }
  836. HRESULT
  837. CIISObject::Browse()
  838. /*++
  839. Routine Description:
  840. Bring up the current path in the browser.
  841. Arguments:
  842. None
  843. Return Value:
  844. Error return code
  845. --*/
  846. {
  847. CString strPath;
  848. BuildFullPath(strPath, FALSE);
  849. CIISInstance * pInstance = FindOwnerInstance();
  850. if (pInstance == NULL)
  851. {
  852. ASSERT(FALSE);
  853. return CError::HResult(ERROR_INVALID_PARAMETER);
  854. }
  855. return pInstance->ShellBrowsePath(strPath);
  856. }
  857. //
  858. // Machine pages
  859. //
  860. CObListPlus * CIISMachine::s_poblNewInstanceCmds = NULL;
  861. CString CIISMachine::s_strLocalMachine;
  862. //
  863. // Define result view for machine objects
  864. //
  865. int CIISMachine::rgnLabels[COL_TOTAL] =
  866. {
  867. IDS_RESULT_COMPUTER_NAME,
  868. IDS_RESULT_COMPUTER_LOCAL,
  869. IDS_RESULT_COMPUTER_CONNECTION_TYPE,
  870. IDS_RESULT_STATUS,
  871. };
  872. int CIISMachine::rgnWidths[COL_TOTAL] =
  873. {
  874. 200,
  875. 50,
  876. 100,
  877. 200,
  878. };
  879. /* static */
  880. void
  881. CIISMachine::InitializeHeaders(
  882. IN LPHEADERCTRL pHeader
  883. )
  884. /*++
  885. Routine Description:
  886. Initialize the result view headers for a machine object
  887. Arguments:
  888. LPHEADERCTRL pHeader : Pointer to header control
  889. Return Value:
  890. None.
  891. --*/
  892. {
  893. CIISObject::BuildResultView(pHeader, COL_TOTAL, rgnLabels, rgnWidths);
  894. }
  895. CIISMachine::CIISMachine(
  896. IN LPCTSTR lpszMachineName
  897. )
  898. /*++
  899. Routine Description:
  900. Constructor for machine object
  901. Arguments:
  902. LPCTSTR lpszMachineName : Machine name
  903. Return Value:
  904. N/A
  905. --*/
  906. : CIISObject(cMachineNode),
  907. m_strMachineName(lpszMachineName),
  908. m_fLocal(::IsServerLocal(lpszMachineName))
  909. {
  910. ASSERT(lpszMachineName != NULL);
  911. VERIFY(m_strDisplayName.LoadString(IDS_NODENAME));
  912. //
  913. // Initialize static members
  914. //
  915. if (CIISMachine::s_strLocalMachine.IsEmpty())
  916. {
  917. //
  918. // AFX_MANAGE_STATE required for resource load
  919. //
  920. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  921. TRACEEOLID("Initializing static strings");
  922. VERIFY(CIISMachine::s_strLocalMachine.LoadString(IDS_LOCAL_COMPUTER));
  923. }
  924. // Determine if current user is administrator
  925. CMetaKey key(lpszMachineName);
  926. if (key.Succeeded())
  927. {
  928. DWORD err = DetermineIfAdministrator(
  929. &key,
  930. _T("w3svc"),
  931. 0,
  932. &m_fIsAdministrator);
  933. if (err != ERROR_SUCCESS)
  934. {
  935. err = DetermineIfAdministrator(
  936. &key,
  937. _T("msftpsvc"),
  938. 0,
  939. &m_fIsAdministrator);
  940. }
  941. }
  942. }
  943. /* virtual */
  944. BOOL
  945. CIISMachine::IsConfigurable() const
  946. /*++
  947. Routine Description:
  948. Determine if the machine is configurable, that is at least
  949. one property page handler was registered for it.
  950. Arguments:
  951. None
  952. Return Value:
  953. TRUE if the machine is configurable, FALSE otherwise
  954. --*/
  955. {
  956. //
  957. // Codework: do a metabase check here
  958. //
  959. return m_fIsAdministrator;
  960. //return CIISMachine::s_poblISMMachinePages != NULL
  961. // && CIISMachine::s_poblISMMachinePages->GetCount() > 0;
  962. }
  963. /* virtual */
  964. HRESULT
  965. CIISMachine::Configure(
  966. IN CWnd * pParent OPTIONAL
  967. )
  968. /*++
  969. Routine Description:
  970. Configure the machine object. In order for the machine object to
  971. be configurable, at least one property page add-on function must
  972. be defined.
  973. Arguments:
  974. CWnd * pParent : Parent window handle
  975. Return Value:
  976. Error return code
  977. --*/
  978. {
  979. AFX_MANAGE_STATE(::AfxGetStaticModuleState() );
  980. CError err;
  981. /*
  982. try
  983. {
  984. CString strTitle, str;
  985. VERIFY(str.LoadString(IDS_MACHINE_PROPERTIES));
  986. strTitle.Format(str, GetMachineName());
  987. PROPSHEETHEADER psh;
  988. psh.dwSize = sizeof(psh);
  989. psh.dwFlags = PSH_DEFAULT | PSH_HASHELP;
  990. psh.hwndParent = pParent ? pParent->m_hWnd : NULL;
  991. psh.hInstance = NULL;
  992. psh.pszIcon = NULL;
  993. psh.pszCaption = (LPTSTR)(LPCTSTR)strTitle;
  994. psh.nStartPage = 0;
  995. psh.nPages = 0;
  996. psh.phpage = NULL;
  997. psh.pfnCallback = NULL;
  998. ASSERT(CIISMachine::s_poblISMMachinePages != NULL);
  999. CObListIter obli(*CIISMachine::s_poblISMMachinePages);
  1000. CISMMachinePageExt * pipe;
  1001. while (pipe = (CISMMachinePageExt *)obli.Next())
  1002. {
  1003. DWORD errDLL = pipe->Load();
  1004. if (errDLL == ERROR_SUCCESS)
  1005. {
  1006. errDLL = pipe->AddPages(GetMachineName(), &psh);
  1007. }
  1008. if (errDLL != ERROR_SUCCESS)
  1009. {
  1010. //
  1011. // Unable to load, display error message
  1012. // with the name of the DLL. This does not
  1013. // necessarily pose problems for the rest
  1014. // of the property sheet.
  1015. //
  1016. ::DisplayFmtMessage(
  1017. IDS_ERR_NO_LOAD,
  1018. MB_OK,
  1019. 0,
  1020. (LPCTSTR)*pipe,
  1021. ::GetSystemMessage(errDLL)
  1022. );
  1023. }
  1024. }
  1025. if (psh.nPages > 0)
  1026. {
  1027. //
  1028. // Display the property sheet
  1029. //
  1030. PropertySheet(&psh);
  1031. //
  1032. // Now clean up the property sheet structure
  1033. //
  1034. // FreeMem(psh.phpage);
  1035. }
  1036. //
  1037. // Unload the extentions
  1038. //
  1039. obli.Reset();
  1040. while (pipe = (CISMMachinePageExt *)obli.Next())
  1041. {
  1042. if ((HINSTANCE)*pipe)
  1043. {
  1044. VERIFY(pipe->UnLoad());
  1045. }
  1046. }
  1047. }
  1048. catch(CMemoryException * e)
  1049. {
  1050. err = ERROR_NOT_ENOUGH_MEMORY;
  1051. e->Delete();
  1052. }
  1053. */
  1054. return err;
  1055. }
  1056. /* virtual */
  1057. HRESULT
  1058. CIISMachine::ConfigureMMC(
  1059. IN LPPROPERTYSHEETCALLBACK lpProvider,
  1060. IN LPARAM param,
  1061. IN LONG_PTR handle
  1062. )
  1063. /*++
  1064. Routine Description:
  1065. Configure using MMC property sheets
  1066. Arguments:
  1067. LPPROPERTYSHEETCALLBACK lpProvider : Prop sheet provider
  1068. LPARAM param : Prop parameter
  1069. LONG_PTR handle : console handle
  1070. Return Value:
  1071. Error return code
  1072. --*/
  1073. {
  1074. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1075. HINSTANCE hOld = AfxGetResourceHandle();
  1076. AfxSetResourceHandle(GetModuleHandle(COMPROP_DLL_NAME));
  1077. HINSTANCE hInstance = AfxGetInstanceHandle();
  1078. CIISMachinePage * ppgMachine = new CIISMachinePage(
  1079. GetMachineName(),
  1080. hInstance
  1081. );
  1082. AfxSetResourceHandle(hOld);
  1083. if (ppgMachine)
  1084. {
  1085. CError err(ppgMachine->QueryResult());
  1086. if (err.Failed())
  1087. {
  1088. if (err == REGDB_E_CLASSNOTREG)
  1089. {
  1090. //
  1091. // There isn't a metabase -- fail gracefully
  1092. //
  1093. ::AfxMessageBox(IDS_NO_MACHINE_PROPS);
  1094. err.Reset();
  1095. }
  1096. delete ppgMachine;
  1097. return err;
  1098. }
  1099. //
  1100. // Patch MFC property page class.
  1101. //
  1102. ppgMachine->m_psp.dwFlags |= PSP_HASHELP;
  1103. MMCPropPageCallback(&ppgMachine->m_psp);
  1104. HPROPSHEETPAGE hPage = CreatePropertySheetPage(
  1105. (LPCPROPSHEETPAGE)&ppgMachine->m_psp
  1106. );
  1107. if (hPage != NULL)
  1108. {
  1109. lpProvider->AddPage(hPage);
  1110. return ERROR_SUCCESS;
  1111. }
  1112. }
  1113. return ERROR_NOT_ENOUGH_MEMORY;
  1114. }
  1115. /* virtual */
  1116. HRESULT
  1117. CIISMachine::AddMenuItems(
  1118. IN LPCONTEXTMENUCALLBACK lpContextMenuCallback
  1119. )
  1120. /*++
  1121. Routine Description:
  1122. Add menu items for machine object
  1123. Arguments:
  1124. LPCONTEXTMENUCALLBACK pContextMenuCallback : Context menu items callback
  1125. Return Value:
  1126. HRESULT
  1127. --*/
  1128. {
  1129. CIISObject::AddMenuItems(lpContextMenuCallback);
  1130. //
  1131. // Add metabase backup/restore
  1132. //
  1133. lpContextMenuCallback->AddItem(&menuSep);
  1134. AddMenuItemByCommand(lpContextMenuCallback, IDM_METABACKREST);
  1135. //
  1136. // Add 'IIS shutdown' command
  1137. //
  1138. // ISSUE: Should there be a capability bit?
  1139. //
  1140. AddMenuItemByCommand(lpContextMenuCallback, IDM_SHUTDOWN);
  1141. if (!CanAddInstance(GetMachineName()))
  1142. {
  1143. return FALSE;
  1144. }
  1145. //
  1146. // Add one 'new instance' for every service that supports
  1147. // instances
  1148. //
  1149. ASSERT(CIISMachine::s_poblNewInstanceCmds);
  1150. POSITION pos = CIISMachine::s_poblNewInstanceCmds->GetHeadPosition();
  1151. int lCommandID = IDM_NEW_EX_INSTANCE;
  1152. HRESULT hr;
  1153. while(pos)
  1154. {
  1155. CNewInstanceCmd * pcmd =
  1156. (CNewInstanceCmd *)s_poblNewInstanceCmds->GetNext(pos);
  1157. ASSERT(pcmd != NULL);
  1158. CONTEXTMENUITEM cmi;
  1159. cmi.strName = pcmd->GetMenuCommand().GetBuffer(0);
  1160. cmi.strStatusBarText = pcmd->GetTTText().GetBuffer(0);
  1161. cmi.lCommandID = lCommandID++;
  1162. cmi.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_NEW;
  1163. cmi.fFlags = 0;
  1164. cmi.fSpecialFlags = 0;
  1165. hr = lpContextMenuCallback->AddItem(&cmi);
  1166. ASSERT(SUCCEEDED(hr));
  1167. }
  1168. return S_OK;
  1169. }
  1170. /* virtual */
  1171. HRESULT
  1172. CIISMachine::AddNextTaskpadItem(
  1173. OUT MMC_TASK * pTask
  1174. )
  1175. /*++
  1176. Routine Description:
  1177. Add next taskpad item
  1178. Arguments:
  1179. MMC_TASK * pTask : Task structure to fill in
  1180. Return Value:
  1181. HRESULT
  1182. --*/
  1183. {
  1184. //
  1185. // Add one 'new instance' for every service that supports
  1186. // instances
  1187. //
  1188. ASSERT(CIISMachine::s_poblNewInstanceCmds);
  1189. static POSITION pos = NULL;
  1190. static BOOL fShownBackup = FALSE;
  1191. static int lCommandID = -1;
  1192. HRESULT hr;
  1193. CString strName, strStatus, strMouseOn, strMouseOff;
  1194. long lCmdID;
  1195. //
  1196. // Metabase backup/restore
  1197. //
  1198. if (!fShownBackup)
  1199. {
  1200. //
  1201. // AFX_MANAGE_STATE required for resource load
  1202. //
  1203. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  1204. CString strResURL;
  1205. hr = BuildResURL(strResURL);
  1206. if (FAILED(hr))
  1207. {
  1208. return hr;
  1209. }
  1210. VERIFY(strName.LoadString(IDS_MENU_BACKUP));
  1211. VERIFY(strStatus.LoadString(IDS_MENU_TT_BACKUP));
  1212. strMouseOn = strResURL + RES_TASKPAD_BACKUP;
  1213. strMouseOff = strMouseOn;
  1214. lCmdID = IDM_METABACKREST;
  1215. ++fShownBackup;
  1216. }
  1217. else
  1218. {
  1219. //
  1220. // Display the new instance commands for each service that
  1221. // supports it.
  1222. //
  1223. if (lCommandID == -1)
  1224. {
  1225. //
  1226. // Initialize (use lCommandID == -1 as a flag
  1227. // to indicate we're at the beginning of the list)
  1228. //
  1229. if (CanAddInstance(GetMachineName()))
  1230. {
  1231. pos = CIISMachine::s_poblNewInstanceCmds->GetHeadPosition();
  1232. lCommandID = IDM_NEW_EX_INSTANCE;
  1233. }
  1234. else
  1235. {
  1236. return S_FALSE;
  1237. }
  1238. }
  1239. if (pos == NULL)
  1240. {
  1241. //
  1242. // No more items remain in the list.
  1243. //
  1244. lCommandID = -1;
  1245. fShownBackup = FALSE;
  1246. return S_FALSE;
  1247. }
  1248. CNewInstanceCmd * pcmd =
  1249. (CNewInstanceCmd *)s_poblNewInstanceCmds->GetNext(pos);
  1250. ASSERT(pcmd != NULL);
  1251. CString strResURL;
  1252. hr = BuildResURL(strResURL, pcmd->QueryInstanceHandle());
  1253. if (FAILED(hr))
  1254. {
  1255. return hr;
  1256. }
  1257. //
  1258. // AFX_MANAGE_STATE required for resource load
  1259. //
  1260. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  1261. VERIFY(strStatus.LoadString(IDS_MENU_DS_NEWINSTANCE));
  1262. strMouseOn = strResURL + RES_TASKPAD_NEWSITE;
  1263. strMouseOff = strMouseOn;
  1264. strName = pcmd->GetTTText();
  1265. lCmdID = lCommandID++;
  1266. }
  1267. return AddTaskpadItemByInfo(
  1268. pTask,
  1269. lCmdID,
  1270. strMouseOn,
  1271. strMouseOff,
  1272. strName,
  1273. strStatus
  1274. );
  1275. }
  1276. /* virtual */
  1277. LPCTSTR
  1278. CIISMachine::GetDisplayText(
  1279. OUT CString & strText
  1280. ) const
  1281. /*++
  1282. Routine Description:
  1283. Get the display text of this object
  1284. Arguments:
  1285. CString & strText : String in which display text is to be returned
  1286. Return Value:
  1287. Pointer to the string
  1288. --*/
  1289. {
  1290. try
  1291. {
  1292. if (m_fIsExtension)
  1293. {
  1294. //
  1295. // This is an extension
  1296. //
  1297. strText = m_strDisplayName;
  1298. }
  1299. else
  1300. {
  1301. if (IsLocalMachine())
  1302. {
  1303. ASSERT(!s_strLocalMachine.IsEmpty());
  1304. strText.Format(s_strLocalMachine, m_strMachineName);
  1305. }
  1306. else
  1307. {
  1308. strText = m_strMachineName;
  1309. }
  1310. }
  1311. }
  1312. catch(CMemoryException * e)
  1313. {
  1314. TRACEEOLID("!!!exception in GetDisplayText");
  1315. e->ReportError();
  1316. e->Delete();
  1317. }
  1318. return strText;
  1319. }
  1320. /* virtual */
  1321. int
  1322. CIISMachine::QueryBitmapIndex() const
  1323. /*++
  1324. Routine Description:
  1325. Determine the bitmap index that represents the current item
  1326. Arguments:
  1327. None
  1328. Return Value:
  1329. Index into the bitmap strip
  1330. --*/
  1331. {
  1332. if (m_fIsExtension)
  1333. {
  1334. return BMP_INETMGR;
  1335. }
  1336. return IsLocalMachine() ? BMP_LOCAL_COMPUTER : BMP_COMPUTER;
  1337. }
  1338. /* virtual */
  1339. void
  1340. CIISMachine::GetResultDisplayInfo(
  1341. IN int nCol,
  1342. OUT CString & str,
  1343. OUT int & nImage
  1344. ) const
  1345. /*++
  1346. Routine Description:
  1347. Get result data item display information.
  1348. Arguments:
  1349. int nCol : Column number
  1350. CString & str : String data
  1351. int & nImage : Image number
  1352. Return Value:
  1353. None
  1354. --*/
  1355. {
  1356. //
  1357. // Need different icon for extension...
  1358. //
  1359. nImage = QueryBitmapIndex();
  1360. str.Empty();
  1361. switch(nCol)
  1362. {
  1363. case COL_NAME: // Computer Name
  1364. GetDisplayText(str);
  1365. break;
  1366. case COL_LOCAL: // Local
  1367. if (m_fIsExtension)
  1368. {
  1369. //
  1370. // If we're an extension, display the type
  1371. //
  1372. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1373. VERIFY(str.LoadString(IDS_SNAPIN_TYPE));
  1374. }
  1375. else
  1376. {
  1377. //
  1378. //
  1379. str = IsLocalMachine()
  1380. ? CIISObject::s_strYes
  1381. : CIISObject::s_strNo;
  1382. }
  1383. break;
  1384. case COL_TYPE: // Connection Type
  1385. if (m_fIsExtension)
  1386. {
  1387. //
  1388. // If we're an extension snap-in we should display
  1389. // the snap-in description in this column
  1390. //
  1391. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1392. VERIFY(str.LoadString(IDS_SNAPIN_DESC));
  1393. }
  1394. else
  1395. {
  1396. str = IS_NETBIOS_NAME(GetMachineName())
  1397. ? CIISObject::s_strNetBIOS
  1398. : CIISObject::s_strTCPIP;
  1399. }
  1400. break;
  1401. case COL_STATUS:
  1402. break;
  1403. default:
  1404. //
  1405. // No other columns current supported
  1406. //
  1407. ASSERT(FALSE);
  1408. }
  1409. }
  1410. int
  1411. CIISMachine::Compare(
  1412. IN int nCol,
  1413. IN CIISObject * pObject
  1414. )
  1415. /*++
  1416. Routine Description:
  1417. Compare against another CIISObject
  1418. Arguments:
  1419. int nCol : Compare on this column
  1420. CIISObject * pObject : Compare against this object
  1421. Routine Description:
  1422. Comparison Return Value
  1423. --*/
  1424. {
  1425. ASSERT(QueryGUID() == pObject->QueryGUID());
  1426. if (QueryGUID() != pObject->QueryGUID())
  1427. {
  1428. //
  1429. // Invalid comparison
  1430. //
  1431. return +1;
  1432. }
  1433. CString str1, str2;
  1434. int n1, n2;
  1435. CIISMachine * pMachine = (CIISMachine *)pObject;
  1436. switch(nCol)
  1437. {
  1438. case COL_NAME: // Computer Name
  1439. GetDisplayText(str1);
  1440. pMachine->GetDisplayText(str2);
  1441. return str1.CompareNoCase(str2);
  1442. case COL_LOCAL: // Local
  1443. n1 = IsLocalMachine();
  1444. n2 = pMachine->IsLocalMachine();
  1445. return n1 - n2;
  1446. case COL_TYPE: // Connection Type
  1447. n1 = IS_NETBIOS_NAME(GetMachineName());
  1448. n2 = IS_NETBIOS_NAME(pMachine->GetMachineName());
  1449. return n1 - n2;
  1450. case COL_STATUS:
  1451. return 0;
  1452. default:
  1453. //
  1454. // No other columns current supported
  1455. //
  1456. ASSERT(FALSE);
  1457. }
  1458. return -1;
  1459. }
  1460. void
  1461. CIISMachine::InitializeChildHeaders(
  1462. IN LPHEADERCTRL pHeader
  1463. )
  1464. /*++
  1465. Routine Description:
  1466. Build result view underneath
  1467. Arguments:
  1468. LPHEADERCTRL pHeader : Header control
  1469. Return Value:
  1470. None
  1471. --*/
  1472. {
  1473. CIISInstance::InitializeHeaders(pHeader);
  1474. }
  1475. //
  1476. // Static Initialization
  1477. //
  1478. CString CIISInstance::s_strFormatState;
  1479. BOOL CIISInstance::s_fServerView = TRUE;
  1480. BOOL CIISInstance::s_fAppendState = TRUE;
  1481. //
  1482. // Instance Result View definition
  1483. //
  1484. int CIISInstance::rgnLabels[COL_TOTAL] =
  1485. {
  1486. IDS_RESULT_SERVICE_DESCRIPTION,
  1487. IDS_RESULT_SERVICE_STATE,
  1488. IDS_RESULT_SERVICE_DOMAIN_NAME,
  1489. IDS_RESULT_SERVICE_IP_ADDRESS,
  1490. IDS_RESULT_SERVICE_TCP_PORT,
  1491. IDS_RESULT_STATUS,
  1492. };
  1493. int CIISInstance::rgnWidths[COL_TOTAL] =
  1494. {
  1495. 180,
  1496. 70,
  1497. 120,
  1498. 105,
  1499. 40,
  1500. 200,
  1501. };
  1502. /* static */
  1503. void
  1504. CIISInstance::InitializeStrings()
  1505. /*++
  1506. Routine Description:
  1507. Static method to initialize the strings.
  1508. Arguments:
  1509. None
  1510. Return Value:
  1511. None
  1512. --*/
  1513. {
  1514. if (!IsInitialized())
  1515. {
  1516. TRACEEOLID("Initializing static strings");
  1517. //
  1518. // iisui.dll is an extension DLL, and this should
  1519. // load automatically, but doesn't -- why?
  1520. //
  1521. HINSTANCE hOld = AfxGetResourceHandle();
  1522. AfxSetResourceHandle(GetModuleHandle(COMPROP_DLL_NAME));
  1523. VERIFY(CIISInstance::s_strFormatState.LoadString(IDS_INSTANCE_STATE_FMT));
  1524. AfxSetResourceHandle(hOld);
  1525. }
  1526. }
  1527. /* static */
  1528. void
  1529. CIISInstance::InitializeHeaders(
  1530. IN LPHEADERCTRL pHeader
  1531. )
  1532. /*++
  1533. Routine Description:
  1534. Initialize the result headers
  1535. Arguments:
  1536. LPHEADERCTRL pHeader : Header control
  1537. Return Value:
  1538. None
  1539. --*/
  1540. {
  1541. CIISObject::BuildResultView(pHeader, COL_TOTAL, rgnLabels, rgnWidths);
  1542. }
  1543. CIISInstance::CIISInstance(
  1544. IN CServerInfo * pServerInfo
  1545. )
  1546. /*++
  1547. Routine Description:
  1548. Constructor for instance object without instance ID code. In other
  1549. words, this is a wrapper for a plain-old down-level CServerInfo
  1550. object.
  1551. Arguments:
  1552. CServerInfo * pServerInfo : Controlling server info
  1553. Return Value:
  1554. N/A
  1555. --*/
  1556. : CIISObject(cInstanceNode),
  1557. m_fDownLevel(TRUE),
  1558. m_fDeletable(FALSE),
  1559. m_fClusterEnabled(FALSE),
  1560. m_fLocalMachine(FALSE),
  1561. m_hrError(S_OK),
  1562. m_sPort(0),
  1563. m_dwIPAddress(0L),
  1564. m_strHostHeaderName(),
  1565. m_strComment(),
  1566. m_strMachine(),
  1567. m_pServerInfo(pServerInfo)
  1568. {
  1569. if (!IsInitialized())
  1570. {
  1571. CIISInstance::InitializeStrings();
  1572. }
  1573. //
  1574. // Some service types do not support instances, but
  1575. // still understand the instance codes
  1576. //
  1577. ASSERT(m_pServerInfo != NULL);
  1578. m_dwID = 0L;
  1579. m_strMachine = m_pServerInfo->QueryServerName();
  1580. m_fLocalMachine = ::IsServerLocal(m_strMachine);
  1581. }
  1582. CIISInstance::CIISInstance(
  1583. IN ISMINSTANCEINFO * pii,
  1584. IN CServerInfo * pServerInfo
  1585. )
  1586. /*++
  1587. Routine Description:
  1588. Initialize IIS Instance from ISMINSTANCEINFO structure
  1589. Arguments:
  1590. ISMINSTANCEINFO * pii : Pointer to ISMINSTANCEINFO structure
  1591. CServerInfo * pServerInfo : Server info structure
  1592. Return Value:
  1593. N/A
  1594. --*/
  1595. : CIISObject(cInstanceNode),
  1596. m_fDownLevel(FALSE),
  1597. m_fLocalMachine(),
  1598. m_strMachine(),
  1599. m_pServerInfo(pServerInfo)
  1600. {
  1601. InitializeFromStruct(pii);
  1602. if (!IsInitialized())
  1603. {
  1604. CIISInstance::InitializeStrings();
  1605. }
  1606. ASSERT(m_pServerInfo != NULL);
  1607. m_strMachine = m_pServerInfo->QueryServerName();
  1608. m_fLocalMachine = ::IsServerLocal(m_strMachine);
  1609. }
  1610. void
  1611. CIISInstance::InitializeFromStruct(
  1612. IN ISMINSTANCEINFO * pii
  1613. )
  1614. /*++
  1615. Routine Description:
  1616. Initialize data from ISMINSTANCEINFO structure
  1617. Arguments:
  1618. ISMINSTANCEINFO * pii : Pointer to ISMINSTANCEINFO structure
  1619. Return Value:
  1620. None.
  1621. --*/
  1622. {
  1623. ASSERT(pii);
  1624. m_dwID = pii->dwID;
  1625. m_strHostHeaderName = pii->szServerName;
  1626. m_strComment = pii->szComment;
  1627. m_nState = pii->nState;
  1628. m_dwIPAddress = pii->dwIPAddress;
  1629. m_sPort = pii->sPort;
  1630. m_fDeletable = pii->fDeletable;
  1631. m_fClusterEnabled = pii->fClusterEnabled;
  1632. CError err(pii->dwError);
  1633. m_hrError = err;
  1634. m_strRedirPath = pii->szRedirPath;
  1635. m_fChildOnlyRedir = pii->fChildOnlyRedir;
  1636. //
  1637. // Home directory path should exist unless someone's been
  1638. // messing up the metabase.
  1639. //
  1640. m_strPhysicalPath = pii->szPath;
  1641. m_strNodeName.Format(_T("%s%c%s%c%ld%c%s"),
  1642. g_cszMachine,
  1643. g_chSep,
  1644. GetServerInfo()->GetMetabaseName(),
  1645. g_chSep,
  1646. m_dwID,
  1647. g_chSep,
  1648. g_cszRoot
  1649. );
  1650. TRACEEOLID(m_strNodeName);
  1651. }
  1652. /* virtual */
  1653. BOOL
  1654. CIISInstance::IsRunning() const
  1655. /*++
  1656. Routine Description:
  1657. Check to see if this instance is currently running.
  1658. Arguments:
  1659. None.
  1660. Return Value:
  1661. TRUE if currently running
  1662. Notes:
  1663. On a down-level (v3) version, this applies to the service, not
  1664. the instance
  1665. --*/
  1666. {
  1667. if (IsDownLevel())
  1668. {
  1669. ASSERT(m_pServerInfo != NULL);
  1670. return m_pServerInfo->IsServiceRunning();
  1671. }
  1672. return m_nState == INetServiceRunning;
  1673. }
  1674. /* virtual */
  1675. BOOL
  1676. CIISInstance::IsStopped() const
  1677. /*++
  1678. Routine Description:
  1679. Check to see if this instance is currently stopped.
  1680. Arguments:
  1681. None.
  1682. Return Value:
  1683. TRUE if currently stopped
  1684. Notes:
  1685. On a down-level (v3) version, this applies to the server, not
  1686. the instance
  1687. --*/
  1688. {
  1689. if (IsDownLevel())
  1690. {
  1691. ASSERT(m_pServerInfo != NULL);
  1692. return m_pServerInfo->IsServiceStopped();
  1693. }
  1694. return m_nState == INetServiceStopped;
  1695. }
  1696. /* virtual */
  1697. BOOL
  1698. CIISInstance::IsPaused() const
  1699. /*++
  1700. Routine Description:
  1701. Check to see if this instance is currently paused.
  1702. Arguments:
  1703. None.
  1704. Return Value:
  1705. TRUE if currently paused
  1706. Notes:
  1707. On a down-level (v3) version, this applies to the server, not
  1708. the instance
  1709. --*/
  1710. {
  1711. if (IsDownLevel())
  1712. {
  1713. ASSERT(m_pServerInfo != NULL);
  1714. return m_pServerInfo->IsServicePaused();
  1715. }
  1716. return m_nState == INetServicePaused;
  1717. }
  1718. /* virtual */
  1719. int
  1720. CIISInstance::QueryState() const
  1721. /*++
  1722. Routine Description:
  1723. Get the ISM state of the instance
  1724. Arguments:
  1725. None.
  1726. Return Value:
  1727. The ISM (INet*) state of the instance
  1728. Notes:
  1729. On a down-level (v3) version, this applies to the server, not
  1730. the instance
  1731. --*/
  1732. {
  1733. if (IsDownLevel())
  1734. {
  1735. return m_pServerInfo->QueryServiceState();
  1736. }
  1737. return m_nState;
  1738. }
  1739. /* virtual */
  1740. HRESULT
  1741. CIISInstance::ChangeState(
  1742. IN int nNewState
  1743. )
  1744. /*++
  1745. Routine Description:
  1746. Change the ISM state of the instance
  1747. Arguments:
  1748. int nNewState
  1749. Return Value:
  1750. Error Return Code
  1751. Notes:
  1752. On a down-level (v3) version, this applies to the server, not
  1753. the instance
  1754. --*/
  1755. {
  1756. ASSERT(m_pServerInfo != NULL);
  1757. int * pnCurrentState;
  1758. DWORD dwID;
  1759. if (IsClusterEnabled())
  1760. {
  1761. //
  1762. // Not supported on cluster server
  1763. //
  1764. return ERROR_BAD_DEV_TYPE;
  1765. }
  1766. if (IsDownLevel())
  1767. {
  1768. dwID = 0;
  1769. pnCurrentState = m_pServerInfo->GetServiceStatePtr();
  1770. }
  1771. else
  1772. {
  1773. dwID = QueryID();
  1774. pnCurrentState = &m_nState;
  1775. }
  1776. return m_pServerInfo->ChangeServiceState(nNewState, pnCurrentState, dwID);
  1777. }
  1778. /* virtual */
  1779. HRESULT
  1780. CIISInstance::Configure(
  1781. IN CWnd * pParent OPTIONAL
  1782. )
  1783. /*++
  1784. Routine Description:
  1785. Configure the instance object
  1786. Arguments:
  1787. CWnd * pParent : Optional parent window
  1788. Return Value:
  1789. Error return code
  1790. --*/
  1791. {
  1792. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1793. ASSERT(m_pServerInfo != NULL);
  1794. //
  1795. // Set help file
  1796. //
  1797. theApp.SetHelpPath(m_pServerInfo);
  1798. CError err(m_pServerInfo->ConfigureServer(pParent->m_hWnd, QueryID()));
  1799. //
  1800. // Restore help path
  1801. //
  1802. theApp.SetHelpPath();
  1803. if (err.Succeeded())
  1804. {
  1805. RefreshData();
  1806. }
  1807. return err;
  1808. }
  1809. /* virtual */
  1810. HRESULT
  1811. CIISInstance::RefreshData()
  1812. /*++
  1813. Routine Description:
  1814. Refresh internal data
  1815. Arguments:
  1816. None
  1817. Return Value:
  1818. Error return code.
  1819. --*/
  1820. {
  1821. CError err;
  1822. if (!IsDownLevel())
  1823. {
  1824. ISMINSTANCEINFO ii;
  1825. err = m_pServerInfo->QueryInstanceInfo(
  1826. WITHOUT_INHERITANCE,
  1827. &ii,
  1828. QueryID()
  1829. );
  1830. if (err.Succeeded())
  1831. {
  1832. InitializeFromStruct(&ii);
  1833. }
  1834. }
  1835. return err;
  1836. }
  1837. /* virtual */
  1838. HRESULT
  1839. CIISInstance::ConfigureMMC(
  1840. IN LPPROPERTYSHEETCALLBACK lpProvider,
  1841. IN LPARAM param,
  1842. IN LONG_PTR handle
  1843. )
  1844. /*++
  1845. Routine Description:
  1846. Configure using MMC property sheets
  1847. Arguments:
  1848. LPPROPERTYSHEETCALLBACK lpProvider : Prop sheet provider
  1849. LPARAM param : Prop parameter
  1850. LONG_PTR handle : console handle
  1851. Return Value:
  1852. Error return code
  1853. --*/
  1854. {
  1855. ASSERT(m_pServerInfo != NULL);
  1856. return m_pServerInfo->MMMCConfigureServer(
  1857. lpProvider,
  1858. param,
  1859. handle,
  1860. QueryID()
  1861. );
  1862. }
  1863. /* virtual */
  1864. LPCTSTR
  1865. CIISInstance::GetStateText() const
  1866. /*++
  1867. Routine Description:
  1868. Return text representation of current state (running/paused/stopped).
  1869. Arguments:
  1870. None
  1871. Return Value:
  1872. Pointer to the string
  1873. --*/
  1874. {
  1875. ASSERT(!CIISObject::s_strRunning.IsEmpty());
  1876. return IsStopped()
  1877. ? CIISObject::s_strStopped
  1878. : IsPaused()
  1879. ? CIISObject::s_strPaused
  1880. : IsRunning()
  1881. ? CIISObject::s_strRunning
  1882. : CIISObject::s_strUnknown;
  1883. }
  1884. /* virtual */
  1885. LPCTSTR
  1886. CIISInstance::GetDisplayText(
  1887. OUT CString & strText
  1888. ) const
  1889. /*++
  1890. Routine Description:
  1891. Get the display text of this object
  1892. Arguments:
  1893. CString & strText : String in which display text is to be returned
  1894. Return Value:
  1895. Pointer to the string
  1896. --*/
  1897. {
  1898. try
  1899. {
  1900. if (m_fDownLevel)
  1901. {
  1902. ASSERT(m_pServerInfo != NULL);
  1903. if (CIISInstance::s_fServerView)
  1904. {
  1905. strText = m_pServerInfo->GetServiceName();
  1906. }
  1907. else
  1908. {
  1909. strText = m_pServerInfo->QueryServerName();
  1910. }
  1911. }
  1912. else
  1913. {
  1914. //
  1915. // GetDisplayText loads from resources
  1916. //
  1917. AFX_MANAGE_STATE(::AfxGetStaticModuleState() );
  1918. CIPAddress ia(m_dwIPAddress);
  1919. CInstanceProps::GetDisplayText(
  1920. strText,
  1921. GetComment(),
  1922. GetHostHeaderName(),
  1923. m_pServerInfo->GetServiceName(),
  1924. ia,
  1925. m_sPort,
  1926. m_dwID
  1927. );
  1928. }
  1929. //
  1930. // Append state (paused, etc) if not running
  1931. //
  1932. if (CIISInstance::s_fAppendState && !IsRunning())
  1933. {
  1934. CString strState;
  1935. strState.Format(CIISInstance::s_strFormatState, GetStateText());
  1936. strText += strState;
  1937. }
  1938. }
  1939. catch(CMemoryException * e)
  1940. {
  1941. TRACEEOLID("!!!exception in GetDisplayText");
  1942. e->ReportError();
  1943. e->Delete();
  1944. }
  1945. return strText;
  1946. }
  1947. /* virtual */
  1948. HRESULT
  1949. CIISInstance::AddChildNode(
  1950. IN OUT CIISChildNode *& pChild
  1951. )
  1952. /*++
  1953. Routine Description:
  1954. Add child node under current node
  1955. Arguments:
  1956. CIISChildNode *& pChild : Child node to be added
  1957. Return Value:
  1958. Error return code.
  1959. --*/
  1960. {
  1961. pChild = NULL;
  1962. ISMCHILDINFO ii;
  1963. CString strParent(g_cszRoot);
  1964. CError err(GetServerInfo()->AddChild(
  1965. &ii,
  1966. sizeof(ii),
  1967. QueryID(),
  1968. strParent
  1969. ));
  1970. if (err.Succeeded())
  1971. {
  1972. pChild = new CIISChildNode(&ii, this);
  1973. }
  1974. return err;
  1975. }
  1976. /* virtual */
  1977. BOOL
  1978. CIISInstance::ChildrenExpanded() const
  1979. /*++
  1980. Routine Description:
  1981. Determine if the child items of this node have already been expanded
  1982. Arguments:
  1983. None
  1984. Return Value:
  1985. TRUE if the items do not need expansion, FALSE if they do.
  1986. --*/
  1987. {
  1988. ASSERT(m_pServerInfo != NULL);
  1989. if (m_pServerInfo->SupportsChildren())
  1990. {
  1991. //
  1992. // Note: timestamps ignored, because MMC will never send me another
  1993. // expansion notification, so we can't refresh after a certain time.
  1994. //
  1995. return m_tmChildrenExpanded > 0L;
  1996. }
  1997. //
  1998. // Can't drill down any lower than this.
  1999. //
  2000. return TRUE;
  2001. }
  2002. /* virtual */
  2003. HRESULT
  2004. CIISInstance::ExpandChildren(
  2005. IN HSCOPEITEM pParent
  2006. )
  2007. /*++
  2008. Routine Description:
  2009. Mark the children as being expanded.
  2010. Arguments:
  2011. HSCOPEITEM pParent : Parent scope item
  2012. Return Value:
  2013. Error return code.
  2014. --*/
  2015. {
  2016. ASSERT(m_pServerInfo != NULL);
  2017. if (m_pServerInfo->SupportsChildren() )
  2018. {
  2019. //
  2020. // Mark the last epxansion time as being now.
  2021. //
  2022. time(&m_tmChildrenExpanded);
  2023. return S_OK;
  2024. }
  2025. //
  2026. // Can't drill down any lower than this.
  2027. //
  2028. return CError::HResult(ERROR_INVALID_FUNCTION);
  2029. }
  2030. /* virtual */
  2031. int
  2032. CIISInstance::QueryBitmapIndex() const
  2033. /*++
  2034. Routine Description:
  2035. Get the bitmap index of the object. This varies with the state
  2036. of the view
  2037. Arguments:
  2038. None
  2039. Return Value:
  2040. Bitmap index
  2041. --*/
  2042. {
  2043. ASSERT(m_pServerInfo != NULL);
  2044. /*
  2045. return OK()
  2046. ? m_pServerInfo->QueryBitmapIndex()
  2047. : BMP_ERROR;
  2048. */
  2049. return m_pServerInfo->QueryBitmapIndex();
  2050. }
  2051. /* virtual */
  2052. HRESULT
  2053. CIISInstance::AddMenuItems(
  2054. IN LPCONTEXTMENUCALLBACK pContextMenuCallback
  2055. )
  2056. /*++
  2057. Routine Description:
  2058. Add context menu items for the instance
  2059. Arguments:
  2060. LPCONTEXTMENUCALLBACK pContextMenuCallback : Context menu callback
  2061. Return Value:
  2062. HRESULT
  2063. --*/
  2064. {
  2065. CIISObject::AddMenuItems(pContextMenuCallback);
  2066. if (SupportsInstances() && CanAddInstance(GetMachineName()))
  2067. {
  2068. AddMenuItemByCommand(pContextMenuCallback, IDM_NEW_INSTANCE);
  2069. }
  2070. if (SupportsChildren())
  2071. {
  2072. AddMenuItemByCommand(pContextMenuCallback, IDM_NEW_VROOT);
  2073. }
  2074. if (SupportsSecurityWizard())
  2075. {
  2076. AddMenuItemByCommand(pContextMenuCallback, IDM_TASK_SECURITY_WIZARD);
  2077. }
  2078. return S_OK;
  2079. }
  2080. /* virtual */
  2081. HRESULT
  2082. CIISInstance::AddNextTaskpadItem(
  2083. OUT MMC_TASK * pTask
  2084. )
  2085. /*++
  2086. Routine Description:
  2087. Add next taskpad item
  2088. Arguments:
  2089. MMC_TASK * pTask : Task structure to fill in
  2090. Return Value:
  2091. HRESULT
  2092. --*/
  2093. {
  2094. //
  2095. // CODEWORK: Ideally I would call the base class here, but that's
  2096. // a pain with enumeration
  2097. //
  2098. static int iIndex = 0;
  2099. //
  2100. // Fall through on the switch until an applicable command is found
  2101. //
  2102. UINT nID;
  2103. switch(iIndex)
  2104. {
  2105. case 0:
  2106. if (SupportsInstances() && CanAddInstance(GetMachineName()))
  2107. {
  2108. nID = IDM_NEW_INSTANCE;
  2109. break;
  2110. }
  2111. ++iIndex;
  2112. //
  2113. // Fall through
  2114. //
  2115. case 1:
  2116. if (SupportsChildren())
  2117. {
  2118. nID = IDM_NEW_VROOT;
  2119. break;
  2120. }
  2121. ++iIndex;
  2122. //
  2123. // Fall through
  2124. //
  2125. case 2:
  2126. if (SupportsSecurityWizard())
  2127. {
  2128. nID = IDM_TASK_SECURITY_WIZARD;
  2129. break;
  2130. }
  2131. ++iIndex;
  2132. //
  2133. // Fall through
  2134. //
  2135. default:
  2136. //
  2137. // All done
  2138. //
  2139. iIndex = 0;
  2140. return S_FALSE;
  2141. }
  2142. HRESULT hr = AddTaskpadItemByCommand(
  2143. nID,
  2144. pTask,
  2145. GetServerInfo()->QueryInstanceHandle()
  2146. );
  2147. if (SUCCEEDED(hr))
  2148. {
  2149. ++iIndex;
  2150. }
  2151. return hr;
  2152. }
  2153. HRESULT
  2154. CIISInstance::Delete()
  2155. /*++
  2156. Routine Description:
  2157. Handle deletion of the current item
  2158. Arguments:
  2159. None
  2160. Return Value:
  2161. Error return code
  2162. --*/
  2163. {
  2164. ASSERT(m_pServerInfo != NULL);
  2165. return m_pServerInfo->DeleteInstance(m_dwID);
  2166. }
  2167. HRESULT
  2168. CIISInstance::SecurityWizard()
  2169. /*++
  2170. Routine Description:
  2171. Launch the security wizard on this instance
  2172. Arguments:
  2173. None
  2174. Return Value:
  2175. Error return code
  2176. --*/
  2177. {
  2178. ASSERT(m_pServerInfo != NULL);
  2179. ASSERT(m_pServerInfo->SupportsSecurityWizard());
  2180. CString strPhysicalPath;
  2181. BuildPhysicalPath(strPhysicalPath);
  2182. return m_pServerInfo->ISMSecurityWizard(m_dwID, _T(""), g_cszRoot);
  2183. }
  2184. int
  2185. CIISInstance::Compare(
  2186. IN int nCol,
  2187. IN CIISObject * pObject
  2188. )
  2189. /*++
  2190. Routine Description:
  2191. Compare against another CIISObject
  2192. Arguments:
  2193. int nCol : Compare on this column
  2194. CIISObject * pObject : Compare against this object
  2195. Routine Description:
  2196. Comparison Return Value
  2197. --*/
  2198. {
  2199. ASSERT(QueryGUID() == pObject->QueryGUID());
  2200. if (QueryGUID() != pObject->QueryGUID())
  2201. {
  2202. //
  2203. // Invalid comparison
  2204. //
  2205. return +1;
  2206. }
  2207. CString str1, str2;
  2208. CIPAddress ia1, ia2;
  2209. DWORD dw1, dw2;
  2210. int n1, n2;
  2211. CIISInstance * pInstance = (CIISInstance *)pObject;
  2212. switch(nCol)
  2213. {
  2214. case COL_DESCRIPTION: // Description
  2215. GetDisplayText(str1);
  2216. pInstance->GetDisplayText(str2);
  2217. return str1.CompareNoCase(str2);
  2218. case COL_STATE: // State
  2219. str1 = GetStateText();
  2220. str2 = pInstance->GetStateText();
  2221. return str1.CompareNoCase(str2);
  2222. case COL_DOMAIN_NAME: // Domain name
  2223. str1 = GetHostHeaderName();
  2224. str2 = pInstance->GetHostHeaderName();
  2225. return str1.CompareNoCase(str2);
  2226. case COL_IP_ADDRESS: // IP Address
  2227. ia1 = GetIPAddress();
  2228. ia2 = pInstance->GetIPAddress();
  2229. return ia1.CompareItem(ia2);
  2230. case COL_TCP_PORT: // Port
  2231. n1 = GetPort();
  2232. n2 = pInstance->GetPort();
  2233. return n1 - n2;
  2234. case COL_STATUS:
  2235. dw1 = m_hrError;
  2236. dw2 = pInstance->QueryError();
  2237. return dw1 > dw2 ? +1 : dw1==dw2 ? 0 : -1;
  2238. default:
  2239. //
  2240. // No other columns current supported
  2241. //
  2242. ASSERT(FALSE);
  2243. return 0;
  2244. }
  2245. return -1;
  2246. }
  2247. /* virtual */
  2248. void
  2249. CIISInstance::GetResultDisplayInfo(
  2250. IN int nCol,
  2251. OUT CString & str,
  2252. OUT int & nImage
  2253. ) const
  2254. /*++
  2255. Routine Description:
  2256. Get result data item display information.
  2257. Arguments:
  2258. int nCol : Column number
  2259. CString & str : String data
  2260. int & nImage : Image number
  2261. Return Value:
  2262. None
  2263. --*/
  2264. {
  2265. nImage = QueryBitmapIndex();
  2266. CIPAddress ia;
  2267. str.Empty();
  2268. switch(nCol)
  2269. {
  2270. case COL_DESCRIPTION: // Description
  2271. GetDisplayText(str);
  2272. break;
  2273. case COL_STATE: // State
  2274. if (OK())
  2275. {
  2276. str = GetStateText();
  2277. }
  2278. break;
  2279. case COL_DOMAIN_NAME: // Domain name
  2280. if (OK())
  2281. {
  2282. str = GetHostHeaderName();
  2283. }
  2284. break;
  2285. case COL_IP_ADDRESS: // IP Address
  2286. if (!IsDownLevel() && OK())
  2287. {
  2288. ia = GetIPAddress();
  2289. if (ia.IsZeroValue())
  2290. {
  2291. str = CIISObject::s_strDefaultIP;
  2292. }
  2293. else
  2294. {
  2295. ia.QueryIPAddress(str);
  2296. }
  2297. }
  2298. break;
  2299. case COL_TCP_PORT: // Port
  2300. if (OK())
  2301. {
  2302. if (GetPort())
  2303. {
  2304. str.Format(_T("%u"), GetPort());
  2305. }
  2306. else
  2307. {
  2308. str.Empty();
  2309. }
  2310. }
  2311. break;
  2312. case COL_STATUS:
  2313. if (!OK())
  2314. {
  2315. CError::TextFromHRESULT(QueryErrorCode(), str);
  2316. }
  2317. break;
  2318. default:
  2319. //
  2320. // No other columns current supported
  2321. //
  2322. ASSERT(FALSE);
  2323. }
  2324. }
  2325. /* virtual */
  2326. LPCTSTR
  2327. CIISInstance::GetComment() const
  2328. /*++
  2329. Routine Description:
  2330. Get the comment string
  2331. Arguments:
  2332. None
  2333. Return Value:
  2334. Pointer to the comment string
  2335. --*/
  2336. {
  2337. if (IsDownLevel())
  2338. {
  2339. ASSERT(m_pServerInfo != NULL);
  2340. return m_pServerInfo->GetServerComment();
  2341. }
  2342. return m_strComment;
  2343. }
  2344. HRESULT
  2345. CIISInstance::ShellBrowsePath(
  2346. IN LPCTSTR lpszPath
  2347. )
  2348. /*++
  2349. Routine Description:
  2350. Generate an URL from the instance and path information given, and
  2351. attempt to resolve that URL
  2352. Arguments:
  2353. IN LPCTSTR lpszPath : Path
  2354. Return Value:
  2355. Error return code
  2356. --*/
  2357. {
  2358. CString strDir;
  2359. CString strOwner;
  2360. ASSERT(IsBrowsable());
  2361. ///////////////////////////////////////////////////////////////////////////
  2362. //
  2363. // Try to build an URL. Use in order of priority:
  2364. //
  2365. // Domain name:port/root
  2366. // ip address:port/root
  2367. // computer name:port/root
  2368. //
  2369. if (HasHostHeaderName())
  2370. {
  2371. strOwner = GetHostHeaderName();
  2372. }
  2373. else if (HasIPAddress())
  2374. {
  2375. CIPAddress ia(GetIPAddress());
  2376. ia.QueryIPAddress(strOwner);
  2377. }
  2378. else
  2379. {
  2380. //
  2381. // Use the computer name (w/o backslashes)
  2382. //
  2383. if (IsLocalMachine())
  2384. {
  2385. strOwner = _T("localhost");
  2386. }
  2387. else
  2388. {
  2389. LPCTSTR lpOwner = GetMachineName();
  2390. strOwner = PURE_COMPUTER_NAME(lpOwner);
  2391. }
  2392. }
  2393. int nPort = GetPort();
  2394. LPCTSTR lpProtocol = GetServerInfo()->GetProtocol();
  2395. if (lpProtocol == NULL)
  2396. {
  2397. return CError::HResult(ERROR_INVALID_PARAMETER);
  2398. }
  2399. //
  2400. // "Root" is a metabase concept which has no place in the
  2401. // path.
  2402. //
  2403. TRACEEOLID(lpszPath);
  2404. lpszPath += lstrlen(g_cszRoot);
  2405. strDir.Format(
  2406. _T("%s://%s:%u%s"),
  2407. lpProtocol,
  2408. (LPCTSTR)strOwner,
  2409. nPort,
  2410. lpszPath
  2411. );
  2412. TRACEEOLID("Attempting to open URL: " << strDir);
  2413. CError err;
  2414. {
  2415. //
  2416. // AFX_MANAGE_STATE required for wait cursor
  2417. //
  2418. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  2419. CWaitCursor wait;
  2420. if (::ShellExecute(
  2421. NULL,
  2422. _T("open"),
  2423. strDir,
  2424. NULL,
  2425. _T(""),
  2426. SW_SHOW
  2427. ) <= (HINSTANCE)32)
  2428. {
  2429. err.GetLastWinError();
  2430. }
  2431. }
  2432. return err;
  2433. }
  2434. void
  2435. CIISInstance::InitializeChildHeaders(
  2436. IN LPHEADERCTRL pHeader
  2437. )
  2438. /*++
  2439. Routine Description:
  2440. Initialize the result headers
  2441. Arguments:
  2442. LPHEADERCTRL pHeader : Header control
  2443. Return Value:
  2444. None
  2445. --*/
  2446. {
  2447. CIISChildNode::InitializeHeaders(pHeader);
  2448. }
  2449. int CIISChildNode::rgnLabels[COL_TOTAL] =
  2450. {
  2451. IDS_RESULT_VDIR_ALIAS,
  2452. IDS_RESULT_PATH,
  2453. IDS_RESULT_STATUS,
  2454. };
  2455. int CIISChildNode::rgnWidths[COL_TOTAL] =
  2456. {
  2457. 120,
  2458. 300,
  2459. 200,
  2460. };
  2461. /* static */
  2462. void
  2463. CIISChildNode::InitializeHeaders(
  2464. IN LPHEADERCTRL pHeader
  2465. )
  2466. /*++
  2467. Routine Description:
  2468. Initialize the result headers
  2469. Arguments:
  2470. LPHEADERCTRL pHeader : Header control
  2471. Return Value:
  2472. None
  2473. --*/
  2474. {
  2475. CIISObject::BuildResultView(pHeader, COL_TOTAL, rgnLabels, rgnWidths);
  2476. }
  2477. void
  2478. CIISChildNode::InitializeChildHeaders(
  2479. LPHEADERCTRL pHeader
  2480. )
  2481. /*++
  2482. Routine Description:
  2483. Initialize the result headers for a child item
  2484. Arguments:
  2485. LPHEADERCTRL pHeader : Header control
  2486. Return Value:
  2487. None
  2488. --*/
  2489. {
  2490. InitializeHeaders(pHeader);
  2491. }
  2492. CIISChildNode::CIISChildNode(
  2493. IN ISMCHILDINFO * pii,
  2494. IN CIISInstance * pOwner
  2495. )
  2496. /*++
  2497. Routine Description:
  2498. Initialize child node object from ISMCHILDINFO structure information
  2499. Arguments:
  2500. ISMCHILDINFO * pii : Pointer to ISMCHILDINFO structure
  2501. CIISInstance * pOwner : Owner instance
  2502. Return Value:
  2503. N/A
  2504. --*/
  2505. : CIISObject(cChildNode),
  2506. m_pOwner(pOwner)
  2507. {
  2508. InitializeFromStruct(pii);
  2509. }
  2510. void
  2511. CIISChildNode::InitializeFromStruct(
  2512. IN ISMCHILDINFO * pii
  2513. )
  2514. /*++
  2515. Routine Description:
  2516. Initialize data from ISMCHILDINFO structure
  2517. Arguments:
  2518. ISMCHILDINFO * pii : Pointer to ISMCHILDINFO structure
  2519. Return Value:
  2520. None.
  2521. --*/
  2522. {
  2523. ASSERT(pii);
  2524. ASSERT(pii->szAlias);
  2525. ASSERT(pii->szPath);
  2526. try
  2527. {
  2528. m_fEnabledApplication = pii->fEnabledApplication;
  2529. CError err(pii->dwError);
  2530. m_hrError = err;
  2531. m_strRedirPath = pii->szRedirPath;
  2532. m_fChildOnlyRedir = pii->fChildOnlyRedir;
  2533. //
  2534. // Initialize base objects
  2535. //
  2536. m_strNodeName = pii->szAlias;
  2537. m_strPhysicalPath = pii->szPath;
  2538. }
  2539. catch(CMemoryException * e)
  2540. {
  2541. e->ReportError();
  2542. e->Delete();
  2543. }
  2544. }
  2545. /* virtual */
  2546. int
  2547. CIISChildNode::QueryBitmapIndex() const
  2548. /*++
  2549. Routine Description:
  2550. Get the bitmap index of the object. This varies with the state
  2551. of the view
  2552. Arguments:
  2553. None
  2554. Return Value:
  2555. Bitmap index
  2556. --*/
  2557. {
  2558. if (!OK())
  2559. {
  2560. return BMP_ERROR;
  2561. }
  2562. if (IsEnabledApplication())
  2563. {
  2564. return BMP_APPLICATION;
  2565. }
  2566. if (IsVirtualDirectory())
  2567. {
  2568. ASSERT(m_pOwner != NULL);
  2569. return m_pOwner->GetServerInfo()->QueryChildBitmapIndex();
  2570. }
  2571. return BMP_DIRECTORY;
  2572. }
  2573. /* virtual */
  2574. LPCTSTR
  2575. CIISChildNode::GetDisplayText(
  2576. OUT CString & strText
  2577. ) const
  2578. /*++
  2579. Routine Description:
  2580. Get the display text of this object
  2581. Arguments:
  2582. CString & strText : String in which display text is to be returned
  2583. Return Value:
  2584. Pointer to the string
  2585. --*/
  2586. {
  2587. strText = m_strNodeName;
  2588. return strText;
  2589. }
  2590. /* virtual */
  2591. HRESULT
  2592. CIISChildNode::AddMenuItems(
  2593. IN LPCONTEXTMENUCALLBACK pContextMenuCallback
  2594. )
  2595. /*++
  2596. Routine Description:
  2597. Add context menu items relevant to this node
  2598. Arguments:
  2599. LPCONTEXTMENUCALLBACK pContextMenuCallback
  2600. Return Value:
  2601. HRESULT
  2602. --*/
  2603. {
  2604. CIISObject::AddMenuItems(pContextMenuCallback);
  2605. AddMenuItemByCommand(pContextMenuCallback, IDM_NEW_VROOT);
  2606. if (SupportsSecurityWizard())
  2607. {
  2608. AddMenuItemByCommand(pContextMenuCallback, IDM_TASK_SECURITY_WIZARD);
  2609. }
  2610. return S_OK;
  2611. }
  2612. /* virtual */
  2613. HRESULT
  2614. CIISChildNode::AddNextTaskpadItem(
  2615. OUT MMC_TASK * pTask
  2616. )
  2617. /*++
  2618. Routine Description:
  2619. Add next taskpad item
  2620. Arguments:
  2621. MMC_TASK * pTask : Task structure to fill in
  2622. Return Value:
  2623. HRESULT
  2624. --*/
  2625. {
  2626. //
  2627. // CODEWORK: Ideally I would call the base class here, but that's
  2628. // a pain with enumeration
  2629. //
  2630. static int iIndex = 0;
  2631. //
  2632. // Fall through on the switch until an applicable command is found
  2633. //
  2634. UINT nID;
  2635. switch(iIndex)
  2636. {
  2637. case 0:
  2638. nID = IDM_NEW_VROOT;
  2639. break;
  2640. case 1:
  2641. if (SupportsSecurityWizard())
  2642. {
  2643. nID = IDM_TASK_SECURITY_WIZARD;
  2644. break;
  2645. }
  2646. ++iIndex;
  2647. //
  2648. // Fall through
  2649. //
  2650. default:
  2651. //
  2652. // All done
  2653. //
  2654. iIndex = 0;
  2655. return S_FALSE;
  2656. }
  2657. HRESULT hr = AddTaskpadItemByCommand(
  2658. nID,
  2659. pTask,
  2660. GetServerInfo()->QueryInstanceHandle()
  2661. );
  2662. if (SUCCEEDED(hr))
  2663. {
  2664. ++iIndex;
  2665. }
  2666. return hr;
  2667. }
  2668. int
  2669. CIISChildNode::Compare(
  2670. IN int nCol,
  2671. IN CIISObject * pObject
  2672. )
  2673. /*++
  2674. Routine Description:
  2675. Compare against another CIISObject
  2676. Arguments:
  2677. int nCol : Compare on this column
  2678. CIISObject * pObject : Compare against this object
  2679. Routine Description:
  2680. Comparison Return Value
  2681. --*/
  2682. {
  2683. ASSERT(QueryGUID() == pObject->QueryGUID());
  2684. if (QueryGUID() != pObject->QueryGUID())
  2685. {
  2686. //
  2687. // Invalid comparison
  2688. //
  2689. return +1;
  2690. }
  2691. DWORD dw1, dw2;
  2692. CIISChildNode * pChild = (CIISChildNode *)pObject;
  2693. switch(nCol)
  2694. {
  2695. case COL_ALIAS: // Alias
  2696. return m_strNodeName.CompareNoCase(pChild->m_strNodeName);
  2697. case COL_PATH: // Path
  2698. dw1 = IsRedirected();
  2699. dw2 = pChild->IsRedirected();
  2700. if (dw1 != dw2)
  2701. {
  2702. return dw1 > dw2 ? +1 : -1;
  2703. }
  2704. return GetPhysicalPath().CompareNoCase(pChild->GetPhysicalPath());
  2705. case COL_STATUS:
  2706. dw1 = m_hrError;
  2707. dw2 = pChild->QueryError();
  2708. return dw1 > dw2 ? +1 : dw1==dw2 ? 0 : -1;
  2709. default:
  2710. //
  2711. // No other columns current supported
  2712. //
  2713. ASSERT(FALSE);
  2714. }
  2715. return -1;
  2716. }
  2717. /* virtual */
  2718. void
  2719. CIISChildNode::GetResultDisplayInfo(
  2720. IN int nCol,
  2721. OUT CString & str,
  2722. OUT int & nImage
  2723. ) const
  2724. /*++
  2725. Routine Description:
  2726. Get result data item display information.
  2727. Arguments:
  2728. int nCol : Column number
  2729. CString & str : String data
  2730. int & nImage : Image number
  2731. Return Value:
  2732. None
  2733. --*/
  2734. {
  2735. nImage = QueryBitmapIndex();
  2736. str.Empty();
  2737. switch(nCol)
  2738. {
  2739. case COL_ALIAS: // Alias
  2740. str = m_strNodeName;
  2741. break;
  2742. case COL_PATH: // Path
  2743. if (IsRedirected())
  2744. {
  2745. str.Format(s_strRedirect, m_strRedirPath);
  2746. }
  2747. else
  2748. {
  2749. str = m_strPhysicalPath;
  2750. }
  2751. break;
  2752. case COL_STATUS:
  2753. if (!OK())
  2754. {
  2755. CError::TextFromHRESULT(QueryErrorCode(), str);
  2756. }
  2757. break;
  2758. default:
  2759. //
  2760. // No other columns current supported
  2761. //
  2762. ASSERT(FALSE);
  2763. }
  2764. }
  2765. /* virtual */
  2766. HRESULT
  2767. CIISChildNode::Configure(
  2768. IN CWnd * pParent
  2769. )
  2770. /*++
  2771. Routine Description:
  2772. Configure the child node object
  2773. Arguments:
  2774. CWnd * pParent : Parent window handle
  2775. Return Value:
  2776. Error return code
  2777. --*/
  2778. {
  2779. ASSERT(m_pOwner != NULL);
  2780. //
  2781. // Ok, build a metabase path on the fly now by getting
  2782. // the nodes of the parents up until the owning instance.
  2783. //
  2784. CString strParent;
  2785. BuildParentPath(strParent, FALSE);
  2786. //
  2787. // Set help file
  2788. //
  2789. theApp.SetHelpPath(GetServerInfo());
  2790. CError err(GetServerInfo()->ConfigureChild(
  2791. pParent->m_hWnd,
  2792. FILE_ATTRIBUTE_VIRTUAL_DIRECTORY,
  2793. m_pOwner->QueryID(),
  2794. strParent,
  2795. m_strNodeName
  2796. ));
  2797. //
  2798. // Set help file
  2799. //
  2800. theApp.SetHelpPath();
  2801. if (err.Succeeded())
  2802. {
  2803. RefreshData();
  2804. }
  2805. return err;
  2806. }
  2807. /* virtual */
  2808. HRESULT
  2809. CIISChildNode::RefreshData()
  2810. /*++
  2811. Routine Description:
  2812. Refresh internal data
  2813. Arguments:
  2814. None
  2815. Return Value:
  2816. Error return code.
  2817. --*/
  2818. {
  2819. ISMCHILDINFO ii;
  2820. CString strParent;
  2821. BuildParentPath(strParent, FALSE);
  2822. CError err(GetServerInfo()->QueryChildInfo(
  2823. WITH_INHERITANCE,
  2824. &ii,
  2825. m_pOwner->QueryID(),
  2826. strParent,
  2827. m_strNodeName
  2828. ));
  2829. if (err.Succeeded())
  2830. {
  2831. InitializeFromStruct(&ii);
  2832. }
  2833. return err;
  2834. }
  2835. /* virtual */
  2836. HRESULT
  2837. CIISChildNode::ConfigureMMC(
  2838. IN LPPROPERTYSHEETCALLBACK lpProvider,
  2839. IN LPARAM param,
  2840. IN LONG_PTR handle
  2841. )
  2842. /*++
  2843. Routine Description:
  2844. Configure using MMC property sheets
  2845. Arguments:
  2846. LPPROPERTYSHEETCALLBACK lpProvider : Prop sheet provider
  2847. LPARAM param : Prop parameter
  2848. LONG_PTR handle : console handle
  2849. Return Value:
  2850. Error return code
  2851. --*/
  2852. {
  2853. ASSERT(m_pOwner != NULL);
  2854. CString strParent;
  2855. BuildParentPath(strParent, FALSE);
  2856. return GetServerInfo()->MMCConfigureChild(lpProvider,
  2857. param,
  2858. handle,
  2859. FILE_ATTRIBUTE_VIRTUAL_DIRECTORY,
  2860. m_pOwner->QueryID(),
  2861. strParent,
  2862. m_strNodeName
  2863. );
  2864. }
  2865. /* virtual */
  2866. HRESULT
  2867. CIISChildNode::AddChildNode(
  2868. CIISChildNode *& pChild
  2869. )
  2870. /*++
  2871. Routine Description:
  2872. Add child node under current node
  2873. Arguments:
  2874. CIISChildNode *& pChild : Child node to be added
  2875. Return Value:
  2876. Error return code.
  2877. --*/
  2878. {
  2879. ASSERT(m_pOwner != NULL);
  2880. ISMCHILDINFO ii;
  2881. CString strPath;
  2882. BuildFullPath(strPath, FALSE);
  2883. pChild = NULL;
  2884. CError err(GetServerInfo()->AddChild(
  2885. &ii,
  2886. sizeof(ii),
  2887. m_pOwner->QueryID(),
  2888. strPath
  2889. ));
  2890. if (err.Succeeded())
  2891. {
  2892. pChild = new CIISChildNode(&ii, m_pOwner);
  2893. }
  2894. return err;
  2895. }
  2896. /* virtual */
  2897. HRESULT
  2898. CIISChildNode::Rename(
  2899. IN LPCTSTR lpszNewName
  2900. )
  2901. /*++
  2902. Routine Description:
  2903. Rename the current node
  2904. Arguments:
  2905. LPCTSTR lpszNewName : New name
  2906. Return Value:
  2907. Error return code.
  2908. --*/
  2909. {
  2910. ASSERT(m_pOwner != NULL);
  2911. CString strPath;
  2912. BuildParentPath(strPath, FALSE);
  2913. CError err(GetServerInfo()->RenameChild(
  2914. m_pOwner->QueryID(),
  2915. strPath,
  2916. m_strNodeName,
  2917. lpszNewName
  2918. ));
  2919. if (err.Succeeded())
  2920. {
  2921. m_strNodeName = lpszNewName;
  2922. }
  2923. return err;
  2924. }
  2925. HRESULT
  2926. CIISChildNode::Delete()
  2927. /*++
  2928. Routine Description:
  2929. Delete the current node
  2930. Arguments:
  2931. None
  2932. Return Value:
  2933. Error return code.
  2934. --*/
  2935. {
  2936. ASSERT(m_pOwner != NULL);
  2937. CString strParent;
  2938. BuildParentPath(strParent, FALSE);
  2939. return GetServerInfo()->DeleteChild(
  2940. m_pOwner->QueryID(),
  2941. strParent,
  2942. m_strNodeName
  2943. );
  2944. }
  2945. HRESULT
  2946. CIISChildNode::SecurityWizard()
  2947. /*++
  2948. Routine Description:
  2949. Launch the security wizard on this child node
  2950. Arguments:
  2951. None
  2952. Return Value:
  2953. Error return code
  2954. --*/
  2955. {
  2956. ASSERT(m_pOwner != NULL);
  2957. CString strParent;
  2958. BuildParentPath(strParent, FALSE);
  2959. return GetServerInfo()->ISMSecurityWizard(
  2960. m_pOwner->QueryID(),
  2961. strParent,
  2962. m_strNodeName
  2963. );
  2964. }
  2965. int CIISFileNode::rgnLabels[COL_TOTAL] =
  2966. {
  2967. IDS_RESULT_VDIR_ALIAS,
  2968. IDS_RESULT_PATH,
  2969. IDS_RESULT_STATUS,
  2970. };
  2971. int CIISFileNode::rgnWidths[COL_TOTAL] =
  2972. {
  2973. 120,
  2974. 300,
  2975. 200,
  2976. };
  2977. /* static */
  2978. void
  2979. CIISFileNode::InitializeHeaders(
  2980. IN LPHEADERCTRL pHeader
  2981. )
  2982. /*++
  2983. Routine Description:
  2984. Initialize the result headers
  2985. Arguments:
  2986. LPHEADERCTRL pHeader : Header control
  2987. Return Value:
  2988. None
  2989. --*/
  2990. {
  2991. CIISObject::BuildResultView(pHeader, COL_TOTAL, rgnLabels, rgnWidths);
  2992. }
  2993. void
  2994. CIISFileNode::InitializeChildHeaders(
  2995. IN LPHEADERCTRL pHeader
  2996. )
  2997. /*++
  2998. Routine Description:
  2999. Initialize the result headers
  3000. Arguments:
  3001. LPHEADERCTRL pHeader : Header control
  3002. Return Value:
  3003. None
  3004. --*/
  3005. {
  3006. InitializeHeaders(pHeader);
  3007. }
  3008. CIISFileNode::CIISFileNode(
  3009. IN LPCTSTR lpszAlias,
  3010. IN DWORD dwAttributes,
  3011. IN CIISInstance * pOwner,
  3012. IN LPCTSTR lpszRedirect,
  3013. IN BOOL fDir OPTIONAL
  3014. )
  3015. /*++
  3016. Routine Description:
  3017. Constructor for file object
  3018. Arguments:
  3019. LPCTSTR lpszPath : Path name
  3020. DWORD dwAttributes : Attributes
  3021. CIISInstance * pOwner : Owner instance
  3022. BOOL fDir : TRUE for directory, FALSE for file
  3023. Return Value:
  3024. N/A
  3025. --*/
  3026. : CIISObject(cFileNode, lpszAlias),
  3027. m_dwAttributes(dwAttributes),
  3028. m_pOwner(pOwner),
  3029. m_fEnabledApplication(FALSE),
  3030. m_fDir(fDir)
  3031. {
  3032. m_strRedirPath = lpszRedirect;
  3033. }
  3034. /* virtual */
  3035. int
  3036. CIISFileNode::QueryBitmapIndex() const
  3037. /*++
  3038. Routine Description:
  3039. Get the bitmap index of the object. This varies with the state
  3040. of the view
  3041. Arguments:
  3042. None
  3043. Return Value:
  3044. Bitmap index
  3045. --*/
  3046. {
  3047. if (IsEnabledApplication())
  3048. {
  3049. return BMP_APPLICATION;
  3050. }
  3051. return IsDirectory() ? BMP_DIRECTORY : BMP_FILE;
  3052. }
  3053. /* virtual */
  3054. LPCTSTR
  3055. CIISFileNode::GetDisplayText(
  3056. OUT CString & strText
  3057. ) const
  3058. /*++
  3059. Routine Description:
  3060. Get the display text of this object
  3061. Arguments:
  3062. CString & strText : String in which display text is to be returned
  3063. Return Value:
  3064. Pointer to the string
  3065. --*/
  3066. {
  3067. strText = m_strNodeName;
  3068. return strText;
  3069. }
  3070. int
  3071. CIISFileNode::Compare(
  3072. IN int nCol,
  3073. IN CIISObject * pObject
  3074. )
  3075. /*++
  3076. Routine Description:
  3077. Compare against another CIISObject
  3078. Arguments:
  3079. int nCol : Compare on this column
  3080. CIISObject * pObject : Compare against this object
  3081. Routine Description:
  3082. Comparison Return Value
  3083. --*/
  3084. {
  3085. ASSERT(QueryGUID() == pObject->QueryGUID());
  3086. if (QueryGUID() != pObject->QueryGUID())
  3087. {
  3088. //
  3089. // Invalid comparison
  3090. //
  3091. return +1;
  3092. }
  3093. return m_strNodeName.CompareNoCase(pObject->GetNodeName());
  3094. }
  3095. /* virtual */
  3096. void
  3097. CIISFileNode::GetResultDisplayInfo(
  3098. IN int nCol,
  3099. OUT CString & str,
  3100. OUT int & nImage
  3101. ) const
  3102. /*++
  3103. Routine Description:
  3104. Get result data item display information.
  3105. Arguments:
  3106. int nCol : Column number
  3107. CString & str : String data
  3108. int & nImage : Image number
  3109. Return Value:
  3110. None
  3111. --*/
  3112. {
  3113. nImage = QueryBitmapIndex();
  3114. str.Empty();
  3115. switch(nCol)
  3116. {
  3117. case COL_ALIAS:
  3118. str = m_strNodeName;
  3119. break;
  3120. case COL_PATH: // Path
  3121. if (IsRedirected())
  3122. {
  3123. str.Format(s_strRedirect, m_strRedirPath);
  3124. }
  3125. else
  3126. {
  3127. str.Empty();
  3128. }
  3129. break;
  3130. case COL_STATUS:
  3131. if (!OK())
  3132. {
  3133. CError::TextFromHRESULT(QueryErrorCode(), str);
  3134. }
  3135. break;
  3136. default:
  3137. //
  3138. // No other columns current supported
  3139. //
  3140. ASSERT(FALSE);
  3141. }
  3142. }
  3143. /* virtual */
  3144. CIISObject *
  3145. CIISFileNode::GetParentObject() const
  3146. /*++
  3147. Routine Description:
  3148. Get the parent object (in the scope view) of this object.
  3149. Arguments:
  3150. None
  3151. Return Value:
  3152. Pointer to the parent object, or NULL if not found
  3153. --*/
  3154. {
  3155. if (!IsDir())
  3156. {
  3157. //
  3158. // File nodes exist on the result side only, and the scope
  3159. // item handle they have points to their _parent_ not to
  3160. // themselves.
  3161. //
  3162. SCOPEDATAITEM sdi;
  3163. sdi.mask = SDI_PARAM;
  3164. sdi.ID = GetScopeHandle();
  3165. HRESULT hr = GetScopeView()->GetItem(&sdi);
  3166. return (CIISObject *)sdi.lParam;
  3167. }
  3168. //
  3169. // Directory nodes work like anyone else
  3170. //
  3171. return CIISObject::GetParentObject();
  3172. }
  3173. /* virtual */
  3174. HRESULT
  3175. CIISFileNode::Configure(
  3176. IN CWnd * pParent
  3177. )
  3178. /*++
  3179. Routine Description:
  3180. Configure using private property sheet provider
  3181. Arguments:
  3182. CWnd * pParent : Parent window
  3183. Return Value:
  3184. Error return code.
  3185. --*/
  3186. {
  3187. ASSERT(m_pOwner != NULL);
  3188. CString strParent;
  3189. BuildParentPath(strParent, FALSE);
  3190. //
  3191. // Set help file
  3192. //
  3193. theApp.SetHelpPath(GetServerInfo());
  3194. CError err(GetServerInfo()->ConfigureChild(
  3195. pParent->m_hWnd,
  3196. m_dwAttributes,
  3197. m_pOwner->QueryID(),
  3198. strParent,
  3199. m_strNodeName
  3200. ));
  3201. //
  3202. // Restore help file
  3203. //
  3204. theApp.SetHelpPath();
  3205. if (err.Succeeded())
  3206. {
  3207. RefreshData();
  3208. }
  3209. return err;
  3210. }
  3211. /* virtual */
  3212. HRESULT
  3213. CIISFileNode::Rename(
  3214. IN LPCTSTR lpszNewName
  3215. )
  3216. /*++
  3217. Routine Description:
  3218. Rename the current node
  3219. Arguments:
  3220. LPCTSTR lpszNewName : New name
  3221. Return Value:
  3222. Error return code.
  3223. --*/
  3224. {
  3225. ASSERT(m_pOwner != NULL);
  3226. ASSERT(lpszNewName != NULL);
  3227. // We need to check if this new name is OK
  3228. LPTSTR p = (LPTSTR)lpszNewName;
  3229. if (*p == 0)
  3230. {
  3231. AFX_MANAGE_STATE(::AfxGetStaticModuleState() );
  3232. ::AfxMessageBox(IDS_ERR_EMPTY_FILENAME, MB_ICONSTOP);
  3233. return ERROR_BAD_PATHNAME;
  3234. }
  3235. while (*p != 0)
  3236. {
  3237. UINT type = PathGetCharType(*p);
  3238. if (type & (GCT_LFNCHAR | GCT_SHORTCHAR))
  3239. {
  3240. p++;
  3241. continue;
  3242. }
  3243. else
  3244. {
  3245. AFX_MANAGE_STATE(::AfxGetStaticModuleState() );
  3246. ::AfxMessageBox(IDS_ERR_INVALID_CHAR, MB_ICONSTOP);
  3247. return ERROR_BAD_PATHNAME;
  3248. }
  3249. }
  3250. CString strPath, strPhysicalPath, strDir, strNewName;
  3251. BuildPhysicalPath(strPhysicalPath);
  3252. BuildParentPath(strPath, FALSE);
  3253. //
  3254. // First make sure there's no conflicting name in the metabase
  3255. //
  3256. ISMCHILDINFO ii;
  3257. ii.dwSize = sizeof(ii);
  3258. CError err(GetServerInfo()->QueryChildInfo(
  3259. WITHOUT_INHERITANCE,
  3260. &ii,
  3261. m_pOwner->QueryID(),
  3262. strPath,
  3263. lpszNewName
  3264. ));
  3265. if (err.Succeeded())
  3266. {
  3267. //
  3268. // That won't do -- the name already exists in the metabase
  3269. // We handle the UI for this message
  3270. //
  3271. AFX_MANAGE_STATE(::AfxGetStaticModuleState() );
  3272. ::AfxMessageBox(IDS_ERR_DUP_METABASE);
  3273. return ERROR_ALREADY_EXISTS;
  3274. }
  3275. if (IsLocalMachine() || ::IsUNCName(strPhysicalPath))
  3276. {
  3277. //
  3278. // Local directory, or already a unc path
  3279. //
  3280. strDir = strPhysicalPath;
  3281. }
  3282. else
  3283. {
  3284. ::MakeUNCPath(strDir, GetMachineName(), strPhysicalPath);
  3285. }
  3286. //
  3287. // Have to make a fully qualified destination name
  3288. //
  3289. strNewName = strDir;
  3290. int iPos = strNewName.ReverseFind(_T('\\'));
  3291. if (iPos <= 0)
  3292. {
  3293. //
  3294. // Bogus file name path!
  3295. //
  3296. ASSERT(FALSE);
  3297. return ERROR_INVALID_PARAMETER;
  3298. }
  3299. strNewName.ReleaseBuffer(iPos + 1);
  3300. strNewName += lpszNewName;
  3301. TRACEEOLID("Attempting to rename file/directory: " << strDir);
  3302. TRACEEOLID("To " << strNewName);
  3303. //
  3304. // Convert to double-null terminated list of null terminated
  3305. // strings
  3306. //
  3307. TCHAR szPath[MAX_PATH + 1];
  3308. TCHAR szDest[MAX_PATH + 1];
  3309. ZeroMemory(szPath, sizeof(szPath));
  3310. ZeroMemory(szDest, sizeof(szDest));
  3311. _tcscpy(szPath, strDir);
  3312. _tcscpy(szDest, strNewName);
  3313. CWnd * pWnd = AfxGetMainWnd();
  3314. //
  3315. // Attempt to delete using shell APIs
  3316. //
  3317. SHFILEOPSTRUCT sos;
  3318. ZeroMemory(&sos, sizeof(sos));
  3319. sos.hwnd = pWnd ? pWnd->m_hWnd : NULL;
  3320. sos.wFunc = FO_RENAME;
  3321. sos.pFrom = szPath;
  3322. sos.pTo = szDest;
  3323. sos.fFlags = FOF_ALLOWUNDO;
  3324. int iReturn = SHFileOperation(&sos);
  3325. if (sos.fAnyOperationsAborted)
  3326. {
  3327. err = ERROR_CANCELLED;
  3328. }
  3329. err = iReturn;
  3330. if (!iReturn && !sos.fAnyOperationsAborted)
  3331. {
  3332. //
  3333. // Successful rename -- now handle the metabase
  3334. // rename as well.
  3335. //
  3336. err = GetServerInfo()->RenameChild(
  3337. m_pOwner->QueryID(),
  3338. strPath,
  3339. m_strNodeName,
  3340. lpszNewName
  3341. );
  3342. if (err.Win32Error() == ERROR_PATH_NOT_FOUND
  3343. || err.Win32Error() == ERROR_FILE_NOT_FOUND
  3344. )
  3345. {
  3346. //
  3347. // Harmless
  3348. //
  3349. err.Reset();
  3350. }
  3351. if (err.Succeeded())
  3352. {
  3353. m_strNodeName = lpszNewName;
  3354. }
  3355. }
  3356. return err;
  3357. }
  3358. HRESULT
  3359. CIISFileNode::Delete()
  3360. /*++
  3361. Routine Description:
  3362. Delete the current node
  3363. Arguments:
  3364. None
  3365. Return Value:
  3366. Error return code.
  3367. --*/
  3368. {
  3369. CString strPhysicalPath, strDir;
  3370. BuildPhysicalPath(strPhysicalPath);
  3371. if (IsLocalMachine() || ::IsUNCName(strPhysicalPath))
  3372. {
  3373. //
  3374. // Local directory, or already a unc path
  3375. //
  3376. strDir = strPhysicalPath;
  3377. }
  3378. else
  3379. {
  3380. ::MakeUNCPath(strDir, GetMachineName(), strPhysicalPath);
  3381. }
  3382. TRACEEOLID("Attempting to remove file/directory: " << strDir);
  3383. //
  3384. // Convert to double-null terminated list of null terminated
  3385. // strings
  3386. //
  3387. TCHAR szPath[MAX_PATH + 1];
  3388. ZeroMemory(szPath, sizeof(szPath));
  3389. _tcscpy(szPath, strDir);
  3390. CWnd * pWnd = AfxGetMainWnd();
  3391. //
  3392. // Attempt to delete using shell APIs
  3393. //
  3394. SHFILEOPSTRUCT sos;
  3395. ZeroMemory(&sos, sizeof(sos));
  3396. sos.hwnd = pWnd ? pWnd->m_hWnd : NULL;
  3397. sos.wFunc = FO_DELETE;
  3398. sos.pFrom = szPath;
  3399. sos.fFlags = FOF_ALLOWUNDO;
  3400. CError err;
  3401. // Use assignment to avoid conversion and wrong constructor call
  3402. err = ::SHFileOperation(&sos);
  3403. if (sos.fAnyOperationsAborted)
  3404. {
  3405. err = ERROR_CANCELLED;
  3406. }
  3407. if (err.Succeeded())
  3408. {
  3409. //
  3410. // Successful deletion -- now delete metabase properties
  3411. ASSERT(m_pOwner != NULL);
  3412. CString strParent;
  3413. BuildParentPath(strParent, FALSE);
  3414. err = GetServerInfo()->DeleteChild(
  3415. m_pOwner->QueryID(),
  3416. strParent,
  3417. m_strNodeName
  3418. );
  3419. if (err.Win32Error() == ERROR_PATH_NOT_FOUND
  3420. || err.Win32Error() == ERROR_FILE_NOT_FOUND
  3421. )
  3422. {
  3423. //
  3424. // Harmless
  3425. //
  3426. err.Reset();
  3427. }
  3428. }
  3429. return err;
  3430. }
  3431. HRESULT
  3432. CIISFileNode::FetchMetaInformation(
  3433. IN CString & strParent,
  3434. OUT BOOL * pfVirtualDirectory OPTIONAL
  3435. )
  3436. /*++
  3437. Routine Description:
  3438. Fetch metabase information on this item.
  3439. Arguments:
  3440. CString & strParent : Parent path
  3441. BOOL * pfVirtualDirectory : Directory
  3442. Return Value:
  3443. Error return code.
  3444. --*/
  3445. {
  3446. ISMCHILDINFO ii;
  3447. CError err(GetServerInfo()->QueryChildInfo(
  3448. WITH_INHERITANCE,
  3449. &ii,
  3450. m_pOwner->QueryID(),
  3451. strParent,
  3452. m_strNodeName
  3453. ));
  3454. if (err.Succeeded())
  3455. {
  3456. //
  3457. // Exists in the metabase
  3458. //
  3459. m_fEnabledApplication = ii.fEnabledApplication;
  3460. m_strRedirPath = ii.szRedirPath;
  3461. m_fChildOnlyRedir = ii.fChildOnlyRedir;
  3462. if (pfVirtualDirectory)
  3463. {
  3464. *pfVirtualDirectory = !ii.fInheritedPath;
  3465. }
  3466. }
  3467. else
  3468. {
  3469. //
  3470. // No entry for this in the metabase
  3471. //
  3472. m_fEnabledApplication = FALSE;
  3473. m_strRedirPath.Empty();
  3474. }
  3475. return S_OK;
  3476. }
  3477. /* virtual */
  3478. HRESULT
  3479. CIISFileNode::RefreshData()
  3480. /*++
  3481. Routine Description:
  3482. Refresh internal data
  3483. Arguments:
  3484. None
  3485. Return Value:
  3486. Error return code.
  3487. --*/
  3488. {
  3489. CString strParent;
  3490. BuildParentPath(strParent, FALSE);
  3491. return FetchMetaInformation(strParent);
  3492. }
  3493. /* virtual */
  3494. HRESULT
  3495. CIISFileNode::ConfigureMMC(
  3496. IN LPPROPERTYSHEETCALLBACK lpProvider,
  3497. IN LPARAM param,
  3498. IN LONG_PTR handle
  3499. )
  3500. /*++
  3501. Routine Description:
  3502. Configure using MMC property sheet provider
  3503. Arguments:
  3504. LPPROPERTYSHEETCALLBACK lpProvider : Property sheet provider
  3505. LPARAM param : Parameter
  3506. LONG_PTR handle : Handle
  3507. Return Value:
  3508. Error return code
  3509. --*/
  3510. {
  3511. ASSERT(m_pOwner != NULL);
  3512. CString strParent;
  3513. BuildParentPath(strParent, FALSE);
  3514. return GetServerInfo()->MMCConfigureChild(
  3515. lpProvider,
  3516. param,
  3517. handle,
  3518. m_dwAttributes,
  3519. m_pOwner->QueryID(),
  3520. strParent,
  3521. m_strNodeName
  3522. );
  3523. }
  3524. /* virtual */
  3525. HRESULT
  3526. CIISFileNode::AddMenuItems(
  3527. IN LPCONTEXTMENUCALLBACK pContextMenuCallback
  3528. )
  3529. /*++
  3530. Routine Description:
  3531. Add context menu items relevant to this node
  3532. Arguments:
  3533. LPCONTEXTMENUCALLBACK pContextMenuCallback
  3534. Return Value:
  3535. HRESULT
  3536. --*/
  3537. {
  3538. CIISObject::AddMenuItems(pContextMenuCallback);
  3539. if (IsDir())
  3540. {
  3541. AddMenuItemByCommand(pContextMenuCallback, IDM_NEW_VROOT);
  3542. }
  3543. if (SupportsSecurityWizard())
  3544. {
  3545. AddMenuItemByCommand(pContextMenuCallback, IDM_TASK_SECURITY_WIZARD);
  3546. }
  3547. return S_OK;
  3548. }
  3549. /* virtual */
  3550. HRESULT
  3551. CIISFileNode::AddNextTaskpadItem(
  3552. OUT MMC_TASK * pTask
  3553. )
  3554. /*++
  3555. Routine Description:
  3556. Add next taskpad item
  3557. Arguments:
  3558. MMC_TASK * pTask : Task structure to fill in
  3559. Return Value:
  3560. HRESULT
  3561. --*/
  3562. {
  3563. //
  3564. // CODEWORK: Ideally I would call be the base class here, but that's
  3565. // a pain with enumeration
  3566. //
  3567. static int iIndex = 0;
  3568. //
  3569. // Fall through on the switch until an applicable command is found
  3570. //
  3571. UINT nID;
  3572. switch(iIndex)
  3573. {
  3574. case 0:
  3575. if (IsDir())
  3576. {
  3577. nID = IDM_NEW_VROOT;
  3578. break;
  3579. }
  3580. default:
  3581. //
  3582. // All done
  3583. //
  3584. iIndex = 0;
  3585. return S_FALSE;
  3586. }
  3587. HRESULT hr = AddTaskpadItemByCommand(
  3588. nID,
  3589. pTask,
  3590. GetServerInfo()->QueryInstanceHandle()
  3591. );
  3592. if (SUCCEEDED(hr))
  3593. {
  3594. ++iIndex;
  3595. }
  3596. return hr;
  3597. }
  3598. /* virtual */
  3599. HRESULT
  3600. CIISFileNode::AddChildNode(
  3601. IN CIISChildNode *& pChild
  3602. )
  3603. /*++
  3604. Routine Description:
  3605. Add child node under current node
  3606. Arguments:
  3607. CIISChildNode *& pChild : Child node to be added
  3608. Return Value:
  3609. Error return code.
  3610. --*/
  3611. {
  3612. ASSERT(m_pOwner != NULL);
  3613. ISMCHILDINFO ii;
  3614. CString strPath;
  3615. BuildFullPath(strPath, FALSE);
  3616. pChild = NULL;
  3617. CError err(GetServerInfo()->AddChild(
  3618. &ii,
  3619. sizeof(ii),
  3620. m_pOwner->QueryID(),
  3621. strPath
  3622. ));
  3623. if (err.Succeeded())
  3624. {
  3625. pChild = new CIISChildNode(
  3626. &ii,
  3627. m_pOwner
  3628. );
  3629. }
  3630. return err;
  3631. }
  3632. HRESULT
  3633. CIISFileNode::SecurityWizard()
  3634. /*++
  3635. Routine Description:
  3636. Launch the security wizard on this file node
  3637. Arguments:
  3638. None
  3639. Return Value:
  3640. Error return code
  3641. --*/
  3642. {
  3643. ASSERT(m_pOwner != NULL);
  3644. ASSERT(SupportsSecurityWizard());
  3645. CString strParent;
  3646. BuildParentPath(strParent, FALSE);
  3647. return GetServerInfo()->ISMSecurityWizard(
  3648. m_pOwner->QueryID(),
  3649. strParent,
  3650. m_strNodeName
  3651. );
  3652. }